xref: /titanic_53/usr/src/cmd/passwd/passwd.c (revision 49335bdececa5fc091b6c63763f9176524390b5e)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
317c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * passwd is a program whose sole purpose is to manage
377c478bd9Sstevel@tonic-gate  * the password file, map, or table. It allows system administrator
387c478bd9Sstevel@tonic-gate  * to add, change and display password attributes.
397c478bd9Sstevel@tonic-gate  * Non privileged user can change password or display
407c478bd9Sstevel@tonic-gate  * password attributes which corresponds to their login name.
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include <stdio.h>
447c478bd9Sstevel@tonic-gate #include <pwd.h>
457c478bd9Sstevel@tonic-gate #include <sys/types.h>
467c478bd9Sstevel@tonic-gate #include <errno.h>
477c478bd9Sstevel@tonic-gate #include <unistd.h>
487c478bd9Sstevel@tonic-gate #include <stdlib.h>
497c478bd9Sstevel@tonic-gate #include <locale.h>
507c478bd9Sstevel@tonic-gate #include <stdarg.h>
517c478bd9Sstevel@tonic-gate #include <errno.h>
527c478bd9Sstevel@tonic-gate #include <string.h>
537c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
547c478bd9Sstevel@tonic-gate #include <security/pam_modules.h>
557c478bd9Sstevel@tonic-gate #include <security/pam_impl.h>
567c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
577c478bd9Sstevel@tonic-gate #undef GROUP
587c478bd9Sstevel@tonic-gate #include <syslog.h>
597c478bd9Sstevel@tonic-gate #include <userdefs.h>
607c478bd9Sstevel@tonic-gate #include <passwdutil.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #include <deflt.h>
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #undef	GROUP
677c478bd9Sstevel@tonic-gate #include <bsm/adt.h>
687c478bd9Sstevel@tonic-gate #include <bsm/adt_event.h>
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * flags indicate password attributes to be modified
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate #define	LFLAG 0x001		/* lock user's password  */
757c478bd9Sstevel@tonic-gate #define	DFLAG 0x002		/* delete user's  password */
767c478bd9Sstevel@tonic-gate #define	MFLAG 0x004		/* set max field -- # of days passwd is valid */
777c478bd9Sstevel@tonic-gate #define	NFLAG 0x008		/* set min field -- # of days between */
787c478bd9Sstevel@tonic-gate 				/* password changes */
797c478bd9Sstevel@tonic-gate #define	SFLAG 0x010		/* display password attributes */
807c478bd9Sstevel@tonic-gate #define	FFLAG 0x020		/* expire  user's password */
817c478bd9Sstevel@tonic-gate #define	AFLAG 0x040		/* display password attributes for all users */
827c478bd9Sstevel@tonic-gate #define	SAFLAG (SFLAG|AFLAG)	/* display password attributes for all users */
837c478bd9Sstevel@tonic-gate #define	WFLAG 0x100		/* warn user to change passwd */
847c478bd9Sstevel@tonic-gate #define	OFLAG 0x200		/* domain name */
857c478bd9Sstevel@tonic-gate #define	EFLAG 0x400		/* change shell */
867c478bd9Sstevel@tonic-gate #define	GFLAG 0x800		/* change gecos information */
877c478bd9Sstevel@tonic-gate #define	HFLAG 0x1000		/* change home directory */
887c478bd9Sstevel@tonic-gate #define	XFLAG 0x2000		/* no login */
897c478bd9Sstevel@tonic-gate #define	UFLAG 0x4000		/* unlock user's password */
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #define	NONAGEFLAG	(EFLAG | GFLAG | HFLAG)
927c478bd9Sstevel@tonic-gate #define	AGEFLAG	(LFLAG | FFLAG | MFLAG | NFLAG | WFLAG | XFLAG | UFLAG)
937c478bd9Sstevel@tonic-gate #define	MUTEXFLAG	(DFLAG | LFLAG | XFLAG | UFLAG | SAFLAG)
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * exit code
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #define	SUCCESS	0	/* succeeded */
1017c478bd9Sstevel@tonic-gate #define	NOPERM	1	/* No permission */
1027c478bd9Sstevel@tonic-gate #define	BADOPT	2	/* Invalid combination of option */
1037c478bd9Sstevel@tonic-gate #define	FMERR	3	/* File/table manipulation error */
1047c478bd9Sstevel@tonic-gate #define	FATAL	4	/* Old file/table can not be recovered */
1057c478bd9Sstevel@tonic-gate #define	FBUSY	5	/* Lock file/table busy */
1067c478bd9Sstevel@tonic-gate #define	BADSYN	6	/* Incorrect syntax */
1077c478bd9Sstevel@tonic-gate #define	BADAGE	7	/* Aging is disabled  */
1087c478bd9Sstevel@tonic-gate #define	NOMEM	8	/* No memory */
1097c478bd9Sstevel@tonic-gate #define	SYSERR	9	/* System error */
1107c478bd9Sstevel@tonic-gate #define	EXPIRED	10	/* Account expired */
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * define error messages
1147c478bd9Sstevel@tonic-gate  */
1157c478bd9Sstevel@tonic-gate #define	MSG_NP		"Permission denied"
1167c478bd9Sstevel@tonic-gate #define	MSG_BS		"Invalid combination of options"
1177c478bd9Sstevel@tonic-gate #define	MSG_FE		"Unexpected failure. Password file/table unchanged."
1187c478bd9Sstevel@tonic-gate #define	MSG_FF		"Unexpected failure. Password file/table missing."
1197c478bd9Sstevel@tonic-gate #define	MSG_FB		"Password file/table busy. Try again later."
1207c478bd9Sstevel@tonic-gate #define	MSG_NV  	"Invalid argument to option"
1217c478bd9Sstevel@tonic-gate #define	MSG_AD		"Password aging is disabled"
1227c478bd9Sstevel@tonic-gate #define	MSG_RS		"Cannot change from restricted shell %s\n"
1237c478bd9Sstevel@tonic-gate #define	MSG_NM		"Out of memory."
1247c478bd9Sstevel@tonic-gate #define	MSG_UNACCEPT	"%s is unacceptable as a new shell\n"
1257c478bd9Sstevel@tonic-gate #define	MSG_UNAVAIL	"warning: %s is unavailable on this machine\n"
1267c478bd9Sstevel@tonic-gate #define	MSG_COLON	"':' is not allowed.\n"
1277c478bd9Sstevel@tonic-gate #define	MSG_MAXLEN	"Maximum number of characters allowed is %d."
1287c478bd9Sstevel@tonic-gate #define	MSG_CONTROL	"Control characters are not allowed.\n"
1297c478bd9Sstevel@tonic-gate #define	MSG_SHELL_UNCHANGED	"Login shell unchanged.\n"
1307c478bd9Sstevel@tonic-gate #define	MSG_GECOS_UNCHANGED	"Finger information unchanged.\n"
1317c478bd9Sstevel@tonic-gate #define	MSG_DIR_UNCHANGED	"Homedir information unchanged.\n"
1327c478bd9Sstevel@tonic-gate #define	MSG_NAME	"\nName [%s]: "
1337c478bd9Sstevel@tonic-gate #define	MSG_HOMEDIR	"\nHome Directory [%s]: "
1347c478bd9Sstevel@tonic-gate #define	MSG_OLDSHELL	"Old shell: %s\n"
1357c478bd9Sstevel@tonic-gate #define	MSG_NEWSHELL	"New shell: "
1367c478bd9Sstevel@tonic-gate #define	MSG_AGAIN	"\nPlease try again\n"
1377c478bd9Sstevel@tonic-gate #define	MSG_INPUTHDR	"Default values are printed inside of '[]'.\n" \
1387c478bd9Sstevel@tonic-gate 			"To accept the default, type <return>.\n" \
1397c478bd9Sstevel@tonic-gate 			"To have a blank entry, type the word 'none'.\n"
1407c478bd9Sstevel@tonic-gate #define	MSG_UNKNOWN	"%s: User unknown: %s\n"
1417c478bd9Sstevel@tonic-gate #define	MSG_ACCOUNT_EXP	"User account has expired: %s\n"
1427c478bd9Sstevel@tonic-gate #define	MSG_AUTHTOK_EXP	"Your password has been expired for too long.\n" \
1437c478bd9Sstevel@tonic-gate 			"Please contact the system administrator.\n"
1447c478bd9Sstevel@tonic-gate #define	MSG_NIS_HOMEDIR	"-h does not apply to NIS"
1457c478bd9Sstevel@tonic-gate #define	MSG_CUR_PASS	"Enter existing login password: "
1467c478bd9Sstevel@tonic-gate #define	MSG_CUR_PASS_UNAME	"Enter %s's existing login password: "
1477c478bd9Sstevel@tonic-gate #define	MSG_SUCCESS	"%s: password information changed for %s\n"
1487c478bd9Sstevel@tonic-gate #define	MSG_SORRY	"%s: Sorry, wrong passwd\n"
1497c478bd9Sstevel@tonic-gate #define	MSG_INFO	"%s: Changing password for %s\n"
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate  * return code from ckarg() routine
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate #define	FAIL 		-1
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  *  defind password file name
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate #define	PASSWD 			"/etc/passwd"
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate #define	MAX_INPUT_LEN		512
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate #define	DEF_ATTEMPTS	3
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /* Number of characters in that make up an encrypted password (for now) */
1677c478bd9Sstevel@tonic-gate #define	NUMCP			13
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate #ifdef DEBUG
1707c478bd9Sstevel@tonic-gate #define	dprintf1	printf
1717c478bd9Sstevel@tonic-gate #else
1727c478bd9Sstevel@tonic-gate #define	dprintf1(w, x)
1737c478bd9Sstevel@tonic-gate #endif
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate extern int	optind;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate static int		retval = SUCCESS;
1787c478bd9Sstevel@tonic-gate static int		pam_retval = PAM_SUCCESS;
1797c478bd9Sstevel@tonic-gate static uid_t		uid;
1807c478bd9Sstevel@tonic-gate static char		*prognamep;
1817c478bd9Sstevel@tonic-gate static long		maxdate;	/* password aging information */
182*49335bdeSbasabi static int		passwd_conv(int, struct pam_message **,
183*49335bdeSbasabi 			    struct pam_response **, void *);
1847c478bd9Sstevel@tonic-gate static struct pam_conv	pam_conv = {passwd_conv, NULL};
1857c478bd9Sstevel@tonic-gate static pam_handle_t	*pamh;		/* Authentication handle */
1867c478bd9Sstevel@tonic-gate static char		*usrname;	/* user whose attribute we update */
1877c478bd9Sstevel@tonic-gate static adt_session_data_t *ah;  /* audit session handle */
1887c478bd9Sstevel@tonic-gate static adt_event_data_t *event = NULL; /* event to be generated */
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate static pam_repository_t	auth_rep;
1917c478bd9Sstevel@tonic-gate static pwu_repository_t	repository;
1927c478bd9Sstevel@tonic-gate static pwu_repository_t	__REPFILES = { "files", NULL, 0 };
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * Function Declarations
1967c478bd9Sstevel@tonic-gate  */
1977c478bd9Sstevel@tonic-gate extern	nis_name	nis_local_directory(void);
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate extern	void		setusershell(void);
2007c478bd9Sstevel@tonic-gate extern	char		*getusershell(void);
2017c478bd9Sstevel@tonic-gate extern	void		endusershell(void);
2027c478bd9Sstevel@tonic-gate 
203*49335bdeSbasabi static	void		passwd_exit(int retcode) __NORETURN;
2047c478bd9Sstevel@tonic-gate static	void		rusage(void);
2057c478bd9Sstevel@tonic-gate static	int		ckuid(void);
2067c478bd9Sstevel@tonic-gate static	int		ckarg(int argc, char **argv, attrlist **attributes);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate static	int		get_namelist(pwu_repository_t, char ***, int *);
2097c478bd9Sstevel@tonic-gate static	int		get_namelist_files(char ***, int *);
2107c478bd9Sstevel@tonic-gate static	int		get_namelist_nisplus(char ***, int *);
2117c478bd9Sstevel@tonic-gate static	int		get_attr(char *, pwu_repository_t *, attrlist **);
2127c478bd9Sstevel@tonic-gate static	void		display_attr(char *, attrlist *);
2137c478bd9Sstevel@tonic-gate static	void		free_attr(attrlist *);
2147c478bd9Sstevel@tonic-gate static	void		attrlist_add(attrlist **, attrtype, char *);
2157c478bd9Sstevel@tonic-gate static	void		attrlist_reorder(attrlist **);
2167c478bd9Sstevel@tonic-gate static	char		*userinput(char *, pwu_repository_t *, attrtype);
2177c478bd9Sstevel@tonic-gate static	char		*getresponse(char *);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate  * main():
2217c478bd9Sstevel@tonic-gate  *	The main routine will call ckarg() to parse the command line
2227c478bd9Sstevel@tonic-gate  *	arguments and call the appropriate functions to perform the
2237c478bd9Sstevel@tonic-gate  *	tasks specified by the arguments. It allows system
2247c478bd9Sstevel@tonic-gate  * 	administrator to add, change and display password attributes.
2257c478bd9Sstevel@tonic-gate  * 	Non privileged user can change password or display
2267c478bd9Sstevel@tonic-gate  * 	password attributes which corresponds to their login name.
2277c478bd9Sstevel@tonic-gate  */
2287c478bd9Sstevel@tonic-gate 
229*49335bdeSbasabi int
230*49335bdeSbasabi main(int argc, char *argv[])
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	int	flag;
2347c478bd9Sstevel@tonic-gate 	char	**namelist;
2357c478bd9Sstevel@tonic-gate 	int	num_user;
2367c478bd9Sstevel@tonic-gate 	int	i;
2377c478bd9Sstevel@tonic-gate 	attrlist *attributes = NULL;
2387c478bd9Sstevel@tonic-gate 	char	*input;
2397c478bd9Sstevel@tonic-gate 	int	tries = 1;
2407c478bd9Sstevel@tonic-gate 	int	updated_reps;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	if (prognamep = strrchr(argv[0], '/'))
2447c478bd9Sstevel@tonic-gate 		++prognamep;
2457c478bd9Sstevel@tonic-gate 	else
2467c478bd9Sstevel@tonic-gate 		prognamep = argv[0];
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	auth_rep.type = NULL;
2497c478bd9Sstevel@tonic-gate 	auth_rep.scope = NULL;
2507c478bd9Sstevel@tonic-gate 	repository.type = NULL;
2517c478bd9Sstevel@tonic-gate 	repository.scope = NULL;
2527c478bd9Sstevel@tonic-gate 	repository.scope_len = 0;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/* initialization for variables, set locale and textdomain  */
2567c478bd9Sstevel@tonic-gate 	i = 0;
2577c478bd9Sstevel@tonic-gate 	flag = 0;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	uid = getuid();		/* get the user id */
2607c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
2637c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
2647c478bd9Sstevel@tonic-gate #endif
2657c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	/*
2687c478bd9Sstevel@tonic-gate 	 * ckarg() parses the arguments. In case of an error,
2697c478bd9Sstevel@tonic-gate 	 * it sets the retval and returns FAIL (-1).
2707c478bd9Sstevel@tonic-gate 	 */
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	flag = ckarg(argc, argv, &attributes);
2737c478bd9Sstevel@tonic-gate 	dprintf1("flag is %0x\n", flag);
2747c478bd9Sstevel@tonic-gate 	if (flag == FAIL)
2757c478bd9Sstevel@tonic-gate 		passwd_exit(retval);
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	argc -= optind;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	if (argc < 1) {
2807c478bd9Sstevel@tonic-gate 		if ((usrname = getlogin()) == NULL) {
2817c478bd9Sstevel@tonic-gate 			struct passwd *pass = getpwuid(uid);
2827c478bd9Sstevel@tonic-gate 			if (pass != NULL)
2837c478bd9Sstevel@tonic-gate 				usrname = pass->pw_name;
2847c478bd9Sstevel@tonic-gate 			else {
2857c478bd9Sstevel@tonic-gate 				rusage();
2867c478bd9Sstevel@tonic-gate 				exit(NOPERM);
2877c478bd9Sstevel@tonic-gate 			}
2887c478bd9Sstevel@tonic-gate 		} else if (flag == 0) {
2897c478bd9Sstevel@tonic-gate 			/*
2907c478bd9Sstevel@tonic-gate 			 * If flag is zero, change passwd.
2917c478bd9Sstevel@tonic-gate 			 * Otherwise, it will display or
2927c478bd9Sstevel@tonic-gate 			 * modify password aging attributes
2937c478bd9Sstevel@tonic-gate 			 */
2947c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(MSG_INFO), prognamep,
2957c478bd9Sstevel@tonic-gate 			    usrname);
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 	} else
2987c478bd9Sstevel@tonic-gate 		usrname = argv[optind];
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	if (pam_start("passwd", usrname, &pam_conv, &pamh) != PAM_SUCCESS)
3017c478bd9Sstevel@tonic-gate 		passwd_exit(NOPERM);
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	auth_rep.type = repository.type;
3047c478bd9Sstevel@tonic-gate 	auth_rep.scope = repository.scope;
3057c478bd9Sstevel@tonic-gate 	auth_rep.scope_len = repository.scope_len;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	if (auth_rep.type != NULL) {
3087c478bd9Sstevel@tonic-gate 		if (pam_set_item(pamh, PAM_REPOSITORY, (void *)&auth_rep)
3097c478bd9Sstevel@tonic-gate 		    != PAM_SUCCESS) {
3107c478bd9Sstevel@tonic-gate 			passwd_exit(NOPERM);
3117c478bd9Sstevel@tonic-gate 		}
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if (flag ==  SAFLAG) {	/* display password attributes for all users */
3157c478bd9Sstevel@tonic-gate 		retval = get_namelist(repository, &namelist, &num_user);
3167c478bd9Sstevel@tonic-gate 		if (retval != SUCCESS)
3177c478bd9Sstevel@tonic-gate 			(void) passwd_exit(retval);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		if (num_user == 0) {
3207c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: %s\n", prognamep,
3217c478bd9Sstevel@tonic-gate 					gettext(MSG_FF));
3227c478bd9Sstevel@tonic-gate 			passwd_exit(FATAL);
3237c478bd9Sstevel@tonic-gate 		}
3247c478bd9Sstevel@tonic-gate 		i = 0;
3257c478bd9Sstevel@tonic-gate 		while (namelist[i] != NULL) {
3267c478bd9Sstevel@tonic-gate 			(void) get_attr(namelist[i], &repository,
3277c478bd9Sstevel@tonic-gate 			    &attributes);
3287c478bd9Sstevel@tonic-gate 			(void) display_attr(namelist[i], attributes);
3297c478bd9Sstevel@tonic-gate 			(void) free(namelist[i]);
3307c478bd9Sstevel@tonic-gate 			(void) free_attr(attributes);
3317c478bd9Sstevel@tonic-gate 			i++;
3327c478bd9Sstevel@tonic-gate 		}
3337c478bd9Sstevel@tonic-gate 		(void) free(namelist);
3347c478bd9Sstevel@tonic-gate 		passwd_exit(SUCCESS);
3357c478bd9Sstevel@tonic-gate 	} else if (flag == SFLAG) { /* display password attributes by user */
3367c478bd9Sstevel@tonic-gate 		if (get_attr(usrname, &repository, &attributes) ==
3377c478bd9Sstevel@tonic-gate 		    PWU_SUCCESS) {
3387c478bd9Sstevel@tonic-gate 			(void) display_attr(usrname, attributes);
3397c478bd9Sstevel@tonic-gate 			(void) free_attr(attributes);
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 		passwd_exit(SUCCESS);
3427c478bd9Sstevel@tonic-gate 		/* NOT REACHED */
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	switch (pam_authenticate(pamh, 0)) {
3477c478bd9Sstevel@tonic-gate 	case PAM_SUCCESS:
3487c478bd9Sstevel@tonic-gate 		break;
3497c478bd9Sstevel@tonic-gate 	case PAM_USER_UNKNOWN:
3507c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep,
3517c478bd9Sstevel@tonic-gate 		    usrname);
3527c478bd9Sstevel@tonic-gate 		passwd_exit(NOPERM);
3537c478bd9Sstevel@tonic-gate 		break;
3547c478bd9Sstevel@tonic-gate 	case PAM_PERM_DENIED:
3557c478bd9Sstevel@tonic-gate 		passwd_exit(NOPERM);
3567c478bd9Sstevel@tonic-gate 		break;
3577c478bd9Sstevel@tonic-gate 	case PAM_AUTH_ERR:
3587c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(MSG_SORRY), prognamep);
3597c478bd9Sstevel@tonic-gate 		passwd_exit(NOPERM);
3607c478bd9Sstevel@tonic-gate 		break;
3617c478bd9Sstevel@tonic-gate 	default:
3627c478bd9Sstevel@tonic-gate 		/* system error */
3637c478bd9Sstevel@tonic-gate 		passwd_exit(FMERR);
3647c478bd9Sstevel@tonic-gate 		break;
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	if (flag == 0) {			/* changing user password */
3687c478bd9Sstevel@tonic-gate 		int	chk_authtok = 0;	/* check password strength */
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		dprintf1("call pam_chauthtok() repository name =%s\n",
3717c478bd9Sstevel@tonic-gate 		    repository.type);
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 		/* Set up for Audit */
3747c478bd9Sstevel@tonic-gate 		if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
3757c478bd9Sstevel@tonic-gate 			perror("adt_start_session");
3767c478bd9Sstevel@tonic-gate 			passwd_exit(SYSERR);
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 		if ((event = adt_alloc_event(ah, ADT_passwd)) == NULL) {
3797c478bd9Sstevel@tonic-gate 			perror("adt_alloc_event");
3807c478bd9Sstevel@tonic-gate 			passwd_exit(NOMEM);
3817c478bd9Sstevel@tonic-gate 		}
3827c478bd9Sstevel@tonic-gate 		if (argc >= 1) {
3837c478bd9Sstevel@tonic-gate 			/* save target user */
3847c478bd9Sstevel@tonic-gate 			event->adt_passwd.username = usrname;
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 		/* Don't check account expiration when invoked by root */
3887c478bd9Sstevel@tonic-gate 		if (ckuid() != SUCCESS) {
3897c478bd9Sstevel@tonic-gate 			pam_retval = pam_acct_mgmt(pamh, PAM_SILENT);
3907c478bd9Sstevel@tonic-gate 			switch (pam_retval) {
3917c478bd9Sstevel@tonic-gate 			case PAM_ACCT_EXPIRED:
3927c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
3937c478bd9Sstevel@tonic-gate 				    gettext(MSG_ACCOUNT_EXP), usrname);
3947c478bd9Sstevel@tonic-gate 				passwd_exit(EXPIRED);
3957c478bd9Sstevel@tonic-gate 				break;
3967c478bd9Sstevel@tonic-gate 			case PAM_AUTHTOK_EXPIRED:
3977c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
3987c478bd9Sstevel@tonic-gate 				    gettext(MSG_AUTHTOK_EXP));
3997c478bd9Sstevel@tonic-gate 				passwd_exit(NOPERM);
4007c478bd9Sstevel@tonic-gate 				break;
4017c478bd9Sstevel@tonic-gate 			case PAM_NEW_AUTHTOK_REQD:
4027c478bd9Sstevel@tonic-gate 				/* valid error when changing passwords */
4037c478bd9Sstevel@tonic-gate 				break;
4047c478bd9Sstevel@tonic-gate 			case PAM_SUCCESS:
4057c478bd9Sstevel@tonic-gate 				/* Ok to change password */
4067c478bd9Sstevel@tonic-gate 				break;
4077c478bd9Sstevel@tonic-gate 			default:
4087c478bd9Sstevel@tonic-gate 				passwd_exit(NOPERM);
4097c478bd9Sstevel@tonic-gate 			}
4107c478bd9Sstevel@tonic-gate 		}
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		pam_retval = PAM_AUTHTOK_ERR;
4147c478bd9Sstevel@tonic-gate 		tries = 1;
4157c478bd9Sstevel@tonic-gate 		if (ckuid() == SUCCESS) {
4167c478bd9Sstevel@tonic-gate 			/* bypass password strength checks */
4177c478bd9Sstevel@tonic-gate 			chk_authtok = PAM_NO_AUTHTOK_CHECK;
4187c478bd9Sstevel@tonic-gate 		}
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 		while (pam_retval == PAM_AUTHTOK_ERR && tries <= DEF_ATTEMPTS) {
4217c478bd9Sstevel@tonic-gate 			if (tries > 1)
4227c478bd9Sstevel@tonic-gate 				(void) printf(gettext(MSG_AGAIN));
4237c478bd9Sstevel@tonic-gate 			pam_retval = pam_chauthtok(pamh, chk_authtok);
4247c478bd9Sstevel@tonic-gate 			if (pam_retval == PAM_TRY_AGAIN) {
4257c478bd9Sstevel@tonic-gate 				(void) sleep(1);
4267c478bd9Sstevel@tonic-gate 				pam_retval = pam_chauthtok(pamh, chk_authtok);
4277c478bd9Sstevel@tonic-gate 			}
4287c478bd9Sstevel@tonic-gate 			tries++;
4297c478bd9Sstevel@tonic-gate 		}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 		switch (pam_retval) {
4327c478bd9Sstevel@tonic-gate 		case PAM_SUCCESS:
4337c478bd9Sstevel@tonic-gate 			retval = SUCCESS;
4347c478bd9Sstevel@tonic-gate 			break;
4357c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_DISABLE_AGING:
4367c478bd9Sstevel@tonic-gate 			retval = BADAGE;
4377c478bd9Sstevel@tonic-gate 			break;
4387c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_LOCK_BUSY:
4397c478bd9Sstevel@tonic-gate 			retval = FBUSY;
4407c478bd9Sstevel@tonic-gate 			break;
4417c478bd9Sstevel@tonic-gate 		case PAM_TRY_AGAIN:
4427c478bd9Sstevel@tonic-gate 			retval = FBUSY;
4437c478bd9Sstevel@tonic-gate 			break;
4447c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_ERR:
4457c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_RECOVERY_ERR:
4467c478bd9Sstevel@tonic-gate 		default:
4477c478bd9Sstevel@tonic-gate 			retval = NOPERM;
4487c478bd9Sstevel@tonic-gate 			break;
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 		(void) passwd_exit(retval);
4527c478bd9Sstevel@tonic-gate 		/* NOT REACHED */
4537c478bd9Sstevel@tonic-gate 	} else {		/* changing attributes */
4547c478bd9Sstevel@tonic-gate 		switch (flag) {
4557c478bd9Sstevel@tonic-gate 		case EFLAG:		/* changing user password attributes */
4567c478bd9Sstevel@tonic-gate 			input = userinput(usrname, &repository, ATTR_SHELL);
4577c478bd9Sstevel@tonic-gate 			if (input)
4587c478bd9Sstevel@tonic-gate 				attrlist_add(&attributes, ATTR_SHELL, input);
4597c478bd9Sstevel@tonic-gate 			else
4607c478bd9Sstevel@tonic-gate 				(void) printf(gettext(MSG_SHELL_UNCHANGED));
4617c478bd9Sstevel@tonic-gate 			break;
4627c478bd9Sstevel@tonic-gate 		case GFLAG:
4637c478bd9Sstevel@tonic-gate 			input = userinput(usrname, &repository, ATTR_GECOS);
4647c478bd9Sstevel@tonic-gate 			if (input)
4657c478bd9Sstevel@tonic-gate 				attrlist_add(&attributes, ATTR_GECOS, input);
4667c478bd9Sstevel@tonic-gate 			else
4677c478bd9Sstevel@tonic-gate 				(void) printf(gettext(MSG_GECOS_UNCHANGED));
4687c478bd9Sstevel@tonic-gate 			break;
4697c478bd9Sstevel@tonic-gate 		case HFLAG:
4707c478bd9Sstevel@tonic-gate 			input = userinput(usrname, &repository, ATTR_HOMEDIR);
4717c478bd9Sstevel@tonic-gate 			if (input)
4727c478bd9Sstevel@tonic-gate 				attrlist_add(&attributes, ATTR_HOMEDIR, input);
4737c478bd9Sstevel@tonic-gate 			else
4747c478bd9Sstevel@tonic-gate 				(void) printf(gettext(MSG_DIR_UNCHANGED));
4757c478bd9Sstevel@tonic-gate 			break;
4767c478bd9Sstevel@tonic-gate 		}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		if (attributes != NULL) {
4797c478bd9Sstevel@tonic-gate 			retval = __set_authtoken_attr(usrname,
4807c478bd9Sstevel@tonic-gate 			    pamh->ps_item[PAM_AUTHTOK].pi_addr,
4817c478bd9Sstevel@tonic-gate 			    NULL, &repository, attributes, &updated_reps);
4827c478bd9Sstevel@tonic-gate 			switch (retval) {
4837c478bd9Sstevel@tonic-gate 			case PWU_SUCCESS:
4847c478bd9Sstevel@tonic-gate 				for (i = 1; i <= REP_LAST; i <<= 1) {
4857c478bd9Sstevel@tonic-gate 					if ((updated_reps & i) == 0)
4867c478bd9Sstevel@tonic-gate 						continue;
4877c478bd9Sstevel@tonic-gate 					(void) printf(gettext(MSG_SUCCESS),
4887c478bd9Sstevel@tonic-gate 					    prognamep, usrname);
4897c478bd9Sstevel@tonic-gate 				}
4907c478bd9Sstevel@tonic-gate 				retval = SUCCESS;
4917c478bd9Sstevel@tonic-gate 				break;
4927c478bd9Sstevel@tonic-gate 			case PWU_AGING_DISABLED:
4937c478bd9Sstevel@tonic-gate 				retval = BADAGE;
4947c478bd9Sstevel@tonic-gate 				break;
4957c478bd9Sstevel@tonic-gate 			default:
4967c478bd9Sstevel@tonic-gate 				retval = NOPERM;
4977c478bd9Sstevel@tonic-gate 				break;
4987c478bd9Sstevel@tonic-gate 			}
4997c478bd9Sstevel@tonic-gate 		} else {
5007c478bd9Sstevel@tonic-gate 			retval = SUCCESS; /* nothing to change won't fail */
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 		(void) passwd_exit(retval);
5037c478bd9Sstevel@tonic-gate 	}
504*49335bdeSbasabi 	/* NOTREACHED */
505*49335bdeSbasabi 	return (0);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate  * Get a line of input from the user.
5107c478bd9Sstevel@tonic-gate  *
5117c478bd9Sstevel@tonic-gate  * If the line is empty, or the input equals 'oldval', NULL is returned.
5127c478bd9Sstevel@tonic-gate  * therwise, a malloced string containing the input (minus the trailing
5137c478bd9Sstevel@tonic-gate  * newline) is returned.
5147c478bd9Sstevel@tonic-gate  */
5157c478bd9Sstevel@tonic-gate char *
5167c478bd9Sstevel@tonic-gate getresponse(char *oldval)
5177c478bd9Sstevel@tonic-gate {
5187c478bd9Sstevel@tonic-gate 	char    resp[MAX_INPUT_LEN];
5197c478bd9Sstevel@tonic-gate 	char    *retval = NULL;
5207c478bd9Sstevel@tonic-gate 	int	resplen;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	(void) fgets(resp, sizeof (resp) - 1, stdin);
5237c478bd9Sstevel@tonic-gate 	resplen = strlen(resp) - 1;
5247c478bd9Sstevel@tonic-gate 	if (resp[resplen] == '\n')
5257c478bd9Sstevel@tonic-gate 		resp[resplen] = '\0';
5267c478bd9Sstevel@tonic-gate 	if (*resp != '\0' && strcmp(resp, oldval) != 0)
5277c478bd9Sstevel@tonic-gate 		retval = strdup(resp);
5287c478bd9Sstevel@tonic-gate 	return (retval);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate  * char *userinput(item)
5337c478bd9Sstevel@tonic-gate  *
5347c478bd9Sstevel@tonic-gate  * user conversation function. The old value of attribute "item" is
5357c478bd9Sstevel@tonic-gate  * displayed while the user is asked to provide a new value.
5367c478bd9Sstevel@tonic-gate  *
5377c478bd9Sstevel@tonic-gate  * returns a malloc()-ed string if the user actualy provided input
5387c478bd9Sstevel@tonic-gate  * or NULL if the user simply hit return or the input equals the old
5397c478bd9Sstevel@tonic-gate  * value (not changed).
5407c478bd9Sstevel@tonic-gate  */
5417c478bd9Sstevel@tonic-gate char *
5427c478bd9Sstevel@tonic-gate userinput(char *name, pwu_repository_t *rep, attrtype type)
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate 	attrlist oldattr;
5457c478bd9Sstevel@tonic-gate 	char *oldval;			/* shorthand for oldattr.data.val_s */
5467c478bd9Sstevel@tonic-gate 	char *valid;			/* points to valid shells */
5477c478bd9Sstevel@tonic-gate 	char *response;
5487c478bd9Sstevel@tonic-gate 	char *cp;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	oldattr.type = type;
5517c478bd9Sstevel@tonic-gate 	oldattr.next = NULL;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	if (__get_authtoken_attr(name, rep, &oldattr) != PWU_SUCCESS)
5547c478bd9Sstevel@tonic-gate 		passwd_exit(FMERR);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	oldval = oldattr.data.val_s;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	if (type == ATTR_SHELL) {
5597c478bd9Sstevel@tonic-gate 		/* No current shell: set DEFSHL as default choice */
5607c478bd9Sstevel@tonic-gate 		if (*oldval == '\0') {
5617c478bd9Sstevel@tonic-gate 			free(oldval);
5627c478bd9Sstevel@tonic-gate 			oldval = strdup(DEFSHL);
5637c478bd9Sstevel@tonic-gate 		}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 		if (ckuid() != SUCCESS) {
5667c478bd9Sstevel@tonic-gate 			/* User must currently have a valid shell */
5677c478bd9Sstevel@tonic-gate 			setusershell();
5687c478bd9Sstevel@tonic-gate 			valid = getusershell();
5697c478bd9Sstevel@tonic-gate 			while (valid && strcmp(valid, oldval) != 0)
5707c478bd9Sstevel@tonic-gate 				valid = getusershell();
5717c478bd9Sstevel@tonic-gate 			endusershell();
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 			if (valid == NULL) {
5747c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(MSG_RS), oldval);
5757c478bd9Sstevel@tonic-gate 				free(oldval);
5767c478bd9Sstevel@tonic-gate 				return (NULL);
5777c478bd9Sstevel@tonic-gate 			}
5787c478bd9Sstevel@tonic-gate 		}
5797c478bd9Sstevel@tonic-gate 		(void) printf(gettext(MSG_OLDSHELL), oldval);
5807c478bd9Sstevel@tonic-gate 		(void) printf(gettext(MSG_NEWSHELL));
5817c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 		response = getresponse(oldval);
5847c478bd9Sstevel@tonic-gate 		free(oldval); /* We don't need the old value anymore */
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 		if (response == NULL || *response == '\0')
5877c478bd9Sstevel@tonic-gate 			return (NULL);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 		/* Make sure new shell is listed */
5907c478bd9Sstevel@tonic-gate 		setusershell();
5917c478bd9Sstevel@tonic-gate 		valid = getusershell();
5927c478bd9Sstevel@tonic-gate 		while (valid) {
5937c478bd9Sstevel@tonic-gate 			char *cp;
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 			/* Allow user to give shell without path */
5967c478bd9Sstevel@tonic-gate 			if (*response == '/') {
5977c478bd9Sstevel@tonic-gate 				cp = valid;
5987c478bd9Sstevel@tonic-gate 			} else {
5997c478bd9Sstevel@tonic-gate 				if ((cp = strrchr(valid, '/')) == NULL)
6007c478bd9Sstevel@tonic-gate 					cp = valid;
6017c478bd9Sstevel@tonic-gate 				else
6027c478bd9Sstevel@tonic-gate 					cp++;
6037c478bd9Sstevel@tonic-gate 			}
6047c478bd9Sstevel@tonic-gate 			if (strcmp(cp, response) == 0) {
6057c478bd9Sstevel@tonic-gate 				if (*response != '/') {
6067c478bd9Sstevel@tonic-gate 					/* take shell name including path */
6077c478bd9Sstevel@tonic-gate 					free(response);
6087c478bd9Sstevel@tonic-gate 					response = strdup(valid);
6097c478bd9Sstevel@tonic-gate 				}
6107c478bd9Sstevel@tonic-gate 				break;
6117c478bd9Sstevel@tonic-gate 			}
6127c478bd9Sstevel@tonic-gate 			valid = getusershell();
6137c478bd9Sstevel@tonic-gate 		}
6147c478bd9Sstevel@tonic-gate 		endusershell();
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 		if (valid == NULL) {    /* No valid shell matches */
6177c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(MSG_UNACCEPT), response);
6187c478bd9Sstevel@tonic-gate 			return (NULL);
6197c478bd9Sstevel@tonic-gate 		}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 		if (access(response, X_OK) < 0)
6227c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(MSG_UNAVAIL), response);
6237c478bd9Sstevel@tonic-gate 		return (response);
6247c478bd9Sstevel@tonic-gate 		/* NOT REACHED */
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 	/*
6277c478bd9Sstevel@tonic-gate 	 * if type == SHELL, we have returned by now. Only GECOS and
6287c478bd9Sstevel@tonic-gate 	 * HOMEDIR get to this point.
6297c478bd9Sstevel@tonic-gate 	 */
6307c478bd9Sstevel@tonic-gate 	(void) printf(gettext(MSG_INPUTHDR));
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	/*
6337c478bd9Sstevel@tonic-gate 	 * PRE: oldval points to malloced string with Old Value
6347c478bd9Sstevel@tonic-gate 	 * INV: oldval remains unchanged
6357c478bd9Sstevel@tonic-gate 	 * POST:response points to valid string or NULL.
6367c478bd9Sstevel@tonic-gate 	 */
6377c478bd9Sstevel@tonic-gate 	for (;;) {
6387c478bd9Sstevel@tonic-gate 		if (type == ATTR_GECOS)
6397c478bd9Sstevel@tonic-gate 			(void) printf(gettext(MSG_NAME), oldval);
6407c478bd9Sstevel@tonic-gate 		else if (type == ATTR_HOMEDIR)
6417c478bd9Sstevel@tonic-gate 			(void) printf(gettext(MSG_HOMEDIR), oldval);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 		response = getresponse(oldval);
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 		if (response && strcmp(response, "none") == 0)
6467c478bd9Sstevel@tonic-gate 			*response = '\0';
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 		/* No-change or empty string are OK */
6497c478bd9Sstevel@tonic-gate 		if (response == NULL || *response == '\0')
6507c478bd9Sstevel@tonic-gate 			break;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 		/* Check for illegal characters */
6537c478bd9Sstevel@tonic-gate 		if (strchr(response, ':')) {
6547c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s", gettext(MSG_COLON));
6557c478bd9Sstevel@tonic-gate 			free(response);
6567c478bd9Sstevel@tonic-gate 		} else if (strlen(response) > MAX_INPUT_LEN - 1) {
6577c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(MSG_MAXLEN),
6587c478bd9Sstevel@tonic-gate 			    MAX_INPUT_LEN);
6597c478bd9Sstevel@tonic-gate 			free(response);
6607c478bd9Sstevel@tonic-gate 		} else {
6617c478bd9Sstevel@tonic-gate 			/* don't allow control characters */
6627c478bd9Sstevel@tonic-gate 			for (cp = response; *cp >= 040; cp++)
6637c478bd9Sstevel@tonic-gate 				;
6647c478bd9Sstevel@tonic-gate 			if (*cp != '\0') {
6657c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(MSG_CONTROL));
6667c478bd9Sstevel@tonic-gate 				free(response);
6677c478bd9Sstevel@tonic-gate 			} else
6687c478bd9Sstevel@tonic-gate 				break;	/* response is a valid string */
6697c478bd9Sstevel@tonic-gate 		}
6707c478bd9Sstevel@tonic-gate 		/*
6717c478bd9Sstevel@tonic-gate 		 * We only get here if the input was invalid.
6727c478bd9Sstevel@tonic-gate 		 * In that case, we again ask the user for input.
6737c478bd9Sstevel@tonic-gate 		 */
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate 	free(oldval);
6767c478bd9Sstevel@tonic-gate 	return (response);
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate /*
6797c478bd9Sstevel@tonic-gate  * ckarg():
6807c478bd9Sstevel@tonic-gate  *	This function parses and verifies the
6817c478bd9Sstevel@tonic-gate  * 	arguments.  It takes three parameters:
6827c478bd9Sstevel@tonic-gate  * 	argc => # of arguments
6837c478bd9Sstevel@tonic-gate  * 	argv => pointer to an argument
6847c478bd9Sstevel@tonic-gate  * 	attrlist => pointer to list of password attributes
6857c478bd9Sstevel@tonic-gate  */
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate static int
6887c478bd9Sstevel@tonic-gate ckarg(int argc, char **argv, attrlist **attributes)
6897c478bd9Sstevel@tonic-gate {
6907c478bd9Sstevel@tonic-gate 	extern char	*optarg;
6917c478bd9Sstevel@tonic-gate 	char		*char_p;
6927c478bd9Sstevel@tonic-gate 	int	opt;
6937c478bd9Sstevel@tonic-gate 	int	flag;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	flag = 0;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:D:N")) != EOF) {
6987c478bd9Sstevel@tonic-gate 		switch (opt) {
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		case 'r': /* Repository Specified */
7017c478bd9Sstevel@tonic-gate 			/* repository: this option should be specified first */
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 			if (repository.type != NULL) {
7047c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
7057c478bd9Sstevel@tonic-gate 			"Repository is already defined or specified.\n"));
7067c478bd9Sstevel@tonic-gate 				rusage();
7077c478bd9Sstevel@tonic-gate 				retval = BADSYN;
7087c478bd9Sstevel@tonic-gate 				return (FAIL);
7097c478bd9Sstevel@tonic-gate 			}
7107c478bd9Sstevel@tonic-gate 			if (strcmp(optarg, "nisplus") == 0) {
7117c478bd9Sstevel@tonic-gate 				repository.type = optarg;
7127c478bd9Sstevel@tonic-gate 				repository.scope = nis_local_directory();
7137c478bd9Sstevel@tonic-gate 				if (repository.scope != NULL) {
7147c478bd9Sstevel@tonic-gate 					repository.scope_len =
7157c478bd9Sstevel@tonic-gate 					    strlen(repository.scope)+ 1;
7167c478bd9Sstevel@tonic-gate 				}
7177c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "nis") == 0) {
7187c478bd9Sstevel@tonic-gate 				repository.type = optarg;
7197c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "ldap") == 0) {
7207c478bd9Sstevel@tonic-gate 				repository.type = optarg;
7217c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "files") == 0) {
7227c478bd9Sstevel@tonic-gate 				repository.type = optarg;
7237c478bd9Sstevel@tonic-gate 			} else {
7247c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
7257c478bd9Sstevel@tonic-gate 				    gettext("invalid repository: %s\n"),
7267c478bd9Sstevel@tonic-gate 				    optarg);
7277c478bd9Sstevel@tonic-gate 				rusage();
7287c478bd9Sstevel@tonic-gate 				retval = BADSYN;
7297c478bd9Sstevel@tonic-gate 				return (FAIL);
7307c478bd9Sstevel@tonic-gate 			}
7317c478bd9Sstevel@tonic-gate 			break;
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 		case 'd': /* Delete Auth Token */
7347c478bd9Sstevel@tonic-gate 			/* if no repository the default for -d is files */
7357c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
7367c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 			/*
7397c478bd9Sstevel@tonic-gate 			 * Delete the password - only privileged processes
7407c478bd9Sstevel@tonic-gate 			 * can execute this for FILES
7417c478bd9Sstevel@tonic-gate 			 */
7427c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE) {
7437c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
7447c478bd9Sstevel@tonic-gate 				    "-d only applies to files repository\n"));
7457c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
7467c478bd9Sstevel@tonic-gate 				retval = BADSYN;
7477c478bd9Sstevel@tonic-gate 				return (FAIL);
7487c478bd9Sstevel@tonic-gate 			}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 			if (ckuid() != SUCCESS) {
7517c478bd9Sstevel@tonic-gate 				retval = NOPERM;
7527c478bd9Sstevel@tonic-gate 				return (FAIL);
7537c478bd9Sstevel@tonic-gate 			}
7547c478bd9Sstevel@tonic-gate 			if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG)) {
7557c478bd9Sstevel@tonic-gate 				rusage();
7567c478bd9Sstevel@tonic-gate 				retval = BADOPT;
7577c478bd9Sstevel@tonic-gate 				return (FAIL);
7587c478bd9Sstevel@tonic-gate 			}
7597c478bd9Sstevel@tonic-gate 			flag |= DFLAG;
7607c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_PASSWD, NULL);
7617c478bd9Sstevel@tonic-gate 			break;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 		case 'N': /* set account to be "no login" */
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 			/* if no repository the default for -N is files */
7667c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
7677c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
7707c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
7717c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
7727c478bd9Sstevel@tonic-gate 			"-N only applies to files or nisplus repository\n"));
7737c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
7747c478bd9Sstevel@tonic-gate 				retval = BADOPT;
7757c478bd9Sstevel@tonic-gate 				return (FAIL);
7767c478bd9Sstevel@tonic-gate 			}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 			/*
7797c478bd9Sstevel@tonic-gate 			 * Only privileged processes can execute this
7807c478bd9Sstevel@tonic-gate 			 * for FILES
7817c478bd9Sstevel@tonic-gate 			 */
7827c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
7837c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
7847c478bd9Sstevel@tonic-gate 				return (FAIL);
7857c478bd9Sstevel@tonic-gate 			if (flag & (MUTEXFLAG|NONAGEFLAG)) {
7867c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
7877c478bd9Sstevel@tonic-gate 				retval = BADOPT;
7887c478bd9Sstevel@tonic-gate 				return (FAIL);
7897c478bd9Sstevel@tonic-gate 			}
7907c478bd9Sstevel@tonic-gate 			flag |= XFLAG;
7917c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_NOLOGIN_ACCOUNT, NULL);
7927c478bd9Sstevel@tonic-gate 			break;
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 		case 'l': /* lock the password */
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 			/* if no repository the default for -l is files */
7977c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
7987c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
8017c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
8027c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
8037c478bd9Sstevel@tonic-gate 			"-l only applies to files or nisplus repository\n"));
8047c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
8057c478bd9Sstevel@tonic-gate 				retval = BADOPT;
8067c478bd9Sstevel@tonic-gate 				return (FAIL);
8077c478bd9Sstevel@tonic-gate 			}
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 			/*
8107c478bd9Sstevel@tonic-gate 			 * Only privileged processes can execute this
8117c478bd9Sstevel@tonic-gate 			 * for FILES
8127c478bd9Sstevel@tonic-gate 			 */
8137c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
8147c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
8157c478bd9Sstevel@tonic-gate 				return (FAIL);
8167c478bd9Sstevel@tonic-gate 			if (flag & (MUTEXFLAG|NONAGEFLAG)) {
8177c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
8187c478bd9Sstevel@tonic-gate 				retval = BADOPT;
8197c478bd9Sstevel@tonic-gate 				return (FAIL);
8207c478bd9Sstevel@tonic-gate 			}
8217c478bd9Sstevel@tonic-gate 			flag |= LFLAG;
8227c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_LOCK_ACCOUNT, NULL);
8237c478bd9Sstevel@tonic-gate 			break;
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 		case 'u': /* unlock the password */
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 			/* if no repository the default for -u is files */
8287c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
8297c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
8327c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
8337c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
8347c478bd9Sstevel@tonic-gate 			"-u only applies to files or nisplus repository\n"));
8357c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
8367c478bd9Sstevel@tonic-gate 				retval = BADOPT;
8377c478bd9Sstevel@tonic-gate 				return (FAIL);
8387c478bd9Sstevel@tonic-gate 			}
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 			/*
8417c478bd9Sstevel@tonic-gate 			 * Only privileged processes can execute this
8427c478bd9Sstevel@tonic-gate 			 * for FILES
8437c478bd9Sstevel@tonic-gate 			 */
8447c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
8457c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
8467c478bd9Sstevel@tonic-gate 				return (FAIL);
8477c478bd9Sstevel@tonic-gate 			if (flag & (MUTEXFLAG|NONAGEFLAG)) {
8487c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
8497c478bd9Sstevel@tonic-gate 				retval = BADOPT;
8507c478bd9Sstevel@tonic-gate 				return (FAIL);
8517c478bd9Sstevel@tonic-gate 			}
8527c478bd9Sstevel@tonic-gate 			flag |= UFLAG;
8537c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_UNLOCK_ACCOUNT, NULL);
8547c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_RST_FAILED_LOGINS, NULL);
8557c478bd9Sstevel@tonic-gate 			break;
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 		case 'x': /* set the max date */
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 			/* if no repository the default for -x is files */
8607c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
8617c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
8647c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
8657c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
8667c478bd9Sstevel@tonic-gate 			"-x only applies to files or nisplus repository\n"));
8677c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
8687c478bd9Sstevel@tonic-gate 				retval = BADSYN;
8697c478bd9Sstevel@tonic-gate 				return (FAIL);
8707c478bd9Sstevel@tonic-gate 			}
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 			/*
8737c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
8747c478bd9Sstevel@tonic-gate 			 * for FILES
8757c478bd9Sstevel@tonic-gate 			 */
8767c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
8777c478bd9Sstevel@tonic-gate 				retval = NOPERM;
8787c478bd9Sstevel@tonic-gate 				return (FAIL);
8797c478bd9Sstevel@tonic-gate 			}
8807c478bd9Sstevel@tonic-gate 			if (flag & (SAFLAG|MFLAG|NONAGEFLAG)) {
8817c478bd9Sstevel@tonic-gate 				retval = BADOPT;
8827c478bd9Sstevel@tonic-gate 				return (FAIL);
8837c478bd9Sstevel@tonic-gate 			}
8847c478bd9Sstevel@tonic-gate 			flag |= MFLAG;
8857c478bd9Sstevel@tonic-gate 			if ((int)strlen(optarg)  <= 0 ||
8867c478bd9Sstevel@tonic-gate 			    (maxdate = strtol(optarg, &char_p, 10)) < -1 ||
8877c478bd9Sstevel@tonic-gate 			    *char_p != '\0') {
8887c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "%s: %s -x\n",
8897c478bd9Sstevel@tonic-gate 					prognamep, gettext(MSG_NV));
8907c478bd9Sstevel@tonic-gate 				retval = BADSYN;
8917c478bd9Sstevel@tonic-gate 				return (FAIL);
8927c478bd9Sstevel@tonic-gate 			}
8937c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_MAX, optarg);
8947c478bd9Sstevel@tonic-gate 			break;
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 		case 'n': /* set the min date */
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 			/* if no repository the default for -n is files */
8997c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
9007c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
9037c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
9047c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
9057c478bd9Sstevel@tonic-gate 			"-n only applies to files or nisplus repository\n"));
9067c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
9077c478bd9Sstevel@tonic-gate 				retval = BADSYN;
9087c478bd9Sstevel@tonic-gate 				return (FAIL);
9097c478bd9Sstevel@tonic-gate 			}
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 			/*
9127c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
9137c478bd9Sstevel@tonic-gate 			 * for FILES
9147c478bd9Sstevel@tonic-gate 			 */
9157c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
9167c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
9177c478bd9Sstevel@tonic-gate 				return (FAIL);
9187c478bd9Sstevel@tonic-gate 			if (flag & (SAFLAG|NFLAG|NONAGEFLAG)) {
9197c478bd9Sstevel@tonic-gate 				retval = BADOPT;
9207c478bd9Sstevel@tonic-gate 				return (FAIL);
9217c478bd9Sstevel@tonic-gate 			}
9227c478bd9Sstevel@tonic-gate 			flag |= NFLAG;
9237c478bd9Sstevel@tonic-gate 			if ((int)strlen(optarg)  <= 0 ||
9247c478bd9Sstevel@tonic-gate 			    (strtol(optarg, &char_p, 10)) < 0 ||
9257c478bd9Sstevel@tonic-gate 			    *char_p != '\0') {
9267c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "%s: %s -n\n",
9277c478bd9Sstevel@tonic-gate 					prognamep, gettext(MSG_NV));
9287c478bd9Sstevel@tonic-gate 				retval = BADSYN;
9297c478bd9Sstevel@tonic-gate 				return (FAIL);
9307c478bd9Sstevel@tonic-gate 			}
9317c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_MIN, optarg);
9327c478bd9Sstevel@tonic-gate 			break;
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		case 'w': /* set the warning field */
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 			/* if no repository the default for -w is files */
9377c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
9387c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
9417c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
9427c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
9437c478bd9Sstevel@tonic-gate 			"-w only applies to files or nisplus repository\n"));
9447c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
9457c478bd9Sstevel@tonic-gate 				retval = BADSYN;
9467c478bd9Sstevel@tonic-gate 				return (FAIL);
9477c478bd9Sstevel@tonic-gate 			}
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 			/*
9507c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
9517c478bd9Sstevel@tonic-gate 			 * for FILES
9527c478bd9Sstevel@tonic-gate 			 */
9537c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
9547c478bd9Sstevel@tonic-gate 				retval = NOPERM;
9557c478bd9Sstevel@tonic-gate 				return (FAIL);
9567c478bd9Sstevel@tonic-gate 			}
9577c478bd9Sstevel@tonic-gate 			if (flag & (SAFLAG|WFLAG|NONAGEFLAG)) {
9587c478bd9Sstevel@tonic-gate 				retval = BADOPT;
9597c478bd9Sstevel@tonic-gate 				return (FAIL);
9607c478bd9Sstevel@tonic-gate 			}
9617c478bd9Sstevel@tonic-gate 			flag |= WFLAG;
9627c478bd9Sstevel@tonic-gate 			if ((int)strlen(optarg)  <= 0 ||
9637c478bd9Sstevel@tonic-gate 			    (strtol(optarg, &char_p, 10)) < 0 ||
9647c478bd9Sstevel@tonic-gate 			    *char_p != '\0') {
9657c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "%s: %s -w\n",
9667c478bd9Sstevel@tonic-gate 					prognamep, gettext(MSG_NV));
9677c478bd9Sstevel@tonic-gate 				retval = BADSYN;
9687c478bd9Sstevel@tonic-gate 				return (FAIL);
9697c478bd9Sstevel@tonic-gate 			}
9707c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_WARN, optarg);
9717c478bd9Sstevel@tonic-gate 			break;
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 		case 's': /* display password attributes */
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 			/* if no repository the default for -s is files */
9767c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
9777c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 			/* display password attributes */
9817c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
9827c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
9837c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
9847c478bd9Sstevel@tonic-gate 			"-s only applies to files or nisplus repository\n"));
9857c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
9867c478bd9Sstevel@tonic-gate 				retval = BADSYN;
9877c478bd9Sstevel@tonic-gate 				return (FAIL);
9887c478bd9Sstevel@tonic-gate 			}
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 			/*
9917c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
9927c478bd9Sstevel@tonic-gate 			 * for FILES
9937c478bd9Sstevel@tonic-gate 			 */
9947c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
9957c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
9967c478bd9Sstevel@tonic-gate 				return (FAIL);
9977c478bd9Sstevel@tonic-gate 			if (flag && (flag != AFLAG)) {
9987c478bd9Sstevel@tonic-gate 				retval = BADOPT;
9997c478bd9Sstevel@tonic-gate 				return (FAIL);
10007c478bd9Sstevel@tonic-gate 			}
10017c478bd9Sstevel@tonic-gate 			flag |= SFLAG;
10027c478bd9Sstevel@tonic-gate 			break;
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 		case 'a': /* display password attributes */
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 			/* if no repository the default for -a is files */
10077c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
10087c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
10117c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
10127c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
10137c478bd9Sstevel@tonic-gate 			"-a only applies to files or nisplus repository\n"));
10147c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
10157c478bd9Sstevel@tonic-gate 				retval = BADSYN;
10167c478bd9Sstevel@tonic-gate 				return (FAIL);
10177c478bd9Sstevel@tonic-gate 			}
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 			/*
10207c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
10217c478bd9Sstevel@tonic-gate 			 * for FILES
10227c478bd9Sstevel@tonic-gate 			 */
10237c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
10247c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
10257c478bd9Sstevel@tonic-gate 				return (FAIL);
10267c478bd9Sstevel@tonic-gate 			if (flag && (flag != SFLAG)) {
10277c478bd9Sstevel@tonic-gate 				retval = BADOPT;
10287c478bd9Sstevel@tonic-gate 				return (FAIL);
10297c478bd9Sstevel@tonic-gate 			}
10307c478bd9Sstevel@tonic-gate 			flag |= AFLAG;
10317c478bd9Sstevel@tonic-gate 			break;
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 		case 'f': /* expire password attributes	*/
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 			/* if no repository the default for -f is files */
10367c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
10377c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) == FALSE &&
10407c478bd9Sstevel@tonic-gate 			    IS_NISPLUS(repository) == FALSE) {
10417c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
10427c478bd9Sstevel@tonic-gate 			"-f only applies to files or nisplus repository\n"));
10437c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
10447c478bd9Sstevel@tonic-gate 				retval = BADSYN;
10457c478bd9Sstevel@tonic-gate 				return (FAIL);
10467c478bd9Sstevel@tonic-gate 			}
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 			/*
10497c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
10507c478bd9Sstevel@tonic-gate 			 * for FILES
10517c478bd9Sstevel@tonic-gate 			 */
10527c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) &&
10537c478bd9Sstevel@tonic-gate 				((retval = ckuid()) != SUCCESS))
10547c478bd9Sstevel@tonic-gate 				return (FAIL);
10557c478bd9Sstevel@tonic-gate 			if (flag & (SAFLAG|FFLAG|NONAGEFLAG)) {
10567c478bd9Sstevel@tonic-gate 				retval = BADOPT;
10577c478bd9Sstevel@tonic-gate 				return (FAIL);
10587c478bd9Sstevel@tonic-gate 			}
10597c478bd9Sstevel@tonic-gate 			flag |= FFLAG;
10607c478bd9Sstevel@tonic-gate 			attrlist_add(attributes, ATTR_EXPIRE_PASSWORD, NULL);
10617c478bd9Sstevel@tonic-gate 			break;
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 		case 'D': /* domain name specified */
10647c478bd9Sstevel@tonic-gate 			if (IS_NISPLUS(repository) == FALSE) {
10657c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
10667c478bd9Sstevel@tonic-gate 				    "-D only applies to nisplus repository\n"));
10677c478bd9Sstevel@tonic-gate 				rusage();	/* exit */
10687c478bd9Sstevel@tonic-gate 				retval = BADSYN;
10697c478bd9Sstevel@tonic-gate 				return (FAIL);
10707c478bd9Sstevel@tonic-gate 			}
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 			if (flag & AFLAG) {
10737c478bd9Sstevel@tonic-gate 				retval = BADOPT;
10747c478bd9Sstevel@tonic-gate 				return (FAIL);
10757c478bd9Sstevel@tonic-gate 			}
10767c478bd9Sstevel@tonic-gate 			/* It is cleaner not to set this flag */
10777c478bd9Sstevel@tonic-gate 			/* flag |= OFLAG; */
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 			/* get domain from optarg */
10807c478bd9Sstevel@tonic-gate 			repository.scope = optarg;
10817c478bd9Sstevel@tonic-gate 			if (repository.scope != NULL) {
10827c478bd9Sstevel@tonic-gate 				repository.scope_len =
10837c478bd9Sstevel@tonic-gate 				    strlen(repository.scope)+1;
10847c478bd9Sstevel@tonic-gate 			}
10857c478bd9Sstevel@tonic-gate 			break;
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 		case 'e': /* change login shell */
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 			/* if no repository the default for -e is files */
10907c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
10917c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 			/*
10947c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
10957c478bd9Sstevel@tonic-gate 			 * for FILES
10967c478bd9Sstevel@tonic-gate 			 */
10977c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
10987c478bd9Sstevel@tonic-gate 				retval = NOPERM;
10997c478bd9Sstevel@tonic-gate 				return (FAIL);
11007c478bd9Sstevel@tonic-gate 			}
11017c478bd9Sstevel@tonic-gate 			if (flag & (EFLAG|SAFLAG|AGEFLAG)) {
11027c478bd9Sstevel@tonic-gate 				retval = BADOPT;
11037c478bd9Sstevel@tonic-gate 				return (FAIL);
11047c478bd9Sstevel@tonic-gate 			}
11057c478bd9Sstevel@tonic-gate 			flag |= EFLAG;
11067c478bd9Sstevel@tonic-gate 			break;
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 		case 'g': /* change gecos information */
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 			/* if no repository the default for -g is files */
11117c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
11127c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 			/*
11157c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
11167c478bd9Sstevel@tonic-gate 			 * for FILES
11177c478bd9Sstevel@tonic-gate 			 */
11187c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
11197c478bd9Sstevel@tonic-gate 				retval = NOPERM;
11207c478bd9Sstevel@tonic-gate 				return (FAIL);
11217c478bd9Sstevel@tonic-gate 			}
11227c478bd9Sstevel@tonic-gate 			if (flag & (GFLAG|SAFLAG|AGEFLAG)) {
11237c478bd9Sstevel@tonic-gate 				retval = BADOPT;
11247c478bd9Sstevel@tonic-gate 				return (FAIL);
11257c478bd9Sstevel@tonic-gate 			}
11267c478bd9Sstevel@tonic-gate 			flag |= GFLAG;
11277c478bd9Sstevel@tonic-gate 			break;
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 		case 'h': /* change home dir */
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 			/* if no repository the default for -h is files */
11327c478bd9Sstevel@tonic-gate 			if (repository.type == NULL)
11337c478bd9Sstevel@tonic-gate 				repository = __REPFILES;
11347c478bd9Sstevel@tonic-gate 			/*
11357c478bd9Sstevel@tonic-gate 			 * Only privileged process can execute this
11367c478bd9Sstevel@tonic-gate 			 * for FILES
11377c478bd9Sstevel@tonic-gate 			 */
11387c478bd9Sstevel@tonic-gate 			if (IS_FILES(repository) && (ckuid() != SUCCESS)) {
11397c478bd9Sstevel@tonic-gate 				retval = NOPERM;
11407c478bd9Sstevel@tonic-gate 				return (FAIL);
11417c478bd9Sstevel@tonic-gate 			}
11427c478bd9Sstevel@tonic-gate 			if (IS_NIS(repository)) {
11437c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "%s\n",
11447c478bd9Sstevel@tonic-gate 				    gettext(MSG_NIS_HOMEDIR));
11457c478bd9Sstevel@tonic-gate 				retval = BADSYN;
11467c478bd9Sstevel@tonic-gate 				return (FAIL);
11477c478bd9Sstevel@tonic-gate 			}
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 			if (flag & (HFLAG|SAFLAG|AGEFLAG)) {
11507c478bd9Sstevel@tonic-gate 				retval = BADOPT;
11517c478bd9Sstevel@tonic-gate 				return (FAIL);
11527c478bd9Sstevel@tonic-gate 			}
11537c478bd9Sstevel@tonic-gate 			flag |= HFLAG;
11547c478bd9Sstevel@tonic-gate 			break;
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 		case '?':
11577c478bd9Sstevel@tonic-gate 			rusage();
11587c478bd9Sstevel@tonic-gate 			retval = BADOPT;
11597c478bd9Sstevel@tonic-gate 			return (FAIL);
11607c478bd9Sstevel@tonic-gate 		}
11617c478bd9Sstevel@tonic-gate 	}
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	argc -= optind;
11647c478bd9Sstevel@tonic-gate 	if (argc > 1) {
11657c478bd9Sstevel@tonic-gate 		rusage();
11667c478bd9Sstevel@tonic-gate 		retval = BADSYN;
11677c478bd9Sstevel@tonic-gate 		return (FAIL);
11687c478bd9Sstevel@tonic-gate 	}
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 	/* Make sure (EXPIRE comes after (MAX comes after MIN)) */
11717c478bd9Sstevel@tonic-gate 	attrlist_reorder(attributes);
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	/* If no options are specified or only the show option */
11747c478bd9Sstevel@tonic-gate 	/* is specified, return because no option error checking */
11757c478bd9Sstevel@tonic-gate 	/* is needed */
11767c478bd9Sstevel@tonic-gate 	if (!flag || (flag == SFLAG))
11777c478bd9Sstevel@tonic-gate 		return (flag);
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 	/* AFLAG must be used with SFLAG */
11807c478bd9Sstevel@tonic-gate 	if (flag == AFLAG) {
11817c478bd9Sstevel@tonic-gate 		rusage();
11827c478bd9Sstevel@tonic-gate 		retval = BADSYN;
11837c478bd9Sstevel@tonic-gate 		return (FAIL);
11847c478bd9Sstevel@tonic-gate 	}
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 	if (flag != SAFLAG && argc < 1) {
11877c478bd9Sstevel@tonic-gate 		/*
11887c478bd9Sstevel@tonic-gate 		 * user name is not specified (argc<1), it can't be
11897c478bd9Sstevel@tonic-gate 		 * aging info update.
11907c478bd9Sstevel@tonic-gate 		 */
11917c478bd9Sstevel@tonic-gate 		if (!(flag & NONAGEFLAG)) {
11927c478bd9Sstevel@tonic-gate 			rusage();
11937c478bd9Sstevel@tonic-gate 			retval = BADSYN;
11947c478bd9Sstevel@tonic-gate 			return (FAIL);
11957c478bd9Sstevel@tonic-gate 		}
11967c478bd9Sstevel@tonic-gate 	}
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	/* user name(s) may not be specified when SAFLAG is used. */
11997c478bd9Sstevel@tonic-gate 	if (flag == SAFLAG && argc >= 1) {
12007c478bd9Sstevel@tonic-gate 		rusage();
12017c478bd9Sstevel@tonic-gate 		retval = BADSYN;
12027c478bd9Sstevel@tonic-gate 		return (FAIL);
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 	/*
12067c478bd9Sstevel@tonic-gate 	 * If aging is being turned off (maxdate == -1), mindate may not
12077c478bd9Sstevel@tonic-gate 	 * be specified.
12087c478bd9Sstevel@tonic-gate 	 */
12097c478bd9Sstevel@tonic-gate 	if ((maxdate == -1) && (flag & NFLAG)) {
12107c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s -n\n",
12117c478bd9Sstevel@tonic-gate 				prognamep, gettext(MSG_NV));
12127c478bd9Sstevel@tonic-gate 		retval = BADOPT;
12137c478bd9Sstevel@tonic-gate 		return (FAIL);
12147c478bd9Sstevel@tonic-gate 	}
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	return (flag);
12177c478bd9Sstevel@tonic-gate }
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate /*
12207c478bd9Sstevel@tonic-gate  *
12217c478bd9Sstevel@tonic-gate  * ckuid():
12227c478bd9Sstevel@tonic-gate  *	This function returns SUCCESS if the caller is root, else
12237c478bd9Sstevel@tonic-gate  *	it returns NOPERM.
12247c478bd9Sstevel@tonic-gate  *
12257c478bd9Sstevel@tonic-gate  */
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate static int
1228*49335bdeSbasabi ckuid(void)
12297c478bd9Sstevel@tonic-gate {
12307c478bd9Sstevel@tonic-gate 	if (uid != 0) {
12317c478bd9Sstevel@tonic-gate 		return (retval = NOPERM);
12327c478bd9Sstevel@tonic-gate 	}
12337c478bd9Sstevel@tonic-gate 	return (SUCCESS);
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate /*
12387c478bd9Sstevel@tonic-gate  * get_attr()
12397c478bd9Sstevel@tonic-gate  */
12407c478bd9Sstevel@tonic-gate int
12417c478bd9Sstevel@tonic-gate get_attr(char *username, pwu_repository_t *repository, attrlist **attributes)
12427c478bd9Sstevel@tonic-gate {
12437c478bd9Sstevel@tonic-gate 	int res;
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 	attrlist_add(attributes, ATTR_PASSWD, NULL);
12467c478bd9Sstevel@tonic-gate 	attrlist_add(attributes, ATTR_LSTCHG, "0");
12477c478bd9Sstevel@tonic-gate 	attrlist_add(attributes, ATTR_MIN, "0");
12487c478bd9Sstevel@tonic-gate 	attrlist_add(attributes, ATTR_MAX, "0");
12497c478bd9Sstevel@tonic-gate 	attrlist_add(attributes, ATTR_WARN, "0");
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 	res = __get_authtoken_attr(username, repository, *attributes);
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate 	if (res == PWU_SUCCESS) {
12547c478bd9Sstevel@tonic-gate 		retval = SUCCESS;
12557c478bd9Sstevel@tonic-gate 		return (PWU_SUCCESS);
12567c478bd9Sstevel@tonic-gate 	}
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	if (res == PWU_NOT_FOUND)
12597c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep,
12607c478bd9Sstevel@tonic-gate 		    username);
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 	retval = NOPERM;
12637c478bd9Sstevel@tonic-gate 	passwd_exit(retval);
12647c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
12657c478bd9Sstevel@tonic-gate }
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate /*
12687c478bd9Sstevel@tonic-gate  * display_attr():
12697c478bd9Sstevel@tonic-gate  * This function prints out the password attributes of a usr
12707c478bd9Sstevel@tonic-gate  * onto standand output.
12717c478bd9Sstevel@tonic-gate  */
12727c478bd9Sstevel@tonic-gate void
12737c478bd9Sstevel@tonic-gate display_attr(char *usrname, attrlist *attributes)
12747c478bd9Sstevel@tonic-gate {
12757c478bd9Sstevel@tonic-gate 	char	*status;
12767c478bd9Sstevel@tonic-gate 	char	*passwd;
12777c478bd9Sstevel@tonic-gate 	long	lstchg;
12787c478bd9Sstevel@tonic-gate 	int	min, max, warn;
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	while (attributes) {
12817c478bd9Sstevel@tonic-gate 		switch (attributes->type) {
12827c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
12837c478bd9Sstevel@tonic-gate 			passwd = attributes->data.val_s;
12847c478bd9Sstevel@tonic-gate 			if (passwd == NULL || *passwd == '\0')
12857c478bd9Sstevel@tonic-gate 				status = "NP  ";
12867c478bd9Sstevel@tonic-gate 			else if (strncmp(passwd, LOCKSTRING,
12877c478bd9Sstevel@tonic-gate 			    sizeof (LOCKSTRING)-1) == 0)
12887c478bd9Sstevel@tonic-gate 				status = "LK  ";
12897c478bd9Sstevel@tonic-gate 			else if (strncmp(passwd, NOLOGINSTRING,
12907c478bd9Sstevel@tonic-gate 			    sizeof (NOLOGINSTRING)-1) == 0)
12917c478bd9Sstevel@tonic-gate 				status = "NL  ";
12927c478bd9Sstevel@tonic-gate 			else
12937c478bd9Sstevel@tonic-gate 				status = "PS  ";
12947c478bd9Sstevel@tonic-gate 			break;
12957c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
12967c478bd9Sstevel@tonic-gate 			lstchg = attributes->data.val_i * DAY;
12977c478bd9Sstevel@tonic-gate 			break;
12987c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
12997c478bd9Sstevel@tonic-gate 			min = attributes->data.val_i;
13007c478bd9Sstevel@tonic-gate 			break;
13017c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
13027c478bd9Sstevel@tonic-gate 			max = attributes->data.val_i;
13037c478bd9Sstevel@tonic-gate 			break;
13047c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
13057c478bd9Sstevel@tonic-gate 			warn = attributes->data.val_i;
13067c478bd9Sstevel@tonic-gate 			break;
13077c478bd9Sstevel@tonic-gate 		}
13087c478bd9Sstevel@tonic-gate 		attributes = attributes->next;
13097c478bd9Sstevel@tonic-gate 	}
13107c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "%-8s  ", usrname);
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate 	if (status)
13137c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "%s  ", status);
13147c478bd9Sstevel@tonic-gate 
13157c478bd9Sstevel@tonic-gate 	if (max != -1) {
13167c478bd9Sstevel@tonic-gate 		if (lstchg == 0) {
13177c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, "00/00/00  ");
13187c478bd9Sstevel@tonic-gate 		} else {
13197c478bd9Sstevel@tonic-gate 			struct tm *tmp;
13207c478bd9Sstevel@tonic-gate 			tmp = gmtime(&lstchg);
13217c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, "%.2d/%.2d/%.2d  ",
13227c478bd9Sstevel@tonic-gate 			    tmp->tm_mon + 1,
13237c478bd9Sstevel@tonic-gate 			    tmp->tm_mday,
13247c478bd9Sstevel@tonic-gate 			    tmp->tm_year % 100);
13257c478bd9Sstevel@tonic-gate 		}
13267c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, (min >= 0) ? "%4d  " : "      ", min);
13277c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, "%4d  ", max);
13287c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, (warn > 0) ? "%4d  " : "      ", warn);
13297c478bd9Sstevel@tonic-gate 	}
13307c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, "\n");
13317c478bd9Sstevel@tonic-gate }
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate void
13347c478bd9Sstevel@tonic-gate free_attr(attrlist *attributes)
13357c478bd9Sstevel@tonic-gate {
13367c478bd9Sstevel@tonic-gate 	while (attributes) {
13377c478bd9Sstevel@tonic-gate 		if (attributes->type == ATTR_PASSWD)
13387c478bd9Sstevel@tonic-gate 			free(attributes->data.val_s);
13397c478bd9Sstevel@tonic-gate 		attributes = attributes->next;
13407c478bd9Sstevel@tonic-gate 	}
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate /*
13447c478bd9Sstevel@tonic-gate  *
13457c478bd9Sstevel@tonic-gate  * get_namelist_files():
13467c478bd9Sstevel@tonic-gate  *	This function gets a list of user names on the system from
13477c478bd9Sstevel@tonic-gate  *	the /etc/passwd file.
13487c478bd9Sstevel@tonic-gate  *
13497c478bd9Sstevel@tonic-gate  */
13507c478bd9Sstevel@tonic-gate int
1351*49335bdeSbasabi get_namelist_files(char ***namelist_p, int *num_user)
13527c478bd9Sstevel@tonic-gate {
13537c478bd9Sstevel@tonic-gate 	FILE		*pwfp;
13547c478bd9Sstevel@tonic-gate 	struct passwd	*pwd;
13557c478bd9Sstevel@tonic-gate 	int		max_user;
13567c478bd9Sstevel@tonic-gate 	int		nuser;
13577c478bd9Sstevel@tonic-gate 	char	**nl;
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	nuser = 0;
13607c478bd9Sstevel@tonic-gate 	errno = 0;
13617c478bd9Sstevel@tonic-gate 	pwd = NULL;
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	if ((pwfp = fopen(PASSWD, "r")) == NULL)
13647c478bd9Sstevel@tonic-gate 		return (NOPERM);
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	/*
13677c478bd9Sstevel@tonic-gate 	 * find out the actual number of entries in the PASSWD file
13687c478bd9Sstevel@tonic-gate 	 */
13697c478bd9Sstevel@tonic-gate 	max_user = 1;			/* need one slot for terminator NULL */
13707c478bd9Sstevel@tonic-gate 	while ((pwd = fgetpwent(pwfp)) != NULL)
13717c478bd9Sstevel@tonic-gate 		max_user++;
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 	/*
13747c478bd9Sstevel@tonic-gate 	 *	reset the file stream pointer
13757c478bd9Sstevel@tonic-gate 	 */
13767c478bd9Sstevel@tonic-gate 	rewind(pwfp);
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 	nl = (char **)calloc(max_user, (sizeof (char *)));
13797c478bd9Sstevel@tonic-gate 	if (nl == NULL) {
13807c478bd9Sstevel@tonic-gate 		(void) fclose(pwfp);
13817c478bd9Sstevel@tonic-gate 		return (FMERR);
13827c478bd9Sstevel@tonic-gate 	}
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate 	while ((pwd = fgetpwent(pwfp)) != NULL) {
13857c478bd9Sstevel@tonic-gate 		if ((nl[nuser] = strdup(pwd->pw_name)) == NULL) {
13867c478bd9Sstevel@tonic-gate 			(void) fclose(pwfp);
13877c478bd9Sstevel@tonic-gate 			return (FMERR);
13887c478bd9Sstevel@tonic-gate 		}
13897c478bd9Sstevel@tonic-gate 		nuser++;
13907c478bd9Sstevel@tonic-gate 	}
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 	nl[nuser] = NULL;
13937c478bd9Sstevel@tonic-gate 	*num_user = nuser;
13947c478bd9Sstevel@tonic-gate 	*namelist_p = nl;
13957c478bd9Sstevel@tonic-gate 	(void) fclose(pwfp);
13967c478bd9Sstevel@tonic-gate 	return (SUCCESS);
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate /*
14007c478bd9Sstevel@tonic-gate  * get_namelist_nisplus
14017c478bd9Sstevel@tonic-gate  *
14027c478bd9Sstevel@tonic-gate  */
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate /*
14057c478bd9Sstevel@tonic-gate  * Our private version of the switch frontend for getspent.  We want to
14067c478bd9Sstevel@tonic-gate  * search just the nisplus sp file, so we want to bypass normal nsswitch.conf
14077c478bd9Sstevel@tonic-gate  * based processing.  This implementation compatible with version 2 of the
14087c478bd9Sstevel@tonic-gate  * name service switch.
14097c478bd9Sstevel@tonic-gate  */
14107c478bd9Sstevel@tonic-gate #define	NSS_NISPLUS_ONLY	"nisplus"
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate extern int str2spwd(const char *, int, void *, char *, int);
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root);
14157c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context);
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate static void
1418*49335bdeSbasabi _np_nss_initf_shadow(nss_db_params_t *p)
14197c478bd9Sstevel@tonic-gate {
14207c478bd9Sstevel@tonic-gate 	p->name	= NSS_DBNAM_SHADOW;
14217c478bd9Sstevel@tonic-gate 	p->config_name    = NSS_DBNAM_PASSWD;	/* Use config for "passwd" */
14227c478bd9Sstevel@tonic-gate 	p->default_config = NSS_NISPLUS_ONLY;   /* Use nisplus only */
14237c478bd9Sstevel@tonic-gate 	p->flags = NSS_USE_DEFAULT_CONFIG;
14247c478bd9Sstevel@tonic-gate }
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate static void
1427*49335bdeSbasabi _np_setspent(void)
14287c478bd9Sstevel@tonic-gate {
14297c478bd9Sstevel@tonic-gate 	nss_setent(&db_root, _np_nss_initf_shadow, &context);
14307c478bd9Sstevel@tonic-gate }
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate static void
1433*49335bdeSbasabi _np_endspent(void)
14347c478bd9Sstevel@tonic-gate {
14357c478bd9Sstevel@tonic-gate 	nss_endent(&db_root, _np_nss_initf_shadow, &context);
14367c478bd9Sstevel@tonic-gate 	nss_delete(&db_root);
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate static struct spwd *
1440*49335bdeSbasabi _np_getspent_r(struct spwd *result, char *buffer, int buflen)
14417c478bd9Sstevel@tonic-gate {
14427c478bd9Sstevel@tonic-gate 	nss_XbyY_args_t arg;
14437c478bd9Sstevel@tonic-gate 	char		*nam;
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 	/* In getXXent_r(), protect the unsuspecting caller from +/- entries */
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 	do {
14487c478bd9Sstevel@tonic-gate 		NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
14497c478bd9Sstevel@tonic-gate 			/* No key to fill in */
14507c478bd9Sstevel@tonic-gate 		(void) nss_getent(&db_root, _np_nss_initf_shadow, &context,
14517c478bd9Sstevel@tonic-gate 		    &arg);
14527c478bd9Sstevel@tonic-gate 	} while (arg.returnval != 0 &&
14537c478bd9Sstevel@tonic-gate 			(nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 &&
14547c478bd9Sstevel@tonic-gate 			(*nam == '+' || *nam == '-'));
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 	return (struct spwd *)NSS_XbyY_FINI(&arg);
14577c478bd9Sstevel@tonic-gate }
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate static nss_XbyY_buf_t *buffer;
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate static struct spwd *
1462*49335bdeSbasabi _np_getspent(void)
14637c478bd9Sstevel@tonic-gate {
14647c478bd9Sstevel@tonic-gate 	nss_XbyY_buf_t	*b;
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW);
14677c478bd9Sstevel@tonic-gate 
14687c478bd9Sstevel@tonic-gate 	return (b == 0 ? 0 : _np_getspent_r(b->result, b->buffer, b->buflen));
14697c478bd9Sstevel@tonic-gate }
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate int
14727c478bd9Sstevel@tonic-gate get_namelist_nisplus(char ***namelist_p, int *num_user)
14737c478bd9Sstevel@tonic-gate {
14747c478bd9Sstevel@tonic-gate 	int nuser = 0;
14757c478bd9Sstevel@tonic-gate 	int alloced = 100;
14767c478bd9Sstevel@tonic-gate 	char **nl;
14777c478bd9Sstevel@tonic-gate 	struct spwd *p;
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	if ((nl = calloc(alloced, sizeof (*nl))) == NULL)
14817c478bd9Sstevel@tonic-gate 		return (FMERR);
14827c478bd9Sstevel@tonic-gate 
14837c478bd9Sstevel@tonic-gate 	(void) _np_setspent();
14847c478bd9Sstevel@tonic-gate 	while ((p = _np_getspent()) != NULL) {
14857c478bd9Sstevel@tonic-gate 		if ((nl[nuser] = strdup(p->sp_namp)) == NULL) {
14867c478bd9Sstevel@tonic-gate 			_np_endspent();
14877c478bd9Sstevel@tonic-gate 			return (FMERR);
14887c478bd9Sstevel@tonic-gate 		}
14897c478bd9Sstevel@tonic-gate 		if (++nuser == alloced) {
14907c478bd9Sstevel@tonic-gate 			alloced += 100;
14917c478bd9Sstevel@tonic-gate 			nl = realloc(nl, alloced * (sizeof (*nl)));
14927c478bd9Sstevel@tonic-gate 			if (nl == NULL) {
14937c478bd9Sstevel@tonic-gate 				_np_endspent();
14947c478bd9Sstevel@tonic-gate 				return (FMERR);
14957c478bd9Sstevel@tonic-gate 			}
14967c478bd9Sstevel@tonic-gate 		}
14977c478bd9Sstevel@tonic-gate 	}
14987c478bd9Sstevel@tonic-gate 	(void) _np_endspent();
14997c478bd9Sstevel@tonic-gate 	nl[nuser] = NULL;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	*namelist_p = nl;
15027c478bd9Sstevel@tonic-gate 	*num_user = nuser;		/* including NULL */
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 	return (SUCCESS);
15057c478bd9Sstevel@tonic-gate }
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate int
15087c478bd9Sstevel@tonic-gate get_namelist(pwu_repository_t repository, char ***namelist, int *num_user)
15097c478bd9Sstevel@tonic-gate {
15107c478bd9Sstevel@tonic-gate 	if (IS_NISPLUS(repository))
15117c478bd9Sstevel@tonic-gate 		return (get_namelist_nisplus(namelist, num_user));
15127c478bd9Sstevel@tonic-gate 	else if (IS_FILES(repository))
15137c478bd9Sstevel@tonic-gate 		return (get_namelist_files(namelist, num_user));
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	rusage();
15167c478bd9Sstevel@tonic-gate 	return (BADSYN);
15177c478bd9Sstevel@tonic-gate }
15187c478bd9Sstevel@tonic-gate 
15197c478bd9Sstevel@tonic-gate /*
15207c478bd9Sstevel@tonic-gate  *
15217c478bd9Sstevel@tonic-gate  * passwd_exit():
15227c478bd9Sstevel@tonic-gate  *	This function will call exit() with appropriate exit code
15237c478bd9Sstevel@tonic-gate  *	according to the input "retcode" value.
15247c478bd9Sstevel@tonic-gate  *	It also calls pam_end() to clean-up buffers before exit.
15257c478bd9Sstevel@tonic-gate  *
15267c478bd9Sstevel@tonic-gate  */
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate void
1529*49335bdeSbasabi passwd_exit(int retcode)
15307c478bd9Sstevel@tonic-gate {
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate 	if (pamh)
15337c478bd9Sstevel@tonic-gate 		(void) pam_end(pamh, pam_retval);
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 	switch (retcode) {
15367c478bd9Sstevel@tonic-gate 	case SUCCESS:
15377c478bd9Sstevel@tonic-gate 			break;
15387c478bd9Sstevel@tonic-gate 	case NOPERM:
15397c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_NP));
15407c478bd9Sstevel@tonic-gate 			break;
15417c478bd9Sstevel@tonic-gate 	case BADOPT:
15427c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_BS));
15437c478bd9Sstevel@tonic-gate 			break;
15447c478bd9Sstevel@tonic-gate 	case FMERR:
15457c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_FE));
15467c478bd9Sstevel@tonic-gate 			break;
15477c478bd9Sstevel@tonic-gate 	case FATAL:
15487c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_FF));
15497c478bd9Sstevel@tonic-gate 			break;
15507c478bd9Sstevel@tonic-gate 	case FBUSY:
15517c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_FB));
15527c478bd9Sstevel@tonic-gate 			break;
15537c478bd9Sstevel@tonic-gate 	case BADSYN:
15547c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_NV));
15557c478bd9Sstevel@tonic-gate 			break;
15567c478bd9Sstevel@tonic-gate 	case BADAGE:
15577c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_AD));
15587c478bd9Sstevel@tonic-gate 			break;
15597c478bd9Sstevel@tonic-gate 	case NOMEM:
15607c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_NM));
15617c478bd9Sstevel@tonic-gate 			break;
15627c478bd9Sstevel@tonic-gate 	default:
15637c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n", gettext(MSG_NP));
15647c478bd9Sstevel@tonic-gate 			retcode = NOPERM;
15657c478bd9Sstevel@tonic-gate 			break;
15667c478bd9Sstevel@tonic-gate 	}
15677c478bd9Sstevel@tonic-gate 	/* write password record */
15687c478bd9Sstevel@tonic-gate 	if (event != NULL) {
15697c478bd9Sstevel@tonic-gate 		if (adt_put_event(event,
15707c478bd9Sstevel@tonic-gate 		    retcode == SUCCESS ? ADT_SUCCESS : ADT_FAILURE,
15717c478bd9Sstevel@tonic-gate 		    retcode == SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM +
15727c478bd9Sstevel@tonic-gate 		    pam_retval) != 0) {
15737c478bd9Sstevel@tonic-gate 			adt_free_event(event);
15747c478bd9Sstevel@tonic-gate 			(void) adt_end_session(ah);
15757c478bd9Sstevel@tonic-gate 			perror("adt_put_event");
15767c478bd9Sstevel@tonic-gate 			exit(retcode);
15777c478bd9Sstevel@tonic-gate 		}
15787c478bd9Sstevel@tonic-gate 		adt_free_event(event);
15797c478bd9Sstevel@tonic-gate 	}
15807c478bd9Sstevel@tonic-gate 	(void) adt_end_session(ah);
15817c478bd9Sstevel@tonic-gate 	exit(retcode);
15827c478bd9Sstevel@tonic-gate }
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate /*
15857c478bd9Sstevel@tonic-gate  *
15867c478bd9Sstevel@tonic-gate  * passwd_conv():
15877c478bd9Sstevel@tonic-gate  *	This is the conv (conversation) function called from
15887c478bd9Sstevel@tonic-gate  *	a PAM authentication module to print error messages
15897c478bd9Sstevel@tonic-gate  *	or garner information from the user.
15907c478bd9Sstevel@tonic-gate  *
15917c478bd9Sstevel@tonic-gate  */
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15947c478bd9Sstevel@tonic-gate static int
1595*49335bdeSbasabi passwd_conv(int num_msg, struct pam_message **msg,
1596*49335bdeSbasabi 	    struct pam_response **response, void *appdata_ptr)
15977c478bd9Sstevel@tonic-gate {
15987c478bd9Sstevel@tonic-gate 	struct pam_message	*m;
15997c478bd9Sstevel@tonic-gate 	struct pam_response	*r;
16007c478bd9Sstevel@tonic-gate 	char 			*temp;
16017c478bd9Sstevel@tonic-gate 	int			k, i;
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate 	if (num_msg <= 0)
16047c478bd9Sstevel@tonic-gate 		return (PAM_CONV_ERR);
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 	*response = (struct pam_response *)calloc(num_msg,
16077c478bd9Sstevel@tonic-gate 						sizeof (struct pam_response));
16087c478bd9Sstevel@tonic-gate 	if (*response == NULL)
16097c478bd9Sstevel@tonic-gate 		return (PAM_BUF_ERR);
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	k = num_msg;
16127c478bd9Sstevel@tonic-gate 	m = *msg;
16137c478bd9Sstevel@tonic-gate 	r = *response;
16147c478bd9Sstevel@tonic-gate 	while (k--) {
16157c478bd9Sstevel@tonic-gate 
16167c478bd9Sstevel@tonic-gate 		switch (m->msg_style) {
16177c478bd9Sstevel@tonic-gate 
16187c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_OFF:
16197c478bd9Sstevel@tonic-gate 			temp = getpassphrase(m->msg);
16207c478bd9Sstevel@tonic-gate 			if (temp != NULL) {
16217c478bd9Sstevel@tonic-gate 				r->resp = strdup(temp);
16227c478bd9Sstevel@tonic-gate 				(void) memset(temp, 0, strlen(temp));
16237c478bd9Sstevel@tonic-gate 				if (r->resp == NULL) {
16247c478bd9Sstevel@tonic-gate 					/* free responses */
16257c478bd9Sstevel@tonic-gate 					r = *response;
16267c478bd9Sstevel@tonic-gate 					for (i = 0; i < num_msg; i++, r++) {
16277c478bd9Sstevel@tonic-gate 						if (r->resp)
16287c478bd9Sstevel@tonic-gate 							free(r->resp);
16297c478bd9Sstevel@tonic-gate 					}
16307c478bd9Sstevel@tonic-gate 					free(*response);
16317c478bd9Sstevel@tonic-gate 					*response = NULL;
16327c478bd9Sstevel@tonic-gate 					return (PAM_BUF_ERR);
16337c478bd9Sstevel@tonic-gate 				}
16347c478bd9Sstevel@tonic-gate 			}
16357c478bd9Sstevel@tonic-gate 			m++;
16367c478bd9Sstevel@tonic-gate 			r++;
16377c478bd9Sstevel@tonic-gate 			break;
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_ON:
16407c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
16417c478bd9Sstevel@tonic-gate 				(void) fputs(m->msg, stdout);
16427c478bd9Sstevel@tonic-gate 			}
16437c478bd9Sstevel@tonic-gate 			r->resp = (char *)calloc(PAM_MAX_RESP_SIZE,
16447c478bd9Sstevel@tonic-gate 							sizeof (char));
16457c478bd9Sstevel@tonic-gate 			if (r->resp == NULL) {
16467c478bd9Sstevel@tonic-gate 				/* free responses */
16477c478bd9Sstevel@tonic-gate 				r = *response;
16487c478bd9Sstevel@tonic-gate 				for (i = 0; i < num_msg; i++, r++) {
16497c478bd9Sstevel@tonic-gate 					if (r->resp)
16507c478bd9Sstevel@tonic-gate 						free(r->resp);
16517c478bd9Sstevel@tonic-gate 				}
16527c478bd9Sstevel@tonic-gate 				free(*response);
16537c478bd9Sstevel@tonic-gate 				*response = NULL;
16547c478bd9Sstevel@tonic-gate 				return (PAM_BUF_ERR);
16557c478bd9Sstevel@tonic-gate 			}
16567c478bd9Sstevel@tonic-gate 			if (fgets(r->resp, PAM_MAX_RESP_SIZE-1, stdin)) {
16577c478bd9Sstevel@tonic-gate 				int len = strlen(r->resp);
16587c478bd9Sstevel@tonic-gate 				if (r->resp[len-1] == '\n')
16597c478bd9Sstevel@tonic-gate 					r->resp[len-1] = '\0';
16607c478bd9Sstevel@tonic-gate 			}
16617c478bd9Sstevel@tonic-gate 			m++;
16627c478bd9Sstevel@tonic-gate 			r++;
16637c478bd9Sstevel@tonic-gate 			break;
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 		case PAM_ERROR_MSG:
16667c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
16677c478bd9Sstevel@tonic-gate 				(void) fputs(m->msg, stderr);
16687c478bd9Sstevel@tonic-gate 				(void) fputs("\n", stderr);
16697c478bd9Sstevel@tonic-gate 			}
16707c478bd9Sstevel@tonic-gate 			m++;
16717c478bd9Sstevel@tonic-gate 			r++;
16727c478bd9Sstevel@tonic-gate 			break;
16737c478bd9Sstevel@tonic-gate 		case PAM_TEXT_INFO:
16747c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
16757c478bd9Sstevel@tonic-gate 				(void) fputs(m->msg, stdout);
16767c478bd9Sstevel@tonic-gate 				(void) fputs("\n", stdout);
16777c478bd9Sstevel@tonic-gate 			}
16787c478bd9Sstevel@tonic-gate 			m++;
16797c478bd9Sstevel@tonic-gate 			r++;
16807c478bd9Sstevel@tonic-gate 			break;
16817c478bd9Sstevel@tonic-gate 
16827c478bd9Sstevel@tonic-gate 		default:
16837c478bd9Sstevel@tonic-gate 			break;
16847c478bd9Sstevel@tonic-gate 		}
16857c478bd9Sstevel@tonic-gate 	}
16867c478bd9Sstevel@tonic-gate 	return (PAM_SUCCESS);
16877c478bd9Sstevel@tonic-gate }
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate /*
16907c478bd9Sstevel@tonic-gate  * 		Utilities Functions
16917c478bd9Sstevel@tonic-gate  */
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate /*
16947c478bd9Sstevel@tonic-gate  * int attrlist_add(attrlist **l, attrtype type, char *val)
16957c478bd9Sstevel@tonic-gate  * add an item, with type "type" and value "val", at the tail of list l.
16967c478bd9Sstevel@tonic-gate  * This functions exits the application on OutOfMem error.
16977c478bd9Sstevel@tonic-gate  */
16987c478bd9Sstevel@tonic-gate void
16997c478bd9Sstevel@tonic-gate attrlist_add(attrlist **l, attrtype type, char *val)
17007c478bd9Sstevel@tonic-gate {
17017c478bd9Sstevel@tonic-gate 	attrlist **w;
17027c478bd9Sstevel@tonic-gate 
17037c478bd9Sstevel@tonic-gate 	/* tail insert */
17047c478bd9Sstevel@tonic-gate 	for (w = l; *w != NULL; w = &(*w)->next)
17057c478bd9Sstevel@tonic-gate 		;
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate 	if ((*w = malloc(sizeof (**w))) == NULL)
17087c478bd9Sstevel@tonic-gate 		passwd_exit(NOMEM);
17097c478bd9Sstevel@tonic-gate 
17107c478bd9Sstevel@tonic-gate 	(*w)->type = type;
17117c478bd9Sstevel@tonic-gate 	(*w)->next = NULL;
17127c478bd9Sstevel@tonic-gate 
17137c478bd9Sstevel@tonic-gate 	switch (type) {
17147c478bd9Sstevel@tonic-gate 	case ATTR_MIN:
17157c478bd9Sstevel@tonic-gate 	case ATTR_WARN:
17167c478bd9Sstevel@tonic-gate 	case ATTR_MAX:
17177c478bd9Sstevel@tonic-gate 		(*w)->data.val_i = atoi(val);
17187c478bd9Sstevel@tonic-gate 		break;
17197c478bd9Sstevel@tonic-gate 	default:
17207c478bd9Sstevel@tonic-gate 		(*w)->data.val_s = val;
17217c478bd9Sstevel@tonic-gate 		break;
17227c478bd9Sstevel@tonic-gate 	}
17237c478bd9Sstevel@tonic-gate }
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate /*
17267c478bd9Sstevel@tonic-gate  * attrlist_reorder(attrlist **l)
17277c478bd9Sstevel@tonic-gate  * Make sure that
17287c478bd9Sstevel@tonic-gate  * 	- if EXPIRE and MAX or MIN is set, EXPIRE comes after MAX/MIN
17297c478bd9Sstevel@tonic-gate  *	- if both MIN and MAX are set, MAX comes before MIN.
17307c478bd9Sstevel@tonic-gate  */
17317c478bd9Sstevel@tonic-gate 
17327c478bd9Sstevel@tonic-gate static void
17337c478bd9Sstevel@tonic-gate attrlist_reorder(attrlist **l)
17347c478bd9Sstevel@tonic-gate {
17357c478bd9Sstevel@tonic-gate 	attrlist	**w;
17367c478bd9Sstevel@tonic-gate 	attrlist	*exp = NULL;	/* ATTR_EXPIRE_PASSWORD, if found */
17377c478bd9Sstevel@tonic-gate 	attrlist	*max = NULL;	/* ATTR_MAX, if found */
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	if (*l == NULL || (*l)->next == NULL)
17407c478bd9Sstevel@tonic-gate 		return;		/* order of list with <= one item is ok */
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 	/*
17437c478bd9Sstevel@tonic-gate 	 * We simply walk the list, take off the EXPIRE and MAX items if
17447c478bd9Sstevel@tonic-gate 	 * they appear, and put them (first MAX, them EXPIRE) at the end
17457c478bd9Sstevel@tonic-gate 	 * of the list.
17467c478bd9Sstevel@tonic-gate 	 */
17477c478bd9Sstevel@tonic-gate 	w = l;
17487c478bd9Sstevel@tonic-gate 	while (*w != NULL) {
17497c478bd9Sstevel@tonic-gate 		if ((*w)->type == ATTR_EXPIRE_PASSWORD) {
17507c478bd9Sstevel@tonic-gate 			exp = *w;
17517c478bd9Sstevel@tonic-gate 			*w = (*w)->next;
17527c478bd9Sstevel@tonic-gate 		} else if ((*w)->type == ATTR_MAX) {
17537c478bd9Sstevel@tonic-gate 			max = *w;
17547c478bd9Sstevel@tonic-gate 			*w = (*w)->next;
17557c478bd9Sstevel@tonic-gate 		} else
17567c478bd9Sstevel@tonic-gate 			w = &(*w)->next;
17577c478bd9Sstevel@tonic-gate 	}
17587c478bd9Sstevel@tonic-gate 
17597c478bd9Sstevel@tonic-gate 	/* 'w' points to the address of the 'next' field of the last element */
17607c478bd9Sstevel@tonic-gate 
17617c478bd9Sstevel@tonic-gate 	if (max) {
17627c478bd9Sstevel@tonic-gate 		*w = max;
17637c478bd9Sstevel@tonic-gate 		w = &max->next;
17647c478bd9Sstevel@tonic-gate 	}
17657c478bd9Sstevel@tonic-gate 	if (exp) {
17667c478bd9Sstevel@tonic-gate 		*w = exp;
17677c478bd9Sstevel@tonic-gate 		w = &exp->next;
17687c478bd9Sstevel@tonic-gate 	}
17697c478bd9Sstevel@tonic-gate 	*w = NULL;
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate 
17727c478bd9Sstevel@tonic-gate void
1773*49335bdeSbasabi rusage(void)
17747c478bd9Sstevel@tonic-gate {
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate #define	MSG(a) (void) fprintf(stderr, gettext((a)));
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate 	MSG("usage:\n");
17797c478bd9Sstevel@tonic-gate 	MSG("\tpasswd [-r files | -r nis | -r nisplus | -r ldap] [name]\n");
17807c478bd9Sstevel@tonic-gate 	MSG("\tpasswd [-r files] [-egh] [name]\n");
17817c478bd9Sstevel@tonic-gate 	MSG("\tpasswd [-r files] -sa\n");
17827c478bd9Sstevel@tonic-gate 	MSG("\tpasswd [-r files] -s [name]\n");
17837c478bd9Sstevel@tonic-gate 	MSG("\tpasswd [-r files] [-d|-l|-N|-u] [-f] [-n min] [-w warn] "
17847c478bd9Sstevel@tonic-gate 	    "[-x max] name\n");
17857c478bd9Sstevel@tonic-gate 	MSG("\tpasswd -r nis [-eg] [name]\n");
17867c478bd9Sstevel@tonic-gate 	MSG("\tpasswd -r nisplus [-egh] [-D domainname] [name]\n");
17877c478bd9Sstevel@tonic-gate 	MSG("\tpasswd -r nisplus -sa\n");
17887c478bd9Sstevel@tonic-gate 	MSG("\tpasswd -r nisplus [-D domainname] -s [name]\n");
17897c478bd9Sstevel@tonic-gate 	MSG("\tpasswd -r nisplus [-D domainname] [-l|-N|-u] [-f] [-n min] "
17907c478bd9Sstevel@tonic-gate 	    "[-w warn]\n");
17917c478bd9Sstevel@tonic-gate 	MSG("\t\t[-x max] name\n");
17927c478bd9Sstevel@tonic-gate 	MSG("\tpasswd -r ldap [-egh] [name]\n");
17937c478bd9Sstevel@tonic-gate #undef MSG
17947c478bd9Sstevel@tonic-gate }
1795