title: Does SSLSocket.startHandshake include certificate verification and hostname verification for SSLSocket?
body: <p>From the security guide <a href="https://developer.android.com/training/articles/security-ssl.html#CommonHostnameProbs" rel="nofollow noreferrer">https://developer.android.com/training/articles/security-ssl.html#CommonHostnameProbs</a>, when an SSLSocket is used seperated from the HttpsUrlConnection, hostname verification is required manually by invoking the hostnameverifier.verify() method:</p>
  
  <pre><code>// Open SSLSocket directly to gmail.com
  SocketFactory sf = SSLSocketFactory.getDefault();
  SSLSocket socket = (SSLSocket) sf.createSocket("gmail.com", 443);
  HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
  SSLSession s = socket.getSession();
  
  
  // Verify that the certicate hostname is for mail.google.com
  // This is due to lack of SNI support in the current SSLSocket.
  if (!hv.verify("mail.google.com", s)) {
      throw new SSLHandshakeException("Expected mail.google.com, "
                                      "found " + s.getPeerPrincipal());
  }
  
  // At this point SSLSocket performed certificate verification and
  // we have performed hostname verification, so it is safe to proceed.
  
  // ... use socket ...
  socket.close();
  </code></pre>
  
  <p>But I also see secure code examples says:</p>
  
  <pre><code>/*
   * This example demostrates how to use a SSLSocket as client to
   * send a HTTP request and get response from an HTTPS server.
   * It assumes that the client is not behind a firewall
   */
  
  public class SSLSocketClient {
  
      public static void main(String[] args) throws Exception {
          try {
              SSLSocketFactory factory =
                  (SSLSocketFactory)SSLSocketFactory.getDefault();
              SSLSocket socket =
                  (SSLSocket)factory.createSocket("www.verisign.com", 443);
  
              /*
               * send http request
               *
               * Before any application data is sent or received, the
               * SSL socket will do SSL handshaking first to set up
               * the security attributes.
               *
               * SSL handshaking can be initiated by either flushing data
               * down the pipe, or by starting the handshaking by hand.
               *
               * Handshaking is started manually in this example because
               * PrintWriter catches all IOExceptions (including
               * SSLExceptions), sets an internal error flag, and then
               * returns without rethrowing the exception.
               *
               * Unfortunately, this means any error messages are lost,
               * which caused lots of confusion for others using this
               * code.  The only way to tell there was an error is to call
               * PrintWriter.checkError().
               */
              socket.startHandshake();
  
              PrintWriter out = new PrintWriter(
                                    new BufferedWriter(
                                    new OutputStreamWriter(
                                    socket.getOutputStream())));
  
              out.println("GET / HTTP/1.0");
              out.println();
              out.flush();
  
              /*
               * Make sure there were no surprises
               */
              if (out.checkError())
                  System.out.println(
                      "SSLSocketClient:  java.io.PrintWriter error");
  
              /* read response */
              BufferedReader in = new BufferedReader(
                                      new InputStreamReader(
                                      socket.getInputStream()));
  
              String inputLine;
              while ((inputLine = in.readLine()) != null)
                  System.out.println(inputLine);
  
              in.close();
              out.close();
              socket.close();
  
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>Whether it is secure? I didn't see any hostname verify method is called before the read/write behavior of this socket. Does the socket.startHandShake() includes it?</p>