001: /*************************************************************************
002: * *
003: * EJBCA: The OpenSource Certificate Authority *
004: * *
005: * This software is free software; you can redistribute it and/or *
006: * modify it under the terms of the GNU Lesser General Public *
007: * License as published by the Free Software Foundation; either *
008: * version 2.1 of the License, or any later version. *
009: * *
010: * See terms of license at gnu.org. *
011: * *
012: *************************************************************************/package org.ejbca.core.protocol.xkms.generators;
013:
014: import java.security.cert.CertificateException;
015: import java.security.cert.CertificateExpiredException;
016: import java.security.cert.CertificateNotYetValidException;
017: import java.security.cert.X509Certificate;
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.Date;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import javax.xml.bind.JAXBElement;
025:
026: import org.apache.log4j.Logger;
027: import org.ejbca.core.model.InternalResources;
028: import org.ejbca.core.model.ca.crl.RevokedCertInfo;
029: import org.ejbca.core.model.ca.store.CertificateInfo;
030: import org.ejbca.core.model.ra.UserDataVO;
031: import org.ejbca.core.protocol.xkms.common.XKMSConstants;
032: import org.ejbca.util.CertTools;
033: import org.ejbca.util.query.IllegalQueryException;
034: import org.ejbca.util.query.Query;
035: import org.ejbca.util.query.UserMatch;
036: import org.w3._2000._09.xmldsig_.KeyInfoType;
037: import org.w3._2000._09.xmldsig_.X509DataType;
038: import org.w3._2002._03.xkms_.QueryKeyBindingType;
039: import org.w3._2002._03.xkms_.RequestAbstractType;
040: import org.w3._2002._03.xkms_.UseKeyWithType;
041:
042: /**
043: * Class generating a response for a locate and validate calls
044: *
045: *
046: * @author Philip Vendil 2006 sep 27
047: *
048: * @version $Id: KISSResponseGenerator.java,v 1.4 2007/01/07 19:44:14 herrvendil Exp $
049: */
050:
051: public class KISSResponseGenerator extends
052: RequestAbstractTypeResponseGenerator {
053:
054: private static Logger log = Logger
055: .getLogger(KISSResponseGenerator.class);
056:
057: private static final InternalResources intres = InternalResources
058: .getInstance();
059:
060: public KISSResponseGenerator(String remoteIP,
061: RequestAbstractType req) {
062: super (remoteIP, req);
063: }
064:
065: /**
066: * Method that should check the request and find
067: * the appropriate certificates
068: * @param queryKeyBindingType
069: * @param name
070: * @param result
071: * @return A List of matching certificates
072: */
073: protected List<X509Certificate> processRequest(
074: QueryKeyBindingType queryKeyBindingType) {
075: ArrayList<X509Certificate> retval = new ArrayList<X509Certificate>();
076:
077: int resSize = getResponseLimit() + 1;
078:
079: if (queryKeyBindingType.getTimeInstant() != null) {
080: // TimeInstant in QueryKeyBinding not supported.
081: resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER;
082: resultMinor = XKMSConstants.RESULTMINOR_TIMEINSTANTNOTSUPPORTED;
083:
084: return retval;
085: }
086:
087: // If keyInfo Exists
088: if (queryKeyBindingType.getKeyInfo() != null) {
089: X509Certificate queryCert = null;
090: // Only X509 Certificate and X509Chain is supported
091: KeyInfoType keyInfoType = queryKeyBindingType.getKeyInfo();
092:
093: if (keyInfoType.getContent().size() > 0) {
094: JAXBElement<X509DataType> x509DataType = (JAXBElement<X509DataType>) keyInfoType
095: .getContent().get(0);
096:
097: Iterator iter = x509DataType
098: .getValue()
099: .getX509IssuerSerialOrX509SKIOrX509SubjectName()
100: .iterator();
101: while (iter.hasNext()) {
102: JAXBElement next = (JAXBElement) iter.next();
103: if (next.getName().getLocalPart().equals(
104: "X509Certificate")) {
105: byte[] encoded = (byte[]) next.getValue();
106:
107: try {
108: X509Certificate nextCert = CertTools
109: .getCertfromByteArray(encoded);
110: if (nextCert.getBasicConstraints() == -1) {
111: queryCert = nextCert;
112: }
113: } catch (CertificateException e) {
114: log
115: .error(
116: intres
117: .getLocalizedMessage("xkms.errordecodingcert"),
118: e);
119: resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER;
120: resultMinor = XKMSConstants.RESULTMINOR_FAILURE;
121: }
122:
123: } else {
124: resultMajor = XKMSConstants.RESULTMAJOR_SENDER;
125: resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED;
126: }
127: }
128:
129: if (queryCert != null
130: && fulfillsKeyUsageAndUseKeyWith(
131: queryKeyBindingType, queryCert)) {
132: retval.add(queryCert);
133: } else {
134: resultMajor = XKMSConstants.RESULTMAJOR_SUCCESS;
135: resultMinor = XKMSConstants.RESULTMINOR_NOMATCH;
136: }
137: } else {
138: resultMajor = XKMSConstants.RESULTMAJOR_SENDER;
139: resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED;
140: }
141: } else {
142: // Check that UseKeyWith isn't empty
143: if (queryKeyBindingType.getUseKeyWith().size() > 0) {
144: Query query = genQueryFromUseKeyWith(queryKeyBindingType
145: .getUseKeyWith());
146:
147: try {
148: Collection userDatas = getUserAdminSession().query(
149: pubAdmin, query, null, null, resSize);
150:
151: Iterator<UserDataVO> userIter = userDatas
152: .iterator();
153: while (userIter.hasNext()
154: && retval.size() <= resSize) {
155: UserDataVO nextUser = userIter.next();
156: // Find all the certificates of the mathing users
157: try {
158: Collection userCerts = getCertStoreSession()
159: .findCertificatesByUsername(
160: pubAdmin,
161: nextUser.getUsername());
162: // For all the certificates
163: Iterator<X509Certificate> userCertIter = userCerts
164: .iterator();
165: while (userCertIter.hasNext()
166: && retval.size() <= resSize) {
167: X509Certificate nextCert = userCertIter
168: .next();
169: try {
170: // Check that the certificate is valid
171: nextCert.checkValidity(new Date());
172: // and not revoked
173: CertificateInfo certInfo = getCertStoreSession()
174: .getCertificateInfo(
175: pubAdmin,
176: CertTools
177: .getFingerprintAsString(nextCert));
178: if (certInfo.getRevocationReason() == RevokedCertInfo.NOT_REVOKED) {
179: if (fulfillsKeyUsageAndUseKeyWith(
180: queryKeyBindingType,
181: nextCert)) {
182: retval.add(nextCert);
183: }
184: }
185: } catch (CertificateExpiredException e) {
186: } catch (CertificateNotYetValidException e) {
187: }
188: }
189: } catch (Exception e) {
190: log
191: .error(
192: intres
193: .getLocalizedMessage("xkms.errorcreatesession"),
194: e);
195: resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER;
196: resultMinor = XKMSConstants.RESULTMINOR_FAILURE;
197: }
198:
199: }
200:
201: } catch (IllegalQueryException e) {
202: log
203: .error(
204: intres
205: .getLocalizedMessage("xkms.illegaluserquery"),
206: e);
207: resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER;
208: resultMinor = XKMSConstants.RESULTMINOR_FAILURE;
209: }
210: } else {
211: resultMajor = XKMSConstants.RESULTMAJOR_SENDER;
212: resultMinor = XKMSConstants.RESULTMINOR_MESSAGENOTSUPPORTED;
213: }
214:
215: }
216:
217: if (resultMajor == null) {
218: if (retval.size() == getResponseLimit() + 1) {
219: retval.remove(retval.size() - 1);
220: resultMajor = XKMSConstants.RESULTMAJOR_SUCCESS;
221: resultMinor = XKMSConstants.RESULTMINOR_TOOMANYRESPONSES;
222: }
223:
224: if (retval.size() == 0) {
225: resultMajor = XKMSConstants.RESULTMAJOR_SUCCESS;
226: resultMinor = XKMSConstants.RESULTMINOR_NOMATCH;
227: }
228: }
229:
230: return retval;
231: }
232:
233: private boolean fulfillsKeyUsageAndUseKeyWith(
234: QueryKeyBindingType queryKeyBindingType,
235: X509Certificate cert) {
236: boolean retval = true;
237: // Check that the certificate fullfills the key usage spec
238: if (queryKeyBindingType.getKeyUsage().size() != 0) {
239: List<String> certKeyUsages = getCertKeyUsageSpec(cert);
240: Iterator<String> iter = queryKeyBindingType.getKeyUsage()
241: .iterator();
242: while (iter.hasNext()) {
243: String next = iter.next();
244: if (!certKeyUsages.contains(next)) {
245: retval = false;
246: break;
247: }
248: }
249:
250: }
251:
252: if (retval == true) {
253: // Check that the certificate fullfills the usekeywith spec
254: if (queryKeyBindingType.getUseKeyWith().size() != 0) {
255: try {
256: List<UseKeyWithType> certUseKeyWithList = genUseKeyWithAttributes(
257: cert, queryKeyBindingType.getUseKeyWith());
258: if (certUseKeyWithList.size() == 0) {
259: retval = false;
260: }
261: } catch (Exception e) {
262: log
263: .error(
264: intres
265: .getLocalizedMessage("xkms.errorextractingusekeywith"),
266: e);
267: resultMajor = XKMSConstants.RESULTMAJOR_RECIEVER;
268: resultMinor = XKMSConstants.RESULTMINOR_FAILURE;
269: }
270: }
271: }
272:
273: return retval;
274: }
275:
276: /**
277: * Method that checks that the given respondWith specification is valid.
278: * I.e contains one supported RespondWith tag.
279: */
280: public boolean checkValidRespondWithRequest(
281: List<String> respondWithList) {
282: boolean returnval = false;
283:
284: String[] supportedRespondWith = {
285: XKMSConstants.RESPONDWITH_KEYNAME,
286: XKMSConstants.RESPONDWITH_KEYVALUE,
287: XKMSConstants.RESPONDWITH_X509CERT,
288: XKMSConstants.RESPONDWITH_X509CHAIN,
289: XKMSConstants.RESPONDWITH_X509CRL };
290:
291: for (int i = 0; i < supportedRespondWith.length; i++) {
292: returnval |= respondWithList
293: .contains(supportedRespondWith[i]);
294: if (returnval) {
295: break;
296: }
297: }
298:
299: return returnval;
300: }
301:
302: protected Query genQueryFromUseKeyWith(List<UseKeyWithType> list) {
303: Query retval = new Query(Query.TYPE_USERQUERY);
304: boolean retvalEmpty = true;
305:
306: Iterator<UseKeyWithType> iter = list.iterator();
307: while (iter.hasNext()) {
308:
309: if (!retvalEmpty) {
310: retval.add(Query.CONNECTOR_OR);
311: }
312:
313: UseKeyWithType useKeyWithType = iter.next();
314: if (useKeyWithType.getApplication().equals(
315: XKMSConstants.USEKEYWITH_XKMS)
316: || useKeyWithType.getApplication().equals(
317: XKMSConstants.USEKEYWITH_XKMSPROFILE)
318: || useKeyWithType.getApplication().equals(
319: XKMSConstants.USEKEYWITH_TLS)) {
320: retval.add(UserMatch.MATCH_WITH_URI,
321: UserMatch.MATCH_TYPE_BEGINSWITH, useKeyWithType
322: .getIdentifier());
323: retvalEmpty = false;
324: }
325: if (useKeyWithType.getApplication().equals(
326: XKMSConstants.USEKEYWITH_SMIME)
327: || useKeyWithType.getApplication().equals(
328: XKMSConstants.USEKEYWITH_PGP)) {
329: retval.add(UserMatch.MATCH_WITH_RFC822NAME,
330: UserMatch.MATCH_TYPE_BEGINSWITH, useKeyWithType
331: .getIdentifier());
332: retvalEmpty = false;
333: }
334: if (useKeyWithType.getApplication().equals(
335: XKMSConstants.USEKEYWITH_TLSHTTP)) {
336: retval.add(UserMatch.MATCH_WITH_COMMONNAME,
337: UserMatch.MATCH_TYPE_BEGINSWITH, useKeyWithType
338: .getIdentifier());
339: retvalEmpty = false;
340: }
341: if (useKeyWithType.getApplication().equals(
342: XKMSConstants.USEKEYWITH_TLSSMTP)) {
343: retval.add(UserMatch.MATCH_WITH_DNSNAME,
344: UserMatch.MATCH_TYPE_BEGINSWITH, useKeyWithType
345: .getIdentifier());
346: retvalEmpty = false;
347: }
348: if (useKeyWithType.getApplication().equals(
349: XKMSConstants.USEKEYWITH_IPSEC)) {
350: retval.add(UserMatch.MATCH_WITH_IPADDRESS,
351: UserMatch.MATCH_TYPE_BEGINSWITH, useKeyWithType
352: .getIdentifier());
353: retvalEmpty = false;
354: }
355: if (useKeyWithType.getApplication().equals(
356: XKMSConstants.USEKEYWITH_PKIX)) {
357: retval.add(UserMatch.MATCH_WITH_DN,
358: UserMatch.MATCH_TYPE_EQUALS, CertTools
359: .stringToBCDNString(useKeyWithType
360: .getIdentifier()));
361: retvalEmpty = false;
362: }
363:
364: }
365:
366: return retval;
367: }
368:
369: }
|