1 /*        $NetBSD: tls_proxy_client_scan.c,v 1.5 2025/02/25 19:15: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 *) &param)
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 #ifdef USE_TLSRPT
119 #define TLSRPT_WRAPPER_INTERNAL
120 #include <tlsrpt_wrapper.h>
121 #endif
122 
123 #define STR(x) vstring_str(x)
124 #define LEN(x) VSTRING_LEN(x)
125 
126 /* tls_proxy_client_param_free - destroy TLS_CLIENT_PARAMS structure */
127 
tls_proxy_client_param_free(TLS_CLIENT_PARAMS * params)128 void    tls_proxy_client_param_free(TLS_CLIENT_PARAMS *params)
129 {
130     myfree(params->tls_cnf_file);
131     myfree(params->tls_cnf_name);
132     myfree(params->tls_high_clist);
133     myfree(params->tls_medium_clist);
134     myfree(params->tls_null_clist);
135     myfree(params->tls_eecdh_auto);
136     myfree(params->tls_eecdh_strong);
137     myfree(params->tls_eecdh_ultra);
138     myfree(params->tls_ffdhe_auto);
139     myfree(params->tls_bug_tweaks);
140     myfree(params->tls_ssl_options);
141     myfree(params->tls_dane_digests);
142     myfree(params->tls_mgr_service);
143     myfree(params->tls_tkt_cipher);
144     myfree((void *) params);
145 }
146 
147 /* tls_proxy_client_param_scan - receive TLS_CLIENT_PARAMS from stream */
148 
tls_proxy_client_param_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)149 int     tls_proxy_client_param_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
150                                                     int flags, void *ptr)
151 {
152     TLS_CLIENT_PARAMS *params
153     = (TLS_CLIENT_PARAMS *) mymalloc(sizeof(*params));
154     int     ret;
155     VSTRING *cnf_file = vstring_alloc(25);
156     VSTRING *cnf_name = vstring_alloc(25);
157     VSTRING *tls_high_clist = vstring_alloc(25);
158     VSTRING *tls_medium_clist = vstring_alloc(25);
159     VSTRING *tls_null_clist = vstring_alloc(25);
160     VSTRING *tls_eecdh_auto = vstring_alloc(25);
161     VSTRING *tls_eecdh_strong = vstring_alloc(25);
162     VSTRING *tls_eecdh_ultra = vstring_alloc(25);
163     VSTRING *tls_ffdhe_auto = vstring_alloc(25);
164     VSTRING *tls_bug_tweaks = vstring_alloc(25);
165     VSTRING *tls_ssl_options = vstring_alloc(25);
166     VSTRING *tls_dane_digests = vstring_alloc(25);
167     VSTRING *tls_mgr_service = vstring_alloc(25);
168     VSTRING *tls_tkt_cipher = vstring_alloc(25);
169 
170     if (msg_verbose)
171           msg_info("begin tls_proxy_client_param_scan");
172 
173     /*
174      * Note: memset() is not a portable way to initialize non-integer types.
175      */
176     memset(params, 0, sizeof(*params));
177     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
178                       RECV_ATTR_STR(TLS_ATTR_CNF_FILE, cnf_file),
179                       RECV_ATTR_STR(TLS_ATTR_CNF_NAME, cnf_name),
180                       RECV_ATTR_STR(VAR_TLS_HIGH_CLIST, tls_high_clist),
181                       RECV_ATTR_STR(VAR_TLS_MEDIUM_CLIST, tls_medium_clist),
182                       RECV_ATTR_STR(VAR_TLS_NULL_CLIST, tls_null_clist),
183                       RECV_ATTR_STR(VAR_TLS_EECDH_AUTO, tls_eecdh_auto),
184                       RECV_ATTR_STR(VAR_TLS_EECDH_STRONG, tls_eecdh_strong),
185                       RECV_ATTR_STR(VAR_TLS_EECDH_ULTRA, tls_eecdh_ultra),
186                       RECV_ATTR_STR(VAR_TLS_FFDHE_AUTO, tls_ffdhe_auto),
187                       RECV_ATTR_STR(VAR_TLS_BUG_TWEAKS, tls_bug_tweaks),
188                       RECV_ATTR_STR(VAR_TLS_SSL_OPTIONS, tls_ssl_options),
189                       RECV_ATTR_STR(VAR_TLS_DANE_DIGESTS, tls_dane_digests),
190                       RECV_ATTR_STR(VAR_TLS_MGR_SERVICE, tls_mgr_service),
191                       RECV_ATTR_STR(VAR_TLS_TKT_CIPHER, tls_tkt_cipher),
192                       RECV_ATTR_INT(VAR_TLS_DAEMON_RAND_BYTES,
193                                         &params->tls_daemon_rand_bytes),
194                       RECV_ATTR_INT(VAR_TLS_APPEND_DEF_CA,
195                                         &params->tls_append_def_CA),
196                       RECV_ATTR_INT(VAR_TLS_BC_PKEY_FPRINT,
197                                         &params->tls_bc_pkey_fprint),
198                       RECV_ATTR_INT(VAR_TLS_PREEMPT_CLIST,
199                                         &params->tls_preempt_clist),
200                       RECV_ATTR_INT(VAR_TLS_MULTI_WILDCARD,
201                                         &params->tls_multi_wildcard),
202                       ATTR_TYPE_END);
203     /* Always construct a well-formed structure. */
204     params->tls_cnf_file = vstring_export(cnf_file);
205     params->tls_cnf_name = vstring_export(cnf_name);
206     params->tls_high_clist = vstring_export(tls_high_clist);
207     params->tls_medium_clist = vstring_export(tls_medium_clist);
208     params->tls_null_clist = vstring_export(tls_null_clist);
209     params->tls_eecdh_auto = vstring_export(tls_eecdh_auto);
210     params->tls_eecdh_strong = vstring_export(tls_eecdh_strong);
211     params->tls_eecdh_ultra = vstring_export(tls_eecdh_ultra);
212     params->tls_ffdhe_auto = vstring_export(tls_ffdhe_auto);
213     params->tls_bug_tweaks = vstring_export(tls_bug_tweaks);
214     params->tls_ssl_options = vstring_export(tls_ssl_options);
215     params->tls_dane_digests = vstring_export(tls_dane_digests);
216     params->tls_mgr_service = vstring_export(tls_mgr_service);
217     params->tls_tkt_cipher = vstring_export(tls_tkt_cipher);
218 
219     ret = (ret == 19 ? 1 : -1);
220     if (ret != 1) {
221           tls_proxy_client_param_free(params);
222           params = 0;
223     }
224     *(TLS_CLIENT_PARAMS **) ptr = params;
225     if (msg_verbose)
226           msg_info("tls_proxy_client_param_scan ret=%d", ret);
227     return (ret);
228 }
229 
230 /* tls_proxy_client_init_free - destroy TLS_CLIENT_INIT_PROPS structure */
231 
tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS * props)232 void    tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS *props)
233 {
234     myfree((void *) props->log_param);
235     myfree((void *) props->log_level);
236     myfree((void *) props->cache_type);
237     myfree((void *) props->chain_files);
238     myfree((void *) props->cert_file);
239     myfree((void *) props->key_file);
240     myfree((void *) props->dcert_file);
241     myfree((void *) props->dkey_file);
242     myfree((void *) props->eccert_file);
243     myfree((void *) props->eckey_file);
244     myfree((void *) props->CAfile);
245     myfree((void *) props->CApath);
246     myfree((void *) props->mdalg);
247     myfree((void *) props);
248 }
249 
250 /* tls_proxy_client_init_scan - receive TLS_CLIENT_INIT_PROPS from stream */
251 
tls_proxy_client_init_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)252 int     tls_proxy_client_init_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
253                                                    int flags, void *ptr)
254 {
255     TLS_CLIENT_INIT_PROPS *props
256     = (TLS_CLIENT_INIT_PROPS *) mymalloc(sizeof(*props));
257     int     ret;
258     VSTRING *log_param = vstring_alloc(25);
259     VSTRING *log_level = vstring_alloc(25);
260     VSTRING *cache_type = vstring_alloc(25);
261     VSTRING *chain_files = vstring_alloc(25);
262     VSTRING *cert_file = vstring_alloc(25);
263     VSTRING *key_file = vstring_alloc(25);
264     VSTRING *dcert_file = vstring_alloc(25);
265     VSTRING *dkey_file = vstring_alloc(25);
266     VSTRING *eccert_file = vstring_alloc(25);
267     VSTRING *eckey_file = vstring_alloc(25);
268     VSTRING *CAfile = vstring_alloc(25);
269     VSTRING *CApath = vstring_alloc(25);
270     VSTRING *mdalg = vstring_alloc(25);
271 
272     if (msg_verbose)
273           msg_info("begin tls_proxy_client_init_scan");
274 
275     /*
276      * Note: memset() is not a portable way to initialize non-integer types.
277      */
278     memset(props, 0, sizeof(*props));
279     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
280                       RECV_ATTR_STR(TLS_ATTR_LOG_PARAM, log_param),
281                       RECV_ATTR_STR(TLS_ATTR_LOG_LEVEL, log_level),
282                       RECV_ATTR_INT(TLS_ATTR_VERIFYDEPTH, &props->verifydepth),
283                       RECV_ATTR_STR(TLS_ATTR_CACHE_TYPE, cache_type),
284                       RECV_ATTR_STR(TLS_ATTR_CHAIN_FILES, chain_files),
285                       RECV_ATTR_STR(TLS_ATTR_CERT_FILE, cert_file),
286                       RECV_ATTR_STR(TLS_ATTR_KEY_FILE, key_file),
287                       RECV_ATTR_STR(TLS_ATTR_DCERT_FILE, dcert_file),
288                       RECV_ATTR_STR(TLS_ATTR_DKEY_FILE, dkey_file),
289                       RECV_ATTR_STR(TLS_ATTR_ECCERT_FILE, eccert_file),
290                       RECV_ATTR_STR(TLS_ATTR_ECKEY_FILE, eckey_file),
291                       RECV_ATTR_STR(TLS_ATTR_CAFILE, CAfile),
292                       RECV_ATTR_STR(TLS_ATTR_CAPATH, CApath),
293                       RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg),
294                       ATTR_TYPE_END);
295     /* Always construct a well-formed structure. */
296     props->log_param = vstring_export(log_param);
297     props->log_level = vstring_export(log_level);
298     props->cache_type = vstring_export(cache_type);
299     props->chain_files = vstring_export(chain_files);
300     props->cert_file = vstring_export(cert_file);
301     props->key_file = vstring_export(key_file);
302     props->dcert_file = vstring_export(dcert_file);
303     props->dkey_file = vstring_export(dkey_file);
304     props->eccert_file = vstring_export(eccert_file);
305     props->eckey_file = vstring_export(eckey_file);
306     props->CAfile = vstring_export(CAfile);
307     props->CApath = vstring_export(CApath);
308     props->mdalg = vstring_export(mdalg);
309     ret = (ret == 14 ? 1 : -1);
310     if (ret != 1) {
311           tls_proxy_client_init_free(props);
312           props = 0;
313     }
314     *(TLS_CLIENT_INIT_PROPS **) ptr = props;
315     if (msg_verbose)
316           msg_info("tls_proxy_client_init_scan ret=%d", ret);
317     return (ret);
318 }
319 
320 /* tls_proxy_client_start_free - destroy TLS_CLIENT_START_PROPS structure */
321 
tls_proxy_client_start_free(TLS_CLIENT_START_PROPS * props)322 void    tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props)
323 {
324     myfree((void *) props->nexthop);
325     myfree((void *) props->host);
326     myfree((void *) props->namaddr);
327     myfree((void *) props->sni);
328     myfree((void *) props->serverid);
329     myfree((void *) props->helo);
330     myfree((void *) props->protocols);
331     myfree((void *) props->cipher_grade);
332     myfree((void *) props->cipher_exclusions);
333     if (props->matchargv)
334           argv_free((ARGV *) props->matchargv);
335     myfree((void *) props->mdalg);
336     if (props->dane)
337           tls_dane_free((TLS_DANE *) props->dane);
338 #ifdef USE_TLSRPT
339     if (props->tlsrpt)
340           trw_free(props->tlsrpt);
341 #endif
342     if (props->ffail_type)
343           myfree(props->ffail_type);
344     myfree((void *) props);
345 }
346 
347 /* tls_proxy_client_tlsa_scan - receive TLS_TLSA from stream */
348 
tls_proxy_client_tlsa_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)349 static int tls_proxy_client_tlsa_scan(ATTR_SCAN_COMMON_FN scan_fn,
350                                                   VSTREAM *fp, int flags, void *ptr)
351 {
352     static VSTRING *data;
353     TLS_TLSA *head;
354     int     count;
355     int     ret;
356 
357     if (data == 0)
358           data = vstring_alloc(64);
359 
360     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
361                       RECV_ATTR_INT(TLS_ATTR_COUNT, &count),
362                       ATTR_TYPE_END);
363     if (ret == 1 && msg_verbose)
364           msg_info("tls_proxy_client_tlsa_scan count=%d", count);
365 
366     for (head = 0; ret == 1 && count > 0; --count) {
367           int     u, s, m;
368 
369           ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
370                           RECV_ATTR_INT(TLS_ATTR_USAGE, &u),
371                           RECV_ATTR_INT(TLS_ATTR_SELECTOR, &s),
372                           RECV_ATTR_INT(TLS_ATTR_MTYPE, &m),
373                           RECV_ATTR_DATA(TLS_ATTR_DATA, data),
374                           ATTR_TYPE_END);
375           if (ret == 4) {
376               ret = 1;
377               /* This makes a copy of the static vstring content */
378               head = tlsa_prepend(head, u, s, m, (unsigned char *) STR(data),
379                                         LEN(data));
380           } else
381               ret = -1;
382     }
383 
384     if (ret != 1) {
385           tls_tlsa_free(head);
386           head = 0;
387     }
388     *(TLS_TLSA **) ptr = head;
389     if (msg_verbose)
390           msg_info("tls_proxy_client_tlsa_scan ret=%d", ret);
391     return (ret);
392 }
393 
394 /* tls_proxy_client_dane_scan - receive TLS_DANE from stream */
395 
tls_proxy_client_dane_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)396 static int tls_proxy_client_dane_scan(ATTR_SCAN_COMMON_FN scan_fn,
397                                                   VSTREAM *fp, int flags, void *ptr)
398 {
399     TLS_DANE *dane = 0;
400     int     ret;
401     int     have_dane = 0;
402 
403     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
404                       RECV_ATTR_INT(TLS_ATTR_DANE, &have_dane),
405                       ATTR_TYPE_END);
406     if (msg_verbose)
407           msg_info("tls_proxy_client_dane_scan have_dane=%d", have_dane);
408 
409     if (ret == 1 && have_dane) {
410           VSTRING *base_domain = vstring_alloc(25);
411 
412           dane = tls_dane_alloc();
413           /* We only need the base domain and TLSA RRs */
414           ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
415                           RECV_ATTR_STR(TLS_ATTR_DOMAIN, base_domain),
416                           RECV_ATTR_FUNC(tls_proxy_client_tlsa_scan,
417                                              &dane->tlsa),
418                           ATTR_TYPE_END);
419 
420           /* Always construct a well-formed structure. */
421           dane->base_domain = vstring_export(base_domain);
422           ret = (ret == 2 ? 1 : -1);
423           if (ret != 1) {
424               tls_dane_free(dane);
425               dane = 0;
426           }
427     }
428     *(TLS_DANE **) ptr = dane;
429     if (msg_verbose)
430           msg_info("tls_proxy_client_dane_scan ret=%d", ret);
431     return (ret);
432 }
433 
434 #define EXPORT_OR_NULL(str, vstr) do { \
435           if (LEN(vstr) > 0) { \
436               (str) = vstring_export(vstr); \
437           } else { \
438               (str) = 0; \
439               vstring_free(vstr); \
440           } \
441     } while (0)
442 
443 #ifdef USE_TLSRPT
444 
445 /* tls_proxy_client_tlsrpt_scan - receive TLSRPT_WRAPPER from stream */
446 
tls_proxy_client_tlsrpt_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)447 static int tls_proxy_client_tlsrpt_scan(ATTR_SCAN_COMMON_FN scan_fn,
448                                                   VSTREAM *fp, int flags, void *ptr)
449 {
450     TLSRPT_WRAPPER *trw = 0;
451     int     ret;
452     int     have_tlsrpt = 0;
453 
454     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
455                       RECV_ATTR_INT(TLS_ATTR_TLSRPT, &have_tlsrpt),
456                       ATTR_TYPE_END);
457     if (msg_verbose)
458           msg_info("tls_proxy_client_tlsrpt_scan have_tlsrpt=%d", have_tlsrpt);
459 
460     if (ret == 1 && have_tlsrpt) {
461           VSTRING *rpt_socket_name = vstring_alloc(100);
462           VSTRING *rpt_policy_domain = vstring_alloc(100);
463           VSTRING *rpt_policy_string = vstring_alloc(100);
464           int     tls_policy_type;
465           ARGV   *tls_policy_strings = 0;
466           VSTRING *tls_policy_domain = vstring_alloc(100);
467           ARGV   *mx_host_patterns = 0;
468           VSTRING *snd_mta_addr = vstring_alloc(100);
469           VSTRING *rcv_mta_name = vstring_alloc(100);
470           VSTRING *rcv_mta_addr = vstring_alloc(100);
471           VSTRING *rcv_mta_ehlo = vstring_alloc(100);
472           int     skip_reused_hs;
473           int     trw_flags;
474 
475           ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
476                           RECV_ATTR_STR(TRW_RPT_SOCKET_NAME, rpt_socket_name),
477                         RECV_ATTR_STR(TRW_RPT_POLICY_DOMAIN, rpt_policy_domain),
478                         RECV_ATTR_STR(TRW_RPT_POLICY_STRING, rpt_policy_string),
479                           RECV_ATTR_INT(TRW_TLS_POLICY_TYPE, &tls_policy_type),
480                           RECV_ATTR_FUNC(argv_attr_scan, &tls_policy_strings),
481                         RECV_ATTR_STR(TRW_TLS_POLICY_DOMAIN, tls_policy_domain),
482                           RECV_ATTR_FUNC(argv_attr_scan, &mx_host_patterns),
483                           RECV_ATTR_STR(TRW_SRC_MTA_ADDR, snd_mta_addr),
484                           RECV_ATTR_STR(TRW_DST_MTA_NAME, rcv_mta_name),
485                           RECV_ATTR_STR(TRW_DST_MTA_ADDR, rcv_mta_addr),
486                           RECV_ATTR_STR(TRW_DST_MTA_EHLO, rcv_mta_ehlo),
487                           RECV_ATTR_INT(TRW_SKIP_REUSED_HS, &skip_reused_hs),
488                           RECV_ATTR_INT(TRW_FLAGS, &trw_flags),
489                           ATTR_TYPE_END);
490 
491           /* Always construct a well-formed structure. */
492           trw = (TLSRPT_WRAPPER *) mymalloc(sizeof(*trw));
493           trw->rpt_socket_name = vstring_export(rpt_socket_name);
494           trw->rpt_policy_domain = vstring_export(rpt_policy_domain);
495           trw->rpt_policy_string = vstring_export(rpt_policy_string);
496           trw->tls_policy_type = tls_policy_type;
497           trw->tls_policy_strings = tls_policy_strings;
498           EXPORT_OR_NULL(trw->tls_policy_domain, tls_policy_domain);
499           trw->mx_host_patterns = mx_host_patterns;
500           EXPORT_OR_NULL(trw->snd_mta_addr, snd_mta_addr);
501           EXPORT_OR_NULL(trw->rcv_mta_name, rcv_mta_name);
502           EXPORT_OR_NULL(trw->rcv_mta_addr, rcv_mta_addr);
503           EXPORT_OR_NULL(trw->rcv_mta_ehlo, rcv_mta_ehlo);
504           trw->skip_reused_hs = skip_reused_hs;
505           trw->flags = trw_flags;
506           ret = (ret == 13 ? 1 : -1);
507           if (ret != 1) {
508               trw_free(trw);
509               trw = 0;
510           }
511     }
512     *(TLSRPT_WRAPPER **) ptr = trw;
513     if (msg_verbose)
514           msg_info("tls_proxy_client_tlsrpt_scan ret=%d", ret);
515     return (ret);
516 }
517 
518 #endif
519 
520 /* tls_proxy_client_start_scan - receive TLS_CLIENT_START_PROPS from stream */
521 
tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)522 int     tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
523                                                     int flags, void *ptr)
524 {
525     TLS_CLIENT_START_PROPS *props
526     = (TLS_CLIENT_START_PROPS *) mymalloc(sizeof(*props));
527     int     ret;
528     VSTRING *nexthop = vstring_alloc(25);
529     VSTRING *host = vstring_alloc(25);
530     VSTRING *namaddr = vstring_alloc(25);
531     VSTRING *sni = vstring_alloc(25);
532     VSTRING *serverid = vstring_alloc(25);
533     VSTRING *helo = vstring_alloc(25);
534     VSTRING *protocols = vstring_alloc(25);
535     VSTRING *cipher_grade = vstring_alloc(25);
536     VSTRING *cipher_exclusions = vstring_alloc(25);
537     VSTRING *mdalg = vstring_alloc(25);
538     VSTRING *ffail_type = vstring_alloc(25);
539 
540 #ifdef USE_TLSRPT
541 #define EXPECT_START_SCAN_RETURN        17
542 #else
543 #define EXPECT_START_SCAN_RETURN        16
544 #endif
545 
546     if (msg_verbose)
547           msg_info("begin tls_proxy_client_start_scan");
548 
549     /*
550      * Note: memset() is not a portable way to initialize non-integer types.
551      */
552     memset(props, 0, sizeof(*props));
553     props->ctx = 0;
554     props->stream = 0;
555     props->fd = -1;
556     props->dane = 0;                                        /* scan_fn may return early */
557     ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
558                       RECV_ATTR_INT(TLS_ATTR_TIMEOUT, &props->timeout),
559                       RECV_ATTR_INT(TLS_ATTR_ENABLE_RPK, &props->enable_rpk),
560                       RECV_ATTR_INT(TLS_ATTR_TLS_LEVEL, &props->tls_level),
561                       RECV_ATTR_STR(TLS_ATTR_NEXTHOP, nexthop),
562                       RECV_ATTR_STR(TLS_ATTR_HOST, host),
563                       RECV_ATTR_STR(TLS_ATTR_NAMADDR, namaddr),
564                       RECV_ATTR_STR(TLS_ATTR_SNI, sni),
565                       RECV_ATTR_STR(TLS_ATTR_SERVERID, serverid),
566                       RECV_ATTR_STR(TLS_ATTR_HELO, helo),
567                       RECV_ATTR_STR(TLS_ATTR_PROTOCOLS, protocols),
568                       RECV_ATTR_STR(TLS_ATTR_CIPHER_GRADE, cipher_grade),
569                       RECV_ATTR_STR(TLS_ATTR_CIPHER_EXCLUSIONS,
570                                         cipher_exclusions),
571                       RECV_ATTR_FUNC(argv_attr_scan, &props->matchargv),
572                       RECV_ATTR_STR(TLS_ATTR_MDALG, mdalg),
573                       RECV_ATTR_FUNC(tls_proxy_client_dane_scan,
574                                          &props->dane),
575 #ifdef USE_TLSRPT
576                       RECV_ATTR_FUNC(tls_proxy_client_tlsrpt_scan,
577                                          &props->tlsrpt),
578 #endif
579                       RECV_ATTR_STR(TLS_ATTR_FFAIL_TYPE, ffail_type),
580                       ATTR_TYPE_END);
581     /* Always construct a well-formed structure. */
582     props->nexthop = vstring_export(nexthop);
583     props->host = vstring_export(host);
584     props->namaddr = vstring_export(namaddr);
585     props->sni = vstring_export(sni);
586     props->serverid = vstring_export(serverid);
587     props->helo = vstring_export(helo);
588     props->protocols = vstring_export(protocols);
589     props->cipher_grade = vstring_export(cipher_grade);
590     props->cipher_exclusions = vstring_export(cipher_exclusions);
591     props->mdalg = vstring_export(mdalg);
592     EXPORT_OR_NULL(props->ffail_type, ffail_type);
593     ret = (ret == EXPECT_START_SCAN_RETURN ? 1 : -1);
594     if (ret != 1) {
595           tls_proxy_client_start_free(props);
596           props = 0;
597     }
598     *(TLS_CLIENT_START_PROPS **) ptr = props;
599     if (msg_verbose)
600           msg_info("tls_proxy_client_start_scan ret=%d", ret);
601     return (ret);
602 }
603 
604 #endif
605