xref: /netbsd-src/external/ibm-public/postfix/dist/src/tls/tls_mgr.c (revision daf6c4152fcddc27c445489775ed1f66ab4ea9a9)
1 /*	$NetBSD: tls_mgr.c,v 1.1.1.1 2009/06/23 10:08:57 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	tls_mgr 3
6 /* SUMMARY
7 /*	tlsmgr client interface
8 /* SYNOPSIS
9 /*	#include <tls_mgr.h>
10 /*
11 /*	int	tls_mgr_seed(buf, len)
12 /*	VSTRING	*buf;
13 /*	int	len;
14 /*
15 /*	int	tls_mgr_policy(cache_type, cachable)
16 /*	const char *cache_type;
17 /*	int	*cachable;
18 /*
19 /*	int	tls_mgr_update(cache_type, cache_id, buf, len)
20 /*	const char *cache_type;
21 /*	const char *cache_id;
22 /*	const char *buf;
23 /*	ssize_t	len;
24 /*
25 /*	int	tls_mgr_lookup(cache_type, cache_id, buf)
26 /*	const char *cache_type;
27 /*	const char *cache_id;
28 /*	VSTRING	*buf;
29 /*
30 /*	int	tls_mgr_delete(cache_type, cache_id)
31 /*	const char *cache_type;
32 /*	const char *cache_id;
33 /* DESCRIPTION
34 /*	These routines communicate with the tlsmgr(8) server for
35 /*	entropy and session cache management. Since these are
36 /*	non-critical services, requests are allowed to fail without
37 /*	disrupting Postfix.
38 /*
39 /*	tls_mgr_seed() requests entropy from the tlsmgr(8)
40 /*	Pseudo Random Number Generator (PRNG) pool.
41 /*
42 /*	tls_mgr_policy() requests the session caching policy.
43 /*
44 /*	tls_mgr_lookup() loads the specified session from
45 /*	the specified session cache.
46 /*
47 /*	tls_mgr_update() saves the specified session to
48 /*	the specified session cache.
49 /*
50 /*	tls_mgr_delete() removes specified session from
51 /*	the specified session cache.
52 /*
53 /*	Arguments
54 /* .IP cache_type
55 /*	One of TLS_MGR_SCACHE_SMTPD, TLS_MGR_SCACHE_SMTP or
56 /*	TLS_MGR_SCACHE_LMTP.
57 /* .IP cachable
58 /*	Pointer to int, set non-zero if the requested cache_type
59 /*	is enabled.
60 /* .IP cache_id
61 /*	The session cache lookup key.
62 /* .IP buf
63 /*	The result or input buffer.
64 /* .IP len
65 /*	The length of the input buffer, or the amount of data requested.
66 /* DIAGNOSTICS
67 /*	All client functions return one of the following status codes:
68 /* .IP TLS_MGR_STAT_OK
69 /*      The request completed, and the requested operation was
70 /*	successful (for example, the requested session was found,
71 /*	or the specified session was saved or removed).
72 /* .IP TLS_MGR_STAT_ERR
73 /*      The request completed, but the requested operation failed
74 /*	(for example, the requested object was not found or the
75 /*	specified session was not saved or removed).
76 /* .IP TLS_MGR_STAT_FAIL
77 /*      The request could not complete (the client could not
78 /*	communicate with the tlsmgr(8) server).
79 /* SEE ALSO
80 /*	tlsmgr(8) TLS session and PRNG management
81 /* LICENSE
82 /* .ad
83 /* .fi
84 /*	The Secure Mailer license must be distributed with this software.
85 /* AUTHOR(S)
86 /*	Wietse Venema
87 /*	IBM T.J. Watson Research
88 /*	P.O. Box 704
89 /*	Yorktown Heights, NY 10598, USA
90 /*--*/
91 
92 /* System library. */
93 
94 #include <sys_defs.h>
95 
96 #ifdef USE_TLS
97 
98 #ifdef STRCASECMP_IN_STRINGS_H
99 #include <strings.h>
100 #endif
101 
102 /* Utility library. */
103 
104 #include <msg.h>
105 #include <vstream.h>
106 #include <vstring.h>
107 #include <attr.h>
108 #include <attr_clnt.h>
109 
110 /* Global library. */
111 
112 #include <mail_params.h>
113 #include <mail_proto.h>
114 #include <tls_mgr.h>
115 
116 /* Application-specific. */
117 
118 static ATTR_CLNT *tls_mgr;
119 
120 /* tls_mgr_open - create client handle */
121 
122 static void tls_mgr_open(void)
123 {
124 
125     /*
126      * Sanity check.
127      */
128     if (tls_mgr != 0)
129 	msg_panic("tls_mgr_open: multiple initialization");
130 
131     /*
132      * Use whatever IPC is preferred for internal use: UNIX-domain sockets or
133      * Solaris streams.
134      */
135 #ifndef VAR_TLS_MGR_SERVICE
136     tls_mgr = attr_clnt_create("local:" TLS_MGR_CLASS "/" TLS_MGR_SERVICE,
137 			       var_ipc_timeout, var_ipc_idle_limit,
138 			       var_ipc_ttl_limit);
139 #else
140     tls_mgr = attr_clnt_create(var_tlsmgr_service, var_ipc_timeout,
141 			       var_ipc_idle_limit, var_ipc_ttl_limit);
142 #endif
143     attr_clnt_control(tls_mgr,
144 		      ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
145 		      ATTR_CLNT_CTL_END);
146 }
147 
148 /* tls_mgr_seed - request PRNG seed */
149 
150 int     tls_mgr_seed(VSTRING *buf, int len)
151 {
152     int     status;
153 
154     /*
155      * Create the tlsmgr client handle.
156      */
157     if (tls_mgr == 0)
158 	tls_mgr_open();
159 
160     /*
161      * Request seed.
162      */
163     if (attr_clnt_request(tls_mgr,
164 			  ATTR_FLAG_NONE,	/* Request attributes */
165 			  ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_SEED,
166 			  ATTR_TYPE_INT, TLS_MGR_ATTR_SIZE, len,
167 			  ATTR_TYPE_END,
168 			  ATTR_FLAG_MISSING,	/* Reply attributes */
169 			  ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status,
170 			  ATTR_TYPE_DATA, TLS_MGR_ATTR_SEED, buf,
171 			  ATTR_TYPE_END) != 2)
172 	status = TLS_MGR_STAT_FAIL;
173     return (status);
174 }
175 
176 /* tls_mgr_policy - request caching policy */
177 
178 int     tls_mgr_policy(const char *cache_type, int *cachable)
179 {
180     int     status;
181 
182     /*
183      * Create the tlsmgr client handle.
184      */
185     if (tls_mgr == 0)
186 	tls_mgr_open();
187 
188     /*
189      * Request policy.
190      */
191     if (attr_clnt_request(tls_mgr,
192 			  ATTR_FLAG_NONE,	/* Request attributes */
193 			ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_POLICY,
194 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
195 			  ATTR_TYPE_END,
196 			  ATTR_FLAG_MISSING,	/* Reply attributes */
197 			  ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status,
198 			  ATTR_TYPE_INT, TLS_MGR_ATTR_CACHABLE, cachable,
199 			  ATTR_TYPE_END) != 2)
200 	status = TLS_MGR_STAT_FAIL;
201     return (status);
202 }
203 
204 /* tls_mgr_lookup - request cached session */
205 
206 int     tls_mgr_lookup(const char *cache_type, const char *cache_id,
207 		               VSTRING *buf)
208 {
209     int     status;
210 
211     /*
212      * Create the tlsmgr client handle.
213      */
214     if (tls_mgr == 0)
215 	tls_mgr_open();
216 
217     /*
218      * Send the request and receive the reply.
219      */
220     if (attr_clnt_request(tls_mgr,
221 			  ATTR_FLAG_NONE,	/* Request */
222 			ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_LOOKUP,
223 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
224 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
225 			  ATTR_TYPE_END,
226 			  ATTR_FLAG_MISSING,	/* Reply */
227 			  ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status,
228 			  ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, buf,
229 			  ATTR_TYPE_END) != 2)
230 	status = TLS_MGR_STAT_FAIL;
231     return (status);
232 }
233 
234 /* tls_mgr_update - save session to cache */
235 
236 int     tls_mgr_update(const char *cache_type, const char *cache_id,
237 		               const char *buf, ssize_t len)
238 {
239     int     status;
240 
241     /*
242      * Create the tlsmgr client handle.
243      */
244     if (tls_mgr == 0)
245 	tls_mgr_open();
246 
247     /*
248      * Send the request and receive the reply.
249      */
250     if (attr_clnt_request(tls_mgr,
251 			  ATTR_FLAG_NONE,	/* Request */
252 			ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_UPDATE,
253 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
254 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
255 			  ATTR_TYPE_DATA, TLS_MGR_ATTR_SESSION, len, buf,
256 			  ATTR_TYPE_END,
257 			  ATTR_FLAG_MISSING,	/* Reply */
258 			  ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status,
259 			  ATTR_TYPE_END) != 1)
260 	status = TLS_MGR_STAT_FAIL;
261     return (status);
262 }
263 
264 /* tls_mgr_delete - remove cached session */
265 
266 int     tls_mgr_delete(const char *cache_type, const char *cache_id)
267 {
268     int     status;
269 
270     /*
271      * Create the tlsmgr client handle.
272      */
273     if (tls_mgr == 0)
274 	tls_mgr_open();
275 
276     /*
277      * Send the request and receive the reply.
278      */
279     if (attr_clnt_request(tls_mgr,
280 			  ATTR_FLAG_NONE,	/* Request */
281 			ATTR_TYPE_STR, TLS_MGR_ATTR_REQ, TLS_MGR_REQ_DELETE,
282 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_TYPE, cache_type,
283 			  ATTR_TYPE_STR, TLS_MGR_ATTR_CACHE_ID, cache_id,
284 			  ATTR_TYPE_END,
285 			  ATTR_FLAG_MISSING,	/* Reply */
286 			  ATTR_TYPE_INT, TLS_MGR_ATTR_STATUS, &status,
287 			  ATTR_TYPE_END) != 1)
288 	status = TLS_MGR_STAT_FAIL;
289     return (status);
290 }
291 
292 #ifdef TEST
293 
294 /* System library. */
295 
296 #include <stdlib.h>
297 
298 /* Utility library. */
299 
300 #include <argv.h>
301 #include <msg_vstream.h>
302 #include <vstring_vstream.h>
303 #include <hex_code.h>
304 
305 /* Global library. */
306 
307 #include <config.h>
308 
309 /* Application-specific. */
310 
311 #define STR(x) vstring_str(x)
312 #define LEN(x) VSTRING_LEN(x)
313 
314 int     main(int unused_ac, char **av)
315 {
316     VSTRING *inbuf = vstring_alloc(10);
317     int     status;
318     ARGV   *argv = 0;
319 
320     msg_vstream_init(av[0], VSTREAM_ERR);
321 
322     msg_verbose = 3;
323 
324     mail_conf_read();
325     msg_info("using config files in %s", var_config_dir);
326 
327     if (chdir(var_queue_dir) < 0)
328 	msg_fatal("chdir %s: %m", var_queue_dir);
329 
330     while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
331 	argv = argv_split(STR(inbuf), " \t\r\n");
332 	if (argv->argc == 0) {
333 	    argv_free(argv);
334 	    continue;
335 	}
336 
337 #define COMMAND(argv, str, len) \
338     (strcasecmp(argv->argv[0], str) == 0 && argv->argc == len)
339 
340 	if (COMMAND(argv, "policy", 2)) {
341 	    int     cachable;
342 
343 	    status = tls_mgr_policy(argv->argv[1], &cachable);
344 	    vstream_printf("status=%d cachable=%d\n", status, cachable);
345 	} else if (COMMAND(argv, "seed", 2)) {
346 	    VSTRING *buf = vstring_alloc(10);
347 	    VSTRING *hex = vstring_alloc(10);
348 	    int     len = atoi(argv->argv[1]);
349 
350 	    status = tls_mgr_seed(buf, len);
351 	    hex_encode(hex, STR(buf), LEN(buf));
352 	    vstream_printf("status=%d seed=%s\n", status, STR(hex));
353 	    vstring_free(hex);
354 	    vstring_free(buf);
355 	} else if (COMMAND(argv, "lookup", 3)) {
356 	    VSTRING *buf = vstring_alloc(10);
357 
358 	    status = tls_mgr_lookup(argv->argv[1], argv->argv[2], buf);
359 	    vstream_printf("status=%d session=%.*s\n",
360 			   status, LEN(buf), STR(buf));
361 	    vstring_free(buf);
362 	} else if (COMMAND(argv, "update", 4)) {
363 	    status = tls_mgr_update(argv->argv[1], argv->argv[2],
364 				    argv->argv[3], strlen(argv->argv[3]));
365 	    vstream_printf("status=%d\n", status);
366 	} else if (COMMAND(argv, "delete", 3)) {
367 	    status = tls_mgr_delete(argv->argv[1], argv->argv[2]);
368 	    vstream_printf("status=%d\n", status);
369 	} else {
370 	    vstream_printf("usage:\n"
371 			   "seed byte_count\n"
372 			   "policy smtpd|smtp|lmtp\n"
373 			   "lookup smtpd|smtp|lmtp cache_id\n"
374 			   "update smtpd|smtp|lmtp cache_id session\n"
375 			   "delete smtpd|smtp|lmtp cache_id\n");
376 	}
377 	vstream_fflush(VSTREAM_OUT);
378 	argv_free(argv);
379     }
380 
381     vstring_free(inbuf);
382     return (0);
383 }
384 
385 #endif					/* TEST */
386 
387 #endif					/* USE_TLS */
388