From: Ben Laurie Date: Sat, 22 Jul 2006 14:27:43 +0000 (+0000) Subject: Add PKCS#7 support. X-Git-Tag: 2.2.3~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0cce395230e9fb3ec5a0e2a746c87016acc44d1c;p=thirdparty%2Fapache%2Fhttpd.git Add PKCS#7 support. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@424584 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 35d0b88bcd7..149eab8984f 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -111,6 +111,9 @@ static const command_rec ssl_config_cmds[] = { SSL_CMD_SRV(CertificateChainFile, TAKE1, "SSL Server CA Certificate Chain file " "(`/path/to/file' - PEM encoded)") + SSL_CMD_SRV(PKCS7CertificateFile, TAKE1, + "PKCS#7 file containing server certificate and chain" + " certificates (`/path/to/file' - PEM ecnoded)") SSL_CMD_ALL(CACertificatePath, TAKE1, "SSL CA Certificate path " "(`/path/to/dir' - contains PEM encoded files)") diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index df6674dd10e..aac695e102c 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -777,6 +777,22 @@ const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *cmd, return NULL; } +const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; + + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->server->pkcs7 = arg; + + return NULL; +} + #define NO_PER_DIR_SSL_CA \ "Your ssl library does not have support for per-directory CA" diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 7eb8ffac1a5..a6afaf6f203 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -357,7 +357,7 @@ static void ssl_init_server_check(server_rec *s, * check for important parameters and the * possibility that the user forgot to set them. */ - if (!mctx->pks->cert_files[0]) { + if (!mctx->pks->cert_files[0] && !mctx->pkcs7) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "No SSL Certificate set [hint: SSLCertificateFile]"); ssl_die(); @@ -639,6 +639,16 @@ static void ssl_init_ctx_crl(server_rec *s, } } +static void ssl_init_ctx_pkcs7_cert_chain(server_rec *s,modssl_ctx_t *mctx) +{ + STACK_OF(X509) *certs=ssl_read_pkcs7(s, mctx->pkcs7); + int n; + + if (!mctx->ssl_ctx->extra_certs) + for (n = 1; n < sk_X509_num(certs); ++n) + SSL_CTX_add_extra_chain_cert(mctx->ssl_ctx, sk_X509_value(certs, n)); +} + static void ssl_init_ctx_cert_chain(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp, @@ -648,6 +658,11 @@ static void ssl_init_ctx_cert_chain(server_rec *s, int i, n; const char *chain = mctx->cert_chain; + if (mctx->pkcs7) { + ssl_init_ctx_pkcs7_cert_chain(s,mctx); + return; + } + /* * Optionally configure extra server certificate chain certificates. * This is usually done by OpenSSL automatically when one of the diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c index 76763e315b9..d9f2e29d504 100644 --- a/modules/ssl/ssl_engine_pphrase.c +++ b/modules/ssl/ssl_engine_pphrase.c @@ -185,30 +185,39 @@ void ssl_pphrase_Handle(server_rec *s, apr_pool_t *p) * Read in server certificate(s): This is the easy part * because this file isn't encrypted in any way. */ - if (sc->server->pks->cert_files[0] == NULL) { + if (sc->server->pks->cert_files[0] == NULL + && sc->server->pkcs7 == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, pServ, "Server should be SSL-aware but has no certificate " "configured [Hint: SSLCertificateFile]"); ssl_die(); } + algoCert = SSL_ALGO_UNKNOWN; algoKey = SSL_ALGO_UNKNOWN; - 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 ((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); - ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); - ssl_die(); - } - + for (i = 0, j = 0; i < SSL_AIDX_MAX + && (sc->server->pks->cert_files[i] != NULL + || sc->server->pkcs7); i++) { + if (sc->server->pkcs7) { + STACK_OF(X509) *certs = ssl_read_pkcs7(pServ, sc->server->pkcs7); + + pX509Cert = sk_X509_value(certs, 0); + i = SSL_AIDX_MAX; + } else { + apr_cpystrn(szPath, sc->server->pks->cert_files[i], sizeof(szPath)); + 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); + ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + } /* * check algorithm type of certificate and make * sure only one certificate per type is used. diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index b66e602311f..efab17e454e 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -430,6 +430,7 @@ typedef struct { const char *pphrase_dialog_path; const char *cert_chain; + const char *pkcs7; /** certificate revocation list */ const char *crl_path; @@ -497,6 +498,7 @@ const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLPKCS7CertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCADNRequestPath(cmd_parms *, void *, const char *); @@ -637,6 +639,9 @@ const char *ssl_asn1_keystr(int keytype); const char *ssl_asn1_table_keyfmt(apr_pool_t *p, const char *id, int keytype); + +STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7); + /** Mutex Support */ int ssl_mutex_init(server_rec *, apr_pool_t *); int ssl_mutex_reinit(server_rec *, apr_pool_t *); diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index 88410849bb0..ef716beda4f 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -265,6 +265,50 @@ const char *ssl_asn1_table_keyfmt(apr_pool_t *p, return apr_pstrcat(p, id, ":", keystr, NULL); } +STACK_OF(X509) *ssl_read_pkcs7(server_rec *s,const char *pkcs7) +{ + PKCS7 *p7; + STACK_OF(X509) *certs; + FILE *f; + + f = fopen(pkcs7, "r"); + if (!f) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Can't open %s", pkcs7); + ssl_die(); + } + + p7 = PEM_read_PKCS7(f,NULL,NULL,NULL); + if (!p7) { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s, + "Can't read PKCS7 object %s", pkcs7); + ssl_log_ssl_error(APLOG_MARK, APLOG_CRIT, s); + exit(1); + } + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + certs = p7->d.sign->cert; + break; + + case NID_pkcs7_signedAndEnveloped: + certs = p7->d.signed_and_enveloped->cert; + break; + + default: + ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, 0, s, + "Don't understand PKCS7 file %s", pkcs7); + ssl_die(); + } + + if (!certs) { + ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_NOERRNO, 0, s, + "No certificates in %s", pkcs7); + ssl_die(); + } + + return certs; +} + #if APR_HAS_THREADS /*