/*
* Copyright 2014, The Sporting Exchange Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.betfair.cougar.core.impl.security;
import com.betfair.cougar.api.security.IdentityToken;
import com.betfair.cougar.api.security.IdentityTokenResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.auth.x500.X500Principal;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* An abstract class to deal with loading application keys from the Common name of a 2-way SSL encryption.
*/
public abstract class SSLAwareTokenResolver<I,O,C> implements IdentityTokenResolver<I,O,C> {
public static final String SSL_CERT_INFO = "X-SSL-Cert-Info";
private final CertInfoExtractor certInfoExtractor;
protected SSLAwareTokenResolver(CertInfoExtractor certInfoExtractor) {
if (certInfoExtractor == null) {
throw new IllegalArgumentException("CertInfoExtractor cannot be null");
}
this.certInfoExtractor = certInfoExtractor;
}
protected void attachCertInfo(List<IdentityToken> credentials, X509Certificate[] certificateChain) throws NamingException {
// Check if a SSL Common name has appeared
String sSLCertInfo = findCertInfo(certificateChain);
if (sSLCertInfo != null) {
credentials.add(new IdentityToken(SSL_CERT_INFO, sSLCertInfo));
}
}
/**
* Find an the info from the cert chain provided. <code>null</code> if none found
*/
protected String findCertInfo(X509Certificate[] x509certificates) throws NamingException {
if (x509certificates != null && x509certificates.length != 0) {
// Only ever use the first certificate, as this si the client supplied one.
// Further ones are trust stores and CAs that have signed the first cert.
Principal subject = x509certificates[0].getSubjectDN();
if (subject != null && subject.getName() != null) {
List<Rdn> rdns;
try {
rdns = new LdapName(subject.getName()).getRdns();
}
catch (InvalidNameException ine) {
return null;
}
return certInfoExtractor.extractCertInfo(rdns);
}
}
return null;
}
}