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
024 package microsoft.exchange.webservices.data.core;
025
026 import org.apache.http.conn.ssl.DefaultHostnameVerifier;
027 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
028 import org.apache.http.ssl.SSLContexts;
029
030 import javax.net.ssl.HostnameVerifier;
031 import javax.net.ssl.SSLContext;
032 import javax.net.ssl.TrustManager;
033
034 import 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 * Example of using custom protocol socket factory for a specific host:
048 * <pre>
049 * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
050 *
051 * URI uri = new URI("https://localhost/", true);
052 * // use relative url only
053 * GetMethod httpget = new GetMethod(uri.getPathQuery());
054 * HostConfiguration hc = new HostConfiguration();
055 * hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
056 * HttpClient client = new HttpClient();
057 * client.executeMethod(hc, httpget);
058 * </pre>
059 * </p>
060 * <p>
061 * Example of using custom protocol socket factory per default instead of the standard one:
062 * <pre>
063 * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
064 * Protocol.registerProtocol("https", easyhttps);
065 *
066 * HttpClient client = new HttpClient();
067 * GetMethod httpget = new GetMethod("https://localhost/");
068 * client.executeMethod(httpget);
069 * </pre>
070 * </p>
071 *
072 * <p>
073 * DISCLAIMER: HttpClient developers DO NOT actively support this component.
074 * The component is provided as a reference material, which may be inappropriate
075 * for use without additional customization.
076 * </p>
077 */
078
079 public class EwsSSLProtocolSocketFactory extends SSLConnectionSocketFactory {
080
081 /**
082 * Default hostname verifier.
083 */
084 private static final HostnameVerifier DEFAULT_HOSTNAME_VERIFIER = new DefaultHostnameVerifier();
085
086
087 /**
088 * The SSL Context.
089 */
090 private final SSLContext sslcontext;
091
092
093 /**
094 * Constructor for EasySSLProtocolSocketFactory.
095 *
096 * @param context SSL context
097 * @param hostnameVerifier hostname verifier
098 */
099 public EwsSSLProtocolSocketFactory(
100 SSLContext context, HostnameVerifier hostnameVerifier
101 ) {
102 super(context, hostnameVerifier);
103 this.sslcontext = context;
104 }
105
106
107 /**
108 * Create and configure SSL protocol socket factory using default hostname verifier.
109 * {@link EwsSSLProtocolSocketFactory#DEFAULT_HOSTNAME_VERIFIER}
110 *
111 * @param trustManager trust manager
112 * @return socket factory for SSL protocol
113 * @throws GeneralSecurityException on security error
114 */
115 public static EwsSSLProtocolSocketFactory build(TrustManager trustManager)
116 throws GeneralSecurityException {
117 return build(trustManager, DEFAULT_HOSTNAME_VERIFIER);
118 }
119
120 /**
121 * Create and configure SSL protocol socket factory using trust manager and hostname verifier.
122 *
123 * @param trustManager trust manager
124 * @param hostnameVerifier hostname verifier
125 * @return socket factory for SSL protocol
126 * @throws GeneralSecurityException on security error
127 */
128 public static EwsSSLProtocolSocketFactory build(
129 TrustManager trustManager, HostnameVerifier hostnameVerifier
130 ) throws GeneralSecurityException {
131 SSLContext sslContext = createSslContext(trustManager);
132 return new EwsSSLProtocolSocketFactory(sslContext, hostnameVerifier);
133 }
134
135 /**
136 * Create SSL context and initialize it using specific trust manager.
137 *
138 * @param trustManager trust manager
139 * @return initialized SSL context
140 * @throws GeneralSecurityException on security error
141 */
142 public static SSLContext createSslContext(TrustManager trustManager)
143 throws GeneralSecurityException {
144 EwsX509TrustManager x509TrustManager = new EwsX509TrustManager(null, trustManager);
145 SSLContext sslContext = SSLContexts.createDefault();
146 sslContext.init(
147 null,
148 new TrustManager[] { x509TrustManager },
149 null
150 );
151 return sslContext;
152 }
153
154
155 /**
156 * @return SSL context
157 */
158 public SSLContext getContext() {
159 return sslcontext;
160 }
161
162 public boolean equals(Object obj) {
163 return ((obj != null) && obj.getClass().equals(EwsSSLProtocolSocketFactory.class));
164 }
165
166 public int hashCode() {
167 return EwsSSLProtocolSocketFactory.class.hashCode();
168 }
169
170 }