1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1987, 1988 Microsoft Corporation */ 31*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * passwd is a program whose sole purpose is to manage 37*7c478bd9Sstevel@tonic-gate * the password file, map, or table. It allows system administrator 38*7c478bd9Sstevel@tonic-gate * to add, change and display password attributes. 39*7c478bd9Sstevel@tonic-gate * Non privileged user can change password or display 40*7c478bd9Sstevel@tonic-gate * password attributes which corresponds to their login name. 41*7c478bd9Sstevel@tonic-gate */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include <stdio.h> 44*7c478bd9Sstevel@tonic-gate #include <pwd.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 46*7c478bd9Sstevel@tonic-gate #include <errno.h> 47*7c478bd9Sstevel@tonic-gate #include <unistd.h> 48*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 49*7c478bd9Sstevel@tonic-gate #include <locale.h> 50*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 51*7c478bd9Sstevel@tonic-gate #include <errno.h> 52*7c478bd9Sstevel@tonic-gate #include <string.h> 53*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 54*7c478bd9Sstevel@tonic-gate #include <security/pam_modules.h> 55*7c478bd9Sstevel@tonic-gate #include <security/pam_impl.h> 56*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h> 57*7c478bd9Sstevel@tonic-gate #undef GROUP 58*7c478bd9Sstevel@tonic-gate #include <syslog.h> 59*7c478bd9Sstevel@tonic-gate #include <userdefs.h> 60*7c478bd9Sstevel@tonic-gate #include <passwdutil.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #include <deflt.h> 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #undef GROUP 67*7c478bd9Sstevel@tonic-gate #include <bsm/adt.h> 68*7c478bd9Sstevel@tonic-gate #include <bsm/adt_event.h> 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * flags indicate password attributes to be modified 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #define LFLAG 0x001 /* lock user's password */ 75*7c478bd9Sstevel@tonic-gate #define DFLAG 0x002 /* delete user's password */ 76*7c478bd9Sstevel@tonic-gate #define MFLAG 0x004 /* set max field -- # of days passwd is valid */ 77*7c478bd9Sstevel@tonic-gate #define NFLAG 0x008 /* set min field -- # of days between */ 78*7c478bd9Sstevel@tonic-gate /* password changes */ 79*7c478bd9Sstevel@tonic-gate #define SFLAG 0x010 /* display password attributes */ 80*7c478bd9Sstevel@tonic-gate #define FFLAG 0x020 /* expire user's password */ 81*7c478bd9Sstevel@tonic-gate #define AFLAG 0x040 /* display password attributes for all users */ 82*7c478bd9Sstevel@tonic-gate #define SAFLAG (SFLAG|AFLAG) /* display password attributes for all users */ 83*7c478bd9Sstevel@tonic-gate #define WFLAG 0x100 /* warn user to change passwd */ 84*7c478bd9Sstevel@tonic-gate #define OFLAG 0x200 /* domain name */ 85*7c478bd9Sstevel@tonic-gate #define EFLAG 0x400 /* change shell */ 86*7c478bd9Sstevel@tonic-gate #define GFLAG 0x800 /* change gecos information */ 87*7c478bd9Sstevel@tonic-gate #define HFLAG 0x1000 /* change home directory */ 88*7c478bd9Sstevel@tonic-gate #define XFLAG 0x2000 /* no login */ 89*7c478bd9Sstevel@tonic-gate #define UFLAG 0x4000 /* unlock user's password */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #define NONAGEFLAG (EFLAG | GFLAG | HFLAG) 92*7c478bd9Sstevel@tonic-gate #define AGEFLAG (LFLAG | FFLAG | MFLAG | NFLAG | WFLAG | XFLAG | UFLAG) 93*7c478bd9Sstevel@tonic-gate #define MUTEXFLAG (DFLAG | LFLAG | XFLAG | UFLAG | SAFLAG) 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * exit code 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #define SUCCESS 0 /* succeeded */ 101*7c478bd9Sstevel@tonic-gate #define NOPERM 1 /* No permission */ 102*7c478bd9Sstevel@tonic-gate #define BADOPT 2 /* Invalid combination of option */ 103*7c478bd9Sstevel@tonic-gate #define FMERR 3 /* File/table manipulation error */ 104*7c478bd9Sstevel@tonic-gate #define FATAL 4 /* Old file/table can not be recovered */ 105*7c478bd9Sstevel@tonic-gate #define FBUSY 5 /* Lock file/table busy */ 106*7c478bd9Sstevel@tonic-gate #define BADSYN 6 /* Incorrect syntax */ 107*7c478bd9Sstevel@tonic-gate #define BADAGE 7 /* Aging is disabled */ 108*7c478bd9Sstevel@tonic-gate #define NOMEM 8 /* No memory */ 109*7c478bd9Sstevel@tonic-gate #define SYSERR 9 /* System error */ 110*7c478bd9Sstevel@tonic-gate #define EXPIRED 10 /* Account expired */ 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * define error messages 114*7c478bd9Sstevel@tonic-gate */ 115*7c478bd9Sstevel@tonic-gate #define MSG_NP "Permission denied" 116*7c478bd9Sstevel@tonic-gate #define MSG_BS "Invalid combination of options" 117*7c478bd9Sstevel@tonic-gate #define MSG_FE "Unexpected failure. Password file/table unchanged." 118*7c478bd9Sstevel@tonic-gate #define MSG_FF "Unexpected failure. Password file/table missing." 119*7c478bd9Sstevel@tonic-gate #define MSG_FB "Password file/table busy. Try again later." 120*7c478bd9Sstevel@tonic-gate #define MSG_NV "Invalid argument to option" 121*7c478bd9Sstevel@tonic-gate #define MSG_AD "Password aging is disabled" 122*7c478bd9Sstevel@tonic-gate #define MSG_RS "Cannot change from restricted shell %s\n" 123*7c478bd9Sstevel@tonic-gate #define MSG_NM "Out of memory." 124*7c478bd9Sstevel@tonic-gate #define MSG_UNACCEPT "%s is unacceptable as a new shell\n" 125*7c478bd9Sstevel@tonic-gate #define MSG_UNAVAIL "warning: %s is unavailable on this machine\n" 126*7c478bd9Sstevel@tonic-gate #define MSG_COLON "':' is not allowed.\n" 127*7c478bd9Sstevel@tonic-gate #define MSG_MAXLEN "Maximum number of characters allowed is %d." 128*7c478bd9Sstevel@tonic-gate #define MSG_CONTROL "Control characters are not allowed.\n" 129*7c478bd9Sstevel@tonic-gate #define MSG_SHELL_UNCHANGED "Login shell unchanged.\n" 130*7c478bd9Sstevel@tonic-gate #define MSG_GECOS_UNCHANGED "Finger information unchanged.\n" 131*7c478bd9Sstevel@tonic-gate #define MSG_DIR_UNCHANGED "Homedir information unchanged.\n" 132*7c478bd9Sstevel@tonic-gate #define MSG_NAME "\nName [%s]: " 133*7c478bd9Sstevel@tonic-gate #define MSG_HOMEDIR "\nHome Directory [%s]: " 134*7c478bd9Sstevel@tonic-gate #define MSG_OLDSHELL "Old shell: %s\n" 135*7c478bd9Sstevel@tonic-gate #define MSG_NEWSHELL "New shell: " 136*7c478bd9Sstevel@tonic-gate #define MSG_AGAIN "\nPlease try again\n" 137*7c478bd9Sstevel@tonic-gate #define MSG_INPUTHDR "Default values are printed inside of '[]'.\n" \ 138*7c478bd9Sstevel@tonic-gate "To accept the default, type <return>.\n" \ 139*7c478bd9Sstevel@tonic-gate "To have a blank entry, type the word 'none'.\n" 140*7c478bd9Sstevel@tonic-gate #define MSG_UNKNOWN "%s: User unknown: %s\n" 141*7c478bd9Sstevel@tonic-gate #define MSG_ACCOUNT_EXP "User account has expired: %s\n" 142*7c478bd9Sstevel@tonic-gate #define MSG_AUTHTOK_EXP "Your password has been expired for too long.\n" \ 143*7c478bd9Sstevel@tonic-gate "Please contact the system administrator.\n" 144*7c478bd9Sstevel@tonic-gate #define MSG_NIS_HOMEDIR "-h does not apply to NIS" 145*7c478bd9Sstevel@tonic-gate #define MSG_CUR_PASS "Enter existing login password: " 146*7c478bd9Sstevel@tonic-gate #define MSG_CUR_PASS_UNAME "Enter %s's existing login password: " 147*7c478bd9Sstevel@tonic-gate #define MSG_SUCCESS "%s: password information changed for %s\n" 148*7c478bd9Sstevel@tonic-gate #define MSG_SORRY "%s: Sorry, wrong passwd\n" 149*7c478bd9Sstevel@tonic-gate #define MSG_INFO "%s: Changing password for %s\n" 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate * return code from ckarg() routine 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate #define FAIL -1 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate /* 158*7c478bd9Sstevel@tonic-gate * defind password file name 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate #define PASSWD "/etc/passwd" 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate #define MAX_INPUT_LEN 512 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate #define DEF_ATTEMPTS 3 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* Number of characters in that make up an encrypted password (for now) */ 167*7c478bd9Sstevel@tonic-gate #define NUMCP 13 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 170*7c478bd9Sstevel@tonic-gate #define dprintf1 printf 171*7c478bd9Sstevel@tonic-gate #else 172*7c478bd9Sstevel@tonic-gate #define dprintf1(w, x) 173*7c478bd9Sstevel@tonic-gate #endif 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate extern int optind; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate static int retval = SUCCESS; 178*7c478bd9Sstevel@tonic-gate static int pam_retval = PAM_SUCCESS; 179*7c478bd9Sstevel@tonic-gate static uid_t uid; 180*7c478bd9Sstevel@tonic-gate static char *prognamep; 181*7c478bd9Sstevel@tonic-gate static long maxdate; /* password aging information */ 182*7c478bd9Sstevel@tonic-gate static int passwd_conv(); 183*7c478bd9Sstevel@tonic-gate static struct pam_conv pam_conv = {passwd_conv, NULL}; 184*7c478bd9Sstevel@tonic-gate static pam_handle_t *pamh; /* Authentication handle */ 185*7c478bd9Sstevel@tonic-gate static char *usrname; /* user whose attribute we update */ 186*7c478bd9Sstevel@tonic-gate static adt_session_data_t *ah; /* audit session handle */ 187*7c478bd9Sstevel@tonic-gate static adt_event_data_t *event = NULL; /* event to be generated */ 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate static pam_repository_t auth_rep; 190*7c478bd9Sstevel@tonic-gate static pwu_repository_t repository; 191*7c478bd9Sstevel@tonic-gate static pwu_repository_t __REPFILES = { "files", NULL, 0 }; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * Function Declarations 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate extern nis_name nis_local_directory(void); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate extern void setusershell(void); 199*7c478bd9Sstevel@tonic-gate extern char *getusershell(void); 200*7c478bd9Sstevel@tonic-gate extern void endusershell(void); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate static void passwd_exit(int retcode); 203*7c478bd9Sstevel@tonic-gate static void rusage(void); 204*7c478bd9Sstevel@tonic-gate static int ckuid(void); 205*7c478bd9Sstevel@tonic-gate static int ckarg(int argc, char **argv, attrlist **attributes); 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate static int get_namelist(pwu_repository_t, char ***, int *); 208*7c478bd9Sstevel@tonic-gate static int get_namelist_files(char ***, int *); 209*7c478bd9Sstevel@tonic-gate static int get_namelist_nisplus(char ***, int *); 210*7c478bd9Sstevel@tonic-gate static int get_attr(char *, pwu_repository_t *, attrlist **); 211*7c478bd9Sstevel@tonic-gate static void display_attr(char *, attrlist *); 212*7c478bd9Sstevel@tonic-gate static void free_attr(attrlist *); 213*7c478bd9Sstevel@tonic-gate static void attrlist_add(attrlist **, attrtype, char *); 214*7c478bd9Sstevel@tonic-gate static void attrlist_reorder(attrlist **); 215*7c478bd9Sstevel@tonic-gate static char *userinput(char *, pwu_repository_t *, attrtype); 216*7c478bd9Sstevel@tonic-gate static char *getresponse(char *); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * main(): 220*7c478bd9Sstevel@tonic-gate * The main routine will call ckarg() to parse the command line 221*7c478bd9Sstevel@tonic-gate * arguments and call the appropriate functions to perform the 222*7c478bd9Sstevel@tonic-gate * tasks specified by the arguments. It allows system 223*7c478bd9Sstevel@tonic-gate * administrator to add, change and display password attributes. 224*7c478bd9Sstevel@tonic-gate * Non privileged user can change password or display 225*7c478bd9Sstevel@tonic-gate * password attributes which corresponds to their login name. 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate void 229*7c478bd9Sstevel@tonic-gate main(argc, argv) 230*7c478bd9Sstevel@tonic-gate int argc; 231*7c478bd9Sstevel@tonic-gate char *argv[]; 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate int flag; 235*7c478bd9Sstevel@tonic-gate char **namelist; 236*7c478bd9Sstevel@tonic-gate int num_user; 237*7c478bd9Sstevel@tonic-gate int i; 238*7c478bd9Sstevel@tonic-gate attrlist *attributes = NULL; 239*7c478bd9Sstevel@tonic-gate char *input; 240*7c478bd9Sstevel@tonic-gate int tries = 1; 241*7c478bd9Sstevel@tonic-gate int updated_reps; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate if (prognamep = strrchr(argv[0], '/')) 245*7c478bd9Sstevel@tonic-gate ++prognamep; 246*7c478bd9Sstevel@tonic-gate else 247*7c478bd9Sstevel@tonic-gate prognamep = argv[0]; 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate auth_rep.type = NULL; 250*7c478bd9Sstevel@tonic-gate auth_rep.scope = NULL; 251*7c478bd9Sstevel@tonic-gate repository.type = NULL; 252*7c478bd9Sstevel@tonic-gate repository.scope = NULL; 253*7c478bd9Sstevel@tonic-gate repository.scope_len = 0; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate /* initialization for variables, set locale and textdomain */ 257*7c478bd9Sstevel@tonic-gate i = 0; 258*7c478bd9Sstevel@tonic-gate flag = 0; 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate uid = getuid(); /* get the user id */ 261*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 264*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 265*7c478bd9Sstevel@tonic-gate #endif 266*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * ckarg() parses the arguments. In case of an error, 270*7c478bd9Sstevel@tonic-gate * it sets the retval and returns FAIL (-1). 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate flag = ckarg(argc, argv, &attributes); 274*7c478bd9Sstevel@tonic-gate dprintf1("flag is %0x\n", flag); 275*7c478bd9Sstevel@tonic-gate if (flag == FAIL) 276*7c478bd9Sstevel@tonic-gate passwd_exit(retval); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate argc -= optind; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate if (argc < 1) { 281*7c478bd9Sstevel@tonic-gate if ((usrname = getlogin()) == NULL) { 282*7c478bd9Sstevel@tonic-gate struct passwd *pass = getpwuid(uid); 283*7c478bd9Sstevel@tonic-gate if (pass != NULL) 284*7c478bd9Sstevel@tonic-gate usrname = pass->pw_name; 285*7c478bd9Sstevel@tonic-gate else { 286*7c478bd9Sstevel@tonic-gate rusage(); 287*7c478bd9Sstevel@tonic-gate exit(NOPERM); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate } else if (flag == 0) { 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * If flag is zero, change passwd. 292*7c478bd9Sstevel@tonic-gate * Otherwise, it will display or 293*7c478bd9Sstevel@tonic-gate * modify password aging attributes 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_INFO), prognamep, 296*7c478bd9Sstevel@tonic-gate usrname); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate } else 299*7c478bd9Sstevel@tonic-gate usrname = argv[optind]; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if (pam_start("passwd", usrname, &pam_conv, &pamh) != PAM_SUCCESS) 302*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate auth_rep.type = repository.type; 305*7c478bd9Sstevel@tonic-gate auth_rep.scope = repository.scope; 306*7c478bd9Sstevel@tonic-gate auth_rep.scope_len = repository.scope_len; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if (auth_rep.type != NULL) { 309*7c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_REPOSITORY, (void *)&auth_rep) 310*7c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 311*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate if (flag == SAFLAG) { /* display password attributes for all users */ 316*7c478bd9Sstevel@tonic-gate retval = get_namelist(repository, &namelist, &num_user); 317*7c478bd9Sstevel@tonic-gate if (retval != SUCCESS) 318*7c478bd9Sstevel@tonic-gate (void) passwd_exit(retval); 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate if (num_user == 0) { 321*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamep, 322*7c478bd9Sstevel@tonic-gate gettext(MSG_FF)); 323*7c478bd9Sstevel@tonic-gate passwd_exit(FATAL); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate i = 0; 326*7c478bd9Sstevel@tonic-gate while (namelist[i] != NULL) { 327*7c478bd9Sstevel@tonic-gate (void) get_attr(namelist[i], &repository, 328*7c478bd9Sstevel@tonic-gate &attributes); 329*7c478bd9Sstevel@tonic-gate (void) display_attr(namelist[i], attributes); 330*7c478bd9Sstevel@tonic-gate (void) free(namelist[i]); 331*7c478bd9Sstevel@tonic-gate (void) free_attr(attributes); 332*7c478bd9Sstevel@tonic-gate i++; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate (void) free(namelist); 335*7c478bd9Sstevel@tonic-gate passwd_exit(SUCCESS); 336*7c478bd9Sstevel@tonic-gate } else if (flag == SFLAG) { /* display password attributes by user */ 337*7c478bd9Sstevel@tonic-gate if (get_attr(usrname, &repository, &attributes) == 338*7c478bd9Sstevel@tonic-gate PWU_SUCCESS) { 339*7c478bd9Sstevel@tonic-gate (void) display_attr(usrname, attributes); 340*7c478bd9Sstevel@tonic-gate (void) free_attr(attributes); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate passwd_exit(SUCCESS); 343*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate switch (pam_authenticate(pamh, 0)) { 348*7c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 349*7c478bd9Sstevel@tonic-gate break; 350*7c478bd9Sstevel@tonic-gate case PAM_USER_UNKNOWN: 351*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep, 352*7c478bd9Sstevel@tonic-gate usrname); 353*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 354*7c478bd9Sstevel@tonic-gate break; 355*7c478bd9Sstevel@tonic-gate case PAM_PERM_DENIED: 356*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 357*7c478bd9Sstevel@tonic-gate break; 358*7c478bd9Sstevel@tonic-gate case PAM_AUTH_ERR: 359*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_SORRY), prognamep); 360*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 361*7c478bd9Sstevel@tonic-gate break; 362*7c478bd9Sstevel@tonic-gate default: 363*7c478bd9Sstevel@tonic-gate /* system error */ 364*7c478bd9Sstevel@tonic-gate passwd_exit(FMERR); 365*7c478bd9Sstevel@tonic-gate break; 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate if (flag == 0) { /* changing user password */ 369*7c478bd9Sstevel@tonic-gate int chk_authtok = 0; /* check password strength */ 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate dprintf1("call pam_chauthtok() repository name =%s\n", 372*7c478bd9Sstevel@tonic-gate repository.type); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate /* Set up for Audit */ 375*7c478bd9Sstevel@tonic-gate if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) { 376*7c478bd9Sstevel@tonic-gate perror("adt_start_session"); 377*7c478bd9Sstevel@tonic-gate passwd_exit(SYSERR); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate if ((event = adt_alloc_event(ah, ADT_passwd)) == NULL) { 380*7c478bd9Sstevel@tonic-gate perror("adt_alloc_event"); 381*7c478bd9Sstevel@tonic-gate passwd_exit(NOMEM); 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate if (argc >= 1) { 384*7c478bd9Sstevel@tonic-gate /* save target user */ 385*7c478bd9Sstevel@tonic-gate event->adt_passwd.username = usrname; 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate /* Don't check account expiration when invoked by root */ 389*7c478bd9Sstevel@tonic-gate if (ckuid() != SUCCESS) { 390*7c478bd9Sstevel@tonic-gate pam_retval = pam_acct_mgmt(pamh, PAM_SILENT); 391*7c478bd9Sstevel@tonic-gate switch (pam_retval) { 392*7c478bd9Sstevel@tonic-gate case PAM_ACCT_EXPIRED: 393*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 394*7c478bd9Sstevel@tonic-gate gettext(MSG_ACCOUNT_EXP), usrname); 395*7c478bd9Sstevel@tonic-gate passwd_exit(EXPIRED); 396*7c478bd9Sstevel@tonic-gate break; 397*7c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_EXPIRED: 398*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 399*7c478bd9Sstevel@tonic-gate gettext(MSG_AUTHTOK_EXP)); 400*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 401*7c478bd9Sstevel@tonic-gate break; 402*7c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD: 403*7c478bd9Sstevel@tonic-gate /* valid error when changing passwords */ 404*7c478bd9Sstevel@tonic-gate break; 405*7c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 406*7c478bd9Sstevel@tonic-gate /* Ok to change password */ 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate default: 409*7c478bd9Sstevel@tonic-gate passwd_exit(NOPERM); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate pam_retval = PAM_AUTHTOK_ERR; 415*7c478bd9Sstevel@tonic-gate tries = 1; 416*7c478bd9Sstevel@tonic-gate if (ckuid() == SUCCESS) { 417*7c478bd9Sstevel@tonic-gate /* bypass password strength checks */ 418*7c478bd9Sstevel@tonic-gate chk_authtok = PAM_NO_AUTHTOK_CHECK; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate while (pam_retval == PAM_AUTHTOK_ERR && tries <= DEF_ATTEMPTS) { 422*7c478bd9Sstevel@tonic-gate if (tries > 1) 423*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_AGAIN)); 424*7c478bd9Sstevel@tonic-gate pam_retval = pam_chauthtok(pamh, chk_authtok); 425*7c478bd9Sstevel@tonic-gate if (pam_retval == PAM_TRY_AGAIN) { 426*7c478bd9Sstevel@tonic-gate (void) sleep(1); 427*7c478bd9Sstevel@tonic-gate pam_retval = pam_chauthtok(pamh, chk_authtok); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate tries++; 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate switch (pam_retval) { 433*7c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 434*7c478bd9Sstevel@tonic-gate retval = SUCCESS; 435*7c478bd9Sstevel@tonic-gate break; 436*7c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_DISABLE_AGING: 437*7c478bd9Sstevel@tonic-gate retval = BADAGE; 438*7c478bd9Sstevel@tonic-gate break; 439*7c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_LOCK_BUSY: 440*7c478bd9Sstevel@tonic-gate retval = FBUSY; 441*7c478bd9Sstevel@tonic-gate break; 442*7c478bd9Sstevel@tonic-gate case PAM_TRY_AGAIN: 443*7c478bd9Sstevel@tonic-gate retval = FBUSY; 444*7c478bd9Sstevel@tonic-gate break; 445*7c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_ERR: 446*7c478bd9Sstevel@tonic-gate case PAM_AUTHTOK_RECOVERY_ERR: 447*7c478bd9Sstevel@tonic-gate default: 448*7c478bd9Sstevel@tonic-gate retval = NOPERM; 449*7c478bd9Sstevel@tonic-gate break; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate (void) passwd_exit(retval); 453*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 454*7c478bd9Sstevel@tonic-gate } else { /* changing attributes */ 455*7c478bd9Sstevel@tonic-gate switch (flag) { 456*7c478bd9Sstevel@tonic-gate case EFLAG: /* changing user password attributes */ 457*7c478bd9Sstevel@tonic-gate input = userinput(usrname, &repository, ATTR_SHELL); 458*7c478bd9Sstevel@tonic-gate if (input) 459*7c478bd9Sstevel@tonic-gate attrlist_add(&attributes, ATTR_SHELL, input); 460*7c478bd9Sstevel@tonic-gate else 461*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_SHELL_UNCHANGED)); 462*7c478bd9Sstevel@tonic-gate break; 463*7c478bd9Sstevel@tonic-gate case GFLAG: 464*7c478bd9Sstevel@tonic-gate input = userinput(usrname, &repository, ATTR_GECOS); 465*7c478bd9Sstevel@tonic-gate if (input) 466*7c478bd9Sstevel@tonic-gate attrlist_add(&attributes, ATTR_GECOS, input); 467*7c478bd9Sstevel@tonic-gate else 468*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_GECOS_UNCHANGED)); 469*7c478bd9Sstevel@tonic-gate break; 470*7c478bd9Sstevel@tonic-gate case HFLAG: 471*7c478bd9Sstevel@tonic-gate input = userinput(usrname, &repository, ATTR_HOMEDIR); 472*7c478bd9Sstevel@tonic-gate if (input) 473*7c478bd9Sstevel@tonic-gate attrlist_add(&attributes, ATTR_HOMEDIR, input); 474*7c478bd9Sstevel@tonic-gate else 475*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_DIR_UNCHANGED)); 476*7c478bd9Sstevel@tonic-gate break; 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if (attributes != NULL) { 480*7c478bd9Sstevel@tonic-gate retval = __set_authtoken_attr(usrname, 481*7c478bd9Sstevel@tonic-gate pamh->ps_item[PAM_AUTHTOK].pi_addr, 482*7c478bd9Sstevel@tonic-gate NULL, &repository, attributes, &updated_reps); 483*7c478bd9Sstevel@tonic-gate switch (retval) { 484*7c478bd9Sstevel@tonic-gate case PWU_SUCCESS: 485*7c478bd9Sstevel@tonic-gate for (i = 1; i <= REP_LAST; i <<= 1) { 486*7c478bd9Sstevel@tonic-gate if ((updated_reps & i) == 0) 487*7c478bd9Sstevel@tonic-gate continue; 488*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_SUCCESS), 489*7c478bd9Sstevel@tonic-gate prognamep, usrname); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate retval = SUCCESS; 492*7c478bd9Sstevel@tonic-gate break; 493*7c478bd9Sstevel@tonic-gate case PWU_AGING_DISABLED: 494*7c478bd9Sstevel@tonic-gate retval = BADAGE; 495*7c478bd9Sstevel@tonic-gate break; 496*7c478bd9Sstevel@tonic-gate default: 497*7c478bd9Sstevel@tonic-gate retval = NOPERM; 498*7c478bd9Sstevel@tonic-gate break; 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate } else { 501*7c478bd9Sstevel@tonic-gate retval = SUCCESS; /* nothing to change won't fail */ 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate (void) passwd_exit(retval); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate /* 508*7c478bd9Sstevel@tonic-gate * Get a line of input from the user. 509*7c478bd9Sstevel@tonic-gate * 510*7c478bd9Sstevel@tonic-gate * If the line is empty, or the input equals 'oldval', NULL is returned. 511*7c478bd9Sstevel@tonic-gate * therwise, a malloced string containing the input (minus the trailing 512*7c478bd9Sstevel@tonic-gate * newline) is returned. 513*7c478bd9Sstevel@tonic-gate */ 514*7c478bd9Sstevel@tonic-gate char * 515*7c478bd9Sstevel@tonic-gate getresponse(char *oldval) 516*7c478bd9Sstevel@tonic-gate { 517*7c478bd9Sstevel@tonic-gate char resp[MAX_INPUT_LEN]; 518*7c478bd9Sstevel@tonic-gate char *retval = NULL; 519*7c478bd9Sstevel@tonic-gate int resplen; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate (void) fgets(resp, sizeof (resp) - 1, stdin); 522*7c478bd9Sstevel@tonic-gate resplen = strlen(resp) - 1; 523*7c478bd9Sstevel@tonic-gate if (resp[resplen] == '\n') 524*7c478bd9Sstevel@tonic-gate resp[resplen] = '\0'; 525*7c478bd9Sstevel@tonic-gate if (*resp != '\0' && strcmp(resp, oldval) != 0) 526*7c478bd9Sstevel@tonic-gate retval = strdup(resp); 527*7c478bd9Sstevel@tonic-gate return (retval); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* 531*7c478bd9Sstevel@tonic-gate * char *userinput(item) 532*7c478bd9Sstevel@tonic-gate * 533*7c478bd9Sstevel@tonic-gate * user conversation function. The old value of attribute "item" is 534*7c478bd9Sstevel@tonic-gate * displayed while the user is asked to provide a new value. 535*7c478bd9Sstevel@tonic-gate * 536*7c478bd9Sstevel@tonic-gate * returns a malloc()-ed string if the user actualy provided input 537*7c478bd9Sstevel@tonic-gate * or NULL if the user simply hit return or the input equals the old 538*7c478bd9Sstevel@tonic-gate * value (not changed). 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate char * 541*7c478bd9Sstevel@tonic-gate userinput(char *name, pwu_repository_t *rep, attrtype type) 542*7c478bd9Sstevel@tonic-gate { 543*7c478bd9Sstevel@tonic-gate attrlist oldattr; 544*7c478bd9Sstevel@tonic-gate char *oldval; /* shorthand for oldattr.data.val_s */ 545*7c478bd9Sstevel@tonic-gate char *valid; /* points to valid shells */ 546*7c478bd9Sstevel@tonic-gate char *response; 547*7c478bd9Sstevel@tonic-gate char *cp; 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate oldattr.type = type; 550*7c478bd9Sstevel@tonic-gate oldattr.next = NULL; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate if (__get_authtoken_attr(name, rep, &oldattr) != PWU_SUCCESS) 553*7c478bd9Sstevel@tonic-gate passwd_exit(FMERR); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate oldval = oldattr.data.val_s; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate if (type == ATTR_SHELL) { 558*7c478bd9Sstevel@tonic-gate /* No current shell: set DEFSHL as default choice */ 559*7c478bd9Sstevel@tonic-gate if (*oldval == '\0') { 560*7c478bd9Sstevel@tonic-gate free(oldval); 561*7c478bd9Sstevel@tonic-gate oldval = strdup(DEFSHL); 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate if (ckuid() != SUCCESS) { 565*7c478bd9Sstevel@tonic-gate /* User must currently have a valid shell */ 566*7c478bd9Sstevel@tonic-gate setusershell(); 567*7c478bd9Sstevel@tonic-gate valid = getusershell(); 568*7c478bd9Sstevel@tonic-gate while (valid && strcmp(valid, oldval) != 0) 569*7c478bd9Sstevel@tonic-gate valid = getusershell(); 570*7c478bd9Sstevel@tonic-gate endusershell(); 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if (valid == NULL) { 573*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_RS), oldval); 574*7c478bd9Sstevel@tonic-gate free(oldval); 575*7c478bd9Sstevel@tonic-gate return (NULL); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_OLDSHELL), oldval); 579*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_NEWSHELL)); 580*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate response = getresponse(oldval); 583*7c478bd9Sstevel@tonic-gate free(oldval); /* We don't need the old value anymore */ 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate if (response == NULL || *response == '\0') 586*7c478bd9Sstevel@tonic-gate return (NULL); 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate /* Make sure new shell is listed */ 589*7c478bd9Sstevel@tonic-gate setusershell(); 590*7c478bd9Sstevel@tonic-gate valid = getusershell(); 591*7c478bd9Sstevel@tonic-gate while (valid) { 592*7c478bd9Sstevel@tonic-gate char *cp; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* Allow user to give shell without path */ 595*7c478bd9Sstevel@tonic-gate if (*response == '/') { 596*7c478bd9Sstevel@tonic-gate cp = valid; 597*7c478bd9Sstevel@tonic-gate } else { 598*7c478bd9Sstevel@tonic-gate if ((cp = strrchr(valid, '/')) == NULL) 599*7c478bd9Sstevel@tonic-gate cp = valid; 600*7c478bd9Sstevel@tonic-gate else 601*7c478bd9Sstevel@tonic-gate cp++; 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate if (strcmp(cp, response) == 0) { 604*7c478bd9Sstevel@tonic-gate if (*response != '/') { 605*7c478bd9Sstevel@tonic-gate /* take shell name including path */ 606*7c478bd9Sstevel@tonic-gate free(response); 607*7c478bd9Sstevel@tonic-gate response = strdup(valid); 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate valid = getusershell(); 612*7c478bd9Sstevel@tonic-gate } 613*7c478bd9Sstevel@tonic-gate endusershell(); 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate if (valid == NULL) { /* No valid shell matches */ 616*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNACCEPT), response); 617*7c478bd9Sstevel@tonic-gate return (NULL); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate if (access(response, X_OK) < 0) 621*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNAVAIL), response); 622*7c478bd9Sstevel@tonic-gate return (response); 623*7c478bd9Sstevel@tonic-gate /* NOT REACHED */ 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate /* 626*7c478bd9Sstevel@tonic-gate * if type == SHELL, we have returned by now. Only GECOS and 627*7c478bd9Sstevel@tonic-gate * HOMEDIR get to this point. 628*7c478bd9Sstevel@tonic-gate */ 629*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_INPUTHDR)); 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* 632*7c478bd9Sstevel@tonic-gate * PRE: oldval points to malloced string with Old Value 633*7c478bd9Sstevel@tonic-gate * INV: oldval remains unchanged 634*7c478bd9Sstevel@tonic-gate * POST:response points to valid string or NULL. 635*7c478bd9Sstevel@tonic-gate */ 636*7c478bd9Sstevel@tonic-gate for (;;) { 637*7c478bd9Sstevel@tonic-gate if (type == ATTR_GECOS) 638*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_NAME), oldval); 639*7c478bd9Sstevel@tonic-gate else if (type == ATTR_HOMEDIR) 640*7c478bd9Sstevel@tonic-gate (void) printf(gettext(MSG_HOMEDIR), oldval); 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate response = getresponse(oldval); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate if (response && strcmp(response, "none") == 0) 645*7c478bd9Sstevel@tonic-gate *response = '\0'; 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate /* No-change or empty string are OK */ 648*7c478bd9Sstevel@tonic-gate if (response == NULL || *response == '\0') 649*7c478bd9Sstevel@tonic-gate break; 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* Check for illegal characters */ 652*7c478bd9Sstevel@tonic-gate if (strchr(response, ':')) { 653*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s", gettext(MSG_COLON)); 654*7c478bd9Sstevel@tonic-gate free(response); 655*7c478bd9Sstevel@tonic-gate } else if (strlen(response) > MAX_INPUT_LEN - 1) { 656*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_MAXLEN), 657*7c478bd9Sstevel@tonic-gate MAX_INPUT_LEN); 658*7c478bd9Sstevel@tonic-gate free(response); 659*7c478bd9Sstevel@tonic-gate } else { 660*7c478bd9Sstevel@tonic-gate /* don't allow control characters */ 661*7c478bd9Sstevel@tonic-gate for (cp = response; *cp >= 040; cp++) 662*7c478bd9Sstevel@tonic-gate ; 663*7c478bd9Sstevel@tonic-gate if (*cp != '\0') { 664*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_CONTROL)); 665*7c478bd9Sstevel@tonic-gate free(response); 666*7c478bd9Sstevel@tonic-gate } else 667*7c478bd9Sstevel@tonic-gate break; /* response is a valid string */ 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate /* 670*7c478bd9Sstevel@tonic-gate * We only get here if the input was invalid. 671*7c478bd9Sstevel@tonic-gate * In that case, we again ask the user for input. 672*7c478bd9Sstevel@tonic-gate */ 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate free(oldval); 675*7c478bd9Sstevel@tonic-gate return (response); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate /* 678*7c478bd9Sstevel@tonic-gate * ckarg(): 679*7c478bd9Sstevel@tonic-gate * This function parses and verifies the 680*7c478bd9Sstevel@tonic-gate * arguments. It takes three parameters: 681*7c478bd9Sstevel@tonic-gate * argc => # of arguments 682*7c478bd9Sstevel@tonic-gate * argv => pointer to an argument 683*7c478bd9Sstevel@tonic-gate * attrlist => pointer to list of password attributes 684*7c478bd9Sstevel@tonic-gate */ 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate static int 687*7c478bd9Sstevel@tonic-gate ckarg(int argc, char **argv, attrlist **attributes) 688*7c478bd9Sstevel@tonic-gate { 689*7c478bd9Sstevel@tonic-gate extern char *optarg; 690*7c478bd9Sstevel@tonic-gate char *char_p; 691*7c478bd9Sstevel@tonic-gate int opt; 692*7c478bd9Sstevel@tonic-gate int flag; 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate flag = 0; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "r:aldefghsux:n:w:D:N")) != EOF) { 697*7c478bd9Sstevel@tonic-gate switch (opt) { 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate case 'r': /* Repository Specified */ 700*7c478bd9Sstevel@tonic-gate /* repository: this option should be specified first */ 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate if (repository.type != NULL) { 703*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 704*7c478bd9Sstevel@tonic-gate "Repository is already defined or specified.\n")); 705*7c478bd9Sstevel@tonic-gate rusage(); 706*7c478bd9Sstevel@tonic-gate retval = BADSYN; 707*7c478bd9Sstevel@tonic-gate return (FAIL); 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate if (strcmp(optarg, "nisplus") == 0) { 710*7c478bd9Sstevel@tonic-gate repository.type = optarg; 711*7c478bd9Sstevel@tonic-gate repository.scope = nis_local_directory(); 712*7c478bd9Sstevel@tonic-gate if (repository.scope != NULL) { 713*7c478bd9Sstevel@tonic-gate repository.scope_len = 714*7c478bd9Sstevel@tonic-gate strlen(repository.scope)+ 1; 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "nis") == 0) { 717*7c478bd9Sstevel@tonic-gate repository.type = optarg; 718*7c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "ldap") == 0) { 719*7c478bd9Sstevel@tonic-gate repository.type = optarg; 720*7c478bd9Sstevel@tonic-gate } else if (strcmp(optarg, "files") == 0) { 721*7c478bd9Sstevel@tonic-gate repository.type = optarg; 722*7c478bd9Sstevel@tonic-gate } else { 723*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 724*7c478bd9Sstevel@tonic-gate gettext("invalid repository: %s\n"), 725*7c478bd9Sstevel@tonic-gate optarg); 726*7c478bd9Sstevel@tonic-gate rusage(); 727*7c478bd9Sstevel@tonic-gate retval = BADSYN; 728*7c478bd9Sstevel@tonic-gate return (FAIL); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate break; 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate case 'd': /* Delete Auth Token */ 733*7c478bd9Sstevel@tonic-gate /* if no repository the default for -d is files */ 734*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 735*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate /* 738*7c478bd9Sstevel@tonic-gate * Delete the password - only privileged processes 739*7c478bd9Sstevel@tonic-gate * can execute this for FILES 740*7c478bd9Sstevel@tonic-gate */ 741*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE) { 742*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 743*7c478bd9Sstevel@tonic-gate "-d only applies to files repository\n")); 744*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 745*7c478bd9Sstevel@tonic-gate retval = BADSYN; 746*7c478bd9Sstevel@tonic-gate return (FAIL); 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate if (ckuid() != SUCCESS) { 750*7c478bd9Sstevel@tonic-gate retval = NOPERM; 751*7c478bd9Sstevel@tonic-gate return (FAIL); 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate if (flag & (LFLAG|SAFLAG|DFLAG|XFLAG|UFLAG)) { 754*7c478bd9Sstevel@tonic-gate rusage(); 755*7c478bd9Sstevel@tonic-gate retval = BADOPT; 756*7c478bd9Sstevel@tonic-gate return (FAIL); 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate flag |= DFLAG; 759*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_PASSWD, NULL); 760*7c478bd9Sstevel@tonic-gate break; 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate case 'N': /* set account to be "no login" */ 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate /* if no repository the default for -N is files */ 765*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 766*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 769*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 770*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 771*7c478bd9Sstevel@tonic-gate "-N only applies to files or nisplus repository\n")); 772*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 773*7c478bd9Sstevel@tonic-gate retval = BADOPT; 774*7c478bd9Sstevel@tonic-gate return (FAIL); 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate /* 778*7c478bd9Sstevel@tonic-gate * Only privileged processes can execute this 779*7c478bd9Sstevel@tonic-gate * for FILES 780*7c478bd9Sstevel@tonic-gate */ 781*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 782*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 783*7c478bd9Sstevel@tonic-gate return (FAIL); 784*7c478bd9Sstevel@tonic-gate if (flag & (MUTEXFLAG|NONAGEFLAG)) { 785*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 786*7c478bd9Sstevel@tonic-gate retval = BADOPT; 787*7c478bd9Sstevel@tonic-gate return (FAIL); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate flag |= XFLAG; 790*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_NOLOGIN_ACCOUNT, NULL); 791*7c478bd9Sstevel@tonic-gate break; 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate case 'l': /* lock the password */ 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate /* if no repository the default for -l is files */ 796*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 797*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 800*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 801*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 802*7c478bd9Sstevel@tonic-gate "-l only applies to files or nisplus repository\n")); 803*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 804*7c478bd9Sstevel@tonic-gate retval = BADOPT; 805*7c478bd9Sstevel@tonic-gate return (FAIL); 806*7c478bd9Sstevel@tonic-gate } 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate /* 809*7c478bd9Sstevel@tonic-gate * Only privileged processes can execute this 810*7c478bd9Sstevel@tonic-gate * for FILES 811*7c478bd9Sstevel@tonic-gate */ 812*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 813*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 814*7c478bd9Sstevel@tonic-gate return (FAIL); 815*7c478bd9Sstevel@tonic-gate if (flag & (MUTEXFLAG|NONAGEFLAG)) { 816*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 817*7c478bd9Sstevel@tonic-gate retval = BADOPT; 818*7c478bd9Sstevel@tonic-gate return (FAIL); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate flag |= LFLAG; 821*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_LOCK_ACCOUNT, NULL); 822*7c478bd9Sstevel@tonic-gate break; 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate case 'u': /* unlock the password */ 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate /* if no repository the default for -u is files */ 827*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 828*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 831*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 832*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 833*7c478bd9Sstevel@tonic-gate "-u only applies to files or nisplus repository\n")); 834*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 835*7c478bd9Sstevel@tonic-gate retval = BADOPT; 836*7c478bd9Sstevel@tonic-gate return (FAIL); 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate /* 840*7c478bd9Sstevel@tonic-gate * Only privileged processes can execute this 841*7c478bd9Sstevel@tonic-gate * for FILES 842*7c478bd9Sstevel@tonic-gate */ 843*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 844*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 845*7c478bd9Sstevel@tonic-gate return (FAIL); 846*7c478bd9Sstevel@tonic-gate if (flag & (MUTEXFLAG|NONAGEFLAG)) { 847*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 848*7c478bd9Sstevel@tonic-gate retval = BADOPT; 849*7c478bd9Sstevel@tonic-gate return (FAIL); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate flag |= UFLAG; 852*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_UNLOCK_ACCOUNT, NULL); 853*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_RST_FAILED_LOGINS, NULL); 854*7c478bd9Sstevel@tonic-gate break; 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate case 'x': /* set the max date */ 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate /* if no repository the default for -x is files */ 859*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 860*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 863*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 864*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 865*7c478bd9Sstevel@tonic-gate "-x only applies to files or nisplus repository\n")); 866*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 867*7c478bd9Sstevel@tonic-gate retval = BADSYN; 868*7c478bd9Sstevel@tonic-gate return (FAIL); 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate /* 872*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 873*7c478bd9Sstevel@tonic-gate * for FILES 874*7c478bd9Sstevel@tonic-gate */ 875*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 876*7c478bd9Sstevel@tonic-gate retval = NOPERM; 877*7c478bd9Sstevel@tonic-gate return (FAIL); 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|MFLAG|NONAGEFLAG)) { 880*7c478bd9Sstevel@tonic-gate retval = BADOPT; 881*7c478bd9Sstevel@tonic-gate return (FAIL); 882*7c478bd9Sstevel@tonic-gate } 883*7c478bd9Sstevel@tonic-gate flag |= MFLAG; 884*7c478bd9Sstevel@tonic-gate if ((int)strlen(optarg) <= 0 || 885*7c478bd9Sstevel@tonic-gate (maxdate = strtol(optarg, &char_p, 10)) < -1 || 886*7c478bd9Sstevel@tonic-gate *char_p != '\0') { 887*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -x\n", 888*7c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 889*7c478bd9Sstevel@tonic-gate retval = BADSYN; 890*7c478bd9Sstevel@tonic-gate return (FAIL); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MAX, optarg); 893*7c478bd9Sstevel@tonic-gate break; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate case 'n': /* set the min date */ 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate /* if no repository the default for -n is files */ 898*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 899*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 902*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 903*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 904*7c478bd9Sstevel@tonic-gate "-n only applies to files or nisplus repository\n")); 905*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 906*7c478bd9Sstevel@tonic-gate retval = BADSYN; 907*7c478bd9Sstevel@tonic-gate return (FAIL); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* 911*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 912*7c478bd9Sstevel@tonic-gate * for FILES 913*7c478bd9Sstevel@tonic-gate */ 914*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 915*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 916*7c478bd9Sstevel@tonic-gate return (FAIL); 917*7c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|NFLAG|NONAGEFLAG)) { 918*7c478bd9Sstevel@tonic-gate retval = BADOPT; 919*7c478bd9Sstevel@tonic-gate return (FAIL); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate flag |= NFLAG; 922*7c478bd9Sstevel@tonic-gate if ((int)strlen(optarg) <= 0 || 923*7c478bd9Sstevel@tonic-gate (strtol(optarg, &char_p, 10)) < 0 || 924*7c478bd9Sstevel@tonic-gate *char_p != '\0') { 925*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -n\n", 926*7c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 927*7c478bd9Sstevel@tonic-gate retval = BADSYN; 928*7c478bd9Sstevel@tonic-gate return (FAIL); 929*7c478bd9Sstevel@tonic-gate } 930*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MIN, optarg); 931*7c478bd9Sstevel@tonic-gate break; 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate case 'w': /* set the warning field */ 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* if no repository the default for -w is files */ 936*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 937*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 940*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 941*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 942*7c478bd9Sstevel@tonic-gate "-w only applies to files or nisplus repository\n")); 943*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 944*7c478bd9Sstevel@tonic-gate retval = BADSYN; 945*7c478bd9Sstevel@tonic-gate return (FAIL); 946*7c478bd9Sstevel@tonic-gate } 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate /* 949*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 950*7c478bd9Sstevel@tonic-gate * for FILES 951*7c478bd9Sstevel@tonic-gate */ 952*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 953*7c478bd9Sstevel@tonic-gate retval = NOPERM; 954*7c478bd9Sstevel@tonic-gate return (FAIL); 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|WFLAG|NONAGEFLAG)) { 957*7c478bd9Sstevel@tonic-gate retval = BADOPT; 958*7c478bd9Sstevel@tonic-gate return (FAIL); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate flag |= WFLAG; 961*7c478bd9Sstevel@tonic-gate if ((int)strlen(optarg) <= 0 || 962*7c478bd9Sstevel@tonic-gate (strtol(optarg, &char_p, 10)) < 0 || 963*7c478bd9Sstevel@tonic-gate *char_p != '\0') { 964*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -w\n", 965*7c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 966*7c478bd9Sstevel@tonic-gate retval = BADSYN; 967*7c478bd9Sstevel@tonic-gate return (FAIL); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_WARN, optarg); 970*7c478bd9Sstevel@tonic-gate break; 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate case 's': /* display password attributes */ 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate /* if no repository the default for -s is files */ 975*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 976*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate /* display password attributes */ 980*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 981*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 982*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 983*7c478bd9Sstevel@tonic-gate "-s only applies to files or nisplus repository\n")); 984*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 985*7c478bd9Sstevel@tonic-gate retval = BADSYN; 986*7c478bd9Sstevel@tonic-gate return (FAIL); 987*7c478bd9Sstevel@tonic-gate } 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate /* 990*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 991*7c478bd9Sstevel@tonic-gate * for FILES 992*7c478bd9Sstevel@tonic-gate */ 993*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 994*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 995*7c478bd9Sstevel@tonic-gate return (FAIL); 996*7c478bd9Sstevel@tonic-gate if (flag && (flag != AFLAG)) { 997*7c478bd9Sstevel@tonic-gate retval = BADOPT; 998*7c478bd9Sstevel@tonic-gate return (FAIL); 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate flag |= SFLAG; 1001*7c478bd9Sstevel@tonic-gate break; 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate case 'a': /* display password attributes */ 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate /* if no repository the default for -a is files */ 1006*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 1007*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 1010*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 1011*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1012*7c478bd9Sstevel@tonic-gate "-a only applies to files or nisplus repository\n")); 1013*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 1014*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1015*7c478bd9Sstevel@tonic-gate return (FAIL); 1016*7c478bd9Sstevel@tonic-gate } 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate /* 1019*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1020*7c478bd9Sstevel@tonic-gate * for FILES 1021*7c478bd9Sstevel@tonic-gate */ 1022*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 1023*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 1024*7c478bd9Sstevel@tonic-gate return (FAIL); 1025*7c478bd9Sstevel@tonic-gate if (flag && (flag != SFLAG)) { 1026*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1027*7c478bd9Sstevel@tonic-gate return (FAIL); 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate flag |= AFLAG; 1030*7c478bd9Sstevel@tonic-gate break; 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate case 'f': /* expire password attributes */ 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate /* if no repository the default for -f is files */ 1035*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 1036*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) == FALSE && 1039*7c478bd9Sstevel@tonic-gate IS_NISPLUS(repository) == FALSE) { 1040*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1041*7c478bd9Sstevel@tonic-gate "-f only applies to files or nisplus repository\n")); 1042*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 1043*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1044*7c478bd9Sstevel@tonic-gate return (FAIL); 1045*7c478bd9Sstevel@tonic-gate } 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate /* 1048*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1049*7c478bd9Sstevel@tonic-gate * for FILES 1050*7c478bd9Sstevel@tonic-gate */ 1051*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && 1052*7c478bd9Sstevel@tonic-gate ((retval = ckuid()) != SUCCESS)) 1053*7c478bd9Sstevel@tonic-gate return (FAIL); 1054*7c478bd9Sstevel@tonic-gate if (flag & (SAFLAG|FFLAG|NONAGEFLAG)) { 1055*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1056*7c478bd9Sstevel@tonic-gate return (FAIL); 1057*7c478bd9Sstevel@tonic-gate } 1058*7c478bd9Sstevel@tonic-gate flag |= FFLAG; 1059*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_EXPIRE_PASSWORD, NULL); 1060*7c478bd9Sstevel@tonic-gate break; 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate case 'D': /* domain name specified */ 1063*7c478bd9Sstevel@tonic-gate if (IS_NISPLUS(repository) == FALSE) { 1064*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1065*7c478bd9Sstevel@tonic-gate "-D only applies to nisplus repository\n")); 1066*7c478bd9Sstevel@tonic-gate rusage(); /* exit */ 1067*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1068*7c478bd9Sstevel@tonic-gate return (FAIL); 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate 1071*7c478bd9Sstevel@tonic-gate if (flag & AFLAG) { 1072*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1073*7c478bd9Sstevel@tonic-gate return (FAIL); 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate /* It is cleaner not to set this flag */ 1076*7c478bd9Sstevel@tonic-gate /* flag |= OFLAG; */ 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate /* get domain from optarg */ 1079*7c478bd9Sstevel@tonic-gate repository.scope = optarg; 1080*7c478bd9Sstevel@tonic-gate if (repository.scope != NULL) { 1081*7c478bd9Sstevel@tonic-gate repository.scope_len = 1082*7c478bd9Sstevel@tonic-gate strlen(repository.scope)+1; 1083*7c478bd9Sstevel@tonic-gate } 1084*7c478bd9Sstevel@tonic-gate break; 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate case 'e': /* change login shell */ 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate /* if no repository the default for -e is files */ 1089*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 1090*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate /* 1093*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1094*7c478bd9Sstevel@tonic-gate * for FILES 1095*7c478bd9Sstevel@tonic-gate */ 1096*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 1097*7c478bd9Sstevel@tonic-gate retval = NOPERM; 1098*7c478bd9Sstevel@tonic-gate return (FAIL); 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate if (flag & (EFLAG|SAFLAG|AGEFLAG)) { 1101*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1102*7c478bd9Sstevel@tonic-gate return (FAIL); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate flag |= EFLAG; 1105*7c478bd9Sstevel@tonic-gate break; 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate case 'g': /* change gecos information */ 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate /* if no repository the default for -g is files */ 1110*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 1111*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate /* 1114*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1115*7c478bd9Sstevel@tonic-gate * for FILES 1116*7c478bd9Sstevel@tonic-gate */ 1117*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 1118*7c478bd9Sstevel@tonic-gate retval = NOPERM; 1119*7c478bd9Sstevel@tonic-gate return (FAIL); 1120*7c478bd9Sstevel@tonic-gate } 1121*7c478bd9Sstevel@tonic-gate if (flag & (GFLAG|SAFLAG|AGEFLAG)) { 1122*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1123*7c478bd9Sstevel@tonic-gate return (FAIL); 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate flag |= GFLAG; 1126*7c478bd9Sstevel@tonic-gate break; 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate case 'h': /* change home dir */ 1129*7c478bd9Sstevel@tonic-gate 1130*7c478bd9Sstevel@tonic-gate /* if no repository the default for -h is files */ 1131*7c478bd9Sstevel@tonic-gate if (repository.type == NULL) 1132*7c478bd9Sstevel@tonic-gate repository = __REPFILES; 1133*7c478bd9Sstevel@tonic-gate /* 1134*7c478bd9Sstevel@tonic-gate * Only privileged process can execute this 1135*7c478bd9Sstevel@tonic-gate * for FILES 1136*7c478bd9Sstevel@tonic-gate */ 1137*7c478bd9Sstevel@tonic-gate if (IS_FILES(repository) && (ckuid() != SUCCESS)) { 1138*7c478bd9Sstevel@tonic-gate retval = NOPERM; 1139*7c478bd9Sstevel@tonic-gate return (FAIL); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate if (IS_NIS(repository)) { 1142*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", 1143*7c478bd9Sstevel@tonic-gate gettext(MSG_NIS_HOMEDIR)); 1144*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1145*7c478bd9Sstevel@tonic-gate return (FAIL); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate if (flag & (HFLAG|SAFLAG|AGEFLAG)) { 1149*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1150*7c478bd9Sstevel@tonic-gate return (FAIL); 1151*7c478bd9Sstevel@tonic-gate } 1152*7c478bd9Sstevel@tonic-gate flag |= HFLAG; 1153*7c478bd9Sstevel@tonic-gate break; 1154*7c478bd9Sstevel@tonic-gate 1155*7c478bd9Sstevel@tonic-gate case '?': 1156*7c478bd9Sstevel@tonic-gate rusage(); 1157*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1158*7c478bd9Sstevel@tonic-gate return (FAIL); 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate } 1161*7c478bd9Sstevel@tonic-gate 1162*7c478bd9Sstevel@tonic-gate argc -= optind; 1163*7c478bd9Sstevel@tonic-gate if (argc > 1) { 1164*7c478bd9Sstevel@tonic-gate rusage(); 1165*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1166*7c478bd9Sstevel@tonic-gate return (FAIL); 1167*7c478bd9Sstevel@tonic-gate } 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate /* Make sure (EXPIRE comes after (MAX comes after MIN)) */ 1170*7c478bd9Sstevel@tonic-gate attrlist_reorder(attributes); 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate /* If no options are specified or only the show option */ 1173*7c478bd9Sstevel@tonic-gate /* is specified, return because no option error checking */ 1174*7c478bd9Sstevel@tonic-gate /* is needed */ 1175*7c478bd9Sstevel@tonic-gate if (!flag || (flag == SFLAG)) 1176*7c478bd9Sstevel@tonic-gate return (flag); 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate /* AFLAG must be used with SFLAG */ 1179*7c478bd9Sstevel@tonic-gate if (flag == AFLAG) { 1180*7c478bd9Sstevel@tonic-gate rusage(); 1181*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1182*7c478bd9Sstevel@tonic-gate return (FAIL); 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate if (flag != SAFLAG && argc < 1) { 1186*7c478bd9Sstevel@tonic-gate /* 1187*7c478bd9Sstevel@tonic-gate * user name is not specified (argc<1), it can't be 1188*7c478bd9Sstevel@tonic-gate * aging info update. 1189*7c478bd9Sstevel@tonic-gate */ 1190*7c478bd9Sstevel@tonic-gate if (!(flag & NONAGEFLAG)) { 1191*7c478bd9Sstevel@tonic-gate rusage(); 1192*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1193*7c478bd9Sstevel@tonic-gate return (FAIL); 1194*7c478bd9Sstevel@tonic-gate } 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate /* user name(s) may not be specified when SAFLAG is used. */ 1198*7c478bd9Sstevel@tonic-gate if (flag == SAFLAG && argc >= 1) { 1199*7c478bd9Sstevel@tonic-gate rusage(); 1200*7c478bd9Sstevel@tonic-gate retval = BADSYN; 1201*7c478bd9Sstevel@tonic-gate return (FAIL); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate /* 1205*7c478bd9Sstevel@tonic-gate * If aging is being turned off (maxdate == -1), mindate may not 1206*7c478bd9Sstevel@tonic-gate * be specified. 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate if ((maxdate == -1) && (flag & NFLAG)) { 1209*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s -n\n", 1210*7c478bd9Sstevel@tonic-gate prognamep, gettext(MSG_NV)); 1211*7c478bd9Sstevel@tonic-gate retval = BADOPT; 1212*7c478bd9Sstevel@tonic-gate return (FAIL); 1213*7c478bd9Sstevel@tonic-gate } 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate return (flag); 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate /* 1219*7c478bd9Sstevel@tonic-gate * 1220*7c478bd9Sstevel@tonic-gate * ckuid(): 1221*7c478bd9Sstevel@tonic-gate * This function returns SUCCESS if the caller is root, else 1222*7c478bd9Sstevel@tonic-gate * it returns NOPERM. 1223*7c478bd9Sstevel@tonic-gate * 1224*7c478bd9Sstevel@tonic-gate */ 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate static int 1227*7c478bd9Sstevel@tonic-gate ckuid() 1228*7c478bd9Sstevel@tonic-gate { 1229*7c478bd9Sstevel@tonic-gate if (uid != 0) { 1230*7c478bd9Sstevel@tonic-gate return (retval = NOPERM); 1231*7c478bd9Sstevel@tonic-gate } 1232*7c478bd9Sstevel@tonic-gate return (SUCCESS); 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate 1236*7c478bd9Sstevel@tonic-gate /* 1237*7c478bd9Sstevel@tonic-gate * get_attr() 1238*7c478bd9Sstevel@tonic-gate */ 1239*7c478bd9Sstevel@tonic-gate int 1240*7c478bd9Sstevel@tonic-gate get_attr(char *username, pwu_repository_t *repository, attrlist **attributes) 1241*7c478bd9Sstevel@tonic-gate { 1242*7c478bd9Sstevel@tonic-gate int res; 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_PASSWD, NULL); 1245*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_LSTCHG, "0"); 1246*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MIN, "0"); 1247*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_MAX, "0"); 1248*7c478bd9Sstevel@tonic-gate attrlist_add(attributes, ATTR_WARN, "0"); 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate res = __get_authtoken_attr(username, repository, *attributes); 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate if (res == PWU_SUCCESS) { 1253*7c478bd9Sstevel@tonic-gate retval = SUCCESS; 1254*7c478bd9Sstevel@tonic-gate return (PWU_SUCCESS); 1255*7c478bd9Sstevel@tonic-gate } 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate if (res == PWU_NOT_FOUND) 1258*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(MSG_UNKNOWN), prognamep, 1259*7c478bd9Sstevel@tonic-gate username); 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate retval = NOPERM; 1262*7c478bd9Sstevel@tonic-gate passwd_exit(retval); 1263*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate /* 1267*7c478bd9Sstevel@tonic-gate * display_attr(): 1268*7c478bd9Sstevel@tonic-gate * This function prints out the password attributes of a usr 1269*7c478bd9Sstevel@tonic-gate * onto standand output. 1270*7c478bd9Sstevel@tonic-gate */ 1271*7c478bd9Sstevel@tonic-gate void 1272*7c478bd9Sstevel@tonic-gate display_attr(char *usrname, attrlist *attributes) 1273*7c478bd9Sstevel@tonic-gate { 1274*7c478bd9Sstevel@tonic-gate char *status; 1275*7c478bd9Sstevel@tonic-gate char *passwd; 1276*7c478bd9Sstevel@tonic-gate long lstchg; 1277*7c478bd9Sstevel@tonic-gate int min, max, warn; 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate while (attributes) { 1280*7c478bd9Sstevel@tonic-gate switch (attributes->type) { 1281*7c478bd9Sstevel@tonic-gate case ATTR_PASSWD: 1282*7c478bd9Sstevel@tonic-gate passwd = attributes->data.val_s; 1283*7c478bd9Sstevel@tonic-gate if (passwd == NULL || *passwd == '\0') 1284*7c478bd9Sstevel@tonic-gate status = "NP "; 1285*7c478bd9Sstevel@tonic-gate else if (strncmp(passwd, LOCKSTRING, 1286*7c478bd9Sstevel@tonic-gate sizeof (LOCKSTRING)-1) == 0) 1287*7c478bd9Sstevel@tonic-gate status = "LK "; 1288*7c478bd9Sstevel@tonic-gate else if (strncmp(passwd, NOLOGINSTRING, 1289*7c478bd9Sstevel@tonic-gate sizeof (NOLOGINSTRING)-1) == 0) 1290*7c478bd9Sstevel@tonic-gate status = "NL "; 1291*7c478bd9Sstevel@tonic-gate else 1292*7c478bd9Sstevel@tonic-gate status = "PS "; 1293*7c478bd9Sstevel@tonic-gate break; 1294*7c478bd9Sstevel@tonic-gate case ATTR_LSTCHG: 1295*7c478bd9Sstevel@tonic-gate lstchg = attributes->data.val_i * DAY; 1296*7c478bd9Sstevel@tonic-gate break; 1297*7c478bd9Sstevel@tonic-gate case ATTR_MIN: 1298*7c478bd9Sstevel@tonic-gate min = attributes->data.val_i; 1299*7c478bd9Sstevel@tonic-gate break; 1300*7c478bd9Sstevel@tonic-gate case ATTR_MAX: 1301*7c478bd9Sstevel@tonic-gate max = attributes->data.val_i; 1302*7c478bd9Sstevel@tonic-gate break; 1303*7c478bd9Sstevel@tonic-gate case ATTR_WARN: 1304*7c478bd9Sstevel@tonic-gate warn = attributes->data.val_i; 1305*7c478bd9Sstevel@tonic-gate break; 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate attributes = attributes->next; 1308*7c478bd9Sstevel@tonic-gate } 1309*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%-8s ", usrname); 1310*7c478bd9Sstevel@tonic-gate 1311*7c478bd9Sstevel@tonic-gate if (status) 1312*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s ", status); 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate if (max != -1) { 1315*7c478bd9Sstevel@tonic-gate if (lstchg == 0) { 1316*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "00/00/00 "); 1317*7c478bd9Sstevel@tonic-gate } else { 1318*7c478bd9Sstevel@tonic-gate struct tm *tmp; 1319*7c478bd9Sstevel@tonic-gate tmp = gmtime(&lstchg); 1320*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%.2d/%.2d/%.2d ", 1321*7c478bd9Sstevel@tonic-gate tmp->tm_mon + 1, 1322*7c478bd9Sstevel@tonic-gate tmp->tm_mday, 1323*7c478bd9Sstevel@tonic-gate tmp->tm_year % 100); 1324*7c478bd9Sstevel@tonic-gate } 1325*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, (min >= 0) ? "%4d " : " ", min); 1326*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%4d ", max); 1327*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, (warn > 0) ? "%4d " : " ", warn); 1328*7c478bd9Sstevel@tonic-gate } 1329*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate void 1333*7c478bd9Sstevel@tonic-gate free_attr(attrlist *attributes) 1334*7c478bd9Sstevel@tonic-gate { 1335*7c478bd9Sstevel@tonic-gate while (attributes) { 1336*7c478bd9Sstevel@tonic-gate if (attributes->type == ATTR_PASSWD) 1337*7c478bd9Sstevel@tonic-gate free(attributes->data.val_s); 1338*7c478bd9Sstevel@tonic-gate attributes = attributes->next; 1339*7c478bd9Sstevel@tonic-gate } 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate /* 1343*7c478bd9Sstevel@tonic-gate * 1344*7c478bd9Sstevel@tonic-gate * get_namelist_files(): 1345*7c478bd9Sstevel@tonic-gate * This function gets a list of user names on the system from 1346*7c478bd9Sstevel@tonic-gate * the /etc/passwd file. 1347*7c478bd9Sstevel@tonic-gate * 1348*7c478bd9Sstevel@tonic-gate */ 1349*7c478bd9Sstevel@tonic-gate int 1350*7c478bd9Sstevel@tonic-gate get_namelist_files(namelist_p, num_user) 1351*7c478bd9Sstevel@tonic-gate char ***namelist_p; 1352*7c478bd9Sstevel@tonic-gate int *num_user; 1353*7c478bd9Sstevel@tonic-gate { 1354*7c478bd9Sstevel@tonic-gate FILE *pwfp; 1355*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 1356*7c478bd9Sstevel@tonic-gate int max_user; 1357*7c478bd9Sstevel@tonic-gate int nuser; 1358*7c478bd9Sstevel@tonic-gate char **nl; 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate nuser = 0; 1361*7c478bd9Sstevel@tonic-gate errno = 0; 1362*7c478bd9Sstevel@tonic-gate pwd = NULL; 1363*7c478bd9Sstevel@tonic-gate 1364*7c478bd9Sstevel@tonic-gate if ((pwfp = fopen(PASSWD, "r")) == NULL) 1365*7c478bd9Sstevel@tonic-gate return (NOPERM); 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate /* 1368*7c478bd9Sstevel@tonic-gate * find out the actual number of entries in the PASSWD file 1369*7c478bd9Sstevel@tonic-gate */ 1370*7c478bd9Sstevel@tonic-gate max_user = 1; /* need one slot for terminator NULL */ 1371*7c478bd9Sstevel@tonic-gate while ((pwd = fgetpwent(pwfp)) != NULL) 1372*7c478bd9Sstevel@tonic-gate max_user++; 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate /* 1375*7c478bd9Sstevel@tonic-gate * reset the file stream pointer 1376*7c478bd9Sstevel@tonic-gate */ 1377*7c478bd9Sstevel@tonic-gate rewind(pwfp); 1378*7c478bd9Sstevel@tonic-gate 1379*7c478bd9Sstevel@tonic-gate nl = (char **)calloc(max_user, (sizeof (char *))); 1380*7c478bd9Sstevel@tonic-gate if (nl == NULL) { 1381*7c478bd9Sstevel@tonic-gate (void) fclose(pwfp); 1382*7c478bd9Sstevel@tonic-gate return (FMERR); 1383*7c478bd9Sstevel@tonic-gate } 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate while ((pwd = fgetpwent(pwfp)) != NULL) { 1386*7c478bd9Sstevel@tonic-gate if ((nl[nuser] = strdup(pwd->pw_name)) == NULL) { 1387*7c478bd9Sstevel@tonic-gate (void) fclose(pwfp); 1388*7c478bd9Sstevel@tonic-gate return (FMERR); 1389*7c478bd9Sstevel@tonic-gate } 1390*7c478bd9Sstevel@tonic-gate nuser++; 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate nl[nuser] = NULL; 1394*7c478bd9Sstevel@tonic-gate *num_user = nuser; 1395*7c478bd9Sstevel@tonic-gate *namelist_p = nl; 1396*7c478bd9Sstevel@tonic-gate (void) fclose(pwfp); 1397*7c478bd9Sstevel@tonic-gate return (SUCCESS); 1398*7c478bd9Sstevel@tonic-gate } 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate /* 1401*7c478bd9Sstevel@tonic-gate * get_namelist_nisplus 1402*7c478bd9Sstevel@tonic-gate * 1403*7c478bd9Sstevel@tonic-gate */ 1404*7c478bd9Sstevel@tonic-gate 1405*7c478bd9Sstevel@tonic-gate /* 1406*7c478bd9Sstevel@tonic-gate * Our private version of the switch frontend for getspent. We want to 1407*7c478bd9Sstevel@tonic-gate * search just the nisplus sp file, so we want to bypass normal nsswitch.conf 1408*7c478bd9Sstevel@tonic-gate * based processing. This implementation compatible with version 2 of the 1409*7c478bd9Sstevel@tonic-gate * name service switch. 1410*7c478bd9Sstevel@tonic-gate */ 1411*7c478bd9Sstevel@tonic-gate #define NSS_NISPLUS_ONLY "nisplus" 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate extern int str2spwd(const char *, int, void *, char *, int); 1414*7c478bd9Sstevel@tonic-gate 1415*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root); 1416*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_GETENT(context); 1417*7c478bd9Sstevel@tonic-gate 1418*7c478bd9Sstevel@tonic-gate static void 1419*7c478bd9Sstevel@tonic-gate _np_nss_initf_shadow(p) 1420*7c478bd9Sstevel@tonic-gate nss_db_params_t *p; 1421*7c478bd9Sstevel@tonic-gate { 1422*7c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_SHADOW; 1423*7c478bd9Sstevel@tonic-gate p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */ 1424*7c478bd9Sstevel@tonic-gate p->default_config = NSS_NISPLUS_ONLY; /* Use nisplus only */ 1425*7c478bd9Sstevel@tonic-gate p->flags = NSS_USE_DEFAULT_CONFIG; 1426*7c478bd9Sstevel@tonic-gate } 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate static void 1429*7c478bd9Sstevel@tonic-gate _np_setspent() 1430*7c478bd9Sstevel@tonic-gate { 1431*7c478bd9Sstevel@tonic-gate nss_setent(&db_root, _np_nss_initf_shadow, &context); 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate static void 1435*7c478bd9Sstevel@tonic-gate _np_endspent() 1436*7c478bd9Sstevel@tonic-gate { 1437*7c478bd9Sstevel@tonic-gate nss_endent(&db_root, _np_nss_initf_shadow, &context); 1438*7c478bd9Sstevel@tonic-gate nss_delete(&db_root); 1439*7c478bd9Sstevel@tonic-gate } 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate static struct spwd * 1442*7c478bd9Sstevel@tonic-gate _np_getspent_r(result, buffer, buflen) 1443*7c478bd9Sstevel@tonic-gate struct spwd *result; 1444*7c478bd9Sstevel@tonic-gate char *buffer; 1445*7c478bd9Sstevel@tonic-gate int buflen; 1446*7c478bd9Sstevel@tonic-gate { 1447*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1448*7c478bd9Sstevel@tonic-gate char *nam; 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate /* In getXXent_r(), protect the unsuspecting caller from +/- entries */ 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate do { 1453*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd); 1454*7c478bd9Sstevel@tonic-gate /* No key to fill in */ 1455*7c478bd9Sstevel@tonic-gate (void) nss_getent(&db_root, _np_nss_initf_shadow, &context, 1456*7c478bd9Sstevel@tonic-gate &arg); 1457*7c478bd9Sstevel@tonic-gate } while (arg.returnval != 0 && 1458*7c478bd9Sstevel@tonic-gate (nam = ((struct spwd *)arg.returnval)->sp_namp) != 0 && 1459*7c478bd9Sstevel@tonic-gate (*nam == '+' || *nam == '-')); 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate return (struct spwd *)NSS_XbyY_FINI(&arg); 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate static nss_XbyY_buf_t *buffer; 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate static struct spwd * 1467*7c478bd9Sstevel@tonic-gate _np_getspent() 1468*7c478bd9Sstevel@tonic-gate { 1469*7c478bd9Sstevel@tonic-gate nss_XbyY_buf_t *b; 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate b = NSS_XbyY_ALLOC(&buffer, sizeof (struct spwd), NSS_BUFLEN_SHADOW); 1472*7c478bd9Sstevel@tonic-gate 1473*7c478bd9Sstevel@tonic-gate return (b == 0 ? 0 : _np_getspent_r(b->result, b->buffer, b->buflen)); 1474*7c478bd9Sstevel@tonic-gate } 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate int 1477*7c478bd9Sstevel@tonic-gate get_namelist_nisplus(char ***namelist_p, int *num_user) 1478*7c478bd9Sstevel@tonic-gate { 1479*7c478bd9Sstevel@tonic-gate int nuser = 0; 1480*7c478bd9Sstevel@tonic-gate int alloced = 100; 1481*7c478bd9Sstevel@tonic-gate char **nl; 1482*7c478bd9Sstevel@tonic-gate struct spwd *p; 1483*7c478bd9Sstevel@tonic-gate 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate if ((nl = calloc(alloced, sizeof (*nl))) == NULL) 1486*7c478bd9Sstevel@tonic-gate return (FMERR); 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate (void) _np_setspent(); 1489*7c478bd9Sstevel@tonic-gate while ((p = _np_getspent()) != NULL) { 1490*7c478bd9Sstevel@tonic-gate if ((nl[nuser] = strdup(p->sp_namp)) == NULL) { 1491*7c478bd9Sstevel@tonic-gate _np_endspent(); 1492*7c478bd9Sstevel@tonic-gate return (FMERR); 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate if (++nuser == alloced) { 1495*7c478bd9Sstevel@tonic-gate alloced += 100; 1496*7c478bd9Sstevel@tonic-gate nl = realloc(nl, alloced * (sizeof (*nl))); 1497*7c478bd9Sstevel@tonic-gate if (nl == NULL) { 1498*7c478bd9Sstevel@tonic-gate _np_endspent(); 1499*7c478bd9Sstevel@tonic-gate return (FMERR); 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate (void) _np_endspent(); 1504*7c478bd9Sstevel@tonic-gate nl[nuser] = NULL; 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate *namelist_p = nl; 1507*7c478bd9Sstevel@tonic-gate *num_user = nuser; /* including NULL */ 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate return (SUCCESS); 1510*7c478bd9Sstevel@tonic-gate } 1511*7c478bd9Sstevel@tonic-gate 1512*7c478bd9Sstevel@tonic-gate int 1513*7c478bd9Sstevel@tonic-gate get_namelist(pwu_repository_t repository, char ***namelist, int *num_user) 1514*7c478bd9Sstevel@tonic-gate { 1515*7c478bd9Sstevel@tonic-gate if (IS_NISPLUS(repository)) 1516*7c478bd9Sstevel@tonic-gate return (get_namelist_nisplus(namelist, num_user)); 1517*7c478bd9Sstevel@tonic-gate else if (IS_FILES(repository)) 1518*7c478bd9Sstevel@tonic-gate return (get_namelist_files(namelist, num_user)); 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate rusage(); 1521*7c478bd9Sstevel@tonic-gate return (BADSYN); 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate /* 1525*7c478bd9Sstevel@tonic-gate * 1526*7c478bd9Sstevel@tonic-gate * passwd_exit(): 1527*7c478bd9Sstevel@tonic-gate * This function will call exit() with appropriate exit code 1528*7c478bd9Sstevel@tonic-gate * according to the input "retcode" value. 1529*7c478bd9Sstevel@tonic-gate * It also calls pam_end() to clean-up buffers before exit. 1530*7c478bd9Sstevel@tonic-gate * 1531*7c478bd9Sstevel@tonic-gate */ 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate void 1534*7c478bd9Sstevel@tonic-gate passwd_exit(retcode) 1535*7c478bd9Sstevel@tonic-gate int retcode; 1536*7c478bd9Sstevel@tonic-gate { 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate if (pamh) 1539*7c478bd9Sstevel@tonic-gate (void) pam_end(pamh, pam_retval); 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate switch (retcode) { 1542*7c478bd9Sstevel@tonic-gate case SUCCESS: 1543*7c478bd9Sstevel@tonic-gate break; 1544*7c478bd9Sstevel@tonic-gate case NOPERM: 1545*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NP)); 1546*7c478bd9Sstevel@tonic-gate break; 1547*7c478bd9Sstevel@tonic-gate case BADOPT: 1548*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_BS)); 1549*7c478bd9Sstevel@tonic-gate break; 1550*7c478bd9Sstevel@tonic-gate case FMERR: 1551*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_FE)); 1552*7c478bd9Sstevel@tonic-gate break; 1553*7c478bd9Sstevel@tonic-gate case FATAL: 1554*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_FF)); 1555*7c478bd9Sstevel@tonic-gate break; 1556*7c478bd9Sstevel@tonic-gate case FBUSY: 1557*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_FB)); 1558*7c478bd9Sstevel@tonic-gate break; 1559*7c478bd9Sstevel@tonic-gate case BADSYN: 1560*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NV)); 1561*7c478bd9Sstevel@tonic-gate break; 1562*7c478bd9Sstevel@tonic-gate case BADAGE: 1563*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_AD)); 1564*7c478bd9Sstevel@tonic-gate break; 1565*7c478bd9Sstevel@tonic-gate case NOMEM: 1566*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NM)); 1567*7c478bd9Sstevel@tonic-gate break; 1568*7c478bd9Sstevel@tonic-gate default: 1569*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gettext(MSG_NP)); 1570*7c478bd9Sstevel@tonic-gate retcode = NOPERM; 1571*7c478bd9Sstevel@tonic-gate break; 1572*7c478bd9Sstevel@tonic-gate } 1573*7c478bd9Sstevel@tonic-gate /* write password record */ 1574*7c478bd9Sstevel@tonic-gate if (event != NULL) { 1575*7c478bd9Sstevel@tonic-gate if (adt_put_event(event, 1576*7c478bd9Sstevel@tonic-gate retcode == SUCCESS ? ADT_SUCCESS : ADT_FAILURE, 1577*7c478bd9Sstevel@tonic-gate retcode == SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM + 1578*7c478bd9Sstevel@tonic-gate pam_retval) != 0) { 1579*7c478bd9Sstevel@tonic-gate adt_free_event(event); 1580*7c478bd9Sstevel@tonic-gate (void) adt_end_session(ah); 1581*7c478bd9Sstevel@tonic-gate perror("adt_put_event"); 1582*7c478bd9Sstevel@tonic-gate exit(retcode); 1583*7c478bd9Sstevel@tonic-gate } 1584*7c478bd9Sstevel@tonic-gate adt_free_event(event); 1585*7c478bd9Sstevel@tonic-gate } 1586*7c478bd9Sstevel@tonic-gate (void) adt_end_session(ah); 1587*7c478bd9Sstevel@tonic-gate exit(retcode); 1588*7c478bd9Sstevel@tonic-gate } 1589*7c478bd9Sstevel@tonic-gate 1590*7c478bd9Sstevel@tonic-gate /* 1591*7c478bd9Sstevel@tonic-gate * 1592*7c478bd9Sstevel@tonic-gate * passwd_conv(): 1593*7c478bd9Sstevel@tonic-gate * This is the conv (conversation) function called from 1594*7c478bd9Sstevel@tonic-gate * a PAM authentication module to print error messages 1595*7c478bd9Sstevel@tonic-gate * or garner information from the user. 1596*7c478bd9Sstevel@tonic-gate * 1597*7c478bd9Sstevel@tonic-gate */ 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1600*7c478bd9Sstevel@tonic-gate static int 1601*7c478bd9Sstevel@tonic-gate passwd_conv(num_msg, msg, response, appdata_ptr) 1602*7c478bd9Sstevel@tonic-gate int num_msg; 1603*7c478bd9Sstevel@tonic-gate struct pam_message **msg; 1604*7c478bd9Sstevel@tonic-gate struct pam_response **response; 1605*7c478bd9Sstevel@tonic-gate void *appdata_ptr; 1606*7c478bd9Sstevel@tonic-gate { 1607*7c478bd9Sstevel@tonic-gate struct pam_message *m; 1608*7c478bd9Sstevel@tonic-gate struct pam_response *r; 1609*7c478bd9Sstevel@tonic-gate char *temp; 1610*7c478bd9Sstevel@tonic-gate int k, i; 1611*7c478bd9Sstevel@tonic-gate 1612*7c478bd9Sstevel@tonic-gate if (num_msg <= 0) 1613*7c478bd9Sstevel@tonic-gate return (PAM_CONV_ERR); 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate *response = (struct pam_response *)calloc(num_msg, 1616*7c478bd9Sstevel@tonic-gate sizeof (struct pam_response)); 1617*7c478bd9Sstevel@tonic-gate if (*response == NULL) 1618*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 1619*7c478bd9Sstevel@tonic-gate 1620*7c478bd9Sstevel@tonic-gate k = num_msg; 1621*7c478bd9Sstevel@tonic-gate m = *msg; 1622*7c478bd9Sstevel@tonic-gate r = *response; 1623*7c478bd9Sstevel@tonic-gate while (k--) { 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate switch (m->msg_style) { 1626*7c478bd9Sstevel@tonic-gate 1627*7c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF: 1628*7c478bd9Sstevel@tonic-gate temp = getpassphrase(m->msg); 1629*7c478bd9Sstevel@tonic-gate if (temp != NULL) { 1630*7c478bd9Sstevel@tonic-gate r->resp = strdup(temp); 1631*7c478bd9Sstevel@tonic-gate (void) memset(temp, 0, strlen(temp)); 1632*7c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 1633*7c478bd9Sstevel@tonic-gate /* free responses */ 1634*7c478bd9Sstevel@tonic-gate r = *response; 1635*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 1636*7c478bd9Sstevel@tonic-gate if (r->resp) 1637*7c478bd9Sstevel@tonic-gate free(r->resp); 1638*7c478bd9Sstevel@tonic-gate } 1639*7c478bd9Sstevel@tonic-gate free(*response); 1640*7c478bd9Sstevel@tonic-gate *response = NULL; 1641*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 1642*7c478bd9Sstevel@tonic-gate } 1643*7c478bd9Sstevel@tonic-gate } 1644*7c478bd9Sstevel@tonic-gate m++; 1645*7c478bd9Sstevel@tonic-gate r++; 1646*7c478bd9Sstevel@tonic-gate break; 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON: 1649*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 1650*7c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout); 1651*7c478bd9Sstevel@tonic-gate } 1652*7c478bd9Sstevel@tonic-gate r->resp = (char *)calloc(PAM_MAX_RESP_SIZE, 1653*7c478bd9Sstevel@tonic-gate sizeof (char)); 1654*7c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 1655*7c478bd9Sstevel@tonic-gate /* free responses */ 1656*7c478bd9Sstevel@tonic-gate r = *response; 1657*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 1658*7c478bd9Sstevel@tonic-gate if (r->resp) 1659*7c478bd9Sstevel@tonic-gate free(r->resp); 1660*7c478bd9Sstevel@tonic-gate } 1661*7c478bd9Sstevel@tonic-gate free(*response); 1662*7c478bd9Sstevel@tonic-gate *response = NULL; 1663*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 1664*7c478bd9Sstevel@tonic-gate } 1665*7c478bd9Sstevel@tonic-gate if (fgets(r->resp, PAM_MAX_RESP_SIZE-1, stdin)) { 1666*7c478bd9Sstevel@tonic-gate int len = strlen(r->resp); 1667*7c478bd9Sstevel@tonic-gate if (r->resp[len-1] == '\n') 1668*7c478bd9Sstevel@tonic-gate r->resp[len-1] = '\0'; 1669*7c478bd9Sstevel@tonic-gate } 1670*7c478bd9Sstevel@tonic-gate m++; 1671*7c478bd9Sstevel@tonic-gate r++; 1672*7c478bd9Sstevel@tonic-gate break; 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG: 1675*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 1676*7c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stderr); 1677*7c478bd9Sstevel@tonic-gate (void) fputs("\n", stderr); 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate m++; 1680*7c478bd9Sstevel@tonic-gate r++; 1681*7c478bd9Sstevel@tonic-gate break; 1682*7c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO: 1683*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 1684*7c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout); 1685*7c478bd9Sstevel@tonic-gate (void) fputs("\n", stdout); 1686*7c478bd9Sstevel@tonic-gate } 1687*7c478bd9Sstevel@tonic-gate m++; 1688*7c478bd9Sstevel@tonic-gate r++; 1689*7c478bd9Sstevel@tonic-gate break; 1690*7c478bd9Sstevel@tonic-gate 1691*7c478bd9Sstevel@tonic-gate default: 1692*7c478bd9Sstevel@tonic-gate break; 1693*7c478bd9Sstevel@tonic-gate } 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 1696*7c478bd9Sstevel@tonic-gate } 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate /* 1699*7c478bd9Sstevel@tonic-gate * Utilities Functions 1700*7c478bd9Sstevel@tonic-gate */ 1701*7c478bd9Sstevel@tonic-gate 1702*7c478bd9Sstevel@tonic-gate /* 1703*7c478bd9Sstevel@tonic-gate * int attrlist_add(attrlist **l, attrtype type, char *val) 1704*7c478bd9Sstevel@tonic-gate * add an item, with type "type" and value "val", at the tail of list l. 1705*7c478bd9Sstevel@tonic-gate * This functions exits the application on OutOfMem error. 1706*7c478bd9Sstevel@tonic-gate */ 1707*7c478bd9Sstevel@tonic-gate void 1708*7c478bd9Sstevel@tonic-gate attrlist_add(attrlist **l, attrtype type, char *val) 1709*7c478bd9Sstevel@tonic-gate { 1710*7c478bd9Sstevel@tonic-gate attrlist **w; 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate /* tail insert */ 1713*7c478bd9Sstevel@tonic-gate for (w = l; *w != NULL; w = &(*w)->next) 1714*7c478bd9Sstevel@tonic-gate ; 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate if ((*w = malloc(sizeof (**w))) == NULL) 1717*7c478bd9Sstevel@tonic-gate passwd_exit(NOMEM); 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate (*w)->type = type; 1720*7c478bd9Sstevel@tonic-gate (*w)->next = NULL; 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate switch (type) { 1723*7c478bd9Sstevel@tonic-gate case ATTR_MIN: 1724*7c478bd9Sstevel@tonic-gate case ATTR_WARN: 1725*7c478bd9Sstevel@tonic-gate case ATTR_MAX: 1726*7c478bd9Sstevel@tonic-gate (*w)->data.val_i = atoi(val); 1727*7c478bd9Sstevel@tonic-gate break; 1728*7c478bd9Sstevel@tonic-gate default: 1729*7c478bd9Sstevel@tonic-gate (*w)->data.val_s = val; 1730*7c478bd9Sstevel@tonic-gate break; 1731*7c478bd9Sstevel@tonic-gate } 1732*7c478bd9Sstevel@tonic-gate } 1733*7c478bd9Sstevel@tonic-gate 1734*7c478bd9Sstevel@tonic-gate /* 1735*7c478bd9Sstevel@tonic-gate * attrlist_reorder(attrlist **l) 1736*7c478bd9Sstevel@tonic-gate * Make sure that 1737*7c478bd9Sstevel@tonic-gate * - if EXPIRE and MAX or MIN is set, EXPIRE comes after MAX/MIN 1738*7c478bd9Sstevel@tonic-gate * - if both MIN and MAX are set, MAX comes before MIN. 1739*7c478bd9Sstevel@tonic-gate */ 1740*7c478bd9Sstevel@tonic-gate 1741*7c478bd9Sstevel@tonic-gate static void 1742*7c478bd9Sstevel@tonic-gate attrlist_reorder(attrlist **l) 1743*7c478bd9Sstevel@tonic-gate { 1744*7c478bd9Sstevel@tonic-gate attrlist **w; 1745*7c478bd9Sstevel@tonic-gate attrlist *exp = NULL; /* ATTR_EXPIRE_PASSWORD, if found */ 1746*7c478bd9Sstevel@tonic-gate attrlist *max = NULL; /* ATTR_MAX, if found */ 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate if (*l == NULL || (*l)->next == NULL) 1749*7c478bd9Sstevel@tonic-gate return; /* order of list with <= one item is ok */ 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate /* 1752*7c478bd9Sstevel@tonic-gate * We simply walk the list, take off the EXPIRE and MAX items if 1753*7c478bd9Sstevel@tonic-gate * they appear, and put them (first MAX, them EXPIRE) at the end 1754*7c478bd9Sstevel@tonic-gate * of the list. 1755*7c478bd9Sstevel@tonic-gate */ 1756*7c478bd9Sstevel@tonic-gate w = l; 1757*7c478bd9Sstevel@tonic-gate while (*w != NULL) { 1758*7c478bd9Sstevel@tonic-gate if ((*w)->type == ATTR_EXPIRE_PASSWORD) { 1759*7c478bd9Sstevel@tonic-gate exp = *w; 1760*7c478bd9Sstevel@tonic-gate *w = (*w)->next; 1761*7c478bd9Sstevel@tonic-gate } else if ((*w)->type == ATTR_MAX) { 1762*7c478bd9Sstevel@tonic-gate max = *w; 1763*7c478bd9Sstevel@tonic-gate *w = (*w)->next; 1764*7c478bd9Sstevel@tonic-gate } else 1765*7c478bd9Sstevel@tonic-gate w = &(*w)->next; 1766*7c478bd9Sstevel@tonic-gate } 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate /* 'w' points to the address of the 'next' field of the last element */ 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate if (max) { 1771*7c478bd9Sstevel@tonic-gate *w = max; 1772*7c478bd9Sstevel@tonic-gate w = &max->next; 1773*7c478bd9Sstevel@tonic-gate } 1774*7c478bd9Sstevel@tonic-gate if (exp) { 1775*7c478bd9Sstevel@tonic-gate *w = exp; 1776*7c478bd9Sstevel@tonic-gate w = &exp->next; 1777*7c478bd9Sstevel@tonic-gate } 1778*7c478bd9Sstevel@tonic-gate *w = NULL; 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate void 1782*7c478bd9Sstevel@tonic-gate rusage() 1783*7c478bd9Sstevel@tonic-gate { 1784*7c478bd9Sstevel@tonic-gate 1785*7c478bd9Sstevel@tonic-gate #define MSG(a) (void) fprintf(stderr, gettext((a))); 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate MSG("usage:\n"); 1788*7c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files | -r nis | -r nisplus | -r ldap] [name]\n"); 1789*7c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] [-egh] [name]\n"); 1790*7c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] -sa\n"); 1791*7c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] -s [name]\n"); 1792*7c478bd9Sstevel@tonic-gate MSG("\tpasswd [-r files] [-d|-l|-N|-u] [-f] [-n min] [-w warn] " 1793*7c478bd9Sstevel@tonic-gate "[-x max] name\n"); 1794*7c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nis [-eg] [name]\n"); 1795*7c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus [-egh] [-D domainname] [name]\n"); 1796*7c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus -sa\n"); 1797*7c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus [-D domainname] -s [name]\n"); 1798*7c478bd9Sstevel@tonic-gate MSG("\tpasswd -r nisplus [-D domainname] [-l|-N|-u] [-f] [-n min] " 1799*7c478bd9Sstevel@tonic-gate "[-w warn]\n"); 1800*7c478bd9Sstevel@tonic-gate MSG("\t\t[-x max] name\n"); 1801*7c478bd9Sstevel@tonic-gate MSG("\tpasswd -r ldap [-egh] [name]\n"); 1802*7c478bd9Sstevel@tonic-gate #undef MSG 1803*7c478bd9Sstevel@tonic-gate } 1804