1 /* $NetBSD: tls_proxy_client_scan.c,v 1.3 2022/10/08 16:12:50 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 124 void tls_proxy_client_param_free(TLS_CLIENT_PARAMS *params) 125 { 126 myfree(params->tls_high_clist); 127 myfree(params->tls_medium_clist); 128 myfree(params->tls_low_clist); 129 myfree(params->tls_export_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_bug_tweaks); 135 myfree(params->tls_ssl_options); 136 myfree(params->tls_dane_digests); 137 myfree(params->tls_mgr_service); 138 myfree(params->tls_tkt_cipher); 139 myfree((void *) params); 140 } 141 142 /* tls_proxy_client_param_scan - receive TLS_CLIENT_PARAMS from stream */ 143 144 int tls_proxy_client_param_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 145 int flags, void *ptr) 146 { 147 TLS_CLIENT_PARAMS *params 148 = (TLS_CLIENT_PARAMS *) mymalloc(sizeof(*params)); 149 int ret; 150 VSTRING *tls_high_clist = vstring_alloc(25); 151 VSTRING *tls_medium_clist = vstring_alloc(25); 152 VSTRING *tls_low_clist = vstring_alloc(25); 153 VSTRING *tls_export_clist = vstring_alloc(25); 154 VSTRING *tls_null_clist = vstring_alloc(25); 155 VSTRING *tls_eecdh_auto = vstring_alloc(25); 156 VSTRING *tls_eecdh_strong = vstring_alloc(25); 157 VSTRING *tls_eecdh_ultra = vstring_alloc(25); 158 VSTRING *tls_bug_tweaks = vstring_alloc(25); 159 VSTRING *tls_ssl_options = vstring_alloc(25); 160 VSTRING *tls_dane_digests = vstring_alloc(25); 161 VSTRING *tls_mgr_service = vstring_alloc(25); 162 VSTRING *tls_tkt_cipher = vstring_alloc(25); 163 164 if (msg_verbose) 165 msg_info("begin tls_proxy_client_param_scan"); 166 167 /* 168 * Note: memset() is not a portable way to initialize non-integer types. 169 */ 170 memset(params, 0, sizeof(*params)); 171 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 172 RECV_ATTR_STR(VAR_TLS_HIGH_CLIST, tls_high_clist), 173 RECV_ATTR_STR(VAR_TLS_MEDIUM_CLIST, tls_medium_clist), 174 RECV_ATTR_STR(VAR_TLS_LOW_CLIST, tls_low_clist), 175 RECV_ATTR_STR(VAR_TLS_EXPORT_CLIST, tls_export_clist), 176 RECV_ATTR_STR(VAR_TLS_NULL_CLIST, tls_null_clist), 177 RECV_ATTR_STR(VAR_TLS_EECDH_AUTO, tls_eecdh_auto), 178 RECV_ATTR_STR(VAR_TLS_EECDH_STRONG, tls_eecdh_strong), 179 RECV_ATTR_STR(VAR_TLS_EECDH_ULTRA, tls_eecdh_ultra), 180 RECV_ATTR_STR(VAR_TLS_BUG_TWEAKS, tls_bug_tweaks), 181 RECV_ATTR_STR(VAR_TLS_SSL_OPTIONS, tls_ssl_options), 182 RECV_ATTR_STR(VAR_TLS_DANE_DIGESTS, tls_dane_digests), 183 RECV_ATTR_STR(VAR_TLS_MGR_SERVICE, tls_mgr_service), 184 RECV_ATTR_STR(VAR_TLS_TKT_CIPHER, tls_tkt_cipher), 185 RECV_ATTR_INT(VAR_TLS_DAEMON_RAND_BYTES, 186 ¶ms->tls_daemon_rand_bytes), 187 RECV_ATTR_INT(VAR_TLS_APPEND_DEF_CA, 188 ¶ms->tls_append_def_CA), 189 RECV_ATTR_INT(VAR_TLS_BC_PKEY_FPRINT, 190 ¶ms->tls_bc_pkey_fprint), 191 RECV_ATTR_INT(VAR_TLS_PREEMPT_CLIST, 192 ¶ms->tls_preempt_clist), 193 RECV_ATTR_INT(VAR_TLS_MULTI_WILDCARD, 194 ¶ms->tls_multi_wildcard), 195 ATTR_TYPE_END); 196 /* Always construct a well-formed structure. */ 197 params->tls_high_clist = vstring_export(tls_high_clist); 198 params->tls_medium_clist = vstring_export(tls_medium_clist); 199 params->tls_low_clist = vstring_export(tls_low_clist); 200 params->tls_export_clist = vstring_export(tls_export_clist); 201 params->tls_null_clist = vstring_export(tls_null_clist); 202 params->tls_eecdh_auto = vstring_export(tls_eecdh_auto); 203 params->tls_eecdh_strong = vstring_export(tls_eecdh_strong); 204 params->tls_eecdh_ultra = vstring_export(tls_eecdh_ultra); 205 params->tls_bug_tweaks = vstring_export(tls_bug_tweaks); 206 params->tls_ssl_options = vstring_export(tls_ssl_options); 207 params->tls_dane_digests = vstring_export(tls_dane_digests); 208 params->tls_mgr_service = vstring_export(tls_mgr_service); 209 params->tls_tkt_cipher = vstring_export(tls_tkt_cipher); 210 211 ret = (ret == 18 ? 1 : -1); 212 if (ret != 1) { 213 tls_proxy_client_param_free(params); 214 params = 0; 215 } 216 *(TLS_CLIENT_PARAMS **) ptr = params; 217 if (msg_verbose) 218 msg_info("tls_proxy_client_param_scan ret=%d", ret); 219 return (ret); 220 } 221 222 /* tls_proxy_client_init_free - destroy TLS_CLIENT_INIT_PROPS structure */ 223 224 void tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *props) 225 { 226 myfree((void *) props->log_param); 227 myfree((void *) props->log_level); 228 myfree((void *) props->cache_type); 229 myfree((void *) props->chain_files); 230 myfree((void *) props->cert_file); 231 myfree((void *) props->key_file); 232 myfree((void *) props->dcert_file); 233 myfree((void *) props->dkey_file); 234 myfree((void *) props->eccert_file); 235 myfree((void *) props->eckey_file); 236 myfree((void *) props->CAfile); 237 myfree((void *) props->CApath); 238 myfree((void *) props->mdalg); 239 myfree((void *) props); 240 } 241 242 /* tls_proxy_client_init_scan - receive TLS_CLIENT_INIT_PROPS from stream */ 243 244 int tls_proxy_client_init_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 245 int flags, void *ptr) 246 { 247 TLS_CLIENT_INIT_PROPS *props 248 = (TLS_CLIENT_INIT_PROPS *) mymalloc(sizeof(*props)); 249 int ret; 250 VSTRING *log_param = vstring_alloc(25); 251 VSTRING *log_level = vstring_alloc(25); 252 VSTRING *cache_type = vstring_alloc(25); 253 VSTRING *chain_files = vstring_alloc(25); 254 VSTRING *cert_file = vstring_alloc(25); 255 VSTRING *key_file = vstring_alloc(25); 256 VSTRING *dcert_file = vstring_alloc(25); 257 VSTRING *dkey_file = vstring_alloc(25); 258 VSTRING *eccert_file = vstring_alloc(25); 259 VSTRING *eckey_file = vstring_alloc(25); 260 VSTRING *CAfile = vstring_alloc(25); 261 VSTRING *CApath = vstring_alloc(25); 262 VSTRING *mdalg = vstring_alloc(25); 263 264 if (msg_verbose) 265 msg_info("begin tls_proxy_client_init_scan"); 266 267 /* 268 * Note: memset() is not a portable way to initialize non-integer types. 269 */ 270 memset(props, 0, sizeof(*props)); 271 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 272 RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param), 273 RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level), 274 RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth), 275 RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type), 276 RECV_ATTR_STR(TLS_ATTR_CHAIN_FILES, chain_files), 277 RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file), 278 RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file), 279 RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file), 280 RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file), 281 RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file), 282 RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file), 283 RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile), 284 RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath), 285 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 286 ATTR_TYPE_END); 287 /* Always construct a well-formed structure. */ 288 props->log_param = vstring_export(log_param); 289 props->log_level = vstring_export(log_level); 290 props->cache_type = vstring_export(cache_type); 291 props->chain_files = vstring_export(chain_files); 292 props->cert_file = vstring_export(cert_file); 293 props->key_file = vstring_export(key_file); 294 props->dcert_file = vstring_export(dcert_file); 295 props->dkey_file = vstring_export(dkey_file); 296 props->eccert_file = vstring_export(eccert_file); 297 props->eckey_file = vstring_export(eckey_file); 298 props->CAfile = vstring_export(CAfile); 299 props->CApath = vstring_export(CApath); 300 props->mdalg = vstring_export(mdalg); 301 ret = (ret == 14 ? 1 : -1); 302 if (ret != 1) { 303 tls_proxy_client_init_free(props); 304 props = 0; 305 } 306 *(TLS_CLIENT_INIT_PROPS **) ptr = props; 307 if (msg_verbose) 308 msg_info("tls_proxy_client_init_scan ret=%d", ret); 309 return (ret); 310 } 311 312 /* tls_proxy_client_start_free - destroy TLS_CLIENT_START_PROPS structure */ 313 314 void tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props) 315 { 316 myfree((void *) props->nexthop); 317 myfree((void *) props->host); 318 myfree((void *) props->namaddr); 319 myfree((void *) props->sni); 320 myfree((void *) props->serverid); 321 myfree((void *) props->helo); 322 myfree((void *) props->protocols); 323 myfree((void *) props->cipher_grade); 324 myfree((void *) props->cipher_exclusions); 325 if (props->matchargv) 326 argv_free((ARGV *) props->matchargv); 327 myfree((void *) props->mdalg); 328 if (props->dane) 329 tls_dane_free((TLS_DANE *) props->dane); 330 myfree((void *) props); 331 } 332 333 /* tls_proxy_client_tlsa_scan - receive TLS_TLSA from stream */ 334 335 static int tls_proxy_client_tlsa_scan(ATTR_SCAN_COMMON_FN scan_fn, 336 VSTREAM *fp, int flags, void *ptr) 337 { 338 static VSTRING *data; 339 TLS_TLSA *head; 340 int count; 341 int ret; 342 343 if (data == 0) 344 data = vstring_alloc(64); 345 346 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 347 RECV_ATTR_INT(TLS_ATTR_COUNT, &count), 348 ATTR_TYPE_END); 349 if (ret == 1 && msg_verbose) 350 msg_info("tls_proxy_client_tlsa_scan count=%d", count); 351 352 for (head = 0; ret == 1 && count > 0; --count) { 353 int u, s, m; 354 355 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 356 RECV_ATTR_INT(TLS_ATTR_USAGE, &u), 357 RECV_ATTR_INT(TLS_ATTR_SELECTOR, &s), 358 RECV_ATTR_INT(TLS_ATTR_MTYPE, &m), 359 RECV_ATTR_DATA(TLS_ATTR_DATA, data), 360 ATTR_TYPE_END); 361 if (ret == 4) { 362 ret = 1; 363 /* This makes a copy of the static vstring content */ 364 head = tlsa_prepend(head, u, s, m, (unsigned char *) STR(data), 365 LEN(data)); 366 } else 367 ret = -1; 368 } 369 370 if (ret != 1) { 371 tls_tlsa_free(head); 372 head = 0; 373 } 374 *(TLS_TLSA **) ptr = head; 375 if (msg_verbose) 376 msg_info("tls_proxy_client_tlsa_scan ret=%d", ret); 377 return (ret); 378 } 379 380 /* tls_proxy_client_dane_scan - receive TLS_DANE from stream */ 381 382 static int tls_proxy_client_dane_scan(ATTR_SCAN_COMMON_FN scan_fn, 383 VSTREAM *fp, int flags, void *ptr) 384 { 385 TLS_DANE *dane = 0; 386 int ret; 387 int have_dane = 0; 388 389 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 390 RECV_ATTR_INT(TLS_ATTR_DANE, &have_dane), 391 ATTR_TYPE_END); 392 if (msg_verbose) 393 msg_info("tls_proxy_client_dane_scan have_dane=%d", have_dane); 394 395 if (ret == 1 && have_dane) { 396 VSTRING *base_domain = vstring_alloc(25); 397 398 dane = tls_dane_alloc(); 399 /* We only need the base domain and TLSA RRs */ 400 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 401 RECV_ATTR_STR(TLS_ATTR_DOMAIN, base_domain), 402 RECV_ATTR_FUNC(tls_proxy_client_tlsa_scan, 403 &dane->tlsa), 404 ATTR_TYPE_END); 405 406 /* Always construct a well-formed structure. */ 407 dane->base_domain = vstring_export(base_domain); 408 ret = (ret == 2 ? 1 : -1); 409 if (ret != 1) { 410 tls_dane_free(dane); 411 dane = 0; 412 } 413 } 414 *(TLS_DANE **) ptr = dane; 415 if (msg_verbose) 416 msg_info("tls_proxy_client_dane_scan ret=%d", ret); 417 return (ret); 418 } 419 420 /* tls_proxy_client_start_scan - receive TLS_CLIENT_START_PROPS from stream */ 421 422 int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 423 int flags, void *ptr) 424 { 425 TLS_CLIENT_START_PROPS *props 426 = (TLS_CLIENT_START_PROPS *) mymalloc(sizeof(*props)); 427 int ret; 428 VSTRING *nexthop = vstring_alloc(25); 429 VSTRING *host = vstring_alloc(25); 430 VSTRING *namaddr = vstring_alloc(25); 431 VSTRING *sni = vstring_alloc(25); 432 VSTRING *serverid = vstring_alloc(25); 433 VSTRING *helo = vstring_alloc(25); 434 VSTRING *protocols = vstring_alloc(25); 435 VSTRING *cipher_grade = vstring_alloc(25); 436 VSTRING *cipher_exclusions = vstring_alloc(25); 437 VSTRING *mdalg = vstring_alloc(25); 438 439 if (msg_verbose) 440 msg_info("begin tls_proxy_client_start_scan"); 441 442 /* 443 * Note: memset() is not a portable way to initialize non-integer types. 444 */ 445 memset(props, 0, sizeof(*props)); 446 props->ctx = 0; 447 props->stream = 0; 448 props->fd = -1; 449 props->dane = 0; /* scan_fn may return early */ 450 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 451 RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout), 452 RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level), 453 RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop), 454 RECV_ATTR_STR(TLS_ATTR_HOST, host), 455 RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr), 456 RECV_ATTR_STR(TLS_ATTR_SNI, sni), 457 RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid), 458 RECV_ATTR_STR(TLS_ATTR_HELO, helo), 459 RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols), 460 RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade), 461 RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS, 462 cipher_exclusions), 463 RECV_ATTR_FUNC(argv_attr_scan, &props->matchargv), 464 RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), 465 RECV_ATTR_FUNC(tls_proxy_client_dane_scan, 466 &props->dane), 467 ATTR_TYPE_END); 468 /* Always construct a well-formed structure. */ 469 props->nexthop = vstring_export(nexthop); 470 props->host = vstring_export(host); 471 props->namaddr = vstring_export(namaddr); 472 props->sni = vstring_export(sni); 473 props->serverid = vstring_export(serverid); 474 props->helo = vstring_export(helo); 475 props->protocols = vstring_export(protocols); 476 props->cipher_grade = vstring_export(cipher_grade); 477 props->cipher_exclusions = vstring_export(cipher_exclusions); 478 props->mdalg = vstring_export(mdalg); 479 ret = (ret == 14 ? 1 : -1); 480 if (ret != 1) { 481 tls_proxy_client_start_free(props); 482 props = 0; 483 } 484 *(TLS_CLIENT_START_PROPS **) ptr = props; 485 if (msg_verbose) 486 msg_info("tls_proxy_client_start_scan ret=%d", ret); 487 return (ret); 488 } 489 490 #endif 491