Search in sources :

Example 1 with KnowCertResult

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

Example 2 with KnowCertResult

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

the class CertStoreQueryExecutor method knowsCertForSerial.

KnowCertResult knowsCertForSerial(NameId ca, BigInteger serial) throws DataAccessException {
    ParamUtil.requireNonNull("serial", serial);
    final String sql = sqls.sqlKnowsCertForSerial;
    ResultSet rs = null;
    PreparedStatement ps = borrowPreparedStatement(sql);
    try {
        ps.setString(1, serial.toString(16));
        ps.setInt(2, ca.getId());
        rs = ps.executeQuery();
        if (!rs.next()) {
            return KnowCertResult.UNKNOWN;
        }
        int userId = rs.getInt("UID");
        return new KnowCertResult(true, userId);
    } catch (SQLException ex) {
        throw datasource.translate(sql, ex);
    } finally {
        releaseDbResources(ps, rs);
    }
}
Also used : SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DEROctetString(org.bouncycastle.asn1.DEROctetString) KnowCertResult(org.xipki.ca.server.impl.KnowCertResult)

Aggregations

KnowCertResult (org.xipki.ca.server.impl.KnowCertResult)2 BigInteger (java.math.BigInteger)1 X509Certificate (java.security.cert.X509Certificate)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 Date (java.util.Date)1 X500Principal (javax.security.auth.x500.X500Principal)1 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)1 DEROctetString (org.bouncycastle.asn1.DEROctetString)1 DERPrintableString (org.bouncycastle.asn1.DERPrintableString)1 ContentInfo (org.bouncycastle.asn1.cms.ContentInfo)1 IssuerAndSerialNumber (org.bouncycastle.asn1.cms.IssuerAndSerialNumber)1 SignedData (org.bouncycastle.asn1.cms.SignedData)1 CertificationRequest (org.bouncycastle.asn1.pkcs.CertificationRequest)1 CertificationRequestInfo (org.bouncycastle.asn1.pkcs.CertificationRequestInfo)1 X500Name (org.bouncycastle.asn1.x500.X500Name)1 Extensions (org.bouncycastle.asn1.x509.Extensions)1 CMSSignedData (org.bouncycastle.cms.CMSSignedData)1 NameId (org.xipki.ca.api.NameId)1