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.model.approval.approvalrequests;
013:
014: import java.io.File;
015: import java.math.BigInteger;
016: import java.rmi.RemoteException;
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.Random;
023:
024: import javax.ejb.RemoveException;
025: import javax.naming.Context;
026:
027: import junit.framework.TestCase;
028:
029: import org.apache.log4j.Logger;
030: import org.ejbca.core.ejb.approval.IApprovalSessionHome;
031: import org.ejbca.core.ejb.approval.IApprovalSessionRemote;
032: import org.ejbca.core.ejb.authorization.IAuthorizationSessionHome;
033: import org.ejbca.core.ejb.authorization.IAuthorizationSessionRemote;
034: import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionHome;
035: import org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionRemote;
036: import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionHome;
037: import org.ejbca.core.ejb.ca.store.ICertificateStoreSessionRemote;
038: import org.ejbca.core.ejb.ra.IUserAdminSessionHome;
039: import org.ejbca.core.ejb.ra.IUserAdminSessionRemote;
040: import org.ejbca.core.model.SecConst;
041: import org.ejbca.core.model.approval.Approval;
042: import org.ejbca.core.model.approval.ApprovalDataVO;
043: import org.ejbca.core.model.approval.ApprovalException;
044: import org.ejbca.core.model.approval.TestApprovalSession;
045: import org.ejbca.core.model.approval.WaitingForApprovalException;
046: import org.ejbca.core.model.authorization.AdminEntity;
047: import org.ejbca.core.model.authorization.AdminGroup;
048: import org.ejbca.core.model.authorization.AuthorizationDeniedException;
049: import org.ejbca.core.model.ca.caadmin.CAInfo;
050: import org.ejbca.core.model.ca.caadmin.X509CAInfo;
051: import org.ejbca.core.model.ca.catoken.CATokenConstants;
052: import org.ejbca.core.model.ca.catoken.CATokenInfo;
053: import org.ejbca.core.model.ca.catoken.SoftCATokenInfo;
054: import org.ejbca.core.model.ca.crl.RevokedCertInfo;
055: import org.ejbca.core.model.log.Admin;
056: import org.ejbca.core.model.ra.NotFoundException;
057: import org.ejbca.core.model.ra.UserDataConstants;
058: import org.ejbca.core.model.ra.UserDataVO;
059: import org.ejbca.ui.cli.batch.BatchMakeP12;
060: import org.ejbca.util.CertTools;
061: import org.ejbca.util.query.ApprovalMatch;
062: import org.ejbca.util.query.BasicMatch;
063: import org.ejbca.util.query.Query;
064:
065: public class TestRevocationApproval extends TestCase {
066:
067: private static Logger log = Logger
068: .getLogger(TestApprovalSession.class);
069:
070: private static IApprovalSessionRemote approvalSession;
071: private static IAuthorizationSessionRemote authorizationSession;
072: private static IUserAdminSessionRemote userAdminSession;
073: private static ICertificateStoreSessionRemote certificateStoreSession;
074: private static ICAAdminSessionRemote caAdminSession;
075:
076: private static String requestingAdminUsername = null;
077: private static String adminUsername = null;
078:
079: private static final Admin internalAdmin = new Admin(
080: Admin.TYPE_INTERNALUSER);
081: private static Admin reuestingAdmin = null;
082: private static Admin approvingAdmin = null;
083: private static ArrayList adminentities;
084:
085: private static int caid = "CN=TEST".hashCode();
086: private int approvalCAID;
087:
088: protected void setUp() throws Exception {
089: super .setUp();
090: Context ctx = new javax.naming.InitialContext();
091: IApprovalSessionHome approvalSessionHome = (IApprovalSessionHome) javax.rmi.PortableRemoteObject
092: .narrow(ctx.lookup(IApprovalSessionHome.JNDI_NAME),
093: IApprovalSessionHome.class);
094: approvalSession = approvalSessionHome.create();
095: IAuthorizationSessionHome authorizationSessionHome = (IAuthorizationSessionHome) javax.rmi.PortableRemoteObject
096: .narrow(
097: ctx.lookup(IAuthorizationSessionHome.JNDI_NAME),
098: IAuthorizationSessionHome.class);
099: authorizationSession = authorizationSessionHome.create();
100: IUserAdminSessionHome userAdminSessionHome = (IUserAdminSessionHome) javax.rmi.PortableRemoteObject
101: .narrow(ctx.lookup(IUserAdminSessionHome.JNDI_NAME),
102: IUserAdminSessionHome.class);
103: userAdminSession = userAdminSessionHome.create();
104: ICertificateStoreSessionHome certificateStoreSessionHome = (ICertificateStoreSessionHome) javax.rmi.PortableRemoteObject
105: .narrow(
106: ctx
107: .lookup(ICertificateStoreSessionHome.JNDI_NAME),
108: ICertificateStoreSessionHome.class);
109: certificateStoreSession = certificateStoreSessionHome.create();
110: ICAAdminSessionHome caAdminSessionHome = (org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionHome) javax.rmi.PortableRemoteObject
111: .narrow(
112: ctx.lookup(ICAAdminSessionHome.JNDI_NAME),
113: org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionHome.class);
114: caAdminSession = caAdminSessionHome.create();
115: CertTools.installBCProvider();
116: adminUsername = genRandomUserName("revocationTestAdmin");
117: requestingAdminUsername = genRandomUserName("revocationTestRequestingAdmin");
118: Iterator iter = authorizationSession
119: .getAuthorizedAdminGroupNames(internalAdmin).iterator();
120: while (iter.hasNext()) {
121: AdminGroup group = (AdminGroup) iter.next();
122: if (group.getAdminGroupName().equals(
123: "Temporary Super Administrator Group")) {
124: caid = group.getCAId();
125: }
126: }
127: UserDataVO userdata = new UserDataVO(adminUsername, "CN="
128: + adminUsername, caid, null, null, 1,
129: SecConst.EMPTY_ENDENTITYPROFILE,
130: SecConst.CERTPROFILE_FIXED_ENDUSER,
131: SecConst.TOKEN_SOFT_P12, 0, null);
132: userdata.setPassword("foo123");
133: userAdminSession.addUser(internalAdmin, userdata, true);
134: UserDataVO userdata2 = new UserDataVO(requestingAdminUsername,
135: "CN=" + requestingAdminUsername, caid, null, null, 1,
136: SecConst.EMPTY_ENDENTITYPROFILE,
137: SecConst.CERTPROFILE_FIXED_ENDUSER,
138: SecConst.TOKEN_SOFT_P12, 0, null);
139: userdata2.setPassword("foo123");
140: userAdminSession.addUser(internalAdmin, userdata2, true);
141: BatchMakeP12 makep12 = new BatchMakeP12();
142: File tmpfile = File.createTempFile("ejbca", "p12");
143: makep12.setMainStoreDir(tmpfile.getParent());
144: makep12.createAllNew();
145: adminentities = new ArrayList();
146: adminentities.add(new AdminEntity(AdminEntity.WITH_COMMONNAME,
147: AdminEntity.TYPE_EQUALCASEINS, adminUsername, caid));
148: adminentities.add(new AdminEntity(AdminEntity.WITH_COMMONNAME,
149: AdminEntity.TYPE_EQUALCASEINS, requestingAdminUsername,
150: caid));
151: authorizationSession.addAdminEntities(internalAdmin,
152: "Temporary Super Administrator Group", caid,
153: adminentities);
154: authorizationSession.forceRuleUpdate(internalAdmin);
155: X509Certificate admincert = (X509Certificate) certificateStoreSession
156: .findCertificatesByUsername(internalAdmin,
157: adminUsername).iterator().next();
158: X509Certificate reqadmincert = (X509Certificate) certificateStoreSession
159: .findCertificatesByUsername(internalAdmin,
160: requestingAdminUsername).iterator().next();
161: approvingAdmin = new Admin(admincert);
162: reuestingAdmin = new Admin(reqadmincert);
163: // Create new CA using approvals
164: String caname = TestRevocationApproval.class.getSimpleName();
165: approvalCAID = createApprovalCA(internalAdmin, caname,
166: CAInfo.REQ_APPROVAL_REVOCATION, caAdminSession);
167: }
168:
169: protected void tearDown() throws Exception {
170: super .tearDown();
171: userAdminSession.deleteUser(internalAdmin, adminUsername);
172: userAdminSession.deleteUser(internalAdmin,
173: requestingAdminUsername);
174: authorizationSession.removeAdminEntities(internalAdmin,
175: "Temporary Super Administrator Group", caid,
176: adminentities);
177: caAdminSession.removeCA(internalAdmin, approvalCAID);
178: }
179:
180: private String genRandomUserName(String usernameBase) {
181: usernameBase += (new Integer((new Random(
182: new Date().getTime() + 4711)).nextInt(999999)))
183: .toString();
184: return usernameBase;
185: }
186:
187: private void createUser(Admin admin, String username, int caID)
188: throws Exception {
189: UserDataVO userdata = new UserDataVO(username,
190: "CN=" + username, caID, null, null, 1,
191: SecConst.EMPTY_ENDENTITYPROFILE,
192: SecConst.CERTPROFILE_FIXED_ENDUSER,
193: SecConst.TOKEN_SOFT_P12, 0, null);
194: userdata.setPassword("foo123");
195: userAdminSession.addUser(admin, userdata, true);
196: BatchMakeP12 makep12 = new BatchMakeP12();
197: File tmpfile = File.createTempFile("ejbca", "p12");
198: makep12.setMainStoreDir(tmpfile.getParent());
199: makep12.createAllNew();
200: }
201:
202: /**
203: * Find all certificates for a user and approve any outstanding revocation.
204: */
205: static public int approveRevocation(Admin internalAdmin,
206: Admin approvingAdmin, String username, int reason,
207: int approvalType,
208: ICertificateStoreSessionRemote certificateStoreSession,
209: IApprovalSessionRemote approvalSession) throws Exception {
210: Collection userCerts = certificateStoreSession
211: .findCertificatesByUsername(internalAdmin, username);
212: Iterator i = userCerts.iterator();
213: int approvedRevocations = 0;
214: while (i.hasNext()) {
215: X509Certificate cert = (X509Certificate) i.next();
216: String issuerDN = cert.getIssuerDN().toString();
217: BigInteger serialNumber = cert.getSerialNumber();
218: if ((reason != RevokedCertInfo.NOT_REVOKED && !certificateStoreSession
219: .isRevoked(internalAdmin, issuerDN, serialNumber)
220: .isRevoked())
221: || (reason == RevokedCertInfo.NOT_REVOKED && certificateStoreSession
222: .isRevoked(internalAdmin, issuerDN,
223: serialNumber).isRevoked())) {
224: int approvalID;
225: if (approvalType == ApprovalDataVO.APPROVALTYPE_REVOKECERTIFICATE) {
226: approvalID = RevocationApprovalRequest
227: .generateApprovalId(approvalType, username,
228: reason, serialNumber, issuerDN);
229: } else {
230: approvalID = RevocationApprovalRequest
231: .generateApprovalId(approvalType, username,
232: reason, null, null);
233: }
234: Query q = new Query(Query.TYPE_APPROVALQUERY);
235: q.add(ApprovalMatch.MATCH_WITH_APPROVALID,
236: BasicMatch.MATCH_TYPE_EQUALS, Integer
237: .toString(approvalID));
238: ApprovalDataVO approvalData = (ApprovalDataVO) (approvalSession
239: .query(internalAdmin, q, 0, 1).get(0));
240: Approval approval = new Approval(
241: "Approved during testing.");
242: approvalSession.approve(approvingAdmin, approvalID,
243: approval);
244: approvalData = (ApprovalDataVO) approvalSession
245: .findApprovalDataVO(internalAdmin, approvalID)
246: .iterator().next();
247: assertTrue(approvalData.getStatus() == ApprovalDataVO.STATUS_EXECUTED);
248: assertTrue(certificateStoreSession.isRevoked(
249: internalAdmin, issuerDN, serialNumber)
250: .getReason() == reason);
251: approvalSession.removeApprovalRequest(internalAdmin,
252: approvalData.getId());
253: approvedRevocations++;
254: }
255: }
256: return approvedRevocations;
257: } // approveRevocation
258:
259: /**
260: * Create a CA with one of the approval-requirements enabled.
261: * @return the CA's ID.
262: */
263: static public int createApprovalCA(Admin internalAdmin,
264: String nameOfCA, int approvalRequirementType,
265: ICAAdminSessionRemote caAdminSession) throws Exception {
266: CATokenInfo catokeninfo = new SoftCATokenInfo();
267: catokeninfo
268: .setSignatureAlgorithm(CATokenConstants.SIGALG_SHA1_WITH_RSA);
269: ((SoftCATokenInfo) catokeninfo)
270: .setSignKeyAlgorithm(CATokenConstants.KEYALGORITHM_RSA);
271: ((SoftCATokenInfo) catokeninfo).setSignKeySpec("1024");
272: catokeninfo
273: .setEncryptionAlgorithm(CATokenConstants.SIGALG_SHA1_WITH_RSA);
274: ((SoftCATokenInfo) catokeninfo)
275: .setEncKeyAlgorithm(CATokenConstants.KEYALGORITHM_RSA);
276: ((SoftCATokenInfo) catokeninfo).setEncKeySpec("1024");
277: ArrayList approvalSettings = new ArrayList();
278: approvalSettings.add(approvalRequirementType);
279: X509CAInfo cainfo = new X509CAInfo("CN=" + nameOfCA, nameOfCA,
280: SecConst.CA_ACTIVE, new Date(), "",
281: SecConst.CERTPROFILE_FIXED_ROOTCA, 365, new Date(System
282: .currentTimeMillis()
283: + 364 * 24 * 3600 * 1000), CAInfo.CATYPE_X509,
284: CAInfo.SELFSIGNED, null, catokeninfo,
285: "Used for testing approvals", -1, null, null, 24, 0,
286: 10, 0, new ArrayList(), true, false, true, false, "",
287: "", "", "", true, new ArrayList(), false,
288: approvalSettings, 1, false, true, false, false);
289: int caID = cainfo.getCAId();
290: try {
291: caAdminSession.revokeCA(internalAdmin, caID,
292: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED);
293: caAdminSession.removeCA(internalAdmin, caID);
294: } catch (Exception e) {
295: }
296: caAdminSession.createCA(internalAdmin, cainfo);
297: cainfo = (X509CAInfo) caAdminSession.getCAInfo(internalAdmin,
298: caID);
299: assertNotNull(cainfo);
300: return caID;
301: }
302:
303: /**
304: * Verify that normal operations are working
305: * @throws RemoveException
306: * @throws AuthorizationDeniedException
307: * @throws RemoteException
308: * @throws NotFoundException
309: */
310: public void test01VerifyAddRemoveUser() throws Exception {
311: String username = genRandomUserName("test01Revocation");
312: try {
313: createUser(internalAdmin, username, approvalCAID);
314: } finally {
315: userAdminSession.deleteUser(internalAdmin, username);
316: }
317: } // test01VerifyAddRemoveUser
318:
319: public void test02RevokeUser() throws Exception {
320: String username = genRandomUserName("test02Revocation");
321: try {
322: createUser(internalAdmin, username, approvalCAID);
323: try {
324: userAdminSession.revokeUser(reuestingAdmin, username,
325: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED);
326: assertTrue("Approval code never interrupted run.",
327: false);
328: } catch (ApprovalException e) {
329: assertTrue(
330: "Reporting that approval request exists, when it does not.",
331: false);
332: } catch (WaitingForApprovalException e) {
333: }
334: try {
335: userAdminSession.revokeUser(reuestingAdmin, username,
336: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED);
337: assertTrue("Approval code never interrupted run.",
338: false);
339: } catch (ApprovalException e) {
340: } catch (WaitingForApprovalException e) {
341: assertTrue(
342: "Allowing addition of identical approval requests.",
343: false);
344: }
345: approveRevocation(internalAdmin, approvingAdmin, username,
346: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED,
347: ApprovalDataVO.APPROVALTYPE_REVOKEENDENTITY,
348: certificateStoreSession, approvalSession);
349: // Make sure userstatus changed to revoked
350: UserDataVO userdata = userAdminSession.findUser(
351: internalAdmin, username);
352: assertTrue(
353: "User was not revoked when last cert was.",
354: userdata.getStatus() == UserDataConstants.STATUS_REVOKED);
355: } finally {
356: userAdminSession.deleteUser(internalAdmin, username);
357: }
358: } // test02RevokeUser
359:
360: public void test03RevokeAndDeleteUser() throws Exception {
361: String username = genRandomUserName("test03Revocation");
362: try {
363: createUser(internalAdmin, username, approvalCAID);
364: try {
365: userAdminSession.revokeAndDeleteUser(reuestingAdmin,
366: username,
367: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED);
368: assertTrue("Approval code never interrupted run.",
369: false);
370: } catch (ApprovalException e) {
371: assertTrue(
372: "Reporting that approval request exists, when it does not.",
373: false);
374: } catch (WaitingForApprovalException e) {
375: }
376: try {
377: userAdminSession.revokeAndDeleteUser(reuestingAdmin,
378: username,
379: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED);
380: assertTrue("Approval code never interrupted run.",
381: false);
382: } catch (ApprovalException e) {
383: } catch (WaitingForApprovalException e) {
384: assertTrue(
385: "Allowing addition of identical approval requests.",
386: false);
387: }
388: approveRevocation(
389: internalAdmin,
390: approvingAdmin,
391: username,
392: RevokedCertInfo.REVOKATION_REASON_UNSPECIFIED,
393: ApprovalDataVO.APPROVALTYPE_REVOKEANDDELETEENDENTITY,
394: certificateStoreSession, approvalSession);
395: } finally {
396: try {
397: userAdminSession.deleteUser(internalAdmin, username);
398: } catch (NotFoundException e) {
399: // This is what we expect if everything went ok
400: }
401: }
402: } // test03RevokeAndDeleteUser
403:
404: public void test04RevokeAndUnrevokeCertificateOnHold()
405: throws Exception {
406: String username = genRandomUserName("test04Revocation");
407: final String ERRORNOTSENTFORAPPROVAL = "The request was never sent for approval.";
408: final String ERRORNONEXISTINGAPPROVALREPORTED = "Reporting that approval request exists, when it does not.";
409: final String ERRORALLOWMORETHANONE = "Allowing more than one identical approval requests.";
410: final String ERRORNOREACTIVATION = "User was never reactivated when last cert was.";
411: final String ERRORNOREVOCATION = "User was never revoked when last cert was.";
412: try {
413: createUser(internalAdmin, username, approvalCAID);
414: X509Certificate usercert = (X509Certificate) certificateStoreSession
415: .findCertificatesByUsername(internalAdmin, username)
416: .iterator().next();
417: try {
418: userAdminSession
419: .revokeCert(
420: reuestingAdmin,
421: usercert.getSerialNumber(),
422: usercert.getIssuerDN().toString(),
423: username,
424: RevokedCertInfo.REVOKATION_REASON_CERTIFICATEHOLD);
425: assertTrue(ERRORNOTSENTFORAPPROVAL, false);
426: } catch (ApprovalException e) {
427: assertTrue(ERRORNONEXISTINGAPPROVALREPORTED, false);
428: } catch (WaitingForApprovalException e) {
429: }
430: try {
431: userAdminSession
432: .revokeCert(
433: reuestingAdmin,
434: usercert.getSerialNumber(),
435: usercert.getIssuerDN().toString(),
436: username,
437: RevokedCertInfo.REVOKATION_REASON_CERTIFICATEHOLD);
438: assertTrue(ERRORNOTSENTFORAPPROVAL, false);
439: } catch (ApprovalException e) {
440: } catch (WaitingForApprovalException e) {
441: assertTrue(ERRORALLOWMORETHANONE, false);
442: }
443: approveRevocation(internalAdmin, approvingAdmin, username,
444: RevokedCertInfo.REVOKATION_REASON_CERTIFICATEHOLD,
445: ApprovalDataVO.APPROVALTYPE_REVOKECERTIFICATE,
446: certificateStoreSession, approvalSession);
447: // Make sure userstatus changed to revoked
448: UserDataVO userdata = userAdminSession.findUser(
449: internalAdmin, username);
450: assertTrue(
451: ERRORNOREVOCATION,
452: userdata.getStatus() == UserDataConstants.STATUS_REVOKED);
453: // Unrevoke
454: try {
455: userAdminSession.revokeCert(reuestingAdmin, usercert
456: .getSerialNumber(), usercert.getIssuerDN()
457: .toString(), username,
458: RevokedCertInfo.NOT_REVOKED);
459: assertTrue(ERRORNOTSENTFORAPPROVAL, false);
460: } catch (ApprovalException e) {
461: assertTrue(ERRORNONEXISTINGAPPROVALREPORTED, false);
462: } catch (WaitingForApprovalException e) {
463: }
464: try {
465: userAdminSession.revokeCert(reuestingAdmin, usercert
466: .getSerialNumber(), usercert.getIssuerDN()
467: .toString(), username,
468: RevokedCertInfo.NOT_REVOKED);
469: assertTrue(ERRORNOTSENTFORAPPROVAL, false);
470: } catch (ApprovalException e) {
471: } catch (WaitingForApprovalException e) {
472: assertTrue(ERRORALLOWMORETHANONE, false);
473: }
474: approveRevocation(internalAdmin, approvingAdmin, username,
475: RevokedCertInfo.NOT_REVOKED,
476: ApprovalDataVO.APPROVALTYPE_REVOKECERTIFICATE,
477: certificateStoreSession, approvalSession);
478: // Make sure userstatus changed to revoked
479: userdata = userAdminSession.findUser(internalAdmin,
480: username);
481: assertTrue(
482: ERRORNOREACTIVATION,
483: userdata.getStatus() == UserDataConstants.STATUS_GENERATED);
484: } finally {
485: userAdminSession.deleteUser(internalAdmin, username);
486: }
487: } // test04RevokeAndUnrevokeCertificateOnHold
488: }
|