1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl.ocsp;
17
18 import io.netty.buffer.ByteBufUtil;
19 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.channel.SimpleChannelInboundHandler;
21 import io.netty.handler.codec.http.FullHttpResponse;
22 import io.netty.handler.codec.http.HttpHeaderNames;
23 import io.netty.util.concurrent.Promise;
24 import io.netty.util.internal.logging.InternalLogger;
25 import io.netty.util.internal.logging.InternalLoggerFactory;
26 import org.bouncycastle.cert.ocsp.OCSPException;
27 import org.bouncycastle.cert.ocsp.OCSPResp;
28
29 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
30 import static io.netty.util.internal.ObjectUtil.checkNotNull;
31
32 final class OcspHttpHandler extends SimpleChannelInboundHandler<FullHttpResponse> {
33
34 private static final InternalLogger LOGGER = InternalLoggerFactory.getInstance(OcspHttpHandler.class);
35 private final Promise<OCSPResp> responseFuture;
36
37 static final String OCSP_REQUEST_TYPE = "application/ocsp-request";
38 static final String OCSP_RESPONSE_TYPE = "application/ocsp-response";
39
40
41
42
43
44
45 OcspHttpHandler(Promise<OCSPResp> responsePromise) {
46 super(FullHttpResponse.class);
47 this.responseFuture = checkNotNull(responsePromise, "ResponsePromise");
48 }
49
50 @Override
51 protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse response) throws Exception {
52 try {
53
54 if (LOGGER.isDebugEnabled()) {
55 LOGGER.debug("Received OCSP HTTP Response: {}", response);
56 }
57
58
59 String contentType = response.headers().get(HttpHeaderNames.CONTENT_TYPE);
60 if (contentType == null) {
61 throw new OCSPException("HTTP Response does not contain 'CONTENT-TYPE' header");
62 }
63
64
65 if (!contentType.equalsIgnoreCase(OCSP_RESPONSE_TYPE)) {
66 throw new OCSPException("Response Content-Type was: " + contentType +
67 "; Expected: " + OCSP_RESPONSE_TYPE);
68 }
69
70
71 if (response.status() != OK) {
72 throw new IllegalArgumentException("HTTP Response Code was: " + response.status().code() +
73 "; Expected: 200");
74 }
75
76 responseFuture.trySuccess(new OCSPResp(ByteBufUtil.getBytes(response.content())));
77 } finally {
78 ctx.channel().close();
79 }
80 }
81
82 @Override
83 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
84 responseFuture.tryFailure(cause);
85 }
86 }