Accepting request 288636 from home:kstreitova:branches:Apache:Modules
- add mod_nss-SNI_support.patch that brings Server Name Indication support that allows to have multiple HTTPS websites with multiple certificates on the same IP address and port. [fate#318331], [bnc#897712] OBS-URL: https://build.opensuse.org/request/show/288636 OBS-URL: https://build.opensuse.org/package/show/Apache:Modules/apache2-mod_nss?expand=0&rev=4
This commit is contained in:
parent
23f3b41e70
commit
ae21fd63fe
@ -1,3 +1,11 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Mar 3 10:25:27 UTC 2015 - kstreitova@suse.com
|
||||
|
||||
- add mod_nss-SNI_support.patch that brings Server Name Indication
|
||||
support that allows to have multiple HTTPS websites with multiple
|
||||
certificates on the same IP address and port.
|
||||
[fate#318331], [bnc#897712]
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Nov 4 14:13:46 UTC 2014 - kstreitova@suse.com
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package apache2-mod_nss
|
||||
#
|
||||
# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@ -74,6 +74,8 @@ Patch23: mod_nss-bnc863518-reopen_dev_tty.diff
|
||||
Patch24: mod_nss-compare_subject_CN_and_VS_hostname.patch
|
||||
# PATCH-FIX-UPSTREAM bnc#902068 kstreitova@suse.com -- small fixes for TLS-v1.2
|
||||
Patch25: mod_nss-add_support_for_enabling_TLS_v1.2.patch
|
||||
# PATCH-FEATURE-UPSTREAM bnc#897712 fate#318331 kstreitova@suse.com -- add Server Name Indication support
|
||||
Patch26: mod_nss-SNI_support.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
%define apxs /usr/sbin/apxs2
|
||||
@ -115,6 +117,7 @@ security library.
|
||||
%patch23 -p0 -b .mod_nss-bnc863518-reopen_dev_tty.rpmpatch
|
||||
%patch24 -p1 -b .mod_nss-compare_subject_CN_and_VS_hostname.rpmpatch
|
||||
%patch25 -p1 -b .mod_nss-add_support_for_enabling_TLS_v1.2.rpmpatch
|
||||
%patch26 -p1 -b .mod_nss-SNI_support.rpmpatch
|
||||
|
||||
# keep this last, otherwise we get fuzzyness from above
|
||||
%if 0%{?suse_version} >= 1300
|
||||
|
397
mod_nss-SNI_support.patch
Normal file
397
mod_nss-SNI_support.patch
Normal file
@ -0,0 +1,397 @@
|
||||
From 07405e4dbd1e2df6583bb571a6230da78788c19b Mon Sep 17 00:00:00 2001
|
||||
From: standa <stokos@suse.de>
|
||||
Date: Thu, 26 Feb 2015 15:23:50 +0100
|
||||
Subject: [PATCH] SNI check with NameVirtualHosts
|
||||
|
||||
---
|
||||
docs/mod_nss.html | 10 ++++++
|
||||
mod_nss.c | 3 ++
|
||||
mod_nss.h | 18 ++++++++++
|
||||
nss_engine_config.c | 11 +++++++
|
||||
nss_engine_init.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
nss_engine_kernel.c | 51 ++++++++++++++++++++++++++++
|
||||
nss_util.c | 19 +++++++++++
|
||||
7 files changed, 199 insertions(+), 8 deletions(-)
|
||||
|
||||
Index: mod_nss-1.0.8/docs/mod_nss.html
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/docs/mod_nss.html
|
||||
+++ mod_nss-1.0.8/docs/mod_nss.html
|
||||
@@ -1079,6 +1079,16 @@ components of the client certificate, th
|
||||
<br>
|
||||
<code>NSSRequire<br>
|
||||
</code><br>
|
||||
+<big><big>NSSSNI</big></big><br>
|
||||
+<br>
|
||||
+Enables or disables Server Name Identification(SNI) extension check for
|
||||
+SSL. This option is turn on by default. SNI vhost_id gets from HTTPS header.
|
||||
+<br>
|
||||
+<br>
|
||||
+<span style="font-weight: bold;">Example</span><br>
|
||||
+<br>
|
||||
+<code>NSSSNI off</code><br>
|
||||
+<br>
|
||||
<big><big>NSSProxyEngine</big></big><br>
|
||||
<br>
|
||||
Enables or disables mod_nss HTTPS support for mod_proxy.<br>
|
||||
Index: mod_nss-1.0.8/mod_nss.c
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/mod_nss.c
|
||||
+++ mod_nss-1.0.8/mod_nss.c
|
||||
@@ -85,6 +85,9 @@ static const command_rec nss_config_cmds
|
||||
SSL_CMD_SRV(FIPS, FLAG,
|
||||
"FIPS 140-1 mode "
|
||||
"(`on', `off')")
|
||||
+ SSL_CMD_SRV(SNI, FLAG,
|
||||
+ "SNI"
|
||||
+ "(`on', `off')")
|
||||
SSL_CMD_ALL(CipherSuite, TAKE1,
|
||||
"Comma-delimited list of permitted SSL Ciphers, + to enable, - to disable "
|
||||
"(`[+-]XXX,...,[+-]XXX' - see manual)")
|
||||
Index: mod_nss-1.0.8/mod_nss.h
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/mod_nss.h
|
||||
+++ mod_nss-1.0.8/mod_nss.h
|
||||
@@ -308,6 +308,7 @@ struct SSLSrvConfigRec {
|
||||
const char *ocsp_name;
|
||||
BOOL ocsp;
|
||||
BOOL enabled;
|
||||
+ BOOL sni;
|
||||
BOOL proxy_enabled;
|
||||
const char *vhost_id;
|
||||
int vhost_id_len;
|
||||
@@ -343,6 +344,20 @@ typedef struct
|
||||
PRInt32 version; /* protocol version valid for this cipher */
|
||||
} cipher_properties;
|
||||
|
||||
+typedef struct {
|
||||
+ const char *vhost_id[70];
|
||||
+ const char *nick[30];
|
||||
+} vhostNick[500];
|
||||
+
|
||||
+typedef struct {
|
||||
+ enum {
|
||||
+ PW_NONE = 0,
|
||||
+ PW_FROMFILE = 1,
|
||||
+ PW_PLAINTEXT = 2,
|
||||
+ PW_EXTERNAL = 3
|
||||
+ } source;
|
||||
+ char *data;
|
||||
+} secuPWData;
|
||||
/* Compatibility between Apache 2.0.x and 2.2.x. The numeric version of
|
||||
* the version first appeared in Apache 2.0.56-dev. I picked 2.0.55 as it
|
||||
* is the last version without this define. This is used for more than just
|
||||
@@ -384,6 +399,7 @@ void *nss_config_perdir_merge(apr_pool_t
|
||||
void *nss_config_server_create(apr_pool_t *p, server_rec *s);
|
||||
void *nss_config_server_merge(apr_pool_t *p, void *basev, void *addv);
|
||||
const char *nss_cmd_NSSFIPS(cmd_parms *, void *, int);
|
||||
+const char *nss_cmd_NSSSNI(cmd_parms *, void *, int);
|
||||
const char *nss_cmd_NSSEngine(cmd_parms *, void *, int);
|
||||
const char *nss_cmd_NSSOCSP(cmd_parms *, void *, int);
|
||||
const char *nss_cmd_NSSOCSPDefaultResponder(cmd_parms *, void *, int);
|
||||
@@ -471,6 +487,8 @@ apr_file_t *nss_util_ppopen(server_rec
|
||||
void nss_util_ppclose(server_rec *, apr_pool_t *, apr_file_t *);
|
||||
char *nss_util_readfilter(server_rec *, apr_pool_t *, const char *,
|
||||
const char * const *);
|
||||
+char *getSECItemData(char *data, int len);
|
||||
+char *getSplitURL(char *url);
|
||||
/* ssl_io_buffer_fill fills the setaside buffering of the HTTP request
|
||||
* to allow an SSL renegotiation to take place. */
|
||||
int nss_io_buffer_fill(request_rec *r);
|
||||
Index: mod_nss-1.0.8/nss_engine_config.c
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/nss_engine_config.c
|
||||
+++ mod_nss-1.0.8/nss_engine_config.c
|
||||
@@ -135,6 +135,7 @@ static SSLSrvConfigRec *nss_config_serve
|
||||
sc->ocsp_name = NULL;
|
||||
sc->fips = UNSET;
|
||||
sc->enabled = UNSET;
|
||||
+ sc->sni = TRUE;
|
||||
sc->proxy_enabled = UNSET;
|
||||
sc->vhost_id = NULL; /* set during module init */
|
||||
sc->vhost_id_len = 0; /* set during module init */
|
||||
@@ -214,6 +215,7 @@ void *nss_config_server_merge(apr_pool_t
|
||||
cfgMerge(ocsp_name, NULL);
|
||||
cfgMergeBool(fips);
|
||||
cfgMergeBool(enabled);
|
||||
+ cfgMergeBool(sni);
|
||||
cfgMergeBool(proxy_enabled);
|
||||
cfgMergeBool(proxy_ssl_check_peer_cn);
|
||||
|
||||
@@ -320,6 +322,15 @@ const char *nss_cmd_NSSFIPS(cmd_parms *c
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
+const char *nss_cmd_NSSSNI(cmd_parms *cmd, void *dcfg, int flag)
|
||||
+{
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
||||
+
|
||||
+ sc->sni = flag ? TRUE : FALSE;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
|
||||
const char *nss_cmd_NSSOCSP(cmd_parms *cmd, void *dcfg, int flag)
|
||||
{
|
||||
Index: mod_nss-1.0.8/nss_engine_init.c
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/nss_engine_init.c
|
||||
+++ mod_nss-1.0.8/nss_engine_init.c
|
||||
@@ -28,12 +28,17 @@ static SECStatus ownHandshakeCallback(PR
|
||||
static SECStatus NSSHandshakeCallback(PRFileDesc *socket, void *arg);
|
||||
static CERTCertificate* FindServerCertFromNickname(const char* name, const CERTCertList* clist);
|
||||
SECStatus nss_AuthCertificate(void *arg, PRFileDesc *socket, PRBool checksig, PRBool isServer);
|
||||
+PRInt32 ownSSLSNISocketConfig(PRFileDesc *fd, const SECItem *sniNameArr,
|
||||
+ PRUint32 sniNameArrSize, void *arg);
|
||||
|
||||
/*
|
||||
* Global variables defined in this file.
|
||||
*/
|
||||
char* INTERNAL_TOKEN_NAME = "internal ";
|
||||
|
||||
+vhostNick vhostNickSNI;
|
||||
+int vhostNickSize = 0;
|
||||
+
|
||||
cipher_properties ciphers_def[ciphernum] =
|
||||
{
|
||||
/* SSL2 cipher suites */
|
||||
@@ -382,6 +387,11 @@ int nss_init_Module(apr_pool_t *p, apr_p
|
||||
sc->vhost_id = nss_util_vhostid(p, s);
|
||||
sc->vhost_id_len = strlen(sc->vhost_id);
|
||||
|
||||
+ if (sc->server->nickname != NULL && sc->vhost_id != NULL) {
|
||||
+ strcpy(vhostNickSNI[vhostNickSize].vhost_id, sc->vhost_id);
|
||||
+ strcpy(vhostNickSNI[vhostNickSize].nick, sc->server->nickname);
|
||||
+ vhostNickSize++;
|
||||
+ }
|
||||
/* Fix up stuff that may not have been set */
|
||||
if (sc->fips == UNSET) {
|
||||
sc->fips = FALSE;
|
||||
@@ -534,7 +544,7 @@ int nss_init_Module(apr_pool_t *p, apr_p
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
|
||||
"Init: Initializing (virtual) servers for SSL");
|
||||
|
||||
- CERTCertList* clist = PK11_ListCerts(PK11CertListUser, NULL);
|
||||
+ CERTCertList* clist = PK11_ListCerts(PK11CertListUserUnique, NULL);
|
||||
|
||||
for (s = base_server; s; s = s->next) {
|
||||
sc = mySrvConfig(s);
|
||||
@@ -547,7 +557,7 @@ int nss_init_Module(apr_pool_t *p, apr_p
|
||||
/*
|
||||
* Read the server certificate and key
|
||||
*/
|
||||
- nss_init_ConfigureServer(s, p, ptemp, sc, clist);
|
||||
+ nss_init_ConfigureServer(s, p, ptemp, sc, clist);
|
||||
}
|
||||
|
||||
if (clist) {
|
||||
@@ -1233,13 +1243,21 @@ static void nss_init_certificate(server_
|
||||
break;
|
||||
}
|
||||
|
||||
- secstatus = SSL_ConfigSecureServer(model, *servercert, *serverkey, *KEAtype);
|
||||
+ secstatus = SSL_ConfigSecureServer(model, *servercert, *serverkey, *KEAtype);
|
||||
if (secstatus != SECSuccess) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
|
||||
"SSL error configuring server: '%s'", nickname);
|
||||
nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
|
||||
nss_die();
|
||||
- }
|
||||
+ }
|
||||
+
|
||||
+ /* SNI */
|
||||
+ if (SSL_SNISocketConfigHook(model, (SSLSNISocketConfig) ownSSLSNISocketConfig, (void*) s) != SECSuccess) {
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
|
||||
+ "SSL_SNISocketConfigHook failed");
|
||||
+ nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
|
||||
+ nss_die();
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -1308,6 +1326,7 @@ static void nss_init_server_certs(server
|
||||
nss_log_nss_error(APLOG_MARK, APLOG_ERR, s);
|
||||
nss_die();
|
||||
}
|
||||
+
|
||||
}
|
||||
|
||||
static void nss_init_proxy_ctx(server_rec *s,
|
||||
@@ -1374,7 +1393,6 @@ void nss_init_Child(apr_pool_t *p, serve
|
||||
/* If any servers have SSL, we want sslenabled set so we
|
||||
* can perform further initialization
|
||||
*/
|
||||
-
|
||||
if (sc->enabled == UNSET) {
|
||||
sc->enabled = FALSE;
|
||||
}
|
||||
@@ -1404,11 +1422,12 @@ void nss_init_Child(apr_pool_t *p, serve
|
||||
nss_init_SSLLibrary(base_server);
|
||||
|
||||
/* Configure all virtual servers */
|
||||
- CERTCertList* clist = PK11_ListCerts(PK11CertListUser, NULL);
|
||||
+ CERTCertList* clist = PK11_ListCerts(PK11CertListUserUnique, NULL);
|
||||
for (s = base_server; s; s = s->next) {
|
||||
sc = mySrvConfig(s);
|
||||
- if (sc->server->servercert == NULL && NSS_IsInitialized())
|
||||
- nss_init_ConfigureServer(s, p, mc->ptemp, sc, clist);
|
||||
+ if (sc->server->servercert == NULL && NSS_IsInitialized()) {
|
||||
+ nss_init_ConfigureServer(s, p, mc->ptemp, sc, clist);
|
||||
+ }
|
||||
}
|
||||
if (clist) {
|
||||
CERT_DestroyCertList(clist);
|
||||
@@ -1741,3 +1760,63 @@ int nss_parse_ciphers(server_rec *s, cha
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+PRInt32 ownSSLSNISocketConfig(PRFileDesc *fd, const SECItem *sniNameArr,
|
||||
+ PRUint32 sniNameArrSize, void *arg)
|
||||
+{
|
||||
+ server_rec *s = (server_rec *)arg;
|
||||
+
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
|
||||
+ "start function ownSSLSNISocketConfig for SNI");
|
||||
+
|
||||
+ secuPWData *pwdata;
|
||||
+ CERTCertificate * cert = NULL;
|
||||
+ SECKEYPrivateKey * privKey = NULL;
|
||||
+ char *nickName = NULL;
|
||||
+ char *vhost = NULL;
|
||||
+ int i;
|
||||
+
|
||||
+ PORT_Assert(fd && sniNameArr);
|
||||
+ if (!fd || !sniNameArr) {
|
||||
+ return SSL_SNI_SEND_ALERT;
|
||||
+ }
|
||||
+ vhost = getSECItemData((char *) sniNameArr->data, sniNameArr->len);
|
||||
+
|
||||
+ for(i = 0; i<vhostNickSize; i++) {
|
||||
+ if (strcmp(getSplitURL(vhostNickSNI[i].vhost_id), vhost) == 0) {
|
||||
+ nickName = vhostNickSNI[i].nick;
|
||||
+ pwdata = SSL_RevealPinArg(fd);
|
||||
+
|
||||
+ /* if pwdata is NULL, then we would not get the key and
|
||||
+ * return an error status. */
|
||||
+ cert = PK11_FindCertFromNickname(nickName, &pwdata);
|
||||
+ if (cert == NULL) {
|
||||
+ goto loser; /* Send alert */
|
||||
+ }
|
||||
+ privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
|
||||
+ if (privKey == NULL) {
|
||||
+ goto loser; /* Send alert */
|
||||
+ }
|
||||
+ SSLKEAType certKEA = NSS_FindCertKEAType(cert);
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
|
||||
+ "start configure vhost:%s", vhostNickSNI[i].vhost_id);
|
||||
+ if (SSL_ConfigSecureServer(fd, cert, privKey, certKEA) != SECSuccess) {
|
||||
+ goto loser; /* Send alert */
|
||||
+ }
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
|
||||
+ "successfull setting vhost with nick:%s", vhostNickSNI[i].nick);
|
||||
+ SECKEY_DestroyPrivateKey(privKey);
|
||||
+ CERT_DestroyCertificate(cert);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+loser:
|
||||
+ if (privKey) {
|
||||
+ SECKEY_DestroyPrivateKey(privKey);
|
||||
+ }
|
||||
+ if (cert) {
|
||||
+ CERT_DestroyCertificate(cert);
|
||||
+ }
|
||||
+ return SSL_SNI_SEND_ALERT;
|
||||
+
|
||||
+}
|
||||
Index: mod_nss-1.0.8/nss_engine_kernel.c
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/nss_engine_kernel.c
|
||||
+++ mod_nss-1.0.8/nss_engine_kernel.c
|
||||
@@ -71,6 +71,57 @@ int nss_hook_ReadReq(request_rec *r)
|
||||
}
|
||||
|
||||
/*
|
||||
+ * SNI check is default on. In same cases you switch of by NSSSNI off
|
||||
+ * sc->sni parameter gets vhost from HTTPS header
|
||||
+ */
|
||||
+ SSLSrvConfigRec *sc = mySrvConfig(r->server);
|
||||
+
|
||||
+ SECItem *hostInfo = NULL;
|
||||
+ hostInfo = SSL_GetNegotiatedHostInfo(ssl);
|
||||
+ if (hostInfo != NULL && sc->sni) {
|
||||
+ if (ap_is_initial_req(r) && (hostInfo->len != 0)) {
|
||||
+ char *servername = NULL;
|
||||
+ char *host, *scope_id;
|
||||
+ apr_port_t port;
|
||||
+ apr_status_t rv;
|
||||
+
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
|
||||
+ "SNI hostInfo hostInfo->data:%s and hostInfo->len:%d"
|
||||
+ , hostInfo->data, hostInfo->len);
|
||||
+
|
||||
+ servername = getSECItemData((char *) hostInfo->data, hostInfo->len);
|
||||
+
|
||||
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
|
||||
+ "SNI hostInfo servername:%s, lenght:%d"
|
||||
+ , servername, (unsigned)strlen(servername));
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ SECITEM_FreeItem(hostInfo, PR_TRUE);
|
||||
+ servername = NULL;
|
||||
+ return HTTP_BAD_REQUEST;
|
||||
+ } else {
|
||||
+ SECITEM_FreeItem(hostInfo, PR_TRUE);
|
||||
+ servername = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ /*
|
||||
* Log information about incoming HTTPS requests
|
||||
*/
|
||||
if (r->server->loglevel >= APLOG_INFO && ap_is_initial_req(r)) {
|
||||
Index: mod_nss-1.0.8/nss_util.c
|
||||
===================================================================
|
||||
--- mod_nss-1.0.8.orig/nss_util.c
|
||||
+++ mod_nss-1.0.8/nss_util.c
|
||||
@@ -100,3 +100,22 @@ char *nss_util_readfilter(server_rec *s,
|
||||
|
||||
return buf;
|
||||
}
|
||||
+
|
||||
+char *getSECItemData(char *data, int len) {
|
||||
+
|
||||
+ data[len]='\0';
|
||||
+
|
||||
+ return data;
|
||||
+}
|
||||
+
|
||||
+char *getSplitURL(char *url) {
|
||||
+
|
||||
+ int iter = 0;
|
||||
+
|
||||
+ while(url[iter] != '\0' && url[iter] != ':'){
|
||||
+ url[iter++];
|
||||
+ }
|
||||
+ url[iter]='\0';
|
||||
+
|
||||
+ return url;
|
||||
+}
|
Loading…
Reference in New Issue
Block a user