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
tls_proxy_client_param_free(TLS_CLIENT_PARAMS * params)124 void 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
tls_proxy_client_param_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)145 int 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
tls_proxy_client_init_free(TLS_CLIENT_INIT_PROPS * props)228 void 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
tls_proxy_client_init_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)248 int 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
tls_proxy_client_start_free(TLS_CLIENT_START_PROPS * props)318 void 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
tls_proxy_client_tlsa_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)339 static 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
tls_proxy_client_dane_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)386 static 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
tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn,VSTREAM * fp,int flags,void * ptr)426 int 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