001/* 002 * Copyright (C) 2017 Neo Visionaries Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package NeoVisionaries.WebSockets; 017 018 019import javax.net.ssl.SSLSocket; 020 021 022/** 023 * The certificate of the peer does not match the expected hostname. 024 * 025 * <EMBED CLASS='external-html' DATA-FILE-ID=LICENSE><BR /> 026 * 027 * <p> 028 * {@link #getError()} of this class returns {@link WebSocketError#HOSTNAME_UNVERIFIED 029 * HOSTNAME_UNVERIFIED}. 030 * </p> 031 * 032 * <p> 033 * See <a href='https://github.com/TakahikoKawasaki/nv-websocket-client/pull/107' 034 * >Verify that certificate is valid for server hostname (#107)</a>. 035 * </p> 036 * 037 * @since 2.1 038 */ 039public class HostnameUnverifiedException extends WebSocketException 040{ 041 private static final long serialVersionUID = 1L; 042 043 044 private final SSLSocket mSSLSocket; 045 private final String mHostname; 046 047 048 /** 049 * Constructor with the SSL socket and the expected hostname. 050 * 051 * @param socket 052 * The SSL socket against which the hostname verification failed. 053 * 054 * @param hostname 055 * The expected hostname. 056 */ 057 public HostnameUnverifiedException(SSLSocket socket, String hostname) 058 { 059 super(WebSocketError.HOSTNAME_UNVERIFIED, 060 String.format("The certificate of the peer%s does not match the expected hostname (%s)", 061 stringifyPrincipal(socket), hostname)); 062 063 mSSLSocket = socket; 064 mHostname = hostname; 065 } 066 067 068 private static String stringifyPrincipal(SSLSocket socket) 069 { 070 try 071 { 072 return String.format(" (%s)", socket.getSession().getPeerPrincipal().toString()); 073 } 074 catch (Exception e) 075 { 076 // Principal information is not available. 077 return ""; 078 } 079 } 080 081 082 /** 083 * Get the SSL socket against which the hostname verification failed. 084 * 085 * @return 086 * The SSL socket. 087 */ 088 public SSLSocket getSSLSocket() 089 { 090 return mSSLSocket; 091 } 092 093 094 /** 095 * Get the expected hostname. 096 * 097 * @return 098 * The expected hostname. 099 */ 100 public String getHostname() 101 { 102 return mHostname; 103 } 104}