[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PAM Testing



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

[Index of Archives]     [Fedora Users]     [Kernel]     [Red Hat Install]     [Linux for the blind]     [Gimp]
  Powered by Linux