KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > protocol > cmp > CrmfMessageHandler


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13
14 package org.ejbca.core.protocol.cmp;
15
16 import java.io.IOException JavaDoc;
17 import java.rmi.RemoteException JavaDoc;
18 import java.security.InvalidKeyException JavaDoc;
19 import java.security.NoSuchAlgorithmException JavaDoc;
20 import java.security.NoSuchProviderException JavaDoc;
21 import java.util.Properties JavaDoc;
22
23 import javax.ejb.CreateException JavaDoc;
24 import javax.ejb.DuplicateKeyException JavaDoc;
25 import javax.ejb.FinderException JavaDoc;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.log4j.Logger;
29 import org.bouncycastle.asn1.DEROctetString;
30 import org.ejbca.core.ejb.ServiceLocator;
31 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionHome;
32 import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionRemote;
33 import org.ejbca.core.ejb.ca.sign.ISignSessionHome;
34 import org.ejbca.core.ejb.ca.sign.ISignSessionRemote;
35 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionHome;
36 import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionRemote;
37 import org.ejbca.core.ejb.ra.IUserAdminSessionHome;
38 import org.ejbca.core.ejb.ra.IUserAdminSessionRemote;
39 import org.ejbca.core.ejb.ra.raadmin.IRaAdminSessionHome;
40 import org.ejbca.core.ejb.ra.raadmin.IRaAdminSessionRemote;
41 import org.ejbca.core.model.InternalResources;
42 import org.ejbca.core.model.SecConst;
43 import org.ejbca.core.model.approval.ApprovalException;
44 import org.ejbca.core.model.approval.WaitingForApprovalException;
45 import org.ejbca.core.model.authorization.AuthorizationDeniedException;
46 import org.ejbca.core.model.ca.AuthLoginException;
47 import org.ejbca.core.model.ca.AuthStatusException;
48 import org.ejbca.core.model.ca.IllegalKeyException;
49 import org.ejbca.core.model.ca.SignRequestException;
50 import org.ejbca.core.model.ca.SignRequestSignatureException;
51 import org.ejbca.core.model.ca.caadmin.CADoesntExistsException;
52 import org.ejbca.core.model.ca.caadmin.CAInfo;
53 import org.ejbca.core.model.log.Admin;
54 import org.ejbca.core.model.ra.NotFoundException;
55 import org.ejbca.core.model.ra.UserDataConstants;
56 import org.ejbca.core.model.ra.UserDataVO;
57 import org.ejbca.core.model.ra.UsernameGenerator;
58 import org.ejbca.core.model.ra.UsernameGeneratorParams;
59 import org.ejbca.core.model.ra.raadmin.UserDoesntFullfillEndEntityProfile;
60 import org.ejbca.core.protocol.FailInfo;
61 import org.ejbca.core.protocol.IResponseMessage;
62 import org.ejbca.core.protocol.ResponseStatus;
63 import org.ejbca.util.Base64;
64 import org.ejbca.util.passgen.IPasswordGenerator;
65 import org.ejbca.util.passgen.PasswordGeneratorFactory;
66
67 import com.novosec.pkix.asn1.cmp.PKIHeader;
68
69 /**
70  * Message handler for certificate request messages in the CRMF format
71  * @author tomas
72  * @version $Id: CrmfMessageHandler.java,v 1.20 2006/12/13 11:23:51 anatom Exp $
73  */

74 public class CrmfMessageHandler implements ICmpMessageHandler {
75     
76     private static Logger log = Logger.getLogger(CrmfMessageHandler.class);
77     /** Internal localization of logs and errors */
78     private static final InternalResources intres = InternalResources.getInstance();
79     
80     /** Defines which component from the DN should be used as username in EJBCA. Can be DN, UID or nothing. Nothing means that the DN will be used to look up the user. */
81     private String JavaDoc extractUsernameComponent = null;
82     /** Parameters used for username generation if we are using RA mode to create users */
83     private UsernameGeneratorParams usernameGeneratorParams = null;
84     /** The endEntityProfile to be used when adding users in RA mode */
85     private int eeProfileId = 0;
86     /** The certificate profile to use when adding users in RA mode */
87     private int certProfileId = 0;
88     /** Tha CA to user when adding users in RA mode */
89     private int caId = 0;
90     /** Parameter used to authenticate RA messages if we are using RA mode to create users */
91     private String JavaDoc raAuthenticationSecret = null;
92     /** Parameter used to determine the type of prtection for the response message */
93     private String JavaDoc responseProtection = null;
94     
95     private Admin admin;
96     private ISignSessionRemote signsession = null;
97     private IUserAdminSessionRemote usersession = null;
98     private ICAAdminSessionRemote casession = null;
99     private IRaAdminSessionRemote rasession = null;
100     private ICertificateStoreSessionRemote storesession = null;
101 // private ISignSessionLocal signsession = null;
102
// private IUserAdminSessionLocal usersession = null;
103
// private ICAAdminSessionLocal casession = null;
104
// private IRaAdminSessionLocal rasession = null;
105
// private ICertificateStoreSessionLocal storesession = null;
106

107     
108     public CrmfMessageHandler(Admin admin, Properties JavaDoc prop) throws CreateException JavaDoc, RemoteException JavaDoc {
109         this.admin = admin;
110         // Get EJB beans, we can not use local beans here because the MBean used for the TCP listener does not work with that
111
ISignSessionHome signHome = (ISignSessionHome)ServiceLocator.getInstance().getRemoteHome(ISignSessionHome.JNDI_NAME, ISignSessionHome.class);
112         IUserAdminSessionHome userHome = (IUserAdminSessionHome) ServiceLocator.getInstance().getRemoteHome(IUserAdminSessionHome.JNDI_NAME, IUserAdminSessionHome.class);
113         ICAAdminSessionHome caHome = (ICAAdminSessionHome) ServiceLocator.getInstance().getRemoteHome(ICAAdminSessionHome.JNDI_NAME, ICAAdminSessionHome.class);
114         IRaAdminSessionHome raHome = (IRaAdminSessionHome) ServiceLocator.getInstance().getRemoteHome(IRaAdminSessionHome.JNDI_NAME, IRaAdminSessionHome.class);
115         ICertificateStoreSessionHome storeHome = (ICertificateStoreSessionHome) ServiceLocator.getInstance().getRemoteHome(ICertificateStoreSessionHome.JNDI_NAME, ICertificateStoreSessionHome.class);
116 // ISignSessionLocalHome signHome = (ISignSessionLocalHome) ServiceLocator.getInstance().getLocalHome(ISignSessionLocalHome.COMP_NAME);
117
// IUserAdminSessionLocalHome userHome = (IUserAdminSessionLocalHome) ServiceLocator.getInstance().getLocalHome(IUserAdminSessionLocalHome.COMP_NAME);
118
// ICAAdminSessionLocalHome caHome = (ICAAdminSessionLocalHome) ServiceLocator.getInstance().getLocalHome(ICAAdminSessionLocalHome.COMP_NAME);
119
// IRaAdminSessionLocalHome raHome = (IRaAdminSessionLocalHome) ServiceLocator.getInstance().getLocalHome(IRaAdminSessionLocalHome.COMP_NAME);
120
// ICertificateStoreSessionLocalHome storeHome = (ICertificateStoreSessionLocalHome) ServiceLocator.getInstance().getLocalHome(ICertificateStoreSessionLocalHome.COMP_NAME);
121
this.signsession = signHome.create();
122         this.usersession = userHome.create();
123         this.casession = caHome.create();
124         this.rasession = raHome.create();
125         this.storesession = storeHome.create();
126
127         String JavaDoc str = prop.getProperty("operationMode");
128         log.debug("operationMode="+str);
129         if (StringUtils.equalsIgnoreCase(str, "ra")) {
130             // create UsernameGeneratorParams
131
usernameGeneratorParams = new UsernameGeneratorParams();
132             str = prop.getProperty("raModeNameGenerationScheme");
133             log.debug("raModeNameGenerationScheme="+str);
134             if (StringUtils.isNotEmpty(str)) {
135                 usernameGeneratorParams.setMode(str);
136             }
137             str = prop.getProperty("raModeNameGenerationParameters");
138             log.debug("raModeNameGenerationParameters="+str);
139             if (StringUtils.isNotEmpty(str)) {
140                 usernameGeneratorParams.setDNGeneratorComponent(str);
141             }
142             str = prop.getProperty("raModeNameGenerationPrefix");
143             log.debug("raModeNameGenerationPrefix="+str);
144             if (StringUtils.isNotEmpty(str)) {
145                 usernameGeneratorParams.setPrefix(str);
146             }
147             str = prop.getProperty("raModeNameGenerationPostfix");
148             log.debug("raModeNameGenerationPostfix="+str);
149             if (StringUtils.isNotEmpty(str)) {
150                 usernameGeneratorParams.setPostfix(str);
151             }
152             str = prop.getProperty("raAuthenticationSecret");
153             if (StringUtils.isNotEmpty(str)) {
154                 log.debug("raAuthenticationSecret is not null");
155                 raAuthenticationSecret = str;
156             }
157             str = prop.getProperty("endEntityProfile");
158             if (StringUtils.isNotEmpty(str)) {
159                 log.debug("endEntityProfile="+str);
160                 eeProfileId = rasession.getEndEntityProfileId(admin, str);
161             }
162             str = prop.getProperty("certificateProfile");
163             if (StringUtils.isNotEmpty(str)) {
164                 log.debug("certificateProfile="+str);
165                 certProfileId = storesession.getCertificateProfileId(admin, str);
166             }
167             str = prop.getProperty("caName");
168             if (StringUtils.isNotEmpty(str)) {
169                 log.debug("caName="+str);
170                 CAInfo info = casession.getCAInfo(admin, str);
171                 caId = info.getCAId();
172             }
173         }
174         str = prop.getProperty("responseProtection");
175         if (StringUtils.isNotEmpty(str)) {
176             log.debug("responseProtection="+str);
177             responseProtection = str;
178         }
179     }
180     public IResponseMessage handleMessage(BaseCmpMessage msg) {
181         log.debug(">handleMessage");
182         IResponseMessage resp = null;
183         try {
184             CrmfRequestMessage crmfreq = null;
185             if (msg instanceof CrmfRequestMessage) {
186                 crmfreq = (CrmfRequestMessage) msg;
187                 crmfreq.getMessage();
188                 int requestId = crmfreq.getRequestId();
189                 int requestType = crmfreq.getRequestType();
190                 // If we have usernameGeneratorParams we want to generate usernames automagically for requests
191
if (usernameGeneratorParams != null) {
192                     // Try to find a HMAC/SHA1 protection key
193
PKIHeader head = crmfreq.getHeader();
194                     DEROctetString os = head.getSenderKID();
195                     if (os != null) {
196                         String JavaDoc keyId = new String JavaDoc(os.getOctets());
197                         log.debug("Found a sender keyId: "+keyId);
198                         try {
199                             CmpPbeVerifyer verifyer = new CmpPbeVerifyer(raAuthenticationSecret, msg.getMessage());
200                             boolean ret = verifyer.verify();
201                             String JavaDoc pbeDigestAlg = verifyer.getOwfOid();
202                             String JavaDoc pbeMacAlg = verifyer.getMacOid();
203                             int pbeIterationCount = verifyer.getIterationCount();
204                             if (ret) {
205                                 // If authentication was correct, we will now create a username and password and register the new user in EJBCA
206
UsernameGenerator gen = UsernameGenerator.getInstance(usernameGeneratorParams);
207                                 String JavaDoc dn = crmfreq.getSubjectDN();
208                                 log.debug("Creating username from base dn: "+dn);
209                                 String JavaDoc username = gen.generateUsername(dn);
210                                 IPasswordGenerator pwdgen = PasswordGeneratorFactory.getInstance(PasswordGeneratorFactory.PASSWORDTYPE_ALLPRINTABLE);
211                                 String JavaDoc pwd = pwdgen.getNewPassword(12, 12);
212                                 // AltNames may be in the request template
213
String JavaDoc altNames = crmfreq.getRequestAltNames();
214                                 boolean addedUser = false; // flag indicating if adding was succesful
215
String JavaDoc failText = null;
216                                 FailInfo failInfo = null;
217                                 try {
218                                     UserDataVO user = null;
219                                     try {
220                                         user = usersession.findUser(admin, username);
221                                     } catch (FinderException JavaDoc e) {
222                                         // User can not be found, leave user as null
223
}
224                                     if (user == null) {
225                                         try {
226                                             log.debug("Creating new user.");
227                                             usersession.addUser(admin, username, pwd, dn, altNames, null, false, eeProfileId, certProfileId, SecConst.USER_ENDUSER, SecConst.TOKEN_SOFT_BROWSERGEN, 0, caId);
228                                         } catch (DuplicateKeyException JavaDoc e) {
229                                             // This was veery strange, we didn't find it before, but now it exists?
230
String JavaDoc errMsg = intres.getLocalizedMessage("cmp.erroradduserupdate", username);
231                                             log.error(errMsg);
232                                             // If the user already exists, we will change him instead and go for that
233
usersession.changeUser(admin, username, pwd, dn, altNames, null, false, eeProfileId, certProfileId, SecConst.USER_ENDUSER, SecConst.TOKEN_SOFT_BROWSERGEN, 0, UserDataConstants.STATUS_NEW, caId);
234                                         }
235                                     } else {
236                                         // If the user already exists, we will change him instead and go for that
237
log.debug("User already exists, so we will update instead.");
238                                         usersession.changeUser(admin, username, pwd, dn, altNames, null, false, eeProfileId, certProfileId, SecConst.USER_ENDUSER, SecConst.TOKEN_SOFT_BROWSERGEN, 0, UserDataConstants.STATUS_NEW, caId);
239                                     }
240                                     addedUser = true;
241                                 } catch (UserDoesntFullfillEndEntityProfile e) {
242                                     String JavaDoc errMsg = intres.getLocalizedMessage("cmp.erroradduser", username);
243                                     log.error(errMsg, e);
244                                     failText = e.getMessage();
245                                 } catch (ApprovalException e) {
246                                     String JavaDoc errMsg = intres.getLocalizedMessage("cmp.erroradduser", username);
247                                     log.error(errMsg, e);
248                                     failText = e.getMessage();
249                                     failInfo = FailInfo.NOT_AUTHORIZED;
250                                 } catch (WaitingForApprovalException e) {
251                                     String JavaDoc errMsg = intres.getLocalizedMessage("cmp.erroradduser", username);
252                                     log.error(errMsg, e);
253                                     failText = e.getMessage();
254                                     failInfo = FailInfo.NOT_AUTHORIZED;
255                                 }
256                                 if (!addedUser) {
257                                     CmpErrorResponseMessage cresp = new CmpErrorResponseMessage();
258                                     cresp.setRecipientNonce(msg.getSenderNonce());
259                                     cresp.setSenderNonce(new String JavaDoc(Base64.encode(CmpMessageHelper.createSenderNonce())));
260                                     cresp.setSender(msg.getRecipient());
261                                     cresp.setRecipient(msg.getSender());
262                                     cresp.setTransactionId(msg.getTransactionId());
263                                     cresp.setFailText(failText);
264                                     cresp.setFailInfo(failInfo);
265                                     cresp.setRequestId(requestId);
266                                     cresp.setRequestType(requestType);
267                                     
268                                     // Set all protection parameters
269
log.debug(responseProtection+", "+pbeDigestAlg+", "+pbeMacAlg+", "+keyId+", "+raAuthenticationSecret);
270                                     if (StringUtils.equals(responseProtection, "pbe") && (pbeDigestAlg != null) && (pbeMacAlg != null) && (keyId != null) && (raAuthenticationSecret != null) ) {
271                                         cresp.setPbeParameters(keyId, raAuthenticationSecret, pbeDigestAlg, pbeMacAlg, pbeIterationCount);
272                                     }
273                                     resp = cresp;
274                                     try {
275                                         resp.create();
276                                     } catch (InvalidKeyException JavaDoc e1) {
277                                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
278                                         log.error(errMsg, e1);
279                                     } catch (NoSuchAlgorithmException JavaDoc e1) {
280                                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
281                                         log.error(errMsg, e1);
282                                     } catch (NoSuchProviderException JavaDoc e1) {
283                                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
284                                         log.error(errMsg, e1);
285                                     } catch (SignRequestException e1) {
286                                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
287                                         log.error(errMsg, e1);
288                                     } catch (NotFoundException e1) {
289                                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
290                                         log.error(errMsg, e1);
291                                     } catch (IOException JavaDoc e1) {
292                                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
293                                         log.error(errMsg, e1);
294                                     }
295                                 }
296                                 crmfreq.setUsername(username);
297                                 crmfreq.setPassword(pwd);
298                                 // Set all protection parameters
299
if (StringUtils.equals(responseProtection, "pbe")) {
300                                     crmfreq.setPbeParameters(keyId, raAuthenticationSecret, pbeDigestAlg, pbeMacAlg, pbeIterationCount);
301                                 }
302                                 // Now we are all set to go ahead and generate a certificate for the poor bastard
303
} else {
304                                 String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorauthmessage");
305                                 log.error(errMsg);
306                                 if (verifyer.getErrMsg() != null) {
307                                     errMsg = verifyer.getErrMsg();
308                                 }
309                                 resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_MESSAGE_CHECK, errMsg);
310                             }
311                         } catch (NoSuchAlgorithmException JavaDoc e) {
312                             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorcalcprotection");
313                             log.error(errMsg, e);
314                             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_MESSAGE_CHECK, e.getMessage());
315                         } catch (NoSuchProviderException JavaDoc e) {
316                             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorcalcprotection");
317                             log.error(errMsg, e);
318                             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_MESSAGE_CHECK, e.getMessage());
319                         } catch (InvalidKeyException JavaDoc e) {
320                             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorcalcprotection");
321                             log.error(errMsg, e);
322                             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_MESSAGE_CHECK, e.getMessage());
323                         }
324                     } else {
325                         String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorunauthmessagera");
326                         log.error(errMsg);
327                         resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_MESSAGE_CHECK, errMsg);
328                     }
329                 } else {
330                     // Try to find the user that is the subject for the request
331
// if extractUsernameComponent is null, we have to find the user from the DN
332
// if not empty the message will find the username itself, in the getUsername method
333
if (StringUtils.isEmpty(extractUsernameComponent)) {
334                         String JavaDoc dn = crmfreq.getSubjectDN();
335                         log.debug("looking for user with dn: "+dn);
336                         UserDataVO data = usersession.findUserBySubjectDN(admin, dn);
337                         if (data != null) {
338                             log.debug("Found username: "+data.getUsername());
339                             crmfreq.setUsername(data.getUsername());
340                         } else {
341                             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.infonouserfordn");
342                             log.info(errMsg);
343                         }
344                     }
345                 }
346             } else {
347                 String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errornocmrfreq");
348                 log.error(errMsg);
349             }
350             // This is a request message, so we want to enroll for a certificate, if we have not created an error already
351
if (resp == null) {
352                 // Get the certificate
353
resp = signsession.createCertificate(admin, crmfreq, -1,
354                         Class.forName("org.ejbca.core.protocol.cmp.CmpResponseMessage"));
355             }
356             if (resp == null) {
357                 String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errornullresp");
358                 log.error(errMsg);
359             }
360         } catch (AuthorizationDeniedException e) {
361             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
362             log.error(errMsg, e);
363         } catch (NotFoundException e) {
364             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
365             log.error(errMsg, e);
366             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_REQUEST, e.getMessage());
367         } catch (AuthStatusException e) {
368             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
369             log.error(errMsg, e);
370             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_REQUEST, e.getMessage());
371         } catch (AuthLoginException e) {
372             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
373             log.error(errMsg, e);
374             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_REQUEST, e.getMessage());
375         } catch (IllegalKeyException e) {
376             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
377             log.error(errMsg, e);
378         } catch (CADoesntExistsException e) {
379             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
380             log.error(errMsg, e);
381             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.WRONG_AUTHORITY, e.getMessage());
382         } catch (SignRequestException e) {
383             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
384             log.error(errMsg, e);
385         } catch (SignRequestSignatureException e) {
386             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
387             log.error(errMsg, e);
388             resp = CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_POP, e.getMessage());
389         } catch (ClassNotFoundException JavaDoc e) {
390             String JavaDoc errMsg = intres.getLocalizedMessage("cmp.errorgeneral");
391             log.error(errMsg, e);
392         } catch (RemoteException JavaDoc e) {
393             // Fatal error
394
String JavaDoc errMsg = intres.getLocalizedMessage("cmp.erroradduser");
395             log.error(errMsg, e);
396             resp = null;
397         }
398         return resp;
399     }
400     
401 }
402
Popular Tags