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; + } +}