DefaultVerifier | Line # 104 | 77 | 31 | 61.5% |
0.6148148
|
(1) | |||
Result | |||
0.43703705
|
issrg.test.ds.TestDS.testIssuing issrg.test.ds.TestDS.testIssuing | 1 PASS | |
1 | /* | |
2 | * Copyright (c) 2000-2005, University of Salford | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are met: | |
7 | * | |
8 | * Redistributions of source code must retain the above copyright notice, this | |
9 | * list of conditions and the following disclaimer. | |
10 | * | |
11 | * Redistributions in binary form must reproduce the above copyright notice, | |
12 | * this list of conditions and the following disclaimer in the documentation | |
13 | * and/or other materials provided with the distribution. | |
14 | * | |
15 | * Neither the name of the University of Salford nor the names of its | |
16 | * contributors may be used to endorse or promote products derived from this | |
17 | * software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | |
31 | /* | |
32 | * Copyright (c) 2006, University of Kent | |
33 | * All rights reserved. | |
34 | * | |
35 | * Redistribution and use in source and binary forms, with or without | |
36 | * modification, are permitted provided that the following conditions are met: | |
37 | * | |
38 | * Redistributions of source code must retain the above copyright notice, this | |
39 | * list of conditions and the following disclaimer. | |
40 | * | |
41 | * Redistributions in binary form must reproduce the above copyright notice, | |
42 | * this list of conditions and the following disclaimer in the documentation | |
43 | * and/or other materials provided with the distribution. | |
44 | * | |
45 | * 1. Neither the name of the University of Kent nor the names of its | |
46 | * contributors may be used to endorse or promote products derived from this | |
47 | * software without specific prior written permission. | |
48 | * | |
49 | * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
50 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
51 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
52 | * PURPOSE ARE DISCLAIMED. | |
53 | * | |
54 | * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
55 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
56 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
57 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
58 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
59 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
60 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
61 | * POSSIBILITY OF SUCH DAMAGE. | |
62 | * | |
63 | * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE | |
64 | * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS | |
65 | * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS | |
66 | * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH | |
67 | * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH | |
68 | * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY | |
69 | * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE | |
70 | * SERIOUS FAULTS, IN THIS SOFTWARE. | |
71 | * | |
72 | * 5. This license is governed, except to the extent that local laws | |
73 | * necessarily apply, by the laws of England and Wales. | |
74 | */ | |
75 | ||
76 | package issrg.security; | |
77 | ||
78 | import issrg.pba.rbac.CustomisePERMIS; | |
79 | ||
80 | import java.security.cert.CertificateFactory; | |
81 | import java.security.cert.CertificateException; | |
82 | import java.security.cert.X509Certificate; | |
83 | import java.security.Signature; | |
84 | ||
85 | import java.io.ByteArrayInputStream; | |
86 | ||
87 | import org.apache.log4j.*; | |
88 | /** | |
89 | * This is the default implementation of a Verifier. It can validate signatures | |
90 | * on the given objects. This component doesn't require any user interaction | |
91 | * and can be used in interface-less applications (e.g. servers). | |
92 | * | |
93 | * <p>This default security supports: | |
94 | * <ul> | |
95 | * <br><li>signature verification, given the PKC</li> | |
96 | * <br><li>validation of the PKCs, given the root CA PKC, and given | |
97 | * certification path is not | |
98 | * deeper than 1 hop (i.e. root CA->end-user)</li> In this case the PKCs of | |
99 | * end-users are retrieved from a given PKCRepository | |
100 | * </ul> | |
101 | * @author A.Otenko | |
102 | */ | |
103 | ||
104 | public class DefaultVerifier implements Verifier { | |
105 | Logger logger = Logger.getLogger("issrg.security.DefaultVerifier"); | |
106 | CertificateFactory cf; | |
107 | ||
108 | X509Certificate [] roots=null; | |
109 | PKCRepository rep=null; | |
110 | ||
111 | /** | |
112 | * This constructor initialises the DefaultVerifier. | |
113 | * | |
114 | * @throws SecurityException, if there were no CertificateFactories found for | |
115 | * "X.509" certificates in this instance of JVM | |
116 | */ | |
117 | 7 | public DefaultVerifier() throws SecurityException { |
118 | 7 | try{ |
119 | 7 | cf = CertificateFactory.getInstance("X.509"); |
120 | }catch (CertificateException ce){ | |
121 | 0 | if(logger.isDebugEnabled()) logger.debug("Could not instantiate a X.509 Certificate factory", ce); |
122 | 0 | throw new SecurityException("Could not instantiate a X.509 Certificate factory", ce); |
123 | } | |
124 | } | |
125 | ||
126 | /** | |
127 | * Sets the root CA by specifying its PKC. | |
128 | * | |
129 | * @param pkc is the BER encoded X.509 PKC of the root CA | |
130 | */ | |
131 | 3 | public void setRootCA(byte [] pkc) throws SecurityException { |
132 | 3 | setRootCAs(new byte[][]{pkc}); |
133 | } | |
134 | ||
135 | /** | |
136 | * Sets the root CA by specifying its PKC. | |
137 | * | |
138 | * @param pkc is the X.509 PKC of the root CA | |
139 | */ | |
140 | 1 | public void setRootCA(X509Certificate pkc) { |
141 | 1 | setRootCAs(new X509Certificate[]{pkc}); |
142 | } | |
143 | ||
144 | /** | |
145 | * This method sets multiple roots of trust by providing their X.509 PKCs. | |
146 | * | |
147 | * @param pkcs - the Public Key Certificates of the CAs | |
148 | */ | |
149 | 4 | public void setRootCAs(X509Certificate [] pkcs) { |
150 | 4 | roots=pkcs; |
151 | } | |
152 | ||
153 | /** | |
154 | * This method returns the array of PKCs of multiple roots of trust. | |
155 | * | |
156 | * @return array of X509Certificate, which can be empty or null, if no roots | |
157 | * of trust have been specified | |
158 | */ | |
159 | 4 | public X509Certificate[] getRootCAs(){ |
160 | 4 | return roots; |
161 | } | |
162 | ||
163 | /** | |
164 | * This method lets you specify multiple Root CAs. If any of them is | |
165 | * a malformed PKC, there will be a SecurityException. | |
166 | * | |
167 | * @param pkcs - an array of BER-encoded X.509 PKCs | |
168 | */ | |
169 | 3 | public void setRootCAs(byte[][] pkcs) throws SecurityException { |
170 | 3 | try{ |
171 | 3 | roots=new X509Certificate[pkcs.length]; |
172 | 6 | for (int i=0; i<roots.length; i++){ |
173 | 3 | roots[i]=(X509Certificate)cf.generateCertificate(new ByteArrayInputStream(pkcs[i])); |
174 | 0 | if(logger.isDebugEnabled()) logger.debug(roots[i].toString()); |
175 | } | |
176 | }catch (java.security.cert.CertificateException ce){ | |
177 | 0 | if(logger.isDebugEnabled()) logger.debug("Certificate decoding error", ce); |
178 | 0 | throw new SecurityException("Certificate decoding error", ce); |
179 | } | |
180 | } | |
181 | ||
182 | /** | |
183 | * Sets the repository that will be used to retrieve user's signature | |
184 | * verification Public Key Certificates. | |
185 | * | |
186 | * @param repository - the PKCRepository that can return the PKCs for a | |
187 | * given principal | |
188 | */ | |
189 | 4 | public void setPKCRepository(PKCRepository repository) { |
190 | 4 | rep=repository; |
191 | } | |
192 | ||
193 | /* | |
194 | * VERIFIER METHODS | |
195 | */ | |
196 | ||
197 | /** | |
198 | * Retrieves the valid certificates of the signer. For this purpose it | |
199 | * contacts the PKCRepository and retrieves | |
200 | * all user certificates from the specified entry. Then the signatures are | |
201 | * verified on them. They should be signed | |
202 | * by one of the Root CAs directly. Malformed user certificates are discarded. | |
203 | * | |
204 | * <p>Certification path validation will be added later. | |
205 | * | |
206 | * @param signerName is the name of the signer's LDAP entry | |
207 | * | |
208 | * @return all valid certificates located in that LDAP entry; never null, but | |
209 | * can be an empty array | |
210 | * | |
211 | * @throws SecurityException if there were errors during processing the | |
212 | * request | |
213 | */ | |
214 | 1009 | public java.security.cert.X509Certificate [] getVerificationCertificates(issrg.utils.repository.TokenLocator signerName) throws SecurityException { |
215 | 1009 | if (roots==null){ |
216 | 0 | throw new SecurityException("Cannot validate the certificates; Root CAs are not specified"); |
217 | } | |
218 | ||
219 | 1009 | try{ |
220 | 0 | if(logger.isDebugEnabled()) logger.debug("getting verification certificates for: "+signerName.getEntry().getEntryName().getName()); |
221 | //System.out.println("getting verification certificates for: "+signerName.getName()); //********** | |
222 | ||
223 | 1009 | javax.naming.directory.Attribute pkcs=null; |
224 | 1009 | if (rep!=null) pkcs=rep.getUserCertificate(signerName); // note, that this code will also retrieve other self-signed certificates of the rootCA. useful for getting userCertificates of the CA |
225 | ||
226 | 1009 | if (pkcs==null){ // the repository can be unspecified. in this case only the rootCA can be a signer |
227 | 0 | pkcs=new javax.naming.directory.BasicAttribute(PKCRepository.USER_PKC_ATTRIBUTE); |
228 | } | |
229 | ||
230 | // now lets verify the signatures on those PKCs | |
231 | //java.security.cert.X509Certificate [] root=new java.security.cert.X509Certificate[]{rootCA}; | |
232 | 1009 | java.util.Vector v=new java.util.Vector(); // vector of valid PKCs |
233 | 0 | if(logger.isDebugEnabled()) logger.debug("got "+pkcs); |
234 | //System.out.println("got "+pkcs); //********** | |
235 | ||
236 | 2018 | for (int i=pkcs.size(); i-->0;){ |
237 | 1009 | boolean valid=false; |
238 | 1009 | try{ |
239 | 0 | if(logger.isDebugEnabled()) logger.debug("PKC["+i+"] : "+pkcs.get(i)); |
240 | //System.out.println("PKC["+i+"] : "+pkcs.get(i)); //********** | |
241 | 1009 | byte[] pkc = null; |
242 | 0 | if (CustomisePERMIS.isMultiParserUsed()) pkc = (byte[])((issrg.pba.RawCredential)pkcs.get(i)).getCredential(); |
243 | 1009 | else pkc = (byte[])pkcs.get(i); |
244 | 1009 | X509Certificate c=(X509Certificate)cf.generateCertificate(new ByteArrayInputStream(pkc)); |
245 | ||
246 | // usually I would need to verify that the DN is the same, too... | |
247 | // lets omit it for brewity. can the DN be different, if the signature matches? | |
248 | // c.getIssuerDN().equals(rootCA.getSubjectDN()) | |
249 | 1009 | valid=verifyByRoot(c.getTBSCertificate(), c.getSignature(), c.getSigAlgOID()); |
250 | 1009 | if (valid){ |
251 | 0 | if(logger.isDebugEnabled()) logger.debug("PKC["+i+"] is valid"); |
252 | //System.out.println("PKC["+i+"] is valid"); //********** | |
253 | 1009 | v.add(c); |
254 | } | |
255 | }catch(Exception ce){ //ignore invalid PKCs | |
256 | 0 | if(logger.isDebugEnabled()) logger.debug("Invalid PKC : " + ce.getMessage()); |
257 | } | |
258 | } | |
259 | ||
260 | 2018 | for (int i=0; i<roots.length; i++){ |
261 | 1009 | if (signerName.getEntry().getEntryName().equals(roots[i].getSubjectDN())){ |
262 | 1 | v.add(roots[i]); |
263 | } | |
264 | } | |
265 | ||
266 | 1009 | java.security.cert.X509Certificate [] certs=(java.security.cert.X509Certificate[])v.toArray(new java.security.cert.X509Certificate[0]); |
267 | ||
268 | 1009 | return certs; |
269 | }catch(Exception e){ | |
270 | 0 | if(logger.isDebugEnabled()) logger.debug("Error while getting certificates", e); |
271 | 0 | throw new SecurityException("Error while getting certificates", e); |
272 | } | |
273 | } | |
274 | ||
275 | /** | |
276 | * This method verifies a signature on the data. It assumes that all X.509 | |
277 | * certificates are still valid and non-revoked in the array. | |
278 | * It is so if they have been retrieved using getVerificationCertificates | |
279 | * method. | |
280 | * In fact, for this reason it uses only the first certificate in the array, | |
281 | * which should be the signature verification certificate | |
282 | * of the signer. | |
283 | * | |
284 | * @param data is the to-be-signed array | |
285 | * @param signature is the signature of that array | |
286 | * @param certs is the array of X.509 PKCs, but only the first one is used in | |
287 | * this implementation | |
288 | * | |
289 | * @return true, if the signature validates; false otherwise | |
290 | * | |
291 | * @throws SecurityException, if there were errors during processing the | |
292 | * request | |
293 | */ | |
294 | 2023 | public boolean verify(byte [] data, byte[] signature, String algorithmID, X509Certificate[] certs) throws SecurityException { |
295 | 2023 | try{ |
296 | 0 | if(logger.isDebugEnabled()) logger.debug(certs[0].getSubjectDN().getName()+" is the holder of the PKC"); |
297 | //System.out.println(certs[0].getSubjectDN().getName()+" is the holder of the PKC"); //************ | |
298 | 2023 | Signature sig = Signature.getInstance(algorithmID); |
299 | ||
300 | 2023 | sig.initVerify(certs[0].getPublicKey()); |
301 | 2023 | sig.update(data); |
302 | 2023 | boolean v = sig.verify(signature); |
303 | 2023 | logger.debug("signature verification = "+v); |
304 | 2023 | return v; |
305 | }catch (Exception e){ | |
306 | 0 | if(logger.isDebugEnabled()) logger.debug("Error while verifying the signature", e); |
307 | 0 | throw new SecurityException("Error while verifying the signature", e); |
308 | } | |
309 | } | |
310 | ||
311 | /** | |
312 | * This method checks if the given data was signed by any of the Root CAs. | |
313 | * | |
314 | * @param data - the to-be-signed byte array | |
315 | * @param signature - the matching signature | |
316 | * @param algorithmID - the signature algorithm identifier | |
317 | * | |
318 | * @return true, if the signature can be verified using one of the PKCs of | |
319 | * the roots of trust; false otherwise (e.g. no Root CAs have been | |
320 | * configured, or there was a problem during signature verification) | |
321 | */ | |
322 | 1009 | public boolean verifyByRoot(byte [] data, byte[] signature, String algorithmID) { |
323 | 1009 | if (roots!=null) for (int i=0; i<roots.length; i++){ |
324 | 1009 | try{ |
325 | 1009 | if (verify(data, signature, algorithmID, new X509Certificate[]{roots[i]})) return true; |
326 | }catch (Exception e){ | |
327 | 0 | if(logger.isDebugEnabled()) logger.debug("Error while verifying the signature", e); |
328 | //throw new SecurityException("Error while verifying the signature", e); | |
329 | } | |
330 | } | |
331 | 0 | return false; // returns false, if none fsof the certificates validates the signature |
332 | } | |
333 | } |
|