]> granicus.if.org Git - apache/blob - modules/ssl/ssl_util.c
remove obsolete ssl_ds_{table,array} api
[apache] / modules / ssl / ssl_util.c
1 /*                      _             _
2 **  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
3 ** | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| |   \__ \__ \ |  www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_|  ftp.modssl.org
6 **                      |_____|
7 **  ssl_util.c
8 **  Utility Functions
9 */
10
11 /* ====================================================================
12  * The Apache Software License, Version 1.1
13  *
14  * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
15  * reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  *
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  *
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in
26  *    the documentation and/or other materials provided with the
27  *    distribution.
28  *
29  * 3. The end-user documentation included with the redistribution,
30  *    if any, must include the following acknowledgment:
31  *       "This product includes software developed by the
32  *        Apache Software Foundation (http://www.apache.org/)."
33  *    Alternately, this acknowledgment may appear in the software itself,
34  *    if and wherever such third-party acknowledgments normally appear.
35  *
36  * 4. The names "Apache" and "Apache Software Foundation" must
37  *    not be used to endorse or promote products derived from this
38  *    software without prior written permission. For written
39  *    permission, please contact apache@apache.org.
40  *
41  * 5. Products derived from this software may not be called "Apache",
42  *    nor may "Apache" appear in their name, without prior written
43  *    permission of the Apache Software Foundation.
44  *
45  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
49  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  * ====================================================================
58  */
59                              /* ``Every day of my life
60                                   I am forced to add another
61                                   name to the list of people
62                                   who piss me off!''
63                                             -- Calvin          */
64
65 #include "mod_ssl.h"
66 #include "ap_mpm.h"
67 #include "apr_thread_mutex.h"
68
69 /*  _________________________________________________________________
70 **
71 **  Utility Functions
72 **  _________________________________________________________________
73 */
74
75 char *ssl_util_vhostid(apr_pool_t *p, server_rec *s)
76 {
77     char *id;
78     SSLSrvConfigRec *sc;
79     char *host;
80     apr_port_t port;
81
82     host = s->server_hostname;
83     if (s->port != 0)
84         port = s->port;
85     else {
86         sc = mySrvConfig(s);
87         if (sc->bEnabled)
88             port = DEFAULT_HTTPS_PORT;
89         else
90             port = DEFAULT_HTTP_PORT;
91     }
92     id = apr_psprintf(p, "%s:%lu", host, (unsigned long)port);
93     return id;
94 }
95
96 void ssl_util_strupper(char *s)
97 {
98     for (; *s; ++s)
99         *s = apr_toupper(*s);
100     return;
101 }
102
103 static const char ssl_util_uuencode_six2pr[64+1] =
104     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
105
106 void ssl_util_uuencode(char *szTo, const char *szFrom, BOOL bPad)
107 {
108     ssl_util_uuencode_binary((unsigned char *)szTo,
109                              (const unsigned char *)szFrom,
110                              strlen(szFrom), bPad);
111 }
112
113 void ssl_util_uuencode_binary(unsigned char *szTo,
114                               const unsigned char *szFrom,
115                               int nLength, BOOL bPad)
116 {
117     const unsigned char *s;
118     int nPad = 0;
119
120     for (s = szFrom; nLength > 0; s += 3) {
121         *szTo++ = ssl_util_uuencode_six2pr[s[0] >> 2];
122         *szTo++ = ssl_util_uuencode_six2pr[(s[0] << 4 | s[1] >> 4) & 0x3f];
123         if (--nLength == 0) {
124             nPad = 2;
125             break;
126         }
127         *szTo++ = ssl_util_uuencode_six2pr[(s[1] << 2 | s[2] >> 6) & 0x3f];
128         if (--nLength == 0) {
129             nPad = 1;
130             break;
131         }
132         *szTo++ = ssl_util_uuencode_six2pr[s[2] & 0x3f];
133         --nLength;
134     }
135     while(bPad && nPad--) {
136         *szTo++ = NUL;
137     }
138     *szTo = NUL;
139     return;
140 }
141
142 apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd,
143                             const char * const *argv)
144 {
145     apr_procattr_t *procattr;
146     apr_proc_t *proc;
147
148     if (apr_procattr_create(&procattr, p) != APR_SUCCESS) 
149         return NULL;
150     if (apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_FULL_BLOCK, 
151                             APR_FULL_BLOCK) != APR_SUCCESS)
152         return NULL;
153     if (apr_procattr_dir_set(procattr, 
154                              ap_make_dirstr_parent(p, cmd)) != APR_SUCCESS)
155         return NULL;
156     if (apr_procattr_cmdtype_set(procattr, APR_PROGRAM) != APR_SUCCESS)
157         return NULL;
158     if ((proc = (apr_proc_t *)apr_pcalloc(p, sizeof(apr_proc_t))) == NULL)
159         return NULL;
160     if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS)
161         return NULL;
162     return proc->out;
163 }
164
165 void ssl_util_ppclose(server_rec *s, apr_pool_t *p, apr_file_t *fp)
166 {
167     apr_file_close(fp);
168     return;
169 }
170
171 /*
172  * Run a filter program and read the first line of its stdout output
173  */
174 char *ssl_util_readfilter(server_rec *s, apr_pool_t *p, const char *cmd,
175                           const char * const *argv)
176 {
177     static char buf[MAX_STRING_LEN];
178     apr_file_t *fp;
179     apr_size_t nbytes = 1;
180     char c;
181     int k;
182
183     if ((fp = ssl_util_ppopen(s, p, cmd, argv)) == NULL)
184         return NULL;
185     /* XXX: we are reading 1 byte at a time here */
186     for (k = 0; apr_file_read(fp, &c, &nbytes) == APR_SUCCESS
187                 && nbytes == 1 && (k < MAX_STRING_LEN-1)     ; ) {
188         if (c == '\n' || c == '\r')
189             break;
190         buf[k++] = c;
191     }
192     buf[k] = NUL;
193     ssl_util_ppclose(s, p, fp);
194
195     return buf;
196 }
197
198 BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p)
199 {
200     apr_finfo_t finfo;
201
202     if (path == NULL)
203         return FALSE;
204     if (pcm & SSL_PCM_EXISTS && apr_stat(&finfo, path, 
205                                 APR_FINFO_TYPE|APR_FINFO_SIZE, p) != 0)
206         return FALSE;
207     if (pcm & SSL_PCM_ISREG && finfo.filetype != APR_REG)
208         return FALSE;
209     if (pcm & SSL_PCM_ISDIR && finfo.filetype != APR_DIR)
210         return FALSE;
211     if (pcm & SSL_PCM_ISNONZERO && finfo.size <= 0)
212         return FALSE;
213     return TRUE;
214 }
215
216 ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey) 
217 {
218     ssl_algo_t t;
219             
220     t = SSL_ALGO_UNKNOWN;
221     if (pCert != NULL)
222         pKey = X509_get_pubkey(pCert);
223     if (pKey != NULL) {
224         switch (EVP_PKEY_key_type(pKey)) {
225             case EVP_PKEY_RSA: 
226                 t = SSL_ALGO_RSA;
227                 break;
228             case EVP_PKEY_DSA: 
229                 t = SSL_ALGO_DSA;
230                 break;
231             default:
232                 break;
233         }
234     }
235     return t;
236 }
237
238 char *ssl_util_algotypestr(ssl_algo_t t) 
239 {
240     char *cp;
241
242     cp = "UNKNOWN";
243     switch (t) {
244         case SSL_ALGO_RSA: 
245             cp = "RSA";
246             break;
247         case SSL_ALGO_DSA: 
248             cp = "DSA";
249             break;
250         default:
251             break;
252     }
253     return cp;
254 }
255
256 char *ssl_util_ptxtsub(apr_pool_t *p, const char *cpLine,
257                        const char *cpMatch, char *cpSubst)
258 {
259 #define MAX_PTXTSUB 100
260     char *cppMatch[MAX_PTXTSUB];
261     char *cpResult;
262     int nResult;
263     int nLine;
264     int nSubst;
265     int nMatch;
266     char *cpI;
267     char *cpO;
268     char *cp;
269     int i;
270
271     /*
272      * Pass 1: find substitution locations and calculate sizes
273      */
274     nLine  = strlen(cpLine);
275     nMatch = strlen(cpMatch);
276     nSubst = strlen(cpSubst);
277     for (cpI = (char *)cpLine, i = 0, nResult = 0;
278          cpI < cpLine+nLine && i < MAX_PTXTSUB;    ) {
279         if ((cp = strstr(cpI, cpMatch)) != NULL) {
280             cppMatch[i++] = cp;
281             nResult += ((cp-cpI)+nSubst);
282             cpI = (cp+nMatch);
283         }
284         else {
285             nResult += strlen(cpI);
286             break;
287         }
288     }
289     cppMatch[i] = NULL;
290     if (i == 0)
291         return NULL;
292
293     /*
294      * Pass 2: allocate memory and assemble result
295      */
296     cpResult = apr_pcalloc(p, nResult+1);
297     for (cpI = (char *)cpLine, cpO = cpResult, i = 0;
298          cppMatch[i] != NULL;
299          i++) {
300         apr_cpystrn(cpO, cpI, cppMatch[i]-cpI+1);
301         cpO += (cppMatch[i]-cpI);
302         apr_cpystrn(cpO, cpSubst, nSubst+1);
303         cpO += nSubst;
304         cpI = (cppMatch[i]+nMatch);
305     }
306     apr_cpystrn(cpO, cpI, cpResult+nResult-cpO+1);
307
308     return cpResult;
309 }
310
311 /*
312  * certain key and cert data needs to survive restarts,
313  * which are stored in the user data table of s->process->pool.
314  * to prevent "leaking" of this data, we use malloc/free
315  * rather than apr_palloc and these wrappers to help make sure
316  * we do not leak the malloc-ed data.
317  */
318 unsigned char *ssl_asn1_table_set(apr_hash_t *table,
319                                   const char *key,
320                                   long int length)
321 {
322     apr_ssize_t klen = strlen(key);
323     ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
324
325     /*
326      * if a value for this key already exists,
327      * reuse as much of the already malloc-ed data
328      * as possible.
329      */
330     if (asn1) {
331         if (asn1->nData != length) {
332             free(asn1->cpData); /* XXX: realloc? */
333             asn1->cpData = NULL;
334         }
335     }
336     else {
337         asn1 = malloc(sizeof(*asn1));
338         asn1->source_mtime = 0; /* used as a note for encrypted private keys */
339         asn1->cpData = NULL;
340     }
341
342     asn1->nData = length;
343     if (!asn1->cpData) {
344         asn1->cpData = malloc(length);
345     }
346
347     apr_hash_set(table, key, klen, asn1);
348
349     return asn1->cpData; /* caller will assign a value to this */
350 }
351
352 ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
353                                const char *key)
354 {
355     return (ssl_asn1_t *)apr_hash_get(table, key, APR_HASH_KEY_STRING);
356 }
357
358 void ssl_asn1_table_unset(apr_hash_t *table,
359                           const char *key)
360 {
361     apr_ssize_t klen = strlen(key);
362     ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
363
364     if (!asn1) {
365         return;
366     }
367
368     if (asn1->cpData) {
369         free(asn1->cpData);
370     }
371     free(asn1);
372
373     apr_hash_set(table, key, klen, NULL);
374 }
375
376 #if APR_HAS_THREADS
377 /*
378  * To ensure thread-safetyness in OpenSSL - work in progress
379  */
380
381 static apr_thread_mutex_t **lock_cs;
382 /* FIXME: CRYPTO_NUM_LOCKS may vary between releases - replace with
383    CRYPT_num_locks() [Ben, Jan 2002] */
384 static long                 lock_count[CRYPTO_NUM_LOCKS];
385
386 static void ssl_util_thr_lock(int mode, int type, const char *file, int line)
387 {
388     if (mode & CRYPTO_LOCK) {
389         apr_thread_mutex_lock(lock_cs[type]);
390         lock_count[type]++;
391     }
392     else {
393         apr_thread_mutex_unlock(lock_cs[type]);
394     }
395 }
396
397 static unsigned long ssl_util_thr_id(void)
398 {
399     return (unsigned long) apr_os_thread_current();
400 }
401
402 static apr_status_t ssl_util_thread_cleanup(void *data)
403 {
404     int i;
405
406     CRYPTO_set_locking_callback(NULL);
407
408     for (i = 0; i < CRYPTO_NUM_LOCKS; i++) {
409         apr_thread_mutex_destroy(lock_cs[i]);
410     }
411
412     return APR_SUCCESS;
413 }
414
415 void ssl_util_thread_setup(server_rec *s, apr_pool_t *p)
416 {
417     int i, threaded_mpm;
418     /* This variable is not used? -aaron
419     SSLModConfigRec *mc = myModConfig(s);
420     */
421
422     ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
423
424     if (!threaded_mpm) {
425         return;
426     }
427
428     lock_cs = apr_palloc(p, CRYPTO_NUM_LOCKS * sizeof(apr_thread_mutex_t *));
429
430     /*
431      * XXX: CRYPTO_NUM_LOCKS == 28
432      * should determine if there are lock types we do not need
433      * for example: debug_malloc, debug_malloc2 (see crypto/cryptlib.c)
434      */
435     for (i = 0; i < CRYPTO_NUM_LOCKS; i++) {
436         lock_count[i] = 0;
437         /* XXX: Can we remove the lock_count now that apr_thread_mutex_t
438          * can support nested (aka recursive) locks? -aaron */
439         apr_thread_mutex_create(&(lock_cs[i]), APR_THREAD_MUTEX_DEFAULT, p);
440     }
441
442     CRYPTO_set_id_callback(ssl_util_thr_id);
443
444     CRYPTO_set_locking_callback(ssl_util_thr_lock);
445
446     apr_pool_cleanup_register(p, NULL,
447                               ssl_util_thread_cleanup,
448                               apr_pool_cleanup_null);
449
450 }
451 #endif