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