Search in sources :

Example 1 with Scep

use of org.xipki.ca.server.api.Scep in project xipki by xipki.

the class HttpScepServlet method service0.

private void service0(HttpServletRequest req, HttpServletResponse resp, boolean viaPost) throws ServletException, IOException {
    AuditServiceRegister auditServiceRegister = ServletHelper.getAuditServiceRegister();
    if (auditServiceRegister == null) {
        LOG.error("ServletHelper.auditServiceRegister not configured");
        sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }
    ResponderManager responderManager = ServletHelper.getResponderManager();
    if (responderManager == null) {
        LOG.error("ServletHelper.responderManager not configured");
        sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }
    String path = StringUtil.getRelativeRequestUri(req.getServletPath(), req.getRequestURI());
    String scepName = 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) {
                scepName = tokens[0];
                certProfileName = tokens[1].toLowerCase();
            }
        }
    // end if
    }
    if (scepName == null || certProfileName == null) {
        sendError(resp, HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    AuditService auditService = auditServiceRegister.getAuditService();
    AuditEvent event = new AuditEvent(new Date());
    event.setApplicationName("SCEP");
    event.setName(CaAuditConstants.NAME_PERF);
    event.addEventData(CaAuditConstants.NAME_SCEP_name, scepName + "/" + certProfileName);
    event.addEventData(CaAuditConstants.NAME_reqType, 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 {
        Scep responder = responderManager.getScep(scepName);
        if (responder == null || !responder.isOnService() || !responder.supportsCertProfile(certProfileName)) {
            auditMessage = "unknown SCEP '" + scepName + "/" + certProfileName + "'";
            LOG.warn(auditMessage);
            auditStatus = AuditStatus.FAILED;
            sendError(resp, HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        String operation = req.getParameter("operation");
        event.addEventData(CaAuditConstants.NAME_SCEP_operation, operation);
        if ("PKIOperation".equalsIgnoreCase(operation)) {
            CMSSignedData reqMessage;
            // parse the request
            try {
                byte[] content;
                if (viaPost) {
                    content = IoUtil.read(req.getInputStream());
                } else {
                    String b64 = req.getParameter("message");
                    content = Base64.decode(b64);
                }
                reqMessage = new CMSSignedData(content);
            } 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;
            }
            byte[] bodyBytes = ci.getEncoded();
            sendOKResponse(resp, CT_RESPONSE, bodyBytes);
        } else if (Operation.GetCACaps.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] caCapsBytes = responder.getCaCaps().getBytes();
            sendOKResponse(resp, ScepConstants.CT_TEXT_PLAIN, caCapsBytes);
        } else if (Operation.GetCACert.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] respBytes = responder.getCaCertResp().getBytes();
            sendOKResponse(resp, ScepConstants.CT_X509_CA_RA_CERT, respBytes);
        } 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;
        }
    } 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 : AuditLevel(org.xipki.audit.AuditLevel) ResponderManager(org.xipki.ca.server.api.ResponderManager) CMSSignedData(org.bouncycastle.cms.CMSSignedData) Date(java.util.Date) ServletException(javax.servlet.ServletException) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) IOException(java.io.IOException) EOFException(java.io.EOFException) OperationException(org.xipki.ca.api.OperationException) AuditStatus(org.xipki.audit.AuditStatus) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) EOFException(java.io.EOFException) AuditEvent(org.xipki.audit.AuditEvent) ErrorCode(org.xipki.ca.api.OperationException.ErrorCode) Scep(org.xipki.ca.server.api.Scep) AuditServiceRegister(org.xipki.audit.AuditServiceRegister) AuditService(org.xipki.audit.AuditService) OperationException(org.xipki.ca.api.OperationException)

Example 2 with Scep

use of org.xipki.ca.server.api.Scep in project xipki by xipki.

the class HttpScepServlet method service.

@Override
public FullHttpResponse service(FullHttpRequest request, ServletURI servletUri, SSLSession sslSession, SslReverseProxyMode sslReverseProxyMode) throws Exception {
    HttpVersion version = request.protocolVersion();
    HttpMethod method = request.method();
    boolean viaPost;
    if (method == HttpMethod.POST) {
        viaPost = true;
    } else if (method == HttpMethod.GET) {
        viaPost = false;
    } else {
        return createErrorResponse(version, HttpResponseStatus.METHOD_NOT_ALLOWED);
    }
    String scepName = null;
    String certProfileName = null;
    if (servletUri.getPath().length() > 1) {
        String scepPath = servletUri.getPath();
        if (scepPath.endsWith(CGI_PROGRAM)) {
            // skip also the first char (which is always '/')
            String path = scepPath.substring(1, scepPath.length() - CGI_PROGRAM_LEN);
            String[] tokens = path.split("/");
            if (tokens.length == 2) {
                scepName = tokens[0];
                certProfileName = tokens[1].toLowerCase();
            }
        }
    // end if
    }
    if (scepName == null || certProfileName == null) {
        return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
    }
    AuditService auditService = auditServiceRegister.getAuditService();
    AuditEvent event = new AuditEvent(new Date());
    event.setApplicationName("SCEP");
    event.setName(CaAuditConstants.NAME_PERF);
    event.addEventData(CaAuditConstants.NAME_SCEP_name, scepName + "/" + certProfileName);
    event.addEventData(CaAuditConstants.NAME_reqType, 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 {
        if (responderManager == null) {
            auditMessage = "responderManager in servlet not configured";
            LOG.error(auditMessage);
            auditLevel = AuditLevel.ERROR;
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
        Scep responder = responderManager.getScep(scepName);
        if (responder == null || !responder.isOnService() || !responder.supportsCertProfile(certProfileName)) {
            auditMessage = "unknown SCEP '" + scepName + "/" + certProfileName + "'";
            LOG.warn(auditMessage);
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
        }
        String operation = servletUri.getParameter("operation");
        event.addEventData(CaAuditConstants.NAME_SCEP_operation, operation);
        if ("PKIOperation".equalsIgnoreCase(operation)) {
            CMSSignedData reqMessage;
            // parse the request
            try {
                byte[] content;
                if (viaPost) {
                    content = readContent(request);
                } else {
                    String b64 = servletUri.getParameter("message");
                    content = Base64.decode(b64);
                }
                reqMessage = new CMSSignedData(content);
            } catch (Exception ex) {
                final String msg = "invalid request";
                LogUtil.error(LOG, ex, msg);
                auditMessage = msg;
                auditStatus = AuditStatus.FAILED;
                return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
            }
            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;
                return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
            } catch (OperationException ex) {
                ErrorCode code = ex.getErrorCode();
                HttpResponseStatus httpCode;
                switch(code) {
                    case ALREADY_ISSUED:
                    case CERT_REVOKED:
                    case CERT_UNREVOKED:
                        httpCode = HttpResponseStatus.FORBIDDEN;
                        break;
                    case BAD_CERT_TEMPLATE:
                    case BAD_REQUEST:
                    case BAD_POP:
                    case INVALID_EXTENSION:
                    case UNKNOWN_CERT:
                    case UNKNOWN_CERT_PROFILE:
                        httpCode = HttpResponseStatus.BAD_REQUEST;
                        break;
                    case NOT_PERMITTED:
                        httpCode = HttpResponseStatus.UNAUTHORIZED;
                        break;
                    case SYSTEM_UNAVAILABLE:
                        httpCode = HttpResponseStatus.SERVICE_UNAVAILABLE;
                        break;
                    case CRL_FAILURE:
                    case DATABASE_FAILURE:
                    case SYSTEM_FAILURE:
                        httpCode = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                        break;
                    default:
                        httpCode = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                        break;
                }
                auditMessage = ex.getMessage();
                LogUtil.error(LOG, ex, auditMessage);
                auditStatus = AuditStatus.FAILED;
                return createErrorResponse(version, httpCode);
            }
            byte[] bodyBytes = ci.getEncoded();
            return createOKResponse(version, CT_RESPONSE, bodyBytes);
        } else if (Operation.GetCACaps.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] caCapsBytes = responder.getCaCaps().getBytes();
            return createOKResponse(version, ScepConstants.CT_TEXT_PLAIN, caCapsBytes);
        } else if (Operation.GetCACert.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] respBytes = responder.getCaCertResp().getBytes();
            return createOKResponse(version, ScepConstants.CT_X509_CA_RA_CERT, respBytes);
        } else if (Operation.GetNextCACert.getCode().equalsIgnoreCase(operation)) {
            auditMessage = "SCEP operation '" + operation + "' is not permitted";
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.FORBIDDEN);
        } else {
            auditMessage = "unknown SCEP operation '" + operation + "'";
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
        }
    } 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";
        return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    } finally {
        audit(auditService, event, auditLevel, auditStatus, auditMessage);
    }
}
Also used : HttpResponseStatus(io.netty.handler.codec.http.HttpResponseStatus) AuditLevel(org.xipki.audit.AuditLevel) CMSSignedData(org.bouncycastle.cms.CMSSignedData) Date(java.util.Date) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) IOException(java.io.IOException) EOFException(java.io.EOFException) OperationException(org.xipki.ca.api.OperationException) AuditStatus(org.xipki.audit.AuditStatus) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) EOFException(java.io.EOFException) AuditEvent(org.xipki.audit.AuditEvent) ErrorCode(org.xipki.ca.api.OperationException.ErrorCode) Scep(org.xipki.ca.server.api.Scep) HttpVersion(io.netty.handler.codec.http.HttpVersion) AuditService(org.xipki.audit.AuditService) HttpMethod(io.netty.handler.codec.http.HttpMethod) OperationException(org.xipki.ca.api.OperationException)

Aggregations

EOFException (java.io.EOFException)2 IOException (java.io.IOException)2 Date (java.util.Date)2 ContentInfo (org.bouncycastle.asn1.cms.ContentInfo)2 CMSSignedData (org.bouncycastle.cms.CMSSignedData)2 AuditEvent (org.xipki.audit.AuditEvent)2 AuditLevel (org.xipki.audit.AuditLevel)2 AuditService (org.xipki.audit.AuditService)2 AuditStatus (org.xipki.audit.AuditStatus)2 OperationException (org.xipki.ca.api.OperationException)2 ErrorCode (org.xipki.ca.api.OperationException.ErrorCode)2 Scep (org.xipki.ca.server.api.Scep)2 MessageDecodingException (org.xipki.scep.exception.MessageDecodingException)2 HttpMethod (io.netty.handler.codec.http.HttpMethod)1 HttpResponseStatus (io.netty.handler.codec.http.HttpResponseStatus)1 HttpVersion (io.netty.handler.codec.http.HttpVersion)1 ServletException (javax.servlet.ServletException)1 AuditServiceRegister (org.xipki.audit.AuditServiceRegister)1 ResponderManager (org.xipki.ca.server.api.ResponderManager)1