"Fossies" - the Fresh Open Source Software Archive

Member "msmtp-1.8.5/src/conf.c" (6 Apr 2019, 51345 Bytes) of package /linux/privat/msmtp-1.8.5.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 last Fossies "Diffs" side-by-side code changes report: 1.8.3_vs_1.8.4.

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