Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / tls / tls_misc.c
blob91e88aa029c4fe20cf0ff1166c29f7990d3b12b7
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* tls_misc 3
6 /* SUMMARY
7 /* miscellaneous TLS support routines
8 /* SYNOPSIS
9 /* #define TLS_INTERNAL
10 /* #include <tls.h>
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;
21 /* TLS_APPL_STATE *tls_alloc_app_context(ssl_ctx)
22 /* SSL_CTX *ssl_ctx;
24 /* void tls_free_app_context(app_ctx)
25 /* void *app_ctx;
27 /* TLS_SESS_STATE *tls_alloc_sess_context(log_level, namaddr)
28 /* int log_level;
29 /* const char *namaddr;
31 /* void tls_free_context(TLScontext)
32 /* TLS_SESS_STATE *TLScontext;
34 /* void tls_check_version()
36 /* long tls_bug_bits()
38 /* void tls_param_init()
40 /* int tls_protocol_mask(plist)
41 /* const char *plist;
43 /* int tls_cipher_grade(name)
44 /* const char *name;
46 /* const char *str_tls_cipher_grade(grade)
47 /* int grade;
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;
55 /* void tls_print_errors()
57 /* void tls_info_callback(ssl, where, ret)
58 /* const SSL *ssl; /* unused */
59 /* int where;
60 /* int ret;
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.
73 /* tls_alloc_app_context() creates an application context that
74 /* holds the SSL context for the application and related cached state.
76 /* tls_free_app_context() deallocates the application context and its
77 /* contents (the application context is stored outside the TLS library).
79 /* tls_alloc_sess_context() creates an initialized TLS session context
80 /* structure with the specified log mask and peer name[addr].
82 /* tls_free_context() destroys a TLScontext structure
83 /* together with OpenSSL structures that are attached to it.
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.
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.
93 /* tls_param_init() loads main.cf parameters used internally in
94 /* TLS library. Any errors are fatal.
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.
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.
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.
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.
119 /* tls_print_errors() queries the OpenSSL error stack,
120 /* logs the error messages, and clears the error stack.
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.
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
143 /* Updated by:
144 /* Wietse Venema
145 /* IBM T.J. Watson Research
146 /* P.O. Box 704
147 /* Yorktown Heights, NY 10598, USA
149 /* Victor Duchovni
150 /* Morgan Stanley
151 /*--*/
153 /* System library. */
155 #include <sys_defs.h>
156 #include <ctype.h>
157 #include <string.h>
159 #ifdef USE_TLS
161 /* Utility library. */
163 #include <vstream.h>
164 #include <msg.h>
165 #include <mymalloc.h>
166 #include <vstring.h>
167 #include <stringops.h>
168 #include <argv.h>
171 * Global library.
173 #include <mail_params.h>
174 #include <mail_conf.h>
177 * TLS library.
179 #define TLS_INTERNAL
180 #include <tls.h>
182 /* Application-specific. */
185 * Tunable parameters.
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;
197 * Index to attach TLScontext pointers to SSL objects, so that they can be
198 * accessed by call-back routines.
200 int TLScontext_index = -1;
203 * Protocol name <=> mask conversion.
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,
213 * Ciphersuite name <=> code conversion.
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,
226 * Parsed OpenSSL version number.
228 typedef struct {
229 int major;
230 int minor;
231 int micro;
232 int patch;
233 int status;
234 } TLS_VINFO;
237 * OpenSSL adopted the cipher selection patch, so we don't expect any more
238 * broken ciphers other than AES and CAMELLIA.
240 typedef struct {
241 const char *ssl_name;
242 const int alg_bits;
243 const char *evp_name;
244 } cipher_probe_t;
246 static const cipher_probe_t cipher_probes[] = {
247 "AES", 256, "AES-256-CBC",
248 "CAMELLIA", 256, "CAMELLIA-256-CBC",
249 0, 0, 0,
252 /* tls_exclude_missing - Append exclusions for missing ciphers */
254 static const char *tls_exclude_missing(SSL_CTX *ctx, VSTRING *buf)
256 const char *myname = "tls_exclude_missing";
257 static ARGV *exclude; /* Cached */
258 SSL *s = 0;
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;
268 * Process a list of probes which specify:
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.
273 * The key size (typically 256) that OpenSSL fails to check, and assumes
274 * available when another key size (typically 128) is usable.
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".
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.
287 if (exclude == 0) {
288 exclude = argv_alloc(1);
291 * Iterate over the probe list
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;
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.
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);
310 * Cipher is not supported by libcrypto, nothing to do if also
311 * not supported by libssl. Flush the OpenSSL error stack.
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.
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!
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;
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);
335 if (s != 0)
336 SSL_free(s);
338 for (i = 0; i < exclude->argc; ++i)
339 vstring_sprintf_append(buf, ":!%s", exclude->argv[i]);
340 return (vstring_str(buf));
343 /* tls_apply_cipher_list - update SSL_CTX cipher list */
345 static const char *tls_apply_cipher_list(TLS_APPL_STATE *app_ctx,
346 const char *context, VSTRING *spec)
348 const char *new = tls_exclude_missing(app_ctx->ssl_ctx, spec);
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);
357 return (new);
360 /* tls_protocol_mask - Bitmask of protocols to exclude */
362 int tls_protocol_mask(const char *plist)
364 char *save;
365 char *tok;
366 char *cp;
367 int code;
368 int exclude = 0;
369 int include = 0;
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;
382 myfree(save);
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.
391 return (include ? (exclude | (TLS_KNOWN_PROTOCOLS & ~include)) : exclude);
394 /* tls_param_init - Load TLS related config parameters */
396 void tls_param_init(void)
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,
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,
412 static int init_done;
414 if (init_done)
415 return;
416 init_done = 1;
418 get_mail_conf_str_table(str_table);
419 get_mail_conf_int_table(int_table);
422 /* tls_set_ciphers - Set SSL context cipher list */
424 const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context,
425 const char *grade, const char *exclusions)
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;
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);
441 if (buf == 0)
442 buf = vstring_alloc(10);
443 VSTRING_RESET(buf);
446 * Given cached state and identical input, we return the same result.
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);
453 /* Change required, flush cached state */
454 app_ctx->cipher_grade = TLS_CIPHER_NONE;
456 myfree(app_ctx->cipher_exclusions);
457 app_ctx->cipher_exclusions = 0;
459 myfree(app_ctx->cipher_list);
460 app_ctx->cipher_list = 0;
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:
481 * The caller MUST provide a valid cipher grade
483 msg_panic("invalid %s cipher grade: %d", context, new_grade);
487 * The base lists for each grade can't be empty.
489 if (VSTRING_LEN(buf) == 0)
490 msg_panic("%s: empty \"%s\" cipherlist", myname, grade);
493 * Apply locally-specified exclusions.
495 #define CIPHER_SEP "\t\n\r ,:"
496 if (exclusions != 0) {
497 cp = save = mystrdup(exclusions);
498 while ((tok = mystrtok(&cp, CIPHER_SEP)) != 0) {
501 * Can't exclude ciphers that start with modifiers.
503 if (strchr("!+-@", *tok)) {
504 vstring_sprintf(app_ctx->why,
505 "invalid unary '!+-@' in %s cipher "
506 "exclusion: \"%s\"", context, tok);
507 return (0);
509 vstring_sprintf_append(buf, ":!%s", tok);
511 myfree(save);
513 if ((new_list = tls_apply_cipher_list(app_ctx, context, buf)) == 0)
514 return (0);
516 /* Cache new state */
517 app_ctx->cipher_grade = new_grade;
518 app_ctx->cipher_exclusions = mystrdup(exclusions);
520 return (app_ctx->cipher_list = mystrdup(new_list));
523 /* tls_alloc_app_context - allocate TLS application context */
525 TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx)
527 TLS_APPL_STATE *app_ctx;
529 app_ctx = (TLS_APPL_STATE *) mymalloc(sizeof(*app_ctx));
531 memset((char *) app_ctx, 0, sizeof(*app_ctx));
532 app_ctx->ssl_ctx = ssl_ctx;
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);
541 return (app_ctx);
544 /* tls_free_app_context - Free TLS application context */
546 void tls_free_app_context(TLS_APPL_STATE *app_ctx)
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);
562 /* tls_alloc_sess_context - allocate TLS session context */
564 TLS_SESS_STATE *tls_alloc_sess_context(int log_level, const char *namaddr)
566 TLS_SESS_STATE *TLScontext;
569 * PORTABILITY: Do not assume that null pointers are all-zero bits. Use
570 * explicit assignments to initialize pointers.
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
575 * However, it's OK to use memset() to zero integer values.
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));
592 return (TLScontext);
595 /* tls_free_context - deallocate TLScontext and members */
597 void tls_free_context(TLS_SESS_STATE *TLScontext)
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.
605 if (TLScontext->con != 0)
606 SSL_free(TLScontext->con);
607 if (TLScontext->network_bio)
608 BIO_free(TLScontext->network_bio);
610 if (TLScontext->namaddr)
611 myfree(TLScontext->namaddr);
612 if (TLScontext->serverid)
613 myfree(TLScontext->serverid);
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);
622 myfree((char *) TLScontext);
625 /* tls_version_split - Split OpenSSL version number into major, minor, ... */
627 static void tls_version_split(long version, TLS_VINFO *info)
631 * OPENSSL_VERSION_NUMBER(3):
633 * OPENSSL_VERSION_NUMBER is a numeric release version identifier:
635 * MMNNFFPPS: major minor fix patch status
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
641 * 0x000906000 == 0.9.6 dev 0x000906023 == 0.9.6b beta 3 0x00090605f ==
642 * 0.9.6e release
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:
647 * MMNNFFRBB major minor fix final beta/patch
649 * for example
651 * 0x000904100 == 0.9.4 release 0x000905000 == 0.9.5 dev
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.
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;
692 /* tls_check_version - Detect mismatch between headers and library. */
694 void tls_check_version(void)
696 TLS_VINFO hdr_info;
697 TLS_VINFO lib_info;
699 tls_version_split(OPENSSL_VERSION_NUMBER, &hdr_info);
700 tls_version_split(SSLeay(), &lib_info);
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);
711 /* tls_bug_bits - SSL bug compatibility bits for this OpenSSL version */
713 long tls_bug_bits(void)
715 long bits = SSL_OP_ALL; /* Work around all known bugs */
717 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
718 long lib_version = SSLeay();
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.
726 if (lib_version >= 0x00908000L && lib_version <= 0x0090802fL) {
727 STACK_OF(SSL_COMP) * comp_methods;
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;
733 #endif
734 return (bits);
737 /* tls_print_errors - print and clear the error stack */
739 void tls_print_errors(void)
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;
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);
761 /* tls_info_callback - callback for logging SSL events via Postfix */
763 void tls_info_callback(const SSL *s, int where, int ret)
765 char *str;
766 int w;
768 /* Adapted from OpenSSL apps/s_cb.c. */
770 w = where & ~SSL_ST_MASK;
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";
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
804 #endif
810 * taken from OpenSSL crypto/bio/b_dump.c.
812 * Modified to save a lot of strcpy and strcat by Matti Aarnio.
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.
819 * 200412 - use %lx to print pointers, after casting them to unsigned long.
822 #define TRUNCATE_SPACE_NULL
823 #define DUMP_WIDTH 16
824 #define VERT_SPLIT 7
826 static void tls_dump_buffer(const unsigned char *start, int len)
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;
834 #ifdef TRUNCATE_SPACE_NULL
835 while (last >= start && (*last == ' ' || *last == 0))
836 last--;
837 #endif
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 ? '|' : ' ');
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, ' ');
862 VSTRING_TERMINATE(buf);
863 msg_info("%s", vstring_str(buf));
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);
873 /* taken from OpenSSL apps/s_cb.c */
875 long tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi,
876 long unused_argl, long ret)
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);
889 return (ret);
892 #else
895 * Broken linker workaround.
897 int tls_dummy_for_broken_linkers;
899 #endif