Search in sources :

Example 11 with X509Ca

use of org.xipki.ca.server.impl.X509Ca in project xipki by xipki.

the class X509CaCmpResponderImpl method generateCertificates.

// method processP10cr
private List<CertResponse> generateCertificates(List<CertTemplateData> certTemplates, List<ASN1Integer> certReqIds, CmpRequestorInfo requestor, ASN1OctetString tid, boolean keyUpdate, PKIMessage request, CmpControl cmpControl, String msgId, AuditEvent event) {
    X509Ca ca = getCa();
    final int n = certTemplates.size();
    List<CertResponse> ret = new ArrayList<>(n);
    if (cmpControl.isGroupEnroll()) {
        try {
            List<X509CertificateInfo> certInfos;
            if (keyUpdate) {
                certInfos = ca.regenerateCertificates(certTemplates, requestor, RequestType.CMP, tid.getOctets(), msgId);
            } else {
                certInfos = ca.generateCertificates(certTemplates, requestor, RequestType.CMP, tid.getOctets(), msgId);
            }
            // save the request
            Long reqDbId = null;
            if (ca.getCaInfo().isSaveRequest()) {
                try {
                    byte[] encodedRequest = request.getEncoded();
                    reqDbId = ca.addRequest(encodedRequest);
                } catch (Exception ex) {
                    LOG.warn("could not save request");
                }
            }
            for (int i = 0; i < n; i++) {
                X509CertificateInfo certInfo = certInfos.get(i);
                ret.add(postProcessCertInfo(certReqIds.get(i), certInfo, tid, cmpControl));
                if (reqDbId != null) {
                    ca.addRequestCert(reqDbId, certInfo.getCert().getCertId());
                }
            }
        } catch (OperationException ex) {
            for (int i = 0; i < n; i++) {
                ret.add(postProcessException(certReqIds.get(i), ex));
            }
        }
    } else {
        Long reqDbId = null;
        boolean savingRequestFailed = false;
        for (int i = 0; i < n; i++) {
            CertTemplateData certTemplate = certTemplates.get(i);
            ASN1Integer certReqId = certReqIds.get(i);
            X509CertificateInfo certInfo;
            try {
                if (keyUpdate) {
                    certInfo = ca.regenerateCertificate(certTemplate, requestor, RequestType.CMP, tid.getOctets(), msgId);
                } else {
                    certInfo = ca.generateCertificate(certTemplate, requestor, RequestType.CMP, tid.getOctets(), msgId);
                }
                if (ca.getCaInfo().isSaveRequest()) {
                    if (reqDbId == null && !savingRequestFailed) {
                        try {
                            byte[] encodedRequest = request.getEncoded();
                            reqDbId = ca.addRequest(encodedRequest);
                        } catch (Exception ex) {
                            savingRequestFailed = true;
                            LOG.warn("could not save request");
                        }
                    }
                    if (reqDbId != null) {
                        ca.addRequestCert(reqDbId, certInfo.getCert().getCertId());
                    }
                }
                ret.add(postProcessCertInfo(certReqId, certInfo, tid, cmpControl));
            } catch (OperationException ex) {
                ret.add(postProcessException(certReqId, ex));
            }
        }
    }
    return ret;
}
Also used : CertResponse(org.bouncycastle.asn1.cmp.CertResponse) X509Ca(org.xipki.ca.server.impl.X509Ca) ArrayList(java.util.ArrayList) X509CertificateInfo(org.xipki.ca.api.publisher.x509.X509CertificateInfo) ASN1Integer(org.bouncycastle.asn1.ASN1Integer) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) IOException(java.io.IOException) OperationException(org.xipki.ca.api.OperationException) CaMgmtException(org.xipki.ca.server.mgmt.api.CaMgmtException) ParseException(java.text.ParseException) CRLException(java.security.cert.CRLException) CRMFException(org.bouncycastle.cert.crmf.CRMFException) InsuffientPermissionException(org.xipki.ca.api.InsuffientPermissionException) CertTemplateData(org.xipki.ca.server.impl.CertTemplateData) OperationException(org.xipki.ca.api.OperationException)

Example 12 with X509Ca

use of org.xipki.ca.server.impl.X509Ca in project xipki by xipki.

the class X509CaCmpResponderImpl method getSystemInfo.

// method checkPermission
private String getSystemInfo(CmpRequestorInfo requestor, Set<Integer> acceptVersions) throws OperationException {
    X509Ca ca = getCa();
    StringBuilder sb = new StringBuilder(2000);
    // current maximal support version is 2
    int version = 2;
    if (CollectionUtil.isNonEmpty(acceptVersions) && !acceptVersions.contains(version)) {
        Integer ver = null;
        for (Integer m : acceptVersions) {
            if (m < version) {
                ver = m;
            }
        }
        if (ver == null) {
            throw new OperationException(ErrorCode.BAD_REQUEST, "none of versions " + acceptVersions + " is supported");
        } else {
            version = ver;
        }
    }
    sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
    sb.append("<systemInfo version=\"").append(version).append("\">");
    if (version == 2) {
        // CACert
        sb.append("<CACert>");
        sb.append(Base64.encodeToString(ca.getCaInfo().getCert().getEncodedCert()));
        sb.append("</CACert>");
        // CMP control
        sb.append("<cmpControl>");
        sb.append("<rrAkiRequired>").append(getCmpControl().isRrAkiRequired()).append("</rrAkiRequired>");
        sb.append("</cmpControl>");
        // Profiles
        Set<String> requestorProfiles = requestor.getCaHasRequestor().getProfiles();
        Set<String> supportedProfileNames = new HashSet<>();
        Set<String> caProfileNames = ca.caManager().getCertprofilesForCa(ca.getCaInfo().getIdent().getName());
        for (String caProfileName : caProfileNames) {
            if (requestorProfiles.contains("all") || requestorProfiles.contains(caProfileName)) {
                supportedProfileNames.add(caProfileName);
            }
        }
        if (CollectionUtil.isNonEmpty(supportedProfileNames)) {
            sb.append("<certprofiles>");
            for (String name : supportedProfileNames) {
                CertprofileEntry entry = ca.caManager().getCertprofile(name);
                if (entry.isFaulty()) {
                    continue;
                }
                sb.append("<certprofile>");
                sb.append("<name>").append(name).append("</name>");
                sb.append("<type>").append(entry.getType()).append("</type>");
                sb.append("<conf>");
                String conf = entry.getConf();
                if (StringUtil.isNotBlank(conf)) {
                    sb.append("<![CDATA[");
                    sb.append(conf);
                    sb.append("]]>");
                }
                sb.append("</conf>");
                sb.append("</certprofile>");
            }
            sb.append("</certprofiles>");
        }
        sb.append("</systemInfo>");
    } else {
        throw new OperationException(ErrorCode.BAD_REQUEST, "unsupported version " + version);
    }
    return sb.toString();
}
Also used : ASN1Integer(org.bouncycastle.asn1.ASN1Integer) BigInteger(java.math.BigInteger) X509Ca(org.xipki.ca.server.impl.X509Ca) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) DERUTF8String(org.bouncycastle.asn1.DERUTF8String) OperationException(org.xipki.ca.api.OperationException) HashSet(java.util.HashSet) CertprofileEntry(org.xipki.ca.server.mgmt.api.CertprofileEntry)

Example 13 with X509Ca

use of org.xipki.ca.server.impl.X509Ca in project xipki by xipki.

the class X509CaCmpResponderImpl method revokeCert.

public void revokeCert(CmpRequestorInfo requestor, BigInteger serialNumber, CrlReason reason, Date invalidityDate, RequestType reqType, String msgId) throws OperationException {
    ParamUtil.requireNonNull("requestor", requestor);
    int permission;
    if (reason == CrlReason.REMOVE_FROM_CRL) {
        permission = PermissionConstants.UNREVOKE_CERT;
    } else {
        permission = PermissionConstants.REVOKE_CERT;
    }
    try {
        checkPermission(requestor, permission);
    } catch (InsuffientPermissionException ex) {
        throw new OperationException(ErrorCode.NOT_PERMITTED, ex.getMessage());
    }
    X509Ca ca = getCa();
    Object returnedObj;
    if (PermissionConstants.UNREVOKE_CERT == permission) {
        // unrevoke
        returnedObj = ca.unrevokeCertificate(serialNumber, msgId);
    } else {
        returnedObj = ca.revokeCertificate(serialNumber, reason, invalidityDate, msgId);
    }
    if (returnedObj == null) {
        throw new OperationException(ErrorCode.UNKNOWN_CERT, "cert not exists");
    }
}
Also used : X509Ca(org.xipki.ca.server.impl.X509Ca) InsuffientPermissionException(org.xipki.ca.api.InsuffientPermissionException) OperationException(org.xipki.ca.api.OperationException)

Example 14 with X509Ca

use of org.xipki.ca.server.impl.X509Ca 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 15 with X509Ca

use of org.xipki.ca.server.impl.X509Ca 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

X509Ca (org.xipki.ca.server.impl.X509Ca)15 OperationException (org.xipki.ca.api.OperationException)13 InsuffientPermissionException (org.xipki.ca.api.InsuffientPermissionException)7 Date (java.util.Date)6 ASN1Integer (org.bouncycastle.asn1.ASN1Integer)6 BigInteger (java.math.BigInteger)5 X509CertificateInfo (org.xipki.ca.api.publisher.x509.X509CertificateInfo)5 ASN1OctetString (org.bouncycastle.asn1.ASN1OctetString)4 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)4 PKIBody (org.bouncycastle.asn1.cmp.PKIBody)4 X500Name (org.bouncycastle.asn1.x500.X500Name)4 Extensions (org.bouncycastle.asn1.x509.Extensions)4 CertTemplateData (org.xipki.ca.server.impl.CertTemplateData)4 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)3 CertificationRequestInfo (org.bouncycastle.asn1.pkcs.CertificationRequestInfo)3 ErrorCode (org.xipki.ca.api.OperationException.ErrorCode)3 CaMgmtException (org.xipki.ca.server.mgmt.api.CaMgmtException)3 IOException (java.io.IOException)2 CRLException (java.security.cert.CRLException)2 X509CRL (java.security.cert.X509CRL)2