diff -rNU 30 ../mod_nss-1.0.8-o/nss_engine_kernel.c ./nss_engine_kernel.c --- ../mod_nss-1.0.8-o/nss_engine_kernel.c 2014-06-25 19:13:26.000000000 +0200 +++ ./nss_engine_kernel.c 2014-06-27 13:57:40.000000000 +0200 @@ -1,102 +1,151 @@ /* Copyright 2001-2004 The Apache Software Foundation * * 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. */ #include "mod_nss.h" #include "secerr.h" static void HandshakeDone(PRFileDesc *fd, void *doneflag); +extern void * sni_callback_arg; + /* * Post Read Request Handler */ int nss_hook_ReadReq(request_rec *r) { SSLConnRec *sslconn = myConnConfig(r->connection); PRFileDesc *ssl = sslconn ? sslconn->ssl : NULL; if (!sslconn) { return DECLINED; } if (sslconn->non_nss_request) { const char *errmsg; char *thisurl; char *thisport = ""; int port = ap_get_server_port(r); if (!ap_is_default_port(port, r)) { thisport = apr_psprintf(r->pool, ":%u", port); } thisurl = ap_escape_html(r->pool, apr_psprintf(r->pool, "https://%s%s/", ap_get_server_name(r), thisport)); errmsg = apr_psprintf(r->pool, "Reason: You're speaking plain HTTP " "to an SSL-enabled server port.
\n" "Instead use the HTTPS scheme to access " "this URL, please.
\n" "
Hint: " "%s
", thisurl, thisurl); apr_table_setn(r->notes, "error-notes", errmsg); /* Now that we have caught this error, forget it. we are done * with using SSL on this request. */ sslconn->non_nss_request = 0; return HTTP_BAD_REQUEST; } /* Get the SSL connection structure and perform the * delayed interlinking from SSL back to request_rec */ if (!ssl) { return DECLINED; } + + /* + * SNI. + * + * global pool-allocated char * sni_callback_arg contains SNI name + * coming from mod_nss_SSLSNISocketConfig() callback by nss as soon as + * SNI extension information was supplied by the client. + * + * With the SNI provided servername, this is now widely analogous + * to mod_ssl; the same checks apply. + * + */ + + + + char *servername; + servername = (char *) sni_callback_arg; + + if(servername[0] != '\0') { + char *host, *scope_id; + apr_port_t port; + apr_status_t rv; + + if (!r->hostname) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Hostname %s provided via SNI, but no hostname" + " provided in HTTP request", servername); + return HTTP_BAD_REQUEST; + } + + rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool); + if (rv != APR_SUCCESS || scope_id) { + return HTTP_BAD_REQUEST; + } + + if (strcasecmp(host, servername)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "Hostname %s provided via SNI and hostname %s provided" + " via HTTP are different", servername, host); + return HTTP_BAD_REQUEST; + } + + + } + + + /* * Log information about incoming HTTPS requests */ if (r->server->loglevel >= APLOG_INFO && ap_is_initial_req(r)) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "%s HTTPS request received for child %ld (server %s)", (r->connection->keepalives <= 0 ? "Initial (No.1)" : apr_psprintf(r->pool, "Subsequent (No.%d)", r->connection->keepalives+1)), r->connection->id, nss_util_vhostid(r->pool, r->server)); } if (sslconn->client_cert != NULL) CERT_DestroyCertificate(sslconn->client_cert); sslconn->client_cert = SSL_PeerCertificate(ssl); sslconn->client_dn = NULL; return DECLINED; } /* * Access Handler */ int nss_hook_Access(request_rec *r) { SSLDirConfigRec *dc = myDirConfig(r); SSLSrvConfigRec *sc = mySrvConfig(r->server); SSLConnRec *sslconn = myConnConfig(r->connection);