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 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <shadow.h> 36*7c478bd9Sstevel@tonic-gate #include <pwd.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <signal.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include <time.h> 42*7c478bd9Sstevel@tonic-gate #include <unistd.h> 43*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 44*7c478bd9Sstevel@tonic-gate #include <locale.h> 45*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 46*7c478bd9Sstevel@tonic-gate #include <secdb.h> 47*7c478bd9Sstevel@tonic-gate #include <user_attr.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #define CMT_SIZE (128+1) /* Argument sizes + 1 (for '\0') */ 50*7c478bd9Sstevel@tonic-gate #define DIR_SIZE (256+1) 51*7c478bd9Sstevel@tonic-gate #define SHL_SIZE (256+1) 52*7c478bd9Sstevel@tonic-gate #define ENTRY_LENGTH 512 /* Max length of an /etc/passwd entry */ 53*7c478bd9Sstevel@tonic-gate #define UID_MIN 100 /* Lower bound of default UID */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define M_MASK 01 /* Masks for the optn_mask variable */ 56*7c478bd9Sstevel@tonic-gate #define L_MASK 02 /* It keeps track of which options */ 57*7c478bd9Sstevel@tonic-gate #define C_MASK 04 /* have been entered */ 58*7c478bd9Sstevel@tonic-gate #define H_MASK 010 59*7c478bd9Sstevel@tonic-gate #define U_MASK 020 60*7c478bd9Sstevel@tonic-gate #define G_MASK 040 61*7c478bd9Sstevel@tonic-gate #define S_MASK 0100 62*7c478bd9Sstevel@tonic-gate #define O_MASK 0200 63*7c478bd9Sstevel@tonic-gate #define A_MASK 0400 64*7c478bd9Sstevel@tonic-gate #define D_MASK 01000 65*7c478bd9Sstevel@tonic-gate #define F_MASK 02000 66*7c478bd9Sstevel@tonic-gate #define E_MASK 04000 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate #define UATTR_MASK 010000 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* flags for info_mask */ 71*7c478bd9Sstevel@tonic-gate #define LOGNAME_EXIST 01 /* logname exists */ 72*7c478bd9Sstevel@tonic-gate #define BOTH_FILES 02 /* touch both password files */ 73*7c478bd9Sstevel@tonic-gate #define WRITE_P_ENTRY 04 /* write out password entry */ 74*7c478bd9Sstevel@tonic-gate #define WRITE_S_ENTRY 010 /* write out shadow entry */ 75*7c478bd9Sstevel@tonic-gate #define NEED_DEF_UID 020 /* need default uid */ 76*7c478bd9Sstevel@tonic-gate #define FOUND 040 /* found the entry in password file */ 77*7c478bd9Sstevel@tonic-gate #define LOCKED 0100 /* did we lock the password file */ 78*7c478bd9Sstevel@tonic-gate #define UATTR_FILE 0200 /* touch user_attr file */ 79*7c478bd9Sstevel@tonic-gate #define BAD_ENT_MESSAGE "%s: Bad entry found in /etc/passwd. Run pwconv.\n" 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate typedef struct kvopts { 82*7c478bd9Sstevel@tonic-gate const char option; 83*7c478bd9Sstevel@tonic-gate const char *key; 84*7c478bd9Sstevel@tonic-gate char *newvalue; 85*7c478bd9Sstevel@tonic-gate } kvopts_t; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* mapping of extensible keywords and options */ 88*7c478bd9Sstevel@tonic-gate kvopts_t ua_opts[] = { 89*7c478bd9Sstevel@tonic-gate { 'A', USERATTR_AUTHS_KW }, 90*7c478bd9Sstevel@tonic-gate { 'P', USERATTR_PROFILES_KW }, 91*7c478bd9Sstevel@tonic-gate { 'R', USERATTR_ROLES_KW }, 92*7c478bd9Sstevel@tonic-gate { 'T', USERATTR_TYPE_KW }, 93*7c478bd9Sstevel@tonic-gate { '\0', USERATTR_DEFAULTPROJ_KW }, 94*7c478bd9Sstevel@tonic-gate { '\0', USERATTR_LIMPRIV_KW }, 95*7c478bd9Sstevel@tonic-gate { '\0', USERATTR_DFLTPRIV_KW }, 96*7c478bd9Sstevel@tonic-gate { '\0', USERATTR_LOCK_AFTER_RETRIES_KW }, 97*7c478bd9Sstevel@tonic-gate }; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate #define UA_KEYS (sizeof (ua_opts)/sizeof (kvopts_t)) 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate char defdir[] = "/home/"; /* default home directory for new user */ 103*7c478bd9Sstevel@tonic-gate char pwdflr[] = "x"; /* password string for /etc/passwd */ 104*7c478bd9Sstevel@tonic-gate char lkstring[] = "*LK*"; /* lock string for shadow password */ 105*7c478bd9Sstevel@tonic-gate char nullstr[] = ""; /* null string */ 106*7c478bd9Sstevel@tonic-gate char *msg; /* pointer to error message */ 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate #define DATMSK "DATEMSK=/etc/datemsk" 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate #define OUSERATTR_FILENAME "/etc/ouser_attr" 111*7c478bd9Sstevel@tonic-gate #define USERATTR_TEMP "/etc/uatmp" 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate extern userattr_t *fgetuserattr(FILE *); 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * Declare all functions that do not return integers. This is here 117*7c478bd9Sstevel@tonic-gate * to get rid of some lint messages 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate void uid_bcom(), add_ublk(), bad_perm(), bad_usage(), bad_arg(), 121*7c478bd9Sstevel@tonic-gate bad_uid(), bad_pasf(), file_error(), bad_news(), no_lock(), 122*7c478bd9Sstevel@tonic-gate add_uid(), rid_tmpf(), ck_p_sz(), ck_s_sz(), bad_name(), 123*7c478bd9Sstevel@tonic-gate bad_uattr(); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate void file_copy(FILE *spf, long NIS_pos); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate static FILE *fp_ptemp, *fp_stemp, *fp_uatemp; 128*7c478bd9Sstevel@tonic-gate static int fd_ptemp, fd_stemp, fd_uatemp; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * The uid_blk structure is used in the search for the default 132*7c478bd9Sstevel@tonic-gate * uid. Each uid_blk represent a range of uid(s) that are currently 133*7c478bd9Sstevel@tonic-gate * used on the system. 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate struct uid_blk { 137*7c478bd9Sstevel@tonic-gate struct uid_blk *link; 138*7c478bd9Sstevel@tonic-gate uid_t low; /* low bound for this uid block */ 139*7c478bd9Sstevel@tonic-gate uid_t high; /* high bound for this uid block */ 140*7c478bd9Sstevel@tonic-gate }; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate #ifndef att 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * getspnan routine that ONLY looks at the local shadow file 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate struct spwd * 147*7c478bd9Sstevel@tonic-gate local_getspnam(name) 148*7c478bd9Sstevel@tonic-gate char *name; 149*7c478bd9Sstevel@tonic-gate { 150*7c478bd9Sstevel@tonic-gate FILE *shadf; 151*7c478bd9Sstevel@tonic-gate struct spwd *sp; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate if ((shadf = fopen("/etc/shadow", "r")) == NULL) 154*7c478bd9Sstevel@tonic-gate return (NULL); 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate while ((sp = fgetspent(shadf)) != NULL) { 157*7c478bd9Sstevel@tonic-gate if (strcmp(sp->sp_namp, name) == 0) 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate fclose(shadf); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate return (sp); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate #endif 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate static void 168*7c478bd9Sstevel@tonic-gate putuserattrent(userattr_t *user, FILE *f) 169*7c478bd9Sstevel@tonic-gate { 170*7c478bd9Sstevel@tonic-gate int i, j; 171*7c478bd9Sstevel@tonic-gate char *key; 172*7c478bd9Sstevel@tonic-gate char *val; 173*7c478bd9Sstevel@tonic-gate kv_t *kv_pair; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * Avoid trivial entries. Those with no attributes or with 177*7c478bd9Sstevel@tonic-gate * only "type=normal". This retains backward compatibility. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate if (user->attr == NULL) 180*7c478bd9Sstevel@tonic-gate return; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate kv_pair = user->attr->data; 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate for (i = j = 0; i < user->attr->length; i++) { 185*7c478bd9Sstevel@tonic-gate key = kv_pair[i].key; 186*7c478bd9Sstevel@tonic-gate val = kv_pair[i].value; 187*7c478bd9Sstevel@tonic-gate if ((key == NULL) || (val == NULL)) 188*7c478bd9Sstevel@tonic-gate break; 189*7c478bd9Sstevel@tonic-gate if (strlen(val) == 0 || 190*7c478bd9Sstevel@tonic-gate (strcmp(key, USERATTR_TYPE_KW) == 0 && 191*7c478bd9Sstevel@tonic-gate strcmp(val, USERATTR_TYPE_NORMAL_KW) == 0)) 192*7c478bd9Sstevel@tonic-gate continue; 193*7c478bd9Sstevel@tonic-gate j++; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate if (j == 0) 196*7c478bd9Sstevel@tonic-gate return; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate (void) fprintf(f, "%s:%s:%s:%s:", user->name, user->qualifier, 199*7c478bd9Sstevel@tonic-gate user->res1, user->res2); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate for (i = j = 0; i < user->attr->length; i++) { 202*7c478bd9Sstevel@tonic-gate key = kv_pair[i].key; 203*7c478bd9Sstevel@tonic-gate val = kv_pair[i].value; 204*7c478bd9Sstevel@tonic-gate if ((key == NULL) || (val == NULL)) 205*7c478bd9Sstevel@tonic-gate break; 206*7c478bd9Sstevel@tonic-gate if (strlen(val) == 0) 207*7c478bd9Sstevel@tonic-gate continue; 208*7c478bd9Sstevel@tonic-gate if (j > 0) 209*7c478bd9Sstevel@tonic-gate (void) fprintf(f, KV_DELIMITER); 210*7c478bd9Sstevel@tonic-gate (void) fprintf(f, "%s=%s", key, val); 211*7c478bd9Sstevel@tonic-gate j++; 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate (void) fprintf(f, "\n"); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate static void 217*7c478bd9Sstevel@tonic-gate assign_attr(userattr_t *user, const char *newkey, char *val) { 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate int i; 220*7c478bd9Sstevel@tonic-gate char *key; 221*7c478bd9Sstevel@tonic-gate kv_t *kv_pair; 222*7c478bd9Sstevel@tonic-gate int avail = -1; 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate if (user->attr != NULL) { 225*7c478bd9Sstevel@tonic-gate kv_pair = user->attr->data; 226*7c478bd9Sstevel@tonic-gate for (i = 0; i < user->attr->length; i++) { 227*7c478bd9Sstevel@tonic-gate key = kv_pair[i].key; 228*7c478bd9Sstevel@tonic-gate if (key == NULL) { 229*7c478bd9Sstevel@tonic-gate avail = i; 230*7c478bd9Sstevel@tonic-gate continue; 231*7c478bd9Sstevel@tonic-gate } else if (strcmp(key, newkey) == 0) { 232*7c478bd9Sstevel@tonic-gate kv_pair[i].value = strdup(val); 233*7c478bd9Sstevel@tonic-gate return; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate if (avail == -1) 238*7c478bd9Sstevel@tonic-gate avail = user->attr->length++; 239*7c478bd9Sstevel@tonic-gate kv_pair[avail].key = strdup(newkey); 240*7c478bd9Sstevel@tonic-gate kv_pair[avail].value = strdup(val); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate static void 245*7c478bd9Sstevel@tonic-gate unassign_role(userattr_t *user, char *rolelist, char *role) { 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate char *roleptr; 248*7c478bd9Sstevel@tonic-gate char *templist; 249*7c478bd9Sstevel@tonic-gate char *temprole; 250*7c478bd9Sstevel@tonic-gate int length; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate roleptr = rolelist; 253*7c478bd9Sstevel@tonic-gate templist = strdup(roleptr); 254*7c478bd9Sstevel@tonic-gate temprole = strtok(templist, ","); 255*7c478bd9Sstevel@tonic-gate while (temprole) { 256*7c478bd9Sstevel@tonic-gate if (strcmp(temprole, role) == 0) { 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate length = strlen(role); 259*7c478bd9Sstevel@tonic-gate roleptr += temprole - templist; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate if (*(roleptr + length) == ',') 262*7c478bd9Sstevel@tonic-gate length++; 263*7c478bd9Sstevel@tonic-gate strcpy(roleptr, roleptr + length); 264*7c478bd9Sstevel@tonic-gate length = strlen(roleptr) - 1; 265*7c478bd9Sstevel@tonic-gate if (*(roleptr + length) == ',') 266*7c478bd9Sstevel@tonic-gate *(roleptr + length) = '\0'; 267*7c478bd9Sstevel@tonic-gate assign_attr(user, USERATTR_ROLES_KW, rolelist); 268*7c478bd9Sstevel@tonic-gate break; 269*7c478bd9Sstevel@tonic-gate } else { 270*7c478bd9Sstevel@tonic-gate temprole = strtok(NULL, ","); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate struct uid_blk *uid_sp; 276*7c478bd9Sstevel@tonic-gate char *prognamp; /* program name */ 277*7c478bd9Sstevel@tonic-gate extern int errno; 278*7c478bd9Sstevel@tonic-gate int optn_mask = 0, info_mask = 0; 279*7c478bd9Sstevel@tonic-gate extern int getdate_err; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate main(argc, argv) 282*7c478bd9Sstevel@tonic-gate int argc; 283*7c478bd9Sstevel@tonic-gate char **argv; 284*7c478bd9Sstevel@tonic-gate { 285*7c478bd9Sstevel@tonic-gate int c, i; 286*7c478bd9Sstevel@tonic-gate char *lognamp, *char_p; 287*7c478bd9Sstevel@tonic-gate int end_of_file = 0; 288*7c478bd9Sstevel@tonic-gate int error; 289*7c478bd9Sstevel@tonic-gate long date = 0; 290*7c478bd9Sstevel@tonic-gate FILE *pwf, *spf, *uaf; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate struct passwd *pw_ptr1p, passwd_st; 293*7c478bd9Sstevel@tonic-gate struct spwd *sp_ptr1p, shadow_st; 294*7c478bd9Sstevel@tonic-gate userattr_t *ua_ptr1p, userattr_st; 295*7c478bd9Sstevel@tonic-gate static kv_t ua_kv[KV_ADD_KEYS]; 296*7c478bd9Sstevel@tonic-gate kva_t ua_kva; 297*7c478bd9Sstevel@tonic-gate struct stat statbuf; 298*7c478bd9Sstevel@tonic-gate struct tm *tm_ptr; 299*7c478bd9Sstevel@tonic-gate int NIS_entry_seen; /* NIS scanning flag */ 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * NIS start pos, really pointer to first entry AFTER first 302*7c478bd9Sstevel@tonic-gate * NIS-referant entry 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate long NIS_pos; 305*7c478bd9Sstevel@tonic-gate long cur_pos; /* Current pos, used with nis-pos above */ 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 310*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 311*7c478bd9Sstevel@tonic-gate #endif 312*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate tzset(); 315*7c478bd9Sstevel@tonic-gate /* Get program name */ 316*7c478bd9Sstevel@tonic-gate prognamp = argv[0]; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* Check identity */ 319*7c478bd9Sstevel@tonic-gate if (geteuid() != 0) 320*7c478bd9Sstevel@tonic-gate bad_perm(); 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* Lock the password file(s) */ 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate if (lckpwdf() != 0) 325*7c478bd9Sstevel@tonic-gate no_lock(); 326*7c478bd9Sstevel@tonic-gate info_mask |= LOCKED; /* remember we locked */ 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* initialize the two structures */ 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate passwd_st.pw_passwd = pwdflr; /* bogus password */ 331*7c478bd9Sstevel@tonic-gate passwd_st.pw_name = nullstr; /* login name */ 332*7c478bd9Sstevel@tonic-gate passwd_st.pw_uid = -1; /* no uid */ 333*7c478bd9Sstevel@tonic-gate passwd_st.pw_gid = 1; /* default gid */ 334*7c478bd9Sstevel@tonic-gate passwd_st.pw_age = nullstr; /* no aging info. */ 335*7c478bd9Sstevel@tonic-gate passwd_st.pw_comment = nullstr; /* no comments */ 336*7c478bd9Sstevel@tonic-gate passwd_st.pw_gecos = nullstr; /* no comments */ 337*7c478bd9Sstevel@tonic-gate passwd_st.pw_dir = nullstr; /* no default directory */ 338*7c478bd9Sstevel@tonic-gate passwd_st.pw_shell = nullstr; /* no default shell */ 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate shadow_st.sp_namp = nullstr; /* no name */ 341*7c478bd9Sstevel@tonic-gate shadow_st.sp_pwdp = lkstring; /* locked password */ 342*7c478bd9Sstevel@tonic-gate shadow_st.sp_lstchg = -1; /* no lastchanged date */ 343*7c478bd9Sstevel@tonic-gate shadow_st.sp_min = -1; /* no min */ 344*7c478bd9Sstevel@tonic-gate shadow_st.sp_max = -1; /* no max */ 345*7c478bd9Sstevel@tonic-gate shadow_st.sp_warn = -1; /* no warn */ 346*7c478bd9Sstevel@tonic-gate shadow_st.sp_inact = -1; /* no inactive */ 347*7c478bd9Sstevel@tonic-gate shadow_st.sp_expire = -1; /* no expire */ 348*7c478bd9Sstevel@tonic-gate shadow_st.sp_flag = 0; /* no flag */ 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate userattr_st.name = nullstr; 351*7c478bd9Sstevel@tonic-gate userattr_st.qualifier = nullstr; 352*7c478bd9Sstevel@tonic-gate userattr_st.res1 = nullstr; 353*7c478bd9Sstevel@tonic-gate userattr_st.res2 = nullstr; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate ua_kva.length = 1; 356*7c478bd9Sstevel@tonic-gate ua_kv[0].key = USERATTR_TYPE_KW; 357*7c478bd9Sstevel@tonic-gate ua_kv[0].value = USERATTR_TYPE_NORMAL_KW; 358*7c478bd9Sstevel@tonic-gate ua_kva.data = ua_kv; 359*7c478bd9Sstevel@tonic-gate userattr_st.attr = &ua_kva; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* parse the command line */ 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, 364*7c478bd9Sstevel@tonic-gate "ml:c:h:u:g:s:f:e:k:A:P:R:T:oadK:")) != -1) { 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate switch (c) { 367*7c478bd9Sstevel@tonic-gate case 'm': 368*7c478bd9Sstevel@tonic-gate /* Modify */ 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate if ((A_MASK|D_MASK|M_MASK) & optn_mask) 371*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate optn_mask |= M_MASK; 374*7c478bd9Sstevel@tonic-gate break; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate case 'l' : 377*7c478bd9Sstevel@tonic-gate /* Change logname */ 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate if ((A_MASK|D_MASK|L_MASK) & optn_mask) 380*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate if (strpbrk(optarg, ":\n") || 383*7c478bd9Sstevel@tonic-gate strlen(optarg) == 0) 384*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -l"); 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate optn_mask |= L_MASK; 387*7c478bd9Sstevel@tonic-gate passwd_st.pw_name = optarg; 388*7c478bd9Sstevel@tonic-gate shadow_st.sp_namp = optarg; 389*7c478bd9Sstevel@tonic-gate userattr_st.name = optarg; 390*7c478bd9Sstevel@tonic-gate break; 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate case 'f' : 393*7c478bd9Sstevel@tonic-gate /* set inactive */ 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate if ((D_MASK|F_MASK) & optn_mask) 396*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 397*7c478bd9Sstevel@tonic-gate if (((shadow_st.sp_inact = 398*7c478bd9Sstevel@tonic-gate strtol(optarg, &char_p, 10)) < (long)0) || 399*7c478bd9Sstevel@tonic-gate (*char_p != '\0') || 400*7c478bd9Sstevel@tonic-gate strlen(optarg) == 0) 401*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -f"); 402*7c478bd9Sstevel@tonic-gate if (shadow_st.sp_inact == 0) 403*7c478bd9Sstevel@tonic-gate shadow_st.sp_inact = -1; 404*7c478bd9Sstevel@tonic-gate optn_mask |= F_MASK; 405*7c478bd9Sstevel@tonic-gate break; 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate case 'e' : 408*7c478bd9Sstevel@tonic-gate /* set expire date */ 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate if ((D_MASK|E_MASK) & optn_mask) 411*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if ((strlen(optarg)) < (size_t)2) 414*7c478bd9Sstevel@tonic-gate shadow_st.sp_expire = -1; 415*7c478bd9Sstevel@tonic-gate else { 416*7c478bd9Sstevel@tonic-gate putenv(DATMSK); 417*7c478bd9Sstevel@tonic-gate if ((tm_ptr = getdate(optarg)) == NULL) { 418*7c478bd9Sstevel@tonic-gate msg = "Invalid argument to option -e"; 419*7c478bd9Sstevel@tonic-gate bad_arg(msg); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate if ((date = mktime(tm_ptr)) < 0) { 422*7c478bd9Sstevel@tonic-gate msg = "Invalid argument to option -e"; 423*7c478bd9Sstevel@tonic-gate bad_arg(msg); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate shadow_st.sp_expire = (date / DAY); 426*7c478bd9Sstevel@tonic-gate if (shadow_st.sp_expire <= DAY_NOW) { 427*7c478bd9Sstevel@tonic-gate msg = "Invalid argument to option -e"; 428*7c478bd9Sstevel@tonic-gate bad_arg(msg); 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate optn_mask |= E_MASK; 433*7c478bd9Sstevel@tonic-gate break; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate case 'c' : 436*7c478bd9Sstevel@tonic-gate /* The comment */ 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate if ((D_MASK|C_MASK) & optn_mask) 439*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate if (strlen(optarg) > (size_t)CMT_SIZE || 442*7c478bd9Sstevel@tonic-gate strpbrk(optarg, ":\n")) 443*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -c"); 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate optn_mask |= C_MASK; 446*7c478bd9Sstevel@tonic-gate passwd_st.pw_comment = optarg; 447*7c478bd9Sstevel@tonic-gate passwd_st.pw_gecos = optarg; 448*7c478bd9Sstevel@tonic-gate break; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate case 'h' : 451*7c478bd9Sstevel@tonic-gate /* The home directory */ 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate if ((D_MASK|H_MASK) & optn_mask) 454*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate if (strlen(optarg) > (size_t)DIR_SIZE || 457*7c478bd9Sstevel@tonic-gate strpbrk(optarg, ":\n")) 458*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -h"); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate optn_mask |= H_MASK; 461*7c478bd9Sstevel@tonic-gate passwd_st.pw_dir = optarg; 462*7c478bd9Sstevel@tonic-gate break; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate case 'u' : 465*7c478bd9Sstevel@tonic-gate /* The uid */ 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate if ((D_MASK|U_MASK) & optn_mask) 468*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate optn_mask |= U_MASK; 471*7c478bd9Sstevel@tonic-gate passwd_st.pw_uid = (uid_t)strtol(optarg, &char_p, 10); 472*7c478bd9Sstevel@tonic-gate if ((*char_p != '\0') || 473*7c478bd9Sstevel@tonic-gate (passwd_st.pw_uid < 0) || 474*7c478bd9Sstevel@tonic-gate (strlen(optarg) == 0)) 475*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -u"); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate break; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate case 'g' : 480*7c478bd9Sstevel@tonic-gate /* The gid */ 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate if ((D_MASK|G_MASK) & optn_mask) 483*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate optn_mask |= G_MASK; 486*7c478bd9Sstevel@tonic-gate passwd_st.pw_gid = (gid_t)strtol(optarg, &char_p, 10); 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate if ((*char_p != '\0') || (passwd_st.pw_gid < 0) || 489*7c478bd9Sstevel@tonic-gate (strlen(optarg) == 0)) 490*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -g"); 491*7c478bd9Sstevel@tonic-gate break; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate case 's' : 494*7c478bd9Sstevel@tonic-gate /* The shell */ 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate if ((D_MASK|S_MASK) & optn_mask) 497*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (strlen(optarg) > (size_t)SHL_SIZE || 500*7c478bd9Sstevel@tonic-gate strpbrk(optarg, ":\n")) 501*7c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -s"); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate optn_mask |= S_MASK; 504*7c478bd9Sstevel@tonic-gate passwd_st.pw_shell = optarg; 505*7c478bd9Sstevel@tonic-gate break; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate case 'o' : 508*7c478bd9Sstevel@tonic-gate /* Override unique uid */ 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if ((D_MASK|O_MASK) & optn_mask) 511*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate optn_mask |= O_MASK; 514*7c478bd9Sstevel@tonic-gate break; 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate case 'a' : 517*7c478bd9Sstevel@tonic-gate /* Add */ 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if ((A_MASK|M_MASK|D_MASK|L_MASK) & optn_mask) 520*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate optn_mask |= A_MASK; 523*7c478bd9Sstevel@tonic-gate break; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate case 'd' : 526*7c478bd9Sstevel@tonic-gate /* Delete */ 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate if ((D_MASK|M_MASK|L_MASK|C_MASK| 529*7c478bd9Sstevel@tonic-gate H_MASK|U_MASK|G_MASK|S_MASK| 530*7c478bd9Sstevel@tonic-gate O_MASK|A_MASK) & optn_mask) 531*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate optn_mask |= D_MASK; 534*7c478bd9Sstevel@tonic-gate break; 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate case 'K': 537*7c478bd9Sstevel@tonic-gate if (D_MASK & optn_mask) 538*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options"); 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate char_p = strchr(optarg, '='); 541*7c478bd9Sstevel@tonic-gate if (char_p == NULL) 542*7c478bd9Sstevel@tonic-gate bad_usage("Missing value in -K option"); 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate *char_p++ = '\0'; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate for (i = 0; i < UA_KEYS; i++) { 547*7c478bd9Sstevel@tonic-gate if (strcmp(optarg, ua_opts[i].key) == 0) { 548*7c478bd9Sstevel@tonic-gate ua_opts[i].newvalue = char_p; 549*7c478bd9Sstevel@tonic-gate assign_attr(&userattr_st, optarg, 550*7c478bd9Sstevel@tonic-gate char_p); 551*7c478bd9Sstevel@tonic-gate break; 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate if (i == UA_KEYS) 555*7c478bd9Sstevel@tonic-gate bad_usage("bad key"); 556*7c478bd9Sstevel@tonic-gate optn_mask |= UATTR_MASK; 557*7c478bd9Sstevel@tonic-gate break; 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate case '?' : 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate bad_usage(""); 562*7c478bd9Sstevel@tonic-gate break; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate default : 565*7c478bd9Sstevel@tonic-gate /* Extended User Attributes */ 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate int j; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate for (j = 0; j < UA_KEYS; j++) { 570*7c478bd9Sstevel@tonic-gate if (ua_opts[j].option == (char)c) { 571*7c478bd9Sstevel@tonic-gate if ((D_MASK) & optn_mask) 572*7c478bd9Sstevel@tonic-gate bad_usage("Invalid combination" 573*7c478bd9Sstevel@tonic-gate " of options"); 574*7c478bd9Sstevel@tonic-gate optn_mask |= UATTR_MASK; 575*7c478bd9Sstevel@tonic-gate assign_attr(&userattr_st, 576*7c478bd9Sstevel@tonic-gate ua_opts[j].key, optarg); 577*7c478bd9Sstevel@tonic-gate ua_opts[j].newvalue = optarg; 578*7c478bd9Sstevel@tonic-gate break; 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate break; 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate /* check command syntax for the following errors */ 587*7c478bd9Sstevel@tonic-gate /* too few or too many arguments */ 588*7c478bd9Sstevel@tonic-gate /* no -a -m or -d option */ 589*7c478bd9Sstevel@tonic-gate /* -o without -u */ 590*7c478bd9Sstevel@tonic-gate /* -m with no other option */ 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate if (optind == argc || argc > (optind+1) || 593*7c478bd9Sstevel@tonic-gate !((A_MASK|M_MASK|D_MASK) & optn_mask) || 594*7c478bd9Sstevel@tonic-gate ((optn_mask & O_MASK) && !(optn_mask & U_MASK)) || 595*7c478bd9Sstevel@tonic-gate ((optn_mask & M_MASK) && 596*7c478bd9Sstevel@tonic-gate !(optn_mask & 597*7c478bd9Sstevel@tonic-gate (L_MASK|C_MASK|H_MASK|U_MASK|G_MASK|S_MASK|F_MASK| 598*7c478bd9Sstevel@tonic-gate E_MASK|UATTR_MASK)))) 599*7c478bd9Sstevel@tonic-gate bad_usage("Invalid command syntax"); 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate /* null string argument or bad characters ? */ 602*7c478bd9Sstevel@tonic-gate if ((strlen(argv[optind]) == 0) || strpbrk(argv[optind], ":\n")) 603*7c478bd9Sstevel@tonic-gate bad_arg("Invalid name"); 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate lognamp = argv [optind]; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* 608*7c478bd9Sstevel@tonic-gate * if we are adding a new user or modifying an existing user 609*7c478bd9Sstevel@tonic-gate * (not the logname), then copy logname into the two data 610*7c478bd9Sstevel@tonic-gate * structures 611*7c478bd9Sstevel@tonic-gate */ 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate if ((A_MASK & optn_mask) || 614*7c478bd9Sstevel@tonic-gate ((M_MASK & optn_mask) && !(optn_mask & L_MASK))) { 615*7c478bd9Sstevel@tonic-gate passwd_st.pw_name = argv [optind]; 616*7c478bd9Sstevel@tonic-gate shadow_st.sp_namp = argv [optind]; 617*7c478bd9Sstevel@tonic-gate userattr_st.name = argv [optind]; 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* Put in directory if we are adding and we need a default */ 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate if (!(optn_mask & H_MASK) && (optn_mask & A_MASK)) { 623*7c478bd9Sstevel@tonic-gate if ((passwd_st.pw_dir = malloc((size_t)DIR_SIZE)) == NULL) 624*7c478bd9Sstevel@tonic-gate file_error(); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate *passwd_st.pw_dir = '\0'; 627*7c478bd9Sstevel@tonic-gate (void) strcat(passwd_st.pw_dir, defdir); 628*7c478bd9Sstevel@tonic-gate (void) strcat(passwd_st.pw_dir, lognamp); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* Check the number of password files we are touching */ 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate if ((!((M_MASK & optn_mask) && !(L_MASK & optn_mask))) || 634*7c478bd9Sstevel@tonic-gate ((M_MASK & optn_mask) && ((E_MASK & optn_mask) || 635*7c478bd9Sstevel@tonic-gate (F_MASK & optn_mask)))) 636*7c478bd9Sstevel@tonic-gate info_mask |= BOTH_FILES; 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate if ((D_MASK|L_MASK|UATTR_MASK) & optn_mask) 639*7c478bd9Sstevel@tonic-gate info_mask |= UATTR_FILE; 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate /* Open the temporary file(s) with appropriate permission mask */ 642*7c478bd9Sstevel@tonic-gate /* and the appropriate owner */ 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate if (stat(PASSWD, &statbuf) < 0) 645*7c478bd9Sstevel@tonic-gate file_error(); 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode); 648*7c478bd9Sstevel@tonic-gate if (fd_ptemp == -1) { 649*7c478bd9Sstevel@tonic-gate if (errno == EEXIST) { 650*7c478bd9Sstevel@tonic-gate if (unlink(PASSTEMP)) { 651*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 652*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp, 653*7c478bd9Sstevel@tonic-gate PASSTEMP); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY, 656*7c478bd9Sstevel@tonic-gate statbuf.st_mode); 657*7c478bd9Sstevel@tonic-gate if (fd_ptemp == -1) { 658*7c478bd9Sstevel@tonic-gate file_error(); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate } else 662*7c478bd9Sstevel@tonic-gate file_error(); 663*7c478bd9Sstevel@tonic-gate } 664*7c478bd9Sstevel@tonic-gate fp_ptemp = fdopen(fd_ptemp, "w"); 665*7c478bd9Sstevel@tonic-gate if (fp_ptemp == NULL) 666*7c478bd9Sstevel@tonic-gate file_error(); 667*7c478bd9Sstevel@tonic-gate error = fchown(fd_ptemp, statbuf.st_uid, statbuf.st_gid); 668*7c478bd9Sstevel@tonic-gate if (error == 0) 669*7c478bd9Sstevel@tonic-gate error = fchmod(fd_ptemp, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 670*7c478bd9Sstevel@tonic-gate if (error != 0) { 671*7c478bd9Sstevel@tonic-gate (void) fclose(fp_ptemp); 672*7c478bd9Sstevel@tonic-gate if (unlink(PASSTEMP)) { 673*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 674*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp, 675*7c478bd9Sstevel@tonic-gate PASSTEMP); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate file_error(); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) { 681*7c478bd9Sstevel@tonic-gate if (stat(SHADOW, &statbuf) < 0) { 682*7c478bd9Sstevel@tonic-gate rid_tmpf(); 683*7c478bd9Sstevel@tonic-gate file_error(); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate fd_stemp = open(SHADTEMP, O_CREAT|O_EXCL|O_WRONLY, 686*7c478bd9Sstevel@tonic-gate statbuf.st_mode); 687*7c478bd9Sstevel@tonic-gate if (fd_stemp == -1) { 688*7c478bd9Sstevel@tonic-gate if (errno == EEXIST) { 689*7c478bd9Sstevel@tonic-gate if (unlink(SHADTEMP)) { 690*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 691*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), 692*7c478bd9Sstevel@tonic-gate prognamp, SHADTEMP); 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate fd_stemp = open(SHADTEMP, 695*7c478bd9Sstevel@tonic-gate O_CREAT|O_EXCL|O_WRONLY, 696*7c478bd9Sstevel@tonic-gate statbuf.st_mode); 697*7c478bd9Sstevel@tonic-gate if (fd_stemp == -1) { 698*7c478bd9Sstevel@tonic-gate rid_tmpf(); 699*7c478bd9Sstevel@tonic-gate file_error(); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate } else { 703*7c478bd9Sstevel@tonic-gate rid_tmpf(); 704*7c478bd9Sstevel@tonic-gate file_error(); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate fp_stemp = fdopen(fd_stemp, "w"); 708*7c478bd9Sstevel@tonic-gate if (fp_stemp == NULL) { 709*7c478bd9Sstevel@tonic-gate rid_tmpf(); 710*7c478bd9Sstevel@tonic-gate file_error(); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate error = fchown(fd_stemp, statbuf.st_uid, statbuf.st_gid); 713*7c478bd9Sstevel@tonic-gate if (error == 0) 714*7c478bd9Sstevel@tonic-gate error = fchmod(fd_stemp, S_IRUSR); 715*7c478bd9Sstevel@tonic-gate if (error != 0) { 716*7c478bd9Sstevel@tonic-gate rid_tmpf(); 717*7c478bd9Sstevel@tonic-gate file_error(); 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) { 722*7c478bd9Sstevel@tonic-gate if (stat(USERATTR_FILENAME, &statbuf) < 0) { 723*7c478bd9Sstevel@tonic-gate rid_tmpf(); 724*7c478bd9Sstevel@tonic-gate file_error(); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate fd_uatemp = open(USERATTR_TEMP, O_CREAT|O_EXCL|O_WRONLY, 727*7c478bd9Sstevel@tonic-gate statbuf.st_mode); 728*7c478bd9Sstevel@tonic-gate if (fd_uatemp == -1) { 729*7c478bd9Sstevel@tonic-gate if (errno == EEXIST) { 730*7c478bd9Sstevel@tonic-gate if (unlink(USERATTR_TEMP)) { 731*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 732*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), 733*7c478bd9Sstevel@tonic-gate prognamp, USERATTR_TEMP); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate fd_uatemp = open(USERATTR_TEMP, 736*7c478bd9Sstevel@tonic-gate O_CREAT|O_EXCL|O_WRONLY, 737*7c478bd9Sstevel@tonic-gate statbuf.st_mode); 738*7c478bd9Sstevel@tonic-gate if (fd_uatemp == -1) { 739*7c478bd9Sstevel@tonic-gate rid_tmpf(); 740*7c478bd9Sstevel@tonic-gate file_error(); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate } else { 744*7c478bd9Sstevel@tonic-gate rid_tmpf(); 745*7c478bd9Sstevel@tonic-gate file_error(); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate fp_uatemp = fdopen(fd_uatemp, "w"); 749*7c478bd9Sstevel@tonic-gate if (fp_uatemp == NULL) { 750*7c478bd9Sstevel@tonic-gate rid_tmpf(); 751*7c478bd9Sstevel@tonic-gate file_error(); 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate error = fchown(fd_uatemp, statbuf.st_uid, statbuf.st_gid); 754*7c478bd9Sstevel@tonic-gate if (error == 0) 755*7c478bd9Sstevel@tonic-gate error = fchmod(fd_uatemp, 756*7c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 757*7c478bd9Sstevel@tonic-gate if (error != 0) { 758*7c478bd9Sstevel@tonic-gate rid_tmpf(); 759*7c478bd9Sstevel@tonic-gate file_error(); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate /* Default uid needed ? */ 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate if (!(optn_mask & U_MASK) && (optn_mask & A_MASK)) { 765*7c478bd9Sstevel@tonic-gate /* mark it in the information mask */ 766*7c478bd9Sstevel@tonic-gate info_mask |= NEED_DEF_UID; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate /* create the head of the uid number list */ 769*7c478bd9Sstevel@tonic-gate uid_sp = malloc(sizeof (struct uid_blk)); 770*7c478bd9Sstevel@tonic-gate if (uid_sp == NULL) { 771*7c478bd9Sstevel@tonic-gate rid_tmpf(); 772*7c478bd9Sstevel@tonic-gate file_error(); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate uid_sp->link = NULL; 776*7c478bd9Sstevel@tonic-gate uid_sp->low = (UID_MIN -1); 777*7c478bd9Sstevel@tonic-gate uid_sp->high = (UID_MIN -1); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate /* 781*7c478bd9Sstevel@tonic-gate * This next section is modified to allow for NIS passwd file 782*7c478bd9Sstevel@tonic-gate * conventions. In the case where a password entry was being 783*7c478bd9Sstevel@tonic-gate * added to the password file, the original AT&T code read 784*7c478bd9Sstevel@tonic-gate * the entire password file in, noted any information needed, and 785*7c478bd9Sstevel@tonic-gate * copied the entries to a temporary file. Then the new entry 786*7c478bd9Sstevel@tonic-gate * was added to the temporary file, and the temporary file was 787*7c478bd9Sstevel@tonic-gate * moved to be the real password file. 788*7c478bd9Sstevel@tonic-gate * 789*7c478bd9Sstevel@tonic-gate * The problem is, that with NIS compatability, we want to add new 790*7c478bd9Sstevel@tonic-gate * entries BEFORE the first NIS-referrant entry, so as not to have 791*7c478bd9Sstevel@tonic-gate * any surprises. To accomplish this without extensively modifying 792*7c478bd9Sstevel@tonic-gate * the logic of the code below, as soon as a NIS-referrant entry is 793*7c478bd9Sstevel@tonic-gate * found we stop copying entries to the TEMP file and instead we 794*7c478bd9Sstevel@tonic-gate * remember 795*7c478bd9Sstevel@tonic-gate * the first NIS entry and where we found it, scan the rest of the 796*7c478bd9Sstevel@tonic-gate * password file without copying entries, then write the new entry, copy 797*7c478bd9Sstevel@tonic-gate * the stored password entry, then copy the rest of the password file. 798*7c478bd9Sstevel@tonic-gate */ 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate error = 0; 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate if ((pwf = fopen("/etc/passwd", "r")) == NULL) { 804*7c478bd9Sstevel@tonic-gate rid_tmpf(); 805*7c478bd9Sstevel@tonic-gate if (errno == ENOENT) 806*7c478bd9Sstevel@tonic-gate bad_news(); 807*7c478bd9Sstevel@tonic-gate else 808*7c478bd9Sstevel@tonic-gate file_error(); 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate NIS_entry_seen = 0; 812*7c478bd9Sstevel@tonic-gate cur_pos = 0; 813*7c478bd9Sstevel@tonic-gate /* The while loop for reading PASSWD entries */ 814*7c478bd9Sstevel@tonic-gate info_mask |= WRITE_P_ENTRY; 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate while (!end_of_file) { 817*7c478bd9Sstevel@tonic-gate pw_ptr1p = fgetpwent(pwf); 818*7c478bd9Sstevel@tonic-gate if (pw_ptr1p == NULL) { 819*7c478bd9Sstevel@tonic-gate if (!feof(pwf)) { 820*7c478bd9Sstevel@tonic-gate /* A real error - report it and exit */ 821*7c478bd9Sstevel@tonic-gate rid_tmpf(); 822*7c478bd9Sstevel@tonic-gate bad_pasf(); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate else 825*7c478bd9Sstevel@tonic-gate break; 826*7c478bd9Sstevel@tonic-gate } 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) 829*7c478bd9Sstevel@tonic-gate info_mask |= WRITE_P_ENTRY; 830*7c478bd9Sstevel@tonic-gate else 831*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_P_ENTRY; 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate /* 834*7c478bd9Sstevel@tonic-gate * Set up the uid usage blocks to find the first 835*7c478bd9Sstevel@tonic-gate * available uid above UID_MIN, if needed 836*7c478bd9Sstevel@tonic-gate */ 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (info_mask & NEED_DEF_UID) 839*7c478bd9Sstevel@tonic-gate add_uid(pw_ptr1p->pw_uid); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate /* Check for unique UID */ 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate if (strcmp(lognamp, pw_ptr1p->pw_name) && 844*7c478bd9Sstevel@tonic-gate (pw_ptr1p->pw_uid == passwd_st.pw_uid) && 845*7c478bd9Sstevel@tonic-gate ((optn_mask & U_MASK) && !(optn_mask & O_MASK))) { 846*7c478bd9Sstevel@tonic-gate rid_tmpf(); /* get rid of temp files */ 847*7c478bd9Sstevel@tonic-gate bad_uid(); 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate /* Check for unique new logname */ 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate if (strcmp(lognamp, pw_ptr1p->pw_name) == 0 && 853*7c478bd9Sstevel@tonic-gate optn_mask & L_MASK && 854*7c478bd9Sstevel@tonic-gate strcmp(pw_ptr1p->pw_name, passwd_st.pw_name) == 0) { 855*7c478bd9Sstevel@tonic-gate rid_tmpf(); 856*7c478bd9Sstevel@tonic-gate #ifdef att 857*7c478bd9Sstevel@tonic-gate if (!getspnam(pw_ptr1p->pw_name)) 858*7c478bd9Sstevel@tonic-gate #else 859*7c478bd9Sstevel@tonic-gate if (!local_getspnam(pw_ptr1p->pw_name)) 860*7c478bd9Sstevel@tonic-gate #endif 861*7c478bd9Sstevel@tonic-gate bad_pasf(); 862*7c478bd9Sstevel@tonic-gate else 863*7c478bd9Sstevel@tonic-gate bad_name("logname already exists"); 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate if (strcmp(lognamp, pw_ptr1p->pw_name) == 0) { 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate /* no good if we want to add an existing logname */ 869*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 870*7c478bd9Sstevel@tonic-gate rid_tmpf(); 871*7c478bd9Sstevel@tonic-gate #ifdef att 872*7c478bd9Sstevel@tonic-gate if (!getspnam(lognamp)) 873*7c478bd9Sstevel@tonic-gate #else 874*7c478bd9Sstevel@tonic-gate if (!local_getspnam(lognamp)) 875*7c478bd9Sstevel@tonic-gate #endif 876*7c478bd9Sstevel@tonic-gate bad_pasf(); 877*7c478bd9Sstevel@tonic-gate else 878*7c478bd9Sstevel@tonic-gate bad_name("name already exists"); 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate /* remember we found it */ 882*7c478bd9Sstevel@tonic-gate info_mask |= FOUND; 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate /* Do not write it out on the fly */ 885*7c478bd9Sstevel@tonic-gate if (optn_mask & D_MASK) 886*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_P_ENTRY; 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate if (optn_mask & M_MASK) { 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate #ifdef att 891*7c478bd9Sstevel@tonic-gate if (!getspnam(lognamp)) 892*7c478bd9Sstevel@tonic-gate #else 893*7c478bd9Sstevel@tonic-gate if (!local_getspnam(lognamp)) 894*7c478bd9Sstevel@tonic-gate #endif 895*7c478bd9Sstevel@tonic-gate { 896*7c478bd9Sstevel@tonic-gate rid_tmpf(); 897*7c478bd9Sstevel@tonic-gate bad_pasf(); 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate if (optn_mask & L_MASK) 900*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_name = passwd_st.pw_name; 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate if (optn_mask & U_MASK) 903*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_uid = passwd_st.pw_uid; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate if (optn_mask & G_MASK) 906*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_gid = passwd_st.pw_gid; 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate if (optn_mask & C_MASK) { 909*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_comment = 910*7c478bd9Sstevel@tonic-gate passwd_st.pw_comment; 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_gecos = 913*7c478bd9Sstevel@tonic-gate passwd_st.pw_comment; 914*7c478bd9Sstevel@tonic-gate } 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate if (optn_mask & H_MASK) 917*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_dir = passwd_st.pw_dir; 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate if (optn_mask & S_MASK) 920*7c478bd9Sstevel@tonic-gate pw_ptr1p->pw_shell = passwd_st.pw_shell; 921*7c478bd9Sstevel@tonic-gate ck_p_sz(pw_ptr1p); /* check entry size */ 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 926*7c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) { 927*7c478bd9Sstevel@tonic-gate char *p; 928*7c478bd9Sstevel@tonic-gate p = strchr("+-", pw_ptr1p->pw_name[0]); 929*7c478bd9Sstevel@tonic-gate if (p != NULL) { 930*7c478bd9Sstevel@tonic-gate /* 931*7c478bd9Sstevel@tonic-gate * Found first NIS entry. 932*7c478bd9Sstevel@tonic-gate * so remember it. 933*7c478bd9Sstevel@tonic-gate */ 934*7c478bd9Sstevel@tonic-gate NIS_pos = cur_pos; 935*7c478bd9Sstevel@tonic-gate NIS_entry_seen = 1; 936*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_P_ENTRY; 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate else 939*7c478bd9Sstevel@tonic-gate cur_pos = ftell(pwf); 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate if (info_mask & WRITE_P_ENTRY) { 944*7c478bd9Sstevel@tonic-gate if (putpwent(pw_ptr1p, fp_ptemp)) { 945*7c478bd9Sstevel@tonic-gate rid_tmpf(); 946*7c478bd9Sstevel@tonic-gate file_error(); 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate } /* end-of-while-loop */ 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate if (error >= 1) { 952*7c478bd9Sstevel@tonic-gate msg = "%s: Bad entry found in /etc/passwd. Run pwconv.\n"; 953*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(msg), prognamp); 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate /* Cannot find the target entry and we are deleting or modifying */ 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) { 959*7c478bd9Sstevel@tonic-gate rid_tmpf(); 960*7c478bd9Sstevel@tonic-gate #ifdef att 961*7c478bd9Sstevel@tonic-gate if (getspnam(lognamp) != NULL) 962*7c478bd9Sstevel@tonic-gate #else 963*7c478bd9Sstevel@tonic-gate if (local_getspnam(lognamp) != NULL) 964*7c478bd9Sstevel@tonic-gate #endif 965*7c478bd9Sstevel@tonic-gate bad_pasf(); 966*7c478bd9Sstevel@tonic-gate else 967*7c478bd9Sstevel@tonic-gate bad_name("name does not exist"); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate /* First available uid above UID_MIN is ... */ 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate if (info_mask & NEED_DEF_UID) 973*7c478bd9Sstevel@tonic-gate passwd_st.pw_uid = uid_sp->high + 1; 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate /* Write out the added entry now */ 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 978*7c478bd9Sstevel@tonic-gate ck_p_sz(&passwd_st); /* Check entry size */ 979*7c478bd9Sstevel@tonic-gate if (putpwent(&passwd_st, fp_ptemp)) { 980*7c478bd9Sstevel@tonic-gate rid_tmpf(); 981*7c478bd9Sstevel@tonic-gate file_error(); 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate /* 984*7c478bd9Sstevel@tonic-gate * Now put out the rest of the password file, if needed. 985*7c478bd9Sstevel@tonic-gate */ 986*7c478bd9Sstevel@tonic-gate if (NIS_entry_seen) { 987*7c478bd9Sstevel@tonic-gate int n; 988*7c478bd9Sstevel@tonic-gate char buf[1024]; 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate if (fseek(pwf, NIS_pos, SEEK_SET) < 0) { 991*7c478bd9Sstevel@tonic-gate rid_tmpf(); 992*7c478bd9Sstevel@tonic-gate file_error(); 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate while ((n = fread(buf, sizeof (char), 1024, pwf)) > 0) { 995*7c478bd9Sstevel@tonic-gate if (fwrite(buf, sizeof (char), n, fp_ptemp) 996*7c478bd9Sstevel@tonic-gate != n) { 997*7c478bd9Sstevel@tonic-gate rid_tmpf(); 998*7c478bd9Sstevel@tonic-gate file_error(); 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate } 1001*7c478bd9Sstevel@tonic-gate } 1002*7c478bd9Sstevel@tonic-gate } 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate (void) fclose(pwf); 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate /* flush and sync the file before closing it */ 1007*7c478bd9Sstevel@tonic-gate if (fflush(fp_ptemp) != 0 || fsync(fd_ptemp) != 0) 1008*7c478bd9Sstevel@tonic-gate file_error(); 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate /* Now we are done with PASSWD */ 1011*7c478bd9Sstevel@tonic-gate (void) fclose(fp_ptemp); 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate /* Do this if we are touching both password files */ 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) { 1017*7c478bd9Sstevel@tonic-gate info_mask &= ~FOUND; /* Reset FOUND flag */ 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate /* The while loop for reading SHADOW entries */ 1020*7c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate end_of_file = 0; 1023*7c478bd9Sstevel@tonic-gate errno = 0; 1024*7c478bd9Sstevel@tonic-gate error = 0; 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate NIS_entry_seen = 0; 1027*7c478bd9Sstevel@tonic-gate cur_pos = 0; 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate if ((spf = fopen("/etc/shadow", "r")) == NULL) { 1030*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1031*7c478bd9Sstevel@tonic-gate file_error(); 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate while (!end_of_file) { 1035*7c478bd9Sstevel@tonic-gate sp_ptr1p = fgetspent(spf); 1036*7c478bd9Sstevel@tonic-gate if (sp_ptr1p == NULL) { 1037*7c478bd9Sstevel@tonic-gate if (!feof(spf)) { 1038*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1039*7c478bd9Sstevel@tonic-gate bad_pasf(); 1040*7c478bd9Sstevel@tonic-gate } 1041*7c478bd9Sstevel@tonic-gate else 1042*7c478bd9Sstevel@tonic-gate break; 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) 1046*7c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY; 1047*7c478bd9Sstevel@tonic-gate else 1048*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY; 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate /* 1051*7c478bd9Sstevel@tonic-gate * See if the new logname already exist in the 1052*7c478bd9Sstevel@tonic-gate * shadow passwd file 1053*7c478bd9Sstevel@tonic-gate */ 1054*7c478bd9Sstevel@tonic-gate if ((optn_mask & M_MASK) && 1055*7c478bd9Sstevel@tonic-gate strcmp(lognamp, shadow_st.sp_namp) != 0 && 1056*7c478bd9Sstevel@tonic-gate strcmp(sp_ptr1p->sp_namp, shadow_st.sp_namp) == 0) { 1057*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1058*7c478bd9Sstevel@tonic-gate bad_pasf(); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate if (strcmp(lognamp, sp_ptr1p->sp_namp) == 0) { 1062*7c478bd9Sstevel@tonic-gate info_mask |= FOUND; 1063*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 1064*7c478bd9Sstevel@tonic-gate /* password file inconsistent */ 1065*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1066*7c478bd9Sstevel@tonic-gate bad_pasf(); 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate if (optn_mask & M_MASK) { 1070*7c478bd9Sstevel@tonic-gate sp_ptr1p->sp_namp = shadow_st.sp_namp; 1071*7c478bd9Sstevel@tonic-gate if (F_MASK & optn_mask) 1072*7c478bd9Sstevel@tonic-gate sp_ptr1p->sp_inact = 1073*7c478bd9Sstevel@tonic-gate shadow_st.sp_inact; 1074*7c478bd9Sstevel@tonic-gate if (E_MASK & optn_mask) 1075*7c478bd9Sstevel@tonic-gate sp_ptr1p->sp_expire = 1076*7c478bd9Sstevel@tonic-gate shadow_st.sp_expire; 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate ck_s_sz(sp_ptr1p); 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate if (optn_mask & D_MASK) 1082*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY; 1083*7c478bd9Sstevel@tonic-gate } 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 1086*7c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) { 1087*7c478bd9Sstevel@tonic-gate char *p; 1088*7c478bd9Sstevel@tonic-gate p = strchr("+-", sp_ptr1p->sp_namp[0]); 1089*7c478bd9Sstevel@tonic-gate if (p != NULL) { 1090*7c478bd9Sstevel@tonic-gate /* 1091*7c478bd9Sstevel@tonic-gate * Found first NIS entry. 1092*7c478bd9Sstevel@tonic-gate * so remember it. 1093*7c478bd9Sstevel@tonic-gate */ 1094*7c478bd9Sstevel@tonic-gate NIS_pos = cur_pos; 1095*7c478bd9Sstevel@tonic-gate NIS_entry_seen = 1; 1096*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY; 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate else 1099*7c478bd9Sstevel@tonic-gate cur_pos = ftell(spf); 1100*7c478bd9Sstevel@tonic-gate } 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate if (info_mask & WRITE_S_ENTRY) { 1104*7c478bd9Sstevel@tonic-gate if (putspent(sp_ptr1p, fp_stemp)) { 1105*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1106*7c478bd9Sstevel@tonic-gate file_error(); 1107*7c478bd9Sstevel@tonic-gate } 1108*7c478bd9Sstevel@tonic-gate } 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate } /* end-of-while-loop */ 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate if (error >= 1) { 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate msg = BAD_ENT_MESSAGE; 1115*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(msg), prognamp); 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate /* 1119*7c478bd9Sstevel@tonic-gate * If we cannot find the entry and we are deleting or 1120*7c478bd9Sstevel@tonic-gate * modifying 1121*7c478bd9Sstevel@tonic-gate */ 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) { 1124*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1125*7c478bd9Sstevel@tonic-gate bad_pasf(); 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 1129*7c478bd9Sstevel@tonic-gate ck_s_sz(&shadow_st); 1130*7c478bd9Sstevel@tonic-gate if (putspent(&shadow_st, fp_stemp)) { 1131*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1132*7c478bd9Sstevel@tonic-gate file_error(); 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate /* 1136*7c478bd9Sstevel@tonic-gate * Now put out the rest of the shadow file, if needed. 1137*7c478bd9Sstevel@tonic-gate */ 1138*7c478bd9Sstevel@tonic-gate if (NIS_entry_seen) { 1139*7c478bd9Sstevel@tonic-gate file_copy(spf, NIS_pos); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate } 1142*7c478bd9Sstevel@tonic-gate 1143*7c478bd9Sstevel@tonic-gate /* flush and sync the file before closing it */ 1144*7c478bd9Sstevel@tonic-gate if (fflush(fp_stemp) != 0 || fsync(fd_stemp) != 0) 1145*7c478bd9Sstevel@tonic-gate file_error(); 1146*7c478bd9Sstevel@tonic-gate (void) fclose(fp_stemp); 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate /* Done with SHADOW */ 1149*7c478bd9Sstevel@tonic-gate (void) fclose(spf); 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate } /* End of if info_mask */ 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) { 1154*7c478bd9Sstevel@tonic-gate info_mask &= ~FOUND; /* Reset FOUND flag */ 1155*7c478bd9Sstevel@tonic-gate 1156*7c478bd9Sstevel@tonic-gate /* The while loop for reading USER_ATTR entries */ 1157*7c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY; 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate end_of_file = 0; 1160*7c478bd9Sstevel@tonic-gate errno = 0; 1161*7c478bd9Sstevel@tonic-gate error = 0; 1162*7c478bd9Sstevel@tonic-gate 1163*7c478bd9Sstevel@tonic-gate NIS_entry_seen = 0; 1164*7c478bd9Sstevel@tonic-gate cur_pos = 0; 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate if ((uaf = fopen(USERATTR_FILENAME, "r")) == NULL) { 1167*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1168*7c478bd9Sstevel@tonic-gate file_error(); 1169*7c478bd9Sstevel@tonic-gate } 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate while (!end_of_file) { 1172*7c478bd9Sstevel@tonic-gate ua_ptr1p = fgetuserattr(uaf); 1173*7c478bd9Sstevel@tonic-gate if (ua_ptr1p == NULL) { 1174*7c478bd9Sstevel@tonic-gate if (!feof(uaf)) { 1175*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1176*7c478bd9Sstevel@tonic-gate bad_uattr(); 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate else 1179*7c478bd9Sstevel@tonic-gate break; 1180*7c478bd9Sstevel@tonic-gate } 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate if (ua_ptr1p->name[0] == '#') { 1183*7c478bd9Sstevel@tonic-gate /* 1184*7c478bd9Sstevel@tonic-gate * If this is a comment, write it back as it 1185*7c478bd9Sstevel@tonic-gate * is. 1186*7c478bd9Sstevel@tonic-gate */ 1187*7c478bd9Sstevel@tonic-gate if (ua_ptr1p->qualifier[0] == '\0' && 1188*7c478bd9Sstevel@tonic-gate ua_ptr1p->res1[0] == '\0' && 1189*7c478bd9Sstevel@tonic-gate ua_ptr1p->res2[0] == '\0' && 1190*7c478bd9Sstevel@tonic-gate (ua_ptr1p->attr == NULL || 1191*7c478bd9Sstevel@tonic-gate ua_ptr1p->attr->length == 0)) 1192*7c478bd9Sstevel@tonic-gate (void) fprintf(fp_uatemp, "%s\n", 1193*7c478bd9Sstevel@tonic-gate ua_ptr1p->name); 1194*7c478bd9Sstevel@tonic-gate else 1195*7c478bd9Sstevel@tonic-gate /* 1196*7c478bd9Sstevel@tonic-gate * This is a commented user_attr entry; 1197*7c478bd9Sstevel@tonic-gate * reformat it, and write it back. 1198*7c478bd9Sstevel@tonic-gate */ 1199*7c478bd9Sstevel@tonic-gate putuserattrent(ua_ptr1p, fp_uatemp); 1200*7c478bd9Sstevel@tonic-gate free_userattr(ua_ptr1p); 1201*7c478bd9Sstevel@tonic-gate continue; 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) 1205*7c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY; 1206*7c478bd9Sstevel@tonic-gate else 1207*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY; 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate /* 1210*7c478bd9Sstevel@tonic-gate * See if the new logname already exist in the 1211*7c478bd9Sstevel@tonic-gate * user_attr file 1212*7c478bd9Sstevel@tonic-gate */ 1213*7c478bd9Sstevel@tonic-gate if ((optn_mask & M_MASK) && 1214*7c478bd9Sstevel@tonic-gate strcmp(lognamp, userattr_st.name) != 0 && 1215*7c478bd9Sstevel@tonic-gate strcmp(ua_ptr1p->name, userattr_st.name) == 0) { 1216*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1217*7c478bd9Sstevel@tonic-gate bad_pasf(); 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate if (strcmp(lognamp, ua_ptr1p->name) == 0) { 1221*7c478bd9Sstevel@tonic-gate info_mask |= FOUND; 1222*7c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) { 1223*7c478bd9Sstevel@tonic-gate /* password file inconsistent */ 1224*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1225*7c478bd9Sstevel@tonic-gate bad_pasf(); 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate if (optn_mask & M_MASK) { 1229*7c478bd9Sstevel@tonic-gate int j; 1230*7c478bd9Sstevel@tonic-gate char *value; 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate for (j = 0; j < UA_KEYS; j++) { 1233*7c478bd9Sstevel@tonic-gate if (ua_opts[j].newvalue != NULL) 1234*7c478bd9Sstevel@tonic-gate continue; 1235*7c478bd9Sstevel@tonic-gate value = 1236*7c478bd9Sstevel@tonic-gate kva_match(ua_ptr1p->attr, 1237*7c478bd9Sstevel@tonic-gate (char *)ua_opts[j].key); 1238*7c478bd9Sstevel@tonic-gate if (value == NULL) 1239*7c478bd9Sstevel@tonic-gate continue; 1240*7c478bd9Sstevel@tonic-gate assign_attr(&userattr_st, 1241*7c478bd9Sstevel@tonic-gate ua_opts[j].key, 1242*7c478bd9Sstevel@tonic-gate value); 1243*7c478bd9Sstevel@tonic-gate } 1244*7c478bd9Sstevel@tonic-gate free_userattr(ua_ptr1p); 1245*7c478bd9Sstevel@tonic-gate ua_ptr1p = &userattr_st; 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate if (optn_mask & D_MASK) 1249*7c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY; 1250*7c478bd9Sstevel@tonic-gate } else if (optn_mask & D_MASK) { 1251*7c478bd9Sstevel@tonic-gate char *rolelist; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate rolelist = kva_match(ua_ptr1p->attr, 1254*7c478bd9Sstevel@tonic-gate USERATTR_ROLES_KW); 1255*7c478bd9Sstevel@tonic-gate if (rolelist) { 1256*7c478bd9Sstevel@tonic-gate unassign_role(ua_ptr1p, 1257*7c478bd9Sstevel@tonic-gate rolelist, lognamp); 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate } 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate if (info_mask & WRITE_S_ENTRY) { 1262*7c478bd9Sstevel@tonic-gate putuserattrent(ua_ptr1p, fp_uatemp); 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate if (!(optn_mask & M_MASK)) 1266*7c478bd9Sstevel@tonic-gate free_userattr(ua_ptr1p); 1267*7c478bd9Sstevel@tonic-gate } /* end-of-while-loop */ 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate if (error >= 1) { 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate msg = BAD_ENT_MESSAGE; 1272*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(msg), prognamp); 1273*7c478bd9Sstevel@tonic-gate } 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate /* 1276*7c478bd9Sstevel@tonic-gate * Add entry in user_attr if masks is UATTR_MASK 1277*7c478bd9Sstevel@tonic-gate * We don't need to do anything for L_MASK if there's 1278*7c478bd9Sstevel@tonic-gate * no user_attr entry for the user being modified. 1279*7c478bd9Sstevel@tonic-gate */ 1280*7c478bd9Sstevel@tonic-gate if (!(info_mask & FOUND) && !(L_MASK & optn_mask) && 1281*7c478bd9Sstevel@tonic-gate !(D_MASK & optn_mask)) { 1282*7c478bd9Sstevel@tonic-gate putuserattrent(&userattr_st, fp_uatemp); 1283*7c478bd9Sstevel@tonic-gate } 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate /* flush and sync the file before closing it */ 1286*7c478bd9Sstevel@tonic-gate if (fflush(fp_uatemp) != 0 || fsync(fd_uatemp) != 0) 1287*7c478bd9Sstevel@tonic-gate file_error(); 1288*7c478bd9Sstevel@tonic-gate (void) fclose(fp_uatemp); 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* Done with USERATTR */ 1291*7c478bd9Sstevel@tonic-gate (void) fclose(uaf); 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate } /* End of if info_mask */ 1294*7c478bd9Sstevel@tonic-gate /* ignore all signals */ 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate for (i = 1; i < NSIG; i++) 1297*7c478bd9Sstevel@tonic-gate (void) sigset(i, SIG_IGN); 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate errno = 0; /* For correcting sigset to SIGKILL */ 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate if (unlink(OPASSWD) && access(OPASSWD, 0) == 0) 1302*7c478bd9Sstevel@tonic-gate file_error(); 1303*7c478bd9Sstevel@tonic-gate 1304*7c478bd9Sstevel@tonic-gate if (link(PASSWD, OPASSWD) == -1) 1305*7c478bd9Sstevel@tonic-gate file_error(); 1306*7c478bd9Sstevel@tonic-gate 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate if (rename(PASSTEMP, PASSWD) == -1) { 1309*7c478bd9Sstevel@tonic-gate if (link(OPASSWD, PASSWD)) 1310*7c478bd9Sstevel@tonic-gate bad_news(); 1311*7c478bd9Sstevel@tonic-gate file_error(); 1312*7c478bd9Sstevel@tonic-gate } 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) { 1316*7c478bd9Sstevel@tonic-gate 1317*7c478bd9Sstevel@tonic-gate if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) { 1318*7c478bd9Sstevel@tonic-gate if (rec_pwd()) 1319*7c478bd9Sstevel@tonic-gate bad_news(); 1320*7c478bd9Sstevel@tonic-gate else 1321*7c478bd9Sstevel@tonic-gate file_error(); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate if (link(SHADOW, OSHADOW) == -1) { 1325*7c478bd9Sstevel@tonic-gate if (rec_pwd()) 1326*7c478bd9Sstevel@tonic-gate bad_news(); 1327*7c478bd9Sstevel@tonic-gate else 1328*7c478bd9Sstevel@tonic-gate file_error(); 1329*7c478bd9Sstevel@tonic-gate } 1330*7c478bd9Sstevel@tonic-gate 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate if (rename(SHADTEMP, SHADOW) == -1) { 1333*7c478bd9Sstevel@tonic-gate if (rename(OSHADOW, SHADOW) == -1) 1334*7c478bd9Sstevel@tonic-gate bad_news(); 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate if (rec_pwd()) 1337*7c478bd9Sstevel@tonic-gate bad_news(); 1338*7c478bd9Sstevel@tonic-gate else 1339*7c478bd9Sstevel@tonic-gate file_error(); 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate } 1343*7c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) { 1344*7c478bd9Sstevel@tonic-gate if (unlink(OUSERATTR_FILENAME) && 1345*7c478bd9Sstevel@tonic-gate access(OUSERATTR_FILENAME, 0) == 0) { 1346*7c478bd9Sstevel@tonic-gate if (rec_pwd()) 1347*7c478bd9Sstevel@tonic-gate bad_news(); 1348*7c478bd9Sstevel@tonic-gate else 1349*7c478bd9Sstevel@tonic-gate file_error(); 1350*7c478bd9Sstevel@tonic-gate } 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate if (link(USERATTR_FILENAME, OUSERATTR_FILENAME) == -1) { 1353*7c478bd9Sstevel@tonic-gate if (rec_pwd()) 1354*7c478bd9Sstevel@tonic-gate bad_news(); 1355*7c478bd9Sstevel@tonic-gate else 1356*7c478bd9Sstevel@tonic-gate file_error(); 1357*7c478bd9Sstevel@tonic-gate } 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate if (rename(USERATTR_TEMP, USERATTR_FILENAME) == -1) { 1361*7c478bd9Sstevel@tonic-gate if (rename(OUSERATTR_FILENAME, USERATTR_FILENAME) == -1) 1362*7c478bd9Sstevel@tonic-gate bad_news(); 1363*7c478bd9Sstevel@tonic-gate 1364*7c478bd9Sstevel@tonic-gate if (rec_pwd()) 1365*7c478bd9Sstevel@tonic-gate bad_news(); 1366*7c478bd9Sstevel@tonic-gate else 1367*7c478bd9Sstevel@tonic-gate file_error(); 1368*7c478bd9Sstevel@tonic-gate } 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate } 1371*7c478bd9Sstevel@tonic-gate 1372*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate /* 1375*7c478bd9Sstevel@tonic-gate * Return 0 status, indicating success 1376*7c478bd9Sstevel@tonic-gate */ 1377*7c478bd9Sstevel@tonic-gate exit(0); 1378*7c478bd9Sstevel@tonic-gate 1379*7c478bd9Sstevel@tonic-gate } /* end of main */ 1380*7c478bd9Sstevel@tonic-gate 1381*7c478bd9Sstevel@tonic-gate /* Try to recover the old password file */ 1382*7c478bd9Sstevel@tonic-gate 1383*7c478bd9Sstevel@tonic-gate int 1384*7c478bd9Sstevel@tonic-gate rec_pwd() 1385*7c478bd9Sstevel@tonic-gate { 1386*7c478bd9Sstevel@tonic-gate if (unlink(PASSWD) || link(OPASSWD, PASSWD)) 1387*7c478bd9Sstevel@tonic-gate return (-1); 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate return (0); 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate /* combine two uid_blk's */ 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate void 1395*7c478bd9Sstevel@tonic-gate uid_bcom(uid_p) 1396*7c478bd9Sstevel@tonic-gate struct uid_blk *uid_p; 1397*7c478bd9Sstevel@tonic-gate { 1398*7c478bd9Sstevel@tonic-gate struct uid_blk *uid_tp; 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate uid_tp = uid_p->link; 1401*7c478bd9Sstevel@tonic-gate uid_p->high = uid_tp->high; 1402*7c478bd9Sstevel@tonic-gate uid_p->link = uid_tp->link; 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate free(uid_tp); 1405*7c478bd9Sstevel@tonic-gate } 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate /* add a new uid_blk */ 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate void 1410*7c478bd9Sstevel@tonic-gate add_ublk(num, uid_p) 1411*7c478bd9Sstevel@tonic-gate uid_t num; 1412*7c478bd9Sstevel@tonic-gate struct uid_blk *uid_p; 1413*7c478bd9Sstevel@tonic-gate { 1414*7c478bd9Sstevel@tonic-gate struct uid_blk *uid_tp; 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate uid_tp = malloc(sizeof (struct uid_blk)); 1417*7c478bd9Sstevel@tonic-gate if (uid_tp == NULL) { 1418*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1419*7c478bd9Sstevel@tonic-gate file_error(); 1420*7c478bd9Sstevel@tonic-gate } 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate uid_tp->high = uid_tp->low = num; 1423*7c478bd9Sstevel@tonic-gate uid_tp->link = uid_p->link; 1424*7c478bd9Sstevel@tonic-gate uid_p->link = uid_tp; 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate /* 1428*7c478bd9Sstevel@tonic-gate * Here we are using a linked list of uid_blk to keep track of all 1429*7c478bd9Sstevel@tonic-gate * the used uids. Each uid_blk represents a range of used uid, 1430*7c478bd9Sstevel@tonic-gate * with low represents the low inclusive end and high represents 1431*7c478bd9Sstevel@tonic-gate * the high inclusive end. In the beginning, we initialize a linked 1432*7c478bd9Sstevel@tonic-gate * list of one uid_blk with low = high = (UID_MIN-1). This was 1433*7c478bd9Sstevel@tonic-gate * done in main(). 1434*7c478bd9Sstevel@tonic-gate * Each time we read in another used uid, we add it onto the linked 1435*7c478bd9Sstevel@tonic-gate * list by either making a new uid_blk, decrementing the low of 1436*7c478bd9Sstevel@tonic-gate * an existing uid_blk, incrementing the high of an existing 1437*7c478bd9Sstevel@tonic-gate * uid_blk, or combining two existing uid_blks. After we finished 1438*7c478bd9Sstevel@tonic-gate * building this linked list, the first available uid above or 1439*7c478bd9Sstevel@tonic-gate * equal to UID_MIN is the high of the first uid_blk in the linked 1440*7c478bd9Sstevel@tonic-gate * list + 1. 1441*7c478bd9Sstevel@tonic-gate */ 1442*7c478bd9Sstevel@tonic-gate /* add_uid() adds uid to the link list of used uids */ 1443*7c478bd9Sstevel@tonic-gate void 1444*7c478bd9Sstevel@tonic-gate add_uid(uid) 1445*7c478bd9Sstevel@tonic-gate uid_t uid; 1446*7c478bd9Sstevel@tonic-gate { 1447*7c478bd9Sstevel@tonic-gate struct uid_blk *uid_p; 1448*7c478bd9Sstevel@tonic-gate /* Only keep track of the ones above UID_MIN */ 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate if (uid >= UID_MIN) { 1451*7c478bd9Sstevel@tonic-gate uid_p = uid_sp; 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate while (uid_p != NULL) { 1454*7c478bd9Sstevel@tonic-gate 1455*7c478bd9Sstevel@tonic-gate if (uid_p->link != NULL) { 1456*7c478bd9Sstevel@tonic-gate 1457*7c478bd9Sstevel@tonic-gate if (uid >= uid_p->link->low) 1458*7c478bd9Sstevel@tonic-gate uid_p = uid_p->link; 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate else if (uid >= uid_p->low && 1461*7c478bd9Sstevel@tonic-gate uid <= uid_p->high) { 1462*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1463*7c478bd9Sstevel@tonic-gate } 1464*7c478bd9Sstevel@tonic-gate 1465*7c478bd9Sstevel@tonic-gate else if (uid == (uid_p->high+1)) { 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate if (++uid_p->high == 1468*7c478bd9Sstevel@tonic-gate (uid_p->link->low - 1)) { 1469*7c478bd9Sstevel@tonic-gate uid_bcom(uid_p); 1470*7c478bd9Sstevel@tonic-gate } 1471*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1472*7c478bd9Sstevel@tonic-gate } 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate else if (uid == (uid_p->link->low - 1)) { 1475*7c478bd9Sstevel@tonic-gate uid_p->link->low --; 1476*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate 1479*7c478bd9Sstevel@tonic-gate else if (uid < uid_p->link->low) { 1480*7c478bd9Sstevel@tonic-gate add_ublk(uid, uid_p); 1481*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1482*7c478bd9Sstevel@tonic-gate } 1483*7c478bd9Sstevel@tonic-gate } /* if uid_p->link */ 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate else { 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate if (uid == (uid_p->high + 1)) { 1488*7c478bd9Sstevel@tonic-gate uid_p->high++; 1489*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1490*7c478bd9Sstevel@tonic-gate } else if (uid >= uid_p->low && 1491*7c478bd9Sstevel@tonic-gate uid <= uid_p->high) { 1492*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1493*7c478bd9Sstevel@tonic-gate } else { 1494*7c478bd9Sstevel@tonic-gate add_ublk(uid, uid_p); 1495*7c478bd9Sstevel@tonic-gate uid_p = NULL; 1496*7c478bd9Sstevel@tonic-gate } 1497*7c478bd9Sstevel@tonic-gate } /* else */ 1498*7c478bd9Sstevel@tonic-gate } /* while uid_p */ 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate } /* if uid */ 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate void 1504*7c478bd9Sstevel@tonic-gate bad_perm() 1505*7c478bd9Sstevel@tonic-gate { 1506*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Permission denied\n"), prognamp); 1507*7c478bd9Sstevel@tonic-gate exit(1); 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate 1510*7c478bd9Sstevel@tonic-gate void 1511*7c478bd9Sstevel@tonic-gate bad_usage(sp) 1512*7c478bd9Sstevel@tonic-gate char *sp; 1513*7c478bd9Sstevel@tonic-gate { 1514*7c478bd9Sstevel@tonic-gate if (strlen(sp) != 0) 1515*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(sp)); 1516*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage:\n\ 1517*7c478bd9Sstevel@tonic-gate %s -a [-c comment] [-h homedir] [-u uid [-o]] [-g gid] \n\ 1518*7c478bd9Sstevel@tonic-gate [-s shell] [-f inactive] [-e expire] name\n\ 1519*7c478bd9Sstevel@tonic-gate %s -m -c comment | -h homedir | -u uid [-o] | -g gid |\n\ 1520*7c478bd9Sstevel@tonic-gate -s shell | -f inactive | -e expire | -l logname name\n\ 1521*7c478bd9Sstevel@tonic-gate %s -d name\n"), prognamp, prognamp, prognamp); 1522*7c478bd9Sstevel@tonic-gate if (info_mask & LOCKED) 1523*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1524*7c478bd9Sstevel@tonic-gate exit(2); 1525*7c478bd9Sstevel@tonic-gate } 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate void 1528*7c478bd9Sstevel@tonic-gate bad_arg(s) 1529*7c478bd9Sstevel@tonic-gate char *s; 1530*7c478bd9Sstevel@tonic-gate { 1531*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s)); 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate if (info_mask & LOCKED) 1534*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1535*7c478bd9Sstevel@tonic-gate exit(3); 1536*7c478bd9Sstevel@tonic-gate } 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate void 1539*7c478bd9Sstevel@tonic-gate bad_name(s) 1540*7c478bd9Sstevel@tonic-gate char *s; 1541*7c478bd9Sstevel@tonic-gate { 1542*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s)); 1543*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1544*7c478bd9Sstevel@tonic-gate exit(9); 1545*7c478bd9Sstevel@tonic-gate } 1546*7c478bd9Sstevel@tonic-gate 1547*7c478bd9Sstevel@tonic-gate void 1548*7c478bd9Sstevel@tonic-gate bad_uid() 1549*7c478bd9Sstevel@tonic-gate { 1550*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: UID in use\n"), prognamp); 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1553*7c478bd9Sstevel@tonic-gate exit(4); 1554*7c478bd9Sstevel@tonic-gate } 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate void 1557*7c478bd9Sstevel@tonic-gate bad_pasf() 1558*7c478bd9Sstevel@tonic-gate { 1559*7c478bd9Sstevel@tonic-gate msg = "%s: Inconsistent password files\n"; 1560*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp); 1561*7c478bd9Sstevel@tonic-gate 1562*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1563*7c478bd9Sstevel@tonic-gate exit(5); 1564*7c478bd9Sstevel@tonic-gate } 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate void 1567*7c478bd9Sstevel@tonic-gate bad_uattr() 1568*7c478bd9Sstevel@tonic-gate { 1569*7c478bd9Sstevel@tonic-gate msg = "%s: Bad user_attr database\n"; 1570*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp); 1571*7c478bd9Sstevel@tonic-gate 1572*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1573*7c478bd9Sstevel@tonic-gate exit(5); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate 1576*7c478bd9Sstevel@tonic-gate void 1577*7c478bd9Sstevel@tonic-gate file_error() 1578*7c478bd9Sstevel@tonic-gate { 1579*7c478bd9Sstevel@tonic-gate msg = "%s: Unexpected failure. Password files unchanged\n"; 1580*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp); 1581*7c478bd9Sstevel@tonic-gate 1582*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1583*7c478bd9Sstevel@tonic-gate exit(6); 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate void 1587*7c478bd9Sstevel@tonic-gate bad_news() 1588*7c478bd9Sstevel@tonic-gate { 1589*7c478bd9Sstevel@tonic-gate msg = "%s: Unexpected failure. Password file(s) missing\n"; 1590*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp); 1591*7c478bd9Sstevel@tonic-gate 1592*7c478bd9Sstevel@tonic-gate ulckpwdf(); 1593*7c478bd9Sstevel@tonic-gate exit(7); 1594*7c478bd9Sstevel@tonic-gate } 1595*7c478bd9Sstevel@tonic-gate 1596*7c478bd9Sstevel@tonic-gate void 1597*7c478bd9Sstevel@tonic-gate no_lock() 1598*7c478bd9Sstevel@tonic-gate { 1599*7c478bd9Sstevel@tonic-gate msg = "%s: Password file(s) busy. Try again later\n"; 1600*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp); 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate exit(8); 1603*7c478bd9Sstevel@tonic-gate } 1604*7c478bd9Sstevel@tonic-gate 1605*7c478bd9Sstevel@tonic-gate /* Check for the size of the whole passwd entry */ 1606*7c478bd9Sstevel@tonic-gate void 1607*7c478bd9Sstevel@tonic-gate ck_p_sz(pwp) 1608*7c478bd9Sstevel@tonic-gate struct passwd *pwp; 1609*7c478bd9Sstevel@tonic-gate { 1610*7c478bd9Sstevel@tonic-gate char ctp[128]; 1611*7c478bd9Sstevel@tonic-gate 1612*7c478bd9Sstevel@tonic-gate /* Ensure that the combined length of the individual */ 1613*7c478bd9Sstevel@tonic-gate /* fields will fit in a passwd entry. The 1 accounts for the */ 1614*7c478bd9Sstevel@tonic-gate /* newline and the 6 accounts for the colons (:'s) */ 1615*7c478bd9Sstevel@tonic-gate if (((int)strlen(pwp->pw_name) + 1 + 1616*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", pwp->pw_uid) + 1617*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", pwp->pw_gid) + 1618*7c478bd9Sstevel@tonic-gate (int)strlen(pwp->pw_comment) + 1619*7c478bd9Sstevel@tonic-gate (int)strlen(pwp->pw_dir) + 1620*7c478bd9Sstevel@tonic-gate (int)strlen(pwp->pw_shell) + 6) > (ENTRY_LENGTH-1)) 1621*7c478bd9Sstevel@tonic-gate { 1622*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1623*7c478bd9Sstevel@tonic-gate bad_arg("New password entry too long"); 1624*7c478bd9Sstevel@tonic-gate } 1625*7c478bd9Sstevel@tonic-gate } 1626*7c478bd9Sstevel@tonic-gate 1627*7c478bd9Sstevel@tonic-gate /* Check for the size of the whole passwd entry */ 1628*7c478bd9Sstevel@tonic-gate void 1629*7c478bd9Sstevel@tonic-gate ck_s_sz(ssp) 1630*7c478bd9Sstevel@tonic-gate struct spwd *ssp; 1631*7c478bd9Sstevel@tonic-gate { 1632*7c478bd9Sstevel@tonic-gate char ctp[128]; 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate /* Ensure that the combined length of the individual */ 1635*7c478bd9Sstevel@tonic-gate /* fields will fit in a shadow entry. The 1 accounts for the */ 1636*7c478bd9Sstevel@tonic-gate /* newline and the 7 accounts for the colons (:'s) */ 1637*7c478bd9Sstevel@tonic-gate if (((int)strlen(ssp->sp_namp) + 1 + 1638*7c478bd9Sstevel@tonic-gate (int)strlen(ssp->sp_pwdp) + 1639*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_lstchg) + 1640*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_min) + 1641*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_max) + 1642*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_warn) + 1643*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_inact) + 1644*7c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_expire) + 7) > (ENTRY_LENGTH - 1)) 1645*7c478bd9Sstevel@tonic-gate { 1646*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1647*7c478bd9Sstevel@tonic-gate bad_arg("New password entry too long"); 1648*7c478bd9Sstevel@tonic-gate } 1649*7c478bd9Sstevel@tonic-gate } 1650*7c478bd9Sstevel@tonic-gate 1651*7c478bd9Sstevel@tonic-gate /* Get rid of the temp files */ 1652*7c478bd9Sstevel@tonic-gate void 1653*7c478bd9Sstevel@tonic-gate rid_tmpf() 1654*7c478bd9Sstevel@tonic-gate { 1655*7c478bd9Sstevel@tonic-gate (void) fclose(fp_ptemp); 1656*7c478bd9Sstevel@tonic-gate 1657*7c478bd9Sstevel@tonic-gate if (unlink(PASSTEMP)) { 1658*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 1659*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp, PASSTEMP); 1660*7c478bd9Sstevel@tonic-gate } 1661*7c478bd9Sstevel@tonic-gate 1662*7c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) { 1663*7c478bd9Sstevel@tonic-gate (void) fclose(fp_stemp); 1664*7c478bd9Sstevel@tonic-gate 1665*7c478bd9Sstevel@tonic-gate if (unlink(SHADTEMP)) { 1666*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 1667*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp, 1668*7c478bd9Sstevel@tonic-gate SHADTEMP); 1669*7c478bd9Sstevel@tonic-gate } 1670*7c478bd9Sstevel@tonic-gate } 1671*7c478bd9Sstevel@tonic-gate 1672*7c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) { 1673*7c478bd9Sstevel@tonic-gate (void) fclose(fp_uatemp); 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate if (unlink(USERATTR_TEMP)) { 1676*7c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n"; 1677*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp, 1678*7c478bd9Sstevel@tonic-gate USERATTR_TEMP); 1679*7c478bd9Sstevel@tonic-gate } 1680*7c478bd9Sstevel@tonic-gate } 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate void 1684*7c478bd9Sstevel@tonic-gate file_copy(FILE *spf, long NIS_pos) 1685*7c478bd9Sstevel@tonic-gate { 1686*7c478bd9Sstevel@tonic-gate int n; 1687*7c478bd9Sstevel@tonic-gate char buf[1024]; 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate if (fseek(spf, NIS_pos, SEEK_SET) < 0) { 1690*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1691*7c478bd9Sstevel@tonic-gate file_error(); 1692*7c478bd9Sstevel@tonic-gate } 1693*7c478bd9Sstevel@tonic-gate while ((n = fread(buf, sizeof (char), 1024, spf)) > 0) { 1694*7c478bd9Sstevel@tonic-gate if (fwrite(buf, sizeof (char), n, fp_stemp) != n) { 1695*7c478bd9Sstevel@tonic-gate rid_tmpf(); 1696*7c478bd9Sstevel@tonic-gate file_error(); 1697*7c478bd9Sstevel@tonic-gate } 1698*7c478bd9Sstevel@tonic-gate } 1699*7c478bd9Sstevel@tonic-gate } 1700