001/* 002 * The MIT License 003 * Copyright (c) 2012 Microsoft Corporation 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining a copy 006 * of this software and associated documentation files (the "Software"), to deal 007 * in the Software without restriction, including without limitation the rights 008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 009 * copies of the Software, and to permit persons to whom the Software is 010 * furnished to do so, subject to the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be included in 013 * all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 021 * THE SOFTWARE. 022 */ 023 024package microsoft.exchange.webservices.data.core; 025 026import org.apache.http.conn.ssl.DefaultHostnameVerifier; 027import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 028import org.apache.http.ssl.SSLContexts; 029 030import javax.net.ssl.HostnameVerifier; 031import javax.net.ssl.SSLContext; 032import javax.net.ssl.TrustManager; 033 034import java.security.GeneralSecurityException; 035 036/** 037 * <p> 038 * EwsSSLProtocolSocketFactory can be used to create SSL {@link java.net.Socket}s 039 * that accept self-signed certificates. 040 * </p> 041 * <p> 042 * This socket factory SHOULD NOT be used for productive systems 043 * due to security reasons, unless it is a conscious decision and 044 * you are perfectly aware of security implications of accepting 045 * self-signed certificates 046 * </p> 047 * <p> 048 * Example of using custom protocol socket factory for a specific host: 049 * </p> 050 * <pre> 051 * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); 052 * 053 * URI uri = new URI("https://localhost/", true); 054 * // use relative url only 055 * GetMethod httpget = new GetMethod(uri.getPathQuery()); 056 * HostConfiguration hc = new HostConfiguration(); 057 * hc.setHost(uri.getHost(), uri.getPort(), easyhttps); 058 * HttpClient client = new HttpClient(); 059 * client.executeMethod(hc, httpget); 060 * </pre> 061 * <p> 062 * Example of using custom protocol socket factory per default instead of the standard one: 063 * </p> 064 * <pre> 065 * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443); 066 * Protocol.registerProtocol("https", easyhttps); 067 * 068 * HttpClient client = new HttpClient(); 069 * GetMethod httpget = new GetMethod("https://localhost/"); 070 * client.executeMethod(httpget); 071 * </pre> 072 * 073 * <p> 074 * DISCLAIMER: HttpClient developers DO NOT actively support this component. 075 * The component is provided as a reference material, which may be inappropriate 076 * for use without additional customization. 077 * </p> 078 */ 079 080public class EwsSSLProtocolSocketFactory extends SSLConnectionSocketFactory { 081 082 /** 083 * Default hostname verifier. 084 */ 085 private static final HostnameVerifier DEFAULT_HOSTNAME_VERIFIER = new DefaultHostnameVerifier(); 086 087 088 /** 089 * The SSL Context. 090 */ 091 private final SSLContext sslcontext; 092 093 094 /** 095 * Constructor for EasySSLProtocolSocketFactory. 096 * 097 * @param context SSL context 098 * @param hostnameVerifier hostname verifier 099 */ 100 public EwsSSLProtocolSocketFactory( 101 SSLContext context, HostnameVerifier hostnameVerifier 102 ) { 103 super(context, hostnameVerifier); 104 this.sslcontext = context; 105 } 106 107 108 /** 109 * Create and configure SSL protocol socket factory using default hostname verifier. 110 * {@link EwsSSLProtocolSocketFactory#DEFAULT_HOSTNAME_VERIFIER} 111 * 112 * @param trustManager trust manager 113 * @return socket factory for SSL protocol 114 * @throws GeneralSecurityException on security error 115 */ 116 public static EwsSSLProtocolSocketFactory build(TrustManager trustManager) 117 throws GeneralSecurityException { 118 return build(trustManager, DEFAULT_HOSTNAME_VERIFIER); 119 } 120 121 /** 122 * Create and configure SSL protocol socket factory using trust manager and hostname verifier. 123 * 124 * @param trustManager trust manager 125 * @param hostnameVerifier hostname verifier 126 * @return socket factory for SSL protocol 127 * @throws GeneralSecurityException on security error 128 */ 129 public static EwsSSLProtocolSocketFactory build( 130 TrustManager trustManager, HostnameVerifier hostnameVerifier 131 ) throws GeneralSecurityException { 132 SSLContext sslContext = createSslContext(trustManager); 133 return new EwsSSLProtocolSocketFactory(sslContext, hostnameVerifier); 134 } 135 136 /** 137 * Create SSL context and initialize it using specific trust manager. 138 * 139 * @param trustManager trust manager 140 * @return initialized SSL context 141 * @throws GeneralSecurityException on security error 142 */ 143 public static SSLContext createSslContext(TrustManager trustManager) 144 throws GeneralSecurityException { 145 EwsX509TrustManager x509TrustManager = new EwsX509TrustManager(null, trustManager); 146 SSLContext sslContext = SSLContexts.createDefault(); 147 sslContext.init( 148 null, 149 new TrustManager[] { x509TrustManager }, 150 null 151 ); 152 return sslContext; 153 } 154 155 156 /** 157 * @return SSL context 158 */ 159 public SSLContext getContext() { 160 return sslcontext; 161 } 162 163 public boolean equals(Object obj) { 164 return ((obj != null) && obj.getClass().equals(EwsSSLProtocolSocketFactory.class)); 165 } 166 167 public int hashCode() { 168 return EwsSSLProtocolSocketFactory.class.hashCode(); 169 } 170 171}