1 /*
2 * conf.c
3 *
4 * This file is part of msmtp, an SMTP client.
5 *
6 * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012,
7 * 2014, 2015, 2016, 2018, 2019, 2020, 2021
8 * Martin Lambers <marlam@marlam.de>
9 * Martin Stenberg <martin@gnutiken.se> (passwordeval support)
10 * Scott Shumate <sshumate@austin.rr.com> (aliases support)
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <limits.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #ifdef HAVE_FNMATCH_H
38 # include <fnmatch.h>
39 #endif
40
41 #include "gettext.h"
42 #define _(string) gettext(string)
43
44 #include "list.h"
45 #include "smtp.h"
46 #include "tools.h"
47 #include "net.h"
48 #include "xalloc.h"
49 #include "conf.h"
50
51 /* buffer size for configuration file lines */
52 #define LINEBUFSIZE 501
53
54
55 /*
56 * account_new()
57 *
58 * see conf.h
59 */
60
account_new(const char * conffile,const char * id)61 account_t *account_new(const char *conffile, const char *id)
62 {
63 account_t *a;
64 a = xmalloc(sizeof(account_t));
65 a->id = id ? xstrdup(id) : NULL;
66 a->conffile = conffile ? xstrdup(conffile) : NULL;
67 a->mask = 0LL;
68 a->host = NULL;
69 a->port = 0; /* this must be set later */
70 a->timeout = 0;
71 a->protocol = SMTP_PROTO_SMTP;
72 a->domain = xstrdup("localhost");
73 a->auto_from = 0;
74 a->from = NULL;
75 a->maildomain = NULL;
76 a->dsn_return = NULL;
77 a->dsn_notify = NULL;
78 a->auth_mech = NULL;
79 a->username = NULL;
80 a->password = NULL;
81 a->passwordeval = NULL;
82 a->ntlmdomain = NULL;
83 a->tls = 0;
84 a->tls_nostarttls = 0;
85 a->tls_key_file = NULL;
86 a->tls_cert_file = NULL;
87 a->tls_trust_file = NULL;
88 a->tls_crl_file = NULL;
89 a->tls_sha256_fingerprint = NULL;
90 a->tls_sha1_fingerprint = NULL;
91 a->tls_md5_fingerprint = NULL;
92 a->tls_nocertcheck = 0;
93 a->tls_min_dh_prime_bits = -1;
94 a->tls_priorities = NULL;
95 a->tls_host_override = NULL;
96 a->logfile = NULL;
97 a->logfile_time_format = NULL;
98 a->syslog = NULL;
99 a->aliases = NULL;
100 a->proxy_host = NULL;
101 a->proxy_port = 0;
102 a->set_from_header = 2;
103 a->set_date_header = 2;
104 a->remove_bcc_headers = 1;
105 a->undisclosed_recipients = 0;
106 a->source_ip = NULL;
107 a->socketname = NULL;
108 return a;
109 }
110
111
112 /*
113 * account_copy()
114 *
115 * see conf.h
116 */
117
account_copy(account_t * acc)118 account_t *account_copy(account_t *acc)
119 {
120 account_t *a = NULL;
121
122 if (acc)
123 {
124 a = xmalloc(sizeof(account_t));
125 a->id = acc->id ? xstrdup(acc->id) : NULL;
126 a->conffile = acc->conffile ? xstrdup(acc->conffile) : NULL;
127 a->mask = acc->mask;
128 a->host = acc->host ? xstrdup(acc->host) : NULL;
129 a->port = acc->port;
130 a->timeout = acc->timeout;
131 a->protocol = acc->protocol;
132 a->domain = acc->domain ? xstrdup(acc->domain) : NULL;
133 a->auto_from = acc->auto_from;
134 a->from = acc->from ? xstrdup(acc->from) : NULL;
135 a->maildomain = acc->maildomain ? xstrdup(acc->maildomain) : NULL;
136 a->dsn_return = acc->dsn_return ? xstrdup(acc->dsn_return) : NULL;
137 a->dsn_notify = acc->dsn_notify ? xstrdup(acc->dsn_notify) : NULL;
138 a->auth_mech = acc->auth_mech ? xstrdup(acc->auth_mech) : NULL;
139 a->username = acc->username ? xstrdup(acc->username) : NULL;
140 a->password = acc->password ? xstrdup(acc->password) : NULL;
141 a->passwordeval = acc->passwordeval ? xstrdup(acc->passwordeval) : NULL;
142 a->ntlmdomain = acc->ntlmdomain ? xstrdup(acc->ntlmdomain) : NULL;
143 a->tls = acc->tls;
144 a->tls_nostarttls = acc->tls_nostarttls;
145 a->tls_key_file = acc->tls_key_file ? xstrdup(acc->tls_key_file) : NULL;
146 a->tls_cert_file =
147 acc->tls_cert_file ? xstrdup(acc->tls_cert_file) : NULL;
148 a->tls_trust_file =
149 acc->tls_trust_file ? xstrdup(acc->tls_trust_file) : NULL;
150 a->tls_crl_file =
151 acc->tls_crl_file ? xstrdup(acc->tls_crl_file) : NULL;
152 if (acc->tls_sha256_fingerprint)
153 {
154 a->tls_sha256_fingerprint = xmalloc(32);
155 memcpy(a->tls_sha256_fingerprint, acc->tls_sha256_fingerprint, 32);
156 }
157 else
158 {
159 a->tls_sha256_fingerprint = NULL;
160 }
161 if (acc->tls_sha1_fingerprint)
162 {
163 a->tls_sha1_fingerprint = xmalloc(20);
164 memcpy(a->tls_sha1_fingerprint, acc->tls_sha1_fingerprint, 20);
165 }
166 else
167 {
168 a->tls_sha1_fingerprint = NULL;
169 }
170 if (acc->tls_md5_fingerprint)
171 {
172 a->tls_md5_fingerprint = xmalloc(16);
173 memcpy(a->tls_md5_fingerprint, acc->tls_md5_fingerprint, 16);
174 }
175 else
176 {
177 a->tls_md5_fingerprint = NULL;
178 }
179 a->tls_nocertcheck = acc->tls_nocertcheck;
180 a->tls_min_dh_prime_bits = acc->tls_min_dh_prime_bits;
181 a->tls_priorities =
182 acc->tls_priorities ? xstrdup(acc->tls_priorities) : NULL;
183 a->tls_host_override =
184 acc->tls_host_override ? xstrdup(acc->tls_host_override) : NULL;
185 a->logfile = acc->logfile ? xstrdup(acc->logfile) : NULL;
186 a->logfile_time_format =
187 acc->logfile_time_format ? xstrdup(acc->logfile_time_format) : NULL;
188 a->syslog = acc->syslog ? xstrdup(acc->syslog) : NULL;
189 a->aliases = acc->aliases ? xstrdup(acc->aliases) : NULL;
190 a->proxy_host = acc->proxy_host ? xstrdup(acc->proxy_host) : NULL;
191 a->proxy_port = acc->proxy_port;
192 a->set_from_header = acc->set_from_header;
193 a->set_date_header = acc->set_date_header;
194 a->remove_bcc_headers = acc->remove_bcc_headers;
195 a->undisclosed_recipients = acc->undisclosed_recipients;
196 a->source_ip = acc->source_ip ? xstrdup(acc->source_ip) : NULL;
197 a->socketname = acc->socketname ? xstrdup(acc->socketname) : NULL;
198 }
199 return a;
200 }
201
202
203 /*
204 * account_free()
205 *
206 * see conf.h
207 */
208
account_free(void * a)209 void account_free(void *a)
210 {
211 account_t *p = a;
212 if (p)
213 {
214 free(p->id);
215 free(p->conffile);
216 free(p->host);
217 free(p->domain);
218 free(p->from);
219 free(p->maildomain);
220 free(p->auth_mech);
221 free(p->username);
222 free(p->password);
223 free(p->passwordeval);
224 free(p->ntlmdomain);
225 free(p->tls_key_file);
226 free(p->tls_cert_file);
227 free(p->tls_trust_file);
228 free(p->tls_crl_file);
229 free(p->tls_sha256_fingerprint);
230 free(p->tls_sha1_fingerprint);
231 free(p->tls_md5_fingerprint);
232 free(p->tls_priorities);
233 free(p->tls_host_override);
234 free(p->dsn_return);
235 free(p->dsn_notify);
236 free(p->logfile);
237 free(p->logfile_time_format);
238 free(p->syslog);
239 free(p->aliases);
240 free(p->proxy_host);
241 free(p->source_ip);
242 free(p->socketname);
243 free(p);
244 }
245 }
246
247
248 /*
249 * find_account()
250 *
251 * see conf.h
252 */
253
find_account(list_t * acc_list,const char * id)254 account_t *find_account(list_t *acc_list, const char *id)
255 {
256 account_t *a = NULL;
257 char *acc_id;
258
259 while (!list_is_empty(acc_list))
260 {
261 acc_list = acc_list->next;
262 acc_id = ((account_t *)(acc_list->data))->id;
263 if (acc_id && strcmp(id, acc_id) == 0)
264 {
265 a = acc_list->data;
266 break;
267 }
268 }
269
270 return a;
271 }
272
273
274 /*
275 * find_account_by_envelope_from()
276 *
277 * see conf.h
278 */
279
find_account_by_envelope_from(list_t * acc_list,const char * from)280 account_t *find_account_by_envelope_from(list_t *acc_list, const char *from)
281 {
282 account_t *a = NULL;
283 const char *from_detail = strchr(from, '+');
284 const char *from_domain = strchr(from, '@');
285 const char *acc_from, *acc_domain;
286
287 while (!list_is_empty(acc_list))
288 {
289 acc_list = acc_list->next;
290 acc_from = ((account_t *)(acc_list->data))->from;
291 if (!acc_from)
292 {
293 continue;
294 }
295 if (from_detail && from_domain && !strchr(acc_from, '+'))
296 {
297 /*
298 * Subaddressing matches the pattern /user+detail@domain/. Take `from` to
299 * match `acc_from` iff both user and domain match; i.e., ignore the detail.
300 */
301 acc_domain = strchr(acc_from, '@');
302 if (acc_domain
303 && (acc_domain - acc_from == from_detail - from)
304 && strncasecmp(from, acc_from, from_detail - from) == 0
305 && strcasecmp(from_domain, acc_domain) == 0)
306 {
307 a = acc_list->data;
308 break;
309 }
310 }
311 #ifdef HAVE_FNMATCH_H
312 else if (strchr(acc_from, '?') || strchr(acc_from, '*') || strchr(acc_from, '['))
313 {
314 /* This is a wildcard pattern according to glob(7) */
315 if (fnmatch(acc_from, from, 0) != FNM_NOMATCH)
316 {
317 a = acc_list->data;
318 break;
319 }
320 }
321 #endif
322 else
323 {
324 /* simple matching */
325 if (strcasecmp(from, acc_from) == 0)
326 {
327 a = acc_list->data;
328 break;
329 }
330 }
331 }
332
333 return a;
334 }
335
336
337 /*
338 * is_on(), is_off(), is_auto()
339 *
340 * see conf.h
341 */
342
is_on(const char * s)343 int is_on(const char *s)
344 {
345 return (strcmp(s, "on") == 0);
346 }
347
is_off(const char * s)348 int is_off(const char *s)
349 {
350 return (strcmp(s, "off") == 0);
351 }
352
is_auto(const char * s)353 int is_auto(const char *s)
354 {
355 return (strcmp(s, "auto") == 0);
356 }
357
358
359 /*
360 * get_pos_int()
361 *
362 * see conf.h
363 */
364
get_pos_int(const char * s)365 int get_pos_int(const char *s)
366 {
367 long x;
368 char *p;
369
370 errno = 0;
371 x = strtol(s, &p, 0);
372 if (p == s || x <= 0 || (x == LONG_MAX && errno == ERANGE) || x > INT_MAX)
373 {
374 x = -1;
375 }
376 else if (*p != '\0')
377 {
378 /* trailing garbage */
379 x = -1;
380 }
381
382 return x;
383 }
384
385
386 /*
387 * get_fingerprint()
388 *
389 * see conf.h
390 */
391
get_fingerprint(const char * s,size_t len)392 unsigned char *get_fingerprint(const char *s, size_t len)
393 {
394 unsigned char *fingerprint = xmalloc(len);
395 unsigned char hex[2];
396 size_t i, j;
397 char c;
398
399 if (strlen(s) != 2 * len + (len - 1))
400 {
401 free(fingerprint);
402 return NULL;
403 }
404 for (i = 0; i < len; i++)
405 {
406 for (j = 0; j < 2; j++)
407 {
408 c = toupper((unsigned char)s[3 * i + j]);
409 if (c >= '0' && c <= '9')
410 {
411 hex[j] = c - '0';
412 }
413 else if (c >= 'A' && c <= 'F')
414 {
415 hex[j] = c - 'A' + 10;
416 }
417 else
418 {
419 free(fingerprint);
420 return NULL;
421 }
422 }
423 if (i < len - 1 && s[3 * i + 2] != ':' && s[3 * i + 2] != ' ')
424 {
425 free(fingerprint);
426 return NULL;
427 }
428 fingerprint[i] = (hex[0] << 4) | hex[1];
429 }
430 return fingerprint;
431 }
432
433
434 /*
435 * check_auth_arg()
436 *
437 * see conf.h
438 */
439
check_auth_arg(char * arg)440 int check_auth_arg(char *arg)
441 {
442 size_t l, i;
443
444 if (*arg == '\0')
445 {
446 return 0;
447 }
448 else if (strcmp(arg, "plain") == 0
449 || strcmp(arg, "cram-md5") == 0
450 || strcmp(arg, "digest-md5") == 0
451 || strcmp(arg, "scram-sha-1") == 0
452 || strcmp(arg, "scram-sha-256") == 0
453 || strcmp(arg, "gssapi") == 0
454 || strcmp(arg, "external") == 0
455 || strcmp(arg, "login") == 0
456 || strcmp(arg, "ntlm") == 0
457 || strcmp(arg, "oauthbearer") == 0
458 || strcmp(arg, "xoauth2") == 0)
459 {
460 l = strlen(arg);
461 for (i = 0; i < l; i++)
462 {
463 arg[i] = toupper((unsigned char)arg[i]);
464 }
465 return 0;
466 }
467 else
468 {
469 return 1;
470 }
471 }
472
473
474 /*
475 * check_dsn_notify_arg()
476 *
477 * see conf.h
478 */
479
check_dsn_notify_arg(char * arg)480 int check_dsn_notify_arg(char *arg)
481 {
482 int count;
483 size_t i;
484 size_t l;
485
486 if (strcmp(arg, "never") != 0)
487 {
488 l = 0;
489 count = 0;
490 if (strstr(arg, "failure"))
491 {
492 count++;
493 l += 7;
494 }
495 if (strstr(arg, "delay"))
496 {
497 count++;
498 l += 5;
499 }
500 if (strstr(arg, "success"))
501 {
502 count++;
503 l += 7;
504 }
505 if (count == 0
506 || (strlen(arg) != l + count - 1)
507 || (count == 2 && !strchr(arg, ','))
508 || (count == 3 && !(strchr(arg, ',')
509 && strchr(strchr(arg, ',') + 1, ','))))
510 {
511 return 1;
512 }
513 }
514 l = strlen(arg);
515 for (i = 0; i < l; i++)
516 {
517 arg[i] = toupper((unsigned char)arg[i]);
518 }
519 return 0;
520 }
521
522
523 /*
524 * check_syslog_arg()
525 *
526 * see conf.h
527 */
528
check_syslog_arg(const char * arg)529 int check_syslog_arg(const char *arg)
530 {
531 if (strcmp(arg, "LOG_USER") == 0
532 || strcmp(arg, "LOG_MAIL") == 0
533 || (strncmp(arg, "LOG_LOCAL", 9) == 0
534 && strlen(arg) == 10
535 && (arg[9] == '0'
536 || arg[9] == '1'
537 || arg[9] == '2'
538 || arg[9] == '3'
539 || arg[9] == '4'
540 || arg[9] == '5'
541 || arg[9] == '6'
542 || arg[9] == '7')))
543 {
544 return 0;
545 }
546 else
547 {
548 return 1;
549 }
550 }
551
552
553 /*
554 * get_default_syslog_facility()
555 *
556 * Returns a pointer to an allocated string containing the default syslog
557 * facility.
558 */
559
get_default_syslog_facility(void)560 char *get_default_syslog_facility(void)
561 {
562 return xstrdup("LOG_USER");
563 }
564
565
566 /*
567 * override_account()
568 *
569 * see conf.h
570 */
571
override_account(account_t * acc1,account_t * acc2)572 void override_account(account_t *acc1, account_t *acc2)
573 {
574 if (acc2->conffile)
575 {
576 free(acc1->conffile);
577 acc1->conffile = xstrdup(acc2->conffile);
578 }
579 if (acc2->mask & ACC_HOST)
580 {
581 free(acc1->host);
582 acc1->host = acc2->host ? xstrdup(acc2->host) : NULL;
583 }
584 if (acc2->mask & ACC_PORT)
585 {
586 acc1->port = acc2->port;
587 }
588 if (acc2->mask & ACC_TIMEOUT)
589 {
590 acc1->timeout = acc2->timeout;
591 }
592 if (acc2->mask & ACC_PROTOCOL)
593 {
594 acc1->protocol = acc2->protocol;
595 }
596 if (acc2->mask & ACC_DOMAIN)
597 {
598 free(acc1->domain);
599 acc1->domain = acc2->domain ? xstrdup(acc2->domain) : NULL;
600 }
601 if (acc2->mask & ACC_AUTO_FROM)
602 {
603 acc1->auto_from = acc2->auto_from;
604 }
605 if (acc2->mask & ACC_FROM)
606 {
607 free(acc1->from);
608 acc1->from = acc2->from ? xstrdup(acc2->from) : NULL;
609 }
610 if (acc2->mask & ACC_MAILDOMAIN)
611 {
612 free(acc1->maildomain);
613 acc1->maildomain = acc2->maildomain ? xstrdup(acc2->maildomain) : NULL;
614 }
615 if (acc2->mask & ACC_AUTH_MECH)
616 {
617 free(acc1->auth_mech);
618 acc1->auth_mech = acc2->auth_mech ? xstrdup(acc2->auth_mech) : NULL;
619 }
620 if (acc2->mask & ACC_USERNAME)
621 {
622 free(acc1->username);
623 acc1->username = acc2->username ? xstrdup(acc2->username) : NULL;
624 }
625 if (acc2->mask & ACC_PASSWORD)
626 {
627 free(acc1->password);
628 acc1->password = acc2->password ? xstrdup(acc2->password) : NULL;
629 }
630 if (acc2->mask & ACC_PASSWORDEVAL)
631 {
632 free(acc1->passwordeval);
633 acc1->passwordeval =
634 acc2->passwordeval ? xstrdup(acc2->passwordeval) : NULL;
635 }
636 if (acc2->mask & ACC_NTLMDOMAIN)
637 {
638 free(acc1->ntlmdomain);
639 acc1->ntlmdomain = acc2->ntlmdomain ? xstrdup(acc2->ntlmdomain) : NULL;
640 }
641 if (acc2->mask & ACC_TLS)
642 {
643 acc1->tls = acc2->tls;
644 }
645 if (acc2->mask & ACC_TLS_NOSTARTTLS)
646 {
647 acc1->tls_nostarttls = acc2->tls_nostarttls;
648 }
649 if (acc2->mask & ACC_TLS_KEY_FILE)
650 {
651 free(acc1->tls_key_file);
652 acc1->tls_key_file =
653 acc2->tls_key_file ? xstrdup(acc2->tls_key_file) : NULL;
654 }
655 if (acc2->mask & ACC_TLS_CERT_FILE)
656 {
657 free(acc1->tls_cert_file);
658 acc1->tls_cert_file =
659 acc2->tls_cert_file ? xstrdup(acc2->tls_cert_file) : NULL;
660 }
661 if (acc2->mask & ACC_TLS_TRUST_FILE)
662 {
663 free(acc1->tls_trust_file);
664 acc1->tls_trust_file =
665 acc2->tls_trust_file ? xstrdup(acc2->tls_trust_file) : NULL;
666 }
667 if (acc2->mask & ACC_TLS_CRL_FILE)
668 {
669 free(acc1->tls_crl_file);
670 acc1->tls_crl_file =
671 acc2->tls_crl_file ? xstrdup(acc2->tls_crl_file) : NULL;
672 }
673 if (acc2->mask & ACC_TLS_FINGERPRINT)
674 {
675 free(acc1->tls_sha256_fingerprint);
676 if (acc2->tls_sha256_fingerprint)
677 {
678 acc1->tls_sha256_fingerprint = xmalloc(32);
679 memcpy(acc1->tls_sha256_fingerprint, acc2->tls_sha256_fingerprint, 32);
680 }
681 else
682 {
683 acc1->tls_sha256_fingerprint = NULL;
684 }
685 free(acc1->tls_sha1_fingerprint);
686 if (acc2->tls_sha1_fingerprint)
687 {
688 acc1->tls_sha1_fingerprint = xmalloc(20);
689 memcpy(acc1->tls_sha1_fingerprint, acc2->tls_sha1_fingerprint, 20);
690 }
691 else
692 {
693 acc1->tls_sha1_fingerprint = NULL;
694 }
695 free(acc1->tls_md5_fingerprint);
696 if (acc2->tls_md5_fingerprint)
697 {
698 acc1->tls_md5_fingerprint = xmalloc(16);
699 memcpy(acc1->tls_md5_fingerprint, acc2->tls_md5_fingerprint, 16);
700 }
701 else
702 {
703 acc1->tls_md5_fingerprint = NULL;
704 }
705 }
706 if (acc2->mask & ACC_TLS_NOCERTCHECK)
707 {
708 acc1->tls_nocertcheck = acc2->tls_nocertcheck;
709 }
710 if (acc2->mask & ACC_TLS_MIN_DH_PRIME_BITS)
711 {
712 acc1->tls_min_dh_prime_bits = acc2->tls_min_dh_prime_bits;
713 }
714 if (acc2->mask & ACC_TLS_PRIORITIES)
715 {
716 free(acc1->tls_priorities);
717 acc1->tls_priorities = acc2->tls_priorities
718 ? xstrdup(acc2->tls_priorities) : NULL;
719 }
720 if (acc2->mask & ACC_TLS_HOST_OVERRIDE)
721 {
722 free(acc1->tls_host_override);
723 acc1->tls_host_override = acc2->tls_host_override
724 ? xstrdup(acc2->tls_host_override) : NULL;
725 }
726 if (acc2->mask & ACC_DSN_RETURN)
727 {
728 free(acc1->dsn_return);
729 acc1->dsn_return = acc2->dsn_return ? xstrdup(acc2->dsn_return) : NULL;
730 }
731 if (acc2->mask & ACC_DSN_NOTIFY)
732 {
733 free(acc1->dsn_notify);
734 acc1->dsn_notify = acc2->dsn_notify ? xstrdup(acc2->dsn_notify) : NULL;
735 }
736 if (acc2->mask & ACC_REMOVE_BCC_HEADERS)
737 {
738 acc1->remove_bcc_headers = acc2->remove_bcc_headers;
739 }
740 if (acc2->mask & ACC_UNDISCLOSED_RECIPIENTS)
741 {
742 acc1->undisclosed_recipients = acc2->undisclosed_recipients;
743 }
744 if (acc2->mask & ACC_LOGFILE)
745 {
746 free(acc1->logfile);
747 acc1->logfile = acc2->logfile ? xstrdup(acc2->logfile) : NULL;
748 }
749 if (acc2->mask & ACC_LOGFILE_TIME_FORMAT)
750 {
751 free(acc1->logfile_time_format);
752 acc1->logfile_time_format =
753 acc2->logfile_time_format ? xstrdup(acc2->logfile_time_format) : NULL;
754 }
755 if (acc2->mask & ACC_SYSLOG)
756 {
757 free(acc1->syslog);
758 acc1->syslog = acc2->syslog ? xstrdup(acc2->syslog) : NULL;
759 }
760 if (acc2->mask & ACC_ALIASES)
761 {
762 free(acc1->aliases);
763 acc1->aliases = acc2->aliases ? xstrdup(acc2->aliases) : NULL;
764 }
765 if (acc2->mask & ACC_PROXY_HOST)
766 {
767 free(acc1->proxy_host);
768 acc1->proxy_host = acc2->proxy_host ? xstrdup(acc2->proxy_host) : NULL;
769 }
770 if (acc2->mask & ACC_PROXY_PORT)
771 {
772 acc1->proxy_port = acc2->proxy_port;
773 }
774 if (acc2->mask & ACC_SET_FROM_HEADER)
775 {
776 acc1->set_from_header = acc2->set_from_header;
777 }
778 if (acc2->mask & ACC_SET_DATE_HEADER)
779 {
780 acc1->set_date_header = acc2->set_date_header;
781 }
782 if (acc2->mask & ACC_SOURCE_IP)
783 {
784 free(acc1->source_ip);
785 acc1->source_ip = acc2->source_ip ? xstrdup(acc2->source_ip) : NULL;
786 }
787 if (acc2->mask & ACC_SOCKET)
788 {
789 free(acc1->socketname);
790 acc1->socketname = acc2->socketname ? xstrdup(acc2->socketname) : NULL;
791 }
792 acc1->mask |= acc2->mask;
793 }
794
795
796 /*
797 * check_account()
798 *
799 * see conf.h
800 */
801
check_account(account_t * acc,int sendmail_mode,char ** errstr)802 int check_account(account_t *acc, int sendmail_mode, char **errstr)
803 {
804 if (!acc->host && !acc->socketname)
805 {
806 *errstr = xasprintf(_("host not set"));
807 return CONF_ESYNTAX;
808 }
809 if (acc->port == 0)
810 {
811 *errstr = xasprintf(_("port not set"));
812 return CONF_ESYNTAX;
813 }
814 if (sendmail_mode && !acc->from)
815 {
816 *errstr = xasprintf(_("envelope-from address is missing"));
817 return CONF_ESYNTAX;
818 }
819 if (acc->tls && !(acc->host || acc->tls_host_override))
820 {
821 *errstr = xasprintf(_("host not set"));
822 return CONF_ESYNTAX;
823 }
824 if (acc->tls_key_file && !acc->tls_cert_file)
825 {
826 *errstr = xasprintf(_("tls_key_file requires tls_cert_file"));
827 return CONF_ESYNTAX;
828 }
829 if (!acc->tls_key_file && acc->tls_cert_file)
830 {
831 *errstr = xasprintf(_("tls_cert_file requires tls_key_file"));
832 return CONF_ESYNTAX;
833 }
834 if (acc->tls && !acc->tls_trust_file
835 && !acc->tls_sha256_fingerprint && !acc->tls_sha1_fingerprint
836 && !acc->tls_md5_fingerprint && !acc->tls_nocertcheck)
837 {
838 *errstr = xasprintf(
839 _("tls requires either tls_trust_file (highly recommended) "
840 "or tls_fingerprint or a disabled tls_certcheck"));
841 return CONF_ESYNTAX;
842 }
843 if (acc->tls_crl_file && !acc->tls_trust_file)
844 {
845 *errstr = xasprintf(_("tls_crl_file requires tls_trust_file"));
846 return CONF_ESYNTAX;
847 }
848
849 return CONF_EOK;
850 }
851
852
853 /*
854 * helper function for expand_from() and expand_domain()
855 */
856
expand_from_or_domain(char ** str,int expand_U,char ** errstr)857 static int expand_from_or_domain(char **str, int expand_U, char **errstr)
858 {
859 char* M = NULL;
860 char* U = NULL;
861 char* H = NULL;
862 char* C = NULL;
863
864 if (strstr(*str, "%M"))
865 {
866 char *sysconfdir;
867 char *filename;
868 FILE *f;
869 char buf[256];
870 size_t buflen;
871
872 sysconfdir = get_sysconfdir();
873 filename = get_filename(sysconfdir, "mailname");
874 free(sysconfdir);
875 if (!(f = fopen(filename, "r")))
876 {
877 *errstr = xasprintf(_("%s: %s"), filename, strerror(errno));
878 free(filename);
879 return CONF_ECANTOPEN;
880 }
881 buf[0] = '\0';
882 if (!fgets(buf, sizeof(buf), f) && ferror(f))
883 {
884 *errstr = xasprintf(_("%s: %s"), filename, strerror(errno));
885 free(filename);
886 fclose(f);
887 return CONF_EIO;
888 }
889 fclose(f);
890 buflen = strlen(buf);
891 if (buflen > 0 && buf[buflen - 1] == '\n')
892 {
893 buf[--buflen] = '\0';
894 }
895 if (buflen > 0 && buf[buflen - 1] == '\r')
896 {
897 buf[--buflen] = '\0';
898 }
899 if (buflen == 0)
900 {
901 *errstr = xasprintf(_("%s: %s"), filename, strerror(EINVAL));
902 free(filename);
903 return CONF_EPARSE;
904 }
905 free(filename);
906 M = xstrdup(buf);
907 sanitize_string(M);
908 }
909 if (expand_U && strstr(*str, "%U"))
910 {
911 U = get_username();
912 sanitize_string(U);
913 }
914 if (strstr(*str, "%H") || strstr(*str, "%C"))
915 {
916 H = get_hostname();
917 sanitize_string(H);
918 }
919 if (strstr(*str, "%C"))
920 {
921 C = net_get_canonical_hostname(H);
922 }
923
924 if (M)
925 {
926 *str = string_replace(*str, "%M", M);
927 free(M);
928 }
929 if (U)
930 {
931 *str = string_replace(*str, "%U", U);
932 free(U);
933 }
934 if (H)
935 {
936 *str = string_replace(*str, "%H", H);
937 free(H);
938 }
939 if (C)
940 {
941 *str = string_replace(*str, "%C", C);
942 free(C);
943 }
944
945 return CONF_EOK;
946 }
947
948
949 /*
950 * expand_from()
951 *
952 * see conf.h
953 */
954
expand_from(char ** from,char ** errstr)955 int expand_from(char **from, char **errstr)
956 {
957 return expand_from_or_domain(from, 1, errstr);
958 }
959
960
961 /*
962 * expand_domain()
963 *
964 * see conf.h
965 */
966
expand_domain(char ** domain,char ** errstr)967 int expand_domain(char **domain, char **errstr)
968 {
969 return expand_from_or_domain(domain, 0, errstr);
970 }
971
972
973 /*
974 * some small helper functions
975 */
976
is_blank(int c)977 int is_blank(int c)
978 {
979 return (c == ' ' || c == '\t');
980 }
981
skip_blanks(const char * s,int i)982 int skip_blanks(const char *s, int i)
983 {
984 while (is_blank(s[i]))
985 {
986 i++;
987 }
988 return i;
989 }
990
get_cmd_length(const char * s)991 int get_cmd_length(const char *s)
992 {
993 int i = 0;
994
995 while (s[i] != '\0' && !is_blank(s[i]))
996 {
997 i++;
998 }
999 return i;
1000 }
1001
1002 /* get index of last non-blank character. -1 means there is none. */
get_last_nonblank(const char * s)1003 int get_last_nonblank(const char *s)
1004 {
1005 int i;
1006
1007 i = (int)strlen(s) - 1;
1008 while (i >= 0 && is_blank(s[i]))
1009 {
1010 i--;
1011 }
1012 return i;
1013 }
1014
1015 /* Return string without whitespace at beginning and end. If the string is
1016 * enclosed in double quotes, remove these, too. String is allocated. */
trim_string(const char * s)1017 char *trim_string(const char *s)
1018 {
1019 char *t;
1020 int i;
1021 int l;
1022
1023 i = skip_blanks(s, 0);
1024 l = get_last_nonblank(s + i);
1025 if (l >= 1 && s[i] == '"' && s[i + l] == '"')
1026 {
1027 t = xmalloc(l * sizeof(char));
1028 strncpy(t, s + i + 1, l - 1);
1029 t[l - 1] = '\0';
1030 }
1031 else
1032 {
1033 t = xmalloc((l + 2) * sizeof(char));
1034 strncpy(t, s + i, l + 1);
1035 t[l + 1] = '\0';
1036 }
1037 return t;
1038 }
1039
1040
1041 /*
1042 * get_next_cmd()
1043 *
1044 * Read a line from 'f'. Split it in a command part (first word after
1045 * whitespace) and an argument part (the word after the command).
1046 * Whitespace is ignored.
1047 * Sets the flag 'empty_line' if the line is empty.
1048 * Sets the flag 'eof' if EOF occurred.
1049 * On errors, 'empty_line' and 'eof', 'cmd' and 'arg' NULL.
1050 * On success, 'cmd' and 'arg' are allocated strings.
1051 * Used error codes: CONF_EIO, CONF_EPARSE
1052 */
1053
get_next_cmd(FILE * f,char ** cmd,char ** arg,int * empty_line,int * eof,char ** errstr)1054 int get_next_cmd(FILE *f, char **cmd, char **arg, int *empty_line, int *eof,
1055 char **errstr)
1056 {
1057 char line[LINEBUFSIZE];
1058 char *p;
1059 int i;
1060 int l;
1061
1062 *eof = 0;
1063 *empty_line = 0;
1064 *cmd = NULL;
1065 *arg = NULL;
1066 if (!fgets(line, (int)sizeof(line), f))
1067 {
1068 if (ferror(f))
1069 {
1070 *errstr = xasprintf(_("input error"));
1071 return CONF_EIO;
1072 }
1073 else /* EOF */
1074 {
1075 *eof = 1;
1076 return CONF_EOK;
1077 }
1078 }
1079
1080 /* Kill '\n'. Beware: sometimes the last line of a file has no '\n' */
1081 if ((p = strchr(line, '\n')))
1082 {
1083 *p = '\0';
1084 /* Kill '\r' (if CRLF line endings are used) */
1085 if (p > line && *(p - 1) == '\r')
1086 {
1087 *(p - 1) = '\0';
1088 }
1089 }
1090 else if (strlen(line) == LINEBUFSIZE - 1)
1091 {
1092 *errstr = xasprintf(_("line longer than %d characters"),
1093 LINEBUFSIZE - 1);
1094 return CONF_EPARSE;
1095 }
1096
1097 i = skip_blanks(line, 0);
1098
1099 if (line[i] == '#' || line[i] == '\0')
1100 {
1101 *empty_line = 1;
1102 return CONF_EOK;
1103 }
1104
1105 l = get_cmd_length(line + i);
1106 *cmd = xmalloc((l + 1) * sizeof(char));
1107 strncpy(*cmd, line + i, (size_t)l);
1108 (*cmd)[l] = '\0';
1109
1110 *arg = trim_string(line + i + l);
1111
1112 return CONF_EOK;
1113 }
1114
1115
1116 /*
1117 * read_account_list()
1118 *
1119 * Helper function for the account command: For every account name in the comma
1120 * separated string 's' search the account in 'acc_list' and add a pointer to
1121 * it to 'l'.
1122 */
1123
read_account_list(int line,list_t * acc_list,char * s,list_t * l,char ** errstr)1124 int read_account_list(int line, list_t *acc_list, char *s, list_t *l,
1125 char **errstr)
1126 {
1127 list_t *lp = l;
1128 char *comma;
1129 char *acc_id;
1130 account_t *acc;
1131
1132 for (;;)
1133 {
1134 comma = strchr(s, ',');
1135 if (comma)
1136 {
1137 *comma = '\0';
1138 }
1139 acc_id = trim_string(s);
1140 if (*acc_id == '\0')
1141 {
1142 free(acc_id);
1143 *errstr = xasprintf(_("line %d: missing account name"), line);
1144 return CONF_ESYNTAX;
1145 }
1146 if (!(acc = find_account(acc_list, acc_id)))
1147 {
1148 *errstr = xasprintf(_("line %d: account %s not (yet) defined"),
1149 line, acc_id);
1150 free(acc_id);
1151 return CONF_ESYNTAX;
1152 }
1153 free(acc_id);
1154 list_insert(lp, acc);
1155 lp = lp->next;
1156 if (comma)
1157 {
1158 s = comma + 1;
1159 }
1160 else
1161 {
1162 break;
1163 }
1164 }
1165 return CONF_EOK;
1166 }
1167
1168
1169 /*
1170 * read_conffile()
1171 *
1172 * Read configuration data from 'f' and store it in 'acc_list'.
1173 * The name of the configuration file, 'conffile', will be stored in the
1174 * "conffile" field of each account.
1175 * Unless an error code is returned, 'acc_list' will always be a new list;
1176 * it may be empty if no accounts were found.
1177 * If the file contains secrets (e.g. passwords), then the flag
1178 * 'conffile_contains_secrets' will be set to 1, else to 0.
1179 * Used error codes: CONF_EIO, CONF_EPARSE, CONF_ESYNTAX
1180 */
1181
read_conffile(const char * conffile,FILE * f,list_t ** acc_list,int * conffile_contains_secrets,char ** errstr)1182 int read_conffile(const char *conffile, FILE *f, list_t **acc_list,
1183 int *conffile_contains_secrets, char **errstr)
1184 {
1185 int e;
1186 list_t *p;
1187 account_t *defaults;
1188 account_t *acc;
1189 int line;
1190 char *cmd;
1191 char *arg;
1192 int empty_line;
1193 int eof;
1194 /* for the account command: */
1195 char *acc_id;
1196 char *t;
1197 list_t *copy_from;
1198 list_t *lp;
1199
1200
1201 *conffile_contains_secrets = 0;
1202 defaults = account_new(NULL, NULL);
1203 *acc_list = list_new();
1204 p = *acc_list;
1205 acc = NULL;
1206 e = CONF_EOK;
1207
1208 for (line = 1; ; line++)
1209 {
1210 if ((e = get_next_cmd(f, &cmd, &arg, &empty_line, &eof,
1211 errstr)) != CONF_EOK)
1212 {
1213 break;
1214 }
1215 if (empty_line)
1216 {
1217 continue;
1218 }
1219 if (eof)
1220 {
1221 break;
1222 }
1223
1224 /* compatibility with 1.2.x: if no account command is given, the first
1225 * account will be named "default". */
1226 if (!acc && strcmp(cmd, "account") != 0 && strcmp(cmd, "defaults") != 0)
1227 {
1228 acc = account_copy(defaults);
1229 acc->id = xstrdup("default");
1230 acc->conffile = xstrdup(conffile);
1231 acc->mask = 0LL;
1232 list_insert(p, acc);
1233 p = p->next;
1234 }
1235 if (strcmp(cmd, "defaults") == 0)
1236 {
1237 if (*arg != '\0')
1238 {
1239 *errstr = xasprintf(
1240 _("line %d: command %s does not take an argument"),
1241 line, cmd);
1242 e = CONF_ESYNTAX;
1243 break;
1244 }
1245 acc = defaults;
1246 }
1247 else if (strcmp(cmd, "account") == 0)
1248 {
1249 copy_from = list_new();
1250 if ((t = strchr(arg, ':')))
1251 {
1252 if ((e = read_account_list(line, *acc_list, t + 1, copy_from,
1253 errstr)) != CONF_EOK)
1254 {
1255 list_free(copy_from);
1256 break;
1257 }
1258 *t = '\0';
1259 acc_id = trim_string(arg);
1260 }
1261 else
1262 {
1263 acc_id = xstrdup(arg);
1264 }
1265 if (*acc_id == '\0')
1266 {
1267 list_free(copy_from);
1268 *errstr = xasprintf(_("line %d: missing account name"), line);
1269 e = CONF_ESYNTAX;
1270 free(acc_id);
1271 break;
1272 }
1273 if (strchr(acc_id, ':') || strchr(acc_id, ','))
1274 {
1275 list_free(copy_from);
1276 *errstr = xasprintf(_("line %d: an account name must not "
1277 "contain colons or commas"), line);
1278 e = CONF_ESYNTAX;
1279 free(acc_id);
1280 break;
1281 }
1282 if (find_account(*acc_list, acc_id))
1283 {
1284 list_free(copy_from);
1285 *errstr = xasprintf(
1286 _("line %d: account %s was already defined"),
1287 line, acc_id);
1288 e = CONF_ESYNTAX;
1289 free(acc_id);
1290 break;
1291 }
1292 acc = account_copy(defaults);
1293 acc->id = acc_id;
1294 acc->conffile = xstrdup(conffile);
1295 acc->mask = 0LL;
1296 list_insert(p, acc);
1297 p = p->next;
1298 lp = copy_from;
1299 while (!list_is_empty(lp))
1300 {
1301 lp = lp->next;
1302 override_account(acc, lp->data);
1303 }
1304 list_free(copy_from);
1305 }
1306 else if (strcmp(cmd, "host") == 0)
1307 {
1308 acc->mask |= ACC_HOST;
1309 if (*arg == '\0')
1310 {
1311 *errstr = xasprintf(_("line %d: command %s needs an argument"),
1312 line, cmd);
1313 e = CONF_ESYNTAX;
1314 break;
1315 }
1316 else
1317 {
1318 free(acc->host);
1319 acc->host = xstrdup(arg);
1320 }
1321 }
1322 else if (strcmp(cmd, "port") == 0)
1323 {
1324 acc->mask |= ACC_PORT;
1325 if (*arg == '\0')
1326 {
1327 /* We should go back to the default, which is to call
1328 * get_default_port(), but we cannot since the account is not
1329 * complete yet. So demand an argument here. */
1330 *errstr = xasprintf(_("line %d: command %s needs an argument"),
1331 line, cmd);
1332 e = CONF_ESYNTAX;
1333 break;
1334 }
1335 else
1336 {
1337 acc->port = get_pos_int(arg);
1338 if (acc->port < 1 || acc->port > 65535)
1339 {
1340 *errstr = xasprintf(
1341 _("line %d: invalid argument %s for command %s"),
1342 line, arg, cmd);
1343 e = CONF_ESYNTAX;
1344 break;
1345 }
1346 }
1347 }
1348 else if (strcmp(cmd, "timeout") == 0
1349 || strcmp(cmd, "connect_timeout") == 0)
1350 {
1351 /* For compatibility with versions <= 1.4.1, connect_timeout is
1352 * accepted as an alias for timeout, though it had a slightly
1353 * different meaning. */
1354 acc->mask |= ACC_TIMEOUT;
1355 if (*arg == '\0')
1356 {
1357 *errstr = xasprintf(_("line %d: command %s needs an argument"),
1358 line, cmd);
1359 e = CONF_ESYNTAX;
1360 break;
1361 }
1362 else
1363 {
1364 if (is_off(arg))
1365 {
1366 acc->timeout = 0;
1367 }
1368 else
1369 {
1370 acc->timeout = get_pos_int(arg);
1371 if (acc->timeout < 1)
1372 {
1373 *errstr = xasprintf(_("line %d: invalid argument %s "
1374 "for command %s"), line, arg, cmd);
1375 e = CONF_ESYNTAX;
1376 break;
1377 }
1378 }
1379 }
1380 }
1381 else if (strcmp(cmd, "protocol") == 0)
1382 {
1383 acc->mask |= ACC_PROTOCOL;
1384 if (*arg == '\0')
1385 {
1386 *errstr = xasprintf(_("line %d: command %s needs an argument"),
1387 line, cmd);
1388 e = CONF_ESYNTAX;
1389 break;
1390 }
1391 else
1392 {
1393 if (strcmp(arg, "smtp") == 0)
1394 {
1395 acc->protocol = SMTP_PROTO_SMTP;
1396 }
1397 else if (strcmp(arg, "lmtp") == 0)
1398 {
1399 acc->protocol = SMTP_PROTO_LMTP;
1400 }
1401 else
1402 {
1403 *errstr = xasprintf(
1404 _("line %d: invalid argument %s for command %s"),
1405 line, arg, cmd);
1406 e = CONF_ESYNTAX;
1407 break;
1408 }
1409 }
1410 }
1411 else if (strcmp(cmd, "domain") == 0)
1412 {
1413 acc->mask |= ACC_DOMAIN;
1414 free(acc->domain);
1415 acc->domain = xstrdup(arg);
1416 }
1417 else if (strcmp(cmd, "from") == 0)
1418 {
1419 acc->mask |= ACC_FROM;
1420 free(acc->from);
1421 acc->from = xstrdup(arg);
1422 }
1423 else if (strcmp(cmd, "auth") == 0)
1424 {
1425 acc->mask |= ACC_AUTH_MECH;
1426 free(acc->auth_mech);
1427 if (*arg == '\0' || is_on(arg))
1428 {
1429 acc->auth_mech = xstrdup("");
1430 }
1431 else if (is_off(arg))
1432 {
1433 acc->auth_mech = NULL;
1434 }
1435 else if (check_auth_arg(arg) == 0)
1436 {
1437 acc->auth_mech = xstrdup(arg);
1438 }
1439 else
1440 {
1441 acc->auth_mech = NULL;
1442 *errstr = xasprintf(
1443 _("line %d: invalid argument %s for command %s"),
1444 line, arg, cmd);
1445 e = CONF_ESYNTAX;
1446 break;
1447 }
1448 }
1449 else if (strcmp(cmd, "user") == 0)
1450 {
1451 acc->mask |= ACC_USERNAME;
1452 free(acc->username);
1453 acc->username = (*arg == '\0') ? NULL : xstrdup(arg);
1454 }
1455 else if (strcmp(cmd, "password") == 0)
1456 {
1457 *conffile_contains_secrets = 1;
1458 acc->mask |= ACC_PASSWORD;
1459 free(acc->password);
1460 acc->password = (*arg == '\0') ? NULL : xstrdup(arg);
1461 }
1462 else if (strcmp(cmd, "passwordeval") == 0)
1463 {
1464 acc->mask |= ACC_PASSWORDEVAL;
1465 free(acc->passwordeval);
1466 acc->passwordeval = (*arg == '\0') ? NULL : xstrdup(arg);
1467 }
1468 else if (strcmp(cmd, "ntlmdomain") == 0)
1469 {
1470 acc->mask |= ACC_NTLMDOMAIN;
1471 free(acc->ntlmdomain);
1472 acc->ntlmdomain = (*arg == '\0') ? NULL : xstrdup(arg);
1473 }
1474 else if (strcmp(cmd, "tls") == 0)
1475 {
1476 acc->mask |= ACC_TLS;
1477 if (*arg == '\0' || is_on(arg))
1478 {
1479 acc->tls = 1;
1480 }
1481 else if (is_off(arg))
1482 {
1483 acc->tls = 0;
1484 }
1485 else
1486 {
1487 *errstr = xasprintf(
1488 _("line %d: invalid argument %s for command %s"),
1489 line, arg, cmd);
1490 e = CONF_ESYNTAX;
1491 break;
1492 }
1493 }
1494 else if (strcmp(cmd, "tls_starttls") == 0)
1495 {
1496 acc->mask |= ACC_TLS_NOSTARTTLS;
1497 if (*arg == '\0' || is_on(arg))
1498 {
1499 acc->tls_nostarttls = 0;
1500 }
1501 else if (is_off(arg))
1502 {
1503 acc->tls_nostarttls = 1;
1504 }
1505 else
1506 {
1507 *errstr = xasprintf(
1508 _("line %d: invalid argument %s for command %s"),
1509 line, arg, cmd);
1510 e = CONF_ESYNTAX;
1511 break;
1512 }
1513 }
1514 else if (strcmp(cmd, "tls_key_file") == 0)
1515 {
1516 acc->mask |= ACC_TLS_KEY_FILE;
1517 free(acc->tls_key_file);
1518 if (*arg == '\0')
1519 {
1520 acc->tls_key_file = NULL;
1521 }
1522 else
1523 {
1524 acc->tls_key_file = expand_tilde(arg);
1525 }
1526 }
1527 else if (strcmp(cmd, "tls_cert_file") == 0)
1528 {
1529 acc->mask |= ACC_TLS_CERT_FILE;
1530 free(acc->tls_cert_file);
1531 if (*arg == '\0')
1532 {
1533 acc->tls_cert_file = NULL;
1534 }
1535 else
1536 {
1537 acc->tls_cert_file = expand_tilde(arg);
1538 }
1539 }
1540 else if (strcmp(cmd, "tls_trust_file") == 0)
1541 {
1542 acc->mask |= ACC_TLS_TRUST_FILE;
1543 free(acc->tls_trust_file);
1544 if (*arg == '\0')
1545 {
1546 acc->tls_trust_file = NULL;
1547 }
1548 else
1549 {
1550 acc->tls_trust_file = expand_tilde(arg);
1551 }
1552 }
1553 else if (strcmp(cmd, "tls_crl_file") == 0)
1554 {
1555 acc->mask |= ACC_TLS_CRL_FILE;
1556 free(acc->tls_crl_file);
1557 if (*arg == '\0')
1558 {
1559 acc->tls_crl_file = NULL;
1560 }
1561 else
1562 {
1563 acc->tls_crl_file = expand_tilde(arg);
1564 }
1565 }
1566 else if (strcmp(cmd, "tls_fingerprint") == 0)
1567 {
1568 acc->mask |= ACC_TLS_FINGERPRINT;
1569 free(acc->tls_sha256_fingerprint);
1570 acc->tls_sha256_fingerprint = NULL;
1571 free(acc->tls_sha1_fingerprint);
1572 acc->tls_sha1_fingerprint = NULL;
1573 free(acc->tls_md5_fingerprint);
1574 acc->tls_md5_fingerprint = NULL;
1575 if (*arg != '\0')
1576 {
1577 if (strlen(arg) == 2 * 32 + 31)
1578 {
1579 acc->tls_sha256_fingerprint = get_fingerprint(arg, 32);
1580 }
1581 else if (strlen(arg) == 2 * 20 + 19)
1582 {
1583 acc->tls_sha1_fingerprint = get_fingerprint(arg, 20);
1584 }
1585 else if (strlen(arg) == 2 * 16 + 15)
1586 {
1587 acc->tls_md5_fingerprint = get_fingerprint(arg, 16);
1588 }
1589 if (!acc->tls_sha256_fingerprint && !acc->tls_sha1_fingerprint
1590 && !acc->tls_md5_fingerprint)
1591 {
1592 *errstr = xasprintf(
1593 _("line %d: invalid argument %s for command %s"),
1594 line, arg, cmd);
1595 e = CONF_ESYNTAX;
1596 break;
1597 }
1598 }
1599 }
1600 else if (strcmp(cmd, "tls_certcheck") == 0)
1601 {
1602 acc->mask |= ACC_TLS_NOCERTCHECK;
1603 if (*arg == '\0' || is_on(arg))
1604 {
1605 acc->tls_nocertcheck = 0;
1606 }
1607 else if (is_off(arg))
1608 {
1609 acc->tls_nocertcheck = 1;
1610 }
1611 else
1612 {
1613 *errstr = xasprintf(
1614 _("line %d: invalid argument %s for command %s"),
1615 line, arg, cmd);
1616 e = CONF_ESYNTAX;
1617 break;
1618 }
1619 }
1620 else if (strcmp(cmd, "tls_min_dh_prime_bits") == 0)
1621 {
1622 acc->mask |= ACC_TLS_MIN_DH_PRIME_BITS;
1623 if (*arg == '\0')
1624 {
1625 acc->tls_min_dh_prime_bits = -1;
1626 }
1627 else
1628 {
1629 acc->tls_min_dh_prime_bits = get_pos_int(arg);
1630 if (acc->tls_min_dh_prime_bits < 1)
1631 {
1632 *errstr = xasprintf(
1633 _("line %d: invalid argument %s for command %s"),
1634 line, arg, cmd);
1635 e = CONF_ESYNTAX;
1636 break;
1637 }
1638 }
1639 }
1640 else if (strcmp(cmd, "tls_priorities") == 0)
1641 {
1642 acc->mask |= ACC_TLS_PRIORITIES;
1643 free(acc->tls_priorities);
1644 if (*arg == '\0')
1645 {
1646 acc->tls_priorities = NULL;
1647 }
1648 else
1649 {
1650 acc->tls_priorities = xstrdup(arg);
1651 }
1652 }
1653 else if (strcmp(cmd, "tls_host_override") == 0)
1654 {
1655 acc->mask |= ACC_TLS_HOST_OVERRIDE;
1656 free(acc->tls_host_override);
1657 if (*arg == '\0')
1658 {
1659 acc->tls_host_override = NULL;
1660 }
1661 else
1662 {
1663 acc->tls_host_override = xstrdup(arg);
1664 }
1665 }
1666 else if (strcmp(cmd, "dsn_return") == 0)
1667 {
1668 acc->mask |= ACC_DSN_RETURN;
1669 free(acc->dsn_return);
1670 if (*arg == '\0')
1671 {
1672 *errstr = xasprintf(_("line %d: command %s needs an argument"),
1673 line, cmd);
1674 e = CONF_ESYNTAX;
1675 break;
1676 }
1677 else
1678 {
1679 if (is_off(arg))
1680 {
1681 acc->dsn_return = NULL;
1682 }
1683 else if (strcmp(arg, "headers") == 0)
1684 {
1685 acc->dsn_return = xstrdup("HDRS");
1686 }
1687 else if (strcmp(arg, "full") == 0)
1688 {
1689 acc->dsn_return = xstrdup("FULL");
1690 }
1691 else
1692 {
1693 *errstr = xasprintf(
1694 _("line %d: invalid argument %s for command %s"),
1695 line, arg, cmd);
1696 e = CONF_ESYNTAX;
1697 break;
1698 }
1699 }
1700 }
1701 else if (strcmp(cmd, "dsn_notify") == 0)
1702 {
1703 acc->mask |= ACC_DSN_NOTIFY;
1704 free(acc->dsn_notify);
1705 if (*arg == '\0')
1706 {
1707 *errstr = xasprintf(_("line %d: command %s needs an argument"),
1708 line, cmd);
1709 e = CONF_ESYNTAX;
1710 break;
1711 }
1712 else
1713 {
1714 if (is_off(arg))
1715 {
1716 acc->dsn_notify = NULL;
1717 }
1718 else if (check_dsn_notify_arg(arg) == 0)
1719 {
1720 acc->dsn_notify = xstrdup(arg);
1721 }
1722 else
1723 {
1724 *errstr = xasprintf(
1725 _("line %d: invalid argument %s for command %s"),
1726 line, arg, cmd);
1727 e = CONF_ESYNTAX;
1728 break;
1729 }
1730 }
1731 }
1732 else if (strcmp(cmd, "logfile") == 0)
1733 {
1734 acc->mask |= ACC_LOGFILE;
1735 free(acc->logfile);
1736 if (*arg == '\0')
1737 {
1738 acc->logfile = NULL;
1739 }
1740 else
1741 {
1742 acc->logfile = expand_tilde(arg);
1743 }
1744 }
1745 else if (strcmp(cmd, "logfile_time_format") == 0)
1746 {
1747 acc->mask |= ACC_LOGFILE_TIME_FORMAT;
1748 free(acc->logfile_time_format);
1749 if (*arg == '\0')
1750 {
1751 acc->logfile_time_format = NULL;
1752 }
1753 else
1754 {
1755 acc->logfile_time_format = xstrdup(arg);
1756 }
1757 }
1758 else if (strcmp(cmd, "syslog") == 0)
1759 {
1760 acc->mask |= ACC_SYSLOG;
1761 free(acc->syslog);
1762 if (*arg == '\0' || is_on(arg))
1763 {
1764 acc->syslog = get_default_syslog_facility();
1765 }
1766 else if (is_off(arg))
1767 {
1768 acc->syslog = NULL;
1769 }
1770 else
1771 {
1772 if (check_syslog_arg(arg) != 0)
1773 {
1774 *errstr = xasprintf(
1775 _("line %d: invalid argument %s for command %s"),
1776 line, arg, cmd);
1777 e = CONF_ESYNTAX;
1778 break;
1779 }
1780 acc->syslog = xstrdup(arg);
1781 }
1782 }
1783 else if (strcmp(cmd, "aliases") == 0)
1784 {
1785 acc->mask |= ACC_ALIASES;
1786 free(acc->aliases);
1787 if (*arg == '\0')
1788 {
1789 acc->aliases = NULL;
1790 }
1791 else
1792 {
1793 acc->aliases = expand_tilde(arg);
1794 }
1795 }
1796 else if (strcmp(cmd, "proxy_host") == 0)
1797 {
1798 acc->mask |= ACC_PROXY_HOST;
1799 free(acc->proxy_host);
1800 if (*arg == '\0')
1801 {
1802 acc->proxy_host = NULL;
1803 }
1804 else
1805 {
1806 acc->proxy_host = xstrdup(arg);
1807 }
1808 }
1809 else if (strcmp(cmd, "proxy_port") == 0)
1810 {
1811 acc->mask |= ACC_PROXY_PORT;
1812 if (*arg == '\0')
1813 {
1814 acc->proxy_port = 0;
1815 }
1816 else
1817 {
1818 acc->proxy_port = get_pos_int(arg);
1819 if (acc->proxy_port < 1 || acc->proxy_port > 65535)
1820 {
1821 *errstr = xasprintf(
1822 _("line %d: invalid argument %s for command %s"),
1823 line, arg, cmd);
1824 e = CONF_ESYNTAX;
1825 break;
1826 }
1827 }
1828 }
1829 else if (strcmp(cmd, "set_from_header") == 0)
1830 {
1831 acc->mask |= ACC_SET_FROM_HEADER;
1832 if (*arg == '\0' || is_auto(arg))
1833 {
1834 acc->set_from_header = 2;
1835 }
1836 else if (is_on(arg))
1837 {
1838 acc->set_from_header = 1;
1839 }
1840 else if (is_off(arg))
1841 {
1842 acc->set_from_header = 0;
1843 }
1844 else
1845 {
1846 *errstr = xasprintf(
1847 _("line %d: invalid argument %s for command %s"),
1848 line, arg, cmd);
1849 e = CONF_ESYNTAX;
1850 break;
1851 }
1852 }
1853 else if (strcmp(cmd, "set_date_header") == 0)
1854 {
1855 acc->mask |= ACC_SET_DATE_HEADER;
1856 if (*arg == '\0' || is_auto(arg))
1857 {
1858 acc->set_date_header = 2;
1859 }
1860 else if (is_off(arg))
1861 {
1862 acc->set_date_header = 0;
1863 }
1864 else
1865 {
1866 *errstr = xasprintf(
1867 _("line %d: invalid argument %s for command %s"),
1868 line, arg, cmd);
1869 e = CONF_ESYNTAX;
1870 break;
1871 }
1872 }
1873 else if (strcmp(cmd, "remove_bcc_headers") == 0)
1874 {
1875 acc->mask |= ACC_REMOVE_BCC_HEADERS;
1876 if (*arg == '\0' || is_on(arg))
1877 {
1878 acc->remove_bcc_headers = 1;
1879 }
1880 else if (is_off(arg))
1881 {
1882 acc->remove_bcc_headers = 0;
1883 }
1884 else
1885 {
1886 *errstr = xasprintf(
1887 _("line %d: invalid argument %s for command %s"),
1888 line, arg, cmd);
1889 e = CONF_ESYNTAX;
1890 break;
1891 }
1892 }
1893 else if (strcmp(cmd, "undisclosed_recipients") == 0)
1894 {
1895 acc->mask |= ACC_UNDISCLOSED_RECIPIENTS;
1896 if (*arg == '\0' || is_on(arg))
1897 {
1898 acc->undisclosed_recipients = 1;
1899 }
1900 else if (is_off(arg))
1901 {
1902 acc->undisclosed_recipients = 0;
1903 }
1904 else
1905 {
1906 *errstr = xasprintf(
1907 _("line %d: invalid argument %s for command %s"),
1908 line, arg, cmd);
1909 e = CONF_ESYNTAX;
1910 break;
1911 }
1912 }
1913 else if (strcmp(cmd, "source_ip") == 0)
1914 {
1915 acc->mask |= ACC_SOURCE_IP;
1916 free(acc->source_ip);
1917 if (*arg == '\0')
1918 {
1919 acc->source_ip = NULL;
1920 }
1921 else
1922 {
1923 acc->source_ip = xstrdup(arg);
1924 }
1925 }
1926 else if (strcmp(cmd, "socket") == 0)
1927 {
1928 acc->mask |= ACC_SOCKET;
1929 free(acc->socketname);
1930 if (*arg == '\0')
1931 {
1932 acc->socketname = NULL;
1933 }
1934 else
1935 {
1936 acc->socketname = xstrdup(arg);
1937 }
1938 }
1939 else if (strcmp(cmd, "add_missing_from_header") == 0)
1940 {
1941 /* compatibility with < 1.8.8 */
1942 acc->mask |= ACC_SET_FROM_HEADER;
1943 if (*arg == '\0' || is_on(arg))
1944 {
1945 acc->set_from_header = 2;
1946 }
1947 else if (is_off(arg))
1948 {
1949 acc->set_from_header = 0;
1950 }
1951 else
1952 {
1953 *errstr = xasprintf(
1954 _("line %d: invalid argument %s for command %s"),
1955 line, arg, cmd);
1956 e = CONF_ESYNTAX;
1957 break;
1958 }
1959 }
1960 else if (strcmp(cmd, "add_missing_date_header") == 0)
1961 {
1962 /* compatibility with < 1.8.8 */
1963 acc->mask |= ACC_SET_DATE_HEADER;
1964 if (*arg == '\0' || is_on(arg))
1965 {
1966 acc->set_date_header = 2;
1967 }
1968 else if (is_off(arg))
1969 {
1970 acc->set_date_header = 0;
1971 }
1972 else
1973 {
1974 *errstr = xasprintf(
1975 _("line %d: invalid argument %s for command %s"),
1976 line, arg, cmd);
1977 e = CONF_ESYNTAX;
1978 break;
1979 }
1980 }
1981 else if (strcmp(cmd, "auto_from") == 0)
1982 {
1983 /* compatibility with <= 1.8.7 */
1984 acc->mask |= ACC_AUTO_FROM;
1985 if (*arg == '\0' || is_on(arg))
1986 {
1987 acc->auto_from = 1;
1988 }
1989 else if (is_off(arg))
1990 {
1991 acc->auto_from = 0;
1992 }
1993 else
1994 {
1995 *errstr = xasprintf(
1996 _("line %d: invalid argument %s for command %s"),
1997 line, arg, cmd);
1998 e = CONF_ESYNTAX;
1999 break;
2000 }
2001 }
2002 else if (strcmp(cmd, "maildomain") == 0)
2003 {
2004 /* compatibility with <= 1.8.7 */
2005 acc->mask |= ACC_MAILDOMAIN;
2006 free(acc->maildomain);
2007 acc->maildomain = xstrdup(arg);
2008 }
2009 else if (strcmp(cmd, "keepbcc") == 0)
2010 {
2011 /* compatibility with 1.4.x */
2012 acc->mask |= ACC_REMOVE_BCC_HEADERS;
2013 if (*arg == '\0' || is_on(arg))
2014 {
2015 acc->remove_bcc_headers = 0;
2016 }
2017 else if (is_off(arg))
2018 {
2019 acc->remove_bcc_headers = 1;
2020 }
2021 else
2022 {
2023 *errstr = xasprintf(
2024 _("line %d: invalid argument %s for command %s"),
2025 line, arg, cmd);
2026 e = CONF_ESYNTAX;
2027 break;
2028 }
2029 }
2030 else if (strcmp(cmd, "tls_nocertcheck") == 0)
2031 {
2032 /* compatibility with 1.2.x */
2033 acc->mask |= ACC_TLS_NOCERTCHECK;
2034 if (*arg != '\0')
2035 {
2036 *errstr = xasprintf(
2037 _("line %d: command %s does not take an argument"),
2038 line, cmd);
2039 e = CONF_ESYNTAX;
2040 break;
2041 }
2042 else
2043 {
2044 acc->tls_nocertcheck = 1;
2045 }
2046 }
2047 else if (strcmp(cmd, "tls_nostarttls") == 0)
2048 {
2049 /* compatibility with 1.2.x */
2050 acc->mask |= ACC_TLS_NOSTARTTLS;
2051 if (*arg != '\0')
2052 {
2053 *errstr = xasprintf(
2054 _("line %d: command %s does not take an argument"),
2055 line, cmd);
2056 e = CONF_ESYNTAX;
2057 break;
2058 }
2059 else
2060 {
2061 acc->tls_nostarttls = 1;
2062 }
2063 }
2064 else if (strcmp(cmd, "tls_force_sslv3") == 0)
2065 {
2066 /* compatibility with versions <= 1.4.32: silently ignore */
2067 }
2068 else
2069 {
2070 *errstr = xasprintf(_("line %d: unknown command %s"), line, cmd);
2071 e = CONF_ESYNTAX;
2072 break;
2073 }
2074 free(cmd);
2075 free(arg);
2076 }
2077 free(cmd);
2078 free(arg);
2079
2080 if (e != CONF_EOK)
2081 {
2082 list_xfree(*acc_list, account_free);
2083 *acc_list = NULL;
2084 }
2085 account_free(defaults);
2086
2087 return e;
2088 }
2089
2090
2091 /*
2092 * get_conf()
2093 *
2094 * see conf.h
2095 */
2096
get_conf(const char * conffile,int securitycheck,list_t ** acc_list,char ** errstr)2097 int get_conf(const char *conffile, int securitycheck, list_t **acc_list,
2098 char **errstr)
2099 {
2100 FILE *f;
2101 int conffile_contains_secrets;
2102 int e;
2103
2104 if (!(f = fopen(conffile, "r")))
2105 {
2106 *errstr = xasprintf("%s", strerror(errno));
2107 return CONF_ECANTOPEN;
2108 }
2109 if ((e = read_conffile(conffile, f, acc_list, &conffile_contains_secrets,
2110 errstr)) != CONF_EOK)
2111 {
2112 fclose(f);
2113 return e;
2114 }
2115 fclose(f);
2116 e = CONF_EOK;
2117 if (securitycheck && conffile_contains_secrets)
2118 {
2119 switch (check_secure(conffile))
2120 {
2121 case 1:
2122 *errstr = xasprintf(_("contains secrets and therefore "
2123 "must be owned by you"));
2124 e = CONF_EINSECURE;
2125 break;
2126
2127 case 2:
2128 *errstr = xasprintf(_("contains secrets and therefore "
2129 "must have no more than user "
2130 "read/write permissions"));
2131 e = CONF_EINSECURE;
2132 break;
2133
2134 case 3:
2135 *errstr = xasprintf("%s", strerror(errno));
2136 e = CONF_EIO;
2137 break;
2138 }
2139 }
2140
2141 return e;
2142 }
2143