1 /* $NetBSD: tls_misc.c,v 1.1.1.1 2009/06/23 10:08:57 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* tls_misc 3 6 /* SUMMARY 7 /* miscellaneous TLS support routines 8 /* SYNOPSIS 9 /* #define TLS_INTERNAL 10 /* #include <tls.h> 11 /* 12 /* char *var_tls_high_clist; 13 /* char *var_tls_medium_clist; 14 /* char *var_tls_low_clist; 15 /* char *var_tls_export_clist; 16 /* char *var_tls_null_clist; 17 /* char *var_tls_eecdh_strong; 18 /* char *var_tls_eecdh_ultra; 19 /* int var_tls_daemon_rand_bytes; 20 /* 21 /* TLS_APPL_STATE *tls_alloc_app_context(ssl_ctx) 22 /* SSL_CTX *ssl_ctx; 23 /* 24 /* void tls_free_app_context(app_ctx) 25 /* void *app_ctx; 26 /* 27 /* TLS_SESS_STATE *tls_alloc_sess_context(log_level, namaddr) 28 /* int log_level; 29 /* const char *namaddr; 30 /* 31 /* void tls_free_context(TLScontext) 32 /* TLS_SESS_STATE *TLScontext; 33 /* 34 /* void tls_check_version() 35 /* 36 /* long tls_bug_bits() 37 /* 38 /* void tls_param_init() 39 /* 40 /* int tls_protocol_mask(plist) 41 /* const char *plist; 42 /* 43 /* int tls_cipher_grade(name) 44 /* const char *name; 45 /* 46 /* const char *str_tls_cipher_grade(grade) 47 /* int grade; 48 /* 49 /* const char *tls_set_ciphers(app_ctx, context, grade, exclusions) 50 /* TLS_APPL_STATE *app_ctx; 51 /* const char *context; 52 /* int grade; 53 /* const char *exclusions; 54 /* 55 /* void tls_print_errors() 56 /* 57 /* void tls_info_callback(ssl, where, ret) 58 /* const SSL *ssl; /* unused */ 59 /* int where; 60 /* int ret; 61 /* 62 /* long tls_bio_dump_cb(bio, cmd, argp, argi, argl, ret) 63 /* BIO *bio; 64 /* int cmd; 65 /* const char *argp; 66 /* int argi; 67 /* long argl; /* unused */ 68 /* long ret; 69 /* DESCRIPTION 70 /* This module implements routines that support the TLS client 71 /* and server internals. 72 /* 73 /* tls_alloc_app_context() creates an application context that 74 /* holds the SSL context for the application and related cached state. 75 /* 76 /* tls_free_app_context() deallocates the application context and its 77 /* contents (the application context is stored outside the TLS library). 78 /* 79 /* tls_alloc_sess_context() creates an initialized TLS session context 80 /* structure with the specified log mask and peer name[addr]. 81 /* 82 /* tls_free_context() destroys a TLScontext structure 83 /* together with OpenSSL structures that are attached to it. 84 /* 85 /* tls_check_version() logs a warning when the run-time OpenSSL 86 /* library differs in its major, minor or micro number from 87 /* the compile-time OpenSSL headers. 88 /* 89 /* tls_bug_bits() returns the bug compatibility mask appropriate 90 /* for the run-time library. Some of the bug work-arounds are 91 /* not appropriate for some library versions. 92 /* 93 /* tls_param_init() loads main.cf parameters used internally in 94 /* TLS library. Any errors are fatal. 95 /* 96 /* tls_protocol_mask() returns a bitmask of excluded protocols, given 97 /* a list (plist) of protocols to include or (preceded by a '!') exclude. 98 /* If "plist" contains invalid protocol names, TLS_PROTOCOL_INVALID is 99 /* returned and no warning is logged. 100 /* 101 /* tls_cipher_grade() converts a case-insensitive cipher grade 102 /* name (high, medium, low, export, null) to the corresponding 103 /* TLS_CIPHER_ constant. When the input specifies an unrecognized 104 /* grade, tls_cipher_grade() logs no warning, and returns 105 /* TLS_CIPHER_NONE. 106 /* 107 /* str_tls_cipher_grade() converts a cipher grade to a name. 108 /* When the input specifies an undefined grade, str_tls_cipher_grade() 109 /* logs no warning, returns a null pointer. 110 /* 111 /* tls_set_ciphers() generates a cipher list from the specified 112 /* grade, minus any ciphers specified via a list of exclusions. 113 /* The cipherlist is applied to the supplied SSL context if it 114 /* is different from the most recently applied value. The return 115 /* value is the cipherlist used and is overwritten upon each call. 116 /* When the input is invalid, tls_set_ciphers() logs a warning with 117 /* the specified context, and returns a null pointer result. 118 /* 119 /* tls_print_errors() queries the OpenSSL error stack, 120 /* logs the error messages, and clears the error stack. 121 /* 122 /* tls_info_callback() is a call-back routine for the 123 /* SSL_CTX_set_info_callback() routine. It logs SSL events 124 /* to the Postfix logfile. 125 /* 126 /* tls_bio_dump_cb() is a call-back routine for the 127 /* BIO_set_callback() routine. It logs SSL content to the 128 /* Postfix logfile. 129 /* LICENSE 130 /* .ad 131 /* .fi 132 /* This software is free. You can do with it whatever you want. 133 /* The original author kindly requests that you acknowledge 134 /* the use of his software. 135 /* AUTHOR(S) 136 /* Originally written by: 137 /* Lutz Jaenicke 138 /* BTU Cottbus 139 /* Allgemeine Elektrotechnik 140 /* Universitaetsplatz 3-4 141 /* D-03044 Cottbus, Germany 142 /* 143 /* Updated by: 144 /* Wietse Venema 145 /* IBM T.J. Watson Research 146 /* P.O. Box 704 147 /* Yorktown Heights, NY 10598, USA 148 /* 149 /* Victor Duchovni 150 /* Morgan Stanley 151 /*--*/ 152 153 /* System library. */ 154 155 #include <sys_defs.h> 156 #include <ctype.h> 157 #include <string.h> 158 159 #ifdef USE_TLS 160 161 /* Utility library. */ 162 163 #include <vstream.h> 164 #include <msg.h> 165 #include <mymalloc.h> 166 #include <vstring.h> 167 #include <stringops.h> 168 #include <argv.h> 169 170 /* 171 * Global library. 172 */ 173 #include <mail_params.h> 174 #include <mail_conf.h> 175 176 /* 177 * TLS library. 178 */ 179 #define TLS_INTERNAL 180 #include <tls.h> 181 182 /* Application-specific. */ 183 184 /* 185 * Tunable parameters. 186 */ 187 char *var_tls_high_clist; 188 char *var_tls_medium_clist; 189 char *var_tls_low_clist; 190 char *var_tls_export_clist; 191 char *var_tls_null_clist; 192 int var_tls_daemon_rand_bytes; 193 char *var_tls_eecdh_strong; 194 char *var_tls_eecdh_ultra; 195 196 /* 197 * Index to attach TLScontext pointers to SSL objects, so that they can be 198 * accessed by call-back routines. 199 */ 200 int TLScontext_index = -1; 201 202 /* 203 * Protocol name <=> mask conversion. 204 */ 205 static const NAME_CODE protocol_table[] = { 206 SSL_TXT_SSLV2, TLS_PROTOCOL_SSLv2, 207 SSL_TXT_SSLV3, TLS_PROTOCOL_SSLv3, 208 SSL_TXT_TLSV1, TLS_PROTOCOL_TLSv1, 209 0, TLS_PROTOCOL_INVALID, 210 }; 211 212 /* 213 * Ciphersuite name <=> code conversion. 214 */ 215 const NAME_CODE tls_cipher_grade_table[] = { 216 "high", TLS_CIPHER_HIGH, 217 "medium", TLS_CIPHER_MEDIUM, 218 "low", TLS_CIPHER_LOW, 219 "export", TLS_CIPHER_EXPORT, 220 "null", TLS_CIPHER_NULL, 221 "invalid", TLS_CIPHER_NONE, 222 0, TLS_CIPHER_NONE, 223 }; 224 225 /* 226 * Parsed OpenSSL version number. 227 */ 228 typedef struct { 229 int major; 230 int minor; 231 int micro; 232 int patch; 233 int status; 234 } TLS_VINFO; 235 236 /* 237 * OpenSSL adopted the cipher selection patch, so we don't expect any more 238 * broken ciphers other than AES and CAMELLIA. 239 */ 240 typedef struct { 241 const char *ssl_name; 242 const int alg_bits; 243 const char *evp_name; 244 } cipher_probe_t; 245 246 static const cipher_probe_t cipher_probes[] = { 247 "AES", 256, "AES-256-CBC", 248 "CAMELLIA", 256, "CAMELLIA-256-CBC", 249 0, 0, 0, 250 }; 251 252 /* tls_exclude_missing - Append exclusions for missing ciphers */ 253 254 static const char *tls_exclude_missing(SSL_CTX *ctx, VSTRING *buf) 255 { 256 const char *myname = "tls_exclude_missing"; 257 static ARGV *exclude; /* Cached */ 258 SSL *s = 0; 259 260 STACK_OF(SSL_CIPHER) * ciphers; 261 SSL_CIPHER *c; 262 const cipher_probe_t *probe; 263 int alg_bits; 264 int num; 265 int i; 266 267 /* 268 * Process a list of probes which specify: 269 * 270 * An SSL cipher-suite name for a family of ciphers that use the same 271 * symmetric algorithm at two or more key sizes, typically 128/256 bits. 272 * 273 * The key size (typically 256) that OpenSSL fails to check, and assumes 274 * available when another key size (typically 128) is usable. 275 * 276 * The OpenSSL name of the symmetric algorithm associated with the SSL 277 * cipher-suite. Typically, this is MUMBLE-256-CBC, where "MUMBLE" is the 278 * name of the SSL cipher-suite that use the MUMBLE symmetric algorithm. 279 * On systems that support the required encryption algorithm, the name is 280 * listed in the output of "openssl list-cipher-algorithms". 281 * 282 * When an encryption algorithm is not available at the given key size but 283 * the corresponding OpenSSL cipher-suite contains ciphers that have have 284 * this key size, the problem ciphers are explicitly disabled in Postfix. 285 * The list is cached in the static "exclude" array. 286 */ 287 if (exclude == 0) { 288 exclude = argv_alloc(1); 289 290 /* 291 * Iterate over the probe list 292 */ 293 for (probe = cipher_probes; probe->ssl_name; ++probe) { 294 /* No exclusions if evp_name is a valid algorithm */ 295 if (EVP_get_cipherbyname(probe->evp_name)) 296 continue; 297 298 /* 299 * Sadly there is no SSL_CTX_get_ciphers() interface, so we are 300 * forced to allocate and free an SSL object. Fatal error if we 301 * can't allocate the SSL object. 302 */ 303 ERR_clear_error(); 304 if (s == 0 && (s = SSL_new(ctx)) == 0) { 305 tls_print_errors(); 306 msg_fatal("%s: error allocating SSL object", myname); 307 } 308 309 /* 310 * Cipher is not supported by libcrypto, nothing to do if also 311 * not supported by libssl. Flush the OpenSSL error stack. 312 * 313 * XXX: There may be additional places in pre-existing code where 314 * SSL errors are generated and ignored, that require a similar 315 * "flush". Better yet, is to always flush before calls that run 316 * tls_print_errors() on failure. 317 * 318 * Contrary to documentation, on SunOS 5.10 SSL_set_cipher_list() 319 * returns success with no ciphers selected, when this happens 320 * SSL_get_ciphers() produces a stack with 0 elements! 321 */ 322 if (SSL_set_cipher_list(s, probe->ssl_name) == 0 323 || (ciphers = SSL_get_ciphers(s)) == 0 324 || (num = sk_SSL_CIPHER_num(ciphers)) == 0) { 325 ERR_clear_error(); /* flush any generated errors */ 326 continue; 327 } 328 for (i = 0; i < num; ++i) { 329 c = sk_SSL_CIPHER_value(ciphers, i); 330 (void) SSL_CIPHER_get_bits(c, &alg_bits); 331 if (alg_bits == probe->alg_bits) 332 argv_add(exclude, SSL_CIPHER_get_name(c), ARGV_END); 333 } 334 } 335 if (s != 0) 336 SSL_free(s); 337 } 338 for (i = 0; i < exclude->argc; ++i) 339 vstring_sprintf_append(buf, ":!%s", exclude->argv[i]); 340 return (vstring_str(buf)); 341 } 342 343 /* tls_apply_cipher_list - update SSL_CTX cipher list */ 344 345 static const char *tls_apply_cipher_list(TLS_APPL_STATE *app_ctx, 346 const char *context, VSTRING *spec) 347 { 348 const char *new = tls_exclude_missing(app_ctx->ssl_ctx, spec); 349 350 ERR_clear_error(); 351 if (SSL_CTX_set_cipher_list(app_ctx->ssl_ctx, new) == 0) { 352 tls_print_errors(); 353 vstring_sprintf(app_ctx->why, "invalid %s cipher list: \"%s\"", 354 context, new); 355 return (0); 356 } 357 return (new); 358 } 359 360 /* tls_protocol_mask - Bitmask of protocols to exclude */ 361 362 int tls_protocol_mask(const char *plist) 363 { 364 char *save; 365 char *tok; 366 char *cp; 367 int code; 368 int exclude = 0; 369 int include = 0; 370 371 save = cp = mystrdup(plist); 372 while ((tok = mystrtok(&cp, "\t\n\r ,:")) != 0) { 373 if (*tok == '!') 374 exclude |= code = 375 name_code(protocol_table, NAME_CODE_FLAG_NONE, ++tok); 376 else 377 include |= code = 378 name_code(protocol_table, NAME_CODE_FLAG_NONE, tok); 379 if (code == TLS_PROTOCOL_INVALID) 380 return TLS_PROTOCOL_INVALID; 381 } 382 myfree(save); 383 384 /* 385 * When the include list is empty, use only the explicit exclusions. 386 * Otherwise, also exclude the complement of the include list from the 387 * built-in list of known protocols. There is no way to exclude protocols 388 * we don't know about at compile time, and this is unavoidable because 389 * the OpenSSL API works with compile-time *exclusion* bit-masks. 390 */ 391 return (include ? (exclude | (TLS_KNOWN_PROTOCOLS & ~include)) : exclude); 392 } 393 394 /* tls_param_init - Load TLS related config parameters */ 395 396 void tls_param_init(void) 397 { 398 static const CONFIG_STR_TABLE str_table[] = { 399 VAR_TLS_HIGH_CLIST, DEF_TLS_HIGH_CLIST, &var_tls_high_clist, 1, 0, 400 VAR_TLS_MEDIUM_CLIST, DEF_TLS_MEDIUM_CLIST, &var_tls_medium_clist, 1, 0, 401 VAR_TLS_LOW_CLIST, DEF_TLS_LOW_CLIST, &var_tls_low_clist, 1, 0, 402 VAR_TLS_EXPORT_CLIST, DEF_TLS_EXPORT_CLIST, &var_tls_export_clist, 1, 0, 403 VAR_TLS_NULL_CLIST, DEF_TLS_NULL_CLIST, &var_tls_null_clist, 1, 0, 404 VAR_TLS_EECDH_STRONG, DEF_TLS_EECDH_STRONG, &var_tls_eecdh_strong, 1, 0, 405 VAR_TLS_EECDH_ULTRA, DEF_TLS_EECDH_ULTRA, &var_tls_eecdh_ultra, 1, 0, 406 0, 407 }; 408 static const CONFIG_INT_TABLE int_table[] = { 409 VAR_TLS_DAEMON_RAND_BYTES, DEF_TLS_DAEMON_RAND_BYTES, &var_tls_daemon_rand_bytes, 1, 0, 410 0, 411 }; 412 static int init_done; 413 414 if (init_done) 415 return; 416 init_done = 1; 417 418 get_mail_conf_str_table(str_table); 419 get_mail_conf_int_table(int_table); 420 } 421 422 /* tls_set_ciphers - Set SSL context cipher list */ 423 424 const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context, 425 const char *grade, const char *exclusions) 426 { 427 const char *myname = "tls_set_ciphers"; 428 static VSTRING *buf; 429 int new_grade; 430 char *save; 431 char *cp; 432 char *tok; 433 const char *new_list; 434 435 new_grade = tls_cipher_grade(grade); 436 if (new_grade == TLS_CIPHER_NONE) { 437 vstring_sprintf(app_ctx->why, "invalid %s cipher grade: \"%s\"", 438 context, grade); 439 return (0); 440 } 441 if (buf == 0) 442 buf = vstring_alloc(10); 443 VSTRING_RESET(buf); 444 445 /* 446 * Given cached state and identical input, we return the same result. 447 */ 448 if (app_ctx->cipher_list) { 449 if (new_grade == app_ctx->cipher_grade 450 && strcmp(app_ctx->cipher_exclusions, exclusions) == 0) 451 return (app_ctx->cipher_list); 452 453 /* Change required, flush cached state */ 454 app_ctx->cipher_grade = TLS_CIPHER_NONE; 455 456 myfree(app_ctx->cipher_exclusions); 457 app_ctx->cipher_exclusions = 0; 458 459 myfree(app_ctx->cipher_list); 460 app_ctx->cipher_list = 0; 461 } 462 switch (new_grade) { 463 case TLS_CIPHER_HIGH: 464 vstring_strcpy(buf, var_tls_high_clist); 465 break; 466 case TLS_CIPHER_MEDIUM: 467 vstring_strcpy(buf, var_tls_medium_clist); 468 break; 469 case TLS_CIPHER_LOW: 470 vstring_strcpy(buf, var_tls_low_clist); 471 break; 472 case TLS_CIPHER_EXPORT: 473 vstring_strcpy(buf, var_tls_export_clist); 474 break; 475 case TLS_CIPHER_NULL: 476 vstring_strcpy(buf, var_tls_null_clist); 477 break; 478 default: 479 480 /* 481 * The caller MUST provide a valid cipher grade 482 */ 483 msg_panic("invalid %s cipher grade: %d", context, new_grade); 484 } 485 486 /* 487 * The base lists for each grade can't be empty. 488 */ 489 if (VSTRING_LEN(buf) == 0) 490 msg_panic("%s: empty \"%s\" cipherlist", myname, grade); 491 492 /* 493 * Apply locally-specified exclusions. 494 */ 495 #define CIPHER_SEP "\t\n\r ,:" 496 if (exclusions != 0) { 497 cp = save = mystrdup(exclusions); 498 while ((tok = mystrtok(&cp, CIPHER_SEP)) != 0) { 499 500 /* 501 * Can't exclude ciphers that start with modifiers. 502 */ 503 if (strchr("!+-@", *tok)) { 504 vstring_sprintf(app_ctx->why, 505 "invalid unary '!+-@' in %s cipher " 506 "exclusion: \"%s\"", context, tok); 507 return (0); 508 } 509 vstring_sprintf_append(buf, ":!%s", tok); 510 } 511 myfree(save); 512 } 513 if ((new_list = tls_apply_cipher_list(app_ctx, context, buf)) == 0) 514 return (0); 515 516 /* Cache new state */ 517 app_ctx->cipher_grade = new_grade; 518 app_ctx->cipher_exclusions = mystrdup(exclusions); 519 520 return (app_ctx->cipher_list = mystrdup(new_list)); 521 } 522 523 /* tls_alloc_app_context - allocate TLS application context */ 524 525 TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx) 526 { 527 TLS_APPL_STATE *app_ctx; 528 529 app_ctx = (TLS_APPL_STATE *) mymalloc(sizeof(*app_ctx)); 530 531 memset((char *) app_ctx, 0, sizeof(*app_ctx)); 532 app_ctx->ssl_ctx = ssl_ctx; 533 534 /* See also: cache purging code in tls_set_ciphers(). */ 535 app_ctx->cipher_grade = TLS_CIPHER_NONE; 536 app_ctx->cipher_exclusions = 0; 537 app_ctx->cipher_list = 0; 538 app_ctx->cache_type = 0; 539 app_ctx->why = vstring_alloc(1); 540 541 return (app_ctx); 542 } 543 544 /* tls_free_app_context - Free TLS application context */ 545 546 void tls_free_app_context(TLS_APPL_STATE *app_ctx) 547 { 548 if (app_ctx->ssl_ctx) 549 SSL_CTX_free(app_ctx->ssl_ctx); 550 if (app_ctx->cache_type) 551 myfree(app_ctx->cache_type); 552 /* See also: cache purging code in tls_set_ciphers(). */ 553 if (app_ctx->cipher_exclusions) 554 myfree(app_ctx->cipher_exclusions); 555 if (app_ctx->cipher_list) 556 myfree(app_ctx->cipher_list); 557 if (app_ctx->why) 558 vstring_free(app_ctx->why); 559 myfree((char *) app_ctx); 560 } 561 562 /* tls_alloc_sess_context - allocate TLS session context */ 563 564 TLS_SESS_STATE *tls_alloc_sess_context(int log_level, const char *namaddr) 565 { 566 TLS_SESS_STATE *TLScontext; 567 568 /* 569 * PORTABILITY: Do not assume that null pointers are all-zero bits. Use 570 * explicit assignments to initialize pointers. 571 * 572 * See the C language FAQ item 5.17, or if you have time to burn, 573 * http://www.google.com/search?q=zero+bit+null+pointer 574 * 575 * However, it's OK to use memset() to zero integer values. 576 */ 577 TLScontext = (TLS_SESS_STATE *) mymalloc(sizeof(TLS_SESS_STATE)); 578 memset((char *) TLScontext, 0, sizeof(*TLScontext)); 579 TLScontext->con = 0; 580 TLScontext->internal_bio = 0; 581 TLScontext->network_bio = 0; 582 TLScontext->cache_type = 0; 583 TLScontext->serverid = 0; 584 TLScontext->peer_CN = 0; 585 TLScontext->issuer_CN = 0; 586 TLScontext->peer_fingerprint = 0; 587 TLScontext->protocol = 0; 588 TLScontext->cipher_name = 0; 589 TLScontext->log_level = log_level; 590 TLScontext->namaddr = lowercase(mystrdup(namaddr)); 591 592 return (TLScontext); 593 } 594 595 /* tls_free_context - deallocate TLScontext and members */ 596 597 void tls_free_context(TLS_SESS_STATE *TLScontext) 598 { 599 600 /* 601 * Free the SSL structure and the BIOs. Warning: the internal_bio is 602 * connected to the SSL structure and is automatically freed with it. Do 603 * not free it again (core dump)!! Only free the network_bio. 604 */ 605 if (TLScontext->con != 0) 606 SSL_free(TLScontext->con); 607 if (TLScontext->network_bio) 608 BIO_free(TLScontext->network_bio); 609 610 if (TLScontext->namaddr) 611 myfree(TLScontext->namaddr); 612 if (TLScontext->serverid) 613 myfree(TLScontext->serverid); 614 615 if (TLScontext->peer_CN) 616 myfree(TLScontext->peer_CN); 617 if (TLScontext->issuer_CN) 618 myfree(TLScontext->issuer_CN); 619 if (TLScontext->peer_fingerprint) 620 myfree(TLScontext->peer_fingerprint); 621 622 myfree((char *) TLScontext); 623 } 624 625 /* tls_version_split - Split OpenSSL version number into major, minor, ... */ 626 627 static void tls_version_split(long version, TLS_VINFO *info) 628 { 629 630 /* 631 * OPENSSL_VERSION_NUMBER(3): 632 * 633 * OPENSSL_VERSION_NUMBER is a numeric release version identifier: 634 * 635 * MMNNFFPPS: major minor fix patch status 636 * 637 * The status nibble has one of the values 0 for development, 1 to e for 638 * betas 1 to 14, and f for release. Parsed OpenSSL version number. for 639 * example 640 * 641 * 0x000906000 == 0.9.6 dev 0x000906023 == 0.9.6b beta 3 0x00090605f == 642 * 0.9.6e release 643 * 644 * Versions prior to 0.9.3 have identifiers < 0x0930. Versions between 645 * 0.9.3 and 0.9.5 had a version identifier with this interpretation: 646 * 647 * MMNNFFRBB major minor fix final beta/patch 648 * 649 * for example 650 * 651 * 0x000904100 == 0.9.4 release 0x000905000 == 0.9.5 dev 652 * 653 * Version 0.9.5a had an interim interpretation that is like the current 654 * one, except the patch level got the highest bit set, to keep continu- 655 * ity. The number was therefore 0x0090581f. 656 */ 657 658 if (version < 0x0930) { 659 info->status = 0; 660 info->patch = version & 0x0f; 661 version >>= 4; 662 info->micro = version & 0x0f; 663 version >>= 4; 664 info->minor = version & 0x0f; 665 version >>= 4; 666 info->major = version & 0x0f; 667 } else if (version < 0x00905800L) { 668 info->patch = version & 0xff; 669 version >>= 8; 670 info->status = version & 0xf; 671 version >>= 4; 672 info->micro = version & 0xff; 673 version >>= 8; 674 info->minor = version & 0xff; 675 version >>= 8; 676 info->major = version & 0xff; 677 } else { 678 info->status = version & 0xf; 679 version >>= 4; 680 info->patch = version & 0xff; 681 version >>= 8; 682 info->micro = version & 0xff; 683 version >>= 8; 684 info->minor = version & 0xff; 685 version >>= 8; 686 info->major = version & 0xff; 687 if (version < 0x00906000L) 688 info->patch &= ~0x80; 689 } 690 } 691 692 /* tls_check_version - Detect mismatch between headers and library. */ 693 694 void tls_check_version(void) 695 { 696 TLS_VINFO hdr_info; 697 TLS_VINFO lib_info; 698 699 tls_version_split(OPENSSL_VERSION_NUMBER, &hdr_info); 700 tls_version_split(SSLeay(), &lib_info); 701 702 if (lib_info.major != hdr_info.major 703 || lib_info.minor != hdr_info.minor 704 || lib_info.micro != hdr_info.micro) 705 msg_warn("run-time library vs. compile-time header version mismatch: " 706 "OpenSSL %d.%d.%d may not be compatible with OpenSSL %d.%d.%d", 707 lib_info.major, lib_info.minor, lib_info.micro, 708 hdr_info.major, hdr_info.minor, hdr_info.micro); 709 } 710 711 /* tls_bug_bits - SSL bug compatibility bits for this OpenSSL version */ 712 713 long tls_bug_bits(void) 714 { 715 long bits = SSL_OP_ALL; /* Work around all known bugs */ 716 717 #if OPENSSL_VERSION_NUMBER >= 0x00908000L 718 long lib_version = SSLeay(); 719 720 /* 721 * In OpenSSL 0.9.8[ab], enabling zlib compression breaks the padding bug 722 * work-around, leading to false positives and failed connections. We may 723 * not interoperate with systems with the bug, but this is better than 724 * breaking on all 0.9.8[ab] systems that have zlib support enabled. 725 */ 726 if (lib_version >= 0x00908000L && lib_version <= 0x0090802fL) { 727 STACK_OF(SSL_COMP) * comp_methods; 728 729 comp_methods = SSL_COMP_get_compression_methods(); 730 if (comp_methods != 0 && sk_SSL_COMP_num(comp_methods) > 0) 731 bits &= ~SSL_OP_TLS_BLOCK_PADDING_BUG; 732 } 733 #endif 734 return (bits); 735 } 736 737 /* tls_print_errors - print and clear the error stack */ 738 739 void tls_print_errors(void) 740 { 741 unsigned long err; 742 char buffer[1024]; /* XXX */ 743 const char *file; 744 const char *data; 745 int line; 746 int flags; 747 unsigned long thread; 748 749 thread = CRYPTO_thread_id(); 750 while ((err = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) { 751 ERR_error_string_n(err, buffer, sizeof(buffer)); 752 if (flags & ERR_TXT_STRING) 753 msg_warn("TLS library problem: %lu:%s:%s:%d:%s:", 754 thread, buffer, file, line, data); 755 else 756 msg_warn("TLS library problem: %lu:%s:%s:%d:", 757 thread, buffer, file, line); 758 } 759 } 760 761 /* tls_info_callback - callback for logging SSL events via Postfix */ 762 763 void tls_info_callback(const SSL *s, int where, int ret) 764 { 765 char *str; 766 int w; 767 768 /* Adapted from OpenSSL apps/s_cb.c. */ 769 770 w = where & ~SSL_ST_MASK; 771 772 if (w & SSL_ST_CONNECT) 773 str = "SSL_connect"; 774 else if (w & SSL_ST_ACCEPT) 775 str = "SSL_accept"; 776 else 777 str = "unknown"; 778 779 if (where & SSL_CB_LOOP) { 780 msg_info("%s:%s", str, SSL_state_string_long((SSL *) s)); 781 } else if (where & SSL_CB_ALERT) { 782 str = (where & SSL_CB_READ) ? "read" : "write"; 783 if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY) 784 msg_info("SSL3 alert %s:%s:%s", str, 785 SSL_alert_type_string_long(ret), 786 SSL_alert_desc_string_long(ret)); 787 } else if (where & SSL_CB_EXIT) { 788 if (ret == 0) 789 msg_info("%s:failed in %s", 790 str, SSL_state_string_long((SSL *) s)); 791 else if (ret < 0) { 792 #ifndef LOG_NON_ERROR_STATES 793 switch (SSL_get_error((SSL *) s, ret)) { 794 case SSL_ERROR_WANT_READ: 795 case SSL_ERROR_WANT_WRITE: 796 /* Don't log non-error states. */ 797 break; 798 default: 799 #endif 800 msg_info("%s:error in %s", 801 str, SSL_state_string_long((SSL *) s)); 802 #ifndef LOG_NON_ERROR_STATES 803 } 804 #endif 805 } 806 } 807 } 808 809 /* 810 * taken from OpenSSL crypto/bio/b_dump.c. 811 * 812 * Modified to save a lot of strcpy and strcat by Matti Aarnio. 813 * 814 * Rewritten by Wietse to elimate fixed-size stack buffer, array index 815 * multiplication and division, sprintf() and strcpy(), and lots of strlen() 816 * calls. We could make it a little faster by using a fixed-size stack-based 817 * buffer. 818 * 819 * 200412 - use %lx to print pointers, after casting them to unsigned long. 820 */ 821 822 #define TRUNCATE_SPACE_NULL 823 #define DUMP_WIDTH 16 824 #define VERT_SPLIT 7 825 826 static void tls_dump_buffer(const unsigned char *start, int len) 827 { 828 VSTRING *buf = vstring_alloc(100); 829 const unsigned char *last = start + len - 1; 830 const unsigned char *row; 831 const unsigned char *col; 832 int ch; 833 834 #ifdef TRUNCATE_SPACE_NULL 835 while (last >= start && (*last == ' ' || *last == 0)) 836 last--; 837 #endif 838 839 for (row = start; row <= last; row += DUMP_WIDTH) { 840 VSTRING_RESET(buf); 841 vstring_sprintf(buf, "%04lx ", (unsigned long) (row - start)); 842 for (col = row; col < row + DUMP_WIDTH; col++) { 843 if (col > last) { 844 vstring_strcat(buf, " "); 845 } else { 846 ch = *col; 847 vstring_sprintf_append(buf, "%02x%c", 848 ch, col - row == VERT_SPLIT ? '|' : ' '); 849 } 850 } 851 VSTRING_ADDCH(buf, ' '); 852 for (col = row; col < row + DUMP_WIDTH; col++) { 853 if (col > last) 854 break; 855 ch = *col; 856 if (!ISPRINT(ch)) 857 ch = '.'; 858 VSTRING_ADDCH(buf, ch); 859 if (col - row == VERT_SPLIT) 860 VSTRING_ADDCH(buf, ' '); 861 } 862 VSTRING_TERMINATE(buf); 863 msg_info("%s", vstring_str(buf)); 864 } 865 #ifdef TRUNCATE_SPACE_NULL 866 if ((last + 1) - start < len) 867 msg_info("%04lx - <SPACES/NULLS>", 868 (unsigned long) ((last + 1) - start)); 869 #endif 870 vstring_free(buf); 871 } 872 873 /* taken from OpenSSL apps/s_cb.c */ 874 875 long tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi, 876 long unused_argl, long ret) 877 { 878 if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { 879 msg_info("read from %08lX [%08lX] (%d bytes => %ld (0x%lX))", 880 (unsigned long) bio, (unsigned long) argp, argi, 881 ret, (unsigned long) ret); 882 tls_dump_buffer((unsigned char *) argp, (int) ret); 883 } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { 884 msg_info("write to %08lX [%08lX] (%d bytes => %ld (0x%lX))", 885 (unsigned long) bio, (unsigned long) argp, argi, 886 ret, (unsigned long) ret); 887 tls_dump_buffer((unsigned char *) argp, (int) ret); 888 } 889 return (ret); 890 } 891 892 #else 893 894 /* 895 * Broken linker workaround. 896 */ 897 int tls_dummy_for_broken_linkers; 898 899 #endif 900