diff options
Diffstat (limited to 'nss_engine_init.c')
-rw-r--r-- | nss_engine_init.c | 107 |
1 files changed, 73 insertions, 34 deletions
diff --git a/nss_engine_init.c b/nss_engine_init.c index 78fb56c..7eda971 100644 --- a/nss_engine_init.c +++ b/nss_engine_init.c @@ -16,7 +16,9 @@ #include "mod_nss.h" #include "apr_thread_proc.h" #include "ap_mpm.h" -#include <secmod.h> +#include "secmod.h" +#include "sslerr.h" +#include "pk11func.h" static SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket); static SECStatus ownHandshakeCallback(PRFileDesc * socket, void *arg); @@ -111,6 +113,7 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled, int fipsenabled, SSLModConfigRec *mc = myModConfig(s); SSLSrvConfigRec *sc; int forked = 0; + char cwd[PATH_MAX]; sc = mySrvConfig(s); @@ -172,8 +175,14 @@ static void nss_init_SSLLibrary(server_rec *s, int sslenabled, int fipsenabled, /* Set the PKCS #11 strings for the internal token. */ PK11_ConfigurePKCS11(NULL,NULL,NULL, INTERNAL_TOKEN_NAME, NULL, NULL,NULL,NULL,8,1); + /* We need to be in the same directory as libnssckbi.so to load the + * root certificates properly. + */ + getcwd(cwd, PATH_MAX); + chdir(mc->pCertificateDatabase); /* Initialize NSS and open the certificate database read-only. */ rv = NSS_Initialize(mc->pCertificateDatabase, mc->pDBPrefix, mc->pDBPrefix, "secmod.db", NSS_INIT_READONLY); + chdir(cwd); /* Assuming everything is ok so far, check the cert database password(s). */ if (sslenabled && (rv != SECSuccess)) { @@ -287,11 +296,9 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, sc->server->sc = sc; } -#ifdef PROXY if (sc->proxy) { sc->proxy->sc = sc; } -#endif /* * Create the server host:port string because we need it a lot @@ -366,8 +373,8 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog, /* - * Announce mod_ssl and SSL library in HTTP Server field - * as ``mod_ssl/X.X.X OpenSSL/X.X.X'' + * Announce mod_nss and SSL library in HTTP Server field + * as ``mod_nss/X.X.X NSS/X.X.X'' */ nss_add_version_components(p, base_server); @@ -391,20 +398,28 @@ static void nss_init_ctx_socket(server_rec *s, nss_die(); } - if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_SERVER, PR_TRUE) + if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_SERVER, mctx->as_server) != SECSuccess) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Unable to set SSL server handshake mode."); nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); nss_die(); } - if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE) + if (SSL_OptionSet(mctx->model, SSL_HANDSHAKE_AS_CLIENT, !mctx->as_server) != SECSuccess) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "Unable to disable handshake as client"); + "Unable to set handshake as client"); nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); nss_die(); } + if (!mctx->as_server) { + if ((SSL_OptionSet(mctx->model, SSL_NO_CACHE, PR_TRUE)) != SECSuccess) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Unable to disable SSL client caching"); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } + } } static void nss_init_ctx_protocol(server_rec *s, @@ -622,7 +637,8 @@ static void nss_init_ctx_cipher_suite(server_rec *s, ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "FIPS mode enabled, permitted SSL ciphers are: [%s]", fipsciphers); - } + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Configuring permitted SSL ciphers [%s]", suite); @@ -666,7 +682,7 @@ static void nss_init_ctx_cipher_suite(server_rec *s, ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Cipher %s is enabled but this is not a FIPS cipher, disabling.", ciphers_def[i].name); cipher_state[i] = PR_FALSE; - } + } } } @@ -728,18 +744,20 @@ static void nss_init_server_certs(server_rec *s, * Get own certificate and private key. */ - if (mctx->nickname == NULL) { + if (mctx->nickname == NULL && mctx->as_server) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "No certificate nickname provided."); nss_die(); } - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "Using nickname %s.", mctx->nickname); + + if (mctx->nickname != NULL) + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "Using nickname %s.", mctx->nickname); mctx->servercert = FindServerCertFromNickname(mctx->nickname); /* Verify the certificate chain. */ - if (mctx->servercert != NULL) { + if (mctx->servercert != NULL && mctx->as_server) { SECCertificateUsage usage = certificateUsageSSLServer; if (CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), mctx->servercert, PR_TRUE, usage, NULL, NULL) != SECSuccess) { @@ -754,14 +772,14 @@ static void nss_init_server_certs(server_rec *s, } } - if (NULL == mctx->servercert) + if (NULL == mctx->servercert && mctx->as_server) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Certificate not found: '%s'", mctx->nickname); nss_die(); } - if (strchr(mctx->nickname, ':')) + if (mctx->nickname && strchr(mctx->nickname, ':')) { char* token = strdup(mctx->nickname); char* colon = strchr(token, ':'); @@ -786,17 +804,20 @@ static void nss_init_server_certs(server_rec *s, slot = PK11_GetInternalKeySlot(); } - mctx->serverkey = PK11_FindPrivateKeyFromCert(slot, mctx->servercert, NULL); - PK11_FreeSlot(slot); + if (mctx->servercert) { + mctx->serverkey = PK11_FindPrivateKeyFromCert(slot, mctx->servercert, NULL); + PK11_FreeSlot(slot); + } - if (mctx->serverkey == NULL) { + if (mctx->as_server && mctx->serverkey == NULL) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "Key not found for: '%s'", mctx->nickname); nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); nss_die(); } - mctx->serverKEAType = NSS_FindCertKEAType(mctx->servercert); + if (mctx->as_server) { + mctx->serverKEAType = NSS_FindCertKEAType(mctx->servercert); /* * Check for certs that are expired or not yet valid and WARN about it @@ -824,6 +845,7 @@ static void nss_init_server_certs(server_rec *s, "Unhandled Certificate time type %d for: '%s'", certtimestatus, mctx->nickname); break; } + } secstatus = (SECStatus)SSL_SetPKCS11PinArg(mctx->model, NULL); if (secstatus != SECSuccess) { @@ -832,15 +854,15 @@ static void nss_init_server_certs(server_rec *s, nss_die(); } -#if 1 - secstatus = SSL_ConfigSecureServer(mctx->model, mctx->servercert, mctx->serverkey, mctx->serverKEAType); - if (secstatus != SECSuccess) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "SSL error configuring server: '%s'", mctx->nickname); - nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); - nss_die(); + if (mctx->as_server) { + secstatus = SSL_ConfigSecureServer(mctx->model, mctx->servercert, mctx->serverkey, mctx->serverKEAType); + if (secstatus != SECSuccess) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "SSL error configuring server: '%s'", mctx->nickname); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, s); + nss_die(); + } } -#endif secstatus = (SECStatus)SSL_HandshakeCallback(mctx->model, (SSLHandshakeCallback)NSSHandshakeCallback, NULL); if (secstatus != SECSuccess) @@ -852,6 +874,16 @@ static void nss_init_server_certs(server_rec *s, } } +static void nss_init_proxy_ctx(server_rec *s, + apr_pool_t *p, + apr_pool_t *ptemp, + SSLSrvConfigRec *sc) +{ + nss_init_ctx(s, p, ptemp, sc->proxy); + + nss_init_server_certs(s, p, ptemp, sc->proxy); +} + static void nss_init_server_ctx(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, @@ -876,11 +908,11 @@ void nss_init_ConfigureServer(server_rec *s, nss_init_server_ctx(s, p, ptemp, sc); } -#ifdef PROXY if (sc->proxy_enabled) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "Enabling proxy."); nss_init_proxy_ctx(s, p, ptemp, sc); } -#endif } void nss_init_Child(apr_pool_t *p, server_rec *s) @@ -936,10 +968,14 @@ SECStatus ownBadCertHandler(void *arg, PRFileDesc * socket) { PRErrorCode err = PR_GetError(); - ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, - "Bad certificate: %d", err); - - return SECFailure; + switch (err) { + default: + ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, + "Bad remote server certificate.", err); + nss_log_nss_error(APLOG_MARK, APLOG_ERR, NULL); + return SECFailure; + break; + } } /* @@ -1028,6 +1064,9 @@ FindServerCertFromNickname(const char* name) PRUint32 bestCertMatchedUsage = 0; PRBool bestCertIsValid = PR_FALSE; + if (name == NULL) + return NULL; + clist = PK11_ListCerts(PK11CertListUser, NULL); for (cln = CERT_LIST_HEAD(clist); !CERT_LIST_END(cln,clist); |