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 5*dd1104fbSMichen Chang * Common Development and Distribution License (the "License"). 6*dd1104fbSMichen 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 /* 22*dd1104fbSMichen Chang * Copyright 2009 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 extern nis_name nis_local_directory(void); 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate extern void setusershell(void); 1977c478bd9Sstevel@tonic-gate extern char *getusershell(void); 1987c478bd9Sstevel@tonic-gate extern void endusershell(void); 1997c478bd9Sstevel@tonic-gate 20049335bdeSbasabi static void passwd_exit(int retcode) __NORETURN; 2017c478bd9Sstevel@tonic-gate static void rusage(void); 2027c478bd9Sstevel@tonic-gate static int ckuid(void); 2037c478bd9Sstevel@tonic-gate static int ckarg(int argc, char **argv, attrlist **attributes); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate static int get_namelist(pwu_repository_t, char ***, int *); 2067c478bd9Sstevel@tonic-gate static int get_namelist_files(char ***, int *); 207*dd1104fbSMichen Chang static int get_namelist_local(char ***, int *); 2087c478bd9Sstevel@tonic-gate static int get_attr(char *, pwu_repository_t *, attrlist **); 2097c478bd9Sstevel@tonic-gate static void display_attr(char *, attrlist *); 2107c478bd9Sstevel@tonic-gate static void free_attr(attrlist *); 2117c478bd9Sstevel@tonic-gate static void attrlist_add(attrlist **, attrtype, char *); 2127c478bd9Sstevel@tonic-gate static void attrlist_reorder(attrlist **); 2137c478bd9Sstevel@tonic-gate static char *userinput(char *, pwu_repository_t *, attrtype); 2147c478bd9Sstevel@tonic-gate static char *getresponse(char *); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * main(): 2187c478bd9Sstevel@tonic-gate * The main routine will call ckarg() to parse the command line 2197c478bd9Sstevel@tonic-gate * arguments and call the appropriate functions to perform the 2207c478bd9Sstevel@tonic-gate * tasks specified by the arguments. It allows system 2217c478bd9Sstevel@tonic-gate * administrator to add, change and display password attributes. 2227c478bd9Sstevel@tonic-gate * Non privileged user can change password or display 2237c478bd9Sstevel@tonic-gate * password attributes which corresponds to their login name. 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate 22649335bdeSbasabi int 22749335bdeSbasabi main(int argc, char *argv[]) 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate int flag; 2317c478bd9Sstevel@tonic-gate char **namelist; 2327c478bd9Sstevel@tonic-gate int num_user; 2337c478bd9Sstevel@tonic-gate int i; 2347c478bd9Sstevel@tonic-gate attrlist *attributes = NULL; 2357c478bd9Sstevel@tonic-gate char *input; 2367c478bd9Sstevel@tonic-gate int tries = 1; 2377c478bd9Sstevel@tonic-gate int updated_reps; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (prognamep = strrchr(argv[0], '/')) 2417c478bd9Sstevel@tonic-gate ++prognamep; 2427c478bd9Sstevel@tonic-gate else 2437c478bd9Sstevel@tonic-gate prognamep = argv[0]; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate auth_rep.type = NULL; 2467c478bd9Sstevel@tonic-gate auth_rep.scope = NULL; 2477c478bd9Sstevel@tonic-gate repository.type = NULL; 2487c478bd9Sstevel@tonic-gate repository.scope = NULL; 2497c478bd9Sstevel@tonic-gate repository.scope_len = 0; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* initialization for variables, set locale and textdomain */ 2537c478bd9Sstevel@tonic-gate i = 0; 2547c478bd9Sstevel@tonic-gate flag = 0; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate uid = getuid(); /* get the user id */ 2577c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 2607c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 2617c478bd9Sstevel@tonic-gate #endif 2627c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * ckarg() parses the arguments. In case of an error, 2667c478bd9Sstevel@tonic-gate * it sets the retval and returns FAIL (-1). 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate flag = ckarg(argc, argv, &attributes); 2707c478bd9Sstevel@tonic-gate dprintf1("flag is %0x\n", flag); 2717c478bd9Sstevel@tonic-gate if (flag == FAIL) 2727c478bd9Sstevel@tonic-gate passwd_exit(retval); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate argc -= optind; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (argc < 1) { 2777c478bd9Sstevel@tonic-gate if ((usrname = getlogin()) == NULL) { 2787c478bd9Sstevel@tonic-gate struct passwd *pass = getpwuid(uid); 2797c478bd9Sstevel@tonic-gate if (pass != NULL) 2807c478bd9Sstevel@tonic-gate usrname = pass->pw_name; 2817c478bd9Sstevel@tonic-gate else { 2827c478bd9Sstevel@tonic-gate rusage(); 2837c478bd9Sstevel@tonic-gate exit(NOPERM); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } else if (flag == 0) { 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * If flag is zero, change passwd. 2887c478bd9Sstevel@tonic-gate * Otherwise, it will display or 2897c478bd9Sstevel@tonic-gate * modify password aging attributes 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_INFO), prognamep, 2927c478bd9Sstevel@tonic-gate usrname); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate } else 2957c478bd9Sstevel@tonic-gate usrname = argv[optind]; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (pam_start("passwd", usrname, &pam_conv, &pamh) != PAM_SUCCESS) 2987c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate auth_rep.type = repository.type; 3017c478bd9Sstevel@tonic-gate auth_rep.scope = repository.scope; 3027c478bd9Sstevel@tonic-gate auth_rep.scope_len = repository.scope_len; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate if (auth_rep.type != NULL) { 3057c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_REPOSITORY, (void *)&auth_rep) 3067c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 3077c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (flag == SAFLAG) { /* display password attributes for all users */ 3127c478bd9Sstevel@tonic-gate retval = get_namelist(repository, &namelist, &num_user); 3137c478bd9Sstevel@tonic-gate if (retval != SUCCESS) 3147c478bd9Sstevel@tonic-gate (void) passwd_exit(retval); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate if (num_user == 0) { 3177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamep, 3187c478bd9Sstevel@tonic-gate gettext(MSG_FF)); 3197c478bd9Sstevel@tonic-gate passwd_exit(FATAL); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate i = 0; 3227c478bd9Sstevel@tonic-gate while (namelist[i] != NULL) { 3237c478bd9Sstevel@tonic-gate (void) get_attr(namelist[i], &repository, 3247c478bd9Sstevel@tonic-gate &attributes); 3257c478bd9Sstevel@tonic-gate (void) display_attr(namelist[i], attributes); 3267c478bd9Sstevel@tonic-gate (void) free(namelist[i]); 3277c478bd9Sstevel@tonic-gate (void) free_attr(attributes); 3287c478bd9Sstevel@tonic-gate i++; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate (void) free(namelist); 3317c478bd9Sstevel@tonic-gate passwd_exit(SUCCESS); 3327c478bd9Sstevel@tonic-gate } else if (flag == SFLAG) { /* display password attributes by user */ 3337c478bd9Sstevel@tonic-gate if (get_attr(usrname, &repository, &attributes) == 3347c478bd9Sstevel@tonic-gate PWU_SUCCESS) { 3357c478bd9Sstevel@tonic-gate (void) display_attr(usrname, attributes); 3367c478bd9Sstevel@tonic-gate (void) free_attr(attributes); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate passwd_exit(SUCCESS); 3397c478bd9Sstevel@tonic-gate /* NOT REACHED */ 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate switch (pam_authenticate(pamh, 0)) { 3447c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 3457c478bd9Sstevel@tonic-gate break; 3467c478bd9Sstevel@tonic-gate case PAM_USER_UNKNOWN: 3477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep, 3487c478bd9Sstevel@tonic-gate usrname); 3497c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 3507c478bd9Sstevel@tonic-gate break; 3517c478bd9Sstevel@tonic-gate case PAM_PERM_DENIED: 3527c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate case PAM_AUTH_ERR: 3557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_SORRY), prognamep); 3567c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 3577c478bd9Sstevel@tonic-gate break; 3587c478bd9Sstevel@tonic-gate default: 3597c478bd9Sstevel@tonic-gate /* system error */ 3607c478bd9Sstevel@tonic-gate passwd_exit(FMERR); 3617c478bd9Sstevel@tonic-gate break; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if (flag == 0) { /* changing user password */ 3657c478bd9Sstevel@tonic-gate int chk_authtok = 0; /* check password strength */ 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate dprintf1("call pam_chauthtok() repository name =%s\n", 3687c478bd9Sstevel@tonic-gate repository.type); 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* Set up for Audit */ 3717c478bd9Sstevel@tonic-gate if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 3727c478bd9Sstevel@tonic-gate perror("adt_start_session"); 3737c478bd9Sstevel@tonic-gate passwd_exit(SYSERR); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate if ((event = adt_alloc_event(ah, ADT_passwd)) == NULL) { 3767c478bd9Sstevel@tonic-gate perror("adt_alloc_event"); 3777c478bd9Sstevel@tonic-gate passwd_exit(NOMEM); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate if (argc >= 1) { 3807c478bd9Sstevel@tonic-gate /* save target user */ 3817c478bd9Sstevel@tonic-gate event->adt_passwd.username = usrname; 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* Don't check account expiration when invoked by root */ 3857c478bd9Sstevel@tonic-gate if (ckuid() != SUCCESS) { 3867c478bd9Sstevel@tonic-gate pam_retval = pam_acct_mgmt(pamh, PAM_SILENT); 3877c478bd9Sstevel@tonic-gate switch (pam_retval) { 3887c478bd9Sstevel@tonic-gate case PAM_ACCT_EXPIRED: 3897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3907c478bd9Sstevel@tonic-gate gettext(MSG_ACCOUNT_EXP), usrname); 3917c478bd9Sstevel@tonic-gate passwd_exit(EXPIRED); 3927c478bd9Sstevel@tonic-gate break; 3937c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_EXPIRED: 3947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3957c478bd9Sstevel@tonic-gate gettext(MSG_AUTHTOK_EXP)); 3967c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 3977c478bd9Sstevel@tonic-gate break; 3987c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD: 3997c478bd9Sstevel@tonic-gate /* valid error when changing passwords */ 4007c478bd9Sstevel@tonic-gate break; 4017c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 4027c478bd9Sstevel@tonic-gate /* Ok to change password */ 4037c478bd9Sstevel@tonic-gate break; 4047c478bd9Sstevel@tonic-gate default: 4057c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate pam_retval = PAM_AUTHTOK_ERR; 4117c478bd9Sstevel@tonic-gate tries = 1; 4127c478bd9Sstevel@tonic-gate if (ckuid() == SUCCESS) { 4137c478bd9Sstevel@tonic-gate /* bypass password strength checks */ 4147c478bd9Sstevel@tonic-gate chk_authtok = PAM_NO_AUTHTOK_CHECK; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate while (pam_retval == PAM_AUTHTOK_ERR && tries <= DEF_ATTEMPTS) { 4187c478bd9Sstevel@tonic-gate if (tries > 1) 4197c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_AGAIN)); 4207c478bd9Sstevel@tonic-gate pam_retval = pam_chauthtok(pamh, chk_authtok); 4217c478bd9Sstevel@tonic-gate if (pam_retval == PAM_TRY_AGAIN) { 4227c478bd9Sstevel@tonic-gate (void) sleep(1); 4237c478bd9Sstevel@tonic-gate pam_retval = pam_chauthtok(pamh, chk_authtok); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate tries++; 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate switch (pam_retval) { 4297c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 4307c478bd9Sstevel@tonic-gate retval = SUCCESS; 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_DISABLE_AGING: 4337c478bd9Sstevel@tonic-gate retval = BADAGE; 4347c478bd9Sstevel@tonic-gate break; 4357c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_LOCK_BUSY: 4367c478bd9Sstevel@tonic-gate retval = FBUSY; 4377c478bd9Sstevel@tonic-gate break; 4387c478bd9Sstevel@tonic-gate case PAM_TRY_AGAIN: 4397c478bd9Sstevel@tonic-gate retval = FBUSY; 4407c478bd9Sstevel@tonic-gate break; 4417c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_ERR: 4427c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_RECOVERY_ERR: 4437c478bd9Sstevel@tonic-gate default: 4447c478bd9Sstevel@tonic-gate retval = NOPERM; 4457c478bd9Sstevel@tonic-gate break; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate (void) passwd_exit(retval); 4497c478bd9Sstevel@tonic-gate /* NOT REACHED */ 4507c478bd9Sstevel@tonic-gate } else { /* changing attributes */ 4517c478bd9Sstevel@tonic-gate switch (flag) { 4527c478bd9Sstevel@tonic-gate case EFLAG: /* changing user password attributes */ 4537c478bd9Sstevel@tonic-gate input = userinput(usrname, &repository, ATTR_SHELL); 4547c478bd9Sstevel@tonic-gate if (input) 4557c478bd9Sstevel@tonic-gate attrlist_add(&attributes, ATTR_SHELL, input); 4567c478bd9Sstevel@tonic-gate else 4577c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_SHELL_UNCHANGED)); 4587c478bd9Sstevel@tonic-gate break; 4597c478bd9Sstevel@tonic-gate case GFLAG: 4607c478bd9Sstevel@tonic-gate input = userinput(usrname, &repository, ATTR_GECOS); 4617c478bd9Sstevel@tonic-gate if (input) 4627c478bd9Sstevel@tonic-gate attrlist_add(&attributes, ATTR_GECOS, input); 4637c478bd9Sstevel@tonic-gate else 4647c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_GECOS_UNCHANGED)); 4657c478bd9Sstevel@tonic-gate break; 4667c478bd9Sstevel@tonic-gate case HFLAG: 4677c478bd9Sstevel@tonic-gate input = userinput(usrname, &repository, ATTR_HOMEDIR); 4687c478bd9Sstevel@tonic-gate if (input) 4697c478bd9Sstevel@tonic-gate attrlist_add(&attributes, ATTR_HOMEDIR, input); 4707c478bd9Sstevel@tonic-gate else 4717c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_DIR_UNCHANGED)); 4727c478bd9Sstevel@tonic-gate break; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if (attributes != NULL) { 4767c478bd9Sstevel@tonic-gate retval = __set_authtoken_attr(usrname, 4777c478bd9Sstevel@tonic-gate pamh->ps_item[PAM_AUTHTOK].pi_addr, 4787c478bd9Sstevel@tonic-gate NULL, &repository, attributes, &updated_reps); 4797c478bd9Sstevel@tonic-gate switch (retval) { 4807c478bd9Sstevel@tonic-gate case PWU_SUCCESS: 4817c478bd9Sstevel@tonic-gate for (i = 1; i <= REP_LAST; i <<= 1) { 4827c478bd9Sstevel@tonic-gate if ((updated_reps & i) == 0) 4837c478bd9Sstevel@tonic-gate continue; 4847c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_SUCCESS), 4857c478bd9Sstevel@tonic-gate prognamep, usrname); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate retval = SUCCESS; 4887c478bd9Sstevel@tonic-gate break; 4897c478bd9Sstevel@tonic-gate case PWU_AGING_DISABLED: 4907c478bd9Sstevel@tonic-gate retval = BADAGE; 4917c478bd9Sstevel@tonic-gate break; 4927c478bd9Sstevel@tonic-gate default: 4937c478bd9Sstevel@tonic-gate retval = NOPERM; 4947c478bd9Sstevel@tonic-gate break; 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate } else { 4977c478bd9Sstevel@tonic-gate retval = SUCCESS; /* nothing to change won't fail */ 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate (void) passwd_exit(retval); 5007c478bd9Sstevel@tonic-gate } 50149335bdeSbasabi /* NOTREACHED */ 50249335bdeSbasabi return (0); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * Get a line of input from the user. 5077c478bd9Sstevel@tonic-gate * 5087c478bd9Sstevel@tonic-gate * If the line is empty, or the input equals 'oldval', NULL is returned. 5097c478bd9Sstevel@tonic-gate * therwise, a malloced string containing the input (minus the trailing 5107c478bd9Sstevel@tonic-gate * newline) is returned. 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate char * 5137c478bd9Sstevel@tonic-gate getresponse(char *oldval) 5147c478bd9Sstevel@tonic-gate { 5157c478bd9Sstevel@tonic-gate char resp[MAX_INPUT_LEN]; 5167c478bd9Sstevel@tonic-gate char *retval = NULL; 5177c478bd9Sstevel@tonic-gate int resplen; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate (void) fgets(resp, sizeof (resp) - 1, stdin); 5207c478bd9Sstevel@tonic-gate resplen = strlen(resp) - 1; 5217c478bd9Sstevel@tonic-gate if (resp[resplen] == '\n') 5227c478bd9Sstevel@tonic-gate resp[resplen] = '\0'; 5237c478bd9Sstevel@tonic-gate if (*resp != '\0' && strcmp(resp, oldval) != 0) 5247c478bd9Sstevel@tonic-gate retval = strdup(resp); 5257c478bd9Sstevel@tonic-gate return (retval); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * char *userinput(item) 5307c478bd9Sstevel@tonic-gate * 5317c478bd9Sstevel@tonic-gate * user conversation function. The old value of attribute "item" is 5327c478bd9Sstevel@tonic-gate * displayed while the user is asked to provide a new value. 5337c478bd9Sstevel@tonic-gate * 5347c478bd9Sstevel@tonic-gate * returns a malloc()-ed string if the user actualy provided input 5357c478bd9Sstevel@tonic-gate * or NULL if the user simply hit return or the input equals the old 5367c478bd9Sstevel@tonic-gate * value (not changed). 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate char * 5397c478bd9Sstevel@tonic-gate userinput(char *name, pwu_repository_t *rep, attrtype type) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate attrlist oldattr; 5427c478bd9Sstevel@tonic-gate char *oldval; /* shorthand for oldattr.data.val_s */ 5437c478bd9Sstevel@tonic-gate char *valid; /* points to valid shells */ 5447c478bd9Sstevel@tonic-gate char *response; 5457c478bd9Sstevel@tonic-gate char *cp; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate oldattr.type = type; 5487c478bd9Sstevel@tonic-gate oldattr.next = NULL; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate if (__get_authtoken_attr(name, rep, &oldattr) != PWU_SUCCESS) 5517c478bd9Sstevel@tonic-gate passwd_exit(FMERR); 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate oldval = oldattr.data.val_s; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (type == ATTR_SHELL) { 5567c478bd9Sstevel@tonic-gate /* No current shell: set DEFSHL as default choice */ 5577c478bd9Sstevel@tonic-gate if (*oldval == '\0') { 5587c478bd9Sstevel@tonic-gate free(oldval); 5597c478bd9Sstevel@tonic-gate oldval = strdup(DEFSHL); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (ckuid() != SUCCESS) { 5637c478bd9Sstevel@tonic-gate /* User must currently have a valid shell */ 5647c478bd9Sstevel@tonic-gate setusershell(); 5657c478bd9Sstevel@tonic-gate valid = getusershell(); 5667c478bd9Sstevel@tonic-gate while (valid && strcmp(valid, oldval) != 0) 5677c478bd9Sstevel@tonic-gate valid = getusershell(); 5687c478bd9Sstevel@tonic-gate endusershell(); 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate if (valid == NULL) { 5717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_RS), oldval); 5727c478bd9Sstevel@tonic-gate free(oldval); 5737c478bd9Sstevel@tonic-gate return (NULL); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_OLDSHELL), oldval); 5777c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_NEWSHELL)); 5787c478bd9Sstevel@tonic-gate (void) fflush(stdout); 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate response = getresponse(oldval); 5817c478bd9Sstevel@tonic-gate free(oldval); /* We don't need the old value anymore */ 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if (response == NULL || *response == '\0') 5847c478bd9Sstevel@tonic-gate return (NULL); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* Make sure new shell is listed */ 5877c478bd9Sstevel@tonic-gate setusershell(); 5887c478bd9Sstevel@tonic-gate valid = getusershell(); 5897c478bd9Sstevel@tonic-gate while (valid) { 5907c478bd9Sstevel@tonic-gate char *cp; 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate /* Allow user to give shell without path */ 5937c478bd9Sstevel@tonic-gate if (*response == '/') { 5947c478bd9Sstevel@tonic-gate cp = valid; 5957c478bd9Sstevel@tonic-gate } else { 5967c478bd9Sstevel@tonic-gate if ((cp = strrchr(valid, '/')) == NULL) 5977c478bd9Sstevel@tonic-gate cp = valid; 5987c478bd9Sstevel@tonic-gate else 5997c478bd9Sstevel@tonic-gate cp++; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate if (strcmp(cp, response) == 0) { 6027c478bd9Sstevel@tonic-gate if (*response != '/') { 6037c478bd9Sstevel@tonic-gate /* take shell name including path */ 6047c478bd9Sstevel@tonic-gate free(response); 6057c478bd9Sstevel@tonic-gate response = strdup(valid); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate valid = getusershell(); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate endusershell(); 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate if (valid == NULL) { /* No valid shell matches */ 6147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNACCEPT), response); 6157c478bd9Sstevel@tonic-gate return (NULL); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate if (access(response, X_OK) < 0) 6197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNAVAIL), response); 6207c478bd9Sstevel@tonic-gate return (response); 6217c478bd9Sstevel@tonic-gate /* NOT REACHED */ 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * if type == SHELL, we have returned by now. Only GECOS and 6257c478bd9Sstevel@tonic-gate * HOMEDIR get to this point. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_INPUTHDR)); 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * PRE: oldval points to malloced string with Old Value 6317c478bd9Sstevel@tonic-gate * INV: oldval remains unchanged 6327c478bd9Sstevel@tonic-gate * POST:response points to valid string or NULL. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate for (;;) { 6357c478bd9Sstevel@tonic-gate if (type == ATTR_GECOS) 6367c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_NAME), oldval); 6377c478bd9Sstevel@tonic-gate else if (type == ATTR_HOMEDIR) 6387c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_HOMEDIR), oldval); 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate response = getresponse(oldval); 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate if (response && strcmp(response, "none") == 0) 6437c478bd9Sstevel@tonic-gate *response = '\0'; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /* No-change or empty string are OK */ 6467c478bd9Sstevel@tonic-gate if (response == NULL || *response == '\0') 6477c478bd9Sstevel@tonic-gate break; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* Check for illegal characters */ 6507c478bd9Sstevel@tonic-gate if (strchr(response, ':')) { 6517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s", gettext(MSG_COLON)); 6527c478bd9Sstevel@tonic-gate free(response); 6537c478bd9Sstevel@tonic-gate } else if (strlen(response) > MAX_INPUT_LEN - 1) { 6547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_MAXLEN), 6557c478bd9Sstevel@tonic-gate MAX_INPUT_LEN); 6567c478bd9Sstevel@tonic-gate free(response); 6577c478bd9Sstevel@tonic-gate } else { 6587c478bd9Sstevel@tonic-gate /* don't allow control characters */ 6597c478bd9Sstevel@tonic-gate for (cp = response; *cp >= 040; cp++) 6607c478bd9Sstevel@tonic-gate ; 6617c478bd9Sstevel@tonic-gate if (*cp != '\0') { 6627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_CONTROL)); 6637c478bd9Sstevel@tonic-gate free(response); 6647c478bd9Sstevel@tonic-gate } else 6657c478bd9Sstevel@tonic-gate break; /* response is a valid string */ 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * We only get here if the input was invalid. 6697c478bd9Sstevel@tonic-gate * In that case, we again ask the user for input. 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate free(oldval); 6737c478bd9Sstevel@tonic-gate return (response); 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * ckarg(): 6777c478bd9Sstevel@tonic-gate * This function parses and verifies the 6787c478bd9Sstevel@tonic-gate * arguments. It takes three parameters: 6797c478bd9Sstevel@tonic-gate * argc => # of arguments 6807c478bd9Sstevel@tonic-gate * argv => pointer to an argument 6817c478bd9Sstevel@tonic-gate * attrlist => pointer to list of password attributes 6827c478bd9Sstevel@tonic-gate */ 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate static int 6857c478bd9Sstevel@tonic-gate ckarg(int argc, char **argv, attrlist **attributes) 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate extern char *optarg; 6887c478bd9Sstevel@tonic-gate char *char_p; 6897c478bd9Sstevel@tonic-gate int opt; 6907c478bd9Sstevel@tonic-gate int flag; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate flag = 0; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:D:N")) != EOF) { 6957c478bd9Sstevel@tonic-gate switch (opt) { 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate case 'r': /* Repository Specified */ 6987c478bd9Sstevel@tonic-gate /* repository: this option should be specified first */ 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if (repository.type != NULL) { 7017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7027c478bd9Sstevel@tonic-gate "Repository is already defined or specified.\n")); 7037c478bd9Sstevel@tonic-gate rusage(); 7047c478bd9Sstevel@tonic-gate retval = BADSYN; 7057c478bd9Sstevel@tonic-gate return (FAIL); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate if (strcmp(optarg, "nisplus") == 0) { 7087c478bd9Sstevel@tonic-gate repository.type = optarg; 7097c478bd9Sstevel@tonic-gate repository.scope = nis_local_directory(); 7107c478bd9Sstevel@tonic-gate if (repository.scope != NULL) { 7117c478bd9Sstevel@tonic-gate repository.scope_len = 7127c478bd9Sstevel@tonic-gate strlen(repository.scope)+ 1; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "nis") == 0) { 7157c478bd9Sstevel@tonic-gate repository.type = optarg; 7167c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "ldap") == 0) { 7177c478bd9Sstevel@tonic-gate repository.type = optarg; 7187c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "files") == 0) { 7197c478bd9Sstevel@tonic-gate repository.type = optarg; 7207c478bd9Sstevel@tonic-gate } else { 7217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7227c478bd9Sstevel@tonic-gate gettext("invalid repository: %s\n"), 7237c478bd9Sstevel@tonic-gate optarg); 7247c478bd9Sstevel@tonic-gate rusage(); 7257c478bd9Sstevel@tonic-gate retval = BADSYN; 7267c478bd9Sstevel@tonic-gate return (FAIL); 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate break; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate case 'd': /* Delete Auth Token */ 7317c478bd9Sstevel@tonic-gate /* if no repository the default for -d is files */ 7327c478bd9Sstevel@tonic-gate if (repository.type == NULL) 7337c478bd9Sstevel@tonic-gate repository = __REPFILES; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* 7367c478bd9Sstevel@tonic-gate * Delete the password - only privileged processes 737*dd1104fbSMichen Chang * can execute this for FILES or LDAP 7387c478bd9Sstevel@tonic-gate */ 739*dd1104fbSMichen Chang if (IS_FILES(repository) == FALSE && 740*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE) { 7417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 742*dd1104fbSMichen Chang "-d only applies to files " 743*dd1104fbSMichen Chang "or ldap repository\n")); 7447c478bd9Sstevel@tonic-gate rusage(); /* exit */ 7457c478bd9Sstevel@tonic-gate retval = BADSYN; 7467c478bd9Sstevel@tonic-gate return (FAIL); 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (ckuid() != SUCCESS) { 7507c478bd9Sstevel@tonic-gate retval = NOPERM; 7517c478bd9Sstevel@tonic-gate return (FAIL); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG)) { 7547c478bd9Sstevel@tonic-gate rusage(); 7557c478bd9Sstevel@tonic-gate retval = BADOPT; 7567c478bd9Sstevel@tonic-gate return (FAIL); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate flag |= DFLAG; 7597c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_PASSWD, NULL); 7607c478bd9Sstevel@tonic-gate break; 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate case 'N': /* set account to be "no login" */ 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate /* if no repository the default for -N is files */ 7657c478bd9Sstevel@tonic-gate if (repository.type == NULL) 7667c478bd9Sstevel@tonic-gate repository = __REPFILES; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 769*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 7707c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 7717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 772*dd1104fbSMichen Chang "-N only applies to files, ldap or " 773*dd1104fbSMichen Chang "nisplus repository\n")); 7747c478bd9Sstevel@tonic-gate rusage(); /* exit */ 7757c478bd9Sstevel@tonic-gate retval = BADOPT; 7767c478bd9Sstevel@tonic-gate return (FAIL); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * Only privileged processes can execute this 781*dd1104fbSMichen Chang * for FILES or LDAP 7827c478bd9Sstevel@tonic-gate */ 783*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 7847c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 7857c478bd9Sstevel@tonic-gate return (FAIL); 7867c478bd9Sstevel@tonic-gate if (flag & (MUTEXFLAG|NONAGEFLAG)) { 7877c478bd9Sstevel@tonic-gate rusage(); /* exit */ 7887c478bd9Sstevel@tonic-gate retval = BADOPT; 7897c478bd9Sstevel@tonic-gate return (FAIL); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate flag |= XFLAG; 7927c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_NOLOGIN_ACCOUNT, NULL); 7937c478bd9Sstevel@tonic-gate break; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate case 'l': /* lock the password */ 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* if no repository the default for -l is files */ 7987c478bd9Sstevel@tonic-gate if (repository.type == NULL) 7997c478bd9Sstevel@tonic-gate repository = __REPFILES; 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 802*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 8037c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 8047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 805*dd1104fbSMichen Chang "-l only applies to files, ldap or " 806*dd1104fbSMichen Chang "nisplus repository\n")); 8077c478bd9Sstevel@tonic-gate rusage(); /* exit */ 8087c478bd9Sstevel@tonic-gate retval = BADOPT; 8097c478bd9Sstevel@tonic-gate return (FAIL); 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * Only privileged processes can execute this 814*dd1104fbSMichen Chang * for FILES or LDAP 8157c478bd9Sstevel@tonic-gate */ 816*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 8177c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 8187c478bd9Sstevel@tonic-gate return (FAIL); 8197c478bd9Sstevel@tonic-gate if (flag & (MUTEXFLAG|NONAGEFLAG)) { 8207c478bd9Sstevel@tonic-gate rusage(); /* exit */ 8217c478bd9Sstevel@tonic-gate retval = BADOPT; 8227c478bd9Sstevel@tonic-gate return (FAIL); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate flag |= LFLAG; 8257c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_LOCK_ACCOUNT, NULL); 8267c478bd9Sstevel@tonic-gate break; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate case 'u': /* unlock the password */ 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate /* if no repository the default for -u is files */ 8317c478bd9Sstevel@tonic-gate if (repository.type == NULL) 8327c478bd9Sstevel@tonic-gate repository = __REPFILES; 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 835*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 8367c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 8377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 838*dd1104fbSMichen Chang "-u only applies to files, ldap or " 839*dd1104fbSMichen Chang "nisplus repository\n")); 8407c478bd9Sstevel@tonic-gate rusage(); /* exit */ 8417c478bd9Sstevel@tonic-gate retval = BADOPT; 8427c478bd9Sstevel@tonic-gate return (FAIL); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate /* 8467c478bd9Sstevel@tonic-gate * Only privileged processes can execute this 847*dd1104fbSMichen Chang * for FILES or LDAP 8487c478bd9Sstevel@tonic-gate */ 849*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 8507c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 8517c478bd9Sstevel@tonic-gate return (FAIL); 8527c478bd9Sstevel@tonic-gate if (flag & (MUTEXFLAG|NONAGEFLAG)) { 8537c478bd9Sstevel@tonic-gate rusage(); /* exit */ 8547c478bd9Sstevel@tonic-gate retval = BADOPT; 8557c478bd9Sstevel@tonic-gate return (FAIL); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate flag |= UFLAG; 8587c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_UNLOCK_ACCOUNT, NULL); 8597c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_RST_FAILED_LOGINS, NULL); 8607c478bd9Sstevel@tonic-gate break; 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate case 'x': /* set the max date */ 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate /* if no repository the default for -x is files */ 8657c478bd9Sstevel@tonic-gate if (repository.type == NULL) 8667c478bd9Sstevel@tonic-gate repository = __REPFILES; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 869*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 8707c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 8717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 872*dd1104fbSMichen Chang "-x only applies to files, ldap or " 873*dd1104fbSMichen Chang "nisplus repository\n")); 8747c478bd9Sstevel@tonic-gate rusage(); /* exit */ 8757c478bd9Sstevel@tonic-gate retval = BADSYN; 8767c478bd9Sstevel@tonic-gate return (FAIL); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate /* 8807c478bd9Sstevel@tonic-gate * Only privileged process can execute this 881*dd1104fbSMichen Chang * for FILES or LDAP 8827c478bd9Sstevel@tonic-gate */ 883*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 884*dd1104fbSMichen Chang (ckuid() != SUCCESS)) { 8857c478bd9Sstevel@tonic-gate retval = NOPERM; 8867c478bd9Sstevel@tonic-gate return (FAIL); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|MFLAG|NONAGEFLAG)) { 8897c478bd9Sstevel@tonic-gate retval = BADOPT; 8907c478bd9Sstevel@tonic-gate return (FAIL); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate flag |= MFLAG; 8937c478bd9Sstevel@tonic-gate if ((int)strlen(optarg) <= 0 || 8947c478bd9Sstevel@tonic-gate (maxdate = strtol(optarg, &char_p, 10)) < -1 || 8957c478bd9Sstevel@tonic-gate *char_p != '\0') { 8967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -x\n", 8977c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 8987c478bd9Sstevel@tonic-gate retval = BADSYN; 8997c478bd9Sstevel@tonic-gate return (FAIL); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MAX, optarg); 9027c478bd9Sstevel@tonic-gate break; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate case 'n': /* set the min date */ 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* if no repository the default for -n is files */ 9077c478bd9Sstevel@tonic-gate if (repository.type == NULL) 9087c478bd9Sstevel@tonic-gate repository = __REPFILES; 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 911*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 9127c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 9137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 914*dd1104fbSMichen Chang "-n only applies to files, ldap or " 915*dd1104fbSMichen Chang "nisplus repository\n")); 9167c478bd9Sstevel@tonic-gate rusage(); /* exit */ 9177c478bd9Sstevel@tonic-gate retval = BADSYN; 9187c478bd9Sstevel@tonic-gate return (FAIL); 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate /* 9227c478bd9Sstevel@tonic-gate * Only privileged process can execute this 923*dd1104fbSMichen Chang * for FILES or LDAP 9247c478bd9Sstevel@tonic-gate */ 925*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 9267c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 9277c478bd9Sstevel@tonic-gate return (FAIL); 9287c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|NFLAG|NONAGEFLAG)) { 9297c478bd9Sstevel@tonic-gate retval = BADOPT; 9307c478bd9Sstevel@tonic-gate return (FAIL); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate flag |= NFLAG; 9337c478bd9Sstevel@tonic-gate if ((int)strlen(optarg) <= 0 || 9347c478bd9Sstevel@tonic-gate (strtol(optarg, &char_p, 10)) < 0 || 9357c478bd9Sstevel@tonic-gate *char_p != '\0') { 9367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -n\n", 9377c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 9387c478bd9Sstevel@tonic-gate retval = BADSYN; 9397c478bd9Sstevel@tonic-gate return (FAIL); 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MIN, optarg); 9427c478bd9Sstevel@tonic-gate break; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate case 'w': /* set the warning field */ 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate /* if no repository the default for -w is files */ 9477c478bd9Sstevel@tonic-gate if (repository.type == NULL) 9487c478bd9Sstevel@tonic-gate repository = __REPFILES; 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 951*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 9527c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 9537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 954*dd1104fbSMichen Chang "-w only applies to files, ldap or " 955*dd1104fbSMichen Chang "nisplus repository\n")); 9567c478bd9Sstevel@tonic-gate rusage(); /* exit */ 9577c478bd9Sstevel@tonic-gate retval = BADSYN; 9587c478bd9Sstevel@tonic-gate return (FAIL); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * Only privileged process can execute this 963*dd1104fbSMichen Chang * for FILES or LDAP 9647c478bd9Sstevel@tonic-gate */ 965*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 966*dd1104fbSMichen Chang (ckuid() != SUCCESS)) { 9677c478bd9Sstevel@tonic-gate retval = NOPERM; 9687c478bd9Sstevel@tonic-gate return (FAIL); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|WFLAG|NONAGEFLAG)) { 9717c478bd9Sstevel@tonic-gate retval = BADOPT; 9727c478bd9Sstevel@tonic-gate return (FAIL); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate flag |= WFLAG; 9757c478bd9Sstevel@tonic-gate if ((int)strlen(optarg) <= 0 || 9767c478bd9Sstevel@tonic-gate (strtol(optarg, &char_p, 10)) < 0 || 9777c478bd9Sstevel@tonic-gate *char_p != '\0') { 9787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -w\n", 9797c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 9807c478bd9Sstevel@tonic-gate retval = BADSYN; 9817c478bd9Sstevel@tonic-gate return (FAIL); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_WARN, optarg); 9847c478bd9Sstevel@tonic-gate break; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate case 's': /* display password attributes */ 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate /* if no repository the default for -s is files */ 9897c478bd9Sstevel@tonic-gate if (repository.type == NULL) 9907c478bd9Sstevel@tonic-gate repository = __REPFILES; 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate /* display password attributes */ 9947c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 995*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 9967c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 9977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 998*dd1104fbSMichen Chang "-s only applies to files, ldap or " 999*dd1104fbSMichen Chang "nisplus repository\n")); 10007c478bd9Sstevel@tonic-gate rusage(); /* exit */ 10017c478bd9Sstevel@tonic-gate retval = BADSYN; 10027c478bd9Sstevel@tonic-gate return (FAIL); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1007*dd1104fbSMichen Chang * for FILES or LDAP 10087c478bd9Sstevel@tonic-gate */ 1009*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 10107c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 10117c478bd9Sstevel@tonic-gate return (FAIL); 10127c478bd9Sstevel@tonic-gate if (flag && (flag != AFLAG)) { 10137c478bd9Sstevel@tonic-gate retval = BADOPT; 10147c478bd9Sstevel@tonic-gate return (FAIL); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate flag |= SFLAG; 10177c478bd9Sstevel@tonic-gate break; 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate case 'a': /* display password attributes */ 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* if no repository the default for -a is files */ 10227c478bd9Sstevel@tonic-gate if (repository.type == NULL) 10237c478bd9Sstevel@tonic-gate repository = __REPFILES; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 1026*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 10277c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 10287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1029*dd1104fbSMichen Chang "-a only applies to files, ldap or " 1030*dd1104fbSMichen Chang "nisplus repository\n")); 10317c478bd9Sstevel@tonic-gate rusage(); /* exit */ 10327c478bd9Sstevel@tonic-gate retval = BADSYN; 10337c478bd9Sstevel@tonic-gate return (FAIL); 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate /* 10377c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1038*dd1104fbSMichen Chang * for FILES or LDAP 10397c478bd9Sstevel@tonic-gate */ 1040*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 10417c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 10427c478bd9Sstevel@tonic-gate return (FAIL); 10437c478bd9Sstevel@tonic-gate if (flag && (flag != SFLAG)) { 10447c478bd9Sstevel@tonic-gate retval = BADOPT; 10457c478bd9Sstevel@tonic-gate return (FAIL); 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate flag |= AFLAG; 10487c478bd9Sstevel@tonic-gate break; 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate case 'f': /* expire password attributes */ 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate /* if no repository the default for -f is files */ 10537c478bd9Sstevel@tonic-gate if (repository.type == NULL) 10547c478bd9Sstevel@tonic-gate repository = __REPFILES; 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 1057*dd1104fbSMichen Chang IS_LDAP(repository) == FALSE && 10587c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 10597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1060*dd1104fbSMichen Chang "-f only applies to files, ldap or " 1061*dd1104fbSMichen Chang "nisplus repository\n")); 10627c478bd9Sstevel@tonic-gate rusage(); /* exit */ 10637c478bd9Sstevel@tonic-gate retval = BADSYN; 10647c478bd9Sstevel@tonic-gate return (FAIL); 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate /* 10687c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1069*dd1104fbSMichen Chang * for FILES or LDAP 10707c478bd9Sstevel@tonic-gate */ 1071*dd1104fbSMichen Chang if ((IS_FILES(repository) || IS_LDAP(repository)) && 10727c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 10737c478bd9Sstevel@tonic-gate return (FAIL); 10747c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|FFLAG|NONAGEFLAG)) { 10757c478bd9Sstevel@tonic-gate retval = BADOPT; 10767c478bd9Sstevel@tonic-gate return (FAIL); 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate flag |= FFLAG; 10797c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_EXPIRE_PASSWORD, NULL); 10807c478bd9Sstevel@tonic-gate break; 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate case 'D': /* domain name specified */ 10837c478bd9Sstevel@tonic-gate if (IS_NISPLUS(repository) == FALSE) { 10847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 10857c478bd9Sstevel@tonic-gate "-D only applies to nisplus repository\n")); 10867c478bd9Sstevel@tonic-gate rusage(); /* exit */ 10877c478bd9Sstevel@tonic-gate retval = BADSYN; 10887c478bd9Sstevel@tonic-gate return (FAIL); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate if (flag & AFLAG) { 10927c478bd9Sstevel@tonic-gate retval = BADOPT; 10937c478bd9Sstevel@tonic-gate return (FAIL); 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate /* It is cleaner not to set this flag */ 10967c478bd9Sstevel@tonic-gate /* flag |= OFLAG; */ 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate /* get domain from optarg */ 10997c478bd9Sstevel@tonic-gate repository.scope = optarg; 11007c478bd9Sstevel@tonic-gate if (repository.scope != NULL) { 11017c478bd9Sstevel@tonic-gate repository.scope_len = 11027c478bd9Sstevel@tonic-gate strlen(repository.scope)+1; 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate break; 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate case 'e': /* change login shell */ 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate /* if no repository the default for -e is files */ 11097c478bd9Sstevel@tonic-gate if (repository.type == NULL) 11107c478bd9Sstevel@tonic-gate repository = __REPFILES; 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate /* 11137c478bd9Sstevel@tonic-gate * Only privileged process can execute this 11147c478bd9Sstevel@tonic-gate * for FILES 11157c478bd9Sstevel@tonic-gate */ 11167c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 11177c478bd9Sstevel@tonic-gate retval = NOPERM; 11187c478bd9Sstevel@tonic-gate return (FAIL); 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate if (flag & (EFLAG|SAFLAG|AGEFLAG)) { 11217c478bd9Sstevel@tonic-gate retval = BADOPT; 11227c478bd9Sstevel@tonic-gate return (FAIL); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate flag |= EFLAG; 11257c478bd9Sstevel@tonic-gate break; 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate case 'g': /* change gecos information */ 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate /* if no repository the default for -g is files */ 11307c478bd9Sstevel@tonic-gate if (repository.type == NULL) 11317c478bd9Sstevel@tonic-gate repository = __REPFILES; 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate /* 11347c478bd9Sstevel@tonic-gate * Only privileged process can execute this 11357c478bd9Sstevel@tonic-gate * for FILES 11367c478bd9Sstevel@tonic-gate */ 11377c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 11387c478bd9Sstevel@tonic-gate retval = NOPERM; 11397c478bd9Sstevel@tonic-gate return (FAIL); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate if (flag & (GFLAG|SAFLAG|AGEFLAG)) { 11427c478bd9Sstevel@tonic-gate retval = BADOPT; 11437c478bd9Sstevel@tonic-gate return (FAIL); 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate flag |= GFLAG; 11467c478bd9Sstevel@tonic-gate break; 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate case 'h': /* change home dir */ 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* if no repository the default for -h is files */ 11517c478bd9Sstevel@tonic-gate if (repository.type == NULL) 11527c478bd9Sstevel@tonic-gate repository = __REPFILES; 11537c478bd9Sstevel@tonic-gate /* 11547c478bd9Sstevel@tonic-gate * Only privileged process can execute this 11557c478bd9Sstevel@tonic-gate * for FILES 11567c478bd9Sstevel@tonic-gate */ 11577c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 11587c478bd9Sstevel@tonic-gate retval = NOPERM; 11597c478bd9Sstevel@tonic-gate return (FAIL); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate if (IS_NIS(repository)) { 11627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", 11637c478bd9Sstevel@tonic-gate gettext(MSG_NIS_HOMEDIR)); 11647c478bd9Sstevel@tonic-gate retval = BADSYN; 11657c478bd9Sstevel@tonic-gate return (FAIL); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate if (flag & (HFLAG|SAFLAG|AGEFLAG)) { 11697c478bd9Sstevel@tonic-gate retval = BADOPT; 11707c478bd9Sstevel@tonic-gate return (FAIL); 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate flag |= HFLAG; 11737c478bd9Sstevel@tonic-gate break; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate case '?': 11767c478bd9Sstevel@tonic-gate rusage(); 11777c478bd9Sstevel@tonic-gate retval = BADOPT; 11787c478bd9Sstevel@tonic-gate return (FAIL); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate argc -= optind; 11837c478bd9Sstevel@tonic-gate if (argc > 1) { 11847c478bd9Sstevel@tonic-gate rusage(); 11857c478bd9Sstevel@tonic-gate retval = BADSYN; 11867c478bd9Sstevel@tonic-gate return (FAIL); 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate /* Make sure (EXPIRE comes after (MAX comes after MIN)) */ 11907c478bd9Sstevel@tonic-gate attrlist_reorder(attributes); 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate /* If no options are specified or only the show option */ 11937c478bd9Sstevel@tonic-gate /* is specified, return because no option error checking */ 11947c478bd9Sstevel@tonic-gate /* is needed */ 11957c478bd9Sstevel@tonic-gate if (!flag || (flag == SFLAG)) 11967c478bd9Sstevel@tonic-gate return (flag); 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate /* AFLAG must be used with SFLAG */ 11997c478bd9Sstevel@tonic-gate if (flag == AFLAG) { 12007c478bd9Sstevel@tonic-gate rusage(); 12017c478bd9Sstevel@tonic-gate retval = BADSYN; 12027c478bd9Sstevel@tonic-gate return (FAIL); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate if (flag != SAFLAG && argc < 1) { 12067c478bd9Sstevel@tonic-gate /* 12077c478bd9Sstevel@tonic-gate * user name is not specified (argc<1), it can't be 12087c478bd9Sstevel@tonic-gate * aging info update. 12097c478bd9Sstevel@tonic-gate */ 12107c478bd9Sstevel@tonic-gate if (!(flag & NONAGEFLAG)) { 12117c478bd9Sstevel@tonic-gate rusage(); 12127c478bd9Sstevel@tonic-gate retval = BADSYN; 12137c478bd9Sstevel@tonic-gate return (FAIL); 12147c478bd9Sstevel@tonic-gate } 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate /* user name(s) may not be specified when SAFLAG is used. */ 12187c478bd9Sstevel@tonic-gate if (flag == SAFLAG && argc >= 1) { 12197c478bd9Sstevel@tonic-gate rusage(); 12207c478bd9Sstevel@tonic-gate retval = BADSYN; 12217c478bd9Sstevel@tonic-gate return (FAIL); 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate /* 12257c478bd9Sstevel@tonic-gate * If aging is being turned off (maxdate == -1), mindate may not 12267c478bd9Sstevel@tonic-gate * be specified. 12277c478bd9Sstevel@tonic-gate */ 12287c478bd9Sstevel@tonic-gate if ((maxdate == -1) && (flag & NFLAG)) { 12297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -n\n", 12307c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 12317c478bd9Sstevel@tonic-gate retval = BADOPT; 12327c478bd9Sstevel@tonic-gate return (FAIL); 12337c478bd9Sstevel@tonic-gate } 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate return (flag); 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate /* 12397c478bd9Sstevel@tonic-gate * 12407c478bd9Sstevel@tonic-gate * ckuid(): 12417c478bd9Sstevel@tonic-gate * This function returns SUCCESS if the caller is root, else 12427c478bd9Sstevel@tonic-gate * it returns NOPERM. 12437c478bd9Sstevel@tonic-gate * 12447c478bd9Sstevel@tonic-gate */ 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate static int 124749335bdeSbasabi ckuid(void) 12487c478bd9Sstevel@tonic-gate { 12497c478bd9Sstevel@tonic-gate if (uid != 0) { 12507c478bd9Sstevel@tonic-gate return (retval = NOPERM); 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate return (SUCCESS); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* 12577c478bd9Sstevel@tonic-gate * get_attr() 12587c478bd9Sstevel@tonic-gate */ 12597c478bd9Sstevel@tonic-gate int 12607c478bd9Sstevel@tonic-gate get_attr(char *username, pwu_repository_t *repository, attrlist **attributes) 12617c478bd9Sstevel@tonic-gate { 12627c478bd9Sstevel@tonic-gate int res; 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_PASSWD, NULL); 12657c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_LSTCHG, "0"); 12667c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MIN, "0"); 12677c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MAX, "0"); 12687c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_WARN, "0"); 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate res = __get_authtoken_attr(username, repository, *attributes); 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate if (res == PWU_SUCCESS) { 12737c478bd9Sstevel@tonic-gate retval = SUCCESS; 12747c478bd9Sstevel@tonic-gate return (PWU_SUCCESS); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate if (res == PWU_NOT_FOUND) 12787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep, 12797c478bd9Sstevel@tonic-gate username); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate retval = NOPERM; 12827c478bd9Sstevel@tonic-gate passwd_exit(retval); 12837c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate /* 12877c478bd9Sstevel@tonic-gate * display_attr(): 12887c478bd9Sstevel@tonic-gate * This function prints out the password attributes of a usr 12897c478bd9Sstevel@tonic-gate * onto standand output. 12907c478bd9Sstevel@tonic-gate */ 12917c478bd9Sstevel@tonic-gate void 12927c478bd9Sstevel@tonic-gate display_attr(char *usrname, attrlist *attributes) 12937c478bd9Sstevel@tonic-gate { 12947c478bd9Sstevel@tonic-gate char *status; 12957c478bd9Sstevel@tonic-gate char *passwd; 12967c478bd9Sstevel@tonic-gate long lstchg; 12977c478bd9Sstevel@tonic-gate int min, max, warn; 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate while (attributes) { 13007c478bd9Sstevel@tonic-gate switch (attributes->type) { 13017c478bd9Sstevel@tonic-gate case ATTR_PASSWD: 13027c478bd9Sstevel@tonic-gate passwd = attributes->data.val_s; 13037c478bd9Sstevel@tonic-gate if (passwd == NULL || *passwd == '\0') 13047c478bd9Sstevel@tonic-gate status = "NP "; 13057c478bd9Sstevel@tonic-gate else if (strncmp(passwd, LOCKSTRING, 13067c478bd9Sstevel@tonic-gate sizeof (LOCKSTRING)-1) == 0) 13077c478bd9Sstevel@tonic-gate status = "LK "; 13087c478bd9Sstevel@tonic-gate else if (strncmp(passwd, NOLOGINSTRING, 13097c478bd9Sstevel@tonic-gate sizeof (NOLOGINSTRING)-1) == 0) 13107c478bd9Sstevel@tonic-gate status = "NL "; 1311b816ddf8Sgww else if ((strlen(passwd) == 13 && passwd[0] != '$') || 1312b816ddf8Sgww passwd[0] == '$') 13137c478bd9Sstevel@tonic-gate status = "PS "; 1314b816ddf8Sgww else 1315b816ddf8Sgww status = "UN "; 13167c478bd9Sstevel@tonic-gate break; 13177c478bd9Sstevel@tonic-gate case ATTR_LSTCHG: 13187c478bd9Sstevel@tonic-gate lstchg = attributes->data.val_i * DAY; 13197c478bd9Sstevel@tonic-gate break; 13207c478bd9Sstevel@tonic-gate case ATTR_MIN: 13217c478bd9Sstevel@tonic-gate min = attributes->data.val_i; 13227c478bd9Sstevel@tonic-gate break; 13237c478bd9Sstevel@tonic-gate case ATTR_MAX: 13247c478bd9Sstevel@tonic-gate max = attributes->data.val_i; 13257c478bd9Sstevel@tonic-gate break; 13267c478bd9Sstevel@tonic-gate case ATTR_WARN: 13277c478bd9Sstevel@tonic-gate warn = attributes->data.val_i; 13287c478bd9Sstevel@tonic-gate break; 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate attributes = attributes->next; 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%-8s ", usrname); 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate if (status) 13357c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s ", status); 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate if (max != -1) { 13387c478bd9Sstevel@tonic-gate if (lstchg == 0) { 13397c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "00/00/00 "); 13407c478bd9Sstevel@tonic-gate } else { 13417c478bd9Sstevel@tonic-gate struct tm *tmp; 13427c478bd9Sstevel@tonic-gate tmp = gmtime(&lstchg); 13437c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%.2d/%.2d/%.2d ", 13447c478bd9Sstevel@tonic-gate tmp->tm_mon + 1, 13457c478bd9Sstevel@tonic-gate tmp->tm_mday, 13467c478bd9Sstevel@tonic-gate tmp->tm_year % 100); 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate (void) fprintf(stdout, (min >= 0) ? "%4d " : " ", min); 13497c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%4d ", max); 13507c478bd9Sstevel@tonic-gate (void) fprintf(stdout, (warn > 0) ? "%4d " : " ", warn); 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate void 13567c478bd9Sstevel@tonic-gate free_attr(attrlist *attributes) 13577c478bd9Sstevel@tonic-gate { 13587c478bd9Sstevel@tonic-gate while (attributes) { 13597c478bd9Sstevel@tonic-gate if (attributes->type == ATTR_PASSWD) 13607c478bd9Sstevel@tonic-gate free(attributes->data.val_s); 13617c478bd9Sstevel@tonic-gate attributes = attributes->next; 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate /* 13667c478bd9Sstevel@tonic-gate * 13677c478bd9Sstevel@tonic-gate * get_namelist_files(): 13687c478bd9Sstevel@tonic-gate * This function gets a list of user names on the system from 13697c478bd9Sstevel@tonic-gate * the /etc/passwd file. 13707c478bd9Sstevel@tonic-gate * 13717c478bd9Sstevel@tonic-gate */ 13727c478bd9Sstevel@tonic-gate int 137349335bdeSbasabi get_namelist_files(char ***namelist_p, int *num_user) 13747c478bd9Sstevel@tonic-gate { 13757c478bd9Sstevel@tonic-gate FILE *pwfp; 13767c478bd9Sstevel@tonic-gate struct passwd *pwd; 13777c478bd9Sstevel@tonic-gate int max_user; 13787c478bd9Sstevel@tonic-gate int nuser; 13797c478bd9Sstevel@tonic-gate char **nl; 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate nuser = 0; 13827c478bd9Sstevel@tonic-gate errno = 0; 13837c478bd9Sstevel@tonic-gate pwd = NULL; 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate if ((pwfp = fopen(PASSWD, "r")) == NULL) 13867c478bd9Sstevel@tonic-gate return (NOPERM); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* 13897c478bd9Sstevel@tonic-gate * find out the actual number of entries in the PASSWD file 13907c478bd9Sstevel@tonic-gate */ 13917c478bd9Sstevel@tonic-gate max_user = 1; /* need one slot for terminator NULL */ 13927c478bd9Sstevel@tonic-gate while ((pwd = fgetpwent(pwfp)) != NULL) 13937c478bd9Sstevel@tonic-gate max_user++; 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate /* 13967c478bd9Sstevel@tonic-gate * reset the file stream pointer 13977c478bd9Sstevel@tonic-gate */ 13987c478bd9Sstevel@tonic-gate rewind(pwfp); 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate nl = (char **)calloc(max_user, (sizeof (char *))); 14017c478bd9Sstevel@tonic-gate if (nl == NULL) { 14027c478bd9Sstevel@tonic-gate (void) fclose(pwfp); 14037c478bd9Sstevel@tonic-gate return (FMERR); 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate while ((pwd = fgetpwent(pwfp)) != NULL) { 14077c478bd9Sstevel@tonic-gate if ((nl[nuser] = strdup(pwd->pw_name)) == NULL) { 14087c478bd9Sstevel@tonic-gate (void) fclose(pwfp); 14097c478bd9Sstevel@tonic-gate return (FMERR); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate nuser++; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate nl[nuser] = NULL; 14157c478bd9Sstevel@tonic-gate *num_user = nuser; 14167c478bd9Sstevel@tonic-gate *namelist_p = nl; 14177c478bd9Sstevel@tonic-gate (void) fclose(pwfp); 14187c478bd9Sstevel@tonic-gate return (SUCCESS); 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate /* 1422*dd1104fbSMichen Chang * get_namelist_local 14237c478bd9Sstevel@tonic-gate * 14247c478bd9Sstevel@tonic-gate */ 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate /* 1427*dd1104fbSMichen Chang * Our private version of the switch frontend for getspent. We want 1428*dd1104fbSMichen Chang * to search just the nisplus or ldap sp file, so we want to bypass 1429*dd1104fbSMichen Chang * normal nsswitch.conf based processing. This implementation 1430*dd1104fbSMichen Chang * compatible with version 2 of the name service switch. 14317c478bd9Sstevel@tonic-gate */ 14327c478bd9Sstevel@tonic-gate #define NSS_NISPLUS_ONLY "nisplus" 1433*dd1104fbSMichen Chang #define NSS_LDAP_ONLY "ldap" 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate extern int str2spwd(const char *, int, void *, char *, int); 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root); 14387c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context); 14397c478bd9Sstevel@tonic-gate 1440*dd1104fbSMichen Chang static char *local_config; 14417c478bd9Sstevel@tonic-gate static void 1442*dd1104fbSMichen Chang _lc_nss_initf_shadow(nss_db_params_t *p) 14437c478bd9Sstevel@tonic-gate { 14447c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_SHADOW; 14457c478bd9Sstevel@tonic-gate p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */ 1446*dd1104fbSMichen Chang p->default_config = local_config; /* Use ldap or nisplus only */ 14477c478bd9Sstevel@tonic-gate p->flags = NSS_USE_DEFAULT_CONFIG; 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate static void 1451*dd1104fbSMichen Chang _lc_setspent(void) 14527c478bd9Sstevel@tonic-gate { 1453*dd1104fbSMichen Chang nss_setent(&db_root, _lc_nss_initf_shadow, &context); 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate static void 1457*dd1104fbSMichen Chang _lc_endspent(void) 14587c478bd9Sstevel@tonic-gate { 1459*dd1104fbSMichen Chang nss_endent(&db_root, _lc_nss_initf_shadow, &context); 14607c478bd9Sstevel@tonic-gate nss_delete(&db_root); 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate static struct spwd * 1464*dd1104fbSMichen Chang _lc_getspent_r(struct spwd *result, char *buffer, int buflen) 14657c478bd9Sstevel@tonic-gate { 14667c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 14677c478bd9Sstevel@tonic-gate char *nam; 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate /* In getXXent_r(), protect the unsuspecting caller from +/- entries */ 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate do { 14727c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd); 14737c478bd9Sstevel@tonic-gate /* No key to fill in */ 1474*dd1104fbSMichen Chang (void) nss_getent(&db_root, _lc_nss_initf_shadow, &context, 14757c478bd9Sstevel@tonic-gate &arg); 14767c478bd9Sstevel@tonic-gate } while (arg.returnval != 0 && 14777c478bd9Sstevel@tonic-gate (nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 && 14787c478bd9Sstevel@tonic-gate (*nam == '+' || *nam == '-')); 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate return (struct spwd *)NSS_XbyY_FINI(&arg); 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate static nss_XbyY_buf_t *buffer; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate static struct spwd * 1486*dd1104fbSMichen Chang _lc_getspent(void) 14877c478bd9Sstevel@tonic-gate { 14887c478bd9Sstevel@tonic-gate nss_XbyY_buf_t *b; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW); 14917c478bd9Sstevel@tonic-gate 1492*dd1104fbSMichen Chang return (b == 0 ? 0 : _lc_getspent_r(b->result, b->buffer, b->buflen)); 14937c478bd9Sstevel@tonic-gate } 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate int 1496*dd1104fbSMichen Chang get_namelist_local(char ***namelist_p, int *num_user) 14977c478bd9Sstevel@tonic-gate { 14987c478bd9Sstevel@tonic-gate int nuser = 0; 14997c478bd9Sstevel@tonic-gate int alloced = 100; 15007c478bd9Sstevel@tonic-gate char **nl; 15017c478bd9Sstevel@tonic-gate struct spwd *p; 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate if ((nl = calloc(alloced, sizeof (*nl))) == NULL) 15057c478bd9Sstevel@tonic-gate return (FMERR); 15067c478bd9Sstevel@tonic-gate 1507*dd1104fbSMichen Chang (void) _lc_setspent(); 1508*dd1104fbSMichen Chang while ((p = _lc_getspent()) != NULL) { 15097c478bd9Sstevel@tonic-gate if ((nl[nuser] = strdup(p->sp_namp)) == NULL) { 1510*dd1104fbSMichen Chang _lc_endspent(); 15117c478bd9Sstevel@tonic-gate return (FMERR); 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate if (++nuser == alloced) { 15147c478bd9Sstevel@tonic-gate alloced += 100; 15157c478bd9Sstevel@tonic-gate nl = realloc(nl, alloced * (sizeof (*nl))); 15167c478bd9Sstevel@tonic-gate if (nl == NULL) { 1517*dd1104fbSMichen Chang _lc_endspent(); 15187c478bd9Sstevel@tonic-gate return (FMERR); 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate } 1522*dd1104fbSMichen Chang (void) _lc_endspent(); 15237c478bd9Sstevel@tonic-gate nl[nuser] = NULL; 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate *namelist_p = nl; 15267c478bd9Sstevel@tonic-gate *num_user = nuser; /* including NULL */ 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate return (SUCCESS); 15297c478bd9Sstevel@tonic-gate } 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate int 15327c478bd9Sstevel@tonic-gate get_namelist(pwu_repository_t repository, char ***namelist, int *num_user) 15337c478bd9Sstevel@tonic-gate { 1534*dd1104fbSMichen Chang if (IS_LDAP(repository)) { 1535*dd1104fbSMichen Chang local_config = NSS_LDAP_ONLY; 1536*dd1104fbSMichen Chang return (get_namelist_local(namelist, num_user)); 1537*dd1104fbSMichen Chang } else if (IS_NISPLUS(repository)) { 1538*dd1104fbSMichen Chang local_config = NSS_NISPLUS_ONLY; 1539*dd1104fbSMichen Chang return (get_namelist_local(namelist, num_user)); 1540*dd1104fbSMichen Chang } else if (IS_FILES(repository)) 15417c478bd9Sstevel@tonic-gate return (get_namelist_files(namelist, num_user)); 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate rusage(); 15447c478bd9Sstevel@tonic-gate return (BADSYN); 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate /* 15487c478bd9Sstevel@tonic-gate * 15497c478bd9Sstevel@tonic-gate * passwd_exit(): 15507c478bd9Sstevel@tonic-gate * This function will call exit() with appropriate exit code 15517c478bd9Sstevel@tonic-gate * according to the input "retcode" value. 15527c478bd9Sstevel@tonic-gate * It also calls pam_end() to clean-up buffers before exit. 15537c478bd9Sstevel@tonic-gate * 15547c478bd9Sstevel@tonic-gate */ 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate void 155749335bdeSbasabi passwd_exit(int retcode) 15587c478bd9Sstevel@tonic-gate { 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate if (pamh) 15617c478bd9Sstevel@tonic-gate (void) pam_end(pamh, pam_retval); 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate switch (retcode) { 15647c478bd9Sstevel@tonic-gate case SUCCESS: 15657c478bd9Sstevel@tonic-gate break; 15667c478bd9Sstevel@tonic-gate case NOPERM: 15677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NP)); 15687c478bd9Sstevel@tonic-gate break; 15697c478bd9Sstevel@tonic-gate case BADOPT: 15707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_BS)); 15717c478bd9Sstevel@tonic-gate break; 15727c478bd9Sstevel@tonic-gate case FMERR: 15737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_FE)); 15747c478bd9Sstevel@tonic-gate break; 15757c478bd9Sstevel@tonic-gate case FATAL: 15767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_FF)); 15777c478bd9Sstevel@tonic-gate break; 15787c478bd9Sstevel@tonic-gate case FBUSY: 15797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_FB)); 15807c478bd9Sstevel@tonic-gate break; 15817c478bd9Sstevel@tonic-gate case BADSYN: 15827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NV)); 15837c478bd9Sstevel@tonic-gate break; 15847c478bd9Sstevel@tonic-gate case BADAGE: 15857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_AD)); 15867c478bd9Sstevel@tonic-gate break; 15877c478bd9Sstevel@tonic-gate case NOMEM: 15887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NM)); 15897c478bd9Sstevel@tonic-gate break; 15907c478bd9Sstevel@tonic-gate default: 15917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NP)); 15927c478bd9Sstevel@tonic-gate retcode = NOPERM; 15937c478bd9Sstevel@tonic-gate break; 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate /* write password record */ 15967c478bd9Sstevel@tonic-gate if (event != NULL) { 15977c478bd9Sstevel@tonic-gate if (adt_put_event(event, 15987c478bd9Sstevel@tonic-gate retcode == SUCCESS ? ADT_SUCCESS : ADT_FAILURE, 15997c478bd9Sstevel@tonic-gate retcode == SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM + 16007c478bd9Sstevel@tonic-gate pam_retval) != 0) { 16017c478bd9Sstevel@tonic-gate adt_free_event(event); 16027c478bd9Sstevel@tonic-gate (void) adt_end_session(ah); 16037c478bd9Sstevel@tonic-gate perror("adt_put_event"); 16047c478bd9Sstevel@tonic-gate exit(retcode); 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate adt_free_event(event); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate (void) adt_end_session(ah); 16097c478bd9Sstevel@tonic-gate exit(retcode); 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate /* 16137c478bd9Sstevel@tonic-gate * 16147c478bd9Sstevel@tonic-gate * passwd_conv(): 16157c478bd9Sstevel@tonic-gate * This is the conv (conversation) function called from 16167c478bd9Sstevel@tonic-gate * a PAM authentication module to print error messages 16177c478bd9Sstevel@tonic-gate * or garner information from the user. 16187c478bd9Sstevel@tonic-gate * 16197c478bd9Sstevel@tonic-gate */ 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 16227c478bd9Sstevel@tonic-gate static int 162349335bdeSbasabi passwd_conv(int num_msg, struct pam_message **msg, 162449335bdeSbasabi struct pam_response **response, void *appdata_ptr) 16257c478bd9Sstevel@tonic-gate { 16267c478bd9Sstevel@tonic-gate struct pam_message *m; 16277c478bd9Sstevel@tonic-gate struct pam_response *r; 16287c478bd9Sstevel@tonic-gate char *temp; 16297c478bd9Sstevel@tonic-gate int k, i; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate if (num_msg <= 0) 16327c478bd9Sstevel@tonic-gate return (PAM_CONV_ERR); 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate *response = (struct pam_response *)calloc(num_msg, 16357c478bd9Sstevel@tonic-gate sizeof (struct pam_response)); 16367c478bd9Sstevel@tonic-gate if (*response == NULL) 16377c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate k = num_msg; 16407c478bd9Sstevel@tonic-gate m = *msg; 16417c478bd9Sstevel@tonic-gate r = *response; 16427c478bd9Sstevel@tonic-gate while (k--) { 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate switch (m->msg_style) { 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF: 16477c478bd9Sstevel@tonic-gate temp = getpassphrase(m->msg); 16487c478bd9Sstevel@tonic-gate if (temp != NULL) { 16497c478bd9Sstevel@tonic-gate r->resp = strdup(temp); 16507c478bd9Sstevel@tonic-gate (void) memset(temp, 0, strlen(temp)); 16517c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 16527c478bd9Sstevel@tonic-gate /* free responses */ 16537c478bd9Sstevel@tonic-gate r = *response; 16547c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 16557c478bd9Sstevel@tonic-gate if (r->resp) 16567c478bd9Sstevel@tonic-gate free(r->resp); 16577c478bd9Sstevel@tonic-gate } 16587c478bd9Sstevel@tonic-gate free(*response); 16597c478bd9Sstevel@tonic-gate *response = NULL; 16607c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate m++; 16647c478bd9Sstevel@tonic-gate r++; 16657c478bd9Sstevel@tonic-gate break; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON: 16687c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 16697c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout); 16707c478bd9Sstevel@tonic-gate } 16717c478bd9Sstevel@tonic-gate r->resp = (char *)calloc(PAM_MAX_RESP_SIZE, 16727c478bd9Sstevel@tonic-gate sizeof (char)); 16737c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 16747c478bd9Sstevel@tonic-gate /* free responses */ 16757c478bd9Sstevel@tonic-gate r = *response; 16767c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 16777c478bd9Sstevel@tonic-gate if (r->resp) 16787c478bd9Sstevel@tonic-gate free(r->resp); 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate free(*response); 16817c478bd9Sstevel@tonic-gate *response = NULL; 16827c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 16837c478bd9Sstevel@tonic-gate } 16847c478bd9Sstevel@tonic-gate if (fgets(r->resp, PAM_MAX_RESP_SIZE-1, stdin)) { 16857c478bd9Sstevel@tonic-gate int len = strlen(r->resp); 16867c478bd9Sstevel@tonic-gate if (r->resp[len-1] == '\n') 16877c478bd9Sstevel@tonic-gate r->resp[len-1] = '\0'; 16887c478bd9Sstevel@tonic-gate } 16897c478bd9Sstevel@tonic-gate m++; 16907c478bd9Sstevel@tonic-gate r++; 16917c478bd9Sstevel@tonic-gate break; 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG: 16947c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 16957c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stderr); 16967c478bd9Sstevel@tonic-gate (void) fputs("\n", stderr); 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate m++; 16997c478bd9Sstevel@tonic-gate r++; 17007c478bd9Sstevel@tonic-gate break; 17017c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO: 17027c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 17037c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout); 17047c478bd9Sstevel@tonic-gate (void) fputs("\n", stdout); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate m++; 17077c478bd9Sstevel@tonic-gate r++; 17087c478bd9Sstevel@tonic-gate break; 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate default: 17117c478bd9Sstevel@tonic-gate break; 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate } 17147c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate /* 17187c478bd9Sstevel@tonic-gate * Utilities Functions 17197c478bd9Sstevel@tonic-gate */ 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate /* 17227c478bd9Sstevel@tonic-gate * int attrlist_add(attrlist **l, attrtype type, char *val) 17237c478bd9Sstevel@tonic-gate * add an item, with type "type" and value "val", at the tail of list l. 17247c478bd9Sstevel@tonic-gate * This functions exits the application on OutOfMem error. 17257c478bd9Sstevel@tonic-gate */ 17267c478bd9Sstevel@tonic-gate void 17277c478bd9Sstevel@tonic-gate attrlist_add(attrlist **l, attrtype type, char *val) 17287c478bd9Sstevel@tonic-gate { 17297c478bd9Sstevel@tonic-gate attrlist **w; 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate /* tail insert */ 17327c478bd9Sstevel@tonic-gate for (w = l; *w != NULL; w = &(*w)->next) 17337c478bd9Sstevel@tonic-gate ; 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate if ((*w = malloc(sizeof (**w))) == NULL) 17367c478bd9Sstevel@tonic-gate passwd_exit(NOMEM); 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate (*w)->type = type; 17397c478bd9Sstevel@tonic-gate (*w)->next = NULL; 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate switch (type) { 17427c478bd9Sstevel@tonic-gate case ATTR_MIN: 17437c478bd9Sstevel@tonic-gate case ATTR_WARN: 17447c478bd9Sstevel@tonic-gate case ATTR_MAX: 17457c478bd9Sstevel@tonic-gate (*w)->data.val_i = atoi(val); 17467c478bd9Sstevel@tonic-gate break; 17477c478bd9Sstevel@tonic-gate default: 17487c478bd9Sstevel@tonic-gate (*w)->data.val_s = val; 17497c478bd9Sstevel@tonic-gate break; 17507c478bd9Sstevel@tonic-gate } 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate /* 17547c478bd9Sstevel@tonic-gate * attrlist_reorder(attrlist **l) 17557c478bd9Sstevel@tonic-gate * Make sure that 17567c478bd9Sstevel@tonic-gate * - if EXPIRE and MAX or MIN is set, EXPIRE comes after MAX/MIN 17577c478bd9Sstevel@tonic-gate * - if both MIN and MAX are set, MAX comes before MIN. 17587c478bd9Sstevel@tonic-gate */ 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate static void 17617c478bd9Sstevel@tonic-gate attrlist_reorder(attrlist **l) 17627c478bd9Sstevel@tonic-gate { 17637c478bd9Sstevel@tonic-gate attrlist **w; 17647c478bd9Sstevel@tonic-gate attrlist *exp = NULL; /* ATTR_EXPIRE_PASSWORD, if found */ 17657c478bd9Sstevel@tonic-gate attrlist *max = NULL; /* ATTR_MAX, if found */ 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate if (*l == NULL || (*l)->next == NULL) 17687c478bd9Sstevel@tonic-gate return; /* order of list with <= one item is ok */ 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate /* 17717c478bd9Sstevel@tonic-gate * We simply walk the list, take off the EXPIRE and MAX items if 17727c478bd9Sstevel@tonic-gate * they appear, and put them (first MAX, them EXPIRE) at the end 17737c478bd9Sstevel@tonic-gate * of the list. 17747c478bd9Sstevel@tonic-gate */ 17757c478bd9Sstevel@tonic-gate w = l; 17767c478bd9Sstevel@tonic-gate while (*w != NULL) { 17777c478bd9Sstevel@tonic-gate if ((*w)->type == ATTR_EXPIRE_PASSWORD) { 17787c478bd9Sstevel@tonic-gate exp = *w; 17797c478bd9Sstevel@tonic-gate *w = (*w)->next; 17807c478bd9Sstevel@tonic-gate } else if ((*w)->type == ATTR_MAX) { 17817c478bd9Sstevel@tonic-gate max = *w; 17827c478bd9Sstevel@tonic-gate *w = (*w)->next; 17837c478bd9Sstevel@tonic-gate } else 17847c478bd9Sstevel@tonic-gate w = &(*w)->next; 17857c478bd9Sstevel@tonic-gate } 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate /* 'w' points to the address of the 'next' field of the last element */ 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate if (max) { 17907c478bd9Sstevel@tonic-gate *w = max; 17917c478bd9Sstevel@tonic-gate w = &max->next; 17927c478bd9Sstevel@tonic-gate } 17937c478bd9Sstevel@tonic-gate if (exp) { 17947c478bd9Sstevel@tonic-gate *w = exp; 17957c478bd9Sstevel@tonic-gate w = &exp->next; 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate *w = NULL; 17987c478bd9Sstevel@tonic-gate } 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate void 180149335bdeSbasabi rusage(void) 18027c478bd9Sstevel@tonic-gate { 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate #define MSG(a) (void) fprintf(stderr, gettext((a))); 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate MSG("usage:\n"); 18077c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files | -r nis | -r nisplus | -r ldap] [name]\n"); 18087c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] [-egh] [name]\n"); 18097c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] -sa\n"); 18107c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] -s [name]\n"); 18117c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] [-d|-l|-N|-u] [-f] [-n min] [-w warn] " 18127c478bd9Sstevel@tonic-gate "[-x max] name\n"); 18137c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nis [-eg] [name]\n"); 18147c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus [-egh] [-D domainname] [name]\n"); 18157c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus -sa\n"); 18167c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus [-D domainname] -s [name]\n"); 18177c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus [-D domainname] [-l|-N|-u] [-f] [-n min] " 18187c478bd9Sstevel@tonic-gate "[-w warn]\n"); 18197c478bd9Sstevel@tonic-gate MSG("\t\t[-x max] name\n"); 18207c478bd9Sstevel@tonic-gate MSG("\tpasswd -r ldap [-egh] [name]\n"); 1821*dd1104fbSMichen Chang MSG("\tpasswd -r ldap -sa\n"); 1822*dd1104fbSMichen Chang MSG("\tpasswd -r ldap -s [name]\n"); 1823*dd1104fbSMichen Chang MSG("\tpasswd -r ldap [-l|-N|-u] [-f] [-n min] [-w warn] " 1824*dd1104fbSMichen Chang "[-x max] name\n"); 18257c478bd9Sstevel@tonic-gate #undef MSG 18267c478bd9Sstevel@tonic-gate } 1827