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    }