Search in sources :

Example 1 with CmpRequestorInfo

use of org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo in project xipki by xipki.

the class BaseCmpResponder method processPkiMessage0.

// method getX500Sender
/**
 * Processes the request and returns the response.
 * @param request
 *          Original request. Will only be used for the storage. Could be{@code null}.
 * @param requestor
 *          Requestor. Must not be {@code null}.
 * @param tid
 *          Transaction id. Must not be {@code null}.
 * @param message
 *          PKI message. Must not be {@code null}.
 * @param msgId
 *          Message id. Must not be {@code null}.
 * @param parameters
 *          Additional parameters.
 * @param event
 *          Audit event. Must not be {@code null}.
 * @return the response
 */
private PKIMessage processPkiMessage0(PKIMessage request, RequestorInfo requestor, ASN1OctetString tid, GeneralPKIMessage message, String msgId, Map<String, String> parameters, AuditEvent event) {
    if (!(requestor instanceof CmpRequestorInfo)) {
        throw new IllegalArgumentException("unknown requestor type " + requestor.getClass().getName());
    }
    CmpRequestorInfo cmpRequestor = (CmpRequestorInfo) requestor;
    event.addEventData(NAME_requestor, cmpRequestor.getIdent().getName());
    PKIHeader reqHeader = message.getHeader();
    PKIHeaderBuilder respHeader = new PKIHeaderBuilder(reqHeader.getPvno().getValue().intValue(), getSender(), reqHeader.getSender());
    respHeader.setTransactionID(tid);
    ASN1OctetString senderNonce = reqHeader.getSenderNonce();
    if (senderNonce != null) {
        respHeader.setRecipNonce(senderNonce);
    }
    PKIBody respBody;
    PKIBody reqBody = message.getBody();
    final int type = reqBody.getType();
    CmpControl cmpControl = getCmpControl();
    try {
        if (type == PKIBody.TYPE_INIT_REQ || type == PKIBody.TYPE_CERT_REQ || type == PKIBody.TYPE_KEY_UPDATE_REQ || type == PKIBody.TYPE_P10_CERT_REQ || type == PKIBody.TYPE_CROSS_CERT_REQ) {
            String eventType;
            if (PKIBody.TYPE_CERT_REQ == type) {
                eventType = Cmp.TYPE_cr;
            } else if (PKIBody.TYPE_INIT_REQ == type) {
                eventType = Cmp.TYPE_ir;
            } else if (PKIBody.TYPE_KEY_UPDATE_REQ == type) {
                eventType = Cmp.TYPE_kur;
            } else if (PKIBody.TYPE_P10_CERT_REQ == type) {
                eventType = Cmp.TYPE_p10cr;
            } else {
                // if (PKIBody.TYPE_CROSS_CERT_REQ == type) {
                eventType = Cmp.TYPE_ccr;
            }
            event.addEventType(eventType);
            String dfltCertprofileName = null;
            if (parameters != null) {
                dfltCertprofileName = parameters.get("certprofile");
            }
            respBody = cmpEnrollCert(dfltCertprofileName, request, respHeader, cmpControl, reqHeader, reqBody, cmpRequestor, tid, msgId, event);
        } else if (type == PKIBody.TYPE_CERT_CONFIRM) {
            event.addEventType(Cmp.TYPE_certConf);
            CertConfirmContent certConf = (CertConfirmContent) reqBody.getContent();
            respBody = confirmCertificates(tid, certConf, msgId);
        } else if (type == PKIBody.TYPE_REVOCATION_REQ) {
            respBody = cmpUnRevokeRemoveCertificates(request, respHeader, cmpControl, reqHeader, reqBody, cmpRequestor, msgId, event);
        } else if (type == PKIBody.TYPE_CONFIRM) {
            event.addEventType(Cmp.TYPE_pkiconf);
            respBody = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
        } else if (type == PKIBody.TYPE_GEN_MSG) {
            respBody = cmpGeneralMsg(respHeader, cmpControl, reqHeader, reqBody, cmpRequestor, tid, msgId, event);
        } else if (type == PKIBody.TYPE_ERROR) {
            event.addEventType(Cmp.TYPE_error);
            revokePendingCertificates(tid, msgId);
            respBody = new PKIBody(PKIBody.TYPE_CONFIRM, DERNull.INSTANCE);
        } else {
            event.addEventType("PKIBody." + type);
            respBody = buildErrorMsgPkiBody(PKIStatus.rejection, PKIFailureInfo.badRequest, "unsupported type " + type);
        }
    } catch (InsufficientPermissionException ex) {
        ErrorMsgContent emc = new ErrorMsgContent(new PKIStatusInfo(PKIStatus.rejection, new PKIFreeText(ex.getMessage()), new PKIFailureInfo(PKIFailureInfo.notAuthorized)));
        respBody = new PKIBody(PKIBody.TYPE_ERROR, emc);
    }
    if (respBody.getType() == PKIBody.TYPE_ERROR) {
        ErrorMsgContent errorMsgContent = (ErrorMsgContent) respBody.getContent();
        org.xipki.security.cmp.PkiStatusInfo pkiStatus = new org.xipki.security.cmp.PkiStatusInfo(errorMsgContent.getPKIStatusInfo());
        event.setStatus(AuditStatus.FAILED);
        String statusString = pkiStatus.statusMessage();
        if (statusString != null) {
            event.addEventData(NAME_message, statusString);
        }
    } else if (event.getStatus() == null) {
        event.setStatus(AuditStatus.SUCCESSFUL);
    }
    return new PKIMessage(respHeader.build(), respBody);
}
Also used : ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) org.bouncycastle.asn1.cmp(org.bouncycastle.asn1.cmp) InsufficientPermissionException(org.xipki.ca.api.InsufficientPermissionException) org.xipki.security(org.xipki.security) java.security(java.security) CmpRequestorInfo(org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo)

Example 2 with CmpRequestorInfo

use of org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo in project xipki by xipki.

the class BaseCmpResponder method processPkiMessage.

// method processPKIMessage0
public PKIMessage processPkiMessage(PKIMessage pkiMessage, X509Cert tlsClientCert, Map<String, String> parameters, AuditEvent event) {
    notNull(pkiMessage, "pkiMessage");
    notNull(event, "event");
    GeneralPKIMessage message = new GeneralPKIMessage(pkiMessage);
    PKIHeader reqHeader = message.getHeader();
    ASN1OctetString tid = reqHeader.getTransactionID();
    String msgId = RandomUtil.nextHexLong();
    event.addEventData(NAME_mid, msgId);
    if (tid == null) {
        byte[] randomBytes = randomTransactionId();
        tid = new DEROctetString(randomBytes);
    }
    String tidStr = Base64.encodeToString(tid.getOctets());
    event.addEventData(NAME_tid, tidStr);
    int reqPvno = reqHeader.getPvno().getValue().intValue();
    if (reqPvno < PVNO_CMP2000) {
        event.update(AuditLevel.INFO, AuditStatus.FAILED);
        event.addEventData(NAME_message, "unsupported version " + reqPvno);
        return buildErrorPkiMessage(tid, reqHeader, PKIFailureInfo.unsupportedVersion, null);
    }
    CmpControl cmpControl = getCmpControl();
    Integer failureCode = null;
    String statusText = null;
    Date messageTime = null;
    if (reqHeader.getMessageTime() != null) {
        try {
            messageTime = reqHeader.getMessageTime().getDate();
        } catch (ParseException ex) {
            LogUtil.error(LOG, ex, "tid=" + tidStr + ": could not parse messageTime");
        }
    }
    GeneralName recipient = reqHeader.getRecipient();
    boolean intentMe = recipient == null || intendsMe(recipient);
    if (!intentMe) {
        LOG.warn("tid={}: I am not the intended recipient, but '{}'", tid, reqHeader.getRecipient());
        failureCode = PKIFailureInfo.badRequest;
        statusText = "I am not the intended recipient";
    } else if (messageTime == null) {
        if (cmpControl.isMessageTimeRequired()) {
            failureCode = PKIFailureInfo.missingTimeStamp;
            statusText = "missing time-stamp";
        }
    } else {
        long messageTimeBias = cmpControl.getMessageTimeBias();
        if (messageTimeBias < 0) {
            messageTimeBias *= -1;
        }
        long msgTimeMs = messageTime.getTime();
        long currentTimeMs = System.currentTimeMillis();
        long bias = (msgTimeMs - currentTimeMs) / 1000L;
        if (bias > messageTimeBias) {
            failureCode = PKIFailureInfo.badTime;
            statusText = "message time is in the future";
        } else if (bias * -1 > messageTimeBias) {
            failureCode = PKIFailureInfo.badTime;
            statusText = "message too old";
        }
    }
    if (failureCode != null) {
        event.update(AuditLevel.INFO, AuditStatus.FAILED);
        event.addEventData(NAME_message, statusText);
        return buildErrorPkiMessage(tid, reqHeader, failureCode, statusText);
    }
    boolean isProtected = message.hasProtection();
    CmpRequestorInfo requestor;
    String errorStatus;
    if (isProtected) {
        try {
            ProtectionVerificationResult verificationResult = verifyProtection(tidStr, message, cmpControl);
            ProtectionResult pr = verificationResult.getProtectionResult();
            if (pr == ProtectionResult.SIGNATURE_VALID || pr == ProtectionResult.MAC_VALID) {
                errorStatus = null;
            } else if (pr == ProtectionResult.SIGNATURE_INVALID) {
                errorStatus = "request is protected by signature but invalid";
            } else if (pr == ProtectionResult.MAC_INVALID) {
                errorStatus = "request is protected by MAC but invalid";
            } else if (pr == ProtectionResult.SENDER_NOT_AUTHORIZED) {
                errorStatus = "request is protected but the requestor is not authorized";
            } else if (pr == ProtectionResult.SIGNATURE_ALGO_FORBIDDEN) {
                errorStatus = "request is protected by signature but the algorithm is forbidden";
            } else if (pr == ProtectionResult.MAC_ALGO_FORBIDDEN) {
                errorStatus = "request is protected by MAC but the algorithm is forbidden";
            } else {
                throw new IllegalStateException("should not reach here, unknown ProtectionResult " + pr);
            }
            requestor = (CmpRequestorInfo) verificationResult.getRequestor();
        } catch (Exception ex) {
            LogUtil.error(LOG, ex, "tid=" + tidStr + ": could not verify the signature");
            errorStatus = "request has invalid signature based protection";
            requestor = null;
        }
    } else if (tlsClientCert != null) {
        boolean authorized = false;
        X500Name x500Sender = getX500Sender(reqHeader);
        requestor = (x500Sender == null) ? null : getRequestor(x500Sender);
        if (requestor != null) {
            if (tlsClientCert.equals(requestor.getCert().getCert())) {
                authorized = true;
            }
        }
        if (authorized) {
            errorStatus = null;
        } else {
            LOG.warn("tid={}: not authorized requestor (TLS client '{}')", tid, tlsClientCert.getSubjectRfc4519Text());
            errorStatus = "requestor (TLS client certificate) is not authorized";
        }
    } else {
        errorStatus = "request has no protection";
        requestor = null;
    }
    if (errorStatus != null) {
        event.update(AuditLevel.INFO, AuditStatus.FAILED);
        event.addEventData(NAME_message, errorStatus);
        return buildErrorPkiMessage(tid, reqHeader, PKIFailureInfo.badMessageCheck, errorStatus);
    }
    PKIMessage resp = processPkiMessage0(pkiMessage, requestor, tid, message, msgId, parameters, event);
    if (isProtected) {
        resp = addProtection(resp, event, requestor);
    }
    return resp;
}
Also used : ProtectionResult(org.xipki.security.cmp.ProtectionResult) ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) ProtectionVerificationResult(org.xipki.security.cmp.ProtectionVerificationResult) X500Name(org.bouncycastle.asn1.x500.X500Name) CMPException(org.bouncycastle.cert.cmp.CMPException) ParseException(java.text.ParseException) InsufficientPermissionException(org.xipki.ca.api.InsufficientPermissionException) CRMFException(org.bouncycastle.cert.crmf.CRMFException) OperationException(org.xipki.ca.api.OperationException) GeneralPKIMessage(org.bouncycastle.cert.cmp.GeneralPKIMessage) CmpRequestorInfo(org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo) ParseException(java.text.ParseException) GeneralName(org.bouncycastle.asn1.x509.GeneralName)

Example 3 with CmpRequestorInfo

use of org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo in project xipki by xipki.

the class BaseCmpResponder method verifyProtection.

// method randomBytes
private ProtectionVerificationResult verifyProtection(String tid, GeneralPKIMessage pkiMessage, CmpControl cmpControl) throws CMPException, InvalidKeyException {
    ProtectedPKIMessage protectedMsg = new ProtectedPKIMessage(pkiMessage);
    PKIHeader header = protectedMsg.getHeader();
    X500Name sender = getX500Sender(header);
    if (sender == null) {
        LOG.warn("tid={}: not authorized requestor 'null'", tid);
        return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
    }
    AlgorithmIdentifier protectionAlg = header.getProtectionAlg();
    if (protectedMsg.hasPasswordBasedMacProtection()) {
        PBMParameter parameter = PBMParameter.getInstance(pkiMessage.getHeader().getProtectionAlg().getParameters());
        HashAlgo owfAlg;
        try {
            owfAlg = HashAlgo.getInstance(parameter.getOwf());
        } catch (NoSuchAlgorithmException ex) {
            LogUtil.warn(LOG, ex);
            return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
        }
        if (!cmpControl.isRequestPbmOwfPermitted(owfAlg)) {
            LOG.warn("MAC_ALGO_FORBIDDEN (PBMParameter.owf: {})", owfAlg.getJceName());
            return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
        }
        SignAlgo macAlg;
        try {
            macAlg = SignAlgo.getInstance(parameter.getMac());
        } catch (NoSuchAlgorithmException ex) {
            LogUtil.warn(LOG, ex);
            return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
        }
        if (!cmpControl.isRequestPbmMacPermitted(macAlg)) {
            LOG.warn("MAC_ALGO_FORBIDDEN (PBMParameter.mac: {})", macAlg.getJceName());
            return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
        }
        int iterationCount = parameter.getIterationCount().getValue().intValue();
        if (iterationCount < 1000) {
            LOG.warn("MAC_ALGO_FORBIDDEN (PBMParameter.iterationCount: {} < 1000)", iterationCount);
            return new ProtectionVerificationResult(null, ProtectionResult.MAC_ALGO_FORBIDDEN);
        }
        ASN1OctetString asn1 = header.getSenderKID();
        byte[] senderKID = (asn1 == null) ? null : asn1.getOctets();
        PKMACBuilder pkMacBuilder = new PKMACBuilder(new JcePKMACValuesCalculator());
        CmpRequestorInfo requestor = getMacRequestor(senderKID);
        if (requestor == null) {
            LOG.warn("tid={}: not authorized requestor with senderKID '{}", tid, (senderKID == null) ? "null" : Hex.toHexString(senderKID));
            return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
        }
        boolean macValid = protectedMsg.verify(pkMacBuilder, requestor.getPassword());
        return new ProtectionVerificationResult(requestor, macValid ? ProtectionResult.MAC_VALID : ProtectionResult.MAC_INVALID);
    } else {
        if (!cmpControl.getSigAlgoValidator().isAlgorithmPermitted(protectionAlg)) {
            LOG.warn("SIG_ALGO_FORBIDDEN: {}", pkiMessage.getHeader().getProtectionAlg().getAlgorithm().getId());
            return new ProtectionVerificationResult(null, ProtectionResult.SIGNATURE_ALGO_FORBIDDEN);
        }
        X500Name x500Sender = getX500Sender(header);
        CmpRequestorInfo requestor = (x500Sender == null) ? null : getRequestor(x500Sender);
        if (requestor == null) {
            LOG.warn("tid={}: not authorized requestor '{}'", tid, header.getSender());
            return new ProtectionVerificationResult(null, ProtectionResult.SENDER_NOT_AUTHORIZED);
        }
        ContentVerifierProvider verifierProvider = securityFactory.getContentVerifierProvider(requestor.getCert().getCert());
        if (verifierProvider == null) {
            LOG.warn("tid={}: not authorized requestor '{}'", tid, sender);
            return new ProtectionVerificationResult(requestor, ProtectionResult.SENDER_NOT_AUTHORIZED);
        }
        boolean signatureValid = protectedMsg.verify(verifierProvider);
        return new ProtectionVerificationResult(requestor, signatureValid ? ProtectionResult.SIGNATURE_VALID : ProtectionResult.SIGNATURE_INVALID);
    }
}
Also used : PKMACBuilder(org.bouncycastle.cert.crmf.PKMACBuilder) ProtectedPKIMessage(org.bouncycastle.cert.cmp.ProtectedPKIMessage) ProtectionVerificationResult(org.xipki.security.cmp.ProtectionVerificationResult) X500Name(org.bouncycastle.asn1.x500.X500Name) AlgorithmIdentifier(org.bouncycastle.asn1.x509.AlgorithmIdentifier) JcePKMACValuesCalculator(org.bouncycastle.cert.crmf.jcajce.JcePKMACValuesCalculator) CmpRequestorInfo(org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo) ContentVerifierProvider(org.bouncycastle.operator.ContentVerifierProvider)

Aggregations

ProtectedPKIMessage (org.bouncycastle.cert.cmp.ProtectedPKIMessage)3 CmpRequestorInfo (org.xipki.ca.api.mgmt.RequestorInfo.CmpRequestorInfo)3 X500Name (org.bouncycastle.asn1.x500.X500Name)2 GeneralPKIMessage (org.bouncycastle.cert.cmp.GeneralPKIMessage)2 InsufficientPermissionException (org.xipki.ca.api.InsufficientPermissionException)2 ProtectionVerificationResult (org.xipki.security.cmp.ProtectionVerificationResult)2 java.security (java.security)1 ParseException (java.text.ParseException)1 org.bouncycastle.asn1.cmp (org.bouncycastle.asn1.cmp)1 AlgorithmIdentifier (org.bouncycastle.asn1.x509.AlgorithmIdentifier)1 GeneralName (org.bouncycastle.asn1.x509.GeneralName)1 CMPException (org.bouncycastle.cert.cmp.CMPException)1 CRMFException (org.bouncycastle.cert.crmf.CRMFException)1 PKMACBuilder (org.bouncycastle.cert.crmf.PKMACBuilder)1 JcePKMACValuesCalculator (org.bouncycastle.cert.crmf.jcajce.JcePKMACValuesCalculator)1 ContentVerifierProvider (org.bouncycastle.operator.ContentVerifierProvider)1 OperationException (org.xipki.ca.api.OperationException)1 org.xipki.security (org.xipki.security)1 ProtectionResult (org.xipki.security.cmp.ProtectionResult)1