diff --git a/apache2-mod_nss.changes b/apache2-mod_nss.changes index 5d1bd0f..d321d44 100644 --- a/apache2-mod_nss.changes +++ b/apache2-mod_nss.changes @@ -1,3 +1,25 @@ +------------------------------------------------------------------- +Thu Jul 24 12:49:29 CEST 2014 - draht@suse.de + +- mod_nss-bnc863518-reopen_dev_tty.diff: close(0) and + open("/dev/tty", ...) to make sure that stdin can be read from. + startproc may inherit wrongly opened file descriptors to httpd. + (Note: An analogous fix exists in startproc(8), too.) + [bnc#863518] +- VirtualHost part in /etc/apache2/conf.d/mod_nss.conf is now + externalized to /etc/apache2/conf.d/vhost-nss.template and not + activated/read by default. [bnc#878681] +- NSSCipherSuite update following additional ciphers of Feb 18 + change. [bnc#878681] + +------------------------------------------------------------------- +Fri Jun 27 16:13:01 CEST 2014 - draht@suse.de + +- mod_nss-SNI-callback.patch, mod_nss-SNI-checks.patch: + server side SNI was not implemented when mod_nss was made; + patches implement SNI with checks if SNI provided hostname + equals Host: field in http request header. + ------------------------------------------------------------------- Tue Feb 18 16:31:45 CET 2014 - draht@suse.de diff --git a/apache2-mod_nss.spec b/apache2-mod_nss.spec index d5504a2..adfb60a 100644 --- a/apache2-mod_nss.spec +++ b/apache2-mod_nss.spec @@ -21,13 +21,14 @@ Summary: SSL/TLS module for the Apache HTTP server License: Apache-2.0 Group: Productivity/Networking/Web/Servers Version: 1.0.8 -Release: 0.4. +Release: 0.4.8 Url: http://directory.fedoraproject.org/wiki/Mod_nss Source: http://directory.fedoraproject.org/sources/mod_nss-%{version}.tar.gz Source1: mod_nss.conf.in Source2: listen_nss.conf Source3: mod_nss_migrate.pl Source4: README-SUSE.txt +Source5: vhost-nss.template Provides: mod_nss Requires: apache2 >= 2.2.12 Requires: findutils @@ -68,6 +69,9 @@ Patch17: mod_nss-overlapping_memcpy.patch Patch18: mod_nss-CVE-2013-4566-NSSVerifyClient.diff Patch19: mod_nss-cipherlist_update_for_tls12.diff Patch20: mod_nss-cipherlist_update_for_tls12-doc.diff +Patch21: mod_nss-SNI-callback.patch +Patch22: mod_nss-SNI-checks.patch +Patch23: mod_nss-bnc863518-reopen_dev_tty.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build %define apxs /usr/sbin/apxs2 %define apache apache2 @@ -86,7 +90,7 @@ security library. %prep %setup -q -n mod_nss-%{version} -#%patch1 -p1 -b .conf.rpmpatch +##%patch1 -p1 -b .conf.rpmpatch %patch2 -p1 -b .gencert.rpmpatch %patch3 -p1 -b .wouldblock.rpmpatch %patch4 -p1 -b .negotiate.rpmpatch @@ -105,6 +109,9 @@ security library. %patch18 -p0 -b .CVE-2013-4566.rpmpatch %patch19 -p0 -b .ciphers.rpmpatch %patch20 -p0 -b .ciphers.doc.rpmpatch +%patch21 -p0 -b .mod_nss-SNI-callback.rpmpatch +%patch22 -p0 -b .mod_nss-SNI-checks.patch.rpmpatch +%patch23 -p0 -b .mod_nss-bnc863518-reopen_dev_tty.rpmpatch # keep this last, otherwise we get fuzzyness from above %if 0%{?suse_version} >= 1300 @@ -146,6 +153,7 @@ make %{?_smp_mflags} all # the build root. mkdir -p $RPM_BUILD_ROOT/%{apache_libexecdir} mkdir -p $RPM_BUILD_ROOT%{apache_sysconfdir}/conf.d +mkdir -p $RPM_BUILD_ROOT%{apache_sysconfdir}/vhosts.d mkdir -p $RPM_BUILD_ROOT%{_sbindir} mkdir -p $RPM_BUILD_ROOT%{apache_sysconf_nssdir} @@ -154,6 +162,7 @@ perl -pi -e "s|\@apache_lib\@|%{_libdir}\/apache2|g" nss.conf %endif install -m 644 nss.conf $RPM_BUILD_ROOT%{apache_sysconfdir}/conf.d/mod_nss.conf +install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{apache_sysconfdir}/vhosts.d/vhost-nss.template install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{apache_sysconfdir}/listen_nss.conf install -m 755 .libs/libmodnss.so $RPM_BUILD_ROOT%{apache_libexecdir}/mod_nss.so install -m 755 nss_pcache $RPM_BUILD_ROOT%{_sbindir}/ @@ -219,6 +228,7 @@ fi %defattr(-,root,root,-) %doc README LICENSE docs/mod_nss.html README-SUSE.txt %config(noreplace) %{apache_sysconfdir}/conf.d/mod_nss.conf +%config(noreplace) %{apache_sysconfdir}/vhosts.d/vhost-nss.template %config(noreplace) %{apache_sysconfdir}/listen_nss.conf %dir %{apache_libexecdir} %{apache_libexecdir}/mod_nss.so diff --git a/mod_nss-SNI-callback.patch b/mod_nss-SNI-callback.patch new file mode 100644 index 0000000..e009906 --- /dev/null +++ b/mod_nss-SNI-callback.patch @@ -0,0 +1,241 @@ +diff -rNU 30 ../mod_nss-1.0.8-o/mod_nss.h ./mod_nss.h +--- ../mod_nss-1.0.8-o/mod_nss.h 2014-06-23 12:23:17.000000000 +0200 ++++ ./mod_nss.h 2014-06-25 15:43:14.000000000 +0200 +@@ -459,31 +459,37 @@ + APR_DECLARE_OPTIONAL_FN(int, nss_engine_disable, (conn_rec *)); + + /* I/O */ + PRFileDesc * nss_io_new_fd(); + int nss_io_layer_init(); + void nss_io_filter_init(conn_rec *c, PRFileDesc *ssl); + void nss_io_filter_register(apr_pool_t *p); + + /* Utility Functions */ + char *nss_util_vhostid(apr_pool_t *, server_rec *); + apr_file_t *nss_util_ppopen(server_rec *, apr_pool_t *, const char *, + const char * const *); + 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 *); + /* 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); + + int nss_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix); + + /* Pass Phrase Handling */ + SECStatus nss_Init_Tokens(server_rec *s); + + /* Logging */ + void nss_log_nss_error(const char *file, int line, int level, server_rec *s); + void nss_die(void); + + /* NSS callback */ + SECStatus nss_AuthCertificate(void *arg, PRFileDesc *socket, PRBool checksig, PRBool isServer); ++ ++ ++#define SNIMAXNAMELEN 100 ++PRInt32 mod_nss_SSLSNISocketConfig(PRFileDesc *, const SECItem *, PRUint32, void *); ++ ++ + #endif /* __MOD_NSS_H__ */ +diff -rNU 30 ../mod_nss-1.0.8-o/nss_engine_init.c ./nss_engine_init.c +--- ../mod_nss-1.0.8-o/nss_engine_init.c 2014-06-23 12:23:17.000000000 +0200 ++++ ./nss_engine_init.c 2014-06-25 18:33:19.000000000 +0200 +@@ -5,60 +5,62 @@ + * 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 "apr_thread_proc.h" + #include "ap_mpm.h" + #include "secmod.h" + #include "sslerr.h" + #include "pk11func.h" + #include "ocsp.h" + #include "keyhi.h" + #include "cert.h" + + static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket); + static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg); + 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); + + /* + * Global variables defined in this file. + */ ++void * sni_callback_arg; ++ + char* INTERNAL_TOKEN_NAME = "internal "; + + cipher_properties ciphers_def[ciphernum] = + { + /* SSL2 cipher suites */ + {"rc4", SSL_EN_RC4_128_WITH_MD5, 0, SSL2}, + {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, 0, SSL2}, + {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, 0, SSL2}, + {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, 0, SSL2}, + {"des", SSL_EN_DES_64_CBC_WITH_MD5, 0, SSL2}, + {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, 0, SSL2}, + /* SSL3/TLS cipher suites */ + {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, 0, SSL3 | TLS}, + {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, 0, SSL3 | TLS}, + {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, 0, SSL3 | TLS}, + {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA, 0, SSL3 | TLS}, + {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, 0, SSL3 | TLS}, + {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, 0, SSL3 | TLS}, + {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5, 0, SSL3 | TLS}, + {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA, 0, SSL3 | TLS}, + {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, 0, SSL3 | TLS}, + {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA, 0, SSL3 | TLS}, + {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, 1, SSL3 | TLS}, + {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, 1, SSL3 | TLS}, + {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA, 1, SSL3 | TLS}, + /* TLS 1.0: Exportable 56-bit Cipher Suites. */ + {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, 0, SSL3 | TLS}, + {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, 0, SSL3 | TLS}, + /* AES ciphers.*/ + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA, 0, SSL3 | TLS}, +@@ -850,60 +852,78 @@ + + static void nss_init_ctx_callbacks(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modnss_ctx_t *mctx) + { + if (SSL_AuthCertificateHook(mctx->model, nss_AuthCertificate, (void *)CERT_GetDefaultCertDB()) != SECSuccess) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "SSL_AuthCertificateHook failed."); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } + if (SSL_BadCertHook(mctx->model, (SSLBadCertHandler) ownBadCertHandler, NULL) != SECSuccess) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "SSL_BadCertHook failed"); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } + if (SSL_HandshakeCallback(mctx->model, (SSLHandshakeCallback) ownHandshakeCallback, NULL) != SECSuccess) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "SSL_HandshakeCallback failed"); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } + if (SSL_GetClientAuthDataHook(mctx->model, NSS_GetClientAuthData, (void *)mctx->nickname) != SECSuccess) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "SSL_GetClientAuthDataHook failed"); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } ++ ++ sni_callback_arg = apr_pcalloc(p, SNIMAXNAMELEN + 1); ++ if(sni_callback_arg) { ++ if(SSL_SNISocketConfigHook(mctx->model, mod_nss_SSLSNISocketConfig, ++ sni_callback_arg)) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "SSL_SNISocketConfigHook failed"); ++ nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); ++ nss_die(); ++ } ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "apr_palloc returned NULL for sni_callback_arg"); ++ nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); ++ nss_die(); ++ } ++ ++ + } + + static void nss_init_ctx_verify(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + modnss_ctx_t *mctx) + { + if (mctx->auth.verify_mode == SSL_CVERIFY_REQUIRE) { + SSL_OptionSet(mctx->model, SSL_REQUEST_CERTIFICATE, PR_TRUE); + SSL_OptionSet(mctx->model, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_ALWAYS); + } else if (mctx->auth.verify_mode == SSL_CVERIFY_OPTIONAL) { + SSL_OptionSet(mctx->model, SSL_REQUEST_CERTIFICATE, PR_TRUE); + SSL_OptionSet(mctx->model, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); + } else { + SSL_OptionSet(mctx->model, SSL_REQUEST_CERTIFICATE, PR_FALSE); + SSL_OptionSet(mctx->model, SSL_REQUIRE_CERTIFICATE, SSL_REQUIRE_NEVER); + } + } + + static int countciphers(PRBool cipher_state[ciphernum], int version) { + int ciphercount = 0; + int i; + + for (i = 0; i < ciphernum; i++) + { + if ((cipher_state[i] == PR_TRUE) && + (ciphers_def[i].version & version)) { + ciphercount++; + } + } +@@ -1702,30 +1722,54 @@ + return -1; + } + + if ((ciphers = strchr(cipher, ','))) { + *ciphers++ = '\0'; + } + + found = PR_FALSE; + + for (i = 0; i < ciphernum; i++) + { + if (!strcasecmp(cipher, ciphers_def[i].name)) { + cipher_list[i] = active; + found = PR_TRUE; + break; + } + } + + if (found == PR_FALSE) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unknown cipher %s", cipher); + } + + if (ciphers) { + cipher = ciphers; + } + } + + return 0; + } ++ ++ ++ ++ ++PRInt32 mod_nss_SSLSNISocketConfig(PRFileDesc *fd, const SECItem *sniNameArr, ++ PRUint32 sniNameArrSize, void *arg) ++{ ++ /* ++ arg is apr pool memory from apr_palloc(), SNIMAXNAMELEN+1 bytes long. ++ initialized zero. ++ */ ++ ++ char * retptr = NULL; ++ const SECItem *mysni = sniNameArr; ++ ++ if(mysni) { ++ retptr = apr_cpystrn(arg, mysni[0].data, ++ ( mysni[0].len + 1 < SNIMAXNAMELEN ) ? mysni[0].len + 1 : SNIMAXNAMELEN ); ++ return 0; ++ } else { ++ /* no SNI provided... Well. */ ++ return SSL_SNI_CURRENT_CONFIG_IS_USED; ++ } ++} diff --git a/mod_nss-SNI-checks.patch b/mod_nss-SNI-checks.patch new file mode 100644 index 0000000..d879292 --- /dev/null +++ b/mod_nss-SNI-checks.patch @@ -0,0 +1,155 @@ +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); diff --git a/mod_nss-bnc863518-reopen_dev_tty.diff b/mod_nss-bnc863518-reopen_dev_tty.diff new file mode 100644 index 0000000..8dad74b --- /dev/null +++ b/mod_nss-bnc863518-reopen_dev_tty.diff @@ -0,0 +1,223 @@ +diff -rNU 50 ../mod_nss-1.0.8-o/nss_engine_pphrase.c ./nss_engine_pphrase.c +--- ../mod_nss-1.0.8-o/nss_engine_pphrase.c 2014-07-24 12:23:30.000000000 +0200 ++++ ./nss_engine_pphrase.c 2014-07-24 13:54:23.000000000 +0200 +@@ -181,199 +181,218 @@ + * that may be done. + */ + static PRBool nss_check_password(unsigned char *cp) + { + int len; + unsigned char *end, ch; + + len = strlen((char *)cp); + if (len < 8) { + return PR_TRUE; + } + end = cp + len; + while (cp < end) { + ch = *cp++; + if (!((ch >= 'A') && (ch <= 'Z')) && + !((ch >= 'a') && (ch <= 'z'))) { + /* pass phrase has at least one non alphabetic in it */ + return PR_TRUE; + } + } + return PR_TRUE; + } + + /* + * Password callback so the user is not prompted to enter the password + * after the server starts. + */ + static char * nss_no_password(PK11SlotInfo *slot, PRBool retry, void *arg) + { + return NULL; + } + + /* + * Password callback to prompt the user for a password. This requires + * twiddling with the tty. Alternatively, if the file password.conf + * exists then it may be used to store the token password(s). + */ + static char *nss_get_password(FILE *input, FILE *output, + PK11SlotInfo *slot, + PRBool (*ok)(unsigned char *), + pphrase_arg_t *parg) + { + char *pwdstr = NULL; + char *token_name = NULL; + int tmp; + FILE *pwd_fileptr; + char *ptr; + char line[1024]; + unsigned char phrase[200]; + int infd = fileno(input); ++ int tmpfd; + int isTTY = isatty(infd); + + token_name = PK11_GetTokenName(slot); + + if (parg->mc->pphrase_dialog_type == SSL_PPTYPE_FILE || + parg->mc->pphrase_dialog_type == SSL_PPTYPE_DEFER) { + /* Try to get the passwords from the password file if it exists. + * THIS IS UNSAFE and is provided for convenience only. Without this + * capability the server would have to be started in foreground mode. + */ + if ((*parg->mc->pphrase_dialog_path != '\0') && + ((pwd_fileptr = fopen(parg->mc->pphrase_dialog_path, "r")) != NULL)) { + while(fgets(line, 1024, pwd_fileptr)) { + if (PL_strstr(line, token_name) == line) { + tmp = PL_strlen(line) - 1; + while((line[tmp] == ' ') || (line[tmp] == '\n')) + tmp--; + line[tmp+1] = '\0'; + ptr = PL_strchr(line, ':'); + if (ptr == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Malformed password entry for token %s. Format should be token:password", token_name); + continue; + } + for(tmp=1; ptr[tmp] == ' '; tmp++) {} + pwdstr = strdup(&(ptr[tmp])); + } + } + fclose(pwd_fileptr); + } else { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to open password file %s", parg->mc->pphrase_dialog_path); + nss_die(); + } + } + + /* For SSL_PPTYPE_DEFER we only want to authenticate passwords found + * in the password file. + */ + if ((parg->mc->pphrase_dialog_type == SSL_PPTYPE_DEFER) && + (pwdstr == NULL)) { + return NULL; + } + + /* This purposely comes after the file check because that is more + * authoritative. + */ + if (parg->mc->nInitCount > 1) { + char buf[1024]; + apr_status_t rv; + apr_size_t nBytes = 1024; + struct sembuf sb; + + /* lock the pipe */ + sb.sem_num = 0; + sb.sem_op = -1; + sb.sem_flg = SEM_UNDO; + if (semop(parg->mc->semid, &sb, 1) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to reserve semaphore resource"); + } + + snprintf(buf, 1024, "RETR\t%s", token_name); + rv = apr_file_write_full(parg->mc->proc.in, buf, strlen(buf), NULL); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to write to pin store for slot: %s APR err: %d", PK11_GetTokenName(slot), rv); + nss_die(); + } + + /* The helper just returns a token pw or "", so we don't have much + * to check for. + */ + memset(buf, 0, sizeof(buf)); + rv = apr_file_read(parg->mc->proc.out, buf, &nBytes); + sb.sem_op = 1; + if (semop(parg->mc->semid, &sb, 1) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to free semaphore resource"); + /* perror("semop free resource id"); */ + } + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Unable to read from pin store for slot: %s APR err: %d", PK11_GetTokenName(slot), rv); + nss_die(); + } + + /* Just return what we got. If we got this far and we don't have a + * PIN then I/O is already shut down, so we can't do anything really + * clever. + */ + pwdstr = strdup(buf); + } + + /* If we got a password we're done */ + if (pwdstr) + return pwdstr; +- ++ ++ /* It happens that stdin is not opened with O_RDONLY. Better make sure ++ * it is and re-open /dev/tty. ++ */ ++ close(infd); /* is 0 normally. open(2) will return first available. */ ++ tmpfd = open("/dev/tty", O_RDONLY); ++ if( tmpfd == -1) { ++ fprintf(output, "Cannot open /dev/tty for reading the passphrase.\n"); ++ nss_die(); ++ } ++ if(tmpfd != infd) { ++ if( dup2(tmpfd, infd) != infd) { ++ fprintf(output, "Problem duplicating /dev/tty file descriptor.\n"); ++ close(tmpfd); ++ nss_die(); ++ } ++ close(tmpfd); ++ } ++ + for (;;) { + /* Prompt for password */ + if (isTTY) { + if (parg->retryCount > 0) { + fprintf(output, "Password incorrect. Please try again.\n"); + } + fprintf(output, "%s", prompt); + echoOff(infd); + } + fgets((char*) phrase, sizeof(phrase), input); + if (isTTY) { + fprintf(output, "\n"); + echoOn(infd); + } + /* stomp on newline */ + phrase[strlen((char*)phrase)-1] = 0; + + /* Validate password */ + if (!(*ok)(phrase)) { + /* Not weird enough */ + if (!isTTY) return 0; + fprintf(output, "Password must be at least 8 characters long with one or more\n"); + fprintf(output, "non-alphabetic characters\n"); + continue; + } + if (PK11_IsFIPS() && strlen(phrase) == 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "The FIPS security policy requires that a password be set."); + nss_die(); + } else + return (char*) PORT_Strdup((char*)phrase); + } + } + + /* + * Turn the echoing off on a tty. + */ + static void echoOff(int fd) + { + if (isatty(fd)) { + struct termios tio; + tcgetattr(fd, &tio); + tio.c_lflag &= ~ECHO; + tcsetattr(fd, TCSAFLUSH, &tio); + } + } + + /* + * Turn the echoing on on a tty. + */ diff --git a/mod_nss.conf.in b/mod_nss.conf.in index a220d52..2a980bf 100644 --- a/mod_nss.conf.in +++ b/mod_nss.conf.in @@ -87,7 +87,7 @@ # # about b) # The Listen directive in /etc/apache2/listen_nss.conf is conditional on -# the server-define "SSL". Add the word SSL to the variable +# the server-flag "SSL". Add the word SSL to the variable # APACHE_SERVER_FLAGS in the file /etc/sysconfig/apache2 . # # Please note that /etc/apache2/listen.conf is read/included from the apache @@ -116,6 +116,11 @@ Include /etc/apache2/mod_nss.d/*.conf ## All SSL configuration in this context applies both to ## the main server and all SSL-enabled virtual hosts. ## +## Please note that _this_ file used to contain a VirtualHost +## section in previous versions/releases. It is now part of the +## /etc/apache2/vhosts.d/vhost-nss.template file, and is not +## activated by default. +## # # Some MIME-types for downloading Certificates and CRLs @@ -175,33 +180,26 @@ NSSRequireSafeNegotiation off -## -## SSL Virtual Host Context -## - - - -# General setup for the virtual host -#DocumentRoot "@apache_prefix@/htdocs" -#ServerName www.example.com:443 -#ServerAdmin you@example.com - -# mod_nss can log to separate log files, you can choose to do that if you'd like -# LogLevel is not inherited from httpd.conf. -#ErrorLog /var/log/apache2/error_log -#TransferLog /var/log/apache2/access_log -LogLevel warn - -# SSL Engine Switch: -# Enable/Disable SSL for this virtual host. -NSSEngine on +# main switch: You may want to turn this on in the context of a VirtualHost +# definition, not here globally. +# NSSEngine on # SSL Cipher Suite: # List the ciphers that the client is permitted to negotiate. # See the mod_nss documentation for a complete list. -# SSL 3 ciphers. SSL 2 is disabled by default. -NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha +# SSL 3 ciphers. SSL 2 is disabled +#NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha + +# The following ciphers are available in SUSE's package after June 2014; +# The GCM mode aes ciphers are of particular interest. +# You may want to add them if so desired: +# +# rsa_aes_128_gcm_sha +# ecdh_ecdsa_aes_128_gcm_sha +# ecdhe_ecdsa_aes_128_gcm_sha +# ecdh_rsa_aes_128_gcm_sha +# ecdhe_rsa_aes_128_gcm_sha # SSL 3 ciphers + ECC ciphers. SSL 2 is disabled by default. # @@ -209,6 +207,16 @@ NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa # ECC enabled NSS and mod_nss and want to use Elliptical Curve Cryptography #NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha,-ecdh_ecdsa_null_sha,+ecdh_ecdsa_rc4_128_sha,+ecdh_ecdsa_3des_sha,+ecdh_ecdsa_aes_128_sha,+ecdh_ecdsa_aes_256_sha,-ecdhe_ecdsa_null_sha,+ecdhe_ecdsa_rc4_128_sha,+ecdhe_ecdsa_3des_sha,+ecdhe_ecdsa_aes_128_sha,+ecdhe_ecdsa_aes_256_sha,-ecdh_rsa_null_sha,+ecdh_rsa_128_sha,+ecdh_rsa_3des_sha,+ecdh_rsa_aes_128_sha,+ecdh_rsa_aes_256_sha,-echde_rsa_null,+ecdhe_rsa_rc4_128_sha,+ecdhe_rsa_3des_sha,+ecdhe_rsa_aes_128_sha,+ecdhe_rsa_aes_256_sha +# The following is taken as default with the apache2-mod_nss package, as +# provided with the August 2014 update (which features the GCM mode ciphers +# along with server side SNI support). +# Ideas: +# * cipher mode may be more important than key length +# (AES-GCM is 128 bit, vs AES256 on a different mode) +# * no rc4, no 3des, no des +# * ephemeral is what you want (PFS). +# * EC has precedence over RSA +NSSCipherSuite +ecdhe_ecdsa_aes_128_gcm_sha,+ecdh_ecdsa_aes_128_gcm_sha,+ecdhe_rsa_aes_256_sha,+ecdh_rsa_aes_256_sha,+ecdhe_rsa_aes_128_gcm_sha,+ecdh_rsa_aes_128_gcm_sha,+ecdhe_rsa_aes_128_sha,+ecdh_rsa_aes_128_sha,+rsa_aes_128_gcm_sha,+rsa_aes_256_sha,+rsa_aes_128_sha # SSL Protocol: # Cryptographic protocols that provide communication security. @@ -224,7 +232,11 @@ NSSProtocol TLSv1.0,TLSv1.1,TLSv1.2 # SSL Certificate Nickname: # The nickname of the RSA server certificate you are going to use. -NSSNickname Server-Cert +# +# This is commented out, as it belongs to a VirtualHost definition. +# If there are no VirtualHost statements in your configuration, then +# here is the right spot: +#NSSNickname Server-Cert # SSL Certificate Nickname: # The nickname of the ECC server certificate you are going to use, if you @@ -235,7 +247,7 @@ NSSNickname Server-Cert # The NSS security database directory that holds the certificates and # keys. The database consists of 3 files: cert8.db, key3.db and secmod.db. # Provide the directory that these files exist. -NSSCertificateDatabase @apache_conf@/mod_nss.d +#NSSCertificateDatabase @apache_conf@/mod_nss.d # Database Prefix: # In order to be able to store multiple NSS databases in one directory @@ -315,14 +327,6 @@ NSSCertificateDatabase @apache_conf@/mod_nss.d NSSOptions +StdEnvVars -# Per-Server Logging: -# The home of a custom SSL log file. Use this when you want a -# compact non-error SSL logfile on a virtual host basis. -#CustomLog /home/rcrit/redhat/apache/logs/ssl_request_log \ -# "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" - - - diff --git a/vhost-nss.template b/vhost-nss.template new file mode 100644 index 0000000..8fd8996 --- /dev/null +++ b/vhost-nss.template @@ -0,0 +1,141 @@ + +## +## SSL Virtual Host Context +## + + +## The idea is that certificate specific options belong to a VirtualHost +## directive block, while the cipher and protocol configuration is a global +## setting that comes from /etc/apache2/conf.d/mod_nss.conf . +## The system-wide mod_nss.conf does not have any certificate-specific +## options set, so you would need to set them in your own config. +## +## Please place this file into /etc/apache2/vhosts.d with a name that ends +## in .conf . Files not named *.conf are ignored by the configuration +## framework. + + + +# General setup for the virtual host +#DocumentRoot "@apache_prefix@/htdocs" +#ServerName www.example.com:443 +#ServerAdmin you@example.com + +# mod_nss can log to separate log files, you can choose to do that if you'd like +# LogLevel is not inherited from httpd.conf. +#ErrorLog /var/log/apache2/error_log +#TransferLog /var/log/apache2/access_log +LogLevel warn + +# SSL Engine Switch: +# Enable/Disable SSL for this virtual host. +NSSEngine on + +# SSL Cipher Suite: +# +# The NSSCipherSuite directive is present in the NSS-specific system-wide +# configuration file /etc/apache2/conf.d/mod_nss.conf . +# You may set the cipher suite on a virtual host basis here, too. + + +# SSL Certificate Nickname: +# The nickname of the RSA server certificate you are going to use. +NSSNickname Server-Cert + +# SSL Certificate Nickname: +# The nickname of the ECC server certificate you are going to use, if you +# have an ECC-enabled version of NSS and mod_nss +#NSSECCNickname Server-Cert-ecc + +# Server Certificate Database: +# The NSS security database directory that holds the certificates and +# keys. The database consists of 3 files: cert8.db, key3.db and secmod.db. +# Provide the directory that these files exist. +NSSCertificateDatabase /etc/apache2/mod_nss.d + +# Database Prefix: +# In order to be able to store multiple NSS databases in one directory +# they need unique names. This option sets the database prefix used for +# cert8.db and key3.db. +#NSSDBPrefix my-prefix- + +# Client Authentication (Type): +# Client certificate verification type. Types are none, optional and +# require. +#NSSVerifyClient none + +# +# Online Certificate Status Protocol (OCSP). +# Verify that certificates have not been revoked before accepting them. +#NSSOCSP off + +# +# Use a default OCSP responder. If enabled this will be used regardless +# of whether one is included in a client certificate. Note that the +# server certificate is verified during startup. +# +# NSSOCSPDefaultURL defines the service URL of the OCSP responder +# NSSOCSPDefaultName is the nickname of the certificate to trust to +# sign the OCSP responses. +#NSSOCSPDefaultResponder on +#NSSOCSPDefaultURL http://example.com/ocsp/status +#NSSOCSPDefaultName ocsp-nickname + +# Access Control: +# With SSLRequire you can do per-directory access control based +# on arbitrary complex boolean expressions containing server +# variable checks and other lookup directives. The syntax is a +# mixture between C and Perl. See the mod_nss documentation +# for more details. +# +#NSSRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \ +# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \ +# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \ +# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \ +# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \ +# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/ +# + +# SSL Engine Options: +# Set various options for the SSL engine. +# o FakeBasicAuth: +# Translate the client X.509 into a Basic Authorisation. This means that +# the standard Auth/DBMAuth methods can be used for access control. The +# user name is the `one line' version of the client's X.509 certificate. +# Note that no password is obtained from the user. Every entry in the user +# file needs this password: `xxj31ZMTZzkVA'. +# o ExportCertData: +# This exports two additional environment variables: SSL_CLIENT_CERT and +# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the +# server (always existing) and the client (only existing when client +# authentication is used). This can be used to import the certificates +# into CGI scripts. +# o StdEnvVars: +# This exports the standard SSL/TLS related `SSL_*' environment variables. +# Per default this exportation is switched off for performance reasons, +# because the extraction step is an expensive operation and is usually +# useless for serving static content. So one usually enables the +# exportation for CGI and SSI requests only. +# o StrictRequire: +# This denies access when "NSSRequireSSL" or "NSSRequire" applied even +# under a "Satisfy any" situation, i.e. when it applies access is denied +# and no other module can change it. +# o OptRenegotiate: +# This enables optimized SSL connection renegotiation handling when SSL +# directives are used in per-directory context. +#NSSOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire + + NSSOptions +StdEnvVars + + + NSSOptions +StdEnvVars + + +# Per-Server Logging: +# The home of a custom SSL log file. Use this when you want a +# compact non-error SSL logfile on a virtual host basis. +#CustomLog /var/log/apache2/ssl_request_log \ +# "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" + + +