1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.crypto.store.wiki.internal

File AbstractX509WikiStore.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

16
51
13
1
317
167
22
0.43
3.92
13
1.69

Classes

Class Line # Actions
AbstractX509WikiStore 54 51 0% 22 5
0.937593.8%
 

Contributing tests

This file is covered by 30 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.crypto.store.wiki.internal;
21   
22    import javax.inject.Inject;
23    import javax.inject.Named;
24    import javax.inject.Provider;
25   
26    import org.xwiki.crypto.BinaryStringEncoder;
27    import org.xwiki.crypto.pkix.CertificateFactory;
28    import org.xwiki.crypto.pkix.params.CertifiedPublicKey;
29    import org.xwiki.crypto.pkix.params.x509certificate.X509CertifiedPublicKey;
30    import org.xwiki.crypto.store.CertificateStoreException;
31    import org.xwiki.crypto.store.StoreReference;
32    import org.xwiki.crypto.store.WikiStoreReference;
33    import org.xwiki.crypto.store.wiki.internal.query.CertificateObjectReference;
34    import org.xwiki.crypto.store.wiki.internal.query.X509CertificateReferenceIssuerAndSerialQuery;
35    import org.xwiki.crypto.store.wiki.internal.query.X509CertificateReferenceKeyIdentifierQuery;
36    import org.xwiki.model.EntityType;
37    import org.xwiki.model.reference.DocumentReference;
38    import org.xwiki.model.reference.EntityReference;
39    import org.xwiki.model.reference.EntityReferenceResolver;
40    import org.xwiki.model.reference.EntityReferenceSerializer;
41    import org.xwiki.query.QueryManager;
42   
43    import com.xpn.xwiki.XWikiContext;
44    import com.xpn.xwiki.XWikiException;
45    import com.xpn.xwiki.doc.XWikiDocument;
46    import com.xpn.xwiki.objects.BaseObject;
47   
48    /**
49    * Abstract base class for X509 stores.
50    *
51    * @version $Id: 0144fd10312565eb7130d828f26285d4b239d8ea $
52    * @since 6.1M2
53    */
 
54    public abstract class AbstractX509WikiStore
55    {
56    /**
57    * Used while accessing documents and objects.
58    */
59    @Inject
60    private Provider<XWikiContext> contextProvider;
61   
62    /**
63    * Used to resolve store references to full references.
64    */
65    @Inject
66    @Named("current")
67    private EntityReferenceResolver<EntityReference> referenceResolver;
68   
69    /**
70    * Used to convert document references returned by query.
71    */
72    @Inject
73    @Named("current")
74    private EntityReferenceResolver<String> stringReferenceResolver;
75   
76    /**
77    * Used to convert document references to query parameters.
78    */
79    @Inject
80    @Named("local")
81    private EntityReferenceSerializer<String> entityReferenceSerializer;
82   
83    /**
84    * Used to encode/decode certificates, private keys and subject keys.
85    */
86    @Inject
87    @Named("Base64")
88    private BinaryStringEncoder base64;
89   
90    /**
91    * Used to create certificate from encoded bytes.
92    */
93    @Inject
94    @Named("X509")
95    private CertificateFactory certificateFactory;
96   
97    /**
98    * Use to query certificate objects.
99    */
100    @Inject
101    private QueryManager queryManager;
102   
103    /**
104    * @return the XWikiContext.
105    */
 
106  22 toggle protected XWikiContext getXWikiContext()
107    {
108  22 return this.contextProvider.get();
109    }
110   
111    /**
112    * @return the base64 encoder.
113    */
 
114  20 toggle protected BinaryStringEncoder getEncoder()
115    {
116  20 return this.base64;
117    }
118   
119    /**
120    * @return the certificate factory.
121    */
 
122  10 toggle protected CertificateFactory getCertificateFactory()
123    {
124  10 return this.certificateFactory;
125    }
126   
127    /**
128    * @return the query manager.
129    */
 
130  8 toggle protected QueryManager getQueryManager()
131    {
132  8 return this.queryManager;
133    }
134   
135    /**
136    * @return the query manager.
137    */
 
138  8 toggle protected EntityReferenceSerializer<String> getSerializer()
139    {
140  8 return this.entityReferenceSerializer;
141    }
142   
143    /**
144    * Create or update a certificate into the appropriate document of the given store, and return the unsaved document.
145    *
146    * @param store the reference of a document or a space where the certificate should be stored.
147    * @param certificate the certificate to store.
148    * @param context the XWikiContext.
149    * @return the XWiki document to be saved where the object was updated or created.
150    * @throws CertificateStoreException on error.
151    */
 
152  14 toggle protected XWikiDocument storeCertificate(StoreReference store, CertifiedPublicKey certificate,
153    XWikiContext context) throws CertificateStoreException
154    {
155  14 if (!(certificate instanceof X509CertifiedPublicKey)) {
156  0 throw new IllegalArgumentException("Certificate should be X509 certificates.");
157    }
158   
159  14 X509CertifiedPublicKey publicKey = (X509CertifiedPublicKey) certificate;
160   
161  14 try {
162  14 CertificateObjectReference certRef = findCertificate(store, publicKey);
163   
164  14 XWikiDocument document;
165  14 BaseObject obj;
166   
167  14 if (certRef != null) {
168  7 document = getDocument(store, certRef, context);
169  7 obj = document.getXObject(X509CertificateWikiStore.CERTIFICATECLASS, certRef.getObjectNumber());
170    } else {
171  7 document = context.getWiki().getDocument(getDocumentReference(store, publicKey), context);
172  7 obj = document.newXObject(X509CertificateWikiStore.CERTIFICATECLASS, context);
173   
174  7 byte[] keyId = publicKey.getSubjectKeyIdentifier();
175  7 if (keyId != null) {
176  5 obj.setStringValue(X509CertificateWikiStore.CERTIFICATECLASS_PROP_KEYID, this.base64.encode(keyId));
177    }
178  7 obj.setStringValue(X509CertificateWikiStore.CERTIFICATECLASS_PROP_ISSUER,
179    publicKey.getIssuer().getName());
180  7 obj.setStringValue(X509CertificateWikiStore.CERTIFICATECLASS_PROP_SERIAL,
181    publicKey.getSerialNumber().toString());
182  7 obj.setStringValue(X509CertificateWikiStore.CERTIFICATECLASS_PROP_SUBJECT,
183    publicKey.getSubject().getName());
184    }
185   
186  14 obj.setLargeStringValue(X509CertificateWikiStore.CERTIFICATECLASS_PROP_CERTIFICATE,
187    this.base64.encode(certificate.getEncoded(), 64));
188   
189  14 return document;
190    } catch (Exception e) {
191  0 throw new CertificateStoreException("Error while preparing certificate for store [" + store + "]", e);
192    }
193    }
194   
195    /**
196    * Find the reference of the XObject storing a matching certificate in the given store.
197    *
198    * @param store the reference to a document or space used to store certificates.
199    * @param publicKey the certificate to find the storage for.
200    * @return a reference to the XObject storing a matching certificate, or null if none were found.
201    * @throws CertificateStoreException on error.
202    */
 
203  18 toggle protected CertificateObjectReference findCertificate(StoreReference store, X509CertifiedPublicKey publicKey)
204    throws CertificateStoreException
205    {
206  18 byte[] keyId = publicKey.getSubjectKeyIdentifier();
207  18 CertificateObjectReference certRef;
208  18 if (keyId != null) {
209  14 certRef =
210    new X509CertificateReferenceKeyIdentifierQuery(resolveStore(store), this.base64, this.queryManager,
211    this.entityReferenceSerializer)
212    .getReference(keyId);
213    } else {
214  4 certRef =
215    new X509CertificateReferenceIssuerAndSerialQuery(resolveStore(store), this.base64, this.queryManager,
216    this.entityReferenceSerializer)
217    .getReference(publicKey.getIssuer(), publicKey.getSerialNumber());
218    }
219   
220  18 return certRef;
221    }
222   
223    /**
224    * Retrieve the document corresponding to a given certificate object reference.
225    *
226    * @param store the reference of a document or a space where the certificates are stored.
227    * @param certRef the certificate object reference to get document from.
228    * @param context the XWikiContext.
229    * @return the document corresponding to the certificate reference.
230    * @throws XWikiException
231    */
 
232  10 toggle protected XWikiDocument getDocument(StoreReference store, CertificateObjectReference certRef, XWikiContext context)
233    throws XWikiException
234    {
235  10 XWikiDocument document;
236  10 document = context.getWiki().getDocument(
237    new DocumentReference(this.stringReferenceResolver.resolve(certRef.getDocumentName(),
238    EntityType.DOCUMENT, store)),
239    context);
240  10 return document;
241    }
242   
243    /**
244    * Resolve the given store into a document reference.
245    *
246    * @param store the store to be resolved.
247    * @return a document reference.
248    */
 
249  8 toggle protected DocumentReference getDocumentReference(StoreReference store)
250    {
251  8 return new DocumentReference(this.referenceResolver.resolve(getStoreReference(store), EntityType.DOCUMENT));
252    }
253   
254    /**
255    * Create a document reference appropriate to store the certificate in the given store.
256    *
257    * @param store the reference to a document or space used to store certificates.
258    * @param publicKey the certificate to store.
259    * @return a document reference to an appropriate document for storage.
260    * @throws Exception on error.
261    */
 
262  7 toggle protected DocumentReference getDocumentReference(StoreReference store, X509CertifiedPublicKey publicKey)
263    throws Exception
264    {
265  7 EntityReference reference = getStoreReference(store);
266   
267  7 if (reference.getType() == EntityType.DOCUMENT) {
268  4 return getDocumentReference(store);
269    }
270  3 return new DocumentReference(this.referenceResolver.resolve(
271    new EntityReference(getCertIdentifier(publicKey), EntityType.DOCUMENT), EntityType.DOCUMENT, reference));
272    }
273   
274    /**
275    * Return a unique identifier appropriate for a document name.
276    * If the certificate as a subject key identifier, the result is this encoded identifier.
277    * Else, use the concatenation of the certificate serial number and the issuer name.
278    *
279    * @param publicKey the certificate.
280    * @return a unique identifier.
281    * @throws Exception on error.
282    */
 
283  3 toggle private String getCertIdentifier(X509CertifiedPublicKey publicKey) throws Exception
284    {
285  3 byte[] keyId = publicKey.getSubjectKeyIdentifier();
286  3 if (keyId != null) {
287  2 return this.base64.encode(keyId);
288    }
289  1 return publicKey.getSerialNumber().toString() + ", " + publicKey.getIssuer().getName();
290    }
291   
292    /**
293    * Resolve a given store into a complete reference (either space or document).
294    *
295    * @param store the store to be resolved.
296    * @return a complete entity reference.
297    */
 
298  26 toggle protected EntityReference resolveStore(StoreReference store)
299    {
300  26 EntityReference reference = getStoreReference(store);
301   
302  26 if (reference.getType() == EntityType.DOCUMENT) {
303  12 return this.referenceResolver.resolve(reference, EntityType.DOCUMENT);
304    }
305   
306  14 return this.referenceResolver.resolve(reference, EntityType.SPACE);
307    }
308   
 
309  41 toggle private EntityReference getStoreReference(StoreReference store)
310    {
311  41 if (store instanceof WikiStoreReference) {
312  41 return ((WikiStoreReference) store).getReference();
313    }
314  0 throw new IllegalArgumentException("Unsupported store reference [" + store.getClass().getName()
315    + "] for this implementation.");
316    }
317    }