xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_misc.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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