Apache HTTPD
ssl_util.c
Go to the documentation of this file.
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/* _ _
18 * _ __ ___ ___ __| | ___ ___| | mod_ssl
19 * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
20 * | | | | | | (_) | (_| | \__ \__ \ |
21 * |_| |_| |_|\___/ \__,_|___|___/___/_|
22 * |_____|
23 * ssl_util.c
24 * Utility Functions
25 */
26 /* ``Every day of my life
27 I am forced to add another
28 name to the list of people
29 who piss me off!''
30 -- Calvin */
31
32#include "ssl_private.h"
33#include "ap_mpm.h"
34#include "apr_thread_mutex.h"
35
36/* _________________________________________________________________
37**
38** Utility Functions
39** _________________________________________________________________
40*/
41
43{
46
47 if (s->port != 0)
48 port = s->port;
49 else {
50 sc = mySrvConfig(s);
52 }
53
54 return apr_psprintf(p, "%s:%lu", s->server_hostname, (unsigned long)port);
55}
56
57/*
58 * Return TRUE iff the given servername matches the server record when
59 * selecting virtual hosts.
60 */
62{
64 int i;
65
66 /* check ServerName */
67 if (!strcasecmp(servername, s->server_hostname)) {
68 return TRUE;
69 }
70
71 /*
72 * if not matched yet, check ServerAlias entries
73 * (adapted from vhost.c:matches_aliases())
74 */
75 names = s->names;
76 if (names) {
77 char **name = (char **)names->elts;
78 for (i = 0; i < names->nelts; ++i) {
79 if (!name[i])
80 continue;
81 if (!strcasecmp(servername, name[i])) {
82 return TRUE;
83 }
84 }
85 }
86
87 /* if still no match, check ServerAlias entries with wildcards */
88 names = s->wild_names;
89 if (names) {
90 char **name = (char **)names->elts;
91 for (i = 0; i < names->nelts; ++i) {
92 if (!name[i])
93 continue;
95 return TRUE;
96 }
97 }
98 }
99
100 return FALSE;
101}
102
104{
107
108 if (!(sslconn && sslconn->ssl) && r->connection->master) {
110 }
111
112 if (sc->enabled == SSL_ENABLED_FALSE || !sslconn || !sslconn->ssl)
113 return 0;
114
115 if (scout) *scout = sslconn;
116
117 return 1;
118}
119
121 const char * const *argv)
122{
123 apr_procattr_t *procattr;
125
126 if (apr_procattr_create(&procattr, p) != APR_SUCCESS)
127 return NULL;
130 return NULL;
131 if (apr_procattr_dir_set(procattr,
133 return NULL;
135 return NULL;
136 proc = apr_pcalloc(p, sizeof(apr_proc_t));
137 if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS)
138 return NULL;
139 return proc->out;
140}
141
143{
144 apr_file_close(fp);
145 return;
146}
147
148/*
149 * Run a filter program and read the first line of its stdout output
150 */
152 const char * const *argv)
153{
154 static char buf[MAX_STRING_LEN];
155 apr_file_t *fp;
156 apr_size_t nbytes = 1;
157 char c;
158 int k;
159
160 if ((fp = ssl_util_ppopen(s, p, cmd, argv)) == NULL)
161 return NULL;
162 /* XXX: we are reading 1 byte at a time here */
163 for (k = 0; apr_file_read(fp, &c, &nbytes) == APR_SUCCESS
164 && nbytes == 1 && (k < MAX_STRING_LEN-1) ; ) {
165 if (c == '\n' || c == '\r')
166 break;
167 buf[k++] = c;
168 }
169 buf[k] = NUL;
170 ssl_util_ppclose(s, p, fp);
171
172 return buf;
173}
174
176{
177 apr_finfo_t finfo;
178
179 if (path == NULL)
180 return FALSE;
181 if (pcm & SSL_PCM_EXISTS && apr_stat(&finfo, path,
183 return FALSE;
186 if (pcm & SSL_PCM_ISREG && finfo.filetype != APR_REG)
187 return FALSE;
188 if (pcm & SSL_PCM_ISDIR && finfo.filetype != APR_DIR)
189 return FALSE;
190 if (pcm & SSL_PCM_ISNONZERO && finfo.size <= 0)
191 return FALSE;
192 return TRUE;
193}
194
195/* Decrypted private keys are cached to survive restarts. The cached
196 * data must have lifetime of the process (hence malloc/free rather
197 * than pools), and uses raw DER since the EVP_PKEY structure
198 * internals may not survive across a module reload. */
200 EVP_PKEY *pkey)
201{
202 apr_ssize_t klen = strlen(key);
203 ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
205 unsigned char *p;
206
207 /* Re-use structure if cached previously. */
208 if (asn1) {
209 if (asn1->nData != length) {
210 asn1->cpData = ap_realloc(asn1->cpData, length);
211 }
212 }
213 else {
214 asn1 = ap_malloc(sizeof(*asn1));
215 asn1->source_mtime = 0; /* used as a note for encrypted private keys */
216 asn1->cpData = ap_malloc(length);
217
218 apr_hash_set(table, key, klen, asn1);
219 }
220
221 asn1->nData = length;
222 p = asn1->cpData;
223 i2d_PrivateKey(pkey, &p); /* increases p by length */
224
225 return asn1;
226}
227
229 const char *key)
230{
232}
233
235 const char *key)
236{
237 apr_ssize_t klen = strlen(key);
238 ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
239
240 if (!asn1) {
241 return;
242 }
243
244 if (asn1->cpData) {
245 free(asn1->cpData);
246 }
247 free(asn1);
248
249 apr_hash_set(table, key, klen, NULL);
250}
251
252#if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API
253
254/*
255 * To ensure thread-safetyness in OpenSSL - work in progress
256 */
257
259static int lock_num_locks;
260
261static void ssl_util_thr_lock(int mode, int type,
262 const char *file, int line)
263{
264 if (type < lock_num_locks) {
265 if (mode & CRYPTO_LOCK) {
267 }
268 else {
270 }
271 }
272}
273
274/* Dynamic lock structure */
277 const char* file;
278 int line;
279 apr_thread_mutex_t *mutex;
280};
281
282/* Global reference to the pool passed into ssl_util_thread_setup() */
284
285/*
286 * Dynamic lock creation callback
287 */
288static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file,
289 int line)
290{
292 apr_pool_t *p;
293 apr_status_t rv;
294
295 /*
296 * We need a pool to allocate our mutex. Since we can't clear
297 * allocated memory from a pool, create a subpool that we can blow
298 * away in the destruction callback.
299 */
301 apr_pool_tag(p, "modssl_dynlock_value");
303 "Creating dynamic lock");
304
305 value = apr_palloc(p, sizeof(struct CRYPTO_dynlock_value));
306 value->pool = p;
307 /* Keep our own copy of the place from which we were created,
308 using our own pool. */
309 value->file = apr_pstrdup(p, file);
310 value->line = line;
312 p);
313 if (rv != APR_SUCCESS) {
315 "Failed to create thread mutex for dynamic lock");
317 return NULL;
318 }
319 return value;
320}
321
322/*
323 * Dynamic locking and unlocking function
324 */
325
326static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
327 const char *file, int line)
328{
329 apr_status_t rv;
330
331 if (mode & CRYPTO_LOCK) {
333 "Acquiring mutex %s:%d", l->file, l->line);
334 rv = apr_thread_mutex_lock(l->mutex);
336 "Mutex %s:%d acquired!", l->file, l->line);
337 }
338 else {
340 "Releasing mutex %s:%d", l->file, l->line);
341 rv = apr_thread_mutex_unlock(l->mutex);
343 "Mutex %s:%d released!", l->file, l->line);
344 }
345}
346
347/*
348 * Dynamic lock destruction callback
349 */
351 const char *file, int line)
352{
353 apr_status_t rv;
354
356 "Destroying dynamic lock %s:%d", l->file, l->line);
357 rv = apr_thread_mutex_destroy(l->mutex);
358 if (rv != APR_SUCCESS) {
359 ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, rv, l->pool,
360 APLOGNO(02192) "Failed to destroy mutex for dynamic "
361 "lock %s:%d", l->file, l->line);
362 }
363
364 /* Trust that whomever owned the CRYPTO_dynlock_value we were
365 * passed has no future use for it...
366 */
367 apr_pool_destroy(l->pool);
368}
369
370#if OPENSSL_VERSION_NUMBER >= 0x10000000L
371
372static void ssl_util_thr_id(CRYPTO_THREADID *id)
373{
374 /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
375 * id is a structure twice that big. Use the TCB pointer instead as a
376 * unique unsigned long.
377 */
378#ifdef __MVS__
379 struct PSA {
380 char unmapped[540]; /* PSATOLD is at offset 540 in the PSA */
381 unsigned long PSATOLD;
382 } *psaptr = 0; /* PSA is at address 0 */
383
385#else
387#endif
388}
389
391{
393 return APR_SUCCESS;
394}
395
396#else
397
398static unsigned long ssl_util_thr_id(void)
399{
400 /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
401 * id is a structure twice that big. Use the TCB pointer instead as a
402 * unique unsigned long.
403 */
404#ifdef __MVS__
405 struct PSA {
406 char unmapped[540];
407 unsigned long PSATOLD;
408 } *psaptr = 0;
409
410 return psaptr->PSATOLD;
411#else
412 return (unsigned long) apr_os_thread_current();
413#endif
414}
415
417{
419 return APR_SUCCESS;
420}
421
422#endif
423
425{
427
431
433
434 /* Let the registered mutex cleanups do their own thing
435 */
436 return APR_SUCCESS;
437}
438
440{
441 int i;
442
445
446 for (i = 0; i < lock_num_locks; i++) {
448 }
449
451
452 /* Set up dynamic locking scaffolding for OpenSSL to use at its
453 * convenience.
454 */
455 dynlockpool = p;
459
462}
463
465{
466#if OPENSSL_VERSION_NUMBER >= 0x10000000L
468#else
470#endif
473}
474
475#endif /* #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API */
476
477int modssl_is_engine_id(const char *name)
478{
479#if MODSSL_HAVE_ENGINE_API || MODSSL_HAVE_OPENSSL_STORE
480 /* ### Can handle any other special ENGINE key names here? */
481 return strncmp(name, "pkcs11:", 7) == 0;
482#else
483 return 0;
484#endif
485}
Apache Multi-Processing Module library.
#define TRUE
Definition abts.h:38
#define FALSE
Definition abts.h:35
APR Thread Mutex Routines.
request_rec int int apr_table_t const char * path
request_rec * r
#define MAX_STRING_LEN
Definition httpd.h:300
#define DEFAULT_HTTPS_PORT
Definition httpd.h:280
#define DEFAULT_HTTP_PORT
Definition httpd.h:278
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_TRACE3
Definition http_log.h:74
#define ap_log_perror
Definition http_log.h:412
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOG_MODULE_INDEX
Definition http_log.h:168
const unsigned char * buf
Definition util_md5.h:50
const char apr_port_t port
Definition http_vhost.h:125
int apr_off_t * length
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
apr_datum_t * pkey
Definition apr_dbm.h:158
int modssl_request_is_tls(const request_rec *r, SSLConnRec **scout)
Definition ssl_util.c:103
int modssl_is_engine_id(const char *name)
Definition ssl_util.c:477
char * ssl_util_readfilter(server_rec *s, apr_pool_t *p, const char *cmd, const char *const *argv)
Definition ssl_util.c:151
#define SSL_PCM_ISNONZERO
unsigned int ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p)
Definition ssl_util.c:175
#define mySrvConfig(srv)
char * ssl_util_vhostid(apr_pool_t *p, server_rec *s)
Definition ssl_util.c:42
unsigned int ssl_util_vhost_matches(const char *servername, server_rec *s)
Definition ssl_util.c:61
#define SSL_PCM_ISDIR
apr_file_t * ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd, const char *const *argv)
Definition ssl_util.c:120
ssl_asn1_t * ssl_asn1_table_set(apr_hash_t *table, const char *key, EVP_PKEY *pkey)
Definition ssl_util.c:199
#define myConnConfig(c)
void ssl_asn1_table_unset(apr_hash_t *table, const char *key)
Definition ssl_util.c:234
unsigned int ssl_pathcheck_t
ssl_asn1_t * ssl_asn1_table_get(apr_hash_t *table, const char *key)
Definition ssl_util.c:228
#define SSL_PCM_EXISTS
#define BOOL
Definition ssl_private.h:81
#define NUL
#define SSL_PCM_ISREG
void ssl_util_ppclose(server_rec *s, apr_pool_t *p, apr_file_t *fp)
Definition ssl_util.c:142
@ SSL_ENABLED_FALSE
int ap_strcasecmp_match(const char *str, const char *expected)
Definition util.c:199
char * ap_make_dirstr_parent(apr_pool_t *p, const char *s)
Definition util.c:692
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
void * ap_realloc(void *ptr, size_t size)
Definition util.c:3168
void * ap_malloc(size_t size) __attribute__((malloc))
Definition util.c:3152
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
@ APR_REG
@ APR_DIR
const char * key
void apr_size_t * nbytes
void * data
const char apr_file_t * file
int type
#define APR_FINFO_TYPE
#define APR_FINFO_SIZE
int strcasecmp(const char *a, const char *b)
apr_ssize_t * klen
Definition apr_hash.h:71
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_uint16_t apr_port_t
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
apr_proc_t * proc
#define APR_FULL_BLOCK
apr_cmdtype_e cmd
@ APR_PROGRAM
apr_pool_t * p
Definition md_event.c:32
const char * argv[3]
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
apr_os_thread_t apr_os_thread_current()
Definition thread.c:142
char * name
Internal interfaces private to mod_ssl.
ssl_enabled_t enabled
apr_filetype_e filetype
apr_off_t size
apr_file_t * out
conn_rec * master
Definition httpd.h:1248
A structure that represents the current request.
Definition httpd.h:845
conn_rec * connection
Definition httpd.h:849
server_rec * server
Definition httpd.h:851
A structure to store information for each virtual server.
Definition httpd.h:1322