1*837e7c1aSchristos /*	$NetBSD: tls_mgr.c,v 1.1.1.3 2017/02/14 01:13:42 christos Exp $	*/
241fbaed0Stron 
341fbaed0Stron /*++
441fbaed0Stron /* NAME
541fbaed0Stron /*	tls_mgr 3
641fbaed0Stron /* SUMMARY
741fbaed0Stron /*	tlsmgr client interface
841fbaed0Stron /* SYNOPSIS
941fbaed0Stron /*	#include <tls_mgr.h>
1041fbaed0Stron /*
1141fbaed0Stron /*	int	tls_mgr_seed(buf, len)
1241fbaed0Stron /*	VSTRING	*buf;
1341fbaed0Stron /*	int	len;
1441fbaed0Stron /*
152e5cb688Stron /*	int	tls_mgr_policy(cache_type, cachable, timeout)
1641fbaed0Stron /*	const char *cache_type;
1741fbaed0Stron /*	int	*cachable;
182e5cb688Stron /*	int	*timeout;
1941fbaed0Stron /*
2041fbaed0Stron /*	int	tls_mgr_update(cache_type, cache_id, buf, len)
2141fbaed0Stron /*	const char *cache_type;
2241fbaed0Stron /*	const char *cache_id;
2341fbaed0Stron /*	const char *buf;
2441fbaed0Stron /*	ssize_t	len;
2541fbaed0Stron /*
2641fbaed0Stron /*	int	tls_mgr_lookup(cache_type, cache_id, buf)
2741fbaed0Stron /*	const char *cache_type;
2841fbaed0Stron /*	const char *cache_id;
2941fbaed0Stron /*	VSTRING	*buf;
3041fbaed0Stron /*
3141fbaed0Stron /*	int	tls_mgr_delete(cache_type, cache_id)
3241fbaed0Stron /*	const char *cache_type;
3341fbaed0Stron /*	const char *cache_id;
342e5cb688Stron /*
352e5cb688Stron /*	TLS_TICKET_KEY *tls_mgr_key(keyname, timeout)
362e5cb688Stron /*	unsigned char *keyname;
372e5cb688Stron /*	int	timeout;
3841fbaed0Stron /* DESCRIPTION
3941fbaed0Stron /*	These routines communicate with the tlsmgr(8) server for
4041fbaed0Stron /*	entropy and session cache management. Since these are
4141fbaed0Stron /*	non-critical services, requests are allowed to fail without
4241fbaed0Stron /*	disrupting Postfix.
4341fbaed0Stron /*
4441fbaed0Stron /*	tls_mgr_seed() requests entropy from the tlsmgr(8)
4541fbaed0Stron /*	Pseudo Random Number Generator (PRNG) pool.
4641fbaed0Stron /*
4741fbaed0Stron /*	tls_mgr_policy() requests the session caching policy.
4841fbaed0Stron /*
4941fbaed0Stron /*	tls_mgr_lookup() loads the specified session from
5041fbaed0Stron /*	the specified session cache.
5141fbaed0Stron /*
5241fbaed0Stron /*	tls_mgr_update() saves the specified session to
5341fbaed0Stron /*	the specified session cache.
5441fbaed0Stron /*
5541fbaed0Stron /*	tls_mgr_delete() removes specified session from
5641fbaed0Stron /*	the specified session cache.
5741fbaed0Stron /*
582e5cb688Stron /*	tls_mgr_key() is used to retrieve the current TLS session ticket
592e5cb688Stron /*	encryption or decryption keys.
602e5cb688Stron /*
612e5cb688Stron /*	Arguments:
6241fbaed0Stron /* .IP cache_type
6341fbaed0Stron /*	One of TLS_MGR_SCACHE_SMTPD, TLS_MGR_SCACHE_SMTP or
6441fbaed0Stron /*	TLS_MGR_SCACHE_LMTP.
6541fbaed0Stron /* .IP cachable
6641fbaed0Stron /*	Pointer to int, set non-zero if the requested cache_type
6741fbaed0Stron /*	is enabled.
682e5cb688Stron /* .IP timeout
692e5cb688Stron /*	Pointer to int, returns the cache entry timeout.
7041fbaed0Stron /* .IP cache_id
7141fbaed0Stron /*	The session cache lookup key.
7241fbaed0Stron /* .IP buf
7341fbaed0Stron /*	The result or input buffer.
7441fbaed0Stron /* .IP len
7541fbaed0Stron /*	The length of the input buffer, or the amount of data requested.
762e5cb688Stron /* .IP keyname
772e5cb688Stron /*	Is null when requesting the current encryption keys.  Otherwise,
782e5cb688Stron /*	keyname is a pointer to an array of TLS_TICKET_NAMELEN unsigned
792e5cb688Stron /*	chars (not NUL terminated) that is an identifier for a key
802e5cb688Stron /*	previously used to encrypt a session ticket.  When encrypting
812e5cb688Stron /*	a null result indicates that session tickets are not supported, when
822e5cb688Stron /*	decrypting it indicates that no matching keys were found.
832e5cb688Stron /* .IP timeout
842e5cb688Stron /*	The encryption key timeout.  Once a key has been active for this many
852e5cb688Stron /*	seconds it is retired and used only for decrypting previously issued
862e5cb688Stron /*	session tickets for another timeout seconds, and is then destroyed.
872e5cb688Stron /*	The timeout must not be longer than half the SSL session lifetime.
8841fbaed0Stron /* DIAGNOSTICS
8941fbaed0Stron /*	All client functions return one of the following status codes:
9041fbaed0Stron /* .IP TLS_MGR_STAT_OK
9141fbaed0Stron /*	The request completed, and the requested operation was
9241fbaed0Stron /*	successful (for example, the requested session was found,
9341fbaed0Stron /*	or the specified session was saved or removed).
9441fbaed0Stron /* .IP TLS_MGR_STAT_ERR
9541fbaed0Stron /*	The request completed, but the requested operation failed
9641fbaed0Stron /*	(for example, the requested object was not found or the
9741fbaed0Stron /*	specified session was not saved or removed).
9841fbaed0Stron /* .IP TLS_MGR_STAT_FAIL
9941fbaed0Stron /*	The request could not complete (the client could not
10041fbaed0Stron /*	communicate with the tlsmgr(8) server).
10141fbaed0Stron /* SEE ALSO
10241fbaed0Stron /*	tlsmgr(8) TLS session and PRNG management
10341fbaed0Stron /* LICENSE
10441fbaed0Stron /* .ad
10541fbaed0Stron /* .fi
10641fbaed0Stron /*	The Secure Mailer license must be distributed with this software.
10741fbaed0Stron /* AUTHOR(S)
10841fbaed0Stron /*	Wietse Venema
10941fbaed0Stron /*	IBM T.J. Watson Research
11041fbaed0Stron /*	P.O. Box 704
11141fbaed0Stron /*	Yorktown Heights, NY 10598, USA
11241fbaed0Stron /*--*/
11341fbaed0Stron 
11441fbaed0Stron /* System library. */
11541fbaed0Stron 
11641fbaed0Stron #include <sys_defs.h>
11741fbaed0Stron 
11841fbaed0Stron #ifdef USE_TLS
11941fbaed0Stron 
12041fbaed0Stron #ifdef STRCASECMP_IN_STRINGS_H
12141fbaed0Stron #include <strings.h>
12241fbaed0Stron #endif
12341fbaed0Stron 
12441fbaed0Stron /* Utility library. */
12541fbaed0Stron 
12641fbaed0Stron #include <msg.h>
12741fbaed0Stron #include <vstream.h>
12841fbaed0Stron #include <vstring.h>
12941fbaed0Stron #include <attr.h>
13041fbaed0Stron #include <attr_clnt.h>
1312e5cb688Stron #include <mymalloc.h>
1322e5cb688Stron #include <stringops.h>
13341fbaed0Stron 
13441fbaed0Stron /* Global library. */
13541fbaed0Stron 
13641fbaed0Stron #include <mail_params.h>
13741fbaed0Stron #include <mail_proto.h>
1382e5cb688Stron 
1392e5cb688Stron /* TLS library. */
14041fbaed0Stron #include <tls_mgr.h>
14141fbaed0Stron 
14241fbaed0Stron /* Application-specific. */
14341fbaed0Stron 
1442e5cb688Stron #define STR(x) vstring_str(x)
1452e5cb688Stron #define LEN(x) VSTRING_LEN(x)
1462e5cb688Stron 
14741fbaed0Stron static ATTR_CLNT *tls_mgr;
14841fbaed0Stron 
14941fbaed0Stron /* tls_mgr_open - create client handle */
15041fbaed0Stron 
15141fbaed0Stron static void tls_mgr_open(void)
15241fbaed0Stron {
1532e5cb688Stron     char   *service;
15441fbaed0Stron 
15541fbaed0Stron     /*
15641fbaed0Stron      * Sanity check.
15741fbaed0Stron      */
15841fbaed0Stron     if (tls_mgr != 0)
15941fbaed0Stron 	msg_panic("tls_mgr_open: multiple initialization");
16041fbaed0Stron 
16141fbaed0Stron     /*
16241fbaed0Stron      * Use whatever IPC is preferred for internal use: UNIX-domain sockets or
16341fbaed0Stron      * Solaris streams.
16441fbaed0Stron      */
1652e5cb688Stron     service = concatenate("local:" TLS_MGR_CLASS "/", var_tls_mgr_service,
1662e5cb688Stron 			  (char *) 0);
1672e5cb688Stron     tls_mgr = attr_clnt_create(service, var_ipc_timeout,
16841fbaed0Stron 			       var_ipc_idle_limit, var_ipc_ttl_limit);
1692e5cb688Stron     myfree(service);
1702e5cb688Stron 
17141fbaed0Stron     attr_clnt_control(tls_mgr,
17241fbaed0Stron 		      ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
17341fbaed0Stron 		      ATTR_CLNT_CTL_END);
17441fbaed0Stron }
17541fbaed0Stron 
17641fbaed0Stron /* tls_mgr_seed - request PRNG seed */
17741fbaed0Stron 
17841fbaed0Stron int     tls_mgr_seed(VSTRING *buf, int len)
17941fbaed0Stron {
18041fbaed0Stron     int     status;
18141fbaed0Stron 
18241fbaed0Stron     /*
18341fbaed0Stron      * Create the tlsmgr client handle.
18441fbaed0Stron      */
18541fbaed0Stron     if (tls_mgr == 0)
18641fbaed0Stron 	tls_mgr_open();
18741fbaed0Stron 
18841fbaed0Stron     /*
18941fbaed0Stron      * Request seed.
19041fbaed0Stron      */
19141fbaed0Stron     if (attr_clnt_request(tls_mgr,
19241fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request attributes */
193*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_SEED),
194*837e7c1aSchristos 			  SEND_ATTR_INT(TLS_MGR_ATTR_SIZE, len),
19541fbaed0Stron 			  ATTR_TYPE_END,
19641fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply attributes */
197*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
198*837e7c1aSchristos 			  RECV_ATTR_DATA(TLS_MGR_ATTR_SEED, buf),
19941fbaed0Stron 			  ATTR_TYPE_END) != 2)
20041fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
20141fbaed0Stron     return (status);
20241fbaed0Stron }
20341fbaed0Stron 
20441fbaed0Stron /* tls_mgr_policy - request caching policy */
20541fbaed0Stron 
2062e5cb688Stron int     tls_mgr_policy(const char *cache_type, int *cachable, int *timeout)
20741fbaed0Stron {
20841fbaed0Stron     int     status;
20941fbaed0Stron 
21041fbaed0Stron     /*
21141fbaed0Stron      * Create the tlsmgr client handle.
21241fbaed0Stron      */
21341fbaed0Stron     if (tls_mgr == 0)
21441fbaed0Stron 	tls_mgr_open();
21541fbaed0Stron 
21641fbaed0Stron     /*
21741fbaed0Stron      * Request policy.
21841fbaed0Stron      */
21941fbaed0Stron     if (attr_clnt_request(tls_mgr,
22041fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request attributes */
221*837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_POLICY),
222*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
22341fbaed0Stron 			  ATTR_TYPE_END,
22441fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply attributes */
225*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
226*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_CACHABLE, cachable),
227*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_SESSTOUT, timeout),
2282e5cb688Stron 			  ATTR_TYPE_END) != 3)
22941fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
23041fbaed0Stron     return (status);
23141fbaed0Stron }
23241fbaed0Stron 
23341fbaed0Stron /* tls_mgr_lookup - request cached session */
23441fbaed0Stron 
23541fbaed0Stron int     tls_mgr_lookup(const char *cache_type, const char *cache_id,
23641fbaed0Stron 		               VSTRING *buf)
23741fbaed0Stron {
23841fbaed0Stron     int     status;
23941fbaed0Stron 
24041fbaed0Stron     /*
24141fbaed0Stron      * Create the tlsmgr client handle.
24241fbaed0Stron      */
24341fbaed0Stron     if (tls_mgr == 0)
24441fbaed0Stron 	tls_mgr_open();
24541fbaed0Stron 
24641fbaed0Stron     /*
24741fbaed0Stron      * Send the request and receive the reply.
24841fbaed0Stron      */
24941fbaed0Stron     if (attr_clnt_request(tls_mgr,
25041fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request */
251*837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_LOOKUP),
252*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
253*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
25441fbaed0Stron 			  ATTR_TYPE_END,
25541fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply */
256*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
257*837e7c1aSchristos 			  RECV_ATTR_DATA(TLS_MGR_ATTR_SESSION, buf),
25841fbaed0Stron 			  ATTR_TYPE_END) != 2)
25941fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
26041fbaed0Stron     return (status);
26141fbaed0Stron }
26241fbaed0Stron 
26341fbaed0Stron /* tls_mgr_update - save session to cache */
26441fbaed0Stron 
26541fbaed0Stron int     tls_mgr_update(const char *cache_type, const char *cache_id,
26641fbaed0Stron 		               const char *buf, ssize_t len)
26741fbaed0Stron {
26841fbaed0Stron     int     status;
26941fbaed0Stron 
27041fbaed0Stron     /*
27141fbaed0Stron      * Create the tlsmgr client handle.
27241fbaed0Stron      */
27341fbaed0Stron     if (tls_mgr == 0)
27441fbaed0Stron 	tls_mgr_open();
27541fbaed0Stron 
27641fbaed0Stron     /*
27741fbaed0Stron      * Send the request and receive the reply.
27841fbaed0Stron      */
27941fbaed0Stron     if (attr_clnt_request(tls_mgr,
28041fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request */
281*837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_UPDATE),
282*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
283*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
284*837e7c1aSchristos 			  SEND_ATTR_DATA(TLS_MGR_ATTR_SESSION, len, buf),
28541fbaed0Stron 			  ATTR_TYPE_END,
28641fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply */
287*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
28841fbaed0Stron 			  ATTR_TYPE_END) != 1)
28941fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
29041fbaed0Stron     return (status);
29141fbaed0Stron }
29241fbaed0Stron 
29341fbaed0Stron /* tls_mgr_delete - remove cached session */
29441fbaed0Stron 
29541fbaed0Stron int     tls_mgr_delete(const char *cache_type, const char *cache_id)
29641fbaed0Stron {
29741fbaed0Stron     int     status;
29841fbaed0Stron 
29941fbaed0Stron     /*
30041fbaed0Stron      * Create the tlsmgr client handle.
30141fbaed0Stron      */
30241fbaed0Stron     if (tls_mgr == 0)
30341fbaed0Stron 	tls_mgr_open();
30441fbaed0Stron 
30541fbaed0Stron     /*
30641fbaed0Stron      * Send the request and receive the reply.
30741fbaed0Stron      */
30841fbaed0Stron     if (attr_clnt_request(tls_mgr,
30941fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request */
310*837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_DELETE),
311*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
312*837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
31341fbaed0Stron 			  ATTR_TYPE_END,
31441fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply */
315*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
31641fbaed0Stron 			  ATTR_TYPE_END) != 1)
31741fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
31841fbaed0Stron     return (status);
31941fbaed0Stron }
32041fbaed0Stron 
3212e5cb688Stron /* request_scache_key - ask tlsmgr(8) for matching key */
3222e5cb688Stron 
3232e5cb688Stron static TLS_TICKET_KEY *request_scache_key(unsigned char *keyname)
3242e5cb688Stron {
3252e5cb688Stron     TLS_TICKET_KEY tmp;
3262e5cb688Stron     static VSTRING *keybuf;
3272e5cb688Stron     char   *name;
3282e5cb688Stron     size_t  len;
3292e5cb688Stron     int     status;
3302e5cb688Stron 
3312e5cb688Stron     /*
3322e5cb688Stron      * Create the tlsmgr client handle.
3332e5cb688Stron      */
3342e5cb688Stron     if (tls_mgr == 0)
3352e5cb688Stron 	tls_mgr_open();
3362e5cb688Stron 
3372e5cb688Stron     if (keybuf == 0)
3382e5cb688Stron 	keybuf = vstring_alloc(sizeof(tmp));
3392e5cb688Stron 
3402e5cb688Stron     /* In tlsmgr requests we encode null key names as empty strings. */
3412e5cb688Stron     name = keyname ? (char *) keyname : "";
3422e5cb688Stron     len = keyname ? TLS_TICKET_NAMELEN : 0;
3432e5cb688Stron 
3442e5cb688Stron     /*
3452e5cb688Stron      * Send the request and receive the reply.
3462e5cb688Stron      */
3472e5cb688Stron     if (attr_clnt_request(tls_mgr,
3482e5cb688Stron 			  ATTR_FLAG_NONE,	/* Request */
349*837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_TKTKEY),
350*837e7c1aSchristos 			  SEND_ATTR_DATA(TLS_MGR_ATTR_KEYNAME, len, name),
3512e5cb688Stron 			  ATTR_TYPE_END,
3522e5cb688Stron 			  ATTR_FLAG_MISSING,	/* Reply */
353*837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
354*837e7c1aSchristos 			  RECV_ATTR_DATA(TLS_MGR_ATTR_KEYBUF, keybuf),
3552e5cb688Stron 			  ATTR_TYPE_END) != 2
3562e5cb688Stron 	|| status != TLS_MGR_STAT_OK
3572e5cb688Stron 	|| LEN(keybuf) != sizeof(tmp))
3582e5cb688Stron 	return (0);
3592e5cb688Stron 
360*837e7c1aSchristos     memcpy((void *) &tmp, STR(keybuf), sizeof(tmp));
3612e5cb688Stron     return (tls_scache_key_rotate(&tmp));
3622e5cb688Stron }
3632e5cb688Stron 
3642e5cb688Stron /* tls_mgr_key - session ticket key lookup, local cache, then tlsmgr(8) */
3652e5cb688Stron 
3662e5cb688Stron TLS_TICKET_KEY *tls_mgr_key(unsigned char *keyname, int timeout)
3672e5cb688Stron {
3682e5cb688Stron     TLS_TICKET_KEY *key = 0;
3692e5cb688Stron     time_t  now = time((time_t *) 0);
3702e5cb688Stron 
3712e5cb688Stron     /* A zero timeout disables session tickets. */
3722e5cb688Stron     if (timeout <= 0)
3732e5cb688Stron 	return (0);
3742e5cb688Stron 
3752e5cb688Stron     if ((key = tls_scache_key(keyname, now, timeout)) == 0)
3762e5cb688Stron 	key = request_scache_key(keyname);
3772e5cb688Stron     return (key);
3782e5cb688Stron }
3792e5cb688Stron 
38041fbaed0Stron #ifdef TEST
38141fbaed0Stron 
38241fbaed0Stron /* System library. */
38341fbaed0Stron 
38441fbaed0Stron #include <stdlib.h>
38541fbaed0Stron 
38641fbaed0Stron /* Utility library. */
38741fbaed0Stron 
38841fbaed0Stron #include <argv.h>
38941fbaed0Stron #include <msg_vstream.h>
39041fbaed0Stron #include <vstring_vstream.h>
39141fbaed0Stron #include <hex_code.h>
39241fbaed0Stron 
39341fbaed0Stron /* Global library. */
39441fbaed0Stron 
39541fbaed0Stron #include <config.h>
39641fbaed0Stron 
39741fbaed0Stron /* Application-specific. */
39841fbaed0Stron 
39941fbaed0Stron int     main(int unused_ac, char **av)
40041fbaed0Stron {
40141fbaed0Stron     VSTRING *inbuf = vstring_alloc(10);
40241fbaed0Stron     int     status;
40341fbaed0Stron     ARGV   *argv = 0;
40441fbaed0Stron 
40541fbaed0Stron     msg_vstream_init(av[0], VSTREAM_ERR);
40641fbaed0Stron 
40741fbaed0Stron     msg_verbose = 3;
40841fbaed0Stron 
40941fbaed0Stron     mail_conf_read();
41041fbaed0Stron     msg_info("using config files in %s", var_config_dir);
41141fbaed0Stron 
41241fbaed0Stron     if (chdir(var_queue_dir) < 0)
41341fbaed0Stron 	msg_fatal("chdir %s: %m", var_queue_dir);
41441fbaed0Stron 
41541fbaed0Stron     while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
416*837e7c1aSchristos 	argv = argv_split(STR(inbuf), CHARS_SPACE);
41741fbaed0Stron 	if (argv->argc == 0) {
41841fbaed0Stron 	    argv_free(argv);
41941fbaed0Stron 	    continue;
42041fbaed0Stron 	}
42141fbaed0Stron #define COMMAND(argv, str, len) \
42241fbaed0Stron     (strcasecmp(argv->argv[0], str) == 0 && argv->argc == len)
42341fbaed0Stron 
42441fbaed0Stron 	if (COMMAND(argv, "policy", 2)) {
42541fbaed0Stron 	    int     cachable;
4262e5cb688Stron 	    int     timeout;
42741fbaed0Stron 
4282e5cb688Stron 	    status = tls_mgr_policy(argv->argv[1], &cachable, &timeout);
4292e5cb688Stron 	    vstream_printf("status=%d cachable=%d timeout=%d\n",
4302e5cb688Stron 			   status, cachable, timeout);
43141fbaed0Stron 	} else if (COMMAND(argv, "seed", 2)) {
43241fbaed0Stron 	    VSTRING *buf = vstring_alloc(10);
43341fbaed0Stron 	    VSTRING *hex = vstring_alloc(10);
43441fbaed0Stron 	    int     len = atoi(argv->argv[1]);
43541fbaed0Stron 
43641fbaed0Stron 	    status = tls_mgr_seed(buf, len);
43741fbaed0Stron 	    hex_encode(hex, STR(buf), LEN(buf));
43841fbaed0Stron 	    vstream_printf("status=%d seed=%s\n", status, STR(hex));
43941fbaed0Stron 	    vstring_free(hex);
44041fbaed0Stron 	    vstring_free(buf);
44141fbaed0Stron 	} else if (COMMAND(argv, "lookup", 3)) {
44241fbaed0Stron 	    VSTRING *buf = vstring_alloc(10);
44341fbaed0Stron 
44441fbaed0Stron 	    status = tls_mgr_lookup(argv->argv[1], argv->argv[2], buf);
44541fbaed0Stron 	    vstream_printf("status=%d session=%.*s\n",
44641fbaed0Stron 			   status, LEN(buf), STR(buf));
44741fbaed0Stron 	    vstring_free(buf);
44841fbaed0Stron 	} else if (COMMAND(argv, "update", 4)) {
44941fbaed0Stron 	    status = tls_mgr_update(argv->argv[1], argv->argv[2],
45041fbaed0Stron 				    argv->argv[3], strlen(argv->argv[3]));
45141fbaed0Stron 	    vstream_printf("status=%d\n", status);
45241fbaed0Stron 	} else if (COMMAND(argv, "delete", 3)) {
45341fbaed0Stron 	    status = tls_mgr_delete(argv->argv[1], argv->argv[2]);
45441fbaed0Stron 	    vstream_printf("status=%d\n", status);
45541fbaed0Stron 	} else {
45641fbaed0Stron 	    vstream_printf("usage:\n"
45741fbaed0Stron 			   "seed byte_count\n"
45841fbaed0Stron 			   "policy smtpd|smtp|lmtp\n"
45941fbaed0Stron 			   "lookup smtpd|smtp|lmtp cache_id\n"
46041fbaed0Stron 			   "update smtpd|smtp|lmtp cache_id session\n"
46141fbaed0Stron 			   "delete smtpd|smtp|lmtp cache_id\n");
46241fbaed0Stron 	}
46341fbaed0Stron 	vstream_fflush(VSTREAM_OUT);
46441fbaed0Stron 	argv_free(argv);
46541fbaed0Stron     }
46641fbaed0Stron 
46741fbaed0Stron     vstring_free(inbuf);
46841fbaed0Stron     return (0);
46941fbaed0Stron }
47041fbaed0Stron 
47141fbaed0Stron #endif					/* TEST */
47241fbaed0Stron 
47341fbaed0Stron #endif					/* USE_TLS */
474