Search in sources :

Example 1 with ResponderAndPath

use of org.xipki.ocsp.api.ResponderAndPath in project xipki by xipki.

the class HttpOcspServlet method servicePost.

private FullHttpResponse servicePost(FullHttpRequest request, ServletURI servletUri, SSLSession sslSession, SslReverseProxyMode sslReverseProxyMode) throws Exception {
    HttpVersion version = request.protocolVersion();
    ResponderAndPath responderAndPath = server.getResponderForPath(servletUri.getPath());
    if (responderAndPath == null) {
        return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
    }
    try {
        // accept only "application/ocsp-request" as content type
        String reqContentType = request.headers().get("Content-Type");
        if (!CT_REQUEST.equalsIgnoreCase(reqContentType)) {
            return createErrorResponse(version, HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE);
        }
        Responder responder = responderAndPath.getResponder();
        int contentLen = request.content().readableBytes();
        // request too long
        if (contentLen > responder.getMaxRequestSize()) {
            return createErrorResponse(version, HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE);
        }
        OcspRespWithCacheInfo ocspRespWithCacheInfo = server.answer(responder, readContent(request), false);
        if (ocspRespWithCacheInfo == null || ocspRespWithCacheInfo.getResponse() == null) {
            LOG.error("processRequest returned null, this should not happen");
            return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
        byte[] encodedOcspResp = ocspRespWithCacheInfo.getResponse();
        return createOKResponse(version, CT_RESPONSE, encodedOcspResp);
    } 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);
        }
        return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    }
// end external try
}
Also used : OcspRespWithCacheInfo(org.xipki.ocsp.api.OcspRespWithCacheInfo) EOFException(java.io.EOFException) ResponderAndPath(org.xipki.ocsp.api.ResponderAndPath) HttpVersion(io.netty.handler.codec.http.HttpVersion) Responder(org.xipki.ocsp.api.Responder)

Example 2 with ResponderAndPath

use of org.xipki.ocsp.api.ResponderAndPath in project xipki by xipki.

the class HttpOcspServlet method serviceGet.

// method servicePost
private FullHttpResponse serviceGet(FullHttpRequest request, ServletURI servletUri, SSLSession sslSession, SslReverseProxyMode sslReverseProxyMode) throws Exception {
    HttpVersion version = request.protocolVersion();
    ResponderAndPath responderAndPath = server.getResponderForPath(servletUri.getPath());
    if (responderAndPath == null) {
        return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
    }
    String path = servletUri.getPath();
    String servletPath = responderAndPath.getServletPath();
    Responder responder = responderAndPath.getResponder();
    if (!responder.supportsHttpGet()) {
        return createErrorResponse(version, HttpResponseStatus.METHOD_NOT_ALLOWED);
    }
    String b64OcspReq;
    int offset = servletPath.length();
    // GET URI contains the request and must be much longer than 10.
    if (path.length() - offset > 10) {
        if (path.charAt(offset) == '/') {
            offset++;
        }
        b64OcspReq = servletUri.getPath().substring(offset);
    } else {
        return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
    }
    try {
        // POST, we support GET for longer requests anyway.
        if (b64OcspReq.length() > responder.getMaxRequestSize()) {
            return createErrorResponse(version, HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE);
        }
        OcspRespWithCacheInfo ocspRespWithCacheInfo = server.answer(responder, Base64.decode(b64OcspReq), true);
        if (ocspRespWithCacheInfo == null || ocspRespWithCacheInfo.getResponse() == null) {
            return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
        byte[] encodedOcspResp = ocspRespWithCacheInfo.getResponse();
        FullHttpResponse response = createOKResponse(version, CT_RESPONSE, encodedOcspResp);
        OcspRespWithCacheInfo.ResponseCacheInfo cacheInfo = ocspRespWithCacheInfo.getCacheInfo();
        if (cacheInfo != null) {
            encodedOcspResp = ocspRespWithCacheInfo.getResponse();
            HttpHeaders headers = response.headers();
            // RFC 5019 6.2: Date: The date and time at which the OCSP server generated
            // the HTTP response.
            headers.add("Date", new Date());
            // RFC 5019 6.2: Last-Modified: date and time at which the OCSP responder
            // last modified the response.
            headers.add("Last-Modified", new Date(cacheInfo.getThisUpdate()));
            // This is overridden by max-age on HTTP/1.1 compatible components
            if (cacheInfo.getNextUpdate() != null) {
                headers.add("Expires", new Date(cacheInfo.getNextUpdate()));
            }
            // RFC 5019 6.2: This profile RECOMMENDS that the ETag value be the ASCII
            // HEX representation of the SHA1 hash of the OCSPResponse structure.
            headers.add("ETag", StringUtil.concat("\\", HashAlgo.SHA1.hexHash(encodedOcspResp), "\\"));
            // Max age must be in seconds in the cache-control header
            long maxAge;
            if (responder.getCacheMaxAge() != null) {
                maxAge = responder.getCacheMaxAge().longValue();
            } else {
                maxAge = DFLT_CACHE_MAX_AGE;
            }
            if (cacheInfo.getNextUpdate() != null) {
                maxAge = Math.min(maxAge, (cacheInfo.getNextUpdate() - cacheInfo.getThisUpdate()) / 1000);
            }
            headers.add("Cache-Control", StringUtil.concat("max-age=", Long.toString(maxAge), ",public,no-transform,must-revalidate"));
        }
        return response;
    } 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);
        }
        return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    }
// end external try
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) ResponderAndPath(org.xipki.ocsp.api.ResponderAndPath) Date(java.util.Date) OcspRespWithCacheInfo(org.xipki.ocsp.api.OcspRespWithCacheInfo) EOFException(java.io.EOFException) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) HttpVersion(io.netty.handler.codec.http.HttpVersion) Responder(org.xipki.ocsp.api.Responder)

Example 3 with ResponderAndPath

use of org.xipki.ocsp.api.ResponderAndPath in project xipki by xipki.

the class HealthCheckServlet method service0.

private FullHttpResponse service0(FullHttpRequest request, ServletURI servletUri, SSLSession sslSession) {
    HttpVersion version = request.protocolVersion();
    HttpMethod method = request.method();
    if (method != HttpMethod.GET) {
        return createErrorResponse(version, HttpResponseStatus.METHOD_NOT_ALLOWED);
    }
    try {
        if (server == null) {
            LOG.error("server in servlet not configured");
            return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
        ResponderAndPath responderAndPath = server.getResponderForPath(servletUri.getPath());
        if (responderAndPath == null) {
            return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
        }
        HealthCheckResult healthResult = server.healthCheck(responderAndPath.getResponder());
        HttpResponseStatus status = healthResult.isHealthy() ? HttpResponseStatus.OK : HttpResponseStatus.INTERNAL_SERVER_ERROR;
        byte[] respBytes = healthResult.toJsonMessage(true).getBytes();
        return createResponse(version, status, HealthCheckServlet.CT_RESPONSE, respBytes);
    } 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);
        }
        return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    }
}
Also used : HttpResponseStatus(io.netty.handler.codec.http.HttpResponseStatus) EOFException(java.io.EOFException) HealthCheckResult(org.xipki.common.HealthCheckResult) ResponderAndPath(org.xipki.ocsp.api.ResponderAndPath) HttpVersion(io.netty.handler.codec.http.HttpVersion) HttpMethod(io.netty.handler.codec.http.HttpMethod)

Example 4 with ResponderAndPath

use of org.xipki.ocsp.api.ResponderAndPath in project xipki by xipki.

the class HealthCheckServlet method doGet.

@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    resp.setHeader("Access-Control-Allow-Origin", "*");
    OcspServer server = ServletHelper.getServer();
    if (server == null) {
        LOG.error("ServletHelper.server not configured");
        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        resp.setContentLength(0);
        return;
    }
    try {
        String path = StringUtil.getRelativeRequestUri(req.getServletPath(), req.getRequestURI());
        ResponderAndPath responderAndPath = server.getResponderForPath(path);
        if (responderAndPath == null) {
            resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
            resp.setContentLength(0);
            return;
        }
        HealthCheckResult healthResult = server.healthCheck(responderAndPath.getResponder());
        int status = healthResult.isHealthy() ? HttpServletResponse.SC_OK : HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        byte[] respBytes = healthResult.toJsonMessage(true).getBytes();
        resp.setStatus(status);
        resp.setContentType(HealthCheckServlet.CT_RESPONSE);
        resp.setContentLength(respBytes.length);
        resp.getOutputStream().write(respBytes);
    } 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);
        }
        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        resp.setContentLength(0);
    } finally {
        resp.flushBuffer();
    }
}
Also used : EOFException(java.io.EOFException) HealthCheckResult(org.xipki.common.HealthCheckResult) ResponderAndPath(org.xipki.ocsp.api.ResponderAndPath) OcspServer(org.xipki.ocsp.api.OcspServer)

Example 5 with ResponderAndPath

use of org.xipki.ocsp.api.ResponderAndPath in project xipki by xipki.

the class HttpOcspServlet method doGet.

// method servicePost
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    OcspServer server = ServletHelper.getServer();
    if (server == null) {
        LOG.error("server in servlet not configured");
        sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
    }
    String path = StringUtil.getRelativeRequestUri(req.getServletPath(), req.getRequestURI());
    ResponderAndPath responderAndPath = server.getResponderForPath(path);
    if (responderAndPath == null) {
        sendError(resp, HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    String servletPath = responderAndPath.getServletPath();
    Responder responder = responderAndPath.getResponder();
    if (!responder.supportsHttpGet()) {
        sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        return;
    }
    String b64OcspReq;
    int offset = servletPath.length();
    // GET URI contains the request and must be much longer than 10.
    if (path.length() - offset > 10) {
        if (path.charAt(offset) == '/') {
            offset++;
        }
        b64OcspReq = path.substring(offset);
    } else {
        sendError(resp, HttpServletResponse.SC_BAD_REQUEST);
        return;
    }
    try {
        // POST, we support GET for longer requests anyway.
        if (b64OcspReq.length() > responder.getMaxRequestSize()) {
            sendError(resp, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
            return;
        }
        OcspRespWithCacheInfo ocspRespWithCacheInfo = server.answer(responder, Base64.decode(b64OcspReq), true);
        if (ocspRespWithCacheInfo == null || ocspRespWithCacheInfo.getResponse() == null) {
            sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
        byte[] encodedOcspResp = ocspRespWithCacheInfo.getResponse();
        OcspRespWithCacheInfo.ResponseCacheInfo cacheInfo = ocspRespWithCacheInfo.getCacheInfo();
        if (cacheInfo != null) {
            encodedOcspResp = ocspRespWithCacheInfo.getResponse();
            long now = System.currentTimeMillis();
            // RFC 5019 6.2: Date: The date and time at which the OCSP server generated
            // the HTTP response.
            resp.addDateHeader("Date", now);
            // RFC 5019 6.2: Last-Modified: date and time at which the OCSP responder
            // last modified the response.
            resp.addDateHeader("Last-Modified", cacheInfo.getThisUpdate());
            // This is overridden by max-age on HTTP/1.1 compatible components
            if (cacheInfo.getNextUpdate() != null) {
                resp.addDateHeader("Expires", cacheInfo.getNextUpdate());
            }
            // RFC 5019 6.2: This profile RECOMMENDS that the ETag value be the ASCII
            // HEX representation of the SHA1 hash of the OCSPResponse structure.
            resp.addHeader("ETag", StringUtil.concat("\\", HashAlgo.SHA1.hexHash(encodedOcspResp), "\\"));
            // Max age must be in seconds in the cache-control header
            long maxAge;
            if (responder.getCacheMaxAge() != null) {
                maxAge = responder.getCacheMaxAge().longValue();
            } else {
                maxAge = DFLT_CACHE_MAX_AGE;
            }
            if (cacheInfo.getNextUpdate() != null) {
                maxAge = Math.min(maxAge, (cacheInfo.getNextUpdate() - cacheInfo.getThisUpdate()) / 1000);
            }
            resp.addHeader("Cache-Control", StringUtil.concat("max-age=", Long.toString(maxAge), ",public,no-transform,must-revalidate"));
        }
        // end if (ocspRespWithCacheInfo)
        resp.setContentLength(encodedOcspResp.length);
        resp.setContentType(CT_RESPONSE);
        resp.getOutputStream().write(encodedOcspResp);
    } 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);
        }
        sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    } finally {
        resp.flushBuffer();
    }
}
Also used : OcspRespWithCacheInfo(org.xipki.ocsp.api.OcspRespWithCacheInfo) EOFException(java.io.EOFException) ResponderAndPath(org.xipki.ocsp.api.ResponderAndPath) OcspServer(org.xipki.ocsp.api.OcspServer) Responder(org.xipki.ocsp.api.Responder)

Aggregations

EOFException (java.io.EOFException)6 ResponderAndPath (org.xipki.ocsp.api.ResponderAndPath)6 OcspRespWithCacheInfo (org.xipki.ocsp.api.OcspRespWithCacheInfo)4 Responder (org.xipki.ocsp.api.Responder)4 HttpVersion (io.netty.handler.codec.http.HttpVersion)3 OcspServer (org.xipki.ocsp.api.OcspServer)3 HealthCheckResult (org.xipki.common.HealthCheckResult)2 FullHttpResponse (io.netty.handler.codec.http.FullHttpResponse)1 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)1 HttpMethod (io.netty.handler.codec.http.HttpMethod)1 HttpResponseStatus (io.netty.handler.codec.http.HttpResponseStatus)1 Date (java.util.Date)1