Search in sources :

Example 51 with ContentInfo

use of com.github.zhenwei.pkix.util.asn1.cms.ContentInfo in project xipki by xipki.

the class ScepServlet method service.

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    boolean post;
    String method = req.getMethod();
    if ("GET".equals(method)) {
        post = false;
    } else if ("POST".equals(method)) {
        post = true;
    } else {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        return;
    }
    AuditEvent event = new AuditEvent();
    event.setName(AuditEvent.NAME_PERF);
    event.putEventData(AuditEvent.NAME_servletPath, req.getServletPath());
    AuditLevel auditLevel = AuditLevel.INFO;
    String auditMessage = null;
    try {
        CaCaps caCaps = responder.getCaCaps();
        if (post && !caCaps.supportsPost()) {
            auditMessage = "HTTP POST is not supported";
            auditLevel = AuditLevel.ERROR;
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        String operation = req.getParameter("operation");
        event.putEventData(AuditEvent.NAME_operation, operation);
        if ("PKIOperation".equalsIgnoreCase(operation)) {
            CMSSignedData reqMessage;
            // parse the request
            try {
                byte[] content = post ? IoUtil.read(req.getInputStream()) : Base64.decode(req.getParameter("message"));
                reqMessage = new CMSSignedData(content);
            } catch (Exception ex) {
                auditMessage = "invalid request";
                auditLevel = AuditLevel.ERROR;
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            ContentInfo ci;
            try {
                ci = responder.servicePkiOperation(reqMessage, event);
            } catch (MessageDecodingException ex) {
                auditMessage = "could not decrypt and/or verify the request";
                auditLevel = AuditLevel.ERROR;
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
                return;
            } catch (CaException ex) {
                ex.printStackTrace();
                auditMessage = "system internal error";
                auditLevel = AuditLevel.ERROR;
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
            byte[] respBytes = ci.getEncoded();
            sendToResponse(resp, CT_RESPONSE, respBytes);
        } else if (Operation.GetCACaps.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] caCapsBytes = responder.getCaCaps().getBytes();
            sendToResponse(resp, ScepConstants.CT_TEXT_PLAIN, caCapsBytes);
        } else if (Operation.GetCACert.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] respBytes;
            String ct;
            if (responder.getRaEmulator() == null) {
                ct = ScepConstants.CT_X509_CA_CERT;
                respBytes = responder.getCaEmulator().getCaCertBytes();
            } else {
                ct = ScepConstants.CT_X509_CA_RA_CERT;
                CMSSignedDataGenerator cmsSignedDataGen = new CMSSignedDataGenerator();
                try {
                    cmsSignedDataGen.addCertificate(responder.getCaEmulator().getCaCert().toBcCert());
                    ct = ScepConstants.CT_X509_CA_RA_CERT;
                    cmsSignedDataGen.addCertificate(responder.getRaEmulator().getRaCert().toBcCert());
                    CMSSignedData degenerateSignedData = cmsSignedDataGen.generate(new CMSAbsentContent());
                    respBytes = degenerateSignedData.getEncoded();
                } catch (CMSException ex) {
                    ex.printStackTrace();
                    auditMessage = "system internal error";
                    auditLevel = AuditLevel.ERROR;
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    return;
                }
            }
            sendToResponse(resp, ct, respBytes);
        } else if (Operation.GetNextCACert.getCode().equalsIgnoreCase(operation)) {
            if (responder.getNextCaAndRa() == null) {
                auditMessage = "SCEP operation '" + operation + "' is not permitted";
                auditLevel = AuditLevel.ERROR;
                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                return;
            }
            try {
                NextCaMessage nextCaMsg = new NextCaMessage();
                nextCaMsg.setCaCert(responder.getNextCaAndRa().getCaCert());
                if (responder.getNextCaAndRa().getRaCert() != null) {
                    X509Cert raCert = responder.getNextCaAndRa().getRaCert();
                    nextCaMsg.setRaCerts(Collections.singletonList(raCert));
                }
                ContentInfo signedData = responder.encode(nextCaMsg);
                byte[] respBytes = signedData.getEncoded();
                sendToResponse(resp, ScepConstants.CT_X509_NEXT_CA_CERT, respBytes);
            } catch (Exception ex) {
                ex.printStackTrace();
                auditMessage = "system internal error";
                auditLevel = AuditLevel.ERROR;
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        } else {
            auditMessage = "unknown SCEP operation '" + operation + "'";
            auditLevel = AuditLevel.ERROR;
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
        }
    // end if ("PKIOperation".equalsIgnoreCase(operation))
    } catch (EOFException ex) {
        LOG.warn("connection reset by peer", ex);
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } catch (Throwable th) {
        LOG.error("Throwable thrown, this should not happen!", th);
        auditLevel = AuditLevel.ERROR;
        auditMessage = "internal error";
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } finally {
        if (event.getLevel() != AuditLevel.ERROR) {
            event.setLevel(auditLevel);
        }
        if (auditMessage != null) {
            event.putEventData("error", auditMessage);
        }
        event.log(LOG);
    }
// end try
}
Also used : CMSSignedDataGenerator(org.bouncycastle.cms.CMSSignedDataGenerator) CMSAbsentContent(org.bouncycastle.cms.CMSAbsentContent) AuditLevel(org.xipki.scep.serveremulator.AuditEvent.AuditLevel) CMSSignedData(org.bouncycastle.cms.CMSSignedData) NextCaMessage(org.xipki.scep.message.NextCaMessage) CMSException(org.bouncycastle.cms.CMSException) MessageDecodingException(org.xipki.scep.message.MessageDecodingException) IOException(java.io.IOException) EOFException(java.io.EOFException) MessageDecodingException(org.xipki.scep.message.MessageDecodingException) CaCaps(org.xipki.scep.message.CaCaps) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) X509Cert(org.xipki.security.X509Cert) EOFException(java.io.EOFException) CMSException(org.bouncycastle.cms.CMSException)

Example 52 with ContentInfo

use of com.github.zhenwei.pkix.util.asn1.cms.ContentInfo in project xipki by xipki.

the class Client method retrieveCaCertStore.

private static AuthorityCertStore retrieveCaCertStore(ScepHttpResponse resp, CaCertValidator caValidator) throws ScepClientException {
    String ct = resp.getContentType();
    X509Cert caCert = null;
    List<X509Cert> raCerts = new LinkedList<>();
    if (ScepConstants.CT_X509_CA_CERT.equalsIgnoreCase(ct)) {
        try {
            caCert = X509Util.parseCert(resp.getContentBytes());
        } catch (CertificateEncodingException ex) {
            throw new ScepClientException("error parsing certificate: " + ex.getMessage(), ex);
        }
    } else if (ScepConstants.CT_X509_CA_RA_CERT.equalsIgnoreCase(ct)) {
        ContentInfo contentInfo = ContentInfo.getInstance(resp.getContentBytes());
        SignedData signedData;
        try {
            signedData = SignedData.getInstance(contentInfo.getContent());
        } catch (IllegalArgumentException ex) {
            throw new ScepClientException("invalid SignedData message: " + ex.getMessage(), ex);
        }
        List<X509Cert> certs;
        try {
            certs = ScepUtil.getCertsFromSignedData(signedData);
        } catch (CertificateException ex) {
            throw new ScepClientException(ex.getMessage(), ex);
        }
        final int n = certs.size();
        if (n < 2) {
            throw new ScepClientException("at least 2 certificates are expected, but only " + n + " is available");
        }
        for (X509Cert cert : certs) {
            if (cert.getBasicConstraints() > -1) {
                if (caCert != null) {
                    throw new ScepClientException("multiple CA certificates is returned, but exactly 1 is expected");
                }
                caCert = cert;
            } else {
                raCerts.add(cert);
            }
        }
        if (caCert == null) {
            throw new ScepClientException("no CA certificate is returned");
        }
    } else {
        throw new ScepClientException("invalid Content-Type '" + ct + "'");
    }
    if (!caValidator.isTrusted(caCert)) {
        throw new ScepClientException("CA certificate '" + caCert.getSubjectRfc4519Text() + "' is not trusted");
    }
    if (raCerts.isEmpty()) {
        return AuthorityCertStore.getInstance(caCert);
    }
    AuthorityCertStore cs = AuthorityCertStore.getInstance(caCert, raCerts.toArray(new X509Cert[0]));
    X509Cert raEncCert = cs.getEncryptionCert();
    X509Cert raSignCert = cs.getSignatureCert();
    try {
        if (!X509Util.issues(caCert, raEncCert)) {
            throw new ScepClientException("RA certificate '" + raEncCert.getSubjectRfc4519Text() + " is not issued by the CA");
        }
        if (raSignCert != raEncCert && X509Util.issues(caCert, raSignCert)) {
            throw new ScepClientException("RA certificate '" + raSignCert.getSubjectRfc4519Text() + " is not issued by the CA");
        }
    } catch (CertificateException ex) {
        throw new ScepClientException("invalid certificate: " + ex.getMessage(), ex);
    }
    return cs;
}
Also used : SignedData(org.bouncycastle.asn1.cms.SignedData) CMSSignedData(org.bouncycastle.cms.CMSSignedData) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) X509Cert(org.xipki.security.X509Cert) CertificateEncodingException(java.security.cert.CertificateEncodingException) LinkedList(java.util.LinkedList) List(java.util.List) CertificateException(java.security.cert.CertificateException) LinkedList(java.util.LinkedList)

Example 53 with ContentInfo

use of com.github.zhenwei.pkix.util.asn1.cms.ContentInfo in project xipki by xipki.

the class Client method scepGetCert.

// method scepGetCrl
public List<X509Cert> scepGetCert(PrivateKey identityKey, X509Cert identityCert, X500Name issuer, BigInteger serialNumber) throws ScepClientException {
    Args.notNull(identityKey, "identityKey");
    Args.notNull(identityCert, "identityCert");
    Args.notNull(issuer, "issuer");
    Args.notNull(serialNumber, "serialNumber");
    initIfNotInited();
    PkiMessage request = new PkiMessage(TransactionId.randomTransactionId(), MessageType.GetCert);
    IssuerAndSerialNumber isn = new IssuerAndSerialNumber(issuer, serialNumber);
    request.setMessageData(isn);
    ContentInfo envRequest = encryptThenSign(request, identityKey, identityCert);
    ScepHttpResponse httpResp = httpSend(Operation.PKIOperation, envRequest);
    CMSSignedData cmsSignedData = parsePkiMessage(httpResp.getContentBytes());
    DecodedPkiMessage response = decode(cmsSignedData, identityKey, identityCert);
    if (response.getPkiStatus() != PkiStatus.SUCCESS) {
        throw new ScepClientException("server returned " + response.getPkiStatus());
    }
    ContentInfo messageData = ContentInfo.getInstance(response.getMessageData());
    try {
        return ScepUtil.getCertsFromSignedData(SignedData.getInstance(messageData.getContent()));
    } catch (CertificateException ex) {
        throw new ScepClientException(ex.getMessage(), ex);
    }
}
Also used : IssuerAndSerialNumber(org.bouncycastle.asn1.cms.IssuerAndSerialNumber) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) CertificateException(java.security.cert.CertificateException) CMSSignedData(org.bouncycastle.cms.CMSSignedData)

Example 54 with ContentInfo

use of com.github.zhenwei.pkix.util.asn1.cms.ContentInfo in project xipki by xipki.

the class Client method scepCertPoll.

// method scepCertPoll
public EnrolmentResponse scepCertPoll(PrivateKey identityKey, X509Cert identityCert, TransactionId transactionId, X500Name issuer, X500Name subject) throws ScepClientException {
    Args.notNull(identityKey, "identityKey");
    Args.notNull(identityCert, "identityCert");
    Args.notNull(issuer, "issuer");
    Args.notNull(transactionId, "transactionId");
    initIfNotInited();
    PkiMessage pkiMessage = new PkiMessage(transactionId, MessageType.CertPoll);
    IssuerAndSubject is = new IssuerAndSubject(issuer, subject);
    pkiMessage.setMessageData(is);
    ContentInfo envRequest = encryptThenSign(pkiMessage, identityKey, identityCert);
    ScepHttpResponse httpResp = httpSend(Operation.PKIOperation, envRequest);
    CMSSignedData cmsSignedData = parsePkiMessage(httpResp.getContentBytes());
    DecodedPkiMessage response = decode(cmsSignedData, identityKey, identityCert);
    assertSameNonce(pkiMessage, response);
    return new EnrolmentResponse(response);
}
Also used : ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) CMSSignedData(org.bouncycastle.cms.CMSSignedData)

Example 55 with ContentInfo

use of com.github.zhenwei.pkix.util.asn1.cms.ContentInfo in project xipki by xipki.

the class HttpScepServlet method service0.

private void service0(HttpServletRequest req, HttpServletResponse resp, boolean viaPost) {
    String path = (String) req.getAttribute(HttpConstants.ATTR_XIPKI_PATH);
    String caAlias = null;
    String certprofileName = null;
    if (path.length() > 1) {
        String scepPath = path;
        if (scepPath.endsWith(CGI_PROGRAM)) {
            // skip also the first char (which is always '/')
            String tpath = scepPath.substring(1, scepPath.length() - CGI_PROGRAM_LEN);
            String[] tokens = tpath.split("/");
            if (tokens.length == 2) {
                caAlias = tokens[0];
                certprofileName = tokens[1].toLowerCase();
            }
        }
    // end if
    }
    if (caAlias == null || certprofileName == null) {
        sendError(resp, HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    AuditService auditService = Audits.getAuditService();
    AuditEvent event = new AuditEvent(new Date());
    event.setApplicationName("SCEP");
    event.setName(CaAuditConstants.NAME_perf);
    event.addEventData(CaAuditConstants.Scep.NAME_name, caAlias + "/" + certprofileName);
    event.addEventData(CaAuditConstants.NAME_req_type, RequestType.SCEP.name());
    String msgId = RandomUtil.nextHexLong();
    event.addEventData(CaAuditConstants.NAME_mid, msgId);
    AuditLevel auditLevel = AuditLevel.INFO;
    AuditStatus auditStatus = AuditStatus.SUCCESSFUL;
    String auditMessage = null;
    try {
        String caName = responderManager.getCaNameForAlias(caAlias);
        if (caName == null) {
            caName = caAlias.toLowerCase();
        }
        ScepResponder responder = responderManager.getScepResponder(caName);
        if (responder == null || !responder.isOnService()) {
            auditMessage = "unknown SCEP '" + caAlias + "/" + certprofileName + "'";
            LOG.warn(auditMessage);
            auditStatus = AuditStatus.FAILED;
            sendError(resp, HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        String operation = req.getParameter("operation");
        event.addEventData(CaAuditConstants.Scep.NAME_operation, operation);
        byte[] requestBytes;
        byte[] respBody;
        String contentType;
        if ("PKIOperation".equalsIgnoreCase(operation)) {
            CMSSignedData reqMessage;
            // parse the request
            try {
                if (viaPost) {
                    requestBytes = IoUtil.read(req.getInputStream());
                } else {
                    String b64 = req.getParameter("message");
                    requestBytes = Base64.decode(b64);
                }
                reqMessage = new CMSSignedData(requestBytes);
            } catch (Exception ex) {
                final String msg = "invalid request";
                LogUtil.error(LOG, ex, msg);
                auditMessage = msg;
                auditStatus = AuditStatus.FAILED;
                sendError(resp, HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            ContentInfo ci;
            try {
                ci = responder.servicePkiOperation(reqMessage, certprofileName, msgId, event);
            } catch (MessageDecodingException ex) {
                final String msg = "could not decrypt and/or verify the request";
                LogUtil.error(LOG, ex, msg);
                auditMessage = msg;
                auditStatus = AuditStatus.FAILED;
                sendError(resp, HttpServletResponse.SC_BAD_REQUEST);
                return;
            } catch (OperationException ex) {
                ErrorCode code = ex.getErrorCode();
                int httpCode;
                switch(code) {
                    case ALREADY_ISSUED:
                    case CERT_REVOKED:
                    case CERT_UNREVOKED:
                        httpCode = HttpServletResponse.SC_FORBIDDEN;
                        break;
                    case BAD_CERT_TEMPLATE:
                    case BAD_REQUEST:
                    case BAD_POP:
                    case INVALID_EXTENSION:
                    case UNKNOWN_CERT:
                    case UNKNOWN_CERT_PROFILE:
                        httpCode = HttpServletResponse.SC_BAD_REQUEST;
                        break;
                    case NOT_PERMITTED:
                        httpCode = HttpServletResponse.SC_UNAUTHORIZED;
                        break;
                    case SYSTEM_UNAVAILABLE:
                        httpCode = HttpServletResponse.SC_SERVICE_UNAVAILABLE;
                        break;
                    case CRL_FAILURE:
                    case DATABASE_FAILURE:
                    case SYSTEM_FAILURE:
                        httpCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
                        break;
                    default:
                        httpCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
                        break;
                }
                auditMessage = ex.getMessage();
                LogUtil.error(LOG, ex, auditMessage);
                auditStatus = AuditStatus.FAILED;
                sendError(resp, httpCode);
                return;
            }
            respBody = ci.getEncoded();
            contentType = CT_RESPONSE;
        } else if (Operation.GetCACaps.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            requestBytes = null;
            contentType = ScepConstants.CT_TEXT_PLAIN;
            respBody = responder.getCaCaps().getBytes();
        } else if (Operation.GetCACert.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            requestBytes = null;
            contentType = ScepConstants.CT_X509_CA_RA_CERT;
            respBody = responder.getCaCertResp().getBytes();
        } else if (Operation.GetNextCACert.getCode().equalsIgnoreCase(operation)) {
            auditMessage = "SCEP operation '" + operation + "' is not permitted";
            auditStatus = AuditStatus.FAILED;
            sendError(resp, HttpServletResponse.SC_FORBIDDEN);
            return;
        } else {
            auditMessage = "unknown SCEP operation '" + operation + "'";
            auditStatus = AuditStatus.FAILED;
            sendError(resp, HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        if (logReqResp && LOG.isDebugEnabled()) {
            if (viaPost) {
                LOG.debug("HTTP POST CA SCEP path: {}\nRequest:\n{}\nResponse:\n{}", req.getRequestURI(), LogUtil.base64Encode(requestBytes), LogUtil.base64Encode(respBody));
            } else {
                LOG.debug("HTTP GET CA SCEP path: {}\nResponse:\n{}", req.getRequestURI(), LogUtil.base64Encode(respBody));
            }
        }
        sendOKResponse(resp, contentType, respBody);
    } catch (Throwable th) {
        if (th instanceof EOFException) {
            final String msg = "connection reset by peer";
            if (LOG.isWarnEnabled()) {
                LogUtil.warn(LOG, th, msg);
            }
            LOG.debug(msg, th);
        } else {
            LOG.error("Throwable thrown, this should not happen!", th);
        }
        auditLevel = AuditLevel.ERROR;
        auditStatus = AuditStatus.FAILED;
        auditMessage = "internal error";
        sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } finally {
        audit(auditService, event, auditLevel, auditStatus, auditMessage);
    }
}
Also used : ScepResponder(org.xipki.ca.server.ScepResponder) CMSSignedData(org.bouncycastle.cms.CMSSignedData) Date(java.util.Date) ServletException(javax.servlet.ServletException) MessageDecodingException(org.xipki.scep.message.MessageDecodingException) IOException(java.io.IOException) EOFException(java.io.EOFException) OperationException(org.xipki.ca.api.OperationException) MessageDecodingException(org.xipki.scep.message.MessageDecodingException) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) EOFException(java.io.EOFException) ErrorCode(org.xipki.ca.api.OperationException.ErrorCode) OperationException(org.xipki.ca.api.OperationException)

Aggregations

ContentInfo (org.bouncycastle.asn1.cms.ContentInfo)60 IOException (java.io.IOException)28 CMSSignedData (org.bouncycastle.cms.CMSSignedData)22 ContentInfo (com.github.zhenwei.pkix.util.asn1.cms.ContentInfo)18 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)15 OutputStream (java.io.OutputStream)12 X509Certificate (java.security.cert.X509Certificate)12 ArrayList (java.util.ArrayList)12 SignedData (org.bouncycastle.asn1.cms.SignedData)12 Iterator (java.util.Iterator)11 ASN1Set (org.bouncycastle.asn1.ASN1Set)11 ASN1EncodableVector (com.github.zhenwei.core.asn1.ASN1EncodableVector)10 ASN1Set (com.github.zhenwei.core.asn1.ASN1Set)10 ASN1OctetString (com.github.zhenwei.core.asn1.ASN1OctetString)9 ByteArrayInputStream (java.io.ByteArrayInputStream)9 ByteArrayOutputStream (java.io.ByteArrayOutputStream)9 ASN1EncodableVector (org.bouncycastle.asn1.ASN1EncodableVector)9 ASN1InputStream (org.bouncycastle.asn1.ASN1InputStream)9 ASN1Sequence (org.bouncycastle.asn1.ASN1Sequence)9 DERSet (org.bouncycastle.asn1.DERSet)9