home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3527 < prev    next >
Internet Message Format  |  1991-06-22  |  36KB

  1. From: df@sei.cmu.edu (Dan Farmer)
  2. Newsgroups: alt.sources
  3. Subject: perl COPS, 3/3
  4. Message-ID: <27545@as0c.sei.cmu.edu>
  5. Date: 22 Jun 91 04:29:32 GMT
  6.  
  7. #!/bin/sh
  8. # this is p-cops.103.03 (part 3 of a multipart archive)
  9. # do not concatenate these parts, unpack them in order with /bin/sh
  10. # file beta/passwd continued
  11. #
  12. if test ! -r _shar_seq_.tmp; then
  13.     echo 'Please unpack part 1 first!'
  14.     exit 1
  15. fi
  16. (read Scheck
  17.  if test "$Scheck" != 3; then
  18.     echo Please unpack part "$Scheck" next!
  19.     exit 1
  20.  else
  21.     exit 0
  22.  fi
  23. ) < _shar_seq_.tmp || exit 1
  24. if test ! -f _shar_wnt_.tmp; then
  25.     echo 'x - still skipping beta/passwd'
  26. else
  27. echo 'x - continuing file beta/passwd'
  28. sed 's/^X//' << 'SHAR_EOF' >> 'beta/passwd' &&
  29. stupak:*OdHloLgJnVCgI:131:20:Kenneth Stupak:/usr/users/stupak:/bin/csh
  30. rdp:fZ3tNW/ICf0TI:159:78:Richard Pethia:/usr/users/rdp:/usr/local/bin/tcsh
  31. connelly:u1KPqdq.5rML6:2955:20:John Connelly:/usr/users/connelly:/bin/csh
  32. ecd:T2iMJ3K55qFOA:2993:78:Edward DeHart:/usr/users/ecd:/usr/local/bin/tcsh
  33. tgp:uAONGKl7Smc/U:2999:70:Tod Pike:/usr/users/tgp:/bin/csh
  34. pjg:*UTkWVHoPfhANw:3086:20:Patrick Glasso:/usr/users/pjg:/bin/csh
  35. ph:*xisuhVETJw.Vo:3144:78:Paul Holbrook:/usr/users/ph:/bin/false
  36. krvw:VaYVunaqW4D9.:3145:78:Kenneth R. van Wyk:/usr/users/krvw:/usr/local/bin/tcsh
  37. tjm:s3oXhld2/.ngc:3159:20:Todd Miller:/usr/users/tjm:/bin/csh
  38. cfalkens:yhJpwSRg/b4LI:3202:78:Carolyn Falkenstern:/usr/users/cfalkens:/bin/csh
  39. byf:ZFRZIqr1ijgs2:3217:78:Barbara Fraser:/usr/users/byf:/usr/local/bin/tcsh
  40. df::3271:78:Dan Farmer:/usr/users/df:/usr/local/bin/tcsh
  41. brg:*:3366:78:Barbara Gratz:/usr/users/brg:/usr/local/bin/tcsh
  42. nobody:*:65534:20:Nobody:/usr/nobody:/bin/date
  43. news:*:8000:8000:News Maintainer:/usr/users/news:/bin/date
  44. lizard:jW4Gl.3ncbiZg:8002:78:BYF's Play Thing:/usr/users/lizard:/usr/local/bin/tcsh
  45. SHAR_EOF
  46. echo 'File beta/passwd is complete' &&
  47. chmod 0600 beta/passwd ||
  48. echo 'restore of beta/passwd failed'
  49. Wc_c="`wc -c < 'beta/passwd'`"
  50. test 1555 -eq "$Wc_c" ||
  51.     echo 'beta/passwd: original size 1555, current size' "$Wc_c"
  52. rm -f _shar_wnt_.tmp
  53. fi
  54. # ============= beta/passwd.chk ==============
  55. if test -f 'beta/passwd.chk' -a X"$1" != X"-c"; then
  56.     echo 'x - skipping beta/passwd.chk (File already exists)'
  57.     rm -f _shar_wnt_.tmp
  58. else
  59. > _shar_wnt_.tmp
  60. echo 'x - extracting beta/passwd.chk (Text)'
  61. sed 's/^X//' << 'SHAR_EOF' > 'beta/passwd.chk' &&
  62. #!/bin/sh -- need to mention perl here to avoid recursion
  63. 'true' || eval 'exec perl -S $0 $argv:q';
  64. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
  65. & eval 'exec /usr/local/bin/perl -S $0 $argv:q'
  66. X        if 0;
  67. X
  68. #
  69. #   passwd.chk
  70. #
  71. # composer@chem.bu.edu
  72. #
  73. # Check password file -- /etc/passwd -- for incorrect number of fields,
  74. # duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
  75. # Mechanism:  This script ensures that each line of the passwd file (in
  76. # $etc, line 47) has 7 fields and is non-blank, as well as examining the
  77. # file for any duplicate users.  It then checks to ensure that the first
  78. # character of the login name is alphanumeric, and that all uid and gid
  79. # numbers are indeed numeric and non-negative.  It also checks the
  80. # validity of the home directory.
  81. # For yellow pages passwords, it does the same checking, but in order to
  82. # get a listing of all members of the password file, it does a "ypcat
  83. # passwd" and uses the output from that as a passwd file.
  84. # The /etc/passwd file has a very specific format, making the task fairly
  85. # simple.  Normally it has lines with 7 fields, each field separated by a
  86. # colon (:).  The first field is the user id, the second field is the
  87. # encrypted password (an asterix (*) means the group has no password,
  88. # otherwise the first two characters are the salt), the third field is the
  89. # user id number, the fourth field is the group id number, the fifth field
  90. # is the GECOS field (basically holds miscellaneous information, varying
  91. # from site to site), the sixth field is the home directory of the user,
  92. # and lastly the seventh field is the login shell of the user.  No blank
  93. # lines should be present.  Uid's will be flagged if over 8 chars, unless
  94. # the $OVER_8 variable (line 45) is set to "YES".
  95. # If a line begins with a plus sign (+), it is a yellow pages entry.  See
  96. # passwd(5) for more information, if this applies to your site.
  97. X
  98. require 'pathconf.pl';
  99. require 'pass.cache.pl';
  100. #   Used for Sun C2 security group file. 'FALSE' (default) will flag
  101. # valid C2 passwd syntax as an error, 'TRUE' attempts to validate it.
  102. # Thanks to Pete Troxell for pointing this out.
  103. $C2='FALSE' if undef($C2);
  104. X
  105. #  Some systems allow long uids; set this to 'TRUE', if so (thanks
  106. # to Pete Shipley (lot of petes around here, eh?)):
  107. $OVER_8='NO' if undef($OVER_8);
  108. X
  109. package passwd_chk;
  110. X
  111. #
  112. # Important files:
  113. $etc_passwd = $'PASSWD || '/etc/passwd';
  114. X
  115. #   Check $etc_passwd for potential problems, or use the alternate method
  116. # set in cops.cf:
  117. if (!"$'GET_PASSWD") {
  118. X    open(Passwd, $etc_passwd) ||
  119. X        warn "$0: Can't open $etc_passwd: $!\n";
  120. X    }
  121. else {
  122. X    open(Passwd, "$'GET_PASSWD|") ||
  123. X        warn "$0: Can't open $etc_passwd: $!\n";
  124. X    }
  125. &chk_passwd_file_format('Passwd');
  126. close Passwd;
  127. X
  128. # check ypcat passwd for potential problems... (same checks)
  129. if (-s $'YPCAT && -x _) {
  130. X    open(YPasswd, "$'YPCAT passwd 2>/dev/null |")
  131. X    || die "$0: Can't popen $'YPCAT: $!\n";
  132. X    &chk_passwd_file_format('YPasswd');
  133. X    close YPasswd;
  134. }
  135. X  
  136. sub chk_passwd_file_format {
  137. X    local($file) = @_;
  138. X    local($W) = "Warning!  $file file,";
  139. X    undef %users;
  140. X  
  141. X    while (<$file>) {
  142. X    # should really check for correct YP syntax
  143. X    next if /^[-+]/;    # skipping YP lines for now
  144. X
  145. X    print "$W line $., is blank\n", next if /^\s*$/;
  146. X
  147. X    # make code a little more readable .. use names.. 
  148. X    ($user,$pass,$uid,$gid,$gcos,$home,$shell) = split(?:?);
  149. X    $users{$user}++;    # keep track of dups
  150. X    print "$W line $., does not have 7 fields:\n\t$_" if (@_ != 7);
  151. X    print "$W line $., nonalphanumeric username:\n\t$_"
  152. X        if $user !~ /^[A-Za-z0-9]+$/;
  153. X    print "$W line $., numeric username:\n\t$_"
  154. X        if $user =~ /^\d+$/;
  155. X    print "$W line $., login name > 8 characters:\n\t$_"
  156. X        if ( ! $OVER_8 && length($user) > 8);
  157. X    print "$W line $., no password:\n\t$_" unless $pass;
  158. X    print "$W line $., invalid password field for C2:\n\t$_"
  159. X        if ($C2 && $pass =~ /^##/ && "##$user" ne $pass);
  160. X    if ($uid !~ /^\d+$/) {
  161. X        if ($uid < 0) {
  162. X        print "$W line $., negative user id (uid):\n\t$_";
  163. X        } else {
  164. X        print "$W line $., nonnumeric user id (uid):\n\t$_";
  165. X        }
  166. X    }
  167. X    # what about checks for certain ranges of UIDs .. -composer
  168. X    print "$W line $., user $user has uid == 0 and is not root\n\t$_"
  169. X        if $uid == 0 && $user ne "root";
  170. X    print "$W line $., nonnumeric group id (gid):\n\t$_"
  171. X        unless $gid =~ /^\d+$/;
  172. X    print "$W line $., invalid home directory:\n\t$_"
  173. X        unless $home =~ m:^/:;
  174. X
  175. X    }
  176. X    # find duplicate usernames
  177. X    # not the best way, but it works ...
  178. X    $dup_warned = 0;
  179. X    for (sort keys %users) {
  180. X    (print "Warning!  Duplicate username(s) found in $file:\n"),
  181. X        $dup_warned++ if !$dup_warned && $users{$_} > 1;
  182. X    print "$_ " if $users{$_} > 1;
  183. X    }
  184. X    print "\n" if $dup_warned;
  185. }
  186. X  
  187. 1;
  188. # end of passwd.chk file
  189. SHAR_EOF
  190. chmod 0700 beta/passwd.chk ||
  191. echo 'restore of beta/passwd.chk failed'
  192. Wc_c="`wc -c < 'beta/passwd.chk'`"
  193. test 4773 -eq "$Wc_c" ||
  194.     echo 'beta/passwd.chk: original size 4773, current size' "$Wc_c"
  195. rm -f _shar_wnt_.tmp
  196. fi
  197. # ============= beta/pathconf.pl ==============
  198. if test -f 'beta/pathconf.pl' -a X"$1" != X"-c"; then
  199.     echo 'x - skipping beta/pathconf.pl (File already exists)'
  200.     rm -f _shar_wnt_.tmp
  201. else
  202. > _shar_wnt_.tmp
  203. echo 'x - extracting beta/pathconf.pl (Text)'
  204. sed 's/^X//' << 'SHAR_EOF' > 'beta/pathconf.pl' &&
  205. $YPCAT = '/usr/bin/ypcat';
  206. $STRINGS = '/usr/ucb/strings';
  207. $TFTP = '/usr/ucb/tftp';
  208. $UUDECODE = '/usr/bin/uudecode';
  209. $CMP = '/bin/cmp';
  210. $LS = '/bin/ls';
  211. X
  212. # end of perl needed programs
  213. X
  214. $AWK = '/bin/awk';
  215. $CAT = '/bin/cat';
  216. $CC = '/bin/cc';
  217. $CHMOD = '/bin/chmod';
  218. $COMM = '/usr/bin/comm';
  219. $CP = '/bin/cp';
  220. $DATE = '/bin/date';
  221. $DIFF = '/bin/diff';
  222. $ECHO = '/bin/echo';
  223. $EGREP = '/usr/bin/egrep';
  224. $EXPR = '/bin/expr';
  225. $FIND = '/usr/bin/find';
  226. $GREP = '/bin/grep';
  227. $MAIL = '/bin/mail';
  228. $MKDIR = '/bin/mkdir';
  229. $MV = '/bin/mv';
  230. $RM = '/bin/rm';
  231. $SED = '/bin/sed';
  232. $SH = '/bin/sh';
  233. $SORT = '/usr/bin/sort';
  234. $TEST = '/bin/test';
  235. $TOUCH = '/usr/bin/touch';
  236. $UNIQ = '/usr/bin/uniq';
  237. X
  238. 1;
  239. SHAR_EOF
  240. chmod 0700 beta/pathconf.pl ||
  241. echo 'restore of beta/pathconf.pl failed'
  242. Wc_c="`wc -c < 'beta/pathconf.pl'`"
  243. test 677 -eq "$Wc_c" ||
  244.     echo 'beta/pathconf.pl: original size 677, current size' "$Wc_c"
  245. rm -f _shar_wnt_.tmp
  246. fi
  247. # ============= beta/pathconf.sh ==============
  248. if test -f 'beta/pathconf.sh' -a X"$1" != X"-c"; then
  249.     echo 'x - skipping beta/pathconf.sh (File already exists)'
  250.     rm -f _shar_wnt_.tmp
  251. else
  252. > _shar_wnt_.tmp
  253. echo 'x - extracting beta/pathconf.sh (Text)'
  254. sed 's/^X//' << 'SHAR_EOF' > 'beta/pathconf.sh' &&
  255. YPCAT = '/usr/bin/ypcat';
  256. STRINGS = '/usr/ucb/strings';
  257. TFTP = '/usr/ucb/tftp';
  258. UUDECODE = '/usr/bin/uudecode';
  259. X
  260. # end of perl needed programs
  261. X
  262. AWK = '/bin/awk';
  263. CAT = '/bin/cat';
  264. CC = '/bin/cc';
  265. CHMOD = '/bin/chmod';
  266. CMP = '/bin/cmp';
  267. COMM = '/usr/bin/comm';
  268. CP = '/bin/cp';
  269. DATE = '/bin/date';
  270. DIFF = '/bin/diff';
  271. ECHO = '/bin/echo';
  272. EGREP = '/usr/bin/egrep';
  273. EXPR = '/bin/expr';
  274. FIND = '/usr/bin/find';
  275. GREP = '/bin/grep';
  276. LS = '/bin/ls';
  277. MAIL = '/bin/mail';
  278. MKDIR = '/bin/mkdir';
  279. MV = '/bin/mv';
  280. RM = '/bin/rm';
  281. SED = '/bin/sed';
  282. SH = '/bin/sh';
  283. SORT = '/usr/bin/sort';
  284. TEST = '/bin/test';
  285. TOUCH = '/usr/bin/touch';
  286. UNIQ = '/usr/bin/uniq';
  287. SHAR_EOF
  288. chmod 0700 beta/pathconf.sh ||
  289. echo 'restore of beta/pathconf.sh failed'
  290. Wc_c="`wc -c < 'beta/pathconf.sh'`"
  291. test 644 -eq "$Wc_c" ||
  292.     echo 'beta/pathconf.sh: original size 644, current size' "$Wc_c"
  293. rm -f _shar_wnt_.tmp
  294. fi
  295. # ============= beta/rc.chk ==============
  296. if test -f 'beta/rc.chk' -a X"$1" != X"-c"; then
  297.     echo 'x - skipping beta/rc.chk (File already exists)'
  298.     rm -f _shar_wnt_.tmp
  299. else
  300. > _shar_wnt_.tmp
  301. echo 'x - extracting beta/rc.chk (Text)'
  302. sed 's/^X//' << 'SHAR_EOF' > 'beta/rc.chk' &&
  303. #!/bin/sh -- need to mention perl here to avoid recursion
  304. 'true' || eval 'exec perl -S $0 $argv:q';
  305. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
  306. & eval 'exec /usr/local/bin/perl -S $0 $argv:q'
  307. X        if 0;
  308. X
  309. #
  310. #  Usage: rc.chk
  311. #
  312. #  This checks pathnames and files inside the shell script files /etc/rc*
  313. # for writability.  The commands inside the files /etc/rc* are executed when
  314. # the machine is booted, so are of special interest.
  315. #
  316. # Made easy by chk_strings :-)
  317. #
  318. # Name: Martin Foord    Username: maf  Date: Thu Jan 17 15:11:09 EST 1991 
  319. # Email: maf%dbsm.oz.au@munnari.oz.au
  320. #
  321. X
  322. require 'chk_strings.pl';
  323. X
  324. # probably don't need to, but might want to do &'glob("/etc/rc*") instead.. ;-)
  325. @all_rc_files = ("/etc/rc*", "/etc/*rc", "/etc/rc*.d/*",
  326. X         "/etc/shutdown.d/*", "/etc/inittab");
  327. X
  328. for $file (@all_rc_files) {
  329. X    while (<${file}>) {
  330. X        if (-r $_) {
  331. X            &chk_strings($_);
  332. X            }
  333. X        }
  334. X    }
  335. X
  336. 1;
  337. SHAR_EOF
  338. chmod 0700 beta/rc.chk ||
  339. echo 'restore of beta/rc.chk failed'
  340. Wc_c="`wc -c < 'beta/rc.chk'`"
  341. test 897 -eq "$Wc_c" ||
  342.     echo 'beta/rc.chk: original size 897, current size' "$Wc_c"
  343. rm -f _shar_wnt_.tmp
  344. fi
  345. # ============= beta/reconfig.pl ==============
  346. if test -f 'beta/reconfig.pl' -a X"$1" != X"-c"; then
  347.     echo 'x - skipping beta/reconfig.pl (File already exists)'
  348.     rm -f _shar_wnt_.tmp
  349. else
  350. > _shar_wnt_.tmp
  351. echo 'x - extracting beta/reconfig.pl (Text)'
  352. sed 's/^X//' << 'SHAR_EOF' > 'beta/reconfig.pl' &&
  353. #!/bin/sh  # need to mention perl here to avoid recursion
  354. # NOTE:
  355. #   If you know where perl is and your system groks #!, put its
  356. # pathname at the top to make this a tad faster.
  357. #
  358. # the following magic is from the perl man page
  359. # and should work to get us to run with perl 
  360. # even if invoked as an sh or csh or foosh script.
  361. # notice we don't use full path cause we don't
  362. # know where the user has perl on their system.
  363. #
  364. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' 
  365. & eval 'exec perl -S $0 $argv:q'
  366. X    if $running_under_some_stupid_shell_instead_of_perl;
  367. X
  368. #  Target shell scripts in question:
  369. $COPS_CONFIG="pathconf.pl";
  370. X
  371. #  Potential directories to find commands:
  372. @all_dirs=("/bin",
  373. X       "/usr/bin",
  374. X       "/usr/ucb",
  375. X       "/usr/local/bin",  # scary
  376. X       "/usr/bsd");
  377. X
  378. # uncomment next line if you want your own current path used instead
  379. #
  380. # @all_dirs = split(/:/, $ENV{'PATH'});
  381. X
  382. #  Target commands in question, sans those checked above:
  383. @all_commands= ("cc", "awk", "cat",
  384. X        "chmod", "cmp", "comm", "cp",
  385. X        "date", "diff", "echo", "egrep", "expr",
  386. X        "find", "grep", "ls", "mail",
  387. X        "mkdir", "mv", "rm", "sed",
  388. X        "sh", "sort", "test", "tftp", "touch",
  389. X        "uudecode", "uniq", "ypcat");
  390. X
  391. @want{@all_commands} = ();
  392. X
  393. %exceptions=   ('strings', 'chk_strings',
  394. X                'tftp', 'misc.chk',
  395. X        'cmp', 'ftp.chk',
  396. X                'uudecode', 'misc.chk');
  397. X
  398. # grab the current values:
  399. open COPS_CONFIG || die "Can't open $COPS_CONFIG: $!\n";
  400. X
  401. $new = "$COPS_CONFIG.$$";
  402. open(NEW_CONFIG, ">$new") || die "Can't open $new: $!\n";
  403. X
  404. while (<COPS_CONFIG>) {
  405. X    unless (/\$(\w+)\s*=\s*(['"])(\S*)\2/) {
  406. X    print NEW_CONFIG;
  407. X    next;
  408. X    } 
  409. X    ($cap_command, $path) = ($1, $3);
  410. X    ($command = $cap_command) =~ tr/A-Z/a-z/;
  411. X    unless (($newpath = &getpath($command)) || $command =~ /^yp/) {
  412. X    warn "Warning!  no path for $command!\n";
  413. X    warn "          $exceptions{$command} will not work as planned!\n"
  414. X             if $exceptions{$command};
  415. X    $errors++;
  416. X    } else {
  417. X    delete $want{$command};
  418. X    } 
  419. X    print "old $path now in $newpath\n" if $newpath ne $path;
  420. X    print NEW_CONFIG "\$$cap_command = '$newpath';\n";
  421. X
  422. }
  423. X
  424. for (sort keys %want) {
  425. X    delete $want{$_} if $path = &getpath($_);
  426. X    tr/a-z/A-Z/;
  427. X    print NEW_CONFIG '$', $_, " = '", $path, "';\n";
  428. X
  429. close(COPS_CONFIG) || die "can't close $COPS_CONFIG: $!\n";
  430. close(NEW_CONFIG) || die "can't close $new: $!\n";
  431. X
  432. if (@missing = keys %want) {
  433. X     warn "Warning!   missing paths for @missing!\n";
  434. X     warn "The shell version may not work right!\n";
  435. X
  436. X
  437. if ($errors) {
  438. X    print STDERR "Not all paths were found: write anyway? ";
  439. X    # what about removing NEW_CONFIG, $new ??
  440. X    exit 1 if <STDIN> !~ /^\s*y/i;
  441. X    print STDERR "Ok, but this might not be right...\n";
  442. X
  443. $old = "$COPS_CONFIG.old";
  444. X
  445. rename($COPS_CONFIG, $old)
  446. X    || die "can't rename $COPS_CONFIG to $old: $!\n";
  447. X
  448. rename($new, $COPS_CONFIG)
  449. X    || die "can't rename $new to $COPS_CONFIG: $!\n";
  450. X
  451. X
  452. open COPS_CONFIG || die "can't re-open $COPS_CONFIG: $!\n";
  453. ($SH_CONF = $COPS_CONFIG) =~ s/\.pl$/.sh/;
  454. open (SH_CONF, ">$SH_CONF") || die "can't create $SH_CONF: $!\n";
  455. X
  456. while (<COPS_CONFIG>) {
  457. X    s/^\$//;
  458. X    print SH_CONF;
  459. close SH_CONF || die "can't close $SH_CONF: $!\n";
  460. X
  461. Xexit 0;
  462. X
  463. #############
  464. X
  465. sub getpath {
  466. X    local($cmd) = @_;
  467. X    local($path);
  468. X
  469. X    for (@all_dirs) {
  470. X    return $path if -x ($path = "$_/$cmd");
  471. X    } 
  472. X    '';
  473. SHAR_EOF
  474. chmod 0700 beta/reconfig.pl ||
  475. echo 'restore of beta/reconfig.pl failed'
  476. Wc_c="`wc -c < 'beta/reconfig.pl'`"
  477. test 3358 -eq "$Wc_c" ||
  478.     echo 'beta/reconfig.pl: original size 3358, current size' "$Wc_c"
  479. rm -f _shar_wnt_.tmp
  480. fi
  481. # ============= beta/root.chk ==============
  482. if test -f 'beta/root.chk' -a X"$1" != X"-c"; then
  483.     echo 'x - skipping beta/root.chk (File already exists)'
  484.     rm -f _shar_wnt_.tmp
  485. else
  486. > _shar_wnt_.tmp
  487. echo 'x - extracting beta/root.chk (Text)'
  488. sed 's/^X//' << 'SHAR_EOF' > 'beta/root.chk' &&
  489. #!/bin/sh -- need to mention perl here to avoid recursion
  490. 'true' || eval 'exec perl -S $0 $argv:q';
  491. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
  492. & eval 'exec /usr/local/bin/perl -S $0 $argv:q'
  493. X        if 0;
  494. X
  495. #
  496. #  Usage: root.chk
  497. #
  498. #  This script checks pathnames inside root's startup files for 
  499. # writability, improper umask settings (world writable), non-root
  500. # entries in /.rhosts, writable binaries in root's path,
  501. # and to ensure that root is in /etc/ftpuser.
  502. #
  503. # Also check for a single "+" in /etc/hosts.equiv (world is trusted),
  504. # and that /bin, /etc and certain key files are root owned, so that you
  505. # can't, say, rcp from a host.equived machine and blow over the password
  506. # file... this may or may not be bad, decide for yourself.
  507. # Startup files are /.login /.cshrc /.profile
  508. #
  509. #  Mechanism:  These files contain paths and filenames that are stripped
  510. # out using "grep".  These strings are then processed by the "is_able"
  511. # program to see if they are world writable.  Strings of the form:
  512. #
  513. #    path=(/bin /usr/bin .)
  514. #        and
  515. #    PATH=/bin:/usr/bin:.:
  516. #
  517. # are checked  to ensure that "." is not in the path.  All
  518. # results are echoed to standard output.  In addition, some effort was
  519. # put into parsing out paths with multiple lines; e.g. ending in "\",
  520. # and continuing on the next line.  Also, all executable files and 
  521. # directories in there are checked for writability as well.
  522. #
  523. #  For umask stuff, simply grep for umask in startup files, and check
  524. # umask value.  For /etc/ftpuser, simple grep to check if root is in
  525. # the file.  For /etc/hosts.equiv, just check to see if "+" is alone
  526. # on a line by awking it.
  527. #
  528. X
  529. # rewritten in perl by tchrist@convex.com
  530. X
  531. # root startup/important files
  532. X
  533. require 'file_owner.pl';
  534. require 'fgrep.pl';
  535. require 'suckline.pl';
  536. require 'is_able.pl';
  537. require 'chk_strings.pl';
  538. require 'glob.pl';
  539. X
  540. package root_chk;
  541. X
  542. # use -a true if you care about non-executables
  543. # in root's path
  544. X
  545. $ARGV[0] eq '-a' && ($all_files++, shift);
  546. X
  547. die "usage: root.chk [-a]\n" if @ARGV;
  548. X
  549. $W = 'Warning! ';
  550. X
  551. $cshrc    = '/.cshrc';
  552. $profile= '/.profile';
  553. $rhosts = '/.rhosts';
  554. X
  555. $| = 1;
  556. X
  557. @big_files= ('/.login', '/.cshrc', '/.profile', '/.logout' );
  558. X
  559. # root should own *at least* these, + $big_files; you can check for all files
  560. # in /bin & /etc, or just the directories (the default.)
  561. # root_files="/bin /bin/* /etc /etc/* $big_files $rhosts"
  562. @root_files= ('/bin','/etc',@big_files,$rhosts,'/etc/passwd','/etc/group');
  563. X
  564. # misc important stuff
  565. $ftp='/etc/ftpusers';
  566. $equiv='/etc/hosts.equiv';
  567. X
  568. #   should't have anyone but root owning /bin or /etc files/directories
  569. # In case some of the critical files don't exist (/.rhost), toss away error
  570. # messages
  571. X
  572. if (@bad_files = grep (-e && &'Owner($_), @root_files)) {
  573. X    print "$W  Root does not own the following file(s):\n";
  574. X    print "\t@bad_files\n";
  575. X
  576. local($chk_strings'recurse) = 1 unless defined $chk_strings'recurse;
  577. X
  578. for $file (@big_files) {
  579. X    open file || next;
  580. X
  581. X    &'chk_strings($file);
  582. X
  583. X    # check for group or other writable umask
  584. X    while (<file>) {
  585. X    next if /^\s*#/;
  586. X    next unless /umask\s*(\d+)/;
  587. X    next unless ~oct($1) & 022;
  588. X    print "$W root's umask set to $1 in $file\n";
  589. X    } 
  590. X
  591. print "$W $ftp exists and root is not in it\n" 
  592. X    if -e $ftp && !&'fgrep($ftp,'root');
  593. X
  594. print "$W A \"+\" entry exists in $equiv!\n" if &'fgrep($equiv, '^\+$');
  595. X
  596. if (open rhosts) {
  597. X    while (<rhosts>) {
  598. X    next unless /\S+\s+(\S+)/ && $1 ne 'root';
  599. X    print "$W Non-root entry in $rhosts! $1\n";
  600. X    }
  601. close(rhosts);
  602. X
  603. undef @rootpath;
  604. X
  605. # checking paths...
  606. #
  607. # Get the root paths from $csh.
  608. X
  609. if (open(CSHRC, $cshrc)) {
  610. X    $path = '';
  611. X    while (<CSHRC>) {
  612. X    next if /^\s*#/;
  613. X    chop unless /\\$/;
  614. X    if (/set\s+path\s*=/) {
  615. X        $_ = &'suckline($cshrc, $_);
  616. X        s/.*set\s+path\s*=\s*//;
  617. X        s/\((.*)\)/$1/;
  618. X        s/#.*/./;
  619. X        @tmppath = grep($_ ne '', split(' '));
  620. X        for (@tmppath) { $whence{$_} .= " " . $cshrc; } 
  621. X        push(@rootpath, @tmppath);
  622. X    } 
  623. X    } 
  624. X    close(CSHRC);
  625. X
  626. if (open login) {
  627. X    $path = '';
  628. X    while (<cshrc>) {
  629. X    next if /^\s*#/;
  630. X    chop unless /\\$/;
  631. X    if (/set\s+path\s*=/) {
  632. X        $_ = &'suckline('login', $_);
  633. X        s/.*set\s+path\s*=\s*//;
  634. X        s/\((.*)\)/$1/;
  635. X        s/#.*/./;
  636. X        @tmppath = grep($_ ne '', split(' '));
  637. X        for (@tmppath) { $whence{$_} .= " " . $login; } 
  638. X        push(@rootpath, @tmppath);
  639. X    } 
  640. X    } 
  641. X    close(login);
  642. }
  643. X
  644. if (open profile) {
  645. X    $path = '';
  646. X    while (<profile>) {
  647. X    next if /^\s*#/;
  648. X    chop unless /\\$/;
  649. X    if (/PATH=/) {
  650. X        $_ = &'suckline('profile', $_);
  651. X        s/.*PATH=//;
  652. X        s/#.*//;
  653. X        @tmppath = split(/:/);
  654. X        for (@tmppath) { $whence{$_} .= " " . $profile; } 
  655. X        push(@rootpath, @tmppath);
  656. X    } 
  657. X    } 
  658. X    close(profile);
  659. X
  660. for (keys %whence) {
  661. X    $whence{$_} =~ s/^ //;
  662. X    $whence{$_} =~ s/ / and /g;
  663. X
  664. undef %seen;
  665. grep($seen{$_}++, @rootpath);
  666. X
  667. $is_able'silent = 1;
  668. for (keys %seen) {
  669. X    if (!-e && $_ ne ".") {
  670. X    print "$W path component $_ in $whence{$_} doesn't exist!\n";
  671. X    next;
  672. X    } 
  673. X
  674. X    if (/^\.?$/) {  # null -> dot
  675. X    print "$W \".\" (or current directory) is in root's path in $whence{$_}!\n";
  676. X    } elsif (&'is_writable($_)) {
  677. X    print "$W Directory $_ is _World_ writable and in root's path in $whence{$_}!\n";
  678. X    next;
  679. X    }
  680. X
  681. X    foreach $file (&'glob("$_/*")) {
  682. X    # can't just check -x here, as that depends on current user
  683. X    $is_executable = -f $file && (&'Mode($file) & 0111);
  684. X    if (($all_files || $is_executable) && 
  685. X            ($how = &'is_writable($file, 'w', 'w'))) {
  686. X        print "$W _World_ $how ",
  687. X            $is_executable ? 'executable' : 'file',
  688. X        " $file in root path component $_ from $whence{$_}!\n";
  689. X    } 
  690. X    }
  691. X
  692. $is_able'silent = 0;
  693. X
  694. 1;
  695. SHAR_EOF
  696. chmod 0700 beta/root.chk ||
  697. echo 'restore of beta/root.chk failed'
  698. Wc_c="`wc -c < 'beta/root.chk'`"
  699. test 5609 -eq "$Wc_c" ||
  700.     echo 'beta/root.chk: original size 5609, current size' "$Wc_c"
  701. rm -f _shar_wnt_.tmp
  702. fi
  703. # ============= beta/rules.pl ==============
  704. if test -f 'beta/rules.pl' -a X"$1" != X"-c"; then
  705.     echo 'x - skipping beta/rules.pl (File already exists)'
  706.     rm -f _shar_wnt_.tmp
  707. else
  708. > _shar_wnt_.tmp
  709. echo 'x - extracting beta/rules.pl (Text)'
  710. sed 's/^X//' << 'SHAR_EOF' > 'beta/rules.pl' &&
  711. sub apply_rules {
  712. X    local($op, $value, @plan) = @_;
  713. X
  714. X    printf("eval($op $value): %s\n", &ascii_plan(@plan)) if $opt_d;
  715. X
  716. X    #
  717. X    # apply UID attack rules...
  718. X    #
  719. X    if ($op eq "u") {
  720. X    #
  721. X    # If we can replace /etc/passwd or /usr/lib/aliases, we can grant 
  722. X    # any uid. 
  723. X    #
  724. X    &addto("r", "/etc/passwd", @plan);
  725. X        &addto("r", "/usr/lib/aliases", @plan);
  726. X        &addto("r", "/etc/aliases", @plan);
  727. X
  728. X    #
  729. X    # Check CF's for all usernames with this uid.
  730. X    #
  731. uname_loop:
  732. X    foreach $uname (split(/ /, $uid2names{$value})) {
  733. X        $home = $uname2dir{$uname};
  734. X
  735. X        next uname_loop unless $home;
  736. X
  737. X        if ($home eq "/") {
  738. X        $home = "";
  739. X        }
  740. X        &addto("r", "$home/.rhosts", @plan);
  741. X        &addto("r", "$home/.login", @plan);
  742. X        &addto("r", "$home/.logout", @plan);
  743. X        &addto("r", "$home/.cshrc", @plan);
  744. X        &addto("r", "$home/.profile", @plan);
  745. X    }
  746. X
  747. X    #
  748. X    # Controlling files for root...
  749. X    #
  750. X    @rootlist = ( 
  751. X        "/etc/rc", "/etc/rc.boot", "/etc/rc.single", 
  752. X        "/etc/rc.config", "/etc/rc.local", "/usr/lib/crontab",
  753. X        "/usr/spool/cron/crontabs",
  754. X        );
  755. X
  756. X    if ($value eq "0") {
  757. X        foreach $file (@rootlist) {
  758. X            &addto("r", $file, @plan);
  759. X        }
  760. X        # Experimental!
  761. X        # you can remove this if desired - tjt
  762. X        #do "rc.prog";
  763. X    }
  764. X
  765. X    #
  766. X    # Other CFs for non-root folks...
  767. X    #
  768. X    if ($value ne "0") {
  769. X        &addto("r", "/etc/hosts.equiv", @plan);
  770. X        if (-s "/etc/hosts.equiv") {
  771. X        &addto("r", "/etc/hosts", @plan);
  772. X        }
  773. X    }
  774. X
  775. X    #
  776. X    # Plans for attacking GIDs...
  777. X    #
  778. X    } elsif ($op eq "g") {    # apply gid attack rules
  779. X
  780. X    #
  781. X    # If we can replace /etc/group we can become any group
  782. X    #                  
  783. X        &addto("r", "/etc/group", @plan);
  784. X
  785. X    #
  786. X    # If we can grant any member of a group we can grant that group
  787. X    #
  788. member_loop:
  789. X    foreach $uname (split(/ /, $gid2members{$value})) {
  790. X        if (! defined($uname2uid{$uname})) {
  791. X        printf(stderr "group '%s' member '%s' doesn't exist.\n",
  792. X            $value,
  793. X            $uname);
  794. X        next member_loop;
  795. X        }
  796. X
  797. X        &addto("u", $uname2uid{$uname}, @plan);
  798. X    }
  799. X
  800. X    #
  801. X    # Plans for attacking files...
  802. X    #
  803. X
  804. X    } elsif ($op eq "r" || $op eq "w") {
  805. X
  806. X        ($owner, $group, $other) = &filewriters($value);
  807. X
  808. X    &addto("u", $owner, @plan) if ($owner ne "");
  809. X    &addto("g", $group, @plan) if ($group ne "");
  810. X    &addto("u", "-1", @plan) if ($other);
  811. X
  812. X    #
  813. X    # If the goal is to replace the file, check the parent directory...
  814. X    #
  815. X    if ($op eq "r") {
  816. X        $parent = $value;
  817. X        $parent =~ s#/[^/]*$##;     # strip last / and remaining stuff
  818. X
  819. X        if ($parent eq "") {
  820. X        $parent = "/";
  821. X        }
  822. X
  823. X        if ($parent ne $value) {
  824. X        &addto("r", $parent, @plan);
  825. X        }
  826. X    }
  827. X
  828. X    } else {            # wow, bad $type of object!
  829. X    printf(stderr "kuang: bad op in apply_rules!\n");
  830. X    printf(stderr "op '%s' value '%s' plan '%s'\n",
  831. X        $op,
  832. X        $value,
  833. X        &ascii_plan(@plan));
  834. X    exit(1);
  835. X    }
  836. }
  837. X
  838. 1;
  839. X
  840. SHAR_EOF
  841. chmod 0600 beta/rules.pl ||
  842. echo 'restore of beta/rules.pl failed'
  843. Wc_c="`wc -c < 'beta/rules.pl'`"
  844. test 2768 -eq "$Wc_c" ||
  845.     echo 'beta/rules.pl: original size 2768, current size' "$Wc_c"
  846. rm -f _shar_wnt_.tmp
  847. fi
  848. # ============= beta/stat.pl ==============
  849. if test -f 'beta/stat.pl' -a X"$1" != X"-c"; then
  850.     echo 'x - skipping beta/stat.pl (File already exists)'
  851.     rm -f _shar_wnt_.tmp
  852. else
  853. > _shar_wnt_.tmp
  854. echo 'x - extracting beta/stat.pl (Text)'
  855. sed 's/^X//' << 'SHAR_EOF' > 'beta/stat.pl' &&
  856. ;# $Header: stat.pl,v 3.0.1.1 90/08/09 04:01:34 lwall Locked $
  857. ;# Usage:
  858. ;#    require 'stat.pl';
  859. ;#    @ary = stat(foo);
  860. ;#    $st_dev = @ary[$ST_DEV];
  861. ;#
  862. $ST_DEV =    0 + $[;
  863. $ST_INO =    1 + $[;
  864. $ST_MODE =    2 + $[;
  865. $ST_NLINK =    3 + $[;
  866. $ST_UID =    4 + $[;
  867. $ST_GID =    5 + $[;
  868. $ST_RDEV =    6 + $[;
  869. $ST_SIZE =    7 + $[;
  870. $ST_ATIME =    8 + $[;
  871. $ST_MTIME =    9 + $[;
  872. $ST_CTIME =    10 + $[;
  873. $ST_BLKSIZE =    11 + $[;
  874. $ST_BLOCKS =    12 + $[;
  875. X
  876. ;# Usage:
  877. ;#    require 'stat.pl';
  878. ;#    do Stat('foo');        # sets st_* as a side effect
  879. ;#
  880. sub Stat {
  881. X    ($st_dev,$st_ino,$st_mode,$st_nlink,$st_uid,$st_gid,$st_rdev,$st_size,
  882. X    $st_atime,$st_mtime,$st_ctime,$st_blksize,$st_blocks) = stat(shift(@_));
  883. }
  884. X
  885. 1;
  886. SHAR_EOF
  887. chmod 0700 beta/stat.pl ||
  888. echo 'restore of beta/stat.pl failed'
  889. Wc_c="`wc -c < 'beta/stat.pl'`"
  890. test 653 -eq "$Wc_c" ||
  891.     echo 'beta/stat.pl: original size 653, current size' "$Wc_c"
  892. rm -f _shar_wnt_.tmp
  893. fi
  894. # ============= beta/suckline.pl ==============
  895. if test -f 'beta/suckline.pl' -a X"$1" != X"-c"; then
  896.     echo 'x - skipping beta/suckline.pl (File already exists)'
  897.     rm -f _shar_wnt_.tmp
  898. else
  899. > _shar_wnt_.tmp
  900. echo 'x - extracting beta/suckline.pl (Text)'
  901. sed 's/^X//' << 'SHAR_EOF' > 'beta/suckline.pl' &&
  902. #
  903. #  As title implies... :-)
  904. #
  905. sub main'suckline {
  906. X    local($file, $_) = @_;
  907. #   local($package) = caller;
  908. X
  909. #   $file =~ s/^([^']+)$/$package'$1/; 
  910. X    {
  911. X    if (s/\\\n?$//) {
  912. X        $_ .= <$file>;
  913. X        redo;
  914. X    }
  915. X    } 
  916. X    $_;
  917. }
  918. X
  919. 1;
  920. SHAR_EOF
  921. chmod 0700 beta/suckline.pl ||
  922. echo 'restore of beta/suckline.pl failed'
  923. Wc_c="`wc -c < 'beta/suckline.pl'`"
  924. test 229 -eq "$Wc_c" ||
  925.     echo 'beta/suckline.pl: original size 229, current size' "$Wc_c"
  926. rm -f _shar_wnt_.tmp
  927. fi
  928. # ============= beta/suid.chk ==============
  929. if test -f 'beta/suid.chk' -a X"$1" != X"-c"; then
  930.     echo 'x - skipping beta/suid.chk (File already exists)'
  931.     rm -f _shar_wnt_.tmp
  932. else
  933. > _shar_wnt_.tmp
  934. echo 'x - extracting beta/suid.chk (Text)'
  935. sed 's/^X//' << 'SHAR_EOF' > 'beta/suid.chk' &&
  936. #!/bin/sh -- need to mention perl here to avoid recursion
  937. 'true' || eval 'exec perl -S $0 $argv:q';
  938. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
  939. & eval 'exec /usr/local/bin/perl -S $0 $argv:q'
  940. X        if 0;
  941. X
  942. #
  943. #  Usage: suid.chk [-n] [-s secure_dir] [search_starting_directory]
  944. #
  945. #   Shell script intended to be run periodically by cron in order
  946. #   to spot changes in files with the suid or sgid bits set.
  947. #
  948. #    suid.chk    840919        Prentiss Riddle
  949. #
  950. #     This changes into the $SECURE directory first, then 
  951. #   uses find(1) to search the directories in $SEARCH for all
  952. #   files with the 4000 or 2000 permission bits set.  $STOP is a file
  953. #   containing "ls -gildsa" output for known setuid or setgid programs.
  954. #   Any additions or changes to this list represent potential security
  955. #   problems, so they are reported.
  956. #
  957. #  Modified 8/15/89, Dan Farmer:
  958. #    Just changed the program/doc names and some of the temp
  959. #  files to make it fit in with the rest of the programs....
  960. #  Modified 12/26/90, df
  961. #       Now flags SUID shell scripts and world writeable SUID files, too.
  962. #
  963. #  Rewritten in perl, 1/17/91, df
  964. #  Major hacks by tchrist 5/14/91
  965. #
  966. X
  967. require "hostname.pl";
  968. require "is_able.pl";
  969. require "file_owner.pl";
  970. require "pathconf.pl";
  971. require "chk_strings.pl";
  972. require "pass.cache.pl";
  973. package suid_chk; # name space protection
  974. $debug=0;
  975. X
  976. #
  977. # Getopts stuff
  978. $usage = "Usage: $0 [-n] [-s secure_dir] [starting_directory]\n";
  979. require 'getopts.pl';
  980. # Process the command args; Either specify verbose or an alternate config file:
  981. die $usage unless &`Getopts('ns:');
  982. X
  983. $suid_dir = $'SECURE || '.';
  984. if (defined($opt_s)) { $suid_dir = $opt_s; }
  985. X
  986. # Do NFS stuff?  Yes unless opt:
  987. if (defined($opt_n)) { $skip_nfs = $opt_n; }
  988. else { $skip_nfs = 0; }
  989. X
  990. $STOP="$suid_dir/suid.stop";
  991. $TEMPOLD="$suid_dir/fsold$$";
  992. $TEMPCUR="$suid_dir/fscur$$";
  993. $TEMPNEW="$suid_dir/fsnew$$";
  994. $TEMPGON="$suid_dir/fsgon$$";
  995. $TEMPM="$suid_dir/fsm$$";
  996. X
  997. if (@ARGV > 1) { die $usage; }
  998. elsif (@ARGV == 1) { $start_dir = shift; }
  999. X
  1000. # these may be terribly rash assumptions....
  1001. $start_dir="/" unless defined $start_dir;
  1002. $find_can_ls = 1 unless defined $find_can_ls;
  1003. X
  1004. $NONFS = '-type d \( -fstype nfs -prune \) -o' if $skip_nfs;  
  1005. $find_ls = $find_can_ls ? '-ls' : "-exec $'LS -gilds {} \\;";
  1006. X
  1007. die "Error -- Security directory $suid_dir doesn't exist\n"
  1008. X    unless -d $suid_dir;
  1009. unless (-d $suid_dir) {
  1010. X    mkdir($suid_dir, 0700) || die "can't mkdir $suid_dir: $!";
  1011. chdir $suid_dir || die "can't chdir $suid_dir: $!\n";
  1012. X
  1013. # find the setuid programs and sort
  1014. &run("$'FIND $start_dir $NONFS -type f \\( -perm -4000 -o -perm -2000 \\) $find_ls | $'SORT > $TEMPCUR");
  1015. X
  1016. # compare with the sorted stop list
  1017. # create stop file if needed
  1018. if (! -f $STOP) { open(S,">$STOP"); close(S); }
  1019. X
  1020. &run("$'SORT <$STOP >$TEMPOLD");
  1021. &run("$'COMM -13 $TEMPOLD $TEMPCUR | $'SORT +8 >$TEMPNEW");
  1022. &run("$'COMM -23 $TEMPOLD $TEMPCUR | $'SORT +8 >$TEMPGON");
  1023. X
  1024. local($is_able'silent) = 1;
  1025. local($chk_strings'recurse) = 0 unless defined $chk_strings'recurse;
  1026. X
  1027. # report changes
  1028. if (-s $TEMPNEW || -s $TEMPGON) {
  1029. X    if (-s $TEMPNEW) {
  1030. X    open TEMPNEW || die "Can't open $TEMPNEW: $!\n";
  1031. X    while (<TEMPNEW>) {
  1032. X        ($file) = /(\S+)$/;
  1033. X
  1034. X        # don't want SUID files to be world writable!
  1035. X        # although *reasonable* systems clear the bit on write
  1036. X        print "Warning!  SUID file $file is _World_ writable!\n" 
  1037. X        if &'is_able ($file, "w", "w"); 
  1038. X            
  1039. X        if (-r $file && -f _ && -T $file) {
  1040. X        print "Warning!  ", &'Owner($file) ? '' : 'ROOT-owned ', 
  1041. X            "SUID file $file is a non-binary, executable file!\n";
  1042. X        }
  1043. X
  1044. X        &'chk_strings($file) if -r _;
  1045. X    }
  1046. X    close TEMPNEW;
  1047. X    }
  1048. X
  1049. X    if (-s $TEMPNEW) {
  1050. X    open TEMPNEW || die "Can't reopen $TEMPNEW: $!\n";
  1051. X    print "\nThese files are newly setuid/setgid:\n\n";
  1052. X    print while <TEMPNEW>;
  1053. X    }
  1054. X
  1055. X    if (-s $TEMPGON) {
  1056. X    open TEMPGON || die "Can't reopen $TEMPGON: $!\n";
  1057. X    print "\nThese files are no longer setuid/setgid:\n\n";
  1058. X    print while <TEMPGON>;
  1059. X    }
  1060. X
  1061. }
  1062. X
  1063. unlink $TEMPOLD, $TEMPCUR, $TEMPNEW, $TEMPGON;
  1064. X
  1065. sub run {
  1066. X    print "running: $_[0]\n" if $debug;
  1067. X    system $_[0];
  1068. X    warn "command $_[0] returned $?" if $?;
  1069. X
  1070. #  end it all....
  1071. X
  1072. 1;
  1073. SHAR_EOF
  1074. chmod 0700 beta/suid.chk ||
  1075. echo 'restore of beta/suid.chk failed'
  1076. Wc_c="`wc -c < 'beta/suid.chk'`"
  1077. test 4128 -eq "$Wc_c" ||
  1078.     echo 'beta/suid.chk: original size 4128, current size' "$Wc_c"
  1079. rm -f _shar_wnt_.tmp
  1080. fi
  1081. # ============= beta/suid.stop ==============
  1082. if test -f 'beta/suid.stop' -a X"$1" != X"-c"; then
  1083.     echo 'x - skipping beta/suid.stop (File already exists)'
  1084.     rm -f _shar_wnt_.tmp
  1085. else
  1086. > _shar_wnt_.tmp
  1087. echo 'x - extracting beta/suid.stop (Text)'
  1088. sed 's/^X//' << 'SHAR_EOF' > 'beta/suid.stop' &&
  1089. SHAR_EOF
  1090. chmod 0700 beta/suid.stop ||
  1091. echo 'restore of beta/suid.stop failed'
  1092. Wc_c="`wc -c < 'beta/suid.stop'`"
  1093. test 0 -eq "$Wc_c" ||
  1094.     echo 'beta/suid.stop: original size 0, current size' "$Wc_c"
  1095. rm -f _shar_wnt_.tmp
  1096. fi
  1097. # ============= beta/user.chk ==============
  1098. if test -f 'beta/user.chk' -a X"$1" != X"-c"; then
  1099.     echo 'x - skipping beta/user.chk (File already exists)'
  1100.     rm -f _shar_wnt_.tmp
  1101. else
  1102. > _shar_wnt_.tmp
  1103. echo 'x - extracting beta/user.chk (Text)'
  1104. sed 's/^X//' << 'SHAR_EOF' > 'beta/user.chk' &&
  1105. #!/bin/sh -- need to mention perl here to avoid recursion
  1106. 'true' || eval 'exec perl -S $0 $argv:q';
  1107. eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
  1108. & eval 'exec /usr/local/bin/perl -S $0 $argv:q'
  1109. X        if 0;
  1110. X
  1111. #
  1112. #  This combines user.chk and home.chk.  It searches for home directories
  1113. # and various user startup files for world writability, as well as flagging
  1114. # any .rhosts and .netrc files that are readable.  You can change the
  1115. # files checked by changing @ftable and @readables, respectively.
  1116. X
  1117. #
  1118. # check for writable files in all user's homes
  1119. #
  1120. require "pass.cache.pl";
  1121. require "is_able.pl";
  1122. X
  1123. # files checked for:
  1124. @ftable = ("rhosts", "profile", "login", "logout", "cshrc",
  1125. X       "bashrc", "bash_profile", "inputrc", "screenrc",
  1126. X       "kshrc", "tcshrc", "netrc", "forward", "dbxinit",
  1127. X       "distfile", "exrc", "emacsrc", "remote", "mh_profile",
  1128. X       "xinitrc", "xsession", "Xdefaults", "Xresources", "rninit");
  1129. X
  1130. @readables = ("netrc", "rhosts");
  1131. X
  1132. local(%done);
  1133. X
  1134. # what's the point of doing a keys and using $i ??
  1135. # why not just do "for $dir (values %uname2dir) {" ????
  1136. for $i (keys %uname2dir) {
  1137. X    $dir = $uname2dir{$i};
  1138. X    #   I don't want to hear about every file in their home dir, if 
  1139. X    # is WW, but still need to check the .netrc file for readability...
  1140. X    next unless $dir;
  1141. X    next if $done{$dir}++;
  1142. X    if (-e $dir) { 
  1143. X        if (&is_able($dir, "w", "w")) {
  1144. X            for $r (@readables) {
  1145. X                if (-s "$dir/.$r") {
  1146. X                    &is_able("$dir/.$r", "w", "r");
  1147. X        }
  1148. X        }
  1149. X            next;
  1150. X    }
  1151. X        for $file (@ftable) {
  1152. X            $foo_file = $dir . "/.$file";
  1153. X            if (-e $foo_file) {
  1154. X                &is_able($foo_file, "w", "w");
  1155. X                for $r (@readables) {
  1156. X                    if ($file eq $r && -s $foo_file) {
  1157. X                        &is_able($foo_file, "w", "r");
  1158. X            }
  1159. X        }
  1160. X        }
  1161. X    }
  1162. X    }
  1163. }
  1164. X
  1165. 1;
  1166. SHAR_EOF
  1167. chmod 0700 beta/user.chk ||
  1168. echo 'restore of beta/user.chk failed'
  1169. Wc_c="`wc -c < 'beta/user.chk'`"
  1170. test 1870 -eq "$Wc_c" ||
  1171.     echo 'beta/user.chk: original size 1870, current size' "$Wc_c"
  1172. rm -f _shar_wnt_.tmp
  1173. fi
  1174. # ============= beta/yagrip.pl ==============
  1175. if test -f 'beta/yagrip.pl' -a X"$1" != X"-c"; then
  1176.     echo 'x - skipping beta/yagrip.pl (File already exists)'
  1177.     rm -f _shar_wnt_.tmp
  1178. else
  1179. > _shar_wnt_.tmp
  1180. echo 'x - extracting beta/yagrip.pl (Text)'
  1181. sed 's/^X//' << 'SHAR_EOF' > 'beta/yagrip.pl' &&
  1182. #Yet Another Getopt Routine In Perl
  1183. # jgreely@cis.ohio-state.edu, 89/11/1
  1184. #usage:
  1185. #&getopt("f:bar") ||
  1186. #    die &usage("script","f:bar","oo","[files ...]");
  1187. #
  1188. sub getopt {
  1189. X    local($_,$flag,$opt,$f,$r,@temp) = @_;
  1190. X    @temp = split(/(.):/);
  1191. X    while ($#temp >= $[) {
  1192. X        $flag .= shift(@temp);
  1193. X        $opt .= shift(@temp);
  1194. X    }
  1195. X    while ($_ = $ARGV[0], /^-(.)(.*)/ && shift(@ARGV)) {
  1196. X        ($f,$r) = ($1,$2);
  1197. X        last if $f eq '-';
  1198. X        if (index($flag,$f) >= $[) {
  1199. X            eval "\$opt_$f++;";
  1200. X            $r =~ /^(.)(.*)/,redo if $r ne '';
  1201. X        }elsif (index($opt,$f) >= $[) {
  1202. X            $r = $r eq '' ? shift(@ARGV) : $r;
  1203. X            eval "\$opt_$f = \$r;";
  1204. X        }else{
  1205. X            print STDERR "Unrecognized switch \"-$f\".\n";
  1206. X            return 0;
  1207. X        }
  1208. X    }
  1209. X    return 1;
  1210. }
  1211. X
  1212. #usage: usage:
  1213. # &usage(progname,arglist,@names,@last);
  1214. #ex:
  1215. # &usage("script","f:bar","oo","[file ...]");
  1216. #would return
  1217. # "usage: script [-f oo] [-bar] [file ...]"
  1218. #
  1219. sub usage {
  1220. X    local($prog,$_,@list) = @_;
  1221. X    local($string,$flag,@string,@temp,@last) = ();
  1222. X    @temp = split(/(.):/);
  1223. X    push(@string,"usage:",$prog);
  1224. X    while ($#temp >= $[) {
  1225. X        if (($flag = shift(@temp)) ne '') {
  1226. X            push(@string,"[-$flag]");
  1227. X        }
  1228. X        if (($flag = shift(@temp)) ne '') {
  1229. X            push(@string,sprintf("[-%s %s]",$flag,shift(@list)));
  1230. X        }
  1231. X    }
  1232. X    push(@string,@list) if $#list >= $[;
  1233. X    return join(' ',@string) . "\n";
  1234. }
  1235. 1;
  1236. SHAR_EOF
  1237. chmod 0600 beta/yagrip.pl ||
  1238. echo 'restore of beta/yagrip.pl failed'
  1239. Wc_c="`wc -c < 'beta/yagrip.pl'`"
  1240. test 1274 -eq "$Wc_c" ||
  1241.     echo 'beta/yagrip.pl: original size 1274, current size' "$Wc_c"
  1242. rm -f _shar_wnt_.tmp
  1243. fi
  1244. rm -f _shar_seq_.tmp
  1245. echo You have unpacked the last part
  1246. exit 0
  1247.