17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54ef27277Sgww * Common Development and Distribution License (the "License"). 64ef27277Sgww * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 224ef27277Sgww * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <syslog.h> 297c478bd9Sstevel@tonic-gate #include <dlfcn.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/stat.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <malloc.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 407c478bd9Sstevel@tonic-gate #include <security/pam_modules.h> 417c478bd9Sstevel@tonic-gate #include <sys/mman.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include <libintl.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #include "pam_impl.h" 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static char *pam_snames [PAM_NUM_MODULE_TYPES] = { 487c478bd9Sstevel@tonic-gate PAM_ACCOUNT_NAME, 497c478bd9Sstevel@tonic-gate PAM_AUTH_NAME, 507c478bd9Sstevel@tonic-gate PAM_PASSWORD_NAME, 517c478bd9Sstevel@tonic-gate PAM_SESSION_NAME 527c478bd9Sstevel@tonic-gate }; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static char *pam_inames [PAM_MAX_ITEMS] = { 557c478bd9Sstevel@tonic-gate /* NONE */ NULL, 567c478bd9Sstevel@tonic-gate /* PAM_SERVICE */ "service", 577c478bd9Sstevel@tonic-gate /* PAM_USER */ "user", 587c478bd9Sstevel@tonic-gate /* PAM_TTY */ "tty", 597c478bd9Sstevel@tonic-gate /* PAM_RHOST */ "rhost", 607c478bd9Sstevel@tonic-gate /* PAM_CONV */ "conv", 617c478bd9Sstevel@tonic-gate /* PAM_AUTHTOK */ "authtok", 627c478bd9Sstevel@tonic-gate /* PAM_OLDAUTHTOK */ "oldauthtok", 637c478bd9Sstevel@tonic-gate /* PAM_RUSER */ "ruser", 647c478bd9Sstevel@tonic-gate /* PAM_USER_PROMPT */ "user_prompt", 657c478bd9Sstevel@tonic-gate /* PAM_REPOSITORY */ "repository", 667c478bd9Sstevel@tonic-gate /* PAM_RESOURCE */ "resource", 67*bf430c99Sgww /* PAM_AUSER */ "auser", 687c478bd9Sstevel@tonic-gate /* Undefined Items */ 697c478bd9Sstevel@tonic-gate }; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * This extra definition is needed in order to build this library 737c478bd9Sstevel@tonic-gate * on pre-64-bit-aware systems. 747c478bd9Sstevel@tonic-gate */ 757c478bd9Sstevel@tonic-gate #if !defined(_LFS64_LARGEFILE) 767c478bd9Sstevel@tonic-gate #define stat64 stat 777c478bd9Sstevel@tonic-gate #endif /* !defined(_LFS64_LARGEFILE) */ 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* functions to dynamically load modules */ 807c478bd9Sstevel@tonic-gate static int load_modules(pam_handle_t *, int, char *, pamtab_t *); 817c478bd9Sstevel@tonic-gate static void *open_module(pam_handle_t *, char *); 827c478bd9Sstevel@tonic-gate static int load_function(void *, char *, int (**func)()); 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* functions to read and store the pam.conf configuration file */ 857c478bd9Sstevel@tonic-gate static int open_pam_conf(struct pam_fh **, pam_handle_t *, char *); 867c478bd9Sstevel@tonic-gate static void close_pam_conf(struct pam_fh *); 877c478bd9Sstevel@tonic-gate static int read_pam_conf(pam_handle_t *, char *); 887c478bd9Sstevel@tonic-gate static int get_pam_conf_entry(struct pam_fh *, pam_handle_t *, 897c478bd9Sstevel@tonic-gate pamtab_t **); 907c478bd9Sstevel@tonic-gate static char *read_next_token(char **); 914ef27277Sgww static char *nextline(struct pam_fh *, pam_handle_t *, int *); 927c478bd9Sstevel@tonic-gate static int verify_pam_conf(pamtab_t *, char *); 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* functions to clean up and free memory */ 957c478bd9Sstevel@tonic-gate static void clean_up(pam_handle_t *); 967c478bd9Sstevel@tonic-gate static void free_pamconf(pamtab_t *); 977c478bd9Sstevel@tonic-gate static void free_pam_conf_info(pam_handle_t *); 987c478bd9Sstevel@tonic-gate static void free_env(env_list *); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* convenience functions for I18N/L10N communication */ 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static void free_resp(int, struct pam_response *); 1037c478bd9Sstevel@tonic-gate static int do_conv(pam_handle_t *, int, int, 1047c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE], void *, 1057c478bd9Sstevel@tonic-gate struct pam_response **); 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate static int log_priority; /* pam_trace syslog priority & facility */ 1087c478bd9Sstevel@tonic-gate static int pam_debug = 0; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static char * 1117c478bd9Sstevel@tonic-gate pam_trace_iname(int item_type, char *iname_buf) 1127c478bd9Sstevel@tonic-gate { 1137c478bd9Sstevel@tonic-gate char *name; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * XXX -- Contracted Consolidation Private 1177c478bd9Sstevel@tonic-gate * to be eliminated when dtlogin contract is terminated 1187c478bd9Sstevel@tonic-gate * Version number requested by PAM's client 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate if (item_type == PAM_MSG_VERSION) 1217c478bd9Sstevel@tonic-gate return ("msg_version"); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if (item_type <= 0 || 1247c478bd9Sstevel@tonic-gate item_type >= PAM_MAX_ITEMS || 1257c478bd9Sstevel@tonic-gate (name = pam_inames[item_type]) == NULL) { 1267c478bd9Sstevel@tonic-gate (void) sprintf(iname_buf, "%d", item_type); 1277c478bd9Sstevel@tonic-gate return (iname_buf); 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate return (name); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate static char * 1337c478bd9Sstevel@tonic-gate pam_trace_fname(int flag) 1347c478bd9Sstevel@tonic-gate { 1357c478bd9Sstevel@tonic-gate if (flag & PAM_BINDING) 1367c478bd9Sstevel@tonic-gate return (PAM_BINDING_NAME); 1377c478bd9Sstevel@tonic-gate if (flag & PAM_INCLUDE) 1387c478bd9Sstevel@tonic-gate return (PAM_INCLUDE_NAME); 1397c478bd9Sstevel@tonic-gate if (flag & PAM_OPTIONAL) 1407c478bd9Sstevel@tonic-gate return (PAM_OPTIONAL_NAME); 1417c478bd9Sstevel@tonic-gate if (flag & PAM_REQUIRED) 1427c478bd9Sstevel@tonic-gate return (PAM_REQUIRED_NAME); 1437c478bd9Sstevel@tonic-gate if (flag & PAM_REQUISITE) 1447c478bd9Sstevel@tonic-gate return (PAM_REQUISITE_NAME); 1457c478bd9Sstevel@tonic-gate if (flag & PAM_SUFFICIENT) 1467c478bd9Sstevel@tonic-gate return (PAM_SUFFICIENT_NAME); 1477c478bd9Sstevel@tonic-gate return ("bad flag name"); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate static char * 1517c478bd9Sstevel@tonic-gate pam_trace_cname(pam_handle_t *pamh) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate if (pamh->pam_conf_name[pamh->include_depth] == NULL) 1547c478bd9Sstevel@tonic-gate return ("NULL"); 1557c478bd9Sstevel@tonic-gate return (pamh->pam_conf_name[pamh->include_depth]); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate #include <deflt.h> 1597c478bd9Sstevel@tonic-gate #include <stdarg.h> 1607c478bd9Sstevel@tonic-gate /* 1617c478bd9Sstevel@tonic-gate * pam_settrace - setup configuration for pam tracing 1627c478bd9Sstevel@tonic-gate * 1637c478bd9Sstevel@tonic-gate * turn on PAM debug if "magic" file exists 1647c478bd9Sstevel@tonic-gate * if exists (original), pam_debug = PAM_DEBUG_DEFAULT, 1657c478bd9Sstevel@tonic-gate * log_priority = LOG_DEBUG(7) and log_facility = LOG_AUTH(4). 1667c478bd9Sstevel@tonic-gate * 1677c478bd9Sstevel@tonic-gate * if has contents, keywork=value pairs: 1687c478bd9Sstevel@tonic-gate * 1697c478bd9Sstevel@tonic-gate * "log_priority=" 0-7, the pam_trace syslog priority to use 1707c478bd9Sstevel@tonic-gate * (see sys/syslog.h) 1717c478bd9Sstevel@tonic-gate * "log_facility=" 0-23, the pam_trace syslog facility to use 1727c478bd9Sstevel@tonic-gate * (see sys/syslog.h) 1737c478bd9Sstevel@tonic-gate * "debug_flags=" PAM_DEBUG_DEFAULT (0x0001), log traditional 1747c478bd9Sstevel@tonic-gate * (original) debugging. 1757c478bd9Sstevel@tonic-gate * Plus the logical or of: 1767c478bd9Sstevel@tonic-gate * PAM_DEBUG_ITEM (0x0002), log item values and 1777c478bd9Sstevel@tonic-gate * pam_get_item. 1787c478bd9Sstevel@tonic-gate * PAM_DEBUG_MODULE (0x0004), log module return status. 1797c478bd9Sstevel@tonic-gate * PAM_DEBUG_CONF (0x0008), log pam.conf parsing. 1807c478bd9Sstevel@tonic-gate * PAM_DEBUG_DATA (0x0010), get/set_data. 1817c478bd9Sstevel@tonic-gate * PAM_DEBUG_CONV (0x0020), conversation/response. 1827c478bd9Sstevel@tonic-gate * 1837c478bd9Sstevel@tonic-gate * If compiled with DEBUG: 1847c478bd9Sstevel@tonic-gate * PAM_DEBUG_AUTHTOK (0x8000), display AUTHTOK value if 1857c478bd9Sstevel@tonic-gate * PAM_DEBUG_ITEM is set and results from 1867c478bd9Sstevel@tonic-gate * PAM_PROMPT_ECHO_OFF responses. 1877c478bd9Sstevel@tonic-gate * USE CAREFULLY, THIS EXPOSES THE USER'S PASSWORDS. 1887c478bd9Sstevel@tonic-gate * 1897c478bd9Sstevel@tonic-gate * or set to 0 and off even if PAM_DEBUG file exists. 1907c478bd9Sstevel@tonic-gate * 1917c478bd9Sstevel@tonic-gate * Output has the general form: 1927c478bd9Sstevel@tonic-gate * <whatever was set syslog> PAM[<pid>]: <interface>(<handle> and other info) 1937c478bd9Sstevel@tonic-gate * <whatever was set syslog> PAM[<pid>]: details requested for <interface> call 1947c478bd9Sstevel@tonic-gate * Where: <pid> is the process ID of the calling process. 1957c478bd9Sstevel@tonic-gate * <handle> is the Hex value of the pam_handle associated with the 1967c478bd9Sstevel@tonic-gate * call. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate static void 2007c478bd9Sstevel@tonic-gate pam_settrace() 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate if (defopen(PAM_DEBUG) == 0) { 2037c478bd9Sstevel@tonic-gate char *arg; 2047c478bd9Sstevel@tonic-gate int code; 2057c478bd9Sstevel@tonic-gate int facility = LOG_AUTH; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate pam_debug = PAM_DEBUG_DEFAULT; 2087c478bd9Sstevel@tonic-gate log_priority = LOG_DEBUG; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate (void) defcntl(DC_SETFLAGS, DC_CASE); 2117c478bd9Sstevel@tonic-gate if ((arg = defread(LOG_PRIORITY)) != NULL) { 2127c478bd9Sstevel@tonic-gate code = (int)strtol(arg, NULL, 10); 2137c478bd9Sstevel@tonic-gate if ((code & ~LOG_PRIMASK) == 0) { 2147c478bd9Sstevel@tonic-gate log_priority = code; 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate if ((arg = defread(LOG_FACILITY)) != NULL) { 2187c478bd9Sstevel@tonic-gate code = (int)strtol(arg, NULL, 10); 2197c478bd9Sstevel@tonic-gate if (code < LOG_NFACILITIES) { 2207c478bd9Sstevel@tonic-gate facility = code << 3; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate if ((arg = defread(DEBUG_FLAGS)) != NULL) { 2247c478bd9Sstevel@tonic-gate pam_debug = (int)strtol(arg, NULL, 0); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate (void) defopen(NULL); /* close */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate log_priority |= facility; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate /* 2337c478bd9Sstevel@tonic-gate * pam_trace - logs tracing messages 2347c478bd9Sstevel@tonic-gate * 2357c478bd9Sstevel@tonic-gate * flag = debug_flags from /etc/pam_debug 2367c478bd9Sstevel@tonic-gate * format and args = message to print (PAM[<pid>]: is prepended). 2377c478bd9Sstevel@tonic-gate * 2387c478bd9Sstevel@tonic-gate * global log_priority = pam_trace syslog (log_priority | log_facility) 2397c478bd9Sstevel@tonic-gate * from /etc/pam_debug 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 2427c478bd9Sstevel@tonic-gate static void 2437c478bd9Sstevel@tonic-gate pam_trace(int flag, char *format, ...) 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate va_list args; 2467c478bd9Sstevel@tonic-gate char message[1024]; 2477c478bd9Sstevel@tonic-gate int savemask; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if ((pam_debug & flag) == 0) 2507c478bd9Sstevel@tonic-gate return; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate savemask = setlogmask(LOG_MASK(log_priority & LOG_PRIMASK)); 2537c478bd9Sstevel@tonic-gate (void) snprintf(message, sizeof (message), "PAM[%ld]: %s", 2547c478bd9Sstevel@tonic-gate (long)getpid(), format); 2557c478bd9Sstevel@tonic-gate va_start(args, format); 2567c478bd9Sstevel@tonic-gate (void) vsyslog(log_priority, message, args); 2577c478bd9Sstevel@tonic-gate va_end(args); 2587c478bd9Sstevel@tonic-gate (void) setlogmask(savemask); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * __pam_log - logs PAM syslog messages 2637c478bd9Sstevel@tonic-gate * 2647c478bd9Sstevel@tonic-gate * priority = message priority 2657c478bd9Sstevel@tonic-gate * format and args = message to log 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 2687c478bd9Sstevel@tonic-gate void 2697c478bd9Sstevel@tonic-gate __pam_log(int priority, const char *format, ...) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate va_list args; 2727c478bd9Sstevel@tonic-gate int savemask = setlogmask(LOG_MASK(priority & LOG_PRIMASK)); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate va_start(args, format); 2757c478bd9Sstevel@tonic-gate (void) vsyslog(priority, format, args); 2767c478bd9Sstevel@tonic-gate va_end(args); 2777c478bd9Sstevel@tonic-gate (void) setlogmask(savemask); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * pam_XXXXX routines 2837c478bd9Sstevel@tonic-gate * 2847c478bd9Sstevel@tonic-gate * These are the entry points to the authentication switch 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* 2887c478bd9Sstevel@tonic-gate * pam_start - initiate an authentication transaction and 2897c478bd9Sstevel@tonic-gate * set parameter values to be used during the 2907c478bd9Sstevel@tonic-gate * transaction 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate int 2947c478bd9Sstevel@tonic-gate pam_start(const char *service, const char *user, 2957c478bd9Sstevel@tonic-gate const struct pam_conv *pam_conv, pam_handle_t **pamh) 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate int err; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate *pamh = (struct pam_handle *)calloc(1, sizeof (struct pam_handle)); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate pam_settrace(); 3027c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 3037c478bd9Sstevel@tonic-gate "pam_start(%s,%s,%p:%p) - debug = %x", 3047c478bd9Sstevel@tonic-gate service ? service : "NULL", user ? user : "NULL", (void *)pam_conv, 3057c478bd9Sstevel@tonic-gate (void *)*pamh, pam_debug); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate if (*pamh == NULL) 3087c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate (*pamh)->pam_inmodule = RO_OK; /* OK to set RO items */ 3117c478bd9Sstevel@tonic-gate if ((err = pam_set_item(*pamh, PAM_SERVICE, (void *)service)) 3127c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 3137c478bd9Sstevel@tonic-gate clean_up(*pamh); 3147c478bd9Sstevel@tonic-gate *pamh = NULL; 3157c478bd9Sstevel@tonic-gate return (err); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if ((err = pam_set_item(*pamh, PAM_USER, (void *)user)) 3197c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 3207c478bd9Sstevel@tonic-gate clean_up(*pamh); 3217c478bd9Sstevel@tonic-gate *pamh = NULL; 3227c478bd9Sstevel@tonic-gate return (err); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate if ((err = pam_set_item(*pamh, PAM_CONV, (void *)pam_conv)) 3267c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 3277c478bd9Sstevel@tonic-gate clean_up(*pamh); 3287c478bd9Sstevel@tonic-gate *pamh = NULL; 3297c478bd9Sstevel@tonic-gate return (err); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate (*pamh)->pam_inmodule = RW_OK; 3337c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * pam_end - terminate an authentication transaction 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate int 3417c478bd9Sstevel@tonic-gate pam_end(pam_handle_t *pamh, int pam_status) 3427c478bd9Sstevel@tonic-gate { 3437c478bd9Sstevel@tonic-gate struct pam_module_data *psd, *p; 3447c478bd9Sstevel@tonic-gate fd_list *expired; 3457c478bd9Sstevel@tonic-gate fd_list *traverse; 3467c478bd9Sstevel@tonic-gate env_list *env_expired; 3477c478bd9Sstevel@tonic-gate env_list *env_traverse; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 3507c478bd9Sstevel@tonic-gate "pam_end(%p): status = %s", (void *)pamh, 3517c478bd9Sstevel@tonic-gate pam_strerror(pamh, pam_status)); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if (pamh == NULL) 3547c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* call the cleanup routines for module specific data */ 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate psd = pamh->ssd; 3597c478bd9Sstevel@tonic-gate while (psd) { 3607c478bd9Sstevel@tonic-gate if (psd->cleanup) { 3617c478bd9Sstevel@tonic-gate psd->cleanup(pamh, psd->data, pam_status); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate p = psd; 3647c478bd9Sstevel@tonic-gate psd = p->next; 3657c478bd9Sstevel@tonic-gate free(p->module_data_name); 3667c478bd9Sstevel@tonic-gate free(p); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate pamh->ssd = NULL; 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* dlclose all module fds */ 3717c478bd9Sstevel@tonic-gate traverse = pamh->fd; 3727c478bd9Sstevel@tonic-gate while (traverse) { 3737c478bd9Sstevel@tonic-gate expired = traverse; 3747c478bd9Sstevel@tonic-gate traverse = traverse->next; 3757c478bd9Sstevel@tonic-gate (void) dlclose(expired->mh); 3767c478bd9Sstevel@tonic-gate free(expired); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate pamh->fd = 0; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate /* remove all environment variables */ 3817c478bd9Sstevel@tonic-gate env_traverse = pamh->pam_env; 3827c478bd9Sstevel@tonic-gate while (env_traverse) { 3837c478bd9Sstevel@tonic-gate env_expired = env_traverse; 3847c478bd9Sstevel@tonic-gate env_traverse = env_traverse->next; 3857c478bd9Sstevel@tonic-gate free_env(env_expired); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate clean_up(pamh); 3897c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * pam_set_item - set the value of a parameter that can be 3947c478bd9Sstevel@tonic-gate * retrieved via a call to pam_get_item() 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate int 3987c478bd9Sstevel@tonic-gate pam_set_item(pam_handle_t *pamh, int item_type, const void *item) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate struct pam_item *pip; 4017c478bd9Sstevel@tonic-gate int size; 4027c478bd9Sstevel@tonic-gate char iname_buf[PAM_MAX_MSG_SIZE]; 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate if (((pam_debug & PAM_DEBUG_ITEM) == 0) || (pamh == NULL)) { 4057c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 4067c478bd9Sstevel@tonic-gate "pam_set_item(%p:%s)", (void *)pamh, 4077c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf)); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if (pamh == NULL) 4117c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* check read only items */ 4147c478bd9Sstevel@tonic-gate if ((item_type == PAM_SERVICE) && (pamh->pam_inmodule != RO_OK)) 4157c478bd9Sstevel@tonic-gate return (PAM_PERM_DENIED); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * XXX -- Contracted Consolidation Private 4197c478bd9Sstevel@tonic-gate * to be eliminated when dtlogin contract is terminated 4207c478bd9Sstevel@tonic-gate * Check if tag is Sun proprietary 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate if (item_type == PAM_MSG_VERSION) { 4237c478bd9Sstevel@tonic-gate if (pamh->pam_client_message_version_number) 4247c478bd9Sstevel@tonic-gate free(pamh->pam_client_message_version_number); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate if (item == NULL) 4277c478bd9Sstevel@tonic-gate pamh->pam_client_message_version_number = NULL; 4287c478bd9Sstevel@tonic-gate else 4297c478bd9Sstevel@tonic-gate if ((pamh->pam_client_message_version_number = 4307c478bd9Sstevel@tonic-gate strdup((char *)item)) == NULL) 4317c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, 4347c478bd9Sstevel@tonic-gate "pam_set_item(%p:%s)=%s", (void *)pamh, 4357c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 4367c478bd9Sstevel@tonic-gate item ? (char *)item : "NULL"); 4377c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* 4417c478bd9Sstevel@tonic-gate * Check that item_type is within valid range 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate if (item_type <= 0 || item_type >= PAM_MAX_ITEMS) 4457c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate pip = &(pamh->ps_item[item_type]); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate switch (item_type) { 4507c478bd9Sstevel@tonic-gate case PAM_AUTHTOK: 4517c478bd9Sstevel@tonic-gate case PAM_OLDAUTHTOK: 4527c478bd9Sstevel@tonic-gate if (pip->pi_addr != NULL) 4537c478bd9Sstevel@tonic-gate (void) memset(pip->pi_addr, 0, pip->pi_size); 4547c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 4557c478bd9Sstevel@tonic-gate case PAM_SERVICE: 4567c478bd9Sstevel@tonic-gate case PAM_USER: 4577c478bd9Sstevel@tonic-gate case PAM_TTY: 4587c478bd9Sstevel@tonic-gate case PAM_RHOST: 4597c478bd9Sstevel@tonic-gate case PAM_RUSER: 4607c478bd9Sstevel@tonic-gate case PAM_USER_PROMPT: 4617c478bd9Sstevel@tonic-gate case PAM_RESOURCE: 462*bf430c99Sgww case PAM_AUSER: 4637c478bd9Sstevel@tonic-gate if (pip->pi_addr != NULL) { 4647c478bd9Sstevel@tonic-gate free(pip->pi_addr); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (item == NULL) { 4687c478bd9Sstevel@tonic-gate pip->pi_addr = NULL; 4697c478bd9Sstevel@tonic-gate pip->pi_size = 0; 4707c478bd9Sstevel@tonic-gate } else { 4717c478bd9Sstevel@tonic-gate pip->pi_addr = strdup((char *)item); 4727c478bd9Sstevel@tonic-gate if (pip->pi_addr == NULL) { 4737c478bd9Sstevel@tonic-gate pip->pi_size = 0; 4747c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate pip->pi_size = strlen(pip->pi_addr); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate break; 4797c478bd9Sstevel@tonic-gate case PAM_CONV: 4807c478bd9Sstevel@tonic-gate if (pip->pi_addr != NULL) 4817c478bd9Sstevel@tonic-gate free(pip->pi_addr); 4827c478bd9Sstevel@tonic-gate size = sizeof (struct pam_conv); 4837c478bd9Sstevel@tonic-gate if ((pip->pi_addr = (void *)calloc(1, size)) == NULL) 4847c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 4857c478bd9Sstevel@tonic-gate if (item != NULL) 4867c478bd9Sstevel@tonic-gate (void) memcpy(pip->pi_addr, item, (unsigned int) size); 4877c478bd9Sstevel@tonic-gate else 4887c478bd9Sstevel@tonic-gate (void) memset(pip->pi_addr, 0, size); 4897c478bd9Sstevel@tonic-gate pip->pi_size = size; 4907c478bd9Sstevel@tonic-gate break; 4917c478bd9Sstevel@tonic-gate case PAM_REPOSITORY: 4927c478bd9Sstevel@tonic-gate if (pip->pi_addr != NULL) { 4937c478bd9Sstevel@tonic-gate pam_repository_t *auth_rep; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate auth_rep = (pam_repository_t *)pip->pi_addr; 4967c478bd9Sstevel@tonic-gate if (auth_rep->type != NULL) 4977c478bd9Sstevel@tonic-gate free(auth_rep->type); 4987c478bd9Sstevel@tonic-gate if (auth_rep->scope != NULL) 4997c478bd9Sstevel@tonic-gate free(auth_rep->scope); 5007c478bd9Sstevel@tonic-gate free(auth_rep); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate if (item != NULL) { 5037c478bd9Sstevel@tonic-gate pam_repository_t *s, *d; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate size = sizeof (struct pam_repository); 5067c478bd9Sstevel@tonic-gate pip->pi_addr = (void *)calloc(1, size); 5077c478bd9Sstevel@tonic-gate if (pip->pi_addr == NULL) 5087c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate s = (struct pam_repository *)item; 5117c478bd9Sstevel@tonic-gate d = (struct pam_repository *)pip->pi_addr; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate d->type = strdup(s->type); 5147c478bd9Sstevel@tonic-gate if (d->type == NULL) 5157c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 5167c478bd9Sstevel@tonic-gate d->scope = malloc(s->scope_len); 5177c478bd9Sstevel@tonic-gate if (d->scope == NULL) 5187c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 5197c478bd9Sstevel@tonic-gate (void) memcpy(d->scope, s->scope, s->scope_len); 5207c478bd9Sstevel@tonic-gate d->scope_len = s->scope_len; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate pip->pi_size = size; 5237c478bd9Sstevel@tonic-gate break; 5247c478bd9Sstevel@tonic-gate default: 5257c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate switch (item_type) { 5287c478bd9Sstevel@tonic-gate case PAM_CONV: 5297c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_set_item(%p:%s)=%p", 5307c478bd9Sstevel@tonic-gate (void *)pamh, 5317c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 5327c478bd9Sstevel@tonic-gate item ? (void *)((struct pam_conv *)item)->conv : 5337c478bd9Sstevel@tonic-gate (void *)0); 5347c478bd9Sstevel@tonic-gate break; 5357c478bd9Sstevel@tonic-gate case PAM_REPOSITORY: 5367c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_set_item(%p:%s)=%s", 5377c478bd9Sstevel@tonic-gate (void *)pamh, 5387c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 5397c478bd9Sstevel@tonic-gate item ? (((struct pam_repository *)item)->type ? 5407c478bd9Sstevel@tonic-gate ((struct pam_repository *)item)->type : "NULL") : 5417c478bd9Sstevel@tonic-gate "NULL"); 5427c478bd9Sstevel@tonic-gate break; 5437c478bd9Sstevel@tonic-gate case PAM_AUTHTOK: 5447c478bd9Sstevel@tonic-gate case PAM_OLDAUTHTOK: 5457c478bd9Sstevel@tonic-gate #ifdef DEBUG 5467c478bd9Sstevel@tonic-gate if (pam_debug & PAM_DEBUG_AUTHTOK) 5477c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, 5487c478bd9Sstevel@tonic-gate "pam_set_item(%p:%s)=%s", (void *)pamh, 5497c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 5507c478bd9Sstevel@tonic-gate item ? (char *)item : "NULL"); 5517c478bd9Sstevel@tonic-gate else 5527c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 5537c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, 5547c478bd9Sstevel@tonic-gate "pam_set_item(%p:%s)=%s", (void *)pamh, 5557c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 5567c478bd9Sstevel@tonic-gate item ? "********" : "NULL"); 5577c478bd9Sstevel@tonic-gate break; 5587c478bd9Sstevel@tonic-gate default: 5597c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_set_item(%p:%s)=%s", 5607c478bd9Sstevel@tonic-gate (void *)pamh, 5617c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 5627c478bd9Sstevel@tonic-gate item ? (char *)item : "NULL"); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * pam_get_item - read the value of a parameter specified in 5707c478bd9Sstevel@tonic-gate * the call to pam_set_item() 5717c478bd9Sstevel@tonic-gate */ 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate int 5747c478bd9Sstevel@tonic-gate pam_get_item(const pam_handle_t *pamh, int item_type, void **item) 5757c478bd9Sstevel@tonic-gate { 5767c478bd9Sstevel@tonic-gate struct pam_item *pip; 5777c478bd9Sstevel@tonic-gate char iname_buf[PAM_MAX_MSG_SIZE]; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (((pam_debug & PAM_DEBUG_ITEM) == 0) || (pamh == NULL)) { 5807c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_get_item(%p:%s)", 5817c478bd9Sstevel@tonic-gate (void *)pamh, pam_trace_iname(item_type, iname_buf)); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate if (pamh == NULL) 5857c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* 5887c478bd9Sstevel@tonic-gate * XXX -- Contracted Consolidation Private 5897c478bd9Sstevel@tonic-gate * to be eliminated when dtlogin contract is terminated 5907c478bd9Sstevel@tonic-gate * Check if tag is Sun proprietary 5917c478bd9Sstevel@tonic-gate */ 5927c478bd9Sstevel@tonic-gate if (item_type == PAM_MSG_VERSION) { 5937c478bd9Sstevel@tonic-gate *item = pamh->pam_client_message_version_number; 5947c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_get_item(%p:%s)=%s", 5957c478bd9Sstevel@tonic-gate (void *)pamh, pam_trace_iname(item_type, iname_buf), 5967c478bd9Sstevel@tonic-gate *item ? (char *)*item : "NULL"); 5977c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (item_type <= 0 || item_type >= PAM_MAX_ITEMS) 6017c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if ((pamh->pam_inmodule != WO_OK) && 6047c478bd9Sstevel@tonic-gate ((item_type == PAM_AUTHTOK || item_type == PAM_OLDAUTHTOK))) { 6057c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_NOTICE, "pam_get_item(%s) called from " 6067c478bd9Sstevel@tonic-gate "a non module context", 6077c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf)); 6087c478bd9Sstevel@tonic-gate return (PAM_PERM_DENIED); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate pip = (struct pam_item *)&(pamh->ps_item[item_type]); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate *item = pip->pi_addr; 6147c478bd9Sstevel@tonic-gate switch (item_type) { 6157c478bd9Sstevel@tonic-gate case PAM_CONV: 6167c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_get_item(%p:%s)=%p", 6177c478bd9Sstevel@tonic-gate (void *)pamh, 6187c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 6197c478bd9Sstevel@tonic-gate (void *)((struct pam_conv *)*item)->conv); 6207c478bd9Sstevel@tonic-gate break; 6217c478bd9Sstevel@tonic-gate case PAM_REPOSITORY: 6227c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_get_item(%p:%s)=%s", 6237c478bd9Sstevel@tonic-gate (void *)pamh, 6247c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 6257c478bd9Sstevel@tonic-gate *item ? (((struct pam_repository *)*item)->type ? 6267c478bd9Sstevel@tonic-gate ((struct pam_repository *)*item)->type : "NULL") : 6277c478bd9Sstevel@tonic-gate "NULL"); 6287c478bd9Sstevel@tonic-gate break; 6297c478bd9Sstevel@tonic-gate case PAM_AUTHTOK: 6307c478bd9Sstevel@tonic-gate case PAM_OLDAUTHTOK: 6317c478bd9Sstevel@tonic-gate #ifdef DEBUG 6327c478bd9Sstevel@tonic-gate if (pam_debug & PAM_DEBUG_AUTHTOK) 6337c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, 6347c478bd9Sstevel@tonic-gate "pam_get_item(%p:%s)=%s", (void *)pamh, 6357c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 6367c478bd9Sstevel@tonic-gate *item ? *(char **)item : "NULL"); 6377c478bd9Sstevel@tonic-gate else 6387c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 6397c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, 6407c478bd9Sstevel@tonic-gate "pam_get_item(%p:%s)=%s", (void *)pamh, 6417c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 6427c478bd9Sstevel@tonic-gate *item ? "********" : "NULL"); 6437c478bd9Sstevel@tonic-gate break; 6447c478bd9Sstevel@tonic-gate default: 6457c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_ITEM, "pam_get_item(%p:%s)=%s", 6467c478bd9Sstevel@tonic-gate (void *)pamh, 6477c478bd9Sstevel@tonic-gate pam_trace_iname(item_type, iname_buf), 6487c478bd9Sstevel@tonic-gate *item ? *(char **)item : "NULL"); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate /* 6557c478bd9Sstevel@tonic-gate * parse_user_name - process the user response: ignore 6567c478bd9Sstevel@tonic-gate * '\t' or ' ' before or after a user name. 6577c478bd9Sstevel@tonic-gate * user_input is a null terminated string. 6587c478bd9Sstevel@tonic-gate * *ret_username will be the user name. 6597c478bd9Sstevel@tonic-gate */ 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate static int 6627c478bd9Sstevel@tonic-gate parse_user_name(char *user_input, char **ret_username) 6637c478bd9Sstevel@tonic-gate { 6647c478bd9Sstevel@tonic-gate register char *ptr; 6657c478bd9Sstevel@tonic-gate register int index = 0; 6667c478bd9Sstevel@tonic-gate char username[PAM_MAX_RESP_SIZE]; 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate /* Set the default value for *ret_username */ 6697c478bd9Sstevel@tonic-gate *ret_username = NULL; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * Set the initial value for username - this is a buffer holds 6737c478bd9Sstevel@tonic-gate * the user name. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate bzero((void *)username, PAM_MAX_RESP_SIZE); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* 6787c478bd9Sstevel@tonic-gate * The user_input is guaranteed to be terminated by a null character. 6797c478bd9Sstevel@tonic-gate */ 6807c478bd9Sstevel@tonic-gate ptr = user_input; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate /* Skip all the leading whitespaces if there are any. */ 6837c478bd9Sstevel@tonic-gate while ((*ptr == ' ') || (*ptr == '\t')) 6847c478bd9Sstevel@tonic-gate ptr++; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate if (*ptr == '\0') { 6877c478bd9Sstevel@tonic-gate /* 6887c478bd9Sstevel@tonic-gate * We should never get here since the user_input we got 6897c478bd9Sstevel@tonic-gate * in pam_get_user() is not all whitespaces nor just "\0". 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate /* 6957c478bd9Sstevel@tonic-gate * username will be the first string we get from user_input 6967c478bd9Sstevel@tonic-gate * - we skip leading whitespaces and ignore trailing whitespaces 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate while (*ptr != '\0') { 6997c478bd9Sstevel@tonic-gate if ((*ptr == ' ') || (*ptr == '\t')) 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate else { 7027c478bd9Sstevel@tonic-gate username[index] = *ptr; 7037c478bd9Sstevel@tonic-gate index++; 7047c478bd9Sstevel@tonic-gate ptr++; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* ret_username will be freed in pam_get_user(). */ 7097c478bd9Sstevel@tonic-gate if ((*ret_username = (char *)malloc((index + 1)*(sizeof (char)))) 7107c478bd9Sstevel@tonic-gate == NULL) 7117c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 7127c478bd9Sstevel@tonic-gate (void) strcpy(*ret_username, username); 7137c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate /* 7177c478bd9Sstevel@tonic-gate * Get the value of PAM_USER. If not set, then use the convenience function 7187c478bd9Sstevel@tonic-gate * to prompt for the user. Use prompt if specified, else use PAM_USER_PROMPT 7197c478bd9Sstevel@tonic-gate * if it is set, else use default. 7207c478bd9Sstevel@tonic-gate */ 7217c478bd9Sstevel@tonic-gate #define WHITESPACE 0 7227c478bd9Sstevel@tonic-gate #define USERNAME 1 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate int 7257c478bd9Sstevel@tonic-gate pam_get_user(pam_handle_t *pamh, char **user, const char *prompt_override) 7267c478bd9Sstevel@tonic-gate { 7277c478bd9Sstevel@tonic-gate int status; 7287c478bd9Sstevel@tonic-gate char *prompt = NULL; 7297c478bd9Sstevel@tonic-gate char *real_username; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate struct pam_response *ret_resp = NULL; 7327c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE]; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 7357c478bd9Sstevel@tonic-gate "pam_get_user(%p, %p, %s)", (void *)pamh, (void *)*user, 7367c478bd9Sstevel@tonic-gate prompt_override ? prompt_override : "NULL"); 7377c478bd9Sstevel@tonic-gate if (pamh == NULL) 7387c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if ((status = pam_get_item(pamh, PAM_USER, (void **)user)) 7417c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 7427c478bd9Sstevel@tonic-gate return (status); 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* if the user is set, return it */ 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if (*user != NULL && *user[0] != '\0') { 7487c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* 7527c478bd9Sstevel@tonic-gate * if the module is requesting a special prompt, use it. 7537c478bd9Sstevel@tonic-gate * else use PAM_USER_PROMPT. 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate if (prompt_override != NULL) { 7577c478bd9Sstevel@tonic-gate prompt = (char *)prompt_override; 7587c478bd9Sstevel@tonic-gate } else { 7597c478bd9Sstevel@tonic-gate status = pam_get_item(pamh, PAM_USER_PROMPT, (void**)&prompt); 7607c478bd9Sstevel@tonic-gate if (status != PAM_SUCCESS) { 7617c478bd9Sstevel@tonic-gate return (status); 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate /* if the prompt is not set, use default */ 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate if (prompt == NULL || prompt[0] == '\0') { 7687c478bd9Sstevel@tonic-gate prompt = dgettext(TEXT_DOMAIN, "Please enter user name: "); 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* prompt for the user */ 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate (void) strncpy(messages[0], prompt, sizeof (messages[0])); 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate for (;;) { 7767c478bd9Sstevel@tonic-gate int state = WHITESPACE; 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate status = do_conv(pamh, PAM_PROMPT_ECHO_ON, 1, messages, 7797c478bd9Sstevel@tonic-gate NULL, &ret_resp); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate if (status != PAM_SUCCESS) { 7827c478bd9Sstevel@tonic-gate return (status); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate if (ret_resp->resp && ret_resp->resp[0] != '\0') { 7867c478bd9Sstevel@tonic-gate int len = strlen(ret_resp->resp); 7877c478bd9Sstevel@tonic-gate int i; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 7907c478bd9Sstevel@tonic-gate if ((ret_resp->resp[i] != ' ') && 7917c478bd9Sstevel@tonic-gate (ret_resp->resp[i] != '\t')) { 7927c478bd9Sstevel@tonic-gate state = USERNAME; 7937c478bd9Sstevel@tonic-gate break; 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate if (state == USERNAME) 7987c478bd9Sstevel@tonic-gate break; 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* set PAM_USER */ 8037c478bd9Sstevel@tonic-gate /* Parse the user input to get the user name. */ 8047c478bd9Sstevel@tonic-gate status = parse_user_name(ret_resp->resp, &real_username); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate if (status != PAM_SUCCESS) { 8077c478bd9Sstevel@tonic-gate if (real_username != NULL) 8087c478bd9Sstevel@tonic-gate free(real_username); 8097c478bd9Sstevel@tonic-gate free_resp(1, ret_resp); 8107c478bd9Sstevel@tonic-gate return (status); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate status = pam_set_item(pamh, PAM_USER, real_username); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate free(real_username); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate free_resp(1, ret_resp); 8187c478bd9Sstevel@tonic-gate if (status != PAM_SUCCESS) { 8197c478bd9Sstevel@tonic-gate return (status); 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate /* 8237c478bd9Sstevel@tonic-gate * finally, get PAM_USER. We have to call pam_get_item to get 8247c478bd9Sstevel@tonic-gate * the value of user because pam_set_item mallocs the memory. 8257c478bd9Sstevel@tonic-gate */ 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate status = pam_get_item(pamh, PAM_USER, (void**)user); 8287c478bd9Sstevel@tonic-gate return (status); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate /* 8327c478bd9Sstevel@tonic-gate * Set module specific data 8337c478bd9Sstevel@tonic-gate */ 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate int 8367c478bd9Sstevel@tonic-gate pam_set_data(pam_handle_t *pamh, const char *module_data_name, void *data, 8377c478bd9Sstevel@tonic-gate void (*cleanup)(pam_handle_t *pamh, void *data, int pam_end_status)) 8387c478bd9Sstevel@tonic-gate { 8397c478bd9Sstevel@tonic-gate struct pam_module_data *psd; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DATA, 8427c478bd9Sstevel@tonic-gate "pam_set_data(%p:%s:%d)=%p", (void *)pamh, 8437c478bd9Sstevel@tonic-gate module_data_name ? module_data_name : "NULL", pamh->pam_inmodule, 8447c478bd9Sstevel@tonic-gate data); 8457c478bd9Sstevel@tonic-gate if (pamh == NULL || (pamh->pam_inmodule != WO_OK) || 8467c478bd9Sstevel@tonic-gate module_data_name == NULL) { 8477c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate /* check if module data already exists */ 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate for (psd = pamh->ssd; psd; psd = psd->next) { 8537c478bd9Sstevel@tonic-gate if (strcmp(psd->module_data_name, module_data_name) == 0) { 8547c478bd9Sstevel@tonic-gate /* clean up original data before setting the new data */ 8557c478bd9Sstevel@tonic-gate if (psd->cleanup) { 8567c478bd9Sstevel@tonic-gate psd->cleanup(pamh, psd->data, PAM_SUCCESS); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate psd->data = (void *)data; 8597c478bd9Sstevel@tonic-gate psd->cleanup = cleanup; 8607c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate psd = malloc(sizeof (struct pam_module_data)); 8657c478bd9Sstevel@tonic-gate if (psd == NULL) 8667c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate psd->module_data_name = strdup(module_data_name); 8697c478bd9Sstevel@tonic-gate if (psd->module_data_name == NULL) { 8707c478bd9Sstevel@tonic-gate free(psd); 8717c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate psd->data = (void *)data; 8757c478bd9Sstevel@tonic-gate psd->cleanup = cleanup; 8767c478bd9Sstevel@tonic-gate psd->next = pamh->ssd; 8777c478bd9Sstevel@tonic-gate pamh->ssd = psd; 8787c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate /* 8827c478bd9Sstevel@tonic-gate * get module specific data 8837c478bd9Sstevel@tonic-gate */ 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate int 8867c478bd9Sstevel@tonic-gate pam_get_data(const pam_handle_t *pamh, const char *module_data_name, 8877c478bd9Sstevel@tonic-gate const void **data) 8887c478bd9Sstevel@tonic-gate { 8897c478bd9Sstevel@tonic-gate struct pam_module_data *psd; 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate if (pamh == NULL || (pamh->pam_inmodule != WO_OK) || 8927c478bd9Sstevel@tonic-gate module_data_name == NULL) { 8937c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DATA, 8947c478bd9Sstevel@tonic-gate "pam_get_data(%p:%s:%d)=%p", (void *)pamh, 8957c478bd9Sstevel@tonic-gate module_data_name ? module_data_name : "NULL", 8967c478bd9Sstevel@tonic-gate pamh->pam_inmodule, *data); 8977c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate for (psd = pamh->ssd; psd; psd = psd->next) { 9017c478bd9Sstevel@tonic-gate if (strcmp(psd->module_data_name, module_data_name) == 0) { 9027c478bd9Sstevel@tonic-gate *data = psd->data; 9037c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DATA, 9047c478bd9Sstevel@tonic-gate "pam_get_data(%p:%s)=%p", (void *)pamh, 9057c478bd9Sstevel@tonic-gate module_data_name, *data); 9067c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DATA, 9107c478bd9Sstevel@tonic-gate "pam_get_data(%p:%s)=%s", (void *)pamh, module_data_name, 9117c478bd9Sstevel@tonic-gate "PAM_NO_MODULE_DATA"); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate return (PAM_NO_MODULE_DATA); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* 9177c478bd9Sstevel@tonic-gate * PAM equivalent to strerror() 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9207c478bd9Sstevel@tonic-gate const char * 9217c478bd9Sstevel@tonic-gate pam_strerror(pam_handle_t *pamh, int errnum) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate switch (errnum) { 9247c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 9257c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Success")); 9267c478bd9Sstevel@tonic-gate case PAM_OPEN_ERR: 9277c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Dlopen failure")); 9287c478bd9Sstevel@tonic-gate case PAM_SYMBOL_ERR: 9297c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Symbol not found")); 9307c478bd9Sstevel@tonic-gate case PAM_SERVICE_ERR: 9317c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9327c478bd9Sstevel@tonic-gate "Error in underlying service module")); 9337c478bd9Sstevel@tonic-gate case PAM_SYSTEM_ERR: 9347c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "System error")); 9357c478bd9Sstevel@tonic-gate case PAM_BUF_ERR: 9367c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Memory buffer error")); 9377c478bd9Sstevel@tonic-gate case PAM_CONV_ERR: 9387c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Conversation failure")); 9397c478bd9Sstevel@tonic-gate case PAM_PERM_DENIED: 9407c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Permission denied")); 9417c478bd9Sstevel@tonic-gate case PAM_MAXTRIES: 9427c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9437c478bd9Sstevel@tonic-gate "Maximum number of attempts exceeded")); 9447c478bd9Sstevel@tonic-gate case PAM_AUTH_ERR: 9457c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Authentication failed")); 9467c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD: 9477c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Get new authentication token")); 9487c478bd9Sstevel@tonic-gate case PAM_CRED_INSUFFICIENT: 9497c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Insufficient credentials")); 9507c478bd9Sstevel@tonic-gate case PAM_AUTHINFO_UNAVAIL: 9517c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9527c478bd9Sstevel@tonic-gate "Can not retrieve authentication info")); 9537c478bd9Sstevel@tonic-gate case PAM_USER_UNKNOWN: 9547c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "No account present for user")); 9557c478bd9Sstevel@tonic-gate case PAM_CRED_UNAVAIL: 9567c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9577c478bd9Sstevel@tonic-gate "Can not retrieve user credentials")); 9587c478bd9Sstevel@tonic-gate case PAM_CRED_EXPIRED: 9597c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9607c478bd9Sstevel@tonic-gate "User credentials have expired")); 9617c478bd9Sstevel@tonic-gate case PAM_CRED_ERR: 9627c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9637c478bd9Sstevel@tonic-gate "Failure setting user credentials")); 9647c478bd9Sstevel@tonic-gate case PAM_ACCT_EXPIRED: 9657c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "User account has expired")); 9667c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_EXPIRED: 9677c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "User password has expired")); 9687c478bd9Sstevel@tonic-gate case PAM_SESSION_ERR: 9697c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9707c478bd9Sstevel@tonic-gate "Can not make/remove entry for session")); 9717c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_ERR: 9727c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9737c478bd9Sstevel@tonic-gate "Authentication token manipulation error")); 9747c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_RECOVERY_ERR: 9757c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9767c478bd9Sstevel@tonic-gate "Authentication token can not be recovered")); 9777c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_LOCK_BUSY: 9787c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9797c478bd9Sstevel@tonic-gate "Authentication token lock busy")); 9807c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_DISABLE_AGING: 9817c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9827c478bd9Sstevel@tonic-gate "Authentication token aging disabled")); 9837c478bd9Sstevel@tonic-gate case PAM_NO_MODULE_DATA: 9847c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9857c478bd9Sstevel@tonic-gate "Module specific data not found")); 9867c478bd9Sstevel@tonic-gate case PAM_IGNORE: 9877c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Ignore module")); 9887c478bd9Sstevel@tonic-gate case PAM_ABORT: 9897c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "General PAM failure ")); 9907c478bd9Sstevel@tonic-gate case PAM_TRY_AGAIN: 9917c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, 9927c478bd9Sstevel@tonic-gate "Unable to complete operation. Try again")); 9937c478bd9Sstevel@tonic-gate default: 9947c478bd9Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unknown error")); 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate static void * 9997c478bd9Sstevel@tonic-gate sm_name(int ind) 10007c478bd9Sstevel@tonic-gate { 10017c478bd9Sstevel@tonic-gate switch (ind) { 10027c478bd9Sstevel@tonic-gate case PAM_AUTHENTICATE: 10037c478bd9Sstevel@tonic-gate return (PAM_SM_AUTHENTICATE); 10047c478bd9Sstevel@tonic-gate case PAM_SETCRED: 10057c478bd9Sstevel@tonic-gate return (PAM_SM_SETCRED); 10067c478bd9Sstevel@tonic-gate case PAM_ACCT_MGMT: 10077c478bd9Sstevel@tonic-gate return (PAM_SM_ACCT_MGMT); 10087c478bd9Sstevel@tonic-gate case PAM_OPEN_SESSION: 10097c478bd9Sstevel@tonic-gate return (PAM_SM_OPEN_SESSION); 10107c478bd9Sstevel@tonic-gate case PAM_CLOSE_SESSION: 10117c478bd9Sstevel@tonic-gate return (PAM_SM_CLOSE_SESSION); 10127c478bd9Sstevel@tonic-gate case PAM_CHAUTHTOK: 10137c478bd9Sstevel@tonic-gate return (PAM_SM_CHAUTHTOK); 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate return (NULL); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate static int 10197c478bd9Sstevel@tonic-gate (*func(pamtab_t *modulep, int ind))() 10207c478bd9Sstevel@tonic-gate { 10217c478bd9Sstevel@tonic-gate void *funcp; 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate if ((funcp = modulep->function_ptr) == NULL) 10247c478bd9Sstevel@tonic-gate return (NULL); 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate switch (ind) { 10277c478bd9Sstevel@tonic-gate case PAM_AUTHENTICATE: 10287c478bd9Sstevel@tonic-gate return (((struct auth_module *)funcp)->pam_sm_authenticate); 10297c478bd9Sstevel@tonic-gate case PAM_SETCRED: 10307c478bd9Sstevel@tonic-gate return (((struct auth_module *)funcp)->pam_sm_setcred); 10317c478bd9Sstevel@tonic-gate case PAM_ACCT_MGMT: 10327c478bd9Sstevel@tonic-gate return (((struct account_module *)funcp)->pam_sm_acct_mgmt); 10337c478bd9Sstevel@tonic-gate case PAM_OPEN_SESSION: 10347c478bd9Sstevel@tonic-gate return (((struct session_module *)funcp)->pam_sm_open_session); 10357c478bd9Sstevel@tonic-gate case PAM_CLOSE_SESSION: 10367c478bd9Sstevel@tonic-gate return (((struct session_module *)funcp)->pam_sm_close_session); 10377c478bd9Sstevel@tonic-gate case PAM_CHAUTHTOK: 10387c478bd9Sstevel@tonic-gate return (((struct password_module *)funcp)->pam_sm_chauthtok); 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate return (NULL); 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* 10447c478bd9Sstevel@tonic-gate * Run through the PAM service module stack for the given module type. 10457c478bd9Sstevel@tonic-gate */ 10467c478bd9Sstevel@tonic-gate static int 10477c478bd9Sstevel@tonic-gate run_stack(pam_handle_t *pamh, int flags, int type, int def_err, int ind, 10487c478bd9Sstevel@tonic-gate char *function_name) 10497c478bd9Sstevel@tonic-gate { 10507c478bd9Sstevel@tonic-gate int err = PAM_SYSTEM_ERR; /* preset */ 10517c478bd9Sstevel@tonic-gate int optional_error = 0; 10527c478bd9Sstevel@tonic-gate int required_error = 0; 10537c478bd9Sstevel@tonic-gate int success = 0; 10547c478bd9Sstevel@tonic-gate pamtab_t *modulep; 10557c478bd9Sstevel@tonic-gate int (*sm_func)(); 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate if (pamh == NULL) 10587c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 10597c478bd9Sstevel@tonic-gate 10607c478bd9Sstevel@tonic-gate /* read initial entries from pam.conf */ 10617c478bd9Sstevel@tonic-gate if ((err = read_pam_conf(pamh, PAM_CONFIG)) != PAM_SUCCESS) { 10627c478bd9Sstevel@tonic-gate return (err); 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate if ((modulep = 10667c478bd9Sstevel@tonic-gate pamh->pam_conf_info[pamh->include_depth][type]) == NULL) { 10677c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "%s no initial module present", 10687c478bd9Sstevel@tonic-gate pam_trace_cname(pamh)); 10697c478bd9Sstevel@tonic-gate goto exit_return; 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate pamh->pam_inmodule = WO_OK; /* OK to get AUTHTOK */ 10737c478bd9Sstevel@tonic-gate include: 10747c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, 10757c478bd9Sstevel@tonic-gate "[%d:%s]:run_stack:%s(%p, %x): %s", pamh->include_depth, 10767c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), function_name, (void *)pamh, flags, 10777c478bd9Sstevel@tonic-gate modulep ? modulep->module_path : "NULL"); 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate while (modulep != NULL) { 10807c478bd9Sstevel@tonic-gate if (modulep->pam_flag & PAM_INCLUDE) { 10817c478bd9Sstevel@tonic-gate /* save the return location */ 10827c478bd9Sstevel@tonic-gate pamh->pam_conf_modulep[pamh->include_depth] = 10837c478bd9Sstevel@tonic-gate modulep->next; 10847c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, 10857c478bd9Sstevel@tonic-gate "setting for include[%d:%p]", 10867c478bd9Sstevel@tonic-gate pamh->include_depth, (void *)modulep->next); 10877c478bd9Sstevel@tonic-gate if (pamh->include_depth++ >= PAM_MAX_INCLUDE) { 10887c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 10897c478bd9Sstevel@tonic-gate "run_stack: includes too deep %d " 10907c478bd9Sstevel@tonic-gate "found trying to include %s from %s, %d " 10917c478bd9Sstevel@tonic-gate "allowed", pamh->include_depth, 10927c478bd9Sstevel@tonic-gate modulep->module_path, pamh->pam_conf_name 10937c478bd9Sstevel@tonic-gate [PAM_MAX_INCLUDE] == NULL ? "NULL" : 10947c478bd9Sstevel@tonic-gate pamh->pam_conf_name[PAM_MAX_INCLUDE], 10957c478bd9Sstevel@tonic-gate PAM_MAX_INCLUDE); 10967c478bd9Sstevel@tonic-gate goto exit_return; 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate if ((err = read_pam_conf(pamh, 10997c478bd9Sstevel@tonic-gate modulep->module_path)) != PAM_SUCCESS) { 11007c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 11017c478bd9Sstevel@tonic-gate "run_stack[%d:%s]: can't read included " 11027c478bd9Sstevel@tonic-gate "conf %s", pamh->include_depth, 11037c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 11047c478bd9Sstevel@tonic-gate modulep->module_path); 11057c478bd9Sstevel@tonic-gate goto exit_return; 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate if ((modulep = pamh->pam_conf_info 11087c478bd9Sstevel@tonic-gate [pamh->include_depth][type]) == NULL) { 11097c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 11107c478bd9Sstevel@tonic-gate "run_stack[%d:%s]: no include module " 11117c478bd9Sstevel@tonic-gate "present %s", pamh->include_depth, 11127c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), function_name); 11137c478bd9Sstevel@tonic-gate goto exit_return; 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate if (modulep->pam_flag & PAM_INCLUDE) { 11167c478bd9Sstevel@tonic-gate /* first line another include */ 11177c478bd9Sstevel@tonic-gate goto include; 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, "include[%d:%s]" 11207c478bd9Sstevel@tonic-gate "(%p, %s)=%s", pamh->include_depth, 11217c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), (void *)pamh, 11227c478bd9Sstevel@tonic-gate function_name, modulep->module_path); 11237c478bd9Sstevel@tonic-gate if ((err = load_modules(pamh, type, sm_name(ind), 11247c478bd9Sstevel@tonic-gate pamh->pam_conf_info 11257c478bd9Sstevel@tonic-gate [pamh->include_depth][type])) != PAM_SUCCESS) { 11267c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 11277c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): load_modules failed", 11287c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 11297c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags); 11307c478bd9Sstevel@tonic-gate goto exit_return; 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate if ((modulep = pamh->pam_conf_info 11337c478bd9Sstevel@tonic-gate [pamh->include_depth][type]) == NULL) { 11347c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 11357c478bd9Sstevel@tonic-gate "%s no initial module present", 11367c478bd9Sstevel@tonic-gate pam_trace_cname(pamh)); 11377c478bd9Sstevel@tonic-gate goto exit_return; 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate } else if ((err = load_modules(pamh, type, sm_name(ind), 11407c478bd9Sstevel@tonic-gate modulep)) != PAM_SUCCESS) { 11417c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 11427c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): load_modules failed", 11437c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 11447c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags); 11457c478bd9Sstevel@tonic-gate goto exit_return; 11467c478bd9Sstevel@tonic-gate } /* PAM_INCLUDE */ 11477c478bd9Sstevel@tonic-gate sm_func = func(modulep, ind); 11487c478bd9Sstevel@tonic-gate if (sm_func) { 11497c478bd9Sstevel@tonic-gate err = sm_func(pamh, flags, modulep->module_argc, 11507c478bd9Sstevel@tonic-gate (const char **)modulep->module_argv); 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, 11537c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): %s returned %s", 11547c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 11557c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags, 11567c478bd9Sstevel@tonic-gate modulep->module_path, pam_strerror(pamh, err)); 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate switch (err) { 11597c478bd9Sstevel@tonic-gate case PAM_IGNORE: 11607c478bd9Sstevel@tonic-gate /* do nothing */ 11617c478bd9Sstevel@tonic-gate break; 11627c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 11637c478bd9Sstevel@tonic-gate if ((modulep->pam_flag & PAM_SUFFI_BIND) && 11647c478bd9Sstevel@tonic-gate !required_error) { 11657c478bd9Sstevel@tonic-gate pamh->pam_inmodule = RW_OK; 11667c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, 11677c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): %s: success", 11687c478bd9Sstevel@tonic-gate pamh->include_depth, 11697c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 11707c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags, 11717c478bd9Sstevel@tonic-gate (modulep->pam_flag & PAM_BINDING) ? 11727c478bd9Sstevel@tonic-gate PAM_BINDING_NAME : 11737c478bd9Sstevel@tonic-gate PAM_SUFFICIENT_NAME); 11747c478bd9Sstevel@tonic-gate goto exit_return; 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate success = 1; 11777c478bd9Sstevel@tonic-gate break; 11787c478bd9Sstevel@tonic-gate case PAM_TRY_AGAIN: 11797c478bd9Sstevel@tonic-gate /* 11807c478bd9Sstevel@tonic-gate * We need to return immediately, and 11817c478bd9Sstevel@tonic-gate * we shouldn't reset the AUTHTOK item 11827c478bd9Sstevel@tonic-gate * since it is not an error per-se. 11837c478bd9Sstevel@tonic-gate */ 11847c478bd9Sstevel@tonic-gate pamh->pam_inmodule = RW_OK; 11857c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, 11867c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): TRY_AGAIN: %s", 11877c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 11887c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags, 11897c478bd9Sstevel@tonic-gate pam_strerror(pamh, required_error ? 11907c478bd9Sstevel@tonic-gate required_error : err)); 11917c478bd9Sstevel@tonic-gate err = required_error ? required_error : err; 11927c478bd9Sstevel@tonic-gate goto exit_return; 11937c478bd9Sstevel@tonic-gate default: 11947c478bd9Sstevel@tonic-gate if (modulep->pam_flag & PAM_REQUISITE) { 11957c478bd9Sstevel@tonic-gate pamh->pam_inmodule = RW_OK; 11967c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, 11977c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): requisite: %s", 11987c478bd9Sstevel@tonic-gate pamh->include_depth, 11997c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 12007c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags, 12017c478bd9Sstevel@tonic-gate pam_strerror(pamh, 12027c478bd9Sstevel@tonic-gate required_error ? required_error : 12037c478bd9Sstevel@tonic-gate err)); 12047c478bd9Sstevel@tonic-gate err = required_error ? 12057c478bd9Sstevel@tonic-gate required_error : err; 12067c478bd9Sstevel@tonic-gate goto exit_return; 12077c478bd9Sstevel@tonic-gate } else if (modulep->pam_flag & PAM_REQRD_BIND) { 12087c478bd9Sstevel@tonic-gate if (!required_error) 12097c478bd9Sstevel@tonic-gate required_error = err; 12107c478bd9Sstevel@tonic-gate } else { 12117c478bd9Sstevel@tonic-gate if (!optional_error) 12127c478bd9Sstevel@tonic-gate optional_error = err; 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 12157c478bd9Sstevel@tonic-gate "[%d:%s]:%s(%p, %x): error %s", 12167c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 12177c478bd9Sstevel@tonic-gate function_name, (void *)pamh, flags, 12187c478bd9Sstevel@tonic-gate pam_strerror(pamh, err)); 12197c478bd9Sstevel@tonic-gate break; 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate modulep = modulep->next; 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, "[%d:%s]:stack_end:%s(%p, %x): %s %s: %s", 12267c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), function_name, 12277c478bd9Sstevel@tonic-gate (void *)pamh, flags, pamh->include_depth ? "included" : "final", 12287c478bd9Sstevel@tonic-gate required_error ? "required" : success ? "success" : 12297c478bd9Sstevel@tonic-gate optional_error ? "optional" : "default", 12307c478bd9Sstevel@tonic-gate pam_strerror(pamh, required_error ? required_error : 12317c478bd9Sstevel@tonic-gate success ? PAM_SUCCESS : optional_error ? optional_error : def_err)); 12327c478bd9Sstevel@tonic-gate if (pamh->include_depth > 0) { 12337c478bd9Sstevel@tonic-gate free_pam_conf_info(pamh); 12347c478bd9Sstevel@tonic-gate pamh->include_depth--; 12357c478bd9Sstevel@tonic-gate /* continue at next entry */ 12367c478bd9Sstevel@tonic-gate modulep = pamh->pam_conf_modulep[pamh->include_depth]; 12377c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, "looping for include[%d:%p]", 12387c478bd9Sstevel@tonic-gate pamh->include_depth, (void *)modulep); 12397c478bd9Sstevel@tonic-gate goto include; 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate free_pam_conf_info(pamh); 12427c478bd9Sstevel@tonic-gate pamh->pam_inmodule = RW_OK; 12437c478bd9Sstevel@tonic-gate if (required_error != 0) 12447c478bd9Sstevel@tonic-gate return (required_error); 12457c478bd9Sstevel@tonic-gate else if (success != 0) 12467c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 12477c478bd9Sstevel@tonic-gate else if (optional_error != 0) 12487c478bd9Sstevel@tonic-gate return (optional_error); 12497c478bd9Sstevel@tonic-gate else 12507c478bd9Sstevel@tonic-gate return (def_err); 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate exit_return: 12537c478bd9Sstevel@tonic-gate /* 12547c478bd9Sstevel@tonic-gate * All done at whatever depth we're at. 12557c478bd9Sstevel@tonic-gate * Go back to not having read /etc/pam.conf 12567c478bd9Sstevel@tonic-gate */ 12577c478bd9Sstevel@tonic-gate while (pamh->include_depth > 0) { 12587c478bd9Sstevel@tonic-gate free_pam_conf_info(pamh); 12597c478bd9Sstevel@tonic-gate pamh->include_depth--; 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate free_pam_conf_info(pamh); 12627c478bd9Sstevel@tonic-gate pamh->pam_inmodule = RW_OK; 12637c478bd9Sstevel@tonic-gate return (err); 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate /* 12677c478bd9Sstevel@tonic-gate * pam_authenticate - authenticate a user 12687c478bd9Sstevel@tonic-gate */ 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate int 12717c478bd9Sstevel@tonic-gate pam_authenticate(pam_handle_t *pamh, int flags) 12727c478bd9Sstevel@tonic-gate { 12737c478bd9Sstevel@tonic-gate int retval; 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags, PAM_AUTH_MODULE, PAM_AUTH_ERR, 12767c478bd9Sstevel@tonic-gate PAM_AUTHENTICATE, "pam_authenticate"); 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS) 12797c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 12807c478bd9Sstevel@tonic-gate return (retval); 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate /* 12847c478bd9Sstevel@tonic-gate * pam_setcred - modify or retrieve user credentials 12857c478bd9Sstevel@tonic-gate */ 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate int 12887c478bd9Sstevel@tonic-gate pam_setcred(pam_handle_t *pamh, int flags) 12897c478bd9Sstevel@tonic-gate { 12907c478bd9Sstevel@tonic-gate int retval; 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags, PAM_AUTH_MODULE, PAM_CRED_ERR, 12937c478bd9Sstevel@tonic-gate PAM_SETCRED, "pam_setcred"); 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS) 12967c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 12977c478bd9Sstevel@tonic-gate return (retval); 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate /* 13017c478bd9Sstevel@tonic-gate * pam_acct_mgmt - check password aging, account expiration 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate int 13057c478bd9Sstevel@tonic-gate pam_acct_mgmt(pam_handle_t *pamh, int flags) 13067c478bd9Sstevel@tonic-gate { 13077c478bd9Sstevel@tonic-gate int retval; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags, PAM_ACCOUNT_MODULE, PAM_ACCT_EXPIRED, 13107c478bd9Sstevel@tonic-gate PAM_ACCT_MGMT, "pam_acct_mgmt"); 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS && 13137c478bd9Sstevel@tonic-gate retval != PAM_NEW_AUTHTOK_REQD) { 13147c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate return (retval); 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate /* 13207c478bd9Sstevel@tonic-gate * pam_open_session - begin session management 13217c478bd9Sstevel@tonic-gate */ 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate int 13247c478bd9Sstevel@tonic-gate pam_open_session(pam_handle_t *pamh, int flags) 13257c478bd9Sstevel@tonic-gate { 13267c478bd9Sstevel@tonic-gate int retval; 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags, PAM_SESSION_MODULE, PAM_SESSION_ERR, 13297c478bd9Sstevel@tonic-gate PAM_OPEN_SESSION, "pam_open_session"); 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS) 13327c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 13337c478bd9Sstevel@tonic-gate return (retval); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate /* 13377c478bd9Sstevel@tonic-gate * pam_close_session - terminate session management 13387c478bd9Sstevel@tonic-gate */ 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate int 13417c478bd9Sstevel@tonic-gate pam_close_session(pam_handle_t *pamh, int flags) 13427c478bd9Sstevel@tonic-gate { 13437c478bd9Sstevel@tonic-gate int retval; 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags, PAM_SESSION_MODULE, PAM_SESSION_ERR, 13467c478bd9Sstevel@tonic-gate PAM_CLOSE_SESSION, "pam_close_session"); 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS) 13497c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 13507c478bd9Sstevel@tonic-gate return (retval); 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate /* 13547c478bd9Sstevel@tonic-gate * pam_chauthtok - change user authentication token 13557c478bd9Sstevel@tonic-gate */ 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate int 13587c478bd9Sstevel@tonic-gate pam_chauthtok(pam_handle_t *pamh, int flags) 13597c478bd9Sstevel@tonic-gate { 13607c478bd9Sstevel@tonic-gate int retval; 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate /* do not let apps use PAM_PRELIM_CHECK or PAM_UPDATE_AUTHTOK */ 13637c478bd9Sstevel@tonic-gate if (flags & (PAM_PRELIM_CHECK | PAM_UPDATE_AUTHTOK)) { 13647c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 13657c478bd9Sstevel@tonic-gate "pam_chauthtok(%p, %x): %s", (void *)pamh, flags, 13667c478bd9Sstevel@tonic-gate pam_strerror(pamh, PAM_SYMBOL_ERR)); 13677c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate /* 1st pass: PRELIM CHECK */ 13717c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags | PAM_PRELIM_CHECK, PAM_PASSWORD_MODULE, 13727c478bd9Sstevel@tonic-gate PAM_AUTHTOK_ERR, PAM_CHAUTHTOK, "pam_chauthtok-prelim"); 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate if (retval == PAM_TRY_AGAIN) 13757c478bd9Sstevel@tonic-gate return (retval); 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS) { 13787c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 13797c478bd9Sstevel@tonic-gate return (retval); 13807c478bd9Sstevel@tonic-gate } 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate /* 2nd pass: UPDATE AUTHTOK */ 13837c478bd9Sstevel@tonic-gate retval = run_stack(pamh, flags | PAM_UPDATE_AUTHTOK, 13847c478bd9Sstevel@tonic-gate PAM_PASSWORD_MODULE, PAM_AUTHTOK_ERR, PAM_CHAUTHTOK, 13857c478bd9Sstevel@tonic-gate "pam_chauthtok-update"); 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate if (retval != PAM_SUCCESS) 13887c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_AUTHTOK, NULL); 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate return (retval); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* 13947c478bd9Sstevel@tonic-gate * pam_putenv - add an environment variable to the PAM handle 13957c478bd9Sstevel@tonic-gate * if name_value == 'NAME=VALUE' then set variable to the value 13967c478bd9Sstevel@tonic-gate * if name_value == 'NAME=' then set variable to an empty value 13977c478bd9Sstevel@tonic-gate * if name_value == 'NAME' then delete the variable 13987c478bd9Sstevel@tonic-gate */ 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate int 14017c478bd9Sstevel@tonic-gate pam_putenv(pam_handle_t *pamh, const char *name_value) 14027c478bd9Sstevel@tonic-gate { 14037c478bd9Sstevel@tonic-gate int error = PAM_SYSTEM_ERR; 14047c478bd9Sstevel@tonic-gate char *equal_sign = 0; 14057c478bd9Sstevel@tonic-gate char *name = NULL, *value = NULL, *tmp_value = NULL; 14067c478bd9Sstevel@tonic-gate env_list *traverse, *trail; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 14097c478bd9Sstevel@tonic-gate "pam_putenv(%p, %s)", (void *)pamh, 14107c478bd9Sstevel@tonic-gate name_value ? name_value : "NULL"); 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate if (pamh == NULL || name_value == NULL) 14137c478bd9Sstevel@tonic-gate goto out; 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate /* see if we were passed 'NAME=VALUE', 'NAME=', or 'NAME' */ 14167c478bd9Sstevel@tonic-gate if ((equal_sign = strchr(name_value, '=')) != 0) { 14177c478bd9Sstevel@tonic-gate if ((name = (char *)calloc(equal_sign - name_value + 1, 14187c478bd9Sstevel@tonic-gate sizeof (char))) == 0) { 14197c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 14207c478bd9Sstevel@tonic-gate goto out; 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate (void) strncpy(name, name_value, equal_sign - name_value); 14237c478bd9Sstevel@tonic-gate if ((value = strdup(++equal_sign)) == 0) { 14247c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 14257c478bd9Sstevel@tonic-gate goto out; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate } else { 14287c478bd9Sstevel@tonic-gate if ((name = strdup(name_value)) == 0) { 14297c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 14307c478bd9Sstevel@tonic-gate goto out; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* check to see if we already have this variable in the PAM handle */ 14357c478bd9Sstevel@tonic-gate traverse = pamh->pam_env; 14367c478bd9Sstevel@tonic-gate trail = traverse; 14377c478bd9Sstevel@tonic-gate while (traverse && strncmp(traverse->name, name, strlen(name))) { 14387c478bd9Sstevel@tonic-gate trail = traverse; 14397c478bd9Sstevel@tonic-gate traverse = traverse->next; 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate if (traverse) { 14437c478bd9Sstevel@tonic-gate /* found a match */ 14447c478bd9Sstevel@tonic-gate if (value == 0) { 14457c478bd9Sstevel@tonic-gate /* remove the env variable */ 14467c478bd9Sstevel@tonic-gate if (pamh->pam_env == traverse) 14477c478bd9Sstevel@tonic-gate pamh->pam_env = traverse->next; 14487c478bd9Sstevel@tonic-gate else 14497c478bd9Sstevel@tonic-gate trail->next = traverse->next; 14507c478bd9Sstevel@tonic-gate free_env(traverse); 14517c478bd9Sstevel@tonic-gate } else if (strlen(value) == 0) { 14527c478bd9Sstevel@tonic-gate /* set env variable to empty value */ 14537c478bd9Sstevel@tonic-gate if ((tmp_value = strdup("")) == 0) { 14547c478bd9Sstevel@tonic-gate error = PAM_SYSTEM_ERR; 14557c478bd9Sstevel@tonic-gate goto out; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate free(traverse->value); 14587c478bd9Sstevel@tonic-gate traverse->value = tmp_value; 14597c478bd9Sstevel@tonic-gate } else { 14607c478bd9Sstevel@tonic-gate /* set the new value */ 14617c478bd9Sstevel@tonic-gate if ((tmp_value = strdup(value)) == 0) { 14627c478bd9Sstevel@tonic-gate error = PAM_SYSTEM_ERR; 14637c478bd9Sstevel@tonic-gate goto out; 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate free(traverse->value); 14667c478bd9Sstevel@tonic-gate traverse->value = tmp_value; 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate } else if (traverse == 0 && value) { 14707c478bd9Sstevel@tonic-gate /* 14717c478bd9Sstevel@tonic-gate * could not find a match in the PAM handle. 14727c478bd9Sstevel@tonic-gate * add the new value if there is one 14737c478bd9Sstevel@tonic-gate */ 14747c478bd9Sstevel@tonic-gate if ((traverse = (env_list *)calloc 14757c478bd9Sstevel@tonic-gate (1, 14767c478bd9Sstevel@tonic-gate sizeof (env_list))) == 0) { 14777c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 14787c478bd9Sstevel@tonic-gate goto out; 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate if ((traverse->name = strdup(name)) == 0) { 14817c478bd9Sstevel@tonic-gate free_env(traverse); 14827c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 14837c478bd9Sstevel@tonic-gate goto out; 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate if ((traverse->value = strdup(value)) == 0) { 14867c478bd9Sstevel@tonic-gate free_env(traverse); 14877c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 14887c478bd9Sstevel@tonic-gate goto out; 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate if (trail == 0) { 14917c478bd9Sstevel@tonic-gate /* new head of list */ 14927c478bd9Sstevel@tonic-gate pamh->pam_env = traverse; 14937c478bd9Sstevel@tonic-gate } else { 14947c478bd9Sstevel@tonic-gate /* adding to end of list */ 14957c478bd9Sstevel@tonic-gate trail->next = traverse; 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate error = PAM_SUCCESS; 15007c478bd9Sstevel@tonic-gate out: 15017c478bd9Sstevel@tonic-gate if (error != PAM_SUCCESS) { 15027c478bd9Sstevel@tonic-gate if (traverse) { 15037c478bd9Sstevel@tonic-gate if (traverse->name) 15047c478bd9Sstevel@tonic-gate free(traverse->name); 15057c478bd9Sstevel@tonic-gate if (traverse->value) 15067c478bd9Sstevel@tonic-gate free(traverse->value); 15077c478bd9Sstevel@tonic-gate free(traverse); 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate if (name) 15117c478bd9Sstevel@tonic-gate free(name); 15127c478bd9Sstevel@tonic-gate if (value) 15137c478bd9Sstevel@tonic-gate free(value); 15147c478bd9Sstevel@tonic-gate return (error); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate /* 15187c478bd9Sstevel@tonic-gate * pam_getenv - retrieve an environment variable from the PAM handle 15197c478bd9Sstevel@tonic-gate */ 15207c478bd9Sstevel@tonic-gate char * 15217c478bd9Sstevel@tonic-gate pam_getenv(pam_handle_t *pamh, const char *name) 15227c478bd9Sstevel@tonic-gate { 15237c478bd9Sstevel@tonic-gate int error = PAM_SYSTEM_ERR; 15247c478bd9Sstevel@tonic-gate env_list *traverse; 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 15277c478bd9Sstevel@tonic-gate "pam_getenv(%p, %p)", (void *)pamh, (void *)name); 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate if (pamh == NULL || name == NULL) 15307c478bd9Sstevel@tonic-gate goto out; 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate /* check to see if we already have this variable in the PAM handle */ 15337c478bd9Sstevel@tonic-gate traverse = pamh->pam_env; 15347c478bd9Sstevel@tonic-gate while (traverse && strncmp(traverse->name, name, strlen(name))) { 15357c478bd9Sstevel@tonic-gate traverse = traverse->next; 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate error = (traverse ? PAM_SUCCESS : PAM_SYSTEM_ERR); 15387c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 15397c478bd9Sstevel@tonic-gate "pam_getenv(%p, %s)=%s", (void *)pamh, name, 15407c478bd9Sstevel@tonic-gate traverse ? traverse->value : "NULL"); 15417c478bd9Sstevel@tonic-gate out: 15427c478bd9Sstevel@tonic-gate return (error ? NULL : strdup(traverse->value)); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate /* 15467c478bd9Sstevel@tonic-gate * pam_getenvlist - retrieve all environment variables from the PAM handle 15477c478bd9Sstevel@tonic-gate */ 15487c478bd9Sstevel@tonic-gate char ** 15497c478bd9Sstevel@tonic-gate pam_getenvlist(pam_handle_t *pamh) 15507c478bd9Sstevel@tonic-gate { 15517c478bd9Sstevel@tonic-gate int error = PAM_SYSTEM_ERR; 15527c478bd9Sstevel@tonic-gate char **list = 0; 15537c478bd9Sstevel@tonic-gate int length = 0; 15547c478bd9Sstevel@tonic-gate env_list *traverse; 15557c478bd9Sstevel@tonic-gate char env_buf[1024]; 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 15587c478bd9Sstevel@tonic-gate "pam_getenvlist(%p)", (void *)pamh); 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate if (pamh == NULL) 15617c478bd9Sstevel@tonic-gate goto out; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate /* find out how many environment variables we have */ 15647c478bd9Sstevel@tonic-gate traverse = pamh->pam_env; 15657c478bd9Sstevel@tonic-gate while (traverse) { 15667c478bd9Sstevel@tonic-gate length++; 15677c478bd9Sstevel@tonic-gate traverse = traverse->next; 15687c478bd9Sstevel@tonic-gate } 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate /* allocate the array we will return to the caller */ 15717c478bd9Sstevel@tonic-gate if ((list = (char **)calloc(length + 1, sizeof (char *))) == 0) { 15727c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 15737c478bd9Sstevel@tonic-gate goto out; 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate /* add the variables one by one */ 15777c478bd9Sstevel@tonic-gate length = 0; 15787c478bd9Sstevel@tonic-gate traverse = pamh->pam_env; 15797c478bd9Sstevel@tonic-gate while (traverse) { 15807c478bd9Sstevel@tonic-gate (void) snprintf(env_buf, sizeof (env_buf), "%s=%s", 15817c478bd9Sstevel@tonic-gate traverse->name, traverse->value); 15827c478bd9Sstevel@tonic-gate if ((list[length] = strdup(env_buf)) == 0) { 15837c478bd9Sstevel@tonic-gate error = PAM_BUF_ERR; 15847c478bd9Sstevel@tonic-gate goto out; 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate length++; 15877c478bd9Sstevel@tonic-gate traverse = traverse->next; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate 15907c478bd9Sstevel@tonic-gate /* null terminate the list */ 15917c478bd9Sstevel@tonic-gate list[length] = 0; 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate error = PAM_SUCCESS; 15947c478bd9Sstevel@tonic-gate out: 15957c478bd9Sstevel@tonic-gate if (error != PAM_SUCCESS) { 15967c478bd9Sstevel@tonic-gate /* free the partially constructed list */ 15977c478bd9Sstevel@tonic-gate if (list) { 15987c478bd9Sstevel@tonic-gate length = 0; 15997c478bd9Sstevel@tonic-gate while (list[length] != NULL) { 16007c478bd9Sstevel@tonic-gate free(list[length]); 16017c478bd9Sstevel@tonic-gate length++; 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate free(list); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate return (error ? NULL : list); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate /* 16107c478bd9Sstevel@tonic-gate * Routines to load a requested module on demand 16117c478bd9Sstevel@tonic-gate */ 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate /* 16147c478bd9Sstevel@tonic-gate * load_modules - load the requested module. 16157c478bd9Sstevel@tonic-gate * if the dlopen or dlsym fail, then 16167c478bd9Sstevel@tonic-gate * the module is ignored. 16177c478bd9Sstevel@tonic-gate */ 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate static int 16207c478bd9Sstevel@tonic-gate load_modules(pam_handle_t *pamh, int type, char *function_name, 16217c478bd9Sstevel@tonic-gate pamtab_t *pam_entry) 16227c478bd9Sstevel@tonic-gate { 16237c478bd9Sstevel@tonic-gate void *mh; 16247c478bd9Sstevel@tonic-gate struct auth_module *authp; 16257c478bd9Sstevel@tonic-gate struct account_module *accountp; 16267c478bd9Sstevel@tonic-gate struct session_module *sessionp; 16277c478bd9Sstevel@tonic-gate struct password_module *passwdp; 16287c478bd9Sstevel@tonic-gate int loading_functions = 0; /* are we currently loading functions? */ 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, "load_modules[%d:%s](%p, %s)=%s:%s", 16317c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), (void *)pamh, 16327c478bd9Sstevel@tonic-gate function_name, pam_trace_fname(pam_entry->pam_flag), 16337c478bd9Sstevel@tonic-gate pam_entry->module_path); 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate while (pam_entry != NULL) { 16367c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 16377c478bd9Sstevel@tonic-gate "while load_modules[%d:%s](%p, %s)=%s", 16387c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), (void *)pamh, 16397c478bd9Sstevel@tonic-gate function_name, pam_entry->module_path); 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate if (pam_entry->pam_flag & PAM_INCLUDE) { 16427c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 16437c478bd9Sstevel@tonic-gate "done load_modules[%d:%s](%p, %s)=%s", 16447c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 16457c478bd9Sstevel@tonic-gate (void *)pamh, function_name, 16467c478bd9Sstevel@tonic-gate pam_entry->module_path); 16477c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate switch (type) { 16507c478bd9Sstevel@tonic-gate case PAM_AUTH_MODULE: 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate /* if the function has already been loaded, return */ 16537c478bd9Sstevel@tonic-gate authp = pam_entry->function_ptr; 16547c478bd9Sstevel@tonic-gate if (!loading_functions && 16557c478bd9Sstevel@tonic-gate (((strcmp(function_name, PAM_SM_AUTHENTICATE) 16567c478bd9Sstevel@tonic-gate == 0) && 16577c478bd9Sstevel@tonic-gate authp && authp->pam_sm_authenticate) || 16587c478bd9Sstevel@tonic-gate ((strcmp(function_name, PAM_SM_SETCRED) == 0) && 16597c478bd9Sstevel@tonic-gate authp && authp->pam_sm_setcred))) { 16607c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate /* function has not been loaded yet */ 16647c478bd9Sstevel@tonic-gate loading_functions = 1; 16657c478bd9Sstevel@tonic-gate if (authp == NULL) { 16667c478bd9Sstevel@tonic-gate authp = (struct auth_module *)calloc(1, 16677c478bd9Sstevel@tonic-gate sizeof (struct auth_module)); 16687c478bd9Sstevel@tonic-gate if (authp == NULL) 16697c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate /* if open_module fails, return error */ 16737c478bd9Sstevel@tonic-gate if ((mh = open_module(pamh, 16747c478bd9Sstevel@tonic-gate pam_entry->module_path)) == NULL) { 16757c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 16767c478bd9Sstevel@tonic-gate "load_modules[%d:%s]: can not open module " 16777c478bd9Sstevel@tonic-gate "%s", pamh->include_depth, 16787c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 16797c478bd9Sstevel@tonic-gate pam_entry->module_path); 16807c478bd9Sstevel@tonic-gate free(authp); 16817c478bd9Sstevel@tonic-gate return (PAM_OPEN_ERR); 16827c478bd9Sstevel@tonic-gate } 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* load the authentication function */ 16857c478bd9Sstevel@tonic-gate if (strcmp(function_name, PAM_SM_AUTHENTICATE) == 0) { 16867c478bd9Sstevel@tonic-gate if (load_function(mh, PAM_SM_AUTHENTICATE, 16877c478bd9Sstevel@tonic-gate &authp->pam_sm_authenticate) 16887c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 16897c478bd9Sstevel@tonic-gate /* return error if dlsym fails */ 16907c478bd9Sstevel@tonic-gate free(authp); 16917c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate /* load the setcred function */ 16957c478bd9Sstevel@tonic-gate } else if (strcmp(function_name, PAM_SM_SETCRED) == 0) { 16967c478bd9Sstevel@tonic-gate if (load_function(mh, PAM_SM_SETCRED, 16977c478bd9Sstevel@tonic-gate &authp->pam_sm_setcred) != PAM_SUCCESS) { 16987c478bd9Sstevel@tonic-gate /* return error if dlsym fails */ 16997c478bd9Sstevel@tonic-gate free(authp); 17007c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate pam_entry->function_ptr = authp; 17047c478bd9Sstevel@tonic-gate break; 17057c478bd9Sstevel@tonic-gate case PAM_ACCOUNT_MODULE: 17067c478bd9Sstevel@tonic-gate accountp = pam_entry->function_ptr; 17077c478bd9Sstevel@tonic-gate if (!loading_functions && 17087c478bd9Sstevel@tonic-gate (strcmp(function_name, PAM_SM_ACCT_MGMT) == 0) && 17097c478bd9Sstevel@tonic-gate accountp && accountp->pam_sm_acct_mgmt) { 17107c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate /* 17147c478bd9Sstevel@tonic-gate * If functions are added to the account module, 17157c478bd9Sstevel@tonic-gate * verify that one of the other functions hasn't 17167c478bd9Sstevel@tonic-gate * already loaded it. See PAM_AUTH_MODULE code. 17177c478bd9Sstevel@tonic-gate */ 17187c478bd9Sstevel@tonic-gate loading_functions = 1; 17197c478bd9Sstevel@tonic-gate accountp = (struct account_module *)calloc(1, 17207c478bd9Sstevel@tonic-gate sizeof (struct account_module)); 17217c478bd9Sstevel@tonic-gate if (accountp == NULL) 17227c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate /* if open_module fails, return error */ 17257c478bd9Sstevel@tonic-gate if ((mh = open_module(pamh, 17267c478bd9Sstevel@tonic-gate pam_entry->module_path)) == NULL) { 17277c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 17287c478bd9Sstevel@tonic-gate "load_modules[%d:%s]: can not open module " 17297c478bd9Sstevel@tonic-gate "%s", pamh->include_depth, 17307c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 17317c478bd9Sstevel@tonic-gate pam_entry->module_path); 17327c478bd9Sstevel@tonic-gate free(accountp); 17337c478bd9Sstevel@tonic-gate return (PAM_OPEN_ERR); 17347c478bd9Sstevel@tonic-gate } 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate if (load_function(mh, PAM_SM_ACCT_MGMT, 17377c478bd9Sstevel@tonic-gate &accountp->pam_sm_acct_mgmt) != PAM_SUCCESS) { 17387c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 17397c478bd9Sstevel@tonic-gate "load_modules[%d:%s]: pam_sm_acct_mgmt() " 17407c478bd9Sstevel@tonic-gate "missing", pamh->include_depth, 17417c478bd9Sstevel@tonic-gate pam_trace_cname(pamh)); 17427c478bd9Sstevel@tonic-gate free(accountp); 17437c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate pam_entry->function_ptr = accountp; 17467c478bd9Sstevel@tonic-gate break; 17477c478bd9Sstevel@tonic-gate case PAM_SESSION_MODULE: 17487c478bd9Sstevel@tonic-gate sessionp = pam_entry->function_ptr; 17497c478bd9Sstevel@tonic-gate if (!loading_functions && 17507c478bd9Sstevel@tonic-gate (((strcmp(function_name, 17517c478bd9Sstevel@tonic-gate PAM_SM_OPEN_SESSION) == 0) && 17527c478bd9Sstevel@tonic-gate sessionp && sessionp->pam_sm_open_session) || 17537c478bd9Sstevel@tonic-gate ((strcmp(function_name, 17547c478bd9Sstevel@tonic-gate PAM_SM_CLOSE_SESSION) == 0) && 17557c478bd9Sstevel@tonic-gate sessionp && sessionp->pam_sm_close_session))) { 17567c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate loading_functions = 1; 17607c478bd9Sstevel@tonic-gate if (sessionp == NULL) { 17617c478bd9Sstevel@tonic-gate sessionp = (struct session_module *) 17627c478bd9Sstevel@tonic-gate calloc(1, sizeof (struct session_module)); 17637c478bd9Sstevel@tonic-gate if (sessionp == NULL) 17647c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* if open_module fails, return error */ 17687c478bd9Sstevel@tonic-gate if ((mh = open_module(pamh, 17697c478bd9Sstevel@tonic-gate pam_entry->module_path)) == NULL) { 17707c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 17717c478bd9Sstevel@tonic-gate "load_modules[%d:%s]: can not open module " 17727c478bd9Sstevel@tonic-gate "%s", pamh->include_depth, 17737c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 17747c478bd9Sstevel@tonic-gate pam_entry->module_path); 17757c478bd9Sstevel@tonic-gate free(sessionp); 17767c478bd9Sstevel@tonic-gate return (PAM_OPEN_ERR); 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate if ((strcmp(function_name, PAM_SM_OPEN_SESSION) == 0) && 17807c478bd9Sstevel@tonic-gate load_function(mh, PAM_SM_OPEN_SESSION, 17817c478bd9Sstevel@tonic-gate &sessionp->pam_sm_open_session) 17827c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 17837c478bd9Sstevel@tonic-gate free(sessionp); 17847c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 17857c478bd9Sstevel@tonic-gate } else if ((strcmp(function_name, 17867c478bd9Sstevel@tonic-gate PAM_SM_CLOSE_SESSION) == 0) && 17877c478bd9Sstevel@tonic-gate load_function(mh, PAM_SM_CLOSE_SESSION, 17887c478bd9Sstevel@tonic-gate &sessionp->pam_sm_close_session) 17897c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 17907c478bd9Sstevel@tonic-gate free(sessionp); 17917c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 17927c478bd9Sstevel@tonic-gate } 17937c478bd9Sstevel@tonic-gate pam_entry->function_ptr = sessionp; 17947c478bd9Sstevel@tonic-gate break; 17957c478bd9Sstevel@tonic-gate case PAM_PASSWORD_MODULE: 17967c478bd9Sstevel@tonic-gate passwdp = pam_entry->function_ptr; 17977c478bd9Sstevel@tonic-gate if (!loading_functions && 17987c478bd9Sstevel@tonic-gate (strcmp(function_name, PAM_SM_CHAUTHTOK) == 0) && 17997c478bd9Sstevel@tonic-gate passwdp && passwdp->pam_sm_chauthtok) { 18007c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate /* 18047c478bd9Sstevel@tonic-gate * If functions are added to the password module, 18057c478bd9Sstevel@tonic-gate * verify that one of the other functions hasn't 18067c478bd9Sstevel@tonic-gate * already loaded it. See PAM_AUTH_MODULE code. 18077c478bd9Sstevel@tonic-gate */ 18087c478bd9Sstevel@tonic-gate loading_functions = 1; 18097c478bd9Sstevel@tonic-gate passwdp = (struct password_module *) 18107c478bd9Sstevel@tonic-gate calloc(1, sizeof (struct password_module)); 18117c478bd9Sstevel@tonic-gate if (passwdp == NULL) 18127c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate /* if open_module fails, continue */ 18157c478bd9Sstevel@tonic-gate if ((mh = open_module(pamh, 18167c478bd9Sstevel@tonic-gate pam_entry->module_path)) == NULL) { 18177c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 18187c478bd9Sstevel@tonic-gate "load_modules[%d:%s]: can not open module " 18197c478bd9Sstevel@tonic-gate "%s", pamh->include_depth, 18207c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 18217c478bd9Sstevel@tonic-gate pam_entry->module_path); 18227c478bd9Sstevel@tonic-gate free(passwdp); 18237c478bd9Sstevel@tonic-gate return (PAM_OPEN_ERR); 18247c478bd9Sstevel@tonic-gate } 18257c478bd9Sstevel@tonic-gate 18267c478bd9Sstevel@tonic-gate if (load_function(mh, PAM_SM_CHAUTHTOK, 18277c478bd9Sstevel@tonic-gate &passwdp->pam_sm_chauthtok) != PAM_SUCCESS) { 18287c478bd9Sstevel@tonic-gate free(passwdp); 18297c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 18307c478bd9Sstevel@tonic-gate } 18317c478bd9Sstevel@tonic-gate pam_entry->function_ptr = passwdp; 18327c478bd9Sstevel@tonic-gate break; 18337c478bd9Sstevel@tonic-gate default: 18347c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 18357c478bd9Sstevel@tonic-gate "load_modules[%d:%s](%p, %s): unsupported type %d", 18367c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), 18377c478bd9Sstevel@tonic-gate (void *)pamh, function_name, type); 18387c478bd9Sstevel@tonic-gate break; 18397c478bd9Sstevel@tonic-gate } 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate pam_entry = pam_entry->next; 18427c478bd9Sstevel@tonic-gate } /* while */ 18437c478bd9Sstevel@tonic-gate 18447c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_MODULE, "load_modules[%d:%s](%p, %s)=done", 18457c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), (void *)pamh, 18467c478bd9Sstevel@tonic-gate function_name); 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate /* 18527c478bd9Sstevel@tonic-gate * open_module - Open the module first checking for 18537c478bd9Sstevel@tonic-gate * propers modes and ownerships on the file. 18547c478bd9Sstevel@tonic-gate */ 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate static void * 18577c478bd9Sstevel@tonic-gate open_module(pam_handle_t *pamh, char *module_so) 18587c478bd9Sstevel@tonic-gate { 18597c478bd9Sstevel@tonic-gate struct stat64 stb; 18607c478bd9Sstevel@tonic-gate char *errmsg; 18617c478bd9Sstevel@tonic-gate void *lfd; 18627c478bd9Sstevel@tonic-gate fd_list *module_fds = 0; 18637c478bd9Sstevel@tonic-gate fd_list *trail = 0; 18647c478bd9Sstevel@tonic-gate fd_list *traverse = 0; 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate /* Check the ownership and file modes */ 18677c478bd9Sstevel@tonic-gate if (stat64(module_so, &stb) < 0) { 18687c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 18697c478bd9Sstevel@tonic-gate "open_module[%d:%s]: stat(%s) failed: %s", 18707c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), module_so, 18717c478bd9Sstevel@tonic-gate strerror(errno)); 18727c478bd9Sstevel@tonic-gate return (NULL); 18737c478bd9Sstevel@tonic-gate } 18747c478bd9Sstevel@tonic-gate if (stb.st_uid != (uid_t)0) { 18757c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 18767c478bd9Sstevel@tonic-gate "open_module[%d:%s]: Owner of the module %s is not root", 18777c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), module_so); 18787c478bd9Sstevel@tonic-gate return (NULL); 18797c478bd9Sstevel@tonic-gate } 18807c478bd9Sstevel@tonic-gate if (stb.st_mode & S_IWGRP) { 18817c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 18827c478bd9Sstevel@tonic-gate "open_module[%d:%s]: module %s writable by group", 18837c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), module_so); 18847c478bd9Sstevel@tonic-gate return (NULL); 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate if (stb.st_mode & S_IWOTH) { 18877c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 18887c478bd9Sstevel@tonic-gate "open_module[%d:%s]: module %s writable by world", 18897c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), module_so); 18907c478bd9Sstevel@tonic-gate return (NULL); 18917c478bd9Sstevel@tonic-gate } 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate /* 18947c478bd9Sstevel@tonic-gate * Perform the dlopen() 18957c478bd9Sstevel@tonic-gate */ 18967c478bd9Sstevel@tonic-gate lfd = (void *)dlopen(module_so, RTLD_LAZY); 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate if (lfd == NULL) { 18997c478bd9Sstevel@tonic-gate errmsg = dlerror(); 19007c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "open_module[%d:%s]: %s " 19017c478bd9Sstevel@tonic-gate "failed: %s", pamh->include_depth, pam_trace_cname(pamh), 19027c478bd9Sstevel@tonic-gate module_so, errmsg != NULL ? errmsg : "Unknown error"); 19037c478bd9Sstevel@tonic-gate return (NULL); 19047c478bd9Sstevel@tonic-gate } else { 19057c478bd9Sstevel@tonic-gate /* add this fd to the pam handle */ 19067c478bd9Sstevel@tonic-gate if ((module_fds = (fd_list *)calloc(1, sizeof (fd_list))) 19077c478bd9Sstevel@tonic-gate == 0) { 19087c478bd9Sstevel@tonic-gate (void) dlclose(lfd); 19097c478bd9Sstevel@tonic-gate lfd = 0; 19107c478bd9Sstevel@tonic-gate return (NULL); 19117c478bd9Sstevel@tonic-gate } 19127c478bd9Sstevel@tonic-gate module_fds->mh = lfd; 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate if (pamh->fd == 0) { 19157c478bd9Sstevel@tonic-gate /* adding new head of list */ 19167c478bd9Sstevel@tonic-gate pamh->fd = module_fds; 19177c478bd9Sstevel@tonic-gate } else { 19187c478bd9Sstevel@tonic-gate /* appending to end of list */ 19197c478bd9Sstevel@tonic-gate traverse = pamh->fd; 19207c478bd9Sstevel@tonic-gate while (traverse) { 19217c478bd9Sstevel@tonic-gate trail = traverse; 19227c478bd9Sstevel@tonic-gate traverse = traverse->next; 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate trail->next = module_fds; 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate return (lfd); 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate /* 19327c478bd9Sstevel@tonic-gate * load_function - call dlsym() to resolve the function address 19337c478bd9Sstevel@tonic-gate */ 19347c478bd9Sstevel@tonic-gate static int 19357c478bd9Sstevel@tonic-gate load_function(void *lfd, char *name, int (**func)()) 19367c478bd9Sstevel@tonic-gate { 19377c478bd9Sstevel@tonic-gate char *errmsg = NULL; 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate if (lfd == NULL) 19407c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate *func = (int (*)())dlsym(lfd, name); 19437c478bd9Sstevel@tonic-gate if (*func == NULL) { 19447c478bd9Sstevel@tonic-gate errmsg = dlerror(); 19457c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "dlsym failed %s: error %s", 19467c478bd9Sstevel@tonic-gate name, errmsg != NULL ? errmsg : "Unknown error"); 19477c478bd9Sstevel@tonic-gate return (PAM_SYMBOL_ERR); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_DEFAULT, 19517c478bd9Sstevel@tonic-gate "load_function: successful load of %s", name); 19527c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate /* 19567c478bd9Sstevel@tonic-gate * Routines to read the pam.conf configuration file 19577c478bd9Sstevel@tonic-gate */ 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate /* 19607c478bd9Sstevel@tonic-gate * open_pam_conf - open the pam.conf config file 19617c478bd9Sstevel@tonic-gate */ 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate static int 19647c478bd9Sstevel@tonic-gate open_pam_conf(struct pam_fh **pam_fh, pam_handle_t *pamh, char *config) 19657c478bd9Sstevel@tonic-gate { 19667c478bd9Sstevel@tonic-gate struct stat64 stb; 19677c478bd9Sstevel@tonic-gate int fd; 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate if ((fd = open(config, O_RDONLY)) == -1) { 19707c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 19717c478bd9Sstevel@tonic-gate "open_pam_conf[%d:%s]: open(%s) failed: %s", 19727c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), config, 19737c478bd9Sstevel@tonic-gate strerror(errno)); 19747c478bd9Sstevel@tonic-gate return (0); 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate /* Check the ownership and file modes */ 19777c478bd9Sstevel@tonic-gate if (fstat64(fd, &stb) < 0) { 19787c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 19797c478bd9Sstevel@tonic-gate "open_pam_conf[%d:%s]: stat(%s) failed: %s", 19807c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), config, 19817c478bd9Sstevel@tonic-gate strerror(errno)); 19827c478bd9Sstevel@tonic-gate (void) close(fd); 19837c478bd9Sstevel@tonic-gate return (0); 19847c478bd9Sstevel@tonic-gate } 19857c478bd9Sstevel@tonic-gate if (stb.st_uid != (uid_t)0) { 19867c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 19877c478bd9Sstevel@tonic-gate "open_pam_conf[%d:%s]: Owner of %s is not root", 19887c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), config); 19897c478bd9Sstevel@tonic-gate (void) close(fd); 19907c478bd9Sstevel@tonic-gate return (0); 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate if (stb.st_mode & S_IWGRP) { 19937c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 19947c478bd9Sstevel@tonic-gate "open_pam_conf[%d:%s]: %s writable by group", 19957c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), config); 19967c478bd9Sstevel@tonic-gate (void) close(fd); 19977c478bd9Sstevel@tonic-gate return (0); 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate if (stb.st_mode & S_IWOTH) { 20007c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ALERT, 20017c478bd9Sstevel@tonic-gate "open_pam_conf[%d:%s]: %s writable by world", 20027c478bd9Sstevel@tonic-gate pamh->include_depth, pam_trace_cname(pamh), config); 20037c478bd9Sstevel@tonic-gate (void) close(fd); 20047c478bd9Sstevel@tonic-gate return (0); 20057c478bd9Sstevel@tonic-gate } 20067c478bd9Sstevel@tonic-gate if ((*pam_fh = calloc(1, sizeof (struct pam_fh))) == NULL) { 20077c478bd9Sstevel@tonic-gate (void) close(fd); 20087c478bd9Sstevel@tonic-gate return (0); 20097c478bd9Sstevel@tonic-gate } 20107c478bd9Sstevel@tonic-gate (*pam_fh)->fconfig = fd; 20117c478bd9Sstevel@tonic-gate (*pam_fh)->bufsize = (size_t)stb.st_size; 20127c478bd9Sstevel@tonic-gate if (((*pam_fh)->data = mmap(0, (*pam_fh)->bufsize, PROT_READ, 20137c478bd9Sstevel@tonic-gate MAP_PRIVATE, (*pam_fh)->fconfig, 0)) == MAP_FAILED) { 20147c478bd9Sstevel@tonic-gate (void) close(fd); 20157c478bd9Sstevel@tonic-gate free (*pam_fh); 20167c478bd9Sstevel@tonic-gate return (0); 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate (*pam_fh)->bufferp = (*pam_fh)->data; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate return (1); 20217c478bd9Sstevel@tonic-gate } 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate /* 20247c478bd9Sstevel@tonic-gate * close_pam_conf - close pam.conf 20257c478bd9Sstevel@tonic-gate */ 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate static void 20287c478bd9Sstevel@tonic-gate close_pam_conf(struct pam_fh *pam_fh) 20297c478bd9Sstevel@tonic-gate { 20307c478bd9Sstevel@tonic-gate (void) munmap(pam_fh->data, pam_fh->bufsize); 20317c478bd9Sstevel@tonic-gate (void) close(pam_fh->fconfig); 20327c478bd9Sstevel@tonic-gate free(pam_fh); 20337c478bd9Sstevel@tonic-gate } 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate /* 20367c478bd9Sstevel@tonic-gate * read_pam_conf - read in each entry in pam.conf and store info 20377c478bd9Sstevel@tonic-gate * under the pam handle. 20387c478bd9Sstevel@tonic-gate */ 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate static int 20417c478bd9Sstevel@tonic-gate read_pam_conf(pam_handle_t *pamh, char *config) 20427c478bd9Sstevel@tonic-gate { 20437c478bd9Sstevel@tonic-gate struct pam_fh *pam_fh; 20447c478bd9Sstevel@tonic-gate pamtab_t *pamentp; 20457c478bd9Sstevel@tonic-gate pamtab_t *tpament; 20467c478bd9Sstevel@tonic-gate char *service; 20477c478bd9Sstevel@tonic-gate int error; 20487c478bd9Sstevel@tonic-gate int i = pamh->include_depth; /* include depth */ 20497c478bd9Sstevel@tonic-gate /* 20507c478bd9Sstevel@tonic-gate * service types: 20517c478bd9Sstevel@tonic-gate * error (-1), "auth" (0), "account" (1), "session" (2), "password" (3) 20527c478bd9Sstevel@tonic-gate */ 20537c478bd9Sstevel@tonic-gate int service_found[PAM_NUM_MODULE_TYPES+1] = {0, 0, 0, 0, 0}; 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_SERVICE, (void **)&service); 20567c478bd9Sstevel@tonic-gate if (service == NULL || *service == '\0') { 20577c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "No service name"); 20587c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate pamh->pam_conf_name[i] = strdup(config); 20627c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, "read_pam_conf[%d:%s](%p) open(%s)", 20637c478bd9Sstevel@tonic-gate i, pam_trace_cname(pamh), (void *)pamh, config); 20644ef27277Sgww if (open_pam_conf(&pam_fh, pamh, config) == 0) { 20657c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 20664ef27277Sgww } 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate while ((error = 20697c478bd9Sstevel@tonic-gate get_pam_conf_entry(pam_fh, pamh, &pamentp)) == PAM_SUCCESS && 20707c478bd9Sstevel@tonic-gate pamentp) { 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate /* See if entry is this service and valid */ 20737c478bd9Sstevel@tonic-gate if (verify_pam_conf(pamentp, service)) { 20747c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 20757c478bd9Sstevel@tonic-gate "read_pam_conf[%d:%s](%p): bad entry error %s", 20767c478bd9Sstevel@tonic-gate i, pam_trace_cname(pamh), (void *)pamh, service); 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate error = PAM_SYSTEM_ERR; 20797c478bd9Sstevel@tonic-gate free_pamconf(pamentp); 20807c478bd9Sstevel@tonic-gate goto out; 20817c478bd9Sstevel@tonic-gate } 20827c478bd9Sstevel@tonic-gate if (strcasecmp(pamentp->pam_service, service) == 0) { 20837c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 20847c478bd9Sstevel@tonic-gate "read_pam_conf[%d:%s](%p): processing %s", 20857c478bd9Sstevel@tonic-gate i, pam_trace_cname(pamh), (void *)pamh, service); 20867c478bd9Sstevel@tonic-gate /* process first service entry */ 20877c478bd9Sstevel@tonic-gate if (service_found[pamentp->pam_type + 1] == 0) { 20887c478bd9Sstevel@tonic-gate /* purge "other" entries */ 20897c478bd9Sstevel@tonic-gate while ((tpament = pamh->pam_conf_info[i] 20907c478bd9Sstevel@tonic-gate [pamentp->pam_type]) != NULL) { 20917c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 20927c478bd9Sstevel@tonic-gate "read_pam_conf(%p): purging " 20937c478bd9Sstevel@tonic-gate "\"other\"[%d:%s][%s]", 20947c478bd9Sstevel@tonic-gate (void *)pamh, i, 20957c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 20967c478bd9Sstevel@tonic-gate pam_snames[pamentp->pam_type]); 20977c478bd9Sstevel@tonic-gate pamh->pam_conf_info[i] 20987c478bd9Sstevel@tonic-gate [pamentp->pam_type] = tpament->next; 20997c478bd9Sstevel@tonic-gate free_pamconf(tpament); 21007c478bd9Sstevel@tonic-gate } 21017c478bd9Sstevel@tonic-gate /* add first service entry */ 21027c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 21037c478bd9Sstevel@tonic-gate "read_pam_conf(%p): adding 1st " 21047c478bd9Sstevel@tonic-gate "%s[%d:%s][%s]", 21057c478bd9Sstevel@tonic-gate (void *)pamh, service, i, 21067c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 21077c478bd9Sstevel@tonic-gate pam_snames[pamentp->pam_type]); 21087c478bd9Sstevel@tonic-gate pamh->pam_conf_info[i][pamentp->pam_type] = 21097c478bd9Sstevel@tonic-gate pamentp; 21107c478bd9Sstevel@tonic-gate service_found[pamentp->pam_type + 1] = 1; 21117c478bd9Sstevel@tonic-gate } else { 21127c478bd9Sstevel@tonic-gate /* append more service entries */ 21137c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 21147c478bd9Sstevel@tonic-gate "read_pam_conf(%p): adding more " 21157c478bd9Sstevel@tonic-gate "%s[%d:%s][%s]", 21167c478bd9Sstevel@tonic-gate (void *)pamh, service, i, 21177c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 21187c478bd9Sstevel@tonic-gate pam_snames[pamentp->pam_type]); 21197c478bd9Sstevel@tonic-gate tpament = 21207c478bd9Sstevel@tonic-gate pamh->pam_conf_info[i][pamentp->pam_type]; 21217c478bd9Sstevel@tonic-gate while (tpament->next != NULL) { 21227c478bd9Sstevel@tonic-gate tpament = tpament->next; 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate tpament->next = pamentp; 21257c478bd9Sstevel@tonic-gate } 21267c478bd9Sstevel@tonic-gate } else if (service_found[pamentp->pam_type + 1] == 0) { 21277c478bd9Sstevel@tonic-gate /* See if "other" entry available and valid */ 21287c478bd9Sstevel@tonic-gate if (verify_pam_conf(pamentp, "other")) { 21297c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 21307c478bd9Sstevel@tonic-gate "read_pam_conf(%p): bad entry error %s " 21317c478bd9Sstevel@tonic-gate "\"other\"[%d:%s]", 21327c478bd9Sstevel@tonic-gate (void *)pamh, service, i, 21337c478bd9Sstevel@tonic-gate pam_trace_cname(pamh)); 21347c478bd9Sstevel@tonic-gate error = PAM_SYSTEM_ERR; 21357c478bd9Sstevel@tonic-gate free_pamconf(pamentp); 21367c478bd9Sstevel@tonic-gate goto out; 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate if (strcasecmp(pamentp->pam_service, "other") == 0) { 21397c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 21407c478bd9Sstevel@tonic-gate "read_pam_conf(%p): processing " 21417c478bd9Sstevel@tonic-gate "\"other\"[%d:%s]", (void *)pamh, i, 21427c478bd9Sstevel@tonic-gate pam_trace_cname(pamh)); 21437c478bd9Sstevel@tonic-gate if ((tpament = pamh->pam_conf_info[i] 21447c478bd9Sstevel@tonic-gate [pamentp->pam_type]) == NULL) { 21457c478bd9Sstevel@tonic-gate /* add first "other" entry */ 21467c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 21477c478bd9Sstevel@tonic-gate "read_pam_conf(%p): adding 1st " 21487c478bd9Sstevel@tonic-gate "other[%d:%s][%s]", (void *)pamh, i, 21497c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 21507c478bd9Sstevel@tonic-gate pam_snames[pamentp->pam_type]); 21517c478bd9Sstevel@tonic-gate pamh->pam_conf_info[i] 21527c478bd9Sstevel@tonic-gate [pamentp->pam_type] = pamentp; 21537c478bd9Sstevel@tonic-gate } else { 21547c478bd9Sstevel@tonic-gate /* append more "other" entries */ 21557c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 21567c478bd9Sstevel@tonic-gate "read_pam_conf(%p): adding more " 21577c478bd9Sstevel@tonic-gate "other[%d:%s][%s]", (void *)pamh, i, 21587c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), 21597c478bd9Sstevel@tonic-gate pam_snames[pamentp->pam_type]); 21607c478bd9Sstevel@tonic-gate while (tpament->next != NULL) { 21617c478bd9Sstevel@tonic-gate tpament = tpament->next; 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate tpament->next = pamentp; 21647c478bd9Sstevel@tonic-gate } 21657c478bd9Sstevel@tonic-gate } else { 21667c478bd9Sstevel@tonic-gate /* irrelevent entry */ 21677c478bd9Sstevel@tonic-gate free_pamconf(pamentp); 21687c478bd9Sstevel@tonic-gate } 21697c478bd9Sstevel@tonic-gate } else { 21707c478bd9Sstevel@tonic-gate /* irrelevent entry */ 21717c478bd9Sstevel@tonic-gate free_pamconf(pamentp); 21727c478bd9Sstevel@tonic-gate } 21737c478bd9Sstevel@tonic-gate } 21747c478bd9Sstevel@tonic-gate out: 21757c478bd9Sstevel@tonic-gate (void) close_pam_conf(pam_fh); 21767c478bd9Sstevel@tonic-gate if (error != PAM_SUCCESS) 21777c478bd9Sstevel@tonic-gate free_pam_conf_info(pamh); 21787c478bd9Sstevel@tonic-gate return (error); 21797c478bd9Sstevel@tonic-gate } 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate /* 21827c478bd9Sstevel@tonic-gate * get_pam_conf_entry - get a pam.conf entry 21837c478bd9Sstevel@tonic-gate */ 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate static int 21867c478bd9Sstevel@tonic-gate get_pam_conf_entry(struct pam_fh *pam_fh, pam_handle_t *pamh, pamtab_t **pam) 21877c478bd9Sstevel@tonic-gate { 21887c478bd9Sstevel@tonic-gate char *cp, *arg; 21897c478bd9Sstevel@tonic-gate int argc; 21907c478bd9Sstevel@tonic-gate char *tmp, *tmp_free; 21917c478bd9Sstevel@tonic-gate int i; 21927c478bd9Sstevel@tonic-gate char *current_line = NULL; 21937c478bd9Sstevel@tonic-gate int error = PAM_SYSTEM_ERR; /* preset to error */ 21944ef27277Sgww int err; 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate /* get the next line from pam.conf */ 21974ef27277Sgww if ((cp = nextline(pam_fh, pamh, &err)) == NULL) { 21987c478bd9Sstevel@tonic-gate /* no more lines in pam.conf ==> return */ 21997c478bd9Sstevel@tonic-gate error = PAM_SUCCESS; 22007c478bd9Sstevel@tonic-gate *pam = NULL; 22017c478bd9Sstevel@tonic-gate goto out; 22027c478bd9Sstevel@tonic-gate } 22037c478bd9Sstevel@tonic-gate 22047c478bd9Sstevel@tonic-gate if ((*pam = (pamtab_t *)calloc(1, sizeof (pamtab_t))) == NULL) { 22057c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory"); 22067c478bd9Sstevel@tonic-gate goto out; 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate /* copy full line for error reporting */ 22107c478bd9Sstevel@tonic-gate if ((current_line = strdup(cp)) == NULL) { 22117c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory"); 22127c478bd9Sstevel@tonic-gate goto out; 22137c478bd9Sstevel@tonic-gate } 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONF, 22167c478bd9Sstevel@tonic-gate "pam.conf[%s] entry:\t%s", pam_trace_cname(pamh), current_line); 22177c478bd9Sstevel@tonic-gate 22187c478bd9Sstevel@tonic-gate /* get service name (e.g. login, su, passwd) */ 22197c478bd9Sstevel@tonic-gate if ((arg = read_next_token(&cp)) == 0) { 22207c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22217c478bd9Sstevel@tonic-gate "illegal pam.conf[%s] entry: %s: missing SERVICE NAME", 22227c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), current_line); 22237c478bd9Sstevel@tonic-gate goto out; 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate if (((*pam)->pam_service = strdup(arg)) == 0) { 22267c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory"); 22277c478bd9Sstevel@tonic-gate goto out; 22287c478bd9Sstevel@tonic-gate } 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate /* get module type (e.g. authentication, acct mgmt) */ 22317c478bd9Sstevel@tonic-gate if ((arg = read_next_token(&cp)) == 0) { 22327c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22337c478bd9Sstevel@tonic-gate "illegal pam.conf[%s] entry: %s: missing MODULE TYPE", 22347c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), current_line); 22357c478bd9Sstevel@tonic-gate (*pam)->pam_type = -1; /* 0 is a valid value */ 22367c478bd9Sstevel@tonic-gate goto getflag; 22377c478bd9Sstevel@tonic-gate } 22387c478bd9Sstevel@tonic-gate if (strcasecmp(arg, PAM_AUTH_NAME) == 0) { 22397c478bd9Sstevel@tonic-gate (*pam)->pam_type = PAM_AUTH_MODULE; 22407c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_ACCOUNT_NAME) == 0) { 22417c478bd9Sstevel@tonic-gate (*pam)->pam_type = PAM_ACCOUNT_MODULE; 22427c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_SESSION_NAME) == 0) { 22437c478bd9Sstevel@tonic-gate (*pam)->pam_type = PAM_SESSION_MODULE; 22447c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_PASSWORD_NAME) == 0) { 22457c478bd9Sstevel@tonic-gate (*pam)->pam_type = PAM_PASSWORD_MODULE; 22467c478bd9Sstevel@tonic-gate } else { 22477c478bd9Sstevel@tonic-gate /* error */ 22487c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22497c478bd9Sstevel@tonic-gate "illegal pam.conf[%s] entry: %s: invalid module " 22507c478bd9Sstevel@tonic-gate "type: %s", pam_trace_cname(pamh), current_line, arg); 22517c478bd9Sstevel@tonic-gate (*pam)->pam_type = -1; /* 0 is a valid value */ 22527c478bd9Sstevel@tonic-gate } 22537c478bd9Sstevel@tonic-gate 22547c478bd9Sstevel@tonic-gate getflag: 22557c478bd9Sstevel@tonic-gate /* get pam flag (e.g., requisite, required, sufficient, optional) */ 22567c478bd9Sstevel@tonic-gate if ((arg = read_next_token(&cp)) == 0) { 22577c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22587c478bd9Sstevel@tonic-gate "illegal pam.conf[%s] entry: %s: missing CONTROL FLAG", 22597c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), current_line); 22607c478bd9Sstevel@tonic-gate goto getpath; 22617c478bd9Sstevel@tonic-gate } 22627c478bd9Sstevel@tonic-gate if (strcasecmp(arg, PAM_BINDING_NAME) == 0) { 22637c478bd9Sstevel@tonic-gate (*pam)->pam_flag = PAM_BINDING; 22647c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_INCLUDE_NAME) == 0) { 22657c478bd9Sstevel@tonic-gate (*pam)->pam_flag = PAM_INCLUDE; 22667c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_OPTIONAL_NAME) == 0) { 22677c478bd9Sstevel@tonic-gate (*pam)->pam_flag = PAM_OPTIONAL; 22687c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_REQUIRED_NAME) == 0) { 22697c478bd9Sstevel@tonic-gate (*pam)->pam_flag = PAM_REQUIRED; 22707c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_REQUISITE_NAME) == 0) { 22717c478bd9Sstevel@tonic-gate (*pam)->pam_flag = PAM_REQUISITE; 22727c478bd9Sstevel@tonic-gate } else if (strcasecmp(arg, PAM_SUFFICIENT_NAME) == 0) { 22737c478bd9Sstevel@tonic-gate (*pam)->pam_flag = PAM_SUFFICIENT; 22747c478bd9Sstevel@tonic-gate } else { 22757c478bd9Sstevel@tonic-gate /* error */ 22767c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22777c478bd9Sstevel@tonic-gate "illegal pam.conf[%s] entry: %s", 22787c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), current_line); 22797c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22807c478bd9Sstevel@tonic-gate "\tinvalid control flag: %s", arg); 22817c478bd9Sstevel@tonic-gate } 22827c478bd9Sstevel@tonic-gate 22837c478bd9Sstevel@tonic-gate getpath: 22847c478bd9Sstevel@tonic-gate /* get module path (e.g. /usr/lib/security/pam_unix_auth.so.1) */ 22857c478bd9Sstevel@tonic-gate if ((arg = read_next_token(&cp)) == 0) { 22867c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_CRIT, 22877c478bd9Sstevel@tonic-gate "illegal pam.conf[%s] entry: %s: missing MODULE PATH", 22887c478bd9Sstevel@tonic-gate pam_trace_cname(pamh), current_line); 22897c478bd9Sstevel@tonic-gate error = PAM_SUCCESS; /* success */ 22907c478bd9Sstevel@tonic-gate goto out; 22917c478bd9Sstevel@tonic-gate } 22927c478bd9Sstevel@tonic-gate if (arg[0] != '/') { 22937c478bd9Sstevel@tonic-gate size_t len; 22947c478bd9Sstevel@tonic-gate /* 22957c478bd9Sstevel@tonic-gate * If module path does not start with "/", then 22967c478bd9Sstevel@tonic-gate * prepend PAM_LIB_DIR (/usr/lib/security/). 22977c478bd9Sstevel@tonic-gate */ 22987c478bd9Sstevel@tonic-gate /* sizeof (PAM_LIB_DIR) has room for '\0' */ 22997c478bd9Sstevel@tonic-gate len = sizeof (PAM_LIB_DIR) + sizeof (PAM_ISA_DIR) + strlen(arg); 23007c478bd9Sstevel@tonic-gate if (((*pam)->module_path = malloc(len)) == NULL) { 23017c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory"); 23027c478bd9Sstevel@tonic-gate goto out; 23037c478bd9Sstevel@tonic-gate } 23047c478bd9Sstevel@tonic-gate if ((*pam)->pam_flag & PAM_INCLUDE) { 23057c478bd9Sstevel@tonic-gate (void) snprintf((*pam)->module_path, len, "%s%s", 23067c478bd9Sstevel@tonic-gate PAM_LIB_DIR, arg); 23077c478bd9Sstevel@tonic-gate } else { 23087c478bd9Sstevel@tonic-gate (void) snprintf((*pam)->module_path, len, "%s%s%s", 23097c478bd9Sstevel@tonic-gate PAM_LIB_DIR, PAM_ISA_DIR, arg); 23107c478bd9Sstevel@tonic-gate } 23117c478bd9Sstevel@tonic-gate } else { 23127c478bd9Sstevel@tonic-gate /* Full path provided for module */ 23137c478bd9Sstevel@tonic-gate char *isa; 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate /* Check for Instruction Set Architecture indicator */ 23167c478bd9Sstevel@tonic-gate if ((isa = strstr(arg, PAM_ISA)) != NULL) { 23177c478bd9Sstevel@tonic-gate size_t len; 23187c478bd9Sstevel@tonic-gate len = strlen(arg) - (sizeof (PAM_ISA)-1) + 23197c478bd9Sstevel@tonic-gate sizeof (PAM_ISA_DIR); 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate /* substitute the architecture dependent path */ 23227c478bd9Sstevel@tonic-gate if (((*pam)->module_path = malloc(len)) == NULL) { 23237c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 23247c478bd9Sstevel@tonic-gate "strdup: out of memory"); 23257c478bd9Sstevel@tonic-gate goto out; 23267c478bd9Sstevel@tonic-gate } 23277c478bd9Sstevel@tonic-gate *isa = '\000'; 23287c478bd9Sstevel@tonic-gate isa += strlen(PAM_ISA); 23297c478bd9Sstevel@tonic-gate (void) snprintf((*pam)->module_path, len, "%s%s%s", 23307c478bd9Sstevel@tonic-gate arg, PAM_ISA_DIR, isa); 23317c478bd9Sstevel@tonic-gate } else if (((*pam)->module_path = strdup(arg)) == 0) { 23327c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory"); 23337c478bd9Sstevel@tonic-gate goto out; 23347c478bd9Sstevel@tonic-gate } 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate 23377c478bd9Sstevel@tonic-gate /* count the number of module-specific options first */ 23387c478bd9Sstevel@tonic-gate argc = 0; 23397c478bd9Sstevel@tonic-gate if ((tmp = strdup(cp)) == NULL) { 23407c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup: out of memory"); 23417c478bd9Sstevel@tonic-gate goto out; 23427c478bd9Sstevel@tonic-gate } 23437c478bd9Sstevel@tonic-gate tmp_free = tmp; 23447c478bd9Sstevel@tonic-gate for (arg = read_next_token(&tmp); arg; arg = read_next_token(&tmp)) 23457c478bd9Sstevel@tonic-gate argc++; 23467c478bd9Sstevel@tonic-gate free(tmp_free); 23477c478bd9Sstevel@tonic-gate 23487c478bd9Sstevel@tonic-gate /* allocate array for the module-specific options */ 23497c478bd9Sstevel@tonic-gate if (argc > 0) { 23507c478bd9Sstevel@tonic-gate if (((*pam)->module_argv = (char **) 23517c478bd9Sstevel@tonic-gate calloc(argc+1, sizeof (char *))) == 0) { 23527c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "calloc: out of memory"); 23537c478bd9Sstevel@tonic-gate goto out; 23547c478bd9Sstevel@tonic-gate } 23557c478bd9Sstevel@tonic-gate i = 0; 23567c478bd9Sstevel@tonic-gate for (arg = read_next_token(&cp); arg; 23577c478bd9Sstevel@tonic-gate arg = read_next_token(&cp)) { 23587c478bd9Sstevel@tonic-gate (*pam)->module_argv[i] = strdup(arg); 23597c478bd9Sstevel@tonic-gate if ((*pam)->module_argv[i] == NULL) { 23607c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, "strdup failed"); 23617c478bd9Sstevel@tonic-gate goto out; 23627c478bd9Sstevel@tonic-gate } 23637c478bd9Sstevel@tonic-gate i++; 23647c478bd9Sstevel@tonic-gate } 23657c478bd9Sstevel@tonic-gate (*pam)->module_argv[argc] = NULL; 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate (*pam)->module_argc = argc; 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate error = PAM_SUCCESS; /* success */ 23704ef27277Sgww (*pam)->pam_err = err; /* was the line truncated */ 23717c478bd9Sstevel@tonic-gate 23727c478bd9Sstevel@tonic-gate out: 23737c478bd9Sstevel@tonic-gate if (current_line) 23747c478bd9Sstevel@tonic-gate free(current_line); 23757c478bd9Sstevel@tonic-gate if (error != PAM_SUCCESS) { 23767c478bd9Sstevel@tonic-gate /* on error free this */ 23777c478bd9Sstevel@tonic-gate if (*pam) 23787c478bd9Sstevel@tonic-gate free_pamconf(*pam); 23797c478bd9Sstevel@tonic-gate } 23807c478bd9Sstevel@tonic-gate return (error); 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate 23837c478bd9Sstevel@tonic-gate 23847c478bd9Sstevel@tonic-gate /* 23857c478bd9Sstevel@tonic-gate * read_next_token - skip tab and space characters and return the next token 23867c478bd9Sstevel@tonic-gate */ 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate static char * 23897c478bd9Sstevel@tonic-gate read_next_token(char **cpp) 23907c478bd9Sstevel@tonic-gate { 23917c478bd9Sstevel@tonic-gate register char *cp = *cpp; 23927c478bd9Sstevel@tonic-gate char *start; 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate if (cp == (char *)0) { 23957c478bd9Sstevel@tonic-gate *cpp = (char *)0; 23967c478bd9Sstevel@tonic-gate return ((char *)0); 23977c478bd9Sstevel@tonic-gate } 23987c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 23997c478bd9Sstevel@tonic-gate cp++; 24007c478bd9Sstevel@tonic-gate if (*cp == '\0') { 24017c478bd9Sstevel@tonic-gate *cpp = (char *)0; 24027c478bd9Sstevel@tonic-gate return ((char *)0); 24037c478bd9Sstevel@tonic-gate } 24047c478bd9Sstevel@tonic-gate start = cp; 24057c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t') 24067c478bd9Sstevel@tonic-gate cp++; 24077c478bd9Sstevel@tonic-gate if (*cp != '\0') 24087c478bd9Sstevel@tonic-gate *cp++ = '\0'; 24097c478bd9Sstevel@tonic-gate *cpp = cp; 24107c478bd9Sstevel@tonic-gate return (start); 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate 24137c478bd9Sstevel@tonic-gate static char * 24147c478bd9Sstevel@tonic-gate pam_conf_strnchr(char *sp, int c, intptr_t count) 24157c478bd9Sstevel@tonic-gate { 24167c478bd9Sstevel@tonic-gate while (count) { 24177c478bd9Sstevel@tonic-gate if (*sp == (char)c) 24187c478bd9Sstevel@tonic-gate return ((char *)sp); 24197c478bd9Sstevel@tonic-gate else { 24207c478bd9Sstevel@tonic-gate sp++; 24217c478bd9Sstevel@tonic-gate count--; 24227c478bd9Sstevel@tonic-gate } 24237c478bd9Sstevel@tonic-gate }; 24247c478bd9Sstevel@tonic-gate return (NULL); 24257c478bd9Sstevel@tonic-gate } 24267c478bd9Sstevel@tonic-gate 24277c478bd9Sstevel@tonic-gate /* 24287c478bd9Sstevel@tonic-gate * nextline - skip all blank lines and comments 24297c478bd9Sstevel@tonic-gate */ 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate static char * 24324ef27277Sgww nextline(struct pam_fh *pam_fh, pam_handle_t *pamh, int *err) 24337c478bd9Sstevel@tonic-gate { 24347c478bd9Sstevel@tonic-gate char *ll; 24357c478bd9Sstevel@tonic-gate int find_a_line = 0; 24367c478bd9Sstevel@tonic-gate char *data = pam_fh->data; 24377c478bd9Sstevel@tonic-gate char *bufferp = pam_fh->bufferp; 24387c478bd9Sstevel@tonic-gate char *bufferendp = &data[pam_fh->bufsize]; 24394ef27277Sgww size_t input_len; 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate /* 24427c478bd9Sstevel@tonic-gate * Skip the blank line, comment line 24437c478bd9Sstevel@tonic-gate */ 24447c478bd9Sstevel@tonic-gate while (!find_a_line) { 24457c478bd9Sstevel@tonic-gate /* if we are at the end of the buffer, there is no next line */ 24467c478bd9Sstevel@tonic-gate if (bufferp == bufferendp) 24477c478bd9Sstevel@tonic-gate return (NULL); 24487c478bd9Sstevel@tonic-gate 24497c478bd9Sstevel@tonic-gate /* skip blank line */ 24507c478bd9Sstevel@tonic-gate while (*bufferp == '\n') { 24517c478bd9Sstevel@tonic-gate /* 24527c478bd9Sstevel@tonic-gate * If we are at the end of the buffer, there is 24537c478bd9Sstevel@tonic-gate * no next line. 24547c478bd9Sstevel@tonic-gate */ 24554ef27277Sgww if (++bufferp == bufferendp) { 24567c478bd9Sstevel@tonic-gate return (NULL); 24574ef27277Sgww } 24587c478bd9Sstevel@tonic-gate /* else we check *bufferp again */ 24597c478bd9Sstevel@tonic-gate } 24607c478bd9Sstevel@tonic-gate 24617c478bd9Sstevel@tonic-gate /* skip comment line */ 24627c478bd9Sstevel@tonic-gate while (*bufferp == '#') { 24637c478bd9Sstevel@tonic-gate if ((ll = pam_conf_strnchr(bufferp, '\n', 24647c478bd9Sstevel@tonic-gate bufferendp - bufferp)) != NULL) { 24657c478bd9Sstevel@tonic-gate bufferp = ll; 24664ef27277Sgww } else { 24674ef27277Sgww /* 24684ef27277Sgww * this comment line the last line. 24694ef27277Sgww * no next line 24704ef27277Sgww */ 24717c478bd9Sstevel@tonic-gate return (NULL); 24724ef27277Sgww } 24737c478bd9Sstevel@tonic-gate 24747c478bd9Sstevel@tonic-gate /* 24757c478bd9Sstevel@tonic-gate * If we are at the end of the buffer, there is 24767c478bd9Sstevel@tonic-gate * no next line. 24777c478bd9Sstevel@tonic-gate */ 24784ef27277Sgww if (bufferp == bufferendp) { 24797c478bd9Sstevel@tonic-gate return (NULL); 24804ef27277Sgww } 24817c478bd9Sstevel@tonic-gate } 24827c478bd9Sstevel@tonic-gate 24834ef27277Sgww if ((*bufferp != '\n') && (*bufferp != '#')) { 24847c478bd9Sstevel@tonic-gate find_a_line = 1; 24854ef27277Sgww } 24867c478bd9Sstevel@tonic-gate } 24877c478bd9Sstevel@tonic-gate 24884ef27277Sgww *err = PAM_SUCCESS; 24897c478bd9Sstevel@tonic-gate /* now we find one line */ 24907c478bd9Sstevel@tonic-gate if ((ll = pam_conf_strnchr(bufferp, '\n', bufferendp - bufferp)) 24914ef27277Sgww != NULL) { 24924ef27277Sgww if ((input_len = ll - bufferp) >= sizeof (pam_fh->line)) { 24934ef27277Sgww __pam_log(LOG_AUTH | LOG_ERR, 24944ef27277Sgww "nextline[%d:%s]: pam.conf line too long %.256s", 24954ef27277Sgww pamh->include_depth, pam_trace_cname(pamh), 24964ef27277Sgww bufferp); 24974ef27277Sgww input_len = sizeof (pam_fh->line) - 1; 24984ef27277Sgww *err = PAM_SERVICE_ERR; 24994ef27277Sgww } 25004ef27277Sgww (void) strncpy(pam_fh->line, bufferp, input_len); 25014ef27277Sgww pam_fh->line[input_len] = '\0'; 25027c478bd9Sstevel@tonic-gate pam_fh->bufferp = ll++; 25037c478bd9Sstevel@tonic-gate } else { 25047c478bd9Sstevel@tonic-gate ll = bufferendp; 25054ef27277Sgww if ((input_len = ll - bufferp) >= sizeof (pam_fh->line)) { 25064ef27277Sgww __pam_log(LOG_AUTH | LOG_ERR, 25074ef27277Sgww "nextline[%d:%s]: pam.conf line too long %.256s", 25084ef27277Sgww pamh->include_depth, pam_trace_cname(pamh), 25094ef27277Sgww bufferp); 25104ef27277Sgww input_len = sizeof (pam_fh->line) - 1; 25114ef27277Sgww *err = PAM_SERVICE_ERR; 25124ef27277Sgww } 25134ef27277Sgww (void) strncpy(pam_fh->line, bufferp, input_len); 25144ef27277Sgww pam_fh->line[input_len] = '\0'; 25157c478bd9Sstevel@tonic-gate pam_fh->bufferp = ll; 25167c478bd9Sstevel@tonic-gate } 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate return (pam_fh->line); 25197c478bd9Sstevel@tonic-gate } 25207c478bd9Sstevel@tonic-gate 25217c478bd9Sstevel@tonic-gate /* 25227c478bd9Sstevel@tonic-gate * verify_pam_conf - verify that the pam_conf entry is filled in. 25237c478bd9Sstevel@tonic-gate * 25244ef27277Sgww * True = Error if there is no service. 25254ef27277Sgww * True = Error if there is a service and it matches the requested service 25264ef27277Sgww * but, the type, flag, line overflow, or path is in error. 25277c478bd9Sstevel@tonic-gate */ 25287c478bd9Sstevel@tonic-gate 25297c478bd9Sstevel@tonic-gate static int 25307c478bd9Sstevel@tonic-gate verify_pam_conf(pamtab_t *pam, char *service) 25317c478bd9Sstevel@tonic-gate { 25327c478bd9Sstevel@tonic-gate return ((pam->pam_service == (char *)NULL) || 25337c478bd9Sstevel@tonic-gate ((strcasecmp(pam->pam_service, service) == 0) && 25347c478bd9Sstevel@tonic-gate ((pam->pam_type == -1) || 25357c478bd9Sstevel@tonic-gate (pam->pam_flag == 0) || 25364ef27277Sgww (pam->pam_err != PAM_SUCCESS) || 25377c478bd9Sstevel@tonic-gate (pam->module_path == (char *)NULL)))); 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate /* 25417c478bd9Sstevel@tonic-gate * Routines to free allocated storage 25427c478bd9Sstevel@tonic-gate */ 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate /* 25457c478bd9Sstevel@tonic-gate * clean_up - free allocated storage in the pam handle 25467c478bd9Sstevel@tonic-gate */ 25477c478bd9Sstevel@tonic-gate 25487c478bd9Sstevel@tonic-gate static void 25497c478bd9Sstevel@tonic-gate clean_up(pam_handle_t *pamh) 25507c478bd9Sstevel@tonic-gate { 25517c478bd9Sstevel@tonic-gate int i; 25527c478bd9Sstevel@tonic-gate pam_repository_t *auth_rep; 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate if (pamh) { 25557c478bd9Sstevel@tonic-gate /* Cleanup Sun proprietary tag information */ 25567c478bd9Sstevel@tonic-gate if (pamh->pam_client_message_version_number) 25577c478bd9Sstevel@tonic-gate free(pamh->pam_client_message_version_number); 25587c478bd9Sstevel@tonic-gate 25597c478bd9Sstevel@tonic-gate while (pamh->include_depth >= 0) { 25607c478bd9Sstevel@tonic-gate free_pam_conf_info(pamh); 25617c478bd9Sstevel@tonic-gate pamh->include_depth--; 25627c478bd9Sstevel@tonic-gate } 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate /* Cleanup PAM_REPOSITORY structure */ 25657c478bd9Sstevel@tonic-gate auth_rep = pamh->ps_item[PAM_REPOSITORY].pi_addr; 25667c478bd9Sstevel@tonic-gate if (auth_rep != NULL) { 25677c478bd9Sstevel@tonic-gate if (auth_rep->type != NULL) 25687c478bd9Sstevel@tonic-gate free(auth_rep->type); 25697c478bd9Sstevel@tonic-gate if (auth_rep->scope != NULL) 25707c478bd9Sstevel@tonic-gate free(auth_rep->scope); 25717c478bd9Sstevel@tonic-gate } 25727c478bd9Sstevel@tonic-gate 25737c478bd9Sstevel@tonic-gate for (i = 0; i < PAM_MAX_ITEMS; i++) { 25747c478bd9Sstevel@tonic-gate if (pamh->ps_item[i].pi_addr != NULL) { 25757c478bd9Sstevel@tonic-gate if (i == PAM_AUTHTOK || i == PAM_OLDAUTHTOK) { 25767c478bd9Sstevel@tonic-gate (void) memset(pamh->ps_item[i].pi_addr, 25777c478bd9Sstevel@tonic-gate 0, pamh->ps_item[i].pi_size); 25787c478bd9Sstevel@tonic-gate } 25797c478bd9Sstevel@tonic-gate free(pamh->ps_item[i].pi_addr); 25807c478bd9Sstevel@tonic-gate } 25817c478bd9Sstevel@tonic-gate } 25827c478bd9Sstevel@tonic-gate free(pamh); 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate } 25857c478bd9Sstevel@tonic-gate 25867c478bd9Sstevel@tonic-gate /* 25877c478bd9Sstevel@tonic-gate * free_pamconf - free memory used to store pam.conf entry 25887c478bd9Sstevel@tonic-gate */ 25897c478bd9Sstevel@tonic-gate 25907c478bd9Sstevel@tonic-gate static void 25917c478bd9Sstevel@tonic-gate free_pamconf(pamtab_t *cp) 25927c478bd9Sstevel@tonic-gate { 25937c478bd9Sstevel@tonic-gate int i; 25947c478bd9Sstevel@tonic-gate 25957c478bd9Sstevel@tonic-gate if (cp) { 25967c478bd9Sstevel@tonic-gate if (cp->pam_service) 25977c478bd9Sstevel@tonic-gate free(cp->pam_service); 25987c478bd9Sstevel@tonic-gate if (cp->module_path) 25997c478bd9Sstevel@tonic-gate free(cp->module_path); 26007c478bd9Sstevel@tonic-gate for (i = 0; i < cp->module_argc; i++) { 26017c478bd9Sstevel@tonic-gate if (cp->module_argv[i]) 26027c478bd9Sstevel@tonic-gate free(cp->module_argv[i]); 26037c478bd9Sstevel@tonic-gate } 26047c478bd9Sstevel@tonic-gate if (cp->module_argc > 0) 26057c478bd9Sstevel@tonic-gate free(cp->module_argv); 26067c478bd9Sstevel@tonic-gate if (cp->function_ptr) 26077c478bd9Sstevel@tonic-gate free(cp->function_ptr); 26087c478bd9Sstevel@tonic-gate 26097c478bd9Sstevel@tonic-gate free(cp); 26107c478bd9Sstevel@tonic-gate } 26117c478bd9Sstevel@tonic-gate } 26127c478bd9Sstevel@tonic-gate 26137c478bd9Sstevel@tonic-gate /* 26147c478bd9Sstevel@tonic-gate * free_pam_conf_info - free memory used to store all pam.conf info 26157c478bd9Sstevel@tonic-gate * under the pam handle 26167c478bd9Sstevel@tonic-gate */ 26177c478bd9Sstevel@tonic-gate 26187c478bd9Sstevel@tonic-gate static void 26197c478bd9Sstevel@tonic-gate free_pam_conf_info(pam_handle_t *pamh) 26207c478bd9Sstevel@tonic-gate { 26217c478bd9Sstevel@tonic-gate pamtab_t *pamentp; 26227c478bd9Sstevel@tonic-gate pamtab_t *pament_trail; 26237c478bd9Sstevel@tonic-gate int i = pamh->include_depth; 26247c478bd9Sstevel@tonic-gate int j; 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate for (j = 0; j < PAM_NUM_MODULE_TYPES; j++) { 26277c478bd9Sstevel@tonic-gate pamentp = pamh->pam_conf_info[i][j]; 26287c478bd9Sstevel@tonic-gate pamh->pam_conf_info[i][j] = NULL; 26297c478bd9Sstevel@tonic-gate pament_trail = pamentp; 26307c478bd9Sstevel@tonic-gate while (pamentp) { 26317c478bd9Sstevel@tonic-gate pamentp = pamentp->next; 26327c478bd9Sstevel@tonic-gate free_pamconf(pament_trail); 26337c478bd9Sstevel@tonic-gate pament_trail = pamentp; 26347c478bd9Sstevel@tonic-gate } 26357c478bd9Sstevel@tonic-gate } 26367c478bd9Sstevel@tonic-gate if (pamh->pam_conf_name[i] != NULL) { 26377c478bd9Sstevel@tonic-gate free(pamh->pam_conf_name[i]); 26387c478bd9Sstevel@tonic-gate pamh->pam_conf_name[i] = NULL; 26397c478bd9Sstevel@tonic-gate } 26407c478bd9Sstevel@tonic-gate } 26417c478bd9Sstevel@tonic-gate 26427c478bd9Sstevel@tonic-gate static void 26437c478bd9Sstevel@tonic-gate free_env(env_list *pam_env) 26447c478bd9Sstevel@tonic-gate { 26457c478bd9Sstevel@tonic-gate if (pam_env) { 26467c478bd9Sstevel@tonic-gate if (pam_env->name) 26477c478bd9Sstevel@tonic-gate free(pam_env->name); 26487c478bd9Sstevel@tonic-gate if (pam_env->value) 26497c478bd9Sstevel@tonic-gate free(pam_env->value); 26507c478bd9Sstevel@tonic-gate free(pam_env); 26517c478bd9Sstevel@tonic-gate } 26527c478bd9Sstevel@tonic-gate } 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate /* 26557c478bd9Sstevel@tonic-gate * Internal convenience functions for Solaris PAM service modules. 26567c478bd9Sstevel@tonic-gate */ 26577c478bd9Sstevel@tonic-gate 26587c478bd9Sstevel@tonic-gate #include <libintl.h> 26597c478bd9Sstevel@tonic-gate #include <nl_types.h> 26607c478bd9Sstevel@tonic-gate #include <synch.h> 26617c478bd9Sstevel@tonic-gate #include <locale.h> 26627c478bd9Sstevel@tonic-gate #include <thread.h> 26637c478bd9Sstevel@tonic-gate 26647c478bd9Sstevel@tonic-gate typedef struct pam_msg_data { 26657c478bd9Sstevel@tonic-gate nl_catd fd; 26667c478bd9Sstevel@tonic-gate } pam_msg_data_t; 26677c478bd9Sstevel@tonic-gate 26687c478bd9Sstevel@tonic-gate /* 26697c478bd9Sstevel@tonic-gate * free_resp(): 26707c478bd9Sstevel@tonic-gate * free storage for responses used in the call back "pam_conv" functions 26717c478bd9Sstevel@tonic-gate */ 26727c478bd9Sstevel@tonic-gate 26737c478bd9Sstevel@tonic-gate void 26747c478bd9Sstevel@tonic-gate free_resp(int num_msg, struct pam_response *resp) 26757c478bd9Sstevel@tonic-gate { 26767c478bd9Sstevel@tonic-gate int i; 26777c478bd9Sstevel@tonic-gate struct pam_response *r; 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate if (resp) { 26807c478bd9Sstevel@tonic-gate r = resp; 26817c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 26827c478bd9Sstevel@tonic-gate if (r->resp) { 26837c478bd9Sstevel@tonic-gate /* clear before freeing -- may be a password */ 26847c478bd9Sstevel@tonic-gate bzero(r->resp, strlen(r->resp)); 26857c478bd9Sstevel@tonic-gate free(r->resp); 26867c478bd9Sstevel@tonic-gate r->resp = NULL; 26877c478bd9Sstevel@tonic-gate } 26887c478bd9Sstevel@tonic-gate } 26897c478bd9Sstevel@tonic-gate free(resp); 26907c478bd9Sstevel@tonic-gate } 26917c478bd9Sstevel@tonic-gate } 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate static int 26947c478bd9Sstevel@tonic-gate do_conv(pam_handle_t *pamh, int msg_style, int num_msg, 26957c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE], void *conv_apdp, 26967c478bd9Sstevel@tonic-gate struct pam_response *ret_respp[]) 26977c478bd9Sstevel@tonic-gate { 26987c478bd9Sstevel@tonic-gate struct pam_message *msg; 26997c478bd9Sstevel@tonic-gate struct pam_message *m; 27007c478bd9Sstevel@tonic-gate int i; 27017c478bd9Sstevel@tonic-gate int k; 27027c478bd9Sstevel@tonic-gate int retcode; 27037c478bd9Sstevel@tonic-gate struct pam_conv *pam_convp; 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate if ((retcode = pam_get_item(pamh, PAM_CONV, 27067c478bd9Sstevel@tonic-gate (void **)&pam_convp)) != PAM_SUCCESS) { 27077c478bd9Sstevel@tonic-gate return (retcode); 27087c478bd9Sstevel@tonic-gate } 27097c478bd9Sstevel@tonic-gate 27107c478bd9Sstevel@tonic-gate /* 27117c478bd9Sstevel@tonic-gate * When pam_set_item() is called to set PAM_CONV and the 27127c478bd9Sstevel@tonic-gate * item is NULL, memset(pip->pi_addr, 0, size) is called. 27137c478bd9Sstevel@tonic-gate * So at this point, we should check whether pam_convp->conv 27147c478bd9Sstevel@tonic-gate * is NULL or not. 27157c478bd9Sstevel@tonic-gate */ 27167c478bd9Sstevel@tonic-gate if ((pam_convp == NULL) || (pam_convp->conv == NULL)) 27177c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 27187c478bd9Sstevel@tonic-gate 27197c478bd9Sstevel@tonic-gate i = 0; 27207c478bd9Sstevel@tonic-gate k = num_msg; 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate msg = (struct pam_message *)calloc(num_msg, 27237c478bd9Sstevel@tonic-gate sizeof (struct pam_message)); 27247c478bd9Sstevel@tonic-gate if (msg == NULL) { 27257c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 27267c478bd9Sstevel@tonic-gate } 27277c478bd9Sstevel@tonic-gate m = msg; 27287c478bd9Sstevel@tonic-gate 27297c478bd9Sstevel@tonic-gate while (k--) { 27307c478bd9Sstevel@tonic-gate /* 27317c478bd9Sstevel@tonic-gate * fill out the message structure to display prompt message 27327c478bd9Sstevel@tonic-gate */ 27337c478bd9Sstevel@tonic-gate m->msg_style = msg_style; 27347c478bd9Sstevel@tonic-gate m->msg = messages[i]; 27357c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONV, 27367c478bd9Sstevel@tonic-gate "pam_conv_msg(%p:%d[%d]=%s)", 27377c478bd9Sstevel@tonic-gate (void *)pamh, msg_style, i, messages[i]); 27387c478bd9Sstevel@tonic-gate m++; 27397c478bd9Sstevel@tonic-gate i++; 27407c478bd9Sstevel@tonic-gate } 27417c478bd9Sstevel@tonic-gate 27427c478bd9Sstevel@tonic-gate /* 27437c478bd9Sstevel@tonic-gate * The UNIX pam modules always calls __pam_get_authtok() and 27447c478bd9Sstevel@tonic-gate * __pam_display_msg() with a NULL pointer as the conv_apdp. 27457c478bd9Sstevel@tonic-gate * In case the conv_apdp is NULL and the pam_convp->appdata_ptr 27467c478bd9Sstevel@tonic-gate * is not NULL, we should pass the pam_convp->appdata_ptr 27477c478bd9Sstevel@tonic-gate * to the conversation function. 27487c478bd9Sstevel@tonic-gate */ 27497c478bd9Sstevel@tonic-gate if (conv_apdp == NULL && pam_convp->appdata_ptr != NULL) 27507c478bd9Sstevel@tonic-gate conv_apdp = pam_convp->appdata_ptr; 27517c478bd9Sstevel@tonic-gate 27527c478bd9Sstevel@tonic-gate /* 27537c478bd9Sstevel@tonic-gate * Call conv function to display the prompt. 27547c478bd9Sstevel@tonic-gate */ 27557c478bd9Sstevel@tonic-gate retcode = (pam_convp->conv)(num_msg, &msg, ret_respp, conv_apdp); 27567c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONV, 27577c478bd9Sstevel@tonic-gate "pam_conv_resp(%p pam_conv = %s) ret_respp = %p", 27587c478bd9Sstevel@tonic-gate (void *)pamh, pam_strerror(pamh, retcode), (void *)ret_respp); 27597c478bd9Sstevel@tonic-gate if (*ret_respp == NULL) { 27607c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONV, 27617c478bd9Sstevel@tonic-gate "pam_conv_resp(%p No response requested)", (void *)pamh); 27627c478bd9Sstevel@tonic-gate } else if ((pam_debug & (PAM_DEBUG_CONV | PAM_DEBUG_AUTHTOK)) != 0) { 27637c478bd9Sstevel@tonic-gate struct pam_response *r = *ret_respp; 27647c478bd9Sstevel@tonic-gate 27657c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 27667c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 27677c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONV, 27687c478bd9Sstevel@tonic-gate "pam_conv_resp(%p:" 27697c478bd9Sstevel@tonic-gate "[%d] NULL response string)", 27707c478bd9Sstevel@tonic-gate (void *)pamh, i); 27717c478bd9Sstevel@tonic-gate } else { 27727c478bd9Sstevel@tonic-gate if (msg_style == PAM_PROMPT_ECHO_OFF) { 27737c478bd9Sstevel@tonic-gate #ifdef DEBUG 27747c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_AUTHTOK, 27757c478bd9Sstevel@tonic-gate "pam_conv_resp(%p:[%d]=%s, " 27767c478bd9Sstevel@tonic-gate "code=%d)", 27777c478bd9Sstevel@tonic-gate (void *)pamh, i, r->resp, 27787c478bd9Sstevel@tonic-gate r->resp_retcode); 27797c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 27807c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONV, 27817c478bd9Sstevel@tonic-gate "pam_conv_resp(%p:[%d] len=%lu, " 27827c478bd9Sstevel@tonic-gate "code=%d)", 27837c478bd9Sstevel@tonic-gate (void *)pamh, i, 27847c478bd9Sstevel@tonic-gate (ulong_t)strlen(r->resp), 27857c478bd9Sstevel@tonic-gate r->resp_retcode); 27867c478bd9Sstevel@tonic-gate } else { 27877c478bd9Sstevel@tonic-gate pam_trace(PAM_DEBUG_CONV, 27887c478bd9Sstevel@tonic-gate "pam_conv_resp(%p:[%d]=%s, " 27897c478bd9Sstevel@tonic-gate "code=%d)", 27907c478bd9Sstevel@tonic-gate (void *)pamh, i, r->resp, 27917c478bd9Sstevel@tonic-gate r->resp_retcode); 27927c478bd9Sstevel@tonic-gate } 27937c478bd9Sstevel@tonic-gate } 27947c478bd9Sstevel@tonic-gate } 27957c478bd9Sstevel@tonic-gate } 27967c478bd9Sstevel@tonic-gate 27977c478bd9Sstevel@tonic-gate if (msg) 27987c478bd9Sstevel@tonic-gate free(msg); 27997c478bd9Sstevel@tonic-gate return (retcode); 28007c478bd9Sstevel@tonic-gate } 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate /* 28037c478bd9Sstevel@tonic-gate * __pam_display_msg(): 28047c478bd9Sstevel@tonic-gate * display message by calling the call back functions 28057c478bd9Sstevel@tonic-gate * provided by the application through "pam_conv" structure 28067c478bd9Sstevel@tonic-gate */ 28077c478bd9Sstevel@tonic-gate 28087c478bd9Sstevel@tonic-gate int 28097c478bd9Sstevel@tonic-gate __pam_display_msg(pam_handle_t *pamh, int msg_style, int num_msg, 28107c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE], void *conv_apdp) 28117c478bd9Sstevel@tonic-gate { 28127c478bd9Sstevel@tonic-gate struct pam_response *ret_respp = NULL; 28137c478bd9Sstevel@tonic-gate 28147c478bd9Sstevel@tonic-gate return (do_conv(pamh, msg_style, num_msg, messages, 28157c478bd9Sstevel@tonic-gate conv_apdp, &ret_respp)); 28167c478bd9Sstevel@tonic-gate } 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate /* 28197c478bd9Sstevel@tonic-gate * __pam_get_authtok() 28207c478bd9Sstevel@tonic-gate * retrieves a password of at most PASS_MAX length from the pam 28217c478bd9Sstevel@tonic-gate * handle (pam_get_item) or from the input stream (do_conv). 28227c478bd9Sstevel@tonic-gate * 28237c478bd9Sstevel@tonic-gate * This function allocates memory for the new authtok. 28247c478bd9Sstevel@tonic-gate * Applications calling this function are responsible for 28257c478bd9Sstevel@tonic-gate * freeing this memory. 28267c478bd9Sstevel@tonic-gate * 28277c478bd9Sstevel@tonic-gate * If "source" is 28287c478bd9Sstevel@tonic-gate * PAM_HANDLE 28297c478bd9Sstevel@tonic-gate * and "type" is: 28307c478bd9Sstevel@tonic-gate * PAM_AUTHTOK - password is taken from pam handle (PAM_AUTHTOK) 28317c478bd9Sstevel@tonic-gate * PAM_OLDAUTHTOK - password is taken from pam handle (PAM_OLDAUTHTOK) 28327c478bd9Sstevel@tonic-gate * 28337c478bd9Sstevel@tonic-gate * If "source" is 28347c478bd9Sstevel@tonic-gate * PAM_PROMPT 28357c478bd9Sstevel@tonic-gate * and "type" is: 28367c478bd9Sstevel@tonic-gate * 0: Prompt for new passwd, do not even attempt 28377c478bd9Sstevel@tonic-gate * to store it in the pam handle. 28387c478bd9Sstevel@tonic-gate * PAM_AUTHTOK: Prompt for new passwd, store in pam handle as 28397c478bd9Sstevel@tonic-gate * PAM_AUTHTOK item if this value is not already set. 28407c478bd9Sstevel@tonic-gate * PAM_OLDAUTHTOK: Prompt for new passwd, store in pam handle as 28417c478bd9Sstevel@tonic-gate * PAM_OLDAUTHTOK item if this value is not 28427c478bd9Sstevel@tonic-gate * already set. 28437c478bd9Sstevel@tonic-gate */ 28447c478bd9Sstevel@tonic-gate int 28457c478bd9Sstevel@tonic-gate __pam_get_authtok(pam_handle_t *pamh, int source, int type, char *prompt, 28467c478bd9Sstevel@tonic-gate char **authtok) 28477c478bd9Sstevel@tonic-gate { 28487c478bd9Sstevel@tonic-gate int error = PAM_SYSTEM_ERR; 28497c478bd9Sstevel@tonic-gate char *new_password = NULL; 28507c478bd9Sstevel@tonic-gate struct pam_response *ret_resp = NULL; 28517c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE]; 28527c478bd9Sstevel@tonic-gate 28537c478bd9Sstevel@tonic-gate if ((*authtok = calloc(PASS_MAX+1, sizeof (char))) == NULL) 28547c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 28557c478bd9Sstevel@tonic-gate 28567c478bd9Sstevel@tonic-gate if (prompt == NULL) 28577c478bd9Sstevel@tonic-gate prompt = dgettext(TEXT_DOMAIN, "password: "); 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate switch (source) { 28607c478bd9Sstevel@tonic-gate case PAM_HANDLE: 28617c478bd9Sstevel@tonic-gate 28627c478bd9Sstevel@tonic-gate /* get password from pam handle item list */ 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate switch (type) { 28657c478bd9Sstevel@tonic-gate case PAM_AUTHTOK: 28667c478bd9Sstevel@tonic-gate case PAM_OLDAUTHTOK: 28677c478bd9Sstevel@tonic-gate 28687c478bd9Sstevel@tonic-gate if ((error = pam_get_item(pamh, type, 28697c478bd9Sstevel@tonic-gate (void **)&new_password)) != PAM_SUCCESS) 28707c478bd9Sstevel@tonic-gate goto err_ret; 28717c478bd9Sstevel@tonic-gate 28727c478bd9Sstevel@tonic-gate if (new_password == NULL || new_password[0] == '\0') { 28737c478bd9Sstevel@tonic-gate free(*authtok); 28747c478bd9Sstevel@tonic-gate *authtok = NULL; 28757c478bd9Sstevel@tonic-gate } else { 28767c478bd9Sstevel@tonic-gate (void) strlcpy(*authtok, new_password, 28777c478bd9Sstevel@tonic-gate PASS_MAX+1); 28787c478bd9Sstevel@tonic-gate } 28797c478bd9Sstevel@tonic-gate break; 28807c478bd9Sstevel@tonic-gate default: 28817c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 28827c478bd9Sstevel@tonic-gate "__pam_get_authtok() invalid type: %d", type); 28837c478bd9Sstevel@tonic-gate error = PAM_SYMBOL_ERR; 28847c478bd9Sstevel@tonic-gate goto err_ret; 28857c478bd9Sstevel@tonic-gate } 28867c478bd9Sstevel@tonic-gate break; 28877c478bd9Sstevel@tonic-gate case PAM_PROMPT: 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate /* 28907c478bd9Sstevel@tonic-gate * Prompt for new password and save in pam handle item list 28917c478bd9Sstevel@tonic-gate * if the that item is not already set. 28927c478bd9Sstevel@tonic-gate */ 28937c478bd9Sstevel@tonic-gate 28947c478bd9Sstevel@tonic-gate (void) strncpy(messages[0], prompt, sizeof (messages[0])); 28957c478bd9Sstevel@tonic-gate if ((error = do_conv(pamh, PAM_PROMPT_ECHO_OFF, 1, messages, 28967c478bd9Sstevel@tonic-gate NULL, &ret_resp)) != PAM_SUCCESS) 28977c478bd9Sstevel@tonic-gate goto err_ret; 28987c478bd9Sstevel@tonic-gate 28997c478bd9Sstevel@tonic-gate if (ret_resp->resp == NULL) { 29007c478bd9Sstevel@tonic-gate /* getpass didn't return anything */ 29017c478bd9Sstevel@tonic-gate error = PAM_SYSTEM_ERR; 29027c478bd9Sstevel@tonic-gate goto err_ret; 29037c478bd9Sstevel@tonic-gate } 29047c478bd9Sstevel@tonic-gate 29057c478bd9Sstevel@tonic-gate /* save the new password if this item was NULL */ 29067c478bd9Sstevel@tonic-gate if (type) { 29077c478bd9Sstevel@tonic-gate if ((error = pam_get_item(pamh, type, 29087c478bd9Sstevel@tonic-gate (void **)&new_password)) != PAM_SUCCESS) { 29097c478bd9Sstevel@tonic-gate free_resp(1, ret_resp); 29107c478bd9Sstevel@tonic-gate goto err_ret; 29117c478bd9Sstevel@tonic-gate } 29127c478bd9Sstevel@tonic-gate if (new_password == NULL) 29137c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, type, ret_resp->resp); 29147c478bd9Sstevel@tonic-gate } 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate (void) strlcpy(*authtok, ret_resp->resp, PASS_MAX+1); 29177c478bd9Sstevel@tonic-gate free_resp(1, ret_resp); 29187c478bd9Sstevel@tonic-gate break; 29197c478bd9Sstevel@tonic-gate default: 29207c478bd9Sstevel@tonic-gate __pam_log(LOG_AUTH | LOG_ERR, 29217c478bd9Sstevel@tonic-gate "__pam_get_authtok() invalid source: %d", source); 29227c478bd9Sstevel@tonic-gate error = PAM_SYMBOL_ERR; 29237c478bd9Sstevel@tonic-gate goto err_ret; 29247c478bd9Sstevel@tonic-gate } 29257c478bd9Sstevel@tonic-gate 29267c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 29277c478bd9Sstevel@tonic-gate 29287c478bd9Sstevel@tonic-gate err_ret: 29297c478bd9Sstevel@tonic-gate bzero(*authtok, PASS_MAX+1); 29307c478bd9Sstevel@tonic-gate free(*authtok); 29317c478bd9Sstevel@tonic-gate *authtok = NULL; 29327c478bd9Sstevel@tonic-gate return (error); 29337c478bd9Sstevel@tonic-gate } 2934