home *** CD-ROM | disk | FTP | other *** search
/ The Hacker's Encyclopedia 1998 / hackers_encyclopedia.iso / programs / kc9_src.arj / KC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-08  |  45.0 KB  |  1,626 lines

  1. /****************************************************************************\
  2. **    Killer Cracker v9.11 LTD - Un*x /etc/passwd 'FAST' cracking engine    **
  3. ** ======================================================================== **
  4. **                 Sourcefile: kc.c -- Last Update: 10/07/91                **
  5. ** ======================================================================== **
  6. **           Written By Doctor Dissector, Copyright (C) 1990, 1991          **
  7. ** ======================================================================== **
  8. **                   LIMITED EDITION -- DO NOT DISTRIBUTE                   **
  9. \****************************************************************************/
  10.  
  11. /*=[ License ]==============================================================*/
  12.  
  13. /*
  14. **  Killer Cracker - Version 9.11 LTD
  15. **  Copyright (C) 1991 By Doctor Dissector
  16. **
  17. **  This program is NOT free software BUT may be used without charge or
  18. **  payment in any form IF your copy is a "registered" distributed version.
  19. **  You may modify it as much as you please, however, you MAY NOT re-
  20. **  distribute it, in any shape or for: ie. modified OR unmodified,
  21. **  without the expressed written consent (ie. e-mail) of
  22. **  Doctor Dissector.
  23. **
  24. **  This program was initially distributed in the hope that it will be
  25. **  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  27. */
  28.  
  29. /*=[ Disclaimer ]===========================================================*/
  30.  
  31. /*
  32. **  The author of this package, Doctor Dissector, will not assume liability
  33. **  for ANY of the effects of the use or distribution of this package.  If
  34. **  you, at ANY time compile or use this package, you will assume full
  35. **  liability for your own actions; Doctor Dissector can neither enforce the
  36. **  lawful use of this package nor your actions before, during, or after
  37. **  exposure to this package.  Doctor Dissector does NOT endorse your unlawful
  38. **  use of this package to appropriate computer accounts not under your lawful
  39. **  ownership.
  40. **
  41. **  The original intent of this package was to prove that Un*x accounts can be
  42. **  easily, efficiently, and effectively cracked utilizing modified DES
  43. **  encryption routines and proper statistical, mathematical, logical, and
  44. **  programming skills.
  45. */
  46.  
  47. /*=[ Copyright ]============================================================*/
  48.  
  49. char kc_c_msg[] = "Source: kc.c, Copyright (c)1991 Doctor Dissector";
  50.  
  51. /*=[ Include: kc.h Header ]=================================================*/
  52.  
  53. #include "kc.h"
  54.  
  55. /*=[ Variable: _stklen ]====================================================*/
  56.  
  57. #ifdef _TURBO
  58. unsigned _stklen = 8192;                /* 8k stack, Turbo/Borland C/C++ */
  59. #endif
  60.  
  61. /*=[ Include Header Files ]=================================================*/
  62.  
  63. #include <stdio.h>
  64. #include <string.h>
  65. #include <time.h>
  66. #include <errno.h>
  67.  
  68. #ifndef _STRIPPED
  69. #include <signal.h>
  70. #else
  71. #include <stdlib.h>
  72. #endif
  73.  
  74. #ifdef _MSDOS
  75. #include <sys\types.h>
  76. #else
  77. #include <sys/types.h>
  78. #include <sys/time.h>
  79. #endif
  80.  
  81. #ifdef _TURBO
  82. #include <alloc.h>
  83. #endif
  84.  
  85. #ifdef _MICROSOFT
  86. #include <malloc.h>
  87. #endif
  88.  
  89. #ifdef _BSD
  90. #include <sys/resource.h>
  91. #endif
  92.  
  93. /*=[ Include: bcrypt.c Encryption Routines ]================================*/
  94.  
  95. #include "bcrypt.c"
  96.  
  97. /*=[ Structure: acc_struct ]================================================*/
  98.  
  99. struct acc_list {
  100.     char            *login,             /* Login field of /etc/passwd */
  101.                     *epw,               /* Password field of /etc/passwd */
  102.                     *gecos,             /* GECOS field of /etc/passwd */
  103.                     *home,              /* Home dir field of /etc/passwd */
  104.                     *shell;             /* Shell field of /etc/passwd */
  105.  
  106.     unsigned        uid,                /* UID field of /etc/passwd */
  107.                     gid;                /* GID field of /etc/passwd */
  108.  
  109.     struct acc_list *next,              /* Pointer to next struct */
  110.                     *prev;              /* Pointer to previous struct */
  111.  
  112.     U32             SL[2];              /* salt "mask" of this account */
  113.     BU64            encode;             /* 64 bits from "decryption" */
  114. };
  115.  
  116. /*=[ Global Variables ]=====================================================*/
  117.  
  118. char            progname[MAX_FILE];     /* KC's current executable name */
  119.  
  120. int             cracked,                /* Amount of accounts cracked */
  121.                 fork_process,           /* Fork process into background? */
  122.                 inactive,               /* Write inactive accounts? */
  123.                 lastuser,               /* Sequential user # */
  124.                 maximize,               /* Maximize resource usage? */
  125.                 quiet,                  /* Quiet mode, no stdout output? */
  126.                 restoring,              /* Restoring a session? */
  127.                 stdin_words,            /* Read words from stdin? */
  128.                 single,                 /* Single-crack mode? */
  129.                 num_accs;               /* Total number of accounts */
  130.  
  131. unsigned long   timeout,                /* Timeout (minutes) */
  132.                 combinations;           /* Total encryption/comparisions */
  133.  
  134. char            lastword[MAX_WORD],     /* Last word read from wordfile */
  135.                 pwfile[MAX_FILE],       /* PWfile filename */
  136.                 restorefile[MAX_FILE],  /* Restorefile filename */
  137.                 validfile[MAX_FILE],    /* Validfile filename */
  138.                 wordfile[MAX_FILE];     /* Wordfile filename */
  139.  
  140. FILE            *vf,                    /* Valid account file stream */
  141.                 *gf;                    /* Word guess file stream */
  142.  
  143. time_t          timer;                  /* Performance timing variable */
  144.  
  145. /*==========================================================================*/
  146.  
  147. /*
  148. **     function: void print_title(void)
  149. **  description: displays the title of this program
  150. **      returns: nothing
  151. */
  152.  
  153. void print_title()
  154. {
  155.     printf("\n");
  156.     printf("Killer Cracker, Version 9.11 LTD (10/7/91)\n");
  157.     printf("Copyright (C) 1991, By Doctor Dissector\n");
  158.     printf("*** DO NOT DISTRIBUTE THIS VERSION ***\n\n");
  159. }
  160.  
  161. /*==========================================================================*/
  162.  
  163. /*
  164. **     function: void print_usage(void)
  165. **  description: displays program usage & options
  166. **      returns: nothing
  167. */
  168.  
  169. void print_usage()
  170. {
  171.     printf("Brief:  Unix /etc/passwd 'FAST' password cracking engine.\n\n");
  172.     printf("Usage:  %s [[flag] ...] [-stdin < [wordfile]]\n\n", progname);
  173.     printf("Flags:  -?                  display this usage menu\n");
  174.  
  175. #ifdef _UNIX
  176.     printf("        -Fork               fork session process into the background\n");
  177. #endif
  178.  
  179.     printf("        -Help               display this usage menu\n");
  180.     printf("        -Inactive           display and write inactive accounts\n");
  181.  
  182. #ifdef _BSD
  183.     printf("        -Maximize           maximize use of system resources\n");
  184. #endif
  185.  
  186.     printf("        -Pwfile:<file>      set passwordfile to <file>\n");
  187.     printf("        -Quiet              suppress all output from stdout\n");
  188.     printf("        -Restore:<file>     restore session using <file> as restorefile\n");
  189.     printf("        -SIngle             read wordfile in 'single-crack' format\n");
  190.     printf("        -STdin              read words from stdin instead of 'wordfile'\n");
  191.     printf("        -TEst               test crypt result for proper encryption\n");
  192.     printf("        -TImeout:<time>     abort session after a period of <time> minutes\n");
  193.     printf("        -Validfile:<file>   set validfile to <file>\n");
  194.     printf("        -Wordfile:<file>    set wordfile to <file>\n\n");
  195. }
  196.  
  197. /*==========================================================================*/
  198.  
  199. /*
  200. **     function: void print_files(void)
  201. **  description: displays settings for pwfile, wordfile, and validfile
  202. **      returns: nothing
  203. */
  204.  
  205. void print_files()
  206. {
  207.     if ((!pwfile[0]) && (!restoring)) {
  208.         printf("PWfile    : ");
  209.         gets(pwfile);
  210.     }
  211.     else
  212.         printf("PWfile    : %s\n", pwfile);
  213.     if (((!wordfile[0]) && (!stdin_words)) && (!restoring)) {
  214.         printf("Wordfile  : ");
  215.         gets(wordfile);
  216.     }
  217.     else
  218.         printf("Wordfile  : %s\n", (stdin_words ? "stdin" : wordfile));
  219.     if (!validfile[0]) {
  220.         printf("Validfile : ");
  221.         gets(validfile);
  222.         printf("\n");
  223.     }
  224.     else
  225.         printf("Validfile : %s\n\n", validfile);
  226. }
  227.  
  228. /*==========================================================================*/
  229.  
  230. /*
  231. **     function: void print_stat(void)
  232. **  description: displays various settings/flags
  233. **      returns: nothing
  234. */
  235.  
  236. void print_stat()
  237. {
  238.     int ok=0;
  239.  
  240.     if (single) {
  241.         printf("->  Single-crack mode\n");
  242.         ok=1;
  243.     }
  244.     if (inactive) {
  245.         printf("->  Write inactive accounts\n");
  246.         ok=1;
  247.     }
  248.     if (maximize) {
  249.         printf("->  Maximize use of system resources\n");
  250.         ok=1;
  251.     }
  252.     if (timeout) {
  253.         printf("->  Session timeout: %ld minutes\n", timeout);
  254.         ok=1;
  255.     }
  256.     if (ok)
  257.         printf("\n");
  258. }
  259.  
  260. /*==========================================================================*/
  261.  
  262. /*
  263. **     function: void init_vars(void)
  264. **  description: pre-initialize global variables
  265. **      returns: nothing
  266. */
  267.  
  268. void init_vars()
  269. {
  270.     vf=NULL;
  271.     gf=NULL;
  272.     timer=0;
  273.     cracked=0;
  274.     combinations=0;
  275.     fork_process=0;
  276.     inactive=0;
  277.     lastuser=0;
  278.     maximize=0;
  279.     quiet=0;
  280.     restoring=0;
  281.     stdin_words=0;
  282.     single=0;
  283.     timeout=0;
  284.     lastword[0]=0;
  285.     pwfile[0]=0;
  286.     restorefile[0]=0;
  287.     validfile[0]=0;
  288.     wordfile[0]=0;
  289. }
  290.  
  291. /*==========================================================================*/
  292.  
  293. /*
  294. **     function: void kc_exit(int exitcode, char *desc1, char *desc2)
  295. **  description: displays an exit/error message and exits with an exit
  296. **               code of <exitcode>
  297. **      returns: nothing
  298. */
  299.  
  300. void kc_exit(exitcode, desc1, desc2)
  301.     register int  exitcode;
  302.     const    char *desc1, *desc2;
  303. {
  304.     if (!((quiet) && (!exitcode))) {
  305.         fprintf(stderr, "\n%s: ", progname);
  306.         if (desc1)
  307.             fprintf(stderr, "%s", desc1);
  308.         else
  309.             fprintf(stderr, "abnormal program termination");
  310.         if (desc2)
  311.             fprintf(stderr, ": %s", desc2);
  312.         fprintf(stderr, "\n\n");
  313.     }
  314.     exit(exitcode);
  315. }
  316.  
  317. /*==========================================================================*/
  318.  
  319. /*
  320. **     function: void show_string(char *str)
  321. **  description: writes <str> to stdout
  322. **      returns: nothing
  323. */
  324.  
  325. void show_string(str)
  326.     char *str;
  327. {
  328.     write(1, str, strlen(str));
  329. }
  330.  
  331. /*==========================================================================*/
  332.  
  333. /*
  334. **     function: char *lowcase(char *str)
  335. **  description: produces the lowercase equivalent of <str>
  336. **      returns: lowercase equivalent of <str>
  337. */
  338.  
  339. char *lowcase(str)
  340.     register char *str;
  341. {
  342.     register char *ptr;
  343.     static   char s[MAX_TAIL];
  344.  
  345.     ptr=s;
  346.     while(*str)
  347.         (*ptr++)=(((*str)>='A') && ((*str)<='Z') ? (*str++)+32 : (*str++));
  348.     *ptr=0;
  349.     return(s);
  350. }
  351.  
  352. /*===========================================================================*/
  353.  
  354. /*
  355. **     function: int open_valid(void)
  356. **  description: opens & prepares the [vf] file stream for writing
  357. **      returns: 0 on success, -1 on error
  358. */
  359.  
  360. int open_valid()
  361. {
  362.     vf=fopen(validfile, "a");
  363.     if (!vf)
  364.         return(-1);
  365.     fprintf(vf, "\n========================================");
  366.     fprintf(vf, "\nPWfile   : %s ", pwfile);
  367.     fprintf(vf, "\nWordfile : %s", (stdin_words ? "stdin" : wordfile));
  368.     fprintf(vf, "\n----------------------------------------");
  369.     fclose(vf);
  370.     return(0);
  371. }
  372.  
  373. /*===========================================================================*/
  374.  
  375. /*
  376. **     function: int open_words(void)
  377. **  description: opens & prepares the [gf] file stream for reading
  378. **      returns: 0 on success, -1 on error
  379. */
  380.  
  381. int open_words()
  382. {
  383.     gf=fopen(wordfile, "r");
  384.     return(!gf ? (-1) : 0);
  385. }
  386.  
  387. /*===========================================================================*/
  388.  
  389. /*
  390. **     function: void close_valid(time_t elapsed, int aborted)
  391. **  description: prepares & closes the [vf] file stream
  392. **      returns: nothing
  393. */
  394.  
  395. void close_valid(elapsed, aborted)
  396.     time_t elapsed;
  397.     int    aborted;
  398. {
  399.     double performance;
  400.  
  401.     if (elapsed<1)
  402.         elapsed=1;
  403.     vf=fopen(validfile, "a");
  404.     if (!vf)
  405.         kc_exit(1, "error opening validfile", validfile);
  406.     if (aborted)
  407.         if (single)
  408.             fprintf(vf, "\n*** Session aborted, user #%d", lastuser);
  409.          else
  410.             fprintf(vf, "\n*** Session aborted, word: %s", lastword);
  411.     fprintf(vf,"\n----------------------------------------");
  412.     performance=(double)((double)combinations/(double)elapsed);
  413.     fprintf(vf, "\nEncryption/Comparisions: %lu", combinations);
  414.     fprintf(vf, "\nTime Elapsed In Seconds: %lu", elapsed);
  415.     fprintf(vf, "\nMean Encryptions/Second: %.2f", performance);
  416.     fprintf(vf, "\n=======================================");
  417.     fclose(vf);
  418. }
  419.  
  420. /*===========================================================================*/
  421.  
  422. /*
  423. **     function: void close_all(time_t elapsed)
  424. **  description: calls function [close_valid] and closes the [gf] file stream
  425. **      returns: nothing
  426. */
  427.  
  428. void close_all(elapsed)
  429.     time_t elapsed;
  430. {
  431.     close_valid(elapsed, 0);
  432.     fclose(gf);
  433. }
  434.  
  435. /*===========================================================================*/
  436.  
  437. /*
  438. **     function: void found_valid(char *login, char *pw, unsigned uid,
  439. **                  unsigned gid, char *gecos, char *home, char *shell)
  440. **  description: writes "valid" account information to the [vf] file stream
  441. **      returns: nothing
  442. */
  443.  
  444. void found_valid(login, pw, uid, gid, gecos, home, shell, ia)
  445.     char     *login, *pw, *gecos, *home, *shell;
  446.     unsigned uid, gid;
  447.     int      ia;
  448. {
  449.     static char s[MAX_LINE];
  450.  
  451.  
  452.     vf=fopen(validfile, "a");
  453.     if (!vf)
  454.         kc_exit(1, "error opening validfile", validfile);
  455.     fprintf(vf, "\n%s:%s:%u:%u:%s:%s:%s", login, pw, uid,
  456.         gid, gecos, home, shell);
  457.     fclose(vf);
  458.     if (!quiet) {
  459.         if (ia)
  460.             sprintf(s, "\b[%s]  ", login);
  461.         else
  462.             sprintf(s, "\b(%s)  ", login);
  463.         show_string(s);
  464.     }
  465. }
  466.  
  467. /*==========================================================================*/
  468.  
  469. /*
  470. **     function: void *kc_malloc(long size)
  471. **  description: allocates memory, simplifies the use of "malloc" type
  472. **               functions between different compilers
  473. **      returns: pointer to a block of allocated memory, exits upon error
  474. */
  475.  
  476. void *kc_malloc(size)
  477.     long size;
  478. {
  479.     void *buf;
  480.     char s[21];
  481.  
  482. #if defined(_TURBO) || defined(_MICROSOFT)
  483.  
  484. #ifdef _TURBO
  485.     buf=(void *)farmalloc(size);
  486. #else
  487.     buf=(void *)_fmalloc(size);
  488. #endif
  489.  
  490. #else
  491.     buf=(void *)malloc((size_t)size);
  492. #endif
  493.  
  494.     if (!buf) {
  495.         sprintf(s, "%ld bytes", size);
  496.         kc_exit(1, "memory allocation error", s);
  497.     }
  498.     return(buf);
  499. }
  500.  
  501. /*==========================================================================*/
  502.  
  503. /*
  504. **     function: void kc_free(void *buf)
  505. **  description: de-allocates memory, simplifies the use of "malloc" type
  506. **               functions between different compilers
  507. **      returns: nothing
  508. */
  509.  
  510. void kc_free(buf)
  511.     void *buf;
  512. {
  513.  
  514. #if defined(_TURBO) || defined(_MICROSOFT)
  515.  
  516. #ifdef _TURBO
  517.     farfree(buf);
  518. #else
  519.     _ffree(buf);
  520. #endif
  521.  
  522. #else
  523.     free(buf);
  524. #endif
  525.  
  526. }
  527.  
  528. /*==========================================================================*/
  529.  
  530. /*
  531. **     function: void acc_free(struct acc_list *acc)
  532. **  description: de-allocates memory from a member of the linked-list
  533. **      returns: nothing
  534. */
  535.  
  536. void acc_free(acc)
  537.     struct acc_list *acc;
  538. {
  539.     kc_free(acc->login);
  540.     kc_free(acc->epw);
  541.     kc_free(acc->gecos);
  542.     kc_free(acc->home);
  543.     kc_free(acc->shell);
  544.     kc_free(acc);
  545. }
  546.  
  547. /*==========================================================================*/
  548.  
  549. /*
  550. **     function: struct acc_list *acc_remove(struct acc_list *root,
  551. **                   struct acc_list *remove)
  552. **  description: removes a member from a linked-list, and calls [acc_free]
  553. **               to de-allocate it
  554. **      returns: root of the new linked-list
  555. */
  556.  
  557. struct acc_list *acc_remove(root, remove)
  558.     struct acc_list *root, *remove;
  559. {
  560.     if (root==remove) {
  561.         root=remove->next;
  562.         if(root)
  563.             root->prev=NULL;
  564.     }
  565.     if (remove->next)
  566.         remove->next->prev=remove->prev;
  567.     if (remove->prev)
  568.         remove->prev->next=remove->next;
  569.     acc_free(remove);
  570.     return(root);
  571. }
  572.  
  573. /*==========================================================================*/
  574.  
  575. /*
  576. **     function: struct acc_list *acc_create(char *login, char *epw,
  577. **                  unsigned uid, unsigned gid, char *gecos, char *home,
  578. **                  char *shell)
  579. **  description: allocates and creates a member of the linked list
  580. **      returns: created member
  581. */
  582.  
  583. struct acc_list *acc_create(login, epw, uid, gid, gecos, home, shell)
  584.     char      *login, *epw, *gecos, *home, *shell;
  585.     unsigned  uid, gid;
  586. {
  587.     struct acc_list *acc;
  588.  
  589.     acc=(struct acc_list *)kc_malloc((long)sizeof(struct acc_list));
  590.     acc->login=(char *)kc_malloc((long)strlen(login)+1);
  591.     strcpy(acc->login, login);
  592.     acc->epw=(char *)kc_malloc((long)13+1);
  593.     epw[13]=0;
  594.     strcpy(acc->epw, epw);
  595.     acc->uid=uid;
  596.     acc->gid=gid;
  597.     acc->gecos=(char *)kc_malloc((long)strlen(gecos)+1);
  598.     strcpy(acc->gecos, gecos);
  599.     acc->home=(char *)kc_malloc((long)strlen(home)+1);
  600.     strcpy(acc->home, home);
  601.     acc->shell=(char *)kc_malloc((long)strlen(shell)+1);
  602.     strcpy(acc->shell, shell);
  603.     bcrypt_salt_to_E(epw[0], epw[1], acc->SL);
  604.     acc->encode=bcrypt_pw_to_BU64(epw+2);
  605.     acc->next=NULL;
  606.     acc->prev=NULL;
  607.     return(acc);
  608. }
  609.  
  610. /*==========================================================================*/
  611.  
  612. /*
  613. **     function: struct acc_list *acc_read_one(char *line)
  614. **  description: reads data from one line of the /etc/passwd file and passes
  615. **               it to [acc_create] to create a new member of the linked-list
  616. **      returns: created member
  617. */
  618.  
  619. struct acc_list *acc_read_one(line)
  620.     char *line;
  621. {
  622.     int  i, ok=0;
  623.     char *login, *epw, *uid, *gid, *gecos, *home, *sh;
  624.  
  625.     for(login=line; (*line!=':') && (*line); line++)
  626.         ;
  627.     if (*line) {
  628.         *line=0;
  629.         for(epw=++line; (*line!=':') && (*line); line++)
  630.             ;
  631.         if (*line) {
  632.             *line=0;
  633.             for(uid=++line; (*line!=':') && (*line); line++)
  634.                 ;
  635.             if (*line) {
  636.                 *line=0;
  637.                 for(gid=++line; (*line!=':') && (*line); line++)
  638.                     ;
  639.                 if (*line) {
  640.                     *line=0;
  641.                     for(gecos=++line; (*line!=':') && (*line); line++)
  642.                         ;
  643.                     if (*line) {
  644.                         *line=0;
  645.                         for(home=++line; (*line!=':') && (*line); line++)
  646.                             ;
  647.                         if (*line) {
  648.                             *line=0;
  649.                             for(sh=++line; (*line!=':') && (*line); line++)
  650.                                 ;
  651.                             *line=0;
  652.                             ok=1;
  653.                         }
  654.                     }
  655.                 }
  656.             }
  657.         }
  658.     }
  659.     if (ok)
  660.         return(acc_create(login, epw, (unsigned)atoi(uid),
  661.             (unsigned)atoi(gid), gecos, home, sh));
  662.     return(NULL);
  663. }
  664.  
  665. /*==========================================================================*/
  666.  
  667. /*
  668. **     function: struct acc_list *acc_strip(struct acc_list *root)
  669. **  description: strips inactive accounts and non-passworded accounts from
  670. **               the linked list <root>
  671. **      returns: result linked-list
  672. */
  673.  
  674. struct acc_list *acc_strip(root)
  675.     struct acc_list *root;
  676. {
  677.     int               delete;
  678.     struct acc_list *cur, *remove;
  679.  
  680.     for(cur=root; cur; ) {
  681.         delete=1;
  682.         if (!cur->epw[0]) {
  683.             found_valid(cur->login, "\0", cur->uid, cur->gid,
  684.                 cur->gecos, cur->home, cur->shell, 0);
  685.             cracked++;
  686.         }
  687.         else if ((cur->epw[0]=='*') || (strlen(cur->epw)!=13)) {
  688.             if (inactive)
  689.                 found_valid(cur->login, "*INACTIVE*", cur->uid, cur->gid,
  690.                     cur->gecos, cur->home, cur->shell, 1);
  691.         }
  692.         else if (cur->login[0]!='+') {
  693.             delete=0;
  694.             cur=cur->next;
  695.         }
  696.         if (delete) {
  697.             remove=cur;
  698.             cur=cur->next;
  699.             root=acc_remove(root, remove);
  700.         }
  701.     }
  702.     return(root);
  703. }
  704.  
  705. /*==========================================================================*/
  706.  
  707. /*
  708. **     function: struct acc_list *read_pwfile()
  709. **  description: creates the full linked-list from an /etc/passwd file
  710. **      returns: result linked-list
  711. */
  712.  
  713. struct acc_list *read_pwfile()
  714. {
  715.     char              line[MAX_LINE];
  716.     FILE              *fp;
  717.     struct acc_list *root, *new;
  718.  
  719.     root=NULL;
  720.     fp=fopen(pwfile, "r");
  721.     if (!fp)
  722.         kc_exit(1, "error reading pwfile", pwfile);
  723.     while(fgets(line, MAX_LINE-1, fp)) {
  724.         if (line[strlen(line)-1]=='\n')
  725.             line[strlen(line)-1]=0;
  726.         if ((new=acc_read_one(line))!=NULL) {
  727.             ++num_accs;
  728.             if (root)
  729.                 root->prev=new;
  730.             new->next=root;
  731.             root=new;
  732.         }
  733.     }
  734.     return(root);
  735. }
  736.  
  737. /*==========================================================================*/
  738.  
  739. /*
  740. **     function: int restore_nextword(char *word)
  741. **  description: reads the next word from a wordlist, used in conjunction
  742. **               with other restore functions
  743. **      returns: 1 upon success, 0 on error; places the word in <word>
  744. */
  745.  
  746. int restore_nextword(word)
  747.     char *word;
  748. {
  749.     if (((!stdin_words) && (fgets(word, MAX_WORD-1, gf))) ||
  750.         ((stdin_words) && (fgets(word, MAX_WORD-1, stdin)))) {
  751.         if (word[strlen(word)-1]=='\n')
  752.             word[strlen(word)-1]=0;
  753.         return(1);
  754.     }
  755.     return(0);
  756. }
  757.  
  758. /*==========================================================================*/
  759.  
  760. /*
  761. **     function: int nextword(void)
  762. **  description: reads the next word from a wordlist and prepares it for
  763. **               encryption routines
  764. **      returns: 1 upon success, 0 on error; places the word in [lastword]
  765. */
  766.  
  767. int nextword()
  768. {
  769.     if (((!stdin_words) && (fgets(lastword, MAX_WORD-1, gf))) ||
  770.         ((stdin_words) && (fgets(lastword, MAX_WORD-1, stdin)))) {
  771.         if (lastword[strlen(lastword)-1]=='\n')
  772.             lastword[strlen(lastword)-1]=0;
  773.         lastword[8]=0;
  774.         bcrypt_set_word(lastword);
  775.         return(1);
  776.     }
  777.     return(0);
  778. }
  779.  
  780. /*===========================================================================*/
  781.  
  782. /*
  783. **     function: void save_options(int done)
  784. **  description: saves the current options and place to the [restorefile]
  785. **      returns: nothing
  786. */
  787.  
  788. void save_options(done)
  789.     int done;
  790. {
  791.     FILE *rf;
  792.  
  793.     if (!restorefile[0])
  794.         rf=fopen("restore", "w");
  795.     else
  796.         rf=fopen(restorefile, "w");
  797.     if (!rf)
  798.         kc_exit(1, "error opening restorefile", restorefile);
  799.     fprintf(rf, "PWfile=%s\n", pwfile);
  800.     fprintf(rf, "Wordfile=%s\n", wordfile);
  801.     fprintf(rf, "Validfile=%s\n", validfile);
  802.  
  803.     if (fork_process)
  804.         fprintf(rf, "Flag=fork\n");
  805.     if (quiet)
  806.         fprintf(rf, "Flag=quiet\n");
  807.     if (stdin_words)
  808.         fprintf(rf, "Flag=stdin\n");
  809.     if (single)
  810.         fprintf(rf, "Flag=single\n");
  811.  
  812. #ifdef _BSD
  813.     if (maximize)
  814.         fprintf(rf, "Flag=maximize\n");
  815. #endif
  816.  
  817.     if (timeout)
  818.         fprintf(rf, "Flag=timeout:%ld\n", timeout);
  819.     if (single) {
  820.         if (done)
  821.             fprintf(rf, "Lastuser=-1\n");
  822.         else
  823.             fprintf(rf, "Lastuser=%d\n", lastuser);
  824.     }
  825.     else {
  826.         if (done)
  827.             fprintf(rf, "Lastword=*****DONE*****\n");
  828.         else
  829.             fprintf(rf, "Lastword=%s\n", lastword);
  830.     }
  831.     fclose(rf);
  832. }
  833.  
  834. /*==========================================================================*/
  835.  
  836. /*
  837. **     function: void/int handler(void)
  838. **  description: handles all interrupt routines, aborts session
  839. **      returns: nothing
  840. */
  841.  
  842. #ifndef _STRIPPED
  843. #ifdef _UNIX
  844. int handler()
  845. #else
  846. void handler()
  847. #endif
  848.  
  849. {
  850.     time_t temp;
  851.  
  852. #ifdef _UNIX
  853.     signal(SIGQUIT, SIG_IGN);
  854.     signal(SIGTERM, SIG_IGN);
  855.     signal(SIGINT, SIG_IGN);
  856.     signal(SIGALRM, SIG_IGN);
  857. #endif
  858.  
  859. #ifdef _MSDOS
  860.     signal(SIGINT, SIG_IGN);
  861. #endif
  862.  
  863.     close_valid(time(&temp)-timer, 1);
  864.     save_options(0);
  865.     fclose(gf);
  866.     kc_exit(0, "session aborted", NULL);
  867.  
  868. #ifdef _UNIX
  869.     return(0);
  870. #endif
  871.  
  872. }
  873.  
  874. /*==========================================================================*/
  875.  
  876. /*
  877. **     function: void crk_s(struct acc_list *root)
  878. **  description: cracks the given linked-list <root> against a wordfile in
  879. **               single-crack format
  880. **      returns: nothing
  881. */
  882.  
  883. void crk_s(root)
  884.     register struct acc_list *root;
  885. {
  886.     register char            spin_index=0, to_remove=0;
  887.     static   char            s[MAX_WORD],
  888.                              *spin[4] = { "\b-","\b\\", "\b|", "\b/" };
  889.     static   time_t          temp;
  890.     register long            info_index=0;
  891.     register BU64            ec;
  892.     register struct acc_list *cur, *remove;
  893.  
  894.     lastuser=0;
  895.     for(cur=root; (cur) && (lastword[0]); ) {
  896.         lastuser++;
  897.         sprintf(s, "\b \n%-12s  ", cur->login);
  898.         show_string(s);
  899.         do {
  900.             if (!strcmp(lastword, "***!***")) {
  901.                 if (!nextword())
  902.                     lastword[0]=0;
  903.                 break;
  904.             }
  905.  
  906. #ifdef DEBUGGING
  907.             show_string(lastword);
  908.             show_string("/");
  909. #endif
  910.  
  911.             ec=bcrypt_encode(cur->SL[0], cur->SL[1]);
  912.             if (!((long)++combinations%30)) {
  913.                 show_string(spin[spin_index]);
  914.                 spin_index=(spin_index>2 ? 0 : spin_index+1);
  915.  
  916. #ifndef _UNIX
  917.                 if (timeout) {
  918.                     if ((timeout*60L)<(time(&temp)-timer))
  919.                         handler();
  920.                 }
  921. #endif
  922.  
  923.             }
  924.             if ((ec.L.U==cur->encode.L.U) && (ec.R.U==cur->encode.R.U)) {
  925.                 cracked++;
  926.                 found_valid(cur->login, lastword, cur->uid, cur->gid,
  927.                     cur->gecos, cur->home, cur->shell, 0);
  928.                 remove=cur;
  929.                 to_remove=1;
  930.                 cur=cur->prev;
  931.                 root=acc_remove(root, remove);
  932.                 if (!root)
  933.                     return;
  934.                 while(nextword()) {
  935.                     if (!strcmp(lastword, "***!***")) {
  936.                         if (!nextword())
  937.                             lastword[0]=0;
  938.                         break;
  939.                     }
  940.                 }
  941.                 break;
  942.             }
  943.         } while(nextword());
  944.         if (to_remove)
  945.             to_remove=0;
  946.         else
  947.             cur=cur->prev;
  948.         if (!(++info_index%10)) {
  949.             temp=time(&temp)-timer;
  950.             sprintf(s, "\b \n**Status**   [ c: %lu, v: %d, s: %lu, c/s: %.2f, v/u: %.3f ] ",
  951.                 (unsigned long)combinations,
  952.                 cracked,
  953.                 (unsigned long)temp,
  954.                 (double)combinations/(double)(temp+.001),
  955.                 (double)cracked/(double)info_index);
  956.             show_string(s);
  957.         }
  958.     }
  959. }
  960.  
  961. /*==========================================================================*/
  962.  
  963. /*
  964. **     function: void crk(struct acc_list *root)
  965. **  description: cracks the given linked-list <root> against a wordfile
  966. **      returns: nothing
  967. */
  968.  
  969. void crk(root)
  970.     register struct acc_list *root;
  971. {
  972.     register char            spin_index=0;
  973.     static   char            s[MAX_WORD],
  974.                              *spin[4] = { "\b-","\b\\", "\b|", "\b/" };
  975.     static   time_t          temp;
  976.     register long            info_index=0;
  977.     register BU64            ec;
  978.     register struct acc_list *cur, *remove;
  979.  
  980.     do {
  981.         sprintf(s, "\b \n%-12s  ", lastword);
  982.         show_string(s);
  983.         for(cur=root; cur; ) {
  984.             ec=bcrypt_encode(cur->SL[0], cur->SL[1]);
  985.             if (!((long)++combinations%30)) {
  986.                 show_string(spin[spin_index]);
  987.                 spin_index=(spin_index>2 ? 0 : spin_index+1);
  988.  
  989. #ifndef _UNIX
  990.                 if (timeout) {
  991.                     if ((timeout*60L)<(time(&temp)-timer))
  992.                         handler();
  993.                 }
  994. #endif
  995.  
  996.             }
  997.             if ((ec.L.U==cur->encode.L.U) && (ec.R.U==cur->encode.R.U)) {
  998.                 cracked++;
  999.                 found_valid(cur->login, lastword, cur->uid, cur->gid,
  1000.                     cur->gecos, cur->home, cur->shell, 0);
  1001.                 remove=cur;
  1002.                 cur=cur->prev;
  1003.                 root=acc_remove(root, remove);
  1004.                 if (!root)
  1005.                     return;
  1006.             }
  1007.             else
  1008.                 cur=cur->prev;
  1009.         }
  1010.         if (!(++info_index%10)) {
  1011.             temp=time(&temp)-timer;
  1012.             sprintf(s, "\b \n**Status**   [ c: %lu, v: %d, s: %lu, c/s: %.2f, v/w: %.3f ] ",
  1013.                 (unsigned long)combinations,
  1014.                 cracked,
  1015.                 (unsigned long)temp,
  1016.                 (double)combinations/(double)(temp+.001),
  1017.                 (double)cracked/(double)info_index);
  1018.             show_string(s);
  1019.         }
  1020.     } while(nextword());
  1021. }
  1022.  
  1023. /*==========================================================================*/
  1024.  
  1025. /*
  1026. **     function: void crk_s_q(struct acc_list *root)
  1027. **  description: cracks the given linked-list <root> against a wordfile in
  1028. **               single-crack format (quiet mode)
  1029. **      returns: nothing
  1030. */
  1031.  
  1032. void crk_s_q(root)
  1033.     register struct acc_list *root;
  1034. {
  1035.     register char            to_remove=0, i=0;
  1036.     register BU64            ec;
  1037.     register struct acc_list *cur, *remove;
  1038.     static   time_t          temp;
  1039.  
  1040.     lastuser=0;
  1041.     for(cur=root; (cur) && (lastword[0]); ) {
  1042.         lastuser++;
  1043.         do {
  1044.             if (!strcmp(lastword, "***!***")) {
  1045.                 if (!nextword())
  1046.                     lastword[0]=0;
  1047.                 break;
  1048.             }
  1049.             ec=bcrypt_encode(cur->SL[0], cur->SL[1]);
  1050.             combinations++;
  1051.  
  1052. #ifndef _UNIX
  1053.             if (timeout) {
  1054.                 if (i++>=30) {
  1055.                     if ((timeout*60L)<(time(&temp)-timer))
  1056.                         handler();
  1057.                     i=0;
  1058.                 }
  1059.             }
  1060. #endif
  1061.  
  1062.             if ((ec.L.U==cur->encode.L.U) && (ec.R.U==cur->encode.R.U)) {
  1063.                 cracked++;
  1064.                 found_valid(cur->login, lastword, cur->uid, cur->gid,
  1065.                     cur->gecos, cur->home, cur->shell, 0);
  1066.                 remove=cur;
  1067.                 to_remove=1;
  1068.                 cur=cur->prev;
  1069.                 root=acc_remove(root, remove);
  1070.                 if (!root)
  1071.                     return;
  1072.                 while(nextword()) {
  1073.                     if (!strcmp(lastword, "***!***")) {
  1074.                         if (!nextword())
  1075.                             lastword[0]=0;
  1076.                         break;
  1077.                     }
  1078.                 }
  1079.                 break;
  1080.             }
  1081.         } while(nextword());
  1082.         if (to_remove)
  1083.             to_remove=0;
  1084.         else
  1085.             cur=cur->prev;
  1086.     }
  1087. }
  1088.  
  1089. /*==========================================================================*/
  1090.  
  1091. /*
  1092. **     function: void crk_q(struct acc_list *root)
  1093. **  description: cracks the given linked-list <root> against a wordfile
  1094. **               (quiet mode)
  1095. **      returns: nothing
  1096. */
  1097.  
  1098. void crk_q(root)
  1099.     register struct acc_list *root;
  1100. {
  1101.     register char            i=0;
  1102.     register BU64            ec;
  1103.     register struct acc_list *cur, *remove;
  1104.     static   time_t          temp;
  1105.  
  1106.     do {
  1107.         for(cur=root; cur; ) {
  1108.             ec=bcrypt_encode(cur->SL[0], cur->SL[1]);
  1109.             combinations++;
  1110.  
  1111. #ifndef _UNIX
  1112.             if (timeout) {
  1113.                 if (i++>=30) {
  1114.                     if ((timeout*60L)<(time(&temp)-timer))
  1115.                         handler();
  1116.                     i=0;
  1117.                 }
  1118.             }
  1119. #endif
  1120.  
  1121.             if ((ec.L.U==cur->encode.L.U) && (ec.R.U==cur->encode.R.U)) {
  1122.                 cracked++;
  1123.                 found_valid(cur->login, lastword, cur->uid, cur->gid,
  1124.                     cur->gecos, cur->home, cur->shell, 0);
  1125.                 remove=cur;
  1126.                 cur=cur->prev;
  1127.                 root=acc_remove(root, remove);
  1128.                 if (!root)
  1129.                     return;
  1130.             }
  1131.             else
  1132.                 cur=cur->prev;
  1133.         }
  1134.     } while(nextword());
  1135. }
  1136.  
  1137. /*==========================================================================*/
  1138.  
  1139. /*
  1140. **     function: void test_crypt(void)
  1141. **  description: performs one crypt and compares the result against a
  1142. **               pre-computed value
  1143. **      returns: nothing
  1144. */
  1145.  
  1146. #define ENCRYPTED_TEST_PASSWORD  "MX4WdnjbWMTKQ"
  1147. #define PLAINTEXT_TEST_PASSWORD  "robert"
  1148.  
  1149. void test_crypt()
  1150. {
  1151.     char   epw[21];
  1152.     U32    SL[2];
  1153.     BU64   epwcode, resultcode;
  1154.  
  1155.     print_title();
  1156.     printf("Testing encrypted password '%s' as '%s'...",
  1157.         ENCRYPTED_TEST_PASSWORD, PLAINTEXT_TEST_PASSWORD);
  1158.     strcpy(epw, ENCRYPTED_TEST_PASSWORD);
  1159.     bcrypt_init();
  1160.     bcrypt_salt_to_E(epw[0], epw[1], SL);
  1161.     epwcode=bcrypt_pw_to_BU64(epw+2);
  1162.     bcrypt_set_word(PLAINTEXT_TEST_PASSWORD);
  1163.     resultcode=bcrypt_encode(SL[0], SL[1]);
  1164.  
  1165. #if defined(_TURBO) || defined(_MICROSOFT)
  1166.     bcrypt_done();
  1167. #endif
  1168.  
  1169.     if ((epwcode.L.U==resultcode.L.U) && (epwcode.R.U==resultcode.R.U)) {
  1170.         printf("\n\nTest complete.  No errors detected.\n");
  1171.         exit(0);
  1172.     }
  1173.     else {
  1174.         printf("\n\nEncryption/compare error.  The encrypted plaintext password");
  1175.         printf("\ndid not match the encrypted password.\n");
  1176.         exit(1);
  1177.     }
  1178. }
  1179.  
  1180. /*==========================================================================*/
  1181.  
  1182. /*
  1183. **     function: int getcmd(char *name)
  1184. **  description: searches [cmdtab] for a matching command
  1185. **      returns: value assigned to each command in [cmdtab] or ERROR_FLAG
  1186. **               upon error
  1187. */
  1188.  
  1189. int getcmd(name)
  1190.     char *name;
  1191. {
  1192.     struct cmd *c;
  1193.  
  1194.     for(c=cmdtab; c; c++) {
  1195.         if (!strncmp(name, c->cmd_name, c->unique)) {
  1196.             if (strlen(name)<=strlen(c->cmd_name)) {
  1197.                 if (!strncmp(name, c->cmd_name, strlen(name)))
  1198.                     return(c->cmd_code);
  1199.             }
  1200.             return(ERROR_FLAG);
  1201.         }
  1202.     }
  1203.     return(ERROR_FLAG);
  1204. }
  1205.  
  1206. /*==========================================================================*/
  1207.  
  1208. /*
  1209. **     function: void process_arg(char *arg)
  1210. **  description: processes the value of one command line argument
  1211. **      returns: nothing
  1212. */
  1213.  
  1214. void process_arg(arg)
  1215.     char *arg;
  1216. {
  1217.     register int  i, result_code;
  1218.     static   char tail[MAX_TAIL];
  1219.  
  1220.     tail[0]=0;
  1221.     for(i=0; (arg[i]!=':') && (arg[i]); i++)
  1222.         ;
  1223.     if (arg[i]) {
  1224.         strcpy(tail, &arg[i+1]);
  1225.         arg[i]=0;
  1226.     }
  1227.     result_code=getcmd(lowcase(arg));
  1228.     switch(result_code) {
  1229.         case HELP_FLAG:
  1230.             print_title();
  1231.             print_usage();
  1232.             exit(0);
  1233.             break;
  1234.  
  1235. #ifdef _UNIX
  1236.         case FORK_FLAG:
  1237.             fork_process=1;
  1238.             quiet=1;
  1239.             break;
  1240. #endif
  1241.  
  1242.         case INACTIVE_FLAG:
  1243.             inactive=1;
  1244.             break;
  1245.  
  1246. #ifdef _BSD
  1247.         case MAXIMIZE_FLAG:
  1248.             maximize=1;
  1249.             break;
  1250. #endif
  1251.  
  1252.         case PWFILE_FLAG:
  1253.             strcpy(pwfile, tail);
  1254.             break;
  1255.         case QUIET_FLAG:
  1256.             quiet=1;
  1257.             break;
  1258.         case RESTORE_FLAG:
  1259.             init_vars();
  1260.             strcpy(restorefile, tail);
  1261.             restoring=1;
  1262.             break;
  1263.         case SINGLE_FLAG:
  1264.             single=1;
  1265.             break;
  1266.         case STDIN_FLAG:
  1267.             stdin_words=1;
  1268.             break;
  1269.         case TEST_FLAG:
  1270.             test_crypt();
  1271.             break;
  1272.         case TIMEOUT_FLAG:
  1273.             timeout=atol(tail);
  1274.             break;
  1275.         case VALIDFILE_FLAG:
  1276.             strcpy(validfile, tail);
  1277.             break;
  1278.         case WORDFILE_FLAG:
  1279.             strcpy(wordfile, tail);
  1280.             break;
  1281.         default:
  1282.             kc_exit(1, "invalid argument", arg);
  1283.             break;
  1284.     }
  1285. }
  1286.  
  1287. /*===========================================================================*/
  1288.  
  1289. /*
  1290. **     function: char *get_next_token(char *s, char c)
  1291. **  description: reads the next token delimited by <c> from <s>
  1292. **      returns: token read
  1293. */
  1294.  
  1295. char *get_next_token(s, c)
  1296.     register char *s, c;
  1297. {
  1298.     register int i, j;
  1299.     static   char token[MAX_TAIL];
  1300.  
  1301.     for(i=0; s[i]!=c; i++)
  1302.         ;
  1303.     i++;
  1304.     for(j=0; (s[i]) && (s[i]!='\r') && (s[i]!='\n'); i++, j++)
  1305.         token[j]=s[i];
  1306.     token[j]=0;
  1307.     return(token);
  1308. }
  1309.  
  1310. /*===========================================================================*/
  1311.  
  1312. /*
  1313. **     function: char *get_first_token(char *s, char c)
  1314. **  description: reads the first token delimited by <c> from <s>
  1315. **      returns: token read
  1316. */
  1317.  
  1318. char *get_first_token(s, c)
  1319.     register char *s, c;
  1320. {
  1321.     register int i;
  1322.     static   char token[MAX_TAIL];
  1323.  
  1324.     for(i=0; ((token[i]=s[i])!=c); i++)
  1325.         ;
  1326.     token[i]=0;
  1327.     return(token);
  1328. }
  1329.  
  1330. /*==========================================================================*/
  1331.  
  1332. /*
  1333. **     function: void restore_session(void)
  1334. **  description: reads saved information from [restorefile] and prepares
  1335. **               to begin the restored session
  1336. **      returns: nothing
  1337. */
  1338.  
  1339. void restore_session()
  1340. {
  1341.     FILE *rf;
  1342.     char s[MAX_LINE], s1[MAX_LINE];
  1343.  
  1344.     rf=fopen(restorefile, "r");
  1345.     if (!rf)
  1346.         kc_exit(1, "error opening restorefile", restorefile);
  1347.     while(fgets(s, MAX_LINE-1, rf)) {
  1348.         strcpy(s1, lowcase(get_first_token(s, '=')));
  1349.         if (!strcmp(s1, "pwfile"))
  1350.             strcpy(pwfile, get_next_token(s, '='));
  1351.         else if (!strcmp(s1, "wordfile"))
  1352.             strcpy(wordfile, get_next_token(s, '='));
  1353.         else if (!strcmp(s1, "validfile"))
  1354.             strcpy(validfile, get_next_token(s, '='));
  1355.         else if (!strcmp(s1, "flag"))
  1356.             process_arg(get_next_token(s, '='));
  1357.         else if (!strcmp(s1, "lastuser"))
  1358.             lastuser=atoi(get_next_token(s, '='));
  1359.         else if (!strcmp(s1, "lastword"))
  1360.             strcpy(lastword, get_next_token(s, '='));
  1361.         else
  1362.             kc_exit(1, "invalid restorefile identifier", s1);
  1363.     }
  1364.     fclose(rf);
  1365.     if (!quiet)
  1366.         print_title();
  1367.     if ((!pwfile[0]) || (!validfile[0]) ||
  1368.         ((!wordfile[0]) && (!stdin_words)))
  1369.         kc_exit(1, "some files not specified", NULL);
  1370.     if ((single) && (!lastuser))
  1371.         kc_exit(1, "last user not specified", NULL);
  1372.     if ((!single) && (!lastword[0]))
  1373.         kc_exit(1, "last word not specified", NULL);
  1374.     if ((!strcmp(lastword, "****DONE*****")) || (lastuser==-1))
  1375.         kc_exit(1, "session previously completed", NULL);
  1376.     if (!quiet) {
  1377.         print_files();
  1378.         print_stat();
  1379.     }
  1380. }
  1381.  
  1382. /*===========================================================================*/
  1383.  
  1384. /*
  1385. **     function: struct acc_list *set_data_pointers(struct acc_list *root)
  1386. **  description: forwards the linked-list and wordfile to the appropriate
  1387. **               index for proper continuation of a restored session
  1388. **      returns: root of new list
  1389. */
  1390.  
  1391. struct acc_list *set_data_pointers(root)
  1392.     struct acc_list *root;
  1393. {
  1394.     int             i;
  1395.     char            word[MAX_WORD];
  1396.     struct acc_list *cur, *remove;
  1397.  
  1398.     if (single) {
  1399.         for(i=1, cur=root; i<lastuser; i++) {
  1400.             remove=cur;
  1401.             cur=cur->next;
  1402.             root=acc_remove(root, remove);
  1403.             do {
  1404.                 i=restore_nextword(word);
  1405.                 if (!i)
  1406.                     kc_exit(1, "single word set not found", NULL);
  1407.             } while(strcmp(word, "***!***"));
  1408.         }
  1409.         nextword();
  1410.     }
  1411.     else {
  1412.         do {
  1413.             i=restore_nextword(word);
  1414.             if (!i)
  1415.                 kc_exit(1, "word not found", lastword);
  1416.         } while(strcmp(word, lastword));
  1417.     }
  1418.     return(root);
  1419. }
  1420.  
  1421. /*==========================================================================*/
  1422.  
  1423. struct acc_list *set_last(root)
  1424.     struct acc_list *root;
  1425. {
  1426.     struct acc_list *cur;
  1427.  
  1428.     for(cur=root; cur->next; cur=cur->next)
  1429.         ;
  1430.     return(cur);
  1431. }
  1432.  
  1433. /*===========================================================================*/
  1434.  
  1435. /*
  1436. **     function: void set_signals(void)
  1437. **  description: sets up all signal/interrupt routines
  1438. **      returns: nothing
  1439. */
  1440.  
  1441. void set_signals()
  1442. {
  1443.  
  1444. #ifdef _MSDOS
  1445.     signal(SIGINT, handler);
  1446. #endif
  1447.  
  1448. #ifdef _UNIX
  1449.     signal(SIGINT, handler);
  1450.     signal(SIGQUIT, handler);
  1451.     signal(SIGTERM, handler);
  1452.     signal(SIGALRM, handler);
  1453.     signal(SIGHUP, SIG_IGN);
  1454. #endif
  1455.  
  1456. }
  1457. #endif
  1458.  
  1459. /*==========================================================================*/
  1460.  
  1461. /*
  1462. **     function: void maximize_resources(void)
  1463. **  description: sets the current resource limit to the maximum allowed
  1464. **               resource limit (BSD versions only)
  1465. **      returns: nothing
  1466. */
  1467.  
  1468. #ifdef _BSD
  1469. void maximize_resources()
  1470. {
  1471.     struct rlimit r;
  1472.  
  1473.     getrlimit(RLIMIT_CPU, &r);
  1474.     r.rlim_cur=r.rlim_max;
  1475.     setrlimit(RLIMIT_CPU, &r);
  1476. }
  1477. #endif
  1478.  
  1479. /*===========================================================================*/
  1480.  
  1481. /*
  1482. **     function: void bg_process(void)
  1483. **  description: puts the session process into the background (Unix only)
  1484. **      returns: nothing
  1485. */
  1486.  
  1487. #ifdef _UNIX
  1488. void bg_process()
  1489. {
  1490.     if (isatty(0)) {
  1491.         close(0);
  1492.         close(1);
  1493.         close(2);
  1494.         if (fork())
  1495.             exit(0);
  1496.     }
  1497.     else {
  1498.         close(0);
  1499.         close(1);
  1500.         close(2);
  1501.     }
  1502. }
  1503. #endif
  1504.  
  1505. /*===========================================================================*/
  1506.  
  1507. /*
  1508. **     function: void session(void)
  1509. **  description: prepares & executes the current crack session
  1510. **      returns: nothing
  1511. */
  1512.  
  1513. void session()
  1514. {
  1515.     char            s[81];
  1516.     time_t          temp;
  1517.     struct acc_list *root;
  1518.  
  1519.     if (!quiet) {
  1520.         print_title();
  1521.         if (((!pwfile[0]) || (!validfile[0])) && (stdin_words))
  1522.             kc_exit(1, "some files not specified", NULL);
  1523.         print_files();
  1524.     }
  1525.     if ((!pwfile[0]) || ((!wordfile[0]) && (!stdin_words)) ||
  1526.         (!validfile[0]))
  1527.         kc_exit(1, "some files not specified", NULL);
  1528.     if (!quiet)
  1529.         print_stat();
  1530.  
  1531. #ifndef _STRIPPED
  1532.     set_signals();
  1533. #endif
  1534.  
  1535.     if (!stdin_words)
  1536.         if (open_words()<0)
  1537.             kc_exit(1, "error opening wordfile", wordfile);
  1538.     if (open_valid()<0)
  1539.         kc_exit(1, "error opening validfile", validfile);
  1540.  
  1541.     if (!quiet) 
  1542.         show_string("Initializing session data...");
  1543.                 
  1544.     root=read_pwfile();
  1545.     if (!quiet) {
  1546.         sprintf(s, "\nLoaded %d total accounts.\n", num_accs); 
  1547.         show_string(s);
  1548.         show_string("\n\n");
  1549.         show_string("Stripping accounts...  ");
  1550.     }
  1551.     root=acc_strip(root);
  1552.     if (!quiet)
  1553.         show_string("\n\n");
  1554.     bcrypt_init();
  1555.  
  1556. #ifdef _UNIX
  1557.     if (fork_process)
  1558.         bg_process();
  1559.     if (timeout)
  1560.         alarm((timeout*60));
  1561. #endif
  1562.  
  1563. #ifdef _BSD
  1564.     if (maximize)
  1565.         maximize_resources();
  1566. #endif
  1567.  
  1568.     fflush(stdout);
  1569.     if (restoring) {
  1570.         if (single)
  1571.             root=set_data_pointers();
  1572.         else
  1573.             set_data_pointers();
  1574.     }
  1575.     else
  1576.         nextword();
  1577.     root=set_last(root);
  1578.     if (!quiet)
  1579.         show_string("Cracking...\n");
  1580.     timer=time(&temp);
  1581.     if (single)
  1582.         if (quiet)
  1583.             crk_s_q(root);
  1584.         else
  1585.             crk_s(root);
  1586.     else
  1587.         if (quiet)
  1588.             crk_q(root);
  1589.         else
  1590.             crk(root);
  1591.     close_all(time(&temp)-timer);
  1592.     if (restorefile[0])
  1593.         save_options(1);
  1594.     if (!quiet)
  1595.         show_string("\n");
  1596.     kc_exit(0, "session complete", NULL);
  1597. }
  1598.  
  1599. /*==========================================================================*/
  1600.  
  1601. /*
  1602. **     function: void main(int argc, char **argv)
  1603. **  description: main function
  1604. **      returns: nothing
  1605. */
  1606.  
  1607. void main(argc, argv)
  1608.     int  argc;
  1609.     char **argv;
  1610. {
  1611.     char s[MAX_LINE];
  1612.  
  1613.     init_vars();
  1614.     strcpy(progname, *argv);
  1615.     for(; --argc; ) {
  1616.         strcpy(s, *++argv);
  1617.         if ((s[0]=='-') || (s[0]=='/'))
  1618.             process_arg(&s[1]);
  1619.         else
  1620.             kc_exit(1, "invalid argument", s);
  1621.     }
  1622.     if (restoring)
  1623.         restore_session();
  1624.     session();
  1625. }
  1626.