Hello! On Thu, Aug 14, 2025 at 06:52:02PM +0300, Maxim Dounin wrote:
> # HG changeset patch > # User Maxim Dounin <[email protected]> > # Date 1755133582 -10800 > # Thu Aug 14 04:06:22 2025 +0300 > # Node ID 870dfc16d381d90644b08159dd84d1ee391cf630 > # Parent 51d23ff6f109765f4c382d449d7ea0cea13ea220 > SSL: support for iPAddress subjectAltName in certificates. > > Known public services with iPAddress subject altnames include 1.1.1.1 > and 8.8.8.8. IP address certificates from Let's Encrypt are expected > to be available soon: > > https://letsencrypt.org/2025/07/01/issuing-our-first-ip-address-certificate > > diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c > +++ b/src/event/ngx_event_openssl.c > @@ -4901,19 +4901,63 @@ ngx_ssl_cleanup_ctx(void *data) > ngx_int_t > ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name) > { > - X509 *cert; > + X509 *cert; > + u_char *addr, addr6[16]; > + size_t alen; > + in_addr_t addr4; > > cert = SSL_get_peer_certificate(c->ssl->connection); > if (cert == NULL) { > return NGX_ERROR; > } > > + if (name->len == 0) { > + goto failed; > + } > + > + addr4 = ngx_inet_addr(name->data, name->len); > + > + if (addr4 != INADDR_NONE) { > + addr = (u_char *) &addr4; > + alen = 4; > + > +#if (NGX_HAVE_INET6) > + } else if (name->data[0] == '[') { > + > + if (name->data[name->len - 1] != ']') { > + goto failed; > + } > + > + if (ngx_inet6_addr(name->data + 1, name->len - 2, &addr6[0]) > + != NGX_OK) > + { > + goto failed; > + } > + > + addr = &addr6[0]; > + alen = 16; > + > +#endif > + } else { > + addr = NULL; > + alen = 0; > + } > + > + > #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT > > /* X509_check_host() is only available in OpenSSL 1.0.2+ */ > > - if (name->len == 0) { > - goto failed; > + if (addr) { > + if (X509_check_ip(cert, addr, alen, 0) != 1) { > + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, > + "X509_check_ip(): no match"); > + goto failed; > + } > + > + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, > + "X509_check_ip(): match"); > + goto found; > } > > if (X509_check_host(cert, (char *) name->data, name->len, 0, NULL) != 1) > { > @@ -4924,12 +4968,13 @@ ngx_ssl_check_host(ngx_connection_t *c, > > ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, > "X509_check_host(): match"); > - > goto found; > > #else > { > int n, i; > + size_t dlen; > + u_char *data; > X509_NAME *sname; > ASN1_STRING *str; > X509_NAME_ENTRY *entry; > @@ -4949,22 +4994,63 @@ ngx_ssl_check_host(ngx_connection_t *c, > for (i = 0; i < n; i++) { > altname = sk_GENERAL_NAME_value(altnames, i); > > - if (altname->type != GEN_DNS) { > - continue; > - } > - > - str = altname->d.dNSName; > - > - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, > - "SSL subjectAltName: \"%*s\"", > - (size_t) ASN1_STRING_length(str), > - ASN1_STRING_data(str)); > - > - if (ngx_ssl_check_name(name, str) == NGX_OK) { > - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, > - "SSL subjectAltName: match"); > - GENERAL_NAMES_free(altnames); > - goto found; > + if (altname->type == GEN_IPADD) { > + > + str = altname->d.iPAddress; > + data = ASN1_STRING_data(str); > + dlen = ASN1_STRING_length(str); > + > +#if (NGX_DEBUG) > + { > + size_t al; > + u_char at[NGX_INET6_ADDRSTRLEN]; > + > + if (dlen == 4) { > + al = ngx_inet_ntop(AF_INET, data, at, > + NGX_INET6_ADDRSTRLEN); > + > +#if (NGX_HAVE_INET6) > + } else if (dlen == 16) { > + al = ngx_inet_ntop(AF_INET6, data, at, > + NGX_INET6_ADDRSTRLEN); > + > +#endif > + } else { > + al = ngx_cpymem(at, "<invalid>", sizeof("<invalid>") - 1) > + - at; > + } > + > + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, > + "SSL subjectAltName: %*s", > + al, at); > + } > +#endif > + > + if (addr > + && alen == dlen > + && ngx_memcmp(addr, data, dlen) == 0) > + { > + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, > + "SSL subjectAltName: match"); > + GENERAL_NAMES_free(altnames); > + goto found; > + } > + > + } else if (altname->type == GEN_DNS) { > + > + str = altname->d.dNSName; > + > + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, > + "SSL subjectAltName: \"%*s\"", > + (size_t) ASN1_STRING_length(str), > + ASN1_STRING_data(str)); > + > + if (ngx_ssl_check_name(name, str) == NGX_OK) { > + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, > + "SSL subjectAltName: match"); > + GENERAL_NAMES_free(altnames); > + goto found; > + } > } > } > > Amended with the following patch, to provide more natural order of altname->type handling: diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -4994,7 +4994,23 @@ ngx_ssl_check_host(ngx_connection_t *c, for (i = 0; i < n; i++) { altname = sk_GENERAL_NAME_value(altnames, i); - if (altname->type == GEN_IPADD) { + if (altname->type == GEN_DNS) { + + str = altname->d.dNSName; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL subjectAltName: \"%*s\"", + (size_t) ASN1_STRING_length(str), + ASN1_STRING_data(str)); + + if (ngx_ssl_check_name(name, str) == NGX_OK) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL subjectAltName: match"); + GENERAL_NAMES_free(altnames); + goto found; + } + + } else if (altname->type == GEN_IPADD) { str = altname->d.iPAddress; data = ASN1_STRING_data(str); @@ -5035,22 +5051,6 @@ ngx_ssl_check_host(ngx_connection_t *c, GENERAL_NAMES_free(altnames); goto found; } - - } else if (altname->type == GEN_DNS) { - - str = altname->d.dNSName; - - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL subjectAltName: \"%*s\"", - (size_t) ASN1_STRING_length(str), - ASN1_STRING_data(str)); - - if (ngx_ssl_check_name(name, str) == NGX_OK) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL subjectAltName: match"); - GENERAL_NAMES_free(altnames); - goto found; - } } } -- Maxim Dounin http://mdounin.ru/
