Hi, at the SambaXP conference last week we talked about testing of PAM modules and we want to do automatic testing. To do this in the Samba build farm we need a separate pam.d config directory for testing. I've created a patch against Linux-PAM which adds a function called pam_start_test(). The only difference is, that it takes a config directory argument. pam_start() calls pam_start_test() with NULL for the config directory and the default (/etc/pam.d/) is used. After this, I've created a patch for http://pamtester.soruceforge.net/ to use pam_start_test() and added the possibility to specify the config directory via a commandline option. It would be great if this would be in a future PAM release. Best regards, -- andreas
Author: Andreas Schneider <mail@xxxxxxxxxxxx> Subject: Add an option to specify the pam config directory and use pam_start_test(). Index: pamtester-0.1.2/src/app.c =================================================================== --- pamtester-0.1.2.orig/src/app.c +++ pamtester-0.1.2/src/app.c @@ -157,6 +157,7 @@ void pamtester_app_init(pamtester_app_t params->app_name = xstrdup(app_name); params->service = NULL; params->user = NULL; + params->config_dir = NULL; params->items = params->last_item = NULL; params->envs = params->last_env = NULL; params->verbose = 0; @@ -171,6 +172,7 @@ void pamtester_app_cleanup(pamtester_app xfree(params->app_name); xfree(params->service); xfree(params->user); + xfree(params->config_dir); for (item = params->items; item != NULL; item = next_item) { next_item = item->next; @@ -209,8 +211,9 @@ int pamtester_app_run(pamtester_app_t *p fprintf(stderr, "%s: invoking pam_start(%s, %s, ...)\n", params->app_name, params->service, params->user); } - if ((err = pam_start((params->service == NULL ? "": params->service), - (params->user == NULL ? "": params->user), &conv, &pamh))) { + if ((err = pam_start_test((params->service == NULL ? "" : params->service), + (params->user == NULL ? "": params->user), + params->config_dir, &conv, &pamh))) { err_msg = xstrdup("Initialization failure"); pamh = NULL; goto out; Index: pamtester-0.1.2/src/app.h =================================================================== --- pamtester-0.1.2.orig/src/app.h +++ pamtester-0.1.2/src/app.h @@ -56,6 +56,7 @@ typedef struct _pamtester_app_t { char *app_name; char *service; char *user; + char *config_dir; int verbose; pamtester_pam_item_t *items; pamtester_pam_item_t *last_item; Index: pamtester-0.1.2/src/pamtester.c =================================================================== --- pamtester-0.1.2.orig/src/pamtester.c +++ pamtester-0.1.2/src/pamtester.c @@ -67,6 +67,17 @@ static int opt_hdlr_verbose(void *param, return 0; } +static int opt_hdlr_configdir(void *param, const char *val) +{ + pamtester_app_t *x = (pamtester_app_t *)param; + + if (val != NULL) { + x->config_dir = xstrdup(val); + } + + return 0; +} + static int opt_hdlr_item(void *param, const char *val) { pamtester_app_t *x = (pamtester_app_t *)param; @@ -127,6 +138,7 @@ static int opt_hdlr_env(void *param, con } pamtester_opt_spec_t options[] = { + { "C", "configdir", 1, 0, '*', opt_hdlr_configdir }, { "I", "item", 1, 1, '*', opt_hdlr_item }, { "E", "env", 1, 1, '*', opt_hdlr_env }, { "v", "verbose", 1, 0, '?', opt_hdlr_verbose }, @@ -143,7 +155,7 @@ int main(int argc, const char **argv) const char *prog_name = xbasename(argv[0]); if (argc < 2) { - fprintf(stderr, "usage: %s [-Eenv=value] [-Iparam=value] service user op_name ...\n", prog_name); + fprintf(stderr, "usage: %s [-Cconfigdir] [-Eenv=value] [-Iparam=value] service user op_name ...\n", prog_name); exit(-1); } Index: pamtester-0.1.2/src/parse_opts.c =================================================================== --- pamtester-0.1.2.orig/src/parse_opts.c +++ pamtester-0.1.2/src/parse_opts.c @@ -49,7 +49,8 @@ #include "util.h" #include "parse_opts.h" -int pamtester_parse_opts(int argc, const char **argv, pamtester_opt_spec_t *options, void *param, int *last_comp, char **err_msg) +int pamtester_parse_opts(int argc, const char **argv, + pamtester_opt_spec_t *options, void *param, int *last_comp, char **err_msg) { int i; int state = 0;
Author: Andreas Schneider <mail@xxxxxxxxxxxx> Subject: Implement a function for testing that you can define a different configuration directory. Index: Linux-PAM-1.0.91/libpam/include/security/pam_appl.h =================================================================== --- Linux-PAM-1.0.91.orig/libpam/include/security/pam_appl.h +++ Linux-PAM-1.0.91/libpam/include/security/pam_appl.h @@ -24,6 +24,12 @@ pam_start(const char *service_name, cons const struct pam_conv *pam_conversation, pam_handle_t **pamh); +extern int PAM_NONNULL((1,4,5)) +pam_start_test(const char *service_name, const char *user, + const char *config_dir, + const struct pam_conv *pam_conversation, + pam_handle_t **pamh); + extern int PAM_NONNULL((1)) pam_end(pam_handle_t *pamh, int pam_status); Index: Linux-PAM-1.0.91/libpam/pam_handlers.c =================================================================== --- Linux-PAM-1.0.91.orig/libpam/pam_handlers.c +++ Linux-PAM-1.0.91/libpam/pam_handlers.c @@ -302,7 +302,8 @@ static int _pam_load_conf_file(pam_handl } if (config_name[0] != '/') { - if (asprintf (&config_path, PAM_CONFIG_DF, config_name) < 0) { + if (asprintf (&config_path, "%s/%s", pamh->config_dir, + config_name) < 0) { pam_syslog(pamh, LOG_CRIT, "asprintf failed"); return PAM_BUF_ERR; } @@ -395,13 +396,14 @@ int _pam_init_handlers(pam_handle_t *pam { struct stat test_d; - /* Is there a PAM_CONFIG_D directory? */ - if ( stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) { + /* Is there a pam config directory? */ + if ( stat(pamh->config_dir, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) { char *filename; int read_something=0; - D(("searching " PAM_CONFIG_D " for config files")); - if (asprintf(&filename, PAM_CONFIG_DF, pamh->service_name) < 0) { + D(("searching %s for config files", pamh->config_dir)); + if (asprintf(&filename, "%s/%s", pamh->config_dir, + pamh->service_name) < 0) { pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: no memory; service %s", pamh->service_name); @@ -448,8 +450,16 @@ int _pam_init_handlers(pam_handle_t *pam if (retval == PAM_SUCCESS) { /* now parse the PAM_DEFAULT_SERVICE_FILE */ - D(("opening %s", PAM_DEFAULT_SERVICE_FILE)); - f = fopen(PAM_DEFAULT_SERVICE_FILE, "r"); + if (asprintf(&filename, "%s/" PAM_DEFAULT_SERVICE, + pamh->config_dir) < 0) { + pam_syslog(pamh, LOG_ERR, + "_pam_init_handlers: no memory; service %s", + pamh->service_name); + return PAM_BUF_ERR; + } + + D(("opening %s", filename)); + f = fopen(filename, "r"); if (f != NULL) { /* would test magic here? */ retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE, @@ -462,7 +472,7 @@ int _pam_init_handlers(pam_handle_t *pam if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: error reading %s", - PAM_DEFAULT_SERVICE_FILE); + filename); pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: [%s]", pam_strerror(pamh, retval)); @@ -473,8 +483,9 @@ int _pam_init_handlers(pam_handle_t *pam D(("unable to open %s", PAM_DEFAULT_SERVICE_FILE)); pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: no default config %s", - PAM_DEFAULT_SERVICE_FILE); + filename); } + _pam_drop(filename); if (!read_something) { /* nothing read successfully */ retval = PAM_ABORT; } Index: Linux-PAM-1.0.91/libpam/pam_private.h =================================================================== --- Linux-PAM-1.0.91.orig/libpam/pam_private.h +++ Linux-PAM-1.0.91/libpam/pam_private.h @@ -26,10 +26,8 @@ #define PAM_CONFIG "/etc/pam.conf" #define PAM_CONFIG_D "/etc/pam.d" -#define PAM_CONFIG_DF "/etc/pam.d/%s" #define PAM_DEFAULT_SERVICE "other" /* lower case */ -#define PAM_DEFAULT_SERVICE_FILE PAM_CONFIG_D "/" PAM_DEFAULT_SERVICE #ifdef PAM_LOCKING /* @@ -154,6 +152,7 @@ struct pam_handle { char *ruser; char *tty; char *xdisplay; + char *config_dir; char *authtok_type; /* PAM_AUTHTOK_TYPE */ struct pam_data *data; struct pam_environ *env; /* structure to maintain environment list */ Index: Linux-PAM-1.0.91/libpam/pam_start.c =================================================================== --- Linux-PAM-1.0.91.orig/libpam/pam_start.c +++ Linux-PAM-1.0.91/libpam/pam_start.c @@ -15,9 +15,18 @@ #include <string.h> #include <syslog.h> -int pam_start ( +int pam_start (const char *service_name, + const char *user, + const struct pam_conv *pam_conversation, + pam_handle_t **pamh) +{ + return pam_start_test(service_name, user, NULL, pam_conversation, pamh); +} + +int pam_start_test ( const char *service_name, const char *user, + const char *config_dir, const struct pam_conv *pam_conversation, pam_handle_t **pamh) { @@ -80,6 +89,20 @@ int pam_start ( } else (*pamh)->user = NULL; + if (config_dir) { + (*pamh)->config_dir = _pam_strdup(config_dir); + } else { + (*pamh)->config_dir = _pam_strdup(PAM_CONFIG_D); + } + + if ((*pamh)->config_dir == NULL) { + pam_syslog(*pamh, LOG_CRIT, + "pam_start: _pam_strdup failed for config_dir"); + _pam_drop((*pamh)->config_dir); + _pam_drop(*pamh); + return (PAM_BUF_ERR); + } + (*pamh)->tty = NULL; (*pamh)->prompt = NULL; /* prompt for pam_get_user() */ (*pamh)->ruser = NULL; @@ -137,3 +160,4 @@ int pam_start ( return PAM_SUCCESS; } + Index: Linux-PAM-1.0.91/libpam/pam_end.c =================================================================== --- Linux-PAM-1.0.91.orig/libpam/pam_end.c +++ Linux-PAM-1.0.91/libpam/pam_end.c @@ -53,6 +53,9 @@ int pam_end(pam_handle_t *pamh, int pam_ _pam_overwrite(pamh->service_name); _pam_drop(pamh->service_name); + _pam_overwrite(pamh->config_dir); + _pam_drop(pamh->config_dir); + _pam_overwrite(pamh->user); _pam_drop(pamh->user); Index: Linux-PAM-1.0.91/libpam/libpam.map =================================================================== --- Linux-PAM-1.0.91.orig/libpam/libpam.map +++ Linux-PAM-1.0.91/libpam/libpam.map @@ -33,6 +33,7 @@ LIBPAM_EXTENSION_1.0 { LIBPAM_EXTENSION_1.1 { global: pam_get_authtok; + pam_start_test; } LIBPAM_EXTENSION_1.0; LIBPAM_MODUTIL_1.0 {
Attachment:
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Pam-list mailing list Pam-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/pam-list