/* Dynamic loading of the authentication backend. * We use GLib's multiplatform dl() wrapper * to open up libauthsql or libauthldap and * populate the global 'auth' structure. * * (c) 2005 Aaron Stone */ #include "dbmail.h" #define THIS_MODULE "auth" static auth_func_t *auth = NULL; extern db_param_t _db_params; /* Returns: * 1 on modules unsupported * 0 on success * -1 on failure to load module * -2 on missing symbols * -3 on memory error */ int auth_load_driver(void) { GModule *module; char *lib = NULL; char *driver = NULL; if (!g_module_supported()) { TRACE(TRACE_FATAL, "loadable modules unsupported on this platform"); return 1; } auth = g_new0(auth_func_t,1); if (strcasecmp(_db_params.authdriver, "SQL") == 0) driver = "auth_sql"; else if (strcasecmp(_db_params.authdriver, "LDAP") == 0) driver = "auth_ldap"; else TRACE(TRACE_FATAL, "unsupported driver: %s, please choose from SQL or LDAP", _db_params.authdriver); field_t library_dir; config_get_value("library_directory", "DBMAIL", library_dir); if (strlen(library_dir) == 0) { TRACE(TRACE_DEBUG, "no value for library_directory, using default [%s]", DEFAULT_LIBRARY_DIR); snprintf(library_dir, sizeof(field_t), "%s", DEFAULT_LIBRARY_DIR); } else { TRACE(TRACE_DEBUG, "library_directory is [%s]", library_dir); } /* Try local build area, then dbmail lib paths, then system lib path. */ int i; char *lib_path[] = { library_dir, NULL }; /* Note that the limit here *includes* the NULL. This is intentional, * to allow g_module_build_path to try the current working directory. */ for (i = 0; i < 3; i++) { lib = g_module_build_path(lib_path[i], driver); module = g_module_open(lib, 0); // non-lazy bind. TRACE(TRACE_DEBUG, "looking for %s as %s", driver, lib); g_free(lib); if (!module) TRACE(TRACE_INFO, "cannot load %s", g_module_error()); if (module) break; } /* If the list is exhausted without opening a module, we'll catch it. */ if (!module) { TRACE(TRACE_FATAL, "could not load auth module - turn up debug level for details"); return -1; } if (!g_module_symbol(module, "auth_connect", (gpointer)&auth->connect ) || !g_module_symbol(module, "auth_disconnect", (gpointer)&auth->disconnect ) || !g_module_symbol(module, "auth_user_exists", (gpointer)&auth->user_exists ) || !g_module_symbol(module, "auth_get_userid", (gpointer)&auth->get_userid ) || !g_module_symbol(module, "auth_check_userid", (gpointer)&auth->check_userid ) || !g_module_symbol(module, "auth_get_known_users", (gpointer)&auth->get_known_users ) || !g_module_symbol(module, "auth_get_known_aliases", (gpointer)&auth->get_known_aliases ) || !g_module_symbol(module, "auth_getclientid", (gpointer)&auth->getclientid ) || !g_module_symbol(module, "auth_getmaxmailsize", (gpointer)&auth->getmaxmailsize ) || !g_module_symbol(module, "auth_getencryption", (gpointer)&auth->getencryption ) || !g_module_symbol(module, "auth_check_user_ext", (gpointer)&auth->check_user_ext ) || !g_module_symbol(module, "auth_adduser", (gpointer)&auth->adduser ) || !g_module_symbol(module, "auth_delete_user", (gpointer)&auth->delete_user ) || !g_module_symbol(module, "auth_change_username", (gpointer)&auth->change_username ) || !g_module_symbol(module, "auth_change_password", (gpointer)&auth->change_password ) || !g_module_symbol(module, "auth_change_clientid", (gpointer)&auth->change_clientid ) || !g_module_symbol(module, "auth_change_mailboxsize", (gpointer)&auth->change_mailboxsize ) || !g_module_symbol(module, "auth_validate", (gpointer)&auth->validate ) || !g_module_symbol(module, "auth_md5_validate", (gpointer)&auth->md5_validate ) || !g_module_symbol(module, "auth_get_users_from_clientid",(gpointer)&auth->get_users_from_clientid) || !g_module_symbol(module, "auth_get_user_aliases", (gpointer)&auth->get_user_aliases ) || !g_module_symbol(module, "auth_get_aliases_ext", (gpointer)&auth->get_aliases_ext ) || !g_module_symbol(module, "auth_addalias", (gpointer)&auth->addalias ) || !g_module_symbol(module, "auth_addalias_ext", (gpointer)&auth->addalias_ext ) || !g_module_symbol(module, "auth_removealias", (gpointer)&auth->removealias ) || !g_module_symbol(module, "auth_removealias_ext", (gpointer)&auth->removealias_ext ) || !g_module_symbol(module, "auth_requires_shadow_user", (gpointer)&auth->requires_shadow_user )) { TRACE(TRACE_FATAL, "cannot find function %s", g_module_error()); return -2; } return 0; } /* This is the first auth_* call anybody should make. */ int auth_connect(void) { auth_load_driver(); return auth->connect(); } /* But sometimes this gets called after help text or an * error but without a matching auth_connect before it. */ int auth_disconnect(void) { if (!auth) return 0; auth->disconnect(); g_free(auth); return 0; } int auth_user_exists(const char *username, u64_t * user_idnr) { return auth->user_exists(username, user_idnr); } char *auth_get_userid(u64_t user_idnr) { return auth->get_userid(user_idnr); } int auth_check_userid(u64_t user_idnr) { return auth->check_userid(user_idnr); } GList * auth_get_known_users(void) { return auth->get_known_users(); } GList * auth_get_known_aliases(void) { return auth->get_known_aliases(); } int auth_getclientid(u64_t user_idnr, u64_t * client_idnr) { return auth->getclientid(user_idnr, client_idnr); } int auth_getmaxmailsize(u64_t user_idnr, u64_t * maxmail_size) { return auth->getmaxmailsize(user_idnr, maxmail_size); } char *auth_getencryption(u64_t user_idnr) { return auth->getencryption(user_idnr); } int auth_check_user_ext(const char *username, struct dm_list *userids, struct dm_list *fwds, int checks) { return auth->check_user_ext(username, userids, fwds, checks); } int auth_adduser(const char *username, const char *password, const char *enctype, u64_t clientid, u64_t maxmail, u64_t * user_idnr) { return auth->adduser(username, password, enctype, clientid, maxmail, user_idnr); } int auth_delete_user(const char *username) { return auth->delete_user(username); } int auth_change_username(u64_t user_idnr, const char *new_name) { return auth->change_username(user_idnr, new_name); } int auth_change_password(u64_t user_idnr, const char *new_pass, const char *enctype) { return auth->change_password(user_idnr, new_pass, enctype); } int auth_change_clientid(u64_t user_idnr, u64_t new_cid) { return auth->change_clientid(user_idnr, new_cid); } int auth_change_mailboxsize(u64_t user_idnr, u64_t new_size) { return auth->change_mailboxsize(user_idnr, new_size); } int auth_validate(clientinfo_t *ci, char *username, char *password, u64_t * user_idnr) { return auth->validate(ci, username, password, user_idnr); } u64_t auth_md5_validate(clientinfo_t *ci, char *username, unsigned char *md5_apop_he, char *apop_stamp) { return auth->md5_validate(ci, username, md5_apop_he, apop_stamp); } int auth_get_users_from_clientid(u64_t client_id, u64_t ** user_ids, unsigned *num_users) { return auth->get_users_from_clientid(client_id, user_ids, num_users); } GList * auth_get_user_aliases(u64_t user_idnr) { return auth->get_user_aliases(user_idnr); } GList * auth_get_aliases_ext(const char *alias) { return auth->get_aliases_ext(alias); } int auth_addalias(u64_t user_idnr, const char *alias, u64_t clientid) { return auth->addalias(user_idnr, alias, clientid); } int auth_addalias_ext(const char *alias, const char *deliver_to, u64_t clientid) { return auth->addalias_ext(alias, deliver_to, clientid); } int auth_removealias(u64_t user_idnr, const char *alias) { return auth->removealias(user_idnr, alias); } int auth_removealias_ext(const char *alias, const char *deliver_to) { return auth->removealias_ext(alias, deliver_to); } gboolean auth_requires_shadow_user(void) { return auth->requires_shadow_user(); }