Search in sources :

Example 61 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CaManagerImpl method revokeCa.

// method republishCertificates
@Override
public void revokeCa(String caName, CertRevocationInfo revocationInfo) throws CaMgmtException {
    caName = ParamUtil.requireNonBlank("caName", caName).toLowerCase();
    ParamUtil.requireNonNull("revocationInfo", revocationInfo);
    asssertMasterMode();
    if (!x509cas.containsKey(caName)) {
        throw new CaMgmtException(concat("unkown CA ", caName));
    }
    LOG.info("revoking CA '{}'", caName);
    X509Ca ca = x509cas.get(caName);
    CertRevocationInfo currentRevInfo = ca.getCaInfo().getRevocationInfo();
    if (currentRevInfo != null) {
        CrlReason currentReason = currentRevInfo.getReason();
        if (currentReason != CrlReason.CERTIFICATE_HOLD) {
            throw new CaMgmtException(concat("CA ", caName, " has been revoked with reason ", currentReason.name()));
        }
    }
    queryExecutor.revokeCa(caName, revocationInfo);
    try {
        ca.revokeCa(revocationInfo, CaAuditConstants.MSGID_ca_mgmt);
    } catch (OperationException ex) {
        throw new CaMgmtException(concat("could not revoke CA ", ex.getMessage()), ex);
    }
    LOG.info("revoked CA '{}'", caName);
    auditLogPciEvent(true, concat("REVOKE CA ", caName));
}
Also used : CertRevocationInfo(org.xipki.security.CertRevocationInfo) CaMgmtException(org.xipki.ca.server.mgmt.api.CaMgmtException) CrlReason(org.xipki.security.CrlReason) OperationException(org.xipki.ca.api.OperationException)

Example 62 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CaManagerImpl method unrevokeCa.

// method revokeCa
@Override
public void unrevokeCa(String caName) throws CaMgmtException {
    caName = ParamUtil.requireNonBlank("caName", caName).toLowerCase();
    asssertMasterMode();
    if (!x509cas.containsKey(caName)) {
        throw new CaMgmtException(concat("could not find CA named ", caName));
    }
    LOG.info("unrevoking of CA '{}'", caName);
    queryExecutor.unrevokeCa(caName);
    X509Ca ca = x509cas.get(caName);
    try {
        ca.unrevokeCa(CaAuditConstants.MSGID_ca_mgmt);
    } catch (OperationException ex) {
        throw new CaMgmtException(concat("could not unrevoke CA " + caName + ": ", ex.getMessage()), ex);
    }
    LOG.info("unrevoked CA '{}'", caName);
    auditLogPciEvent(true, concat("UNREVOKE CA ", caName));
}
Also used : CaMgmtException(org.xipki.ca.server.mgmt.api.CaMgmtException) OperationException(org.xipki.ca.api.OperationException)

Example 63 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CaManagerImpl method clearPublishQueue.

// method auditLogPciEvent
@Override
public void clearPublishQueue(String caName, List<String> publisherNames) throws CaMgmtException {
    asssertMasterMode();
    publisherNames = CollectionUtil.toLowerCaseList(publisherNames);
    if (caName == null) {
        if (CollectionUtil.isNonEmpty(publisherNames)) {
            throw new IllegalArgumentException("non-empty publisherNames is not allowed");
        }
        try {
            certstore.clearPublishQueue((NameId) null, (NameId) null);
            return;
        } catch (OperationException ex) {
            throw new CaMgmtException(ex.getMessage(), ex);
        }
    } else {
        caName = caName.toLowerCase();
    }
    X509Ca ca = x509cas.get(caName);
    if (ca == null) {
        throw new CaMgmtException(concat("could not find CA named ", caName));
    }
    if (ca.clearPublishQueue(publisherNames)) {
        throw new CaMgmtException("could not clear publisher Queue of CA " + caName + " for publishers " + publisherNames);
    }
}
Also used : CaMgmtException(org.xipki.ca.server.mgmt.api.CaMgmtException) OperationException(org.xipki.ca.api.OperationException)

Example 64 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class RestImpl method service.

public RestResponse service(String path, AuditEvent event, byte[] request, HttpRequestMetadataRetriever httpRetriever) {
    event.setApplicationName(CaAuditConstants.APPNAME);
    event.setName(CaAuditConstants.NAME_PERF);
    event.addEventData(CaAuditConstants.NAME_reqType, RequestType.REST.name());
    String msgId = RandomUtil.nextHexLong();
    event.addEventData(CaAuditConstants.NAME_mid, msgId);
    AuditLevel auditLevel = AuditLevel.INFO;
    AuditStatus auditStatus = AuditStatus.SUCCESSFUL;
    String auditMessage = null;
    try {
        if (responderManager == null) {
            String message = "responderManager in servlet not configured";
            LOG.error(message);
            throw new HttpRespAuditException(HttpResponseStatus.INTERNAL_SERVER_ERROR, null, message, AuditLevel.ERROR, AuditStatus.FAILED);
        }
        String caName = null;
        String command = null;
        X509Ca ca = null;
        if (path.length() > 1) {
            // the first char is always '/'
            String coreUri = path;
            int sepIndex = coreUri.indexOf('/', 1);
            if (sepIndex == -1 || sepIndex == coreUri.length() - 1) {
                String message = "invalid path " + path;
                LOG.error(message);
                throw new HttpRespAuditException(HttpResponseStatus.NOT_FOUND, null, message, AuditLevel.ERROR, AuditStatus.FAILED);
            }
            // skip also the first char ('/')
            String caAlias = coreUri.substring(1, sepIndex);
            command = coreUri.substring(sepIndex + 1);
            caName = responderManager.getCaNameForAlias(caAlias);
            if (caName == null) {
                caName = caAlias.toLowerCase();
            }
            ca = ((X509CaCmpResponderImpl) responderManager.getX509CaResponder(caName)).getCa();
        }
        if (caName == null || ca == null || ca.getCaInfo().getStatus() != CaStatus.ACTIVE) {
            String message;
            if (caName == null) {
                message = "no CA is specified";
            } else if (ca == null) {
                message = "unknown CA '" + caName + "'";
            } else {
                message = "CA '" + caName + "' is out of service";
            }
            LOG.warn(message);
            throw new HttpRespAuditException(HttpResponseStatus.NOT_FOUND, null, message, AuditLevel.INFO, AuditStatus.FAILED);
        }
        event.addEventData(CaAuditConstants.NAME_ca, ca.getCaIdent().getName());
        event.addEventType(command);
        RequestorInfo requestor;
        // Retrieve the user:password
        String hdrValue = httpRetriever.getHeader("Authorization");
        if (hdrValue != null && hdrValue.startsWith("Basic ")) {
            String user = null;
            byte[] password = null;
            if (hdrValue.length() > 6) {
                String b64 = hdrValue.substring(6);
                byte[] userPwd = Base64.decodeFast(b64);
                int idx = -1;
                for (int i = 0; i < userPwd.length; i++) {
                    if (userPwd[i] == ':') {
                        idx = i;
                        break;
                    }
                }
                if (idx != -1 && idx < userPwd.length - 1) {
                    user = new String(Arrays.copyOfRange(userPwd, 0, idx));
                    password = Arrays.copyOfRange(userPwd, idx + 1, userPwd.length);
                }
            }
            if (user == null) {
                throw new HttpRespAuditException(HttpResponseStatus.UNAUTHORIZED, "invalid Authorization information", AuditLevel.INFO, AuditStatus.FAILED);
            }
            NameId userIdent = ca.authenticateUser(user, password);
            if (userIdent == null) {
                throw new HttpRespAuditException(HttpResponseStatus.UNAUTHORIZED, "could not authenticate user", AuditLevel.INFO, AuditStatus.FAILED);
            }
            requestor = ca.getByUserRequestor(userIdent);
        } else {
            X509Certificate clientCert = httpRetriever.getTlsClientCert();
            if (clientCert == null) {
                throw new HttpRespAuditException(HttpResponseStatus.UNAUTHORIZED, null, "no client certificate", AuditLevel.INFO, AuditStatus.FAILED);
            }
            requestor = ca.getRequestor(clientCert);
        }
        if (requestor == null) {
            throw new OperationException(ErrorCode.NOT_PERMITTED, "no requestor specified");
        }
        event.addEventData(CaAuditConstants.NAME_requestor, requestor.getIdent().getName());
        String respCt = null;
        byte[] respBytes = null;
        if (RestAPIConstants.CMD_cacert.equalsIgnoreCase(command)) {
            respCt = RestAPIConstants.CT_pkix_cert;
            respBytes = ca.getCaInfo().getCert().getEncodedCert();
        } else if (RestAPIConstants.CMD_enroll_cert.equalsIgnoreCase(command)) {
            String profile = httpRetriever.getParameter(RestAPIConstants.PARAM_profile);
            if (StringUtil.isBlank(profile)) {
                throw new HttpRespAuditException(HttpResponseStatus.BAD_REQUEST, null, "required parameter " + RestAPIConstants.PARAM_profile + " not specified", AuditLevel.INFO, AuditStatus.FAILED);
            }
            profile = profile.toLowerCase();
            try {
                requestor.assertPermitted(PermissionConstants.ENROLL_CERT);
            } catch (InsuffientPermissionException ex) {
                throw new OperationException(ErrorCode.NOT_PERMITTED, ex.getMessage());
            }
            if (!requestor.isCertProfilePermitted(profile)) {
                throw new OperationException(ErrorCode.NOT_PERMITTED, "certProfile " + profile + " is not allowed");
            }
            String ct = httpRetriever.getHeader("Content-Type");
            if (!RestAPIConstants.CT_pkcs10.equalsIgnoreCase(ct)) {
                String message = "unsupported media type " + ct;
                throw new HttpRespAuditException(HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE, message, AuditLevel.INFO, AuditStatus.FAILED);
            }
            String strNotBefore = httpRetriever.getParameter(RestAPIConstants.PARAM_not_before);
            Date notBefore = (strNotBefore == null) ? null : DateUtil.parseUtcTimeyyyyMMddhhmmss(strNotBefore);
            String strNotAfter = httpRetriever.getParameter(RestAPIConstants.PARAM_not_after);
            Date notAfter = (strNotAfter == null) ? null : DateUtil.parseUtcTimeyyyyMMddhhmmss(strNotAfter);
            byte[] encodedCsr = request;
            CertificationRequest csr = CertificationRequest.getInstance(encodedCsr);
            ca.checkCsr(csr);
            CertificationRequestInfo certTemp = csr.getCertificationRequestInfo();
            X500Name subject = certTemp.getSubject();
            SubjectPublicKeyInfo publicKeyInfo = certTemp.getSubjectPublicKeyInfo();
            Extensions extensions = CaUtil.getExtensions(certTemp);
            CertTemplateData certTemplate = new CertTemplateData(subject, publicKeyInfo, notBefore, notAfter, extensions, profile);
            X509CertificateInfo certInfo = ca.generateCertificate(certTemplate, requestor, RequestType.REST, null, msgId);
            if (ca.getCaInfo().isSaveRequest()) {
                long dbId = ca.addRequest(encodedCsr);
                ca.addRequestCert(dbId, certInfo.getCert().getCertId());
            }
            X509Cert cert = certInfo.getCert();
            if (cert == null) {
                String message = "could not generate certificate";
                LOG.warn(message);
                throw new HttpRespAuditException(HttpResponseStatus.INTERNAL_SERVER_ERROR, null, message, AuditLevel.INFO, AuditStatus.FAILED);
            }
            respCt = RestAPIConstants.CT_pkix_cert;
            respBytes = cert.getEncodedCert();
        } else if (RestAPIConstants.CMD_revoke_cert.equalsIgnoreCase(command) || RestAPIConstants.CMD_delete_cert.equalsIgnoreCase(command)) {
            int permission;
            if (RestAPIConstants.CMD_revoke_cert.equalsIgnoreCase(command)) {
                permission = PermissionConstants.REVOKE_CERT;
            } else {
                permission = PermissionConstants.REMOVE_CERT;
            }
            try {
                requestor.assertPermitted(permission);
            } catch (InsuffientPermissionException ex) {
                throw new OperationException(ErrorCode.NOT_PERMITTED, ex.getMessage());
            }
            String strCaSha1 = httpRetriever.getParameter(RestAPIConstants.PARAM_ca_sha1);
            if (StringUtil.isBlank(strCaSha1)) {
                throw new HttpRespAuditException(HttpResponseStatus.BAD_REQUEST, null, "required parameter " + RestAPIConstants.PARAM_ca_sha1 + " not specified", AuditLevel.INFO, AuditStatus.FAILED);
            }
            String strSerialNumber = httpRetriever.getParameter(RestAPIConstants.PARAM_serial_number);
            if (StringUtil.isBlank(strSerialNumber)) {
                throw new HttpRespAuditException(HttpResponseStatus.BAD_REQUEST, null, "required parameter " + RestAPIConstants.PARAM_serial_number + " not specified", AuditLevel.INFO, AuditStatus.FAILED);
            }
            if (!strCaSha1.equalsIgnoreCase(ca.getHexSha1OfCert())) {
                throw new HttpRespAuditException(HttpResponseStatus.BAD_REQUEST, null, "unknown " + RestAPIConstants.PARAM_ca_sha1, AuditLevel.INFO, AuditStatus.FAILED);
            }
            BigInteger serialNumber = toBigInt(strSerialNumber);
            if (RestAPIConstants.CMD_revoke_cert.equalsIgnoreCase(command)) {
                String strReason = httpRetriever.getParameter(RestAPIConstants.PARAM_reason);
                CrlReason reason = (strReason == null) ? CrlReason.UNSPECIFIED : CrlReason.forNameOrText(strReason);
                if (reason == CrlReason.REMOVE_FROM_CRL) {
                    ca.unrevokeCertificate(serialNumber, msgId);
                } else {
                    Date invalidityTime = null;
                    String strInvalidityTime = httpRetriever.getParameter(RestAPIConstants.PARAM_invalidity_time);
                    if (StringUtil.isNotBlank(strInvalidityTime)) {
                        invalidityTime = DateUtil.parseUtcTimeyyyyMMddhhmmss(strInvalidityTime);
                    }
                    ca.revokeCertificate(serialNumber, reason, invalidityTime, msgId);
                }
            } else if (RestAPIConstants.CMD_delete_cert.equalsIgnoreCase(command)) {
                ca.removeCertificate(serialNumber, msgId);
            }
        } else if (RestAPIConstants.CMD_crl.equalsIgnoreCase(command)) {
            try {
                requestor.assertPermitted(PermissionConstants.GET_CRL);
            } catch (InsuffientPermissionException ex) {
                throw new OperationException(ErrorCode.NOT_PERMITTED, ex.getMessage());
            }
            String strCrlNumber = httpRetriever.getParameter(RestAPIConstants.PARAM_crl_number);
            BigInteger crlNumber = null;
            if (StringUtil.isNotBlank(strCrlNumber)) {
                try {
                    crlNumber = toBigInt(strCrlNumber);
                } catch (NumberFormatException ex) {
                    String message = "invalid crlNumber '" + strCrlNumber + "'";
                    LOG.warn(message);
                    throw new HttpRespAuditException(HttpResponseStatus.BAD_REQUEST, null, message, AuditLevel.INFO, AuditStatus.FAILED);
                }
            }
            X509CRL crl = ca.getCrl(crlNumber);
            if (crl == null) {
                String message = "could not get CRL";
                LOG.warn(message);
                throw new HttpRespAuditException(HttpResponseStatus.INTERNAL_SERVER_ERROR, null, message, AuditLevel.INFO, AuditStatus.FAILED);
            }
            respCt = RestAPIConstants.CT_pkix_crl;
            respBytes = crl.getEncoded();
        } else if (RestAPIConstants.CMD_new_crl.equalsIgnoreCase(command)) {
            try {
                requestor.assertPermitted(PermissionConstants.GEN_CRL);
            } catch (InsuffientPermissionException ex) {
                throw new OperationException(ErrorCode.NOT_PERMITTED, ex.getMessage());
            }
            X509CRL crl = ca.generateCrlOnDemand(msgId);
            if (crl == null) {
                String message = "could not generate CRL";
                LOG.warn(message);
                throw new HttpRespAuditException(HttpResponseStatus.INTERNAL_SERVER_ERROR, null, message, AuditLevel.INFO, AuditStatus.FAILED);
            }
            respCt = RestAPIConstants.CT_pkix_crl;
            respBytes = crl.getEncoded();
        } else {
            String message = "invalid command '" + command + "'";
            LOG.error(message);
            throw new HttpRespAuditException(HttpResponseStatus.NOT_FOUND, message, AuditLevel.INFO, AuditStatus.FAILED);
        }
        Map<String, String> headers = new HashMap<>();
        headers.put(RestAPIConstants.HEADER_PKISTATUS, RestAPIConstants.PKISTATUS_accepted);
        return new RestResponse(HttpResponseStatus.OK, respCt, headers, respBytes);
    } catch (OperationException ex) {
        ErrorCode code = ex.getErrorCode();
        if (LOG.isWarnEnabled()) {
            String msg = StringUtil.concat("generate certificate, OperationException: code=", code.name(), ", message=", ex.getErrorMessage());
            LOG.warn(msg);
            LOG.debug(msg, ex);
        }
        int sc;
        String failureInfo;
        switch(code) {
            case ALREADY_ISSUED:
                sc = HttpResponseStatus.BAD_REQUEST;
                failureInfo = RestAPIConstants.FAILINFO_badRequest;
                break;
            case BAD_CERT_TEMPLATE:
                sc = HttpResponseStatus.BAD_REQUEST;
                failureInfo = RestAPIConstants.FAILINFO_badCertTemplate;
                break;
            case BAD_REQUEST:
                sc = HttpResponseStatus.BAD_REQUEST;
                failureInfo = RestAPIConstants.FAILINFO_badRequest;
                break;
            case CERT_REVOKED:
                sc = HttpResponseStatus.CONFLICT;
                failureInfo = RestAPIConstants.FAILINFO_certRevoked;
                break;
            case CRL_FAILURE:
                sc = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                failureInfo = RestAPIConstants.FAILINFO_systemFailure;
                break;
            case DATABASE_FAILURE:
                sc = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                failureInfo = RestAPIConstants.FAILINFO_systemFailure;
                break;
            case NOT_PERMITTED:
                sc = HttpResponseStatus.UNAUTHORIZED;
                failureInfo = RestAPIConstants.FAILINFO_notAuthorized;
                break;
            case INVALID_EXTENSION:
                sc = HttpResponseStatus.BAD_REQUEST;
                failureInfo = RestAPIConstants.FAILINFO_badRequest;
                break;
            case SYSTEM_FAILURE:
                sc = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                failureInfo = RestAPIConstants.FAILINFO_systemFailure;
                break;
            case SYSTEM_UNAVAILABLE:
                sc = HttpResponseStatus.SERVICE_UNAVAILABLE;
                failureInfo = RestAPIConstants.FAILINFO_systemUnavail;
                break;
            case UNKNOWN_CERT:
                sc = HttpResponseStatus.BAD_REQUEST;
                failureInfo = RestAPIConstants.FAILINFO_badCertId;
                break;
            case UNKNOWN_CERT_PROFILE:
                sc = HttpResponseStatus.BAD_REQUEST;
                failureInfo = RestAPIConstants.FAILINFO_badCertTemplate;
                break;
            default:
                sc = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                failureInfo = RestAPIConstants.FAILINFO_systemFailure;
                break;
        }
        // end switch (code)
        event.setStatus(AuditStatus.FAILED);
        event.addEventData(CaAuditConstants.NAME_message, code.name());
        switch(code) {
            case DATABASE_FAILURE:
            case SYSTEM_FAILURE:
                auditMessage = code.name();
                break;
            default:
                auditMessage = code.name() + ": " + ex.getErrorMessage();
                break;
        }
        // end switch code
        Map<String, String> headers = new HashMap<>();
        headers.put(RestAPIConstants.HEADER_PKISTATUS, RestAPIConstants.PKISTATUS_rejection);
        if (StringUtil.isNotBlank(failureInfo)) {
            headers.put(RestAPIConstants.HEADER_failInfo, failureInfo);
        }
        return new RestResponse(sc, null, headers, null);
    } catch (HttpRespAuditException ex) {
        auditStatus = ex.getAuditStatus();
        auditLevel = ex.getAuditLevel();
        auditMessage = ex.getAuditMessage();
        return new RestResponse(ex.getHttpStatus(), null, null, null);
    } catch (Throwable th) {
        if (th instanceof EOFException) {
            LogUtil.warn(LOG, th, "connection reset by peer");
        } else {
            LOG.error("Throwable thrown, this should not happen!", th);
        }
        auditLevel = AuditLevel.ERROR;
        auditStatus = AuditStatus.FAILED;
        auditMessage = "internal error";
        return new RestResponse(HttpResponseStatus.INTERNAL_SERVER_ERROR, null, null, null);
    } finally {
        event.setStatus(auditStatus);
        event.setLevel(auditLevel);
        if (auditMessage != null) {
            event.addEventData(CaAuditConstants.NAME_message, auditMessage);
        }
    }
}
Also used : CertificationRequestInfo(org.bouncycastle.asn1.pkcs.CertificationRequestInfo) X509CRL(java.security.cert.X509CRL) NameId(org.xipki.ca.api.NameId) HashMap(java.util.HashMap) X509Ca(org.xipki.ca.server.impl.X509Ca) InsuffientPermissionException(org.xipki.ca.api.InsuffientPermissionException) X500Name(org.bouncycastle.asn1.x500.X500Name) Extensions(org.bouncycastle.asn1.x509.Extensions) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) CertTemplateData(org.xipki.ca.server.impl.CertTemplateData) X509Cert(org.xipki.security.X509Cert) EOFException(java.io.EOFException) CrlReason(org.xipki.security.CrlReason) OperationException(org.xipki.ca.api.OperationException) RestResponse(org.xipki.ca.server.api.RestResponse) AuditLevel(org.xipki.audit.AuditLevel) X509CertificateInfo(org.xipki.ca.api.publisher.x509.X509CertificateInfo) X509Certificate(java.security.cert.X509Certificate) Date(java.util.Date) AuditStatus(org.xipki.audit.AuditStatus) BigInteger(java.math.BigInteger) ErrorCode(org.xipki.ca.api.OperationException.ErrorCode) HashMap(java.util.HashMap) Map(java.util.Map) RequestorInfo(org.xipki.ca.server.mgmt.api.RequestorInfo) CertificationRequest(org.bouncycastle.asn1.pkcs.CertificationRequest)

Example 65 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class ScepImpl method servicePkiOperation0.

// method servicePkiOperation
private PkiMessage servicePkiOperation0(CMSSignedData requestContent, DecodedPkiMessage req, String certProfileName, String msgId, AuditEvent event) throws MessageDecodingException, OperationException {
    ParamUtil.requireNonNull("requestContent", requestContent);
    ParamUtil.requireNonNull("req", req);
    String tid = req.getTransactionId().getId();
    // verify and decrypt the request
    audit(event, CaAuditConstants.NAME_tid, tid);
    if (req.getFailureMessage() != null) {
        audit(event, CaAuditConstants.NAME_SCEP_failureMessage, req.getFailureMessage());
    }
    Boolean bo = req.isSignatureValid();
    if (bo != null && !bo.booleanValue()) {
        audit(event, CaAuditConstants.NAME_SCEP_signature, "invalid");
    }
    bo = req.isDecryptionSuccessful();
    if (bo != null && !bo.booleanValue()) {
        audit(event, CaAuditConstants.NAME_SCEP_decryption, "failed");
    }
    PkiMessage rep = new PkiMessage(req.getTransactionId(), MessageType.CertRep, Nonce.randomNonce());
    rep.setRecipientNonce(req.getSenderNonce());
    if (req.getFailureMessage() != null) {
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badRequest);
        return rep;
    }
    bo = req.isSignatureValid();
    if (bo != null && !bo.booleanValue()) {
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badMessageCheck);
        return rep;
    }
    bo = req.isDecryptionSuccessful();
    if (bo != null && !bo.booleanValue()) {
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badRequest);
        return rep;
    }
    Date signingTime = req.getSigningTime();
    if (maxSigningTimeBiasInMs > 0) {
        boolean isTimeBad = false;
        if (signingTime == null) {
            isTimeBad = true;
        } else {
            long now = System.currentTimeMillis();
            long diff = now - signingTime.getTime();
            if (diff < 0) {
                diff = -1 * diff;
            }
            isTimeBad = diff > maxSigningTimeBiasInMs;
        }
        if (isTimeBad) {
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badTime);
            return rep;
        }
    }
    // end if
    // check the digest algorithm
    String oid = req.getDigestAlgorithm().getId();
    ScepHashAlgo hashAlgo = ScepHashAlgo.forNameOrOid(oid);
    if (hashAlgo == null) {
        LOG.warn("tid={}: unknown digest algorithm {}", tid, oid);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badAlg);
        return rep;
    }
    boolean supported = false;
    if (hashAlgo == ScepHashAlgo.SHA1) {
        if (caCaps.containsCapability(CaCapability.SHA1)) {
            supported = true;
        }
    } else if (hashAlgo == ScepHashAlgo.SHA256) {
        if (caCaps.containsCapability(CaCapability.SHA256)) {
            supported = true;
        }
    } else if (hashAlgo == ScepHashAlgo.SHA512) {
        if (caCaps.containsCapability(CaCapability.SHA512)) {
            supported = true;
        }
    }
    if (!supported) {
        LOG.warn("tid={}: unsupported digest algorithm {}", tid, oid);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badAlg);
        return rep;
    }
    // check the content encryption algorithm
    ASN1ObjectIdentifier encOid = req.getContentEncryptionAlgorithm();
    if (CMSAlgorithm.DES_EDE3_CBC.equals(encOid)) {
        if (!caCaps.containsCapability(CaCapability.DES3)) {
            LOG.warn("tid={}: encryption with DES3 algorithm is not permitted", tid, encOid);
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badAlg);
            return rep;
        }
    } else if (AES_ENC_ALGOS.contains(encOid)) {
        if (!caCaps.containsCapability(CaCapability.AES)) {
            LOG.warn("tid={}: encryption with AES algorithm {} is not permitted", tid, encOid);
            rep.setPkiStatus(PkiStatus.FAILURE);
            rep.setFailInfo(FailInfo.badAlg);
            return rep;
        }
    } else {
        LOG.warn("tid={}: encryption with algorithm {} is not permitted", tid, encOid);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(FailInfo.badAlg);
        return rep;
    }
    X509Ca ca;
    try {
        ca = caManager.getX509Ca(caIdent);
    } catch (CaMgmtException ex) {
        LogUtil.error(LOG, ex, tid + "=" + tid + ",could not get X509CA");
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, ex);
    }
    X500Name caX500Name = ca.getCaInfo().getCert().getSubjectAsX500Name();
    try {
        SignedData signedData;
        MessageType mt = req.getMessageType();
        audit(event, CaAuditConstants.NAME_SCEP_messageType, mt.toString());
        switch(mt) {
            case PKCSReq:
            case RenewalReq:
            case UpdateReq:
                CertificationRequest csr = CertificationRequest.getInstance(req.getMessageData());
                X500Name reqSubject = csr.getCertificationRequestInfo().getSubject();
                if (LOG.isInfoEnabled()) {
                    LOG.info("tid={}, subject={}", tid, X509Util.getRfc4519Name(reqSubject));
                }
                try {
                    ca.checkCsr(csr);
                } catch (OperationException ex) {
                    LogUtil.warn(LOG, ex, "tid=" + tid + " POPO verification failed");
                    throw FailInfoException.BAD_MESSAGE_CHECK;
                }
                CertificationRequestInfo csrReqInfo = csr.getCertificationRequestInfo();
                X509Certificate reqSignatureCert = req.getSignatureCert();
                X500Principal reqSigCertSubject = reqSignatureCert.getSubjectX500Principal();
                boolean selfSigned = reqSigCertSubject.equals(reqSignatureCert.getIssuerX500Principal());
                if (selfSigned) {
                    X500Name tmp = X500Name.getInstance(reqSigCertSubject.getEncoded());
                    if (!tmp.equals(csrReqInfo.getSubject())) {
                        LOG.warn("tid={}, self-signed identityCert.subject != csr.subject");
                        throw FailInfoException.BAD_REQUEST;
                    }
                }
                if (X509Util.getCommonName(csrReqInfo.getSubject()) == null) {
                    throw new OperationException(ErrorCode.BAD_CERT_TEMPLATE, "tid=" + tid + ": no CommonName in requested subject");
                }
                NameId userIdent = null;
                String challengePwd = CaUtil.getChallengePassword(csrReqInfo);
                if (challengePwd != null) {
                    String[] strs = challengePwd.split(":");
                    if (strs == null || strs.length != 2) {
                        LOG.warn("tid={}: challengePassword does not have the format <user>:<password>", tid);
                        throw FailInfoException.BAD_REQUEST;
                    }
                    String user = strs[0];
                    String password = strs[1];
                    userIdent = ca.authenticateUser(user, password.getBytes());
                    if (userIdent == null) {
                        LOG.warn("tid={}: could not authenticate user {}", tid, user);
                        throw FailInfoException.BAD_REQUEST;
                    }
                }
                if (selfSigned) {
                    if (MessageType.PKCSReq != mt) {
                        LOG.warn("tid={}: self-signed certificate is not permitted for" + " messageType {}", tid, mt);
                        throw FailInfoException.BAD_REQUEST;
                    }
                    if (userIdent == null) {
                        LOG.warn("tid={}: could not extract user & password from challengePassword" + ", which are required for self-signed signature certificate", tid);
                        throw FailInfoException.BAD_REQUEST;
                    }
                } else {
                    // certificate is known by the CA
                    if (userIdent == null) {
                        // up to draft-nourse-scep-23 the client sends all messages to enroll
                        // certificate via MessageType PKCSReq
                        KnowCertResult knowCertRes = ca.knowsCertificate(reqSignatureCert);
                        if (!knowCertRes.isKnown()) {
                            LOG.warn("tid={}: signature certificate is not trusted by the CA", tid);
                            throw FailInfoException.BAD_REQUEST;
                        }
                        Integer userId = knowCertRes.getUserId();
                        if (userId == null) {
                            LOG.warn("tid={}: could not extract user from the signature cert", tid);
                            throw FailInfoException.BAD_REQUEST;
                        }
                        userIdent = ca.getUserIdent(userId);
                    }
                // end if
                }
                // end if
                ByUserRequestorInfo requestor = ca.getByUserRequestor(userIdent);
                checkUserPermission(requestor, certProfileName);
                byte[] tidBytes = getTransactionIdBytes(tid);
                Extensions extensions = CaUtil.getExtensions(csrReqInfo);
                CertTemplateData certTemplateData = new CertTemplateData(csrReqInfo.getSubject(), csrReqInfo.getSubjectPublicKeyInfo(), (Date) null, (Date) null, extensions, certProfileName);
                X509CertificateInfo cert = ca.generateCertificate(certTemplateData, requestor, RequestType.SCEP, tidBytes, msgId);
                /* Don't save SCEP message, since it contains password in plaintext
          if (ca.getCaInfo().isSaveRequest() && cert.getCert().getCertId() != null) {
            byte[] encodedRequest;
            try {
              encodedRequest = requestContent.getEncoded();
            } catch (IOException ex) {
              LOG.warn("could not encode request");
              encodedRequest = null;
            }
            if (encodedRequest != null) {
              long reqId = ca.addRequest(encodedRequest);
              ca.addRequestCert(reqId, cert.getCert().getCertId());
            }
          }*/
                signedData = buildSignedData(cert.getCert().getCert());
                break;
            case CertPoll:
                IssuerAndSubject is = IssuerAndSubject.getInstance(req.getMessageData());
                audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(is.getIssuer()));
                audit(event, CaAuditConstants.NAME_subject, X509Util.getRfc4519Name(is.getSubject()));
                ensureIssuedByThisCa(caX500Name, is.getIssuer());
                signedData = pollCert(ca, is.getSubject(), req.getTransactionId());
                break;
            case GetCert:
                IssuerAndSerialNumber isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
                BigInteger serial = isn.getSerialNumber().getPositiveValue();
                audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(isn.getName()));
                audit(event, CaAuditConstants.NAME_serial, LogUtil.formatCsn(serial));
                ensureIssuedByThisCa(caX500Name, isn.getName());
                signedData = getCert(ca, isn.getSerialNumber().getPositiveValue());
                break;
            case GetCRL:
                isn = IssuerAndSerialNumber.getInstance(req.getMessageData());
                serial = isn.getSerialNumber().getPositiveValue();
                audit(event, CaAuditConstants.NAME_issuer, X509Util.getRfc4519Name(isn.getName()));
                audit(event, CaAuditConstants.NAME_serial, LogUtil.formatCsn(serial));
                ensureIssuedByThisCa(caX500Name, isn.getName());
                signedData = getCrl(ca, serial);
                break;
            default:
                LOG.error("unknown SCEP messageType '{}'", req.getMessageType());
                throw FailInfoException.BAD_REQUEST;
        }
        // end switch<
        ContentInfo ci = new ContentInfo(CMSObjectIdentifiers.signedData, signedData);
        rep.setMessageData(ci);
        rep.setPkiStatus(PkiStatus.SUCCESS);
    } catch (FailInfoException ex) {
        LogUtil.error(LOG, ex);
        rep.setPkiStatus(PkiStatus.FAILURE);
        rep.setFailInfo(ex.getFailInfo());
    }
    return rep;
}
Also used : IssuerAndSerialNumber(org.bouncycastle.asn1.cms.IssuerAndSerialNumber) CertificationRequestInfo(org.bouncycastle.asn1.pkcs.CertificationRequestInfo) NameId(org.xipki.ca.api.NameId) X509Ca(org.xipki.ca.server.impl.X509Ca) X500Name(org.bouncycastle.asn1.x500.X500Name) KnowCertResult(org.xipki.ca.server.impl.KnowCertResult) Extensions(org.bouncycastle.asn1.x509.Extensions) IssuerAndSubject(org.xipki.scep.message.IssuerAndSubject) CertTemplateData(org.xipki.ca.server.impl.CertTemplateData) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) OperationException(org.xipki.ca.api.OperationException) MessageType(org.xipki.scep.transaction.MessageType) SignedData(org.bouncycastle.asn1.cms.SignedData) CMSSignedData(org.bouncycastle.cms.CMSSignedData) ScepHashAlgo(org.xipki.scep.crypto.ScepHashAlgo) X509CertificateInfo(org.xipki.ca.api.publisher.x509.X509CertificateInfo) Date(java.util.Date) X509Certificate(java.security.cert.X509Certificate) BigInteger(java.math.BigInteger) CaMgmtException(org.xipki.ca.server.mgmt.api.CaMgmtException) DecodedPkiMessage(org.xipki.scep.message.DecodedPkiMessage) PkiMessage(org.xipki.scep.message.PkiMessage) X500Principal(javax.security.auth.x500.X500Principal) BigInteger(java.math.BigInteger) ByUserRequestorInfo(org.xipki.ca.server.impl.ByUserRequestorInfo) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier) CertificationRequest(org.bouncycastle.asn1.pkcs.CertificationRequest)

Aggregations

OperationException (org.xipki.ca.api.OperationException)70 DERPrintableString (org.bouncycastle.asn1.DERPrintableString)20 CaMgmtException (org.xipki.ca.server.mgmt.api.CaMgmtException)19 Date (java.util.Date)16 BigInteger (java.math.BigInteger)15 X509Certificate (java.security.cert.X509Certificate)15 CertificateException (java.security.cert.CertificateException)13 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)13 X509Ca (org.xipki.ca.server.impl.X509Ca)13 PreparedStatement (java.sql.PreparedStatement)12 SQLException (java.sql.SQLException)12 IOException (java.io.IOException)11 X509CertificateInfo (org.xipki.ca.api.publisher.x509.X509CertificateInfo)11 DEROctetString (org.bouncycastle.asn1.DEROctetString)10 X500Name (org.bouncycastle.asn1.x500.X500Name)10 CRLDistPoint (org.bouncycastle.asn1.x509.CRLDistPoint)10 IssuingDistributionPoint (org.bouncycastle.asn1.x509.IssuingDistributionPoint)10 CrlReason (org.xipki.security.CrlReason)10 AuditEvent (org.xipki.audit.AuditEvent)9 NameId (org.xipki.ca.api.NameId)9