10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*108Sbasabi * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate 320Sstevel@tonic-gate /* pwconv.c */ 330Sstevel@tonic-gate /* Conversion aid to copy appropriate fields from the */ 340Sstevel@tonic-gate /* password file to the shadow file. */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <pwd.h> 370Sstevel@tonic-gate #include <fcntl.h> 380Sstevel@tonic-gate #include <stdio.h> 390Sstevel@tonic-gate #include <sys/types.h> 400Sstevel@tonic-gate #include <sys/stat.h> 410Sstevel@tonic-gate #include <time.h> 420Sstevel@tonic-gate #include <shadow.h> 430Sstevel@tonic-gate #include <grp.h> 440Sstevel@tonic-gate #include <signal.h> 450Sstevel@tonic-gate #include <errno.h> 460Sstevel@tonic-gate #include <unistd.h> 470Sstevel@tonic-gate #include <stdlib.h> 480Sstevel@tonic-gate #include <locale.h> 490Sstevel@tonic-gate 500Sstevel@tonic-gate #define PRIVILEGED 0 /* priviledged id */ 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* exit code */ 530Sstevel@tonic-gate #define SUCCESS 0 /* succeeded */ 540Sstevel@tonic-gate #define NOPERM 1 /* No permission */ 550Sstevel@tonic-gate #define BADSYN 2 /* Incorrect syntax */ 560Sstevel@tonic-gate #define FMERR 3 /* File manipulation error */ 570Sstevel@tonic-gate #define FATAL 4 /* Old file can not be recover */ 580Sstevel@tonic-gate #define FBUSY 5 /* Lock file busy */ 590Sstevel@tonic-gate #define BADSHW 6 /* Bad entry in shadow file */ 600Sstevel@tonic-gate 610Sstevel@tonic-gate #define DELPTMP() (void) unlink(PASSTEMP) 620Sstevel@tonic-gate #define DELSHWTMP() (void) unlink(SHADTEMP) 630Sstevel@tonic-gate 640Sstevel@tonic-gate char pwdflr[] = "x"; /* password filler */ 650Sstevel@tonic-gate char *prognamp; 66*108Sbasabi void f_err(void), f_miss(void), f_bdshw(void); 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * getspnan routine that ONLY looks at the local shadow file 700Sstevel@tonic-gate */ 710Sstevel@tonic-gate struct spwd * 72*108Sbasabi local_getspnam(char *name) 730Sstevel@tonic-gate { 740Sstevel@tonic-gate FILE *shadf; 750Sstevel@tonic-gate struct spwd * sp; 760Sstevel@tonic-gate 770Sstevel@tonic-gate 780Sstevel@tonic-gate if ((shadf = fopen("/etc/shadow", "r")) == NULL) 790Sstevel@tonic-gate return (NULL); 800Sstevel@tonic-gate 810Sstevel@tonic-gate while ((sp = fgetspent(shadf)) != NULL) { 820Sstevel@tonic-gate if (strcmp(sp->sp_namp, name) == 0) 830Sstevel@tonic-gate break; 840Sstevel@tonic-gate } 850Sstevel@tonic-gate 860Sstevel@tonic-gate fclose(shadf); 870Sstevel@tonic-gate 880Sstevel@tonic-gate return (sp); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate 91*108Sbasabi int 92*108Sbasabi main(int argc, char **argv) 930Sstevel@tonic-gate { 940Sstevel@tonic-gate extern int errno; 95*108Sbasabi void no_recover(void), no_convert(void); 960Sstevel@tonic-gate struct passwd *pwdp; 970Sstevel@tonic-gate struct spwd *sp, sp_pwd; /* default entry */ 980Sstevel@tonic-gate struct stat buf; 990Sstevel@tonic-gate FILE *tp_fp, *tsp_fp; 100*108Sbasabi time_t when, minweeks, maxweeks; 1010Sstevel@tonic-gate int file_exist = 1; 1020Sstevel@tonic-gate int end_of_file = 0; 1030Sstevel@tonic-gate mode_t mode; 1040Sstevel@tonic-gate int pwerr = 0; 1050Sstevel@tonic-gate ushort i; 1060Sstevel@tonic-gate gid_t pwd_gid, sp_gid; 1070Sstevel@tonic-gate uid_t pwd_uid, sp_uid; 1080Sstevel@tonic-gate FILE *pwf; 1090Sstevel@tonic-gate int black_magic = 0; 1100Sstevel@tonic-gate int count; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 1150Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1160Sstevel@tonic-gate #endif 1170Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate prognamp = argv[0]; 1200Sstevel@tonic-gate /* only PRIVILEGED can execute this command */ 1210Sstevel@tonic-gate if (getuid() != PRIVILEGED) { 1220Sstevel@tonic-gate fprintf(stderr, gettext("%s: Permission denied.\n"), prognamp); 1230Sstevel@tonic-gate exit(NOPERM); 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* No argument can be passed to the command */ 1270Sstevel@tonic-gate if (argc > 1) { 1280Sstevel@tonic-gate (void) fprintf(stderr, 1290Sstevel@tonic-gate gettext("%s: Invalid command syntax.\n"), 1300Sstevel@tonic-gate prognamp); 1310Sstevel@tonic-gate fprintf(stderr, gettext("Usage: pwconv\n")); 1320Sstevel@tonic-gate exit(BADSYN); 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* lock file so that only one process can read or write at a time */ 1360Sstevel@tonic-gate if (lckpwdf() < 0) { 1370Sstevel@tonic-gate (void) fprintf(stderr, 1380Sstevel@tonic-gate gettext("%s: Password file(s) busy. Try again later.\n"), 1390Sstevel@tonic-gate prognamp); 1400Sstevel@tonic-gate exit(FBUSY); 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* All signals will be ignored during the execution of pwconv */ 1440Sstevel@tonic-gate for (i = 1; i < NSIG; i++) 1450Sstevel@tonic-gate sigset(i, SIG_IGN); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* reset errno to avoid side effects of a failed */ 1480Sstevel@tonic-gate /* sigset (e.g., SIGKILL) */ 1490Sstevel@tonic-gate errno = 0; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate /* check the file status of the password file */ 1520Sstevel@tonic-gate /* get the gid of the password file */ 1530Sstevel@tonic-gate if (stat(PASSWD, &buf) < 0) { 1540Sstevel@tonic-gate (void) f_miss(); 1550Sstevel@tonic-gate exit(FATAL); 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate pwd_gid = buf.st_gid; 1580Sstevel@tonic-gate pwd_uid = buf.st_uid; 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* mode for the password file should be read-only or less */ 1610Sstevel@tonic-gate umask(S_IAMB & ~(buf.st_mode & (S_IRUSR|S_IRGRP|S_IROTH))); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate /* open temporary password file */ 1640Sstevel@tonic-gate if ((tp_fp = fopen(PASSTEMP, "w")) == NULL) { 1650Sstevel@tonic-gate (void) f_err(); 1660Sstevel@tonic-gate exit(FMERR); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate if (chown(PASSTEMP, pwd_uid, pwd_gid) < 0) { 1700Sstevel@tonic-gate DELPTMP(); 1710Sstevel@tonic-gate (void) f_err(); 1720Sstevel@tonic-gate exit(FMERR); 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate /* default mode mask of the shadow file */ 1750Sstevel@tonic-gate mode = S_IAMB & ~(S_IRUSR); 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate /* check the existence of shadow file */ 1780Sstevel@tonic-gate /* if the shadow file exists, get mode mask and group id of the file */ 1790Sstevel@tonic-gate /* if file does not exist, the default group name will be the group */ 1800Sstevel@tonic-gate /* name of the password file. */ 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate if (access(SHADOW, F_OK) == 0) { 1830Sstevel@tonic-gate if (stat(SHADOW, &buf) == 0) { 1840Sstevel@tonic-gate mode = S_IAMB & ~(buf.st_mode & S_IRUSR); 1850Sstevel@tonic-gate sp_gid = buf.st_gid; 1860Sstevel@tonic-gate sp_uid = buf.st_uid; 1870Sstevel@tonic-gate } else { 1880Sstevel@tonic-gate DELPTMP(); 1890Sstevel@tonic-gate (void) f_err(); 1900Sstevel@tonic-gate exit(FMERR); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate } else { 1930Sstevel@tonic-gate sp_gid = pwd_gid; 1940Sstevel@tonic-gate sp_uid = pwd_uid; 1950Sstevel@tonic-gate file_exist = 0; 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * get the mode of shadow password file -- mode of the file should 1990Sstevel@tonic-gate * be read-only for user or less. 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate umask(mode); 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate /* open temporary shadow file */ 2040Sstevel@tonic-gate if ((tsp_fp = fopen(SHADTEMP, "w")) == NULL) { 2050Sstevel@tonic-gate DELPTMP(); 2060Sstevel@tonic-gate (void) f_err(); 2070Sstevel@tonic-gate exit(FMERR); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate /* change the group of the temporary shadow password file */ 2110Sstevel@tonic-gate if (chown(SHADTEMP, sp_uid, sp_gid) < 0) { 2120Sstevel@tonic-gate (void) no_convert(); 2130Sstevel@tonic-gate exit(FMERR); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate /* Reads the password file. */ 2170Sstevel@tonic-gate /* If the shadow password file not exists, or */ 2180Sstevel@tonic-gate /* if an entry doesn't have a corresponding entry in */ 2190Sstevel@tonic-gate /* the shadow file, entries/entry will be created. */ 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate if ((pwf = fopen("/etc/passwd", "r")) == NULL) { 2220Sstevel@tonic-gate no_recover(); 2230Sstevel@tonic-gate exit(FATAL); 2240Sstevel@tonic-gate } 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate count = 0; 2270Sstevel@tonic-gate while (!end_of_file) { 2280Sstevel@tonic-gate count++; 2290Sstevel@tonic-gate if ((pwdp = fgetpwent(pwf)) != NULL) { 2300Sstevel@tonic-gate if (!file_exist || 2310Sstevel@tonic-gate (sp = local_getspnam(pwdp->pw_name)) == NULL) { 2320Sstevel@tonic-gate if (errno == EINVAL) { 2330Sstevel@tonic-gate /* Bad entry in shadow exit */ 2340Sstevel@tonic-gate DELSHWTMP(); 2350Sstevel@tonic-gate DELPTMP(); 2360Sstevel@tonic-gate (void) f_bdshw(); 2370Sstevel@tonic-gate exit(BADSHW); 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate sp = &sp_pwd; 2400Sstevel@tonic-gate sp->sp_namp = pwdp->pw_name; 2410Sstevel@tonic-gate if (!pwdp->pw_passwd || 2420Sstevel@tonic-gate (pwdp->pw_passwd && 2430Sstevel@tonic-gate *pwdp->pw_passwd == NULL)) { 2440Sstevel@tonic-gate (void) fprintf(stderr, 2450Sstevel@tonic-gate gettext("%s: WARNING user %s has no password\n"), 2460Sstevel@tonic-gate prognamp, sp->sp_namp); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * copy the password field in the password 2500Sstevel@tonic-gate * file to the shadow file. 2510Sstevel@tonic-gate * replace the password field with an 'x'. 2520Sstevel@tonic-gate */ 2530Sstevel@tonic-gate sp->sp_pwdp = pwdp->pw_passwd; 2540Sstevel@tonic-gate pwdp->pw_passwd = pwdflr; 2550Sstevel@tonic-gate /* 2560Sstevel@tonic-gate * if aging, split the aging info 2570Sstevel@tonic-gate * into age, max and min 2580Sstevel@tonic-gate * convert aging info from weeks to days 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate if (pwdp->pw_age && *pwdp->pw_age != NULL) { 2610Sstevel@tonic-gate when = (long) a64l(pwdp->pw_age); 2620Sstevel@tonic-gate maxweeks = when & 077; 2630Sstevel@tonic-gate minweeks = (when >> 6) & 077; 2640Sstevel@tonic-gate when >>= 12; 2650Sstevel@tonic-gate sp->sp_lstchg = when * 7; 2660Sstevel@tonic-gate sp->sp_min = minweeks * 7; 2670Sstevel@tonic-gate sp->sp_max = maxweeks * 7; 2680Sstevel@tonic-gate sp->sp_warn = -1; 2690Sstevel@tonic-gate sp->sp_inact = -1; 2700Sstevel@tonic-gate sp->sp_expire = -1; 2710Sstevel@tonic-gate sp->sp_flag = 0; 2720Sstevel@tonic-gate pwdp->pw_age = ""; /* do we care? */ 2730Sstevel@tonic-gate } else { 2740Sstevel@tonic-gate /* 2750Sstevel@tonic-gate * if !aging, last_changed will be the day the 2760Sstevel@tonic-gate * conversion is done, min and max fields will 2770Sstevel@tonic-gate * be null - use timezone to get local time 2780Sstevel@tonic-gate */ 2790Sstevel@tonic-gate sp->sp_lstchg = DAY_NOW; 2800Sstevel@tonic-gate sp->sp_min = -1; 2810Sstevel@tonic-gate sp->sp_max = -1; 2820Sstevel@tonic-gate sp->sp_warn = -1; 2830Sstevel@tonic-gate sp->sp_inact = -1; 2840Sstevel@tonic-gate sp->sp_expire = -1; 2850Sstevel@tonic-gate sp->sp_flag = 0; 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate } else { 2880Sstevel@tonic-gate /* 2890Sstevel@tonic-gate * if the passwd field has a string other than 'x', 2900Sstevel@tonic-gate * the entry will be written into the shadow file 2910Sstevel@tonic-gate * and the character 'x' is re-written as the passwd 2920Sstevel@tonic-gate * if !aging, last_changed as above 2930Sstevel@tonic-gate */ 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate /* 2960Sstevel@tonic-gate * with NIS, only warn about password missing if entry 2970Sstevel@tonic-gate * is not a NIS-lookup entry ("+" or "-") 2980Sstevel@tonic-gate * black_magic from getpwnam_r.c 2990Sstevel@tonic-gate */ 3000Sstevel@tonic-gate black_magic = (*pwdp->pw_name == '+' || 3010Sstevel@tonic-gate *pwdp->pw_name == '-'); 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * moan about absence of non "+/-" passwd 3040Sstevel@tonic-gate * we could do more, but what? 3050Sstevel@tonic-gate */ 3060Sstevel@tonic-gate if ((!pwdp->pw_passwd || 3070Sstevel@tonic-gate (pwdp->pw_passwd && *pwdp->pw_passwd == NULL)) && 3080Sstevel@tonic-gate !black_magic) { 3090Sstevel@tonic-gate (void) fprintf(stderr, 3100Sstevel@tonic-gate gettext("%s: WARNING user %s has no password\n"), 3110Sstevel@tonic-gate prognamp, sp->sp_namp); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate if (pwdp->pw_passwd && *pwdp->pw_passwd) { 3140Sstevel@tonic-gate if (strcmp(pwdp->pw_passwd, pwdflr)) { 3150Sstevel@tonic-gate sp->sp_pwdp = pwdp->pw_passwd; 3160Sstevel@tonic-gate pwdp->pw_passwd = pwdflr; 3170Sstevel@tonic-gate if (!pwdp->pw_age || 3180Sstevel@tonic-gate (pwdp->pw_age && 3190Sstevel@tonic-gate *pwdp->pw_age == NULL)) { 3200Sstevel@tonic-gate sp->sp_lstchg = DAY_NOW; 3210Sstevel@tonic-gate sp->sp_min = -1; 3220Sstevel@tonic-gate sp->sp_max = -1; 3230Sstevel@tonic-gate sp->sp_warn = -1; 3240Sstevel@tonic-gate sp->sp_inact = -1; 3250Sstevel@tonic-gate sp->sp_expire = -1; 3260Sstevel@tonic-gate sp->sp_flag = 0; 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate } else { 3300Sstevel@tonic-gate /* 3310Sstevel@tonic-gate * black_magic needs a non-null passwd 3320Sstevel@tonic-gate * and pwdflr seem appropriate here 3330Sstevel@tonic-gate * clear garbage if any 3340Sstevel@tonic-gate */ 3350Sstevel@tonic-gate sp->sp_pwdp = ""; 3360Sstevel@tonic-gate pwdp->pw_passwd = pwdflr; 3370Sstevel@tonic-gate sp->sp_lstchg = sp->sp_min = sp->sp_max = -1; 3380Sstevel@tonic-gate sp->sp_warn = sp->sp_inact = sp->sp_expire = -1; 3390Sstevel@tonic-gate sp->sp_flag = 0; 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate /* 3420Sstevel@tonic-gate * if aging, split the aging info 3430Sstevel@tonic-gate * into age, max and min 3440Sstevel@tonic-gate * convert aging info from weeks to days 3450Sstevel@tonic-gate */ 3460Sstevel@tonic-gate if (pwdp->pw_age && *pwdp->pw_age != NULL) { 3470Sstevel@tonic-gate when = (long) a64l(pwdp->pw_age); 3480Sstevel@tonic-gate maxweeks = when & 077; 3490Sstevel@tonic-gate minweeks = (when >> 6) & 077; 3500Sstevel@tonic-gate when >>= 12; 3510Sstevel@tonic-gate sp->sp_lstchg = when * 7; 3520Sstevel@tonic-gate sp->sp_min = minweeks * 7; 3530Sstevel@tonic-gate sp->sp_max = maxweeks * 7; 3540Sstevel@tonic-gate sp->sp_warn = -1; 3550Sstevel@tonic-gate sp->sp_inact = -1; 3560Sstevel@tonic-gate sp->sp_expire = -1; 3570Sstevel@tonic-gate sp->sp_flag = 0; 3580Sstevel@tonic-gate pwdp->pw_age = ""; /* do we care? */ 3590Sstevel@tonic-gate } 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* write an entry to temporary password file */ 3630Sstevel@tonic-gate if ((putpwent(pwdp, tp_fp)) != 0) { 3640Sstevel@tonic-gate (void) no_convert(); 3650Sstevel@tonic-gate exit(FMERR); 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* write an entry to temporary shadow password file */ 3690Sstevel@tonic-gate if (putspent(sp, tsp_fp) != 0) { 3700Sstevel@tonic-gate (void) no_convert(); 3710Sstevel@tonic-gate exit(FMERR); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate } else { 3740Sstevel@tonic-gate if (feof(pwf)) { 3750Sstevel@tonic-gate end_of_file = 1; 3760Sstevel@tonic-gate } else { 3770Sstevel@tonic-gate errno = 0; 3780Sstevel@tonic-gate pwerr = 1; 3790Sstevel@tonic-gate (void) fprintf(stderr, 3800Sstevel@tonic-gate gettext("%s: ERROR: bad entry or blank line at line %d in /etc/passwd\n"), 3810Sstevel@tonic-gate prognamp, count); 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate } /* end of while */ 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate (void) fclose(pwf); 3870Sstevel@tonic-gate (void) fclose(tsp_fp); 3880Sstevel@tonic-gate (void) fclose(tp_fp); 3890Sstevel@tonic-gate if (pwerr) { 3900Sstevel@tonic-gate (void) no_convert(); 3910Sstevel@tonic-gate exit(FMERR); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate /* delete old password file if it exists */ 3950Sstevel@tonic-gate if (unlink(OPASSWD) && (access(OPASSWD, F_OK) == 0)) { 3960Sstevel@tonic-gate (void) no_convert(); 3970Sstevel@tonic-gate exit(FMERR); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* rename the password file to old password file */ 4010Sstevel@tonic-gate if (rename(PASSWD, OPASSWD) == -1) { 4020Sstevel@tonic-gate (void) no_convert(); 4030Sstevel@tonic-gate exit(FMERR); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate /* rename temporary password file to password file */ 4070Sstevel@tonic-gate if (rename(PASSTEMP, PASSWD) == -1) { 4080Sstevel@tonic-gate /* link old password file to password file */ 4090Sstevel@tonic-gate if (link(OPASSWD, PASSWD) < 0) { 4100Sstevel@tonic-gate (void) no_recover(); 4110Sstevel@tonic-gate exit(FATAL); 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate (void) no_convert(); 4140Sstevel@tonic-gate exit(FMERR); 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate /* delete old shadow password file if it exists */ 4180Sstevel@tonic-gate if (unlink(OSHADOW) && (access(OSHADOW, R_OK) == 0)) { 4190Sstevel@tonic-gate /* link old password file to password file */ 4200Sstevel@tonic-gate if (unlink(PASSWD) || link(OPASSWD, PASSWD)) { 4210Sstevel@tonic-gate (void) no_recover(); 4220Sstevel@tonic-gate exit(FATAL); 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate (void) no_convert(); 4250Sstevel@tonic-gate exit(FMERR); 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate /* link shadow password file to old shadow password file */ 4290Sstevel@tonic-gate if (file_exist && rename(SHADOW, OSHADOW)) { 4300Sstevel@tonic-gate /* link old password file to password file */ 4310Sstevel@tonic-gate if (unlink(PASSWD) || link(OPASSWD, PASSWD)) { 4320Sstevel@tonic-gate (void) no_recover(); 4330Sstevel@tonic-gate exit(FATAL); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate (void) no_convert(); 4360Sstevel@tonic-gate exit(FMERR); 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate /* link temporary shadow password file to shadow password file */ 4410Sstevel@tonic-gate if (rename(SHADTEMP, SHADOW) == -1) { 4420Sstevel@tonic-gate /* link old shadow password file to shadow password file */ 4430Sstevel@tonic-gate if (file_exist && (link(OSHADOW, SHADOW))) { 4440Sstevel@tonic-gate (void) no_recover(); 4450Sstevel@tonic-gate exit(FATAL); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate if (unlink(PASSWD) || link(OPASSWD, PASSWD)) { 4480Sstevel@tonic-gate (void) no_recover(); 4490Sstevel@tonic-gate exit(FATAL); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate (void) no_convert(); 4520Sstevel@tonic-gate exit(FMERR); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate /* Change old password file to read only by owner */ 4560Sstevel@tonic-gate /* If chmod fails, delete the old password file so that */ 4570Sstevel@tonic-gate /* the password fields can not be read by others */ 4580Sstevel@tonic-gate if (chmod(OPASSWD, S_IRUSR) < 0) 4590Sstevel@tonic-gate (void) unlink(OPASSWD); 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate (void) ulckpwdf(); 462*108Sbasabi return (0); 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate void 466*108Sbasabi no_recover(void) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate DELPTMP(); 4690Sstevel@tonic-gate DELSHWTMP(); 4700Sstevel@tonic-gate (void) f_miss(); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate void 474*108Sbasabi no_convert(void) 4750Sstevel@tonic-gate { 4760Sstevel@tonic-gate DELPTMP(); 4770Sstevel@tonic-gate DELSHWTMP(); 4780Sstevel@tonic-gate (void) f_err(); 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate void 482*108Sbasabi f_err(void) 4830Sstevel@tonic-gate { 4840Sstevel@tonic-gate fprintf(stderr, 4850Sstevel@tonic-gate gettext("%s: Unexpected failure. Conversion not done.\n"), 4860Sstevel@tonic-gate prognamp); 4870Sstevel@tonic-gate (void) ulckpwdf(); 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate void 491*108Sbasabi f_miss(void) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate fprintf(stderr, 4940Sstevel@tonic-gate gettext("%s: Unexpected failure. Password file(s) missing.\n"), 4950Sstevel@tonic-gate prognamp); 4960Sstevel@tonic-gate (void) ulckpwdf(); 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate void 500*108Sbasabi f_bdshw(void) 5010Sstevel@tonic-gate { 5020Sstevel@tonic-gate fprintf(stderr, 5030Sstevel@tonic-gate gettext("%s: Bad entry in /etc/shadow. Conversion not done.\n"), 5040Sstevel@tonic-gate prognamp); 5050Sstevel@tonic-gate (void) ulckpwdf(); 5060Sstevel@tonic-gate } 507