/* Parse mcast and ttl options */
int config_param_shcupd_mcastif (char *str, char **iface, char **ttl) {
    char buf[150];
    char *sp;

    if (strlen(str) >= sizeof buf) {
      config_error_set("Invalid option for IFACE[,TTL]");
      return 0;
    }

    sp = strchr(str, ',');
    if (!sp) {
        if (!strcmp(str, "*"))
            *iface = NULL;
        else
            *iface = str;
        *ttl = NULL;
        return 1;
    }
    else if (!strncmp(str, "*", sp - str)) {
        *iface = NULL;
    }
    else {
        *sp = 0;
        *iface = str;
    }
    *ttl = sp + 1;

    return 1;
}
Example #2
0
stud_config * config_new (void) {
  stud_config *r = NULL;
  r = malloc(sizeof(stud_config));
  if (r == NULL) {
    config_error_set("Unable to allocate memory for configuration structure: %s", strerror(errno));
    return NULL;
  }

  // set default values

  r->ETYPE              = ENC_TLS;
  r->PMODE              = SSL_SERVER;
  r->WRITE_IP_OCTET     = 0;
  r->WRITE_PROXY_LINE   = 0;
  r->PROXY_PROXY_LINE   = 0;
  r->CHROOT             = NULL;
  r->UID                = 0;
  r->GID                = 0;
  r->FRONT_IP           = NULL;
  r->FRONT_PORT         = strdup("8443");
  r->BACK_IP            = strdup("127.0.0.1");
  r->BACK_PORT          = strdup("8000");
#ifdef _SC_NPROCESSORS_ONLN
  r->NCORES             = sysconf(_SC_NPROCESSORS_ONLN);
#endif
  r->CERT_FILES         = NULL;
  r->CIPHER_SUITE       = NULL;
  r->NAMED_CURVE        = NULL;
  r->ENGINE             = NULL;
  r->BACKLOG            = 100;

#ifdef USE_SHARED_CACHE
  r->SHARED_CACHE       = 0;
  r->SHCUPD_IP          = NULL;
  r->SHCUPD_PORT        = NULL;

  for (int i = 0 ; i < MAX_SHCUPD_PEERS; i++)
    memset(&r->SHCUPD_PEERS[i], 0, sizeof(shcupd_peer_opt));

  r->SHCUPD_MCASTIF     = NULL;
  r->SHCUPD_MCASTTTL    = NULL;
#endif

  r->QUIET              = 0;
  r->SYSLOG             = 0;
  r->SYSLOG_FACILITY    = LOG_DAEMON;
  r->TCP_KEEPALIVE_TIME = 3600;
  r->DAEMONIZE          = 0;
  r->PREFER_SERVER_CIPHERS = 0;

  config_param_val_pid_file(NULL, r->PID_FILE);

  return r;
}
int config_param_val_intl_pos (char *str, long int *dst) {
  long int num = 0;
  if (str != NULL)
    num = atol(str);

  if (num < 1) {
    config_error_set("Not a positive number.");
    return 0;
  }

  *dst = num;
  return 1;
}
void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int line) {
  int r = 1;
  struct stat st;

  if (strcmp(k, "tls") == 0) {
    cfg->ETYPE = ENC_TLS;
  }
  else if (strcmp(k, "ssl") == 0) {
    cfg->ETYPE = ENC_SSL;
  }
  else if (strcmp(k, CFG_CIPHERS) == 0) {
    if (v != NULL && strlen(v) > 0) {
      config_assign_str(&cfg->CIPHER_SUITE, v);
    }
  }
  else if (strcmp(k, CFG_SSL_ENGINE) == 0) {
    if (v != NULL && strlen(v) > 0) {
      config_assign_str(&cfg->ENGINE, v);
    }
  }
  else if (strcmp(k, CFG_PREFER_SERVER_CIPHERS) == 0) {
    r = config_param_val_bool(v, &cfg->PREFER_SERVER_CIPHERS);
  }
  else if (strcmp(k, CFG_FRONTEND) == 0) {
    r = config_param_host_port_wildcard(v, &cfg->FRONT_IP, &cfg->FRONT_PORT, 1);
  }
  else if (strcmp(k, CFG_BACKEND) == 0) {
    r = config_param_host_port(v, &cfg->BACK_IP, &cfg->BACK_PORT);
  }
  else if (strcmp(k, CFG_WORKERS) == 0) {
    r = config_param_val_intl_pos(v, &cfg->NCORES);
  }
  else if (strcmp(k, CFG_BACKLOG) == 0) {
    r = config_param_val_int(v, &cfg->BACKLOG);
    if (r && cfg->BACKLOG < -1) cfg->BACKLOG = -1;
  }
  else if (strcmp(k, CFG_KEEPALIVE) == 0) {
    r = config_param_val_int_pos(v, &cfg->TCP_KEEPALIVE_TIME);
  }
#ifdef USE_SHARED_CACHE
  else if (strcmp(k, CFG_SHARED_CACHE) == 0) {
    r = config_param_val_int(v, &cfg->SHARED_CACHE);
  }
  else if (strcmp(k, CFG_SHARED_CACHE_LISTEN) == 0) {
    if (v != NULL && strlen(v) > 0)
      r = config_param_host_port_wildcard(v, &cfg->SHCUPD_IP, &cfg->SHCUPD_PORT, 1);
  }
  else if (strcmp(k, CFG_SHARED_CACHE_PEER) == 0) {
    r = config_param_shcupd_peer(v, cfg);
  }
  else if (strcmp(k, CFG_SHARED_CACHE_MCASTIF) == 0) {
    r = config_param_shcupd_mcastif(v, &cfg->SHCUPD_MCASTIF, &cfg->SHCUPD_MCASTTTL);
  }
#endif
  else if (strcmp(k, CFG_CHROOT) == 0) {
    if (v != NULL && strlen(v) > 0) {
      // check directory
      if (stat(v, &st) != 0) {
        config_error_set("Unable to stat directory '%s': %s'.", v, strerror(errno));
        r = 0;
      } else {
        if (! S_ISDIR(st.st_mode)) {
          config_error_set("Bad chroot directory '%s': Not a directory.", v, strerror(errno));
          r = 0;
        } else {
          config_assign_str(&cfg->CHROOT, v);
        }
      }
    }
  }
  else if (strcmp(k, CFG_USER) == 0) {
    if (v != NULL && strlen(v) > 0) {
      struct passwd *passwd;
      passwd = getpwnam(v);
      if (!passwd) {
        config_error_set("Invalid user '%s'.", v);
        r = 0;
      } else {
        cfg->UID = passwd->pw_uid;
        cfg->GID = passwd->pw_gid;
      }
    }
  }
  else if (strcmp(k, CFG_GROUP) == 0) {
    if (v != NULL && strlen(v) > 0) {
      struct group *grp;
      grp = getgrnam(v);
      if (!grp) {
        config_error_set("Invalid group '%s'.", v);
        r = 0;
      } else {
        cfg->GID = grp->gr_gid;
      }
    }
  }
  else if (strcmp(k, CFG_QUIET) == 0) {
    r = config_param_val_bool(v, &cfg->QUIET);
  }
  else if (strcmp(k, CFG_SYSLOG) == 0) {
    r = config_param_val_bool(v, &cfg->SYSLOG);
  }
  else if (strcmp(k, CFG_SYSLOG_FACILITY) == 0) {
    r = 1;
    if (!strcmp(v, "auth") || !strcmp(v, "authpriv"))
      cfg->SYSLOG_FACILITY = LOG_AUTHPRIV;
    else if (!strcmp(v, "cron"))
      cfg->SYSLOG_FACILITY = LOG_CRON;
    else if (!strcmp(v, "daemon"))
      cfg->SYSLOG_FACILITY = LOG_DAEMON;
    else if (!strcmp(v, "ftp"))
      cfg->SYSLOG_FACILITY = LOG_FTP;
    else if (!strcmp(v, "local0"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL0;
    else if (!strcmp(v, "local1"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL1;
    else if (!strcmp(v, "local2"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL2;
    else if (!strcmp(v, "local3"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL3;
    else if (!strcmp(v, "local4"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL4;
    else if (!strcmp(v, "local5"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL5;
    else if (!strcmp(v, "local6"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL6;
    else if (!strcmp(v, "local7"))
      cfg->SYSLOG_FACILITY = LOG_LOCAL7;
    else if (!strcmp(v, "lpr"))
      cfg->SYSLOG_FACILITY = LOG_LPR;
    else if (!strcmp(v, "mail"))
      cfg->SYSLOG_FACILITY = LOG_MAIL;
    else if (!strcmp(v, "news"))
      cfg->SYSLOG_FACILITY = LOG_NEWS;
    else if (!strcmp(v, "user"))
      cfg->SYSLOG_FACILITY = LOG_USER;
    else if (!strcmp(v, "uucp"))
      cfg->SYSLOG_FACILITY = LOG_UUCP;
    else {
      config_error_set("Invalid facility '%s'.", v);
      r = 0;
    }
  }
  else if (strcmp(k, CFG_DAEMON) == 0) {
    r = config_param_val_bool(v, &cfg->DAEMONIZE);
  }
  else if (strcmp(k, CFG_WRITE_IP) == 0) {
    r = config_param_val_bool(v, &cfg->WRITE_IP_OCTET);
  }
  else if (strcmp(k, CFG_WRITE_PROXY) == 0) {
    r = config_param_val_bool(v, &cfg->WRITE_PROXY_LINE);
  }
  else if (strcmp(k, CFG_PROXY_PROXY) == 0) {
    r = config_param_val_bool(v, &cfg->PROXY_PROXY_LINE);
  }
  else if (strcmp(k, CFG_PEM_FILE) == 0) {
      printf( "strcmp %s\n", k );
    if (v != NULL && strlen(v) > 0) {
      if (stat(v, &st) != 0) {
        config_error_set("Unable to stat x509 certificate PEM file '%s': ", v, strerror(errno));
        r = 0;
      }
      else if (! S_ISREG(st.st_mode)) {
        config_error_set("Invalid x509 certificate PEM file '%s': Not a file.", v);
        r = 0;
      } else {
        struct cert_files *cert = calloc(1, sizeof(*cert));
        config_assign_str(&cert->CERT_FILE, v);
        cert->NEXT = cfg->CERT_FILES;
        cfg->CERT_FILES = cert;
      }
    }
  }
  else {
    fprintf(
      stderr,
      "Ignoring unknown configuration key '%s' in configuration file '%s', line %d\n",
      k, file, line
    );
  }

  if (! r) {
    if (file != NULL)
      config_die("Error in configuration file '%s', line %d: %s\n", file, line, config_error_get());
    else
      config_die("Invalid parameter '%s': %s", k, config_error_get());
  }
}
int config_param_shcupd_peer (char *str, stud_config *cfg) {
  if (cfg == NULL) {
    config_error_set("Configuration pointer is NULL.");
    return 0;
  }

  // parse result
  int r = 1;

  // find place for new peer
  int offset = 0;
  int i = 0;
  for (i = 0; i < MAX_SHCUPD_PEERS; i++) {
    if (cfg->SHCUPD_PEERS[i].ip == NULL && cfg->SHCUPD_PEERS[i].port == NULL) {
      offset = i;
      break;
    }
  }
  if (i >= MAX_SHCUPD_PEERS) {
    config_error_set(
      "Reached maximum number of shared cache update peers (%d).",
      MAX_SHCUPD_PEERS
    );
    return 0;
  }

  // create place for new peer
  char *addr = malloc(ADDR_LEN);
  if (addr == NULL) {
    config_error_set(
      "Unable to allocate memory for new shared cache update peer address: %s",
      strerror(errno)
    );
    r = 0;
    goto outta_parse_peer;
  }
  memset(addr, '\0', ADDR_LEN);
  char *port = malloc(PORT_LEN);
  if (port == NULL) {
    config_error_set(
      "Unable to allocate memory for new shared cache update peer port: %s",
      strerror(errno)
    );
    r = 0;
    goto outta_parse_peer;
  }
  memset(port, '\0', PORT_LEN);

  // try to parse address
  if (! config_param_host_port(str, &addr, &port)) {
    r = 0;
    goto outta_parse_peer;
  }

  outta_parse_peer:

  if (! r) {
    if (addr != NULL) free(addr);
    if (port != NULL) free(port);
  } else {
    cfg->SHCUPD_PEERS[offset].ip = addr;
    cfg->SHCUPD_PEERS[offset].port = port;
  }

  return r;
}
int config_param_host_port_wildcard (char *str, char **addr, char **port, int wildcard_okay) {
  int len = (str != NULL) ? strlen(str) : 0;
  if (str == NULL || ! len) {
    config_error_set("Invalid/unset host/port string.");
    return 0;
  }

  // address/port buffers
  char port_buf[PORT_LEN];
  char addr_buf[ADDR_LEN];

  memset(port_buf, '\0', sizeof(port_buf));
  memset(addr_buf, '\0', sizeof(addr_buf));

  // NEW FORMAT: [address]:port
  if (*str == '[') {
    char *ptr = str + 1;
    char *x = strrchr(ptr, ']');
    if (x == NULL) {
      config_error_set("Invalid address '%s'.", str);
      return 0;
    }

    // address
    memcpy(addr_buf, ptr, (x - ptr));

    // port
    x += 2;
    memcpy(port_buf, x, sizeof(port_buf) - 1);
  }
  // OLD FORMAT: address,port
  else {
    char *x = strrchr(str, ',');
    if (x == NULL) {
      config_error_set("Invalid address string '%s'", str);
      return 0;
    }
    // addr
    int addr_len = x - str;
    memcpy(addr_buf, str, addr_len);
    // port
    memcpy(port_buf, (++x), sizeof(port_buf));
  }

  // printf("PARSED ADDR '%s', PORT '%s'\n", addr_buf, port_buf);

  // check port
  int p = atoi(port_buf);
  if (p < 1 || p > 65536) {
    config_error_set("Invalid port number '%s'", port_buf);
    return 0;
  }

  // write
  if (strcmp(addr_buf, "*") == 0) {
    if (wildcard_okay)
      free(*addr);
    else {
      config_error_set("Invalid address: wildcards are not allowed.");
      return 0;
    }
  } else {
    //if (*addr != NULL) free(*addr);
    *addr = strdup(addr_buf);
  }
  // if (**port != NULL) free(*port);
  *port = strdup(port_buf);

  // printf("ADDR FINAL: '%s', '%s'\n", *addr, *port);

  return 1;
}