001/** 002 * 003 * Copyright 2014 the original author or authors 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smack.java7; 019 020import java.security.Principal; 021import java.security.cert.Certificate; 022import java.security.cert.CertificateException; 023import java.security.cert.X509Certificate; 024 025import javax.net.ssl.HostnameVerifier; 026import javax.net.ssl.SSLPeerUnverifiedException; 027import javax.net.ssl.SSLSession; 028import javax.security.auth.kerberos.KerberosPrincipal; 029 030import sun.security.util.HostnameChecker; 031 032/** 033 * <p> 034 * HostnameVerifier implementation which implements the same policy as the Java built-in 035 * pre-HostnameVerifier policy. 036 * </p> 037 * <p> 038 * Based on the <a href="found at http://kevinlocke.name/bits 039 * /2012/10/03/ssl-certificate-verification-in-dispatch-and-asynchttpclient/">work by Kevin 040 * Locke</a> (released under CC0 1.0 Universal / Public Domain Dedication). 041 * </p> 042 */ 043public class Java7HostnameVerifier implements HostnameVerifier { 044 045 @Override 046 public boolean verify(String hostname, SSLSession session) { 047 HostnameChecker checker = HostnameChecker.getInstance(HostnameChecker.TYPE_TLS); 048 049 boolean validCertificate = false, validPrincipal = false; 050 try { 051 Certificate[] peerCertificates = session.getPeerCertificates(); 052 053 if (peerCertificates.length > 0 && peerCertificates[0] instanceof X509Certificate) { 054 X509Certificate peerCertificate = (X509Certificate) peerCertificates[0]; 055 056 try { 057 checker.match(hostname, peerCertificate); 058 // Certificate matches hostname 059 validCertificate = true; 060 } 061 catch (CertificateException ex) { 062 // Certificate does not match hostname 063 } 064 } 065 else { 066 // Peer does not have any certificates or they aren't X.509 067 } 068 } 069 catch (SSLPeerUnverifiedException ex) { 070 // Not using certificates for peers, try verifying the principal 071 try { 072 Principal peerPrincipal = session.getPeerPrincipal(); 073 if (peerPrincipal instanceof KerberosPrincipal) { 074 validPrincipal = HostnameChecker.match(hostname, 075 (KerberosPrincipal) peerPrincipal); 076 } 077 else { 078 // Can't verify principal, not Kerberos 079 } 080 } 081 catch (SSLPeerUnverifiedException ex2) { 082 // Can't verify principal, no principal 083 } 084 } 085 086 return validCertificate || validPrincipal; 087 } 088}