HostNameVerifier не вызывается для сайтов с подстановочным знаком или сертификатом SAN - PullRequest
0 голосов
/ 05 октября 2018

В нашем приложении мы делаем HTTP-вызов для аутентификации через HTTPS.Я должен убедиться, что мы делаем все необходимые проверки, чтобы убедиться, что соединение безопасно.В качестве части этого я должен реализовать следующее:

  1. Убедитесь, что сертификат сервера аутентификации выпущен известным CA.
  2. Убедитесь, что имя хоста, присутствующее в сертификате сервера аутентификации, совпадаетимя хоста, которое мы используем для подключения к серверу авторизации.

У меня нет проблем с пунктом 1.

Для пункта 2 я пытаюсь использовать HostNameVerifier реализация.

Мой код на данный момент:

package com.company;

import sun.security.x509.X500Name;

import javax.net.ssl.*;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Main {

    public static void main(String[] args) throws Exception {

        URL endpoint = new URL("https://example.com");
        HttpsURLConnection conn = (HttpsURLConnection) endpoint.openConnection();
        conn.setHostnameVerifier(new MyHostNameVerifier());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[] {trustAll}, null);
        conn.setSSLSocketFactory(sslContext.getSocketFactory());

        System.out.println("HTTP Response: " + conn.getResponseCode());
    }

    public static final X509TrustManager trustAll = new X509TrustManager() {

        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates,
                                       String s) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates,
                                       String s) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    };

    public static class MyHostNameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostName, SSLSession sslSession) {
            System.out.println("*** Validating host name for " + hostName);
            return false;
        }
    }
}

Я ожидал, что MyHostNameVerifier#verify всегда будет вызываться, и я могу сделать определенные проверки там.

Однако я заметил, что метод HostNameVerifier#verify вызывается только в том случае, если я использовал IP-адрес сайта или только если имя хоста не совпадает с темой сертификата или каким-либо из альтернативных имен субъекта.

HostNameVerifier#verify не вызывается в следующих случаях:

  1. Если сертификат сайта является подстановочным сертификатом и соответствует используемому имени хоста.
  2. Если сертификат сайта является сертификатом SANа если имя хостаЯ использую либо CN субъекта, либо указан как одно из значений альтернативного имени субъекта.

Например: в приведенном выше коде я пытаюсь подключиться к «example.com».
SSL-сертификат «example.com» выдается CN «www.example.org».
Однако «example.com» указан в «Subject Alternate Names» (SAN) сертификата.

Если я вместо этого использую IP-адрес «example.com», то вызывается мой верификатор имени хоста.

URL endpoint = new URL("https://93.184.216.34/");

Может ли кто-нибудь подтвердить мне, что Java внутренне обрабатывает сертификаты подстановочных знаков и проверки сертификатов SAN?Если да, тогда мне, возможно, не придется вносить какие-либо дополнительные изменения кода.

1 Ответ

0 голосов
/ 08 октября 2018

Я мог бы немного выйти за границы, цитируя документацию по Java , но это наш самый чистый источник.

Во время установления связи, если имя хоста URL-адреса и идентификационное имя хоста сервера не совпадают, механизм проверки может перезвонить разработчикам этого интерфейса, чтобы определить, следует ли разрешить это соединение.

Этиобратные вызовы используются при сбое правил по умолчанию для проверки имени хоста URL.

Что в основном подтверждает ваше наблюдение о том, что, как только вы введете недействительный сертификат, он будет и только тогда вызывать функцию, чтобы увидеть, если вы все еще хотитечтобы позволить это.С помощью вашего собственного теста на то, что правильный подстановочный сертификат не вызывал функцию, мы можем сказать, что он определенно подтвердил его действительность и не нуждается в вашей помощи с ним.То же самое и с сертификатом SAN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...