1 /* pam_handlers.c -- pam config file parsing and module loading */
4 * created by Marc Ewing.
5 * Currently maintained by Andrew G. Morgan <morgan@kernel.org>
14 #include <sys/types.h>
25 #endif /* PAM_DYNAMIC */
27 #include "pam_private.h"
29 /* If not required, define as nothing */
30 #ifndef SHLIB_SYM_PREFIX
31 # define SHLIB_SYM_PREFIX ""
35 #define MODULE_CHUNK 4
36 #define UNKNOWN_MODULE_PATH "<*unknown module path*>"
38 static int _pam_assemble_line(FILE *f, char *buf, int buf_len);
40 static void _pam_free_handlers_aux(struct handler **hp);
42 static int _pam_add_handler(pam_handle_t *pamh
43 , int must_fail, int other, int type
44 , int *actions, const char *mod_path
45 , int argc, char **argv, int argvlen);
47 /* Values for module type */
54 static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
55 , const char *known_service /* specific file */
56 #ifdef PAM_READ_BOTH_CONFS
58 #endif /* PAM_READ_BOTH_CONFS */
62 int x; /* read a line from the FILE *f ? */
64 * read a line from the configuration (FILE *) f
66 while ((x = _pam_assemble_line(f, buf, BUF_SIZE)) > 0) {
67 char *tok, *nexttok=NULL;
68 const char *this_service;
70 int module_type, actions[_PAM_RETURN_VALUES];
71 int other; /* set if module is for PAM_DEFAULT_SERVICE */
72 int res; /* module added successfully? */
73 int must_fail=0; /* a badly formatted line must fail when used */
78 D(("_pam_init_handler: LINE: %s", buf));
79 if (known_service != NULL) {
81 /* No service field: all lines are for the known service. */
82 this_service = known_service;
84 this_service = tok = _pam_StrTok(buf, " \n\t", &nexttok);
87 #ifdef PAM_READ_BOTH_CONFS
91 #endif /* PAM_READ_BOTH_CONFS */
92 other = !_pam_strCMP(this_service, PAM_DEFAULT_SERVICE);
94 /* accept "service name" or PAM_DEFAULT_SERVICE modules */
95 if (!_pam_strCMP(this_service, pamh->service_name) || other) {
96 /* This is a service we are looking for */
97 D(("_pam_init_handlers: Found PAM config entry for: %s"
100 tok = _pam_StrTok(NULL, " \n\t", &nexttok);
101 if (!_pam_strCMP("auth", tok)) {
102 module_type = PAM_T_AUTH;
103 } else if (!_pam_strCMP("session", tok)) {
104 module_type = PAM_T_SESS;
105 } else if (!_pam_strCMP("account", tok)) {
106 module_type = PAM_T_ACCT;
107 } else if (!_pam_strCMP("password", tok)) {
108 module_type = PAM_T_PASS;
110 /* Illegal module type */
111 D(("_pam_init_handlers: bad module type: %s", tok));
112 _pam_system_log(LOG_ERR, "(%s) illegal module type: %s",
114 module_type = PAM_T_AUTH; /* most sensitive */
115 must_fail = 1; /* install as normal but fail when dispatched */
117 D(("Using %s config entry: %s", must_fail?"BAD ":"", tok));
119 /* reset the actions to .._UNDEF's -- this is so that
120 we can work out which entries are not yet set (for default). */
123 for (i=0; i<_PAM_RETURN_VALUES;
124 actions[i++] = _PAM_ACTION_UNDEF);
126 tok = _pam_StrTok(NULL, " \n\t", &nexttok);
127 if (!_pam_strCMP("required", tok)) {
128 D(("*PAM_F_REQUIRED*"));
129 actions[PAM_SUCCESS] = _PAM_ACTION_OK;
130 actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
131 actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
132 _pam_set_default_control(actions, _PAM_ACTION_BAD);
133 } else if (!_pam_strCMP("requisite", tok)) {
134 D(("*PAM_F_REQUISITE*"));
135 actions[PAM_SUCCESS] = _PAM_ACTION_OK;
136 actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
137 actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
138 _pam_set_default_control(actions, _PAM_ACTION_DIE);
139 } else if (!_pam_strCMP("optional", tok)) {
140 D(("*PAM_F_OPTIONAL*"));
141 actions[PAM_SUCCESS] = _PAM_ACTION_OK;
142 actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
143 _pam_set_default_control(actions, _PAM_ACTION_IGNORE);
144 } else if (!_pam_strCMP("sufficient", tok)) {
145 D(("*PAM_F_SUFFICIENT*"));
146 actions[PAM_SUCCESS] = _PAM_ACTION_DONE;
147 actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_DONE;
148 _pam_set_default_control(actions, _PAM_ACTION_IGNORE);
150 D(("will need to parse %s", tok));
151 _pam_parse_control(actions, tok);
152 /* by default the default is to treat as failure */
153 _pam_set_default_control(actions, _PAM_ACTION_BAD);
156 tok = _pam_StrTok(NULL, " \n\t", &nexttok);
159 D(("mod_path = %s",mod_path));
161 /* no module name given */
162 D(("_pam_init_handlers: no module name supplied"));
163 _pam_system_log(LOG_ERR,
164 "(%s) no module name supplied", this_service);
169 /* nexttok points to remaining arguments... */
171 if (nexttok != NULL) {
172 D(("list: %s",nexttok));
173 argvlen = _pam_mkargv(nexttok, &argv, &argc);
174 D(("argvlen = %d",argvlen));
175 } else { /* there are no arguments so fix by hand */
176 D(("_pam_init_handlers: empty argument list"));
185 D(("CONF%s: %s%s %d %s %d"
186 , must_fail?"<*will fail*>":""
187 , this_service, other ? "(backup)":""
190 for (y = 0; y < argc; y++) {
191 D(("CONF: %s", argv[y]));
193 for (y = 0; y<_PAM_RETURN_VALUES; ++y) {
194 D(("RETURN %s(%d) -> %d %s",
195 _pam_token_returns[y], y, actions[y],
196 actions[y]>0 ? "jump":
197 _pam_token_actions[-actions[y]]));
202 res = _pam_add_handler(pamh, must_fail, other
203 , module_type, actions, mod_path
204 , argc, argv, argvlen);
205 if (res != PAM_SUCCESS) {
206 _pam_system_log(LOG_ERR, "error loading %s", mod_path);
207 D(("failed to load module - aborting"));
213 return ( (x < 0) ? PAM_ABORT:PAM_SUCCESS );
216 /* Parse config file, allocate handler structures, dlopen() */
217 int _pam_init_handlers(pam_handle_t *pamh)
222 D(("_pam_init_handlers called"));
223 IF_NO_PAMH("_pam_init_handlers",pamh,PAM_SYSTEM_ERR);
225 /* Return immediately if everything is already loaded */
226 if (pamh->handlers.handlers_loaded) {
230 D(("_pam_init_handlers: initializing"));
232 /* First clean the service structure */
234 _pam_free_handlers(pamh);
235 if (! pamh->handlers.module) {
236 if ((pamh->handlers.module =
237 malloc(MODULE_CHUNK * sizeof(struct loaded_module))) == NULL) {
238 _pam_system_log(LOG_CRIT,
239 "_pam_init_handlers: no memory loading module");
242 pamh->handlers.modules_allocated = MODULE_CHUNK;
243 pamh->handlers.modules_used = 0;
246 if (pamh->service_name == NULL) {
247 return PAM_BAD_ITEM; /* XXX - better error? */
251 /* Is the PAM subsystem locked? */
255 if ((fd_tmp = open( PAM_LOCK_FILE, O_RDONLY )) != -1) {
256 _pam_system_log(LOG_ERR, "_pam_init_handlers: PAM lockfile ("
257 PAM_LOCK_FILE ") exists - aborting");
258 (void) close(fd_tmp);
260 * to avoid swamping the system with requests
262 _pam_start_timer(pamh);
263 pam_fail_delay(pamh, 5000000);
264 _pam_await_timer(pamh, PAM_ABORT);
269 #endif /* PAM_LOCKING */
272 * Now parse the config file(s) and add handlers
277 /* Is there a PAM_CONFIG_D directory? */
278 if ( stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) {
280 int read_something=0;
282 D(("searching " PAM_CONFIG_D " for config files"));
283 filename = malloc(sizeof(PAM_CONFIG_DF)
284 +strlen(pamh->service_name));
285 if (filename == NULL) {
286 _pam_system_log(LOG_ERR,
287 "_pam_init_handlers: no memory; service %s",
291 sprintf(filename, PAM_CONFIG_DF, pamh->service_name);
292 D(("opening %s", filename));
293 f = fopen(filename, "r");
295 /* would test magic here? */
296 retval = _pam_parse_conf_file(pamh, f, pamh->service_name
297 #ifdef PAM_READ_BOTH_CONFS
299 #endif /* PAM_READ_BOTH_CONFS */
302 if (retval != PAM_SUCCESS) {
303 _pam_system_log(LOG_ERR,
304 "_pam_init_handlers: error reading %s",
306 _pam_system_log(LOG_ERR, "_pam_init_handlers: [%s]",
307 pam_strerror(pamh, retval));
312 D(("unable to open %s", filename));
313 #ifdef PAM_READ_BOTH_CONFS
314 D(("checking %s", PAM_CONFIG));
316 if ((f = fopen(PAM_CONFIG,"r")) != NULL) {
317 retval = _pam_parse_conf_file(pamh, f, NULL, 1);
320 #endif /* PAM_READ_BOTH_CONFS */
321 retval = PAM_SUCCESS;
323 * XXX - should we log an error? Some people want to always
329 if (retval == PAM_SUCCESS) {
330 /* now parse the PAM_DEFAULT_SERVICE_FILE */
332 D(("opening %s", PAM_DEFAULT_SERVICE_FILE));
333 f = fopen(PAM_DEFAULT_SERVICE_FILE, "r");
335 /* would test magic here? */
336 retval = _pam_parse_conf_file(pamh, f
337 , PAM_DEFAULT_SERVICE
338 #ifdef PAM_READ_BOTH_CONFS
340 #endif /* PAM_READ_BOTH_CONFS */
343 if (retval != PAM_SUCCESS) {
344 _pam_system_log(LOG_ERR,
345 "_pam_init_handlers: error reading %s",
346 PAM_DEFAULT_SERVICE_FILE);
347 _pam_system_log(LOG_ERR,
348 "_pam_init_handlers: [%s]",
349 pam_strerror(pamh, retval));
354 D(("unable to open %s", PAM_DEFAULT_SERVICE_FILE));
355 _pam_system_log(LOG_ERR,
356 "_pam_init_handlers: no default config %s",
357 PAM_DEFAULT_SERVICE_FILE);
359 if (!read_something) { /* nothing read successfully */
364 if ((f = fopen(PAM_CONFIG, "r")) == NULL) {
365 _pam_system_log(LOG_ERR, "_pam_init_handlers: could not open "
370 retval = _pam_parse_conf_file(pamh, f, NULL
371 #ifdef PAM_READ_BOTH_CONFS
373 #endif /* PAM_READ_BOTH_CONFS */
376 D(("closing configuration file"));
381 if (retval != PAM_SUCCESS) {
383 _pam_system_log(LOG_ERR, "error reading PAM configuration file");
387 pamh->handlers.handlers_loaded = 1;
389 D(("_pam_init_handlers exiting"));
394 * This is where we read a line of the PAM config file. The line may be
395 * preceeded by lines of comments and also extended with "\\\n"
398 static int _pam_assemble_line(FILE *f, char *buffer, int buf_len)
404 /* loop broken with a 'break' when a non-'\\n' ended line is read */
408 if (used >= buf_len) {
410 D(("_pam_assemble_line: overflow"));
413 if (fgets(p, buf_len - used, f) == NULL) {
415 /* Incomplete read */
423 /* skip leading spaces --- line may be blank */
425 s = p + strspn(p, " \n\t");
426 if (*s && (*s != '#')) {
430 * we are only interested in characters before the first '#'
434 while (*s && *s != '#')
439 break; /* the line has been read */
445 * Check for backslash by scanning back from the end of
446 * the entered line, the '\n' has been included since
447 * normally a line is terminated with this
448 * character. fgets() should only return one though!
452 while (s > os && ((*--s == ' ') || (*s == '\t')
455 /* check if it ends with a backslash */
457 *s++ = ' '; /* replace backslash with ' ' */
458 *s = '\0'; /* truncate the line here */
460 p = s; /* there is more ... */
462 /* End of the line! */
464 break; /* this is the complete line */
468 /* Nothing in this line */
476 typedef int (*servicefn)(pam_handle_t *, int, int, char **);
478 int _pam_add_handler(pam_handle_t *pamh
479 , int must_fail, int other, int type
480 , int *actions, const char *mod_path
481 , int argc, char **argv, int argvlen)
483 struct loaded_module *mod;
485 struct handler **handler_p;
486 struct handler **handler_p2;
487 struct handlers *the_handlers;
488 const char *sym, *sym2;
490 const char *_sym, *_sym2;
492 char *mod_full_path=NULL;
493 servicefn func, func2;
497 IF_NO_PAMH("_pam_add_handler",pamh,PAM_SYSTEM_ERR);
499 /* if NULL set to something that can be searched for */
500 switch (mod_path != NULL) {
502 if (mod_path[0] == '/') {
505 mod_full_path = malloc(sizeof(DEFAULT_MODULE_PATH)+strlen(mod_path));
507 sprintf(mod_full_path, DEFAULT_MODULE_PATH "%s", mod_path);
508 mod_path = mod_full_path;
511 _pam_system_log(LOG_CRIT, "cannot malloc full mod path");
513 mod_path = UNKNOWN_MODULE_PATH;
516 D(("_pam_add_handler: adding type %d, module `%s'",type,mod_path));
517 mod = pamh->handlers.module;
519 /* First, ensure the module is loaded */
520 while (x < pamh->handlers.modules_used) {
521 if (!strcmp(mod[x].name, mod_path)) { /* case sensitive ! */
526 if (x == pamh->handlers.modules_used) {
528 if (pamh->handlers.modules_allocated == pamh->handlers.modules_used) {
529 /* will need more memory */
530 void *tmp = realloc(pamh->handlers.module,
531 (pamh->handlers.modules_allocated+MODULE_CHUNK)
532 *sizeof(struct loaded_module));
534 D(("cannot enlarge module pointer memory"));
535 _pam_system_log(LOG_ERR,
536 "realloc returned NULL in _pam_add_handler");
537 _pam_drop(mod_full_path);
540 pamh->handlers.module = tmp;
541 pamh->handlers.modules_allocated += MODULE_CHUNK;
543 mod = &(pamh->handlers.module[x]);
544 /* Be pessimistic... */
548 D(("_pam_add_handler: dlopen(%s) -> %lx", mod_path, &mod->dl_handle));
551 shl_load(mod_path, BIND_IMMEDIATE, 0L);
553 dlopen(mod_path, RTLD_NOW);
554 # endif /* PAM_SHL */
555 D(("_pam_add_handler: dlopen'ed"));
556 if (mod->dl_handle == NULL) {
557 D(("_pam_add_handler: dlopen(%s) failed", mod_path));
558 _pam_system_log(LOG_ERR, "unable to dlopen(%s)", mod_path);
560 _pam_system_log(LOG_ERR, "[dlerror: %s]", dlerror());
561 # endif /* PAM_SHL */
562 /* Don't abort yet; static code may be able to find function.
563 * But defaults to abort if nothing found below... */
565 D(("module added successfully"));
566 success = PAM_SUCCESS;
567 mod->type = PAM_MT_DYNAMIC_MOD;
568 pamh->handlers.modules_used++;
572 /* Only load static function if function was not found dynamically.
573 * This code should work even if no dynamic loading is available. */
574 if (success != PAM_SUCCESS) {
575 D(("_pam_add_handler: open static handler %s", mod_path));
576 mod->dl_handle = _pam_open_static_handler(mod_path);
577 if (mod->dl_handle == NULL) {
578 D(("_pam_add_handler: unable to find static handler %s",
580 _pam_system_log(LOG_ERR,
581 "unable to open static handler %s", mod_path);
582 /* Didn't find module in dynamic or static..will mark bad */
584 D(("static module added successfully"));
585 success = PAM_SUCCESS;
586 mod->type = PAM_MT_STATIC_MOD;
587 pamh->handlers.modules_used++;
592 if (success != PAM_SUCCESS) { /* add a malformed module */
593 mod->dl_handle = NULL;
594 mod->type = PAM_MT_FAULTY_MOD;
595 pamh->handlers.modules_used++;
596 _pam_system_log(LOG_ERR, "adding faulty module: %s", mod_path);
597 success = PAM_SUCCESS; /* We have successfully added a module */
600 /* indicate its name - later we will search for it by this */
601 if ((mod->name = _pam_strdup(mod_path)) == NULL) {
602 D(("_pam_handler: couldn't get memory for mod_path"));
603 _pam_system_log(LOG_ERR, "no memory for module path", mod_path);
607 } else { /* x != pamh->handlers.modules_used */
608 mod += x; /* the located module */
609 success = PAM_SUCCESS;
612 _pam_drop(mod_full_path);
613 mod_path = NULL; /* no longer needed or trusted */
615 /* Now return error if necessary after trying all possible ways... */
616 if (success != PAM_SUCCESS)
620 * At this point 'mod' points to the stored/loaded module. If its
621 * dl_handle is unknown, then we must be able to indicate dispatch
622 * failure with 'must_fail'
625 /* Now define the handler(s) based on mod->dlhandle and type */
627 /* decide which list of handlers to use */
628 the_handlers = (other) ? &pamh->handlers.other : &pamh->handlers.conf;
630 handler_p = handler_p2 = NULL;
637 /* point handler_p's at the root addresses of the function stacks */
640 handler_p = &the_handlers->authenticate;
641 sym = SHLIB_SYM_PREFIX "pam_sm_authenticate";
642 handler_p2 = &the_handlers->setcred;
643 sym2 = SHLIB_SYM_PREFIX "pam_sm_setcred";
645 _sym = "_pam_sm_authenticate";
646 _sym2 = "_pam_sm_setcred";
650 handler_p = &the_handlers->open_session;
651 sym = SHLIB_SYM_PREFIX "pam_sm_open_session";
652 handler_p2 = &the_handlers->close_session;
653 sym2 = SHLIB_SYM_PREFIX "pam_sm_close_session";
655 _sym = "_pam_sm_open_session";
656 _sym2 = "_pam_sm_close_session";
660 handler_p = &the_handlers->acct_mgmt;
661 sym = SHLIB_SYM_PREFIX "pam_sm_acct_mgmt";
663 _sym = "_pam_sm_acct_mgmt";
667 handler_p = &the_handlers->chauthtok;
668 sym = SHLIB_SYM_PREFIX "pam_sm_chauthtok";
670 _sym = "_pam_sm_chauthtok";
674 /* Illegal module type */
675 D(("_pam_add_handler: illegal module type %d", type));
679 /* are the modules reliable? */
682 mod->type != PAM_MT_DYNAMIC_MOD
684 #endif /* PAM_DYNAMIC */
686 mod->type != PAM_MT_STATIC_MOD
688 #endif /* PAM_STATIC */
689 mod->type != PAM_MT_FAULTY_MOD
691 D(("_pam_add_handlers: illegal module library type; %d", mod->type));
692 _pam_system_log(LOG_ERR,
693 "internal error: module library type not known: %s;%d",
698 /* now identify this module's functions - for non-faulty modules */
701 if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
703 (shl_findsym(&mod->dl_handle, sym, (short) TYPE_PROCEDURE, &func) &&
704 shl_findsym(&mod->dl_handle, _sym, (short) TYPE_PROCEDURE, &func))
706 (func = (servicefn) dlsym(mod->dl_handle, sym)) == NULL
707 # endif /* PAM_SHL */
709 _pam_system_log(LOG_ERR, "unable to resolve symbol: %s", sym);
713 if ((mod->type == PAM_MT_STATIC_MOD) &&
714 (func = (servicefn)_pam_get_static_sym(mod->dl_handle, sym)) == NULL) {
715 _pam_system_log(LOG_ERR, "unable to resolve static symbol: %s", sym);
720 if ((mod->type == PAM_MT_DYNAMIC_MOD) &&
722 (shl_findsym(&mod->dl_handle,sym2,(short)TYPE_PROCEDURE, &func2)&&
723 shl_findsym(&mod->dl_handle,_sym2,(short)TYPE_PROCEDURE, &func2))
725 (func2 = (servicefn) dlsym(mod->dl_handle, sym2)) == NULL
726 # endif /* PAM_SHL */
728 _pam_system_log(LOG_ERR, "unable to resolve symbol: %s", sym2);
732 if ((mod->type == PAM_MT_STATIC_MOD) &&
733 (func2 = (servicefn)_pam_get_static_sym(mod->dl_handle, sym2))
735 _pam_system_log(LOG_ERR, "unable to resolve symbol: %s", sym2);
740 /* here func (and perhaps func2) point to the appropriate functions */
742 /* add new handler to end of existing list */
743 while (*handler_p != NULL) {
744 handler_p = &((*handler_p)->next);
747 if ((*handler_p = malloc(sizeof(struct handler))) == NULL) {
748 _pam_system_log(LOG_CRIT, "cannot malloc struct handler #1");
752 (*handler_p)->must_fail = must_fail; /* failure forced? */
753 (*handler_p)->func = func;
754 memcpy((*handler_p)->actions,actions,sizeof((*handler_p)->actions));
755 (*handler_p)->cached_retval = _PAM_INVALID_RETVAL;
756 (*handler_p)->cached_retval_p = &((*handler_p)->cached_retval);
757 (*handler_p)->argc = argc;
758 (*handler_p)->argv = argv; /* not a copy */
759 (*handler_p)->next = NULL;
761 /* some of the modules have a second calling function */
763 /* add new handler to end of existing list */
764 while (*handler_p2) {
765 handler_p2 = &((*handler_p2)->next);
768 if ((*handler_p2 = malloc(sizeof(struct handler))) == NULL) {
769 _pam_system_log(LOG_CRIT, "cannot malloc struct handler #2");
773 (*handler_p2)->must_fail = must_fail; /* failure forced? */
774 (*handler_p2)->func = func2;
775 memcpy((*handler_p2)->actions,actions,sizeof((*handler_p2)->actions));
776 (*handler_p2)->cached_retval = _PAM_INVALID_RETVAL; /* ignored */
777 /* Note, this next entry points to the handler_p value! */
778 (*handler_p2)->cached_retval_p = &((*handler_p)->cached_retval);
779 (*handler_p2)->argc = argc;
781 if (((*handler_p2)->argv = malloc(argvlen)) == NULL) {
782 _pam_system_log(LOG_CRIT, "cannot malloc argv for handler #2");
785 memcpy((*handler_p2)->argv, argv, argvlen);
787 (*handler_p2)->argv = NULL; /* no arguments */
789 (*handler_p2)->next = NULL;
792 D(("_pam_add_handler: returning successfully"));
797 /* Free various allocated structures and dlclose() the libs */
798 int _pam_free_handlers(pam_handle_t *pamh)
800 struct loaded_module *mod;
803 IF_NO_PAMH("_pam_free_handlers",pamh,PAM_SYSTEM_ERR);
805 mod = pamh->handlers.module;
807 /* Close all loaded modules */
809 while (pamh->handlers.modules_used) {
810 D(("_pam_free_handlers: dlclose(%s)", mod->name));
813 if (mod->type == PAM_MT_DYNAMIC_MOD) {
815 shl_unload(mod->dl_handle);
817 dlclose(mod->dl_handle);
822 pamh->handlers.modules_used--;
825 /* Free all the handlers */
827 _pam_free_handlers_aux(&(pamh->handlers.conf.authenticate));
828 _pam_free_handlers_aux(&(pamh->handlers.conf.setcred));
829 _pam_free_handlers_aux(&(pamh->handlers.conf.acct_mgmt));
830 _pam_free_handlers_aux(&(pamh->handlers.conf.open_session));
831 _pam_free_handlers_aux(&(pamh->handlers.conf.close_session));
832 _pam_free_handlers_aux(&(pamh->handlers.conf.chauthtok));
834 _pam_free_handlers_aux(&(pamh->handlers.other.authenticate));
835 _pam_free_handlers_aux(&(pamh->handlers.other.setcred));
836 _pam_free_handlers_aux(&(pamh->handlers.other.acct_mgmt));
837 _pam_free_handlers_aux(&(pamh->handlers.other.open_session));
838 _pam_free_handlers_aux(&(pamh->handlers.other.close_session));
839 _pam_free_handlers_aux(&(pamh->handlers.other.chauthtok));
841 /* no more loaded modules */
843 _pam_drop(pamh->handlers.module);
845 /* Indicate that handlers are not initialized for this pamh */
847 pamh->handlers.handlers_loaded = 0;
852 void _pam_start_handlers(pam_handle_t *pamh)
855 /* NB. There is no check for a NULL pamh here, since no return
856 * value to communicate the fact! */
858 /* Indicate that handlers are not initialized for this pamh */
859 pamh->handlers.handlers_loaded = 0;
861 pamh->handlers.modules_allocated = 0;
862 pamh->handlers.modules_used = 0;
863 pamh->handlers.module = NULL;
865 /* initialize the .conf and .other entries */
867 pamh->handlers.conf.authenticate = NULL;
868 pamh->handlers.conf.setcred = NULL;
869 pamh->handlers.conf.acct_mgmt = NULL;
870 pamh->handlers.conf.open_session = NULL;
871 pamh->handlers.conf.close_session = NULL;
872 pamh->handlers.conf.chauthtok = NULL;
874 pamh->handlers.other.authenticate = NULL;
875 pamh->handlers.other.setcred = NULL;
876 pamh->handlers.other.acct_mgmt = NULL;
877 pamh->handlers.other.open_session = NULL;
878 pamh->handlers.other.close_session = NULL;
879 pamh->handlers.other.chauthtok = NULL;
882 void _pam_free_handlers_aux(struct handler **hp)
884 struct handler *h = *hp;
885 struct handler *last;
890 _pam_drop(h->argv); /* This is all alocated in a single chunk */
892 memset(last, 0, sizeof(*last));