1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * _ __ ___ ___ __| | ___ ___| | mod_ssl
19 * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
20 * | | | | | | (_) | (_| | \__ \__ \ |
21 * |_| |_| |_|\___/ \__,_|___|___/___/_|
26 /* ``Every day of my life
27 I am forced to add another
28 name to the list of people
32 #include "ssl_private.h"
34 #include "apr_thread_mutex.h"
36 /* _________________________________________________________________
39 ** _________________________________________________________________
42 char *ssl_util_vhostid(apr_pool_t *p, server_rec *s)
49 host = s->server_hostname;
54 if (sc->enabled == TRUE)
55 port = DEFAULT_HTTPS_PORT;
57 port = DEFAULT_HTTP_PORT;
59 id = apr_psprintf(p, "%s:%lu", host, (unsigned long)port);
63 apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd,
64 const char * const *argv)
66 apr_procattr_t *procattr;
69 if (apr_procattr_create(&procattr, p) != APR_SUCCESS)
71 if (apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_FULL_BLOCK,
72 APR_FULL_BLOCK) != APR_SUCCESS)
74 if (apr_procattr_dir_set(procattr,
75 ap_make_dirstr_parent(p, cmd)) != APR_SUCCESS)
77 if (apr_procattr_cmdtype_set(procattr, APR_PROGRAM) != APR_SUCCESS)
79 proc = apr_pcalloc(p, sizeof(apr_proc_t));
80 if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS)
85 void ssl_util_ppclose(server_rec *s, apr_pool_t *p, apr_file_t *fp)
92 * Run a filter program and read the first line of its stdout output
94 char *ssl_util_readfilter(server_rec *s, apr_pool_t *p, const char *cmd,
95 const char * const *argv)
97 static char buf[MAX_STRING_LEN];
99 apr_size_t nbytes = 1;
103 if ((fp = ssl_util_ppopen(s, p, cmd, argv)) == NULL)
105 /* XXX: we are reading 1 byte at a time here */
106 for (k = 0; apr_file_read(fp, &c, &nbytes) == APR_SUCCESS
107 && nbytes == 1 && (k < MAX_STRING_LEN-1) ; ) {
108 if (c == '\n' || c == '\r')
113 ssl_util_ppclose(s, p, fp);
118 BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p)
124 if (pcm & SSL_PCM_EXISTS && apr_stat(&finfo, path,
125 APR_FINFO_TYPE|APR_FINFO_SIZE, p) != 0)
127 AP_DEBUG_ASSERT((pcm & SSL_PCM_EXISTS) ||
128 !(pcm & (SSL_PCM_ISREG|SSL_PCM_ISDIR|SSL_PCM_ISNONZERO)));
129 if (pcm & SSL_PCM_ISREG && finfo.filetype != APR_REG)
131 if (pcm & SSL_PCM_ISDIR && finfo.filetype != APR_DIR)
133 if (pcm & SSL_PCM_ISNONZERO && finfo.size <= 0)
139 * certain key data needs to survive restarts,
140 * which are stored in the user data table of s->process->pool.
141 * to prevent "leaking" of this data, we use malloc/free
142 * rather than apr_palloc and these wrappers to help make sure
143 * we do not leak the malloc-ed data.
145 unsigned char *ssl_asn1_table_set(apr_hash_t *table,
149 apr_ssize_t klen = strlen(key);
150 ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
153 * if a value for this key already exists,
154 * reuse as much of the already malloc-ed data
158 if (asn1->nData != length) {
159 free(asn1->cpData); /* XXX: realloc? */
164 asn1 = ap_malloc(sizeof(*asn1));
165 asn1->source_mtime = 0; /* used as a note for encrypted private keys */
169 asn1->nData = length;
171 asn1->cpData = ap_malloc(length);
174 apr_hash_set(table, key, klen, asn1);
176 return asn1->cpData; /* caller will assign a value to this */
179 ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
182 return (ssl_asn1_t *)apr_hash_get(table, key, APR_HASH_KEY_STRING);
185 void ssl_asn1_table_unset(apr_hash_t *table,
188 apr_ssize_t klen = strlen(key);
189 ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
200 apr_hash_set(table, key, klen, NULL);
205 * To ensure thread-safetyness in OpenSSL - work in progress
208 static apr_thread_mutex_t **lock_cs;
209 static int lock_num_locks;
211 static void ssl_util_thr_lock(int mode, int type,
212 const char *file, int line)
214 if (type < lock_num_locks) {
215 if (mode & CRYPTO_LOCK) {
216 apr_thread_mutex_lock(lock_cs[type]);
219 apr_thread_mutex_unlock(lock_cs[type]);
224 /* Dynamic lock structure */
225 struct CRYPTO_dynlock_value {
229 apr_thread_mutex_t *mutex;
232 /* Global reference to the pool passed into ssl_util_thread_setup() */
233 apr_pool_t *dynlockpool = NULL;
236 * Dynamic lock creation callback
238 static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file,
241 struct CRYPTO_dynlock_value *value;
246 * We need a pool to allocate our mutex. Since we can't clear
247 * allocated memory from a pool, create a subpool that we can blow
248 * away in the destruction callback.
250 apr_pool_create(&p, dynlockpool);
251 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE1, 0, p,
252 "Creating dynamic lock");
254 value = apr_palloc(p, sizeof(struct CRYPTO_dynlock_value));
256 /* Keep our own copy of the place from which we were created,
257 using our own pool. */
258 value->file = apr_pstrdup(p, file);
260 rv = apr_thread_mutex_create(&(value->mutex), APR_THREAD_MUTEX_DEFAULT,
262 if (rv != APR_SUCCESS) {
263 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, p, APLOGNO(02186)
264 "Failed to create thread mutex for dynamic lock");
272 * Dynamic locking and unlocking function
275 static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
276 const char *file, int line)
280 if (mode & CRYPTO_LOCK) {
281 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, 0, l->pool,
282 "Acquiring mutex %s:%d", l->file, l->line);
283 rv = apr_thread_mutex_lock(l->mutex);
284 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, rv, l->pool,
285 "Mutex %s:%d acquired!", l->file, l->line);
288 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, 0, l->pool,
289 "Releasing mutex %s:%d", l->file, l->line);
290 rv = apr_thread_mutex_unlock(l->mutex);
291 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE3, rv, l->pool,
292 "Mutex %s:%d released!", l->file, l->line);
297 * Dynamic lock destruction callback
299 static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value *l,
300 const char *file, int line)
304 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE1, 0, l->pool,
305 "Destroying dynamic lock %s:%d", l->file, l->line);
306 rv = apr_thread_mutex_destroy(l->mutex);
307 if (rv != APR_SUCCESS) {
308 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, l->pool,
309 APLOGNO(02192) "Failed to destroy mutex for dynamic "
310 "lock %s:%d", l->file, l->line);
313 /* Trust that whomever owned the CRYPTO_dynlock_value we were
314 * passed has no future use for it...
316 apr_pool_destroy(l->pool);
319 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
321 static void ssl_util_thr_id(CRYPTO_THREADID *id)
323 /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
324 * id is a structure twice that big. Use the TCB pointer instead as a
325 * unique unsigned long.
330 unsigned long PSATOLD;
333 CRYPTO_THREADID_set_numeric(id, psaptr->PSATOLD);
335 CRYPTO_THREADID_set_numeric(id, (unsigned long) apr_os_thread_current());
341 static unsigned long ssl_util_thr_id(void)
343 /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
344 * id is a structure twice that big. Use the TCB pointer instead as a
345 * unique unsigned long.
350 unsigned long PSATOLD;
353 return psaptr->PSATOLD;
355 return (unsigned long) apr_os_thread_current();
361 static apr_status_t ssl_util_thread_cleanup(void *data)
363 CRYPTO_set_locking_callback(NULL);
364 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
365 CRYPTO_THREADID_set_callback(NULL);
367 CRYPTO_set_id_callback(NULL);
370 CRYPTO_set_dynlock_create_callback(NULL);
371 CRYPTO_set_dynlock_lock_callback(NULL);
372 CRYPTO_set_dynlock_destroy_callback(NULL);
376 /* Let the registered mutex cleanups do their own thing
381 void ssl_util_thread_setup(apr_pool_t *p)
385 lock_num_locks = CRYPTO_num_locks();
386 lock_cs = apr_palloc(p, lock_num_locks * sizeof(*lock_cs));
388 for (i = 0; i < lock_num_locks; i++) {
389 apr_thread_mutex_create(&(lock_cs[i]), APR_THREAD_MUTEX_DEFAULT, p);
392 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
393 CRYPTO_THREADID_set_callback(ssl_util_thr_id);
395 CRYPTO_set_id_callback(ssl_util_thr_id);
398 CRYPTO_set_locking_callback(ssl_util_thr_lock);
400 /* Set up dynamic locking scaffolding for OpenSSL to use at its
404 CRYPTO_set_dynlock_create_callback(ssl_dyn_create_function);
405 CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock_function);
406 CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy_function);
408 apr_pool_cleanup_register(p, NULL, ssl_util_thread_cleanup,
409 apr_pool_cleanup_null);