"Fossies" - the Fresh Open Source Software Archive

Member "hitch-1.7.2/src/configuration.c" (29 Nov 2021, 47171 Bytes) of package /linux/www/hitch-1.7.2.tar.gz:


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 "configuration.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.7.0_vs_1.7.2.

    1 /**
    2  * configuration.c
    3  *
    4  * Original author: Brane F. Gracnar
    5  */
    6 
    7 #include "config.h"
    8 
    9 #include <sys/types.h>
   10 #include <sys/stat.h>
   11 
   12 #include <stdio.h>
   13 #include <string.h>
   14 #include <strings.h>
   15 #include <errno.h>
   16 #include <fnmatch.h>
   17 #include <stdarg.h>
   18 #include <stdlib.h>
   19 #include <dirent.h>
   20 #include <ctype.h>
   21 #include <unistd.h>
   22 #include <getopt.h>
   23 #include <pwd.h>
   24 #include <grp.h>
   25 #include <syslog.h>
   26 #include <libgen.h>
   27 #include <limits.h>
   28 
   29 #include "configuration.h"
   30 #include "foreign/miniobj.h"
   31 #include "foreign/vas.h"
   32 #include "foreign/vsb.h"
   33 
   34 #include "cfg_parser.h"
   35 
   36 #define ADDR_LEN 150
   37 #define PORT_LEN 6
   38 #define CFG_BOOL_ON "on"
   39 
   40 
   41 // BEGIN: configuration parameters
   42 #define CFG_CIPHERS "ciphers"
   43 #define CFG_SSL_ENGINE "ssl-engine"
   44 #define CFG_PREFER_SERVER_CIPHERS "prefer-server-ciphers"
   45 #define CFG_BACKEND "backend"
   46 #define CFG_FRONTEND "frontend"
   47 #define CFG_WORKERS "workers"
   48 #define CFG_BACKLOG "backlog"
   49 #define CFG_KEEPALIVE "keepalive"
   50 #define CFG_BACKEND_REFRESH "backendrefresh"
   51 #define CFG_CHROOT "chroot"
   52 #define CFG_USER "user"
   53 #define CFG_GROUP "group"
   54 #define CFG_QUIET "quiet"
   55 #define CFG_SYSLOG "syslog"
   56 #define CFG_SYSLOG_FACILITY "syslog-facility"
   57 #define CFG_PARAM_SYSLOG_FACILITY 11015
   58 #define CFG_PARAM_SEND_BUFSIZE 11016
   59 #define CFG_PARAM_RECV_BUFSIZE 11017
   60 #define CFG_DAEMON "daemon"
   61 #define CFG_WRITE_IP "write-ip"
   62 #define CFG_WRITE_PROXY "write-proxy"
   63 #define CFG_WRITE_PROXY_V1 "write-proxy-v1"
   64 #define CFG_WRITE_PROXY_V2 "write-proxy-v2"
   65 #define CFG_PEM_FILE "pem-file"
   66 #define CFG_PROXY_PROXY "proxy-proxy"
   67 #define CFG_ALPN_PROTOS "alpn-protos"
   68 #define CFG_PARAM_ALPN_PROTOS 48173
   69 #define CFG_BACKEND_CONNECT_TIMEOUT "backend-connect-timeout"
   70 #define CFG_SSL_HANDSHAKE_TIMEOUT "ssl-handshake-timeout"
   71 #define CFG_RECV_BUFSIZE "recv-bufsize"
   72 #define CFG_SEND_BUFSIZE "send-bufsize"
   73 #define CFG_LOG_FILENAME "log-filename"
   74 #define CFG_LOG_LEVEL "log-level"
   75 #define CFG_RING_SLOTS "ring-slots"
   76 #define CFG_RING_DATA_LEN "ring-data-len"
   77 #define CFG_PIDFILE "pidfile"
   78 #define CFG_SNI_NOMATCH_ABORT "sni-nomatch-abort"
   79 #define CFG_OCSP_DIR "ocsp-dir"
   80 #define CFG_TLS_PROTOS "tls-protos"
   81 #define CFG_PARAM_TLS_PROTOS 11018
   82 #define CFG_DBG_LISTEN "dbg-listen"
   83 #define CFG_PARAM_DBG_LISTEN 11019
   84 #ifdef TCP_FASTOPEN_WORKS
   85     #define CFG_TFO "enable-tcp-fastopen"
   86 #endif
   87 
   88 #ifdef USE_SHARED_CACHE
   89     #define CFG_SHARED_CACHE "shared-cache"
   90     #define CFG_SHARED_CACHE_LISTEN "shared-cache-listen"
   91     #define CFG_SHARED_CACHE_PEER "shared-cache-peer"
   92     #define CFG_SHARED_CACHE_MCASTIF "shared-cache-if"
   93 #endif
   94 
   95 #define FMT_STR "%s = %s\n"
   96 #define FMT_QSTR "%s = \"%s\"\n"
   97 #define FMT_ISTR "%s = %d\n"
   98 
   99 #define CONFIG_BUF_SIZE 1024
  100 #define CFG_PARAM_CFGFILE 10000
  101 
  102 #define CFG_CONFIG "config"
  103 
  104 #define CFG_DEFAULT_CIPHERS \
  105     "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
  106 
  107 extern FILE *yyin;
  108 extern int yyparse(hitch_config *);
  109 
  110 void cfg_cert_file_free(struct cfg_cert_file **cfptr);
  111 
  112 // END: configuration parameters
  113 
  114 static char error_buf[CONFIG_BUF_SIZE];
  115 static char tmp_buf[150];
  116 
  117 /* declare printf like functions: */
  118 void config_error_set(char *fmt, ...)
  119     __attribute__((format(printf, 1, 2)));
  120 
  121 void
  122 config_error_set(char *fmt, ...)
  123 {
  124     int len;
  125     char buf[CONFIG_BUF_SIZE] = "";
  126 
  127     va_list args;
  128     va_start(args, fmt);
  129     len = vsnprintf(buf, (sizeof(buf) - 1), fmt, args);
  130     va_end(args);
  131 
  132     len += 1;
  133     if (len > CONFIG_BUF_SIZE)
  134         len = CONFIG_BUF_SIZE;
  135     memcpy(error_buf, buf, len);
  136 }
  137 
  138 const char *
  139 config_error_get(void)
  140 {
  141     return (error_buf);
  142 }
  143 
  144 struct front_arg *
  145 front_arg_new(void)
  146 {
  147     struct front_arg *fa;
  148 
  149     ALLOC_OBJ(fa, FRONT_ARG_MAGIC);
  150     AN(fa);
  151     fa->match_global_certs = -1;
  152     fa->sni_nomatch_abort = -1;
  153     fa->selected_protos = 0;
  154     fa->prefer_server_ciphers = -1;
  155     fa->client_verify = -1;
  156 
  157     return (fa);
  158 }
  159 
  160 void
  161 front_arg_destroy(struct front_arg *fa)
  162 {
  163     struct cfg_cert_file *cf, *cftmp;
  164 
  165     CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC);
  166     free(fa->ip);
  167     free(fa->port);
  168     free(fa->pspec);
  169     free(fa->ciphers_tlsv12);
  170     free(fa->ciphersuites_tlsv13);
  171     HASH_ITER(hh, fa->certs, cf, cftmp) {
  172         CHECK_OBJ_NOTNULL(cf, CFG_CERT_FILE_MAGIC);
  173         HASH_DEL(fa->certs, cf);
  174         cfg_cert_file_free(&cf);
  175     }
  176     FREE_OBJ(fa);
  177 }
  178 
  179 hitch_config *
  180 config_new(void)
  181 {
  182     int i;
  183     hitch_config *r;
  184     struct front_arg *fa;
  185 
  186     r = calloc(1, sizeof(hitch_config));
  187     AN(r);
  188 
  189     (void) i;
  190     // set default values
  191 
  192     r->PMODE            = SSL_SERVER;
  193     r->SELECTED_TLS_PROTOS      = 0;
  194     r->WRITE_IP_OCTET       = 0;
  195     r->WRITE_PROXY_LINE_V1      = 0;
  196     r->WRITE_PROXY_LINE_V2      = 0;
  197     r->PROXY_TLV            = 1;
  198     r->PROXY_AUTHORITY      = 1;
  199     r->PROXY_CLIENT_CERT        = 0;
  200     r->PROXY_PROXY_LINE     = 0;
  201     r->ALPN_PROTOS          = NULL;
  202     r->ALPN_PROTOS_LV       = NULL;
  203     r->ALPN_PROTOS_LV_LEN       = 0;
  204     r->CHROOT           = NULL;
  205     r->UID              = -1;
  206     r->GID              = -1;
  207     r->BACK_IP          = strdup("127.0.0.1");
  208     r->BACK_PORT            = strdup("8000");
  209     r->NCORES           = 1;
  210     r->CIPHERS_TLSv12       = strdup(CFG_DEFAULT_CIPHERS);
  211     r->ENGINE           = NULL;
  212     r->BACKLOG          = 100;
  213     r->SNI_NOMATCH_ABORT        = 0;
  214     r->CERT_DEFAULT         = NULL;
  215     r->CERT_FILES           = NULL;
  216     r->LISTEN_ARGS          = NULL;
  217     r->PEM_DIR          = NULL;
  218     r->OCSP_DIR         = strdup("/var/lib/hitch/");
  219     AN(r->OCSP_DIR);
  220     r->OCSP_VFY         = 0;
  221     r->OCSP_RESP_TMO        = 10.0;
  222     r->OCSP_CONN_TMO        = 4.0;
  223     r->OCSP_REFRESH_INTERVAL    = 1800;
  224     r->CLIENT_VERIFY        = SSL_VERIFY_NONE;
  225     r->CLIENT_VERIFY_CA     = NULL;
  226 #ifdef TCP_FASTOPEN_WORKS
  227     r->TFO              = 0;
  228 #endif
  229 
  230 #ifdef USE_SHARED_CACHE
  231     r->SHARED_CACHE         = 0;
  232     r->SHCUPD_IP            = NULL;
  233     r->SHCUPD_PORT          = NULL;
  234 
  235     for (i = 0 ; i < MAX_SHCUPD_PEERS; i++)
  236         memset(&r->SHCUPD_PEERS[i], 0, sizeof(shcupd_peer_opt));
  237 
  238     r->SHCUPD_MCASTIF       = NULL;
  239     r->SHCUPD_MCASTTTL      = NULL;
  240 #endif
  241 
  242     r->LOG_LEVEL            = 1;
  243     r->SYSLOG           = 0;
  244     r->SYSLOG_FACILITY      = LOG_DAEMON;
  245     r->TCP_KEEPALIVE_TIME       = 3600;
  246     r->BACKEND_REFRESH_TIME     = 0;
  247     r->DAEMONIZE            = 0;
  248     r->PREFER_SERVER_CIPHERS    = 0;
  249     r->TEST             = 0;
  250 
  251     r->BACKEND_CONNECT_TIMEOUT  = 30;
  252     r->SSL_HANDSHAKE_TIMEOUT    = 30;
  253 
  254     r->RECV_BUFSIZE         = -1;
  255     r->SEND_BUFSIZE         = -1;
  256 
  257     r->LOG_FILENAME         = NULL;
  258     r->PIDFILE          = NULL;
  259 
  260     r->RING_SLOTS           = 0;
  261     r->RING_DATA_LEN        = 0;
  262 
  263     fa = front_arg_new();
  264     fa->port = strdup("8443");
  265     AN(fa->port);
  266     fa->pspec = strdup("default");
  267     AN(fa->pspec);
  268     HASH_ADD_KEYPTR(hh, r->LISTEN_ARGS, fa->pspec, strlen(fa->pspec), fa);
  269     r->LISTEN_DEFAULT       = fa;
  270 
  271     return (r);
  272 }
  273 
  274 void
  275 config_destroy(hitch_config *cfg)
  276 {
  277     // printf("config_destroy() in pid %d: %p\n", getpid(), cfg);
  278     struct front_arg *fa, *ftmp;
  279     struct cfg_cert_file *cf, *cftmp;
  280     if (cfg == NULL)
  281         return;
  282 
  283     // free all members!
  284     free(cfg->CHROOT);
  285     HASH_ITER(hh, cfg->LISTEN_ARGS, fa, ftmp) {
  286         CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC);
  287         HASH_DEL(cfg->LISTEN_ARGS, fa);
  288         front_arg_destroy(fa);
  289     }
  290     free(cfg->BACK_IP);
  291     free(cfg->BACK_PORT);
  292     HASH_ITER(hh, cfg->CERT_FILES, cf, cftmp) {
  293         CHECK_OBJ_NOTNULL(cf, CFG_CERT_FILE_MAGIC);
  294         HASH_DEL(cfg->CERT_FILES, cf);
  295         cfg_cert_file_free(&cf);
  296     }
  297 
  298     if (cfg->CERT_DEFAULT != NULL)
  299         cfg_cert_file_free(&cfg->CERT_DEFAULT);
  300 
  301     free(cfg->CIPHERS_TLSv12);
  302     free(cfg->CIPHERSUITES_TLSv13);
  303     free(cfg->ENGINE);
  304     free(cfg->PIDFILE);
  305     free(cfg->OCSP_DIR);
  306     free(cfg->ALPN_PROTOS);
  307     free(cfg->ALPN_PROTOS_LV);
  308     free(cfg->PEM_DIR);
  309     free(cfg->PEM_DIR_GLOB);
  310     free(cfg->CLIENT_VERIFY_CA);
  311 #ifdef USE_SHARED_CACHE
  312     int i;
  313     free(cfg->SHCUPD_IP);
  314     free(cfg->SHCUPD_PORT);
  315 
  316     for (i = 0; i < MAX_SHCUPD_PEERS; i++) {
  317         free(cfg->SHCUPD_PEERS[i].ip);
  318         free(cfg->SHCUPD_PEERS[i].port);
  319     }
  320 
  321     free(cfg->SHCUPD_MCASTIF);
  322     free(cfg->SHCUPD_MCASTTTL);
  323 #endif
  324     free(cfg);
  325 }
  326 
  327 static char *
  328 config_assign_str(char **dst, char *v)
  329 {
  330     assert(v != NULL);
  331 
  332     if (strlen(v) <= 0)
  333         return (NULL);
  334     if (*dst != NULL)
  335         free(*dst);
  336 
  337     *dst = strdup(v);
  338     return (*dst);
  339 }
  340 
  341 static int
  342 config_param_val_bool(char *val, int *res)
  343 {
  344     assert(val != NULL);
  345 
  346     if (strcasecmp(val, CFG_BOOL_ON) == 0 || strcasecmp(val, "yes") == 0 ||
  347         strcasecmp(val, "y") == 0 || strcasecmp(val, "true") == 0 ||
  348         strcasecmp(val, "t") == 0 || strcasecmp(val, "1") == 0)
  349         *res = 1;
  350     else if (strcasecmp(val, "off") == 0 || strcasecmp(val, "no") == 0
  351         || strcasecmp(val, "n") == 0 || strcasecmp(val, "false") == 0
  352         || strcasecmp(val, "f") == 0 || strcasecmp(val, "0") == 0)
  353         *res = 0;
  354 
  355     return (1);
  356 }
  357 
  358 static int
  359 config_param_uds(const char *str, char **path)
  360 {
  361     struct stat st;
  362 
  363     AN(path);
  364 
  365     if (strlen(str) > 104) {
  366         config_error_set("UNIX domain socket path too long.");
  367         return (0);
  368     }
  369 
  370     if (stat(str, &st)) {
  371         config_error_set("Unable to stat path '%s': %s", str,
  372             strerror(errno));
  373         return (0);
  374     }
  375 
  376     if (!S_ISSOCK(st.st_mode)) {
  377         config_error_set("Invalid path '%s': Not a socket.", str);
  378         return (0);
  379     }
  380 
  381     *path = strdup(str);
  382     return (1);
  383 }
  384 
  385 static int
  386 config_param_host_port_wildcard(const char *str, char **addr,
  387     char **port, char **cert, int wildcard_okay, char **path)
  388 {
  389     const char *cert_ptr = NULL;
  390     char port_buf[PORT_LEN];
  391     char addr_buf[ADDR_LEN];
  392 
  393     if (str == NULL) {
  394         config_error_set("Invalid/unset host/port string.");
  395         return (0);
  396     }
  397 
  398     /* UDS addresses start with a '/' */
  399     if (path != NULL && *str == '/') {
  400         *addr = NULL;
  401         *port = NULL;
  402         return (config_param_uds(str, path));
  403     }
  404 
  405     if (strlen(str) > ADDR_LEN) {
  406         config_error_set("Host address too long.");
  407         return (0);
  408     }
  409 
  410     memset(port_buf, '\0', sizeof(port_buf));
  411     memset(addr_buf, '\0', sizeof(addr_buf));
  412 
  413     // FORMAT IS: [address]:port
  414     if (*str != '[') {
  415         config_error_set("Invalid address string '%s'", str);
  416         return (0);
  417     }
  418 
  419     const char *ptr = str + 1;
  420     const char *x = strrchr(ptr, ']');
  421     if (x == NULL) {
  422         config_error_set("Invalid address '%s'.", str);
  423         return (0);
  424     }
  425 
  426     unsigned addrlen = x - ptr;
  427     // address
  428     if (addrlen >= sizeof(addr_buf)) {
  429         config_error_set("Invalid address '%s'.", str);
  430         return (0);
  431     }
  432     strncpy(addr_buf, ptr, addrlen);
  433 
  434     // port
  435     if (x[1] != ':' || x[2] == '\0') {
  436         config_error_set("Invalid port specifier in string '%s'.", str);
  437         return (0);
  438     }
  439     ptr = x + 2;
  440     x = strchr(ptr, '+');
  441     if (x == NULL)
  442         memcpy(port_buf, ptr, sizeof(port_buf) - 1);
  443     else
  444         memcpy(port_buf, ptr, (x - ptr));
  445 
  446     // cert
  447     if (cert && x)
  448         cert_ptr = x + 1;
  449 
  450     // printf("PARSED ADDR '%s', PORT '%s'\n", addr_buf, port_buf);
  451 
  452     int p = atoi(port_buf);
  453     if (p < 0 || p > 65536) {
  454         config_error_set("Invalid port number '%s'", port_buf);
  455         return (0);
  456     }
  457 
  458     if (strcmp(addr_buf, "*") == 0) {
  459         if (wildcard_okay) {
  460             free(*addr);
  461             *addr = NULL;
  462         }
  463         else {
  464             config_error_set(
  465                 "Invalid address: wildcards are not allowed.");
  466             return (0);
  467         }
  468     } else {
  469         *addr = strdup(addr_buf);
  470     }
  471     *port = strdup(port_buf);
  472     if (cert_ptr != NULL)
  473         *cert = strdup(cert_ptr);
  474 
  475     /* printf("ADDR FINAL: '%s', '%s', '%s'\n", *addr, *port, */
  476     /*     cert ? *cert : ""); */
  477 
  478     return (1);
  479 }
  480 
  481 static int
  482 config_param_host_port(char *str, char **addr, char **port, char **path)
  483 {
  484     return (config_param_host_port_wildcard(str, addr, port,
  485         NULL, 0, path));
  486 }
  487 
  488 
  489 static int
  490 config_param_val_int(char *str, int *dst, int non_negative)
  491 {
  492     long  lval;
  493     char *ep;
  494 
  495     assert(str != NULL);
  496 
  497     errno = 0;
  498     lval = strtol(str, &ep, 10);
  499 
  500     if (*str == '\0' || *ep != '\0') {
  501         config_error_set("Not a number.");
  502         return (0);
  503     }
  504     if ((errno == ERANGE && (lval == LONG_MIN || lval == LONG_MAX)) ||
  505         lval < INT_MIN || lval > INT_MAX) {
  506         config_error_set("Number out of range.");
  507         return (0);
  508     }
  509     if (non_negative && lval < 0) {
  510         config_error_set("Negative number.");
  511         return (0);
  512     }
  513 
  514     *dst = (int)lval;
  515     return (1);
  516 }
  517 
  518 static int
  519 config_param_val_long(char *str, long *dst, int non_negative)
  520 {
  521     long  lval;
  522     char *ep;
  523 
  524     assert(str != NULL);
  525 
  526     errno = 0;
  527     lval = strtol(str, &ep, 10);
  528 
  529     if (*str == '\0' || *ep != '\0') {
  530         config_error_set("Not a number.");
  531         return (0);
  532     }
  533     if (errno == ERANGE && (lval == LONG_MIN || lval == LONG_MAX)) {
  534         config_error_set("Number out of range.");
  535         return (0);
  536     }
  537     if (non_negative && lval < 0) {
  538         config_error_set("Negative number.");
  539         return (0);
  540     }
  541 
  542     *dst = lval;
  543     return (1);
  544 }
  545 
  546 static double
  547 mtim2double(const struct stat *sb)
  548 {
  549     double d = sb->st_mtime;
  550 
  551 #if defined(HAVE_STRUCT_STAT_ST_MTIM)
  552     d += sb->st_mtim.tv_nsec * 1e-9;
  553 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
  554     d += sb->st_mtimespec.tv_nsec * 1e-9;
  555 #endif
  556     return (d);
  557 }
  558 
  559 struct cfg_cert_file *
  560 cfg_cert_file_new(void)
  561 {
  562     struct cfg_cert_file *cert;
  563     ALLOC_OBJ(cert, CFG_CERT_FILE_MAGIC);
  564     AN(cert);
  565     cert->ocsp_vfy = -1;
  566     return (cert);
  567 }
  568 
  569 void
  570 cfg_cert_file_free(struct cfg_cert_file **cfptr)
  571 {
  572     struct cfg_cert_file *cf;
  573 
  574     CHECK_OBJ_NOTNULL(*cfptr, CFG_CERT_FILE_MAGIC);
  575     cf = *cfptr;
  576     free(cf->filename);
  577     free(cf->ocspfn);
  578     FREE_OBJ(cf);
  579     *cfptr = NULL;
  580 }
  581 
  582 int
  583 cfg_cert_vfy(struct cfg_cert_file *cf)
  584 {
  585     struct stat st;
  586     double d;
  587 
  588     CHECK_OBJ_NOTNULL(cf, CFG_CERT_FILE_MAGIC);
  589     AN(cf->filename);
  590 
  591     if (cf->filename == NULL || strlen(cf->filename) <= 0)
  592         return (0);
  593 
  594     if (stat(cf->filename, &st) != 0) {
  595         config_error_set("Unable to stat x509 "
  596             "certificate PEM file '%s': %s", cf->filename,
  597             strerror(errno));
  598         return (0);
  599     }
  600     if (!S_ISREG(st.st_mode)) {
  601         config_error_set("Invalid x509 certificate "
  602             "PEM file '%s': Not a file.", cf->filename);
  603         return (0);
  604     }
  605     cf->mtim = mtim2double(&st);
  606 
  607     if (cf->ocspfn != NULL) {
  608         if (stat(cf->ocspfn, &st) == -1) {
  609             config_error_set("Unable to stat OCSP "
  610                 "stapling file '%s': %s", cf->ocspfn,
  611                 strerror(errno));
  612             return (0);
  613         }
  614         if (!S_ISREG(st.st_mode)) {
  615             config_error_set("Invalid OCSP stapling file "
  616                 "'%s': Not a file.", cf->ocspfn);
  617             return (0);
  618         }
  619         cf->ocsp_mtim = mtim2double(&st);
  620     }
  621 
  622     if (cf->priv_key_filename != NULL &&
  623         strlen(cf->priv_key_filename) > 0) {
  624 
  625         if (stat(cf->priv_key_filename, &st) != 0) {
  626             config_error_set("Unable to stat private keyfile "
  627                 "'%s': %s", cf->priv_key_filename,
  628                 strerror(errno));
  629             return (0);
  630         }
  631         if (!S_ISREG(st.st_mode)) {
  632             config_error_set("Invalid private keyfile "
  633                 "'%s': Not a file.", cf->priv_key_filename);
  634             return (0);
  635         }
  636 
  637         d = mtim2double(&st);
  638         cf->mtim = cf->mtim > d ? cf->mtim : d;
  639     }
  640     return (1);
  641 }
  642 
  643 void
  644 cfg_cert_add(struct cfg_cert_file *cf, struct cfg_cert_file **dst)
  645 {
  646     CHECK_OBJ_NOTNULL(cf, CFG_CERT_FILE_MAGIC);
  647     AN(dst);
  648     CHECK_OBJ_ORNULL(*dst, CFG_CERT_FILE_MAGIC);
  649     HASH_ADD_KEYPTR(hh, *dst, cf->filename, strlen(cf->filename), cf);
  650 }
  651 
  652 #ifdef USE_SHARED_CACHE
  653 /* Parse mcast and ttl options */
  654 static int
  655 config_param_shcupd_mcastif(char *str, char **iface, char **ttl)
  656 {
  657     char buf[150];
  658     char *sp;
  659 
  660     if (strlen(str) >= sizeof buf) {
  661         config_error_set("Invalid option for IFACE[,TTL]");
  662         return (0);
  663     }
  664 
  665     sp = strchr(str, ',');
  666     if (!sp) {
  667         if (!strcmp(str, "*"))
  668             *iface = NULL;
  669         else
  670             *iface = strdup(str);
  671         *ttl = NULL;
  672         return (1);
  673     }
  674     else if (!strncmp(str, "*", sp - str))
  675         *iface = NULL;
  676     else {
  677         *sp = 0;
  678         *iface = strdup(str);
  679     }
  680     *ttl = strdup(sp + 1);
  681 
  682     return (1);
  683 }
  684 
  685 static int
  686 config_param_shcupd_peer(char *str, hitch_config *cfg)
  687 {
  688     if (cfg == NULL) {
  689         config_error_set("Configuration pointer is NULL.");
  690         return (0);
  691     }
  692 
  693     // parse result
  694     int r = 1;
  695 
  696     // find place for new peer
  697     int offset = 0;
  698     int i = 0;
  699     for (i = 0; i < MAX_SHCUPD_PEERS; i++) {
  700         if (cfg->SHCUPD_PEERS[i].ip == NULL &&
  701             cfg->SHCUPD_PEERS[i].port == NULL) {
  702             offset = i;
  703             break;
  704         }
  705     }
  706     if (i >= MAX_SHCUPD_PEERS) {
  707         config_error_set(
  708             "Reached maximum number of shared cache update peers (%d).",
  709             MAX_SHCUPD_PEERS
  710         );
  711         return (0);
  712     }
  713 
  714     // create place for new peer
  715     char *addr = malloc(ADDR_LEN);
  716     if (addr == NULL) {
  717         config_error_set(
  718             "Unable to allocate memory for new shared cache update peer address: %s",
  719             strerror(errno)
  720         );
  721         r = 0;
  722         goto outta_parse_peer;
  723     }
  724     memset(addr, '\0', ADDR_LEN);
  725     char *port = malloc(PORT_LEN);
  726     if (port == NULL) {
  727         config_error_set(
  728             "Unable to allocate memory for new shared cache update peer port: %s",
  729             strerror(errno)
  730         );
  731         r = 0;
  732         goto outta_parse_peer;
  733     }
  734     memset(port, '\0', PORT_LEN);
  735 
  736     // try to parse address
  737     if (! config_param_host_port(str, &addr, &port, NULL)) {
  738         r = 0;
  739         goto outta_parse_peer;
  740     }
  741 
  742     outta_parse_peer:
  743 
  744     if (! r) {
  745         free(addr);
  746         free(port);
  747     } else {
  748         cfg->SHCUPD_PEERS[offset].ip = addr;
  749         cfg->SHCUPD_PEERS[offset].port = port;
  750     }
  751 
  752     return (r);
  753 }
  754 
  755 #endif /* USE_SHARED_CACHE */
  756 
  757 static int
  758 check_frontend_uniqueness(struct front_arg *cur_fa, hitch_config *cfg)
  759 {
  760     struct front_arg *fa, *fatmp;
  761     int retval = 1;
  762 
  763     HASH_ITER(hh, cfg->LISTEN_ARGS, fa, fatmp) {
  764         if (cur_fa->ip == NULL && fa->ip == NULL &&
  765             strcmp(cur_fa->port, fa->port) == 0) {
  766             retval = 0;
  767             break;
  768         }
  769         else if (cur_fa->ip == NULL || fa->ip == NULL)
  770             continue;
  771         else if (strcmp(cur_fa->ip, fa->ip) == 0 &&
  772              strcmp(cur_fa->port, fa->port) == 0) {
  773             retval = 0;
  774             break;
  775         }
  776     }
  777 
  778     if (retval == 0) {
  779         config_error_set("Redundant frontend "
  780             "(matching IP and port) definition: '%s:%s'.",
  781             fa->ip, fa->port);
  782     }
  783 
  784     return(retval);
  785 }
  786 
  787 int
  788 front_arg_add(hitch_config *cfg, struct front_arg *fa)
  789 {
  790     struct vsb pspec;
  791 
  792     CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC);
  793     if (cfg->LISTEN_DEFAULT != NULL) {
  794         /* drop default listen arg. */
  795         struct front_arg *def = NULL;
  796         HASH_FIND_STR(cfg->LISTEN_ARGS, "default", def);
  797         AN(def);
  798         HASH_DEL(cfg->LISTEN_ARGS, def);
  799         free(def->ip);
  800         free(def->port);
  801         free(def->pspec);
  802         FREE_OBJ(def);
  803         cfg->LISTEN_DEFAULT = NULL;
  804     }
  805 
  806     VSB_new(&pspec, NULL, 0, VSB_AUTOEXTEND);
  807     VSB_printf(&pspec, "[%s]:%s", fa->ip, fa->port);
  808     VSB_finish(&pspec);
  809     fa->pspec = VSB_data(&pspec);
  810 
  811     if (fa->port == NULL) {
  812         config_error_set("No port number specified "
  813             "for frontend '%s'", fa->pspec);
  814         return (0);
  815     }
  816 
  817     if (check_frontend_uniqueness(fa, cfg) == 0)
  818         return (0);
  819 
  820     HASH_ADD_KEYPTR(hh, cfg->LISTEN_ARGS, fa->pspec,
  821         strlen(fa->pspec), fa);
  822 
  823     if (fa->match_global_certs == -1) {
  824         if (HASH_CNT(hh, fa->certs) == 0)
  825             fa->match_global_certs = 1;
  826         else
  827             fa->match_global_certs = 0;
  828     } else {
  829         if (HASH_CNT(hh, fa->certs) == 0
  830             && fa->match_global_certs == 0) {
  831             config_error_set("No certificate configured "
  832                 "for frontend '%s'", fa->pspec);
  833             return (0);
  834         }
  835     }
  836 
  837     return (1);
  838 }
  839 
  840 int
  841 config_param_validate(const char *k, char *v, hitch_config *cfg,
  842     char *file, int line)
  843 {
  844     int r = 1;
  845     struct stat st;
  846 
  847     assert(k != NULL);
  848     assert(v != NULL);
  849     assert(strlen(k) >= 2);
  850 
  851     if (strcmp(k, "tls") == 0) {
  852         cfg->SELECTED_TLS_PROTOS = TLS_OPTION_PROTOS;
  853     } else if (strcmp(k, "ssl") == 0) {
  854         cfg->SELECTED_TLS_PROTOS = SSL_OPTION_PROTOS;
  855     } else if (strcmp(k, CFG_CIPHERS) == 0) {
  856         if (strlen(v) > 0) {
  857             config_assign_str(&cfg->CIPHERS_TLSv12, v);
  858         }
  859     } else if (strcmp(k, CFG_SSL_ENGINE) == 0) {
  860         if (strlen(v) > 0) {
  861             config_assign_str(&cfg->ENGINE, v);
  862         }
  863     } else if (strcmp(k, CFG_PREFER_SERVER_CIPHERS) == 0) {
  864         r = config_param_val_bool(v, &cfg->PREFER_SERVER_CIPHERS);
  865     } else if (strcmp(k, CFG_FRONTEND) == 0) {
  866         struct front_arg *fa;
  867         struct cfg_cert_file *cert;
  868         char *certfile = NULL;
  869 
  870         fa = front_arg_new();
  871         r = config_param_host_port_wildcard(v,
  872             &fa->ip, &fa->port, &certfile, 1, NULL);
  873         if (r != 0) {
  874             if (certfile != NULL) {
  875                 cert = cfg_cert_file_new();
  876                 config_assign_str(&cert->filename, certfile);
  877                 r = cfg_cert_vfy(cert);
  878                 if (r != 0)
  879                     cfg_cert_add(cert, &fa->certs);
  880                 else
  881                     cfg_cert_file_free(&cert);
  882                 free(certfile);
  883             }
  884             if (r != 0)
  885                 r = front_arg_add(cfg, fa);
  886             else
  887                 FREE_OBJ(fa);
  888         }
  889     } else if (strcmp(k, CFG_BACKEND) == 0) {
  890         free(cfg->BACK_PORT);
  891         free(cfg->BACK_IP);
  892         free(cfg->BACK_PATH);
  893         r = config_param_host_port(v, &cfg->BACK_IP, &cfg->BACK_PORT,
  894             &cfg->BACK_PATH);
  895     } else if (strcmp(k, CFG_WORKERS) == 0) {
  896         r = config_param_val_long(v, &cfg->NCORES, 1);
  897     } else if (strcmp(k, CFG_BACKLOG) == 0) {
  898         r = config_param_val_int(v, &cfg->BACKLOG, 0);
  899     } else if (strcmp(k, CFG_KEEPALIVE) == 0) {
  900         r = config_param_val_int(v, &cfg->TCP_KEEPALIVE_TIME, 1);
  901     } else if (strcmp(k, CFG_BACKEND_REFRESH) == 0) {
  902         r = config_param_val_int(v, &cfg->BACKEND_REFRESH_TIME, 1);
  903     }
  904 #ifdef USE_SHARED_CACHE
  905     else if (strcmp(k, CFG_SHARED_CACHE) == 0) {
  906         r = config_param_val_int(v, &cfg->SHARED_CACHE, 1);
  907     } else if (strcmp(k, CFG_SHARED_CACHE_LISTEN) == 0) {
  908         if (strlen(v) > 0)
  909             r = config_param_host_port_wildcard(v, &cfg->SHCUPD_IP,
  910                 &cfg->SHCUPD_PORT, NULL, 1, NULL);
  911     } else if (strcmp(k, CFG_SHARED_CACHE_PEER) == 0) {
  912         r = config_param_shcupd_peer(v, cfg);
  913     } else if (strcmp(k, CFG_SHARED_CACHE_MCASTIF) == 0) {
  914         r = config_param_shcupd_mcastif(v, &cfg->SHCUPD_MCASTIF,
  915             &cfg->SHCUPD_MCASTTTL);
  916     }
  917 #endif
  918     else if (strcmp(k, CFG_CHROOT) == 0) {
  919         if (strlen(v) > 0) {
  920             // check directory
  921             if (stat(v, &st) != 0) {
  922                 config_error_set("Unable to stat directory"
  923                     " '%s': %s'.",v,strerror(errno));
  924                 r = 0;
  925             } else {
  926                 if (! S_ISDIR(st.st_mode)) {
  927                     config_error_set("Bad chroot directory "
  928                         "'%s': Not a directory", v);
  929                     r = 0;
  930                 } else {
  931                     config_assign_str(&cfg->CHROOT, v);
  932                 }
  933             }
  934         }
  935     } else if (strcmp(k, CFG_USER) == 0) {
  936         if (strlen(v) > 0) {
  937             struct passwd *passwd;
  938             passwd = getpwnam(v);
  939             if (!passwd) {
  940                 config_error_set("Invalid user '%s'.", v);
  941                 r = 0;
  942             } else {
  943                 cfg->UID = passwd->pw_uid;
  944                 cfg->GID = passwd->pw_gid;
  945             }
  946         }
  947     } else if (strcmp(k, CFG_GROUP) == 0) {
  948         if (strlen(v) > 0) {
  949             struct group *grp;
  950             grp = getgrnam(v);
  951             if (!grp) {
  952                 config_error_set("Invalid group '%s'.", v);
  953                 r = 0;
  954             } else {
  955                 cfg->GID = grp->gr_gid;
  956             }
  957         }
  958     } else if (strcmp(k, CFG_QUIET) == 0) {
  959         int b;
  960         r = config_param_val_bool(v, &b);
  961         if (b)
  962             cfg->LOG_LEVEL = 0;
  963         else
  964             cfg->LOG_LEVEL = 1;
  965     } else if (strcmp(k, CFG_LOG_LEVEL) == 0) {
  966         r = config_param_val_int(v, &cfg->LOG_LEVEL, 1);
  967     } else if (strcmp(k, CFG_LOG_FILENAME) == 0) {
  968         if (strlen(v) > 0) {
  969             config_assign_str(&cfg->LOG_FILENAME, v);
  970         }
  971     } else if (strcmp(k, CFG_SYSLOG) == 0) {
  972         r = config_param_val_bool(v, &cfg->SYSLOG);
  973     } else if (strcmp(k, CFG_SYSLOG_FACILITY) == 0) {
  974         int facility = -1;
  975         r = 1;
  976 #define SYSLOG_FAC(m, s)                \
  977         if (!strcmp(v, s))          \
  978             facility = m;
  979 #include "sysl_tbl.h"
  980 #undef SYSLOG_FAC
  981         if (facility != -1)
  982             cfg->SYSLOG_FACILITY = facility;
  983         else {
  984             config_error_set("Invalid facility '%s'.", v);
  985             r = 0;
  986         }
  987     } else if (strcmp(k, CFG_DAEMON) == 0) {
  988         r = config_param_val_bool(v, &cfg->DAEMONIZE);
  989     } else if (strcmp(k, CFG_WRITE_IP) == 0) {
  990         r = config_param_val_bool(v, &cfg->WRITE_IP_OCTET);
  991     } else if (strcmp(k, CFG_WRITE_PROXY) == 0) {
  992         r = config_param_val_bool(v, &cfg->WRITE_PROXY_LINE_V2);
  993     } else if (strcmp(k, CFG_WRITE_PROXY_V1) == 0) {
  994         r = config_param_val_bool(v, &cfg->WRITE_PROXY_LINE_V1);
  995     } else if (strcmp(k, CFG_WRITE_PROXY_V2) == 0) {
  996         r = config_param_val_bool(v, &cfg->WRITE_PROXY_LINE_V2);
  997     } else if (strcmp(k, CFG_PROXY_PROXY) == 0) {
  998         r = config_param_val_bool(v, &cfg->PROXY_PROXY_LINE);
  999     } else if (strcmp(k, CFG_ALPN_PROTOS) == 0) {
 1000         if (strlen(v) > 0) {
 1001             config_assign_str(&cfg->ALPN_PROTOS, v);
 1002         }
 1003     } else if (strcmp(k, CFG_PEM_FILE) == 0) {
 1004         struct cfg_cert_file *cert;
 1005         cert = cfg_cert_file_new();
 1006         config_assign_str(&cert->filename, v);
 1007         r = cfg_cert_vfy(cert);
 1008         if (r != 0) {
 1009             if (cfg->CERT_DEFAULT != NULL) {
 1010                 struct cfg_cert_file *tmp = cfg->CERT_DEFAULT;
 1011                 cfg_cert_add(tmp, &cfg->CERT_FILES);
 1012             }
 1013             cfg->CERT_DEFAULT = cert;
 1014         } else
 1015             cfg_cert_file_free(&cert);
 1016     } else if (strcmp(k, CFG_BACKEND_CONNECT_TIMEOUT) == 0) {
 1017         r = config_param_val_int(v, &cfg->BACKEND_CONNECT_TIMEOUT, 1);
 1018     } else if (strcmp(k, CFG_SSL_HANDSHAKE_TIMEOUT) == 0) {
 1019         r = config_param_val_int(v, &cfg->SSL_HANDSHAKE_TIMEOUT, 1);
 1020     } else if (strcmp(k, CFG_RECV_BUFSIZE) == 0) {
 1021         r = config_param_val_int(v, &cfg->RECV_BUFSIZE, 1);
 1022     } else if (strcmp(k, CFG_SEND_BUFSIZE) == 0) {
 1023         r = config_param_val_int(v, &cfg->SEND_BUFSIZE, 1);
 1024     } else if (strcmp(k, CFG_PIDFILE) == 0) {
 1025         if (strlen(v) > 0) {
 1026             config_assign_str(&cfg->PIDFILE, v);
 1027         }
 1028     } else if (strcmp(k, CFG_RING_SLOTS) == 0) {
 1029         r = config_param_val_int(v, &cfg->RING_SLOTS, 1);
 1030     } else if (strcmp(k, CFG_RING_DATA_LEN) == 0) {
 1031         r = config_param_val_int(v, &cfg->RING_DATA_LEN, 1);
 1032     } else if (strcmp(k, CFG_SNI_NOMATCH_ABORT) == 0) {
 1033         r = config_param_val_bool(v, &cfg->SNI_NOMATCH_ABORT);
 1034     } else if (strcmp(k, CFG_OCSP_DIR) == 0) {
 1035         config_assign_str(&cfg->OCSP_DIR, v);
 1036 #ifdef TCP_FASTOPEN_WORKS
 1037     } else if (strcmp(k, CFG_TFO) == 0) {
 1038         config_param_val_bool(v, &cfg->TFO);
 1039 #endif
 1040     } else if (strcmp(k, CFG_TLS_PROTOS) == 0) {
 1041         cfg->SELECTED_TLS_PROTOS = 0;
 1042 #define TLS_PROTO(u, i, s)              \
 1043         if (strcasestr(v, s))           \
 1044             cfg->SELECTED_TLS_PROTOS |= i;
 1045 #include "tls_proto_tbl.h"
 1046         if (cfg->SELECTED_TLS_PROTOS == 0) {
 1047             config_error_set("Invalid 'tls-protos' option '%s'", v);
 1048             return (1);
 1049         }
 1050     } else if (strcmp(k, CFG_DBG_LISTEN) == 0) {
 1051         config_assign_str(&cfg->DEBUG_LISTEN_ADDR, v);
 1052     } else {
 1053         fprintf(
 1054             stderr,
 1055             "Ignoring unknown configuration key '%s' in configuration file '%s', line %d\n",
 1056             k, file, line
 1057         );
 1058     }
 1059 
 1060     if (!r) {
 1061         if (file != NULL)
 1062             config_error_set("Error in configuration file '%s', "
 1063                 "line %d: %s\n", file, line, config_error_get());
 1064         else
 1065             config_error_set("Invalid parameter '%s': %s", k,
 1066                 config_error_get());
 1067         return (1);
 1068     }
 1069 
 1070     return (0);
 1071 }
 1072 
 1073 static int
 1074 config_file_parse(char *file, hitch_config *cfg)
 1075 {
 1076     FILE *fp = NULL;
 1077     int r = 0;
 1078 
 1079     AN(cfg);
 1080 
 1081     // should we read stdin?
 1082     if (file == NULL || strlen(file) < 1 || strcmp(file, "-") == 0)
 1083         fp = stdin;
 1084     else
 1085         fp = fopen(file, "r");
 1086 
 1087     if (fp == NULL) {
 1088         config_error_set("Unable to open configuration file '%s': %s\n",
 1089             file, strerror(errno));
 1090         return (1);
 1091     }
 1092 
 1093     yyin = fp;
 1094     do {
 1095         if (yyparse(cfg) != 0) {
 1096             r = 1;
 1097             break;
 1098         }
 1099     } while (!feof(yyin));
 1100 
 1101     fclose(fp);
 1102     return (r);
 1103 }
 1104 
 1105 static char *
 1106 config_disp_str(char *str)
 1107 {
 1108     return ((str == NULL) ? "" : str);
 1109 }
 1110 
 1111 static char *
 1112 config_disp_bool(int v)
 1113 {
 1114     return ((v > 0) ? CFG_BOOL_ON : "off");
 1115 }
 1116 
 1117 static char *
 1118 config_disp_uid(uid_t uid)
 1119 {
 1120     memset(tmp_buf, '\0', sizeof(tmp_buf));
 1121     if (uid == 0 && geteuid() != 0)
 1122         return (tmp_buf);
 1123     struct passwd *pw = getpwuid(uid);
 1124     if (pw) {
 1125         strncpy(tmp_buf, pw->pw_name, sizeof(tmp_buf));
 1126         tmp_buf[sizeof(tmp_buf) - 1] = '\0';
 1127     }
 1128     return (tmp_buf);
 1129 }
 1130 
 1131 static char *
 1132 config_disp_gid (gid_t gid)
 1133 {
 1134     memset(tmp_buf, '\0', sizeof(tmp_buf));
 1135     if (gid == 0 && geteuid() != 0)
 1136         return (tmp_buf);
 1137     struct group *gr = getgrgid(gid);
 1138     if (gr) {
 1139         strncpy(tmp_buf, gr->gr_name, sizeof(tmp_buf));
 1140         tmp_buf[sizeof(tmp_buf) - 1] = '\0';
 1141     }
 1142     return (tmp_buf);
 1143 }
 1144 
 1145 static const char *
 1146 config_disp_hostport(char *host, char *port)
 1147 {
 1148     memset(tmp_buf, '\0', sizeof(tmp_buf));
 1149     if (host == NULL && port == NULL)
 1150         return ("");
 1151 
 1152     strcat(tmp_buf, "[");
 1153     if (host == NULL)
 1154         strcat(tmp_buf, "*");
 1155     else
 1156         strncat(tmp_buf, host, 40);
 1157     strcat(tmp_buf, "]:");
 1158     strncat(tmp_buf, port, 5);
 1159     return (tmp_buf);
 1160 }
 1161 
 1162 static const char *
 1163 config_disp_log_facility (int facility)
 1164 {
 1165     switch (facility)
 1166     {
 1167 #define SYSLOG_FAC(m, s)            \
 1168         case m:             \
 1169             return (s);
 1170 #include "sysl_tbl.h"
 1171 #undef SYSLOG_FAC
 1172         default:
 1173             return ("UNKNOWN");
 1174     }
 1175 }
 1176 
 1177 int
 1178 config_scan_pem_dir(char *pemdir, hitch_config *cfg)
 1179 {
 1180     int n, i, plen;
 1181     int retval = 0;
 1182     struct dirent **d;
 1183     struct stat st;
 1184 
 1185     n = scandir(pemdir, &d, NULL, alphasort);
 1186     if (n < 0) {
 1187         config_error_set("Unable to open directory '%s': %s", pemdir,
 1188             strerror(errno));
 1189         return (1);
 1190     }
 1191     for (i = 0; i < n; i++) {
 1192         struct cfg_cert_file *cert;
 1193         char *fpath;
 1194 
 1195         plen = strlen(pemdir) + strlen(d[i]->d_name) + 1;
 1196 
 1197         if (cfg->PEM_DIR_GLOB != NULL) {
 1198             if (fnmatch(cfg->PEM_DIR_GLOB, d[i]->d_name, 0))
 1199                 continue;
 1200         }
 1201         if (d[i]->d_type != DT_UNKNOWN && d[i]->d_type != DT_REG)
 1202             continue;
 1203 
 1204         fpath = malloc(plen);
 1205         AN(fpath);
 1206 
 1207         if (snprintf(fpath, plen, "%s%s", pemdir, d[i]->d_name) < 0) {
 1208             config_error_set("An error occurred while "
 1209                 "combining path");
 1210             free(fpath);
 1211             retval = 1;
 1212             break;
 1213         }
 1214 
 1215         if (d[i]->d_type == DT_UNKNOWN) {
 1216             /* The underlying filesystem does not support d_type. */
 1217             if (lstat(fpath, &st) < 0) {
 1218                 fprintf(stderr, "Warning: unable to stat '%s': %s. Skipping.\n",
 1219                     fpath, strerror(errno));
 1220                 free(fpath);
 1221                 continue;
 1222             }
 1223             if (!S_ISREG(st.st_mode)) {
 1224                 free(fpath);
 1225                 continue;
 1226             }
 1227         }
 1228 
 1229         cert = cfg_cert_file_new();
 1230         config_assign_str(&cert->filename, fpath);
 1231         free(fpath);
 1232 
 1233         int r = cfg_cert_vfy(cert);
 1234         if (r != 0) {
 1235             /* If no default has been set, use the first
 1236              * match according to alphasort  */
 1237             if (cfg->CERT_DEFAULT == NULL)
 1238                 cfg->CERT_DEFAULT = cert;
 1239             else
 1240                 cfg_cert_add(cert, &cfg->CERT_FILES);
 1241         } else {
 1242             cfg_cert_file_free(&cert);
 1243         }
 1244     }
 1245 
 1246     for (i = 0; i < n; i++)
 1247         free(d[i]);
 1248     free(d);
 1249 
 1250     return (retval);
 1251 }
 1252 
 1253 void
 1254 config_print_usage_fd(char *prog, FILE *out)
 1255 {
 1256     hitch_config *cfg;
 1257 
 1258     cfg = config_new();
 1259     AN(cfg);
 1260 
 1261     if (out == NULL)
 1262         out = stderr;
 1263     fprintf(out, "Usage: %s [OPTIONS] PEM\n\n", basename(prog));
 1264     fprintf(out, "This is hitch, The Scalable TLS Unwrapping Daemon.\n\n");
 1265     fprintf(out, "CONFIGURATION:\n");
 1266     fprintf(out, "\n");
 1267     fprintf(out, "\t--config=FILE\n");
 1268     fprintf(out, "\t\tLoad configuration from specified file.\n");
 1269     fprintf(out, "\n");
 1270     fprintf(out, "ENCRYPTION METHODS:\n");
 1271     fprintf(out, "\n");
 1272     fprintf(out, "\t--tls-protos=LIST\n");
 1273     fprintf(out, "\t\tSpecifies which SSL/TLS protocols to use.\n");
 1274     fprintf(out, "\t\tAvailable tokens are SSLv3, TLSv1.0, TLSv1.1\n");
 1275     fprintf(out, "\t\tTLSv1.2 and TLSv1.3. (Default: \"TLSv1.2 TLSv1.3\")\n");
 1276     fprintf(out, "\t-c  --ciphers=SUITE\n");
 1277     fprintf(out, "\t\tSets allowed ciphers (Default: \"%s\")\n",
 1278         config_disp_str(cfg->CIPHERS_TLSv12));
 1279     fprintf(out, "\t-e  --ssl-engine=NAME\n");
 1280     fprintf(out, "\t\tSets OpenSSL engine (Default: \"%s\")\n",
 1281         config_disp_str(cfg->ENGINE));
 1282     fprintf(out, "\t-O  --prefer-server-ciphers[=on|off]\n");
 1283     fprintf(out, "\t\tPrefer server list order (Default: \"%s\")\n",
 1284         config_disp_bool(cfg->PREFER_SERVER_CIPHERS));
 1285     fprintf(out, "\n");
 1286     fprintf(out, "SOCKET:\n");
 1287     fprintf(out, "\n");
 1288     fprintf(out, "\t--client\n");
 1289     fprintf(out, "\t\tEnable client proxy mode\n");
 1290     fprintf(out, "\t-b  --backend=[HOST]:PORT\n");
 1291     fprintf(out, "\t\tBackend endpoint (default is \"%s\")\n",
 1292         config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT));
 1293     fprintf(out,
 1294         "\t\tThe -b argument can also take a UNIX domain socket path\n");
 1295     fprintf(out, "\t\tE.g. --backend=\"/path/to/sock\"\n");
 1296     fprintf(out, "\t-f  --frontend=[HOST]:PORT[+CERT]\n");
 1297     fprintf(out, "\t\tFrontend listen endpoint (default is \"%s\")\n",
 1298         config_disp_hostport(cfg->LISTEN_DEFAULT->ip,
 1299         cfg->LISTEN_DEFAULT->port));
 1300     fprintf(out,
 1301         "\t\t(Note: brackets are mandatory in endpoint specifiers.)\n");
 1302     fprintf(out, "\t--recv-bufsize=SIZE\n");
 1303     fprintf(out, "\t\tReceive buffer size on client socket (Default: %d)\n",
 1304         cfg->RECV_BUFSIZE);
 1305     fprintf(out, "\t--send-bufsize=SIZE\n");
 1306     fprintf(out, "\t\tSend buffer size on client socket (Default: %d)\n",
 1307         cfg->SEND_BUFSIZE);
 1308 
 1309 #ifdef USE_SHARED_CACHE
 1310     fprintf(out, "\n");
 1311     fprintf(out, "\t-U  --shared-cache-listen=[HOST]:PORT\n");
 1312     fprintf(out, "\t\tAccept cache updates on UDP (Default: \"%s\")\n",
 1313         config_disp_hostport(cfg->SHCUPD_IP, cfg->SHCUPD_PORT));
 1314     fprintf(out,
 1315         "\t\tNOTE: This option requires enabled SSL session cache.\n");
 1316     fprintf(out, "\t-P  --shared-cache-peer=[HOST]:PORT\n");
 1317     fprintf(out, "\t\tSend cache updates to specified peer\n");
 1318     fprintf(out,
 1319         "\t\tNOTE: This option can be specified multiple times.\n");
 1320     fprintf(out, "\t-M  --shared-cache-if=IFACE[,TTL]\n");
 1321     fprintf(out,
 1322         "\t\tForce iface and ttl to receive and send multicast updates\n");
 1323 #endif
 1324 
 1325     fprintf(out, "\n");
 1326     fprintf(out, "PERFORMANCE:\n");
 1327     fprintf(out, "\n");
 1328     fprintf(out, "\t-n  --workers=NUM\n");
 1329     fprintf(out, "\t\tNumber of worker processes (Default: %ld)\n",
 1330         cfg->NCORES);
 1331     fprintf(out, "\t-B  --backlog=NUM\n");
 1332     fprintf(out, "\t\tSet listen backlog size (Default: %d)\n", cfg->BACKLOG);
 1333     fprintf(out, "\t-k  --keepalive=SECS\n");
 1334     fprintf(out, "\t\tTCP keepalive on client socket (Default: %d)\n",
 1335         cfg->TCP_KEEPALIVE_TIME);
 1336     fprintf(out, "\t-R  --backend-refresh=SECS\n");
 1337     fprintf(out, "\t\tPeriodic backend IP lookup, 0 to disable (Default: %d)\n",
 1338         cfg->BACKEND_REFRESH_TIME);
 1339 
 1340 #ifdef USE_SHARED_CACHE
 1341     fprintf(out, "\t-C  --session-cache=NUM\n");
 1342     fprintf(out,
 1343         "\t\tEnable and set SSL session cache to specified number\n");
 1344     fprintf(out, "\t\tof sessions (Default: %d)\n", cfg->SHARED_CACHE);
 1345 #endif
 1346 #ifdef TCP_FASTOPEN_WORKS
 1347     fprintf(out, "\t--enable-tcp-fastopen[=on|off]\n");
 1348     fprintf(out, "\t\tEnable client-side TCP Fast Open. (Default: %s)\n",
 1349         config_disp_bool(cfg->TFO));
 1350 #endif
 1351     fprintf(out, "\n");
 1352     fprintf(out, "SECURITY:\n");
 1353     fprintf(out, "\n");
 1354     fprintf(out, "\t-r  --chroot=DIR\n");
 1355     fprintf(out, "\t\tSets chroot directory (Default: \"%s\")\n",
 1356         config_disp_str(cfg->CHROOT));
 1357     fprintf(out, "\t-u  --user=USER\n ");
 1358     fprintf(out,
 1359         "\t\tSet uid/gid after binding the socket (Default: \"%s\")\n",
 1360         config_disp_uid(cfg->UID));
 1361     fprintf(out, "\t-g  --group=GROUP\n");
 1362     fprintf(out, "\t\tSet gid after binding the socket (Default: \"%s\")\n",
 1363         config_disp_gid(cfg->GID));
 1364     fprintf(out, "\n");
 1365     fprintf(out, "LOGGING:\n");
 1366     fprintf(out, "\t-q  --quiet[=on|off]\n");
 1367     fprintf(out, "\t\tBe quiet; emit only error messages "
 1368         "(deprecated, use 'log-level')\n");
 1369     fprintf(out, "\t-L  --log-level=NUM\n");
 1370     fprintf(out, "\t\tLog level. 0=silence, 1=err, 2=info/debug (Default: %d)\n",
 1371         cfg->LOG_LEVEL);
 1372     fprintf(out, "\t-l  --log-filename=FILE \n");
 1373     fprintf(out,
 1374         "\t\tSend log message to a logfile instead of stderr/stdout\n");
 1375     fprintf(out, "\t-s  --syslog[=on|off]   \n");
 1376     fprintf(out,
 1377         "\t\tSend log message to syslog in addition to stderr/stdout\n");
 1378     fprintf(out, "\t--syslog-facility=FACILITY\n");
 1379     fprintf(out, "\t\tSyslog facility to use (Default: \"%s\")\n",
 1380         config_disp_log_facility(cfg->SYSLOG_FACILITY));
 1381     fprintf(out, "\n");
 1382     fprintf(out, "OTHER OPTIONS:\n");
 1383     fprintf(out, "\t--daemon[=on|off]\n");
 1384     fprintf(out, "\t\tFork into background and become a daemon (Default: %s)\n",
 1385         config_disp_bool(cfg->DAEMONIZE));
 1386     fprintf(out, "\t--write-ip[=on|off]\n");
 1387     fprintf(out,
 1388         "\t\tWrite 1 octet with the IP family followed by the IP\n");
 1389     fprintf(out,
 1390         "\t\taddress in 4 (IPv4) or 16 (IPv6) octets little-endian\n");
 1391     fprintf(out,
 1392         "\t\tto backend before the actual data\n");
 1393     fprintf(out,
 1394         "\t\t(Default: %s)\n", config_disp_bool(cfg->WRITE_IP_OCTET));
 1395     fprintf(out, "\t--write-proxy-v1[=on|off]\n");
 1396     fprintf(out,
 1397         "\t\tWrite HAProxy's PROXY v1 (IPv4 or IPv6) protocol line\n");
 1398     fprintf(out, "\t\tbefore actual data\n");
 1399     fprintf(out, "\t\t(Default: %s)\n",
 1400         config_disp_bool(cfg->WRITE_PROXY_LINE_V1));
 1401     fprintf(out, "\t--write-proxy-v2[=on|off]\n");
 1402     fprintf(out, "\t\tWrite HAProxy's PROXY v2 binary (IPv4 or IPv6)\n");
 1403     fprintf(out, "\t\t protocol line before actual data\n");
 1404     fprintf(out, "\t\t(Default: %s)\n",
 1405         config_disp_bool(cfg->WRITE_PROXY_LINE_V2));
 1406     fprintf(out, "\t--write-proxy[=on|off]\n");
 1407     fprintf(out, "\t\tEquivalent to --write-proxy-v2. For PROXY \n");
 1408     fprintf(out, "\t\tversion 1 use --write-proxy-v1 explicitly\n");
 1409     fprintf(out, "\t--proxy-proxy[=on|off]\n");
 1410     fprintf(out, "\t\tProxy HAProxy's PROXY (IPv4 or IPv6) protocol\n");
 1411     fprintf(out, "\t\tbefore actual data (PROXYv1 and PROXYv2)\n");
 1412     fprintf(out, "\t\t(Default: %s)\n",
 1413         config_disp_bool(cfg->PROXY_PROXY_LINE));
 1414     fprintf(out, "\t--sni-nomatch-abort[=on|off]\n");
 1415     fprintf(out, "\t\tAbort handshake when client submits an\n");
 1416     fprintf(out, "\t\tunrecognized SNI server name\n" );
 1417     fprintf(out, "\t\t(Default: %s)\n",
 1418             config_disp_bool(cfg->SNI_NOMATCH_ABORT));
 1419     fprintf(out, "\t--alpn-protos=LIST\n");
 1420     fprintf(out, "\t\tSets the protocols for ALPN/NPN negotiation,\n");
 1421     fprintf(out, "\t\tprovided as a list of comma-separated tokens\n");
 1422     fprintf(out, "\t--ocsp-dir=DIR\n");
 1423     fprintf(out, "\t\tSet OCSP staple cache directory\n");
 1424     fprintf(out, "\t\tThis enables automated retrieval and stapling\n"
 1425         "\t\tof OCSP responses\n");
 1426     fprintf(out, "\t\t(Default: \"%s\")\n", config_disp_str(cfg->OCSP_DIR));
 1427     fprintf(out, "\n");
 1428     fprintf(out, "\t-t  --test\n");
 1429     fprintf(out, "\t\tTest configuration and exit\n");
 1430     fprintf(out, "\t-p  --pidfile=FILE\n");
 1431     fprintf(out, "\t\tPID file\n");
 1432     fprintf(out, "\t-V  --version\n");
 1433     fprintf(out, "\t\tPrint program version and exit\n");
 1434     fprintf(out, "\t-h  --help\n");
 1435     fprintf(out, "\t\tThis help message\n");
 1436 
 1437     config_destroy(cfg);
 1438 }
 1439 
 1440 static void
 1441 config_print_usage(char *prog)
 1442 {
 1443     config_print_usage_fd(prog, stdout);
 1444 }
 1445 
 1446 static int
 1447 create_alpn_callback_data(hitch_config *cfg, char **error)
 1448 {
 1449     size_t i = 1, j, l;
 1450 
 1451     AN(cfg->ALPN_PROTOS);
 1452     l = strlen(cfg->ALPN_PROTOS);
 1453     cfg->ALPN_PROTOS_LV = malloc(l + 1);
 1454     AN(cfg->ALPN_PROTOS_LV);
 1455 
 1456     // first remove spaces while copying to cfg->ALPN_PROTOS_LV
 1457     for(j = 0; j < l; j++)
 1458         if (!isspace(cfg->ALPN_PROTOS[j])) {
 1459             cfg->ALPN_PROTOS_LV[i] = cfg->ALPN_PROTOS[j];
 1460             i++;
 1461         }
 1462 
 1463     l = i - 1; // same as before iff cfg->ALPN_PROTOS has no spaces
 1464     i = 0; // location of next "length" byte
 1465     for(j = 1; j <= l; j++) {
 1466         if (cfg->ALPN_PROTOS_LV[j] == ',') {
 1467             if (i + 1 == j) {
 1468                 *error = "alpn-protos has empty proto in list";
 1469                 return (0); // failure
 1470             }
 1471             if (j - i > 256) {
 1472                 free(cfg->ALPN_PROTOS_LV);
 1473                 cfg->ALPN_PROTOS_LV = NULL;
 1474                 *error = "alpn protocol too long";
 1475                 return (0);
 1476             }
 1477             cfg->ALPN_PROTOS_LV[i] = (unsigned char)(j - i - 1);
 1478             i = j;
 1479         }
 1480     }
 1481     if (i == j) {
 1482         // alpn-protos ends with a comma - we let it slide
 1483         cfg->ALPN_PROTOS_LV_LEN = l;
 1484     } else {
 1485         if (j - i > 256) {
 1486             free(cfg->ALPN_PROTOS_LV);
 1487             cfg->ALPN_PROTOS_LV = NULL;
 1488             *error = "alpn protocol too long";
 1489             return (0);
 1490         }
 1491         cfg->ALPN_PROTOS_LV[i] = (unsigned char)(j - i - 1);
 1492         cfg->ALPN_PROTOS_LV_LEN = l + 1;
 1493     }
 1494     return (1); // ok!
 1495 }
 1496 
 1497 int
 1498 config_parse_cli(int argc, char **argv, hitch_config *cfg)
 1499 {
 1500     static int tls = 0, ssl = 0;
 1501     struct front_arg *fa, *fatmp;
 1502     static int client = 0;
 1503     int c, i;
 1504 
 1505     optind = 1;
 1506 
 1507     struct option long_options[] = {
 1508         { CFG_CONFIG, 1, NULL, CFG_PARAM_CFGFILE },
 1509         { "tls", 0, &tls, 1},
 1510         { "ssl", 0, &ssl, 1},
 1511         { "client", 0, &client, 1},
 1512         { CFG_CIPHERS, 1, NULL, 'c' },
 1513         { CFG_PREFER_SERVER_CIPHERS, 2, NULL, 'O' },
 1514         { CFG_BACKEND, 1, NULL, 'b' },
 1515         { CFG_FRONTEND, 1, NULL, 'f' },
 1516         { CFG_WORKERS, 1, NULL, 'n' },
 1517         { CFG_BACKLOG, 1, NULL, 'B' },
 1518 #ifdef USE_SHARED_CACHE
 1519         { CFG_SHARED_CACHE, 1, NULL, 'C' },
 1520         { CFG_SHARED_CACHE_LISTEN, 1, NULL, 'U' },
 1521         { CFG_SHARED_CACHE_PEER, 1, NULL, 'P' },
 1522         { CFG_SHARED_CACHE_MCASTIF, 1, NULL, 'M' },
 1523 #endif
 1524         { CFG_PIDFILE, 1, NULL, 'p' },
 1525         { CFG_KEEPALIVE, 1, NULL, 'k' },
 1526         { CFG_BACKEND_REFRESH, 1, NULL, 'R' },
 1527         { CFG_CHROOT, 1, NULL, 'r' },
 1528         { CFG_USER, 1, NULL, 'u' },
 1529         { CFG_GROUP, 1, NULL, 'g' },
 1530         { CFG_QUIET, 2, NULL, 'q' },
 1531         { CFG_LOG_FILENAME, 1, NULL, 'l' },
 1532         { CFG_LOG_LEVEL, 1, NULL, 'L' },
 1533         { CFG_SYSLOG, 2, NULL, 's' },
 1534         { CFG_SYSLOG_FACILITY, 1, NULL, CFG_PARAM_SYSLOG_FACILITY },
 1535         { CFG_SEND_BUFSIZE, 1, NULL, CFG_PARAM_SEND_BUFSIZE },
 1536         { CFG_RECV_BUFSIZE, 1, NULL, CFG_PARAM_RECV_BUFSIZE },
 1537 #ifdef TCP_FASTOPEN_WORKS
 1538         { CFG_TFO, 2, NULL, 1 },
 1539 #endif
 1540         { CFG_DAEMON, 2, NULL, 1 },
 1541         { CFG_WRITE_IP, 2, NULL, 1 },
 1542         { CFG_WRITE_PROXY_V1, 2, NULL, 1 },
 1543         { CFG_WRITE_PROXY_V2, 2, NULL, 1 },
 1544         { CFG_WRITE_PROXY, 2, NULL, 1 },
 1545         { CFG_PROXY_PROXY, 2, NULL, 1 },
 1546         { CFG_ALPN_PROTOS, 1, NULL, CFG_PARAM_ALPN_PROTOS },
 1547         { CFG_SNI_NOMATCH_ABORT, 2, NULL, 1 },
 1548         { CFG_OCSP_DIR, 1, NULL, 'o' },
 1549         { CFG_TLS_PROTOS, 1, NULL, CFG_PARAM_TLS_PROTOS },
 1550         { CFG_DBG_LISTEN, 1, NULL, CFG_PARAM_DBG_LISTEN },
 1551         { "test", 0, NULL, 't' },
 1552         { "version", 0, NULL, 'V' },
 1553         { "help", 0, NULL, 'h' },
 1554         { 0, 0, 0, 0 }
 1555     };
 1556 #define SHORT_OPTS "c:e:Ob:f:n:B:l:L:C:U:p:P:M:k:r:u:g:qstVho:R:"
 1557 
 1558     if (argc == 1) {
 1559         config_print_usage(argv[0]);
 1560         return (1);
 1561     }
 1562 
 1563     /* First do a pass over the args string to see if there was a
 1564      * config file present. If so, apply its options first in
 1565      * order to let them be overridden by the command line.  */
 1566     while (1) {
 1567         int option_index = 0;
 1568         c = getopt_long(argc, argv, SHORT_OPTS,
 1569             long_options, &option_index);
 1570         if (c == -1) {
 1571             break;
 1572         }
 1573         else if (c == '?') {
 1574             config_error_set("Invalid command line parameters. "
 1575                 "Run %s --help for instructions.",
 1576                 basename(argv[0]));
 1577             return (1);
 1578         }
 1579         else if (c == CFG_PARAM_CFGFILE) {
 1580             if (config_file_parse(optarg, cfg) != 0) {
 1581                 return (1);
 1582             }
 1583         }
 1584     }
 1585 
 1586     int tls_protos_config_file = cfg->SELECTED_TLS_PROTOS;
 1587 
 1588     optind = 1;
 1589     while (1) {
 1590         int ret = 0;
 1591         int option_index = 0;
 1592         c = getopt_long(argc, argv, SHORT_OPTS,
 1593             long_options, &option_index);
 1594 
 1595         if (c == -1)
 1596             break;
 1597 
 1598         switch (c) {
 1599         case 0:
 1600             break;
 1601         case CFG_PARAM_CFGFILE:
 1602             /* Handled above */
 1603             break;
 1604 #define CFG_ARG(opt, key)                       \
 1605             case opt:                   \
 1606             ret = config_param_validate(key,        \
 1607                 optarg, cfg, NULL, 0);          \
 1608             break;
 1609 #define CFG_BOOL(opt, key)                      \
 1610             case opt:                   \
 1611             ret = config_param_validate(key,        \
 1612                 optarg ? optarg : CFG_BOOL_ON,      \
 1613                 cfg, NULL, 0);              \
 1614             break;
 1615 CFG_ARG(CFG_PARAM_SYSLOG_FACILITY, CFG_SYSLOG_FACILITY);
 1616 CFG_ARG(CFG_PARAM_SEND_BUFSIZE, CFG_SEND_BUFSIZE);
 1617 CFG_ARG(CFG_PARAM_RECV_BUFSIZE, CFG_RECV_BUFSIZE);
 1618 CFG_ARG(CFG_PARAM_ALPN_PROTOS, CFG_ALPN_PROTOS);
 1619 CFG_ARG(CFG_PARAM_TLS_PROTOS, CFG_TLS_PROTOS);
 1620 CFG_ARG(CFG_PARAM_DBG_LISTEN, CFG_DBG_LISTEN);
 1621 CFG_ARG('c', CFG_CIPHERS);
 1622 CFG_ARG('e', CFG_SSL_ENGINE);
 1623 CFG_ARG('b', CFG_BACKEND);
 1624 CFG_ARG('f', CFG_FRONTEND);
 1625 CFG_ARG('n', CFG_WORKERS);
 1626 CFG_ARG('B', CFG_BACKLOG);
 1627 #ifdef USE_SHARED_CACHE
 1628 CFG_ARG('C', CFG_SHARED_CACHE);
 1629 CFG_ARG('U', CFG_SHARED_CACHE_LISTEN);
 1630 CFG_ARG('P', CFG_SHARED_CACHE_PEER);
 1631 CFG_ARG('M', CFG_SHARED_CACHE_MCASTIF);
 1632 #endif
 1633 CFG_ARG('p', CFG_PIDFILE);
 1634 CFG_ARG('k', CFG_KEEPALIVE);
 1635 CFG_ARG('R', CFG_BACKEND_REFRESH);
 1636 CFG_ARG('r', CFG_CHROOT);
 1637 CFG_ARG('u', CFG_USER);
 1638 CFG_ARG('g', CFG_GROUP);
 1639 CFG_ARG('o', CFG_OCSP_DIR);
 1640 CFG_BOOL('O', CFG_PREFER_SERVER_CIPHERS);
 1641 CFG_BOOL('q', CFG_QUIET);
 1642 CFG_ARG('l', CFG_LOG_FILENAME);
 1643 CFG_ARG('L', CFG_LOG_LEVEL);
 1644 CFG_BOOL('s', CFG_SYSLOG);
 1645 #undef CFG_ARG
 1646 #undef CFG_BOOL
 1647         case 1:
 1648             assert (option_index > 0);
 1649             if (optarg != NULL) {
 1650                 if (strcmp(optarg, "on") &&
 1651                     strcmp(optarg, "off")) {
 1652                     config_error_set(
 1653                         "Invalid argument '%s' for option '%s': "
 1654                             "expected one of 'on' or 'off",
 1655                             optarg,
 1656                             long_options[option_index].name);
 1657                     return (1);
 1658                 }
 1659             }
 1660             ret = config_param_validate(
 1661                 long_options[option_index].name,
 1662                     optarg ? optarg : CFG_BOOL_ON,
 1663                     cfg, NULL, 0);
 1664             break;
 1665         case 't':
 1666             cfg->TEST = 1;
 1667             break;
 1668         case 'V':
 1669             printf("%s %s\n", basename(argv[0]), VERSION);
 1670             exit(0);
 1671         case 'h':
 1672             config_print_usage(argv[0]);
 1673             exit(0);
 1674         default:
 1675             config_error_set("Invalid command line parameters. "
 1676                 "Run %s --help for instructions.",
 1677                 basename(argv[0]));
 1678             return (1);
 1679         }
 1680 
 1681         if (ret != 0) {
 1682             return (1);
 1683         }
 1684     }
 1685 
 1686     if ((tls || ssl) && tls_protos_config_file != 0) {
 1687         config_error_set("Deprecated options --tls and --ssl cannot be"
 1688             " used to override tls-protos in a config file.");
 1689         return (1);
 1690     }
 1691     if (tls && ssl) {
 1692         config_error_set("Options --tls and --ssl are mutually"
 1693             " exclusive.");
 1694         return (1);
 1695     } else {
 1696         if (ssl)
 1697             cfg->SELECTED_TLS_PROTOS = SSL_OPTION_PROTOS;
 1698         else if (tls)
 1699             cfg->SELECTED_TLS_PROTOS = TLS_OPTION_PROTOS;
 1700     }
 1701     if (cfg->SELECTED_TLS_PROTOS == 0)
 1702         cfg->SELECTED_TLS_PROTOS = DEFAULT_TLS_PROTOS;
 1703 
 1704     if (client)
 1705         cfg->PMODE = SSL_CLIENT;
 1706 
 1707     if ((!!cfg->WRITE_IP_OCTET + !!cfg->PROXY_PROXY_LINE +
 1708         !!cfg->WRITE_PROXY_LINE_V1 + !!cfg->WRITE_PROXY_LINE_V2) >= 2) {
 1709         config_error_set("Options --write-ip, --write-proxy-proxy,"
 1710             " --write-proxy-v1 and --write-proxy-v2 are"
 1711             " mutually exclusive.");
 1712         return (1);
 1713     }
 1714 
 1715     if (cfg->CLIENT_VERIFY != SSL_VERIFY_NONE &&
 1716         cfg->CLIENT_VERIFY_CA == NULL) {
 1717         config_error_set("Setting 'client-verify-ca' is required when"
 1718             " configuring client-verify");
 1719         return (1);
 1720     }
 1721 
 1722     HASH_ITER(hh, cfg->LISTEN_ARGS, fa, fatmp) {
 1723         if (fa->client_verify != -1 &&
 1724             fa->client_verify != SSL_VERIFY_NONE) {
 1725             if (!fa->client_verify_ca && !cfg->CLIENT_VERIFY_CA) {
 1726                 config_error_set("No 'client-verify-ca' "
 1727                     "configured for frontend '%s'",
 1728                     fa->pspec);
 1729                 return (1);
 1730             }
 1731         }
 1732 
 1733     }
 1734 
 1735 
 1736 #ifdef USE_SHARED_CACHE
 1737     if (cfg->SHCUPD_IP != NULL && ! cfg->SHARED_CACHE) {
 1738         config_error_set("Shared cache update listener is defined,"
 1739             " but shared cache is disabled.");
 1740         return (1);
 1741     }
 1742 #endif
 1743 
 1744     /* ALPN/NPN protocol negotiation additional configuration and error
 1745        handling */
 1746     if (cfg->ALPN_PROTOS != NULL) {
 1747         char *error;
 1748         if (!create_alpn_callback_data(cfg, &error)) {
 1749             if (error)
 1750                 config_error_set("alpn-protos configuration"
 1751                     " \"%s\" is bad. %s",
 1752                     cfg->ALPN_PROTOS, error);
 1753             else
 1754                 config_error_set("alpn-protos configuration"
 1755                     " \"%s\" is bad. See man page for more"
 1756                     " info.",
 1757                     cfg->ALPN_PROTOS);
 1758             return (1);
 1759         }
 1760 #if defined(OPENSSL_WITH_NPN) || defined(OPENSSL_WITH_ALPN)
 1761         /*
 1762         if (cfg->WRITE_PROXY_LINE_V2)
 1763             fprintf(stderr, ALPN_NPN_PREFIX_STR
 1764                 " Negotiated protocol will be communicated to the"
 1765                 " backend.\n");
 1766         */
 1767 #  ifndef OPENSSL_WITH_ALPN
 1768         fprintf(stderr, ALPN_NPN_PREFIX_STR " Warning: Hitch has been"
 1769             " compiled against a version of OpenSSL without ALPN"
 1770             " support.\n");
 1771 #  endif
 1772 #else
 1773         AN(cfg->ALPN_PROTOS_LV);
 1774         int multi_proto =
 1775             cfg->ALPN_PROTOS_LV[0] != cfg->ALPN_PROTOS_LV_LEN - 1;
 1776         /* No support for ALPN / NPN support in OpenSSL */
 1777         if (multi_proto ||
 1778             0 != strncmp((char *)cfg->ALPN_PROTOS_LV, "\x8http/1.1", 9)) {
 1779             config_error_set("This is compiled against OpenSSL version"
 1780                 " %lx, which does not have NPN or ALPN support,"
 1781                 " yet alpn-protos has been set to %s.",
 1782                 OPENSSL_VERSION_NUMBER, cfg->ALPN_PROTOS);
 1783             return (1);
 1784         }
 1785         else
 1786             fprintf(stderr, "This is compiled against OpenSSL version"
 1787                 " %lx, which does not have NPN or ALPN support."
 1788                 " alpn-protos setting \"http/1.1\" will be ignored.\n",
 1789                 OPENSSL_VERSION_NUMBER);
 1790 #endif
 1791     }
 1792 
 1793     // Any arguments left are presumed to be PEM files
 1794     argc -= optind;
 1795     argv += optind;
 1796     for (i = 0; i < argc; i++) {
 1797         if (config_param_validate(CFG_PEM_FILE, argv[i], cfg, NULL, 0)) {
 1798             return (1);
 1799         }
 1800     }
 1801 
 1802     if (cfg->PEM_DIR != NULL) {
 1803         if (config_scan_pem_dir(cfg->PEM_DIR, cfg))
 1804             return (1);
 1805     }
 1806 
 1807     if (cfg->PMODE == SSL_SERVER && cfg->CERT_DEFAULT == NULL) {
 1808         HASH_ITER(hh, cfg->LISTEN_ARGS, fa, fatmp)
 1809             if (HASH_CNT(hh, fa->certs) == 0) {
 1810                 config_error_set("No x509 certificate PEM file "
 1811                     "specified for frontend '%s'!", fa->pspec);
 1812                 return (1);
 1813             }
 1814     }
 1815 
 1816     if (cfg->OCSP_DIR != NULL) {
 1817         struct stat sb;
 1818 
 1819         if (stat(cfg->OCSP_DIR, &sb) != 0) {
 1820             fprintf(stderr,
 1821                 "{ocsp} Warning: Unable to stat directory '%s': %s'."
 1822                 " OCSP stapling will be disabled.\n",
 1823                 cfg->OCSP_DIR, strerror(errno));
 1824             free(cfg->OCSP_DIR);
 1825             cfg->OCSP_DIR = NULL;
 1826         } else {
 1827             if (!S_ISDIR(sb.st_mode)) {
 1828                 fprintf(stderr, "{ocsp} Bad ocsp-dir "
 1829                     "'%s': Not a directory."
 1830                     " OCSP stapling will be disabled.\n", cfg->OCSP_DIR);
 1831                 free(cfg->OCSP_DIR);
 1832                 cfg->OCSP_DIR = NULL;
 1833             }
 1834         }
 1835     }
 1836 
 1837     return (0);
 1838 }