home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume22 / crack / part02 < prev    next >
Text File  |  1991-08-23  |  59KB  |  2,932 lines

  1. Newsgroups: comp.sources.misc
  2. From: Alec David Muffett <aem@aber.ac.uk>
  3. Subject:  v22i050:  crack - The Password Cracker, version 3.2a, Part02/04
  4. Message-ID: <1991Aug23.150416.999@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 14cb360e7ff676b07065904a1d45e698
  6. Date: Fri, 23 Aug 1991 15:04:16 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Alec David Muffett <aem@aber.ac.uk>
  10. Posting-number: Volume 22, Issue 50
  11. Archive-name: crack/part02
  12. Environment: UNIX
  13.  
  14. #! /bin/sh
  15. # it by saving it into a file and typing "sh file".  To overwrite existing
  16. # files, type "sh file -c".  You can also feed this as standard input via
  17. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  18. # will see the following message at the end:
  19. #        "End of archive 2 (of 4)."
  20. # Contents:  APPENDIX Crack DictSrc/bad_pws.dat Sources/crack-pp.c
  21. #   Sources/crack-pwc.c Sources/goodpass.c
  22. # Wrapped by aem@aberda on Fri Aug 23 13:20:41 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'APPENDIX' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'APPENDIX'\"
  26. else
  27. echo shar: Extracting \"'APPENDIX'\" \(12711 characters\)
  28. sed "s/^X//" >'APPENDIX' <<'END_OF_FILE'
  29. XOdds and sods that I thought are interesting:
  30. X
  31. X********
  32. X
  33. XSeveral people have asked me why I don't write Crack so that it
  34. Xdistributes dictionaries over the network and hacks the same password
  35. Xfile on each machine, as opposed to spreading users over the network and
  36. Xusing the same dictionaries.
  37. X
  38. XThere are several reasons for this, which I will outline.
  39. X
  40. XThe reasoning that spreading the dictionaries over the network is faster
  41. Xis correct in the case of cracking the passwords of ONE user - it is
  42. Xmost efficient to run different dictionaries on him on several machines,
  43. Xand you will break his password eventually.
  44. X
  45. XScaling this by a factor of 'n' users causes problems.  Firstly, if a
  46. Xmachine guesses one persons password, it must inform all others on the
  47. Xnetwork not to waste time cracking him, but to get on with the other
  48. Xusers.  This is difficult and nasty.
  49. X
  50. XSecondly, it is not what Crack was designed to do.  The name "Crack" is
  51. Xactually a misnomer - Crack really ought to be called "Passwdcheck" or
  52. Xsomething similar, but such names lack sex appeal.
  53. X
  54. XCrack is not a program designed to break the password of every user in
  55. Xthe file.  Rather, it is designed to find weak passwords in the file, by
  56. Xattacking those sorts of bad passwords which are most likely to be used,
  57. Xin the order in which they would most easily be found (ie: are most
  58. Xlikely to be used by a moronic user).
  59. X
  60. XCrack is not designed to break user passwords; it is designed to break
  61. Xpassword files.  This is a subtle but important distinction.
  62. X
  63. XIf you want to break into a safe, you do not take a hammer at every bit
  64. Xof it in turn; instead, first you try some simple combinations, then you
  65. Xtry blowing the hinges off, then you get out an acetylene torch and go
  66. Xfor the bolt.  If that doesnt work, THEN you start on the walls.  You go
  67. Xfor the bits which are most likely to be weak first.
  68. X
  69. XConsider a password file with 'n' users in it.  Say that your serial
  70. Xpassword cracker uses a dictionary of 1000 words, and tries each word 6
  71. Xways (upper/lower/mixed case, permuted with forwards/backwards)
  72. X
  73. XAlso consider that out of that 1000 users, only one (the last one) has a
  74. Xguessable password - "fred".
  75. X
  76. XAlso say that it takes time 'T' seconds to encrypt a word.
  77. X
  78. XIf you use the "try each user in turn" method, like the COPS password
  79. Xcracker, you will have to wait for a time:-
  80. X
  81. X    999 users * 1000 words * 6 ways * T = 5994000 T seconds
  82. X
  83. Xbefore you get to that last user.  Spreading this load around on a
  84. Xnetwork only alleviates the number of words to be searched (divides them
  85. Xby the number of machines you are working on).
  86. X
  87. XThus, if you use 10 machines, the machine which will guess "fred" will
  88. Xget to that last user in:-
  89. X
  90. X    999 * (1000 / 10) * 6 ways = 599400 T seconds.
  91. X
  92. XAlternatively you can try it the Crack way - "fred" is a word which
  93. Xappears in a forwards dictionary.  You will only wait:-
  94. X
  95. X    999 users * 1000 words * 1st way * T = 999000 T seconds
  96. X
  97. Xto get to that user.  Now split the _USERS_ across 10 machines:-
  98. X
  99. X    (999 / 10) users * 1000 words * 1st way = 99900 T seconds
  100. X
  101. XTo get to his password, in ONLY 17% of the time taken by networking
  102. Xusing the serial cracking method.  This is only a boundary case, but I
  103. Xhope I have illustrated the concept.
  104. X
  105. X********
  106. X
  107. XCrack has several other optimisations because of its structured password
  108. Xguesses.  The figures below are entirely empirical, but I reckon that
  109. Xthey're as good as any:
  110. X
  111. XThe first pass that Crack makes is over the user data user information
  112. Xgleaned from the users' password field.  In my test file, this gets
  113. Xabout 3% of the passwords (out of a total of 11% guessed).  This pass
  114. Xalso completes the quickest of all, working as it does from a very small
  115. Xamount of data, but one which is very frequently used for passwords.
  116. X
  117. XMy test password file is 1150 users big, and the first pass completes in
  118. Xa little over 2 minutes.  In that time Crack gets 35 accounts.
  119. X
  120. XThe first sweep of the second pass, consisting of lowercase dictionary
  121. Xwords, gets about another 5% of the passwords.  This means that, for our
  122. X1150 users, we have now cracked a cumulative total of 91 accounts.  The
  123. Xlength of the first sweep depends on how much CPU and how many
  124. Xdictionaries I supply, but using the Ultrix /usr/dict/words and my
  125. Xbad_pws.dat, over 4 CPUs, it doesn't take much more that a couple of
  126. Xhours.
  127. X
  128. XFor the further sweeps, the percentages cracked per sweep tail off, 2%,
  129. X1%, 0.5%...  But they are the people with fairly exotic passwords, and
  130. Xit's only common sense that that they will take some time to crack.
  131. X
  132. X********
  133. X
  134. XThere is one more major optimisation that I haven't mentioned.  Because
  135. Xof the way the UNIX crypt() algorithm works, each encryption is "salted"
  136. Xwith a two letter sequence which is stored as the first two characters
  137. Xof the encrypted password.  This salting means that the word "fred" can
  138. Xbe encrypted and appear in a password file in (literally) thousands of
  139. Xdifferent ways - so long as each encryption has a different salt.
  140. X
  141. XHence, it makes sense to do things in this manner:
  142. X
  143. X1) sort and group the input data by encryption salt.
  144. X2) for each different groups' encryption salt
  145. X    * get a dictionary word
  146. X    * encrypt it using that salt (This is the time consuming bit)
  147. X    * compare the encryption with each member of the group with that salt
  148. X    * if it matches, you have guessed that users password.
  149. X
  150. XThis knocks (empirical guesswork time again) up to one third of the
  151. Xdictionary encryptions off - thus saving you 0.3 of the time all the
  152. Xdictionary sweeps would ordinarily take.  You can work out this figure
  153. Xyourself: Crack gives this statistic when it says
  154. X
  155. X    pwc: Loaded 'n' password entries into 'm' salted lines.
  156. X
  157. Xso you can work out the percentage of users who have the same salt:-
  158. X
  159. X            x = (m / n) * 100
  160. X
  161. Xand hence the percentage of encryption time that you save = (100 - x).
  162. X
  163. X********
  164. X
  165. XListening to the REM album 'Green' on the way back from the Cropredy
  166. Xfolk festival yesterday, whilst I was thinking over things to do to
  167. XCrack, and I was struck (not for the first time) by the words of the
  168. Xfirst verse to 'World Leader Pretend':-
  169. X
  170. X    I sit at my table, and wage war upon myself.
  171. X    It seems like it's all, it's all for nothing.
  172. X    I know the barricades, and I know the mortar in the wall
  173. X    I recognise the weapons, I use them well.
  174. X
  175. X    This is my mistake, let me make it good,
  176. X    I raised the wall, and I will be the one to knock it down...
  177. X
  178. X- writing password cracking programs gets to you after a bit.
  179. X
  180. X********
  181. X
  182. XSome people have asked me how to generate safe passwords.  This, sadly,
  183. Xhas become a religious issue, and there are now, on USENET, several
  184. Xvociferous "password geeks" who will say "my method is the best", in the
  185. Xsame way that some mathematicians will try to compare so-called "random
  186. Xnumber generating algorithms".  Such statements are pointless.  I'm
  187. Xsorry for adding to the confusion, but I must say that I think they are
  188. Xwrong.
  189. X
  190. XOkay, so I am a security fatalist and a security philosopher, but I am
  191. Xnot going to give and hard and fast answers; rather, I'd like to make
  192. Xsome points and recommendations to the people out there.  Security isn't
  193. Xa tangible thing, it is applied psychology.
  194. X
  195. XThe whole point of a password is to prevent people accessing your
  196. Xsystem, getting into it from outside.  Once someone is inside your
  197. Xsystem, assuming that they have the relevant knowledge of your O/S, it
  198. Xis safest to assume that anyone can get to be 'superuser'.  Your only
  199. Xsecurity once someone is on your system is called "security by
  200. Xobscurity".  If your user has sufficient knowledge, you've "had it". 
  201. X
  202. XThe question isn't "How secure can my system be made?".
  203. X
  204. XThe question really should be, "How much do I care, how much can I trust?".
  205. X
  206. XA system can be perfectly secure without any passwords at all, so long
  207. Xas it is in an environment of people who recognise its purpose and
  208. Xdepend on it.  I say this after having had acounts on several 'public'
  209. Xmachines, which could have been taken to bits by any competent Unix
  210. Xperson, but were largely safe - because when someone worked out who did
  211. Xanything nasty, the culprit was ostracised from the community.  There
  212. X_is_ a caveat to this, however. 
  213. X
  214. XThe problem is the sort of people who go around the world 'collecting'
  215. Xcomputer accounts and breaking machines, those who have either a
  216. Xchildish mentality or an ulterior motive. 
  217. X
  218. XThe former are like the little boys who go around breaking windows and
  219. Xvandalising things 'for kicks'.  They are the ones who see every
  220. Xpassword file as a "NO ENTRY" sign, and therefore, driven by what they
  221. Xthink is anarchy and fun, they break in and smash the place up.  Tell
  222. Xthem that they are behaving like children, and they will behave moreso. 
  223. X
  224. XThe latter are driven by personal motives or money.  Their reasons are
  225. Xtoo complex for me to analyse here. 
  226. X
  227. XThe 'babyish' hackers need a lesson (which I hope that eventually they
  228. Xlearn) that true anarchy is for the general good, and is best achieved
  229. Xby fiat amongst the community.  USENET is a good example - there is a
  230. Xlot of petty bickering and arguing, but an incredible amount of good
  231. Xcomes out of it.  It is anarchy that the old greek philosophers would
  232. Xhave approved of. 
  233. X
  234. XWhat I am trying to say is that, when I say that if someone gets into
  235. Xyour system, you've "had it", you should consider whether there is
  236. Xanything to have "had" in the first place.  There is no point in getting
  237. Xyourself paranoid over security - if you do, you'll lose out.  Don't be
  238. Xtoo paranoid.  Be SENSIBLE instead, and secure your system according to
  239. Xit's needs, and not according to some 'holy bible' of absolute security. 
  240. X
  241. XIf someone gets into your system, you find out how they did it, patch
  242. Xthe hole, check for back doors, brush yourself off, and start again. 
  243. XIt's not the end of the world. 
  244. X
  245. XWhat this statement doesn't address (yet) is the needs of system
  246. Xmanagers who have a REAL need for security - be it corporate data or
  247. Xresearch work - on their system.  As I have said before, most O/S's have
  248. Xgaping holes in them that cannot be entirely filled, and so the users
  249. Xmust be stopped on the doorstep.  At the password login. 
  250. X
  251. XPeople who say that they have a way of generating safe passwords are
  252. Xmisinformed, IMHO.  Saying that the password "wyufwqpl" is secure is as
  253. Xmeaningful as saying that the number "4" is random.  Password security,
  254. Xlike any other form of computer security, is not an absolute, but should
  255. Xbe taken in context. 
  256. X
  257. XYou can't say that a certain method will provide secure, random
  258. Xpasswords, because, in defining an algorithm to create these passwords,
  259. Xyou will use only a subset of all the possible passwords that could ever
  260. Xexist.  You have shrunk the 'search space' for the passwords. 
  261. X
  262. XSomeone merely has to write a password cracker which will search this
  263. Xsmall subset of passwords, in order to break your system.  Passwords
  264. Xgenerated by any algorithm, human or computer based, are merly
  265. Xpseudo-secure, in the same way that numbers can be pseudo-random.  For
  266. Xillustration of this aspect of password security, read the document
  267. X"Password Security, A Case History" by Morris and Thompson.
  268. X
  269. XThere is an incredibly large set of possible passwords in the world, and
  270. Xthe best approach toward choosing a password is not to try to find a way
  271. Xto generate 'secure' passwords - there are no such things - but rather
  272. Xyou should learn to choose passwords which are not easily searched for. 
  273. XPasswords which are out of the 'search space' of most password crackers
  274. Xlike 'Crack'. 
  275. X
  276. XRead the Crack documentation.  See what sort of things other programs
  277. Xlike Crack would search for.  Think of some yourself.  I am not going to
  278. Xspecifically mention methods, you should really work something out for
  279. Xyourself. 
  280. X
  281. XAt the bottom line, the password "fred" is just as secure (random) as
  282. Xthe password "blurflpox"; the only problem is that "fred" is in a more
  283. Xeasily searched part of the "password space". 
  284. X
  285. XBoth of these passwords are more easily found than "Dxk&2+15^N" however. 
  286. XNow you must ask yourself if you can cope with remembering "Dxk&2+15^N". 
  287. X
  288. X8-)
  289. X
  290. X********
  291. X
  292. XI'd like to thank Chris Samuel & Piercarlo (Peter) Grandi for all their
  293. Xhelp in beta-testing Crack, and in Peter's case especially, for dropping
  294. Xme into the deep end of troff.  Die, you bastard.  8->
  295. X
  296. XI'd also like to thank Chris Myers for giving me an archive site to work
  297. Xfrom (saving me a lot of tedious email) and heaps of suggestions. 
  298. X
  299. XSimilarly for Randal Schwartz for his information and Chris Lewis (the
  300. Xpsroff guy) for all his suggestions. 
  301. X                        - alec
  302. X--
  303. XINET: aem@aber.ac.uk      JANET: aem@uk.ac.aber      BITNET: aem%aber@ukacrl
  304. XUUCP: ...!mcsun!ukc!aber!aem         ARPA: aem%uk.ac.aber@nsfnet-relay.ac.uk
  305. XSNAIL: Alec Muffett, Computer Unit, Llandinam UCW, Aberystwyth, UK, SY23 3DB
  306. END_OF_FILE
  307. if test 12711 -ne `wc -c <'APPENDIX'`; then
  308.     echo shar: \"'APPENDIX'\" unpacked with wrong size!
  309. fi
  310. # end of 'APPENDIX'
  311. fi
  312. if test -f 'Crack' -a "${1}" != "-c" ; then 
  313.   echo shar: Will not clobber existing file \"'Crack'\"
  314. else
  315. echo shar: Extracting \"'Crack'\" \(3891 characters\)
  316. sed "s/^X//" >'Crack' <<'END_OF_FILE'
  317. X#!/bin/csh
  318. X
  319. X###
  320. X# This program written by ADE Muffett (aem@aber.ac.uk), August 1991,
  321. X# as part of the 'Crack' password cracking package.
  322. X###
  323. X
  324. X###
  325. X# You must put DOUBLE QUOTES around this is you work relative to ~username
  326. X###
  327. X
  328. Xsetenv CRACK_HOME "~aem/SEC/CRACK32"
  329. X
  330. Xset trash="/dev/null"
  331. Xset remote="FALSE"
  332. Xset default_bin="generic"
  333. Xset tmpfile="/tmp/cpwfs.$$"
  334. Xset net_cf="Scripts/network.conf"
  335. X
  336. X###
  337. X# Check existance of a home directory
  338. X###
  339. X
  340. Xif ( -d $CRACK_HOME ) then
  341. X    cd $CRACK_HOME || exit 1
  342. Xelse
  343. X    echo "Error: The directory $CRACK_HOME does not exist."
  344. X    echo ""
  345. X    echo "Please set the value of CRACK_HOME in the Crack script to the CRACK31"
  346. X    echo "installation directory."
  347. X    echo ""
  348. X    echo "The current working directory is" `pwd`
  349. X    exit 1
  350. Xendif
  351. X
  352. X###
  353. X# Announce ourselves.
  354. X###
  355. X
  356. Xecho "Crack 3.2a Password Cracker by ADE Muffett, 1991"
  357. X
  358. X###
  359. X# Check that we have arguments
  360. X###
  361. X
  362. Xif ( "$1" == "" ) then
  363. X    echo "Usage:    $0 [options] [bindir] passwdfile [...]"
  364. X    echo "Or:       $0 -network [options] passwdfile [...]"
  365. X    echo "With options:-"
  366. X    echo "    -v              - to produce verbose output (if configured)"
  367. X    echo "    -nnicevalue     - to run niced"
  368. X    echo "    -rpointfile     - to recover a crashed-out job"
  369. X    echo "    -Rpointfile     - to recover (with verify) a crashed-out job"
  370. X    exit 1
  371. Xendif
  372. X
  373. X###
  374. X# Parse command line
  375. X###
  376. X
  377. Xset argl=()
  378. X
  379. Xwhile ( 1 )
  380. X    switch ( $1 )
  381. X        case -network:          # push onto the remote machines
  382. X            if ( ! -f $net_cf ) then
  383. X                echo "$0: error: no file $net_cf"
  384. X                exit 1
  385. X            endif
  386. X            shift
  387. X            Scripts/Crack.network $*
  388. X            exit 0
  389. X            breaksw         # redundant
  390. X        case -remote:           # This is being called remotely
  391. X            echo "Invoked: $0 $*"
  392. X            set remote="TRUE"
  393. X            shift
  394. X            breaksw
  395. X        case -v*:                       # verbose
  396. X        case -n*:                       # nice
  397. X        case -r*:                       # recover
  398. X        case -R*:                       # recover/verify
  399. X            set argl=($argl $1)
  400. X            shift
  401. X            breaksw
  402. X        case -*:                        # anything else
  403. X            echo "Crack: unknown argument $1"
  404. X            shift
  405. X            breaksw
  406. X        default:
  407. X            break
  408. X            breaksw                 # redundant
  409. X    endsw
  410. Xend
  411. X
  412. X###
  413. X# Test first non-switch argument for existance
  414. X###
  415. X
  416. Xif ( -f "$1" ) then
  417. X    setenv CRACK_ARCH $CRACK_HOME/$default_bin
  418. X    if ( ! -d $default_bin ) then
  419. X        echo "Making default binary directory: $default_bin"
  420. X        mkdir $default_bin || exit 1
  421. X    endif
  422. Xelse if ( -d "$1" ) then
  423. X    setenv CRACK_ARCH $CRACK_HOME/$1
  424. X    shift
  425. Xelse
  426. X    echo "Crack: error: There is no directory or file $1."
  427. X    echo "Crack: warning: Creating directory $1"
  428. X    mkdir $1 || exit 1
  429. X    setenv CRACK_ARCH $CRACK_HOME/$1
  430. X    shift
  431. Xendif
  432. X
  433. X###
  434. X# Double check the dictionary directory
  435. X###
  436. X
  437. Xif ( ! -d $CRACK_HOME/Dicts ) then
  438. X    echo "Crack: error: There is no directory or file Dicts."
  439. X    echo "Crack: warning: Creating directory Dicts"
  440. X    mkdir Dicts || exit 1
  441. Xendif
  442. X
  443. X###
  444. X# Now to tidy up a bit
  445. X###
  446. X
  447. Xmake -f Scripts/crack.mf cleanprogs >& /dev/null
  448. X
  449. Xecho "Using binaries in directory: $CRACK_ARCH"
  450. X
  451. Xcd $CRACK_ARCH || exit 1                        # Can we get there from here ?
  452. X
  453. X###
  454. X# Install makefiles if necessary.
  455. X###
  456. X
  457. Xif ( ! -f Makefile ) then                       # Has it a Makefile ?
  458. X    cp $CRACK_HOME/Scripts/install.mf Makefile
  459. Xendif
  460. X
  461. Xmake crack-pwc || exit 1                        # Check binaries are OK
  462. X
  463. Xcd $CRACK_HOME                                  # Get back to home base
  464. X
  465. Xmake -f Scripts/crack.mf dictstamp || exit 1    # Make the dictionaries
  466. X
  467. X###
  468. X# Check how we have been invoked : ergo how we get our data.
  469. X###
  470. X
  471. Xif ( "$remote" == "TRUE" ) then
  472. X    cat > $tmpfile                                  # Use stdin
  473. Xelse
  474. X    Scripts/joinfiles $* > $tmpfile || exit 1       # Process the passwords
  475. Xendif
  476. X
  477. Xecho "Backgrounding program. Output will be written to a file in this directory."
  478. X
  479. X$CRACK_ARCH/crack-pwc $argl -i$tmpfile Dicts/dict.* < /dev/null >& $trash &
  480. X
  481. X###
  482. X# There are horrible timeraces involved in removing $tmpfile, so I dont.
  483. X###
  484. END_OF_FILE
  485. if test 3891 -ne `wc -c <'Crack'`; then
  486.     echo shar: \"'Crack'\" unpacked with wrong size!
  487. fi
  488. chmod +x 'Crack'
  489. # end of 'Crack'
  490. fi
  491. if test -f 'DictSrc/bad_pws.dat' -a "${1}" != "-c" ; then 
  492.   echo shar: Will not clobber existing file \"'DictSrc/bad_pws.dat'\"
  493. else
  494. echo shar: Extracting \"'DictSrc/bad_pws.dat'\" \(6485 characters\)
  495. sed "s/^X//" >'DictSrc/bad_pws.dat' <<'END_OF_FILE'
  496. X0
  497. X1
  498. X123456
  499. X12345678
  500. X2
  501. X3
  502. X4
  503. X5
  504. X6
  505. X7
  506. X8
  507. X9
  508. XA
  509. XAdrian
  510. XAdrianna
  511. XAlasdair
  512. XAlbert
  513. XAlex
  514. XAlexander
  515. XAlice
  516. XAlicia
  517. XAlisa
  518. XAlison
  519. XAlistair
  520. XAlister
  521. XAllison
  522. XAmanda
  523. XAmber
  524. XAmy
  525. XAndrea
  526. XAnduin
  527. XAngela
  528. XAngie
  529. XAnita
  530. XAnn
  531. XAnna
  532. XAnne
  533. XAnnette
  534. XApril
  535. XArlene
  536. XArthur
  537. XAthena
  538. XB
  539. XBBROYGBVGW
  540. XBailey
  541. XBarbara
  542. XBart
  543. XBartman
  544. XBecky
  545. XBeryl
  546. XBeth
  547. XBetsie
  548. XBetty
  549. XBeverly
  550. XBishop
  551. XBob
  552. XBrandi
  553. XBrandy
  554. XBrenda
  555. XBridget
  556. XC
  557. XCalvin
  558. XCamille
  559. XCandi
  560. XCandy
  561. XCaren
  562. XCarla
  563. XCarmen
  564. XCarol
  565. XCarole
  566. XCarolina
  567. XCaroline
  568. XCarrie
  569. XCatherine
  570. XCathy
  571. XCecily
  572. XCharity
  573. XCharles
  574. XChristina
  575. XChristine
  576. XChristy
  577. XCindy
  578. XClaudia
  579. XCollins
  580. XConnie
  581. XCornelius
  582. XCristina
  583. XCrystal
  584. XCynthia
  585. XD
  586. XDaisy
  587. XDana
  588. XDaniel
  589. XDanielle
  590. XDawn
  591. XDeb
  592. XDebbie
  593. XDeborah
  594. XDenise
  595. XDesiree
  596. XDiana
  597. XDiane
  598. XDoobrie
  599. XDulce
  600. XDuncan
  601. XE
  602. XEdwina
  603. XEileen
  604. XEinstein
  605. XElaine
  606. XElanor
  607. XElizabeth
  608. XEllen
  609. XEmily
  610. XEmmanuel
  611. XErica
  612. XErika
  613. XErin
  614. XEvelyn
  615. XF
  616. XFelicia
  617. XG
  618. XGabriel
  619. XGeorge
  620. XGertrude
  621. XGilly
  622. XGina
  623. XGinger
  624. XH
  625. XHarvey
  626. XHeather
  627. XHeidi
  628. XHiawatha
  629. XHobbes
  630. XHolly
  631. XI
  632. XIngrid
  633. XIrene
  634. XJ
  635. XJackie
  636. XJane
  637. XJanet
  638. XJanice
  639. XJanie
  640. XJasmin
  641. XJean
  642. XJeanne
  643. XJen
  644. XJenni
  645. XJennifer
  646. XJenny
  647. XJessica
  648. XJill
  649. XJoanne
  650. XJody
  651. XJohnny
  652. XJoseph
  653. XJoshua
  654. XJoy
  655. XJoyce
  656. XJudith
  657. XJudy
  658. XJulia
  659. XJulie
  660. XJune
  661. XK
  662. XKaren
  663. XKarie
  664. XKarina
  665. XKate
  666. XKathleen
  667. XKathrine
  668. XKathy
  669. XKatina
  670. XKatrina
  671. XKelly
  672. XKeri
  673. XKerri
  674. XKerrie
  675. XKerry
  676. XKim
  677. XKimberly
  678. XKitten
  679. XKrista
  680. XKristen
  681. XKristi
  682. XKristie
  683. XKristin
  684. XKristine
  685. XKristy
  686. XL
  687. XLana
  688. XLara
  689. XLaura
  690. XLeah
  691. XLeslie
  692. XLinda
  693. XLisa
  694. XLiz
  695. XLois
  696. XLori
  697. XLorin
  698. XLorraine
  699. XLouis
  700. XLouise
  701. XLucy
  702. XLynn
  703. XLynne
  704. XM
  705. XMVEMJSUNP
  706. XMalcolm
  707. XMara
  708. XMarci
  709. XMarcy
  710. XMaria
  711. XMarietta
  712. XMarni
  713. XMary
  714. XMaurice
  715. XMeagan
  716. XMegan
  717. XMelissa
  718. XMichael
  719. XMichele
  720. XMichelle
  721. XMickey
  722. XMonica
  723. XMortis
  724. XN
  725. XNancy
  726. XNicole
  727. XNita
  728. XNoreen
  729. XO
  730. XOlivia
  731. XP
  732. XPam
  733. XPamela
  734. XPat
  735. XPatricia
  736. XPatty
  737. XPaula
  738. XPenelope
  739. XPierre
  740. XPolly
  741. XQ
  742. XR
  743. XRachel
  744. XRachelle
  745. XRebecca
  746. XRenee
  747. XRobin
  748. XRobyn
  749. XRochelle
  750. XRonald
  751. XRonnie
  752. XRose
  753. XRosemary
  754. XS
  755. XSamantha
  756. XSandra
  757. XSandy
  758. XSara
  759. XSarah
  760. XShannon
  761. XSharon
  762. XSherri
  763. XShirley
  764. XSnarfel
  765. XSondra
  766. XSonia
  767. XSonya
  768. XStacey
  769. XStaci
  770. XStacie
  771. XStacy
  772. XSteph
  773. XStephanie
  774. XSusan
  775. XSusanne
  776. XSusie
  777. XSuzanne
  778. XSuzie
  779. XSybil
  780. XT
  781. XTamara
  782. XTami
  783. XTamie
  784. XTammy
  785. XTara
  786. XTheresa
  787. XTiffany
  788. XTina
  789. XTraci
  790. XTracie
  791. XTracy
  792. XTrisha
  793. XU
  794. XUrsula
  795. XV
  796. XValerie
  797. XVeronica
  798. XVicky
  799. XVirginia
  800. XW
  801. XWOBAFGKMRNS
  802. XWarren
  803. XWendi
  804. XWendy
  805. XWhitney
  806. XWilliam
  807. XWillie
  808. XWilma
  809. XX
  810. XY
  811. XYolanda
  812. XZ
  813. Xa
  814. Xaaa
  815. Xabc
  816. Xabcd
  817. Xabcde
  818. Xabcdef
  819. Xabcdefg
  820. Xabcdefgh
  821. Xacademia
  822. Xacademic
  823. Xaccess
  824. Xada
  825. Xadmin
  826. Xaerobics
  827. Xairplane
  828. Xalbany
  829. Xalbatross
  830. Xalf
  831. Xalgebra
  832. Xalias
  833. Xaliases
  834. Xalpha
  835. Xalphabet
  836. Xama
  837. Xamadeus
  838. Xamorphous
  839. Xanalog
  840. Xanchor
  841. Xandromache
  842. Xandy
  843. Xanimals
  844. Xanswer
  845. Xanthropogenic
  846. Xanvils
  847. Xanything
  848. Xaria
  849. Xariadne
  850. Xarrow
  851. Xasd
  852. Xasdfgh
  853. Xasm
  854. Xasshole
  855. Xatmosphere
  856. Xaztecs
  857. Xazure
  858. Xb
  859. Xbacchus
  860. Xbadass
  861. Xbanana
  862. Xbananas
  863. Xbandit
  864. Xbanks
  865. Xbarber
  866. Xbaritone
  867. Xbasic
  868. Xbass
  869. Xbassoon
  870. Xbatch
  871. Xbatman
  872. Xbeach
  873. Xbeater
  874. Xbeauty
  875. Xbeaver
  876. Xbeethoven
  877. Xbeetledrive
  878. Xbeloved
  879. Xbenz
  880. Xbeowulf
  881. Xberkeley
  882. Xberlin
  883. Xberliner
  884. Xbeta
  885. Xbicameral
  886. Xbitch
  887. Xbizzy
  888. Xbradley
  889. Xbrian
  890. Xbroadway
  891. Xbsd
  892. Xbuggerall
  893. Xbumbling
  894. Xburgess
  895. Xbuzby
  896. Xc
  897. Xcad
  898. Xcampanile
  899. Xcantor
  900. Xcardinal
  901. Xcarmen
  902. Xcarolina
  903. Xcarson
  904. Xcascades
  905. Xcastle
  906. Xcat
  907. Xcayuga
  908. Xceltics
  909. Xcerulean
  910. Xchange
  911. Xcharles
  912. Xcharming
  913. Xcharon
  914. Xchat
  915. Xcheesecake
  916. Xchem
  917. Xchemistry
  918. Xchess
  919. Xchester
  920. Xchocolate
  921. Xcigar
  922. Xcinelli
  923. Xclass
  924. Xclassic
  925. Xcluster
  926. Xclusters
  927. Xcode
  928. Xcoffee
  929. Xcoke
  930. Xcollins
  931. Xcommrades
  932. Xcomputer
  933. Xcomrade
  934. Xcomrades
  935. Xcondo
  936. Xcondom
  937. Xconnect
  938. Xconsole
  939. Xcookie
  940. Xcookie
  941. Xcooper
  942. Xcornelius
  943. Xcouscous
  944. Xcreate
  945. Xcreation
  946. Xcreosote
  947. Xcretin
  948. Xcriminal
  949. Xcshrc
  950. Xd
  951. Xdaemon
  952. Xdancer
  953. Xdaniel
  954. Xdanny
  955. Xdapper
  956. Xdata
  957. Xdave
  958. Xdecember
  959. Xdefault
  960. Xdefoe
  961. Xdeluge
  962. Xdesperate
  963. Xdevelop
  964. Xdevice
  965. Xdial
  966. Xdiet
  967. Xdieter
  968. Xdigital
  969. Xdisc
  970. Xdiscbox
  971. Xdiscovery
  972. Xdisk
  973. Xdisney
  974. Xdog
  975. Xdos
  976. Xdrought
  977. Xe
  978. Xeager
  979. Xearth
  980. Xeasier
  981. Xeasy
  982. Xeatme
  983. Xedges
  984. Xedinburgh
  985. Xedwin
  986. Xegghead
  987. Xeiderdown
  988. Xelephant
  989. Xemail
  990. Xemerald
  991. Xenemy
  992. Xengine
  993. Xengineer
  994. Xenterprise
  995. Xenzyme
  996. Xersatz
  997. Xestablish
  998. Xestate
  999. Xeternity
  1000. Xeuclid
  1001. Xeugene
  1002. Xextension
  1003. Xf
  1004. Xfairway
  1005. Xfender
  1006. Xfermat
  1007. Xferrari
  1008. Xfidelity
  1009. Xfield
  1010. Xfile
  1011. Xfinite
  1012. Xfishers
  1013. Xflakes
  1014. Xfloat
  1015. Xflower
  1016. Xflowers
  1017. Xfoolproof
  1018. Xfootball
  1019. Xforesight
  1020. Xformat
  1021. Xforsythe
  1022. Xfourier
  1023. Xfred
  1024. Xfriend
  1025. Xfrighten
  1026. Xfun
  1027. Xfunction
  1028. Xfungible
  1029. Xg
  1030. Xgabriel
  1031. Xgames
  1032. Xgardner
  1033. Xgarfield
  1034. Xgatt
  1035. Xgauss
  1036. Xgeorge
  1037. Xgertrude
  1038. Xgibson
  1039. Xglacier
  1040. Xgnu
  1041. Xgolf
  1042. Xgolfer
  1043. Xgorgeous
  1044. Xgorges
  1045. Xgosling
  1046. Xgouge
  1047. Xgraham
  1048. Xgrahm
  1049. Xgrass
  1050. Xgroup
  1051. Xgryphon
  1052. Xgucci
  1053. Xguess
  1054. Xguest
  1055. Xguitar
  1056. Xgumption
  1057. Xguntis
  1058. Xgweledigaeth
  1059. Xh
  1060. Xhack
  1061. Xhacker
  1062. Xhal
  1063. Xhamlet
  1064. Xhandily
  1065. Xhappening
  1066. Xharmony
  1067. Xharold
  1068. Xhawaii
  1069. Xhebrides
  1070. Xheinlein
  1071. Xhello
  1072. Xhelp
  1073. Xherbert
  1074. Xhibernia
  1075. Xhidden
  1076. Xhobbit
  1077. Xhomework
  1078. Xhoney
  1079. Xhorse
  1080. Xhorus
  1081. Xhutchins
  1082. Xhydrogen
  1083. Xibm
  1084. Xiluvben
  1085. Ximbroglio
  1086. Ximperial
  1087. Xinclude
  1088. Xingres
  1089. Xingress
  1090. Xinna
  1091. Xinnocuous
  1092. Xinternet
  1093. Xirishman
  1094. Xisis
  1095. Xizzy
  1096. Xj
  1097. Xjapan
  1098. Xjester
  1099. Xjixian
  1100. Xjohnny
  1101. Xjuggle
  1102. Xjupiter
  1103. Xk
  1104. Xkalajira
  1105. Xkermit
  1106. Xkernel
  1107. Xkey
  1108. Xkipper
  1109. Xkirkland
  1110. Xknight
  1111. Xl
  1112. Xladle
  1113. Xlager
  1114. Xlambda
  1115. Xlamination
  1116. Xlarkin
  1117. Xlarry
  1118. Xlazarus
  1119. Xlebesgue
  1120. Xlee
  1121. Xleland
  1122. Xleroy
  1123. Xlewis
  1124. Xlibrary
  1125. Xlight
  1126. Xlisp
  1127. Xllareggub
  1128. Xlock
  1129. Xlockout
  1130. Xlove
  1131. Xm
  1132. Xmacintosh
  1133. Xmack
  1134. Xmaggot
  1135. Xmagic
  1136. Xmail
  1137. Xmaint
  1138. Xmalcom
  1139. Xmanager
  1140. Xmark
  1141. Xmarkus
  1142. Xmars
  1143. Xmarty
  1144. Xmarvin
  1145. Xmaster
  1146. Xmath
  1147. Xmaurice
  1148. Xmellon
  1149. Xmemory
  1150. Xmercury
  1151. Xmerlin
  1152. Xmets
  1153. Xmgr
  1154. Xmichael
  1155. Xmike
  1156. Xminimum
  1157. Xminsky
  1158. Xmit
  1159. Xmodem
  1160. Xmogul
  1161. Xmoguls
  1162. Xmoose
  1163. Xmorley
  1164. Xmortis
  1165. Xmouse
  1166. Xmozart
  1167. Xmuser
  1168. Xmutant
  1169. Xn
  1170. Xnagel
  1171. Xnapoleon
  1172. Xnasa
  1173. Xnepenthe
  1174. Xneptune
  1175. Xness
  1176. Xnet
  1177. Xnetwork
  1178. Xnew
  1179. Xnews
  1180. Xnewton
  1181. Xnext
  1182. Xnobody
  1183. Xnoxious
  1184. Xnuclear
  1185. Xnutrition
  1186. Xnyquist
  1187. Xo
  1188. Xoceanography
  1189. Xocelot
  1190. Xoerhrdle
  1191. Xoffice
  1192. Xolivetti
  1193. Xolivia
  1194. Xopen
  1195. Xoperator
  1196. Xoracle
  1197. Xorca
  1198. Xorchid
  1199. Xorwell
  1200. Xosiris
  1201. Xoutlaw
  1202. Xoxford
  1203. Xp
  1204. Xpacific
  1205. Xpad
  1206. Xpainless
  1207. Xpakistan
  1208. Xpaper
  1209. Xpapers
  1210. Xpass
  1211. Xpassword
  1212. Xpencil
  1213. Xpenguin
  1214. Xpenis
  1215. Xpeoria
  1216. Xpercolate
  1217. Xpersimmon
  1218. Xpersona
  1219. Xpete
  1220. Xpeter
  1221. Xphilip
  1222. Xphoenix
  1223. Xphone
  1224. Xpierre
  1225. Xpizza
  1226. Xplane
  1227. Xplayboy
  1228. Xplover
  1229. Xpluto
  1230. Xplymouth
  1231. Xpolynomial
  1232. Xpondering
  1233. Xpork
  1234. Xporsche
  1235. Xposter
  1236. Xpower
  1237. Xpraise
  1238. Xprecious
  1239. Xprelude
  1240. Xpresto
  1241. Xprince
  1242. Xprinceton
  1243. Xpriv
  1244. Xprivate
  1245. Xprivs
  1246. Xprofessor
  1247. Xprofile
  1248. Xprogram
  1249. Xprotect
  1250. Xprotozoa
  1251. Xpub
  1252. Xpublic
  1253. Xpumpkin
  1254. Xpuneet
  1255. Xpuppet
  1256. Xq
  1257. Xqwerty
  1258. Xqwertyui
  1259. Xr
  1260. Xrabbit
  1261. Xrachmaninoff
  1262. Xrainbow
  1263. Xraindrop
  1264. Xraleigh
  1265. Xrandom
  1266. Xrascal
  1267. Xreagan
  1268. Xreally
  1269. Xregional
  1270. Xremote
  1271. Xrick
  1272. Xripple
  1273. Xrisc
  1274. Xrje
  1275. Xrobot
  1276. Xrobotics
  1277. Xrochester
  1278. Xrodent
  1279. Xrolex
  1280. Xromano
  1281. Xronald
  1282. Xroot
  1283. Xrosebud
  1284. Xroses
  1285. Xruben
  1286. Xrules
  1287. Xruth
  1288. Xs
  1289. Xsal
  1290. Xsaturn
  1291. Xsaxon
  1292. Xscamper
  1293. Xscheme
  1294. Xschool
  1295. Xscott
  1296. Xscotty
  1297. Xsecret
  1298. Xsecurity
  1299. Xsensor
  1300. Xserenity
  1301. Xservice
  1302. Xsesame
  1303. Xsex
  1304. Xsharc
  1305. Xsharks
  1306. Xsharon
  1307. Xsheffield
  1308. Xsheldon
  1309. Xshell
  1310. Xshit
  1311. Xshitforbrains
  1312. Xshiva
  1313. Xshivers
  1314. Xshuttle
  1315. Xsignature
  1316. Xsilverlake
  1317. Xsimon
  1318. Xsimple
  1319. Xsimpsons
  1320. Xsinger
  1321. Xsingle
  1322. Xsmile
  1323. Xsmiles
  1324. Xsmooch
  1325. Xsmother
  1326. Xsnatch
  1327. Xsnoopy
  1328. Xsoap
  1329. Xsocrates
  1330. Xsomebody
  1331. Xsossina
  1332. Xsparrows
  1333. Xspit
  1334. Xsplatter
  1335. Xsplodge
  1336. Xspring
  1337. Xspringer
  1338. Xsquires
  1339. Xstrangle
  1340. Xstratford
  1341. Xstudent
  1342. Xstuttgart
  1343. Xsubway
  1344. Xsuccess
  1345. Xsucker
  1346. Xsummer
  1347. Xsun
  1348. Xsuper
  1349. Xsuperstage
  1350. Xsuperuser
  1351. Xsupport
  1352. Xsupported
  1353. Xsurfer
  1354. Xswearer
  1355. Xsymmetry
  1356. Xsys
  1357. Xsysadmin
  1358. Xsystem
  1359. Xt
  1360. Xtangerine
  1361. Xtape
  1362. Xtarget
  1363. Xtarragon
  1364. Xtaylor
  1365. Xteabag
  1366. Xtech
  1367. Xtelephone
  1368. Xtemptation
  1369. Xtennis
  1370. Xterminal
  1371. Xtest
  1372. Xthailand
  1373. Xthanatos
  1374. Xtiger
  1375. Xtoggle
  1376. Xtomato
  1377. Xtopography
  1378. Xtortoise
  1379. Xtoxic
  1380. Xtoyota
  1381. Xtrails
  1382. Xtransfer
  1383. Xtrivial
  1384. Xtrombone
  1385. Xtty
  1386. Xtubas
  1387. Xtuttle
  1388. Xu
  1389. Xumesh
  1390. Xunhappy
  1391. Xunicorn
  1392. Xunix
  1393. Xunknown
  1394. Xuranus
  1395. Xurchin
  1396. Xutil
  1397. Xutility
  1398. Xuucp
  1399. Xv
  1400. Xvasant
  1401. Xvenus
  1402. Xvertigo
  1403. Xvillage
  1404. Xvirgin
  1405. Xvisitor
  1406. Xvortex
  1407. Xw
  1408. Xwargames
  1409. Xwarren
  1410. Xwater
  1411. Xweenie
  1412. Xwhatever
  1413. Xwhatnot
  1414. Xwhiting
  1415. Xwhitney
  1416. Xwholesale
  1417. Xwill
  1418. Xwilliam
  1419. Xwilliamsburg
  1420. Xwillie
  1421. Xwinston
  1422. Xwisconsin
  1423. Xwizard
  1424. Xwizzy
  1425. Xwombat
  1426. Xwoodwind
  1427. Xword
  1428. Xwork
  1429. Xwormwood
  1430. Xwyoming
  1431. Xx
  1432. Xxerox
  1433. Xxfer
  1434. Xxmodem
  1435. Xxyz
  1436. Xy
  1437. Xyaco
  1438. Xyang
  1439. Xyellowstone
  1440. Xyosemite
  1441. Xz
  1442. Xzap
  1443. Xzerox
  1444. Xzimmerman
  1445. Xzmodem
  1446. Xzxcvbn
  1447. END_OF_FILE
  1448. if test 6485 -ne `wc -c <'DictSrc/bad_pws.dat'`; then
  1449.     echo shar: \"'DictSrc/bad_pws.dat'\" unpacked with wrong size!
  1450. fi
  1451. # end of 'DictSrc/bad_pws.dat'
  1452. fi
  1453. if test -f 'Sources/crack-pp.c' -a "${1}" != "-c" ; then 
  1454.   echo shar: Will not clobber existing file \"'Sources/crack-pp.c'\"
  1455. else
  1456. echo shar: Extracting \"'Sources/crack-pp.c'\" \(4025 characters\)
  1457. sed "s/^X//" >'Sources/crack-pp.c' <<'END_OF_FILE'
  1458. X#include "crack.h"
  1459. X
  1460. X/*
  1461. X * This program is copyright (c) Alec Muffett 1991 except for certain
  1462. X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
  1463. X * Sparry and Alec Muffett.  The author(s) disclaims all responsibility or
  1464. X * liability with respect to it's usage or its effect upon hardware or
  1465. X * computer systems.  This software is in the public domain and is freely
  1466. X * redistributable PROVIDED that this notice remains intact.
  1467. X */
  1468. X
  1469. X
  1470. X/* THIS IS THE STRING TO MODIFY TO ADD OTHER LEADING/TRAILING CHARS */
  1471. X
  1472. Xchar trailing_chars[] = "01";
  1473. X
  1474. X/* These used to be enums. Oh well... non-portability rules OK */
  1475. X#define ORDER_LCF    0
  1476. X#define ORDER_LCFP    1
  1477. X#define ORDER_MCF    2
  1478. X#define ORDER_LCB    3
  1479. X#define ORDER_LCFT    4
  1480. X#define ORDER_UCF    5
  1481. X#define ORDER_UCB    6
  1482. X#define ORDER_MCB    7
  1483. X#define NUMFILES    8
  1484. X
  1485. Xint
  1486. Xmain (argc, argv)
  1487. X    int argc;
  1488. X    char *argv[];
  1489. X{
  1490. X    register int i;
  1491. X    register char *ptr;
  1492. X    int length;
  1493. X    int all_digits;
  1494. X    int all_letters_upper;
  1495. X    int all_letters_lower;
  1496. X    char buffer[STRINGSIZE];
  1497. X
  1498. X    FILE *fp;
  1499. X    FILE *fps[NUMFILES];
  1500. X
  1501. X    if (argc == 1)
  1502. X    {
  1503. X    printf ("Usage:\t%s dictsrc [dictsrc ...]\n", argv[0]);
  1504. X    exit (1);
  1505. X    }
  1506. X    for (i = 0; i < NUMFILES; i++)
  1507. X    {
  1508. X    char scratch[255];
  1509. X
  1510. X    fps[i] = (FILE *) 0;
  1511. X#ifndef CRACK_PLURAL        /* if not defined, skip opening it */
  1512. X    if (i == ORDER_LCFP)
  1513. X    {
  1514. X        continue;
  1515. X    }
  1516. X#endif                /* CRACK_PLURAL */
  1517. X#ifndef CRACK_TRAILING        /* if not defined, skip opening it */
  1518. X    if (i == ORDER_LCFT)
  1519. X    {
  1520. X        continue;
  1521. X    }
  1522. X#endif                /* CRACK_TRAILING */
  1523. X    sprintf (scratch, "dict.%c", i + 'a');
  1524. X    if (!(fps[i] = fopen (scratch, "w")))
  1525. X    {
  1526. X        perror (scratch);
  1527. X        exit (3);
  1528. X    }
  1529. X    }
  1530. X
  1531. X    for (i = 1; argv[i]; i++)
  1532. X    {
  1533. X    if (!(fp = fopen (argv[i], "r")))
  1534. X    {
  1535. X        perror (argv[i]);
  1536. X        exit (1);
  1537. X    }
  1538. X    printf ("dictpp: sourcing from file '%s'\n", argv[i]);
  1539. X
  1540. X    while (fgets (buffer, STRINGSIZE, fp))
  1541. X    {
  1542. X        Trim (buffer);
  1543. X
  1544. X        /* skip single letters and comments*/
  1545. X        if (!*buffer || !buffer[1] || buffer[0] == '#')
  1546. X        {
  1547. X        continue;
  1548. X        }
  1549. X        length = strlen (buffer);
  1550. X#ifndef CRACK_SHORT_PASSWDS
  1551. X        if (length < 5)
  1552. X        {
  1553. X        continue;
  1554. X        }
  1555. X#endif
  1556. X        all_letters_upper = 1;
  1557. X        all_letters_lower = 1;
  1558. X        all_digits = 1;
  1559. X
  1560. X        for (ptr = buffer; *ptr; ptr++)
  1561. X        {
  1562. X        if (!isdigit (*ptr))
  1563. X        {
  1564. X            all_digits = 0;
  1565. X        }
  1566. X        if (isupper (*ptr))
  1567. X        {
  1568. X            all_letters_lower = 0;
  1569. X        } else if (islower (*ptr))
  1570. X        {
  1571. X            all_letters_upper = 0;
  1572. X        }
  1573. X        }
  1574. X
  1575. X        if (all_digits)
  1576. X        {
  1577. X        fprintf (fps[ORDER_LCF], "%.8s\n", buffer);
  1578. X        continue;    /* hehehehehe */
  1579. X        }
  1580. X        if (!all_letters_upper)
  1581. X        {
  1582. X        fprintf (fps[ORDER_UCF], "%.8s\n", Uppercase (buffer));
  1583. X        fprintf (fps[ORDER_UCB], "%.8s\n", Uppercase (Reverse (buffer)));
  1584. X        } else
  1585. X        {
  1586. X        fprintf (fps[ORDER_UCF], "%.8s\n", buffer);
  1587. X        fprintf (fps[ORDER_UCB], "%.8s\n", Reverse (buffer));
  1588. X        }
  1589. X
  1590. X        if (!all_letters_lower)
  1591. X        {
  1592. X        fprintf (fps[ORDER_LCF], "%.8s\n", Lowercase (buffer));
  1593. X        fprintf (fps[ORDER_LCB], "%.8s\n", Lowercase (Reverse (buffer)));
  1594. X        } else
  1595. X        {
  1596. X        fprintf (fps[ORDER_LCF], "%.8s\n", buffer);
  1597. X        fprintf (fps[ORDER_LCB], "%.8s\n", Reverse (buffer));
  1598. X#ifdef CRACK_PLURAL
  1599. X        /* PLURALISATION */
  1600. X        if (length < 8 && buffer[length - 1] != 's')
  1601. X        {
  1602. X            /*
  1603. X             * Fix suggested by Jim Mattson (mattson@cs.ucsc.edu):-
  1604. X             * we should not pluralise anything more than 7 chars
  1605. X             * long, as it is a waste.
  1606. X             */
  1607. X            fprintf (fps[ORDER_LCFP], "%.7ss\n", buffer);
  1608. X        }
  1609. X#endif                /* CRACK_PLURAL */
  1610. X
  1611. X#ifdef CRACK_TRAILING
  1612. X        /* NUMERALISATION */
  1613. X        if (length < 8)
  1614. X        {
  1615. X            for (ptr = trailing_chars; *ptr; ptr++)
  1616. X            {
  1617. X            fprintf (fps[ORDER_LCFT], "%.7s%c\n", buffer, *ptr);
  1618. X            fprintf (fps[ORDER_LCFT], "%c%.7s\n", *ptr, buffer);
  1619. X            }
  1620. X        }
  1621. X#endif                /* CRACK_TRAILING */
  1622. X        }
  1623. X
  1624. X        if (!all_letters_lower && !all_letters_upper)
  1625. X        {
  1626. X        fprintf (fps[ORDER_MCF], "%.8s\n", buffer);
  1627. X        fprintf (fps[ORDER_MCB], "%.8s\n", Reverse (buffer));
  1628. X        }
  1629. X    }
  1630. X    fclose (fp);
  1631. X    }
  1632. X
  1633. X    for (i = 0; i < NUMFILES; i++)
  1634. X    {
  1635. X    if (fps[i])
  1636. X    {
  1637. X        fclose (fps[i]);
  1638. X    }
  1639. X    }
  1640. X}
  1641. END_OF_FILE
  1642. if test 4025 -ne `wc -c <'Sources/crack-pp.c'`; then
  1643.     echo shar: \"'Sources/crack-pp.c'\" unpacked with wrong size!
  1644. fi
  1645. # end of 'Sources/crack-pp.c'
  1646. fi
  1647. if test -f 'Sources/crack-pwc.c' -a "${1}" != "-c" ; then 
  1648.   echo shar: Will not clobber existing file \"'Sources/crack-pwc.c'\"
  1649. else
  1650. echo shar: Extracting \"'Sources/crack-pwc.c'\" \(17109 characters\)
  1651. sed "s/^X//" >'Sources/crack-pwc.c' <<'END_OF_FILE'
  1652. X#include "crack.h"
  1653. Xchar version[] = "3.2a";    /* version of prog */
  1654. X
  1655. X/*
  1656. X * This program is copyright (c) Alec Muffett 1991 except for certain
  1657. X * portions of code ("crack-fcrypt.c") copyright (c) Robert Baldwin, Icarus
  1658. X * Sparry and Alec Muffett.  The author(s) disclaims all responsibility or
  1659. X * liability with respect to it's usage or its effect upon hardware or
  1660. X * computer systems.  This software is in the public domain and is freely
  1661. X * redistributable PROVIDED that this notice remains intact.
  1662. X */
  1663. X
  1664. X/*
  1665. X * crack-pwc.c - an optimised password cracker. (c) ADE Muffett, July 1991.
  1666. X * Totally rewritten from an 'standard' password cracker that had been
  1667. X * floating about on ther network. Apart from the entire re-write, to save my
  1668. X * sanity, this thing orders passwords to minimise calls to crypt(). Use
  1669. X * fcrypt() where you have it.
  1670. X */
  1671. X
  1672. X/* Structure definitions */
  1673. X
  1674. Xstruct USER_ENTRY
  1675. X{
  1676. X    int done;
  1677. X    char *filename;
  1678. X    struct passwd passwd;
  1679. X    struct USER_ENTRY *across;
  1680. X    struct USER_ENTRY *next;
  1681. X};
  1682. X
  1683. Xstruct DICT_ENTRY
  1684. X{
  1685. X    char *word;
  1686. X    struct DICT_ENTRY *next;
  1687. X};
  1688. X/* Variable declarations */
  1689. X
  1690. Xstruct USER_ENTRY *user_root;    /* root of the USER linked list */
  1691. X
  1692. Xint verify_recover;        /* we will doublecheck usernames on recovery */
  1693. Xint recover_bool;        /* we are trying to recover from a crash */
  1694. Xint rpid;            /* pid we are recovering */
  1695. Xint rusercount;            /* count of user we are recovering at;
  1696. X                 * strictly, this is the line of the user we
  1697. X                 * are recovering */
  1698. Xchar rdict[STRINGSIZE];        /* dict we are recovering */
  1699. Xchar rusername[STRINGSIZE];    /* username we are recovering */
  1700. X#ifdef CRACK_NETWORK
  1701. Xchar rhostname[STRINGSIZE];    /* hostname we are recovering on */
  1702. X#endif
  1703. X
  1704. Xint verbose_bool;        /* is verbose switched on ? */
  1705. X
  1706. Xint pid;            /* pid of parent process */
  1707. Xchar opfile[STRINGSIZE];    /* name of output file */
  1708. Xchar diefile[STRINGSIZE];    /* name of diefile */
  1709. Xchar pointfile[STRINGSIZE];    /* name of pointfile */
  1710. X
  1711. X#ifdef CRACK_NETWORK
  1712. Xchar hostname[STRINGSIZE];
  1713. X#endif
  1714. X
  1715. X/*
  1716. X * DIDDY LITTLE USEFUL FUNCTIONS
  1717. X */
  1718. X
  1719. Xvoid
  1720. XLog (fmt, a, b, c, d, e, f, g, h, i, j)
  1721. X    char *fmt;
  1722. X{
  1723. X    long t;
  1724. X
  1725. X    time (&t);
  1726. X    printf ("pwc: %-15.15s ", ctime (&t) + 4);
  1727. X    printf (fmt, a, b, c, d, e, f, g, h, i, j);
  1728. X    fflush (stdout);
  1729. X}
  1730. X
  1731. Xvoid
  1732. XCatchTERM ()
  1733. X{
  1734. X    /* bury magnets */
  1735. X    Log ("Caught a SIGTERM! Commiting suicide...\n");
  1736. X    /* swallow the rapture */
  1737. X    Log ("<argh!>\n");
  1738. X    /* let's gather feathers */
  1739. X    sync ();
  1740. X    /* don't fall on me */
  1741. X    exit (0);
  1742. X}
  1743. X
  1744. Xvoid
  1745. XSetPoint (dict, usernumber, username)    /* Sets the pointfile up */
  1746. X    char *dict;
  1747. X    int usernumber;
  1748. X    char *username;
  1749. X{
  1750. X    FILE *fp;
  1751. X
  1752. X    if (!(fp = fopen (pointfile, "w")))
  1753. X    {
  1754. X    perror (pointfile);
  1755. X    return;
  1756. X    }
  1757. X#ifdef CRACK_NETWORK
  1758. X    fprintf (fp, "%s\n", hostname);
  1759. X#endif
  1760. X    fprintf (fp, "%d\n", pid);
  1761. X    fprintf (fp, "%s\n", dict);
  1762. X    fprintf (fp, "%d\n", usernumber);
  1763. X    fprintf (fp, "%s\n", username);
  1764. X    fclose (fp);
  1765. X}
  1766. X
  1767. Xint                /* returns 0 if OK, -1 if not recovering */
  1768. XGetPoint (pf)
  1769. X    char *pf;
  1770. X{
  1771. X    FILE *fp;
  1772. X    char buffer[STRINGSIZE];
  1773. X
  1774. X    if (!(fp = fopen (pf, "r")))
  1775. X    {
  1776. X    perror (pf);
  1777. X    return (-1);
  1778. X    }
  1779. X#ifdef CRACK_NETWORK
  1780. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the hostname */
  1781. X    {
  1782. X    fprintf (stderr, "get hostname flopped\n");
  1783. X    return (-1);
  1784. X    }
  1785. X    Trim (buffer);
  1786. X
  1787. X    if (strcmp (buffer, hostname))    /* Not running on original host */
  1788. X    {
  1789. X    fprintf (stderr, "cmp hostname flopped\n");
  1790. X    return (-1);
  1791. X    }
  1792. X    strcpy (rhostname, buffer);
  1793. X#endif
  1794. X
  1795. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the pid */
  1796. X    {
  1797. X    fprintf (stderr, "get pid flopped\n");
  1798. X    return (-1);
  1799. X    }
  1800. X    Trim (buffer);
  1801. X    rpid = atoi (buffer);
  1802. X
  1803. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the dictname */
  1804. X    {
  1805. X    fprintf (stderr, "get dict flopped\n");
  1806. X    return (-1);
  1807. X    }
  1808. X    Trim (buffer);
  1809. X    strcpy (rdict, buffer);
  1810. X
  1811. X    if (!fgets (buffer, STRINGSIZE, fp))
  1812. X    {
  1813. X    fprintf (stderr, "get usercount flopped\n");
  1814. X    return (-1);
  1815. X    }
  1816. X    Trim (buffer);
  1817. X    rusercount = atoi (buffer);    /* Get the usernumber to recover */
  1818. X
  1819. X    if (!fgets (buffer, STRINGSIZE, fp))    /* Get the username */
  1820. X    {
  1821. X    fprintf (stderr, "get username flopped\n");
  1822. X    return (-1);
  1823. X    }
  1824. X    Trim (buffer);
  1825. X    strcpy (rusername, buffer);
  1826. X
  1827. X    fclose (fp);
  1828. X    return (0);
  1829. X}
  1830. X/*
  1831. X * STRUCTURE SPECIFIC FUNCTIONS
  1832. X */
  1833. X
  1834. Xchar *
  1835. XPWSkip (p)            /* jump the ':' in a pwent */
  1836. X    register char *p;
  1837. X{
  1838. X    while (*p && *p != ':')
  1839. X    {
  1840. X    p++;
  1841. X    }
  1842. X    if (*p)
  1843. X    {
  1844. X    *p++ = '\0';
  1845. X    }
  1846. X    return (p);
  1847. X}
  1848. X
  1849. Xstruct USER_ENTRY *
  1850. XParse (buffer)            /* break up input into a structure */
  1851. X    register char *buffer;
  1852. X{
  1853. X    register char *p;
  1854. X    register struct USER_ENTRY *retval;
  1855. X
  1856. X    retval = (struct USER_ENTRY *) malloc (sizeof (struct USER_ENTRY));
  1857. X    retval -> next = retval -> across = NULL;
  1858. X    retval -> done = 0;
  1859. X    Trim (buffer);
  1860. X
  1861. X    p = Clone (buffer);
  1862. X    retval -> filename = p;
  1863. X    p = PWSkip (p);
  1864. X    retval -> passwd.pw_name = p;
  1865. X    p = PWSkip (p);
  1866. X    retval -> passwd.pw_passwd = p;
  1867. X    p = PWSkip (p);
  1868. X    retval -> passwd.pw_uid = 1;
  1869. X    p = PWSkip (p);
  1870. X    retval -> passwd.pw_gid = 1;
  1871. X    p = PWSkip (p);
  1872. X    retval -> passwd.pw_gecos = p;
  1873. X    p = PWSkip (p);
  1874. X    retval -> passwd.pw_dir = p;
  1875. X    p = PWSkip (p);
  1876. X    retval -> passwd.pw_shell = p;
  1877. X    return (retval);
  1878. X}
  1879. X/*
  1880. X * START OF MODULES
  1881. X */
  1882. X
  1883. Xvoid
  1884. XLoadData ()            /* load sorted entries into memory */
  1885. X{
  1886. X    char *ptr;
  1887. X    char salt[2];
  1888. X    char buffer[STRINGSIZE];
  1889. X    int numlines;
  1890. X    int numentries;
  1891. X    register struct USER_ENTRY *new_element;
  1892. X    register struct USER_ENTRY *current_line;
  1893. X
  1894. X    numlines = 0;
  1895. X    numentries = 0;
  1896. X    current_line = NULL;
  1897. X
  1898. X    while (fgets (buffer, STRINGSIZE, stdin))
  1899. X    {
  1900. X    if (!*buffer || isspace (*buffer))
  1901. X    {
  1902. X        continue;
  1903. X    }
  1904. X    new_element = Parse (buffer);
  1905. X
  1906. X    ptr = new_element -> passwd.pw_passwd;
  1907. X    if (!ptr[0])
  1908. X    {
  1909. X        Log ("Warning! %s (%s in %s) has a null password!\n",
  1910. X         new_element -> passwd.pw_name,
  1911. X         new_element -> passwd.pw_shell,
  1912. X         new_element -> filename);
  1913. X        continue;
  1914. X    }
  1915. X    if (ptr[0] == '*' || ptr[0] == '!')
  1916. X    {
  1917. X        Log ("User %s (in %s) has a locked password.\n",
  1918. X         new_element -> passwd.pw_name,
  1919. X         new_element -> filename);
  1920. X        continue;
  1921. X    }
  1922. X#ifdef CRACK_PW_VERIFY
  1923. X    if (strlen (ptr) < 13)
  1924. X    {
  1925. X        Log ("User %s (in %s) has a short crypted password - ignoring.\n",
  1926. X         new_element -> passwd.pw_name,
  1927. X         new_element -> filename);
  1928. X        continue;
  1929. X    }
  1930. X    if (strlen (ptr) > 13)
  1931. X    {
  1932. X        Log ("User %s (in %s) has a LONG crypted password - truncating.\n",
  1933. X         new_element -> passwd.pw_name,
  1934. X         new_element -> filename);
  1935. X        ptr[13] = '\0';
  1936. X    }
  1937. X#endif                /* CRACK_PW_VERIFY */
  1938. X    numentries++;
  1939. X
  1940. X    if (ptr[0] == salt[0] && ptr[1] == salt[1])
  1941. X    {
  1942. X        new_element -> across = current_line;
  1943. X        current_line = new_element;
  1944. X    } else
  1945. X    {
  1946. X        if (current_line)
  1947. X        {
  1948. X        current_line -> next = user_root;
  1949. X        }
  1950. X        user_root = current_line;
  1951. X        current_line = new_element;
  1952. X        numlines++;
  1953. X        salt[0] = ptr[0];
  1954. X        salt[1] = ptr[1];
  1955. X    }
  1956. X    }
  1957. X
  1958. X    if (current_line)        /* last one tends to hang about */
  1959. X    {
  1960. X    current_line -> next = user_root;
  1961. X    user_root = current_line;
  1962. X    numlines++;
  1963. X    }
  1964. X    Log ("Loaded %d password entries into %d salted lines.\n",
  1965. X     numentries, --numlines);
  1966. X
  1967. X    return;
  1968. X}
  1969. X
  1970. Xvoid
  1971. XPrintGuess (eptr, guess)
  1972. X    register struct USER_ENTRY *eptr;
  1973. X    char *guess;
  1974. X{
  1975. X    Log ("Guessed %s (%s in %s) [%s] \n",
  1976. X     eptr -> passwd.pw_name,
  1977. X     eptr -> passwd.pw_shell,
  1978. X     eptr -> filename,
  1979. X#ifdef CRACK_PRINTOUT
  1980. X     guess
  1981. X#else
  1982. X     "<not printed>"
  1983. X#endif                /* CRACK_PRINTOUT */
  1984. X    );
  1985. X}
  1986. X/*
  1987. X * PASSWORD CRACKING LOW LEVEL FUNCTIONS
  1988. X */
  1989. X
  1990. Xint
  1991. XTryManyUsers (eptr, guess)    /* returns 0 if all done this line */
  1992. X    register struct USER_ENTRY *eptr;
  1993. X    char *guess;
  1994. X{
  1995. X    register int retval;
  1996. X    char guess_crypted[STRINGSIZE];
  1997. X
  1998. X    if (eptr -> done && !eptr -> across)
  1999. X    {
  2000. X    return (0);
  2001. X    }
  2002. X    strcpy (guess_crypted, crypt (guess, eptr -> passwd.pw_passwd));
  2003. X
  2004. X    retval = 0;
  2005. X
  2006. X    while (eptr)
  2007. X    {
  2008. X#ifdef CRACK_VERBOSE        /* Really want to fill your filestore ? */
  2009. X    if (verbose_bool)
  2010. X    {
  2011. X        Log ("Trying '%s' on %s from line %s\n",
  2012. X         guess,
  2013. X         eptr -> passwd.pw_name,
  2014. X         eptr -> filename);
  2015. X    }
  2016. X#endif
  2017. X    if (!strcmp (guess_crypted, eptr -> passwd.pw_passwd))
  2018. X    {
  2019. X        if (!eptr -> done)    /* haven't printed it before */
  2020. X        {
  2021. X        PrintGuess (eptr, guess);
  2022. X        }
  2023. X        eptr -> done = 1;
  2024. X    }
  2025. X    retval += (!eptr -> done);
  2026. X    eptr = eptr -> across;
  2027. X    }
  2028. X
  2029. X    return (retval);
  2030. X}
  2031. X
  2032. Xint
  2033. XTryOneUser (eptr, guess)    /* returns non-null on guessed user */
  2034. X    register struct USER_ENTRY *eptr;
  2035. X    register char *guess;
  2036. X{
  2037. X    if (!guess || !*guess || eptr -> done)
  2038. X    {
  2039. X    return (0);
  2040. X    }
  2041. X#ifdef CRACK_VERBOSE
  2042. X    if (verbose_bool)
  2043. X    {
  2044. X    Log ("Trying '%s' on %s from %s\n",
  2045. X         guess,
  2046. X         eptr -> passwd.pw_name,
  2047. X         eptr -> filename);
  2048. X    }
  2049. X#endif
  2050. X    if (strcmp (crypt (guess, eptr -> passwd.pw_passwd),
  2051. X        eptr -> passwd.pw_passwd))
  2052. X    {
  2053. X    return (0);
  2054. X    }
  2055. X    eptr -> done = 1;
  2056. X    PrintGuess (eptr, guess);
  2057. X    return (1);
  2058. X}
  2059. X/*
  2060. X * TOP LEVEL CRACKING FUNCTION INTERFACE ROUTINE - SINGLE USER ONLY
  2061. X */
  2062. X
  2063. Xint
  2064. XWordTry (entry_ptr, guess)
  2065. X    register struct USER_ENTRY *entry_ptr;
  2066. X    register char *guess;
  2067. X{
  2068. X    int all_lower;
  2069. X    int all_upper;
  2070. X    register char *ptr;
  2071. X    char guess2[STRINGSIZE];
  2072. X
  2073. X    if (!guess[1])        /* avoid wasting time on initials */
  2074. X    {
  2075. X    return (0);
  2076. X    }
  2077. X    if (TryOneUser (entry_ptr, guess) ||
  2078. X    TryOneUser (entry_ptr, Reverse (guess)))
  2079. X    {
  2080. X    return (1);
  2081. X    }
  2082. X    all_upper = all_lower = 1;
  2083. X    ptr = guess;
  2084. X
  2085. X    for (ptr = guess; *ptr; ptr++)
  2086. X    {
  2087. X    if (islower (*ptr))
  2088. X    {
  2089. X        all_upper = 0;
  2090. X    } else if (isupper (*ptr))
  2091. X    {
  2092. X        all_lower = 0;
  2093. X    }
  2094. X    }
  2095. X
  2096. X    if (!all_lower)
  2097. X    {
  2098. X    strcpy (guess2, Lowercase (guess));
  2099. X    if (TryOneUser (entry_ptr, guess2) ||
  2100. X        TryOneUser (entry_ptr, Reverse (guess2)))
  2101. X    {
  2102. X        return (1);
  2103. X    }
  2104. X    }
  2105. X    if (!all_upper)
  2106. X    {
  2107. X    strcpy (guess2, Uppercase (guess));
  2108. X    if (TryOneUser (entry_ptr, guess2) ||
  2109. X        TryOneUser (entry_ptr, Reverse (guess2)))
  2110. X    {
  2111. X        return (1);
  2112. X    }
  2113. X    }
  2114. X    return (0);
  2115. X}
  2116. X/*
  2117. X * END OF PASSWORD GUESSING LAYERS
  2118. X */
  2119. X
  2120. Xvoid
  2121. XPass1 ()
  2122. X{
  2123. X    int cracked;
  2124. X    struct USER_ENTRY *head;
  2125. X    register char *ptr;
  2126. X    register char *ptr2;
  2127. X    char junk[STRINGSIZE];
  2128. X    register struct USER_ENTRY *this;
  2129. X
  2130. X    Log ("starting pass1 password information\n");
  2131. X
  2132. X    for (head = user_root; head; head = head -> next)
  2133. X    {
  2134. X    for (this = head; this; this = this -> across)
  2135. X    {
  2136. X        /* username */
  2137. X        ptr = this -> passwd.pw_name;
  2138. X        if (WordTry (this, ptr))
  2139. X        {
  2140. X        continue;
  2141. X        }
  2142. X        /* usernameusername */
  2143. X        strcpy (junk, ptr);
  2144. X        strcat (junk, ptr);
  2145. X        if (WordTry (this, junk))
  2146. X        {
  2147. X        continue;
  2148. X        }
  2149. X        /* usernameemanresu */
  2150. X        strcpy (junk, ptr);
  2151. X        strcat (junk, Reverse (ptr));
  2152. X        if (WordTry (this, junk))
  2153. X        {
  2154. X        continue;
  2155. X        }
  2156. X#ifdef CRACK_GECOS
  2157. X        /* Gecos information field */
  2158. X        cracked = 0;
  2159. X        ptr = junk;
  2160. X        strcpy (junk, this -> passwd.pw_gecos);
  2161. X        if (*ptr == '-')    /* never seen this, but... */
  2162. X        {
  2163. X        ptr++;
  2164. X        }
  2165. X        if (ptr2 = (char *) strchr (ptr, ';'))    /* trim off junk */
  2166. X        {
  2167. X        *ptr2 = '\0';
  2168. X        }
  2169. X        if (ptr2 = (char *) strchr (ptr, ','))    /* trim off more junk */
  2170. X        {
  2171. X        *ptr2 = '\0';
  2172. X        }
  2173. X        for (;;)
  2174. X        {
  2175. X        if (ptr2 = (char *) strchr (ptr, ' '))
  2176. X        {
  2177. X            *(ptr2++) = '\0';
  2178. X        }
  2179. X        if (WordTry (this, ptr))
  2180. X        {
  2181. X            cracked++;
  2182. X            break;
  2183. X        }
  2184. X        if (ptr2)
  2185. X        {
  2186. X            ptr = ptr2;
  2187. X            while (*ptr && isspace (*ptr))
  2188. X            {
  2189. X            ptr++;
  2190. X            }
  2191. X        } else
  2192. X        {
  2193. X            break;
  2194. X        }
  2195. X        }
  2196. X
  2197. X        if (cracked)
  2198. X        {
  2199. X        continue;
  2200. X        }
  2201. X#endif                /* CRACK_GECOS */
  2202. X    }
  2203. X    }
  2204. X    return;
  2205. X}
  2206. X
  2207. Xvoid
  2208. XPass2 (dictfile)
  2209. X    char *dictfile;
  2210. X{
  2211. X    FILE *fp;
  2212. X    register struct USER_ENTRY *head;
  2213. X    int dictcount;
  2214. X    struct DICT_ENTRY *dictroot;
  2215. X    register struct DICT_ENTRY *scratch;
  2216. X    int pointuser;
  2217. X    char buffer[STRINGSIZE];
  2218. X
  2219. X    Log ("Starting pass2 on dictionary %s\n", dictfile);
  2220. X
  2221. X    if (!(fp = fopen (dictfile, "r")))
  2222. X    {
  2223. X    perror (dictfile);
  2224. X    return;
  2225. X    }
  2226. X    dictcount = 0;
  2227. X    dictroot = (struct DICT_ENTRY *) 0;
  2228. X
  2229. X    while (fgets (buffer, STRINGSIZE, fp))
  2230. X    {
  2231. X    Trim (buffer);
  2232. X    if (!*buffer)
  2233. X    {
  2234. X        continue;
  2235. X    }
  2236. X    scratch = (struct DICT_ENTRY *) malloc (sizeof (struct DICT_ENTRY));
  2237. X    scratch -> word = Clone (buffer);
  2238. X    scratch -> next = dictroot;
  2239. X    dictroot = scratch;
  2240. X    dictcount++;
  2241. X    }
  2242. X
  2243. X    fclose (fp);
  2244. X
  2245. X    Log ("Loaded %d words from %s\n", dictcount, dictfile);
  2246. X
  2247. X    if (dictcount <= 0)
  2248. X    {
  2249. X    Log ("Oops! Where did I get an empty dictionary from ?\n");
  2250. X    return;
  2251. X    }
  2252. X    head = (struct USER_ENTRY *) 0;    /* See "for" loop below */
  2253. X
  2254. X    if (recover_bool)        /* We are recovering */
  2255. X    {
  2256. X    recover_bool = 0;    /* Switch it off */
  2257. X    head = user_root;    /* Start of the userlist */
  2258. X    while (head && rusercount--)    /* For the recover count */
  2259. X    {
  2260. X        head = head -> next;/* Skip to the next user */
  2261. X    }            /* God this is taking a long time to do */
  2262. X    if (!head)        /* Legs on the ground, feet at the bottom */
  2263. X    {
  2264. X        Log ("Recover: data changed : looking for %s ran off end of list",
  2265. X         rusername);
  2266. X        Log ("Exiting...\n");
  2267. X        exit (0);
  2268. X    }
  2269. X    if (verify_recover && strcmp (rusername, head -> passwd.pw_name))
  2270. X    {
  2271. X        Log ("Recover: data changed : looking for %s found %s\n",
  2272. X         rusername, head -> passwd.pw_name);
  2273. X        Log ("Exiting...\n");
  2274. X        exit (0);
  2275. X    }
  2276. X    }
  2277. X    pointuser = 0;        /* we havent pointed anyone yet */
  2278. X
  2279. X    for (head = head ? head : user_root; head; head = head -> next)
  2280. X    {
  2281. X    SetPoint (dictfile, pointuser++, head -> passwd.pw_name);
  2282. X    for (scratch = dictroot; scratch; scratch = scratch -> next)
  2283. X    {
  2284. X        if (!TryManyUsers (head, scratch->word))
  2285. X        {
  2286. X        break;
  2287. X        }
  2288. X    }
  2289. X    }
  2290. X
  2291. X    Log ("Freeing memory from pass of %s\n", dictfile);
  2292. X    while (dictroot)
  2293. X    {
  2294. X    free (dictroot -> word);
  2295. X    scratch = dictroot -> next;
  2296. X    free (dictroot);
  2297. X    dictroot = scratch;
  2298. X    }
  2299. X}
  2300. X
  2301. Xint
  2302. Xmain (argc, argv)
  2303. X    int argc;
  2304. X    char *argv[];
  2305. X{
  2306. X    int i;
  2307. X    FILE *fp;
  2308. X    char *file;
  2309. X    int uerr;
  2310. X    extern int optind;
  2311. X    extern char *optarg;
  2312. X
  2313. X    uerr = 0;
  2314. X    pid = getpid ();        /* fill this out FIRST THING */
  2315. X
  2316. X#ifdef CRACK_NETWORK
  2317. X    if (gethostname (hostname, STRINGSIZE))    /* and this too ! */
  2318. X    {
  2319. X    perror ("gethostname");
  2320. X    }
  2321. X#endif
  2322. X
  2323. X    if (argc == 1)
  2324. X    {
  2325. X    uerr++;
  2326. X    }
  2327. X    while ((i = getopt (argc, argv, "vi:r:R:n:")) != EOF)
  2328. X    {
  2329. X    switch (i)
  2330. X    {
  2331. X    case 'v':
  2332. X        verbose_bool = 1;
  2333. X        break;
  2334. X    case 'n':
  2335. X        nice (atoi (optarg));
  2336. X        break;
  2337. X    case 'i':
  2338. X        if (!freopen (optarg, "r", stdin))
  2339. X        {
  2340. X        perror (optarg);
  2341. X        exit (1);
  2342. X        }
  2343. X        break;
  2344. X    case 'R':
  2345. X        verify_recover = 1;
  2346. X        /* nobreak; */
  2347. X    case 'r':
  2348. X        if (GetPoint (optarg))    /* We are not a recovering machine */
  2349. X        {
  2350. X        exit (0);    /* so, silently die... */
  2351. X        }
  2352. X        recover_bool = 1;
  2353. X        break;
  2354. X    default:
  2355. X    case '?':
  2356. X        uerr++;
  2357. X        break;
  2358. X    }
  2359. X    }
  2360. X
  2361. X    if (optind >= argc)
  2362. X    {
  2363. X    uerr++;
  2364. X    }
  2365. X    if (uerr)
  2366. X    {
  2367. X    fprintf (stderr,
  2368. X        "Usage: %s [-v] [-i file] [-nn] [-<R|r> file] dictfile [...]\n",
  2369. X         argv[0]);
  2370. X    exit (1);
  2371. X    }
  2372. X#ifdef CRACK_NETWORK
  2373. X    sprintf (opfile, "out.%s.%d", hostname, pid);
  2374. X    sprintf (diefile, "die.%s.%d", hostname, pid);
  2375. X    sprintf (pointfile, "point.%s.%d", hostname, pid);
  2376. X#else
  2377. X    sprintf (opfile, "out.%d", pid);
  2378. X    sprintf (diefile, "die.%d", pid);
  2379. X    sprintf (pointfile, "point.%d", pid);
  2380. X#endif                /* CRACK_NETWORK */
  2381. X
  2382. X    if (!freopen (opfile, "w", stdout))
  2383. X    {
  2384. X    perror ("freopen(stdout)");
  2385. X    exit (1);
  2386. X    }
  2387. X    if (!freopen (opfile, "a", stderr))
  2388. X    {
  2389. X    perror ("freopen(stderr)");
  2390. X    exit (1);
  2391. X    }
  2392. X    if (!(fp = fopen (diefile, "w")))
  2393. X    {
  2394. X    perror (diefile);
  2395. X    exit (1);
  2396. X    }
  2397. X    Log ("Crack: A Sensible Password Cracker v%s by ADE Muffett, 1991\n",
  2398. X     version);
  2399. X
  2400. X#ifdef CRACK_NETWORK
  2401. X    Log ("We are running on networked machine %s\n", hostname);
  2402. X#endif
  2403. X
  2404. X    if (recover_bool)
  2405. X    {
  2406. X#ifdef CRACK_NETWORK
  2407. X    Log ("We are recovering from a crash on %s, PID %d.\n", rhostname, rpid);
  2408. X#else
  2409. X    Log ("We are recovering PID %d from a crash.\n", rpid);
  2410. X#endif
  2411. X    Log ("From Dictionary %s, User number %d.\n", rdict, rusercount);
  2412. X    Log ("Username must match %s\n", rusername);
  2413. X    }
  2414. X    fprintf (fp, "#!/bin/sh\n");
  2415. X#ifdef CRACK_NETWORK
  2416. X    fprintf (fp, "rsh %s kill -15 %d\n", hostname, pid);
  2417. X#else
  2418. X    fprintf (fp, "kill -15 %d\n", pid);
  2419. X#endif                /* CRACK_NETWORK */
  2420. X    fprintf (fp, "rm $0\n");
  2421. X    fclose (fp);
  2422. X
  2423. X    chmod (diefile, 0700);
  2424. X
  2425. X#ifdef FCRYPT
  2426. X    init_des ();
  2427. X#endif
  2428. X
  2429. X    /* Quick verify that we are sane ! */
  2430. X
  2431. X    if (strcmp (crypt ("fredfred", "fredfred"), "frxWbx4IRuBBA"))
  2432. X    {
  2433. X    Log ("Version of crypt() being used internally is not compatible with standard.\n");
  2434. X    Log ("Versions of 'gcc' have been known to cause compatibility problems.\n");
  2435. X    Log ("If there is another reason for this, edit the source to remove this assertion.\n");
  2436. X    Log ("Terminating...\n");
  2437. X    exit (0);
  2438. X    }
  2439. X    signal (SIGTERM, CatchTERM);
  2440. X
  2441. X    Log ("Loading...\n");
  2442. X
  2443. X    LoadData ();
  2444. X
  2445. X    if (!recover_bool)
  2446. X    {
  2447. X    /* We are starting afresh ! Ah, the birds in May ! */
  2448. X    Pass1 ();
  2449. X    } else
  2450. X    {
  2451. X    /* Some spodulous creep pulled our plug... */
  2452. X    while ((optind < argc) && strcmp (argv[optind], rdict))
  2453. X    {
  2454. X        optind++;        /* Fly over dicts that we have done */
  2455. X    }
  2456. X    }
  2457. X
  2458. X    for (i = optind; i < argc; i++)
  2459. X    {
  2460. X    Pass2 (argv[i]);
  2461. X    }
  2462. X
  2463. X    Log ("Finished.\n");
  2464. X    return (0);
  2465. X}
  2466. END_OF_FILE
  2467. if test 17109 -ne `wc -c <'Sources/crack-pwc.c'`; then
  2468.     echo shar: \"'Sources/crack-pwc.c'\" unpacked with wrong size!
  2469. fi
  2470. # end of 'Sources/crack-pwc.c'
  2471. fi
  2472. if test -f 'Sources/goodpass.c' -a "${1}" != "-c" ; then 
  2473.   echo shar: Will not clobber existing file \"'Sources/goodpass.c'\"
  2474. else
  2475. echo shar: Extracting \"'Sources/goodpass.c'\" \(8361 characters\)
  2476. sed "s/^X//" >'Sources/goodpass.c' <<'END_OF_FILE'
  2477. X#include <ctype.h>
  2478. X#include <pwd.h>
  2479. X#include <stdio.h>
  2480. X#include <string.h>
  2481. X#include <sys/file.h>
  2482. X
  2483. X/*
  2484. X * goodpass.c : A simple yes/no password sensibility function to be wired
  2485. X * into "passwd" & "yppasswd", etc.  (c) ADE Muffett, 1991 (aem@aber.ac.uk).
  2486. X * This module is freely redistributable for use in software so long as this
  2487. X * copyright notice remains intact.  Distributed as part of the 'Crack' suite
  2488. X * of password testing programs.
  2489. X */
  2490. X
  2491. X/* Usage:- */
  2492. X/* char *result = GoodPass(char *password); */
  2493. X/* where password is a text string to be tested for suitability */
  2494. X/* GoodPass returns NULL if the password is OK */
  2495. X/* GoodPass returns a diagnostic string if the password is NOT ok */
  2496. X
  2497. X#define PWLENGTH    8    /* significant length of text */
  2498. X#define MINDIFF        5    /* minimum number of different characters */
  2499. X#define MAXSTEP        3    /* max number of steps up/down in char set */
  2500. X#define MINLENGTH    6    /* minimum length of a password */
  2501. X#define STRINGSIZE    255    /* a standard buffer size */
  2502. X#define STRIDE        4    /* word skipping length */
  2503. X#undef DEBUG
  2504. X
  2505. Xstatic char *dikshunarys[] =
  2506. X{
  2507. X    "/usr/dict/words",
  2508. X    "/usr/local/lib/bad_pws.dat",
  2509. X    NULL
  2510. X};
  2511. X
  2512. Xstatic int
  2513. XPmatch (control, string)
  2514. X    char *control;
  2515. X    char *string;
  2516. X{
  2517. X    while (*control)
  2518. X    {
  2519. X    if (!*string)
  2520. X    {
  2521. X        return (0);
  2522. X    }
  2523. X    switch (*control)
  2524. X    {
  2525. X    case 'u':
  2526. X        if (!isupper (*string))
  2527. X        {
  2528. X        return (0);
  2529. X        }
  2530. X        break;
  2531. X    case 'l':
  2532. X        if (!islower (*string))
  2533. X        {
  2534. X        return (0);
  2535. X        }
  2536. X        break;
  2537. X    case 'd':
  2538. X        if (!isdigit (*string))
  2539. X        {
  2540. X        return (0);
  2541. X        }
  2542. X        break;
  2543. X    case 'c':
  2544. X        if (!isalpha (*string))
  2545. X        {
  2546. X        return (0);
  2547. X        }
  2548. X        break;
  2549. X    case '.':
  2550. X    default:
  2551. X        if (!isalnum (*string))
  2552. X        {
  2553. X        return (0);
  2554. X        }
  2555. X        break;
  2556. X    }
  2557. X    control++;
  2558. X    string++;
  2559. X    }
  2560. X    return (1);
  2561. X}
  2562. X
  2563. Xstatic void
  2564. XTrim (string)            /* remove trailing whitespace from a string */
  2565. X    register char *string;
  2566. X{
  2567. X    register char *ptr;
  2568. X
  2569. X    for (ptr = string; *ptr; ptr++);
  2570. X    while ((--ptr >= string) && isspace (*ptr));
  2571. X    *(++ptr) = '\0';
  2572. X}
  2573. X
  2574. Xstatic char *
  2575. XReverse (str)            /* return a pointer to a reversal */
  2576. X    register char *str;
  2577. X{
  2578. X    register int i;
  2579. X    register int j;
  2580. X    register char *ptr;
  2581. X    static char area[STRINGSIZE];
  2582. X
  2583. X    j = i = strlen (str);
  2584. X    while (*str)
  2585. X    {
  2586. X    area[--i] = *str++;
  2587. X    }
  2588. X    area[j] = '\0';
  2589. X    return (area);
  2590. X}
  2591. X/******* THE TEST FUNCTION *******/
  2592. X
  2593. Xstatic int
  2594. XTry (input, guess)
  2595. X    register char *input;
  2596. X    register char *guess;
  2597. X{
  2598. X    if (!strncasecmp (input, guess, PWLENGTH) ||
  2599. X    !strncasecmp (input, Reverse (guess), PWLENGTH))
  2600. X    {
  2601. X    return (-1);
  2602. X    }
  2603. X    return (0);
  2604. X}
  2605. X/******* DICTIONARY SEARCHING *******/
  2606. X
  2607. Xstatic int
  2608. XGetWord (fp, buff)
  2609. X    FILE *fp;
  2610. X    char *buff;
  2611. X{
  2612. X    register int c;
  2613. X
  2614. X    for (;;)
  2615. X    {
  2616. X    c = getc (fp);
  2617. X    if (c == EOF)
  2618. X    {
  2619. X        return (-1);
  2620. X    }
  2621. X    if (c == '\n')
  2622. X    {
  2623. X        break;
  2624. X    }
  2625. X    *(buff++) = (char) c;
  2626. X    }
  2627. X    *buff = 0;
  2628. X    return (0);
  2629. X}
  2630. X
  2631. Xstatic int
  2632. XDictSearch (input)
  2633. X    char *input;
  2634. X{
  2635. X    int i;
  2636. X    int loops;
  2637. X    register long top;
  2638. X    register long bot;
  2639. X    register long mid;
  2640. X    long scratch;
  2641. X    char word[STRINGSIZE];
  2642. X    FILE *fp;
  2643. X    char **dictionary;
  2644. X
  2645. X    for (dictionary = dikshunarys; *dictionary; dictionary++)
  2646. X    {
  2647. X    if (!(fp = fopen (*dictionary, "r")))
  2648. X    {
  2649. X        perror (*dictionary);
  2650. X        continue;
  2651. X    }
  2652. X    bot = 0L;        /* start of file */
  2653. X    fseek (fp, 0L, 2);    /* to end of file */
  2654. X    top = ftell (fp);
  2655. X
  2656. X    for (loops = 0; loops < 1000; loops++)
  2657. X    {
  2658. X        mid = (top + bot) / 2;    /* calculate the middle */
  2659. X        scratch = mid;
  2660. X
  2661. X      stride_loop:
  2662. X
  2663. X        scratch -= STRIDE;    /* calculate a bit beforehand */
  2664. X        if (scratch < 0)    /* error fixing */
  2665. X        {
  2666. X        mid = scratch = 0L;
  2667. X        fseek (fp, 0L, 0);
  2668. X        } else
  2669. X        {            /* find the start of the current word */
  2670. X        fseek (fp, scratch, 0);    /* go read the scratch buffer */
  2671. X        fread (word, 1, STRIDE, fp);
  2672. X
  2673. X        for (i = STRIDE - 1; i >= 0; i--)
  2674. X        {
  2675. X            if (word[i] == '\n')    /* where 'mid' is is start of
  2676. X                         * word */
  2677. X            {
  2678. X            break;
  2679. X            } else
  2680. X            {        /* mid is between words */
  2681. X            mid--;
  2682. X            }
  2683. X        }
  2684. X        if (i < 0)
  2685. X        {
  2686. X            goto stride_loop;
  2687. X        }
  2688. X        }
  2689. X
  2690. X        fseek (fp, mid, 0);
  2691. X        GetWord (fp, word);
  2692. X
  2693. X        i = strncasecmp (input, word, PWLENGTH);
  2694. X
  2695. X        if (i > 0)
  2696. X        {
  2697. X        bot = mid + strlen (word) + 1;    /* why retest this word ever */
  2698. X        } else if (i < 0)
  2699. X        {
  2700. X        if (mid >= top)
  2701. X        {
  2702. X            break;
  2703. X        }
  2704. X        top = mid;
  2705. X        } else
  2706. X        {
  2707. X        fclose (fp);
  2708. X        return (-1);    /* found it */
  2709. X        }
  2710. X    }
  2711. X    fclose (fp);
  2712. X    }
  2713. X
  2714. X    return (0);
  2715. X}
  2716. X/******* THE EXTERNAL CALL *******/
  2717. X
  2718. Xchar *
  2719. XGoodPass (input)
  2720. X    char *input;
  2721. X{
  2722. X    register int i;
  2723. X    register char *ptr;
  2724. X    register char *ptr2;
  2725. X    struct passwd *pwd;
  2726. X    char junk[STRINGSIZE];
  2727. X    char password[STRINGSIZE];
  2728. X
  2729. X    /* back it up. */
  2730. X    strcpy (password, input);
  2731. X    Trim (password);
  2732. X
  2733. X    /* who is it ? */
  2734. X    pwd = getpwuid (getuid ());
  2735. X    if (!pwd)
  2736. X    {
  2737. X    perror ("getpwuid");
  2738. X    return ("Error - no password entry found to verify against.");
  2739. X    }
  2740. X    /* size */
  2741. X    if (strlen (password) < MINLENGTH)
  2742. X    {
  2743. X    return ("it is too short - use more characters.");
  2744. X    }
  2745. X    /* username */
  2746. X    if (Try (password, pwd -> pw_name))
  2747. X    {
  2748. X    return ("it is your username");
  2749. X    }
  2750. X    /* usernameusername */
  2751. X    strcpy (junk, pwd -> pw_name);
  2752. X    strcat (junk, pwd -> pw_name);
  2753. X    if (Try (password, junk))
  2754. X    {
  2755. X    return ("it is your username, doubled");
  2756. X    }
  2757. X    /* Gecos information field */
  2758. X    strcpy (junk, pwd -> pw_gecos);
  2759. X    ptr = junk;
  2760. X    if (*ptr == '-')        /* never seen this, but... */
  2761. X    {
  2762. X    ptr++;
  2763. X    }
  2764. X    if (ptr2 = strchr (ptr, ';'))    /* trim off junk */
  2765. X    {
  2766. X    *ptr2 = '\0';
  2767. X    }
  2768. X    if (ptr2 = strchr (ptr, ','))    /* trim off more junk */
  2769. X    {
  2770. X    *ptr2 = '\0';
  2771. X    }
  2772. X    for (;;)
  2773. X    {
  2774. X    if (ptr2 = strchr (ptr, ' '))
  2775. X    {
  2776. X        *(ptr2++) = '\0';
  2777. X    }
  2778. X    if (Try (password, ptr))
  2779. X    {
  2780. X        return ("it is part of your name. Use something less obvious.");
  2781. X    }
  2782. X    if (ptr2)
  2783. X    {
  2784. X        ptr = ptr2;
  2785. X        while (*ptr && isspace (*ptr))
  2786. X        {
  2787. X        ptr++;
  2788. X        }
  2789. X    } else
  2790. X    {
  2791. X        break;
  2792. X    }
  2793. X    }
  2794. X
  2795. X    /* check for repeated characters */
  2796. X    bzero (junk, sizeof (junk));
  2797. X    for (i = 0; i < PWLENGTH && password[i]; i++)
  2798. X    {
  2799. X    if (!strchr (junk, password[i]))
  2800. X    {
  2801. X        strncat (junk, password + i, 1);
  2802. X    }
  2803. X    }
  2804. X    if (strlen (junk) < MINDIFF)
  2805. X    {
  2806. X    return ("it does not contain enough different characters.\nUse more different characters.");
  2807. X    }
  2808. X    /* check for over simplicity */
  2809. X    i = 0;
  2810. X    ptr = password;
  2811. X    while (ptr[0] && ptr[1])
  2812. X    {
  2813. X    if ((ptr[1] == (ptr[0] + 1)) ||
  2814. X        (ptr[0] == (ptr[1] + 1)))
  2815. X    {
  2816. X        i++;
  2817. X    }
  2818. X    ptr++;
  2819. X    }
  2820. X    if (i > MAXSTEP)
  2821. X    {
  2822. X    return ("it is too simplistic. Try something more random.");
  2823. X    }
  2824. X    /* lets get a little silly... */
  2825. X    if (Pmatch ("cdddccc", password))
  2826. X    {
  2827. X    return ("it looks like a new style car registration.");
  2828. X    }
  2829. X    if (Pmatch ("cccdddc", password))
  2830. X    {
  2831. X    return ("it looks like a old style car registration.");
  2832. X    }
  2833. X    if (Pmatch ("cccddd", password) || Pmatch ("dddccc", password))
  2834. X    {
  2835. X    return ("it looks like an old-style car registration.");
  2836. X    }
  2837. X    if (Pmatch ("ccddddddc", password))
  2838. X    {
  2839. X    return ("it looks like a National Insurance number.");
  2840. X    }
  2841. X    strcpy (junk, input);
  2842. X
  2843. X    /* do a dictionary search here */
  2844. X    if (DictSearch (junk))
  2845. X    {
  2846. X    return ("it is a guessable dictionary word.");
  2847. X    }
  2848. X    if (DictSearch (Reverse (junk)))
  2849. X    {
  2850. X    return ("it is a guessable reversed dictionary word.");
  2851. X    }
  2852. X    /* strip off possible initial number and do a dictionary search here */
  2853. X    if (isdigit (junk[0]))
  2854. X    {
  2855. X    if (DictSearch (junk + 1))
  2856. X    {
  2857. X        return ("it is a digit + guessable dictionary word.");
  2858. X    }
  2859. X    if (DictSearch (Reverse (junk + 1)))
  2860. X    {
  2861. X        return ("it is a digit + guessable reversed dictionary word.");
  2862. X    }
  2863. X    }
  2864. X    i = strlen (junk) - 1;
  2865. X    if (isdigit (junk[i]))
  2866. X    {
  2867. X    junk[i] = '\0';
  2868. X    if (DictSearch (junk))
  2869. X    {
  2870. X        return ("it is a guessable dictionary word + digit.");
  2871. X    }
  2872. X    if (DictSearch (Reverse (junk)))
  2873. X    {
  2874. X        return ("it is a guessable reversed dictionary word + digit.");
  2875. X    }
  2876. X    } else if (junk[i] == 's')
  2877. X    {
  2878. X    junk[i] = '\0';
  2879. X    if (DictSearch (junk))
  2880. X    {
  2881. X        return ("it is a pluralised dictionary word.");
  2882. X    }
  2883. X    }
  2884. X    return ((char *) NULL);
  2885. X}
  2886. X#ifdef DEBUG
  2887. Xmain (argc, argv)
  2888. X    int argc;
  2889. X    char *argv[];
  2890. X{
  2891. X    int i;
  2892. X    char *p;
  2893. X
  2894. X    for (i = 1; i < argc; i++)
  2895. X    {
  2896. X    printf ("'%s'\n", argv[i]);
  2897. X
  2898. X    if (p = GoodPass (argv[i]))
  2899. X    {
  2900. X        printf ("\t%s\n", p);
  2901. X    } else
  2902. X    {
  2903. X        printf ("\tok\n");
  2904. X    }
  2905. X    }
  2906. X}
  2907. X#endif
  2908. END_OF_FILE
  2909. if test 8361 -ne `wc -c <'Sources/goodpass.c'`; then
  2910.     echo shar: \"'Sources/goodpass.c'\" unpacked with wrong size!
  2911. fi
  2912. # end of 'Sources/goodpass.c'
  2913. fi
  2914. echo shar: End of archive 2 \(of 4\).
  2915. cp /dev/null ark2isdone
  2916. MISSING=""
  2917. for I in 1 2 3 4 ; do
  2918.     if test ! -f ark${I}isdone ; then
  2919.     MISSING="${MISSING} ${I}"
  2920.     fi
  2921. done
  2922. if test "${MISSING}" = "" ; then
  2923.     echo You have unpacked all 4 archives.
  2924.     rm -f ark[1-9]isdone
  2925. else
  2926.     echo You still need to unpack the following archives:
  2927.     echo "        " ${MISSING}
  2928. fi
  2929. ##  End of shell archive.
  2930. exit 0
  2931. exit 0 # Just in case...
  2932.