View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.conn.ssl;
29  
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.security.cert.Certificate;
33  import java.security.cert.X509Certificate;
34  
35  import javax.net.ssl.SSLException;
36  import javax.net.ssl.SSLSession;
37  import javax.net.ssl.SSLSocket;
38  
39  import org.apache.http.annotation.Immutable;
40  
41  /**
42   * Abstract base class for all standard {@link org.apache.http.conn.ssl.X509HostnameVerifier}
43   * implementations that provides common methods extracting
44   * {@link java.security.cert.X509Certificate} instance to be verified from either
45   * {@link javax.net.ssl.SSLSocket} or {@link javax.net.ssl.SSLSession}.
46   *
47   * @since 4.4
48   */
49  @Immutable
50  public abstract class AbstractBaseHostnameVerifier implements X509HostnameVerifier {
51  
52      @Override
53      public final void verify(final String host, final SSLSocket ssl)
54            throws IOException {
55          if(host == null) {
56              throw new NullPointerException("host to verify is null");
57          }
58  
59          SSLSession session = ssl.getSession();
60          if(session == null) {
61              // In our experience this only happens under IBM 1.4.x when
62              // spurious (unrelated) certificates show up in the server'
63              // chain.  Hopefully this will unearth the real problem:
64              final InputStream in = ssl.getInputStream();
65              in.available();
66              /*
67                If you're looking at the 2 lines of code above because
68                you're running into a problem, you probably have two
69                options:
70  
71                  #1.  Clean up the certificate chain that your server
72                       is presenting (e.g. edit "/etc/apache2/server.crt"
73                       or wherever it is your server's certificate chain
74                       is defined).
75  
76                                             OR
77  
78                  #2.   Upgrade to an IBM 1.5.x or greater JVM, or switch
79                        to a non-IBM JVM.
80              */
81  
82              // If ssl.getInputStream().available() didn't cause an
83              // exception, maybe at least now the session is available?
84              session = ssl.getSession();
85              if(session == null) {
86                  // If it's still null, probably a startHandshake() will
87                  // unearth the real problem.
88                  ssl.startHandshake();
89  
90                  // Okay, if we still haven't managed to cause an exception,
91                  // might as well go for the NPE.  Or maybe we're okay now?
92                  session = ssl.getSession();
93              }
94          }
95  
96          final Certificate[] certs = session.getPeerCertificates();
97          final X509Certificate x509 = (X509Certificate) certs[0];
98          verify(host, x509);
99      }
100 
101     @Override
102     public final boolean verify(final String host, final SSLSession session) {
103         try {
104             final Certificate[] certs = session.getPeerCertificates();
105             final X509Certificate x509 = (X509Certificate) certs[0];
106             verify(host, x509);
107             return true;
108         }
109         catch(final SSLException e) {
110             return false;
111         }
112     }
113 
114 }