Home | History | Annotate | Download | only in okhttp
      1 /*
      2  * Copyright (C) 2013 Square, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.squareup.okhttp;
     18 
     19 import com.squareup.okhttp.internal.Util;
     20 import java.security.Principal;
     21 import java.security.cert.Certificate;
     22 import java.security.cert.X509Certificate;
     23 import java.util.Collections;
     24 import java.util.List;
     25 import javax.net.ssl.SSLPeerUnverifiedException;
     26 import javax.net.ssl.SSLSession;
     27 
     28 /**
     29  * A record of a TLS handshake. For HTTPS clients, the client is <i>local</i>
     30  * and the remote server is its <i>peer</i>.
     31  *
     32  * <p>This value object describes a completed handshake. Use {@link
     33  * javax.net.ssl.SSLSocketFactory} to set policy for new handshakes.
     34  */
     35 public final class Handshake {
     36   private final String cipherSuite;
     37   private final List<Certificate> peerCertificates;
     38   private final List<Certificate> localCertificates;
     39 
     40   private Handshake(
     41       String cipherSuite, List<Certificate> peerCertificates, List<Certificate> localCertificates) {
     42     this.cipherSuite = cipherSuite;
     43     this.peerCertificates = peerCertificates;
     44     this.localCertificates = localCertificates;
     45   }
     46 
     47   public static Handshake get(SSLSession session) {
     48     String cipherSuite = session.getCipherSuite();
     49     if (cipherSuite == null) throw new IllegalStateException("cipherSuite == null");
     50 
     51     Certificate[] peerCertificates;
     52     try {
     53       peerCertificates = session.getPeerCertificates();
     54     } catch (SSLPeerUnverifiedException ignored) {
     55       peerCertificates = null;
     56     }
     57     List<Certificate> peerCertificatesList = peerCertificates != null
     58         ? Util.immutableList(peerCertificates)
     59         : Collections.<Certificate>emptyList();
     60 
     61     Certificate[] localCertificates = session.getLocalCertificates();
     62     List<Certificate> localCertificatesList = localCertificates != null
     63         ? Util.immutableList(localCertificates)
     64         : Collections.<Certificate>emptyList();
     65 
     66     return new Handshake(cipherSuite, peerCertificatesList, localCertificatesList);
     67   }
     68 
     69   public static Handshake get(
     70       String cipherSuite, List<Certificate> peerCertificates, List<Certificate> localCertificates) {
     71     if (cipherSuite == null) throw new IllegalArgumentException("cipherSuite == null");
     72     return new Handshake(cipherSuite, Util.immutableList(peerCertificates),
     73         Util.immutableList(localCertificates));
     74   }
     75 
     76   /** Returns a cipher suite name like "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA". */
     77   public String cipherSuite() {
     78     return cipherSuite;
     79   }
     80 
     81   /** Returns a possibly-empty list of certificates that identify the remote peer. */
     82   public List<Certificate> peerCertificates() {
     83     return peerCertificates;
     84   }
     85 
     86   /** Returns the remote peer's principle, or null if that peer is anonymous. */
     87   public Principal peerPrincipal() {
     88     return !peerCertificates.isEmpty()
     89         ? ((X509Certificate) peerCertificates.get(0)).getSubjectX500Principal()
     90         : null;
     91   }
     92 
     93   /** Returns a possibly-empty list of certificates that identify this peer. */
     94   public List<Certificate> localCertificates() {
     95     return localCertificates;
     96   }
     97 
     98   /** Returns the local principle, or null if this peer is anonymous. */
     99   public Principal localPrincipal() {
    100     return !localCertificates.isEmpty()
    101         ? ((X509Certificate) localCertificates.get(0)).getSubjectX500Principal()
    102         : null;
    103   }
    104 
    105   @Override public boolean equals(Object other) {
    106     if (!(other instanceof Handshake)) return false;
    107     Handshake that = (Handshake) other;
    108     return cipherSuite.equals(that.cipherSuite)
    109         && peerCertificates.equals(that.peerCertificates)
    110         && localCertificates.equals(that.localCertificates);
    111   }
    112 
    113   @Override public int hashCode() {
    114     int result = 17;
    115     result = 31 * result + cipherSuite.hashCode();
    116     result = 31 * result + peerCertificates.hashCode();
    117     result = 31 * result + localCertificates.hashCode();
    118     return result;
    119   }
    120 }
    121