/***************************************************************************** POPular -- A POP3 server and proxy for large mail systems $Id: pdm.c,v 1.9 2001/04/08 18:23:57 sqrt Exp $ http://www.remote.org/jochen/mail/popular/ ****************************************************************************** Copyright (C) 1999-2001 Jochen Topf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *****************************************************************************/ #if HAVE_CONFIG_H # include #endif #include "popular.h" extern int debug; extern struct pdm_module *first_pdm_module; struct pdm_mvar mvar; /***************************************************************************** pdm_attach() dir - the directory where the module can be found argc - number of arguments in argv argv - arguments argv[0] - id (symbolic name) for this instance of the module argv[1] - name of module without the prefix 'pdm_' and suffix '.so' argv[2] - first argument etc. *****************************************************************************/ struct pdm_module * pdm_attach(const char *dir, int argc, char *argv[]) { char soname[MAXLEN_SONAME]; void *lib; struct pdm_module *module; char *errtext; int n; strlcpy(soname, dir, sizeof(soname)); strlcat(soname, "/libpdm_", sizeof(soname)); strlcat(soname, argv[1], sizeof(soname)); strlcat(soname, ".so", sizeof(soname)); lib = dlopen(soname, RTLD_NOW); if (! lib) { DEBUG2(DG_AUTH, "pdm_attach", "could not open database module pdm_%s.so: %s", argv[1], dlerror()); return NULL; } module = malloc(sizeof(struct pdm_module)); if (! module) { DEBUG0(DG_AUTH, "pdm_attach", "out of memory"); return NULL; } strlcpy(module->id, argv[0], sizeof(module->id)); strlcpy(module->name, argv[1], sizeof(module->name)); module->next = NULL; module->lib = lib; module->init = dlsym(lib, "pdm_init"); module->reload = dlsym(lib, "pdm_reload"); module->close = dlsym(lib, "pdm_close"); module->args = dlsym(lib, "pdm_args"); module->check = dlsym(lib, "pdm_check"); module->auth = dlsym(lib, "pdm_auth"); if (! module->init) { DEBUG1(DG_AUTH, "pdm_attach", "pdm_init() missing in pdm_%s.so module", argv[1]); goto error; } if (! module->close) { DEBUG1(DG_AUTH, "pdm_attach", "pdm_close() missing in pdm_%s.so module", argv[1]); goto error; } if (! module->check && ! module->auth) { DEBUG1(DG_AUTH, "pdm_attach", "pdm_check() and pdm_auth() missing in pdm_%s.so module", argv[1]); goto error; } DEBUG1(DG_AUTH, "pdm_attach", "calling pdm_init() with argc=%d", argc); for (n=0; ninit))(argc, argv, &mvar, &(module->ctx)); if (errtext) { DEBUG2(DG_AUTH, "pdm_attach", "init of pdm_%s.so module failed: %s", argv[1], errtext); goto error; } return module; error: free(module); dlclose(lib); return NULL; } /***************************************************************************** pdm_detach() *****************************************************************************/ int pdm_detach(struct pdm_module *m) { int r = m->close(m->ctx); dlclose(m->lib); free(m); return r; } /***************************************************************************** pdm_get_args() *****************************************************************************/ char * pdm_get_args(struct pdm_module *m) { if (m->args) return (*(m->args))(m->ctx); else return "[unknown args]"; } /***************************************************************************** pdm_call_reload() *****************************************************************************/ int pdm_call_reload(struct pdm_module *m) { if (m->reload) return (*(m->reload))(m->ctx); /* XLOG-DOC:ADM:004c:pdm_reload_failed * The reloading of a pdm module failed because this module doesn't * support the pdm_reload() function. */ xlog_printf(xlog_adm, 0x004c, "pdm_reload_failed"); return 0; } /***************************************************************************** pmd_auth_user() *****************************************************************************/ pdm_result_t pdm_auth_user(const struct pdm_request *pr, struct pdm_data *pd) { struct pdm_module *e; pdm_result_t result; DEBUG0(DG_AUTH, "pdm_auth_user", "start"); memset(pd, 0, sizeof(struct pdm_data)); for (e = first_pdm_module; e; e = e->next) { if (! e->check) continue; DEBUG1(DG_AUTH, "pdm_auth_user", "Trying module '%s' (check)", e->id); result = (*(e->check))(e->ctx, pr, pd); switch (result) { case pdmAccept: DEBUG0(DG_AUTH, "pdm_auth_user", "User accepted"); return pdmAccept; case pdmFail: DEBUG3(DG_AUTH, "pdm_auth_user", "User exists, but auth failed (backend='%s' user='%s' pass='%s')", pd->backend, pd->user, pd->pass); goto try_auth_only; case pdmError: /* XLOG-DOC:SOS:004d:pdm_error * A module returned an internal error while checking a user. This * means that the module is confused, maybe the underlain database * is corrupted. Check for log messages from the module itself to * find out more. */ xlog_printf(xlog_sos, 0x004d, "pdm_error module='%s'", e->id); break; case pdmUnknown: break; } } DEBUG0(DG_AUTH, "pdm_auth_user", "No module found the user"); return pdmUnknown; try_auth_only: for (e = first_pdm_module; e; e = e->next) { if (! e->auth) continue; DEBUG1(DG_AUTH, "pdm_auth_user", "Trying module '%s' (auth)", e->id); result = (*(e->auth))(e->ctx, pr, pd); switch (result) { case pdmAccept: DEBUG0(DG_AUTH, "pdm_auth_user", "User accepted"); return pdmAccept; case pdmError: /* XLOG-DOC:SOS:004e:pdm_error * A module returned an internal error while checking a user. This * means that the module is confused, maybe the underlain database * is corrupted. Check for log messages from the module itself to * find out more. */ xlog_printf(xlog_sos, 0x004e, "pdm_error module='%s'", e->id); break; case pdmFail: break; case pdmUnknown: break; } } DEBUG0(DG_AUTH, "pdm_auth_user", "User exists, but couldn't be authenticated"); return pdmFail; } /** THE END *****************************************************************/