static char sccsid
[] = "@(#)passwd.c 4.6 (Berkeley) %G%";
* Enter a password in the password file.
* This program should be suid with an owner
* with write permission on /etc/passwd.
char temp
[] = "/etc/ptmp";
char passwd
[] = "/etc/passwd";
if ((uname
= getlogin()) == NULL
) {
printf ("Usage: passwd user\n");
printf("Changing password for %s\n", uname
);
if (pwd
== NULL
|| (u
!= 0 && u
!= pwd
->pw_uid
)) {
printf("Permission denied.\n");
if (pwd
->pw_passwd
[0] && u
!= 0) {
strcpy(pwbuf
, getpass("Old password:"));
pw
= crypt(pwbuf
, pwd
->pw_passwd
);
if (strcmp(pw
, pwd
->pw_passwd
) != 0) {
strcpy(pwbuf
, getpass("New password:"));
printf("Password unchanged.\n");
* Insure password is of reasonable length and
* composition. If we really wanted to make things
* sticky, we could check the dictionary for common
* words, but then things would really be slow.
if (c
>= 'a' && c
<= 'z')
else if (c
>= 'A' && c
<= 'Z')
else if (c
>= '0' && c
<= '9')
if (flags
>= 7 && pwlen
>= 4)
if ((flags
== 2 || flags
== 4) && pwlen
>= 6)
if ((flags
== 3 || flags
== 5 || flags
== 6) && pwlen
>= 5)
printf("Please use %s.\n", flags
== 1 ?
"at least one non-numeric character" :
if (strcmp(pwbuf
, getpass("Retype new password:")) != 0) {
printf("Mismatch - password unchanged.\n");
saltc
[1] = (salt
>>6) & 077;
for (i
= 0; i
< 2; i
++) {
pw
= crypt(pwbuf
, saltc
);
signal(SIGQUIT
, SIG_IGN
);
fd
= open(temp
, O_WRONLY
|O_CREAT
|O_EXCL
, 0644);
fprintf(stderr
, "passwd: ");
fprintf(stderr
, "password file busy - try again.\n");
signal(SIGTSTP
, SIG_IGN
);
if ((tf
= fdopen(fd
, "w")) == NULL
) {
fprintf(stderr
, "passwd: fdopen failed?\n");
if ((dp
= ndbmopen(passwd
, O_RDWR
, 0644)) == NULL
) {
fprintf(stderr
, "Warning: dbminit failed: ");
} else if (flock(dp
->db_dirf
, LOCK_EX
) < 0) {
perror("Warning: lock failed");
* Copy passwd to temp, replacing matching lines
while ((pwd
= getpwent()) != NULL
) {
if (strcmp(pwd
->pw_name
, uname
) == 0) {
if (u
&& u
!= pwd
->pw_uid
) {
fprintf(stderr
, "passwd: permission denied.\n");
if (pwd
->pw_gecos
[0] == '*')
fprintf(tf
,"%s:%s:%d:%d:%s:%s:%s\n",
if (rename(temp
, passwd
) < 0) {
fprintf(stderr
, "passwd: "), perror("rename");
* Replace the password entry in the dbm data base with pwd.
#define COMPACT(e) tp = pwd->pw_/**/e; while (*cp++ = *tp++);
*(int *)cp
= pwd
->pw_uid
; cp
+= sizeof (int);
*(int *)cp
= pwd
->pw_gid
; cp
+= sizeof (int);
*(int *)cp
= pwd
->pw_quota
; cp
+= sizeof (int);
content
.dsize
= cp
- buf
;
key
.dsize
= strlen(pwd
->pw_name
);
dbmstore(dp
, key
, content
, DB_REPLACE
);
key
.dptr
= (char *)&pwd
->pw_uid
;
key
.dsize
= sizeof (int);
dbmstore(dp
, key
, content
, DB_REPLACE
);