diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:18:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:18:56 +0000 |
commit | b7c15c31519dc44c1f691e0466badd556ffe9423 (patch) | |
tree | f944572f288bab482a615e09af627d9a2b6727d8 /src/tls/tls_proxy_client_scan.c | |
parent | Initial commit. (diff) | |
download | postfix-b7c15c31519dc44c1f691e0466badd556ffe9423.tar.xz postfix-b7c15c31519dc44c1f691e0466badd556ffe9423.zip |
Adding upstream version 3.7.10.upstream/3.7.10
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tls/tls_proxy_client_scan.c')
-rw-r--r-- | src/tls/tls_proxy_client_scan.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/src/tls/tls_proxy_client_scan.c b/src/tls/tls_proxy_client_scan.c new file mode 100644 index 0000000..7083353 --- /dev/null +++ b/src/tls/tls_proxy_client_scan.c @@ -0,0 +1,496 @@ +/*++ +/* NAME +/* tls_proxy_client_scan 3 +/* SUMMARY +/* read TLS_CLIENT_XXX structures from stream +/* SYNOPSIS +/* #include <tls_proxy.h> +/* +/* int tls_proxy_client_param_scan(scan_fn, stream, flags, ptr) +/* ATTR_SCAN_COMMON_FN scan_fn; +/* VSTREAM *stream; +/* int flags; +/* void *ptr; +/* +/* void tls_proxy_client_param_free(params) +/* TLS_CLIENT_PARAMS *params; +/* +/* int tls_proxy_client_init_scan(scan_fn, stream, flags, ptr) +/* ATTR_SCAN_COMMON_FN scan_fn; +/* VSTREAM *stream; +/* int flags; +/* void *ptr; +/* +/* void tls_proxy_client_init_free(init_props) +/* TLS_CLIENT_INIT_PROPS *init_props; +/* +/* int tls_proxy_client_start_scan(scan_fn, stream, flags, ptr) +/* ATTR_SCAN_COMMON_FN scan_fn; +/* VSTREAM *stream; +/* int flags; +/* void *ptr; +/* +/* void tls_proxy_client_start_free(start_props) +/* TLS_CLIENT_START_PROPS *start_props; +/* DESCRIPTION +/* tls_proxy_client_param_scan() reads a TLS_CLIENT_PARAMS structure from +/* the named stream using the specified attribute scan routine. +/* tls_proxy_client_param_scan() is meant to be passed as a call-back +/* function to attr_scan(), as shown below. +/* +/* tls_proxy_client_param_free() destroys a TLS_CLIENT_PARAMS structure +/* that was created by tls_proxy_client_param_scan(). +/* +/* TLS_CLIENT_PARAMS *param = 0; +/* ... +/* ... RECV_ATTR_FUNC(tls_proxy_client_param_scan, (void *) ¶m) +/* ... +/* if (param != 0) +/* tls_proxy_client_param_free(param); +/* +/* tls_proxy_client_init_scan() reads a full TLS_CLIENT_INIT_PROPS +/* structure from the named stream using the specified attribute +/* scan routine. tls_proxy_client_init_scan() is meant to be passed +/* as a call-back function to attr_scan(), as shown below. +/* +/* tls_proxy_client_init_free() destroys a TLS_CLIENT_INIT_PROPS +/* structure that was created by tls_proxy_client_init_scan(). +/* +/* TLS_CLIENT_INIT_PROPS *init_props = 0; +/* ... +/* ... RECV_ATTR_FUNC(tls_proxy_client_init_scan, (void *) &init_props) +/* ... +/* if (init_props != 0) +/* tls_proxy_client_init_free(init_props); +/* +/* tls_proxy_client_start_scan() reads a TLS_CLIENT_START_PROPS +/* structure, without the stream of file descriptor members, +/* from the named stream using the specified attribute scan +/* routine. tls_proxy_client_start_scan() is meant to be passed +/* as a call-back function to attr_scan(), as shown below. +/* +/* tls_proxy_client_start_free() destroys a TLS_CLIENT_START_PROPS +/* structure that was created by tls_proxy_client_start_scan(). +/* +/* TLS_CLIENT_START_PROPS *start_props = 0; +/* ... +/* ... RECV_ATTR_FUNC(tls_proxy_client_start_scan, (void *) &start_props) +/* ... +/* if (start_props != 0) +/* tls_proxy_client_start_free(start_props); +/* DIAGNOSTICS +/* Fatal: out of memory. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +#ifdef USE_TLS + +/* System library. */ + +#include <sys_defs.h> + +/* Utility library */ + +#include <argv_attr.h> +#include <attr.h> +#include <msg.h> +#include <vstring.h> + +/* Global library. */ + +#include <mail_params.h> + +/* TLS library. */ + +#define TLS_INTERNAL +#include <tls.h> +#include <tls_proxy.h> + +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + +/* tls_proxy_client_param_free - destroy TLS_CLIENT_PARAMS structure */ + +void tls_proxy_client_param_free(TLS_CLIENT_PARAMS *params) +{ + myfree(params->tls_cnf_file); + myfree(params->tls_cnf_name); + myfree(params->tls_high_clist); + myfree(params->tls_medium_clist); + myfree(params->tls_low_clist); + myfree(params->tls_export_clist); + myfree(params->tls_null_clist); + myfree(params->tls_eecdh_auto); + myfree(params->tls_eecdh_strong); + myfree(params->tls_eecdh_ultra); + myfree(params->tls_bug_tweaks); + myfree(params->tls_ssl_options); + myfree(params->tls_dane_digests); + myfree(params->tls_mgr_service); + myfree(params->tls_tkt_cipher); + myfree((void *) params); +} + +/* tls_proxy_client_param_scan - receive TLS_CLIENT_PARAMS from stream */ + +int tls_proxy_client_param_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, + int flags, void *ptr) +{ + TLS_CLIENT_PARAMS *params + = (TLS_CLIENT_PARAMS *) mymalloc(sizeof(*params)); + int ret; + VSTRING *cnf_file = vstring_alloc(25); + VSTRING *cnf_name = vstring_alloc(25); + VSTRING *tls_high_clist = vstring_alloc(25); + VSTRING *tls_medium_clist = vstring_alloc(25); + VSTRING *tls_low_clist = vstring_alloc(25); + VSTRING *tls_export_clist = vstring_alloc(25); + VSTRING *tls_null_clist = vstring_alloc(25); + VSTRING *tls_eecdh_auto = vstring_alloc(25); + VSTRING *tls_eecdh_strong = vstring_alloc(25); + VSTRING *tls_eecdh_ultra = vstring_alloc(25); + VSTRING *tls_bug_tweaks = vstring_alloc(25); + VSTRING *tls_ssl_options = vstring_alloc(25); + VSTRING *tls_dane_digests = vstring_alloc(25); + VSTRING *tls_mgr_service = vstring_alloc(25); + VSTRING *tls_tkt_cipher = vstring_alloc(25); + + if (msg_verbose) + msg_info("begin tls_proxy_client_param_scan"); + + /* + * Note: memset() is not a portable way to initialize non-integer types. + */ + memset(params, 0, sizeof(*params)); + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_STR(TLS_ATTR_CNF_FILE, cnf_file), + RECV_ATTR_STR(TLS_ATTR_CNF_NAME, cnf_name), + RECV_ATTR_STR(VAR_TLS_HIGH_CLIST, tls_high_clist), + RECV_ATTR_STR(VAR_TLS_MEDIUM_CLIST, tls_medium_clist), + RECV_ATTR_STR(VAR_TLS_LOW_CLIST, tls_low_clist), + RECV_ATTR_STR(VAR_TLS_EXPORT_CLIST, tls_export_clist), + RECV_ATTR_STR(VAR_TLS_NULL_CLIST, tls_null_clist), + RECV_ATTR_STR(VAR_TLS_EECDH_AUTO, tls_eecdh_auto), + RECV_ATTR_STR(VAR_TLS_EECDH_STRONG, tls_eecdh_strong), + RECV_ATTR_STR(VAR_TLS_EECDH_ULTRA, tls_eecdh_ultra), + RECV_ATTR_STR(VAR_TLS_BUG_TWEAKS, tls_bug_tweaks), + RECV_ATTR_STR(VAR_TLS_SSL_OPTIONS, tls_ssl_options), + RECV_ATTR_STR(VAR_TLS_DANE_DIGESTS, tls_dane_digests), + RECV_ATTR_STR(VAR_TLS_MGR_SERVICE, tls_mgr_service), + RECV_ATTR_STR(VAR_TLS_TKT_CIPHER, tls_tkt_cipher), + RECV_ATTR_INT(VAR_TLS_DAEMON_RAND_BYTES, + ¶ms->tls_daemon_rand_bytes), + RECV_ATTR_INT(VAR_TLS_APPEND_DEF_CA, + ¶ms->tls_append_def_CA), + RECV_ATTR_INT(VAR_TLS_BC_PKEY_FPRINT, + ¶ms->tls_bc_pkey_fprint), + RECV_ATTR_INT(VAR_TLS_PREEMPT_CLIST, + ¶ms->tls_preempt_clist), + RECV_ATTR_INT(VAR_TLS_MULTI_WILDCARD, + ¶ms->tls_multi_wildcard), + ATTR_TYPE_END); + /* Always construct a well-formed structure. */ + params->tls_cnf_file = vstring_export(cnf_file); + params->tls_cnf_name = vstring_export(cnf_name); + params->tls_high_clist = vstring_export(tls_high_clist); + params->tls_medium_clist = vstring_export(tls_medium_clist); + params->tls_low_clist = vstring_export(tls_low_clist); + params->tls_export_clist = vstring_export(tls_export_clist); + params->tls_null_clist = vstring_export(tls_null_clist); + params->tls_eecdh_auto = vstring_export(tls_eecdh_auto); + params->tls_eecdh_strong = vstring_export(tls_eecdh_strong); + params->tls_eecdh_ultra = vstring_export(tls_eecdh_ultra); + params->tls_bug_tweaks = vstring_export(tls_bug_tweaks); + params->tls_ssl_options = vstring_export(tls_ssl_options); + params->tls_dane_digests = vstring_export(tls_dane_digests); + params->tls_mgr_service = vstring_export(tls_mgr_service); + params->tls_tkt_cipher = vstring_export(tls_tkt_cipher); + + ret = (ret == 20 ? 1 : -1); + if (ret != 1) { + tls_proxy_client_param_free(params); + params = 0; + } + *(TLS_CLIENT_PARAMS **) ptr = params; + if (msg_verbose) + msg_info("tls_proxy_client_param_scan ret=%d", ret); + return (ret); +} + +/* tls_proxy_client_init_free - destroy TLS_CLIENT_INIT_PROPS structure */ + +void tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *props) +{ + myfree((void *) props->log_param); + myfree((void *) props->log_level); + myfree((void *) props->cache_type); + myfree((void *) props->chain_files); + myfree((void *) props->cert_file); + myfree((void *) props->key_file); + myfree((void *) props->dcert_file); + myfree((void *) props->dkey_file); + myfree((void *) props->eccert_file); + myfree((void *) props->eckey_file); + myfree((void *) props->CAfile); + myfree((void *) props->CApath); + myfree((void *) props->mdalg); + myfree((void *) props); +} + +/* tls_proxy_client_init_scan - receive TLS_CLIENT_INIT_PROPS from stream */ + +int tls_proxy_client_init_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, + int flags, void *ptr) +{ + TLS_CLIENT_INIT_PROPS *props + = (TLS_CLIENT_INIT_PROPS *) mymalloc(sizeof(*props)); + int ret; + VSTRING *log_param = vstring_alloc(25); + VSTRING *log_level = vstring_alloc(25); + VSTRING *cache_type = vstring_alloc(25); + VSTRING *chain_files = vstring_alloc(25); + VSTRING *cert_file = vstring_alloc(25); + VSTRING *key_file = vstring_alloc(25); + VSTRING *dcert_file = vstring_alloc(25); + VSTRING *dkey_file = vstring_alloc(25); + VSTRING *eccert_file = vstring_alloc(25); + VSTRING *eckey_file = vstring_alloc(25); + VSTRING *CAfile = vstring_alloc(25); + VSTRING *CApath = vstring_alloc(25); + VSTRING *mdalg = vstring_alloc(25); + + if (msg_verbose) + msg_info("begin tls_proxy_client_init_scan"); + + /* + * Note: memset() is not a portable way to initialize non-integer types. + */ + memset(props, 0, sizeof(*props)); + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param), + RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level), + RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth), + RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type), + RECV_ATTR_STR(TLS_ATTR_CHAIN_FILES, chain_files), + RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file), + RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file), + RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file), + RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file), + RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file), + RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file), + RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile), + RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath), + RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), + ATTR_TYPE_END); + /* Always construct a well-formed structure. */ + props->log_param = vstring_export(log_param); + props->log_level = vstring_export(log_level); + props->cache_type = vstring_export(cache_type); + props->chain_files = vstring_export(chain_files); + props->cert_file = vstring_export(cert_file); + props->key_file = vstring_export(key_file); + props->dcert_file = vstring_export(dcert_file); + props->dkey_file = vstring_export(dkey_file); + props->eccert_file = vstring_export(eccert_file); + props->eckey_file = vstring_export(eckey_file); + props->CAfile = vstring_export(CAfile); + props->CApath = vstring_export(CApath); + props->mdalg = vstring_export(mdalg); + ret = (ret == 14 ? 1 : -1); + if (ret != 1) { + tls_proxy_client_init_free(props); + props = 0; + } + *(TLS_CLIENT_INIT_PROPS **) ptr = props; + if (msg_verbose) + msg_info("tls_proxy_client_init_scan ret=%d", ret); + return (ret); +} + +/* tls_proxy_client_start_free - destroy TLS_CLIENT_START_PROPS structure */ + +void tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props) +{ + myfree((void *) props->nexthop); + myfree((void *) props->host); + myfree((void *) props->namaddr); + myfree((void *) props->sni); + myfree((void *) props->serverid); + myfree((void *) props->helo); + myfree((void *) props->protocols); + myfree((void *) props->cipher_grade); + myfree((void *) props->cipher_exclusions); + if (props->matchargv) + argv_free((ARGV *) props->matchargv); + myfree((void *) props->mdalg); + if (props->dane) + tls_dane_free((TLS_DANE *) props->dane); + myfree((void *) props); +} + +/* tls_proxy_client_tlsa_scan - receive TLS_TLSA from stream */ + +static int tls_proxy_client_tlsa_scan(ATTR_SCAN_COMMON_FN scan_fn, + VSTREAM *fp, int flags, void *ptr) +{ + static VSTRING *data; + TLS_TLSA *head; + int count; + int ret; + + if (data == 0) + data = vstring_alloc(64); + + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_INT(TLS_ATTR_COUNT, &count), + ATTR_TYPE_END); + if (ret == 1 && msg_verbose) + msg_info("tls_proxy_client_tlsa_scan count=%d", count); + + for (head = 0; ret == 1 && count > 0; --count) { + int u, s, m; + + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_INT(TLS_ATTR_USAGE, &u), + RECV_ATTR_INT(TLS_ATTR_SELECTOR, &s), + RECV_ATTR_INT(TLS_ATTR_MTYPE, &m), + RECV_ATTR_DATA(TLS_ATTR_DATA, data), + ATTR_TYPE_END); + if (ret == 4) { + ret = 1; + /* This makes a copy of the static vstring content */ + head = tlsa_prepend(head, u, s, m, (unsigned char *) STR(data), + LEN(data)); + } else + ret = -1; + } + + if (ret != 1) { + tls_tlsa_free(head); + head = 0; + } + *(TLS_TLSA **) ptr = head; + if (msg_verbose) + msg_info("tls_proxy_client_tlsa_scan ret=%d", ret); + return (ret); +} + +/* tls_proxy_client_dane_scan - receive TLS_DANE from stream */ + +static int tls_proxy_client_dane_scan(ATTR_SCAN_COMMON_FN scan_fn, + VSTREAM *fp, int flags, void *ptr) +{ + TLS_DANE *dane = 0; + int ret; + int have_dane = 0; + + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_INT(TLS_ATTR_DANE, &have_dane), + ATTR_TYPE_END); + if (msg_verbose) + msg_info("tls_proxy_client_dane_scan have_dane=%d", have_dane); + + if (ret == 1 && have_dane) { + VSTRING *base_domain = vstring_alloc(25); + + dane = tls_dane_alloc(); + /* We only need the base domain and TLSA RRs */ + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_STR(TLS_ATTR_DOMAIN, base_domain), + RECV_ATTR_FUNC(tls_proxy_client_tlsa_scan, + &dane->tlsa), + ATTR_TYPE_END); + + /* Always construct a well-formed structure. */ + dane->base_domain = vstring_export(base_domain); + ret = (ret == 2 ? 1 : -1); + if (ret != 1) { + tls_dane_free(dane); + dane = 0; + } + } + *(TLS_DANE **) ptr = dane; + if (msg_verbose) + msg_info("tls_proxy_client_dane_scan ret=%d", ret); + return (ret); +} + +/* tls_proxy_client_start_scan - receive TLS_CLIENT_START_PROPS from stream */ + +int tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, + int flags, void *ptr) +{ + TLS_CLIENT_START_PROPS *props + = (TLS_CLIENT_START_PROPS *) mymalloc(sizeof(*props)); + int ret; + VSTRING *nexthop = vstring_alloc(25); + VSTRING *host = vstring_alloc(25); + VSTRING *namaddr = vstring_alloc(25); + VSTRING *sni = vstring_alloc(25); + VSTRING *serverid = vstring_alloc(25); + VSTRING *helo = vstring_alloc(25); + VSTRING *protocols = vstring_alloc(25); + VSTRING *cipher_grade = vstring_alloc(25); + VSTRING *cipher_exclusions = vstring_alloc(25); + VSTRING *mdalg = vstring_alloc(25); + + if (msg_verbose) + msg_info("begin tls_proxy_client_start_scan"); + + /* + * Note: memset() is not a portable way to initialize non-integer types. + */ + memset(props, 0, sizeof(*props)); + props->ctx = 0; + props->stream = 0; + props->fd = -1; + props->dane = 0; /* scan_fn may return early */ + ret = scan_fn(fp, flags | ATTR_FLAG_MORE, + RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout), + RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level), + RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop), + RECV_ATTR_STR(TLS_ATTR_HOST, host), + RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr), + RECV_ATTR_STR(TLS_ATTR_SNI, sni), + RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid), + RECV_ATTR_STR(TLS_ATTR_HELO, helo), + RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols), + RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade), + RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS, + cipher_exclusions), + RECV_ATTR_FUNC(argv_attr_scan, &props->matchargv), + RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg), + RECV_ATTR_FUNC(tls_proxy_client_dane_scan, + &props->dane), + ATTR_TYPE_END); + /* Always construct a well-formed structure. */ + props->nexthop = vstring_export(nexthop); + props->host = vstring_export(host); + props->namaddr = vstring_export(namaddr); + props->sni = vstring_export(sni); + props->serverid = vstring_export(serverid); + props->helo = vstring_export(helo); + props->protocols = vstring_export(protocols); + props->cipher_grade = vstring_export(cipher_grade); + props->cipher_exclusions = vstring_export(cipher_exclusions); + props->mdalg = vstring_export(mdalg); + ret = (ret == 14 ? 1 : -1); + if (ret != 1) { + tls_proxy_client_start_free(props); + props = 0; + } + *(TLS_CLIENT_START_PROPS **) ptr = props; + if (msg_verbose) + msg_info("tls_proxy_client_start_scan ret=%d", ret); + return (ret); +} + +#endif |