Research V7 development
[unix-history] / usr / src / cmd / passwd.c
/*
* enter a password in the password file
* this program should be suid with owner
* with an owner with write permission on /etc/passwd
*/
#include <stdio.h>
#include <signal.h>
#include <pwd.h>
char passwd[] = "/etc/passwd";
char temp[] = "/etc/ptmp";
struct passwd *pwd;
struct passwd *getpwent();
int endpwent();
char *strcpy();
char *crypt();
char *getpass();
char *getlogin();
char *pw;
char pwbuf[10];
char buf[512];
main(argc, argv)
char *argv[];
{
char *p;
int i;
char saltc[2];
long salt;
int u,fi,fo;
int insist;
int ok, flags;
int c;
int pwlen;
FILE *tf;
char *uname;
insist = 0;
if(argc < 2) {
if ((uname = getlogin()) == NULL) {
printf ("Usage: passwd user\n");
goto bex;
} else {
printf("Changing password for %s\n", uname);
}
} else {
uname = argv[1];
}
while(((pwd=getpwent()) != NULL)&&(strcmp(pwd->pw_name,uname)!=0));
u = getuid();
if((pwd==NULL) || (u!=0 && u != pwd->pw_uid))
{
printf("Permission denied.\n");
goto bex;
}
endpwent();
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) {
printf("Sorry.\n");
goto bex;
}
}
tryagn:
strcpy(pwbuf, getpass("New password:"));
pwlen = strlen(pwbuf);
if (pwlen == 0) {
printf("Password unchanged.\n");
goto bex;
}
ok = 0;
flags = 0;
p = pwbuf;
while(c = *p++){
if(c>='a' && c<='z') flags |= 2;
else if(c>='A' && c<='Z') flags |= 4;
else if(c>='0' && c<='9') flags |= 1;
else flags |= 8;
}
if(flags >=7 && pwlen>= 4) ok = 1;
if(((flags==2)||(flags==4)) && pwlen>=6) ok = 1;
if(((flags==3)||(flags==5)||(flags==6))&&pwlen>=5) ok = 1;
if((ok==0) && (insist<2)){
if(flags==1)
printf("Please use at least one non-numeric character.\n");
else
printf("Please use a longer password.\n");
insist++;
goto tryagn;
}
if (strcmp(pwbuf,getpass("Retype new password:")) != 0) {
printf ("Mismatch - password unchanged.\n");
goto bex;
}
time(&salt);
salt += getpid();
saltc[0] = salt & 077;
saltc[1] = (salt>>6) & 077;
for(i=0;i<2;i++){
c = saltc[i] + '.';
if(c>'9') c += 7;
if(c>'Z') c += 6;
saltc[i] = c;
}
pw = crypt(pwbuf, saltc);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if(access(temp, 0) >= 0) {
printf("Temporary file busy -- try again\n");
goto bex;
}
close(creat(temp,0600));
if((tf=fopen(temp,"w")) == NULL) {
printf("Cannot create temporary file\n");
goto bex;
}
/*
* copy passwd to temp, replacing matching lines
* with new password.
*/
while((pwd=getpwent()) != NULL) {
if(strcmp(pwd->pw_name,uname) == 0) {
u = getuid();
if(u != 0 && u != pwd->pw_uid) {
printf("Permission denied.\n");
goto out;
}
pwd->pw_passwd = pw;
}
fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
pwd->pw_name,
pwd->pw_passwd,
pwd->pw_uid,
pwd->pw_gid,
pwd->pw_gecos,
pwd->pw_dir,
pwd->pw_shell);
}
endpwent();
fclose(tf);
/*
* copy temp back to passwd file
*/
if((fi=open(temp,0)) < 0) {
printf("Temp file disappeared!\n");
goto out;
}
if((fo=creat(passwd, 0644)) < 0) {
printf("Cannot recreat passwd file.\n");
goto out;
}
while((u=read(fi,buf,sizeof(buf))) > 0) write(fo,buf,u);
out:
unlink(temp);
bex:
exit(1);
}