Path: utzoo!utgpu!watmath!att!dptg!rutgers!cs.utexas.edu!csd4.milw.wisc.edu!uakari.primate.wisc.edu!indri!aplcen!haven!adm!xadmx!rbj@dsys.ncsl.nist.gov From: rbj@dsys.ncsl.nist.gov (Root Boy Jim) Newsgroups: comp.unix.questions Subject: Password checking program Message-ID: <20557@adm.BRL.MIL> Date: 9 Aug 89 12:11:19 GMT Sender: news@adm.BRL.MIL Lines: 126 ? From: CCEL? I'm still getting requests for that silly password checking program ? I talked about last week, and I thought i'd posted the source here How about a more portable and safe version? Comments follow. ? Remember to take my .sig off the end of this guy. You might have saved yourself some embarrassment if you had. ? -------------------------------CUT HERE----------------------------- ? /* Password hacking program */ ? /* Written by: Matt Hopkins (2138a3@gmuvax2.gmu.edu) */ ? #include ? #include ? #define NOTDONE 0 ? #define DONE 1 ? #define ENDOFFILE -1 ? void main() ? { ? FILE *dict; ? FILE *passwd; ? char word[40],ch; ? char *userpass; ? char salt[3]; ? int done=NOTDONE; ? char username[20],testname[20],garbage[120],hold[15]; ? printf("Enter username to search for: "); ? gets(username); Hmmm. Now if only I can get you to install this guy suid root with a well known network port :-) To explain that remark, `gets' is a dangerous function to use, especially when an automatic variable is its target. By typing averylongname, containing machine code, one can overwrite the stack's return address and jump to the machine code. In fact, such a technique was exploited by the Internet worm last November. ? printf("Searching for '%s' ...\n",username); ? { ? passwd=fopen("/etc/passwd","r"); ? while (done==NOTDONE) ? { ? fscanf(passwd,"%s",garbage); ? fscanf(passwd,"\n"); Use fscanf(passwd,"%s\n",garbage); In fact, avoid the use of fscanf (or scanf) altogether. Use fgets followed by sscanf. Error recovery is easier. ? strcpy(testname,strtok(garbage,":")); Strtok is a System V routine, not generally found on BSD systems. Why didn't you just use fscanf directly to parse the colons and separate the username and passwd? In fact, why didn't you use getpwent to find the username and bypass this loop altogether? ? strcpy(hold,strtok(NULL,":")); ? salt[0]=hold[0]; ? salt[1]=hold[1]; ? salt[2]='\0'; ? userpass=hold+2; ? if (strcmp(testname,username)==0) ? done=DONE; ? else ? if (feof(passwd)) ? done=ENDOFFILE; ? } ? if (done==ENDOFFILE) ? { ? strcpy(userpass,"NOTFOUND"); ? puts("User not found in passwd file."); ? } ? } ? fclose(passwd); ? if (done!=ENDOFFILE) ? done=NOTDONE; ? dict=fopen("/usr/dict/words","r"); ? ch=0; ? while (done==NOTDONE) ? { ? fscanf(dict,"%s\n",word); Another good use for fgets. ? if ((word[0]>='a') && (word[0]>ch)) ? { ? ch=word[0]; ? printf("Now on the %c's (chug .. chug .. chug)\n",ch); ? } ? if (isupper(word[0])) word[0]+=32; How about using tolower? ? if (strcmp(userpass-2,crypt(word,salt))==0) ? { ? printf("The password is '%s'\n",word); ? done=DONE; ? } ? if ((feof(dict)) && (done!=DONE)) ? done=ENDOFFILE; ? } ? if (done==ENDOFFILE) ? puts("Sorry ... password not found in dict.\n"); Sorry? That's GOOD news! ? fclose(dict); ? } I won't bother too much with style matters, except to say that both of your loops could use `for(;;)' and `break'. ? -------------------------------CUT HERE----------------------------- ? -------------------------------------- ? Randy Tidd MITRE-McLean CCEL Lab ? rtidd@mitre.arpa ccel%community-chest@gateway.mitre.org Root Boy Jim Have GNU, Will Travel.