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_ssl.c 24 * Additional Utility Functions for OpenSSL 25 */ 26 27#include "ssl_private.h" 28 29/* _________________________________________________________________ 30** 31** Additional High-Level Functions for OpenSSL 32** _________________________________________________________________ 33*/ 34 35/* we initialize this index at startup time 36 * and never write to it at request time, 37 * so this static is thread safe. 38 * also note that OpenSSL increments at static variable when 39 * SSL_get_ex_new_index() is called, so we _must_ do this at startup. 40 */ 41static int SSL_app_data2_idx = -1; 42 43void SSL_init_app_data2_idx(void) 44{ 45 int i; 46 47 if (SSL_app_data2_idx > -1) { 48 return; 49 } 50 51 /* we _do_ need to call this twice */ 52 for (i=0; i<=1; i++) { 53 SSL_app_data2_idx = 54 SSL_get_ex_new_index(0, 55 "Second Application Data for SSL", 56 NULL, NULL, NULL); 57 } 58} 59 60void *SSL_get_app_data2(SSL *ssl) 61{ 62 return (void *)SSL_get_ex_data(ssl, SSL_app_data2_idx); 63} 64 65void SSL_set_app_data2(SSL *ssl, void *arg) 66{ 67 SSL_set_ex_data(ssl, SSL_app_data2_idx, (char *)arg); 68 return; 69} 70 71/* _________________________________________________________________ 72** 73** High-Level Certificate / Private Key Loading 74** _________________________________________________________________ 75*/ 76 77X509 *SSL_read_X509(char* filename, X509 **x509, modssl_read_bio_cb_fn *cb) 78{ 79 X509 *rc; 80 BIO *bioS; 81 BIO *bioF; 82 83 /* 1. try PEM (= DER+Base64+headers) */ 84 if ((bioS=BIO_new_file(filename, "r")) == NULL) 85 return NULL; 86 rc = modssl_PEM_read_bio_X509 (bioS, x509, cb, NULL); 87 BIO_free(bioS); 88 89 if (rc == NULL) { 90 /* 2. try DER+Base64 */ 91 if ((bioS=BIO_new_file(filename, "r")) == NULL) 92 return NULL; 93 94 if ((bioF = BIO_new(BIO_f_base64())) == NULL) { 95 BIO_free(bioS); 96 return NULL; 97 } 98 bioS = BIO_push(bioF, bioS); 99 rc = d2i_X509_bio(bioS, NULL); 100 BIO_free_all(bioS); 101 102 if (rc == NULL) { 103 /* 3. try plain DER */ 104 if ((bioS=BIO_new_file(filename, "r")) == NULL) 105 return NULL; 106 rc = d2i_X509_bio(bioS, NULL); 107 BIO_free(bioS); 108 } 109 } 110 if (rc != NULL && x509 != NULL) { 111 if (*x509 != NULL) 112 X509_free(*x509); 113 *x509 = rc; 114 } 115 return rc; 116} 117 118#if SSL_LIBRARY_VERSION <= 0x00904100 119static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY **key) 120{ 121 return ((EVP_PKEY *)ASN1_d2i_bio( 122 (char *(*)())EVP_PKEY_new, 123 (char *(*)())d2i_PrivateKey, 124 (bio), (unsigned char **)(key))); 125} 126#endif 127 128EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, modssl_read_bio_cb_fn *cb, void *s) 129{ 130 EVP_PKEY *rc; 131 BIO *bioS; 132 BIO *bioF; 133 134 /* 1. try PEM (= DER+Base64+headers) */ 135 if ((bioS=BIO_new_file(filename, "r")) == NULL) 136 return NULL; 137 rc = modssl_PEM_read_bio_PrivateKey(bioS, key, cb, s); 138 BIO_free(bioS); 139 140 if (rc == NULL) { 141 /* 2. try DER+Base64 */ 142 if ((bioS = BIO_new_file(filename, "r")) == NULL) 143 return NULL; 144 145 if ((bioF = BIO_new(BIO_f_base64())) == NULL) { 146 BIO_free(bioS); 147 return NULL; 148 } 149 bioS = BIO_push(bioF, bioS); 150 rc = d2i_PrivateKey_bio(bioS, NULL); 151 BIO_free_all(bioS); 152 153 if (rc == NULL) { 154 /* 3. try plain DER */ 155 if ((bioS = BIO_new_file(filename, "r")) == NULL) 156 return NULL; 157 rc = d2i_PrivateKey_bio(bioS, NULL); 158 BIO_free(bioS); 159 } 160 } 161 if (rc != NULL && key != NULL) { 162 if (*key != NULL) 163 EVP_PKEY_free(*key); 164 *key = rc; 165 } 166 return rc; 167} 168 169/* _________________________________________________________________ 170** 171** Smart shutdown 172** _________________________________________________________________ 173*/ 174 175int SSL_smart_shutdown(SSL *ssl) 176{ 177 int i; 178 int rc; 179 180 /* 181 * Repeat the calls, because SSL_shutdown internally dispatches through a 182 * little state machine. Usually only one or two interation should be 183 * needed, so we restrict the total number of restrictions in order to 184 * avoid process hangs in case the client played bad with the socket 185 * connection and OpenSSL cannot recognize it. 186 */ 187 rc = 0; 188 for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) { 189 if ((rc = SSL_shutdown(ssl))) 190 break; 191 } 192 return rc; 193} 194 195/* _________________________________________________________________ 196** 197** Certificate Revocation List (CRL) Storage 198** _________________________________________________________________ 199*/ 200 201X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath) 202{ 203 X509_STORE *pStore; 204 X509_LOOKUP *pLookup; 205 int rv = 1; 206 207 ERR_clear_error(); 208 209 if (cpFile == NULL && cpPath == NULL) 210 return NULL; 211 if ((pStore = X509_STORE_new()) == NULL) 212 return NULL; 213 if (cpFile != NULL) { 214 pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()); 215 if (pLookup == NULL) { 216 X509_STORE_free(pStore); 217 return NULL; 218 } 219 rv = X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM); 220 } 221 if (cpPath != NULL && rv == 1) { 222 pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir()); 223 if (pLookup == NULL) { 224 X509_STORE_free(pStore); 225 return NULL; 226 } 227 rv = X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM); 228 } 229 return rv == 1 ? pStore : NULL; 230} 231 232int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType, 233 X509_NAME *pName, X509_OBJECT *pObj) 234{ 235 X509_STORE_CTX pStoreCtx; 236 int rc; 237 238 X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL); 239 rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj); 240 X509_STORE_CTX_cleanup(&pStoreCtx); 241 return rc; 242} 243 244/* _________________________________________________________________ 245** 246** Cipher Suite Spec String Creation 247** _________________________________________________________________ 248*/ 249 250char *SSL_make_ciphersuite(apr_pool_t *p, SSL *ssl) 251{ 252 STACK_OF(SSL_CIPHER) *sk; 253 SSL_CIPHER *c; 254 int i; 255 int l; 256 char *cpCipherSuite; 257 char *cp; 258 259 if (ssl == NULL) 260 return ""; 261 if ((sk = (STACK_OF(SSL_CIPHER) *)SSL_get_ciphers(ssl)) == NULL) 262 return ""; 263 l = 0; 264 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { 265 c = sk_SSL_CIPHER_value(sk, i); 266 l += strlen(SSL_CIPHER_get_name(c))+2+1; 267 } 268 if (l == 0) 269 return ""; 270 cpCipherSuite = (char *)apr_palloc(p, l+1); 271 cp = cpCipherSuite; 272 for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { 273 c = sk_SSL_CIPHER_value(sk, i); 274 l = strlen(SSL_CIPHER_get_name(c)); 275 memcpy(cp, SSL_CIPHER_get_name(c), l); 276 cp += l; 277 *cp++ = '/'; 278 *cp++ = (SSL_CIPHER_get_valid(c) == 1 ? '1' : '0'); 279 *cp++ = ':'; 280 } 281 *(cp-1) = NUL; 282 return cpCipherSuite; 283} 284 285/* _________________________________________________________________ 286** 287** Certificate Checks 288** _________________________________________________________________ 289*/ 290 291/* check whether cert contains extended key usage with a SGC tag */ 292BOOL SSL_X509_isSGC(X509 *cert) 293{ 294#ifdef HAVE_SSL_X509V3_EXT_d2i 295 X509_EXTENSION *ext; 296 int ext_nid; 297 EXTENDED_KEY_USAGE *sk; 298 BOOL is_sgc; 299 int idx; 300 int i; 301 302 is_sgc = FALSE; 303 idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1); 304 if (idx >= 0) { 305 ext = X509_get_ext(cert, idx); 306 if ((sk = (EXTENDED_KEY_USAGE *)X509V3_EXT_d2i(ext)) != NULL) { 307 for (i = 0; i < sk_ASN1_OBJECT_num(sk); i++) { 308 ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_ASN1_OBJECT_value(sk, i)); 309 if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) { 310 is_sgc = TRUE; 311 break; 312 } 313 } 314 } 315 } 316 return is_sgc; 317#else 318 return FALSE; 319#endif 320} 321 322/* retrieve basic constraints ingredients */ 323BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen) 324{ 325#ifdef HAVE_SSL_X509V3_EXT_d2i 326 X509_EXTENSION *ext; 327 BASIC_CONSTRAINTS *bc; 328 int idx; 329 BIGNUM *bn = NULL; 330 char *cp; 331 332 if ((idx = X509_get_ext_by_NID(cert, NID_basic_constraints, -1)) < 0) 333 return FALSE; 334 ext = X509_get_ext(cert, idx); 335 if (ext == NULL) 336 return FALSE; 337 if ((bc = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext)) == NULL) 338 return FALSE; 339 *ca = bc->ca; 340 *pathlen = -1 /* unlimited */; 341 if (bc->pathlen != NULL) { 342 if ((bn = ASN1_INTEGER_to_BN(bc->pathlen, NULL)) == NULL) 343 return FALSE; 344 if ((cp = BN_bn2dec(bn)) == NULL) 345 return FALSE; 346 *pathlen = atoi(cp); 347 free(cp); 348 BN_free(bn); 349 } 350 BASIC_CONSTRAINTS_free(bc); 351 return TRUE; 352#else 353 return FALSE; 354#endif 355} 356 357/* retrieve subject CommonName of certificate */ 358BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN) 359{ 360 X509_NAME *xsn; 361 X509_NAME_ENTRY *xsne; 362 int i, nid; 363 unsigned char *data_ptr; 364 int data_len; 365 366 xsn = X509_get_subject_name(xs); 367 for (i = 0; i < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) 368 X509_NAME_get_entries(xsn)); i++) { 369 xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) 370 X509_NAME_get_entries(xsn), i); 371 nid = OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); 372 if (nid == NID_commonName) { 373 data_ptr = X509_NAME_ENTRY_get_data_ptr(xsne); 374 data_len = X509_NAME_ENTRY_get_data_len(xsne); 375 *cppCN = apr_palloc(p, data_len+1); 376 apr_cpystrn(*cppCN, (char *)data_ptr, data_len+1); 377 (*cppCN)[data_len] = NUL; 378 ap_xlate_proto_from_ascii(*cppCN, data_len); 379 return TRUE; 380 } 381 } 382 return FALSE; 383} 384 385/* 386 * convert an X509_NAME to an RFC 2253 formatted string, optionally truncated 387 * to maxlen characters (specify a maxlen of 0 for no length limit) 388 */ 389char *SSL_X509_NAME_to_string(apr_pool_t *p, X509_NAME *dn, unsigned int maxlen) 390{ 391 char *result = NULL; 392 BIO *bio; 393 int len; 394 395 if ((bio = BIO_new(BIO_s_mem())) == NULL) 396 return NULL; 397 X509_NAME_print_ex(bio, dn, 0, XN_FLAG_RFC2253); 398 len = BIO_pending(bio); 399 if (len > 0) { 400 result = apr_palloc(p, maxlen ? maxlen+1 : len+1); 401 if (maxlen && maxlen < len) { 402 len = BIO_read(bio, result, maxlen); 403 if (maxlen > 2) { 404 /* insert trailing ellipsis if there's enough space */ 405 apr_snprintf(result + maxlen - 3, 4, "..."); 406 } 407 } else { 408 len = BIO_read(bio, result, len); 409 } 410 result[len] = NUL; 411 } 412 BIO_free(bio); 413 414 return result; 415} 416 417/* _________________________________________________________________ 418** 419** Low-Level CA Certificate Loading 420** _________________________________________________________________ 421*/ 422 423BOOL SSL_X509_INFO_load_file(apr_pool_t *ptemp, 424 STACK_OF(X509_INFO) *sk, 425 const char *filename) 426{ 427 BIO *in; 428 429 if (!(in = BIO_new(BIO_s_file()))) { 430 return FALSE; 431 } 432 433 if (BIO_read_filename(in, MODSSL_PCHAR_CAST filename) <= 0) { 434 BIO_free(in); 435 return FALSE; 436 } 437 438 ERR_clear_error(); 439 440 modssl_PEM_X509_INFO_read_bio(in, sk, NULL, NULL); 441 442 BIO_free(in); 443 444 return TRUE; 445} 446 447BOOL SSL_X509_INFO_load_path(apr_pool_t *ptemp, 448 STACK_OF(X509_INFO) *sk, 449 const char *pathname) 450{ 451 /* XXX: this dir read code is exactly the same as that in 452 * ssl_engine_init.c, only the call to handle the fullname is different, 453 * should fold the duplication. 454 */ 455 apr_dir_t *dir; 456 apr_finfo_t dirent; 457 apr_int32_t finfo_flags = APR_FINFO_TYPE|APR_FINFO_NAME; 458 const char *fullname; 459 BOOL ok = FALSE; 460 461 if (apr_dir_open(&dir, pathname, ptemp) != APR_SUCCESS) { 462 return FALSE; 463 } 464 465 while ((apr_dir_read(&dirent, finfo_flags, dir)) == APR_SUCCESS) { 466 if (dirent.filetype == APR_DIR) { 467 continue; /* don't try to load directories */ 468 } 469 470 fullname = apr_pstrcat(ptemp, 471 pathname, "/", dirent.name, 472 NULL); 473 474 if (SSL_X509_INFO_load_file(ptemp, sk, fullname)) { 475 ok = TRUE; 476 } 477 } 478 479 apr_dir_close(dir); 480 481 return ok; 482} 483 484/* _________________________________________________________________ 485** 486** Extra Server Certificate Chain Support 487** _________________________________________________________________ 488*/ 489 490/* 491 * Read a file that optionally contains the server certificate in PEM 492 * format, possibly followed by a sequence of CA certificates that 493 * should be sent to the peer in the SSL Certificate message. 494 */ 495int SSL_CTX_use_certificate_chain( 496 SSL_CTX *ctx, char *file, int skipfirst, modssl_read_bio_cb_fn *cb) 497{ 498 BIO *bio; 499 X509 *x509; 500 unsigned long err; 501 int n; 502 STACK_OF(X509) *extra_certs; 503 504 if ((bio = BIO_new(BIO_s_file_internal())) == NULL) 505 return -1; 506 if (BIO_read_filename(bio, file) <= 0) { 507 BIO_free(bio); 508 return -1; 509 } 510 /* optionally skip a leading server certificate */ 511 if (skipfirst) { 512 if ((x509 = modssl_PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) { 513 BIO_free(bio); 514 return -1; 515 } 516 X509_free(x509); 517 } 518 /* free a perhaps already configured extra chain */ 519 extra_certs=SSL_CTX_get_extra_certs(ctx); 520 if (extra_certs != NULL) { 521 sk_X509_pop_free((STACK_OF(X509) *)extra_certs, X509_free); 522 SSL_CTX_set_extra_certs(ctx,NULL); 523 } 524 /* create new extra chain by loading the certs */ 525 n = 0; 526 while ((x509 = modssl_PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) { 527 if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) { 528 X509_free(x509); 529 BIO_free(bio); 530 return -1; 531 } 532 n++; 533 } 534 /* Make sure that only the error is just an EOF */ 535 if ((err = ERR_peek_error()) > 0) { 536 if (!( ERR_GET_LIB(err) == ERR_LIB_PEM 537 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { 538 BIO_free(bio); 539 return -1; 540 } 541 while (ERR_get_error() > 0) ; 542 } 543 BIO_free(bio); 544 return n; 545} 546 547/* _________________________________________________________________ 548** 549** Session Stuff 550** _________________________________________________________________ 551*/ 552 553char *SSL_SESSION_id2sz(unsigned char *id, int idlen, 554 char *str, int strsize) 555{ 556 char *cp; 557 int n; 558 559 cp = str; 560 for (n = 0; n < idlen && n < SSL_MAX_SSL_SESSION_ID_LENGTH; n++) { 561 apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); 562 cp += 2; 563 } 564 *cp = NUL; 565 return str; 566} 567 568/* sslc+OpenSSL compat */ 569 570int modssl_session_get_time(SSL_SESSION *session) 571{ 572#ifdef OPENSSL_VERSION_NUMBER 573 return SSL_SESSION_get_time(session); 574#else /* assume sslc */ 575 CRYPTO_TIME_T ct; 576 SSL_SESSION_get_time(session, &ct); 577 return CRYPTO_time_to_int(&ct); 578#endif 579} 580 581#ifndef SSLC_VERSION_NUMBER 582#define SSLC_VERSION_NUMBER 0x0000 583#endif 584 585DH *modssl_dh_configure(unsigned char *p, int plen, 586 unsigned char *g, int glen) 587{ 588 DH *dh; 589 590 if (!(dh = DH_new())) { 591 return NULL; 592 } 593 594#if defined(OPENSSL_VERSION_NUMBER) || (SSLC_VERSION_NUMBER < 0x2000) 595 dh->p = BN_bin2bn(p, plen, NULL); 596 dh->g = BN_bin2bn(g, glen, NULL); 597 if (!(dh->p && dh->g)) { 598 DH_free(dh); 599 return NULL; 600 } 601#else 602 R_EITEMS_add(dh->data, PK_TYPE_DH, PK_DH_P, 0, p, plen, R_EITEMS_PF_COPY); 603 R_EITEMS_add(dh->data, PK_TYPE_DH, PK_DH_G, 0, g, glen, R_EITEMS_PF_COPY); 604#endif 605 606 return dh; 607} 608