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