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
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;
55 port = DEFAULT_HTTPS_PORT;
57 port = DEFAULT_HTTP_PORT;
59 id = apr_psprintf(p, "%s:%lu", host, (unsigned long)port);
63 void ssl_util_strupper(char *s)
70 static const char ssl_util_uuencode_six2pr[64+1] =
71 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
73 void ssl_util_uuencode(char *szTo, const char *szFrom, BOOL bPad)
75 ssl_util_uuencode_binary((unsigned char *)szTo,
76 (const unsigned char *)szFrom,
77 strlen(szFrom), bPad);
80 void ssl_util_uuencode_binary(unsigned char *szTo,
81 const unsigned char *szFrom,
82 int nLength, BOOL bPad)
84 const unsigned char *s;
87 for (s = szFrom; nLength > 0; s += 3) {
88 *szTo++ = ssl_util_uuencode_six2pr[s[0] >> 2];
89 *szTo++ = ssl_util_uuencode_six2pr[(s[0] << 4 | s[1] >> 4) & 0x3f];
94 *szTo++ = ssl_util_uuencode_six2pr[(s[1] << 2 | s[2] >> 6) & 0x3f];
99 *szTo++ = ssl_util_uuencode_six2pr[s[2] & 0x3f];
102 while(bPad && nPad--) {
109 apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd,
110 const char * const *argv)
112 apr_procattr_t *procattr;
115 if (apr_procattr_create(&procattr, p) != APR_SUCCESS)
117 if (apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_FULL_BLOCK,
118 APR_FULL_BLOCK) != APR_SUCCESS)
120 if (apr_procattr_dir_set(procattr,
121 ap_make_dirstr_parent(p, cmd)) != APR_SUCCESS)
123 if (apr_procattr_cmdtype_set(procattr, APR_PROGRAM) != APR_SUCCESS)
125 if ((proc = (apr_proc_t *)apr_pcalloc(p, sizeof(apr_proc_t))) == NULL)
127 if (apr_proc_create(proc, cmd, argv, NULL, procattr, p) != APR_SUCCESS)
132 void ssl_util_ppclose(server_rec *s, apr_pool_t *p, apr_file_t *fp)
139 * Run a filter program and read the first line of its stdout output
141 char *ssl_util_readfilter(server_rec *s, apr_pool_t *p, const char *cmd,
142 const char * const *argv)
144 static char buf[MAX_STRING_LEN];
146 apr_size_t nbytes = 1;
150 if ((fp = ssl_util_ppopen(s, p, cmd, argv)) == NULL)
152 /* XXX: we are reading 1 byte at a time here */
153 for (k = 0; apr_file_read(fp, &c, &nbytes) == APR_SUCCESS
154 && nbytes == 1 && (k < MAX_STRING_LEN-1) ; ) {
155 if (c == '\n' || c == '\r')
160 ssl_util_ppclose(s, p, fp);
165 BOOL ssl_util_path_check(ssl_pathcheck_t pcm, const char *path, apr_pool_t *p)
171 if (pcm & SSL_PCM_EXISTS && apr_stat(&finfo, path,
172 APR_FINFO_TYPE|APR_FINFO_SIZE, p) != 0)
174 if (pcm & SSL_PCM_ISREG && finfo.filetype != APR_REG)
176 if (pcm & SSL_PCM_ISDIR && finfo.filetype != APR_DIR)
178 if (pcm & SSL_PCM_ISNONZERO && finfo.size <= 0)
183 ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
187 t = SSL_ALGO_UNKNOWN;
189 pKey = X509_get_pubkey(pCert);
191 switch (EVP_PKEY_key_type(pKey)) {
205 char *ssl_util_algotypestr(ssl_algo_t t)
223 char *ssl_util_ptxtsub(apr_pool_t *p, const char *cpLine,
224 const char *cpMatch, char *cpSubst)
226 #define MAX_PTXTSUB 100
227 char *cppMatch[MAX_PTXTSUB];
239 * Pass 1: find substitution locations and calculate sizes
241 nLine = strlen(cpLine);
242 nMatch = strlen(cpMatch);
243 nSubst = strlen(cpSubst);
244 for (cpI = (char *)cpLine, i = 0, nResult = 0;
245 cpI < cpLine+nLine && i < MAX_PTXTSUB; ) {
246 if ((cp = strstr(cpI, cpMatch)) != NULL) {
248 nResult += ((cp-cpI)+nSubst);
252 nResult += strlen(cpI);
261 * Pass 2: allocate memory and assemble result
263 cpResult = apr_pcalloc(p, nResult+1);
264 for (cpI = (char *)cpLine, cpO = cpResult, i = 0;
267 apr_cpystrn(cpO, cpI, cppMatch[i]-cpI+1);
268 cpO += (cppMatch[i]-cpI);
269 apr_cpystrn(cpO, cpSubst, nSubst+1);
271 cpI = (cppMatch[i]+nMatch);
273 apr_cpystrn(cpO, cpI, cpResult+nResult-cpO+1);
279 * certain key and cert data needs to survive restarts,
280 * which are stored in the user data table of s->process->pool.
281 * to prevent "leaking" of this data, we use malloc/free
282 * rather than apr_palloc and these wrappers to help make sure
283 * we do not leak the malloc-ed data.
285 unsigned char *ssl_asn1_table_set(apr_hash_t *table,
289 apr_ssize_t klen = strlen(key);
290 ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
293 * if a value for this key already exists,
294 * reuse as much of the already malloc-ed data
298 if (asn1->nData != length) {
299 free(asn1->cpData); /* XXX: realloc? */
304 asn1 = malloc(sizeof(*asn1));
305 asn1->source_mtime = 0; /* used as a note for encrypted private keys */
309 asn1->nData = length;
311 asn1->cpData = malloc(length);
314 apr_hash_set(table, key, klen, asn1);
316 return asn1->cpData; /* caller will assign a value to this */
319 ssl_asn1_t *ssl_asn1_table_get(apr_hash_t *table,
322 return (ssl_asn1_t *)apr_hash_get(table, key, APR_HASH_KEY_STRING);
325 void ssl_asn1_table_unset(apr_hash_t *table,
328 apr_ssize_t klen = strlen(key);
329 ssl_asn1_t *asn1 = apr_hash_get(table, key, klen);
340 apr_hash_set(table, key, klen, NULL);
343 static const char *ssl_asn1_key_types[] = {"RSA", "DSA"};
345 const char *ssl_asn1_keystr(int keytype)
347 if (keytype >= SSL_AIDX_MAX) {
351 return ssl_asn1_key_types[keytype];
354 const char *ssl_asn1_table_keyfmt(apr_pool_t *p,
358 const char *keystr = ssl_asn1_keystr(keytype);
360 return apr_pstrcat(p, id, ":", keystr, NULL);
366 * To ensure thread-safetyness in OpenSSL - work in progress
369 static apr_thread_mutex_t **lock_cs;
370 static int lock_num_locks;
372 #ifdef SSLC_VERSION_NUMBER
373 #if SSLC_VERSION_NUMBER >= 0x2000
374 static int ssl_util_thr_lock(int mode, int type,
375 const char *file, int line)
377 static void ssl_util_thr_lock(int mode, int type,
378 const char *file, int line)
381 static void ssl_util_thr_lock(int mode, int type,
382 const char *file, int line)
385 if (type < lock_num_locks) {
386 if (mode & CRYPTO_LOCK) {
387 apr_thread_mutex_lock(lock_cs[type]);
390 apr_thread_mutex_unlock(lock_cs[type]);
392 #ifdef SSLC_VERSION_NUMBER
393 #if SSLC_VERSION_NUMBER >= 0x2000
403 static unsigned long ssl_util_thr_id(void)
405 /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread
406 * id is a structure twice that big. Use the TCB pointer instead as a
407 * unique unsigned long.
412 unsigned long PSATOLD;
415 return psaptr->PSATOLD;
417 return (unsigned long) apr_os_thread_current();
421 static apr_status_t ssl_util_thread_cleanup(void *data)
423 CRYPTO_set_locking_callback(NULL);
424 CRYPTO_set_id_callback(NULL);
426 /* Let the registered mutex cleanups do their own thing
431 void ssl_util_thread_setup(apr_pool_t *p)
435 lock_num_locks = CRYPTO_num_locks();
436 lock_cs = apr_palloc(p, lock_num_locks * sizeof(*lock_cs));
438 for (i = 0; i < lock_num_locks; i++) {
439 apr_thread_mutex_create(&(lock_cs[i]), APR_THREAD_MUTEX_DEFAULT, p);
442 CRYPTO_set_id_callback(ssl_util_thr_id);
444 CRYPTO_set_locking_callback(ssl_util_thr_lock);
446 apr_pool_cleanup_register(p, NULL, ssl_util_thread_cleanup,
447 apr_pool_cleanup_null);