/*****************************************************************************
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 <jochen@remote.org>
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 <config.h>
#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; n<argc; n++) {
DEBUG2(DG_AUTH, "pdm_attach", "calling pdm_init() with argv[%d]=%s", n, argv[n]);
}
/* these pointers are needed by the module for debug logging */
mvar.debug = &debug;
mvar.xlog_printf = xlog_printf;
errtext = (*(module->init))(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 *****************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1