"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.17/src/conf.c" (27 Sep 2021, 57613 Bytes) of package /linux/privat/msmtp-1.8.17.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "conf.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.8.16_vs_1.8.17.

    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 
   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 
  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 
  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 
  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 
  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 
  343 int is_on(const char *s)
  344 {
  345     return (strcmp(s, "on") == 0);
  346 }
  347 
  348 int is_off(const char *s)
  349 {
  350     return (strcmp(s, "off") == 0);
  351 }
  352 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  977 int is_blank(int c)
  978 {
  979     return (c == ' ' || c == '\t');
  980 }
  981 
  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 
  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. */
 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. */
 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 
 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 
 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 
 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 
 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 }