PAM Testing

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

 



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