From 73fe8961f585f2948c796fe0cf94aac25982b75a Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Thu, 1 Feb 2018 22:31:42 +0100 Subject: [PATCH 1/9] Refactored SecurityDataArchivalProcessedEvent. The SecurityDataArchivalProcessedEvent has been modified to provide separate factory methods for SUCCESS and FAILURE events. https://pagure.io/dogtagpki/issue/2848 Change-Id: Ie102aabaa81553ac1ea6963841a0568f1b6e04a5 (cherry picked from commit c1f607dc515f1b37a848a8b013d02f9d366e5402) (cherry picked from commit f2d828681d8b40e4d801af8d3bd5a6d6aaf71391) --- .../event/SecurityDataArchivalProcessedEvent.java | 49 +++++++--- .../src/com/netscape/kra/EnrollmentService.java | 4 +- .../src/com/netscape/kra/KeyRecoveryAuthority.java | 11 +-- .../src/com/netscape/kra/NetkeyKeygenService.java | 6 +- .../com/netscape/kra/SecurityDataProcessor.java | 102 +++++++++++++-------- 5 files changed, 112 insertions(+), 60 deletions(-) diff --git a/base/common/src/com/netscape/certsrv/logging/event/SecurityDataArchivalProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/SecurityDataArchivalProcessedEvent.java index dd88b45..2d87ece 100644 --- a/base/common/src/com/netscape/certsrv/logging/event/SecurityDataArchivalProcessedEvent.java +++ b/base/common/src/com/netscape/certsrv/logging/event/SecurityDataArchivalProcessedEvent.java @@ -18,6 +18,7 @@ package com.netscape.certsrv.logging.event; import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.logging.SignedAuditEvent; import com.netscape.certsrv.request.RequestId; @@ -28,9 +29,33 @@ public class SecurityDataArchivalProcessedEvent extends SignedAuditEvent { private static final String LOGGING_PROPERTY = "LOGGING_SIGNED_AUDIT_SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED"; - public SecurityDataArchivalProcessedEvent( + public SecurityDataArchivalProcessedEvent() { + super(LOGGING_PROPERTY); + } + + public static SecurityDataArchivalProcessedEvent createSuccessEvent( + String subjectID, + String archivalRequestId, + RequestId requestID, + String clientKeyID, + KeyId keyID, + String pubkey) { + + SecurityDataArchivalProcessedEvent event = new SecurityDataArchivalProcessedEvent(); + + event.setAttribute("SubjectID", subjectID); + event.setAttribute("Outcome", ILogger.SUCCESS); + event.setAttribute("ArchivalRequestID", archivalRequestId); + event.setAttribute("RequestId", requestID); + event.setAttribute("ClientKeyID", clientKeyID); + event.setAttribute("KeyID", keyID); + event.setAttribute("PubKey", pubkey); + + return event; + } + + public static SecurityDataArchivalProcessedEvent createFailureEvent( String subjectID, - String outcome, String archivalRequestId, RequestId requestID, String clientKeyID, @@ -38,15 +63,17 @@ public class SecurityDataArchivalProcessedEvent extends SignedAuditEvent { String failureReason, String pubkey) { - super(LOGGING_PROPERTY); + SecurityDataArchivalProcessedEvent event = new SecurityDataArchivalProcessedEvent(); + + event.setAttribute("SubjectID", subjectID); + event.setAttribute("Outcome", ILogger.FAILURE); + event.setAttribute("ArchivalRequestID", archivalRequestId); + event.setAttribute("RequestId", requestID); + event.setAttribute("ClientKeyID", clientKeyID); + event.setAttribute("KeyID", keyID); + event.setAttribute("FailureReason", failureReason); + event.setAttribute("PubKey", pubkey); - setAttribute("SubjectID", subjectID); - setAttribute("Outcome", outcome); - setAttribute("ArchivalRequestID", archivalRequestId); - setAttribute("RequestId", requestID); - setAttribute("ClientKeyID", clientKeyID); - setAttribute("KeyID", keyID); - setAttribute("FailureReason", failureReason); - setAttribute("PubKey", pubkey); + return event; } } diff --git a/base/kra/src/com/netscape/kra/EnrollmentService.java b/base/kra/src/com/netscape/kra/EnrollmentService.java index 93493fe..ee8a754 100644 --- a/base/kra/src/com/netscape/kra/EnrollmentService.java +++ b/base/kra/src/com/netscape/kra/EnrollmentService.java @@ -602,14 +602,12 @@ public class EnrollmentService implements IService { // store a message in the signed audit log file auditPublicKey = auditPublicKey(rec); - signedAuditLogger.log(new SecurityDataArchivalProcessedEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createSuccessEvent( auditSubjectID, - ILogger.SUCCESS, auditRequesterID, requestId, null, new KeyId(rec.getSerialNumber()), - null, auditPublicKey)); // Xxx - should sign this proof of archival diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java index 964a73c..05c7e71 100644 --- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java +++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthority.java @@ -59,8 +59,8 @@ import com.netscape.certsrv.kra.IKeyService; import com.netscape.certsrv.listeners.EListenersException; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.logging.LogEvent; -import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent; import com.netscape.certsrv.logging.event.SecurityDataArchivalProcessedEvent; +import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent; import com.netscape.certsrv.logging.event.SecurityDataRecoveryEvent; import com.netscape.certsrv.logging.event.SecurityDataRecoveryProcessedEvent; import com.netscape.certsrv.request.ARequestNotifier; @@ -783,19 +783,18 @@ public class KeyRecoveryAuthority implements IAuthority, IKeyService, IKeyRecove queue.processRequest(r); } - audit(new SecurityDataArchivalProcessedEvent( + audit(SecurityDataArchivalProcessedEvent.createSuccessEvent( auditSubjectID, - ILogger.SUCCESS, auditRequesterID, r.getRequestId(), null, new KeyId(rec.getSerialNumber()), - null, auditPublicKey)); + } catch (EBaseException eAudit1) { - audit(new SecurityDataArchivalProcessedEvent( + + audit(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, - ILogger.FAILURE, auditRequesterID, r.getRequestId(), null, diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java index 1cd827f..052c289 100644 --- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java @@ -50,8 +50,8 @@ import com.netscape.certsrv.dbs.keydb.KeyId; import com.netscape.certsrv.kra.IKeyRecoveryAuthority; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.logging.LogEvent; -import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent; import com.netscape.certsrv.logging.event.SecurityDataArchivalProcessedEvent; +import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent; import com.netscape.certsrv.logging.event.SecurityDataExportEvent; import com.netscape.certsrv.logging.event.ServerSideKeyGenEvent; import com.netscape.certsrv.logging.event.ServerSideKeyGenProcessedEvent; @@ -495,14 +495,12 @@ public class NetkeyKeygenService implements IService { storage.addKeyRecord(rec); CMS.debug("NetkeyKeygenService: key archived for " + rCUID + ":" + rUserid); - audit(new SecurityDataArchivalProcessedEvent( + audit(SecurityDataArchivalProcessedEvent.createSuccessEvent( agentId, - ILogger.SUCCESS, auditSubjectID, request.getRequestId(), null, new KeyId(serialNo), - null, PubKey)); } //if archive diff --git a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java index 8de1311..5a64530 100644 --- a/base/kra/src/com/netscape/kra/SecurityDataProcessor.java +++ b/base/kra/src/com/netscape/kra/SecurityDataProcessor.java @@ -40,7 +40,6 @@ import com.netscape.certsrv.key.KeyRequestResource; import com.netscape.certsrv.kra.EKRAException; import com.netscape.certsrv.kra.IKeyRecoveryAuthority; import com.netscape.certsrv.logging.ILogger; -import com.netscape.certsrv.logging.LogEvent; import com.netscape.certsrv.logging.event.SecurityDataArchivalProcessedEvent; import com.netscape.certsrv.profile.IEnrollProfile; import com.netscape.certsrv.request.IRequest; @@ -121,8 +120,16 @@ public class SecurityDataProcessor { //Check here even though restful layer checks for this. if (clientKeyId == null || dataType == null) { - auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId, - clientKeyId, null, "Bad data in request"); + + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + null, + "Bad data in request", + null)); + throw new EBaseException("Bad data in SecurityDataService.serviceRequest"); } @@ -237,14 +244,29 @@ public class SecurityDataProcessor { privateSecurityData = storageUnit.encryptInternalPrivate(securityData, params); doEncrypt = true; } else { // We have no data. - auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId, - clientKeyId, null, "Failed to create security data to archive"); + + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + null, + "Failed to create security data to archive", + null)); + throw new EBaseException("Failed to create security data to archive!"); } } catch (Exception e) { CMS.debug("Failed to create security data to archive: " + e.getMessage()); - auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId, - clientKeyId, null, CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY")); + + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + null, + CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY"), + null)); throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY")); } finally { @@ -269,8 +291,16 @@ public class SecurityDataProcessor { //Now we need a serial number for our new key. if (rec.getSerialNumber() != null) { - auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId, - clientKeyId, null, CMS.getUserMessage("CMS_KRA_INVALID_STATE")); + + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + null, + CMS.getUserMessage("CMS_KRA_INVALID_STATE"), + null)); + throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); } @@ -279,8 +309,16 @@ public class SecurityDataProcessor { if (serialNo == null) { kra.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_GET_NEXT_SERIAL")); - auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId, - clientKeyId, null, "Failed to get next Key ID"); + + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + null, + "Failed to get next Key ID", + null)); + throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE")); } @@ -302,8 +340,16 @@ public class SecurityDataProcessor { } catch (Exception e) { kra.log(ILogger.LL_FAILURE, "Failed to store wrapping parameters: " + e); - auditArchivalRequestProcessed(auditSubjectID, ILogger.FAILURE, requestId, - clientKeyId, null, "Failed to store wrapping parameters"); + + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + null, + "Failed to store wrapping parameters", + null)); + throw new EBaseException(CMS.getUserMessage("CMS_KRA_INVALID_STATE"), e); } @@ -311,8 +357,13 @@ public class SecurityDataProcessor { keyRepository.addKeyRecord(rec); - auditArchivalRequestProcessed(auditSubjectID, ILogger.SUCCESS, requestId, - clientKeyId, new KeyId(serialNo), "None"); + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createSuccessEvent( + auditSubjectID, + null, + requestId, + clientKeyId, + new KeyId(serialNo), + null)); request.setExtData(ATTR_KEY_RECORD, serialNo); request.setExtData(IRequest.RESULT, IRequest.RES_SUCCESS); @@ -852,25 +903,4 @@ public class SecurityDataProcessor { return retData; } - - private void audit(String msg) { - signedAuditLogger.log(msg); - } - - protected void audit(LogEvent event) { - signedAuditLogger.log(event); - } - - private void auditArchivalRequestProcessed(String subjectID, String status, RequestId requestID, String clientKeyID, - KeyId keyID, String reason) { - audit(new SecurityDataArchivalProcessedEvent( - subjectID, - status, - null, - requestID, - clientKeyID, - keyID, - reason, - null)); - } } -- 1.8.3.1 From 0347843054e0a977826c4d7b50260e9f711190a9 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Thu, 1 Feb 2018 22:48:29 +0100 Subject: [PATCH 2/9] Changed audit event types in EnrollmentService. The EnrollmentService has been modified to generate SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED instead of. SECURITY_DATA_ARCHIVAL_REQUEST. https://pagure.io/dogtagpki/issue/2848 Change-Id: I63017c4d9c058daac92fe606f0096402ca78b6ec (cherry picked from commit 3c4770d520d6dab967bdba1b67b638c81a959e48) (cherry picked from commit a30eee31512022a1a419bb949f912b08419ddf8d) --- .../src/com/netscape/kra/EnrollmentService.java | 74 +++++++++++++--------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/base/kra/src/com/netscape/kra/EnrollmentService.java b/base/kra/src/com/netscape/kra/EnrollmentService.java index ee8a754..20d68ff 100644 --- a/base/kra/src/com/netscape/kra/EnrollmentService.java +++ b/base/kra/src/com/netscape/kra/EnrollmentService.java @@ -51,7 +51,6 @@ import com.netscape.certsrv.kra.ProofOfArchival; import com.netscape.certsrv.logging.AuditFormat; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.logging.event.SecurityDataArchivalProcessedEvent; -import com.netscape.certsrv.logging.event.SecurityDataArchivalRequestEvent; import com.netscape.certsrv.profile.IEnrollProfile; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.IService; @@ -203,12 +202,14 @@ public class EnrollmentService implements IService { } catch (IOException e) { - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY") + ": " + e, e); @@ -250,12 +251,14 @@ public class EnrollmentService implements IService { } catch (Exception e) { mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_UNWRAP_USER_KEY")); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY") + ": " + e, e); @@ -288,12 +291,14 @@ public class EnrollmentService implements IService { String message = CMS.getLogMessage("CMSCORE_KRA_PUBLIC_NOT_FOUND"); mKRA.log(ILogger.LL_FAILURE, message); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - message)); + null, + message, + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_PUBLIC_KEY") + ": " + message); @@ -329,12 +334,14 @@ public class EnrollmentService implements IService { mKRA.log(ILogger.LL_DEBUG, e.getMessage()); mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_WRAP_USER_KEY")); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY") + ": " + e, e); @@ -357,12 +364,14 @@ public class EnrollmentService implements IService { jssSubsystem.obscureBytes(unwrapped); mKRA.log(ILogger.LL_FAILURE, e.toString()); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_PUBLIC_KEY") + ": " + e, e); @@ -383,12 +392,14 @@ public class EnrollmentService implements IService { String message = CMS.getLogMessage("CMSCORE_KRA_OWNER_NAME_NOT_FOUND"); mKRA.log(ILogger.LL_FAILURE, message); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - message)); + null, + message, + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_KEYRECORD") + ": " + message); @@ -419,12 +430,14 @@ public class EnrollmentService implements IService { mKRA.log(ILogger.LL_DEBUG, e.getMessage()); mKRA.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_KRA_WRAP_USER_KEY")); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_PRIVATE_KEY") + ": " + e, e); @@ -450,12 +463,14 @@ public class EnrollmentService implements IService { rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); } catch (InvalidKeyException e) { - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_KEYRECORD") + ": " + e, e); @@ -499,12 +514,14 @@ public class EnrollmentService implements IService { String message = CMS.getLogMessage("CMSCORE_KRA_INVALID_SERIAL_NUMBER", rec.getSerialNumber().toString()); mKRA.log(ILogger.LL_FAILURE, message); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - message)); + null, + message, + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_STATE") + ": " + message); @@ -521,12 +538,14 @@ public class EnrollmentService implements IService { } catch (Exception e) { mKRA.log(ILogger.LL_FAILURE, "Failed to store wrapping parameters"); // TODO(alee) Set correct audit message here - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - e)); + null, + e.toString(), + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_STATE") + ": " + e, e); @@ -539,12 +558,14 @@ public class EnrollmentService implements IService { String message = CMS.getLogMessage("CMSCORE_KRA_GET_NEXT_SERIAL"); mKRA.log(ILogger.LL_FAILURE, message); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createFailureEvent( + signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createFailureEvent( auditSubjectID, auditRequesterID, requestId, null, - message)); + null, + message, + null)); throw new EKRAException( CMS.getUserMessage("CMS_KRA_INVALID_STATE") + ": " + message); @@ -594,13 +615,6 @@ public class EnrollmentService implements IService { "serial number: 0x" + serialNo.toString(16) } ); - signedAuditLogger.log(SecurityDataArchivalRequestEvent.createSuccessEvent( - auditSubjectID, - auditRequesterID, - requestId, - null)); - - // store a message in the signed audit log file auditPublicKey = auditPublicKey(rec); signedAuditLogger.log(SecurityDataArchivalProcessedEvent.createSuccessEvent( auditSubjectID, -- 1.8.3.1 From 138f1464d072690f9efb6f55c6c3ac297fb098d8 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Fri, 2 Feb 2018 21:54:01 +0100 Subject: [PATCH 3/9] Fixed try-catch block in NetkeyKeygenService.serviceRequest(). The try-catch block in NetkeyKeygenService.serviceRequest() has been fixed to return false on exception. It also has been split into two blocks. https://pagure.io/dogtagpki/issue/2848 Change-Id: Ia78bd5371720dc551c2470898d83597d554183b7 (cherry picked from commit 4d54490f7fec01a6c5bc113f5f48f1d08e8b47a5) (cherry picked from commit 70dff0d5d4b68f17058d30338bfebf81bbf96fa6) --- .../kra/src/com/netscape/kra/NetkeyKeygenService.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java index 052c289..17ac66d 100644 --- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java @@ -65,7 +65,6 @@ import com.netscape.cms.logging.SignedAuditLogger; import com.netscape.cms.servlet.key.KeyRecordParser; import com.netscape.cmscore.dbs.KeyRecord; import com.netscape.cmscore.security.JssSubsystem; -import com.netscape.cmscore.util.Debug; import com.netscape.cmsutil.crypto.CryptoUtil; import com.netscape.cmsutil.util.Utils; @@ -279,8 +278,10 @@ public class NetkeyKeygenService implements IService { return false; } + CMS.debug("NetkeyKeygenService: finished generate key pair for " + rCUID + ":" + rUserid); + java.security.PrivateKey privKey; try { publicKeyData = keypair.getPublic().getEncoded(); if (publicKeyData == null) { @@ -309,8 +310,7 @@ public class NetkeyKeygenService implements IService { PubKey)); //...extract the private key handle (not privatekeydata) - java.security.PrivateKey privKey = - keypair.getPrivate(); + privKey = keypair.getPrivate(); if (privKey == null) { request.setExtData(IRequest.RESULT, Integer.valueOf(4)); @@ -386,6 +386,13 @@ public class NetkeyKeygenService implements IService { iv_s = /*base64Encode(iv);*/com.netscape.cmsutil.util.Utils.SpecialEncode(iv); request.setExtData("iv_s", iv_s); + } catch (Exception e) { + CMS.debug(e); + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + return false; + } + + try { /* * archival - option flag "archive" controllable by the caller - TPS */ @@ -505,11 +512,13 @@ public class NetkeyKeygenService implements IService { } //if archive request.setExtData(IRequest.RESULT, Integer.valueOf(1)); + } catch (Exception e) { - CMS.debug("NetKeyKeygenService: " + e.toString()); - Debug.printStackTrace(e); + CMS.debug(e); request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + return false; } + } else request.setExtData(IRequest.RESULT, Integer.valueOf(2)); -- 1.8.3.1 From 625ac01b2f13ef469a3fc05a91b96522db802991 Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Fri, 2 Feb 2018 16:39:30 -0800 Subject: [PATCH 4/9] Ticket #2920 CMC: Audit Events needed for failures in SharedToken scenarios This patch adds the missing CERT_STATUS_CHANGE_REQUEST_PROCESSED event in case of shared token failure at revocation; In addition, a missing validate() call is made for decrypted POP request as well as the failure audit event. fixes: https://pagure.io/dogtagpki/issue/2920 Change-Id: I45b53f579794c3a5f32cc475a6293240025922c2 (cherry picked from commit e7ec7d3004354f4a4a98d696833e531fb7a0e41c) (cherry picked from commit 4b0816d706ac4c70bd03633a34b07c2ff12f9690) --- .../CertStatusChangeRequestProcessedEvent.java | 22 ++++++++ .../cms/servlet/common/CMCOutputTemplate.java | 66 ++++++++++++++++++---- .../servlet/profile/ProfileSubmitCMCServlet.java | 6 ++ 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/base/common/src/com/netscape/certsrv/logging/event/CertStatusChangeRequestProcessedEvent.java b/base/common/src/com/netscape/certsrv/logging/event/CertStatusChangeRequestProcessedEvent.java index 259a395..8c7f9c9 100644 --- a/base/common/src/com/netscape/certsrv/logging/event/CertStatusChangeRequestProcessedEvent.java +++ b/base/common/src/com/netscape/certsrv/logging/event/CertStatusChangeRequestProcessedEvent.java @@ -51,6 +51,28 @@ public class CertStatusChangeRequestProcessedEvent extends SignedAuditEvent { public CertStatusChangeRequestProcessedEvent( String subjectID, String outcome, + String requesterID, + String serialNumber, + String requestType, + String reasonNum, + RequestStatus approvalStatus, + String info) { + + super(LOGGING_PROPERTY); + + setAttribute("SubjectID", subjectID); + setAttribute("Outcome", outcome); + setAttribute("ReqID", requesterID); + setAttribute("CertSerialNum", serialNumber); + setAttribute("RequestType", requestType); + setAttribute("RevokeReasonNum", reasonNum); + setAttribute("Approval", approvalStatus); + setAttribute("Info", info); + } + + public CertStatusChangeRequestProcessedEvent( + String subjectID, + String outcome, IRequest request, String serialNumber, String requestType, diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java index 6c40d2d..814a9c2 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java +++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java @@ -1094,10 +1094,26 @@ public class CMCOutputTemplate { } ISharedToken tokenClass = (ISharedToken) sharedTokenAuth; - char[] sharedSecret = tokenClass.getSharedToken(revokeSerial); + char[] sharedSecret = null; + try { + sharedSecret = tokenClass.getSharedToken(revokeSerial); + } catch (Exception eShrTok) { + CMS.debug("CMCOutputTemplate: " + eShrTok.toString()); + } if (sharedSecret == null) { - CMS.debug("CMCOutputTemplate: shared secret not found."); + msg = " shared secret not found"; + CMS.debug(method + msg); + audit(new CertStatusChangeRequestProcessedEvent( + auditSubjectID, + ILogger.FAILURE, + auditReqID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus, + msg)); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), null, null); SEQUENCE failed_bpids = new SEQUENCE(); @@ -1127,8 +1143,8 @@ public class CMCOutputTemplate { secret1.clear(); secret2.clear(); } else { - CMS.debug(method - + " Client and server shared secret are not the same, cannot revoke certificate."); + msg = " Client and server shared secret are not the same, cannot revoke certificate."; + CMS.debug(method + msg); OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), null, null); SEQUENCE failed_bpids = new SEQUENCE(); @@ -1146,7 +1162,8 @@ public class CMCOutputTemplate { auditSerialNumber, auditRequestType, auditReasonNum, - auditApprovalStatus)); + auditApprovalStatus, + msg)); secret1.clear(); secret2.clear(); @@ -1165,7 +1182,18 @@ public class CMCOutputTemplate { } if (record == null) { - CMS.debug(method + " The certificate is not found"); + msg = " The certificate is not found"; + CMS.debug(method + msg); + audit(new CertStatusChangeRequestProcessedEvent( + auditSubjectID, + ILogger.FAILURE, + auditReqID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus, + msg)); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null, null); SEQUENCE failed_bpids = new SEQUENCE(); failed_bpids.addElement(attrbpid); @@ -1178,7 +1206,18 @@ public class CMCOutputTemplate { } if (record.getStatus().equals(ICertRecord.STATUS_REVOKED)) { - CMS.debug("CMCOutputTemplate: The certificate is already revoked:" + auditSerialNumber); + msg = " The certificate is already revoked:" + auditSerialNumber; + CMS.debug( method + msg); + audit(new CertStatusChangeRequestProcessedEvent( + auditSubjectID, + ILogger.FAILURE, + auditReqID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus, + msg)); + SEQUENCE success_bpids = new SEQUENCE(); success_bpids.addElement(attrbpid); cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.SUCCESS, @@ -1198,7 +1237,7 @@ public class CMCOutputTemplate { // principal matches that of the revoking cert if ((reqSecret == null) && authManagerId.equals("CMCUserSignedAuth")) { if (!certPrincipal.equals(signerPrincipal)) { - msg = "certificate principal and signer do not match"; + msg = " certificate principal and signer do not match"; CMS.debug(method + msg); OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), null, null); @@ -1218,7 +1257,8 @@ public class CMCOutputTemplate { auditSerialNumber, auditRequestType, auditReasonNum, - auditApprovalStatus)); + auditApprovalStatus, + msg)); return bpid; } else { @@ -1260,8 +1300,9 @@ public class CMCOutputTemplate { Integer result = revReq.getExtDataInInteger(IRequest.RESULT); CMS.debug(method + " revReq result = " + result); if (result.equals(IRequest.RES_ERROR)) { - CMS.debug("CMCOutputTemplate: revReq exception: " + - revReq.getExtDataInString(IRequest.ERROR)); + msg = " revReq exception: " + + revReq.getExtDataInString(IRequest.ERROR); + CMS.debug(method + msg); OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null, null); SEQUENCE failed_bpids = new SEQUENCE(); @@ -1280,7 +1321,8 @@ public class CMCOutputTemplate { auditSerialNumber, auditRequestType, auditReasonNum, - auditApprovalStatus)); + auditApprovalStatus, + msg)); return bpid; } diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java index c702624..5509080 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java +++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java @@ -909,6 +909,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { auditRequesterID = auditRequesterID(provedReq); try { + profile.validate(provedReq); profile.execute(provedReq); reqs = new IRequest[1]; reqs[0] = provedReq; @@ -950,6 +951,11 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { error_codes[0] = Integer.parseInt(errorCode); profile.getRequestQueue().updateRequest(provedReq); CMS.debug("ProfileSubmitCMCServlet: provedReq updateRequest"); + audit(CertRequestProcessedEvent.createFailureEvent( + auditSubjectID, + auditRequesterID, + ILogger.SIGNED_AUDIT_REJECTION, + errorReason)); } } -- 1.8.3.1 From 5781a5d47809fb1361a668e29e8fce07ce947303 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Fri, 2 Feb 2018 22:32:18 +0100 Subject: [PATCH 5/9] Added SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED events in NetkeyKeygenService. The NetkeyKeygenService.serviceRequest() has been modified to catch all exceptions and generate SECURITY_DATA_ARCHIVAL_REQUEST_PROCESSED with FAILURE outcome. https://pagure.io/dogtagpki/issue/2848 Change-Id: I08608fbb21ef14fddc2076d2e993766c30fd3cf0 (cherry picked from commit 74d72d9b5798d16e68054c0859d79288a38eee36) (cherry picked from commit a33c542fd4c8b2b7db259f092c2875fdbc842e95) --- .../src/com/netscape/kra/NetkeyKeygenService.java | 42 +++++++++++----------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java index 17ac66d..55fd9a0 100644 --- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java @@ -424,10 +424,10 @@ public class NetkeyKeygenService implements IService { params.setPayloadEncryptionIV(params.getPayloadWrappingIV()); privateKeyData = mStorageUnit.wrap((org.mozilla.jss.crypto.PrivateKey) privKey, params); + } catch (Exception e) { request.setExtData(IRequest.RESULT, Integer.valueOf(4)); - CMS.debug("NetkeyKeygenService: privatekey encryption by storage unit failed"); - return false; + throw new Exception("Unable to wrap private key with storage key", e); } CMS.debug("NetkeyKeygenService: privatekey encryption by storage unit successful"); @@ -443,13 +443,13 @@ public class NetkeyKeygenService implements IService { if (rKeytype.equals("RSA")) { try { RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); - rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); + } catch (InvalidKeyException e) { request.setExtData(IRequest.RESULT, Integer.valueOf(11)); - CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); - return false; + throw new Exception("Invalid RSA public key", e); } + } else if (rKeytype.equals("EC")) { CMS.debug("NetkeyKeygenService: alg is EC"); String oidDescription = "UNDETERMINED"; @@ -490,8 +490,7 @@ public class NetkeyKeygenService implements IService { if (serialNo == null) { request.setExtData(IRequest.RESULT, Integer.valueOf(11)); - CMS.debug("NetkeyKeygenService: serialNo null"); - return false; + throw new Exception("Unable to generate next serial number"); } rec.setWrappingParams(params, allowEncDecrypt_archival); @@ -515,7 +514,22 @@ public class NetkeyKeygenService implements IService { } catch (Exception e) { CMS.debug(e); - request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + + audit(SecurityDataArchivalProcessedEvent.createFailureEvent( + agentId, + auditSubjectID, + request.getRequestId(), + null, + null, + e.toString(), + PubKey)); + + Integer result = request.getExtDataInInteger(IRequest.RESULT); + if (result == null) { + // set default RESULT code + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + } + return false; } @@ -525,18 +539,6 @@ public class NetkeyKeygenService implements IService { return true; } //serviceRequest - /** - * Signed Audit Log - * y - * This method is called to store messages to the signed audit log. - *

- * - * @param msg signed audit log message - */ - private void audit(String msg) { - signedAuditLogger.log(msg); - } - protected void audit(LogEvent event) { signedAuditLogger.log(event); } -- 1.8.3.1 From d80696789edf427fe0b05c208da0270249af44e0 Mon Sep 17 00:00:00 2001 From: Jack Magne Date: Thu, 1 Feb 2018 14:58:30 -0800 Subject: [PATCH 6/9] Fix Bug 1522938 - CC: Missing failure resumption detection and audit event logging at startup This patch addressed two cases listed in the bug: 1. Signing Failure due to bad HSM connection. 2. Audit log failure of some kind. I felt the best and safest way to handle these conditions was to simply write to the error console, which results in a simple System.err.println being sent to the former catalina.out file now covered with the journalctl command. I considered using some other dogtag log file, but if we are in some sort of emergency or resource constrained situation, it is best to write the log out mostly simply. Quick testing instructions: 1. To see signing failure put this in the CS.cfg for ONLY testing purposes. ca.signing.testSignatureFailure=true , This will force an error when trying to sign and log it. Approve a certificate request, which will trigger a signing operation. 2. Check the journalctl for a log message. 3. Remove the config value to resume normal operation. 4. To see an audit log failure do the following: [root@localhost signedAudit]# ps -fe | grep pki pkiuser 8456 1 2 14:39 ? 00:00:32 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java lsof /var/lib/pki/pki-tomcat/ca/logs/signedAudit/ca_audit java 9905 pkiuser 124u REG 253,0 17298 3016784 /var/log/pki/pki-tomcat/ca/signedAudit/ca_audit gdb /usr/lib/jvm/jre-1.8.0-openjdk/bin/java 8456 , Use the pid from above Inside gdb do this: call close(124) This will close the file descriptor for the running server. 5. Now just try to do anything with the CS UI and observe errors written to the journalctl log, having to do with not being able to write to the ca_adit file. If signed audid logging is configured, many of these conditions will result in the the shutdown of the server. Change-Id: I21c62a5ad6bedfe8678144a764bff2e2a4716dce (cherry picked from commit 268cc70782b517c17439a17a5036f9f51182b650) (cherry picked from commit cdfe6f3e5a29fa061a0e6b6fb599dcddc19984c3) --- base/ca/src/com/netscape/ca/SigningUnit.java | 16 +++++++ .../cms/src/com/netscape/cms/logging/LogFile.java | 23 ++++++++++ .../cms/src/com/netscape/cms/logging/LogQueue.java | 22 ++++++--- .../netscape/cms/logging/SignedAuditLogger.java | 53 ++++++++++++++-------- base/server/cmsbundle/src/UserMessages.properties | 2 + .../src/com/netscape/cmscore/apps/CMSEngine.java | 9 ++++ 6 files changed, 99 insertions(+), 26 deletions(-) diff --git a/base/ca/src/com/netscape/ca/SigningUnit.java b/base/ca/src/com/netscape/ca/SigningUnit.java index 3194380..7cd0dd4 100644 --- a/base/ca/src/com/netscape/ca/SigningUnit.java +++ b/base/ca/src/com/netscape/ca/SigningUnit.java @@ -41,7 +41,9 @@ import com.netscape.certsrv.base.ISubsystem; import com.netscape.certsrv.ca.CAMissingCertException; import com.netscape.certsrv.ca.CAMissingKeyException; import com.netscape.certsrv.ca.ECAException; +import com.netscape.certsrv.logging.ConsoleError; import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.SystemEvent; import com.netscape.certsrv.security.ISigningUnit; import com.netscape.cms.logging.Logger; import com.netscape.cmscore.security.JssSubsystem; @@ -274,6 +276,7 @@ public final class SigningUnit implements ISigningUnit { if (!mInited) { throw new EBaseException("CASigningUnit not initialized!"); } + boolean testSignatureFailure = false; try { // XXX for now do this mapping until James changes the names // to match JCA names and provide a getAlgorithm method. @@ -303,6 +306,13 @@ public final class SigningUnit implements ISigningUnit { // XXX add something more descriptive. CMS.debug("Signing Certificate"); + + testSignatureFailure = mConfig.getBoolean("testSignatureFailure",false); + + if(testSignatureFailure == true) { + throw new SignatureException("Signature Exception forced for testing purposes."); + } + return signer.sign(); } catch (NoSuchAlgorithmException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); @@ -319,6 +329,12 @@ public final class SigningUnit implements ISigningUnit { } catch (SignatureException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", e.toString())); CMS.debug("SigningUnit.sign: " + e.toString()); + + //For this one case, show the eventual erorr message that will be written to the system error + //log in case of a Signature failure. + if (testSignatureFailure == true) { + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_CA_SIGNING_OPERATION_FAILED", e.toString()))); + } CMS.checkForAndAutoShutdown(); // XXX fix this exception later. throw new EBaseException(e); diff --git a/base/server/cms/src/com/netscape/cms/logging/LogFile.java b/base/server/cms/src/com/netscape/cms/logging/LogFile.java index 510e796..74a8ada 100644 --- a/base/server/cms/src/com/netscape/cms/logging/LogFile.java +++ b/base/server/cms/src/com/netscape/cms/logging/LogFile.java @@ -824,6 +824,7 @@ public class LogFile implements ILogEventListener, IExtendedPluginInfo { mFileName))); } catch (GeneralSecurityException gse) { // error with signed audit log, shutdown CMS + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_OPEN_FAILED", mFileName, gse.toString()))); gse.printStackTrace(); shutdownCMS(); } @@ -843,6 +844,8 @@ public class LogFile implements ILogEventListener, IExtendedPluginInfo { } catch (ELogException le) { ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_FLUSH_LOG_FAILED", mFileName, le.toString()))); + le.printStackTrace(); + shutdownCMS(); } } @@ -858,8 +861,15 @@ public class LogFile implements ILogEventListener, IExtendedPluginInfo { } } catch (GeneralSecurityException gse) { // error with signed audit log, shutdown CMS + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_FLUSH_LOG_FAILED", mFileName, gse.toString()))); gse.printStackTrace(); shutdownCMS(); + } catch (Exception ee) { + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_FLUSH_LOG_FAILED", mFileName, ee.toString()))); + if(mLogSigning) { + ee.printStackTrace(); + shutdownCMS(); + } } mBytesUnflushed = 0; @@ -995,6 +1005,11 @@ public class LogFile implements ILogEventListener, IExtendedPluginInfo { if (mLogWriter == null) { String[] params = { mFileName, entry }; + if (mLogSigning) { + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_LOGFILE_CLOSED", params))); + // Failed to write to audit log, shut down CMS + shutdownCMS(); + } throw new ELogException(CMS.getUserMessage("CMS_LOG_LOGFILE_CLOSED", params)); } else { try { @@ -1066,6 +1081,14 @@ public class LogFile implements ILogEventListener, IExtendedPluginInfo { gse.printStackTrace(); ConsoleError.send(new SignedAuditEvent(CMS.getLogMessage( LOG_SIGNED_AUDIT_EXCEPTION, gse.toString()))); + } catch (Exception ee) { // Make darn sure we got everything + ConsoleError.send(new SignedAuditEvent(CMS.getLogMessage(LOG_SIGNED_AUDIT_EXCEPTION, ee.toString()))); + if (mLogSigning) { + // Failed to write to audit log, shut down CMS + ee.printStackTrace(); + shutdownCMS(); + } + } // XXX diff --git a/base/server/cms/src/com/netscape/cms/logging/LogQueue.java b/base/server/cms/src/com/netscape/cms/logging/LogQueue.java index 1b40676..5eb96d7 100644 --- a/base/server/cms/src/com/netscape/cms/logging/LogQueue.java +++ b/base/server/cms/src/com/netscape/cms/logging/LogQueue.java @@ -19,10 +19,13 @@ package com.netscape.cms.logging; import java.util.Vector; -import com.netscape.certsrv.logging.ELogException; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.logging.ConsoleError; import com.netscape.certsrv.logging.ILogEvent; import com.netscape.certsrv.logging.ILogEventListener; import com.netscape.certsrv.logging.ILogQueue; +import com.netscape.certsrv.logging.SignedAuditEvent; +import com.netscape.certsrv.logging.SystemEvent; /** * A class represents a log queue. @@ -95,13 +98,20 @@ public class LogQueue implements ILogQueue { */ public void log(ILogEvent event) { for (int i = 0; i < mListeners.size(); i++) { + + boolean isAudit = false; + + if( event instanceof SignedAuditEvent) { + isAudit = true; + } try { mListeners.elementAt(i).log(event); - } catch (ELogException e) { - // Raidzilla Bug #57592: Don't display potentially - // incorrect log message. - // ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_EVENT_FAILED", - // event.getEventType(), e.toString()))); + } catch (Exception e) {//Try to catch ELogException or possible RuntimeExceptions if thrown + //Last resort log to the system for failed audit log attempt + if(isAudit == true) { + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_LOG_WRITE_FAILED", event.getEventType(), e.toString(), + "Audit Event Failure!"))); + } } } } diff --git a/base/server/cms/src/com/netscape/cms/logging/SignedAuditLogger.java b/base/server/cms/src/com/netscape/cms/logging/SignedAuditLogger.java index 183f93c..90b5d5d 100644 --- a/base/server/cms/src/com/netscape/cms/logging/SignedAuditLogger.java +++ b/base/server/cms/src/com/netscape/cms/logging/SignedAuditLogger.java @@ -18,11 +18,13 @@ package com.netscape.cms.logging; import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.logging.ConsoleError; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.logging.LogCategory; import com.netscape.certsrv.logging.LogEvent; import com.netscape.certsrv.logging.LogSource; import com.netscape.certsrv.logging.SignedAuditEvent; +import com.netscape.certsrv.logging.SystemEvent; /** * A class represents certificate server logger @@ -53,37 +55,48 @@ public class SignedAuditLogger extends Logger { Object params[], boolean multiline) { // create event - SignedAuditEvent event = (SignedAuditEvent)create( + SignedAuditEvent event = (SignedAuditEvent) create( category, source, level, message, params, multiline); // parse attributes in message int start = 0; - while (start < message.length()) { - // find [name=value] - int i = message.indexOf("[", start); - if (i < 0) break; + try { + while (start < message.length()) { - int j = message.indexOf("=", i + 1); - if (j < 0) { - throw new RuntimeException("Missing equal sign: " + message); - } + // find [name=value] + int i = message.indexOf("[", start); + if (i < 0) + break; - // get attribute name - String name = message.substring(i + 1, j); + int j = message.indexOf("=", i + 1); + if (j < 0) { + throw new RuntimeException("Missing equal sign: " + message); + } - int k = message.indexOf("]", j + 1); - if (k < 0) { - throw new RuntimeException("Missing closing bracket: " + message); - } + // get attribute name + String name = message.substring(i + 1, j); + + int k = message.indexOf("]", j + 1); + if (k < 0) { + throw new RuntimeException("Missing closing bracket: " + message); + } - // get attribute value - String value = message.substring(j + 1, k); + // get attribute value + String value = message.substring(j + 1, k); + + // store attribute in event + event.setAttribute(name, value); + + start = k + 1; + } - // store attribute in event - event.setAttribute(name, value); + } catch (Exception e) { //Catch any of our RunTime exceptions just so we can log it to the console + ConsoleError + .send(new SystemEvent(CMS.getUserMessage("CMS_LOG_WRITE_FAILED", event.getEventType(), e.toString(), + "Audit Event Failure!"))); - start = k + 1; + throw e; } mLogQueue.log(event); diff --git a/base/server/cmsbundle/src/UserMessages.properties b/base/server/cmsbundle/src/UserMessages.properties index 8007ce1..9c324f5 100644 --- a/base/server/cmsbundle/src/UserMessages.properties +++ b/base/server/cmsbundle/src/UserMessages.properties @@ -387,6 +387,7 @@ CMS_CA_SET_SERIALNO_FAILED=Request {0} was completed with errors.\nError setting CMS_CA_NOSERIALNO=Request {0} was completed with errors.\nCA has exausted all available serial numbers CMS_CA_SIGNING_CRL_FAILED=Failed signing CRL. Error {0} CMS_CA_SIGNING_CERT_FAILED=Failed signing certificate. Error {0} +CMS_CA_SIGNING_OPERATION_FAILED=Signing Unit signing operation failed. Error {0} CMS_CA_MISSING_INFO_IN_ISSUEREQ=Missing certificate info in issuing request CMS_CA_MISSING_INFO_IN_REVREQ=Missing revocation info in revocation request CMS_CA_MISSING_INFO_IN_CLAREQ=Missing CLA certificate info in cert4crl request @@ -506,6 +507,7 @@ CMS_LOG_INVALID_FILE_NAME=Attempt to initialize log with an invalid filename: \" CMS_LOG_UNEXPECTED_EXCEPTION=Caught unexpected exception: {0} CMS_LOG_ILLEGALARGUMENT=Illegal argument when opening: {0} CMS_LOG_CLOSE_FAILED=Failed to close file \"{0}\", error: {1} +CMS_LOG_OPEN_FAILED=Failed to open file \"{0}\", error: {1} CMS_LOG_INVALID_LOG_TYPE=Invalid log type in \"{0}\" property: {1} CMS_LOG_SRVLT_ILL_PLUGIN_ID=Another plugin ID already exists {0} CMS_LOG_SRVLT_NULL_CLASS=Plugin classname is null diff --git a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java index be79607..b1df429 100644 --- a/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java +++ b/base/server/cmscore/src/com/netscape/cmscore/apps/CMSEngine.java @@ -100,12 +100,14 @@ import com.netscape.certsrv.ldap.ELdapException; import com.netscape.certsrv.ldap.ILdapAuthInfo; import com.netscape.certsrv.ldap.ILdapConnFactory; import com.netscape.certsrv.ldap.ILdapConnInfo; +import com.netscape.certsrv.logging.ConsoleError; import com.netscape.certsrv.logging.ELogException; import com.netscape.certsrv.logging.IAuditor; import com.netscape.certsrv.logging.ILogEvent; import com.netscape.certsrv.logging.ILogEventListener; import com.netscape.certsrv.logging.ILogQueue; import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.SystemEvent; import com.netscape.certsrv.notification.IEmailFormProcessor; import com.netscape.certsrv.notification.IEmailResolver; import com.netscape.certsrv.notification.IEmailResolverKeys; @@ -1318,6 +1320,7 @@ public class CMSEngine implements ICMSEngine { public void checkForAndAutoShutdown() { String method= "CMSEngine: checkForAndAutoShutdown: "; CMS.debug(method + "begins"); + try { boolean allowShutdown = mConfig.getBoolean("autoShutdown.allowed", false); if ((!allowShutdown) || (mSigningKey == null) || @@ -1336,7 +1339,13 @@ public class CMSEngine implements ICMSEngine { byte[] result = signer.sign(); CMS.debug(method + " signining successful: " + new String(result)); } catch (SignatureException e) { + + //Let's write to the error console in case we are in a bad memory situation + //This will be the most likely to work, giving us a record of the signing failure + ConsoleError.send(new SystemEvent(CMS.getUserMessage("CMS_CA_SIGNING_OPERATION_FAILED", e.toString()))); + CMS.debug(method + "autoShutdown for " + e.toString()); + CMS.autoShutdown(); } catch (Exception e) { CMS.debug(method + "continue for " + e.toString()); -- 1.8.3.1 From 54a52b8cfffdb3d39408d3e765e45f5751715700 Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Thu, 1 Feb 2018 18:37:10 -0800 Subject: [PATCH 7/9] Ticket #2880 missing CMC request and response record This patch adds audit events to record received CMC requests and signed CMC responses: CMC_REQUEST_RECEIVED CMC_RESPONSE_SENT This patch fixes https://pagure.io/dogtagpki/issue/2880 Change-Id: Id093225b22a2c434e680726442c49b410fa738a3 (cherry picked from commit 55a6fa09d24b1c30bfd9d80357d69a8905ee4090) (cherry picked from commit d9ae15065d96bf5b634bae6dfa4b6d0e4780d4ae) --- base/ca/shared/conf/CS.cfg | 4 ++-- .../com/netscape/certsrv/logging/AuditEvent.java | 4 ++++ .../cms/servlet/common/CMCOutputTemplate.java | 15 ++++++++++++++ .../servlet/profile/ProfileSubmitCMCServlet.java | 23 ++++++++++++++++++---- base/server/cmsbundle/src/LogMessages.properties | 19 ++++++++++++++++-- .../com/netscape/cmsutil/crypto/CryptoUtil.java | 10 +--------- base/util/src/com/netscape/cmsutil/util/Utils.java | 23 ++++++++++++++++++++++ 7 files changed, 81 insertions(+), 17 deletions(-) diff --git a/base/ca/shared/conf/CS.cfg b/base/ca/shared/conf/CS.cfg index 76a7057..59de904 100644 --- a/base/ca/shared/conf/CS.cfg +++ b/base/ca/shared/conf/CS.cfg @@ -905,11 +905,11 @@ log.instance.SignedAudit._001=## Signed Audit Logging log.instance.SignedAudit._002=## log.instance.SignedAudit._003=## log.instance.SignedAudit._004=## Available Audit events: -log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,CERT_SIGNING_INFO,OCSP_SIGNING_INFO,CRL_SIGNING_INFO,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ,INTER_BOUNDARY,AUTH,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CMC_PROOF_OF_IDENTIFICATION,CMC_ID_POP_LINK_WITNESS,SCHEDULE_CRL_GENERATION,DELTA_CRL_GENERATION,DELTA_CRL_PUBLISHING,FULL_CRL_GENERATION,FULL_CRL_PUBLISHING,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,CMC_USER_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_GENERATION,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,AUTHORITY_CONFIG,ACCESS_SESSION_ESTABLISH,ACCESS_SESSION_TERMINATED,SECURITY_DATA_ARCHIVAL_REQUEST,RANDOM_GENERATION +log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,CERT_SIGNING_INFO,OCSP_SIGNING_INFO,CRL_SIGNING_INFO,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ,INTER_BOUNDARY,AUTH,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CMC_PROOF_OF_IDENTIFICATION,CMC_ID_POP_LINK_WITNESS,SCHEDULE_CRL_GENERATION,DELTA_CRL_GENERATION,DELTA_CRL_PUBLISHING,FULL_CRL_GENERATION,FULL_CRL_PUBLISHING,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,CMC_USER_SIGNED_REQUEST_SIG_VERIFY,CMC_REQUEST_RECEIVED,CMC_RESPONSE_SENT,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_GENERATION,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,AUTHORITY_CONFIG,ACCESS_SESSION_ESTABLISH,ACCESS_SESSION_TERMINATED,SECURITY_DATA_ARCHIVAL_REQUEST,RANDOM_GENERATION log.instance.SignedAudit._006=## log.instance.SignedAudit.bufferSize=512 log.instance.SignedAudit.enable=true -log.instance.SignedAudit.events=ACCESS_SESSION_ESTABLISH,ACCESS_SESSION_TERMINATED,AUTH,AUTHZ,CERT_REQUEST_PROCESSED,CERT_SIGNING_INFO,CMC_SIGNED_REQUEST_SIG_VERIFY,CMC_USER_SIGNED_REQUEST_SIG_VERIFY,CONFIG_AUTH,CONFIG_CERT_PROFILE,CONFIG_ENCRYPTION,CONFIG_ROLE,CONFIG_SERIAL_NUMBER,CONFIG_SIGNED_AUDIT,CONFIG_TRUSTED_PUBLIC_KEY,CRL_SIGNING_INFO,DELTA_CRL_GENERATION,FULL_CRL_GENERATION,LOG_PATH_CHANGE,OCSP_GENERATION,OCSP_SIGNING_INFO,PROFILE_CERT_REQUEST,PROOF_OF_POSSESSION,RANDOM_GENERATION,ROLE_ASSUME,SECURITY_DOMAIN_UPDATE,SELFTESTS_EXECUTION +log.instance.SignedAudit.events=ACCESS_SESSION_ESTABLISH,ACCESS_SESSION_TERMINATED,AUTH,AUTHZ,CERT_REQUEST_PROCESSED,CERT_SIGNING_INFO,CMC_SIGNED_REQUEST_SIG_VERIFY,CMC_USER_SIGNED_REQUEST_SIG_VERIFY,CMC_REQUEST_RECEIVED,CMC_RESPONSE_SENT,CONFIG_AUTH,CONFIG_CERT_PROFILE,CONFIG_ENCRYPTION,CONFIG_ROLE,CONFIG_SERIAL_NUMBER,CONFIG_SIGNED_AUDIT,CONFIG_TRUSTED_PUBLIC_KEY,CRL_SIGNING_INFO,DELTA_CRL_GENERATION,FULL_CRL_GENERATION,LOG_PATH_CHANGE,OCSP_GENERATION,OCSP_SIGNING_INFO,PROFILE_CERT_REQUEST,PROOF_OF_POSSESSION,RANDOM_GENERATION,ROLE_ASSUME,SECURITY_DOMAIN_UPDATE,SELFTESTS_EXECUTION log.instance.SignedAudit.filters.CMC_SIGNED_REQUEST_SIG_VERIFY=(Outcome=Failure) log.instance.SignedAudit.filters.CMC_USER_SIGNED_REQUEST_SIG_VERIFY=(Outcome=Failure) log.instance.SignedAudit.filters.DELTA_CRL_GENERATION=(Outcome=Failure) diff --git a/base/common/src/com/netscape/certsrv/logging/AuditEvent.java b/base/common/src/com/netscape/certsrv/logging/AuditEvent.java index 131b2a9..db58f34 100644 --- a/base/common/src/com/netscape/certsrv/logging/AuditEvent.java +++ b/base/common/src/com/netscape/certsrv/logging/AuditEvent.java @@ -67,6 +67,10 @@ public class AuditEvent extends LogEvent { "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5"; public final static String PROFILE_CERT_REQUEST = "LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST_5"; + public final static String CMC_REQUEST_RECEIVED = + "LOGGING_SIGNED_AUDIT_CMC_REQUEST_RECEIVED_3"; + public final static String CMC_RESPONSE_SENT = + "LOGGING_SIGNED_AUDIT_CMC_RESPONSE_SENT_3"; public final static String INTER_BOUNDARY = "LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS_5"; public final static String CERT_PROFILE_APPROVAL = diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java index 814a9c2..e89c9a0 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java +++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java @@ -79,6 +79,7 @@ import com.netscape.certsrv.base.SessionContext; import com.netscape.certsrv.ca.ICertificateAuthority; import com.netscape.certsrv.dbs.certdb.ICertRecord; import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditEvent; import com.netscape.certsrv.logging.AuditFormat; import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.logging.LogEvent; @@ -150,6 +151,7 @@ public class CMCOutputTemplate { OutputStream os = resp.getOutputStream(); os.write(contentBytes); os.flush(); + auditCMCResponseSent(Utils.base64encode(contentBytes, false)); } catch (Exception e) { CMS.debug("CMCOutputTemplate createFullResponseWithFailedStatus Exception: " + e.toString()); return; @@ -480,6 +482,7 @@ public class CMCOutputTemplate { OutputStream os = resp.getOutputStream(); os.write(contentBytes); os.flush(); + auditCMCResponseSent(Utils.base64encode(contentBytes, false)); CMS.debug(method + "ends"); } catch (java.security.cert.CertificateEncodingException e) { CMS.debug(method + e.toString()); @@ -722,6 +725,7 @@ public class CMCOutputTemplate { OutputStream os = resp.getOutputStream(); os.write(contentBytes); os.flush(); + auditCMCResponseSent(Utils.base64encode(contentBytes, false)); } catch (java.security.cert.CertificateEncodingException e) { CMS.debug("CMCOutputTemplate exception: " + e.toString()); } catch (InvalidBERException e) { @@ -1391,6 +1395,17 @@ public class CMCOutputTemplate { signedAuditLogger.log(msg); } + protected void auditCMCResponseSent(String response) { + SessionContext context = SessionContext.getContext(); + + String auditMessage = CMS.getLogMessage( + AuditEvent.CMC_RESPONSE_SENT, + (String) context.get(SessionContext.USER_ID), + ILogger.SUCCESS, + Utils.normalizeString(response)); + audit(auditMessage); + } + private RevocationReason toRevocationReason(ENUMERATED n) { long code = n.getValue(); if (code == RevokeRequest.aACompromise.getValue()) diff --git a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java index 5509080..91a26b1 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java +++ b/base/server/cms/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java @@ -46,9 +46,10 @@ import com.netscape.certsrv.authentication.IAuthToken; import com.netscape.certsrv.authorization.AuthzToken; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.SessionContext; -import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditEvent; import com.netscape.certsrv.logging.event.AuthEvent; import com.netscape.certsrv.logging.event.CertRequestProcessedEvent; +import com.netscape.certsrv.logging.ILogger; import com.netscape.certsrv.profile.ECMCBadIdentityException; import com.netscape.certsrv.profile.ECMCBadMessageCheckException; import com.netscape.certsrv.profile.ECMCBadRequestException; @@ -67,6 +68,8 @@ import com.netscape.certsrv.request.INotify; import com.netscape.certsrv.request.IRequest; import com.netscape.certsrv.request.RequestId; import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.logging.Logger; +import com.netscape.cms.logging.SignedAuditLogger; import com.netscape.cms.servlet.common.AuthCredentials; import com.netscape.cms.servlet.common.CMCOutputTemplate; import com.netscape.cms.servlet.common.CMSRequest; @@ -85,6 +88,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { /** * */ + private static Logger signedAuditLogger = SignedAuditLogger.getLogger(); private static final long serialVersionUID = -8017841111435988197L; private static final String PROP_PROFILE_ID = "profileId"; @@ -112,7 +116,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { } private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { - + String method = "ProfileSubmitCMCServlet.setInputsIntoContext: "; // passing inputs into context Enumeration inputIds = profile.getProfileInputIds(); @@ -126,6 +130,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { String inputName = inputNames.nextElement(); if (request.getParameter(inputName) != null) { + CMS.debug(method + "setting: " + inputName); ctx.set(inputName, request.getParameter(inputName)); } } @@ -399,7 +404,7 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { IProfileContext ctx = profile.createContext(); if (requestB64 != null) { ctx.set("cert_request_type", cert_request_type); - ctx.set("cert_request", requestB64); + ctx.set("cert_request", Utils.normalizeString(requestB64)); } // passing auths into context IProfileAuthenticator authenticator = null; @@ -481,6 +486,17 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { } } + String auditSubjectID = auditSubjectID(); + if (authToken != null) { + auditSubjectID = authToken.getInString(IAuthToken.USER_ID); + } + String auditMessage = CMS.getLogMessage( + AuditEvent.CMC_REQUEST_RECEIVED, + auditSubjectID, + ILogger.SUCCESS, + Utils.normalizeString(requestB64)); + signedAuditLogger.log(auditMessage); + IRequest reqs[] = null; /////////////////////////////////////////////// @@ -777,7 +793,6 @@ public class ProfileSubmitCMCServlet extends ProfileServlet { } } //for - String auditSubjectID = auditSubjectID(); String auditRequesterID = ILogger.UNIDENTIFIED; try { diff --git a/base/server/cmsbundle/src/LogMessages.properties b/base/server/cmsbundle/src/LogMessages.properties index 9ca508a..7963f6f 100644 --- a/base/server/cmsbundle/src/LogMessages.properties +++ b/base/server/cmsbundle/src/LogMessages.properties @@ -2008,6 +2008,21 @@ LOGGING_SIGNED_AUDIT_CRL_SIGNING_INFO=:[AuditEvent=CRL_SI # LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5=:[AuditEvent=NON_PROFILE_CERT_REQUEST][SubjectID={0}][Outcome={1}][ReqID={2}][ServiceID={3}][CertSubject={4}] certificate request made without certificate profiles # +# LOGGING_SIGNED_AUDIT_CMC_REQUEST_RECEIVED +# - used when a CMC request is received. +# SubjectID must be the UID of user that triggered this event +# (if CMC requests is signed by an agent, SubjectID should +# be that of the agent) +# In case of an unsigned request, it would bear $Unidentified$ +# +LOGGING_SIGNED_AUDIT_CMC_REQUEST_RECEIVED_3=:[AuditEvent=CMC_REQUEST_RECEIVED][SubjectID={0}][Outcome={1}][CMCRequest={2}] CMC request received +# +# LOGGING_SIGNED_AUDIT_CMC_RESPONSE_SENT +# - used when a CMC response is sent +# SubjectID must be the UID of user that triggered this event +# +LOGGING_SIGNED_AUDIT_CMC_RESPONSE_SENT_3=:[AuditEvent=CMC_RESPONSE_SENT][SubjectID={0}][Outcome={1}][CMCResponse={2}] CMC response sent +# # LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST # - used when a profile certificate request is made (before approval process) # SubjectID must be the UID of user that triggered this event @@ -2220,13 +2235,13 @@ LOGGING_SIGNED_AUDIT_OCSP_GENERATION=:[AuditEvent=OCSP_GEN LOGGING_SIGNED_AUDIT_RANDOM_GENERATION=:[AuditEvent=RANDOM_GENERATION]{0} Random number generation # # LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY -# - used when CMC (agent-pre-signed) certificate requests or revocation requests +# - used when agent signed CMC certificate requests or revocation requests # are submitted and signature is verified # ReqType must be the request type (enrollment, or revocation) # CertSubject must be the certificate subject name of the certificate request # SignerInfo must be a unique String representation for the signer # -LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY=:[AuditEvent=CMC_SIGNED_REQUEST_SIG_VERIFY]{0} agent pre-approved CMC request signature verification +LOGGING_SIGNED_AUDIT_CMC_SIGNED_REQUEST_SIG_VERIFY=:[AuditEvent=CMC_SIGNED_REQUEST_SIG_VERIFY]{0} agent signed CMC request signature verification # # LOGGING_SIGNED_AUDIT_CMC_USER_SIGNED_REQUEST_SIG_VERIFY # - used when CMC (user-signed or self-signed) certificate requests or revocation requests diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java index f527967..27ae0de 100644 --- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java @@ -1198,15 +1198,7 @@ public class CryptoUtil { // grammar defined at https://tools.ietf.org/html/rfc7468#section-3 s = s.replaceAll("-----(BEGIN|END) [\\p{Print}&&[^- ]]([- ]?[\\p{Print}&&[^- ]])*-----", ""); - StringBuffer sb = new StringBuffer(); - StringTokenizer st = new StringTokenizer(s, "\r\n "); - - while (st.hasMoreTokens()) { - String nextLine = st.nextToken(); - nextLine = nextLine.trim(); - sb.append(nextLine); - } - return sb.toString(); + return Utils.normalizeString(s); } public static String normalizeCertStr(String s) { diff --git a/base/util/src/com/netscape/cmsutil/util/Utils.java b/base/util/src/com/netscape/cmsutil/util/Utils.java index a9ee974..5ff78ad 100644 --- a/base/util/src/com/netscape/cmsutil/util/Utils.java +++ b/base/util/src/com/netscape/cmsutil/util/Utils.java @@ -32,6 +32,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.StringTokenizer; import java.util.Vector; import org.apache.commons.codec.binary.Base64; @@ -330,4 +331,26 @@ public class Utils { public static byte[] base64decode(String string) { return Base64.decodeBase64(string); } + + /** + * Normalize B64 input String + * + * @pram string base-64 string + * @return normalized string + */ + public static String normalizeString(String string) { + if (string == null) { + return string; + } + + StringBuffer sb = new StringBuffer(); + StringTokenizer st = new StringTokenizer(string, "\r\n "); + + while (st.hasMoreTokens()) { + String nextLine = st.nextToken(); + nextLine = nextLine.trim(); + sb.append(nextLine); + } + return sb.toString(); + } } -- 1.8.3.1 From 5d46447f9c680fff61bbb72b36dee13e53f549af Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Sat, 3 Feb 2018 15:50:24 -0800 Subject: [PATCH 8/9] Ticket #2921 CMC: Revocation works with an unknown revRequest.issuer This patche adds check between the issuer value of the RevokeRequest against the issuer of the certificate to be revoked. fixes: https://pagure.io/dogtagpki/issue/2921 Change-Id: Ib2bb2debeb7d1c7ffea1799b5c32630062ddca6a (cherry picked from commit c2c5bdad088fabbb89a8d3634530c74dae78c875) (cherry picked from commit d3fa14e61d76de48631a209f95ae6f91d9da4484) --- .../com/netscape/certsrv/base/SessionContext.java | 1 + .../src/com/netscape/cmstools/CMCRequest.java | 1 + .../cms/authentication/CMCUserSignedAuth.java | 18 ++++++++ .../cms/servlet/common/CMCOutputTemplate.java | 52 +++++++++++++++++++--- 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/base/common/src/com/netscape/certsrv/base/SessionContext.java b/base/common/src/com/netscape/certsrv/base/SessionContext.java index 9323e6e..691173b 100644 --- a/base/common/src/com/netscape/certsrv/base/SessionContext.java +++ b/base/common/src/com/netscape/certsrv/base/SessionContext.java @@ -56,6 +56,7 @@ public class SessionContext extends Hashtable { * Principal name object of the signed CMC request */ public static final String CMC_SIGNER_PRINCIPAL = "cmcSignerPrincipal"; + public static final String CMC_ISSUER_PRINCIPAL = "cmcISSUERPrincipal"; public static final String CMC_SIGNER_INFO = "cmcSignerInfo"; public static final String CMC_REQUEST_CERT_SUBJECT = "cmcRequestCertSubject"; diff --git a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java index fc58f4e..8146cee 100644 --- a/base/java-tools/src/com/netscape/cmstools/CMCRequest.java +++ b/base/java-tools/src/com/netscape/cmstools/CMCRequest.java @@ -1180,6 +1180,7 @@ public class CMCRequest { System.out.println(method + "issuer name must be supplied when shared secret is used"); System.exit(1); } + System.out.println(method + "adding revRequestIssuer: " + revRequestIssuer); issuerName = new X500Name(revRequestIssuer); } else { // signing case; revokeSignCert is required if (revokeSignCert == null) { diff --git a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java index 9dbf787..527b7e5 100644 --- a/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java +++ b/base/server/cms/src/com/netscape/cms/authentication/CMCUserSignedAuth.java @@ -40,6 +40,7 @@ import java.util.Locale; import java.util.Vector; import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.INTEGER; @@ -491,6 +492,23 @@ public class CMCUserSignedAuth implements IAuthManager, IExtendedPluginInfo, Integer IntObject = Integer.valueOf((int) reasonCode); authToken.set(REASON_CODE, IntObject); + ANY issuerANY = revRequest.getIssuerName(); + // handling of faillures with issuer is deferred + // to CMCOutputTemplate so that we can + // have a chance to capture user identification info + if (issuerANY != null) { + try { + byte[] issuerBytes = issuerANY.getEncoded(); + X500Name issuerName = new X500Name(issuerBytes); + CMS.debug(method + "revRequest issuer name = " + issuerName.toString()); + // capture issuer principal to be checked against + // cert issuer principal later in CMCOutputTemplate + auditContext.put(SessionContext.CMC_ISSUER_PRINCIPAL, issuerName); + } catch (Exception e) { + CMS.debug(method + "failed getting issuer from RevokeRequest:" + e.toString()); + } + } + //authToken.set("uid", uid); //authToken.set("userid", userid); diff --git a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java index e89c9a0..a0a946d 100644 --- a/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java +++ b/base/server/cms/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java @@ -971,10 +971,6 @@ public class CMCOutputTemplate { CMS.debug(method + "authManagerId =" + authManagerId); } - // in case of CMCUserSignedAuth, - // for matching signer and revoked cert principal - X500Name signerPrincipal = null; - // for auditing String auditRequesterID = null; auditRequesterID = (String) context.get(SessionContext.USER_ID); @@ -984,7 +980,14 @@ public class CMCOutputTemplate { } else { auditRequesterID = ILogger.NONROLEUSER; } - signerPrincipal = (X500Name) context.get(SessionContext.CMC_SIGNER_PRINCIPAL); + + // in case of CMCUserSignedAuth, + // for matching signer and revoked cert principal + X500Name reqSignerPrincipal = (X500Name) context.get(SessionContext.CMC_SIGNER_PRINCIPAL); + + // in case of shared secret revocation, for matching issuer + X500Name reqIssuerPrincipal = (X500Name) context.get(SessionContext.CMC_ISSUER_PRINCIPAL); + String auditSubjectID = null; String auditRequestType = "revoke"; String auditSerialNumber = null; @@ -1019,7 +1022,7 @@ public class CMCOutputTemplate { if (needVerify) { if (authManagerId.equals("CMCUserSignedAuth")) { - if (signerPrincipal == null) { + if (reqSignerPrincipal == null) { CMS.debug(method + "missing CMC signer principal"); OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), @@ -1235,12 +1238,47 @@ public class CMCOutputTemplate { X509CertImpl impl = record.getCertificate(); X500Name certPrincipal = (X500Name) impl.getSubjectDN(); + X500Name certIssuerPrincipal = (X500Name) impl.getIssuerDN(); auditSubjectID = certPrincipal.toString(); + // for Shared Secret case, check if issuer DN matches + if (reqSecret != null) { + CMS.debug(method + "shared secret revocation: checking issuer DN"); + if ((reqIssuerPrincipal == null) || + ! reqIssuerPrincipal.equals(certIssuerPrincipal)) { + msg = " certificate issuer DN and revocation request issuer DN do not match"; + CMS.debug(method + msg); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), + null, null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfoV2 = new CMCStatusInfoV2(CMCStatusInfoV2.FAILED, failed_bpids, msg, + otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_statusInfoV2, cmcStatusInfoV2); + controlSeq.addElement(tagattr); + + audit(new CertStatusChangeRequestProcessedEvent( + auditSubjectID, + ILogger.FAILURE, + auditReqID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus, + msg)); + + return bpid; + } else { + CMS.debug( method + "certificate issuer DN and revocation request issuer DN match"); + } + } + // in case of user-signed request, check if signer // principal matches that of the revoking cert if ((reqSecret == null) && authManagerId.equals("CMCUserSignedAuth")) { - if (!certPrincipal.equals(signerPrincipal)) { + if (!certPrincipal.equals(reqSignerPrincipal)) { msg = " certificate principal and signer do not match"; CMS.debug(method + msg); OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_IDENTITY), -- 1.8.3.1 From 8f94902f7837fa3f9338e461e706f7ca85cdf7fd Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Fri, 19 Jan 2018 17:01:12 +1100 Subject: [PATCH 9/9] Fix profile import dropping backslash characters When writing (importing, updating) RAW profile data, config values that have backslashes in them have the backslashes dropped, leading to issuance failures or issuance of incorrect certificates. For example: policyset.x.1.default.params.name=CN=$request.req_subject_name.cn$,O=Red Hat\, Inc. becomes: policyset.x.1.default.params.name=CN=$request.req_subject_name.cn$,O=Red Hat, Inc. which causes issuance failures due to parse failure of the resulting DN. This occurs because java.util.Properties is opinionated about what does or doesn't need to be escaped. The ProfileSubsystem "raw" methods originally used Properties to avoid more use of our "custom" SimpleProperties class. That turned out to be a mistake, due to Properties' incompatible treatment of backslashes. Switch over to SimpleProperties for handling raw profile data. Fixes: https://pagure.io/dogtagpki/issue/2909 Change-Id: I5cd738651cbfba0cad607d2b02edea04fe6be561 (cherry picked from commit e634316eb7f2aedc65fe528fb572b15e1bdc1eb2) (cherry picked from commit 10498f9c1db06ff31712a5543a9a0a76cb2523e2) --- .../dogtagpki/server/ca/rest/ProfileService.java | 27 ++++------------------ 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java b/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java index 3a68a1c..2884704 100644 --- a/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java +++ b/base/ca/src/org/dogtagpki/server/ca/rest/ProfileService.java @@ -29,7 +29,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Properties; import java.util.Vector; import javax.ws.rs.PathParam; @@ -523,9 +522,7 @@ public class ProfileService extends SubsystemService implements ProfileResource Map auditParams = new LinkedHashMap(); String profileId = null; String classId = null; - // First read the data into a Properties to process escaped - // separator characters (':', '=') in values - Properties properties = new Properties(); + SimpleProperties properties = new SimpleProperties(); try { // load data and read profileId and classId properties.load(new ByteArrayInputStream(data)); @@ -543,16 +540,9 @@ public class ProfileService extends SubsystemService implements ProfileResource properties.remove("profileId"); properties.remove("classId"); - // Now copy into SimpleProperties to avoid unwanted escapes - // of separator characters in output - SimpleProperties simpleProperties = new SimpleProperties(); - for (String k : properties.stringPropertyNames()) { - simpleProperties.setProperty(k, properties.getProperty(k)); - } - try { ByteArrayOutputStream out = new ByteArrayOutputStream(); - simpleProperties.store(out, null); + properties.store(out, null); data = out.toByteArray(); // original data sans profileId, classId IProfile profile = ps.getProfile(profileId); @@ -669,9 +659,7 @@ public class ProfileService extends SubsystemService implements ProfileResource throw new ConflictingOperationException("Cannot change profile data. Profile must be disabled"); } - // First read the data into a Properties to process escaped - // separator characters (':', '=') in values - Properties properties = new Properties(); + SimpleProperties properties = new SimpleProperties(); try { properties.load(new ByteArrayInputStream(data)); } catch (IOException e) { @@ -680,13 +668,6 @@ public class ProfileService extends SubsystemService implements ProfileResource properties.remove("profileId"); properties.remove("classId"); - // Now copy into SimpleProperties to avoid unwanted escapes - // of separator characters in output - SimpleProperties simpleProperties = new SimpleProperties(); - for (String k : properties.stringPropertyNames()) { - simpleProperties.setProperty(k, properties.getProperty(k)); - } - try { IProfile profile = ps.getProfile(profileId); if (profile == null) { @@ -694,7 +675,7 @@ public class ProfileService extends SubsystemService implements ProfileResource } ByteArrayOutputStream out = new ByteArrayOutputStream(); - simpleProperties.store(out, null); + properties.store(out, null); data = out.toByteArray(); // original data sans profileId, classId // create temporary profile to verify profile configuration -- 1.8.3.1