File mod_nss-SNI-callback.patch of Package apache2-mod_nss

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