Example #1
0
/* usage: SFTPPAMOptions opt1 ... */
MODRET set_sftppamoptions(cmd_rec *cmd) {
  config_rec *c = NULL;
  register unsigned int i = 0;
  unsigned long opts = 0UL;

  if (cmd->argc-1 == 0)
    CONF_ERROR(cmd, "wrong number of parameters");

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  c = add_config_param(cmd->argv[0], 1, NULL);

  for (i = 1; i < cmd->argc; i++) {
    if (strcmp(cmd->argv[i], "NoTTY") == 0) {
      opts |= SFTP_PAM_OPT_NO_TTY;

    } else if (strcmp(cmd->argv[i], "NoInfoMsgs") == 0) {
      opts |= SFTP_PAM_OPT_NO_INFO_MSGS;

    } else if (strcmp(cmd->argv[i], "NoRadioMsgs") == 0) {
      opts |= SFTP_PAM_OPT_NO_RADIO_MSGS;

    } else {
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown SFTPPAMOption: '",
        cmd->argv[i], "'", NULL));
    }
  }

  c->argv[0] = pcalloc(c->pool, sizeof(unsigned long));
  *((unsigned long *) c->argv[0]) = opts;

  return PR_HANDLED(cmd);
}
Example #2
0
/* usage: MemcacheOptions opt1 opt2 ... */
MODRET set_memcacheoptions(cmd_rec *cmd) {
  config_rec *c = NULL;
  register unsigned int i = 0;
  unsigned long opts = 0UL;

  if (cmd->argc-1 == 0) {
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  c = add_config_param(cmd->argv[0], 1, NULL);

  for (i = 1; i < cmd->argc; i++) {
    if (strcmp(cmd->argv[i], "NoBinaryProtocol") == 0) {
      opts |= PR_MEMCACHE_FL_NO_BINARY_PROTOCOL;

    } else if (strcmp(cmd->argv[i], "NoRandomReplicaReads") == 0) {
      opts |= PR_MEMCACHE_FL_NO_RANDOM_REPLICA_READ;

    } else {
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown MemcacheOption '",
        cmd->argv[i], "'", NULL));
    }
  }

  c->argv[0] = pcalloc(c->pool, sizeof(unsigned long));
  *((unsigned long *) c->argv[0]) = opts;

  return PR_HANDLED(cmd);
}
Example #3
0
/* usage: ModulePath path */
MODRET set_modulepath(cmd_rec *cmd) {
  int res;
  struct stat st;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT);

  if (pr_fs_valid_path(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, "must be an absolute path");

  /* Make sure that the configured path is not world-writeable. */
  res = pr_fsio_stat(cmd->argv[1], &st);
  if (res < 0)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error checking '",
      cmd->argv[1], "': ", strerror(errno), NULL)); 

  if (!S_ISDIR(st.st_mode))
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, cmd->argv[1], " is not a directory",
      NULL));

  if (st.st_mode & S_IWOTH)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, cmd->argv[1], " is world-writable",
      NULL));

  if (lt_dlsetsearchpath(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error setting module path: ",
      lt_dlerror(), NULL));

  dso_module_path = pstrdup(dso_pool, cmd->argv[1]);
  return PR_HANDLED(cmd);
}
Example #4
0
/* usage: ModuleControlsACLs actions|all allow|deny user|group list */
MODRET set_modulectrlsacls(cmd_rec *cmd) {
#ifdef PR_USE_CTRLS
  char *bad_action = NULL, **actions = NULL;

  CHECK_ARGS(cmd, 4);
  CHECK_CONF(cmd, CONF_ROOT);

  actions = ctrls_parse_acl(cmd->tmp_pool, cmd->argv[1]);

  if (strcmp(cmd->argv[2], "allow") != 0 &&
      strcmp(cmd->argv[2], "deny") != 0)
    CONF_ERROR(cmd, "second parameter must be 'allow' or 'deny'");

  if (strcmp(cmd->argv[3], "user") != 0 &&
      strcmp(cmd->argv[3], "group") != 0)
    CONF_ERROR(cmd, "third parameter must be 'user' or 'group'");

  bad_action = pr_ctrls_set_module_acls(dso_acttab, dso_pool, actions,
    cmd->argv[2], cmd->argv[3], cmd->argv[4]);
  if (bad_action != NULL)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown action: '",
      bad_action, "'", NULL));

  return PR_HANDLED(cmd);
#else
  CONF_ERROR(cmd, "requires Controls support (--enable-ctrls)");
#endif
}
Example #5
0
/* usage: LoadFile path */
MODRET set_loadfile(cmd_rec *cmd) {

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT);

  if (pr_fs_valid_path(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, "must be an absolute path");

  if (dso_load_file(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error loading '", cmd->argv[1],
      "': ", strerror(errno), NULL));

  return PR_HANDLED(cmd);
}
/* usage: FailureLog path [logfmt-name] */
MODRET set_failurelog(cmd_rec *cmd) {
  config_rec *c;
  const char *path;
  char *log_fmt = NULL;

  if (cmd->argc < 2 ||
      cmd->argc > 3) {
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  path = cmd->argv[1];
  if (*path != '/') {
    CONF_ERROR(cmd, "must be an absolute path");
  }

  if (cmd->argc == 3) {
    const char *fmt_name;

    fmt_name = cmd->argv[2];

    /* Double-check that logfmt-name is valid, defined, etc. Look up the
     * format string, and stash a pointer to that in the config_rec (but NOT
     * a copy of the format string; don't need to use that much memory).
     */
    c = find_config(cmd->server->conf, CONF_PARAM, "LogFormat", FALSE);
    while (c != NULL) {
      if (strcmp(c->argv[0], fmt_name) == 0) {
        log_fmt = c->argv[1];
        break;
      }

      log_fmt = NULL;
      c = find_config_next(c, c->next, CONF_PARAM, "LogFormat", FALSE);
    }

    if (log_fmt == NULL) {
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "no such LogFormat '",
        cmd->argv[2], "' configured", NULL));
    }
  }

  c = add_config_param(cmd->argv[0], 2, NULL, NULL);
  c->argv[0] = pstrdup(c->pool, path);
  c->argv[1] = log_fmt;

  return PR_HANDLED(cmd);
}
/* usage: CounterFile path */
MODRET set_counterfile(cmd_rec *cmd) {
  config_rec *c;
  const char *path;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL|CONF_ANON|CONF_DIR);

  path = cmd->argv[1];
  if (*path != '/') {
    CONF_ERROR(cmd, "must be an absolute path");
  }

  /* In theory, we could open a filehandle on the configured path right
   * here, and fail if the file couldn't be created/opened.  Then we
   * could just stash that filehandle in the cmd_rec.  Easy.
   *
   * However, that would mean that we would have open descriptors for
   * vhosts to which the client may not connect.  We would also need to
   * use pr_fs_get_usable_fd() so that these filehandles don't use the wrong
   * fds.  Instead, then, we wait to open the filehandles in sess_init(),
   * where we know vhost to which the client connected.
   */

  c = add_config_param_str(cmd->argv[0], 1, path);
  c->flags |= CF_MERGEDOWN;

  return PR_HANDLED(cmd);
}
/* usage:
 *  CounterMaxReaders max
 *  CounterMaxWriters max
 */
MODRET set_countermaxreaderswriters(cmd_rec *cmd) {
  int count;
  config_rec *c;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL|CONF_ANON|CONF_DIR);

  /* A count of zero means that an unlimited number of readers (or writers),
   * as is the default without this module, is in effect.
   */

  count = atoi(cmd->argv[1]);
  if (count < 0 ||
      count > INT_MAX) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "invalid number: ", cmd->argv[1],
      NULL));
  }

  c = add_config_param(cmd->argv[0], 1, NULL);
  c->argv[0] = pcalloc(c->pool, sizeof(int));
  *((int *) c->argv[0]) = count;
  c->flags |= CF_MERGEDOWN;

  return PR_HANDLED(cmd);
}
MODRET add_lmd_allow_from(cmd_rec *cmd) {
    config_rec *c;
    int i;
    array_header *allowed_acls;

    if(cmd->argc < 2 )
        CONF_ERROR(cmd, "argument missing");

    CHECK_CONF(cmd, CONF_ROOT|CONF_GLOBAL);

    /* argv => LMDMemcachedHost 127.0.0.1 192.168.0.1 ... */
    c = find_config(main_server->conf, CONF_PARAM, "LMDBAllow", FALSE);
    if(c && c->argv[0]) {
        allowed_acls = c->argv[0];
    } else {
        c = add_config_param(cmd->argv[0], 0, NULL);
        c->argv[0] = allowed_acls =
          make_array(cmd->server->pool, 0, sizeof(char *));
    }

    for(i=1; i < cmd->argc; i++) {
        char *entry = cmd->argv[i];
        if (strcasecmp(entry, "all") == 0 ||
            strcasecmp(entry, "none") == 0) {
            break;
        }
        pr_netacl_t *acl = pr_netacl_create(cmd->server->pool, entry);
        *((pr_netacl_t **) push_array(allowed_acls)) = acl;
        pr_log_debug(DEBUG2,
            "%s: add LMDBAllow[%d] %s", MODULE_NAME, i, entry);
    }

    return PR_HANDLED(cmd);
}
MODRET add_lmd_memcached_host(cmd_rec *cmd) {
    int i;
    memcached_return rc;
    memcached_server_st *server = NULL;

    if(cmd->argc < 2 )
        CONF_ERROR(cmd, "argument missing");

    CHECK_CONF(cmd, CONF_ROOT|CONF_GLOBAL);

    /* NOTICE: i = 1 */
    for(i=1; i < cmd->argc; i++) {
        const char *arg = cmd->argv[i];
        server = memcached_servers_parse(arg);
        rc = memcached_server_push(memcached_deny_blacklist_mmc, server);
        if(rc != MEMCACHED_SUCCESS){
            pr_log_auth(PR_LOG_ERR,
              "Fatal %s: failed memcached_strerror(): %s",
              MODULE_NAME, memcached_strerror(memcached_deny_blacklist_mmc, rc));
            exit(1);
        }
        pr_log_debug(DEBUG2,
            "%s: add memcached server %s", MODULE_NAME, arg);
    }
    is_set_server = true;
    return PR_HANDLED(cmd);
}
Example #11
0
/* usage: MemcacheConnectFailures count */
MODRET set_memcacheconnectfailures(cmd_rec *cmd) {
  char *ptr = NULL;
  config_rec *c;
  uint64_t count = 0;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

#ifdef HAVE_STRTOULL
  count = strtoull(cmd->argv[1], &ptr, 10);
#else
  count = strtoul(cmd->argv[1], &ptr, 10);
#endif /* HAVE_STRTOULL */

  if (ptr &&
      *ptr) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "bad connect failures parameter: ",
      cmd->argv[1], NULL));
  }

  c = add_config_param(cmd->argv[0], 1, NULL);
  c->argv[0] = palloc(c->pool, sizeof(uint64_t));
  *((uint64_t *) c->argv[0]) = count;

  return PR_HANDLED(cmd);
}
Example #12
0
/* usage: LoadModule module */
MODRET set_loadmodule(cmd_rec *cmd) {

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT);

  if (dso_load_module(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error loading module '",
      cmd->argv[1], "': ", strerror(errno), NULL));

  return PR_HANDLED(cmd);
}
Example #13
0
/* usage: DynMasqRefresh <seconds> */
MODRET set_dynmasqrefresh(cmd_rec *cmd) {
    CHECK_CONF(cmd, CONF_ROOT);
    CHECK_ARGS(cmd, 1);

    dynmasq_timer_interval = atoi(cmd->argv[1]);
    if (dynmasq_timer_interval < 1)
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
                                "must be greater than zero: '", cmd->argv[1], "'", NULL));

    return PR_HANDLED(cmd);
}
/* usage: CounterLog path|"none" */
MODRET set_counterlog(cmd_rec *cmd) {
  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  if (pr_fs_valid_path(cmd->argv[1]) < 0) {
    CONF_ERROR(cmd, "must be an absolute path");
  }

  add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
  return PR_HANDLED(cmd);
}
Example #15
0
/* usage: QoSOptions */
MODRET set_qosoptions(cmd_rec *cmd) {
  register unsigned int i;
  config_rec *c;
  int ctrlqos = 0, dataqos = 0;

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL);

  /* Make sure we have the right number of parameters. */
  if ((cmd->argc-1) % 2 != 0) {
   CONF_ERROR(cmd, "bad number of parameters");
  }

  for (i = 1; i < cmd->argc; i++) {
    if (strcasecmp(cmd->argv[i], "dataqos") == 0) {
      dataqos = qos_get_int(cmd->argv[++i]);
      if (dataqos == -1) {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown dataqos parameter '",
          cmd->argv[i-1], "'", NULL));
      }

    } else if (strcasecmp(cmd->argv[i], "ctrlqos") == 0) {
      ctrlqos = qos_get_int(cmd->argv[++i]);
      if (ctrlqos == -1) {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown ctrlqos parameter '",
          cmd->argv[i-1], "'", NULL));
      }

    } else {
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown QoS option: '",
        cmd->argv[i], "'", NULL));
    }
  }

  c = add_config_param(cmd->argv[0], 2, NULL, NULL);
  c->argv[0] = pcalloc(c->pool, sizeof(int));
  *((int *) c->argv[0]) = ctrlqos;
  c->argv[1] = pcalloc(c->pool, sizeof(int));
  *((int *) c->argv[1]) = dataqos;

  return PR_HANDLED(cmd);
}
Example #16
0
/* usage: MemcacheServers host1[:port1] ... */
MODRET set_memcacheservers(cmd_rec *cmd) {
  register unsigned int i;
  config_rec *c;
  char *str = "";
  int ctxt;
  memcached_server_st *memcache_servers = NULL;

  if (cmd->argc-1 < 1) {
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  c = add_config_param(cmd->argv[0], 1, NULL);
  for (i = 1; i < cmd->argc; i++) {
    str = pstrcat(cmd->pool, str, *str ? ", " : "", cmd->argv[i], NULL);
  }

  memcache_servers = memcached_servers_parse(str);
  if (memcache_servers == NULL) {
    CONF_ERROR(cmd, "unable to parse server parameters");
  }

  ctxt = (cmd->config && cmd->config->config_type != CONF_PARAM ?
    cmd->config->config_type : cmd->server->config_type ?
    cmd->server->config_type : CONF_ROOT);

  if (ctxt == CONF_ROOT) {
    /* If we're the "server config" context, set the server list now.  This
     * would let mod_memcache talk to those servers for e.g. ftpdctl actions.
     */
    memcache_set_servers(memcache_servers);
  }

  c->argv[0] = memcache_servers;

  /* Add the libmemcached-allocated pointer to a list, for later freeing. */
  *((memcached_server_st **) push_array(memcache_server_lists)) = memcache_servers;
  return PR_HANDLED(cmd);
}
Example #17
0
/* usage: DynMasqControlsACLs actions|all allow|deny user|group list */
MODRET set_dynmasqctrlsacls(cmd_rec *cmd) {
#ifdef PR_USE_CTRLS
    char *bad_action = NULL, **actions = NULL;

    CHECK_ARGS(cmd, 4);
    CHECK_CONF(cmd, CONF_ROOT);

    /* We can cheat here, and use the ctrls_parse_acl() routine to
     * separate the given string...
     */
    actions = ctrls_parse_acl(cmd->tmp_pool, cmd->argv[1]);

    /* Check the second parameter to make sure it is "allow" or "deny" */
    if (strcmp(cmd->argv[2], "allow") != 0 &&
            strcmp(cmd->argv[2], "deny") != 0) {
        CONF_ERROR(cmd, "second parameter must be 'allow' or 'deny'");
    }

    /* Check the third parameter to make sure it is "user" or "group" */
    if (strcmp(cmd->argv[3], "user") != 0 &&
            strcmp(cmd->argv[3], "group") != 0) {
        CONF_ERROR(cmd, "third parameter must be 'user' or 'group'");
    }

    bad_action = pr_ctrls_set_module_acls(dynmasq_acttab, dynmasq_act_pool,
                                          actions, cmd->argv[2], cmd->argv[3], cmd->argv[4]);
    if (bad_action != NULL) {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown action: '",
                                bad_action, "'", NULL));
    }

    return PR_HANDLED(cmd);
#else
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "The ", cmd->argv[0],
                            " directive requires Controls support (--enable-ctrls)", NULL));
#endif /* PR_USE_CTRLS */
}
MODRET add_lmd_allow_user_regex(cmd_rec *cmd) {
    array_header *list;
    pr_regex_t *pre;
    int i, res;
    config_rec *c;

    if(cmd->argc < 2)
        CONF_ERROR(cmd, "missing argument");
    CHECK_CONF(cmd, CONF_ROOT|CONF_GLOBAL);

    /* argv => LMDBAllowUserRegex ^test */
    c = find_config(cmd->server->conf, CONF_PARAM, "LMDBAllowedUserRegex", FALSE);
    if(c && c->argv[0]) {
        list = c->argv[0];
    } else {
        c = add_config_param(cmd->argv[0], 0, NULL);
        c->argv[0] = list = make_array(cmd->server->pool, 0, sizeof(regex_t *));
    }

    for(i=1; i < cmd->argc; i++) {
        pre = pr_regexp_alloc(&libmemcached_deny_blacklist_module);
        res = pr_regexp_compile(pre, cmd->argv[i], REG_NOSUB);
        if (res != 0) {
            char errstr[200] = {'\0'};
            pr_regexp_error(res, pre, errstr, sizeof(errstr));
            pr_regexp_free(NULL, pre);
            CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", cmd->argv[i], "' failed "
               "regex compilation: ", errstr, NULL));
        }
        *((pr_regex_t **) push_array(list)) = pre;
        pr_log_debug(DEBUG2,
            "%s: add LMDBAllowedUserRegex[%d] %s", MODULE_NAME, i, cmd->argv[i]);
    }

    return PR_HANDLED(cmd);
}
MODRET set_lmd_ignore_memcached_down(cmd_rec *cmd) {
  int ignore = -1;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  ignore = get_boolean(cmd, 1);
  if (ignore == -1)
    CONF_ERROR(cmd, "expected Boolean parameter");

  if(ignore == TRUE) {
      ignore_memcached_down = true;
  }

  return PR_HANDLED(cmd);
}
Example #20
0
/* usage: CopyEngine on|off */
MODRET set_copyengine(cmd_rec *cmd) {
  int engine = -1;
  config_rec *c;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  engine = get_boolean(cmd, 1);
  if (engine == -1) {
    CONF_ERROR(cmd, "expected Boolean parameter");
  }

  c = add_config_param(cmd->argv[0], 1, NULL);
  c->argv[0] = palloc(c->pool, sizeof(int));
  *((int *) c->argv[0]) = engine;

  return PR_HANDLED(cmd);
}
MODRET add_lmd_allow_user(cmd_rec *cmd) {
    config_rec *c;
    int i;
    pr_table_t *explicit_users;

    if(cmd->argc < 2)
        CONF_ERROR(cmd, "missing argument");

    CHECK_CONF(cmd, CONF_ROOT|CONF_GLOBAL);

    /* argv => LMDBAllowedUser nobody nobody1 nobody2 */
    c = find_config(main_server->conf, CONF_PARAM, "LMDBAllowedUser", FALSE);
    if(c && c->argv[0]) {
        explicit_users = c->argv[0];
    } else {
        c = add_config_param(cmd->argv[0], 0, NULL);
        c->argv[0] = explicit_users = pr_table_alloc(main_server->pool, 0);
    }

    for(i=1; i < cmd->argc; i++) {
        const char *account = pstrdup(main_server->pool, cmd->argv[i]);
        if(pr_table_exists(explicit_users, account) > 0) {
            pr_log_debug(DEBUG2,
                "%s: %s is already registerd", MODULE_NAME, account);
            continue;
        }

        if(pr_table_add_dup(explicit_users, account, "y", 0) < 0){
            pr_log_pri(PR_LOG_ERR,
                "%s: failed pr_table_add_dup(): %s",
                 MODULE_NAME, strerror(errno));
            exit(1);
        }
        pr_log_debug(DEBUG2,
            "%s: add LMDBAllowedUser[%d] %s", MODULE_NAME, i, account);
    }

    return PR_HANDLED(cmd);
}
Example #22
0
/**
 * 配置初始化
 */
int TestContext::cfg_init(const char* config, ngx_tcp_server_srv_conf_t* tcp_svr_cfg)
{
	test_config_t* testcfg = &this->m_config;
	CIniFile inifile(config);
	if(!inifile.ReadFile()){
		CONF_ERROR("read config [%s] failed! err: %s", config, strerror(errno));
		return NGX_ERROR;
	} 

	string ip = inifile.GetValue("backend", "ip", "127.0.0.1");
	strncpy(testcfg->backend_ip, ip.c_str(), sizeof(testcfg->backend_ip));
	testcfg->backend_port = inifile.GetValueI("backend", "port", 2014);
	
	mysql_config_read(&inifile, &testcfg->mysql_config, "mysql");
	//这一步很重要,当使用异步方式时,timeout必须为0,否则mysql_connect会出错。
	
	if(tcp_svr_cfg->use_async){
		testcfg->mysql_config.timeout = 0;
	}
	NLOG_DEBUG("mysql: config:%s", testcfg->mysql_config.host);
	return NGX_OK;
}
Example #23
0
/* usage: ModuleOrder mod1 mod2 ... modN */
MODRET set_moduleorder(cmd_rec *cmd) {
  register unsigned int i;
  module *m, *mn, *module_list = NULL;

  if (cmd->argc-1 < 1)
    CONF_ERROR(cmd, "wrong number of parameters");

  CHECK_CONF(cmd, CONF_ROOT);

  /* What about duplicate names in the list?
   *
   * What if the given list is longer than the one already in loaded_modules?
   * This will be caught by the existence check.  Otherwise, the only way for
   * the list to be longer is if there are duplicates, which will be caught
   * by the duplicate check.
   */

  /* Make sure the given module names exist. */
  for (i = 1; i < cmd->argc; i++) {
    if (pr_module_get(cmd->argv[i]) == NULL)
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "no such module '", cmd->argv[i],
      "' loaded", NULL));
  }

  /* Make sure there are no duplicate module names in the list. */
  for (i = 1; i < cmd->argc; i++) {
    register unsigned int j;

    for (j = i + 1; j < cmd->argc; j++) {
      if (strcmp(cmd->argv[i], cmd->argv[j]) == 0) {
        char ibuf[4], jbuf[4];

        snprintf(ibuf, sizeof(ibuf), "%u", i);
        ibuf[sizeof(ibuf)-1] = '\0';

        snprintf(jbuf, sizeof(jbuf), "%u", j);
        jbuf[sizeof(jbuf)-1] = '\0';

        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
          "duplicate module name '", cmd->argv[i], "' as parameters ",
          ibuf, " and ", jbuf, NULL));
      }
    }
  }

  pr_log_debug(DEBUG4, "%s: reordering modules", cmd->argv[0]);
  for (i = 1; i < cmd->argc; i++) {
    m = pr_module_get(cmd->argv[i]);

    if (module_list) {
      m->next = module_list;
      module_list->prev = m;
      module_list = m;

    } else
      module_list = m;
  }

  /* Now, unload all the modules in the loaded_modules list, then load
   * the modules in our module_list.
   */
  for (m = loaded_modules; m;) {
    mn = m->next;

    if (pr_module_unload(m) < 0) {
      pr_log_debug(DEBUG0, "%s: error unloading module 'mod_%s.c': %s",
        cmd->argv[0], m->name, strerror(errno));
    }

    m = mn;
  }

  for (m = module_list; m; m = m->next) {
    if (pr_module_load(m) < 0) {
      pr_log_debug(DEBUG0, "%s: error loading module 'mod_%s.c': %s",
        cmd->argv[0], m->name, strerror(errno));
      exit(1);
    }
  }

  pr_log_pri(PR_LOG_NOTICE, "module order is now:");
  for (m = loaded_modules; m; m = m->next) {
    pr_log_pri(PR_LOG_NOTICE, " mod_%s.c", m->name);
  }

  return PR_HANDLED(cmd);
}
Example #24
0
/* Usage: <IfVersion [!]op version-string|regex> */
MODRET start_ifversion(cmd_rec *cmd) {
  unsigned int ifversion_ctx_count = 1;
  int compared, matched = FALSE, negated = FALSE;
  char buf[PR_TUNABLE_BUFFER_SIZE], *config_line = NULL;
  char *error = NULL, *version_str = NULL, *op_str = NULL;
  size_t op_len;

  if (cmd->argc-1 == 0 ||
      cmd->argc-1 > 2) {
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  if (cmd->argc-1 == 2) {
    op_str = cmd->argv[1];

    if (*op_str == '!' &&
        strlen(op_str) > 1) {
      negated = TRUE;
      op_str++;
    }

    op_len = strlen(op_str);
    version_str = cmd->argv[2];

  } else {
    /* Assume that if only a version-string was supplied, the operator
     * is intended to be the equality operator.
     */
    op_str = "=";
    op_len = 1;
    version_str = cmd->argv[1];
  }

  switch (*op_str) {
    case '=':
      if (*version_str != '/') {
        /* Normal equality comparison */
        compared = compare_version(cmd->tmp_pool, version_str, &error);
        if (error != NULL) {
          CONF_ERROR(cmd, error);
        }

        matched = (compared == 0);
        break;
      }

      /* Otherwise, it's a regular expression */
      if (version_str[strlen(version_str)-1] != '/') {
        CONF_ERROR(cmd, "Missing terminating '/' of regular expression");
      }

      /* Fall through to the next case in order to handle/evaluate the
       * regular expression.  Be sure to remove the bracketing '/' characters
       * for the regex compilation.
       */
      version_str[strlen(version_str)-1] = '\0';
      version_str++;

    case '~': 
      /* Regular expression */
      matched = match_version(cmd->tmp_pool, version_str, &error);
      if (error != NULL) {
        CONF_ERROR(cmd, error);
      }

      break;

    case '<':
      compared = compare_version(cmd->tmp_pool, version_str, &error);
      if (error != NULL) {
        CONF_ERROR(cmd, error);
      }

      if (compared == -1 ||
          (op_len == 2 && compared == 0)) {
        matched = TRUE;
      }

      break;

    case '>':
      compared = compare_version(cmd->tmp_pool, version_str, &error);
      if (error != NULL) {
        CONF_ERROR(cmd, error);
      }

      if (compared == 1 ||
          (op_len == 2 && compared == 0)) {
        matched = TRUE;
      }

      break;

    default:
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown comparison operator '",
        op_str, "'", NULL));
  } 

  if ((matched && !negated) ||
      (!matched && negated)) {
    pr_log_debug(DEBUG3, "%s: using '%s %s' section at line %u",
      cmd->argv[0], cmd->argv[1], cmd->argv[2], pr_parser_get_lineno());
      return PR_HANDLED(cmd);
  }

  pr_log_debug(DEBUG3, "%s: skipping '%s %s' section at line %u",
    cmd->argv[0], cmd->argv[1], cmd->argv[2], pr_parser_get_lineno());

  while (ifversion_ctx_count > 0 &&
         (config_line = pr_parser_read_line(buf, sizeof(buf))) != NULL) {
    pr_signals_handle();

    if (strncasecmp(config_line, "<IfVersion", 10) == 0) {
      ifversion_ctx_count++;
    }

    if (strcasecmp(config_line, "</IfVersion>") == 0) {
      ifversion_ctx_count--;
    }
  }

  /* If there are still unclosed <IfVersion> sections, signal an error.
   */
  if (ifversion_ctx_count > 0) {
    CONF_ERROR(cmd, "unclosed <IfVersion> section");
  }

  return PR_HANDLED(cmd);
}
Example #25
0
/* usage: AuthGroupFile path [id <min-max>] [name <regex>] */
MODRET set_authgroupfile(cmd_rec *cmd) {
  config_rec *c = NULL;
  authfile_file_t *file = NULL;
  int flags = 0;
  char *path;

#ifdef PR_USE_REGEX
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 5) {
#else
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 2) {
#endif /* regex support */
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  path = cmd->argv[1];
  if (*path != '/') {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use relative path for ", (char *) cmd->argv[0], " '",
      path, "'.", NULL));
  }

  /* Make sure the configured file has the correct permissions.  Note that
   * AuthGroupFiles, unlike AuthUserFiles, do not contain any sensitive
   * information, and can thus be world-readable.
   */
  flags = PR_AUTH_FILE_FL_ALLOW_WORLD_READABLE;
  if (af_check_file(cmd->tmp_pool, cmd->argv[0], cmd->argv[1], flags) < 0) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use ", path, ": ", strerror(errno), NULL));
  }

  c = add_config_param(cmd->argv[0], 1, NULL);

  file = pcalloc(c->pool, sizeof(authfile_file_t));
  file->af_path = pstrdup(c->pool, path);
  c->argv[0] = (void *) file;

  /* Check for restrictions */
  if (cmd->argc-1 != 1) {
    register unsigned int i = 0;

    for (i = 2; i < cmd->argc; i++) {
      if (strncmp(cmd->argv[i], "id", 3) == 0) {
        gid_t min, max;
        char *sep = NULL, *tmp = NULL;

        /* The range restriction parameter is of the form "min-max", where max
         * must be >= min.
         */

        sep = strchr(cmd->argv[++i], '-');
        if (sep == NULL) {
          CONF_ERROR(cmd, "badly formatted ID restriction parameter");
        }

        *sep = '\0';

        min = strtol(cmd->argv[i], &tmp, 10);
        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted minimum ID");
        }

        tmp = NULL;

        max = strtol(sep+1, &tmp, 10);
        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted maximum ID");
        }

        if (min > max) {
          CONF_ERROR(cmd, "minimum cannot be larger than maximum");
        }

        file->af_min_id.gid = min;
        file->af_max_id.gid = max;
        file->af_restricted_ids = TRUE;

#ifdef PR_USE_REGEX
      } else if (strncmp(cmd->argv[i], "name", 5) == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_name_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_name_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_name_regex = pre;
        file->af_restricted_names = TRUE;
#endif /* regex support */

      } else {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown restriction '",
          cmd->argv[i], "'", NULL));
      }
    }
  }

  return PR_HANDLED(cmd);
}

/* usage: AuthUserFile path [home <regexp>] [id <min-max>] [name <regex>] */
MODRET set_authuserfile(cmd_rec *cmd) {
  config_rec *c = NULL;
  authfile_file_t *file = NULL;
  int flags = 0;
  char *path;

#ifdef PR_USE_REGEX
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 7) {
#else
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 2) {
#endif /* regex support */
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  path = cmd->argv[1];
  if (*path != '/') {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use relative path for ", (char *) cmd->argv[0], " '",
      path, "'.", NULL));
  }

  /* Make sure the configured file has the correct permissions.  Note that
   * AuthUserFiles, unlike AuthGroupFiles, DO contain any sensitive
   * information, and thus CANNOT be world-readable.
   */
  flags = 0;
  if (af_check_file(cmd->tmp_pool, cmd->argv[0], cmd->argv[1], flags) < 0) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use ", path, ": ", strerror(errno), NULL));
  }

  c = add_config_param(cmd->argv[0], 1, NULL);

  file = pcalloc(c->pool, sizeof(authfile_file_t));
  file->af_path = pstrdup(c->pool, path);
  c->argv[0] = (void *) file;

  /* Check for restrictions */
  if (cmd->argc-1 != 1) {
    register unsigned int i = 0;

    for (i = 2; i < cmd->argc; i++) {
      if (strncmp(cmd->argv[i], "id", 3) == 0) {
        uid_t min, max;
        char *sep = NULL, *tmp = NULL;

        /* The range restriction parameter is of the form "min-max", where max
         * must be >= min.
         */

        sep = strchr(cmd->argv[++i], '-');
        if (sep == NULL) {
          CONF_ERROR(cmd, "badly formatted ID restriction parameter");
        }

        *sep = '\0';

        min = strtol(cmd->argv[i], &tmp, 10);
        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted minimum ID");
        }

        tmp = NULL;

        max = strtol(sep+1, &tmp, 10);

        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted maximum ID");
        }

        if (min > max) {
          CONF_ERROR(cmd, "minimum cannot be larger than maximum");
        }

        file->af_min_id.uid = min;
        file->af_max_id.uid = max;
        file->af_restricted_ids = TRUE;

#ifdef PR_USE_REGEX
      } else if (strncmp(cmd->argv[i], "home", 5) == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_home_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_home_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_home_regex = pre;
        file->af_restricted_homes = TRUE;

      } else if (strncmp(cmd->argv[i], "name", 5) == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_name_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_name_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_name_regex = pre;
        file->af_restricted_names = TRUE;
#endif /* regex support */

      } else {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown restriction '",
          cmd->argv[i], "'", NULL));
      }
    }
  }

  return PR_HANDLED(cmd);
}

/* Event listeners
 */

static void authfile_sess_reinit_ev(const void *event_data, void *user_data) {
  int res;

  /* A HOST command changed the main_server pointer, reinitialize ourselves. */

  pr_event_unregister(&auth_file_module, "core.session-reinit",
    authfile_sess_reinit_ev);

  af_user_file = NULL;
  af_group_file = NULL;

  res = authfile_sess_init();
  if (res < 0) {
    pr_session_disconnect(&auth_file_module,
      PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL);
  }
}
Example #26
0
/* usage: AuthGroupFile path [id <min-max>] [name <regex>] */
MODRET set_authgroupfile(cmd_rec *cmd) {
  config_rec *c = NULL;
  authfile_file_t *file = NULL;

#ifdef PR_USE_REGEX
  if (cmd->argc-1 < 1 || cmd->argc-1 > 5)
#else
  if (cmd->argc-1 < 1 || cmd->argc-1 > 2)
#endif /* regex support */
    CONF_ERROR(cmd, "wrong number of parameters");

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  if (*(cmd->argv[1]) != '/')
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use relative path for ", cmd->argv[0], " '",
      cmd->argv[1], "'.", NULL));

  c = add_config_param(cmd->argv[0], 1, NULL);

  file = pcalloc(c->pool, sizeof(authfile_file_t));
  file->af_path = pstrdup(c->pool, cmd->argv[1]);
  c->argv[0] = (void *) file;

  /* Check for restrictions */
  if (cmd->argc-1 != 1) {
    register unsigned int i = 0;

    for (i = 2; i < cmd->argc; i++) {
      if (strcmp(cmd->argv[i], "id") == 0) {
        gid_t min, max;
        char *sep = NULL, *tmp = NULL;

        /* The range restriction parameter is of the form "min-max", where max
         * must be >= min.
         */

        sep = strchr(cmd->argv[++i], '-');
        if (sep == NULL)
          CONF_ERROR(cmd, "badly formatted ID restriction parameter");

        *sep = '\0';

        min = strtol(cmd->argv[i], &tmp, 10);

        if (tmp && *tmp)
          CONF_ERROR(cmd, "badly formatted minimum ID");

        tmp = NULL;

        max = strtol(sep+1, &tmp, 10);

        if (tmp && *tmp)
          CONF_ERROR(cmd, "badly formatted maximum ID");

        if (min > max)
          CONF_ERROR(cmd, "minimum cannot be larger than maximum");

        file->af_min_id.gid = min;
        file->af_max_id.gid = max;
        file->af_restricted_ids = TRUE;

#ifdef PR_USE_REGEX
      } else if (strcmp(cmd->argv[i], "name") == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_name_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_name_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_name_regex = pre;
        file->af_restricted_names = TRUE;
#endif /* regex support */

      } else {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown restriction '",
          cmd->argv[i], "'", NULL));
      }
    }
  }

  return PR_HANDLED(cmd);
}
Example #27
0
/* usage: AuthGroupFile path [id <min-max>] [name <regex>] */
MODRET set_authgroupfile(cmd_rec *cmd) {
  config_rec *c = NULL;
  authfile_file_t *file = NULL;
  int flags = 0;

#ifdef PR_USE_REGEX
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 5) {
#else
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 2) {
#endif /* regex support */
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  if (*(cmd->argv[1]) != '/') {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use relative path for ", cmd->argv[0], " '",
      cmd->argv[1], "'.", NULL));
  }

  /* Make sure the configured file has the correct permissions.  Note that
   * AuthGroupFiles, unlike AuthUserFiles, do not contain any sensitive
   * information, and can thus be world-readable.
   */
  flags = PR_AUTH_FILE_FL_ALLOW_WORLD_READABLE;
  if (af_check_file(cmd->tmp_pool, cmd->argv[0], cmd->argv[1], flags) < 0) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use ", cmd->argv[1], ": ", strerror(errno), NULL));
  }

  c = add_config_param(cmd->argv[0], 1, NULL);

  file = pcalloc(c->pool, sizeof(authfile_file_t));
  file->af_path = pstrdup(c->pool, cmd->argv[1]);
  c->argv[0] = (void *) file;

  /* Check for restrictions */
  if (cmd->argc-1 != 1) {
    register unsigned int i = 0;

    for (i = 2; i < cmd->argc; i++) {
      if (strncmp(cmd->argv[i], "id", 3) == 0) {
        gid_t min, max;
        char *sep = NULL, *tmp = NULL;

        /* The range restriction parameter is of the form "min-max", where max
         * must be >= min.
         */

        sep = strchr(cmd->argv[++i], '-');
        if (sep == NULL) {
          CONF_ERROR(cmd, "badly formatted ID restriction parameter");
        }

        *sep = '\0';

        min = strtol(cmd->argv[i], &tmp, 10);
        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted minimum ID");
        }

        tmp = NULL;

        max = strtol(sep+1, &tmp, 10);
        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted maximum ID");
        }

        if (min > max) {
          CONF_ERROR(cmd, "minimum cannot be larger than maximum");
        }

        file->af_min_id.gid = min;
        file->af_max_id.gid = max;
        file->af_restricted_ids = TRUE;

#ifdef PR_USE_REGEX
      } else if (strncmp(cmd->argv[i], "name", 5) == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_name_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_name_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_name_regex = pre;
        file->af_restricted_names = TRUE;
#endif /* regex support */

      } else {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown restriction '",
          cmd->argv[i], "'", NULL));
      }
    }
  }

  return PR_HANDLED(cmd);
}

/* usage: AuthUserFile path [home <regexp>] [id <min-max>] [name <regex>] */
MODRET set_authuserfile(cmd_rec *cmd) {
  config_rec *c = NULL;
  authfile_file_t *file = NULL;
  int flags = 0;

#ifdef PR_USE_REGEX
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 7) {
#else
  if (cmd->argc-1 < 1 ||
      cmd->argc-1 > 2) {
#endif /* regex support */
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  if (*(cmd->argv[1]) != '/') {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use relative path for ", cmd->argv[0], " '",
      cmd->argv[1], "'.", NULL));
  }

  /* Make sure the configured file has the correct permissions.  Note that
   * AuthUserFiles, unlike AuthGroupFiles, DO contain any sensitive
   * information, and thus CANNOT be world-readable.
   */
  flags = 0;
  if (af_check_file(cmd->tmp_pool, cmd->argv[0], cmd->argv[1], flags) < 0) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "unable to use ", cmd->argv[1], ": ", strerror(errno), NULL));
  }

  c = add_config_param(cmd->argv[0], 1, NULL);

  file = pcalloc(c->pool, sizeof(authfile_file_t));
  file->af_path = pstrdup(c->pool, cmd->argv[1]);
  c->argv[0] = (void *) file;

  /* Check for restrictions */
  if (cmd->argc-1 != 1) {
    register unsigned int i = 0;

    for (i = 2; i < cmd->argc; i++) {
      if (strncmp(cmd->argv[i], "id", 3) == 0) {
        uid_t min, max;
        char *sep = NULL, *tmp = NULL;

        /* The range restriction parameter is of the form "min-max", where max
         * must be >= min.
         */

        sep = strchr(cmd->argv[++i], '-');
        if (sep == NULL) {
          CONF_ERROR(cmd, "badly formatted ID restriction parameter");
        }

        *sep = '\0';

        min = strtol(cmd->argv[i], &tmp, 10);
        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted minimum ID");
        }

        tmp = NULL;

        max = strtol(sep+1, &tmp, 10);

        if (tmp && *tmp) {
          CONF_ERROR(cmd, "badly formatted maximum ID");
        }

        if (min > max) {
          CONF_ERROR(cmd, "minimum cannot be larger than maximum");
        }

        file->af_min_id.uid = min;
        file->af_max_id.uid = max;
        file->af_restricted_ids = TRUE;

#ifdef PR_USE_REGEX
      } else if (strncmp(cmd->argv[i], "home", 5) == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_home_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_home_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_home_regex = pre;
        file->af_restricted_homes = TRUE;

      } else if (strncmp(cmd->argv[i], "name", 5) == 0) {
        char *filter = cmd->argv[++i];
        pr_regex_t *pre = NULL;
        int res = 0;

        pre = pr_regexp_alloc(&auth_file_module);

        /* Check for a ! negation/inversion filter prefix. */
        if (*filter == '!') {
          filter++;
          file->af_name_regex_inverted = TRUE;
        }

        res = pr_regexp_compile(pre, filter, REG_EXTENDED|REG_NOSUB);
        if (res != 0) {
          char errstr[200] = {'\0'};

          pr_regexp_error(res, pre, errstr, sizeof(errstr));
          pr_regexp_free(NULL, pre);

          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "'", filter, "' failed "
            "regex compilation: ", errstr, NULL));
        }

        file->af_name_filter = pstrdup(c->pool, cmd->argv[i]);
        file->af_name_regex = pre;
        file->af_restricted_names = TRUE;
#endif /* regex support */

      } else {
        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown restriction '",
          cmd->argv[i], "'", NULL));
      }
    }
  }

  return PR_HANDLED(cmd);
}

/* Command handlers
 */

MODRET authfile_post_host(cmd_rec *cmd) {

  /* If the HOST command changed the main_server pointer, reinitialize
   * ourselves.
   */
  if (session.prev_server != NULL) {
    int res;

    af_user_file = NULL;
    af_group_file = NULL;

    res = authfile_sess_init();
    if (res < 0) {
      pr_session_disconnect(&auth_file_module,
        PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL);
    }
  }

  return PR_DECLINED(cmd);
}

/* Initialization routines
 */

static int authfile_init(void) {
  const char *key, *salt, *hash;

  /* On some Unix platforms, giving crypt(3) an empty string for the salt,
   * no matter what the input key, results in an empty string being returned.
   * (The salt string is what is obtained from the AuthUserFile that has been
   * configured.)
   *
   * On other platforms, given crypt(3) a real key and an empty string for
   * the salt returns in a real string.  (I'm looking at you, Mac OSX.)
   *
   * Thus in order to handle the edge case of an AuthUserFile with a passwd
   * field being empty the same on such differing platforms, we perform a
   * runtime check (at startup), to see how crypt(3) behaves -- and then
   * preserve the principle of least surprise appropriately.
   */

  key = "key";
  salt = "";
  hash = crypt(key, salt);
  if (hash != NULL) {
    if (strcmp(hash, "") != 0) {
      /* We're probably on a Mac OSX or similar platform. */
      handle_empty_salt = TRUE;
    }
  }

  return 0;
}

static int authfile_sess_init(void) {
  config_rec *c = NULL;

  c = find_config(main_server->conf, CONF_PARAM, "AuthUserFile", FALSE);
  if (c) {
    af_user_file = c->argv[0];
  }

  c = find_config(main_server->conf, CONF_PARAM, "AuthGroupFile", FALSE);
  if (c) {
    af_group_file = c->argv[0];
  }

  return 0;
}
Example #28
0
/* This function was copied, almost verbatim, from the set_sysloglevel()
 * function in modules/mod_core.c.  I hereby cite the source for this code
 * as MacGuyver <*****@*****.**>. =)
 */
MODRET set_tcpaccesssysloglevels(cmd_rec *cmd) {
  config_rec *c = NULL;
  int allow_level, deny_level;

  CHECK_ARGS(cmd, 2);
  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_ANON|CONF_GLOBAL);

  if (!strcasecmp(cmd->argv[1], "emerg")) {
    allow_level = PR_LOG_EMERG;

  } else if (!strcasecmp(cmd->argv[1], "alert")) {
    allow_level = PR_LOG_ALERT;

  } else if (!strcasecmp(cmd->argv[1], "crit")) {
    allow_level = PR_LOG_CRIT;

  } else if (!strcasecmp(cmd->argv[1], "error")) {
    allow_level = PR_LOG_ERR;

  } else if (!strcasecmp(cmd->argv[1], "warn")) {
    allow_level = PR_LOG_WARNING;

  } else if (!strcasecmp(cmd->argv[1], "notice")) {
    allow_level = PR_LOG_NOTICE;

  } else if (!strcasecmp(cmd->argv[1], "info")) {
    allow_level = PR_LOG_INFO;

  } else if (!strcasecmp(cmd->argv[1], "debug")) {
    allow_level = PR_LOG_DEBUG;

  } else {
    CONF_ERROR(cmd, "TCPAccessSyslogLevels requires \"allow\" level keyword: "
      "one of emerg/alert/crit/error/warn/notice/info/debug");
  }

  if (!strcasecmp(cmd->argv[2], "emerg")) {
    deny_level = PR_LOG_EMERG;

  } else if(!strcasecmp(cmd->argv[2], "alert")) {
    deny_level = PR_LOG_ALERT;

  } else if(!strcasecmp(cmd->argv[2], "crit")) {
    deny_level = PR_LOG_CRIT;

  } else if(!strcasecmp(cmd->argv[2], "error")) {
    deny_level = PR_LOG_ERR;

  } else if(!strcasecmp(cmd->argv[2], "warn")) {
    deny_level = PR_LOG_WARNING;

  } else if(!strcasecmp(cmd->argv[2], "notice")) {
    deny_level = PR_LOG_NOTICE;

  } else if(!strcasecmp(cmd->argv[2], "info")) {
    deny_level = PR_LOG_INFO;

  } else if(!strcasecmp(cmd->argv[2], "debug")) {
    deny_level = PR_LOG_DEBUG;

  } else {
    CONF_ERROR(cmd, "TCPAccessSyslogLevels requires \"deny\" level keyword: "
      "one of emerg/alert/crit/error/warn/notice/info/debug");
  }

  c = add_config_param(cmd->argv[0], 2, (void *) allow_level,
    (void *) deny_level);
  c->flags |= CF_MERGEDOWN;

  return HANDLED(cmd);
}
Example #29
0
/* usage: MemcacheTimeouts conn-timeout read-timeout write-timeout
 *                         [ejected-timeout]
 */
MODRET set_memcachetimeouts(cmd_rec *cmd) {
  config_rec *c;
  unsigned long conn_millis, read_millis, write_millis, ejected_sec = 0;
  char *ptr = NULL;

  if (cmd->argc-1 < 3 ||
      cmd->argc-1 > 4) {
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);

  conn_millis = strtoul(cmd->argv[1], &ptr, 10);
  if (ptr && *ptr) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "badly formatted connect timeout value: ", cmd->argv[1], NULL));
  }

  ptr = NULL;
  read_millis = strtoul(cmd->argv[2], &ptr, 10);
  if (ptr && *ptr) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "badly formatted read timeout value: ", cmd->argv[2], NULL));
  }

  ptr = NULL;
  write_millis = strtoul(cmd->argv[3], &ptr, 10);
  if (ptr && *ptr) {
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
      "badly formatted write timeout value: ", cmd->argv[3], NULL));
  }

  if (cmd->argc-1 == 4) {
    ptr = NULL;
    ejected_sec = strtoul(cmd->argv[4], &ptr, 10);
    if (ptr && *ptr) {
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool,
        "badly formatted retry timeout value: ", cmd->argv[4], NULL));
    }
  }

#if 0
  /* XXX If we're the "server config" context, set the timeouts now.
   * This would let mod_memcache talk to those servers for e.g. ftpdctl
   * actions.
   */
  memcache_set_timeouts(conn_timeout, read_timeout, write_timeout,
    ejected_sec);
#endif

  c = add_config_param(cmd->argv[0], 4, NULL, NULL, NULL, NULL);
  c->argv[0] = palloc(c->pool, sizeof(unsigned long));
  *((unsigned long *) c->argv[0]) = conn_millis;
  c->argv[1] = palloc(c->pool, sizeof(unsigned long));
  *((unsigned long *) c->argv[1]) = read_millis;
  c->argv[2] = palloc(c->pool, sizeof(unsigned long));
  *((unsigned long *) c->argv[2]) = write_millis;
  c->argv[3] = palloc(c->pool, sizeof(unsigned long));
  *((unsigned long *) c->argv[3]) = ejected_sec;

  return PR_HANDLED(cmd);
}