1/* $NetBSD: tls_proxy_client_scan.c,v 1.4 2023/12/23 20:30:45 christos Exp $ */ 2 3/*++ 4/* NAME 5/* tls_proxy_client_scan 3 6/* SUMMARY 7/* read TLS_CLIENT_XXX structures from stream 8/* SYNOPSIS 9/* #include <tls_proxy.h> 10/* 11/* int tls_proxy_client_param_scan(scan_fn, stream, flags, ptr) 12/* ATTR_SCAN_COMMON_FN scan_fn; 13/* VSTREAM *stream; 14/* int flags; 15/* void *ptr; 16/* 17/* void tls_proxy_client_param_free(params) 18/* TLS_CLIENT_PARAMS *params; 19/* 20/* int tls_proxy_client_init_scan(scan_fn, stream, flags, ptr) 21/* ATTR_SCAN_COMMON_FN scan_fn; 22/* VSTREAM *stream; 23/* int flags; 24/* void *ptr; 25/* 26/* void tls_proxy_client_init_free(init_props) 27/* TLS_CLIENT_INIT_PROPS *init_props; 28/* 29/* int tls_proxy_client_start_scan(scan_fn, stream, flags, ptr) 30/* ATTR_SCAN_COMMON_FN scan_fn; 31/* VSTREAM *stream; 32/* int flags; 33/* void *ptr; 34/* 35/* void tls_proxy_client_start_free(start_props) 36/* TLS_CLIENT_START_PROPS *start_props; 37/* DESCRIPTION 38/* tls_proxy_client_param_scan() reads a TLS_CLIENT_PARAMS structure from 39/* the named stream using the specified attribute scan routine. 40/* tls_proxy_client_param_scan() is meant to be passed as a call-back 41/* function to attr_scan(), as shown below. 42/* 43/* tls_proxy_client_param_free() destroys a TLS_CLIENT_PARAMS structure 44/* that was created by tls_proxy_client_param_scan(). 45/* 46/* TLS_CLIENT_PARAMS *param = 0; 47/* ... 48/* ... RECV_ATTR_FUNC(tls_proxy_client_param_scan, (void *) ¶m) 49/* ... 50/* if (param != 0) 51/* tls_proxy_client_param_free(param); 52/* 53/* tls_proxy_client_init_scan() reads a full TLS_CLIENT_INIT_PROPS 54/* structure from the named stream using the specified attribute 55/* scan routine. tls_proxy_client_init_scan() is meant to be passed 56/* as a call-back function to attr_scan(), as shown below. 57/* 58/* tls_proxy_client_init_free() destroys a TLS_CLIENT_INIT_PROPS 59/* structure that was created by tls_proxy_client_init_scan(). 60/* 61/* TLS_CLIENT_INIT_PROPS *init_props = 0; 62/* ... 63/* ... RECV_ATTR_FUNC(tls_proxy_client_init_scan, (void *) &init_props) 64/* ... 65/* if (init_props != 0) 66/* tls_proxy_client_init_free(init_props); 67/* 68/* tls_proxy_client_start_scan() reads a TLS_CLIENT_START_PROPS 69/* structure, without the stream of file descriptor members, 70/* from the named stream using the specified attribute scan 71/* routine. tls_proxy_client_start_scan() is meant to be passed 72/* as a call-back function to attr_scan(), as shown below. 73/* 74/* tls_proxy_client_start_free() destroys a TLS_CLIENT_START_PROPS 75/* structure that was created by tls_proxy_client_start_scan(). 76/* 77/* TLS_CLIENT_START_PROPS *start_props = 0; 78/* ... 79/* ... RECV_ATTR_FUNC(tls_proxy_client_start_scan, (void *) &start_props) 80/* ... 81/* if (start_props != 0) 82/* tls_proxy_client_start_free(start_props); 83/* DIAGNOSTICS 84/* Fatal: out of memory. 85/* LICENSE 86/* .ad 87/* .fi 88/* The Secure Mailer license must be distributed with this software. 89/* AUTHOR(S) 90/* Wietse Venema 91/* Google, Inc. 92/* 111 8th Avenue 93/* New York, NY 10011, USA 94/*--*/ 95 96#ifdef USE_TLS 97 98/* System library. */ 99 100#include <sys_defs.h> 101 102/* Utility library */ 103 104#include <argv_attr.h> 105#include <attr.h> 106#include <msg.h> 107#include <vstring.h> 108 109/* Global library. */ 110 111#include <mail_params.h> 112 113/* TLS library. */ 114 115#define TLS_INTERNAL 116#include <tls.h> 117#include <tls_proxy.h> 118 119#define STR(x) vstring_str(x) 120#define LEN(x) VSTRING_LEN(x) 121 122/* tls_proxy_client_param_free - destroy TLS_CLIENT_PARAMS structure */ 123 124void tls_proxy_client_param_free(TLS_CLIENT_PARAMS *params) 125{ 126 myfree(params->tls_cnf_file); 127 myfree(params->tls_cnf_name); 128 myfree(params->tls_high_clist); 129 myfree(params->tls_medium_clist); 130 myfree(params->tls_null_clist); 131 myfree(params->tls_eecdh_auto); 132 myfree(params->tls_eecdh_strong); 133 myfree(params->tls_eecdh_ultra); 134 myfree(params->tls_ffdhe_auto); 135 myfree(params->tls_bug_tweaks); 136 myfree(params->tls_ssl_options); 137 myfree(params->tls_dane_digests); 138 myfree(params->tls_mgr_service); 139 myfree(params->tls_tkt_cipher); 140 myfree((void *) params); 141} 142 143/* tls_proxy_client_param_scan - receive TLS_CLIENT_PARAMS from stream */ 144 145int tls_proxy_client_param_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 146 int flags, void *ptr) 147{ 148 TLS_CLIENT_PARAMS *params 149 = (TLS_CLIENT_PARAMS *) mymalloc(sizeof(*params)); 150 int ret; 151 VSTRING *cnf_file = vstring_alloc(25); 152 VSTRING *cnf_name = vstring_alloc(25); 153 VSTRING *tls_high_clist = vstring_alloc(25); 154 VSTRING *tls_medium_clist = vstring_alloc(25); 155 VSTRING *tls_null_clist = vstring_alloc(25); 156 VSTRING *tls_eecdh_auto = vstring_alloc(25); 157 VSTRING *tls_eecdh_strong = vstring_alloc(25); 158 VSTRING *tls_eecdh_ultra = vstring_alloc(25); 159 VSTRING *tls_ffdhe_auto = vstring_alloc(25); 160 VSTRING *tls_bug_tweaks = vstring_alloc(25); 161 VSTRING *tls_ssl_options = vstring_alloc(25); 162 VSTRING *tls_dane_digests = vstring_alloc(25); 163 VSTRING *tls_mgr_service = vstring_alloc(25); 164 VSTRING *tls_tkt_cipher = vstring_alloc(25); 165 166 if (msg_verbose) 167 msg_info("begin tls_proxy_client_param_scan"); 168 169 /* 170 * Note: memset() is not a portable way to initialize non-integer types. 171 */ 172 memset(params, 0, sizeof(*params)); 173 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 174 RECV_ATTR_STR(TLS_ATTR_CNF_FILE, cnf_file), 175 RECV_ATTR_STR(TLS_ATTR_CNF_NAME, cnf_name), 176 RECV_ATTR_STR(VAR_TLS_HIGH_CLIST, tls_high_clist), 177 RECV_ATTR_STR(VAR_TLS_MEDIUM_CLIST, tls_medium_clist), 178 RECV_ATTR_STR(VAR_TLS_NULL_CLIST, tls_null_clist), 179 RECV_ATTR_STR(VAR_TLS_EECDH_AUTO, tls_eecdh_auto), 180 RECV_ATTR_STR(VAR_TLS_EECDH_STRONG, tls_eecdh_strong), 181 RECV_ATTR_STR(VAR_TLS_EECDH_ULTRA, tls_eecdh_ultra), 182 RECV_ATTR_STR(VAR_TLS_FFDHE_AUTO, tls_ffdhe_auto), 183 RECV_ATTR_STR(VAR_TLS_BUG_TWEAKS, tls_bug_tweaks), 184 RECV_ATTR_STR(VAR_TLS_SSL_OPTIONS, tls_ssl_options), 185 RECV_ATTR_STR(VAR_TLS_DANE_DIGESTS, tls_dane_digests), 186 RECV_ATTR_STR(VAR_TLS_MGR_SERVICE, tls_mgr_service), 187 RECV_ATTR_STR(VAR_TLS_TKT_CIPHER, tls_tkt_cipher), 188 RECV_ATTR_INT(VAR_TLS_DAEMON_RAND_BYTES, 189 ¶ms->tls_daemon_rand_bytes), 190 RECV_ATTR_INT(VAR_TLS_APPEND_DEF_CA, 191 ¶ms->tls_append_def_CA), 192 RECV_ATTR_INT(VAR_TLS_BC_PKEY_FPRINT, 193 ¶ms->tls_bc_pkey_fprint), 194 RECV_ATTR_INT(VAR_TLS_PREEMPT_CLIST, 195 ¶ms->tls_preempt_clist), 196 RECV_ATTR_INT(VAR_TLS_MULTI_WILDCARD, 197 ¶ms->tls_multi_wildcard), 198 ATTR_TYPE_END); 199 /* Always construct a well-formed structure. */ 200 params->tls_cnf_file = vstring_export(cnf_file); 201 params->tls_cnf_name = vstring_export(cnf_name); 202 params->tls_high_clist = vstring_export(tls_high_clist); 203 params->tls_medium_clist = vstring_export(tls_medium_clist); 204 params->tls_null_clist = vstring_export(tls_null_clist); 205 params->tls_eecdh_auto = vstring_export(tls_eecdh_auto); 206 params->tls_eecdh_strong = vstring_export(tls_eecdh_strong); 207 params->tls_eecdh_ultra = vstring_export(tls_eecdh_ultra); 208 params->tls_ffdhe_auto = vstring_export(tls_ffdhe_auto); 209 params->tls_bug_tweaks = vstring_export(tls_bug_tweaks); 210 params->tls_ssl_options = vstring_export(tls_ssl_options); 211 params->tls_dane_digests = vstring_export(tls_dane_digests); 212 params->tls_mgr_service = vstring_export(tls_mgr_service); 213 params->tls_tkt_cipher = vstring_export(tls_tkt_cipher); 214 215 ret = (ret == 19 ? 1 : -1); 216 if (ret != 1) { 217 tls_proxy_client_param_free(params); 218 params = 0; 219 } 220 *(TLS_CLIENT_PARAMS **) ptr = params; 221 if (msg_verbose) 222 msg_info("tls_proxy_client_param_scan ret=%d", ret); 223 return (ret); 224} 225 226/* tls_proxy_client_init_free - destroy TLS_CLIENT_INIT_PROPS structure */ 227 228void tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *props) 229{ 230 myfree((void *) props->log_param); 231 myfree((void *) props->log_level); 232 myfree((void *) props->cache_type); 233 myfree((void *) props->chain_files); 234 myfree((void *) props->cert_file); 235 myfree((void *) props->key_file); 236 myfree((void *) props->dcert_file); 237 myfree((void *) props->dkey_file); 238 myfree((void *) props->eccert_file); 239 myfree((void *) props->eckey_file); 240 myfree((void *) props->CAfile); 241 myfree((void *) props->CApath); 242 myfree((void *) props->mdalg); 243 myfree((void *) props); 244} 245 246/* tls_proxy_client_init_scan - receive TLS_CLIENT_INIT_PROPS from stream */ 247 248int tls_proxy_client_init_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 249 int flags, void *ptr) 250{ 251 TLS_CLIENT_INIT_PROPS *props 252 = (TLS_CLIENT_INIT_PROPS *) mymalloc(sizeof(*props)); 253 int ret; 254 VSTRING *log_param = vstring_alloc(25); 255 VSTRING *log_level = vstring_alloc(25); 256 VSTRING *cache_type = vstring_alloc(25); 257 VSTRING *chain_files = vstring_alloc(25); 258 VSTRING *cert_file = vstring_alloc(25); 259 VSTRING *key_file = vstring_alloc(25); 260 VSTRING *dcert_file = vstring_alloc(25); 261 VSTRING *dkey_file = vstring_alloc(25); 262 VSTRING *eccert_file = vstring_alloc(25); 263 VSTRING *eckey_file = vstring_alloc(25); 264 VSTRING *CAfile = vstring_alloc(25); 265 VSTRING *CApath = vstring_alloc(25); 266 VSTRING *mdalg = vstring_alloc(25); 267 268 if (msg_verbose) 269 msg_info("begin tls_proxy_client_init_scan"); 270 271 /* 272 * Note: memset() is not a portable way to initialize non-integer types. 273 */ 274 memset(props, 0, sizeof(*props)); 275 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 276 RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param), 277 RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level), 278 RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth), 279 RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type), 280 RECV_ATTR_STR(TLS_ATTR_CHAIN_FILES, chain_files), 281 RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file), 282 RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file), 283 RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file), 284 RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file), 285 RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file), 286 RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file), 287 RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile), 288 RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath), 289 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 290 ATTR_TYPE_END); 291 /* Always construct a well-formed structure. */ 292 props->log_param = vstring_export(log_param); 293 props->log_level = vstring_export(log_level); 294 props->cache_type = vstring_export(cache_type); 295 props->chain_files = vstring_export(chain_files); 296 props->cert_file = vstring_export(cert_file); 297 props->key_file = vstring_export(key_file); 298 props->dcert_file = vstring_export(dcert_file); 299 props->dkey_file = vstring_export(dkey_file); 300 props->eccert_file = vstring_export(eccert_file); 301 props->eckey_file = vstring_export(eckey_file); 302 props->CAfile = vstring_export(CAfile); 303 props->CApath = vstring_export(CApath); 304 props->mdalg = vstring_export(mdalg); 305 ret = (ret == 14 ? 1 : -1); 306 if (ret != 1) { 307 tls_proxy_client_init_free(props); 308 props = 0; 309 } 310 *(TLS_CLIENT_INIT_PROPS **) ptr = props; 311 if (msg_verbose) 312 msg_info("tls_proxy_client_init_scan ret=%d", ret); 313 return (ret); 314} 315 316/* tls_proxy_client_start_free - destroy TLS_CLIENT_START_PROPS structure */ 317 318void tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props) 319{ 320 myfree((void *) props->nexthop); 321 myfree((void *) props->host); 322 myfree((void *) props->namaddr); 323 myfree((void *) props->sni); 324 myfree((void *) props->serverid); 325 myfree((void *) props->helo); 326 myfree((void *) props->protocols); 327 myfree((void *) props->cipher_grade); 328 myfree((void *) props->cipher_exclusions); 329 if (props->matchargv) 330 argv_free((ARGV *) props->matchargv); 331 myfree((void *) props->mdalg); 332 if (props->dane) 333 tls_dane_free((TLS_DANE *) props->dane); 334 myfree((void *) props); 335} 336 337/* tls_proxy_client_tlsa_scan - receive TLS_TLSA from stream */ 338 339static int tls_proxy_client_tlsa_scan(ATTR_SCAN_COMMON_FN scan_fn, 340 VSTREAM *fp, int flags, void *ptr) 341{ 342 static VSTRING *data; 343 TLS_TLSA *head; 344 int count; 345 int ret; 346 347 if (data == 0) 348 data = vstring_alloc(64); 349 350 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 351 RECV_ATTR_INT(TLS_ATTR_COUNT, &count), 352 ATTR_TYPE_END); 353 if (ret == 1 && msg_verbose) 354 msg_info("tls_proxy_client_tlsa_scan count=%d", count); 355 356 for (head = 0; ret == 1 && count > 0; --count) { 357 int u, s, m; 358 359 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 360 RECV_ATTR_INT(TLS_ATTR_USAGE, &u), 361 RECV_ATTR_INT(TLS_ATTR_SELECTOR, &s), 362 RECV_ATTR_INT(TLS_ATTR_MTYPE, &m), 363 RECV_ATTR_DATA(TLS_ATTR_DATA, data), 364 ATTR_TYPE_END); 365 if (ret == 4) { 366 ret = 1; 367 /* This makes a copy of the static vstring content */ 368 head = tlsa_prepend(head, u, s, m, (unsigned char *) STR(data), 369 LEN(data)); 370 } else 371 ret = -1; 372 } 373 374 if (ret != 1) { 375 tls_tlsa_free(head); 376 head = 0; 377 } 378 *(TLS_TLSA **) ptr = head; 379 if (msg_verbose) 380 msg_info("tls_proxy_client_tlsa_scan ret=%d", ret); 381 return (ret); 382} 383 384/* tls_proxy_client_dane_scan - receive TLS_DANE from stream */ 385 386static int tls_proxy_client_dane_scan(ATTR_SCAN_COMMON_FN scan_fn, 387 VSTREAM *fp, int flags, void *ptr) 388{ 389 TLS_DANE *dane = 0; 390 int ret; 391 int have_dane = 0; 392 393 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 394 RECV_ATTR_INT(TLS_ATTR_DANE, &have_dane), 395 ATTR_TYPE_END); 396 if (msg_verbose) 397 msg_info("tls_proxy_client_dane_scan have_dane=%d", have_dane); 398 399 if (ret == 1 && have_dane) { 400 VSTRING *base_domain = vstring_alloc(25); 401 402 dane = tls_dane_alloc(); 403 /* We only need the base domain and TLSA RRs */ 404 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 405 RECV_ATTR_STR(TLS_ATTR_DOMAIN, base_domain), 406 RECV_ATTR_FUNC(tls_proxy_client_tlsa_scan, 407 &dane->tlsa), 408 ATTR_TYPE_END); 409 410 /* Always construct a well-formed structure. */ 411 dane->base_domain = vstring_export(base_domain); 412 ret = (ret == 2 ? 1 : -1); 413 if (ret != 1) { 414 tls_dane_free(dane); 415 dane = 0; 416 } 417 } 418 *(TLS_DANE **) ptr = dane; 419 if (msg_verbose) 420 msg_info("tls_proxy_client_dane_scan ret=%d", ret); 421 return (ret); 422} 423 424/* tls_proxy_client_start_scan - receive TLS_CLIENT_START_PROPS from stream */ 425 426int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 427 int flags, void *ptr) 428{ 429 TLS_CLIENT_START_PROPS *props 430 = (TLS_CLIENT_START_PROPS *) mymalloc(sizeof(*props)); 431 int ret; 432 VSTRING *nexthop = vstring_alloc(25); 433 VSTRING *host = vstring_alloc(25); 434 VSTRING *namaddr = vstring_alloc(25); 435 VSTRING *sni = vstring_alloc(25); 436 VSTRING *serverid = vstring_alloc(25); 437 VSTRING *helo = vstring_alloc(25); 438 VSTRING *protocols = vstring_alloc(25); 439 VSTRING *cipher_grade = vstring_alloc(25); 440 VSTRING *cipher_exclusions = vstring_alloc(25); 441 VSTRING *mdalg = vstring_alloc(25); 442 443 if (msg_verbose) 444 msg_info("begin tls_proxy_client_start_scan"); 445 446 /* 447 * Note: memset() is not a portable way to initialize non-integer types. 448 */ 449 memset(props, 0, sizeof(*props)); 450 props->ctx = 0; 451 props->stream = 0; 452 props->fd = -1; 453 props->dane = 0; /* scan_fn may return early */ 454 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 455 RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout), 456 RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level), 457 RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop), 458 RECV_ATTR_STR(TLS_ATTR_HOST, host), 459 RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr), 460 RECV_ATTR_STR(TLS_ATTR_SNI, sni), 461 RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid), 462 RECV_ATTR_STR(TLS_ATTR_HELO, helo), 463 RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols), 464 RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade), 465 RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS, 466 cipher_exclusions), 467 RECV_ATTR_FUNC(argv_attr_scan, &props->matchargv), 468 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 469 RECV_ATTR_FUNC(tls_proxy_client_dane_scan, 470 &props->dane), 471 ATTR_TYPE_END); 472 /* Always construct a well-formed structure. */ 473 props->nexthop = vstring_export(nexthop); 474 props->host = vstring_export(host); 475 props->namaddr = vstring_export(namaddr); 476 props->sni = vstring_export(sni); 477 props->serverid = vstring_export(serverid); 478 props->helo = vstring_export(helo); 479 props->protocols = vstring_export(protocols); 480 props->cipher_grade = vstring_export(cipher_grade); 481 props->cipher_exclusions = vstring_export(cipher_exclusions); 482 props->mdalg = vstring_export(mdalg); 483 ret = (ret == 14 ? 1 : -1); 484 if (ret != 1) { 485 tls_proxy_client_start_free(props); 486 props = 0; 487 } 488 *(TLS_CLIENT_START_PROPS **) ptr = props; 489 if (msg_verbose) 490 msg_info("tls_proxy_client_start_scan ret=%d", ret); 491 return (ret); 492} 493 494#endif 495