Index: apache-fork/mod_ssl/pkg.sslmod/mod_ssl.c diff -u apache-fork/mod_ssl/pkg.sslmod/mod_ssl.c:1.1.2.1 apache-fork/mod_ssl/pkg.sslmod/mod_ssl.c:1.4 --- apache-fork/mod_ssl/pkg.sslmod/mod_ssl.c:1.1.2.1 Fri Jan 25 18:07:16 2002 +++ apache-fork/mod_ssl/pkg.sslmod/mod_ssl.c Tue Feb 5 17:54:53 2002 @@ -113,9 +113,21 @@ AP_SRV_CMD(CertificateFile, TAKE1, "SSL Server Certificate file " "(`/path/to/file' - PEM or DER encoded)") + AP_SRV_CMD(CertificateDB, TAKE2, + "SSL Server Certificate DB File and Key " + "(`/path/to/dbfile key' - PEM encoded)") + AP_SRV_CMD(CertificateDERDB, TAKE2, + "SSL Server Certificate DER DB File and Key " + "(`/path/to/dbfile key' - DER encoded)") AP_SRV_CMD(CertificateKeyFile, TAKE1, "SSL Server Private Key file " "(`/path/to/file' - PEM or DER encoded)") + AP_SRV_CMD(CertificateKeyDB, TAKE2, + "SSL Server Private Key DB File and Key " + "(`/path/to/dbfile key' - PEM encoded)") + AP_SRV_CMD(CertificateKeyDERDB, TAKE2, + "SSL Server Private Key DER DB File and Key " + "(`/path/to/dbfile key' - DER encoded)") AP_SRV_CMD(CertificateChainFile, TAKE1, "SSL Server CA Certificate Chain file " "(`/path/to/file' - PEM encoded)") @@ -158,6 +170,9 @@ AP_SRV_CMD(Protocol, RAW_ARGS, "Enable or disable various SSL protocols" "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)") + AP_SRV_CMD(OnlyOnPort, TAKE1, + "SSL port for this virtual host" + "(`N' - number of SSL port)") #ifdef SSL_EXPERIMENTAL_PROXY /* Index: apache-fork/mod_ssl/pkg.sslmod/mod_ssl.h diff -u apache-fork/mod_ssl/pkg.sslmod/mod_ssl.h:1.1.2.1 apache-fork/mod_ssl/pkg.sslmod/mod_ssl.h:1.5 --- apache-fork/mod_ssl/pkg.sslmod/mod_ssl.h:1.1.2.1 Fri Jan 25 18:07:16 2002 +++ apache-fork/mod_ssl/pkg.sslmod/mod_ssl.h Thu Feb 7 16:44:33 2002 @@ -461,10 +461,26 @@ typedef enum { SSL_PPTYPE_UNSET = UNSET, SSL_PPTYPE_BUILTIN = 0, - SSL_PPTYPE_FILTER = 1 + SSL_PPTYPE_FILTER = 1, + SSL_PPTYPE_NONE = 2 } ssl_pphrase_t; /* + * Define the SSL source type (for grabbing keys or certificats) + */ +typedef enum { + SSL_SOURCE_FILE = 0, + SSL_SOURCE_DB = 1, + SSL_SOURCE_DERDB = 2 +} ssl_source_type_t; + +typedef struct { + char *szDataA; + char *szDataB; + ssl_source_type_t nType; +} ssl_source_t; + +/* * Define the Path Checking modes */ #define SSL_PCM_EXISTS 1 @@ -553,6 +569,7 @@ array_header *aRandSeed; ssl_ds_table *tTmpKeys; void *pTmpKeys[SSL_TKPIDX_MAX]; + pool *pCrtPool; ssl_ds_table *tPublicCert; ssl_ds_table *tPrivateKey; #ifdef SSL_EXPERIMENTAL_ENGINE @@ -573,8 +590,8 @@ */ typedef struct { BOOL bEnabled; - char *szPublicCertFile[SSL_AIDX_MAX]; - char *szPrivateKeyFile[SSL_AIDX_MAX]; + ssl_source_t *pPublicCertSource[SSL_AIDX_MAX]; + ssl_source_t *pPrivateKeySource[SSL_AIDX_MAX]; char *szCertificateChain; char *szCACertificatePath; char *szCACertificateFile; @@ -591,6 +608,7 @@ int nPassPhraseDialogType; char *szPassPhraseDialogPath; ssl_proto_t nProtocol; + int nOnlyOnPort; char *szCARevocationPath; char *szCARevocationFile; X509_STORE *pRevocationStore; @@ -657,7 +675,11 @@ const char *ssl_cmd_SSLEngine(cmd_parms *, char *, int); const char *ssl_cmd_SSLCipherSuite(cmd_parms *, SSLDirConfigRec *, char *); const char *ssl_cmd_SSLCertificateFile(cmd_parms *, char *, char *); +const char *ssl_cmd_SSLCertificateDB(cmd_parms *, char *, char *, char *); +const char *ssl_cmd_SSLCertificateDERDB(cmd_parms *, char *, char *, char *); const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, char *, char *); +const char *ssl_cmd_SSLCertificateKeyDB(cmd_parms *, char *, char *, char *); +const char *ssl_cmd_SSLCertificateKeyDERDB(cmd_parms *, char *, char *, char *); const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, char *, char *); const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, SSLDirConfigRec *, char *); const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, SSLDirConfigRec *, char *); @@ -670,6 +692,7 @@ const char *ssl_cmd_SSLLog(cmd_parms *, char *, char *); const char *ssl_cmd_SSLLogLevel(cmd_parms *, char *, char *); const char *ssl_cmd_SSLProtocol(cmd_parms *, char *, const char *); +const char *ssl_cmd_SSLOnlyOnPort(cmd_parms *, char *, char *); const char *ssl_cmd_SSLOptions(cmd_parms *, SSLDirConfigRec *, const char *); const char *ssl_cmd_SSLRequireSSL(cmd_parms *, SSLDirConfigRec *, char *); const char *ssl_cmd_SSLRequire(cmd_parms *, SSLDirConfigRec *, char *); @@ -754,8 +777,9 @@ void ssl_scache_shmcb_status(server_rec *, pool *, void (*)(char *, void *), void *); /* Pass Phrase Support */ -void ssl_pphrase_Handle(server_rec *, pool *); +void ssl_pphrase_Handle(server_rec *, pool *, BOOL); int ssl_pphrase_Handle_CB(char *, int, int); +void ssl_pphrase_Handle_dbfile(server_rec *, pool *, char *, char *, int *, char **, pool *, FILE **); /* Diffie-Hellman Parameter Support */ DH *ssl_dh_GetTmpParam(int); Index: apache-fork/mod_ssl/pkg.sslmod/ssl_engine_config.c diff -u apache-fork/mod_ssl/pkg.sslmod/ssl_engine_config.c:1.1.2.1 apache-fork/mod_ssl/pkg.sslmod/ssl_engine_config.c:1.4 --- apache-fork/mod_ssl/pkg.sslmod/ssl_engine_config.c:1.1.2.1 Fri Jan 25 18:07:16 2002 +++ apache-fork/mod_ssl/pkg.sslmod/ssl_engine_config.c Tue Feb 5 17:54:53 2002 @@ -137,8 +137,9 @@ mc->nMutexFD = -1; mc->nMutexSEMID = -1; mc->aRandSeed = ap_make_array(pPool, 4, sizeof(ssl_randseed_t)); - mc->tPrivateKey = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t)); - mc->tPublicCert = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t)); + mc->pCrtPool = ap_make_sub_pool(pPool); + mc->tPrivateKey = ssl_ds_table_make(mc->pCrtPool, sizeof(ssl_asn1_t)); + mc->tPublicCert = ssl_ds_table_make(mc->pCrtPool, sizeof(ssl_asn1_t)); mc->tTmpKeys = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t)); #ifdef SSL_EXPERIMENTAL_ENGINE mc->szCryptoDevice = NULL; @@ -203,6 +204,7 @@ sc->nPassPhraseDialogType = SSL_PPTYPE_UNSET; sc->szPassPhraseDialogPath = NULL; sc->nProtocol = SSL_PROTOCOL_ALL; + sc->nOnlyOnPort = NULL; sc->fileLogFile = NULL; sc->pSSLCtx = NULL; sc->szCARevocationPath = NULL; @@ -221,8 +223,8 @@ sc->pSSLProxyCtx = NULL; #endif - (void)memset(sc->szPublicCertFile, 0, SSL_AIDX_MAX*sizeof(char *)); - (void)memset(sc->szPrivateKeyFile, 0, SSL_AIDX_MAX*sizeof(char *)); + (void)memset(sc->pPublicCertSource, 0, SSL_AIDX_MAX*sizeof(ssl_source_t *)); + (void)memset(sc->pPrivateKeySource, 0, SSL_AIDX_MAX*sizeof(ssl_source_t *)); (void)memset(sc->pPublicCert, 0, SSL_AIDX_MAX*sizeof(X509 *)); (void)memset(sc->pPrivateKey, 0, SSL_AIDX_MAX*sizeof(EVP_PKEY *)); @@ -259,6 +261,7 @@ cfgMerge(nPassPhraseDialogType, SSL_PPTYPE_UNSET); cfgMergeString(szPassPhraseDialogPath); cfgMerge(nProtocol, SSL_PROTOCOL_ALL); + cfgMergeInt(nOnlyOnPort); cfgMerge(fileLogFile, NULL); cfgMerge(pSSLCtx, NULL); cfgMerge(szCARevocationPath, NULL); @@ -266,8 +269,8 @@ cfgMerge(pRevocationStore, NULL); for (i = 0; i < SSL_AIDX_MAX; i++) { - cfgMergeString(szPublicCertFile[i]); - cfgMergeString(szPrivateKeyFile[i]); + cfgMergeString(pPublicCertSource[i]); /* even though not a string, this works */ + cfgMergeString(pPrivateKeySource[i]); /* even though not a string, this works */ cfgMerge(pPublicCert[i], NULL); cfgMerge(pPrivateKey[i], NULL); } @@ -431,6 +434,10 @@ sc->nPassPhraseDialogType = SSL_PPTYPE_BUILTIN; sc->szPassPhraseDialogPath = NULL; } + else if (strcEQ(arg, "none")) { + sc->nPassPhraseDialogType = SSL_PPTYPE_NONE; + sc->szPassPhraseDialogPath = NULL; + } else if (strlen(arg) > 5 && strEQn(arg, "exec:", 5)) { sc->nPassPhraseDialogType = SSL_PPTYPE_FILTER; sc->szPassPhraseDialogPath = ssl_util_server_root_relative(cmd->pool, "dialog", arg+5); @@ -559,19 +566,78 @@ { SSLSrvConfigRec *sc = mySrvConfig(cmd->server); char *cpPath; + ssl_source_t *pSource; int i; cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg); if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath)) return ap_pstrcat(cmd->pool, "SSLCertificateFile: file '", cpPath, "' not exists or empty", NULL); - for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) + pSource = (ssl_source_t*)ap_palloc(cmd->pool, sizeof(ssl_source_t)); + pSource->nType = SSL_SOURCE_FILE; + pSource->szDataA = cpPath; + pSource->szDataB = NULL; + for (i = 0; i < SSL_AIDX_MAX && sc->pPublicCertSource[i] != NULL; i++) ; if (i == SSL_AIDX_MAX) return ap_psprintf(cmd->pool, "SSLCertificateFile: only up to %d " "different certificates per virtual host allowed", SSL_AIDX_MAX); - sc->szPublicCertFile[i] = cpPath; + sc->pPublicCertSource[i] = pSource; + return NULL; +} + +const char *ssl_cmd_SSLCertificateDB( + cmd_parms *cmd, char *struct_ptr, char *arg_dbfile, char *arg_key) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + char *cpPath; + char *cpKey; + ssl_source_t *pSource; + int i; + + cpPath = ap_server_root_relative(cmd->pool, arg_dbfile); + if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath)) + return ap_pstrcat(cmd->pool, "SSLCertificateDB: file '", + cpPath, "' not exists or empty", NULL); + pSource = (ssl_source_t*)ap_palloc(cmd->pool, sizeof(ssl_source_t)); + pSource->nType = SSL_SOURCE_DB; + pSource->szDataA = cpPath; + pSource->szDataB = ap_pstrdup(cmd->pool, arg_key); + for (i = 0; i < SSL_AIDX_MAX && sc->pPublicCertSource[i] != NULL; i++) + ; + if (i == SSL_AIDX_MAX) + return ap_psprintf(cmd->pool, "SSLCertificateDB: only up to %d " + "different certificates per virtual host allowed", + SSL_AIDX_MAX); + sc->pPublicCertSource[i] = pSource; + return NULL; +} + +const char *ssl_cmd_SSLCertificateDERDB( + cmd_parms *cmd, char *struct_ptr, char *arg_dbfile, char *arg_key) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + char *cpPath; + char *cpKey; + ssl_source_t *pSource; + int i; + + cpPath = ap_server_root_relative(cmd->pool, arg_dbfile); + if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath)) + return ap_pstrcat(cmd->pool, "SSLCertificateDERDB: file '", + cpPath, "' not exists or empty", NULL); + pSource = (ssl_source_t*)ap_palloc(cmd->pool, sizeof(ssl_source_t)); + pSource->nType = SSL_SOURCE_DERDB; + pSource->szDataA = cpPath; + pSource->szDataB = ap_pstrdup(cmd->pool, arg_key); + for (i = 0; i < SSL_AIDX_MAX && sc->pPublicCertSource[i] != NULL; i++) + ; + if (i == SSL_AIDX_MAX) + return ap_psprintf(cmd->pool, "SSLCertificateDERDB: only up to %d " + "different certificates per virtual host allowed", + SSL_AIDX_MAX); + sc->pPublicCertSource[i] = pSource; return NULL; } @@ -580,19 +646,76 @@ { SSLSrvConfigRec *sc = mySrvConfig(cmd->server); char *cpPath; + ssl_source_t *pSource; int i; cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg); if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath)) return ap_pstrcat(cmd->pool, "SSLCertificateKeyFile: file '", cpPath, "' not exists or empty", NULL); - for (i = 0; i < SSL_AIDX_MAX && sc->szPrivateKeyFile[i] != NULL; i++) + pSource = (ssl_source_t*)ap_palloc(cmd->pool, sizeof(ssl_source_t)); + pSource->nType = SSL_SOURCE_FILE; + pSource->szDataA = cpPath; + pSource->szDataB = NULL; + for (i = 0; i < SSL_AIDX_MAX && sc->pPrivateKeySource[i] != NULL; i++) ; if (i == SSL_AIDX_MAX) return ap_psprintf(cmd->pool, "SSLCertificateKeyFile: only up to %d " "different private keys per virtual host allowed", SSL_AIDX_MAX); - sc->szPrivateKeyFile[i] = cpPath; + sc->pPrivateKeySource[i] = pSource; + return NULL; +} + +const char *ssl_cmd_SSLCertificateKeyDERDB( + cmd_parms *cmd, char *struct_ptr, char *arg_dbfile, char *arg_key) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + char *cpPath; + ssl_source_t *pSource; + int i; + + cpPath = ap_server_root_relative(cmd->pool, arg_dbfile); + if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath)) + return ap_pstrcat(cmd->pool, "SSLCertificateKeyDERDB: file '", + cpPath, "' not exists or empty", NULL); + pSource = (ssl_source_t*)ap_palloc(cmd->pool, sizeof(ssl_source_t)); + pSource->nType = SSL_SOURCE_DERDB; + pSource->szDataA = cpPath; + pSource->szDataB = ap_pstrdup(cmd->pool, arg_key); + for (i = 0; i < SSL_AIDX_MAX && sc->pPrivateKeySource[i] != NULL; i++) + ; + if (i == SSL_AIDX_MAX) + return ap_psprintf(cmd->pool, "SSLCertificateKeyDERDB: only up to %d " + "different private keys per virtual host allowed", + SSL_AIDX_MAX); + sc->pPrivateKeySource[i] = pSource; + return NULL; +} + +const char *ssl_cmd_SSLCertificateKeyDB( + cmd_parms *cmd, char *struct_ptr, char *arg_dbfile, char *arg_key) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + char *cpPath; + ssl_source_t *pSource; + int i; + + cpPath = ap_server_root_relative(cmd->pool, arg_dbfile); + if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath)) + return ap_pstrcat(cmd->pool, "SSLCertificateKeyDB: file '", + cpPath, "' not exists or empty", NULL); + pSource = (ssl_source_t*)ap_palloc(cmd->pool, sizeof(ssl_source_t)); + pSource->nType = SSL_SOURCE_DB; + pSource->szDataA = cpPath; + pSource->szDataB = ap_pstrdup(cmd->pool, arg_key); + for (i = 0; i < SSL_AIDX_MAX && sc->pPrivateKeySource[i] != NULL; i++) + ; + if (i == SSL_AIDX_MAX) + return ap_psprintf(cmd->pool, "SSLCertificateKeyDB: only up to %d " + "different private keys per virtual host allowed", + SSL_AIDX_MAX); + sc->pPrivateKeySource[i] = pSource; return NULL; } @@ -843,6 +966,17 @@ sc->nLogLevel = SSL_LOG_DEBUG; else return "SSLLogLevel: Invalid argument"; + return NULL; +} + +const char *ssl_cmd_SSLOnlyOnPort( + cmd_parms *cmd, char *struct_ptr, char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + + sc->nOnlyOnPort = atoi(arg); + if (sc->nOnlyOnPort < 0) + return "SSLOnlyOnPort: Invalid argument"; return NULL; } Index: apache-fork/mod_ssl/pkg.sslmod/ssl_engine_init.c diff -u apache-fork/mod_ssl/pkg.sslmod/ssl_engine_init.c:1.1.2.1 apache-fork/mod_ssl/pkg.sslmod/ssl_engine_init.c:1.3 --- apache-fork/mod_ssl/pkg.sslmod/ssl_engine_init.c:1.1.2.1 Fri Jan 25 18:07:16 2002 +++ apache-fork/mod_ssl/pkg.sslmod/ssl_engine_init.c Tue Feb 5 17:54:53 2002 @@ -242,13 +242,21 @@ } #endif if (mc->nInitCount == 1) { - ssl_pphrase_Handle(s, p); + ssl_pphrase_Handle(s, p, FALSE); ssl_init_TmpKeysHandle(SSL_TKP_GEN, s, p); #ifndef WIN32 return; #endif } +#ifdef WIN32 + if (mc->nInitCount > 1) + ssl_pphrase_Handle(s, p, TRUE); +#else + if (mc->nInitCount > 2) + ssl_pphrase_Handle(s, p, TRUE); +#endif + /* * SSL external crypto device ("engine") support */ @@ -547,7 +555,7 @@ * Now check for important parameters and the * possibility that the user forgot to set them. */ - if (sc->szPublicCertFile[0] == NULL) { + if (sc->pPublicCertSource[0] == NULL) { ssl_log(s, SSL_LOG_ERROR, "Init: (%s) No SSL Certificate set [hint: SSLCertificateFile]", cpVHostID); @@ -859,8 +867,9 @@ */ if (sc->szCertificateChain != NULL) { bSkipFirst = FALSE; - for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) { - if (strEQ(sc->szPublicCertFile[i], sc->szCertificateChain)) { + for (i = 0; i < SSL_AIDX_MAX && sc->pPublicCertSource[i] != NULL; i++) { + if (sc->pPublicCertSource[i]->nType == SSL_SOURCE_FILE && + strEQ(sc->pPublicCertSource[i]->szDataA, sc->szCertificateChain)) { bSkipFirst = TRUE; break; } Index: apache-fork/mod_ssl/pkg.sslmod/ssl_engine_kernel.c diff -u apache-fork/mod_ssl/pkg.sslmod/ssl_engine_kernel.c:1.1.2.1 apache-fork/mod_ssl/pkg.sslmod/ssl_engine_kernel.c:1.4 --- apache-fork/mod_ssl/pkg.sslmod/ssl_engine_kernel.c:1.1.2.1 Fri Jan 25 18:07:16 2002 +++ apache-fork/mod_ssl/pkg.sslmod/ssl_engine_kernel.c Tue Feb 5 17:54:53 2002 @@ -137,6 +137,7 @@ char *cpVHostMD5; X509 *xs; int rc; + unsigned port; /* * Get context @@ -144,6 +145,7 @@ srvr = conn->server; fb = conn->client; sc = mySrvConfig(srvr); + port = ntohs(conn->local_addr.sin_port); /* * Create SSL context @@ -156,6 +158,13 @@ */ if (sc == NULL || !sc->bEnabled) return; + + if (sc->nOnlyOnPort && sc->nOnlyOnPort != port) + { + ssl_log(srvr, SSL_LOG_INFO, "Connection to child %d on port %d set non-SSL by OnlyOnPort (server %s:%d)", + conn->child_num, port, srvr->server_hostname, srvr->port); + return; + } /* * Remember the connection information for Index: apache-fork/mod_ssl/pkg.sslmod/ssl_engine_pphrase.c diff -u apache-fork/mod_ssl/pkg.sslmod/ssl_engine_pphrase.c:1.1.2.1 apache-fork/mod_ssl/pkg.sslmod/ssl_engine_pphrase.c:1.4 --- apache-fork/mod_ssl/pkg.sslmod/ssl_engine_pphrase.c:1.1.2.1 Fri Jan 25 18:07:16 2002 +++ apache-fork/mod_ssl/pkg.sslmod/ssl_engine_pphrase.c Thu Feb 7 16:44:33 2002 @@ -65,6 +65,18 @@ -- Clifford Stoll */ #include "mod_ssl.h" +/* + * DERDB_IGNORE_BYTES + * Nubmer of byes to ingnore at the beginning of a DERDB database key. + * this should be used for an MD5 hash of the PEM encoded certificate + * or key, so that the program which fills the DERDB can be smart enough + * to only convert key/certs which have changed since the DERDB was + * created. + */ +#ifndef DERDB_IGNORE_BYTES +#define DERDB_IGNORE_BYTES 32 +#endif + /* _________________________________________________________________ ** @@ -77,7 +89,7 @@ #define BUILTIN_DIALOG_BACKOFF 2 #define BUILTIN_DIALOG_RETRIES 5 -void ssl_pphrase_Handle(server_rec *s, pool *p) +void ssl_pphrase_Handle(server_rec *s, pool *p, BOOL bGracefulRestart) { SSLModConfigRec *mc = myModConfig(); SSLSrvConfigRec *sc; @@ -103,6 +115,32 @@ ssl_algo_t algoCert, algoKey, at; char *an; char *cp; + int bNeedsRewind; + int bCloseFile; + char* szSourceName; + int nData; + char *cpData; + char szAnStatic[5]; + + /* + * Do nothing on graceful restarts if we have SSL_PTYPE_BUILTIN anywhere + */ + if (bGracefulRestart) { + for (pServ = s; pServ != NULL; pServ = pServ->next) { + sc = mySrvConfig(pServ); + if (!sc->bEnabled) + continue; + if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) { + cpVHostID = ssl_util_vhostid(p, pServ); + ssl_log(pServ, SSL_LOG_INFO, + "Init: Skipping certificate & private key reload on all " + "servers because of SSLPassPhraseDialog=builtin on " + "SSL-aware server %s", + cpVHostID); + return; + } + } + } /* * Start with a fresh pass phrase array @@ -112,6 +150,17 @@ nPassPhraseDialog = 0; /* + * Clear the certificate and key hashes if this is a restart + */ + if (bGracefulRestart) { + ssl_ds_table_kill(mc->tPrivateKey); + ssl_ds_table_kill(mc->tPublicCert); + ap_clear_pool(mc->pCrtPool); + mc->tPrivateKey = ssl_ds_table_make(mc->pCrtPool, sizeof(ssl_asn1_t)); + mc->tPublicCert = ssl_ds_table_make(mc->pCrtPool, sizeof(ssl_asn1_t)); + } + + /* * Walk through all configured servers */ for (pServ = s; pServ != NULL; pServ = pServ->next) { @@ -129,7 +178,7 @@ * Read in server certificate(s): This is the easy part * because this file isn't encrypted in any way. */ - if (sc->szPublicCertFile[0] == NULL) { + if (sc->pPublicCertSource[0] == NULL) { ssl_log(pServ, SSL_LOG_ERROR, "Init: Server %s should be SSL-aware but has no certificate configured " "[Hint: SSLCertificateFile]", cpVHostID); @@ -137,20 +186,70 @@ } algoCert = SSL_ALGO_UNKNOWN; algoKey = SSL_ALGO_UNKNOWN; - for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) { + for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->pPublicCertSource[i] != NULL; i++) { - ap_cpystrn(szPath, sc->szPublicCertFile[i], sizeof(szPath)); - if ((fp = ap_pfopen(p, szPath, "r")) == NULL) { - ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, - "Init: Can't open server certificate file %s", szPath); - ssl_die(); + /* + * Read this certificate depending on the + * ssl_source_type_t configuration + */ + if ( sc->pPublicCertSource[i]->nType == SSL_SOURCE_DERDB ) + { + ssl_pphrase_Handle_dbfile(s, p, sc->pPublicCertSource[i]->szDataA, + sc->pPublicCertSource[i]->szDataB, + &nData, &cpData, mc->pCrtPool, NULL); + nData -= DERDB_IGNORE_BYTES + 3; + cpData += DERDB_IGNORE_BYTES + 3; + if (nData < 0) { + ssl_log(s, SSL_LOG_ERROR, "Init: DERDB key %s from file %s is not at " + "least %d bytes", sc->pPublicCertSource[i]->szDataB, + sc->pPublicCertSource[i]->szDataA, DERDB_IGNORE_BYTES + 3); + ssl_die(); + } + szAnStatic[0] = cpData[-3]; + szAnStatic[1] = cpData[-2]; + szAnStatic[2] = cpData[-1]; + szAnStatic[3] = 0; + cp = ap_psprintf(mc->pCrtPool, "%s:%s", cpVHostID, szAnStatic); + asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPublicCert, cp); + asn1->nData = nData; + asn1->cpData = cpData; } - if ((pX509Cert = SSL_read_X509(fp, NULL, NULL)) == NULL) { - ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR, - "Init: Unable to read server certificate from file %s", szPath); + else + { +/* BEGIN NON INDENTED BLOCK */ + + if ( sc->pPublicCertSource[i]->nType == SSL_SOURCE_FILE ) + { + ap_cpystrn(szPath, sc->pPublicCertSource[i]->szDataA, sizeof(szPath)); + if ((fp = ap_pfopen(p, szPath, "r")) == NULL) { + ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, + "Init: Can't open server certificate file %s", szPath); + ssl_die(); + } + if ((pX509Cert = SSL_read_X509(fp, NULL, NULL)) == NULL) { + ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR, + "Init: Unable to read server certificate from file %s", szPath); + ssl_die(); + } + ap_pfclose(p, fp); + } + else if ( sc->pPublicCertSource[i]->nType == SSL_SOURCE_DB ) + { + ssl_pphrase_Handle_dbfile(s, p, sc->pPublicCertSource[i]->szDataA, + sc->pPublicCertSource[i]->szDataB, + NULL, NULL, NULL, &fp); + if ((pX509Cert = SSL_read_X509(fp, NULL, NULL)) == NULL) { + ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR, + "Init: Unable to read server certificate from dbfile %s key %s", + sc->pPublicCertSource[i]->szDataA, sc->pPublicCertSource[i]->szDataB); + ssl_die(); + } + } + else { + ssl_log(s, SSL_LOG_ERROR, + "Init: Invalid ssl_source_type_t in cert %d of %s vhost", i, cpVHostID); ssl_die(); } - ap_pfclose(p, fp); /* * check algorithm type of certificate and make @@ -172,10 +271,10 @@ * certificate is actually used to configure mod_ssl's per-server * configuration structures). */ - cp = ap_psprintf(mc->pPool, "%s:%s", cpVHostID, an); + cp = ap_psprintf(mc->pCrtPool, "%s:%s", cpVHostID, an); asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPublicCert, cp); asn1->nData = i2d_X509(pX509Cert, NULL); - asn1->cpData = ap_palloc(mc->pPool, asn1->nData); + asn1->cpData = ap_palloc(mc->pCrtPool, asn1->nData); ucp = asn1->cpData; i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */ /* @@ -183,6 +282,9 @@ */ X509_free(pX509Cert); +/* END NON INDENTED BLOCK */ + } + /* * Read in the private key: This is the non-trivial part, because the * key is typically encrypted, so a pass phrase dialog has to be used @@ -200,8 +302,64 @@ * phrase for all). When this is the case we can minimize the dialogs * by trying to re-use already known/entered pass phrases. */ - if (sc->szPrivateKeyFile[j] != NULL) - ap_cpystrn(szPath, sc->szPrivateKeyFile[j++], sizeof(szPath)); + if (sc->pPrivateKeySource[j] == NULL) + continue; + + if (sc->pPrivateKeySource[j]->nType == SSL_SOURCE_DERDB) + { + ssl_pphrase_Handle_dbfile(s, p, sc->pPrivateKeySource[j]->szDataA, + sc->pPrivateKeySource[j]->szDataB, + &nData, &cpData, mc->pCrtPool, NULL); + nData -= DERDB_IGNORE_BYTES + 3; + cpData += DERDB_IGNORE_BYTES + 3; + if (nData < 0) { + ssl_log(s, SSL_LOG_ERROR, "Init: DERDB key %s from file %s is not at " + "least %d bytes", sc->pPublicCertSource[i]->szDataB, + sc->pPublicCertSource[i]->szDataA, DERDB_IGNORE_BYTES + 3); + ssl_die(); + } + szAnStatic[0] = cpData[-3]; + szAnStatic[1] = cpData[-2]; + szAnStatic[2] = cpData[-1]; + szAnStatic[3] = 0; + cp = ap_psprintf(mc->pCrtPool, "%s:%s", cpVHostID, szAnStatic); + asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPrivateKey, cp); + asn1->nData = nData; + asn1->cpData = cpData; + } + else + { +/* BEGIN NON INDENTED BLOCK */ + + if (sc->pPrivateKeySource[j]->nType == SSL_SOURCE_FILE) + { + ap_cpystrn(szPath, sc->pPrivateKeySource[j]->szDataA, sizeof(szPath)); + if ((fp = ap_pfopen(p, szPath, "r")) == NULL) { + ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, + "Init: Can't open server private key file %s", szPath); + ssl_die(); + } + szSourceName = ap_psprintf(p, "file %s", szPath); + bNeedsRewind = 0; + bCloseFile = 1; + } + else if (sc->pPrivateKeySource[j]->nType == SSL_SOURCE_DB) + { + ssl_pphrase_Handle_dbfile(s, p, sc->pPrivateKeySource[j]->szDataA, + sc->pPrivateKeySource[j]->szDataB, + NULL, NULL, NULL, &fp); + szSourceName = ap_psprintf(p, "dbfile %s key %s", + sc->pPrivateKeySource[j]->szDataA, + sc->pPrivateKeySource[j]->szDataB); + bNeedsRewind = 0; + bCloseFile = 0; + } + else { + ssl_log(s, SSL_LOG_ERROR, + "Init: Invalid ssl_source_type_t in key %d of %s vhost", j, cpVHostID); + ssl_die(); + } + j++; /* * Try to read the private key file with the help of @@ -232,15 +390,12 @@ * the callback function which serves the pass * phrases to OpenSSL */ - if ((fp = ap_pfopen(p, szPath, "r")) == NULL) { - ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, - "Init: Can't open server private key file %s", szPath); - ssl_die(); - } + if (bNeedsRewind) + (void)fseek(fp, 0L, SEEK_SET); /* perhaps we should check the return value??? */ cpPassPhraseCur = NULL; bReadable = ((pPrivateKey = SSL_read_PrivateKey(fp, NULL, ssl_pphrase_Handle_CB)) != NULL ? TRUE : FALSE); - ap_pfclose(p, fp); + bNeedsRewind = 1; /* * when the private key file now was readable, @@ -305,6 +460,12 @@ } /* + * close the file if needed + */ + if (bCloseFile) + ap_pfclose(p, fp); + + /* * check algorithm type of private key and make * sure only one private key per type is used. */ @@ -350,20 +511,29 @@ * because the SSL library uses static variables inside a * RSA structure which do not survive DSO reloads!) */ - cp = ap_psprintf(mc->pPool, "%s:%s", cpVHostID, an); + cp = ap_psprintf(mc->pCrtPool, "%s:%s", cpVHostID, an); asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPrivateKey, cp); asn1->nData = i2d_PrivateKey(pPrivateKey, NULL); - asn1->cpData = ap_palloc(mc->pPool, asn1->nData); + asn1->cpData = ap_palloc(mc->pCrtPool, asn1->nData); ucp = asn1->cpData; i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ /* * Free the private key structure */ EVP_PKEY_free(pPrivateKey); + +/* END NON INDENTED BLOCK */ + } + } } /* + * Close and dbfile that might be open + */ + ssl_pphrase_Handle_dbfile(s, p, NULL, NULL, NULL, NULL, NULL, NULL); + + /* * Let the user know when we're successful. */ if (nPassPhraseDialog > 0) { @@ -547,6 +717,19 @@ } /* + * No passphrase dialouge option + */ + else if (sc->nPassPhraseDialogType == SSL_PPTYPE_NONE) { + char *prompt; + int i; + + ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, + "Init: Key is encrypted with SSLPassPhraseDialog=none for server %s", + cpVHostID); + ssl_die(); + } + + /* * Ok, we now have the pass phrase, so give it back */ *cppPassPhraseCur = ap_pstrdup(p, buf); @@ -555,5 +738,203 @@ * And return it's length to OpenSSL... */ return (len); +} + +static int bytecompare( unsigned char *aa, unsigned char *bb, int len) +{ + int ii; + for (ii=0; ii += sizeof(int), ii