ssl_engine_pphrase.c revision c3e233736c4a453cbb2166a041f779e86230630a
967e5f3c25249c779575864692935627004d3f9eChristian Maeder/* Licensed to the Apache Software Foundation (ASF) under one or more
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * contributor license agreements. See the NOTICE file distributed with
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * this work for additional information regarding copyright ownership.
75a6279dbae159d018ef812185416cf6df386c10Till Mossakowski * The ASF licenses this file to You under the Apache License, Version 2.0
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * (the "License"); you may not use this file except in compliance with
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * the License. You may obtain a copy of the License at
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder * http://www.apache.org/licenses/LICENSE-2.0
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * Unless required by applicable law or agreed to in writing, software
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * distributed under the License is distributed on an "AS IS" BASIS,
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * See the License for the specific language governing permissions and
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * limitations under the License.
34c05dd06c937d85e7f552e4ff0d36ca0393daeaChristian Maeder * _ __ ___ ___ __| | ___ ___| | mod_ssl
7221c71b38c871ce66eee4537cb681d468308dfbChristian Maeder * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * | | | | | | (_) | (_| | \__ \__ \ |
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * |_| |_| |_|\___/ \__,_|___|___/___/_|
997c56f3bc74a703043010978e5013fdb074d659Christian Maeder * Pass Phrase Dialog
9744c7d9fa61d255d5e73beec7edc3499522e9e2Till Mossakowski /* ``Treat your password like your
9744c7d9fa61d255d5e73beec7edc3499522e9e2Till Mossakowski toothbrush. Don't let anybody
fd896e2068ad7e50aed66ac18c3720ea7ff2619fChristian Maeder else use it, and get a new one
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder every six months.''
fd896e2068ad7e50aed66ac18c3720ea7ff2619fChristian Maeder -- Clifford Stoll */
fd896e2068ad7e50aed66ac18c3720ea7ff2619fChristian Maeder * Return true if the named file exists and is readable
dea4c92f0c061d589c542d0640a18dab36dfbb46Christian Maederstatic apr_status_t exists_and_readable(char *fname, apr_pool_t *pool, apr_time_t *mtime)
dea4c92f0c061d589c542d0640a18dab36dfbb46Christian Maeder if ((stat = apr_stat(&sbuf, fname, APR_FINFO_MIN, pool)) != APR_SUCCESS)
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder if ((stat = apr_file_open(&fd, fname, APR_READ, 0, pool)) != APR_SUCCESS)
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * reuse vhost keys for asn1 tables where keys are allocated out
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * of s->process->pool to prevent "leaking" each time we format
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * a vhost key. since the key is stored in a table with lifetime
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * of s->process->pool, the key needs to have the same lifetime.
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * XXX: probably seems silly to use a hash table with keys and values
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * being the same, but it is easier than doing a linear search
239090e32b9079422ea1ce61197557e5b816f455Christian Maeder * and will make it easier to remove keys if needed in the future.
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * also have the problem with apr_array_header_t that if we
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * underestimate the number of vhost keys when we apr_array_make(),
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * the array will get resized when we push past the initial number
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * of elts. this resizing in the s->process->pool means "leaking"
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * since apr_array_push() will apr_alloc arr->nalloc * 2 elts,
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder * leaving the original arr->elts to waste.
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maederstatic char *asn1_table_vhost_key(SSLModConfigRec *mc, apr_pool_t *p,
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder /* 'p' pool used here is cleared on restarts (or sooner) */
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder char *key = apr_psprintf(p, "%s:%s", id, an);
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder void *keyptr = apr_hash_get(mc->tVHostKeys, key,
09eef8548cd62d787cf3a6535f9eae10592eec89Christian Maeder /* make a copy out of s->process->pool */
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder return (char *)keyptr;
34c05dd06c937d85e7f552e4ff0d36ca0393daeaChristian Maeder/* _________________________________________________________________
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder** Pass Phrase and Private Key Handling
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder** _________________________________________________________________
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder * sslc has a nasty flaw where its
adee28c3eb7bb0b9bb045d26ee6d35e19cf39053Christian Maeder * PEM_read_bio_PrivateKey does not take a callback arg.
adee28c3eb7bb0b9bb045d26ee6d35e19cf39053Christian Maederstatic server_rec *ssl_pphrase_server_rec = NULL;
967e5f3c25249c779575864692935627004d3f9eChristian Maederint ssl_pphrase_Handle_CB(char *, int, int);
967e5f3c25249c779575864692935627004d3f9eChristian Maederint ssl_pphrase_Handle_CB(char *, int, int, void *);
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maederstatic char *pphrase_array_get(apr_array_header_t *arr, int idx)
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maederstatic void pphrase_array_clear(apr_array_header_t *arr)
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder memset(arr->elts, 0, arr->elt_size * arr->nelts);
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maedervoid ssl_pphrase_Handle(server_rec *s, apr_pool_t *p)
bfa9e03532243ceb487f0384d0f6a447f1ce7670Till Mossakowski unsigned char *ucp;
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * Start with a fresh pass phrase array
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder aPassPhrase = apr_array_make(p, 2, sizeof(char *));
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * Walk through all configured servers
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder for (pServ = s; pServ != NULL; pServ = pServ->next) {
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder ap_log_error(APLOG_MARK, APLOG_INFO, 0, pServ,
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder "Loading certificate & private key of SSL-aware server");
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * Read in server certificate(s): This is the easy part
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * because this file isn't encrypted in any way.
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder ap_log_error(APLOG_MARK, APLOG_ERR, 0, pServ,
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder "Server should be SSL-aware but has no certificate "
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder "configured [Hint: SSLCertificateFile] (%s:%d)",
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder pServ->defn_name, pServ->defn_line_number);
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder for (i = 0, j = 0; i < SSL_AIDX_MAX
967e5f3c25249c779575864692935627004d3f9eChristian Maeder STACK_OF(X509) *certs = ssl_read_pkcs7(pServ,
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder apr_cpystrn(szPath, sc->server->pks->cert_files[i],
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder if ((rv = exists_and_readable(szPath, p, NULL))
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder "Init: Can't open server certificate file %s",
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder if ((pX509Cert = SSL_read_X509(szPath, NULL, NULL)) == NULL) {
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder "Init: Unable to read server certificate from"
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder * check algorithm type of certificate and make
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder * sure only one certificate per type is used.
7221c71b38c871ce66eee4537cb681d468308dfbChristian Maeder "Init: Multiple %s server certificates not "
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s);
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * Insert the certificate into global module configuration to let it
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * survive the processing between the 1st Apache API init round (where
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * we operate here) and the 2nd Apache init round (where the
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * certificate is actually used to configure mod_ssl's per-server
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * configuration structures).
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder cp = asn1_table_vhost_key(mc, p, cpVHostID, an);
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder ucp = ssl_asn1_table_set(mc->tPublicCert, cp, length);
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder (void)i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * Free the X509 structure
nPassPhraseCur = 0;
nPassPhraseRetry = 0;
nPassPhraseDialogCur = 0;
ssl_die();
if (pkey_mtime) {
for (i=0; i < SSL_AIDX_MAX; i++) {
const char *key_id =
0, pServ,
if (bReadable)
#ifndef WIN32
#ifdef WIN32
ssl_die();
if (writetty) {
if (writetty) {
ssl_die();
ssl_die();
ssl_die();
if (nPassPhraseDialogCur == 0) {
nPassPhrase++;
if (nPassPhraseDialogCur != 0) {
if (nPassPhraseDialog > 0) {
if (writetty) {
if (readtty) {
char **args;
const char *pname;
return rc;
#ifdef WIN32
#ifdef SSLC_VERSION_NUMBER
server_rec *s;
apr_pool_t *p;
int *pnPassPhraseCur;
char **cppPassPhraseCur;
char *cpVHostID;
char *cpAlgoType;
int *pnPassPhraseDialog;
int *pnPassPhraseDialogCur;
char *cpp;
(*pnPassPhraseDialog)++;
(*pnPassPhraseDialogCur)++;
return len;
char *prompt;
if (!readtty) {
!= APR_SUCCESS) {
#ifdef WIN32
if (*pbPassPhraseDialogOnce) {
apr_file_printf(writetty, "Apache:mod_ssl:Error: Pass phrase empty (needs to be at least 1 character).\n");
char *result;
return (len);