ASF Bugzilla – Attachment 28756 Details for
Bug 52473
Patch to integrate apache server with OpenSSL generic PKCS#11 engine.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
"Minimal support for (openssl) engine managed keys" patch from bug 42687 adapted for 2.4.2
engine_managed_keys_1-http_2.4.2.diff.patch (text/plain), 16.07 KB, created by
Moran Jacuel
on 2012-05-10 09:09:25 UTC
(
hide
)
Description:
"Minimal support for (openssl) engine managed keys" patch from bug 42687 adapted for 2.4.2
Filename:
MIME Type:
Creator:
Moran Jacuel
Created:
2012-05-10 09:09:25 UTC
Size:
16.07 KB
patch
obsolete
>diff -ru httpd.2.4.2/ssl_engine_config.c httpd.2.4.2_new/ssl_engine_config.c >--- httpd.2.4.2/ssl_engine_config.c 2011-12-24 09:34:06.000000000 +0200 >+++ httpd.2.4.2_new/ssl_engine_config.c 2012-04-30 10:00:32.000000000 +0300 >@@ -69,6 +69,7 @@ > mc->tPublicCert = apr_hash_make(pool); > #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) > mc->szCryptoDevice = NULL; >+ mc->engine = NULL; > #endif > #ifdef HAVE_OCSP_STAPLING > mc->stapling_cache = NULL; >@@ -468,9 +469,9 @@ > if (strcEQ(arg, "builtin")) { > mc->szCryptoDevice = NULL; > } >- else if ((e = ENGINE_by_id(arg))) { >+ else if ((e = ssl_ossle_get_engine(cmd->server, arg, NULL, 0))) { > mc->szCryptoDevice = arg; >- ENGINE_free(e); >+ ssl_ossle_release_engine(cmd->server); > } > else { > err = "SSLCryptoDevice: Invalid argument; must be one of: " >@@ -718,11 +719,6 @@ > SSLSrvConfigRec *sc = mySrvConfig(parms->server); > const char *err, *desc=NULL, **files=NULL; > int i; >- >- if ((err = ssl_cmd_check_file(parms, &arg))) { >- return err; >- } >- > switch (idx) { > case SSL_AIDX_CERTS: > desc = "certificates"; >diff -ru httpd.2.4.2/ssl_engine_init.c httpd.2.4.2_new/ssl_engine_init.c >--- httpd.2.4.2/ssl_engine_init.c 2012-04-03 15:37:56.000000000 +0300 >+++ httpd.2.4.2_new/ssl_engine_init.c 2012-05-07 10:47:16.000000000 +0300 >@@ -56,6 +56,134 @@ > modver, AP_SERVER_BASEVERSION, incver); > } > >+/* _________________________________________________________________ >+** >+** Centralized engine loading & configuration >+** _________________________________________________________________ >+*/ >+ >+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) >+void ssl_ossle_release_engine(server_rec *s) >+{ >+ SSLModConfigRec *mc = myModConfig(s); >+ if (!mc->engine) { >+ return; >+ } >+ >+ /* unload any dynamic engines pulled in by CONF_modules_load_file, >+ * but don't unload the built in engines */ >+ CONF_modules_unload(0); >+ >+ /* Releases all the references retained via ssl_ossl_get_engine */ >+ ENGINE_finish(mc->engine); >+ >+ mc->engine = 0; >+} >+ >+ENGINE * ssl_ossle_get_engine(server_rec *s, const char *enginename, >+ const char *opensslcnf, int disablecnf) >+{ >+ SSLModConfigRec *mc = myModConfig(s); >+ ENGINE *e = 0; >+ int conf_modules = 0; >+ int funct_ref = 0; >+ >+ if (mc->engine) { >+ return mc->engine; >+ } >+ >+ /* CONF_modules_load_file allows for the declaration of engine names, and >+ * associated parameters, in an openssl formated configuration file. >+ * opensslcnf may be NULL, in which case openssl's default cofniguration >+ * file is used automaticaly. (Eg, "/etc/ssl/openssl.cnf"). >+ * >+ * To completely disable openssl config processing pass NULL for >+ * `opensslcnf' and set `disablecnf' to any non zero value. */ >+ >+ if (!disablecnf && CONF_modules_load_file(opensslcnf, 0, 0) <= 0) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, >+ "Init: Failed to load openssl config file `%s'", >+ opensslcnf); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); >+ goto x_fail; >+ } >+ if (!disablecnf) { >+ conf_modules = 1; >+ } >+ >+ /* side effect: aquires an additional `structure ref' */ >+ e = ENGINE_by_id(enginename); >+ if (!e) { >+ goto x_fail; >+ } >+ >+ ENGINE_free(e); /* drop the struct_ref taken out by ENGINE_by_id */ >+ >+ /* Take out a functional reference, all user configuration is handled in >+ * openssl.cnf and is now complete, so ENGINE_init can succede if the >+ * chosen engine has been configured appropriately. */ >+ if (!(funct_ref = ENGINE_init(e))) { >+ goto x_fail; >+ } >+ >+ /* Remove our engine from openssl's internal list and drop the associated >+ * reference. This means ENGINE_by_id will no longer succede and hence >+ * can't cause further reference counting hell. */ >+ if (!ENGINE_remove(e)) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, >+ "Init: Failed to apply engine configuration `%s' `%s'", >+ enginename, opensslcnf >+ ); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); >+ goto x_fail; >+ } >+ >+ mc->engine = e; >+ return mc->engine; >+ >+x_fail: >+ if (e) { >+ if (funct_ref) { >+ ENGINE_finish(e); >+ } >+ } >+ if (conf_modules) { >+ /* unload any dynamic engines pulled in by CONF_modules_load_file, >+ * but don't unload the built in engines. */ >+ CONF_modules_unload(0); >+ } >+ >+ return NULL; >+ >+} >+ >+/* ssl_ossle_load_cert_engine_pkcs11 >+ * >+ * This is specific to the engine_pkcs11 wrapper provided by the opensc >+ * project. more general support *is* possible but lets get some feed back >+ * before writing a tone of code. >+ */ >+X509* ssl_ossle_load_cert_engine_pkcs11(server_rec *s, const char *identifier) >+{ >+ int cmdno; >+ struct { >+ const char *identifier; >+ void *cert; >+ } param = {identifier, 0}; >+ >+ SSLModConfigRec *mc = myModConfig(s); >+ if (!mc->engine) { >+ return NULL; >+ } >+ >+ cmdno = ENGINE_ctrl(mc->engine, >+ ENGINE_CTRL_GET_CMD_FROM_NAME, -1, "LOAD_CERT_CTRL", 0); >+ /* XXX: check the value of cmdno */ >+ ENGINE_ctrl(mc->engine, cmdno, -1, ¶m, 0); >+ >+ return (X509 *)param.cert; >+} >+#endif > > /* > * Handle the Temporary RSA Keys and DH Params >@@ -433,7 +561,7 @@ > ENGINE *e; > > if (mc->szCryptoDevice) { >- if (!(e = ENGINE_by_id(mc->szCryptoDevice))) { >+ if (!(e = ssl_ossle_get_engine(s, mc->szCryptoDevice, NULL, 0))) { > ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(01888) > "Init: Failed to load Crypto Device API `%s'", > mc->szCryptoDevice); >@@ -455,8 +583,6 @@ > ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01890) > "Init: loaded Crypto Device API `%s'", > mc->szCryptoDevice); >- >- ENGINE_free(e); > } > } > #endif >@@ -1024,12 +1150,25 @@ > "Configuring %s server private key", type); > > ptr = asn1->cpData; >- if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) >- { >- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237) >- "Unable to import %s server private key", type); >- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); >- ssl_die(); >+ >+ if (!mc->engine) { >+ if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) { >+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02237) >+ "Unable to import %s server private key", type); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); >+ ssl_die(); >+ } >+ } >+ else { >+ /* cpData is a null terminated character string */ >+ if (!(pkey = ENGINE_load_private_key(mc->engine, (char*)asn1->cpData, >+ 0 /*ui_method*/, 0 /*cbdata*/))) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, >+ "Unable to import (ENGINE) %s server private key", >+ type); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); >+ ssl_die(); >+ } > } > > if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) { >@@ -1057,6 +1196,9 @@ > > mctx->pks->keys[idx] = pkey; > >+ /* Release the engine if there is one. */ >+ ssl_ossle_release_engine(s); >+ > return TRUE; > } > >diff -ru httpd.2.4.2/ssl_engine_pphrase.c httpd.2.4.2_new/ssl_engine_pphrase.c >--- httpd.2.4.2/ssl_engine_pphrase.c 2011-12-18 20:02:20.000000000 +0200 >+++ httpd.2.4.2_new/ssl_engine_pphrase.c 2012-05-07 10:49:58.000000000 +0300 >@@ -220,13 +220,14 @@ > } else { > apr_cpystrn(szPath, sc->server->pks->cert_files[i], > sizeof(szPath)); >- if ((rv = exists_and_readable(szPath, p, NULL)) >- != APR_SUCCESS) { >+ if (!mc->engine) { >+ if ((rv = exists_and_readable(szPath, p, NULL)) >+ != APR_SUCCESS) { > ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02201) > "Init: Can't open server certificate file %s", > szPath); > ssl_die(); >- } >+ } > if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) { > ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02241) > "Init: Unable to read server certificate from" >@@ -237,7 +238,32 @@ > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02202) > "Init: Read server certificate from '%s'", > szPath); >- } >+ } >+ else { >+ /* For backwards compat, and convenience for engine >+ * implementors, we should probably have a configurable >+ * means to say: "for these named engines, use apaches >+ * existing pem file support to load server keys and >+ * certificates", this patch treats all engines the same >+ * TODO: >+ * 1. explicit support for passing UI callbacks and >+ * data necessary for hardware that needs password entry, >+ * or other interactions, in order to load keys. It's a can >+ * of worms so I'm leaving it out for now. >+ * 2. Add at least "SSLCryptoDeviceLoadCertCmd" in order to >+ * enable a more general purpose implementation of engine >+ * based certificate loading. */ >+ pX509Cert = ssl_ossle_load_cert_engine_pkcs11(s, szPath); >+ if (!pX509Cert) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, >+ "Init: Unable to server certificate `%s' using " >+ "engine `%s'", szPath, mc->szCryptoDevice); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); >+ ssl_die(); >+ } >+ } >+ } >+ > /* > * check algorithm type of certificate and make > * sure only one certificate per type is used. >@@ -323,7 +349,7 @@ > * the callback function which serves the pass > * phrases to OpenSSL > */ >- if ((rv = exists_and_readable(szPath, p, >+ if (!mc->engine && (rv = exists_and_readable(szPath, p, > &pkey_mtime)) != APR_SUCCESS ) { > ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02243) > "Init: Can't open server private key file " >@@ -373,9 +399,19 @@ > * functions will fail spuriously if the error stack > * is not empty. */ > ERR_clear_error(); >- >- bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath, NULL, >- ssl_pphrase_Handle_CB, s)) != NULL ? TRUE : FALSE); >+ >+ if (!mc->engine) { >+ bReadable = ((pPrivateKey = SSL_read_PrivateKey(szPath, >+ NULL, ssl_pphrase_Handle_CB, s)) >+ != NULL ? TRUE : FALSE); >+ } >+ else { >+ pPrivateKey = ENGINE_load_private_key(mc->engine, szPath, >+ UI_OpenSSL() >+ /*ui_method*/, >+ 0 /*cbdata*/); >+ bReadable = pPrivateKey != NULL ? TRUE : FALSE; >+ } > > /* > * when the private key file now was readable, >@@ -474,12 +510,23 @@ > continue; > > if (pPrivateKey == NULL) { >- ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247) >- "Init: Unable to read server private key from " >- "file %s [Hint: Perhaps it is in a separate file? " >- " See SSLCertificateKeyFile]", szPath); >- ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); >- ssl_die(); >+ if (!mc->engine) { >+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02247) >+ "Init: Unable to read server private key from " >+ "file %s [Hint: Perhaps it is in a separate file? " >+ " See SSLCertificateKeyFile]", szPath); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s); >+ ssl_die(); >+ } >+ else { >+ /* log the error with clear indication that engine format >+ * keys are in play. */ >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, >+ "Init: Unable to load server private key " >+ "using the identifier `%s' and engine `%s'", >+ szPath, mc->szCryptoDevice); >+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); >+ } > } > > /* >@@ -535,14 +582,31 @@ > * because the SSL library uses static variables inside a > * RSA structure which do not survive DSO reloads!) > */ >- length = i2d_PrivateKey(pPrivateKey, NULL); >- ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length); >- (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ >- >- if (nPassPhraseDialogCur != 0) { >- /* remember mtime of encrypted keys */ >- asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); >- asn1->source_mtime = pkey_mtime; >+ if (!mc->engine){ >+ length = i2d_PrivateKey(pPrivateKey, NULL); >+ ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length); >+ (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ >+ >+ if (nPassPhraseDialogCur != 0) { >+ /* remember mtime of encrypted keys */ >+ asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); >+ asn1->source_mtime = pkey_mtime; >+ } >+ } >+ else { >+ /* the asn1 trick does not play well with hardware hosted >+ keys. */ >+ length = strlen(szPath) + 1; >+ /* cpData is the key_id */ >+ ucp = ssl_asn1_table_set(mc->tPrivateKey, key_id, length); >+ memcpy(ucp, szPath, length); >+ /* un-necessary, given we will reload, but retained for >+ * consistency. */ >+ if (nPassPhraseDialogCur != 0) { >+ /* remember mtime of encrypted keys */ >+ asn1 = ssl_asn1_table_get(mc->tPrivateKey, key_id); >+ asn1->source_mtime = pkey_mtime; >+ } > } > > /* >diff -ru httpd.2.4.2/ssl_private.h httpd.2.4.2_new/ssl_private.h >--- httpd.2.4.2/ssl_private.h 2012-04-03 15:37:56.000000000 +0300 >+++ httpd.2.4.2_new/ssl_private.h 2012-04-30 10:29:40.000000000 +0300 >@@ -529,6 +529,7 @@ > > #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) > const char *szCryptoDevice; >+ ENGINE *engine; > #endif > > #ifdef HAVE_OCSP_STAPLING >@@ -774,6 +775,12 @@ > void ssl_init_Child(apr_pool_t *, server_rec *); > apr_status_t ssl_init_ModuleKill(void *data); > >+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) >+void ssl_ossle_release_engine(server_rec *s); >+ENGINE *ssl_ossle_get_engine(server_rec *s, const char *enginename, const char *opensslcnf, int disablecnf); >+X509 *ssl_ossle_load_cert_engine_pkcs11(server_rec *s, const char *identifier); >+#endif >+ > /** Apache API hooks */ > int ssl_hook_Auth(request_rec *); > int ssl_hook_UserCheck(request_rec *);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 52473
:
28161
|
28755
| 28756