下面列出了javax.net.ssl.SSLSession#getPeerCertificateChain ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private ServerInterceptor mutualTLSInterceptor(byte[] expectedClientCert, AtomicBoolean toggleHandshakeOccured) {
return new ServerInterceptor() {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
SSLSession sslSession = serverCall.getAttributes().get(Grpc.TRANSPORT_ATTR_SSL_SESSION);
try {
javax.security.cert.X509Certificate[] certChain = sslSession.getPeerCertificateChain();
Assert.assertFalse("Client didn't send TLS certificate", certChain == null || certChain.length == 0);
byte[] clientRawCert = certChain[0].getEncoded();
// Ensure the client TLS cert matches the expected one - the one it was created with
boolean equalCerts = Arrays.equals(clientRawCert, expectedClientCert);
Assert.assertTrue("Expected certificate doesn't match actual", equalCerts);
toggleHandshakeOccured.set(true);
} catch (Exception e) {
Assert.fail(String.format("Uncaught exception: %s", e.toString()));
e.printStackTrace();
}
return serverCallHandler.startCall(serverCall, metadata);
}
};
}
@Override
protected boolean verify(ChannelHandlerContext ctx, ReferenceCountedOpenSslEngine engine) throws Exception {
byte[] staple = engine.getOcspResponse();
if (staple == null) {
throw new IllegalStateException("Server didn't provide an OCSP staple!");
}
OCSPResp response = new OCSPResp(staple);
if (response.getStatus() != OCSPResponseStatus.SUCCESSFUL) {
return false;
}
SSLSession session = engine.getSession();
X509Certificate[] chain = session.getPeerCertificateChain();
BigInteger certSerial = chain[0].getSerialNumber();
BasicOCSPResp basicResponse = (BasicOCSPResp) response.getResponseObject();
SingleResp first = basicResponse.getResponses()[0];
// ATTENTION: CertificateStatus.GOOD is actually a null value! Do not use
// equals() or you'll NPE!
CertificateStatus status = first.getCertStatus();
BigInteger ocspSerial = first.getCertID().getSerialNumber();
String message = new StringBuilder()
.append("OCSP status of ").append(ctx.channel().remoteAddress())
.append("\n Status: ").append(status == CertificateStatus.GOOD ? "Good" : status)
.append("\n This Update: ").append(first.getThisUpdate())
.append("\n Next Update: ").append(first.getNextUpdate())
.append("\n Cert Serial: ").append(certSerial)
.append("\n OCSP Serial: ").append(ocspSerial)
.toString();
System.out.println(message);
return status == CertificateStatus.GOOD && certSerial.equals(ocspSerial);
}
private void getCert(SSLSocket socket) throws SSLPeerUnverifiedException {
SSLSession session = socket.getSession();
javax.security.cert.X509Certificate[] certs = session.getPeerCertificateChain();
if (this.cert == null) {
this.cert = certs[certs.length - 1];
}
}
/**
* Verifies the certificate chain presented by the server to which
* a secure Socket has just connected. Specifically, the provided host
* name is checked against the Common Name of the server certificate;
* additional checks may or may not be performed.
*
* @param host the requested host name
* @param session SSLSession used on the connection to host
* @throws Exception if the certificate chain cannot be verified
*/
protected void verify(String host, SSLSession session) throws Exception {
X509Certificate[] chain;
X509Certificate certificate;
Principal principal;
PublicKey publicKey;
String DN;
String CN;
int start;
int end;
String emsg;
chain = session.getPeerCertificateChain();
certificate = chain[0];
principal = certificate.getSubjectDN();
DN = String.valueOf(principal);
start = DN.indexOf("CN=");
if (start < 0) {
throw new UnknownHostException(
Error.getMessage(ErrorCode.M_SERVER_SECURE_VERIFY_1));
}
start += 3;
end = DN.indexOf(',', start);
CN = DN.substring(start, (end > -1) ? end
: DN.length());
if (CN.length() < 1) {
throw new UnknownHostException(
Error.getMessage(ErrorCode.M_SERVER_SECURE_VERIFY_2));
}
if (!CN.equalsIgnoreCase(host)) {
// TLS_HOSTNAME_MISMATCH
throw new UnknownHostException(
Error.getMessage(
ErrorCode.M_SERVER_SECURE_VERIFY_3, 0, new Object[] {
CN, host
}));
}
}
/**
* Describe <code>verifyHostname</code> method here.
*
* @param socket a <code>SSLSocket</code> value
* @exception SSLPeerUnverifiedException If there are problems obtaining
* the server certificates from the SSL session, or the server host name
* does not match with the "Common Name" in the server certificates
* SubjectDN.
* @exception UnknownHostException If we are not able to resolve
* the SSL sessions returned server host name.
*/
private void verifyHostname(SSLSocket socket)
throws SSLPeerUnverifiedException, UnknownHostException {
if (! verifyHostname)
return;
SSLSession session = socket.getSession();
String hostname = session.getPeerHost();
try {
InetAddress addr = InetAddress.getByName(hostname);
} catch (UnknownHostException uhe) {
throw new UnknownHostException("Could not resolve SSL sessions "
+ "server hostname: " + hostname);
}
X509Certificate[] certs = session.getPeerCertificateChain();
if (certs == null || certs.length == 0)
throw new SSLPeerUnverifiedException("No server certificates found!");
//get the servers DN in its string representation
String dn = certs[0].getSubjectDN().getName();
//might be useful to print out all certificates we receive from the
//server, in case one has to debug a problem with the installed certs.
if (LOG.isDebugEnabled()) {
LOG.debug("Server certificate chain:");
for (int i = 0; i < certs.length; i++) {
LOG.debug("X509Certificate[" + i + "]=" + certs[i]);
}
}
//get the common name from the first cert
String cn = getCN(dn);
if (hostname.equalsIgnoreCase(cn)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Target hostname valid: " + cn);
}
} else {
throw new SSLPeerUnverifiedException(
"HTTPS hostname invalid: expected '" + hostname + "', received '" + cn + "'");
}
}
/**
* Intercept incoming and outgoing messages and enforce any necessary controls
*
* @param call the request message
* @param headers the request metadata
* @param next the next interceptor in the interceptor chain prior to the service implementation
* @param <I> The message request type (e.g. ReqT)
* @param <O> The message reply type (e.g. RespT)
*
* @return a listener for the incoming call.
*/
@Override
public <I, O> ServerCall.Listener<I> interceptCall(
final ServerCall<I, O> call,
final Metadata headers,
final ServerCallHandler<I, O> next) {
final Attributes attributes = call.getAttributes();
final SocketAddress socketAddress = attributes.get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
final String clientIp = clientIp(socketAddress);
String foundSubject = DEFAULT_FOUND_SUBJECT;
// enforce that the DN on the client cert matches the configured pattern
final SSLSession sslSession = attributes.get(Grpc.TRANSPORT_ATTR_SSL_SESSION);
if(this.authorizedDNpattern != null && sslSession != null) {
try {
final X509Certificate[] certs = sslSession.getPeerCertificateChain();
if(certs != null && certs.length > 0) {
for (final X509Certificate cert : certs) {
foundSubject = cert.getSubjectDN().getName();
if(authorizedDNpattern.matcher(foundSubject).matches()) {
break;
} else {
logger.warn("Rejecting transfer attempt from " + foundSubject + " because the DN is not authorized, host=" + clientIp);
call.close(Status.PERMISSION_DENIED.withDescription(DN_UNAUTHORIZED + foundSubject), headers);
return IDENTITY_LISTENER;
}
}
}
} catch (final SSLPeerUnverifiedException e) {
logger.debug("skipping DN authorization for request from {}.", new Object[] {clientIp}, e);
}
}
// contextualize the DN and IP for use in the RPC implementation
final Context context = Context.current()
.withValue(REMOTE_HOST_KEY, clientIp)
.withValue(REMOTE_DN_KEY, foundSubject);
// if we got to this point, there were no errors, call the next interceptor in the chain
return Contexts.interceptCall(context, call, headers, next);
}
/**
* Describe <code>verifyHostname</code> method here.
*
* @param socket a <code>SSLSocket</code> value
* @exception SSLPeerUnverifiedException If there are problems obtaining
* the server certificates from the SSL session, or the server host name
* does not match with the "Common Name" in the server certificates
* SubjectDN.
* @exception UnknownHostException If we are not able to resolve
* the SSL sessions returned server host name.
*/
protected void verifyHostname(SSLSocket socket)
throws SSLPeerUnverifiedException, UnknownHostException {
if (! verifyHostname)
return;
SSLSession session = socket.getSession();
if (session==null) {
throw new UnknownHostException("could not obtain session from socket");
}
String hostname = session.getPeerHost();
try {
InetAddress.getByName(hostname);
} catch (UnknownHostException uhe) {
String msg = "Could not resolve SSL sessions server hostname: " + hostname;
// Under WebSphere, hostname can be equal to proxy-hostname
log.warn(msg,uhe);
// throw new UnknownHostException(msg);
}
javax.security.cert.X509Certificate[] certs = session.getPeerCertificateChain();
if (certs == null || certs.length == 0)
throw new SSLPeerUnverifiedException("No server certificates found!");
//get the servers DN in its string representation
String dn = certs[0].getSubjectDN().getName();
//might be useful to print out all certificates we receive from the
//server, in case one has to debug a problem with the installed certs.
if (log.isInfoEnabled()) {
log.info("Server certificate chain:");
for (int i = 0; i < certs.length; i++) {
log.info("X509Certificate[" + i + "]=" + certs[i]);
}
}
//get the common name from the first cert
String cn = getCN(dn);
if (hostname.equalsIgnoreCase(cn)) {
if (log.isInfoEnabled()) {
log.info("Target hostname valid: " + cn);
}
} else {
throw new SSLPeerUnverifiedException(
"HTTPS hostname invalid: expected '" + hostname + "', received '" + cn + "'");
}
}