Search in sources :

Example 1 with OcspRespWithCacheInfo

use of org.xipki.ocsp.api.OcspRespWithCacheInfo 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 OcspRespWithCacheInfo

use of org.xipki.ocsp.api.OcspRespWithCacheInfo 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 OcspRespWithCacheInfo

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

the class ResponseCacher method getOcspResponse.

OcspRespWithCacheInfo getOcspResponse(int issuerId, BigInteger serialNumber, AlgorithmCode sigAlg) throws DataAccessException {
    final String sql = sqlSelectOcsp;
    byte[] identBytes = buildIdent(serialNumber, sigAlg);
    long id = deriveId(issuerId, identBytes);
    PreparedStatement ps = prepareStatement(sql);
    ResultSet rs = null;
    try {
        ps.setLong(1, id);
        rs = ps.executeQuery();
        if (!rs.next()) {
            return null;
        }
        int dbIid = rs.getInt("IID");
        if (dbIid != issuerId) {
            return null;
        }
        String ident = Base64.encodeToString(identBytes);
        String dbIdent = rs.getString("IDENT");
        if (!ident.equals(dbIdent)) {
            return null;
        }
        long nextUpdate = rs.getLong("NEXT_UPDATE");
        if (nextUpdate != 0) {
            // nextUpdate must be at least in 600 seconds
            long minNextUpdate = System.currentTimeMillis() / 1000 + 600;
            if (nextUpdate < minNextUpdate) {
                return null;
            }
        }
        long thisUpdate = rs.getLong("THIS_UPDATE");
        String b64Resp = rs.getString("RESP");
        byte[] encoded = Base64.decodeFast(b64Resp);
        ResponseCacheInfo cacheInfo = new ResponseCacheInfo(thisUpdate);
        if (nextUpdate != 0) {
            cacheInfo.setNextUpdate(nextUpdate);
        }
        return new OcspRespWithCacheInfo(encoded, cacheInfo);
    } catch (SQLException ex) {
        throw datasource.translate(sql, ex);
    } finally {
        datasource.releaseResources(ps, rs);
    }
}
Also used : SQLException(java.sql.SQLException) OcspRespWithCacheInfo(org.xipki.ocsp.api.OcspRespWithCacheInfo) ResultSet(java.sql.ResultSet) ResponseCacheInfo(org.xipki.ocsp.api.OcspRespWithCacheInfo.ResponseCacheInfo) PreparedStatement(java.sql.PreparedStatement)

Example 4 with OcspRespWithCacheInfo

use of org.xipki.ocsp.api.OcspRespWithCacheInfo 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)

Example 5 with OcspRespWithCacheInfo

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

the class HttpOcspServlet method doPost.

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    OcspServer server = ServletHelper.getServer();
    try {
        if (server == null) {
            LOG.error("ServletHelper.server 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;
        }
        // accept only "application/ocsp-request" as content type
        String reqContentType = req.getHeader("Content-Type");
        if (!CT_REQUEST.equalsIgnoreCase(reqContentType)) {
            sendError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
            return;
        }
        Responder responder = responderAndPath.getResponder();
        byte[] reqContent = IoUtil.read(req.getInputStream());
        // request too long
        if (reqContent.length > responder.getMaxRequestSize()) {
            sendError(resp, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
            return;
        }
        OcspRespWithCacheInfo ocspRespWithCacheInfo = server.answer(responder, reqContent, false);
        if (ocspRespWithCacheInfo == null || ocspRespWithCacheInfo.getResponse() == null) {
            LOG.error("processRequest returned null, this should not happen");
            sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
        byte[] encodedOcspResp = ocspRespWithCacheInfo.getResponse();
        resp.setStatus(HttpServletResponse.SC_OK);
        resp.setContentType(CT_RESPONSE);
        resp.setContentLength(encodedOcspResp.length);
        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

OcspRespWithCacheInfo (org.xipki.ocsp.api.OcspRespWithCacheInfo)6 EOFException (java.io.EOFException)4 Responder (org.xipki.ocsp.api.Responder)4 ResponderAndPath (org.xipki.ocsp.api.ResponderAndPath)4 HttpVersion (io.netty.handler.codec.http.HttpVersion)2 Date (java.util.Date)2 ResponseCacheInfo (org.xipki.ocsp.api.OcspRespWithCacheInfo.ResponseCacheInfo)2 OcspServer (org.xipki.ocsp.api.OcspServer)2 FullHttpResponse (io.netty.handler.codec.http.FullHttpResponse)1 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 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 LinkedList (java.util.LinkedList)1 ASN1InputStream (org.bouncycastle.asn1.ASN1InputStream)1 ASN1Sequence (org.bouncycastle.asn1.ASN1Sequence)1 AlgorithmIdentifier (org.bouncycastle.asn1.x509.AlgorithmIdentifier)1