17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53bf5ae9eSrica * Common Development and Distribution License (the "License").
63bf5ae9eSrica * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*07925104Sgww * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
267c478bd9Sstevel@tonic-gate /* All Rights Reserved */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <shadow.h>
317c478bd9Sstevel@tonic-gate #include <pwd.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <time.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
397c478bd9Sstevel@tonic-gate #include <locale.h>
407c478bd9Sstevel@tonic-gate #include <fcntl.h>
417c478bd9Sstevel@tonic-gate #include <secdb.h>
427c478bd9Sstevel@tonic-gate #include <user_attr.h>
43*07925104Sgww #include <nss.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #define CMT_SIZE (128+1) /* Argument sizes + 1 (for '\0') */
467c478bd9Sstevel@tonic-gate #define DIR_SIZE (256+1)
477c478bd9Sstevel@tonic-gate #define SHL_SIZE (256+1)
487c478bd9Sstevel@tonic-gate #define ENTRY_LENGTH 512 /* Max length of an /etc/passwd entry */
497c478bd9Sstevel@tonic-gate #define UID_MIN 100 /* Lower bound of default UID */
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #define M_MASK 01 /* Masks for the optn_mask variable */
527c478bd9Sstevel@tonic-gate #define L_MASK 02 /* It keeps track of which options */
537c478bd9Sstevel@tonic-gate #define C_MASK 04 /* have been entered */
547c478bd9Sstevel@tonic-gate #define H_MASK 010
557c478bd9Sstevel@tonic-gate #define U_MASK 020
567c478bd9Sstevel@tonic-gate #define G_MASK 040
577c478bd9Sstevel@tonic-gate #define S_MASK 0100
587c478bd9Sstevel@tonic-gate #define O_MASK 0200
597c478bd9Sstevel@tonic-gate #define A_MASK 0400
607c478bd9Sstevel@tonic-gate #define D_MASK 01000
617c478bd9Sstevel@tonic-gate #define F_MASK 02000
627c478bd9Sstevel@tonic-gate #define E_MASK 04000
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate #define UATTR_MASK 010000
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate /* flags for info_mask */
677c478bd9Sstevel@tonic-gate #define LOGNAME_EXIST 01 /* logname exists */
687c478bd9Sstevel@tonic-gate #define BOTH_FILES 02 /* touch both password files */
697c478bd9Sstevel@tonic-gate #define WRITE_P_ENTRY 04 /* write out password entry */
707c478bd9Sstevel@tonic-gate #define WRITE_S_ENTRY 010 /* write out shadow entry */
717c478bd9Sstevel@tonic-gate #define NEED_DEF_UID 020 /* need default uid */
727c478bd9Sstevel@tonic-gate #define FOUND 040 /* found the entry in password file */
737c478bd9Sstevel@tonic-gate #define LOCKED 0100 /* did we lock the password file */
747c478bd9Sstevel@tonic-gate #define UATTR_FILE 0200 /* touch user_attr file */
757c478bd9Sstevel@tonic-gate #define BAD_ENT_MESSAGE "%s: Bad entry found in /etc/passwd. Run pwconv.\n"
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate typedef struct kvopts {
787c478bd9Sstevel@tonic-gate const char option;
797c478bd9Sstevel@tonic-gate const char *key;
807c478bd9Sstevel@tonic-gate char *newvalue;
817c478bd9Sstevel@tonic-gate } kvopts_t;
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /* mapping of extensible keywords and options */
847c478bd9Sstevel@tonic-gate kvopts_t ua_opts[] = {
857c478bd9Sstevel@tonic-gate { 'A', USERATTR_AUTHS_KW },
867c478bd9Sstevel@tonic-gate { 'P', USERATTR_PROFILES_KW },
877c478bd9Sstevel@tonic-gate { 'R', USERATTR_ROLES_KW },
887c478bd9Sstevel@tonic-gate { 'T', USERATTR_TYPE_KW },
897c478bd9Sstevel@tonic-gate { '\0', USERATTR_DEFAULTPROJ_KW },
907c478bd9Sstevel@tonic-gate { '\0', USERATTR_LIMPRIV_KW },
917c478bd9Sstevel@tonic-gate { '\0', USERATTR_DFLTPRIV_KW },
927c478bd9Sstevel@tonic-gate { '\0', USERATTR_LOCK_AFTER_RETRIES_KW },
933bf5ae9eSrica { '\0', USERATTR_LABELVIEW },
943bf5ae9eSrica { '\0', USERATTR_CLEARANCE },
953bf5ae9eSrica { '\0', USERATTR_MINLABEL },
963bf5ae9eSrica { '\0', USERATTR_IDLECMD_KW },
973bf5ae9eSrica { '\0', USERATTR_IDLETIME_KW },
98*07925104Sgww { '\0', USERATTR_AUDIT_FLAGS_KW },
997c478bd9Sstevel@tonic-gate };
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate #define UA_KEYS (sizeof (ua_opts)/sizeof (kvopts_t))
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate char defdir[] = "/home/"; /* default home directory for new user */
1057c478bd9Sstevel@tonic-gate char pwdflr[] = "x"; /* password string for /etc/passwd */
1067c478bd9Sstevel@tonic-gate char lkstring[] = "*LK*"; /* lock string for shadow password */
1077c478bd9Sstevel@tonic-gate char nullstr[] = ""; /* null string */
1087c478bd9Sstevel@tonic-gate char *msg; /* pointer to error message */
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate #define DATMSK "DATEMSK=/etc/datemsk"
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate #define OUSERATTR_FILENAME "/etc/ouser_attr"
1137c478bd9Sstevel@tonic-gate #define USERATTR_TEMP "/etc/uatmp"
1147c478bd9Sstevel@tonic-gate
11549335bdeSbasabi struct uid_blk {
11649335bdeSbasabi struct uid_blk *link;
11749335bdeSbasabi uid_t low; /* low bound for this uid block */
11849335bdeSbasabi uid_t high; /* high bound for this uid block */
11949335bdeSbasabi };
12049335bdeSbasabi
1217c478bd9Sstevel@tonic-gate extern userattr_t *fgetuserattr(FILE *);
1227c478bd9Sstevel@tonic-gate
12349335bdeSbasabi
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate * Declare all functions that do not return integers. This is here
1267c478bd9Sstevel@tonic-gate * to get rid of some lint messages
1277c478bd9Sstevel@tonic-gate */
1287c478bd9Sstevel@tonic-gate
12949335bdeSbasabi void uid_bcom(struct uid_blk *), add_ublk(uid_t, struct uid_blk *),
13049335bdeSbasabi bad_perm(void),
13149335bdeSbasabi bad_usage(char *), bad_arg(char *), bad_uid(void), bad_pasf(void),
13249335bdeSbasabi file_error(void), bad_news(void), no_lock(void), add_uid(uid_t),
13349335bdeSbasabi rid_tmpf(void), ck_p_sz(struct passwd *), ck_s_sz(struct spwd *),
13449335bdeSbasabi bad_name(char *), bad_uattr(void);
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate void file_copy(FILE *spf, long NIS_pos);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate static FILE *fp_ptemp, *fp_stemp, *fp_uatemp;
1397c478bd9Sstevel@tonic-gate static int fd_ptemp, fd_stemp, fd_uatemp;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate * The uid_blk structure is used in the search for the default
1437c478bd9Sstevel@tonic-gate * uid. Each uid_blk represent a range of uid(s) that are currently
1447c478bd9Sstevel@tonic-gate * used on the system.
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate #ifndef att
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate * getspnan routine that ONLY looks at the local shadow file
1517c478bd9Sstevel@tonic-gate */
1527c478bd9Sstevel@tonic-gate struct spwd *
local_getspnam(char * name)15349335bdeSbasabi local_getspnam(char *name)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate FILE *shadf;
1567c478bd9Sstevel@tonic-gate struct spwd *sp;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate if ((shadf = fopen("/etc/shadow", "r")) == NULL)
1597c478bd9Sstevel@tonic-gate return (NULL);
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate while ((sp = fgetspent(shadf)) != NULL) {
1627c478bd9Sstevel@tonic-gate if (strcmp(sp->sp_namp, name) == 0)
1637c478bd9Sstevel@tonic-gate break;
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate fclose(shadf);
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate return (sp);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate #endif
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate static void
putuserattrent(userattr_t * user,FILE * f)1737c478bd9Sstevel@tonic-gate putuserattrent(userattr_t *user, FILE *f)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate int i, j;
1767c478bd9Sstevel@tonic-gate char *key;
1777c478bd9Sstevel@tonic-gate char *val;
1787c478bd9Sstevel@tonic-gate kv_t *kv_pair;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate * Avoid trivial entries. Those with no attributes or with
1827c478bd9Sstevel@tonic-gate * only "type=normal". This retains backward compatibility.
1837c478bd9Sstevel@tonic-gate */
1847c478bd9Sstevel@tonic-gate if (user->attr == NULL)
1857c478bd9Sstevel@tonic-gate return;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate kv_pair = user->attr->data;
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate for (i = j = 0; i < user->attr->length; i++) {
1907c478bd9Sstevel@tonic-gate key = kv_pair[i].key;
1917c478bd9Sstevel@tonic-gate val = kv_pair[i].value;
1927c478bd9Sstevel@tonic-gate if ((key == NULL) || (val == NULL))
1937c478bd9Sstevel@tonic-gate break;
1947c478bd9Sstevel@tonic-gate if (strlen(val) == 0 ||
1957c478bd9Sstevel@tonic-gate (strcmp(key, USERATTR_TYPE_KW) == 0 &&
1967c478bd9Sstevel@tonic-gate strcmp(val, USERATTR_TYPE_NORMAL_KW) == 0))
1977c478bd9Sstevel@tonic-gate continue;
1987c478bd9Sstevel@tonic-gate j++;
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate if (j == 0)
2017c478bd9Sstevel@tonic-gate return;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate (void) fprintf(f, "%s:%s:%s:%s:", user->name, user->qualifier,
2047c478bd9Sstevel@tonic-gate user->res1, user->res2);
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate for (i = j = 0; i < user->attr->length; i++) {
2077c478bd9Sstevel@tonic-gate key = kv_pair[i].key;
208*07925104Sgww val = _escape(kv_pair[i].value, KV_SPECIAL);
2097c478bd9Sstevel@tonic-gate if ((key == NULL) || (val == NULL))
2107c478bd9Sstevel@tonic-gate break;
2117c478bd9Sstevel@tonic-gate if (strlen(val) == 0)
2127c478bd9Sstevel@tonic-gate continue;
2137c478bd9Sstevel@tonic-gate if (j > 0)
2147c478bd9Sstevel@tonic-gate (void) fprintf(f, KV_DELIMITER);
2157c478bd9Sstevel@tonic-gate (void) fprintf(f, "%s=%s", key, val);
2167c478bd9Sstevel@tonic-gate j++;
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate (void) fprintf(f, "\n");
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate static void
assign_attr(userattr_t * user,const char * newkey,char * val)2227c478bd9Sstevel@tonic-gate assign_attr(userattr_t *user, const char *newkey, char *val) {
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate int i;
2257c478bd9Sstevel@tonic-gate char *key;
2267c478bd9Sstevel@tonic-gate kv_t *kv_pair;
2277c478bd9Sstevel@tonic-gate int avail = -1;
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate if (user->attr != NULL) {
2307c478bd9Sstevel@tonic-gate kv_pair = user->attr->data;
2317c478bd9Sstevel@tonic-gate for (i = 0; i < user->attr->length; i++) {
2327c478bd9Sstevel@tonic-gate key = kv_pair[i].key;
2337c478bd9Sstevel@tonic-gate if (key == NULL) {
2347c478bd9Sstevel@tonic-gate avail = i;
2357c478bd9Sstevel@tonic-gate continue;
2367c478bd9Sstevel@tonic-gate } else if (strcmp(key, newkey) == 0) {
2377c478bd9Sstevel@tonic-gate kv_pair[i].value = strdup(val);
2387c478bd9Sstevel@tonic-gate return;
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate if (avail == -1)
2437c478bd9Sstevel@tonic-gate avail = user->attr->length++;
2447c478bd9Sstevel@tonic-gate kv_pair[avail].key = strdup(newkey);
2457c478bd9Sstevel@tonic-gate kv_pair[avail].value = strdup(val);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate static void
unassign_role(userattr_t * user,char * rolelist,char * role)2507c478bd9Sstevel@tonic-gate unassign_role(userattr_t *user, char *rolelist, char *role) {
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate char *roleptr;
2537c478bd9Sstevel@tonic-gate char *templist;
2547c478bd9Sstevel@tonic-gate char *temprole;
2557c478bd9Sstevel@tonic-gate int length;
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate roleptr = rolelist;
2587c478bd9Sstevel@tonic-gate templist = strdup(roleptr);
2597c478bd9Sstevel@tonic-gate temprole = strtok(templist, ",");
2607c478bd9Sstevel@tonic-gate while (temprole) {
2617c478bd9Sstevel@tonic-gate if (strcmp(temprole, role) == 0) {
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate length = strlen(role);
2647c478bd9Sstevel@tonic-gate roleptr += temprole - templist;
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate if (*(roleptr + length) == ',')
2677c478bd9Sstevel@tonic-gate length++;
2687c478bd9Sstevel@tonic-gate strcpy(roleptr, roleptr + length);
2697c478bd9Sstevel@tonic-gate length = strlen(roleptr) - 1;
2707c478bd9Sstevel@tonic-gate if (*(roleptr + length) == ',')
2717c478bd9Sstevel@tonic-gate *(roleptr + length) = '\0';
2727c478bd9Sstevel@tonic-gate assign_attr(user, USERATTR_ROLES_KW, rolelist);
2737c478bd9Sstevel@tonic-gate break;
2747c478bd9Sstevel@tonic-gate } else {
2757c478bd9Sstevel@tonic-gate temprole = strtok(NULL, ",");
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate struct uid_blk *uid_sp;
2817c478bd9Sstevel@tonic-gate char *prognamp; /* program name */
2827c478bd9Sstevel@tonic-gate extern int errno;
2837c478bd9Sstevel@tonic-gate int optn_mask = 0, info_mask = 0;
2847c478bd9Sstevel@tonic-gate extern int getdate_err;
2857c478bd9Sstevel@tonic-gate
28649335bdeSbasabi int
main(int argc,char ** argv)28749335bdeSbasabi main(int argc, char **argv)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate int c, i;
2907c478bd9Sstevel@tonic-gate char *lognamp, *char_p;
2917c478bd9Sstevel@tonic-gate int end_of_file = 0;
2927c478bd9Sstevel@tonic-gate int error;
2937c478bd9Sstevel@tonic-gate long date = 0;
2947c478bd9Sstevel@tonic-gate FILE *pwf, *spf, *uaf;
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate struct passwd *pw_ptr1p, passwd_st;
2977c478bd9Sstevel@tonic-gate struct spwd *sp_ptr1p, shadow_st;
2987c478bd9Sstevel@tonic-gate userattr_t *ua_ptr1p, userattr_st;
2997c478bd9Sstevel@tonic-gate static kv_t ua_kv[KV_ADD_KEYS];
3007c478bd9Sstevel@tonic-gate kva_t ua_kva;
3017c478bd9Sstevel@tonic-gate struct stat statbuf;
3027c478bd9Sstevel@tonic-gate struct tm *tm_ptr;
3037c478bd9Sstevel@tonic-gate int NIS_entry_seen; /* NIS scanning flag */
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate * NIS start pos, really pointer to first entry AFTER first
3067c478bd9Sstevel@tonic-gate * NIS-referant entry
3077c478bd9Sstevel@tonic-gate */
3087c478bd9Sstevel@tonic-gate long NIS_pos;
3097c478bd9Sstevel@tonic-gate long cur_pos; /* Current pos, used with nis-pos above */
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
3147c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
3157c478bd9Sstevel@tonic-gate #endif
3167c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate tzset();
3197c478bd9Sstevel@tonic-gate /* Get program name */
3207c478bd9Sstevel@tonic-gate prognamp = argv[0];
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate /* Check identity */
3237c478bd9Sstevel@tonic-gate if (geteuid() != 0)
3247c478bd9Sstevel@tonic-gate bad_perm();
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate /* Lock the password file(s) */
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate if (lckpwdf() != 0)
3297c478bd9Sstevel@tonic-gate no_lock();
3307c478bd9Sstevel@tonic-gate info_mask |= LOCKED; /* remember we locked */
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate /* initialize the two structures */
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate passwd_st.pw_passwd = pwdflr; /* bogus password */
3357c478bd9Sstevel@tonic-gate passwd_st.pw_name = nullstr; /* login name */
3367c478bd9Sstevel@tonic-gate passwd_st.pw_uid = -1; /* no uid */
3377c478bd9Sstevel@tonic-gate passwd_st.pw_gid = 1; /* default gid */
3387c478bd9Sstevel@tonic-gate passwd_st.pw_age = nullstr; /* no aging info. */
3397c478bd9Sstevel@tonic-gate passwd_st.pw_comment = nullstr; /* no comments */
3407c478bd9Sstevel@tonic-gate passwd_st.pw_gecos = nullstr; /* no comments */
3417c478bd9Sstevel@tonic-gate passwd_st.pw_dir = nullstr; /* no default directory */
3427c478bd9Sstevel@tonic-gate passwd_st.pw_shell = nullstr; /* no default shell */
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate shadow_st.sp_namp = nullstr; /* no name */
3457c478bd9Sstevel@tonic-gate shadow_st.sp_pwdp = lkstring; /* locked password */
3467c478bd9Sstevel@tonic-gate shadow_st.sp_lstchg = -1; /* no lastchanged date */
3477c478bd9Sstevel@tonic-gate shadow_st.sp_min = -1; /* no min */
3487c478bd9Sstevel@tonic-gate shadow_st.sp_max = -1; /* no max */
3497c478bd9Sstevel@tonic-gate shadow_st.sp_warn = -1; /* no warn */
3507c478bd9Sstevel@tonic-gate shadow_st.sp_inact = -1; /* no inactive */
3517c478bd9Sstevel@tonic-gate shadow_st.sp_expire = -1; /* no expire */
3527c478bd9Sstevel@tonic-gate shadow_st.sp_flag = 0; /* no flag */
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate userattr_st.name = nullstr;
3557c478bd9Sstevel@tonic-gate userattr_st.qualifier = nullstr;
3567c478bd9Sstevel@tonic-gate userattr_st.res1 = nullstr;
3577c478bd9Sstevel@tonic-gate userattr_st.res2 = nullstr;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate ua_kva.length = 1;
3607c478bd9Sstevel@tonic-gate ua_kv[0].key = USERATTR_TYPE_KW;
3617c478bd9Sstevel@tonic-gate ua_kv[0].value = USERATTR_TYPE_NORMAL_KW;
3627c478bd9Sstevel@tonic-gate ua_kva.data = ua_kv;
3637c478bd9Sstevel@tonic-gate userattr_st.attr = &ua_kva;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate /* parse the command line */
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv,
3687c478bd9Sstevel@tonic-gate "ml:c:h:u:g:s:f:e:k:A:P:R:T:oadK:")) != -1) {
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate switch (c) {
3717c478bd9Sstevel@tonic-gate case 'm':
3727c478bd9Sstevel@tonic-gate /* Modify */
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate if ((A_MASK|D_MASK|M_MASK) & optn_mask)
3757c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate optn_mask |= M_MASK;
3787c478bd9Sstevel@tonic-gate break;
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate case 'l' :
3817c478bd9Sstevel@tonic-gate /* Change logname */
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate if ((A_MASK|D_MASK|L_MASK) & optn_mask)
3847c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate if (strpbrk(optarg, ":\n") ||
3877c478bd9Sstevel@tonic-gate strlen(optarg) == 0)
3887c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -l");
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate optn_mask |= L_MASK;
3917c478bd9Sstevel@tonic-gate passwd_st.pw_name = optarg;
3927c478bd9Sstevel@tonic-gate shadow_st.sp_namp = optarg;
3937c478bd9Sstevel@tonic-gate userattr_st.name = optarg;
3947c478bd9Sstevel@tonic-gate break;
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate case 'f' :
3977c478bd9Sstevel@tonic-gate /* set inactive */
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate if ((D_MASK|F_MASK) & optn_mask)
4007c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
4017c478bd9Sstevel@tonic-gate if (((shadow_st.sp_inact =
4027c478bd9Sstevel@tonic-gate strtol(optarg, &char_p, 10)) < (long)0) ||
4037c478bd9Sstevel@tonic-gate (*char_p != '\0') ||
4047c478bd9Sstevel@tonic-gate strlen(optarg) == 0)
4057c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -f");
4067c478bd9Sstevel@tonic-gate if (shadow_st.sp_inact == 0)
4077c478bd9Sstevel@tonic-gate shadow_st.sp_inact = -1;
4087c478bd9Sstevel@tonic-gate optn_mask |= F_MASK;
4097c478bd9Sstevel@tonic-gate break;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate case 'e' :
4127c478bd9Sstevel@tonic-gate /* set expire date */
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate if ((D_MASK|E_MASK) & optn_mask)
4157c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate if ((strlen(optarg)) < (size_t)2)
4187c478bd9Sstevel@tonic-gate shadow_st.sp_expire = -1;
4197c478bd9Sstevel@tonic-gate else {
4207c478bd9Sstevel@tonic-gate putenv(DATMSK);
4217c478bd9Sstevel@tonic-gate if ((tm_ptr = getdate(optarg)) == NULL) {
4227c478bd9Sstevel@tonic-gate msg = "Invalid argument to option -e";
4237c478bd9Sstevel@tonic-gate bad_arg(msg);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate if ((date = mktime(tm_ptr)) < 0) {
4267c478bd9Sstevel@tonic-gate msg = "Invalid argument to option -e";
4277c478bd9Sstevel@tonic-gate bad_arg(msg);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate shadow_st.sp_expire = (date / DAY);
4307c478bd9Sstevel@tonic-gate if (shadow_st.sp_expire <= DAY_NOW) {
4317c478bd9Sstevel@tonic-gate msg = "Invalid argument to option -e";
4327c478bd9Sstevel@tonic-gate bad_arg(msg);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate optn_mask |= E_MASK;
4377c478bd9Sstevel@tonic-gate break;
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate case 'c' :
4407c478bd9Sstevel@tonic-gate /* The comment */
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate if ((D_MASK|C_MASK) & optn_mask)
4437c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate if (strlen(optarg) > (size_t)CMT_SIZE ||
4467c478bd9Sstevel@tonic-gate strpbrk(optarg, ":\n"))
4477c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -c");
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate optn_mask |= C_MASK;
4507c478bd9Sstevel@tonic-gate passwd_st.pw_comment = optarg;
4517c478bd9Sstevel@tonic-gate passwd_st.pw_gecos = optarg;
4527c478bd9Sstevel@tonic-gate break;
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate case 'h' :
4557c478bd9Sstevel@tonic-gate /* The home directory */
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate if ((D_MASK|H_MASK) & optn_mask)
4587c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate if (strlen(optarg) > (size_t)DIR_SIZE ||
4617c478bd9Sstevel@tonic-gate strpbrk(optarg, ":\n"))
4627c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -h");
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate optn_mask |= H_MASK;
4657c478bd9Sstevel@tonic-gate passwd_st.pw_dir = optarg;
4667c478bd9Sstevel@tonic-gate break;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate case 'u' :
4697c478bd9Sstevel@tonic-gate /* The uid */
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate if ((D_MASK|U_MASK) & optn_mask)
4727c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate optn_mask |= U_MASK;
4757c478bd9Sstevel@tonic-gate passwd_st.pw_uid = (uid_t)strtol(optarg, &char_p, 10);
4767c478bd9Sstevel@tonic-gate if ((*char_p != '\0') ||
4777c478bd9Sstevel@tonic-gate (passwd_st.pw_uid < 0) ||
4787c478bd9Sstevel@tonic-gate (strlen(optarg) == 0))
4797c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -u");
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate break;
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate case 'g' :
4847c478bd9Sstevel@tonic-gate /* The gid */
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate if ((D_MASK|G_MASK) & optn_mask)
4877c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate optn_mask |= G_MASK;
4907c478bd9Sstevel@tonic-gate passwd_st.pw_gid = (gid_t)strtol(optarg, &char_p, 10);
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate if ((*char_p != '\0') || (passwd_st.pw_gid < 0) ||
4937c478bd9Sstevel@tonic-gate (strlen(optarg) == 0))
4947c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -g");
4957c478bd9Sstevel@tonic-gate break;
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate case 's' :
4987c478bd9Sstevel@tonic-gate /* The shell */
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate if ((D_MASK|S_MASK) & optn_mask)
5017c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate if (strlen(optarg) > (size_t)SHL_SIZE ||
5047c478bd9Sstevel@tonic-gate strpbrk(optarg, ":\n"))
5057c478bd9Sstevel@tonic-gate bad_arg("Invalid argument to option -s");
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate optn_mask |= S_MASK;
5087c478bd9Sstevel@tonic-gate passwd_st.pw_shell = optarg;
5097c478bd9Sstevel@tonic-gate break;
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate case 'o' :
5127c478bd9Sstevel@tonic-gate /* Override unique uid */
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate if ((D_MASK|O_MASK) & optn_mask)
5157c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate optn_mask |= O_MASK;
5187c478bd9Sstevel@tonic-gate break;
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate case 'a' :
5217c478bd9Sstevel@tonic-gate /* Add */
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate if ((A_MASK|M_MASK|D_MASK|L_MASK) & optn_mask)
5247c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate optn_mask |= A_MASK;
5277c478bd9Sstevel@tonic-gate break;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate case 'd' :
5307c478bd9Sstevel@tonic-gate /* Delete */
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate if ((D_MASK|M_MASK|L_MASK|C_MASK|
5337c478bd9Sstevel@tonic-gate H_MASK|U_MASK|G_MASK|S_MASK|
5347c478bd9Sstevel@tonic-gate O_MASK|A_MASK) & optn_mask)
5357c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate optn_mask |= D_MASK;
5387c478bd9Sstevel@tonic-gate break;
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate case 'K':
5417c478bd9Sstevel@tonic-gate if (D_MASK & optn_mask)
5427c478bd9Sstevel@tonic-gate bad_usage("Invalid combination of options");
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate char_p = strchr(optarg, '=');
5457c478bd9Sstevel@tonic-gate if (char_p == NULL)
5467c478bd9Sstevel@tonic-gate bad_usage("Missing value in -K option");
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate *char_p++ = '\0';
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate for (i = 0; i < UA_KEYS; i++) {
5517c478bd9Sstevel@tonic-gate if (strcmp(optarg, ua_opts[i].key) == 0) {
552*07925104Sgww ua_opts[i].newvalue =
553*07925104Sgww _escape(char_p, KV_SPECIAL);
5547c478bd9Sstevel@tonic-gate assign_attr(&userattr_st, optarg,
5557c478bd9Sstevel@tonic-gate char_p);
5567c478bd9Sstevel@tonic-gate break;
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate if (i == UA_KEYS)
5607c478bd9Sstevel@tonic-gate bad_usage("bad key");
5617c478bd9Sstevel@tonic-gate optn_mask |= UATTR_MASK;
5627c478bd9Sstevel@tonic-gate break;
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate case '?' :
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate bad_usage("");
5677c478bd9Sstevel@tonic-gate break;
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate default :
5707c478bd9Sstevel@tonic-gate /* Extended User Attributes */
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate int j;
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate for (j = 0; j < UA_KEYS; j++) {
5757c478bd9Sstevel@tonic-gate if (ua_opts[j].option == (char)c) {
5767c478bd9Sstevel@tonic-gate if ((D_MASK) & optn_mask)
577*07925104Sgww bad_usage("Invalid "
578*07925104Sgww "combination of "
579*07925104Sgww " options");
5807c478bd9Sstevel@tonic-gate optn_mask |= UATTR_MASK;
5817c478bd9Sstevel@tonic-gate assign_attr(&userattr_st,
582*07925104Sgww ua_opts[j].key,
583*07925104Sgww _escape(optarg,
584*07925104Sgww KV_SPECIAL));
585*07925104Sgww ua_opts[j].newvalue =
586*07925104Sgww _escape(optarg, KV_SPECIAL);
5877c478bd9Sstevel@tonic-gate break;
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate break;
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate /* check command syntax for the following errors */
5967c478bd9Sstevel@tonic-gate /* too few or too many arguments */
5977c478bd9Sstevel@tonic-gate /* no -a -m or -d option */
5987c478bd9Sstevel@tonic-gate /* -o without -u */
5997c478bd9Sstevel@tonic-gate /* -m with no other option */
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate if (optind == argc || argc > (optind+1) ||
6027c478bd9Sstevel@tonic-gate !((A_MASK|M_MASK|D_MASK) & optn_mask) ||
6037c478bd9Sstevel@tonic-gate ((optn_mask & O_MASK) && !(optn_mask & U_MASK)) ||
6047c478bd9Sstevel@tonic-gate ((optn_mask & M_MASK) &&
6057c478bd9Sstevel@tonic-gate !(optn_mask &
6067c478bd9Sstevel@tonic-gate (L_MASK|C_MASK|H_MASK|U_MASK|G_MASK|S_MASK|F_MASK|
6077c478bd9Sstevel@tonic-gate E_MASK|UATTR_MASK))))
6087c478bd9Sstevel@tonic-gate bad_usage("Invalid command syntax");
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate /* null string argument or bad characters ? */
6117c478bd9Sstevel@tonic-gate if ((strlen(argv[optind]) == 0) || strpbrk(argv[optind], ":\n"))
6127c478bd9Sstevel@tonic-gate bad_arg("Invalid name");
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate lognamp = argv [optind];
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate /*
6177c478bd9Sstevel@tonic-gate * if we are adding a new user or modifying an existing user
6187c478bd9Sstevel@tonic-gate * (not the logname), then copy logname into the two data
6197c478bd9Sstevel@tonic-gate * structures
6207c478bd9Sstevel@tonic-gate */
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate if ((A_MASK & optn_mask) ||
6237c478bd9Sstevel@tonic-gate ((M_MASK & optn_mask) && !(optn_mask & L_MASK))) {
6247c478bd9Sstevel@tonic-gate passwd_st.pw_name = argv [optind];
6257c478bd9Sstevel@tonic-gate shadow_st.sp_namp = argv [optind];
6267c478bd9Sstevel@tonic-gate userattr_st.name = argv [optind];
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate /* Put in directory if we are adding and we need a default */
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate if (!(optn_mask & H_MASK) && (optn_mask & A_MASK)) {
6327c478bd9Sstevel@tonic-gate if ((passwd_st.pw_dir = malloc((size_t)DIR_SIZE)) == NULL)
6337c478bd9Sstevel@tonic-gate file_error();
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate *passwd_st.pw_dir = '\0';
6367c478bd9Sstevel@tonic-gate (void) strcat(passwd_st.pw_dir, defdir);
6377c478bd9Sstevel@tonic-gate (void) strcat(passwd_st.pw_dir, lognamp);
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate /* Check the number of password files we are touching */
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate if ((!((M_MASK & optn_mask) && !(L_MASK & optn_mask))) ||
6437c478bd9Sstevel@tonic-gate ((M_MASK & optn_mask) && ((E_MASK & optn_mask) ||
6447c478bd9Sstevel@tonic-gate (F_MASK & optn_mask))))
6457c478bd9Sstevel@tonic-gate info_mask |= BOTH_FILES;
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate if ((D_MASK|L_MASK|UATTR_MASK) & optn_mask)
6487c478bd9Sstevel@tonic-gate info_mask |= UATTR_FILE;
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate /* Open the temporary file(s) with appropriate permission mask */
6517c478bd9Sstevel@tonic-gate /* and the appropriate owner */
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate if (stat(PASSWD, &statbuf) < 0)
6547c478bd9Sstevel@tonic-gate file_error();
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
6577c478bd9Sstevel@tonic-gate if (fd_ptemp == -1) {
6587c478bd9Sstevel@tonic-gate if (errno == EEXIST) {
6597c478bd9Sstevel@tonic-gate if (unlink(PASSTEMP)) {
6607c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
6617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp,
6627c478bd9Sstevel@tonic-gate PASSTEMP);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY,
6657c478bd9Sstevel@tonic-gate statbuf.st_mode);
6667c478bd9Sstevel@tonic-gate if (fd_ptemp == -1) {
6677c478bd9Sstevel@tonic-gate file_error();
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate } else
6717c478bd9Sstevel@tonic-gate file_error();
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate fp_ptemp = fdopen(fd_ptemp, "w");
6747c478bd9Sstevel@tonic-gate if (fp_ptemp == NULL)
6757c478bd9Sstevel@tonic-gate file_error();
6767c478bd9Sstevel@tonic-gate error = fchown(fd_ptemp, statbuf.st_uid, statbuf.st_gid);
6777c478bd9Sstevel@tonic-gate if (error == 0)
6787c478bd9Sstevel@tonic-gate error = fchmod(fd_ptemp, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
6797c478bd9Sstevel@tonic-gate if (error != 0) {
6807c478bd9Sstevel@tonic-gate (void) fclose(fp_ptemp);
6817c478bd9Sstevel@tonic-gate if (unlink(PASSTEMP)) {
6827c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
6837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp,
6847c478bd9Sstevel@tonic-gate PASSTEMP);
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate file_error();
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) {
6907c478bd9Sstevel@tonic-gate if (stat(SHADOW, &statbuf) < 0) {
6917c478bd9Sstevel@tonic-gate rid_tmpf();
6927c478bd9Sstevel@tonic-gate file_error();
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate fd_stemp = open(SHADTEMP, O_CREAT|O_EXCL|O_WRONLY,
6957c478bd9Sstevel@tonic-gate statbuf.st_mode);
6967c478bd9Sstevel@tonic-gate if (fd_stemp == -1) {
6977c478bd9Sstevel@tonic-gate if (errno == EEXIST) {
6987c478bd9Sstevel@tonic-gate if (unlink(SHADTEMP)) {
6997c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
7007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg),
7017c478bd9Sstevel@tonic-gate prognamp, SHADTEMP);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate fd_stemp = open(SHADTEMP,
704*07925104Sgww O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
7057c478bd9Sstevel@tonic-gate if (fd_stemp == -1) {
7067c478bd9Sstevel@tonic-gate rid_tmpf();
7077c478bd9Sstevel@tonic-gate file_error();
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate } else {
7117c478bd9Sstevel@tonic-gate rid_tmpf();
7127c478bd9Sstevel@tonic-gate file_error();
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate fp_stemp = fdopen(fd_stemp, "w");
7167c478bd9Sstevel@tonic-gate if (fp_stemp == NULL) {
7177c478bd9Sstevel@tonic-gate rid_tmpf();
7187c478bd9Sstevel@tonic-gate file_error();
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate error = fchown(fd_stemp, statbuf.st_uid, statbuf.st_gid);
7217c478bd9Sstevel@tonic-gate if (error == 0)
7227c478bd9Sstevel@tonic-gate error = fchmod(fd_stemp, S_IRUSR);
7237c478bd9Sstevel@tonic-gate if (error != 0) {
7247c478bd9Sstevel@tonic-gate rid_tmpf();
7257c478bd9Sstevel@tonic-gate file_error();
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) {
7307c478bd9Sstevel@tonic-gate if (stat(USERATTR_FILENAME, &statbuf) < 0) {
7317c478bd9Sstevel@tonic-gate rid_tmpf();
7327c478bd9Sstevel@tonic-gate file_error();
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate fd_uatemp = open(USERATTR_TEMP, O_CREAT|O_EXCL|O_WRONLY,
7357c478bd9Sstevel@tonic-gate statbuf.st_mode);
7367c478bd9Sstevel@tonic-gate if (fd_uatemp == -1) {
7377c478bd9Sstevel@tonic-gate if (errno == EEXIST) {
7387c478bd9Sstevel@tonic-gate if (unlink(USERATTR_TEMP)) {
7397c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
7407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg),
7417c478bd9Sstevel@tonic-gate prognamp, USERATTR_TEMP);
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate fd_uatemp = open(USERATTR_TEMP,
744*07925104Sgww O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
7457c478bd9Sstevel@tonic-gate if (fd_uatemp == -1) {
7467c478bd9Sstevel@tonic-gate rid_tmpf();
7477c478bd9Sstevel@tonic-gate file_error();
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate } else {
7517c478bd9Sstevel@tonic-gate rid_tmpf();
7527c478bd9Sstevel@tonic-gate file_error();
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate fp_uatemp = fdopen(fd_uatemp, "w");
7567c478bd9Sstevel@tonic-gate if (fp_uatemp == NULL) {
7577c478bd9Sstevel@tonic-gate rid_tmpf();
7587c478bd9Sstevel@tonic-gate file_error();
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate error = fchown(fd_uatemp, statbuf.st_uid, statbuf.st_gid);
7617c478bd9Sstevel@tonic-gate if (error == 0)
7627c478bd9Sstevel@tonic-gate error = fchmod(fd_uatemp,
7637c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
7647c478bd9Sstevel@tonic-gate if (error != 0) {
7657c478bd9Sstevel@tonic-gate rid_tmpf();
7667c478bd9Sstevel@tonic-gate file_error();
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate /* Default uid needed ? */
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate if (!(optn_mask & U_MASK) && (optn_mask & A_MASK)) {
7727c478bd9Sstevel@tonic-gate /* mark it in the information mask */
7737c478bd9Sstevel@tonic-gate info_mask |= NEED_DEF_UID;
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate /* create the head of the uid number list */
7767c478bd9Sstevel@tonic-gate uid_sp = malloc(sizeof (struct uid_blk));
7777c478bd9Sstevel@tonic-gate if (uid_sp == NULL) {
7787c478bd9Sstevel@tonic-gate rid_tmpf();
7797c478bd9Sstevel@tonic-gate file_error();
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate uid_sp->link = NULL;
7837c478bd9Sstevel@tonic-gate uid_sp->low = (UID_MIN -1);
7847c478bd9Sstevel@tonic-gate uid_sp->high = (UID_MIN -1);
7857c478bd9Sstevel@tonic-gate }
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate /*
7887c478bd9Sstevel@tonic-gate * This next section is modified to allow for NIS passwd file
7897c478bd9Sstevel@tonic-gate * conventions. In the case where a password entry was being
7907c478bd9Sstevel@tonic-gate * added to the password file, the original AT&T code read
7917c478bd9Sstevel@tonic-gate * the entire password file in, noted any information needed, and
7927c478bd9Sstevel@tonic-gate * copied the entries to a temporary file. Then the new entry
7937c478bd9Sstevel@tonic-gate * was added to the temporary file, and the temporary file was
7947c478bd9Sstevel@tonic-gate * moved to be the real password file.
7957c478bd9Sstevel@tonic-gate *
7967c478bd9Sstevel@tonic-gate * The problem is, that with NIS compatability, we want to add new
7977c478bd9Sstevel@tonic-gate * entries BEFORE the first NIS-referrant entry, so as not to have
7987c478bd9Sstevel@tonic-gate * any surprises. To accomplish this without extensively modifying
7997c478bd9Sstevel@tonic-gate * the logic of the code below, as soon as a NIS-referrant entry is
8007c478bd9Sstevel@tonic-gate * found we stop copying entries to the TEMP file and instead we
8017c478bd9Sstevel@tonic-gate * remember
8027c478bd9Sstevel@tonic-gate * the first NIS entry and where we found it, scan the rest of the
8037c478bd9Sstevel@tonic-gate * password file without copying entries, then write the new entry, copy
8047c478bd9Sstevel@tonic-gate * the stored password entry, then copy the rest of the password file.
8057c478bd9Sstevel@tonic-gate */
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate error = 0;
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
8117c478bd9Sstevel@tonic-gate rid_tmpf();
8127c478bd9Sstevel@tonic-gate if (errno == ENOENT)
8137c478bd9Sstevel@tonic-gate bad_news();
8147c478bd9Sstevel@tonic-gate else
8157c478bd9Sstevel@tonic-gate file_error();
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate NIS_entry_seen = 0;
8197c478bd9Sstevel@tonic-gate cur_pos = 0;
8207c478bd9Sstevel@tonic-gate /* The while loop for reading PASSWD entries */
8217c478bd9Sstevel@tonic-gate info_mask |= WRITE_P_ENTRY;
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate while (!end_of_file) {
8247c478bd9Sstevel@tonic-gate pw_ptr1p = fgetpwent(pwf);
8257c478bd9Sstevel@tonic-gate if (pw_ptr1p == NULL) {
8267c478bd9Sstevel@tonic-gate if (!feof(pwf)) {
8277c478bd9Sstevel@tonic-gate /* A real error - report it and exit */
8287c478bd9Sstevel@tonic-gate rid_tmpf();
8297c478bd9Sstevel@tonic-gate bad_pasf();
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate else
8327c478bd9Sstevel@tonic-gate break;
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate if (!NIS_entry_seen)
8367c478bd9Sstevel@tonic-gate info_mask |= WRITE_P_ENTRY;
8377c478bd9Sstevel@tonic-gate else
8387c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_P_ENTRY;
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate /*
8417c478bd9Sstevel@tonic-gate * Set up the uid usage blocks to find the first
8427c478bd9Sstevel@tonic-gate * available uid above UID_MIN, if needed
8437c478bd9Sstevel@tonic-gate */
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate if (info_mask & NEED_DEF_UID)
8467c478bd9Sstevel@tonic-gate add_uid(pw_ptr1p->pw_uid);
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate /* Check for unique UID */
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate if (strcmp(lognamp, pw_ptr1p->pw_name) &&
8517c478bd9Sstevel@tonic-gate (pw_ptr1p->pw_uid == passwd_st.pw_uid) &&
8527c478bd9Sstevel@tonic-gate ((optn_mask & U_MASK) && !(optn_mask & O_MASK))) {
8537c478bd9Sstevel@tonic-gate rid_tmpf(); /* get rid of temp files */
8547c478bd9Sstevel@tonic-gate bad_uid();
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate /* Check for unique new logname */
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate if (strcmp(lognamp, pw_ptr1p->pw_name) == 0 &&
8607c478bd9Sstevel@tonic-gate optn_mask & L_MASK &&
8617c478bd9Sstevel@tonic-gate strcmp(pw_ptr1p->pw_name, passwd_st.pw_name) == 0) {
8627c478bd9Sstevel@tonic-gate rid_tmpf();
8637c478bd9Sstevel@tonic-gate #ifdef att
8647c478bd9Sstevel@tonic-gate if (!getspnam(pw_ptr1p->pw_name))
8657c478bd9Sstevel@tonic-gate #else
8667c478bd9Sstevel@tonic-gate if (!local_getspnam(pw_ptr1p->pw_name))
8677c478bd9Sstevel@tonic-gate #endif
8687c478bd9Sstevel@tonic-gate bad_pasf();
8697c478bd9Sstevel@tonic-gate else
8707c478bd9Sstevel@tonic-gate bad_name("logname already exists");
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate if (strcmp(lognamp, pw_ptr1p->pw_name) == 0) {
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate /* no good if we want to add an existing logname */
8767c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
8777c478bd9Sstevel@tonic-gate rid_tmpf();
8787c478bd9Sstevel@tonic-gate #ifdef att
8797c478bd9Sstevel@tonic-gate if (!getspnam(lognamp))
8807c478bd9Sstevel@tonic-gate #else
8817c478bd9Sstevel@tonic-gate if (!local_getspnam(lognamp))
8827c478bd9Sstevel@tonic-gate #endif
8837c478bd9Sstevel@tonic-gate bad_pasf();
8847c478bd9Sstevel@tonic-gate else
8857c478bd9Sstevel@tonic-gate bad_name("name already exists");
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate /* remember we found it */
8897c478bd9Sstevel@tonic-gate info_mask |= FOUND;
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate /* Do not write it out on the fly */
8927c478bd9Sstevel@tonic-gate if (optn_mask & D_MASK)
8937c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_P_ENTRY;
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate if (optn_mask & M_MASK) {
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate #ifdef att
8987c478bd9Sstevel@tonic-gate if (!getspnam(lognamp))
8997c478bd9Sstevel@tonic-gate #else
9007c478bd9Sstevel@tonic-gate if (!local_getspnam(lognamp))
9017c478bd9Sstevel@tonic-gate #endif
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate rid_tmpf();
9047c478bd9Sstevel@tonic-gate bad_pasf();
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate if (optn_mask & L_MASK)
9077c478bd9Sstevel@tonic-gate pw_ptr1p->pw_name = passwd_st.pw_name;
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate if (optn_mask & U_MASK)
9107c478bd9Sstevel@tonic-gate pw_ptr1p->pw_uid = passwd_st.pw_uid;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate if (optn_mask & G_MASK)
9137c478bd9Sstevel@tonic-gate pw_ptr1p->pw_gid = passwd_st.pw_gid;
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate if (optn_mask & C_MASK) {
9167c478bd9Sstevel@tonic-gate pw_ptr1p->pw_comment =
9177c478bd9Sstevel@tonic-gate passwd_st.pw_comment;
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate pw_ptr1p->pw_gecos =
9207c478bd9Sstevel@tonic-gate passwd_st.pw_comment;
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate
9237c478bd9Sstevel@tonic-gate if (optn_mask & H_MASK)
9247c478bd9Sstevel@tonic-gate pw_ptr1p->pw_dir = passwd_st.pw_dir;
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate if (optn_mask & S_MASK)
9277c478bd9Sstevel@tonic-gate pw_ptr1p->pw_shell = passwd_st.pw_shell;
9287c478bd9Sstevel@tonic-gate ck_p_sz(pw_ptr1p); /* check entry size */
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
9337c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) {
9347c478bd9Sstevel@tonic-gate char *p;
9357c478bd9Sstevel@tonic-gate p = strchr("+-", pw_ptr1p->pw_name[0]);
9367c478bd9Sstevel@tonic-gate if (p != NULL) {
9377c478bd9Sstevel@tonic-gate /*
9387c478bd9Sstevel@tonic-gate * Found first NIS entry.
9397c478bd9Sstevel@tonic-gate * so remember it.
9407c478bd9Sstevel@tonic-gate */
9417c478bd9Sstevel@tonic-gate NIS_pos = cur_pos;
9427c478bd9Sstevel@tonic-gate NIS_entry_seen = 1;
9437c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_P_ENTRY;
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate else
9467c478bd9Sstevel@tonic-gate cur_pos = ftell(pwf);
9477c478bd9Sstevel@tonic-gate }
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate if (info_mask & WRITE_P_ENTRY) {
9517c478bd9Sstevel@tonic-gate if (putpwent(pw_ptr1p, fp_ptemp)) {
9527c478bd9Sstevel@tonic-gate rid_tmpf();
9537c478bd9Sstevel@tonic-gate file_error();
9547c478bd9Sstevel@tonic-gate }
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate } /* end-of-while-loop */
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate if (error >= 1) {
9597c478bd9Sstevel@tonic-gate msg = "%s: Bad entry found in /etc/passwd. Run pwconv.\n";
9607c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(msg), prognamp);
9617c478bd9Sstevel@tonic-gate }
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate /* Cannot find the target entry and we are deleting or modifying */
9647c478bd9Sstevel@tonic-gate
9657c478bd9Sstevel@tonic-gate if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) {
9667c478bd9Sstevel@tonic-gate rid_tmpf();
9677c478bd9Sstevel@tonic-gate #ifdef att
9687c478bd9Sstevel@tonic-gate if (getspnam(lognamp) != NULL)
9697c478bd9Sstevel@tonic-gate #else
9707c478bd9Sstevel@tonic-gate if (local_getspnam(lognamp) != NULL)
9717c478bd9Sstevel@tonic-gate #endif
9727c478bd9Sstevel@tonic-gate bad_pasf();
9737c478bd9Sstevel@tonic-gate else
9747c478bd9Sstevel@tonic-gate bad_name("name does not exist");
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate /* First available uid above UID_MIN is ... */
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate if (info_mask & NEED_DEF_UID)
9807c478bd9Sstevel@tonic-gate passwd_st.pw_uid = uid_sp->high + 1;
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate /* Write out the added entry now */
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
9857c478bd9Sstevel@tonic-gate ck_p_sz(&passwd_st); /* Check entry size */
9867c478bd9Sstevel@tonic-gate if (putpwent(&passwd_st, fp_ptemp)) {
9877c478bd9Sstevel@tonic-gate rid_tmpf();
9887c478bd9Sstevel@tonic-gate file_error();
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate /*
9917c478bd9Sstevel@tonic-gate * Now put out the rest of the password file, if needed.
9927c478bd9Sstevel@tonic-gate */
9937c478bd9Sstevel@tonic-gate if (NIS_entry_seen) {
9947c478bd9Sstevel@tonic-gate int n;
9957c478bd9Sstevel@tonic-gate char buf[1024];
9967c478bd9Sstevel@tonic-gate
9977c478bd9Sstevel@tonic-gate if (fseek(pwf, NIS_pos, SEEK_SET) < 0) {
9987c478bd9Sstevel@tonic-gate rid_tmpf();
9997c478bd9Sstevel@tonic-gate file_error();
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate while ((n = fread(buf, sizeof (char), 1024, pwf)) > 0) {
10027c478bd9Sstevel@tonic-gate if (fwrite(buf, sizeof (char), n, fp_ptemp)
10037c478bd9Sstevel@tonic-gate != n) {
10047c478bd9Sstevel@tonic-gate rid_tmpf();
10057c478bd9Sstevel@tonic-gate file_error();
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate }
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate (void) fclose(pwf);
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate /* flush and sync the file before closing it */
10147c478bd9Sstevel@tonic-gate if (fflush(fp_ptemp) != 0 || fsync(fd_ptemp) != 0)
10157c478bd9Sstevel@tonic-gate file_error();
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate /* Now we are done with PASSWD */
10187c478bd9Sstevel@tonic-gate (void) fclose(fp_ptemp);
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate /* Do this if we are touching both password files */
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) {
10247c478bd9Sstevel@tonic-gate info_mask &= ~FOUND; /* Reset FOUND flag */
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate /* The while loop for reading SHADOW entries */
10277c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY;
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate end_of_file = 0;
10307c478bd9Sstevel@tonic-gate errno = 0;
10317c478bd9Sstevel@tonic-gate error = 0;
10327c478bd9Sstevel@tonic-gate
10337c478bd9Sstevel@tonic-gate NIS_entry_seen = 0;
10347c478bd9Sstevel@tonic-gate cur_pos = 0;
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate if ((spf = fopen("/etc/shadow", "r")) == NULL) {
10377c478bd9Sstevel@tonic-gate rid_tmpf();
10387c478bd9Sstevel@tonic-gate file_error();
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate while (!end_of_file) {
10427c478bd9Sstevel@tonic-gate sp_ptr1p = fgetspent(spf);
10437c478bd9Sstevel@tonic-gate if (sp_ptr1p == NULL) {
10447c478bd9Sstevel@tonic-gate if (!feof(spf)) {
10457c478bd9Sstevel@tonic-gate rid_tmpf();
10467c478bd9Sstevel@tonic-gate bad_pasf();
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate else
10497c478bd9Sstevel@tonic-gate break;
10507c478bd9Sstevel@tonic-gate }
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate if (!NIS_entry_seen)
10537c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY;
10547c478bd9Sstevel@tonic-gate else
10557c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY;
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate /*
10587c478bd9Sstevel@tonic-gate * See if the new logname already exist in the
10597c478bd9Sstevel@tonic-gate * shadow passwd file
10607c478bd9Sstevel@tonic-gate */
10617c478bd9Sstevel@tonic-gate if ((optn_mask & M_MASK) &&
10627c478bd9Sstevel@tonic-gate strcmp(lognamp, shadow_st.sp_namp) != 0 &&
10637c478bd9Sstevel@tonic-gate strcmp(sp_ptr1p->sp_namp, shadow_st.sp_namp) == 0) {
10647c478bd9Sstevel@tonic-gate rid_tmpf();
10657c478bd9Sstevel@tonic-gate bad_pasf();
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate
10687c478bd9Sstevel@tonic-gate if (strcmp(lognamp, sp_ptr1p->sp_namp) == 0) {
10697c478bd9Sstevel@tonic-gate info_mask |= FOUND;
10707c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
10717c478bd9Sstevel@tonic-gate /* password file inconsistent */
10727c478bd9Sstevel@tonic-gate rid_tmpf();
10737c478bd9Sstevel@tonic-gate bad_pasf();
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate if (optn_mask & M_MASK) {
10777c478bd9Sstevel@tonic-gate sp_ptr1p->sp_namp = shadow_st.sp_namp;
10787c478bd9Sstevel@tonic-gate if (F_MASK & optn_mask)
10797c478bd9Sstevel@tonic-gate sp_ptr1p->sp_inact =
10807c478bd9Sstevel@tonic-gate shadow_st.sp_inact;
10817c478bd9Sstevel@tonic-gate if (E_MASK & optn_mask)
10827c478bd9Sstevel@tonic-gate sp_ptr1p->sp_expire =
10837c478bd9Sstevel@tonic-gate shadow_st.sp_expire;
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate ck_s_sz(sp_ptr1p);
10867c478bd9Sstevel@tonic-gate }
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate if (optn_mask & D_MASK)
10897c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY;
10907c478bd9Sstevel@tonic-gate }
10917c478bd9Sstevel@tonic-gate
10927c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
10937c478bd9Sstevel@tonic-gate if (!NIS_entry_seen) {
10947c478bd9Sstevel@tonic-gate char *p;
10957c478bd9Sstevel@tonic-gate p = strchr("+-", sp_ptr1p->sp_namp[0]);
10967c478bd9Sstevel@tonic-gate if (p != NULL) {
10977c478bd9Sstevel@tonic-gate /*
10987c478bd9Sstevel@tonic-gate * Found first NIS entry.
10997c478bd9Sstevel@tonic-gate * so remember it.
11007c478bd9Sstevel@tonic-gate */
11017c478bd9Sstevel@tonic-gate NIS_pos = cur_pos;
11027c478bd9Sstevel@tonic-gate NIS_entry_seen = 1;
11037c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY;
11047c478bd9Sstevel@tonic-gate }
11057c478bd9Sstevel@tonic-gate else
11067c478bd9Sstevel@tonic-gate cur_pos = ftell(spf);
11077c478bd9Sstevel@tonic-gate }
11087c478bd9Sstevel@tonic-gate }
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate if (info_mask & WRITE_S_ENTRY) {
11117c478bd9Sstevel@tonic-gate if (putspent(sp_ptr1p, fp_stemp)) {
11127c478bd9Sstevel@tonic-gate rid_tmpf();
11137c478bd9Sstevel@tonic-gate file_error();
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate } /* end-of-while-loop */
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate if (error >= 1) {
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate msg = BAD_ENT_MESSAGE;
11227c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(msg), prognamp);
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate /*
11267c478bd9Sstevel@tonic-gate * If we cannot find the entry and we are deleting or
11277c478bd9Sstevel@tonic-gate * modifying
11287c478bd9Sstevel@tonic-gate */
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) {
11317c478bd9Sstevel@tonic-gate rid_tmpf();
11327c478bd9Sstevel@tonic-gate bad_pasf();
11337c478bd9Sstevel@tonic-gate }
11347c478bd9Sstevel@tonic-gate
11357c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
11367c478bd9Sstevel@tonic-gate ck_s_sz(&shadow_st);
11377c478bd9Sstevel@tonic-gate if (putspent(&shadow_st, fp_stemp)) {
11387c478bd9Sstevel@tonic-gate rid_tmpf();
11397c478bd9Sstevel@tonic-gate file_error();
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate /*
11437c478bd9Sstevel@tonic-gate * Now put out the rest of the shadow file, if needed.
11447c478bd9Sstevel@tonic-gate */
11457c478bd9Sstevel@tonic-gate if (NIS_entry_seen) {
11467c478bd9Sstevel@tonic-gate file_copy(spf, NIS_pos);
11477c478bd9Sstevel@tonic-gate }
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate /* flush and sync the file before closing it */
11517c478bd9Sstevel@tonic-gate if (fflush(fp_stemp) != 0 || fsync(fd_stemp) != 0)
11527c478bd9Sstevel@tonic-gate file_error();
11537c478bd9Sstevel@tonic-gate (void) fclose(fp_stemp);
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate /* Done with SHADOW */
11567c478bd9Sstevel@tonic-gate (void) fclose(spf);
11577c478bd9Sstevel@tonic-gate
11587c478bd9Sstevel@tonic-gate } /* End of if info_mask */
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) {
11617c478bd9Sstevel@tonic-gate info_mask &= ~FOUND; /* Reset FOUND flag */
11627c478bd9Sstevel@tonic-gate
11637c478bd9Sstevel@tonic-gate /* The while loop for reading USER_ATTR entries */
11647c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY;
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate end_of_file = 0;
11677c478bd9Sstevel@tonic-gate errno = 0;
11687c478bd9Sstevel@tonic-gate error = 0;
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate NIS_entry_seen = 0;
11717c478bd9Sstevel@tonic-gate cur_pos = 0;
11727c478bd9Sstevel@tonic-gate
11737c478bd9Sstevel@tonic-gate if ((uaf = fopen(USERATTR_FILENAME, "r")) == NULL) {
11747c478bd9Sstevel@tonic-gate rid_tmpf();
11757c478bd9Sstevel@tonic-gate file_error();
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate while (!end_of_file) {
11797c478bd9Sstevel@tonic-gate ua_ptr1p = fgetuserattr(uaf);
11807c478bd9Sstevel@tonic-gate if (ua_ptr1p == NULL) {
11817c478bd9Sstevel@tonic-gate if (!feof(uaf)) {
11827c478bd9Sstevel@tonic-gate rid_tmpf();
11837c478bd9Sstevel@tonic-gate bad_uattr();
11847c478bd9Sstevel@tonic-gate }
11857c478bd9Sstevel@tonic-gate else
11867c478bd9Sstevel@tonic-gate break;
11877c478bd9Sstevel@tonic-gate }
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate if (ua_ptr1p->name[0] == '#') {
11907c478bd9Sstevel@tonic-gate /*
11917c478bd9Sstevel@tonic-gate * If this is a comment, write it back as it
11927c478bd9Sstevel@tonic-gate * is.
11937c478bd9Sstevel@tonic-gate */
11947c478bd9Sstevel@tonic-gate if (ua_ptr1p->qualifier[0] == '\0' &&
11957c478bd9Sstevel@tonic-gate ua_ptr1p->res1[0] == '\0' &&
11967c478bd9Sstevel@tonic-gate ua_ptr1p->res2[0] == '\0' &&
11977c478bd9Sstevel@tonic-gate (ua_ptr1p->attr == NULL ||
11987c478bd9Sstevel@tonic-gate ua_ptr1p->attr->length == 0))
11997c478bd9Sstevel@tonic-gate (void) fprintf(fp_uatemp, "%s\n",
12007c478bd9Sstevel@tonic-gate ua_ptr1p->name);
12017c478bd9Sstevel@tonic-gate else
12027c478bd9Sstevel@tonic-gate /*
12037c478bd9Sstevel@tonic-gate * This is a commented user_attr entry;
12047c478bd9Sstevel@tonic-gate * reformat it, and write it back.
12057c478bd9Sstevel@tonic-gate */
12067c478bd9Sstevel@tonic-gate putuserattrent(ua_ptr1p, fp_uatemp);
12077c478bd9Sstevel@tonic-gate free_userattr(ua_ptr1p);
12087c478bd9Sstevel@tonic-gate continue;
12097c478bd9Sstevel@tonic-gate }
12107c478bd9Sstevel@tonic-gate
12117c478bd9Sstevel@tonic-gate if (!NIS_entry_seen)
12127c478bd9Sstevel@tonic-gate info_mask |= WRITE_S_ENTRY;
12137c478bd9Sstevel@tonic-gate else
12147c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY;
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate /*
12177c478bd9Sstevel@tonic-gate * See if the new logname already exist in the
12187c478bd9Sstevel@tonic-gate * user_attr file
12197c478bd9Sstevel@tonic-gate */
12207c478bd9Sstevel@tonic-gate if ((optn_mask & M_MASK) &&
12217c478bd9Sstevel@tonic-gate strcmp(lognamp, userattr_st.name) != 0 &&
12227c478bd9Sstevel@tonic-gate strcmp(ua_ptr1p->name, userattr_st.name) == 0) {
12237c478bd9Sstevel@tonic-gate rid_tmpf();
12247c478bd9Sstevel@tonic-gate bad_pasf();
12257c478bd9Sstevel@tonic-gate }
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate if (strcmp(lognamp, ua_ptr1p->name) == 0) {
12287c478bd9Sstevel@tonic-gate info_mask |= FOUND;
12297c478bd9Sstevel@tonic-gate if (optn_mask & A_MASK) {
12307c478bd9Sstevel@tonic-gate /* password file inconsistent */
12317c478bd9Sstevel@tonic-gate rid_tmpf();
12327c478bd9Sstevel@tonic-gate bad_pasf();
12337c478bd9Sstevel@tonic-gate }
12347c478bd9Sstevel@tonic-gate
12357c478bd9Sstevel@tonic-gate if (optn_mask & M_MASK) {
12367c478bd9Sstevel@tonic-gate int j;
12377c478bd9Sstevel@tonic-gate char *value;
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate for (j = 0; j < UA_KEYS; j++) {
12407c478bd9Sstevel@tonic-gate if (ua_opts[j].newvalue != NULL)
12417c478bd9Sstevel@tonic-gate continue;
12427c478bd9Sstevel@tonic-gate value =
12437c478bd9Sstevel@tonic-gate kva_match(ua_ptr1p->attr,
12447c478bd9Sstevel@tonic-gate (char *)ua_opts[j].key);
12457c478bd9Sstevel@tonic-gate if (value == NULL)
12467c478bd9Sstevel@tonic-gate continue;
12477c478bd9Sstevel@tonic-gate assign_attr(&userattr_st,
12487c478bd9Sstevel@tonic-gate ua_opts[j].key,
12497c478bd9Sstevel@tonic-gate value);
12507c478bd9Sstevel@tonic-gate }
12517c478bd9Sstevel@tonic-gate free_userattr(ua_ptr1p);
12527c478bd9Sstevel@tonic-gate ua_ptr1p = &userattr_st;
12537c478bd9Sstevel@tonic-gate }
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate if (optn_mask & D_MASK)
12567c478bd9Sstevel@tonic-gate info_mask &= ~WRITE_S_ENTRY;
12577c478bd9Sstevel@tonic-gate } else if (optn_mask & D_MASK) {
12587c478bd9Sstevel@tonic-gate char *rolelist;
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate rolelist = kva_match(ua_ptr1p->attr,
12617c478bd9Sstevel@tonic-gate USERATTR_ROLES_KW);
12627c478bd9Sstevel@tonic-gate if (rolelist) {
12637c478bd9Sstevel@tonic-gate unassign_role(ua_ptr1p,
12647c478bd9Sstevel@tonic-gate rolelist, lognamp);
12657c478bd9Sstevel@tonic-gate }
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate if (info_mask & WRITE_S_ENTRY) {
12697c478bd9Sstevel@tonic-gate putuserattrent(ua_ptr1p, fp_uatemp);
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate
12727c478bd9Sstevel@tonic-gate if (!(optn_mask & M_MASK))
12737c478bd9Sstevel@tonic-gate free_userattr(ua_ptr1p);
12747c478bd9Sstevel@tonic-gate } /* end-of-while-loop */
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate if (error >= 1) {
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate msg = BAD_ENT_MESSAGE;
12797c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(msg), prognamp);
12807c478bd9Sstevel@tonic-gate }
12817c478bd9Sstevel@tonic-gate
12827c478bd9Sstevel@tonic-gate /*
12837c478bd9Sstevel@tonic-gate * Add entry in user_attr if masks is UATTR_MASK
12847c478bd9Sstevel@tonic-gate * We don't need to do anything for L_MASK if there's
12857c478bd9Sstevel@tonic-gate * no user_attr entry for the user being modified.
12867c478bd9Sstevel@tonic-gate */
12877c478bd9Sstevel@tonic-gate if (!(info_mask & FOUND) && !(L_MASK & optn_mask) &&
12887c478bd9Sstevel@tonic-gate !(D_MASK & optn_mask)) {
12897c478bd9Sstevel@tonic-gate putuserattrent(&userattr_st, fp_uatemp);
12907c478bd9Sstevel@tonic-gate }
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate /* flush and sync the file before closing it */
12937c478bd9Sstevel@tonic-gate if (fflush(fp_uatemp) != 0 || fsync(fd_uatemp) != 0)
12947c478bd9Sstevel@tonic-gate file_error();
12957c478bd9Sstevel@tonic-gate (void) fclose(fp_uatemp);
12967c478bd9Sstevel@tonic-gate
12977c478bd9Sstevel@tonic-gate /* Done with USERATTR */
12987c478bd9Sstevel@tonic-gate (void) fclose(uaf);
12997c478bd9Sstevel@tonic-gate
13007c478bd9Sstevel@tonic-gate } /* End of if info_mask */
13017c478bd9Sstevel@tonic-gate /* ignore all signals */
13027c478bd9Sstevel@tonic-gate
13037c478bd9Sstevel@tonic-gate for (i = 1; i < NSIG; i++)
13047c478bd9Sstevel@tonic-gate (void) sigset(i, SIG_IGN);
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate errno = 0; /* For correcting sigset to SIGKILL */
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate if (unlink(OPASSWD) && access(OPASSWD, 0) == 0)
13097c478bd9Sstevel@tonic-gate file_error();
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate if (link(PASSWD, OPASSWD) == -1)
13127c478bd9Sstevel@tonic-gate file_error();
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate
13157c478bd9Sstevel@tonic-gate if (rename(PASSTEMP, PASSWD) == -1) {
13167c478bd9Sstevel@tonic-gate if (link(OPASSWD, PASSWD))
13177c478bd9Sstevel@tonic-gate bad_news();
13187c478bd9Sstevel@tonic-gate file_error();
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) {
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) {
13257c478bd9Sstevel@tonic-gate if (rec_pwd())
13267c478bd9Sstevel@tonic-gate bad_news();
13277c478bd9Sstevel@tonic-gate else
13287c478bd9Sstevel@tonic-gate file_error();
13297c478bd9Sstevel@tonic-gate }
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate if (link(SHADOW, OSHADOW) == -1) {
13327c478bd9Sstevel@tonic-gate if (rec_pwd())
13337c478bd9Sstevel@tonic-gate bad_news();
13347c478bd9Sstevel@tonic-gate else
13357c478bd9Sstevel@tonic-gate file_error();
13367c478bd9Sstevel@tonic-gate }
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate if (rename(SHADTEMP, SHADOW) == -1) {
13407c478bd9Sstevel@tonic-gate if (rename(OSHADOW, SHADOW) == -1)
13417c478bd9Sstevel@tonic-gate bad_news();
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate if (rec_pwd())
13447c478bd9Sstevel@tonic-gate bad_news();
13457c478bd9Sstevel@tonic-gate else
13467c478bd9Sstevel@tonic-gate file_error();
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate }
13507c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) {
13517c478bd9Sstevel@tonic-gate if (unlink(OUSERATTR_FILENAME) &&
13527c478bd9Sstevel@tonic-gate access(OUSERATTR_FILENAME, 0) == 0) {
13537c478bd9Sstevel@tonic-gate if (rec_pwd())
13547c478bd9Sstevel@tonic-gate bad_news();
13557c478bd9Sstevel@tonic-gate else
13567c478bd9Sstevel@tonic-gate file_error();
13577c478bd9Sstevel@tonic-gate }
13587c478bd9Sstevel@tonic-gate
13597c478bd9Sstevel@tonic-gate if (link(USERATTR_FILENAME, OUSERATTR_FILENAME) == -1) {
13607c478bd9Sstevel@tonic-gate if (rec_pwd())
13617c478bd9Sstevel@tonic-gate bad_news();
13627c478bd9Sstevel@tonic-gate else
13637c478bd9Sstevel@tonic-gate file_error();
13647c478bd9Sstevel@tonic-gate }
13657c478bd9Sstevel@tonic-gate
13667c478bd9Sstevel@tonic-gate
13677c478bd9Sstevel@tonic-gate if (rename(USERATTR_TEMP, USERATTR_FILENAME) == -1) {
13687c478bd9Sstevel@tonic-gate if (rename(OUSERATTR_FILENAME, USERATTR_FILENAME) == -1)
13697c478bd9Sstevel@tonic-gate bad_news();
13707c478bd9Sstevel@tonic-gate
13717c478bd9Sstevel@tonic-gate if (rec_pwd())
13727c478bd9Sstevel@tonic-gate bad_news();
13737c478bd9Sstevel@tonic-gate else
13747c478bd9Sstevel@tonic-gate file_error();
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate }
13787c478bd9Sstevel@tonic-gate
13797c478bd9Sstevel@tonic-gate ulckpwdf();
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate /*
13827c478bd9Sstevel@tonic-gate * Return 0 status, indicating success
13837c478bd9Sstevel@tonic-gate */
138449335bdeSbasabi return (0);
13857c478bd9Sstevel@tonic-gate
13867c478bd9Sstevel@tonic-gate } /* end of main */
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate /* Try to recover the old password file */
13897c478bd9Sstevel@tonic-gate
13907c478bd9Sstevel@tonic-gate int
rec_pwd(void)139149335bdeSbasabi rec_pwd(void)
13927c478bd9Sstevel@tonic-gate {
13937c478bd9Sstevel@tonic-gate if (unlink(PASSWD) || link(OPASSWD, PASSWD))
13947c478bd9Sstevel@tonic-gate return (-1);
13957c478bd9Sstevel@tonic-gate
13967c478bd9Sstevel@tonic-gate return (0);
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate /* combine two uid_blk's */
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate void
uid_bcom(struct uid_blk * uid_p)140249335bdeSbasabi uid_bcom(struct uid_blk *uid_p)
14037c478bd9Sstevel@tonic-gate {
14047c478bd9Sstevel@tonic-gate struct uid_blk *uid_tp;
14057c478bd9Sstevel@tonic-gate
14067c478bd9Sstevel@tonic-gate uid_tp = uid_p->link;
14077c478bd9Sstevel@tonic-gate uid_p->high = uid_tp->high;
14087c478bd9Sstevel@tonic-gate uid_p->link = uid_tp->link;
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate free(uid_tp);
14117c478bd9Sstevel@tonic-gate }
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate /* add a new uid_blk */
14147c478bd9Sstevel@tonic-gate
14157c478bd9Sstevel@tonic-gate void
add_ublk(uid_t num,struct uid_blk * uid_p)141649335bdeSbasabi add_ublk(uid_t num, struct uid_blk *uid_p)
14177c478bd9Sstevel@tonic-gate {
14187c478bd9Sstevel@tonic-gate struct uid_blk *uid_tp;
14197c478bd9Sstevel@tonic-gate
14207c478bd9Sstevel@tonic-gate uid_tp = malloc(sizeof (struct uid_blk));
14217c478bd9Sstevel@tonic-gate if (uid_tp == NULL) {
14227c478bd9Sstevel@tonic-gate rid_tmpf();
14237c478bd9Sstevel@tonic-gate file_error();
14247c478bd9Sstevel@tonic-gate }
14257c478bd9Sstevel@tonic-gate
14267c478bd9Sstevel@tonic-gate uid_tp->high = uid_tp->low = num;
14277c478bd9Sstevel@tonic-gate uid_tp->link = uid_p->link;
14287c478bd9Sstevel@tonic-gate uid_p->link = uid_tp;
14297c478bd9Sstevel@tonic-gate }
14307c478bd9Sstevel@tonic-gate
14317c478bd9Sstevel@tonic-gate /*
14327c478bd9Sstevel@tonic-gate * Here we are using a linked list of uid_blk to keep track of all
14337c478bd9Sstevel@tonic-gate * the used uids. Each uid_blk represents a range of used uid,
14347c478bd9Sstevel@tonic-gate * with low represents the low inclusive end and high represents
14357c478bd9Sstevel@tonic-gate * the high inclusive end. In the beginning, we initialize a linked
14367c478bd9Sstevel@tonic-gate * list of one uid_blk with low = high = (UID_MIN-1). This was
14377c478bd9Sstevel@tonic-gate * done in main().
14387c478bd9Sstevel@tonic-gate * Each time we read in another used uid, we add it onto the linked
14397c478bd9Sstevel@tonic-gate * list by either making a new uid_blk, decrementing the low of
14407c478bd9Sstevel@tonic-gate * an existing uid_blk, incrementing the high of an existing
14417c478bd9Sstevel@tonic-gate * uid_blk, or combining two existing uid_blks. After we finished
14427c478bd9Sstevel@tonic-gate * building this linked list, the first available uid above or
14437c478bd9Sstevel@tonic-gate * equal to UID_MIN is the high of the first uid_blk in the linked
14447c478bd9Sstevel@tonic-gate * list + 1.
14457c478bd9Sstevel@tonic-gate */
14467c478bd9Sstevel@tonic-gate /* add_uid() adds uid to the link list of used uids */
14477c478bd9Sstevel@tonic-gate void
add_uid(uid_t uid)144849335bdeSbasabi add_uid(uid_t uid)
14497c478bd9Sstevel@tonic-gate {
14507c478bd9Sstevel@tonic-gate struct uid_blk *uid_p;
14517c478bd9Sstevel@tonic-gate /* Only keep track of the ones above UID_MIN */
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate if (uid >= UID_MIN) {
14547c478bd9Sstevel@tonic-gate uid_p = uid_sp;
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate while (uid_p != NULL) {
14577c478bd9Sstevel@tonic-gate
14587c478bd9Sstevel@tonic-gate if (uid_p->link != NULL) {
14597c478bd9Sstevel@tonic-gate
14607c478bd9Sstevel@tonic-gate if (uid >= uid_p->link->low)
14617c478bd9Sstevel@tonic-gate uid_p = uid_p->link;
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate else if (uid >= uid_p->low &&
14647c478bd9Sstevel@tonic-gate uid <= uid_p->high) {
14657c478bd9Sstevel@tonic-gate uid_p = NULL;
14667c478bd9Sstevel@tonic-gate }
14677c478bd9Sstevel@tonic-gate
14687c478bd9Sstevel@tonic-gate else if (uid == (uid_p->high+1)) {
14697c478bd9Sstevel@tonic-gate
14707c478bd9Sstevel@tonic-gate if (++uid_p->high ==
14717c478bd9Sstevel@tonic-gate (uid_p->link->low - 1)) {
14727c478bd9Sstevel@tonic-gate uid_bcom(uid_p);
14737c478bd9Sstevel@tonic-gate }
14747c478bd9Sstevel@tonic-gate uid_p = NULL;
14757c478bd9Sstevel@tonic-gate }
14767c478bd9Sstevel@tonic-gate
14777c478bd9Sstevel@tonic-gate else if (uid == (uid_p->link->low - 1)) {
14787c478bd9Sstevel@tonic-gate uid_p->link->low --;
14797c478bd9Sstevel@tonic-gate uid_p = NULL;
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate
14827c478bd9Sstevel@tonic-gate else if (uid < uid_p->link->low) {
14837c478bd9Sstevel@tonic-gate add_ublk(uid, uid_p);
14847c478bd9Sstevel@tonic-gate uid_p = NULL;
14857c478bd9Sstevel@tonic-gate }
14867c478bd9Sstevel@tonic-gate } /* if uid_p->link */
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate else {
14897c478bd9Sstevel@tonic-gate
14907c478bd9Sstevel@tonic-gate if (uid == (uid_p->high + 1)) {
14917c478bd9Sstevel@tonic-gate uid_p->high++;
14927c478bd9Sstevel@tonic-gate uid_p = NULL;
14937c478bd9Sstevel@tonic-gate } else if (uid >= uid_p->low &&
14947c478bd9Sstevel@tonic-gate uid <= uid_p->high) {
14957c478bd9Sstevel@tonic-gate uid_p = NULL;
14967c478bd9Sstevel@tonic-gate } else {
14977c478bd9Sstevel@tonic-gate add_ublk(uid, uid_p);
14987c478bd9Sstevel@tonic-gate uid_p = NULL;
14997c478bd9Sstevel@tonic-gate }
15007c478bd9Sstevel@tonic-gate } /* else */
15017c478bd9Sstevel@tonic-gate } /* while uid_p */
15027c478bd9Sstevel@tonic-gate
15037c478bd9Sstevel@tonic-gate } /* if uid */
15047c478bd9Sstevel@tonic-gate }
15057c478bd9Sstevel@tonic-gate
15067c478bd9Sstevel@tonic-gate void
bad_perm(void)150749335bdeSbasabi bad_perm(void)
15087c478bd9Sstevel@tonic-gate {
15097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: Permission denied\n"), prognamp);
15107c478bd9Sstevel@tonic-gate exit(1);
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gate void
bad_usage(char * sp)151449335bdeSbasabi bad_usage(char *sp)
15157c478bd9Sstevel@tonic-gate {
15167c478bd9Sstevel@tonic-gate if (strlen(sp) != 0)
15177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(sp));
15187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage:\n\
15197c478bd9Sstevel@tonic-gate %s -a [-c comment] [-h homedir] [-u uid [-o]] [-g gid] \n\
15207c478bd9Sstevel@tonic-gate [-s shell] [-f inactive] [-e expire] name\n\
15217c478bd9Sstevel@tonic-gate %s -m -c comment | -h homedir | -u uid [-o] | -g gid |\n\
15227c478bd9Sstevel@tonic-gate -s shell | -f inactive | -e expire | -l logname name\n\
15237c478bd9Sstevel@tonic-gate %s -d name\n"), prognamp, prognamp, prognamp);
15247c478bd9Sstevel@tonic-gate if (info_mask & LOCKED)
15257c478bd9Sstevel@tonic-gate ulckpwdf();
15267c478bd9Sstevel@tonic-gate exit(2);
15277c478bd9Sstevel@tonic-gate }
15287c478bd9Sstevel@tonic-gate
15297c478bd9Sstevel@tonic-gate void
bad_arg(char * s)153049335bdeSbasabi bad_arg(char *s)
15317c478bd9Sstevel@tonic-gate {
15327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s));
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate if (info_mask & LOCKED)
15357c478bd9Sstevel@tonic-gate ulckpwdf();
15367c478bd9Sstevel@tonic-gate exit(3);
15377c478bd9Sstevel@tonic-gate }
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate void
bad_name(char * s)154049335bdeSbasabi bad_name(char *s)
15417c478bd9Sstevel@tonic-gate {
15427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s));
15437c478bd9Sstevel@tonic-gate ulckpwdf();
15447c478bd9Sstevel@tonic-gate exit(9);
15457c478bd9Sstevel@tonic-gate }
15467c478bd9Sstevel@tonic-gate
15477c478bd9Sstevel@tonic-gate void
bad_uid(void)154849335bdeSbasabi bad_uid(void)
15497c478bd9Sstevel@tonic-gate {
15507c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: UID in use\n"), prognamp);
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate ulckpwdf();
15537c478bd9Sstevel@tonic-gate exit(4);
15547c478bd9Sstevel@tonic-gate }
15557c478bd9Sstevel@tonic-gate
15567c478bd9Sstevel@tonic-gate void
bad_pasf(void)155749335bdeSbasabi bad_pasf(void)
15587c478bd9Sstevel@tonic-gate {
15597c478bd9Sstevel@tonic-gate msg = "%s: Inconsistent password files\n";
15607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp);
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate ulckpwdf();
15637c478bd9Sstevel@tonic-gate exit(5);
15647c478bd9Sstevel@tonic-gate }
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate void
bad_uattr(void)156749335bdeSbasabi bad_uattr(void)
15687c478bd9Sstevel@tonic-gate {
15697c478bd9Sstevel@tonic-gate msg = "%s: Bad user_attr database\n";
15707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp);
15717c478bd9Sstevel@tonic-gate
15727c478bd9Sstevel@tonic-gate ulckpwdf();
15737c478bd9Sstevel@tonic-gate exit(5);
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate void
file_error(void)157749335bdeSbasabi file_error(void)
15787c478bd9Sstevel@tonic-gate {
15797c478bd9Sstevel@tonic-gate msg = "%s: Unexpected failure. Password files unchanged\n";
15807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp);
15817c478bd9Sstevel@tonic-gate
15827c478bd9Sstevel@tonic-gate ulckpwdf();
15837c478bd9Sstevel@tonic-gate exit(6);
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate void
bad_news(void)158749335bdeSbasabi bad_news(void)
15887c478bd9Sstevel@tonic-gate {
15897c478bd9Sstevel@tonic-gate msg = "%s: Unexpected failure. Password file(s) missing\n";
15907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp);
15917c478bd9Sstevel@tonic-gate
15927c478bd9Sstevel@tonic-gate ulckpwdf();
15937c478bd9Sstevel@tonic-gate exit(7);
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate
15967c478bd9Sstevel@tonic-gate void
no_lock(void)159749335bdeSbasabi no_lock(void)
15987c478bd9Sstevel@tonic-gate {
15997c478bd9Sstevel@tonic-gate msg = "%s: Password file(s) busy. Try again later\n";
16007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp);
16017c478bd9Sstevel@tonic-gate
16027c478bd9Sstevel@tonic-gate exit(8);
16037c478bd9Sstevel@tonic-gate }
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate /* Check for the size of the whole passwd entry */
16067c478bd9Sstevel@tonic-gate void
ck_p_sz(struct passwd * pwp)160749335bdeSbasabi ck_p_sz(struct passwd *pwp)
16087c478bd9Sstevel@tonic-gate {
16097c478bd9Sstevel@tonic-gate char ctp[128];
16107c478bd9Sstevel@tonic-gate
16117c478bd9Sstevel@tonic-gate /* Ensure that the combined length of the individual */
16127c478bd9Sstevel@tonic-gate /* fields will fit in a passwd entry. The 1 accounts for the */
16137c478bd9Sstevel@tonic-gate /* newline and the 6 accounts for the colons (:'s) */
16147c478bd9Sstevel@tonic-gate if (((int)strlen(pwp->pw_name) + 1 +
16157c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", pwp->pw_uid) +
16167c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", pwp->pw_gid) +
16177c478bd9Sstevel@tonic-gate (int)strlen(pwp->pw_comment) +
16187c478bd9Sstevel@tonic-gate (int)strlen(pwp->pw_dir) +
16191316014bSbasabi (int)strlen(pwp->pw_shell) + 6) > (ENTRY_LENGTH-1)) {
16207c478bd9Sstevel@tonic-gate rid_tmpf();
16217c478bd9Sstevel@tonic-gate bad_arg("New password entry too long");
16227c478bd9Sstevel@tonic-gate }
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gate /* Check for the size of the whole passwd entry */
16267c478bd9Sstevel@tonic-gate void
ck_s_sz(struct spwd * ssp)162749335bdeSbasabi ck_s_sz(struct spwd *ssp)
16287c478bd9Sstevel@tonic-gate {
16297c478bd9Sstevel@tonic-gate char ctp[128];
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate /* Ensure that the combined length of the individual */
16327c478bd9Sstevel@tonic-gate /* fields will fit in a shadow entry. The 1 accounts for the */
16337c478bd9Sstevel@tonic-gate /* newline and the 7 accounts for the colons (:'s) */
16347c478bd9Sstevel@tonic-gate if (((int)strlen(ssp->sp_namp) + 1 +
16357c478bd9Sstevel@tonic-gate (int)strlen(ssp->sp_pwdp) +
16367c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_lstchg) +
16377c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_min) +
16387c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_max) +
16397c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_warn) +
16407c478bd9Sstevel@tonic-gate sprintf(ctp, "%d", ssp->sp_inact) +
16411316014bSbasabi sprintf(ctp, "%d", ssp->sp_expire) + 7) > (ENTRY_LENGTH - 1)) {
16427c478bd9Sstevel@tonic-gate rid_tmpf();
16437c478bd9Sstevel@tonic-gate bad_arg("New password entry too long");
16447c478bd9Sstevel@tonic-gate }
16457c478bd9Sstevel@tonic-gate }
16467c478bd9Sstevel@tonic-gate
16477c478bd9Sstevel@tonic-gate /* Get rid of the temp files */
16487c478bd9Sstevel@tonic-gate void
rid_tmpf(void)164949335bdeSbasabi rid_tmpf(void)
16507c478bd9Sstevel@tonic-gate {
16517c478bd9Sstevel@tonic-gate (void) fclose(fp_ptemp);
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate if (unlink(PASSTEMP)) {
16547c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
16557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp, PASSTEMP);
16567c478bd9Sstevel@tonic-gate }
16577c478bd9Sstevel@tonic-gate
16587c478bd9Sstevel@tonic-gate if (info_mask & BOTH_FILES) {
16597c478bd9Sstevel@tonic-gate (void) fclose(fp_stemp);
16607c478bd9Sstevel@tonic-gate
16617c478bd9Sstevel@tonic-gate if (unlink(SHADTEMP)) {
16627c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
16637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp,
16647c478bd9Sstevel@tonic-gate SHADTEMP);
16657c478bd9Sstevel@tonic-gate }
16667c478bd9Sstevel@tonic-gate }
16677c478bd9Sstevel@tonic-gate
16687c478bd9Sstevel@tonic-gate if (info_mask & UATTR_FILE) {
16697c478bd9Sstevel@tonic-gate (void) fclose(fp_uatemp);
16707c478bd9Sstevel@tonic-gate
16717c478bd9Sstevel@tonic-gate if (unlink(USERATTR_TEMP)) {
16727c478bd9Sstevel@tonic-gate msg = "%s: warning: cannot unlink %s\n";
16737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(msg), prognamp,
16747c478bd9Sstevel@tonic-gate USERATTR_TEMP);
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate }
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate void
file_copy(FILE * spf,long NIS_pos)16807c478bd9Sstevel@tonic-gate file_copy(FILE *spf, long NIS_pos)
16817c478bd9Sstevel@tonic-gate {
16827c478bd9Sstevel@tonic-gate int n;
16837c478bd9Sstevel@tonic-gate char buf[1024];
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate if (fseek(spf, NIS_pos, SEEK_SET) < 0) {
16867c478bd9Sstevel@tonic-gate rid_tmpf();
16877c478bd9Sstevel@tonic-gate file_error();
16887c478bd9Sstevel@tonic-gate }
16897c478bd9Sstevel@tonic-gate while ((n = fread(buf, sizeof (char), 1024, spf)) > 0) {
16907c478bd9Sstevel@tonic-gate if (fwrite(buf, sizeof (char), n, fp_stemp) != n) {
16917c478bd9Sstevel@tonic-gate rid_tmpf();
16927c478bd9Sstevel@tonic-gate file_error();
16937c478bd9Sstevel@tonic-gate }
16947c478bd9Sstevel@tonic-gate }
16957c478bd9Sstevel@tonic-gate }
1696