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 if ((proc
= (apr_proc_t
*)apr_pcalloc(p
, sizeof(apr_proc_t
))) == NULL
)
81 if (apr_proc_create(proc
, cmd
, argv
, NULL
, procattr
, p
) != APR_SUCCESS
)
86 void ssl_util_ppclose(server_rec
*s
, apr_pool_t
*p
, apr_file_t
*fp
)
93 * Run a filter program and read the first line of its stdout output
95 char *ssl_util_readfilter(server_rec
*s
, apr_pool_t
*p
, const char *cmd
,
96 const char * const *argv
)
98 static char buf
[MAX_STRING_LEN
];
100 apr_size_t nbytes
= 1;
104 if ((fp
= ssl_util_ppopen(s
, p
, cmd
, argv
)) == NULL
)
106 /* XXX: we are reading 1 byte at a time here */
107 for (k
= 0; apr_file_read(fp
, &c
, &nbytes
) == APR_SUCCESS
108 && nbytes
== 1 && (k
< MAX_STRING_LEN
-1) ; ) {
109 if (c
== '\n' || c
== '\r')
114 ssl_util_ppclose(s
, p
, fp
);
119 BOOL
ssl_util_path_check(ssl_pathcheck_t pcm
, const char *path
, apr_pool_t
*p
)
125 if (pcm
& SSL_PCM_EXISTS
&& apr_stat(&finfo
, path
,
126 APR_FINFO_TYPE
|APR_FINFO_SIZE
, p
) != 0)
128 if (pcm
& SSL_PCM_ISREG
&& finfo
.filetype
!= APR_REG
)
130 if (pcm
& SSL_PCM_ISDIR
&& finfo
.filetype
!= APR_DIR
)
132 if (pcm
& SSL_PCM_ISNONZERO
&& finfo
.size
<= 0)
137 ssl_algo_t
ssl_util_algotypeof(X509
*pCert
, EVP_PKEY
*pKey
)
140 EVP_PKEY
*pFreeKey
= NULL
;
142 t
= SSL_ALGO_UNKNOWN
;
144 pFreeKey
= pKey
= X509_get_pubkey(pCert
);
146 switch (EVP_PKEY_key_type(pKey
)) {
157 #ifdef OPENSSL_VERSION_NUMBER
158 /* Only refcounted in OpenSSL */
159 if (pFreeKey
!= NULL
)
160 EVP_PKEY_free(pFreeKey
);
165 char *ssl_util_algotypestr(ssl_algo_t t
)
184 * certain key and cert data needs to survive restarts,
185 * which are stored in the user data table of s->process->pool.
186 * to prevent "leaking" of this data, we use malloc/free
187 * rather than apr_palloc and these wrappers to help make sure
188 * we do not leak the malloc-ed data.
190 unsigned char *ssl_asn1_table_set(apr_hash_t
*table
,
194 apr_ssize_t klen
= strlen(key
);
195 ssl_asn1_t
*asn1
= apr_hash_get(table
, key
, klen
);
198 * if a value for this key already exists,
199 * reuse as much of the already malloc-ed data
203 if (asn1
->nData
!= length
) {
204 free(asn1
->cpData
); /* XXX: realloc? */
209 asn1
= malloc(sizeof(*asn1
));
210 asn1
->source_mtime
= 0; /* used as a note for encrypted private keys */
214 asn1
->nData
= length
;
216 asn1
->cpData
= malloc(length
);
219 apr_hash_set(table
, key
, klen
, asn1
);
221 return asn1
->cpData
; /* caller will assign a value to this */
224 ssl_asn1_t
*ssl_asn1_table_get(apr_hash_t
*table
,
227 return (ssl_asn1_t
*)apr_hash_get(table
, key
, APR_HASH_KEY_STRING
);
230 void ssl_asn1_table_unset(apr_hash_t
*table
,
233 apr_ssize_t klen
= strlen(key
);
234 ssl_asn1_t
*asn1
= apr_hash_get(table
, key
, klen
);
245 apr_hash_set(table
, key
, klen
, NULL
);
248 static const char *ssl_asn1_key_types
[] = {"RSA", "DSA"};
250 const char *ssl_asn1_keystr(int keytype
)
252 if (keytype
>= SSL_AIDX_MAX
) {
256 return ssl_asn1_key_types
[keytype
];
259 const char *ssl_asn1_table_keyfmt(apr_pool_t
*p
,
263 const char *keystr
= ssl_asn1_keystr(keytype
);
265 return apr_pstrcat(p
, id
, ":", keystr
, NULL
);
268 STACK_OF(X509
) *ssl_read_pkcs7(server_rec
*s
, const char *pkcs7
)
271 STACK_OF(X509
) *certs
= NULL
;
274 f
= fopen(pkcs7
, "r");
276 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, s
, "Can't open %s", pkcs7
);
280 p7
= PEM_read_PKCS7(f
, NULL
, NULL
, NULL
);
282 ap_log_error(APLOG_MARK
, APLOG_ERR
|APLOG_NOERRNO
, 0, s
,
283 "Can't read PKCS7 object %s", pkcs7
);
284 ssl_log_ssl_error(APLOG_MARK
, APLOG_CRIT
, s
);
288 switch (OBJ_obj2nid(p7
->type
)) {
289 case NID_pkcs7_signed
:
290 certs
= p7
->d
.sign
->cert
;
293 case NID_pkcs7_signedAndEnveloped
:
294 certs
= p7
->d
.signed_and_enveloped
->cert
;
298 ap_log_error(APLOG_MARK
, APLOG_CRIT
|APLOG_NOERRNO
, 0, s
,
299 "Don't understand PKCS7 file %s", pkcs7
);
304 ap_log_error(APLOG_MARK
, APLOG_CRIT
|APLOG_NOERRNO
, 0, s
,
305 "No certificates in %s", pkcs7
);
317 * To ensure thread-safetyness in OpenSSL - work in progress
320 static apr_thread_mutex_t
**lock_cs
;
321 static int lock_num_locks
;
324 #if SSLC_VERSION_NUMBER >= 0x2000
325 static int ssl_util_thr_lock(int mode
, int type
,
326 char *file
, int line
)
328 static void ssl_util_thr_lock(int mode
, int type
,
329 char *file
, int line
)
332 static void ssl_util_thr_lock(int mode
, int type
,
333 const char *file
, int line
)
336 if (type
< lock_num_locks
) {
337 if (mode
& CRYPTO_LOCK
) {
338 apr_thread_mutex_lock(lock_cs
[type
]);
341 apr_thread_mutex_unlock(lock_cs
[type
]);
344 #if SSLC_VERSION_NUMBER >= 0x2000
354 /* Dynamic lock structure */
355 struct CRYPTO_dynlock_value
{
359 apr_thread_mutex_t
*mutex
;
362 /* Global reference to the pool passed into ssl_util_thread_setup() */
363 apr_pool_t
*dynlockpool
= NULL
;
366 * Dynamic lock creation callback
368 static struct CRYPTO_dynlock_value
*ssl_dyn_create_function(const char *file
,
371 struct CRYPTO_dynlock_value
*value
;
376 * We need a pool to allocate our mutex. Since we can't clear
377 * allocated memory from a pool, create a subpool that we can blow
378 * away in the destruction callback.
380 rv
= apr_pool_create(&p
, dynlockpool
);
381 if (rv
!= APR_SUCCESS
) {
382 ap_log_perror(file
, line
, APLOG_ERR
, rv
, dynlockpool
,
383 "Failed to create subpool for dynamic lock");
387 ap_log_perror(file
, line
, APLOG_DEBUG
, 0, p
,
388 "Creating dynamic lock");
390 value
= (struct CRYPTO_dynlock_value
*)apr_palloc(p
,
391 sizeof(struct CRYPTO_dynlock_value
));
393 ap_log_perror(file
, line
, APLOG_ERR
, 0, p
,
394 "Failed to allocate dynamic lock structure");
399 /* Keep our own copy of the place from which we were created,
400 using our own pool. */
401 value
->file
= apr_pstrdup(p
, file
);
403 rv
= apr_thread_mutex_create(&(value
->mutex
), APR_THREAD_MUTEX_DEFAULT
,
405 if (rv
!= APR_SUCCESS
) {
406 ap_log_perror(file
, line
, APLOG_ERR
, rv
, p
,
407 "Failed to create thread mutex for dynamic lock");
415 * Dynamic locking and unlocking function
418 static void ssl_dyn_lock_function(int mode
, struct CRYPTO_dynlock_value
*l
,
419 const char *file
, int line
)
423 if (mode
& CRYPTO_LOCK
) {
424 ap_log_perror(file
, line
, APLOG_DEBUG
, 0, l
->pool
,
425 "Acquiring mutex %s:%d", l
->file
, l
->line
);
426 rv
= apr_thread_mutex_lock(l
->mutex
);
427 ap_log_perror(file
, line
, APLOG_DEBUG
, rv
, l
->pool
,
428 "Mutex %s:%d acquired!", l
->file
, l
->line
);
431 ap_log_perror(file
, line
, APLOG_DEBUG
, 0, l
->pool
,
432 "Releasing mutex %s:%d", l
->file
, l
->line
);
433 rv
= apr_thread_mutex_unlock(l
->mutex
);
434 ap_log_perror(file
, line
, APLOG_DEBUG
, rv
, l
->pool
,
435 "Mutex %s:%d released!", l
->file
, l
->line
);
440 * Dynamic lock destruction callback
442 static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value
*l
,
443 const char *file
, int line
)
447 ap_log_perror(file
, line
, APLOG_DEBUG
, 0, l
->pool
,
448 "Destroying dynamic lock %s:%d", l
->file
, l
->line
);
449 rv
= apr_thread_mutex_destroy(l
->mutex
);
450 if (rv
!= APR_SUCCESS
) {
451 ap_log_perror(file
, line
, APLOG_ERR
, rv
, l
->pool
,
452 "Failed to destroy mutex for dynamic lock %s:%d",
456 /* Trust that whomever owned the CRYPTO_dynlock_value we were
457 * passed has no future use for it...
459 apr_pool_destroy(l
->pool
);
462 static unsigned long ssl_util_thr_id(void)
464 /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
465 * id is a structure twice that big. Use the TCB pointer instead as a
466 * unique unsigned long.
471 unsigned long PSATOLD
;
474 return psaptr
->PSATOLD
;
476 return (unsigned long) apr_os_thread_current();
480 static apr_status_t
ssl_util_thread_cleanup(void *data
)
482 CRYPTO_set_locking_callback(NULL
);
483 CRYPTO_set_id_callback(NULL
);
485 CRYPTO_set_dynlock_create_callback(NULL
);
486 CRYPTO_set_dynlock_lock_callback(NULL
);
487 CRYPTO_set_dynlock_destroy_callback(NULL
);
491 /* Let the registered mutex cleanups do their own thing
496 void ssl_util_thread_setup(apr_pool_t
*p
)
500 lock_num_locks
= CRYPTO_num_locks();
501 lock_cs
= apr_palloc(p
, lock_num_locks
* sizeof(*lock_cs
));
503 for (i
= 0; i
< lock_num_locks
; i
++) {
504 apr_thread_mutex_create(&(lock_cs
[i
]), APR_THREAD_MUTEX_DEFAULT
, p
);
507 CRYPTO_set_id_callback(ssl_util_thr_id
);
509 CRYPTO_set_locking_callback(ssl_util_thr_lock
);
511 /* Set up dynamic locking scaffolding for OpenSSL to use at its
515 CRYPTO_set_dynlock_create_callback(ssl_dyn_create_function
);
516 CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock_function
);
517 CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy_function
);
519 apr_pool_cleanup_register(p
, NULL
, ssl_util_thread_cleanup
,
520 apr_pool_cleanup_null
);