blob: 71a73db71f102c98c0cb4cea723b1f5e360a5793 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.qpid.transport.network.security.ssl;
import org.apache.qpid.transport.TransportException;
import org.apache.qpid.transport.util.Logger;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
public class SSLUtil
{
private static final Logger log = Logger.get(SSLUtil.class);
private SSLUtil()
{
}
public static void verifyHostname(SSLEngine engine,String hostnameExpected)
{
try
{
Certificate cert = engine.getSession().getPeerCertificates()[0];
Principal p = ((X509Certificate)cert).getSubjectDN();
String dn = p.getName();
String hostname = null;
if (dn.contains("CN="))
{
hostname = dn.substring(3,
dn.indexOf(",") == -1? dn.length(): dn.indexOf(","));
}
if (log.isDebugEnabled())
{
log.debug("Hostname expected : " + hostnameExpected);
log.debug("Distinguished Name for server certificate : " + dn);
log.debug("Host Name obtained from DN : " + hostname);
}
if (hostname != null && !(hostname.equalsIgnoreCase(hostnameExpected) ||
hostname.equalsIgnoreCase(hostnameExpected + ".localdomain")))
{
throw new TransportException("SSL hostname verification failed." +
" Expected : " + hostnameExpected +
" Found in cert : " + hostname);
}
}
catch(SSLPeerUnverifiedException e)
{
log.warn("Exception received while trying to verify hostname",e);
// For some reason the SSL engine sets the handshake status to FINISH twice
// in succession. The first time the peer certificate
// info is not available. The second time it works !
// Therefore have no choice but to ignore the exception here.
}
}
public static String retriveIdentity(SSLEngine engine)
{
StringBuffer id = new StringBuffer();
try
{
Certificate cert = engine.getSession().getLocalCertificates()[0];
Principal p = ((X509Certificate)cert).getSubjectDN();
String dn = p.getName();
if (dn.contains("CN="))
{
id.append(dn.substring(3,
dn.indexOf(",") == -1? dn.length(): dn.indexOf(",")));
}
if (dn.contains("DC="))
{
id.append("@");
int c = 0;
for (String toks : dn.split(","))
{
if (toks.contains("DC"))
{
if (c > 0) {id.append(".");}
id.append(toks.substring(
toks.indexOf("=")+1,
toks.indexOf(",") == -1? toks.length(): toks.indexOf(",")));
c++;
}
}
}
}
catch(Exception e)
{
log.info("Exception received while trying to retrive client identity from SSL cert",e);
}
log.debug("Extracted Identity from client certificate : " + id);
return id.toString();
}
public static KeyStore getInitializedKeyStore(String storePath, String storePassword) throws GeneralSecurityException, IOException
{
KeyStore ks = KeyStore.getInstance("JKS");
InputStream in = null;
try
{
File f = new File(storePath);
if (f.exists())
{
in = new FileInputStream(f);
}
else
{
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath);
}
if (in == null)
{
throw new IOException("Unable to load keystore resource: " + storePath);
}
char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
ks.load(in, storeCharPassword);
}
finally
{
if (in != null)
{
//noinspection EmptyCatchBlock
try
{
in.close();
}
catch (IOException ignored)
{
}
}
}
return ks;
}
}