END_TEST START_TEST (module_get_test) { module m, *res; res = pr_module_get(NULL); fail_unless(res == NULL, "Failed to handle null argument"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); res = pr_module_get("mod_foo.c"); fail_unless(res == NULL, "Failed to handle nonexistent module"); fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT, strerror(errno), errno); memset(&m, 0, sizeof(m)); m.name = "bar"; loaded_modules = &m; res = pr_module_get("mod_foo.c"); fail_unless(res == NULL, "Failed to handle nonexistent module"); fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT, strerror(errno), errno); res = pr_module_get("mod_bar.c"); fail_unless(res != NULL, "Failed to detect existing module"); fail_unless(res == &m, "Expected %p, got %p", &m, res); res = pr_module_get("mod_BAR.c"); fail_unless(res == NULL, "Failed to handle nonexistent module"); fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT, strerror(errno), errno); loaded_modules = NULL; }
static int dso_unload_module_by_name(const char *name) { module *m; if (strncmp(name, "mod_", 4) != 0 || name[strlen(name)-2] != '.' || name[strlen(name)-1] != 'c') { errno = EINVAL; return -1; } /* Lookup the module pointer for the given module name. */ m = pr_module_get(name); if (!m) { errno = ENOENT; return -1; } return dso_unload_module(m); }
int pr_auth_check(pool *p, const char *cpw, const char *name, const char *pw) { cmd_rec *cmd = NULL; modret_t *mr = NULL; module *m = NULL; int res = PR_AUTH_BADPWD; cmd = make_cmd(p, 3, cpw, name, pw); /* First, check for any of the modules in the "authenticating only" list * of modules. This is usually only mod_auth_pam, but other modules * might also add themselves (e.g. mod_radius under certain conditions). */ if (auth_module_list) { struct auth_module_elt *elt; for (elt = (struct auth_module_elt *) auth_module_list->xas_list; elt; elt = elt->next) { m = pr_module_get(elt->name); if (m) { mr = dispatch_auth(cmd, "check", &m); if (MODRET_ISHANDLED(mr)) { pr_trace_msg(trace_channel, 4, "module '%s' used for authenticating user '%s'", elt->name, name); res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; } if (MODRET_ISERROR(mr)) { res = MODRET_ERROR(mr); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; } m = NULL; } } } if (auth_tab) { /* Fetch the specific module to be used for authenticating this user. */ void *v = pr_table_get(auth_tab, name, NULL); if (v) { m = *((module **) v); pr_trace_msg(trace_channel, 4, "using module 'mod_%s.c' from authcache to authenticate user '%s'", m->name, name); } } mr = dispatch_auth(cmd, "check", m ? &m : NULL); if (MODRET_ISHANDLED(mr)) res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } return res; }
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; }
int pr_module_load(module *m) { char buf[256]; if (m == NULL || m->name == NULL) { errno = EINVAL; return -1; } /* Check the API version the module wants to use. */ if (m->api_version < PR_MODULE_API_VERSION) { errno = EACCES; return -1; } /* Do not allow multiple modules with the same name. */ 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 = EEXIST; return -1; } /* Invoke the module's initialization routine. */ if (!m->init || m->init() >= 0) { /* Assign a priority to this module. */ m->priority = curr_module_pri++; /* Add the module's config, cmd, and auth tables. */ if (pr_module_load_conftab(m) < 0) { return -1; } if (pr_module_load_cmdtab(m) < 0) { return -1; } if (pr_module_load_authtab(m) < 0) { return -1; } /* Add the module to the loaded_modules list. */ if (loaded_modules) { m->next = loaded_modules; loaded_modules->prev = m; } loaded_modules = m; /* Generate an event. */ pr_event_generate("core.module-load", buf); return 0; } errno = EPERM; return -1; }
unsigned char pr_module_exists(const char *name) { return pr_module_get(name) != NULL ? TRUE : FALSE; }
/* 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); }