1 /* $NetBSD: tls_proxy_client_scan.c,v 1.2 2020/03/18 19:05:21 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_MASTER_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_MASTER_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_MASTER_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 #include <tls.h> 116 #include <tls_proxy.h> 117 118 #define STR(x) vstring_str(x) 119 #define LEN(x) VSTRING_LEN(x) 120 121 /* tls_proxy_client_param_free - destroy TLS_CLIENT_PARAMS structure */ 122 123 void tls_proxy_client_param_free(TLS_CLIENT_PARAMS *params) 124 { 125 myfree(params->tls_high_clist); 126 myfree(params->tls_medium_clist); 127 myfree(params->tls_low_clist); 128 myfree(params->tls_export_clist); 129 myfree(params->tls_null_clist); 130 myfree(params->tls_eecdh_auto); 131 myfree(params->tls_eecdh_strong); 132 myfree(params->tls_eecdh_ultra); 133 myfree(params->tls_bug_tweaks); 134 myfree(params->tls_ssl_options); 135 myfree(params->tls_dane_digests); 136 myfree(params->tls_mgr_service); 137 myfree(params->tls_tkt_cipher); 138 myfree((void *) params); 139 } 140 141 /* tls_proxy_client_param_scan - receive TLS_CLIENT_PARAMS from stream */ 142 143 int tls_proxy_client_param_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, 144 int flags, void *ptr) 145 { 146 TLS_CLIENT_PARAMS *params 147 = (TLS_CLIENT_PARAMS *) mymalloc(sizeof(*params)); 148 int ret; 149 VSTRING *tls_high_clist = vstring_alloc(25); 150 VSTRING *tls_medium_clist = vstring_alloc(25); 151 VSTRING *tls_low_clist = vstring_alloc(25); 152 VSTRING *tls_export_clist = vstring_alloc(25); 153 VSTRING *tls_null_clist = vstring_alloc(25); 154 VSTRING *tls_eecdh_auto = vstring_alloc(25); 155 VSTRING *tls_eecdh_strong = vstring_alloc(25); 156 VSTRING *tls_eecdh_ultra = vstring_alloc(25); 157 VSTRING *tls_bug_tweaks = vstring_alloc(25); 158 VSTRING *tls_ssl_options = vstring_alloc(25); 159 VSTRING *tls_dane_digests = vstring_alloc(25); 160 VSTRING *tls_mgr_service = vstring_alloc(25); 161 VSTRING *tls_tkt_cipher = vstring_alloc(25); 162 163 if (msg_verbose) 164 msg_info("begin tls_proxy_client_param_scan"); 165 166 /* 167 * Note: memset() is not a portable way to initialize non-integer types. 168 */ 169 memset(params, 0, sizeof(*params)); 170 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 171 RECV_ATTR_STR(VAR_TLS_HIGH_CLIST, tls_high_clist), 172 RECV_ATTR_STR(VAR_TLS_MEDIUM_CLIST, tls_medium_clist), 173 RECV_ATTR_STR(VAR_TLS_LOW_CLIST, tls_low_clist), 174 RECV_ATTR_STR(VAR_TLS_EXPORT_CLIST, tls_export_clist), 175 RECV_ATTR_STR(VAR_TLS_NULL_CLIST, tls_null_clist), 176 RECV_ATTR_STR(VAR_TLS_EECDH_AUTO, tls_eecdh_auto), 177 RECV_ATTR_STR(VAR_TLS_EECDH_STRONG, tls_eecdh_strong), 178 RECV_ATTR_STR(VAR_TLS_EECDH_ULTRA, tls_eecdh_ultra), 179 RECV_ATTR_STR(VAR_TLS_BUG_TWEAKS, tls_bug_tweaks), 180 RECV_ATTR_STR(VAR_TLS_SSL_OPTIONS, tls_ssl_options), 181 RECV_ATTR_STR(VAR_TLS_DANE_DIGESTS, tls_dane_digests), 182 RECV_ATTR_STR(VAR_TLS_MGR_SERVICE, tls_mgr_service), 183 RECV_ATTR_STR(VAR_TLS_TKT_CIPHER, tls_tkt_cipher), 184 RECV_ATTR_INT(VAR_TLS_DAEMON_RAND_BYTES, 185 ¶ms->tls_daemon_rand_bytes), 186 RECV_ATTR_INT(VAR_TLS_APPEND_DEF_CA, 187 ¶ms->tls_append_def_CA), 188 RECV_ATTR_INT(VAR_TLS_BC_PKEY_FPRINT, 189 ¶ms->tls_bc_pkey_fprint), 190 RECV_ATTR_INT(VAR_TLS_PREEMPT_CLIST, 191 ¶ms->tls_preempt_clist), 192 RECV_ATTR_INT(VAR_TLS_MULTI_WILDCARD, 193 ¶ms->tls_multi_wildcard), 194 ATTR_TYPE_END); 195 /* Always construct a well-formed structure. */ 196 params->tls_high_clist = vstring_export(tls_high_clist); 197 params->tls_medium_clist = vstring_export(tls_medium_clist); 198 params->tls_low_clist = vstring_export(tls_low_clist); 199 params->tls_export_clist = vstring_export(tls_export_clist); 200 params->tls_null_clist = vstring_export(tls_null_clist); 201 params->tls_eecdh_auto = vstring_export(tls_eecdh_auto); 202 params->tls_eecdh_strong = vstring_export(tls_eecdh_strong); 203 params->tls_eecdh_ultra = vstring_export(tls_eecdh_ultra); 204 params->tls_bug_tweaks = vstring_export(tls_bug_tweaks); 205 params->tls_ssl_options = vstring_export(tls_ssl_options); 206 params->tls_dane_digests = vstring_export(tls_dane_digests); 207 params->tls_mgr_service = vstring_export(tls_mgr_service); 208 params->tls_tkt_cipher = vstring_export(tls_tkt_cipher); 209 210 ret = (ret == 18 ? 1 : -1); 211 if (ret != 1) { 212 tls_proxy_client_param_free(params); 213 params = 0; 214 } 215 *(TLS_CLIENT_PARAMS **) ptr = params; 216 if (msg_verbose) 217 msg_info("tls_proxy_client_param_scan ret=%d", ret); 218 return (ret); 219 } 220 221 /* tls_proxy_client_init_free - destroy TLS_CLIENT_INIT_PROPS structure */ 222 223 void tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *props) 224 { 225 myfree((void *) props->log_param); 226 myfree((void *) props->log_level); 227 myfree((void *) props->cache_type); 228 myfree((void *) props->chain_files); 229 myfree((void *) props->cert_file); 230 myfree((void *) props->key_file); 231 myfree((void *) props->dcert_file); 232 myfree((void *) props->dkey_file); 233 myfree((void *) props->eccert_file); 234 myfree((void *) props->eckey_file); 235 myfree((void *) props->CAfile); 236 myfree((void *) props->CApath); 237 myfree((void *) props->mdalg); 238 myfree((void *) props); 239 } 240 241 /* tls_proxy_client_init_scan - receive TLS_CLIENT_INIT_PROPS from stream */ 242 243 int tls_proxy_client_init_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, 244 int flags, void *ptr) 245 { 246 TLS_CLIENT_INIT_PROPS *props 247 = (TLS_CLIENT_INIT_PROPS *) mymalloc(sizeof(*props)); 248 int ret; 249 VSTRING *log_param = vstring_alloc(25); 250 VSTRING *log_level = vstring_alloc(25); 251 VSTRING *cache_type = vstring_alloc(25); 252 VSTRING *chain_files = vstring_alloc(25); 253 VSTRING *cert_file = vstring_alloc(25); 254 VSTRING *key_file = vstring_alloc(25); 255 VSTRING *dcert_file = vstring_alloc(25); 256 VSTRING *dkey_file = vstring_alloc(25); 257 VSTRING *eccert_file = vstring_alloc(25); 258 VSTRING *eckey_file = vstring_alloc(25); 259 VSTRING *CAfile = vstring_alloc(25); 260 VSTRING *CApath = vstring_alloc(25); 261 VSTRING *mdalg = vstring_alloc(25); 262 263 if (msg_verbose) 264 msg_info("begin tls_proxy_client_init_scan"); 265 266 /* 267 * Note: memset() is not a portable way to initialize non-integer types. 268 */ 269 memset(props, 0, sizeof(*props)); 270 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 271 RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param), 272 RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level), 273 RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth), 274 RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type), 275 RECV_ATTR_STR(TLS_ATTR_CHAIN_FILES, chain_files), 276 RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file), 277 RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file), 278 RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file), 279 RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file), 280 RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file), 281 RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file), 282 RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile), 283 RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath), 284 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 285 ATTR_TYPE_END); 286 /* Always construct a well-formed structure. */ 287 props->log_param = vstring_export(log_param); 288 props->log_level = vstring_export(log_level); 289 props->cache_type = vstring_export(cache_type); 290 props->chain_files = vstring_export(chain_files); 291 props->cert_file = vstring_export(cert_file); 292 props->key_file = vstring_export(key_file); 293 props->dcert_file = vstring_export(dcert_file); 294 props->dkey_file = vstring_export(dkey_file); 295 props->eccert_file = vstring_export(eccert_file); 296 props->eckey_file = vstring_export(eckey_file); 297 props->CAfile = vstring_export(CAfile); 298 props->CApath = vstring_export(CApath); 299 props->mdalg = vstring_export(mdalg); 300 ret = (ret == 14 ? 1 : -1); 301 if (ret != 1) { 302 tls_proxy_client_init_free(props); 303 props = 0; 304 } 305 *(TLS_CLIENT_INIT_PROPS **) ptr = props; 306 if (msg_verbose) 307 msg_info("tls_proxy_client_init_scan ret=%d", ret); 308 return (ret); 309 } 310 311 /* tls_proxy_client_certs_free - destroy TLS_PKEYS from stream */ 312 313 static void tls_proxy_client_certs_free(TLS_CERTS *tp) 314 { 315 if (tp->next) 316 tls_proxy_client_certs_free(tp->next); 317 if (tp->cert) 318 X509_free(tp->cert); 319 myfree((void *) tp); 320 } 321 322 /* tls_proxy_client_pkeys_free - destroy TLS_PKEYS from stream */ 323 324 static void tls_proxy_client_pkeys_free(TLS_PKEYS *tp) 325 { 326 if (tp->next) 327 tls_proxy_client_pkeys_free(tp->next); 328 if (tp->pkey) 329 EVP_PKEY_free(tp->pkey); 330 myfree((void *) tp); 331 } 332 333 /* tls_proxy_client_tlsa_free - destroy TLS_TLSA from stream */ 334 335 static void tls_proxy_client_tlsa_free(TLS_TLSA *tp) 336 { 337 if (tp->next) 338 tls_proxy_client_tlsa_free(tp->next); 339 myfree(tp->mdalg); 340 if (tp->certs) 341 argv_free(tp->certs); 342 if (tp->pkeys) 343 argv_free(tp->pkeys); 344 myfree((void *) tp); 345 } 346 347 /* tls_proxy_client_dane_free - destroy TLS_DANE from stream */ 348 349 static void tls_proxy_client_dane_free(TLS_DANE *dane) 350 { 351 if (dane->ta) 352 tls_proxy_client_tlsa_free(dane->ta); 353 if (dane->ee) 354 tls_proxy_client_tlsa_free(dane->ee); 355 if (dane->certs) 356 tls_proxy_client_certs_free(dane->certs); 357 if (dane->pkeys) 358 tls_proxy_client_pkeys_free(dane->pkeys); 359 myfree(dane->base_domain); 360 if (dane->refs-- == 1) 361 myfree((void *) dane); 362 } 363 364 /* tls_proxy_client_start_free - destroy TLS_CLIENT_START_PROPS structure */ 365 366 void tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props) 367 { 368 myfree((void *) props->nexthop); 369 myfree((void *) props->host); 370 myfree((void *) props->namaddr); 371 myfree((void *) props->sni); 372 myfree((void *) props->serverid); 373 myfree((void *) props->helo); 374 myfree((void *) props->protocols); 375 myfree((void *) props->cipher_grade); 376 myfree((void *) props->cipher_exclusions); 377 if (props->matchargv) 378 argv_free((ARGV *) props->matchargv); 379 myfree((void *) props->mdalg); 380 if (props->dane) 381 tls_proxy_client_dane_free((TLS_DANE *) props->dane); 382 myfree((void *) props); 383 } 384 385 /* tls_proxy_client_certs_scan - receive TLS_CERTS from stream */ 386 387 static int tls_proxy_client_certs_scan(ATTR_SCAN_MASTER_FN scan_fn, 388 VSTREAM *fp, int flags, void *ptr) 389 { 390 int ret; 391 int count; 392 VSTRING *buf = 0; 393 TLS_CERTS **tpp; 394 TLS_CERTS *head = 0; 395 TLS_CERTS *tp; 396 int n; 397 398 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 399 RECV_ATTR_INT(TLS_ATTR_COUNT, &count), 400 ATTR_TYPE_END); 401 if (msg_verbose) 402 msg_info("tls_proxy_client_certs_scan count=%d", count); 403 404 for (tpp = &head, n = 0; ret == 1 && n < count; n++, tpp = &tp->next) { 405 *tpp = tp = (TLS_CERTS *) mymalloc(sizeof(*tp)); 406 const unsigned char *bp; 407 408 if (buf == 0) 409 buf = vstring_alloc(100); 410 411 /* 412 * Note: memset() is not a portable way to initialize non-integer 413 * types. 414 */ 415 memset(tp, 0, sizeof(*tp)); 416 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 417 RECV_ATTR_DATA(TLS_ATTR_CERT, buf), 418 ATTR_TYPE_END); 419 /* Always construct a well-formed structure. */ 420 if (ret == 1) { 421 bp = (const unsigned char *) STR(buf); 422 if (d2i_X509(&tp->cert, &bp, LEN(buf)) == 0 423 || LEN(buf) != ((char *) bp) - STR(buf)) { 424 msg_warn("malformed certificate in TLS_CERTS"); 425 ret = -1; 426 } 427 } else { 428 tp->cert = 0; 429 } 430 tp->next = 0; 431 } 432 if (buf) 433 vstring_free(buf); 434 if (ret != 1) { 435 tls_proxy_client_certs_free(head); 436 head = 0; 437 } 438 *(TLS_CERTS **) ptr = head; 439 if (msg_verbose) 440 msg_info("tls_proxy_client_certs_scan ret=%d", ret); 441 return (ret); 442 } 443 444 /* tls_proxy_client_pkeys_scan - receive TLS_PKEYS from stream */ 445 446 static int tls_proxy_client_pkeys_scan(ATTR_SCAN_MASTER_FN scan_fn, 447 VSTREAM *fp, int flags, void *ptr) 448 { 449 int ret; 450 int count; 451 VSTRING *buf = vstring_alloc(100); 452 TLS_PKEYS **tpp; 453 TLS_PKEYS *head = 0; 454 TLS_PKEYS *tp; 455 int n; 456 457 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 458 RECV_ATTR_INT(TLS_ATTR_COUNT, &count), 459 ATTR_TYPE_END); 460 if (msg_verbose) 461 msg_info("tls_proxy_client_pkeys_scan count=%d", count); 462 463 for (tpp = &head, n = 0; ret == 1 && n < count; n++, tpp = &tp->next) { 464 *tpp = tp = (TLS_PKEYS *) mymalloc(sizeof(*tp)); 465 const unsigned char *bp; 466 467 if (buf == 0) 468 buf = vstring_alloc(100); 469 470 /* 471 * Note: memset() is not a portable way to initialize non-integer 472 * types. 473 */ 474 memset(tp, 0, sizeof(*tp)); 475 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 476 RECV_ATTR_DATA(TLS_ATTR_PKEY, buf), 477 ATTR_TYPE_END); 478 /* Always construct a well-formed structure. */ 479 if (ret == 1) { 480 bp = (const unsigned char *) STR(buf); 481 if (d2i_PUBKEY(&tp->pkey, &bp, LEN(buf)) == 0 482 || LEN(buf) != (char *) bp - STR(buf)) { 483 msg_warn("malformed public key in TLS_PKEYS"); 484 ret = -1; 485 } 486 } else { 487 tp->pkey = 0; 488 } 489 tp->next = 0; 490 } 491 if (buf) 492 vstring_free(buf); 493 if (ret != 1) { 494 tls_proxy_client_pkeys_free(head); 495 head = 0; 496 } 497 *(TLS_PKEYS **) ptr = head; 498 if (msg_verbose) 499 msg_info("tls_proxy_client_pkeys_scan ret=%d", ret); 500 return (ret); 501 } 502 503 /* tls_proxy_client_tlsa_scan - receive TLS_TLSA from stream */ 504 505 static int tls_proxy_client_tlsa_scan(ATTR_SCAN_MASTER_FN scan_fn, 506 VSTREAM *fp, int flags, void *ptr) 507 { 508 int ret; 509 int count; 510 TLS_TLSA **tpp; 511 TLS_TLSA *head = 0; 512 TLS_TLSA *tp; 513 int n; 514 515 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 516 RECV_ATTR_INT(TLS_ATTR_COUNT, &count), 517 ATTR_TYPE_END); 518 if (msg_verbose) 519 msg_info("tls_proxy_client_tlsa_scan count=%d", count); 520 521 for (tpp = &head, n = 0; ret == 1 && n < count; n++, tpp = &tp->next) { 522 *tpp = tp = (TLS_TLSA *) mymalloc(sizeof(*tp)); 523 VSTRING *mdalg = vstring_alloc(25); 524 525 /* 526 * Note: memset() is not a portable way to initialize non-integer 527 * types. 528 */ 529 memset(tp, 0, sizeof(*tp)); 530 /* Always construct a well-formed structure. */ 531 tp->certs = 0; /* scan_fn may return early */ 532 tp->pkeys = 0; 533 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 534 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 535 RECV_ATTR_FUNC(argv_attr_scan, &tp->certs), 536 RECV_ATTR_FUNC(argv_attr_scan, &tp->pkeys), 537 ATTR_TYPE_END); 538 tp->mdalg = vstring_export(mdalg); 539 tp->next = 0; 540 ret = (ret == 3 ? 1 : -1); 541 } 542 if (ret != 1) { 543 tls_proxy_client_tlsa_free(head); 544 head = 0; 545 } 546 *(TLS_TLSA **) ptr = head; 547 if (msg_verbose) 548 msg_info("tls_proxy_client_tlsa_scan ret=%d", ret); 549 return (ret); 550 } 551 552 /* tls_proxy_client_dane_scan - receive TLS_DANE from stream */ 553 554 static int tls_proxy_client_dane_scan(ATTR_SCAN_MASTER_FN scan_fn, 555 VSTREAM *fp, int flags, void *ptr) 556 { 557 TLS_DANE *dane = 0; 558 int ret; 559 int have_dane = 0; 560 561 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 562 RECV_ATTR_INT(TLS_ATTR_DANE, &have_dane), 563 ATTR_TYPE_END); 564 if (msg_verbose) 565 msg_info("tls_proxy_client_dane_scan have_dane=%d", have_dane); 566 567 if (ret == 1 && have_dane) { 568 VSTRING *base_domain = vstring_alloc(25); 569 long expires; 570 571 dane = (TLS_DANE *) mymalloc(sizeof(*dane)); 572 573 /* 574 * Note: memset() is not a portable way to initialize non-integer 575 * types. 576 */ 577 memset(dane, 0, sizeof(*dane)); 578 /* Always construct a well-formed structure. */ 579 dane->ta = 0; /* scan_fn may return early */ 580 dane->ee = 0; 581 dane->certs = 0; 582 dane->pkeys = 0; 583 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 584 RECV_ATTR_FUNC(tls_proxy_client_tlsa_scan, 585 &dane->ta), 586 RECV_ATTR_FUNC(tls_proxy_client_tlsa_scan, 587 &dane->ee), 588 RECV_ATTR_FUNC(tls_proxy_client_certs_scan, 589 &dane->certs), 590 RECV_ATTR_FUNC(tls_proxy_client_pkeys_scan, 591 &dane->pkeys), 592 RECV_ATTR_STR(TLS_ATTR_DOMAIN, base_domain), 593 RECV_ATTR_INT(TLS_ATTR_FLAGS, &dane->flags), 594 RECV_ATTR_LONG(TLS_ATTR_EXP, &expires), 595 ATTR_TYPE_END); 596 /* Always construct a well-formed structure. */ 597 dane->base_domain = vstring_export(base_domain); 598 dane->expires = expires; 599 dane->refs = 1; 600 ret = (ret == 7 ? 1 : -1); 601 /* XXX if scan_fn() completed normally, sanity check dane->flags. */ 602 if (ret != 1) { 603 tls_proxy_client_dane_free(dane); 604 dane = 0; 605 } 606 } 607 *(TLS_DANE **) ptr = dane; 608 if (msg_verbose) 609 msg_info("tls_proxy_client_dane_scan ret=%d", ret); 610 return (ret); 611 } 612 613 /* tls_proxy_client_start_scan - receive TLS_CLIENT_START_PROPS from stream */ 614 615 int tls_proxy_client_start_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, 616 int flags, void *ptr) 617 { 618 TLS_CLIENT_START_PROPS *props 619 = (TLS_CLIENT_START_PROPS *) mymalloc(sizeof(*props)); 620 int ret; 621 VSTRING *nexthop = vstring_alloc(25); 622 VSTRING *host = vstring_alloc(25); 623 VSTRING *namaddr = vstring_alloc(25); 624 VSTRING *sni = vstring_alloc(25); 625 VSTRING *serverid = vstring_alloc(25); 626 VSTRING *helo = vstring_alloc(25); 627 VSTRING *protocols = vstring_alloc(25); 628 VSTRING *cipher_grade = vstring_alloc(25); 629 VSTRING *cipher_exclusions = vstring_alloc(25); 630 VSTRING *mdalg = vstring_alloc(25); 631 632 if (msg_verbose) 633 msg_info("begin tls_proxy_client_start_scan"); 634 635 /* 636 * Note: memset() is not a portable way to initialize non-integer types. 637 */ 638 memset(props, 0, sizeof(*props)); 639 props->ctx = 0; 640 props->stream = 0; 641 props->fd = -1; 642 props->dane = 0; /* scan_fn may return early */ 643 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 644 RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout), 645 RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level), 646 RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop), 647 RECV_ATTR_STR(TLS_ATTR_HOST, host), 648 RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr), 649 RECV_ATTR_STR(TLS_ATTR_SNI, sni), 650 RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid), 651 RECV_ATTR_STR(TLS_ATTR_HELO, helo), 652 RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols), 653 RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade), 654 RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS, 655 cipher_exclusions), 656 RECV_ATTR_FUNC(argv_attr_scan, &props->matchargv), 657 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 658 RECV_ATTR_FUNC(tls_proxy_client_dane_scan, 659 &props->dane), 660 ATTR_TYPE_END); 661 /* Always construct a well-formed structure. */ 662 props->nexthop = vstring_export(nexthop); 663 props->host = vstring_export(host); 664 props->namaddr = vstring_export(namaddr); 665 props->sni = vstring_export(sni); 666 props->serverid = vstring_export(serverid); 667 props->helo = vstring_export(helo); 668 props->protocols = vstring_export(protocols); 669 props->cipher_grade = vstring_export(cipher_grade); 670 props->cipher_exclusions = vstring_export(cipher_exclusions); 671 props->mdalg = vstring_export(mdalg); 672 ret = (ret == 14 ? 1 : -1); 673 if (ret != 1) { 674 tls_proxy_client_start_free(props); 675 props = 0; 676 } 677 *(TLS_CLIENT_START_PROPS **) ptr = props; 678 if (msg_verbose) 679 msg_info("tls_proxy_client_start_scan ret=%d", ret); 680 return (ret); 681 } 682 683 #endif 684