]> granicus.if.org Git - apache/blob - modules/ssl/ssl_util.c
mod_cache: Don't add cached/revalidated entity headers to a 304 response.
[apache] / modules / ssl / ssl_util.c
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
42 char *ssl_util_vhostid(apr_pool_t *p, server_rec *s)
43 {
44     char *id;
45     SSLSrvConfigRec *sc;
46     char *host;
47     apr_port_t port;
48
49     host = s->server_hostname;
50     if (s->port != 0)
51         port = s->port;
52     else {
53         sc = mySrvConfig(s);
54         if (sc->enabled == TRUE)
55             port = DEFAULT_HTTPS_PORT;
56         else
57             port = DEFAULT_HTTP_PORT;
58     }
59     id = apr_psprintf(p, "%s:%lu", host, (unsigned long)port);
60     return id;
61 }
62
63 apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd,
64                             const char * const *argv)
65 {
66     apr_procattr_t *procattr;
67     apr_proc_t *proc;
68
69     if (apr_procattr_create(&procattr, p) != APR_SUCCESS)
70         return NULL;
71     if (apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_FULL_BLOCK,
72                             APR_FULL_BLOCK) != APR_SUCCESS)
73         return NULL;
74     if (apr_procattr_dir_set(procattr,
75                              ap_make_dirstr_parent(p, cmd)) != APR_SUCCESS)
76         return NULL;
77     if (apr_procattr_cmdtype_set(procattr, APR_PROGRAM) != APR_SUCCESS)
78         return NULL;
79     proc = apr_pcalloc(p, sizeof(apr_proc_t));
80     if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS)
81         return NULL;
82     return proc->out;
83 }
84
85 void ssl_util_ppclose(server_rec *s, apr_pool_t *p, apr_file_t *fp)
86 {
87     apr_file_close(fp);
88     return;
89 }
90
91 /*
92  * Run a filter program and read the first line of its stdout output
93  */
94 char *ssl_util_readfilter(server_rec *s, apr_pool_t *p, const char *cmd,
95                           const char * const *argv)
96 {
97     static char buf[MAX_STRING_LEN];
98     apr_file_t *fp;
99     apr_size_t nbytes = 1;
100     char c;
101     int k;
102
103     if ((fp = ssl_util_ppopen(s, p, cmd, argv)) == NULL)
104         return 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')
109             break;
110         buf[k++] = c;
111     }
112     buf[k] = NUL;
113     ssl_util_ppclose(s, p, fp);
114
115     return buf;
116 }
117
118 BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p)
119 {
120     apr_finfo_t finfo;
121
122     if (path == NULL)
123         return FALSE;
124     if (pcm & SSL_PCM_EXISTS && apr_stat(&finfo, path,
125                                 APR_FINFO_TYPE|APR_FINFO_SIZE, p) != 0)
126         return FALSE;
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)
130         return FALSE;
131     if (pcm & SSL_PCM_ISDIR && finfo.filetype != APR_DIR)
132         return FALSE;
133     if (pcm & SSL_PCM_ISNONZERO && finfo.size <= 0)
134         return FALSE;
135     return TRUE;
136 }
137
138 /*
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.
144  */
145 unsigned char *ssl_asn1_table_set(apr_hash_t *table,
146                                   const char *key,
147                                   long int length)
148 {
149     apr_ssize_t klen = strlen(key);
150     ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
151
152     /*
153      * if a value for this key already exists,
154      * reuse as much of the already malloc-ed data
155      * as possible.
156      */
157     if (asn1) {
158         if (asn1->nData != length) {
159             free(asn1->cpData); /* XXX: realloc? */
160             asn1->cpData = NULL;
161         }
162     }
163     else {
164         asn1 = ap_malloc(sizeof(*asn1));
165         asn1->source_mtime = 0; /* used as a note for encrypted private keys */
166         asn1->cpData = NULL;
167     }
168
169     asn1->nData = length;
170     if (!asn1->cpData) {
171         asn1->cpData = ap_malloc(length);
172     }
173
174     apr_hash_set(table, key, klen, asn1);
175
176     return asn1->cpData; /* caller will assign a value to this */
177 }
178
179 ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
180                                const char *key)
181 {
182     return (ssl_asn1_t *)apr_hash_get(table, key, APR_HASH_KEY_STRING);
183 }
184
185 void ssl_asn1_table_unset(apr_hash_t *table,
186                           const char *key)
187 {
188     apr_ssize_t klen = strlen(key);
189     ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
190
191     if (!asn1) {
192         return;
193     }
194
195     if (asn1->cpData) {
196         free(asn1->cpData);
197     }
198     free(asn1);
199
200     apr_hash_set(table, key, klen, NULL);
201 }
202
203 #if APR_HAS_THREADS
204 /*
205  * To ensure thread-safetyness in OpenSSL - work in progress
206  */
207
208 static apr_thread_mutex_t **lock_cs;
209 static int                  lock_num_locks;
210
211 static void ssl_util_thr_lock(int mode, int type,
212                               const char *file, int line)
213 {
214     if (type < lock_num_locks) {
215         if (mode & CRYPTO_LOCK) {
216             apr_thread_mutex_lock(lock_cs[type]);
217         }
218         else {
219             apr_thread_mutex_unlock(lock_cs[type]);
220         }
221     }
222 }
223
224 /* Dynamic lock structure */
225 struct CRYPTO_dynlock_value {
226     apr_pool_t *pool;
227     const char* file;
228     int line;
229     apr_thread_mutex_t *mutex;
230 };
231
232 /* Global reference to the pool passed into ssl_util_thread_setup() */
233 apr_pool_t *dynlockpool = NULL;
234
235 /*
236  * Dynamic lock creation callback
237  */
238 static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file,
239                                                      int line)
240 {
241     struct CRYPTO_dynlock_value *value;
242     apr_pool_t *p;
243     apr_status_t rv;
244
245     /*
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.
249      */
250     apr_pool_create(&p, dynlockpool);
251     ap_log_perror(file, line, APLOG_MODULE_INDEX, APLOG_TRACE1, 0, p,
252                   "Creating dynamic lock");
253
254     value = apr_palloc(p, sizeof(struct CRYPTO_dynlock_value));
255     value->pool = p;
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);
259     value->line = line;
260     rv = apr_thread_mutex_create(&(value->mutex), APR_THREAD_MUTEX_DEFAULT,
261                                 p);
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");
265         apr_pool_destroy(p);
266         return NULL;
267     }
268     return value;
269 }
270
271 /*
272  * Dynamic locking and unlocking function
273  */
274
275 static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
276                            const char *file, int line)
277 {
278     apr_status_t rv;
279
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);
286     }
287     else {
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);
293     }
294 }
295
296 /*
297  * Dynamic lock destruction callback
298  */
299 static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value *l,
300                           const char *file, int line)
301 {
302     apr_status_t rv;
303
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);
311     }
312
313     /* Trust that whomever owned the CRYPTO_dynlock_value we were
314      * passed has no future use for it...
315      */
316     apr_pool_destroy(l->pool);
317 }
318
319 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
320
321 static void ssl_util_thr_id(CRYPTO_THREADID *id)
322 {
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.
326      */
327 #ifdef __MVS__
328     struct PSA {
329         char unmapped[540];
330         unsigned long PSATOLD;
331     } *psaptr = 0;
332
333     CRYPTO_THREADID_set_numeric(id, psaptr->PSATOLD);
334 #else
335     CRYPTO_THREADID_set_numeric(id, (unsigned long) apr_os_thread_current());
336 #endif
337 }
338
339 #else
340
341 static unsigned long ssl_util_thr_id(void)
342 {
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.
346      */
347 #ifdef __MVS__
348     struct PSA {
349         char unmapped[540];
350         unsigned long PSATOLD;
351     } *psaptr = 0;
352
353     return psaptr->PSATOLD;
354 #else
355     return (unsigned long) apr_os_thread_current();
356 #endif
357 }
358
359 #endif
360
361 static apr_status_t ssl_util_thread_cleanup(void *data)
362 {
363     CRYPTO_set_locking_callback(NULL);
364 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
365     CRYPTO_THREADID_set_callback(NULL);
366 #else
367     CRYPTO_set_id_callback(NULL);
368 #endif
369
370     CRYPTO_set_dynlock_create_callback(NULL);
371     CRYPTO_set_dynlock_lock_callback(NULL);
372     CRYPTO_set_dynlock_destroy_callback(NULL);
373
374     dynlockpool = NULL;
375
376     /* Let the registered mutex cleanups do their own thing
377      */
378     return APR_SUCCESS;
379 }
380
381 void ssl_util_thread_setup(apr_pool_t *p)
382 {
383     int i;
384
385     lock_num_locks = CRYPTO_num_locks();
386     lock_cs = apr_palloc(p, lock_num_locks * sizeof(*lock_cs));
387
388     for (i = 0; i < lock_num_locks; i++) {
389         apr_thread_mutex_create(&(lock_cs[i]), APR_THREAD_MUTEX_DEFAULT, p);
390     }
391
392 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
393     CRYPTO_THREADID_set_callback(ssl_util_thr_id);
394 #else
395     CRYPTO_set_id_callback(ssl_util_thr_id);
396 #endif
397
398     CRYPTO_set_locking_callback(ssl_util_thr_lock);
399
400     /* Set up dynamic locking scaffolding for OpenSSL to use at its
401      * convenience.
402      */
403     dynlockpool = p;
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);
407
408     apr_pool_cleanup_register(p, NULL, ssl_util_thread_cleanup,
409                                        apr_pool_cleanup_null);
410 }
411 #endif