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 void qos_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(&qos_module, "core.data-connect", qos_data_connect_ev); pr_event_unregister(&qos_module, "core.data-listen", qos_data_listen_ev); pr_event_unregister(&qos_module, "core.session-reinit", qos_sess_reinit_ev); res = qos_sess_init(); if (res < 0) { pr_session_disconnect(&qos_module, PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL); } }
static void log_failure_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_log_failure.c", (const char *) event_data) == 0) { pr_event_unregister(&log_failure_module, NULL); destroy_pool(log_failure_pool); log_failure_pool = NULL; } }
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 set_up(void) { if (p == NULL) { p = permanent_pool = make_sub_pool(NULL); } pr_event_unregister(NULL, NULL, NULL); }
static void counter_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_counter.c", (const char *) event_data) == 0) { pr_event_unregister(&counter_module, NULL, NULL); if (counter_pool) { destroy_pool(counter_pool); } } }
static int dynmasq_sess_init(void) { /* Ensure that the timer only fires on the daemon process. */ pr_timer_remove(dynmasq_timer_id, &dynmasq_module); dynmasq_timer_id = -1; pr_event_unregister(&dynmasq_module, "core.restart", NULL); return 0; }
static void sftppam_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_sftp_pam.c", (const char *) event_data) == 0) { if (sftppam_user) { free(sftppam_user); sftppam_user = NULL; sftppam_userlen = 0; } sftp_kbdint_unregister_driver("pam"); pr_event_unregister(&sftp_pam_module, NULL, NULL); } }
END_TEST START_TEST (event_unregister_test) { int res; const char *event = "foo"; res = pr_event_unregister(NULL, NULL, NULL); fail_unless(res == 0, "Failed to handle empty event lists"); res = pr_event_register(NULL, event, event_cb, NULL); fail_unless(res == 0, "Failed to register event: %s", strerror(errno)); res = pr_event_unregister(NULL, "bar", NULL); fail_unless(res == -1, "Failed to handle unregistered event"); fail_unless(errno == ENOENT, "Failed to set errno to ENOENT"); res = pr_event_unregister(NULL, event, event_cb2); fail_unless(res == -1, "Failed to handle unregistered event"); fail_unless(errno == ENOENT, "Failed to set errno to ENOENT"); res = pr_event_unregister(NULL, event, event_cb); fail_unless(res == 0, "Failed to unregister event: %s", strerror(errno)); res = pr_event_register(NULL, event, event_cb, NULL); fail_unless(res == 0, "Failed to register event: %s", strerror(errno)); res = pr_event_unregister(NULL, event, NULL); fail_unless(res == 0, "Failed to unregister event: %s", strerror(errno)); res = pr_event_register(NULL, event, event_cb, NULL); fail_unless(res == 0, "Failed to register event: %s", strerror(errno)); res = pr_event_unregister(NULL, NULL, NULL); fail_unless(res == 0, "Failed to unregister event: %s", strerror(errno)); }
static void finish_terminate(void) { if (is_master && mpid == getpid()) { PRIVS_ROOT /* Do not need the pidfile any longer. */ if (ServerType == SERVER_STANDALONE && !nodaemon) { pr_pidfile_remove(); } /* Run any exit handlers registered in the master process here, so that * they may have the benefit of root privs. More than likely these * exit handlers were registered by modules' module initialization * functions, which also occur under root priv conditions. * * If an exit handler is registered after the fork(), it won't be run here; * that registration occurs in a different process space. */ pr_event_generate("core.exit", NULL); pr_event_generate("core.shutdown", NULL); /* Remove the registered exit handlers now, so that the ensuing * pr_session_end() call (outside the root privs condition) does not call * the exit handlers for the master process again. */ pr_event_unregister(NULL, "core.exit", NULL); pr_event_unregister(NULL, "core.shutdown", NULL); PRIVS_RELINQUISH if (ServerType == SERVER_STANDALONE) { pr_log_pri(PR_LOG_NOTICE, "ProFTPD " PROFTPD_VERSION_TEXT " standalone mode SHUTDOWN"); /* Clean up the scoreboard */ PRIVS_ROOT pr_delete_scoreboard(); PRIVS_RELINQUISH }
static void sql_postgres_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_sql_postgres.c", (const char *) event_data) == 0) { /* Unegister ourselves with mod_sql. */ if (sql_unregister_backend("postgres") < 0) { pr_log_pri(PR_LOG_NOTICE, MOD_SQL_POSTGRES_VERSION ": notice: error unregistering backend: %s", strerror(errno)); pr_session_end(0); } /* Unregister ourselves from all events. */ pr_event_unregister(&sql_postgres_module, NULL, NULL); } }
static void trace_restart_ev(const void *event_data, void *user_data) { trace_opts = PR_TRACE_OPT_DEFAULT; close(trace_logfd); trace_logfd = -1; if (trace_pool) { destroy_pool(trace_pool); trace_pool = NULL; trace_tab = NULL; pr_event_unregister(NULL, "core.restart", trace_restart_ev); } return; }
static void wrap_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(&wrap_module, "core.session-reinit", wrap_sess_reinit_ev); /* Reset defaults */ wrap_service_name = "proftpd"; res = wrap_sess_init(); if (res < 0) { pr_session_disconnect(&wrap_module, PR_SESS_DISCONNECT_SESSION_INIT_FAILED, NULL); } }
static void dynmasq_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_dynmasq.c", (const char *) event_data) == 0) { pr_event_unregister(&dynmasq_module, NULL, NULL); # ifdef PR_USE_CTRLS /* Unregister any control actions. */ pr_ctrls_unregister(&dynmasq_module, "dynmasq"); destroy_pool(dynmasq_act_pool); dynmasq_act_pool = NULL; # endif /* PR_USE_CTRLS */ pr_timer_remove(dynmasq_timer_id, &dynmasq_module); dynmasq_timer_id = -1; } }
END_TEST START_TEST (event_generate_test) { int res; const char *event = "foo"; pr_event_generate(NULL, NULL); fail_unless(event_triggered == 0, "Expected triggered count %u, got %u", 0, event_triggered); pr_event_generate(event, NULL); fail_unless(event_triggered == 0, "Expected triggered count %u, got %u", 0, event_triggered); res = pr_event_register(NULL, event, event_cb, NULL); fail_unless(res == 0, "Failed to register event: %s", strerror(errno)); pr_event_generate("bar", NULL); fail_unless(event_triggered == 0, "Expected triggered count %u, got %u", 0, event_triggered); pr_event_generate(event, NULL); fail_unless(event_triggered == 1, "Expected triggered count %u, got %u", 1, event_triggered); pr_event_generate(event, NULL); fail_unless(event_triggered == 2, "Expected triggered count %u, got %u", 2, event_triggered); res = pr_event_unregister(NULL, NULL, NULL); fail_unless(res == 0, "Failed to unregister events: %s", strerror(errno)); pr_event_generate(event, NULL); fail_unless(event_triggered == 2, "Expected triggered count %u, got %u", 2, event_triggered); }
static void filetab_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_quotatab_file.c", (const char *) event_data) == 0) { pr_event_unregister("atab_file_module, NULL, NULL); quotatab_unregister_backend("file", QUOTATAB_LIMIT_SRC|QUOTATAB_TALLY_SRC); } }
static int dso_sess_init(void) { pr_event_unregister(&dso_module, "core.restart", dso_restart_ev); return 0; }
int pr_module_unload(module *m) { char buf[256]; if (m == NULL || m->name == NULL) { errno = EINVAL; return -1; } /* Make sure this module has been loaded. We can't unload a module that * has not been loaded, now can we? */ memset(buf, '\0', sizeof(buf)); snprintf(buf, sizeof(buf), "mod_%s.c", m->name); buf[sizeof(buf)-1] = '\0'; if (pr_module_get(buf) == NULL) { errno = ENOENT; return -1; } /* Generate an event. */ pr_event_generate("core.module-unload", buf); /* Remove the module from the loaded_modules list. */ if (m->prev) { m->prev->next = m->next; } else { /* This module is the start of the loaded_modules list (prev is NULL), * so we need to update that pointer, too. */ loaded_modules = m->next; } if (m->next) m->next->prev = m->prev; m->prev = m->next = NULL; /* Remove the module's config, cmd, and auth tables. */ if (m->conftable) { conftable *conftab; for (conftab = m->conftable; conftab->directive; conftab++) { pr_stash_remove_symbol(PR_SYM_CONF, conftab->directive, conftab->m); } } if (m->cmdtable) { cmdtable *cmdtab; for (cmdtab = m->cmdtable; cmdtab->command; cmdtab++) { if (cmdtab->cmd_type == HOOK) { pr_stash_remove_symbol(PR_SYM_HOOK, cmdtab->command, cmdtab->m); } else { /* All other cmd_types are for CMDs: PRE_CMD, CMD, POST_CMD, etc. */ pr_stash_remove_symbol(PR_SYM_CMD, cmdtab->command, cmdtab->m); } } } if (m->authtable) { authtable *authtab; for (authtab = m->authtable; authtab->name; authtab++) { pr_stash_remove_symbol(PR_SYM_AUTH, authtab->name, authtab->m); } } /* Remove any callbacks that the module may have registered, i.e.: * * ctrls * events * timers * * Ideally we would also automatically unregister other callbacks that * the module may have registered, such as FSIO, NetIO, variables, and * response handlers. However, these APIs do not yet allow for * removal of all callbacks for a given module. */ #ifdef PR_USE_CTRLS pr_ctrls_unregister(m, NULL); #endif /* PR_USE_CTRLS */ pr_event_unregister(m, NULL, NULL); pr_timer_remove(-1, m); return 0; }
static void qos_mod_unload_ev(const void *event_data, void *user_data) { if (strcmp("mod_qos.c", (const char *) event_data) == 0) { pr_event_unregister(&qos_module, NULL, NULL); } }
/* 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); } }