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