static bool is_allowed_user(cmd_rec *cmd, const char *account) { config_rec *c; /* ハッシュテーブルにアカウントがあるか否か */ c = find_config(cmd->server->conf, CONF_PARAM, "LMDBAllowedUser", FALSE); if(c && c->argv[0]) { pr_table_t *explicit_users = c->argv[0]; if(pr_table_exists(explicit_users, account) > 0 ) { pr_log_debug(DEBUG2, "%s: '%s' match with LMDBAllowedUser", MODULE_NAME, account); return true; } } /* 正規表現にマッチするか否か */ c = find_config(cmd->server->conf, CONF_PARAM, "LMDBAllowedUserRegex", FALSE); if(c && c->argv[0]) { int i; array_header *regex_list = c->argv[0]; regex_t ** elts = regex_list->elts; for (i = 0; i < regex_list->nelts; i++) { regex_t *preg = elts[i]; if(regexec(preg, account, 0, NULL, 0) == 0) { pr_log_debug(DEBUG2, "%s: '%s' match with LMDBAllowedUserRegex", MODULE_NAME, account); return true; } } } return false; }
int proxy_forward_sess_init(pool *p, const char *tables_dir, struct proxy_session *proxy_sess) { config_rec *c; int allowed = FALSE; void *enabled = NULL; /* By default, only allow connections from RFC1918 addresses to use * forward proxying. Otherwise, it must be from an explicitly allowed * connection class, via the class notes. */ if (session.conn_class != NULL) { enabled = pr_table_get(session.conn_class->cls_notes, PROXY_FORWARD_ENABLED_NOTE, NULL); } if (enabled != NULL) { allowed = *((int *) enabled); if (allowed == FALSE) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "forward proxying not allowed from client address %s in <Class %s> " "(see ProxyForwardEnabled)", pr_netaddr_get_ipstr(session.c->remote_addr), session.conn_class->cls_name); } } else { if (pr_netaddr_is_rfc1918(session.c->remote_addr) == TRUE) { allowed = TRUE; } else { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "forward proxying not allowed from non-RFC1918 client address %s", pr_netaddr_get_ipstr(session.c->remote_addr)); } } if (allowed == FALSE) { errno = EPERM; return -1; } c = find_config(main_server->conf, CONF_PARAM, "ProxyForwardMethod", FALSE); if (c != NULL) { proxy_method = *((int *) c->argv[0]); } c = find_config(main_server->conf, CONF_PARAM, "ProxyRetryCount", FALSE); if (c != NULL) { forward_retry_count = *((int *) c->argv[0]); } 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; }
static void qos_data_connect_ev(const void *event_data, void *user_data) { const struct socket_ctx *sc; sc = event_data; /* Only set TOS flags on IPv4 sockets; IPv6 sockets don't seem to support * them. */ if (pr_netaddr_get_family(sc->addr) == AF_INET) { config_rec *c; c = find_config(sc->server->conf, CONF_PARAM, "QoSOptions", FALSE); if (c) { int dataqos, res; dataqos = *((int *) c->argv[1]); res = setsockopt(sc->sockfd, ip_level, IP_TOS, (void *) &dataqos, sizeof(dataqos)); if (res < 0) { pr_log_pri(PR_LOG_NOTICE, MOD_QOS_VERSION ": error setting data socket IP_TOS: %s", strerror(errno)); } } } }
static bool is_allowed(cmd_rec *cmd, pr_netaddr_t *na) { int i; config_rec *c; array_header *allowed_acls; c = find_config(cmd->server->conf, CONF_PARAM, "LMDBAllow", FALSE); if(NULL == c) return false; allowed_acls = c->argv[0]; if(NULL == allowed_acls) { pr_log_auth(PR_LOG_ERR, "%s: pr_table_t is NULL. something fatal", MODULE_NAME); return false; } #ifdef DEBUG pr_table_do(allowed_acls, walk_table, NULL, 0); #endif pr_netacl_t **elts = allowed_acls->elts; for (i = 0; i < allowed_acls->nelts; i++) { pr_netacl_t *acl = elts[i]; if(pr_netacl_match(acl, na) == 1) { pr_log_auth(PR_LOG_INFO, "%s: client IP matched with LMDBAllow '%s'. Skip last process", MODULE_NAME, pr_netacl_get_str(cmd->tmp_pool, acl)); return true; } } return false; }
MODRET memcache_post_host(cmd_rec *cmd) { /* If the HOST command changed the main_server pointer, reinitialize * ourselves. */ if (session.prev_server != NULL) { int res; config_rec *c; pr_event_unregister(&memcache_module, "core.exit", mcache_exit_ev); (void) close(memcache_logfd); c = find_config(session.prev_server->conf, CONF_PARAM, "MemcacheServers", FALSE); if (c != NULL) { memcached_server_st *memcache_servers; memcache_servers = c->argv[0]; memcache_set_servers(memcache_servers); } /* XXX Restore other memcache settings? */ res = mcache_sess_init(); if (res < 0) { pr_session_disconnect(&memcache_module, PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL); } } return PR_DECLINED(cmd); }
static void resolve_deferred_patterns(pool *p, const char *directive) { #if PR_USE_REGEX config_rec *c; c = find_config(main_server->conf, CONF_PARAM, directive, FALSE); while (c != NULL) { register unsigned int i; array_header *deferred_filters, *filters; pr_signals_handle(); filters = c->argv[0]; deferred_filters = c->argv[1]; for (i = 0; i < deferred_filters->nelts; i++) { const char *query_name; array_header *sql_filters; query_name = ((const char **) deferred_filters->elts)[i]; sql_filters = get_sql_filters(p, query_name); if (sql_filters == NULL) { continue; } array_cat(filters, sql_filters); } c = find_config_next(c, c->next, CONF_PARAM, directive, FALSE); } #endif /* PR_USE_REGEX */ }
/*! \brief Finds Config. \details Looks for Config up the EventType tree until Config is found or the root EventType is reached. Uses dmz::Config::lookup_all_config_merged(). \param[in] Name String containing the name of the Config data to find. \return Returns a Config object. The Config object will be empty if the named Config can not be found. */ dmz::Config dmz::EventType::find_config (const String &Name) const { EventType type; return find_config (Name, type); }
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); }
static void mcache_sess_reinit_ev(const void *event_data, void *user_data) { int res; config_rec *c; /* A HOST command changed the main_server pointer, reinitialize ourselves. */ pr_event_unregister(&memcache_module, "core.exit", mcache_exit_ev); pr_event_unregister(&memcache_module, "core.session-reinit", mcache_sess_reinit_ev); (void) close(memcache_logfd); memcache_logfd = -1; c = find_config(session.prev_server->conf, CONF_PARAM, "MemcacheServers", FALSE); if (c != NULL) { memcached_server_st *memcache_servers; memcache_servers = c->argv[0]; memcache_set_servers(memcache_servers); } /* XXX Restore other memcache settings? */ /* reset MemcacheOptions */ /* reset MemcacheReplicas */ /* reset MemcacheTimeout */ res = mcache_sess_init(); if (res < 0) { pr_session_disconnect(&memcache_module, PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL); } }
static int authfile_sess_init(void) { config_rec *c = NULL; pr_event_register(&auth_file_module, "core.session-reinit", authfile_sess_reinit_ev, 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; }
static int sftppam_sess_init(void) { config_rec *c; c = find_config(main_server->conf, CONF_PARAM, "SFTPPAMEngine", FALSE); if (c != NULL) { int engine; engine = *((int *) c->argv[0]); if (engine == FALSE) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_PAM_VERSION, "disabled by SFTPPAMEngine setting, unregistered 'pam' driver"); sftp_kbdint_unregister_driver("pam"); return 0; } } /* To preserve the principle of least surprise, also check for the AuthPAM * directive. */ c = find_config(main_server->conf, CONF_PARAM, "AuthPAM", FALSE); if (c != NULL) { unsigned char auth_pam; auth_pam = *((unsigned char *) c->argv[0]); if (auth_pam == FALSE) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_PAM_VERSION, "disabled by AuthPAM setting, unregistered 'pam' driver"); sftp_kbdint_unregister_driver("pam"); return 0; } } c = find_config(main_server->conf, CONF_PARAM, "SFTPPAMServiceName", FALSE); if (c != NULL) { sftppam_service = c->argv[0]; } pr_trace_msg(trace_channel, 8, "using PAM service name '%s'", sftppam_service); return 0; }
static void dynmasq_refresh(void) { server_rec *s; pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION ": resolving all MasqueradeAddress directives (could take a little while)"); for (s = (server_rec *) server_list->xas_list; s; s = s->next) { config_rec *c; c = find_config(s->conf, CONF_PARAM, "MasqueradeAddress", FALSE); if (c != NULL) { const char *masq_addr; pr_netaddr_t *na; masq_addr = c->argv[1]; pr_netaddr_clear_ipcache(masq_addr); na = pr_netaddr_get_addr(s->pool, masq_addr, NULL); if (na != NULL) { /* Compare the obtained netaddr with the one already present. * Only update the "live" netaddr if they differ. */ pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION ": resolved MasqueradeAddress '%s' to IP address %s", masq_addr, pr_netaddr_get_ipstr(na)); if (pr_netaddr_cmp(c->argv[0], na) != 0) { pr_log_pri(PR_LOG_DEBUG, MOD_DYNMASQ_VERSION ": MasqueradeAddress '%s' updated for new address %s (was %s)", masq_addr, pr_netaddr_get_ipstr(na), pr_netaddr_get_ipstr(c->argv[0])); /* Overwrite the old netaddr pointer. Note that this constitutes * a minor memory leak, as there currently isn't a way to free * the memory used by a netaddr object. Hrm. */ c->argv[0] = na; } else { pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION ": MasqueradeAddress '%s' has not changed addresses", masq_addr); } } else { pr_log_pri(PR_LOG_INFO, MOD_DYNMASQ_VERSION ": unable to resolve '%s', keeping previous address", masq_addr); } } } return; }
/* 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); }
int pr_ipbind_add_binds(server_rec *serv) { int res = 0; config_rec *c = NULL; conn_t *listen_conn = NULL; const pr_netaddr_t *addr = NULL; if (serv == NULL) { errno = EINVAL; return -1; } c = find_config(serv->conf, CONF_PARAM, "_bind_", FALSE); while (c != NULL) { listen_conn = NULL; pr_signals_handle(); addr = pr_netaddr_get_addr(serv->pool, c->argv[0], NULL); if (addr == NULL) { pr_log_pri(PR_LOG_WARNING, "notice: unable to determine IP address of '%s'", (char *) c->argv[0]); c = find_config_next(c, c->next, CONF_PARAM, "_bind_", FALSE); continue; } /* If the SocketBindTight directive is in effect, create a separate * listen socket for this address, and add it to the binding list. */ if (SocketBindTight && serv->ServerPort) { listen_conn = pr_ipbind_get_listening_conn(serv, addr, serv->ServerPort); if (listen_conn == NULL) { return -1; } PR_CREATE_IPBIND(serv, addr, serv->ServerPort); PR_OPEN_IPBIND(addr, serv->ServerPort, listen_conn, FALSE, FALSE, TRUE); } else { PR_CREATE_IPBIND(serv, addr, serv->ServerPort); PR_OPEN_IPBIND(addr, serv->ServerPort, serv->listen, FALSE, FALSE, TRUE); } c = find_config_next(c, c->next, CONF_PARAM, "_bind_", FALSE); } return 0; }
static int copy_sess_init(void) { config_rec *c; c = find_config(main_server->conf, CONF_PARAM, "CopyEngine", FALSE); if (c != NULL) { copy_engine = *((int *) c->argv[0]); } if (copy_engine == FALSE) { return 0; } /* Advertise support for the SITE command */ pr_feat_add("SITE COPY"); return 0; }
const char *proxy_ftp_msg_fmt_addr(pool *p, const pr_netaddr_t *addr, unsigned short port, int use_masqaddr) { char *addr_str, *msg, *ptr; size_t msglen; if (p == NULL || addr == NULL) { errno = EINVAL; return NULL; } if (use_masqaddr) { config_rec *c; /* TODO What about TLSMasqueradeAddress? */ /* Handle MasqueradeAddress. */ c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress", FALSE); if (c != NULL) { addr = c->argv[0]; } } addr_str = pstrdup(p, pr_netaddr_get_ipstr(addr)); /* Fixup the address string for use in PORT commands/PASV responses. */ ptr = strrchr(addr_str, ':'); if (ptr != NULL) { addr_str = ptr + 1; } for (ptr = addr_str; *ptr; ptr++) { if (*ptr == '.') { *ptr = ','; } } /* Allocate enough room for 6 numbers (3 digits max each), 5 separators, * and a trailing NUL. */ msglen = (6 * 3) + (5 * 1) + 1; msg = pcalloc(p, msglen); snprintf(msg, msglen-1, "%s,%u,%u", addr_str, (port >> 8) & 255, port & 255); return msg; }
MODRET copy_post_pass(cmd_rec *cmd) { config_rec *c; if (copy_engine == FALSE) { return PR_DECLINED(cmd); } /* The CopyEngine directive may have been changed for this user by * e.g. mod_ifsession, thus we check again. */ c = find_config(main_server->conf, CONF_PARAM, "CopyEngine", FALSE); if (c != NULL) { copy_engine = *((int *) c->argv[0]); } return PR_DECLINED(cmd); }
void lease_update_from_configs(void) { /* changes to the config may change current leases. */ struct dhcp_lease *lease; struct dhcp_config *config; char *name; for (lease = leases; lease; lease = lease->next) if (lease->flags & (LEASE_TA | LEASE_NA)) continue; else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && (config->flags & CONFIG_NAME) && (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr)) lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL); else if ((name = host_from_dns(lease->addr))) lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */ }
/* Check for a CreateHome directive, and act on it if present. If not, do * nothing. */ int create_home(pool *p, const char *home, const char *user, uid_t uid, gid_t gid) { int res; config_rec *c = find_config(main_server->conf, CONF_PARAM, "CreateHome", FALSE); if (!c || (c && *((unsigned char *) c->argv[0]) == FALSE)) return 0; PRIVS_ROOT /* Create the configured path. */ res = create_path(p, home, user, uid, gid, *((mode_t *) c->argv[2]), *((mode_t *) c->argv[1])); if (res < 0 && errno != EEXIST) { PRIVS_RELINQUISH return -1; }
static int forward_dst_filter(pool *p, const char *hostport) { #ifdef PR_USE_REGEX config_rec *c; pr_regex_t *pre; int negated = FALSE, res; c = find_config(main_server->conf, CONF_PARAM, "ProxyForwardTo", FALSE); if (c == NULL) { return 0; } pre = c->argv[0]; negated = *((int *) c->argv[1]); res = pr_regexp_exec(pre, hostport, 0, NULL, 0, 0, 0); if (res == 0) { /* Pattern matched */ if (negated == TRUE) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "host/port '%.100s' matched ProxyForwardTo !%s, rejecting", hostport, pr_regexp_get_pattern(pre)); errno = EPERM; return -1; } } else { /* Pattern NOT matched */ if (negated == FALSE) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "host/port '%.100s' did not match ProxyForwardTo %s, rejecting", hostport, pr_regexp_get_pattern(pre)); errno = EPERM; return -1; } } #endif /* PR_USE_REGEX */ return 0; }
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); }
static int qos_sess_init(void) { #ifdef IP_TOS config_rec *c; c = find_config(main_server->conf, CONF_PARAM, "QoSOptions", FALSE); if (c) { int dataqos; dataqos = *((int *) c->argv[1]); if (dataqos != 0) { pr_event_register(&qos_module, "core.data-connect", qos_data_connect_ev, NULL); pr_event_register(&qos_module, "core.data-listen", qos_data_listen_ev, NULL); } } #endif pr_event_register(&qos_module, "core.session-reinit", qos_sess_reinit_ev, NULL); return 0; }
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); }
static void load_widgets_tab(unsigned char tidx) { struct widget_config cfg; struct widget_state s; struct widget **w, **r; unsigned char tab = tab_list[tidx+1]; /* disable refresh interrupt */ EIMSK &= ~_BV(INT0); /* wait until lock is released */ if (nlock == 0) goto locked; max7456_clr(); w = all_widgets; r = rlist; do { find_config(tab, (*w)->id, &cfg); if (cfg.tab != 0xff) { s.props = WIDGET_ENABLED | WIDGET_INIT; s.x = cfg.x; s.y = cfg.y; *r++ = *w; (*w)->do_state(&s); } } while ((*++w) != NULL); *r = NULL; rwid = rlist; current_tidx = tidx; locked: /* re-enable interrupt if we have at least 1 widget to render */ if ((*rwid) != NULL) EIMSK |= _BV(INT0); }
/* Check for a CreateHome directive, and act on it if present. If not, do * nothing. */ int create_home(pool *p, const char *home, const char *user, uid_t uid, gid_t gid) { int res; config_rec *c; mode_t dir_mode, dst_mode; uid_t dir_uid, dst_uid; gid_t dir_gid, dst_gid, home_gid; c = find_config(main_server->conf, CONF_PARAM, "CreateHome", FALSE); if (c == NULL || (c && *((unsigned char *) c->argv[0]) == FALSE)) { return 0; } /* Create the configured path. */ dir_uid = *((uid_t *) c->argv[4]); dir_gid = *((gid_t *) c->argv[5]); dir_mode = *((mode_t *) c->argv[2]); home_gid = *((gid_t *) c->argv[6]); dst_uid = uid; dst_gid = (home_gid == -1) ? gid : home_gid; dst_mode = *((mode_t *) c->argv[1]); PRIVS_ROOT res = create_path(p, home, user, dir_uid, dir_gid, dir_mode, dst_uid, dst_gid, dst_mode); if (res < 0 && errno != EEXIST) { PRIVS_RELINQUISH return -1; }
MODRET wrap_handle_request(cmd_rec *cmd) { /* these variables are names expected to be set by the TCP wrapper code */ struct request_info request; char *user = NULL; config_rec *conf = NULL, *access_conf = NULL, *syslog_conf = NULL; hosts_allow_table = NULL; hosts_deny_table = NULL; /* hide passwords */ session.hide_password = TRUE; /* Sneaky...found in mod_auth.c's cmd_pass() function. Need to find the * login UID in order to resolve the possibly-login-dependent filename. */ user = (char *) get_param_ptr(cmd->server->conf, C_USER, FALSE); /* It's possible that a PASS command came before USER. This is a PRE_CMD * handler, so it won't be protected from this case; we'll need to do * it manually. */ if (!user) return DECLINED(cmd); /* Use mod_auth's _auth_resolve_user() [imported for use here] to get the * right configuration set, since the user may be logging in anonymously, * and the session struct hasn't yet been set for that yet (thus short- * circuiting the easiest way to get the right context...the macros. */ conf = wrap_resolve_user(cmd->pool, &user); /* Search first for user-specific access files. Multiple TCPUserAccessFiles * directives are allowed. */ if ((access_conf = find_config(conf ? conf->subset : CURRENT_CONF, CONF_PARAM, "TCPUserAccessFiles", FALSE)) != NULL) { int matched = FALSE; array_header *user_array = NULL; while (access_conf) { user_array = make_array(cmd->tmp_pool, 0, sizeof(char *)); *((char **) push_array(user_array)) = pstrdup(cmd->tmp_pool, user); /* Check the user expression -- don't forget the offset, to skip * the access file name strings in argv */ if (wrap_eval_expression(((char **) access_conf->argv) + 2, user_array)) { pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": matched TCPUserAccessFiles expression"); matched = TRUE; break; } access_conf = find_config_next(access_conf, access_conf->next, CONF_PARAM, "TCPUserAccessFiles", FALSE); } if (!matched) access_conf = NULL; } /* Next, search for group-specific access files. Multiple * TCPGroupAccessFiles directives are allowed. */ if (!access_conf && (access_conf = find_config(conf ? conf->subset : CURRENT_CONF, CONF_PARAM, "TCPGroupAccessFiles", FALSE)) != NULL) { unsigned char matched = FALSE; /* NOTE: this gid_array is only necessary until Bug#1461 is fixed */ array_header *gid_array = make_array(cmd->pool, 0, sizeof(gid_t)); array_header *group_array = make_array(cmd->pool, 0, sizeof(char *)); while (access_conf) { if (pr_auth_getgroups(cmd->pool, user, &gid_array, &group_array) < 1) { pr_log_debug(DEBUG3, MOD_WRAP_VERSION ": no supplemental groups found for user '%s'", user); } else { /* Check the group expression -- don't forget the offset, to skip * the access file names strings in argv */ if (wrap_eval_expression(((char **) access_conf->argv) + 2, group_array)) { pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": matched TCPGroupAccessFiles expression"); matched = TRUE; break; } } access_conf = find_config_next(access_conf, access_conf->next, CONF_PARAM, "TCPGroupAccessFiles", FALSE); } if (!matched) access_conf = NULL; } /* Finally for globally-applicable access files. Only one such directive * is allowed. */ if (!access_conf) { access_conf = find_config(conf ? conf->subset : CURRENT_CONF, CONF_PARAM, "TCPAccessFiles", FALSE); } if (access_conf) { hosts_allow_table = (char *) access_conf->argv[0]; hosts_deny_table = (char *) access_conf->argv[1]; } /* Now, check the retrieved filename, and see if it requires a login-time * file. */ if (hosts_allow_table != NULL && hosts_allow_table[0] == '~' && hosts_allow_table[1] == '/') { char *allow_real_table = NULL; allow_real_table = wrap_get_user_table(cmd, user, hosts_allow_table); if (!wrap_is_usable_file(allow_real_table)) { pr_log_pri(PR_LOG_WARNING, MOD_WRAP_VERSION ": configured TCPAllowFile %s is unusable", hosts_allow_table); hosts_allow_table = NULL; } else hosts_allow_table = allow_real_table; } if (hosts_deny_table != NULL && hosts_deny_table[0] == '~' && hosts_deny_table[1] == '/') { char *deny_real_table = NULL; deny_real_table = dir_realpath(cmd->pool, hosts_deny_table); if (!wrap_is_usable_file(deny_real_table)) { pr_log_pri(PR_LOG_WARNING, MOD_WRAP_VERSION ": configured TCPDenyFile %s is unusable", hosts_deny_table); hosts_deny_table = NULL; } else hosts_deny_table = deny_real_table; } /* Make sure that _both_ allow and deny TCPAccessFiles are present. * If not, log the missing file, and by default allow request to succeed. */ if (hosts_allow_table != NULL && hosts_deny_table != NULL) { /* Most common case...nothing more necessary */ } else if (hosts_allow_table == NULL && hosts_deny_table != NULL) { /* Log the missing file */ pr_log_pri(PR_LOG_INFO, MOD_WRAP_VERSION ": no usable allow access file -- " "allowing connection"); return DECLINED(cmd); } else if (hosts_allow_table != NULL && hosts_deny_table == NULL) { /* log the missing file */ pr_log_pri(PR_LOG_INFO, MOD_WRAP_VERSION ": no usable deny access file -- " "allowing connection"); return DECLINED(cmd); } else { /* Neither set -- assume the admin hasn't configured these directives * at all. */ return DECLINED(cmd); } /* Log the names of the allow/deny files being used. */ pr_log_pri(PR_LOG_DEBUG, MOD_WRAP_VERSION ": using access files: %s, %s", hosts_allow_table, hosts_deny_table); /* retrieve the user-defined syslog priorities, if any. Fall back to the * defaults as seen in tcpd.h if not defined. */ syslog_conf = find_config(main_server->conf, CONF_PARAM, "TCPAccessSyslogLevels", FALSE); if (syslog_conf) { allow_severity = (int) syslog_conf->argv[1]; deny_severity = (int) syslog_conf->argv[2]; } else { allow_severity = PR_LOG_INFO; deny_severity = PR_LOG_WARNING; } pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": checking under service name '%s'", wrap_service_name); request_init(&request, RQ_DAEMON, wrap_service_name, RQ_FILE, session.c->rfd, 0); fromhost(&request); if (STR_EQ(eval_hostname(request.client), paranoid) || !hosts_access(&request)) { char *denymsg = NULL; /* log the denied connection */ wrap_log_request_denied(deny_severity, &request); /* check for AccessDenyMsg */ if ((denymsg = (char *) get_param_ptr(TOPLEVEL_CONF, "AccessDenyMsg", FALSE)) != NULL) denymsg = sreplace(cmd->tmp_pool, denymsg, "%u", user, NULL); if (denymsg) return ERROR_MSG(cmd, R_530, denymsg); else return ERROR_MSG(cmd, R_530, "Access denied."); } /* If request is allowable, return DECLINED (for engine to act as if this * handler was never called, else ERROR (for engine to abort processing and * deny request. */ wrap_log_request_allowed(allow_severity, &request); return DECLINED(cmd); }
const char *proxy_ftp_msg_fmt_ext_addr(pool *p, const pr_netaddr_t *addr, unsigned short port, int cmd_id, int use_masqaddr) { const char *addr_str; char delim = '|', *msg; int family = 0; size_t addr_strlen, msglen; if (p == NULL || addr == NULL) { errno = EINVAL; return NULL; } if (use_masqaddr) { config_rec *c; /* Handle MasqueradeAddress. */ c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress", FALSE); if (c != NULL) { addr = c->argv[0]; } } /* Format is <d>proto<d>ip address<d>port<d> (ASCII in network order), * where <d> is an arbitrary delimiter character. */ switch (pr_netaddr_get_family(addr)) { case AF_INET: family = 1; break; #ifdef PR_USE_IPV6 case AF_INET6: family = 2; break; #endif /* PR_USE_IPV6 */ default: /* Unlikely to happen. */ errno = EINVAL; return NULL; } addr_str = pr_netaddr_get_ipstr(addr); addr_strlen = strlen(addr_str); /* 4 delimiters, the network protocol, the IP address, the port, and a NUL. */ msglen = (4 * 1) + addr_strlen + 6 + 1; msg = pcalloc(p, msglen); switch (cmd_id) { case PR_CMD_EPRT_ID: snprintf(msg, msglen, "%c%d%c%s%c%hu%c", delim, family, delim, addr_str, delim, port, delim); break; case PR_CMD_EPSV_ID: snprintf(msg, msglen-1, "%c%c%c%u%c", delim, delim, delim, port, delim); break; default: pr_trace_msg(trace_channel, 3, "invalid/unsupported command ID: %d", cmd_id); errno = EINVAL; return NULL; } return msg; }
/* yet more plagiarizing...this one raided from mod_auth's _auth_resolve_user() * function [in case you haven't noticed yet, I'm quite the hack, in the * _true_ sense of the world]. =) hmmm...I wonder if it'd be feasible * to make some of mod_auth's functions visible from src/auth.c? */ static config_rec *wrap_resolve_user(pool *pool, char **user) { config_rec *conf = NULL, *top_conf; char *ourname = NULL, *anonname = NULL; unsigned char is_alias = FALSE, force_anon = FALSE; /* Precendence rules: * 1. Search for UserAlias directive. * 2. Search for Anonymous directive. * 3. Normal user login */ ourname = (char*) get_param_ptr(main_server->conf, "UserName", FALSE); conf = find_config(main_server->conf, CONF_PARAM, "UserAlias", TRUE); if (conf) do { if (!strcmp(conf->argv[0], "*") || !strcmp(conf->argv[0], *user)) { is_alias = TRUE; break; } } while ((conf = find_config_next(conf, conf->next, CONF_PARAM, "UserAlias", TRUE)) != NULL); /* if AuthAliasOnly is set, ignore this one and continue */ top_conf = conf; while (conf && conf->parent && find_config(conf->parent->set, CONF_PARAM, "AuthAliasOnly", FALSE)) { is_alias = FALSE; find_config_set_top(top_conf); conf = find_config_next(conf, conf->next, CONF_PARAM, "UserAlias", TRUE); if (conf && (!strcmp(conf->argv[0], "*") || !strcmp(conf->argv[0], *user))) is_alias = TRUE; } if (conf) { *user = conf->argv[1]; /* If the alias is applied inside an <Anonymous> context, we have found * our anon block */ if (conf->parent && conf->parent->config_type == CONF_ANON) conf = conf->parent; else conf = NULL; } /* Next, search for an anonymous entry */ if (!conf) conf = find_config(main_server->conf, CONF_ANON, NULL, FALSE); else find_config_set_top(conf); if (conf) do { anonname = (char*) get_param_ptr(conf->subset, "UserName", FALSE); if (!anonname) anonname = ourname; if (anonname && !strcmp(anonname, *user)) { break; } } while ((conf = find_config_next(conf, conf->next, CONF_ANON, NULL, FALSE)) != NULL); if (!is_alias && !force_anon) { if (find_config((conf ? conf->subset : main_server->conf), CONF_PARAM, "AuthAliasOnly", FALSE)) { if (conf && conf->config_type == CONF_ANON) conf = NULL; else *user = NULL; if (*user && find_config(main_server->conf, CONF_PARAM, "AuthAliasOnly", FALSE)) *user = NULL; } } return conf; }
MODRET counter_stor(cmd_rec *cmd) { config_rec *c; int res; pr_fh_t *fh; const char *path; if (counter_engine == FALSE) { return PR_DECLINED(cmd); } c = find_config(CURRENT_CONF, CONF_PARAM, "CounterMaxWriters", FALSE); counter_max_writers = c ? *((int *) c->argv[0]) : COUNTER_DEFAULT_MAX_WRITERS; if (counter_max_writers == 0) { return PR_DECLINED(cmd); } path = pr_table_get(cmd->notes, "mod_xfer.store-path", NULL); if (path == NULL) { return PR_DECLINED(cmd); } /* Note that for purposes of our semaphores, we need to use the absolute * path. */ counter_curr_path = counter_abs_path(cmd->pool, path, FALSE); fh = counter_get_fh(cmd->tmp_pool, counter_curr_path); if (fh == NULL) { (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "%s: no CounterFile found for path '%s'", (char *) cmd->argv[0], counter_curr_path); /* No CounterFile configured/available for this path. */ return PR_DECLINED(cmd); } counter_curr_semid = counter_get_sem(fh, counter_curr_path); if (counter_curr_semid < 0) { (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "unable to get semaphore for '%s': %s", counter_curr_path, strerror(errno)); return PR_DECLINED(cmd); } /* Add a writer to this file by decrementing the writer counter value. * This functions as a sort of "lock". */ res = counter_add_writer(counter_curr_semid); if (res < 0 && errno == EAGAIN) { /* The lock acquisition failed, which means the file is busy. * The upload should be failed. */ (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "%s: max number of writers (%d) reached for '%s'", (char *) cmd->argv[0], counter_max_writers, counter_curr_path); pr_response_add_err(R_450, _("%s: File busy"), cmd->arg); return PR_ERROR(cmd); } counter_pending |= COUNTER_HAVE_WRITER; (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION, "%s: added writer counter for '%s' (semaphore ID %d)", (char *) cmd->argv[0], counter_curr_path, counter_curr_semid); return PR_DECLINED(cmd); }