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
}
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
}
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);
}
}
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();
}
}
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();
}
}
Aggregations