1*fb52cf35Schristos /*	$NetBSD: tls_mgr.c,v 1.4 2022/10/08 16:12:50 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
112*fb52cf35Schristos /*
113*fb52cf35Schristos /*	Wietse Venema
114*fb52cf35Schristos /*	Google, Inc.
115*fb52cf35Schristos /*	111 8th Avenue
116*fb52cf35Schristos /*	New York, NY 10011, USA
11741fbaed0Stron /*--*/
11841fbaed0Stron 
11941fbaed0Stron /* System library. */
12041fbaed0Stron 
12141fbaed0Stron #include <sys_defs.h>
12241fbaed0Stron 
12341fbaed0Stron #ifdef USE_TLS
12441fbaed0Stron 
12541fbaed0Stron #ifdef STRCASECMP_IN_STRINGS_H
12641fbaed0Stron #include <strings.h>
12741fbaed0Stron #endif
12841fbaed0Stron 
12941fbaed0Stron /* Utility library. */
13041fbaed0Stron 
13141fbaed0Stron #include <msg.h>
13241fbaed0Stron #include <vstream.h>
13341fbaed0Stron #include <vstring.h>
13441fbaed0Stron #include <attr.h>
13541fbaed0Stron #include <attr_clnt.h>
1362e5cb688Stron #include <mymalloc.h>
1372e5cb688Stron #include <stringops.h>
13841fbaed0Stron 
13941fbaed0Stron /* Global library. */
14041fbaed0Stron 
14141fbaed0Stron #include <mail_params.h>
14241fbaed0Stron #include <mail_proto.h>
1432e5cb688Stron 
1442e5cb688Stron /* TLS library. */
14541fbaed0Stron #include <tls_mgr.h>
14641fbaed0Stron 
14741fbaed0Stron /* Application-specific. */
14841fbaed0Stron 
1492e5cb688Stron #define STR(x) vstring_str(x)
1502e5cb688Stron #define LEN(x) VSTRING_LEN(x)
1512e5cb688Stron 
15241fbaed0Stron static ATTR_CLNT *tls_mgr;
15341fbaed0Stron 
154*fb52cf35Schristos /* tls_mgr_handshake - receive server protocol announcement */
155*fb52cf35Schristos 
tls_mgr_handshake(VSTREAM * stream)156*fb52cf35Schristos static int tls_mgr_handshake(VSTREAM *stream)
157*fb52cf35Schristos {
158*fb52cf35Schristos     return (attr_scan(stream, ATTR_FLAG_STRICT,
159*fb52cf35Schristos 		   RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
160*fb52cf35Schristos 		      ATTR_TYPE_END));
161*fb52cf35Schristos }
162*fb52cf35Schristos 
16341fbaed0Stron /* tls_mgr_open - create client handle */
16441fbaed0Stron 
tls_mgr_open(void)16541fbaed0Stron static void tls_mgr_open(void)
16641fbaed0Stron {
1672e5cb688Stron     char   *service;
16841fbaed0Stron 
16941fbaed0Stron     /*
17041fbaed0Stron      * Sanity check.
17141fbaed0Stron      */
17241fbaed0Stron     if (tls_mgr != 0)
17341fbaed0Stron 	msg_panic("tls_mgr_open: multiple initialization");
17441fbaed0Stron 
17541fbaed0Stron     /*
17641fbaed0Stron      * Use whatever IPC is preferred for internal use: UNIX-domain sockets or
17741fbaed0Stron      * Solaris streams.
17841fbaed0Stron      */
1792e5cb688Stron     service = concatenate("local:" TLS_MGR_CLASS "/", var_tls_mgr_service,
1802e5cb688Stron 			  (char *) 0);
1812e5cb688Stron     tls_mgr = attr_clnt_create(service, var_ipc_timeout,
18241fbaed0Stron 			       var_ipc_idle_limit, var_ipc_ttl_limit);
1832e5cb688Stron     myfree(service);
1842e5cb688Stron 
18541fbaed0Stron     attr_clnt_control(tls_mgr,
18641fbaed0Stron 		      ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
187*fb52cf35Schristos 		      ATTR_CLNT_CTL_HANDSHAKE, tls_mgr_handshake,
18841fbaed0Stron 		      ATTR_CLNT_CTL_END);
18941fbaed0Stron }
19041fbaed0Stron 
19141fbaed0Stron /* tls_mgr_seed - request PRNG seed */
19241fbaed0Stron 
tls_mgr_seed(VSTRING * buf,int len)19341fbaed0Stron int     tls_mgr_seed(VSTRING *buf, int len)
19441fbaed0Stron {
19541fbaed0Stron     int     status;
19641fbaed0Stron 
19741fbaed0Stron     /*
19841fbaed0Stron      * Create the tlsmgr client handle.
19941fbaed0Stron      */
20041fbaed0Stron     if (tls_mgr == 0)
20141fbaed0Stron 	tls_mgr_open();
20241fbaed0Stron 
20341fbaed0Stron     /*
20441fbaed0Stron      * Request seed.
20541fbaed0Stron      */
20641fbaed0Stron     if (attr_clnt_request(tls_mgr,
20741fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request attributes */
208837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_SEED),
209837e7c1aSchristos 			  SEND_ATTR_INT(TLS_MGR_ATTR_SIZE, len),
21041fbaed0Stron 			  ATTR_TYPE_END,
21141fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply attributes */
212837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
213837e7c1aSchristos 			  RECV_ATTR_DATA(TLS_MGR_ATTR_SEED, buf),
21441fbaed0Stron 			  ATTR_TYPE_END) != 2)
21541fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
21641fbaed0Stron     return (status);
21741fbaed0Stron }
21841fbaed0Stron 
21941fbaed0Stron /* tls_mgr_policy - request caching policy */
22041fbaed0Stron 
tls_mgr_policy(const char * cache_type,int * cachable,int * timeout)2212e5cb688Stron int     tls_mgr_policy(const char *cache_type, int *cachable, int *timeout)
22241fbaed0Stron {
22341fbaed0Stron     int     status;
22441fbaed0Stron 
22541fbaed0Stron     /*
22641fbaed0Stron      * Create the tlsmgr client handle.
22741fbaed0Stron      */
22841fbaed0Stron     if (tls_mgr == 0)
22941fbaed0Stron 	tls_mgr_open();
23041fbaed0Stron 
23141fbaed0Stron     /*
23241fbaed0Stron      * Request policy.
23341fbaed0Stron      */
23441fbaed0Stron     if (attr_clnt_request(tls_mgr,
23541fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request attributes */
236837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_POLICY),
237837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
23841fbaed0Stron 			  ATTR_TYPE_END,
23941fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply attributes */
240837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
241837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_CACHABLE, cachable),
242837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_SESSTOUT, timeout),
2432e5cb688Stron 			  ATTR_TYPE_END) != 3)
24441fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
24541fbaed0Stron     return (status);
24641fbaed0Stron }
24741fbaed0Stron 
24841fbaed0Stron /* tls_mgr_lookup - request cached session */
24941fbaed0Stron 
tls_mgr_lookup(const char * cache_type,const char * cache_id,VSTRING * buf)25041fbaed0Stron int     tls_mgr_lookup(const char *cache_type, const char *cache_id,
25141fbaed0Stron 		               VSTRING *buf)
25241fbaed0Stron {
25341fbaed0Stron     int     status;
25441fbaed0Stron 
25541fbaed0Stron     /*
25641fbaed0Stron      * Create the tlsmgr client handle.
25741fbaed0Stron      */
25841fbaed0Stron     if (tls_mgr == 0)
25941fbaed0Stron 	tls_mgr_open();
26041fbaed0Stron 
26141fbaed0Stron     /*
26241fbaed0Stron      * Send the request and receive the reply.
26341fbaed0Stron      */
26441fbaed0Stron     if (attr_clnt_request(tls_mgr,
26541fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request */
266837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_LOOKUP),
267837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
268837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
26941fbaed0Stron 			  ATTR_TYPE_END,
27041fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply */
271837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
272837e7c1aSchristos 			  RECV_ATTR_DATA(TLS_MGR_ATTR_SESSION, buf),
27341fbaed0Stron 			  ATTR_TYPE_END) != 2)
27441fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
27541fbaed0Stron     return (status);
27641fbaed0Stron }
27741fbaed0Stron 
27841fbaed0Stron /* tls_mgr_update - save session to cache */
27941fbaed0Stron 
tls_mgr_update(const char * cache_type,const char * cache_id,const char * buf,ssize_t len)28041fbaed0Stron int     tls_mgr_update(const char *cache_type, const char *cache_id,
28141fbaed0Stron 		               const char *buf, ssize_t len)
28241fbaed0Stron {
28341fbaed0Stron     int     status;
28441fbaed0Stron 
28541fbaed0Stron     /*
28641fbaed0Stron      * Create the tlsmgr client handle.
28741fbaed0Stron      */
28841fbaed0Stron     if (tls_mgr == 0)
28941fbaed0Stron 	tls_mgr_open();
29041fbaed0Stron 
29141fbaed0Stron     /*
29241fbaed0Stron      * Send the request and receive the reply.
29341fbaed0Stron      */
29441fbaed0Stron     if (attr_clnt_request(tls_mgr,
29541fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request */
296837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_UPDATE),
297837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
298837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
299837e7c1aSchristos 			  SEND_ATTR_DATA(TLS_MGR_ATTR_SESSION, len, buf),
30041fbaed0Stron 			  ATTR_TYPE_END,
30141fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply */
302837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
30341fbaed0Stron 			  ATTR_TYPE_END) != 1)
30441fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
30541fbaed0Stron     return (status);
30641fbaed0Stron }
30741fbaed0Stron 
30841fbaed0Stron /* tls_mgr_delete - remove cached session */
30941fbaed0Stron 
tls_mgr_delete(const char * cache_type,const char * cache_id)31041fbaed0Stron int     tls_mgr_delete(const char *cache_type, const char *cache_id)
31141fbaed0Stron {
31241fbaed0Stron     int     status;
31341fbaed0Stron 
31441fbaed0Stron     /*
31541fbaed0Stron      * Create the tlsmgr client handle.
31641fbaed0Stron      */
31741fbaed0Stron     if (tls_mgr == 0)
31841fbaed0Stron 	tls_mgr_open();
31941fbaed0Stron 
32041fbaed0Stron     /*
32141fbaed0Stron      * Send the request and receive the reply.
32241fbaed0Stron      */
32341fbaed0Stron     if (attr_clnt_request(tls_mgr,
32441fbaed0Stron 			  ATTR_FLAG_NONE,	/* Request */
325837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_DELETE),
326837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_TYPE, cache_type),
327837e7c1aSchristos 			  SEND_ATTR_STR(TLS_MGR_ATTR_CACHE_ID, cache_id),
32841fbaed0Stron 			  ATTR_TYPE_END,
32941fbaed0Stron 			  ATTR_FLAG_MISSING,	/* Reply */
330837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
33141fbaed0Stron 			  ATTR_TYPE_END) != 1)
33241fbaed0Stron 	status = TLS_MGR_STAT_FAIL;
33341fbaed0Stron     return (status);
33441fbaed0Stron }
33541fbaed0Stron 
3362e5cb688Stron /* request_scache_key - ask tlsmgr(8) for matching key */
3372e5cb688Stron 
request_scache_key(unsigned char * keyname)3382e5cb688Stron static TLS_TICKET_KEY *request_scache_key(unsigned char *keyname)
3392e5cb688Stron {
3402e5cb688Stron     TLS_TICKET_KEY tmp;
3412e5cb688Stron     static VSTRING *keybuf;
3422e5cb688Stron     char   *name;
3432e5cb688Stron     size_t  len;
3442e5cb688Stron     int     status;
3452e5cb688Stron 
3462e5cb688Stron     /*
3472e5cb688Stron      * Create the tlsmgr client handle.
3482e5cb688Stron      */
3492e5cb688Stron     if (tls_mgr == 0)
3502e5cb688Stron 	tls_mgr_open();
3512e5cb688Stron 
3522e5cb688Stron     if (keybuf == 0)
3532e5cb688Stron 	keybuf = vstring_alloc(sizeof(tmp));
3542e5cb688Stron 
3552e5cb688Stron     /* In tlsmgr requests we encode null key names as empty strings. */
3562e5cb688Stron     name = keyname ? (char *) keyname : "";
3572e5cb688Stron     len = keyname ? TLS_TICKET_NAMELEN : 0;
3582e5cb688Stron 
3592e5cb688Stron     /*
3602e5cb688Stron      * Send the request and receive the reply.
3612e5cb688Stron      */
3622e5cb688Stron     if (attr_clnt_request(tls_mgr,
3632e5cb688Stron 			  ATTR_FLAG_NONE,	/* Request */
364837e7c1aSchristos 			SEND_ATTR_STR(TLS_MGR_ATTR_REQ, TLS_MGR_REQ_TKTKEY),
365837e7c1aSchristos 			  SEND_ATTR_DATA(TLS_MGR_ATTR_KEYNAME, len, name),
3662e5cb688Stron 			  ATTR_TYPE_END,
3672e5cb688Stron 			  ATTR_FLAG_MISSING,	/* Reply */
368837e7c1aSchristos 			  RECV_ATTR_INT(TLS_MGR_ATTR_STATUS, &status),
369837e7c1aSchristos 			  RECV_ATTR_DATA(TLS_MGR_ATTR_KEYBUF, keybuf),
3702e5cb688Stron 			  ATTR_TYPE_END) != 2
3712e5cb688Stron 	|| status != TLS_MGR_STAT_OK
3722e5cb688Stron 	|| LEN(keybuf) != sizeof(tmp))
3732e5cb688Stron 	return (0);
3742e5cb688Stron 
375837e7c1aSchristos     memcpy((void *) &tmp, STR(keybuf), sizeof(tmp));
3762e5cb688Stron     return (tls_scache_key_rotate(&tmp));
3772e5cb688Stron }
3782e5cb688Stron 
3792e5cb688Stron /* tls_mgr_key - session ticket key lookup, local cache, then tlsmgr(8) */
3802e5cb688Stron 
tls_mgr_key(unsigned char * keyname,int timeout)3812e5cb688Stron TLS_TICKET_KEY *tls_mgr_key(unsigned char *keyname, int timeout)
3822e5cb688Stron {
3832e5cb688Stron     TLS_TICKET_KEY *key = 0;
3842e5cb688Stron     time_t  now = time((time_t *) 0);
3852e5cb688Stron 
3862e5cb688Stron     /* A zero timeout disables session tickets. */
3872e5cb688Stron     if (timeout <= 0)
3882e5cb688Stron 	return (0);
3892e5cb688Stron 
3902e5cb688Stron     if ((key = tls_scache_key(keyname, now, timeout)) == 0)
3912e5cb688Stron 	key = request_scache_key(keyname);
3922e5cb688Stron     return (key);
3932e5cb688Stron }
3942e5cb688Stron 
39541fbaed0Stron #ifdef TEST
39641fbaed0Stron 
39741fbaed0Stron /* System library. */
39841fbaed0Stron 
39941fbaed0Stron #include <stdlib.h>
40041fbaed0Stron 
40141fbaed0Stron /* Utility library. */
40241fbaed0Stron 
40341fbaed0Stron #include <argv.h>
40441fbaed0Stron #include <msg_vstream.h>
40541fbaed0Stron #include <vstring_vstream.h>
40641fbaed0Stron #include <hex_code.h>
40741fbaed0Stron 
40841fbaed0Stron /* Global library. */
40941fbaed0Stron 
41041fbaed0Stron #include <config.h>
41141fbaed0Stron 
41241fbaed0Stron /* Application-specific. */
41341fbaed0Stron 
main(int unused_ac,char ** av)41441fbaed0Stron int     main(int unused_ac, char **av)
41541fbaed0Stron {
41641fbaed0Stron     VSTRING *inbuf = vstring_alloc(10);
41741fbaed0Stron     int     status;
41841fbaed0Stron     ARGV   *argv = 0;
41941fbaed0Stron 
42041fbaed0Stron     msg_vstream_init(av[0], VSTREAM_ERR);
42141fbaed0Stron 
42241fbaed0Stron     msg_verbose = 3;
42341fbaed0Stron 
42441fbaed0Stron     mail_conf_read();
42541fbaed0Stron     msg_info("using config files in %s", var_config_dir);
42641fbaed0Stron 
42741fbaed0Stron     if (chdir(var_queue_dir) < 0)
42841fbaed0Stron 	msg_fatal("chdir %s: %m", var_queue_dir);
42941fbaed0Stron 
43041fbaed0Stron     while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
431837e7c1aSchristos 	argv = argv_split(STR(inbuf), CHARS_SPACE);
43241fbaed0Stron 	if (argv->argc == 0) {
43341fbaed0Stron 	    argv_free(argv);
43441fbaed0Stron 	    continue;
43541fbaed0Stron 	}
43641fbaed0Stron #define COMMAND(argv, str, len) \
43741fbaed0Stron     (strcasecmp(argv->argv[0], str) == 0 && argv->argc == len)
43841fbaed0Stron 
43941fbaed0Stron 	if (COMMAND(argv, "policy", 2)) {
44041fbaed0Stron 	    int     cachable;
4412e5cb688Stron 	    int     timeout;
44241fbaed0Stron 
4432e5cb688Stron 	    status = tls_mgr_policy(argv->argv[1], &cachable, &timeout);
4442e5cb688Stron 	    vstream_printf("status=%d cachable=%d timeout=%d\n",
4452e5cb688Stron 			   status, cachable, timeout);
44641fbaed0Stron 	} else if (COMMAND(argv, "seed", 2)) {
44741fbaed0Stron 	    VSTRING *buf = vstring_alloc(10);
44841fbaed0Stron 	    VSTRING *hex = vstring_alloc(10);
44941fbaed0Stron 	    int     len = atoi(argv->argv[1]);
45041fbaed0Stron 
45141fbaed0Stron 	    status = tls_mgr_seed(buf, len);
45241fbaed0Stron 	    hex_encode(hex, STR(buf), LEN(buf));
45341fbaed0Stron 	    vstream_printf("status=%d seed=%s\n", status, STR(hex));
45441fbaed0Stron 	    vstring_free(hex);
45541fbaed0Stron 	    vstring_free(buf);
45641fbaed0Stron 	} else if (COMMAND(argv, "lookup", 3)) {
45741fbaed0Stron 	    VSTRING *buf = vstring_alloc(10);
45841fbaed0Stron 
45941fbaed0Stron 	    status = tls_mgr_lookup(argv->argv[1], argv->argv[2], buf);
46041fbaed0Stron 	    vstream_printf("status=%d session=%.*s\n",
4613c275423Schristos 			   status, (int) LEN(buf), STR(buf));
46241fbaed0Stron 	    vstring_free(buf);
46341fbaed0Stron 	} else if (COMMAND(argv, "update", 4)) {
46441fbaed0Stron 	    status = tls_mgr_update(argv->argv[1], argv->argv[2],
46541fbaed0Stron 				    argv->argv[3], strlen(argv->argv[3]));
46641fbaed0Stron 	    vstream_printf("status=%d\n", status);
46741fbaed0Stron 	} else if (COMMAND(argv, "delete", 3)) {
46841fbaed0Stron 	    status = tls_mgr_delete(argv->argv[1], argv->argv[2]);
46941fbaed0Stron 	    vstream_printf("status=%d\n", status);
47041fbaed0Stron 	} else {
47141fbaed0Stron 	    vstream_printf("usage:\n"
47241fbaed0Stron 			   "seed byte_count\n"
47341fbaed0Stron 			   "policy smtpd|smtp|lmtp\n"
47441fbaed0Stron 			   "lookup smtpd|smtp|lmtp cache_id\n"
47541fbaed0Stron 			   "update smtpd|smtp|lmtp cache_id session\n"
47641fbaed0Stron 			   "delete smtpd|smtp|lmtp cache_id\n");
47741fbaed0Stron 	}
47841fbaed0Stron 	vstream_fflush(VSTREAM_OUT);
47941fbaed0Stron 	argv_free(argv);
48041fbaed0Stron     }
48141fbaed0Stron 
48241fbaed0Stron     vstring_free(inbuf);
48341fbaed0Stron     return (0);
48441fbaed0Stron }
48541fbaed0Stron 
48641fbaed0Stron #endif					/* TEST */
48741fbaed0Stron 
48841fbaed0Stron #endif					/* USE_TLS */
489