ASF Bugzilla – Attachment 28161 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.0.x
engine_managed_keys_1-http_2.0.x.diff.patch (text/plain), 15.63 KB, created by
Moran Jacuel
on 2012-01-16 16:45:23 UTC
(
hide
)
Description:
"Minimal support for (openssl) engine managed keys" patch from bug 42687 adapted for 2.0.x
Filename:
MIME Type:
Creator:
Moran Jacuel
Created:
2012-01-16 16:45:23 UTC
Size:
15.63 KB
patch
obsolete
>diff -bru httpd-2.0.x\ssl_engine_config.c httpd-2.0.x.new\ssl_engine_config.c >--- httpd-2.0.x\ssl_engine_config.c Mon Jan 16 14:06:01 2012 >+++ httpd-2.0.x.new\ssl_engine_config.c Mon Jan 16 16:01:34 2012 >@@ -74,6 +74,7 @@ > mc->tPublicCert = apr_hash_make(pool); > #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) > mc->szCryptoDevice = NULL; >+ mc->engine = NULL; > #endif > > memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys)); >@@ -508,9 +509,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: " >@@ -763,10 +764,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: >diff -bru httpd-2.0.x\ssl_engine_init.c httpd-2.0.x.new\ssl_engine_init.c >--- httpd-2.0.x\ssl_engine_init.c Mon Jan 16 14:06:25 2012 >+++ httpd-2.0.x.new\ssl_engine_init.c Mon Jan 16 15:53:50 2012 >@@ -51,6 +51,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(APLOG_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(APLOG_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 >@@ -352,7 +480,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_ERR, 0, s, > "Init: Failed to load Crypto Device API `%s'", > mc->szCryptoDevice); >@@ -374,8 +502,6 @@ > ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, > "Init: loaded Crypto Device API `%s'", > mc->szCryptoDevice); >- >- ENGINE_free(e); > } > } > #endif >@@ -835,13 +961,26 @@ > "Configuring %s server private key", type); > > ptr = asn1->cpData; >- if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) >- { >+ >+ if (!mc->engine) { >+ if (!(pkey = d2i_PrivateKey(pkey_type, NULL, &ptr, asn1->nData))) { > ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, > "Unable to import %s server private key", type); > ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, 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(APLOG_MARK, APLOG_ERR, s); >+ ssl_die(); >+ } >+ } > > if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) <= 0) { > ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, >@@ -867,6 +1006,9 @@ > } > > mctx->pks->keys[idx] = pkey; >+ >+ /* Release the engine if there is one. */ >+ ssl_ossle_release_engine(s); > > return TRUE; > } >diff -bru httpd-2.0.x\ssl_engine_pphrase.c httpd-2.0.x.new\ssl_engine_pphrase.c >--- httpd-2.0.x\ssl_engine_pphrase.c Mon Jan 16 14:06:33 2012 >+++ httpd-2.0.x.new\ssl_engine_pphrase.c Mon Jan 16 16:10:53 2012 >@@ -197,18 +197,45 @@ > for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->server->pks->cert_files[i] != NULL; i++) { > > apr_cpystrn(szPath, sc->server->pks->cert_files[i], sizeof(szPath)); >+ if (!mc->engine) { > if ((rv = exists_and_readable(szPath, p, NULL)) != APR_SUCCESS) { > ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, > "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_ERR, 0, s, >- "Init: Unable to read server certificate from file %s", szPath); >+ "Init: Unable to read server certificate " >+ "from file %s", szPath); >+ ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); >+ ssl_die(); >+ } >+ } >+ 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(APLOG_MARK, APLOG_ERR, s); > ssl_die(); > } >+ } > > /* > * check algorithm type of certificate and make >@@ -291,7 +318,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_ERR, rv, s, > "Init: Can't open server private key file " >@@ -347,13 +374,19 @@ > * 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, >- * it's fine and we go out of the loop >- */ > if (bReadable) > break; > >@@ -440,13 +473,24 @@ > } > > if (pPrivateKey == NULL) { >+ if (!mc->engine) { > ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, > "Init: Unable to read server private key from " >- "file %s [Hint: Perhaps it is in a separate file? " >- " See SSLCertificateKeyFile]", szPath); >+ "file %s [Hint: Perhaps it is in a separate " >+ "file? See SSLCertificateKeyFile]", szPath); > ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, 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(APLOG_MARK, APLOG_ERR, s); >+ } >+ } > > /* > * check algorithm type of private key and make >@@ -502,14 +546,33 @@ > * RSA structure which do not survive DSO reloads!) > */ > cp = asn1_table_vhost_key(mc, p, cpVHostID, an); >+ >+ if (!mc->engine){ > length = i2d_PrivateKey(pPrivateKey, NULL); > ucp = ssl_asn1_table_set(mc->tPrivateKey, cp, length); >- (void)i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */ >+ /* 2nd arg increments */ >+ (void)i2d_PrivateKey(pPrivateKey, &ucp); > > if (nPassPhraseDialogCur != 0) { > /* remember mtime of encrypted keys */ > asn1 = ssl_asn1_table_get(mc->tPrivateKey, cp); > 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, cp, 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, cp); >+ asn1->source_mtime = pkey_mtime; >+ } > } > > /* >diff -bru httpd-2.0.x\ssl_private.h httpd-2.0.x.new\ssl_private.h >--- httpd-2.0.x\ssl_private.h Mon Jan 16 14:06:44 2012 >+++ httpd-2.0.x.new\ssl_private.h Tue Nov 15 14:27:34 2011 >@@ -398,6 +398,7 @@ > apr_hash_t *tPrivateKey; > #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) > const char *szCryptoDevice; >+ ENGINE *engine; > #endif > struct { > void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10; >@@ -571,6 +572,7 @@ > > const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag); > >+ > /** module initialization */ > int ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *); > void ssl_init_Engine(server_rec *, apr_pool_t *); >@@ -580,6 +582,12 @@ > *ssl_init_FindCAList(server_rec *, apr_pool_t *, const char *, const char *); > 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 *);
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