/* * enter a password in the password file * this program should be suid with owner * with an owner with write permission on /etc/passwd */ #include #include #include 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); }