All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.okhttp3.tls.internal.TlsUtil.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package okhttp3.tls.internal

import java.io.InputStream
import java.security.KeyStore
import java.security.cert.Certificate
import java.security.cert.X509Certificate
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509ExtendedTrustManager
import javax.net.ssl.X509KeyManager
import javax.net.ssl.X509TrustManager
import okhttp3.internal.platform.Platform
import okhttp3.tls.HandshakeCertificates
import okhttp3.tls.HeldCertificate
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

object TlsUtil {
  val password = "password".toCharArray()

  private val localhost: HandshakeCertificates by lazy {
    // Generate a self-signed cert for the server to serve and the client to trust.
    val heldCertificate =
      HeldCertificate.Builder()
        .commonName("localhost")
        .addSubjectAlternativeName("localhost")
        .addSubjectAlternativeName("localhost.localdomain")
        .build()
    return@lazy HandshakeCertificates.Builder()
      .heldCertificate(heldCertificate)
      .addTrustedCertificate(heldCertificate.certificate)
      .build()
  }

  /** Returns an SSL client for this host's localhost address. */
  @JvmStatic
  fun localhost(): HandshakeCertificates = localhost

  /** Returns a trust manager that trusts `trustedCertificates`. */
  @JvmStatic @IgnoreJRERequirement
  fun newTrustManager(
    keyStoreType: String?,
    trustedCertificates: List,
    insecureHosts: List,
  ): X509TrustManager {
    val trustStore = newEmptyKeyStore(keyStoreType)
    for (i in trustedCertificates.indices) {
      trustStore.setCertificateEntry("cert_$i", trustedCertificates[i])
    }

    val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
    factory.init(trustStore)
    val result = factory.trustManagers!!
    check(result.size == 1 && result[0] is X509TrustManager) {
      "Unexpected trust managers: ${result.contentToString()}"
    }

    val trustManager = result[0] as X509TrustManager

    return when {
      insecureHosts.isEmpty() -> trustManager
      Platform.isAndroid -> InsecureAndroidTrustManager(trustManager, insecureHosts)
      else -> InsecureExtendedTrustManager(trustManager as X509ExtendedTrustManager, insecureHosts)
    }
  }

  /**
   * Returns a key manager for the held certificate and its chain. Returns an empty key manager if
   * `heldCertificate` is null.
   */
  @JvmStatic
  fun newKeyManager(
    keyStoreType: String?,
    heldCertificate: HeldCertificate?,
    vararg intermediates: X509Certificate,
  ): X509KeyManager {
    val keyStore = newEmptyKeyStore(keyStoreType)
    if (heldCertificate != null) {
      val chain = arrayOfNulls(1 + intermediates.size)
      chain[0] = heldCertificate.certificate
      intermediates.copyInto(chain, 1)
      keyStore.setKeyEntry("private", heldCertificate.keyPair.private, password, chain)
    }

    val factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
    factory.init(keyStore, password)
    val result = factory.keyManagers!!
    check(result.size == 1 && result[0] is X509KeyManager) {
      "Unexpected key managers:${result.contentToString()}"
    }

    return result[0] as X509KeyManager
  }

  private fun newEmptyKeyStore(keyStoreType: String?): KeyStore {
    return KeyStore.getInstance(keyStoreType ?: KeyStore.getDefaultType()).apply {
      val inputStream: InputStream? = null // By convention, 'null' creates an empty key store.
      load(inputStream, password)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy