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