2 ** _ __ ___ ___ __| | ___ ___| | mod_ssl
3 ** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
8 ** Additional Utility Functions for OpenSSL
11 /* ====================================================================
12 * The Apache Software License, Version 1.1
14 * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
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
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.
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.
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.
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
57 * ====================================================================
62 /* _________________________________________________________________
64 ** Additional High-Level Functions for OpenSSL
65 ** _________________________________________________________________
68 int SSL_get_app_data2_idx(void)
70 static int app_data2_idx = -1;
72 if (app_data2_idx < 0) {
73 app_data2_idx = SSL_get_ex_new_index(0,
74 "Second Application Data for SSL", NULL, NULL, NULL);
75 app_data2_idx = SSL_get_ex_new_index(0,
76 "Second Application Data for SSL", NULL, NULL, NULL);
78 return(app_data2_idx);
81 void *SSL_get_app_data2(SSL *ssl)
83 return (void *)SSL_get_ex_data(ssl, SSL_get_app_data2_idx());
86 void SSL_set_app_data2(SSL *ssl, void *arg)
88 SSL_set_ex_data(ssl, SSL_get_app_data2_idx(), (char *)arg);
92 /* _________________________________________________________________
94 ** High-Level Certificate / Private Key Loading
95 ** _________________________________________________________________
98 X509 *SSL_read_X509(FILE *fp, X509 **x509, int (*cb)())
104 /* 1. try PEM (= DER+Base64+headers) */
105 #if SSL_LIBRARY_VERSION < 0x00904000
106 rc = PEM_read_X509(fp, x509, cb);
108 rc = PEM_read_X509(fp, x509, cb, NULL);
111 /* 2. try DER+Base64 */
112 fseek(fp, 0L, SEEK_SET);
113 if ((bioS = BIO_new(BIO_s_fd())) == NULL)
115 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
116 if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
120 bioS = BIO_push(bioF, bioS);
121 rc = d2i_X509_bio(bioS, NULL);
124 /* 3. try plain DER */
125 fseek(fp, 0L, SEEK_SET);
126 if ((bioS = BIO_new(BIO_s_fd())) == NULL)
128 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
129 rc = d2i_X509_bio(bioS, NULL);
133 if (rc != NULL && x509 != NULL) {
141 #if SSL_LIBRARY_VERSION <= 0x00904100
142 static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY **key)
144 return ((EVP_PKEY *)ASN1_d2i_bio(
145 (char *(*)())EVP_PKEY_new,
146 (char *(*)())d2i_PrivateKey,
147 (bio), (unsigned char **)(key)));
151 EVP_PKEY *SSL_read_PrivateKey(FILE *fp, EVP_PKEY **key, int (*cb)())
157 /* 1. try PEM (= DER+Base64+headers) */
158 #if SSL_LIBRARY_VERSION < 0x00904000
159 rc = PEM_read_PrivateKey(fp, key, cb);
161 rc = PEM_read_PrivateKey(fp, key, cb, NULL);
164 /* 2. try DER+Base64 */
165 fseek(fp, 0L, SEEK_SET);
166 if ((bioS = BIO_new(BIO_s_fd())) == NULL)
168 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
169 if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
173 bioS = BIO_push(bioF, bioS);
174 rc = d2i_PrivateKey_bio(bioS, NULL);
177 /* 3. try plain DER */
178 fseek(fp, 0L, SEEK_SET);
179 if ((bioS = BIO_new(BIO_s_fd())) == NULL)
181 BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
182 rc = d2i_PrivateKey_bio(bioS, NULL);
186 if (rc != NULL && key != NULL) {
194 /* _________________________________________________________________
197 ** _________________________________________________________________
200 int SSL_smart_shutdown(SSL *ssl)
206 * Repeat the calls, because SSL_shutdown internally dispatches through a
207 * little state machine. Usually only one or two interation should be
208 * needed, so we restrict the total number of restrictions in order to
209 * avoid process hangs in case the client played bad with the socket
210 * connection and OpenSSL cannot recognize it.
213 for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) {
214 if ((rc = SSL_shutdown(ssl)))
220 /* _________________________________________________________________
222 ** Certificate Revocation List (CRL) Storage
223 ** _________________________________________________________________
226 X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath)
229 X509_LOOKUP *pLookup;
231 if (cpFile == NULL && cpPath == NULL)
233 if ((pStore = X509_STORE_new()) == NULL)
235 if (cpFile != NULL) {
236 if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file())) == NULL) {
237 X509_STORE_free(pStore);
240 X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
242 if (cpPath != NULL) {
243 if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir())) == NULL) {
244 X509_STORE_free(pStore);
247 X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
252 int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
253 X509_NAME *pName, X509_OBJECT *pObj)
255 X509_STORE_CTX pStoreCtx;
258 X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
259 rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
260 X509_STORE_CTX_cleanup(&pStoreCtx);
264 /* _________________________________________________________________
266 ** Cipher Suite Spec String Creation
267 ** _________________________________________________________________
270 char *SSL_make_ciphersuite(apr_pool_t *p, SSL *ssl)
272 STACK_OF(SSL_CIPHER) *sk;
281 if ((sk = SSL_get_ciphers(ssl)) == NULL)
284 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
285 c = sk_SSL_CIPHER_value(sk, i);
286 l += strlen(c->name)+2+1;
290 cpCipherSuite = (char *)apr_palloc(p, l+1);
292 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
293 c = sk_SSL_CIPHER_value(sk, i);
295 memcpy(cp, c->name, l);
298 *cp++ = (c->valid == 1 ? '1' : '0');
302 return cpCipherSuite;
305 /* _________________________________________________________________
307 ** Certificate Checks
308 ** _________________________________________________________________
311 /* check whether cert contains extended key usage with a SGC tag */
312 BOOL SSL_X509_isSGC(X509 *cert)
322 idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
324 ext = X509_get_ext(cert, idx);
325 if ((sk = (STACK *)X509V3_EXT_d2i(ext)) != NULL) {
326 for (i = 0; i < sk_num(sk); i++) {
327 ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_value(sk, i));
328 if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {
338 /* retrieve basic constraints ingredients */
339 BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
342 BASIC_CONSTRAINTS *bc;
347 if ((idx = X509_get_ext_by_NID(cert, NID_basic_constraints, -1)) < 0)
349 ext = X509_get_ext(cert, idx);
352 if ((bc = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext)) == NULL)
355 *pathlen = -1 /* unlimited */;
356 if (bc->pathlen != NULL) {
357 if ((bn = ASN1_INTEGER_to_BN(bc->pathlen, NULL)) == NULL)
359 if ((cp = BN_bn2dec(bn)) == NULL)
365 BASIC_CONSTRAINTS_free(bc);
369 /* retrieve subject CommonName of certificate */
370 BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN)
373 X509_NAME_ENTRY *xsne;
376 xsn = X509_get_subject_name(xs);
377 for (i = 0; i < sk_X509_NAME_ENTRY_num(xsn->entries); i++) {
378 xsne = sk_X509_NAME_ENTRY_value(xsn->entries, i);
379 nid = OBJ_obj2nid(xsne->object);
380 if (nid == NID_commonName) {
381 *cppCN = apr_palloc(p, xsne->value->length+1);
382 apr_cpystrn(*cppCN, (char *)xsne->value->data, xsne->value->length+1);
383 (*cppCN)[xsne->value->length] = NUL;
384 #ifdef CHARSET_EBCDIC
385 ascii2ebcdic(*cppCN, *cppCN, strlen(*cppCN));
393 /* _________________________________________________________________
395 ** Low-Level CA Certificate Loading
396 ** _________________________________________________________________
399 #ifdef SSL_EXPERIMENTAL_PROXY
401 BOOL SSL_load_CrtAndKeyInfo_file(apr_pool_t *p, STACK_OF(X509_INFO) *sk, char *filename)
405 if ((in = BIO_new(BIO_s_file())) == NULL)
407 if (BIO_read_filename(in, filename) <= 0) {
412 #if SSL_LIBRARY_VERSION < 0x00904000
413 PEM_X509_INFO_read_bio(in, sk, NULL);
415 PEM_X509_INFO_read_bio(in, sk, NULL, NULL);
421 BOOL SSL_load_CrtAndKeyInfo_path(apr_pool_t *p, STACK_OF(X509_INFO) *sk, char *pathname)
429 sp = apr_pool_sub_make(p, NULL);
430 if (apr_dir_open(&dir, pathname, sp)) != APR_SUCCESS) {
431 apr_pool_destroy(sp);
435 while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dir)) == APR_SUCCESS) {
436 fullname = apr_pstrcat(sp, pathname, "/", dirent.name, NULL);
437 if (dirent.filetype != APR_REG)
439 if (SSL_load_CrtAndKeyInfo_file(sp, sk, fullname))
443 apr_pool_destroy(sp);
447 #endif /* SSL_EXPERIMENTAL_PROXY */
449 /* _________________________________________________________________
451 ** Extra Server Certificate Chain Support
452 ** _________________________________________________________________
456 * Read a file that optionally contains the server certificate in PEM
457 * format, possibly followed by a sequence of CA certificates that
458 * should be sent to the peer in the SSL Certificate message.
460 int SSL_CTX_use_certificate_chain(
461 SSL_CTX *ctx, char *file, int skipfirst, int (*cb)())
468 if ((bio = BIO_new(BIO_s_file_internal())) == NULL)
470 if (BIO_read_filename(bio, file) <= 0) {
474 /* optionally skip a leading server certificate */
476 #if SSL_LIBRARY_VERSION < 0x00904000
477 if ((x509 = PEM_read_bio_X509(bio, NULL, cb)) == NULL) {
479 if ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) {
486 /* free a perhaps already configured extra chain */
487 if (ctx->extra_certs != NULL) {
488 sk_X509_pop_free(ctx->extra_certs, X509_free);
489 ctx->extra_certs = NULL;
491 /* create new extra chain by loading the certs */
493 #if SSL_LIBRARY_VERSION < 0x00904000
494 while ((x509 = PEM_read_bio_X509(bio, NULL, cb)) != NULL) {
496 while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) {
498 if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
505 /* Make sure that only the error is just an EOF */
506 if ((err = ERR_peek_error()) > 0) {
507 if (!( ERR_GET_LIB(err) == ERR_LIB_PEM
508 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
512 while (ERR_get_error() > 0) ;
518 /* _________________________________________________________________
521 ** _________________________________________________________________
524 char *SSL_SESSION_id2sz(unsigned char *id, int idlen)
526 static char str[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2];
531 for (n = 0; n < idlen && n < SSL_MAX_SSL_SESSION_ID_LENGTH; n++) {
532 apr_snprintf(cp, sizeof(str)-(cp-str), "%02X", id[n]);