rpms/pam/devel pam-0.99.8.1-substack.patch, NONE, 1.1 pam.spec, 1.161, 1.162

Tomas Mraz (tmraz) fedora-extras-commits at redhat.com
Wed Nov 7 11:42:22 UTC 2007


Author: tmraz

Update of /cvs/pkgs/rpms/pam/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv15738

Modified Files:
	pam.spec 
Added Files:
	pam-0.99.8.1-substack.patch 
Log Message:
* Wed Nov  7 2007 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-11
- add substack support


pam-0.99.8.1-substack.patch:

--- NEW FILE pam-0.99.8.1-substack.patch ---
Index: libpam/pam_dispatch.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_dispatch.c,v
retrieving revision 1.11
diff -u -p -r1.11 pam_dispatch.c
--- libpam/pam_dispatch.c	1 Aug 2006 08:54:57 -0000	1.11
+++ libpam/pam_dispatch.c	12 Oct 2007 16:23:37 -0000
@@ -34,7 +34,8 @@
 static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
 			     _pam_boolean resumed, int use_cached_chain)
 {
-    int depth, impression, status, skip_depth;
+    int depth, impression, status, skip_depth, prev_level, stack_level;
+    struct _pam_substack_state *substates = NULL;
 
     IF_NO_PAMH("_pam_dispatch_aux", pamh, PAM_SYSTEM_ERR);
 
@@ -54,27 +55,51 @@ static int _pam_dispatch_aux(pam_handle_
 	skip_depth = pamh->former.depth;
 	status = pamh->former.status;
 	impression = pamh->former.impression;
+	substates = pamh->former.substates;
 	/* forget all that */
 	pamh->former.impression = _PAM_UNDEF;
 	pamh->former.status = PAM_MUST_FAIL_CODE;
 	pamh->former.depth = 0;
+	pamh->former.substates = NULL;
     } else {
 	skip_depth = 0;
-	impression = _PAM_UNDEF;
-	status = PAM_MUST_FAIL_CODE;
+	substates = malloc(PAM_SUBSTACK_MAX_LEVEL * sizeof(*substates));
+	if (substates == NULL) {
+	    pam_syslog(pamh, LOG_CRIT,
+		       "_pam_dispatch_aux: no memory for substack states");
+	    return PAM_BUF_ERR;
+	}
+	substates[0].impression = impression = _PAM_UNDEF;
+	substates[0].status = status = PAM_MUST_FAIL_CODE;
     }
 
+    prev_level = 0;
+
     /* Loop through module logic stack */
-    for (depth=0 ; h != NULL ; h = h->next, ++depth) {
+    for (depth=0 ; h != NULL ; prev_level = stack_level, h = h->next, ++depth) {
 	int retval, cached_retval, action;
 
+        stack_level = h->stack_level;
+
 	/* skip leading modules if they have already returned */
 	if (depth < skip_depth) {
 	    continue;
 	}
 
+	/* remember state if we are entering a substack */
+	if (prev_level < stack_level) { 
+	    substates[stack_level].impression = impression;
+	    substates[stack_level].status = status;
+	}
+
 	/* attempt to call the module */
-	if (h->func == NULL) {
+	if (h->handler_type == PAM_HT_MUST_FAIL) {
+	    D(("module poorly listed in PAM config; forcing failure"));
+	    retval = PAM_MUST_FAIL_CODE;
+	} else if (h->handler_type == PAM_HT_SUBSTACK) {
+	    D(("skipping substack handler"));
+	    continue;
+	} else if (h->func == NULL) {
 	    D(("module function is not defined, indicating failure"));
 	    retval = PAM_MODULE_UNKNOWN;
 	} else {
@@ -83,10 +108,6 @@ static int _pam_dispatch_aux(pam_handle_
 	    retval = h->func(pamh, flags, h->argc, h->argv);
 	    pamh->mod_name=NULL;
 	    D(("module returned: %s", pam_strerror(pamh, retval)));
-	    if (h->must_fail) {
-		D(("module poorly listed in PAM config; forcing failure"));
-		retval = PAM_MUST_FAIL_CODE;
-	    }
 	}
 
 	/*
@@ -100,6 +121,7 @@ static int _pam_dispatch_aux(pam_handle_
 	    pamh->former.impression = impression;
 	    pamh->former.status = status;
 	    pamh->former.depth = depth;
+	    pamh->former.substates = substates;
 
 	    D(("module %d returned PAM_INCOMPLETE", depth));
 	    return retval;
@@ -176,8 +198,8 @@ static int _pam_dispatch_aux(pam_handle_
 	switch (action) {
 	case _PAM_ACTION_RESET:
 
-	    impression = _PAM_UNDEF;
-	    status = PAM_MUST_FAIL_CODE;
+	    impression = substates[stack_level].impression;
+	    status = substates[stack_level].status;
 	    break;
 
 	case _PAM_ACTION_OK:
@@ -244,9 +266,13 @@ static int _pam_dispatch_aux(pam_handle_
 		}
 
 		/* this means that we need to skip #action stacked modules */
-		do {
- 		    h = h->next;
-		} while ( --action > 0 && h != NULL );
+		while (h->next != NULL && h->next->stack_level >= stack_level && action > 0) {
+ 		    do {
+			h = h->next;
+			++depth;
+		    } while (h->next != NULL && h->next->stack_level > stack_level);
+		    --action;
+		}
 
 		/* note if we try to skip too many modules action is
                    still non-zero and we snag the next if. */
@@ -254,14 +280,19 @@ static int _pam_dispatch_aux(pam_handle_
 
 	    /* this case is a syntax error: we can't succeed */
 	    if (action) {
-		D(("action syntax error"));
+		pam_syslog(pamh, LOG_ERR, "bad jump in stack");
 		impression = _PAM_NEGATIVE;
 		status = PAM_MUST_FAIL_CODE;
 	    }
 	}
-    }
-
+	continue;
+	
 decision_made:     /* by getting  here we have made a decision */
+	while (h->next != NULL && h->next->stack_level >= stack_level) {
+	    h = h->next;
+	    ++depth;
+	}
+    }
 
     /* Sanity check */
     if ( status == PAM_SUCCESS && impression != _PAM_POSITIVE ) {
@@ -269,6 +300,7 @@ decision_made:     /* by getting  here w
 	status = PAM_MUST_FAIL_CODE;
     }
 
+    free(substates);
     /* We have made a decision about the modules executed */
     return status;
 }
Index: libpam/pam_end.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_end.c,v
retrieving revision 1.4
diff -u -p -r1.4 pam_end.c
--- libpam/pam_end.c	12 Jan 2006 10:06:49 -0000	1.4
+++ libpam/pam_end.c	12 Oct 2007 16:23:37 -0000
@@ -71,6 +71,8 @@ int pam_end(pam_handle_t *pamh, int pam_
     _pam_drop(pamh->pam_conversation);
     pamh->fail_delay.delay_fn_ptr = NULL;
 
+    _pam_drop(pamh->former.substates);
+
     /* and finally liberate the memory for the pam_handle structure */
 
     _pam_drop(pamh);
Index: libpam/pam_handlers.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_handlers.c,v
retrieving revision 1.24
diff -u -p -r1.24 pam_handlers.c
--- libpam/pam_handlers.c	14 Jun 2006 11:41:47 -0000	1.24
+++ libpam/pam_handlers.c	12 Oct 2007 16:23:37 -0000
@@ -18,7 +18,7 @@
 
 #define BUF_SIZE                  1024
 #define MODULE_CHUNK              4
-#define UNKNOWN_MODULE_PATH       "<*unknown module path*>"
+#define UNKNOWN_MODULE       "<*unknown module*>"
 #ifndef _PAM_ISA
 #define _PAM_ISA "."
 #endif
@@ -28,7 +28,7 @@ static int _pam_assemble_line(FILE *f, c
 static void _pam_free_handlers_aux(struct handler **hp);
 
 static int _pam_add_handler(pam_handle_t *pamh
-		     , int must_fail, int other, int type
+		     , int must_fail, int other, int stack_level, int type
 		     , int *actions, const char *mod_path
 		     , int argc, char **argv, int argvlen);
 
@@ -43,6 +43,7 @@ static int _pam_add_handler(pam_handle_t
 static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
 				, const char *service /* specific file */
 				, int module_type /* specific type */
+				, int stack_level /* level of substack */
 #ifdef PAM_READ_BOTH_CONFS
 				, int not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -51,6 +52,7 @@ static int _pam_load_conf_file(pam_handl
 static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
 				, const char *known_service /* specific file */
 				, int requested_module_type /* specific type */
+				, int stack_level /* level of substack */
 #ifdef PAM_READ_BOTH_CONFS
 				, int not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -68,7 +70,7 @@ static int _pam_parse_conf_file(pam_hand
 	int module_type, actions[_PAM_RETURN_VALUES];
 	int other;            /* set if module is for PAM_DEFAULT_SERVICE */
 	int res;              /* module added successfully? */
-	int must_fail=0;      /* a badly formatted line must fail when used */
+	int handler_type = PAM_HT_MODULE; /* regular handler from a module */
 	int argc;
 	char **argv;
 	int argvlen;
@@ -92,6 +94,7 @@ static int _pam_parse_conf_file(pam_hand
 	/* accept "service name" or PAM_DEFAULT_SERVICE modules */
 	if (!strcasecmp(this_service, pamh->service_name) || other) {
 	    int pam_include = 0;
+	    int substack = 0;
 
 	    /* This is a service we are looking for */
 	    D(("_pam_init_handlers: Found PAM config entry for: %s"
@@ -105,7 +108,7 @@ static int _pam_parse_conf_file(pam_hand
 			   "(%s) empty module type", this_service);
 	        module_type = (requested_module_type != PAM_T_ANY) ?
 		  requested_module_type : PAM_T_AUTH;	/* most sensitive */
-	        must_fail = 1; /* install as normal but fail when dispatched */
+	        handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
 	    } else if (!strcasecmp("auth", tok)) {
 		module_type = PAM_T_AUTH;
 	    } else if (!strcasecmp("session", tok)) {
@@ -121,9 +124,9 @@ static int _pam_parse_conf_file(pam_hand
 			   this_service, tok);
 		module_type = (requested_module_type != PAM_T_ANY) ?
 			      requested_module_type : PAM_T_AUTH;	/* most sensitive */
-		must_fail = 1; /* install as normal but fail when dispatched */
+		handler_type = PAM_HT_MUST_FAIL; /* install as normal but fail when dispatched */
 	    }
-	    D(("Using %s config entry: %s", must_fail?"BAD ":"", tok));
+	    D(("Using %s config entry: %s", handler_type?"BAD ":"", tok));
 	    if (requested_module_type != PAM_T_ANY &&
 	        module_type != requested_module_type) {
 		D(("Skipping config entry: %s (requested=%d, found=%d)",
@@ -145,7 +148,7 @@ static int _pam_parse_conf_file(pam_hand
 		pam_syslog(pamh, LOG_ERR,
 			   "(%s) no control flag supplied", this_service);
 		_pam_set_default_control(actions, _PAM_ACTION_BAD);
-		must_fail = 1;
+		handler_type = PAM_HT_MUST_FAIL;
 	    } else if (!strcasecmp("required", tok)) {
 		D(("*PAM_F_REQUIRED*"));
 		actions[PAM_SUCCESS] = _PAM_ACTION_OK;
@@ -171,6 +174,11 @@ static int _pam_parse_conf_file(pam_hand
 	    } else if (!strcasecmp("include", tok)) {
 		D(("*PAM_F_INCLUDE*"));
 		pam_include = 1;
+		substack = 0;
+	    } else if (!strcasecmp("substack", tok)) {
+		D(("*PAM_F_SUBSTACK*"));
+		pam_include = 1;
+		substack = 1;
 	    } else {
 		D(("will need to parse %s", tok));
 		_pam_parse_control(actions, tok);
@@ -180,7 +188,18 @@ static int _pam_parse_conf_file(pam_hand
 
 	    tok = _pam_StrTok(NULL, " \n\t", &nexttok);
 	    if (pam_include) {
-		if (_pam_load_conf_file(pamh, tok, this_service, module_type
+	    	if (substack) {
+		    res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
+		    		stack_level, module_type, actions, tok,
+		    		0, NULL, 0);
+		    if (res != PAM_SUCCESS) {
+			pam_syslog(pamh, LOG_ERR, "error adding substack %s", tok);
+			D(("failed to load module - aborting"));
+			return PAM_ABORT;
+		    }  	    
+	    	}
+		if (_pam_load_conf_file(pamh, tok, this_service, module_type,
+		    stack_level + substack
 #ifdef PAM_READ_BOTH_CONFS
 					      , !other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -188,7 +207,7 @@ static int _pam_parse_conf_file(pam_hand
 		    continue;
 		_pam_set_default_control(actions, _PAM_ACTION_BAD);
 		mod_path = NULL;
-		must_fail = 1;
+		handler_type = PAM_HT_MUST_FAIL;
 		nexttok = NULL;
 	    } else if (tok != NULL) {
 		mod_path = tok;
@@ -199,7 +218,7 @@ static int _pam_parse_conf_file(pam_hand
 		pam_syslog(pamh, LOG_ERR,
 		           "(%s) no module name supplied", this_service);
 		mod_path = NULL;
-		must_fail = 1;
+		handler_type = PAM_HT_MUST_FAIL;
 	    }
 
 	    /* nexttok points to remaining arguments... */
@@ -219,7 +238,7 @@ static int _pam_parse_conf_file(pam_hand
 		int y;
 
 		D(("CONF%s: %s%s %d %s %d"
-		   , must_fail?"<*will fail*>":""
+		   , handler_type==PAM_HT_MUST_FAIL?"<*will fail*>":""
 		   , this_service, other ? "(backup)":""
 		   , module_type
 		   , mod_path, argc));
@@ -235,7 +254,7 @@ static int _pam_parse_conf_file(pam_hand
 	    }
 #endif
 
-	    res = _pam_add_handler(pamh, must_fail, other
+	    res = _pam_add_handler(pamh, handler_type, other, stack_level
 				   , module_type, actions, mod_path
 				   , argc, argv, argvlen);
 	    if (res != PAM_SUCCESS) {
@@ -252,6 +271,7 @@ static int _pam_parse_conf_file(pam_hand
 static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
 				, const char *service /* specific file */
 				, int module_type /* specific type */
+				, int stack_level /* level of substack */
 #ifdef PAM_READ_BOTH_CONFS
 				, int not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -263,6 +283,12 @@ static int _pam_load_conf_file(pam_handl
 
     D(("_pam_load_conf_file called"));
 
+    if (stack_level >= PAM_SUBSTACK_MAX_LEVEL) {
+	D(("maximum level of substacks reached"));
+	pam_syslog(pamh, LOG_ERR, "maximum level of substacks reached");
+	return PAM_ABORT;
+    }
+
     if (config_name == NULL) {
 	D(("no config file supplied"));
 	pam_syslog(pamh, LOG_ERR, "(%s) no config file supplied", service);
@@ -280,7 +306,7 @@ static int _pam_load_conf_file(pam_handl
     D(("opening %s", config_name));
     f = fopen(config_name, "r");
     if (f != NULL) {
-	retval = _pam_parse_conf_file(pamh, f, service, module_type
+	retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level
 #ifdef PAM_READ_BOTH_CONFS
 					      , not_other
 #endif /* PAM_READ_BOTH_CONFS */
@@ -379,7 +405,8 @@ int _pam_init_handlers(pam_handle_t *pam
 	    f = fopen(filename, "r");
 	    if (f != NULL) {
 		/* would test magic here? */
-		retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY
+		retval = _pam_parse_conf_file(pamh, f, pamh->service_name,
+		    PAM_T_ANY, 0
 #ifdef PAM_READ_BOTH_CONFS
 					      , 0
 #endif /* PAM_READ_BOTH_CONFS */
@@ -400,7 +427,7 @@ int _pam_init_handlers(pam_handle_t *pam
 		D(("checking %s", PAM_CONFIG));
 
 		if ((f = fopen(PAM_CONFIG,"r")) != NULL) {
-		    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 1);
+		    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0, 1);
 		    fclose(f);
 		} else
 #endif /* PAM_READ_BOTH_CONFS */
@@ -419,9 +446,8 @@ int _pam_init_handlers(pam_handle_t *pam
 		f = fopen(PAM_DEFAULT_SERVICE_FILE, "r");
 		if (f != NULL) {
 		    /* would test magic here? */
-		    retval = _pam_parse_conf_file(pamh, f
-						  , PAM_DEFAULT_SERVICE
-						  , PAM_T_ANY
+		    retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE,
+			PAM_T_ANY, 0
 #ifdef PAM_READ_BOTH_CONFS
 						  , 0
 #endif /* PAM_READ_BOTH_CONFS */
@@ -454,7 +480,7 @@ int _pam_init_handlers(pam_handle_t *pam
 		return PAM_ABORT;
 	    }
 
-	    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY
+	    retval = _pam_parse_conf_file(pamh, f, NULL, PAM_T_ANY, 0
 #ifdef PAM_READ_BOTH_CONFS
 					  , 0
 #endif /* PAM_READ_BOTH_CONFS */
@@ -581,46 +607,19 @@ extract_modulename(const char *mod_path)
   return retval;
 }
 
-int _pam_add_handler(pam_handle_t *pamh
-		     , int must_fail, int other, int type
-		     , int *actions, const char *mod_path
-		     , int argc, char **argv, int argvlen)
+static struct loaded_module *
+_pam_load_module(pam_handle_t *pamh, const char *mod_path)
 {
-    struct loaded_module *mod;
     int x = 0;
-    struct handler **handler_p;
-    struct handler **handler_p2;
-    struct handlers *the_handlers;
-    const char *sym, *sym2;
-    char *mod_full_path=NULL;
+    int success;
 #ifndef PAM_STATIC
     char *mod_full_isa_path=NULL, *isa=NULL;
 #endif
-    servicefn func, func2;
-    int success;
-
-    D(("called."));
-    IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
-
-    /* if NULL set to something that can be searched for */
-    switch (mod_path != NULL) {
-    default:
-	if (mod_path[0] == '/') {
-	    break;
-	}
-	if (asprintf(&mod_full_path, "%s%s",
-		     DEFAULT_MODULE_PATH, mod_path) >= 0) {
-	    mod_path = mod_full_path;
-	    break;
-	}
-	mod_full_path = NULL;
-	pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
-    case 0:
-	mod_path = UNKNOWN_MODULE_PATH;
-    }
+    struct loaded_module *mod;
 
-    D(("_pam_add_handler: adding type %d, module `%s'",type,mod_path));
-    mod  = pamh->handlers.module;
+    D(("_pam_load_module: loading module `%s'", mod_path));
+    
+    mod = pamh->handlers.module;
 
     /* First, ensure the module is loaded */
     while (x < pamh->handlers.modules_used) {
@@ -639,9 +638,8 @@ int _pam_add_handler(pam_handle_t *pamh
 	    if (tmp == NULL) {
 		D(("cannot enlarge module pointer memory"));
 		pam_syslog(pamh, LOG_ERR,
-				"realloc returned NULL in _pam_add_handler");
-		_pam_drop(mod_full_path);
-		return PAM_ABORT;
+				"realloc returned NULL in _pam_load_module");
+		return NULL;
 	    }
 	    pamh->handlers.module = tmp;
 	    pamh->handlers.modules_allocated += MODULE_CHUNK;
@@ -654,10 +652,10 @@ int _pam_add_handler(pam_handle_t *pamh
 	/* Only load static function if function was not found dynamically.
 	 * This code should work even if no dynamic loading is available. */
 	if (success != PAM_SUCCESS) {
-	    D(("_pam_add_handler: open static handler %s", mod_path));
+	    D(("_pam_load_module: open static handler %s", mod_path));
 	    mod->dl_handle = _pam_open_static_handler(pamh, mod_path);
 	    if (mod->dl_handle == NULL) {
-	        D(("_pam_add_handler: unable to find static handler %s",
+	        D(("_pam_load_module: unable to find static handler %s",
 		   mod_path));
 		pam_syslog(pamh, LOG_ERR,
 				"unable to open static handler %s", mod_path);
@@ -670,15 +668,15 @@ int _pam_add_handler(pam_handle_t *pamh
 	    }
 	}
 #else
-	D(("_pam_add_handler: _pam_dlopen(%s)", mod_path));
+	D(("_pam_load_module: _pam_dlopen(%s)", mod_path));
 	mod->dl_handle = _pam_dlopen(mod_path);
-	D(("_pam_add_handler: _pam_dlopen'ed"));
-	D(("_pam_add_handler: dlopen'ed"));
+	D(("_pam_load_module: _pam_dlopen'ed"));
+	D(("_pam_load_module: dlopen'ed"));
 	if (mod->dl_handle == NULL) {
 	    if (strstr(mod_path, "$ISA")) {
 		mod_full_isa_path = malloc(strlen(mod_path) + strlen(_PAM_ISA) + 1);
 		if (mod_full_isa_path == NULL) {
-		    D(("_pam_handler: couldn't get memory for mod_path"));
+		    D(("_pam_load_module: couldn't get memory for mod_path"));
 		    pam_syslog(pamh, LOG_ERR, "no memory for module path");
 		    success = PAM_ABORT;
 		} else {
@@ -694,9 +692,9 @@ int _pam_add_handler(pam_handle_t *pamh
 	    }
 	}
 	if (mod->dl_handle == NULL) {
-	    D(("_pam_add_handler: _pam_dlopen(%s) failed", mod_path));
-	    pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s)", mod_path);
-	    pam_syslog(pamh, LOG_ERR, "[error: %s]", _pam_dlerror());
+	    D(("_pam_load_module: _pam_dlopen(%s) failed", mod_path));
+	    pam_syslog(pamh, LOG_ERR, "unable to dlopen(%s): %s", mod_path,
+	        _pam_dlerror());
 	    /* Don't abort yet; static code may be able to find function.
 	     * But defaults to abort if nothing found below... */
 	} else {
@@ -717,7 +715,7 @@ int _pam_add_handler(pam_handle_t *pamh
 
 	/* indicate its name - later we will search for it by this */
 	if ((mod->name = _pam_strdup(mod_path)) == NULL) {
-	    D(("_pam_handler: couldn't get memory for mod_path"));
+	    D(("_pam_load_module: couldn't get memory for mod_path"));
 	    pam_syslog(pamh, LOG_ERR, "no memory for module path");
 	    success = PAM_ABORT;
 	}
@@ -726,18 +724,54 @@ int _pam_add_handler(pam_handle_t *pamh
 	mod += x;                                    /* the located module */
 	success = PAM_SUCCESS;
     }
+    return success == PAM_SUCCESS ? mod : NULL;
+}
+
+int _pam_add_handler(pam_handle_t *pamh
+		     , int handler_type, int other, int stack_level, int type
+		     , int *actions, const char *mod_path
+		     , int argc, char **argv, int argvlen)
+{
+    struct loaded_module *mod = NULL;
+    struct handler **handler_p;
+    struct handler **handler_p2;
+    struct handlers *the_handlers;
+    const char *sym, *sym2;
+    char *mod_full_path;
+    servicefn func, func2;
+    int mod_type = PAM_MT_FAULTY_MOD;
+
+    D(("called."));
+    IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
 
-    _pam_drop(mod_full_path);
-    mod_path = NULL;                        /* no longer needed or trusted */
+    D(("_pam_add_handler: adding type %d, handler_type %d, module `%s'",
+	type, handler_type, mod_path));
 
-    /* Now return error if necessary after trying all possible ways... */
-    if (success != PAM_SUCCESS)
-	return(success);
+    if (handler_type == PAM_HT_MODULE && mod_path != NULL) {
+	if (mod_path[0] == '/') {
+	    mod = _pam_load_module(pamh, mod_path);
+	} else if (asprintf(&mod_full_path, "%s%s",
+			     DEFAULT_MODULE_PATH, mod_path) >= 0) {
+	    mod = _pam_load_module(pamh, mod_full_path);
+	    _pam_drop(mod_full_path);
+	} else {
+	    pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
+	    return PAM_ABORT;
+	}
+
+	if (mod == NULL) {
+	    /* if we get here with NULL it means allocation error */
+	    return PAM_ABORT;
+	}
+	
+	mod_type = mod->type;
+    }
+    
+    if (mod_path == NULL)
+    	mod_path = UNKNOWN_MODULE;
 
     /*
-     * At this point 'mod' points to the stored/loaded module. If its
-     * dl_handle is unknown, then we must be able to indicate dispatch
-     * failure with 'must_fail'
+     * At this point 'mod' points to the stored/loaded module.
      */
 
     /* Now define the handler(s) based on mod->dlhandle and type */
@@ -780,43 +814,43 @@ int _pam_add_handler(pam_handle_t *pamh
     /* are the modules reliable? */
     if (
 #ifdef PAM_STATIC
-	 mod->type != PAM_MT_STATIC_MOD
+	 mod_type != PAM_MT_STATIC_MOD
 	 &&
 #else
-	 mod->type != PAM_MT_DYNAMIC_MOD
+	 mod_type != PAM_MT_DYNAMIC_MOD
 	 &&
 #endif
-	 mod->type != PAM_MT_FAULTY_MOD
+	 mod_type != PAM_MT_FAULTY_MOD
 	) {
-	D(("_pam_add_handlers: illegal module library type; %d", mod->type));
+	D(("_pam_add_handlers: illegal module library type; %d", mod_type));
 	pam_syslog(pamh, LOG_ERR,
 			"internal error: module library type not known: %s;%d",
-			sym, mod->type);
+			sym, mod_type);
 	return PAM_ABORT;
     }
 
     /* now identify this module's functions - for non-faulty modules */
 
 #ifdef PAM_STATIC
-    if ((mod->type == PAM_MT_STATIC_MOD) &&
+    if ((mod_type == PAM_MT_STATIC_MOD) &&
         (func = (servicefn)_pam_get_static_sym(mod->dl_handle, sym)) == NULL) {
 	pam_syslog(pamh, LOG_ERR, "unable to resolve static symbol: %s", sym);
     }
 #else
-    if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
+    if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
         !(func = _pam_dlsym(mod->dl_handle, sym)) ) {
 	pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym);
     }
 #endif
     if (sym2) {
 #ifdef PAM_STATIC
-	if ((mod->type == PAM_MT_STATIC_MOD) &&
+	if ((mod_type == PAM_MT_STATIC_MOD) &&
 	    (func2 = (servicefn)_pam_get_static_sym(mod->dl_handle, sym2))
 	    == NULL) {
 	    pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
 	}
 #else
-	if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
+	if ((mod_type == PAM_MT_DYNAMIC_MOD) &&
 	    !(func2 = _pam_dlsym(mod->dl_handle, sym2)) ) {
 	    pam_syslog(pamh, LOG_ERR, "unable to resolve symbol: %s", sym2);
 	}
@@ -835,14 +869,15 @@ int _pam_add_handler(pam_handle_t *pamh
 	return (PAM_ABORT);
     }
 
-    (*handler_p)->must_fail = must_fail;        /* failure forced? */
+    (*handler_p)->handler_type = handler_type;
+    (*handler_p)->stack_level = stack_level;
     (*handler_p)->func = func;
     memcpy((*handler_p)->actions,actions,sizeof((*handler_p)->actions));
     (*handler_p)->cached_retval = _PAM_INVALID_RETVAL;
     (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
     (*handler_p)->argc = argc;
     (*handler_p)->argv = argv;                       /* not a copy */
-    (*handler_p)->mod_name = extract_modulename(mod->name);
+    (*handler_p)->mod_name = extract_modulename(mod_path);
     (*handler_p)->next = NULL;
 
     /* some of the modules have a second calling function */
@@ -857,7 +892,8 @@ int _pam_add_handler(pam_handle_t *pamh
 	    return (PAM_ABORT);
 	}
 
-	(*handler_p2)->must_fail = must_fail;        /* failure forced? */
+	(*handler_p2)->handler_type = handler_type;
+	(*handler_p2)->stack_level = stack_level;
 	(*handler_p2)->func = func2;
 	memcpy((*handler_p2)->actions,actions,sizeof((*handler_p2)->actions));
 	(*handler_p2)->cached_retval =  _PAM_INVALID_RETVAL;     /* ignored */
@@ -873,7 +909,7 @@ int _pam_add_handler(pam_handle_t *pamh
 	} else {
 	    (*handler_p2)->argv = NULL;              /* no arguments */
 	}
-	(*handler_p2)->mod_name = extract_modulename(mod->name);
+	(*handler_p2)->mod_name = extract_modulename(mod_path);
 	(*handler_p2)->next = NULL;
     }
 
Index: libpam/pam_private.h
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_private.h,v
retrieving revision 1.19
diff -u -p -r1.19 pam_private.h
--- libpam/pam_private.h	24 Jul 2006 15:47:40 -0000	1.19
+++ libpam/pam_private.h	12 Oct 2007 16:23:37 -0000
@@ -44,7 +44,7 @@
 #define _PAM_INVALID_RETVAL  -1    /* default value for cached_retval */
 
 struct handler {
-    int must_fail;
+    int handler_type;
     int (*func)(pam_handle_t *pamh, int flags, int argc, char **argv);
     int actions[_PAM_RETURN_VALUES];
     /* set by authenticate, open_session, chauthtok(1st)
@@ -54,8 +54,13 @@ struct handler {
     char **argv;
     struct handler *next;
     char *mod_name;
+    int stack_level;
 };
 
+#define PAM_HT_MODULE       0
+#define PAM_HT_MUST_FAIL    1
+#define PAM_HT_SUBSTACK     2
+
 struct loaded_module {
     char *name;
     int type; /* PAM_STATIC_MOD or PAM_DYNAMIC_MOD */
@@ -76,7 +81,7 @@ struct handlers {
 };
 
 struct service {
-    struct loaded_module *module; /* Only used for dynamic loading */
+    struct loaded_module *module; /* Array of modules */
     int modules_allocated;
     int modules_used;
     int handlers_loaded;
@@ -111,6 +116,12 @@ struct _pam_fail_delay {
     const void *delay_fn_ptr;
 };
 
+/* initial state in substack */
+struct _pam_substack_state {
+    int impression;
+    int status;
+};
+
 struct _pam_former_state {
 /* this is known and set by _pam_dispatch() */
     int choice;            /* which flavor of module function did we call? */
@@ -119,6 +130,7 @@ struct _pam_former_state {
     int depth;             /* how deep in the stack were we? */
     int impression;        /* the impression at that time */
     int status;            /* the status before returning incomplete */
+    struct _pam_substack_state *substates; /* array of initial substack states */
 
 /* state info used by pam_get_user() function */
     int fail_user;
@@ -175,6 +187,8 @@ struct pam_handle {
 #define _PAM_ACTION_UNDEF      -6   /* this is treated as an error
 				       ( = _PAM_ACTION_BAD) */
 
+#define PAM_SUBSTACK_MAX_LEVEL 16   /* maximum level of substacks */
+
 /* character tables for parsing config files */
 extern const char * const _pam_token_actions[-_PAM_ACTION_UNDEF];
 extern const char * const _pam_token_returns[_PAM_RETURN_VALUES+1];
Index: libpam/pam_start.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/libpam/pam_start.c,v
retrieving revision 1.9
diff -u -p -r1.9 pam_start.c
--- libpam/pam_start.c	24 Jul 2006 15:47:40 -0000	1.9
+++ libpam/pam_start.c	12 Oct 2007 16:23:37 -0000
@@ -88,6 +88,7 @@ int pam_start (
     (*pamh)->oldauthtok = NULL;
     (*pamh)->fail_delay.delay_fn_ptr = NULL;
     (*pamh)->former.choice = PAM_NOT_STACKED;
+    (*pamh)->former.substates = NULL;
 #ifdef HAVE_LIBAUDIT
     (*pamh)->audit_state = 0;
 #endif
Index: doc/man/pam.conf-syntax.xml
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/doc/man/pam.conf-syntax.xml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- doc/man/pam.conf-syntax.xml	26 Aug 2007 22:44:51 -0000	1.4
+++ doc/man/pam.conf-syntax.xml	19 Oct 2007 17:06:30 -0000	1.5
@@ -180,6 +180,24 @@
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term>substack</term>
+        <listitem>
+          <para>
+            include all lines of given type from the configuration
+            file specified as an argument to this control. This differs from
+            <emphasis>include</emphasis> in that evaluation of the
+            <emphasis>done</emphasis> and <emphasis>die</emphasis> actions
+            in a substack does not cause skipping the rest of the complete
+            module stack, but only of the substack. Jumps in a substack
+            also can not make evaluation jump out of it, and the whole substack
+            is counted as one module when the jump is done in a parent stack.
+            The <emphasis>reset</emphasis> action will reset the state of a
+            module stack to the state it was in as of beginning of the substack
+            evaluation.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
 
     <para>


Index: pam.spec
===================================================================
RCS file: /cvs/pkgs/rpms/pam/devel/pam.spec,v
retrieving revision 1.161
retrieving revision 1.162
diff -u -r1.161 -r1.162
--- pam.spec	25 Sep 2007 20:26:29 -0000	1.161
+++ pam.spec	7 Nov 2007 11:41:49 -0000	1.162
@@ -11,7 +11,7 @@
 Summary: A security tool which provides authentication for applications
 Name: pam
 Version: 0.99.8.1
-Release: 10%{?dist}
+Release: 11%{?dist}
 # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant
 # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+,
 # pam_rhosts_auth module is BSD with advertising
@@ -44,6 +44,7 @@
 Patch45: pam-0.99.8.1-selinux-permit.patch
 Patch46: pam-0.99.8.1-succif-in-operator.patch
 Patch47: pam-0.99.8.1-xauth-no-free.patch
+Patch48: pam-0.99.8.1-substack.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 Requires: cracklib, cracklib-dicts >= 2.8
@@ -115,6 +116,7 @@
 %patch45 -p1 -b .permit
 %patch46 -p1 -b .in-operator
 %patch47 -p1 -b .no-free
+%patch48 -p0 -b .substack
 
 autoreconf
 
@@ -407,6 +409,9 @@
 %doc doc/adg/*.txt doc/adg/html
 
 %changelog
+* Wed Nov  7 2007 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-11
+- add substack support
+
 * Tue Sep 25 2007 Tomas Mraz <tmraz at redhat.com> 0.99.8.1-10
 - update db4 to 4.6.19 (#274661)
 




More information about the fedora-extras-commits mailing list