df@sei.cmu.edu (Dan Farmer) (01/08/91)
#!/bin/sh # This is cops, a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 01/08/1991 03:41 UTC by df@death.cert.sei.cmu.edu # Source directory /usr/users/df/COPS # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1093 -rw------- cops/MANIFEST # 22466 -rw------- cops/README # 1752 -rwx------ cops/README.apollo # 636 -rw------- cops/README.xenix # 3417 -rw------- cops/XTRA_CREDIT # 3254 -rw------- cops/src/addto.c # 702 -rw------- cops/src/clearfiles.c # 9920 -rw------- cops/src/crc.c # 4068 -rw------- cops/src/crc_check.c # 2420 -rw------- cops/src/filewriters.c # 2916 -rw------- cops/src/home.chk.c # 5278 -rw------- cops/src/is_able.c # 3206 -rw------- cops/src/is_something.c # 1258 -rw------- cops/src/members.c # 15629 -rw------- cops/src/pass.c # 401 -rw------- cops/src/tilde.c # 1721 -rw------- cops/src/user.chk.c # 1551 -rwx------ cops/chk_strings # 5482 -rwx------ cops/cops # 7085 -rw------- cops/cover_letter # 2093 -rwx------ cops/crc.chk # 1045 -rw------- cops/crc_list # 2240 -rwx------ cops/cron.chk # 3332 -rwx------ cops/dev.chk # 20290 -rwx------ cops/README.C2 # 1123 -rw------- cops/disclaimer # 7580 -rwx------ cops/ftp.chk # 5147 -rwx------ cops/group.chk # 773 -rwx------ cops/init_kuang # 1637 -rwx------ cops/is_able.chk # 1547 -rw------- cops/is_able.lst # 5969 -rwx------ cops/kuang # 41217 -rw------- cops/kuang.pl.shar # 2250 -rw------- cops/makefile # 3240 -rwx------ cops/misc.chk # 3278 -rw------- cops/pass.words # 5702 -rwx------ cops/passwd.chk # 31849 -rw------- cops/docs/COPS.report # 886 -rw------- cops/docs/KUANG.README # 501 -rw------- cops/docs/SUID.README # 2568 -rw------- cops/docs/cops # 875 -rw------- cops/docs/dev.chk # 4278 -rw------- cops/docs/CRC.README # 270 -rw------- cops/docs/home.chk # 1524 -rw------- cops/docs/pass.chk # 980 -rw------- cops/docs/is_able # 2809 -rw------- cops/docs/kuang.1 # 36594 -rw------- cops/docs/kuang.man # 775 -rw------- cops/docs/rc.chk # 992 -rw------- cops/docs/is_able.chk # 3833 -rw------- cops/docs/release.notes # 1157 -rw------- cops/docs/suid.man # 230 -rw------- cops/docs/tilde # 13863 -rw------- cops/docs/warnings # 509 -rw------- cops/docs/root.chk # 973 -rw------- cops/docs/cron.chk # 654 -rw------- cops/docs/group.chk # 743 -rw------- cops/docs/pass_diff.chk # 481 -rw------- cops/docs/user.chk # 1945 -rw------- cops/docs/makefile # 941 -rw------- cops/docs/passwd.chk # 593 -rw------- cops/docs/misc.chk # 2838 -rw------- cops/docs/ftp.chk # 1638 -rw------- cops/extensions/THINGS_2_DO # 595 -rw------- cops/extensions/YAR # 395 -rw------- cops/extensions/crypto-stuff # 1859 -rw------- cops/extensions/netstuff # 690 -rw------- cops/extensions/passwords # 13339 -rw------- cops/extensions/questions # 2685 -rwx------ cops/pass_diff.chk # 21 -rw------- cops/patchlevel.h # 2403 -rwx------ cops/rc.chk # 5322 -rwx------ cops/reconfig # 886 -rwx------ cops/res_diff # 4901 -rwx------ cops/root.chk # 644 -rw------- cops/stop.sample # 4209 -rwx------ cops/suid.chk # 582 -rw------- cops/README.yp # 827 -rw------- cops/yp_pass.chk # # ============= cops/MANIFEST ============== if test ! -d 'cops'; then echo 'x - creating directory cops' mkdir 'cops' fi if test -f 'cops/MANIFEST' -a X"$1" != X"-c"; then echo 'x - skipping cops/MANIFEST (File already exists)' else echo 'x - extracting cops/MANIFEST (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/MANIFEST' && XFile Name X================== XMANIFEST XREADME XREADME.apollo XREADME.xenix XREADME.yp XXTRA_CREDIT Xchk_strings Xcops Xcover_letter Xcrc.chk Xcrc_list Xcron.chk Xdev.chk Xdisclaimer Xdocs Xextensions Xftp.chk Xgroup.chk Xinit_kuang Xis_able.chk Xis_able.lst Xkuang Xkuang.pl.shar Xmakefile Xmisc.chk Xpass.words Xpass_diff.chk Xpasswd.chk Xpatchlevel.h Xrc.chk Xreconfig Xres_diff Xroot.chk Xsrc Xstop.sample Xsuid.chk Xyp_pass.chk X Xdocs/COPS.report Xdocs/COPS.report Xdocs/CRC.README Xdocs/KUANG.README Xdocs/SUID.README Xdocs/cops Xdocs/cron.chk Xdocs/dev.chk Xdocs/ftp.chk Xdocs/group.chk Xdocs/home.chk Xdocs/is_able Xdocs/is_able.chk Xdocs/kuang.1 Xdocs/kuang.man Xdocs/makefile Xdocs/misc.chk Xdocs/pass.chk Xdocs/pass_diff.chk Xdocs/passwd.chk Xdocs/rc.chk Xdocs/release.notes Xdocs/root.chk Xdocs/suid.man Xdocs/tilde Xdocs/user.chk Xdocs/warnings X Xextensions/THINGS_2_DO Xextensions/YAR Xextensions/crypto-stuff Xextensions/netstuff Xextensions/passwords Xextensions/questions X Xsrc/addto.c Xsrc/clearfiles.c Xsrc/crc.c Xsrc/crc_check.c Xsrc/filewriters.c Xsrc/home.chk.c Xsrc/is_able.c Xsrc/is_something.c Xsrc/members.c Xsrc/pass.c Xsrc/tilde.c Xsrc/user.chk.c SHAR_EOF chmod 0600 cops/MANIFEST || echo 'restore of cops/MANIFEST failed' Wc_c="`wc -c < 'cops/MANIFEST'`" test 1093 -eq "$Wc_c" || echo 'cops/MANIFEST: original size 1093, current size' "$Wc_c" fi # ============= cops/README ============== if test -f 'cops/README' -a X"$1" != X"-c"; then echo 'x - skipping cops/README (File already exists)' else echo 'x - extracting cops/README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/README' && X X Welcome! You now hold in your hands (terminal?) a collection Xof security tools that are designed specifically to aid the typical XUNIX systems administrator, programmer, operator, or consultant in Xthe oft neglected area of computer security. X X The package, which will be henceforth be referred to as COPS X(Computer Oracle and Password System), can be broken down into three Xkey parts. The first is the actual set of programs that attempt Xto automate security checks that are often performed manually (or Xperhaps with self written short shell scripts or programs) by a systems Xadministrator. The second part is the documentation, which details Xhow to set up, operate, and to interpret any results given by the Xprograms. Finally, COPS is an evolving beast. It includes a list Xof possible extensions that might appear in future releases, as well Xas pointers to other works in UNIX security that could not be included Xat this time, due to space or other restrictions. X X This document contains six sections: X X 1) What is COPS? X 2) What COPS is _not_ X 3) How to Configure COPS X 4) Running COPS for the 1st Time X 5) Continued Use and Installing COPS X 6) Disclaimer and End Notes X X X1) What is COPS? X----------------- X X COPS is a collection of about a dozen (actually, a few more, but Xa dozen is such a good sounding number) programs that each attempt Xto tackle a different problem area of UNIX security. Here is what it Xcurrently checks: X Xo file, directory, and device permissions/modes. X Xo poor passwords. X Xo content, format, and security of password and group files. X Xo the programs and files run in /etc/rc* and cron(tab) files. X Xo finds SUID files, and checks for their writeability and if they are X shell scripts. X Xo runs a crc check against important binaries or key files, and reports X any changes therein. X Xo writability of users home directories and startup files (.profile, X .cshrc, etc.) X Xo anonymous ftp setup. X Xo unrestricted tftp, decode alias in sendmail, SUID uudecode problems. X Xo miscellaneous root checks -- current directory in the search path, X a "+" in /etc/host.equiv, unrestricted NFS mounts, ensures root is X in /etc/ftpusers, etc. X Xo includes the Kuang expert system, that takes a set of rules and tries X to determine if your system can be compromised (for a more complete list X of all of the checks, look at the file "release.notes" or "cops.report"; X for more on Kuang, look at at "kuang.man".) X X All of the programs merely warn the user of a potential problem -- XCOPS DOES NOT ATTEMPT TO CORRECT OR EXPLOIT ANY OF THE POTENTIAL PROBLEMS XIT FINDS! COPS either mails or creates a file (user selectable) of any Xof the problems it finds while running on your system. And because COPS Xdoes not correct potential hazards it finds, it does _not_ have to be Xrun by a privileged account (i.e. root or whomever.) The only security Xcheck that should be run by root to get maximum results is the SUID checker; Xalthough it can be run as an unprivileged user, to find all the SUID files Xin a system, it should be run as root (in addition, if key binaries are Xnot world readable, only executable, the CRC checking program ("crc.chk") Xneeds to be run as a privileged user to read the file in question to get Xthe result.) In addition, COPS cannot used to probe a host remotely; all Xthe tests and checks made require a shell that is on the site being tested. X X The programs are mostly written in Bourne shell (using awk, sed, grep, Xetc. as well) for (hopefully) maximum portability. A few are written Xin C for speed (most notably the Kuang expert system and for implementing Xfast user home directory searching), but the entire system should run on Xmost BSD and System V machines with a minimum of tweaking. X X2) What COPS is _not_ X---------------------- X X COPS merely provides a method of checking for common procedural errors. XIt is not meant to be used as a replacement for common sense or user/ Xoperator/administrative alertness! Think of it as an aid, a first line Xof defense -- not as an impenetrable shield against security woes. An Xexperienced wrong-doer could easily circumnavigate _any_ protection that XCOPS can give. However, COPS _can_ aid a system in protecting its users Xfrom (their own?) ignorance, carelessness, and the occasional malcontent Xuser. X X Once again, COPS does not correct any errors found. There are several Xreasons for this; first and foremost, computer security is a slippery Xbeast. What is a major breach in security at one site may be a standard Xpolicy of openness at another site. Additionally, in order to correct all Xproblems it finds, it would have to be run as a privileged user; and I'm Xnot going to go into the myriad problems of running SUID shell scripts X(See the bibliography at the end of the technical report "cops.report" Xfor pointer to a good paper on this subject by Matt Bishop.) X X At this time, COPS does not attempt to detect bugs or features (such Xas the infamous ftpd, fingerd, etc) that may cause security problems. Although Xthis may change in future versions, the current line of reasoning to avoid Xgeneral publication of programs such as these is that all the problems that XCOPS detects can be repaired on any system it runs on. However, many bugs Xcan be readily repaired only be having source code (and possibly a good Xvendor to repair it), and many sites would have serious troubles if they Xsuddenly discovered unrepairable problems that could compromise their Xlivelihood. It is possible that a more controlled release may come out Xin the future to address such problems (but don't mail to me about getting Xthem -- unless you want to help write them! :-)) X X3) How to Configure COPS X------------------------- X X System V users, other Non-BSD systems, or sites with commands in Xstrange places -- you may have to run a shell script called "reconfig" Xto change the pathnames of the executable programs called when using XCOPS. If your system does not use the paths listed in the shell Xscripts, try running "reconfig". This will reconfigure the pathnames Xused by COPS to your system; COPS should run fine then, if it Xcan find all of the commands (reconfig should tell you if it Xcannot.) If trouble persists, you will have to change the paths Xto your executable files (awk, sed, etc) by hand. A drag, I know. XThis all may change without notice, anyway :-) X X With all the varieties of unix, there are a few types that may need Xextra help to run the system. I've got README files for Apollo and Xenix Xin the distribution -- see the files "README.apollo", and "README.xenix", Xrespectively -- if you have any troubles, drop me a line, and I'll Xsee what I can do about working out a patch with you. Some problems Xmight arise with some SYSV machines (heck, to any machine :-)), due to Xweird files and names for stuff. What can I say? Portability is a Xproblem. You can comment out line 39 and 38 in "misc.chk", if you use X/etc/servers instead of /etc/inetd.conf. X X4) Running COPS for the 1st Time X--------------------------------- X X Since most of COPS was written and tested mostly on just a few machines X(at least compared to the total number out there!), you may have significant Xdifferences that were not anticipated -- unfortunately, or fortunately, XUNIX is not quite standardized yet. However, I haven't run into a UNIX Xyet that I haven't been able to get it running on, with just a small amount Xof change, so feel free to mail to me for help. X X COPS is run by simply typing "cops". "cops" is a Bourne shell script Xthat runs each of the programs, accumulates the output, and then either Xmails or stores any results in a file. "suid.chk" (and possibly "crc.chk") Xis the only package that is meant to be run separately, simply because it Xcan take a long time to run, and possibly because it needs a privileged Xaccount to run it; look at "suid.man" for more information. By all means, Xhowever, do not ignore the SUID checker! Run it at least once a week, if Xpossible, more (daily?); intruders into a system often leave SUID files Xto gain privileges later. "crc.chk" should also be run; it can either Xbe run as a standalone program (preferred), or as part of the COPS package; Xread the file "CRC.README", and the man page for more information. X X To run COPS for the first time, I suggest doing the following: X X -- Look at the disclaimer, file "disclaimer". Don't sue me. X Actually, this holds for all the times you use COPS (1/4 :-)) X X -- Type "make" and "make docs" to create the formatted manual pages, X to compile the C programs, and to make the shell programs executable. X A couple of potential (hopefully minor problems) might occur, probably X only for SysV based machines; one, if you don't have the "-ms" package X for nroff (i.e. you, get an error message after typing "make" about X it), just remove the "-ms" flag; e.g., change line 7 of the X "docs/makefile" file, from: X X ROFFLAGS = -ms X to X ROFFLAGS = X X The second potential problem might be with the password checking X program; if it fails to compile, try uncommenting out line 20 in X "makefile" -- e.g., enable the "BRAINDEADFLAGS = -lcrypt" flag. X If this doesn't work... well, you can either work it out, or e-mail me. X X -- Read the technical report to understand what COPS is doing and X what is going on -- "cops.report". This gives a look at the X philosophies, design notes, and finally a general outlay of the X COPS system and UNIX security. This can be forsaken, for those X who just want to get to the results/see some action (people like X me.) X X -- Next, change lines 51 and 52 in the "cops" shell file; this is X what they were: X X SECURE=/usr/foo/bar X SECURE_USERS="foo@bar.edu" X X SECURE should be the same directory as the directory that contains X the cops programs, and SECURE_USERS should be your own login id, or X to whomever you designate as the recipient of the output (your enemy?) X X -- Set "MMAIL=NO" in the "cops" shell file (line 24). This will prevent X a large mail file from choking the mailer. All of the output will be X put into a file called "year_month_day" (obviously, that's like: X "1991_Dec_31", not actually the words, "year_month_day" :-)), and X should be automatically placed by COPS in a directory that has the X same name as the host it was run on (e.g., your own hostname.) X X -- Look at the directory and file configuration file, "is_able.lst" X This contains critical files that COPS checks for group and world X writability and readability. Add or delete whatever files/directories X you wish; if a file doesn't exist, COPS will effectively ignore it. X (If you don't know or are uncertain what files/directories are X important, what is given there is a good set to start with on most X systems.) X X -- If you allow anonymous ftp access to your system, add a "-a" flag X to "ftp.chk" on line 104 of "cops". Right now, it is set up so X that key files and directories are expected to be owned by root; X however, it has provisions for two owners, $primary and $secondary -- X some may wish to change the second to "ftp", or some other user. X Read the man page for ftp.chk, or look at "ftp.chk" for further notes. X X -- You may wish to comment out the password checker (line 109 in the X "cops" shell file). Although this is not necessary, it will speed X up the package if you wish for immediate gratification. X If you are using yellow pages/NIS, read "README.yp" for tips on how X to check passwords there. X X -- Uncomment out the crc checker, "crc.chk" (line 123), if you desire to X run it as part of the normal COPS run. X X You should be ready to roll. COPS is run by simply typing "cops" (you Xmay wish to put in the background....) If you followed my advice and Xset "MAIL=NO" in the "cops" shell file, after COPS is finished, there Xwill be a report file created ("year_month_day") that lists the time and Xmachine it was created on. Otherwise, COPS mails the report to the user Xlisted on the line 'SECURE_USERS="foo@bar.edu"'. There is a file X"warnings", which contains most of the warning messages COPS uses, as well Xas a brief explanation of how the message might pertain to your system and Xfinally a suggestion as how to "fix" any problem. X X NOTE: Change the shell script "cops" to reflect who you want the output Xsent to and where the location of the program is BEFORE running the program. X X X5) Continued Use and Installing COPS X------------------------------------- X X Once you are satisfied that COPS indeed does something useful X(hopefully this will occur :-)), a good way to use it is to run it Xon at least a semi-regular basis. Even if it doesn't find any problems Ximmediately, the types of problems and holes it can detect are of the Xsort that can pop up at any given time. One way of running COPS Xmight be to run it as an "at" job or by cron. X X I highly advise that whatever directory COPS is placed in is to be Xreadable, writable, and executable only by the owner (typing X"chmod 700 /usr/foo/bar" or whatever the name is will do this) of the Xdirectory. This is to prevent prying eyes from seeing any security Xproblems your site may have. Even if you don't think of them as Ximportant, someone else might come around and change your mind. Since XCOPS is fairly configurable, an intruder could easily change the paths Xand files that COPS checks for, hence making it fairly worthless. Again, Xthis comes back to the point that COPS is only a tool -- don't put down Xyour defensive shields merely because COPS says "all clear". If this Xsounds paranoid, it is! Security people are traditionally paranoid, Xfor a reason.... In any case, it is probably not a good idea to advertise Xany (even) potential weaknesses. X X Typing "make install" will create (if necessary) a subdirectory with Xthe name you put in $INSTALL_DIR (found on line 7 of "makefile"); if you Xrun a network with multiple architectures, you can have several executable Xversions of COPS in the same NFS mounted directory structure. You can run XCOPS with "cops archtype", and it will cd into the archtype directory, use Xthe binaries in that directory (placed there by a "make install"), and put Xany results in a subdirectory of the archtype directory with the appropriate Xhost name. X X For example, assume you have the following setup: X Xmachine architecture hostname If run COPS with: X===================== ======== ================== Xcray ribcage cops Xvax bar cops vax Xvax foo cops vax Xsun earth cops sun Xsun mars cops sun Xsun venus cops sun Xmips hades cops X X If $SECURE (the secure directory variable in the "cops" shell script) was Xset to "/usr/secure", the resulting directory/reporting structure would be: X X/usr/secure/cops/ribcage X/usr/secure/cops/vax/bar X/usr/secure/cops/vax/foo X/usr/secure/cops/sun/earth X/usr/secure/cops/sun/mars X/usr/secure/cops/sun/venus X/usr/secure/cops/hades X X Sometimes you will get the same report over and over again, everytime you Xrun COPS; for instance, with Ultrix 3.x, /dev/kmem is world readable -- this Xis a security hole, but many utilities in Ultrix need this to function. If Xyou wish to only see reports that are _different_ than the old reports, you Xfirst need to have an older report saved in a file (in $SECURE/hostname, or Xwherever you usually save the reports); you can then set "MMAIL=YES" _and_ X"ONLY_DIFF=YES" (lines 25 & 30, respectively) in "cops"; everytime COPS is Xrun after that, it will compare the report it generated for the current Xcheck with the old report; if it detects any differences, it will mail you Xa report. If not, it simply discards it. This can be a real boon for a Xsite with a lot of machines running COPS every night... X X There are a couple of further options you may wish to explore. First Xof all, since so many breakins are because of poor passwords selection Xby users, it would be a wise idea to add options to your password checking Xprogram (line 109 in "cops"). You may wish to try some words from a Xdictionary; you may use either your system dictionary (usually found in X/usr/dict/words), or you may use the same dictionary that the internet Xworm found so lucrative when hitting all those thousands of hosts; that Xdictionary is in the file "pass.words" (example; the way to include the Xworm dictionary is: "pass.chk -w pass.words"). Also, try some of the options Xin the password program, such as "-b", "-g", "-s", and "-c", which add Xchecks for backward, gecos, single letter & number, and upper and lower Xcase guesses, respectively. Just as a note, each option will increase the Xtime needed to crack the passwords, of course; experiment! See what is Xreasonable for your hardware and resource capabilities. X X By using the "pass_diff.chk" program, you only check accounts that have X_changed_ their password since the last time you've checked -- this can Xsave enormous amounts of times with large systems; you can check your users Xthoroughly once, then only check them as they change their passwords again. XBe careful, though, if you use this, and then later expand your checks Xand/or your dictionary used to search for passwords, the earlier accounts Xthat were already checked with an inferior method will not be checked again Xuntil they change their password. See the file "passwords" in the X"extensions" directory for a replacement "passwd" program, that can disallow Xpoor passwords to begin with. X X The file "is_able.lst" contains a list of files that are to be checked Xfor world readability and/or writability; look at the file; add or delete Xany files you feel are important to your system. X X After running COPS, if any warnings are given that compromise any Xindividual users accounts (such as world writable .profiles, home Xdirectories, guessed passwords, etc.), and the warnings are not corrected Ximmediately (or you are not sure whether or not it is worth hassling Xthe user to change it), try this: X X Edit the file "init_kuang", and add the compromised user(s) uids and Xgroups in their respective target lines (below lines 20 and 27, Xrespectively), and run kuang again to see if the users can compromise Xthe entire system. You may change your mind about not thinking Xthey are a problem! In addition, kuang does not have to have "root" Xas a target (the last line). Try putting in system administrators or Xother powerful figures to see if they are in danger as well. If you Xhave "perl" installed on your system, try the perl version of kuang -- X"kuang.pl" (you'll have to unpack the shar file this is inside -- X"kuang.pl.shar", and you may have to edit the first line of the file X"kuang.pl", to reflect where the location that perl is on your system.) X X6) Disclaimer and End Notes X---------------------------- X X COPS is meant to be a tool to aid in the tightening of security, not Xas a weapon to be used by an enemy to find security flaws in a system. XIt may be argued that allowing anyone to have access to such a tool may Xbe dangerous. But hopefully the overall benefit for systems that use Xthis package will outweigh any negative impact. To me it is akin to a Xlaw enforcement problem -- that although telling the public how to break Xinto a house may foster a slight rise in break-in attempts, the overall Xrise in public awareness on how to defend themselves would actually result Xin a drop in break-ins. The crackers with black hats already know how Xto crush system defenses and have similar tools, I'm sure. It's time Xwe fought back. X X COPS is not the final answer to anyone's security woes. You can use Xthe system as long as you realize that COPS has no warranty, implied Xor otherwise, and that any problems that you may have with it are Xnot my or any of the other authors' fault. I will certainly attempt to Xhelp you solve them, if I am able. If you have ideas for additional Xprograms, or a better implementation of any of the programs here, I would Xbe very interested in seeing them. COPS was the work of a LOT of people, Xboth in writing code and in the testing phase (thanks beta testers!). For Xa complete list of contributors, look at the file "XTRA_CREDIT". X X So good luck, and I hope you find COPS useful as we plunge into UNIX Xof the 1990's. X X dan farmer X January 31, 1989 X (Now January 31, 1990) X X X# include "./disclaimer" X X Just for snix, here are some of the machine/OS's I know this sucker works Xon; far and away the most common problem was getting that stupid password Xcracking program to compile, followed by systems without the -ms package to Xnroff. Some minor problems with config files -- I *think* these are all Xok: X X XDECstation 2100, 3100, 5000, Ultrix 2.x, 3.x, 4.x X(It should, I'm sitting in front of one now. Ultrix is braindead) X XSun 3's, 4's (incl. Solbourne) -- 3.x, 4.x XGould 9080 Powernode, hacked up Gould OS (whatever it is) Xsequent S-87 symmetry, dynix V3.0.12 (both att & bsd universes; att required X "BRAINDEADFLAGS = -lcrypt" to be uncommented. Xeta-10P, Sys V R3 based XConvex boxes, all types, most OS's (up to 9.x, the most recent) XApollo dn3000 & dsp90, Domain SR 9.7 XVax 11/780, 4.3 BSD (Mt. Xinu, tahoe and stock) XVaxstation, MicroVax, Vax 6320 & 8800, Ultrix 2.0, 3.x XHP900/370, HP-UX 6.5 XCray 2 & Y-MP, UNICOS 5.0, 6.0 XAmdahl 5880, UTS 580-1.2.3 XSGI 2500's, IRIX GL 3.6 XSGI 4D's, IRIX System V Release 3.X X'286 & '386 Boxes, running Xenix (README.xenix) X XApple Mac IIci, running AUX 2.x. The "test -z" seemed broken on this, but I Xonly had a brief chance to test it out, but kuang didn't like it as a result. XI'll get a working version soon; everything seemed ok (change the /etc/servers Xline in "misc.chk".) X XNeXT, 1.x X(password stuff is different on this machine, tho; cracking is strange. Diffs?) X XMultimax 320, 12 Processors, 64Mb Memory, Encore Mach Version B1.0c (Beta) X(no crypt(3) on this machine. Sigh.) X XIBM rs6000, AIX 3.1 (BRAINDEAD -- boo. hiss.) XCOPS will *NOT* work well on this piece of trash -- the shell utilities are Xgarbage; however, you can still get *some* useful info. I'm not going to Xrewrite everything because big-blue won't write an awk that works: SHAR_EOF chmod 0600 cops/README || echo 'restore of cops/README failed' Wc_c="`wc -c < 'cops/README'`" test 22466 -eq "$Wc_c" || echo 'cops/README: original size 22466, current size' "$Wc_c" fi # ============= cops/README.apollo ============== if test -f 'cops/README.apollo' -a X"$1" != X"-c"; then echo 'x - skipping cops/README.apollo (File already exists)' else echo 'x - extracting cops/README.apollo (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/README.apollo' && X X Try setting the $OVER_8 variable (line 50) in "passwd.chk" to "YES", Xif you get warnings about having extra long uid's. X X X This little script can be used to generate a better password file for Xthe password cracker, if you use those funky more-than-one-field in field Xone of the password file; e.g., if you have something that looks like: X Xroot.foo.bar:xxxxxxxxxxxxx:0:0:Mr. Fu Bear:/:/bin/sh X X This will change it to: X Xroot:xxxxxxxxxxxxx:0:0:foo bar Mr. Fu Bear:/:/bin/sh X X So that you can use the extra fields as gcos information for password Xcracking. You can substitute the normal password cracking stuff in "cops" X("pass.chk") with something like (assuming you call this "apollo.sh"): X Xapollo.sh > ./apollo.pw.$$ Xpass.chk -P ./apollo.pw.$$ Xrm -f ./apollo.pw.$$ X X X In addition, you can add these 2 lines to the "passwd.chk" shell script X(right before the start of the awk on line 82 would be fine): X X$AWK -F: '{print $1}' $etc_passwd | $AWK -F. '{if (NF > 3) X printf("Warning! Password file, line %d, has %d sub-fields in the user field: \n\t%s\n", NR, NF, $0) }' X X And if you're running YP (is that possible, with all of that? :-) XYou can add these 2 lines before line 119: X X$AWK -F: '{print $1}' $yp_passwd | $AWK -F. '{if (NF > 3) X printf("Warning! YPassword file, line %d, has %d sub-fields in the user field: \n\t%s\n", NR, NF, $0) }' X X X: X# X# apollo.pw X# XAWK=/bin/awk X X# Quote from the man page (passwd): X# On DOMAIN systems, passwords are kept in the registry files (/registry/*). X# X# Important files: Xetc_passwd=/etc/passwd X X$AWK -F: '{split($1,temp,"."); \ X $1=temp[1]; \ X for (i in temp) { X if (i!=1) \ X $5 = $5" "temp[i]; \ X } \ X for (j=1;j<=NF;j++) X printf("%s:",$j); \ X printf("\n") \ X }' $etc_passwd X X# end SHAR_EOF chmod 0700 cops/README.apollo || echo 'restore of cops/README.apollo failed' Wc_c="`wc -c < 'cops/README.apollo'`" test 1752 -eq "$Wc_c" || echo 'cops/README.apollo: original size 1752, current size' "$Wc_c" fi # ============= cops/README.xenix ============== if test -f 'cops/README.xenix' -a X"$1" != X"-c"; then echo 'x - skipping cops/README.xenix (File already exists)' else echo 'x - extracting cops/README.xenix (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/README.xenix' && X X Uncomment the "BRAINDEADFLAGS=-lcrypt" in the makefile, and put the line: X Xextern char *crypt(); X X Right after the #include lines in "pass.c". This apparently came from Xthe makers of Xenix, about the availability of crypt(3): X X======================== XSubject: crypt in Xenix X XDue to the export restrictions on CRYPT, we do not ship it with the Xstandard product. We do ship it as an SLS: the relevant numbers are Xlng190 (for shipment inside the U.S. only) and lng225, which can be Xshipped outside the U.S.. X======================== X X Make the following change in dev.chk: X Xline 39: X> mtab=/etc/fstab X XTo: X< mtab=/etc/checklist X SHAR_EOF chmod 0600 cops/README.xenix || echo 'restore of cops/README.xenix failed' Wc_c="`wc -c < 'cops/README.xenix'`" test 636 -eq "$Wc_c" || echo 'cops/README.xenix: original size 636, current size' "$Wc_c" fi # ============= cops/XTRA_CREDIT ============== if test -f 'cops/XTRA_CREDIT' -a X"$1" != X"-c"; then echo 'x - skipping cops/XTRA_CREDIT (File already exists)' else echo 'x - extracting cops/XTRA_CREDIT (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/XTRA_CREDIT' && X X Code credits are where code credits are due. If I miss anyone, please Xforgive (and notify) me! X XGene Spafford -- overall design help. X XRobert Baldwin and Steve Romig -- the original kuang package/design, and Xthe perl rewrite, respectively. X XCraig Leres, Jef Poskanzer, Seth Alford, Roger Southwick, Steve Dum, Xand Rick Lindsley all get credit for the password guessing program. X XPrentiss Riddle -- the suid checker. X XMark Mendel and Jon Zeef -- the crc generator. X X In round III (this patch), Muffy Barkocy and Michelle Crabb both gave me Xgood ideas to use. Pete Shipley fixed up some code (is_able) and generally Xhelped my motivation to get things out the door. Gandalph suggested ftp.chk, XJay Batson made me fix root.chk, Shelley Shostak fixed and added features Xto pass.chk, and Brian Moore gave me the shell script checking --> SUID Xconcept. Jim W Lai pointed out some other pass.chk things (what a buggy Xprogram :-)). Rob Kolstad told me about some bugs in the ftp checker, and Xgently pointed out that some stuff wasn't using the YP passwd files when Xthey should be, and Jim Ellis helped get this to work on a Cray. There Xare probably more that I've forgotten (sorry, if so!) Thanks, people... X X In round II (the first patch), Mark Plumbly fixed rc.chk so it would Xwork like I said it would, as well as pointing out a few problems with Xthe password guesser. X X And of course lots of credit goes to my great Beta-release sweatshop team; Xespecially Adri Verhoef for tightening up lots of my crummy code (cops, Xgroup.chk, root.chk, is_writable, dev.chk, dir.chk & file.chk among others), XSteve Romig for good ideas _and_ letting me use a system V machine to test Xon (how many people do you know that would let you test a security Xsystem on their system with no strings attached!) Jason Levitt, Jim XKimble, Jim Rowan, Stefan Vorkoetter, Judy Scheltema, Pete Troxell (all Xthe Sun C2 stuff....), Dennis Conley, and of course John Sechrest. XTony Petrost pointed out some of my incorrect assumptions and helped Xfix cron.chk. Kudos also to Bruce Spence for giving me some good Ximplementation ideas at LISA III. X X If strings is not available to you, a version is available on uunet; Xalso a nifty install program written by Kevin Braunsdorf that can be used Xas a super directory/file mode checker/security device might be available Xsoon in comp.sources.unix (these programs large sizes preculudes their Xinclusion in COPS, but I recommend looking into them.) Both can be gotten Xvia anonymous ftp. Strings is in comp.unix.sources directory, install, Xshould be in j.cc.purdue.edu, methinks. X Everything else not explicitely mentioned in the COPS.report.ms paper Xor here was written by me. Not mentioned execpt in the source code are Xsome small changes made by myself to make everything fit in as a cohesive Xwhole; I tried to make comments in the source code if I changed it (never Xto drastic in any case.) X X For a good story on the subject, you might want to read _The Cuckoo's XEgg_, by Clifford Stoll. This is a true tale of a sysadmin's fight Xagainst beaurocracy and a system cracker. Good stuff. X X For a a good read on Unix security in general, look at Dave Curry's now Xinfamous "white paper", via anon-ftp, SPAM.ITSTD.SRI.COM (128.18.4.3) as Xthe file "pub/security-doc.tar.Z. But don't believe him when he says Yellow XPages is secure. It's not. Not much is, these days... good luck, tho! X X -- dan SHAR_EOF chmod 0600 cops/XTRA_CREDIT || echo 'restore of cops/XTRA_CREDIT failed' Wc_c="`wc -c < 'cops/XTRA_CREDIT'`" test 3417 -eq "$Wc_c" || echo 'cops/XTRA_CREDIT: original size 3417, current size' "$Wc_c" fi # ============= cops/src/addto.c ============== if test ! -d 'cops/src'; then echo 'x - creating directory cops/src' mkdir 'cops/src' fi if test -f 'cops/src/addto.c' -a X"$1" != X"-c"; then echo 'x - skipping cops/src/addto.c (File already exists)' else echo 'x - extracting cops/src/addto.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/src/addto.c' && X/* Copyright 1985 Robert W. Baldwin */ X/* Copyright 1986 Robert W. Baldwin */ Xstatic char *notice85 = "Copyright 1985 Robert W. Baldwin"; Xstatic char *notice86 = "Copyright 1986 Robert W. Baldwin"; X X/* X August 15, added "Warning!" To prepend warning messages. X -- dan farmer X*/ X X X/* X * Add a goal, check for duplicates and completions. X * Trace messages written to stdout, success messages written to stderr. X * Usage: addto fileroot key comments X * Files are arranged in families based on a root name; for example, X * uids.k -- uids we Know how to access X * uids.n -- uids to process Next X * uids.p -- uids Pending results (for duplicate detection) X * uids.x -- uids being eXamined currently X */ X X X#include <stdio.h> X X#define LINELEN 600 /* Max chars in a line. */ X#define SUCCESS "Success" /* Filename to put success messages. */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char *type = argv[1]; X char *key = argv[2]; X int i; X char linebuf[LINELEN]; X char keypending[150]; X char filename[150]; X FILE *tmpfile; X X if (argc < 3) { X fprintf(stderr, "addto: missing arguments\n"); X exit(1); X } X X tmpfile = NULL; X X keypending[0] = NULL; X strcat(keypending, key); X strcat(keypending, " "); X/* X * If the uid is known, print out the comments and exit. X */ X filename[0] = NULL; X strcat(filename, type); X strcat(filename, ".k"); X if ((tmpfile = fopen(filename, "r")) == NULL) { X fprintf(stderr, "addto: can't open %s.\n", filename); X exit(1); X } X while (fgets(linebuf, LINELEN, tmpfile) != NULL) { X if (strncmp(linebuf, key, strlen(key)) == 0) { X if ((tmpfile = freopen(SUCCESS,"a",tmpfile)) == NULL) { X fprintf(stderr, "addto: can't open %s.\n", X SUCCESS); X exit(1); X } X fprintf(stderr, "Success^G^G\t"); X fprintf(tmpfile, "Warning! "); X for (i = 1 ; i < argc ; i++) { X fprintf(tmpfile, argv[i]); X fprintf(tmpfile, " "); X fprintf(stderr, argv[i]); X fprintf(stderr, " "); X } X fprintf(tmpfile, "\n"); X fprintf(stderr, "\n"); X X exit(0); X } X } X/* X * If a duplicate, don't add it. X */ X filename[0] = NULL; X strcat(filename, type); X strcat(filename, ".p"); X if (freopen(filename, "r", tmpfile) == NULL) { X fprintf(stderr, "addto: can't open %s.\n", filename); X exit(1); X } X while (fgets(linebuf, LINELEN, tmpfile) != NULL) { X if (strncmp(linebuf, keypending, strlen(keypending)) == 0) { X exit(0); /* Its a duplicate. */ X } X } X/* X * Add the goal to the pending file. X */ X filename[0] = NULL; X strcat(filename, type); X strcat(filename, ".p"); X if (freopen(filename, "a", tmpfile) == NULL) { X fprintf(stderr,"addto: can't open %s for append.\n", filename); X exit(1); X } X fprintf(tmpfile, keypending); X fprintf(tmpfile, "\n"); X/* X * Add the goal to the next goal (type) file. X */ X filename[0] = NULL; X strcat(filename, type); X strcat(filename, ".n"); X if (freopen(filename, "a", tmpfile) == NULL) { X fprintf(stderr,"addto: can't open %s for append.\n", filename); X exit(1); X } X fprintf(stdout, " "); X fprintf(stdout, "%s %s ", argv[0], argv[1]); X for (i = 2 ; i < argc ; i++) { X fprintf(tmpfile, argv[i]); X fprintf(tmpfile, " "); X fprintf(stdout, argv[i]); X fprintf(stdout, " "); X } X fprintf(tmpfile, "\n"); X fprintf(stdout, "\n"); X exit(0); X} X X X SHAR_EOF chmod 0600 cops/src/addto.c || echo 'restore of cops/src/addto.c failed' Wc_c="`wc -c < 'cops/src/addto.c'`" test 3254 -eq "$Wc_c" || echo 'cops/src/addto.c: original size 3254, current size' "$Wc_c" fi # ============= cops/src/clearfiles.c ============== if test -f 'cops/src/clearfiles.c' -a X"$1" != X"-c"; then echo 'x - skipping cops/src/clearfiles.c (File already exists)' else echo 'x - extracting cops/src/clearfiles.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/src/clearfiles.c' && X/* Copyright 1985 Robert W. Baldwin */ X/* Copyright 1986 Robert W. Baldwin */ Xstatic char *notice85 = "Copyright 1985 Robert W. Baldwin"; Xstatic char *notice86 = "Copyright 1986 Robert W. Baldwin"; X X/* X * Reset the info files used by Kuang. X */ X X X#include <stdio.h> X Xchar *filelist[] = { X "uids.k", X "Success", X "uids.k", X "uids.p", X "uids.n", X "uids.x", X "gids.k", X "gids.p", X "gids.n", X "gids.x", X "files.k", X "files.p", X "files.n", X "files.x", X "", X }; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int i; X X for (i = 0 ; filelist[i][0] != NULL ; i++) { X if (freopen(filelist[i], "w", stdout) == NULL) { X fprintf(stderr, "%s: can't open %s.\n", X argv[0], filelist[i]); X exit(1); X } X } X} X SHAR_EOF chmod 0600 cops/src/clearfiles.c || echo 'restore of cops/src/clearfiles.c failed' Wc_c="`wc -c < 'cops/src/clearfiles.c'`" test 702 -eq "$Wc_c" || echo 'cops/src/clearfiles.c: original size 702, current size' "$Wc_c" fi # ============= cops/src/crc.c ============== if test -f 'cops/src/crc.c' -a X"$1" != X"-c"; then echo 'x - skipping cops/src/crc.c (File already exists)' else echo 'x - extracting cops/src/crc.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cops/src/crc.c' && X X/* updcrc(3), crc(1) - calculate crc polynomials X * X * Calculate, intelligently, the CRC of a dataset incrementally given a X * buffer full at a time. X * X * Usage: X * newcrc = updcrc( oldcrc, bufadr, buflen ) X * unsigned int oldcrc, buflen; X * char *bufadr; X * X * Compiling with -DTEST creates a program to print the CRC of stdin to stdout. X * Compile with -DMAKETAB to print values for crctab to stdout. If you change X * the CRC polynomial parameters, be sure to do this and change X * crctab's initial value. X * X * Notes: X * Regards the data stream as an integer whose MSB is the MSB of the first X * byte recieved. This number is 'divided' (using xor instead of subtraction) X * by the crc-polynomial P. X * XMODEM does things a little differently, essentially treating the LSB of X * the first data byte as the MSB of the integer. Define SWAPPED to make X * things behave in this manner. X * X * Author: Mark G. Mendel, 7/86 X * UUCP: ihnp4!umn-cs!hyper!mark, GEnie: mgm X */ X X#define TEST X X/* The CRC polynomial. X * These 4 values define the crc-polynomial. X * If you change them, you must change crctab[]'s initial value to what is X * printed by initcrctab() [see 'compile with -DMAKETAB' above]. X */ X X/* Value used by: CITT XMODEM ARC */ X#define P 0xA001 /* the poly: 0x1021 0x1021 A001 */ X#define INIT_CRC 0L /* init value: -1 0 0 */ X#define SWAPPED /* bit order: undef defined defined */ X#define W 16 /* bits in CRC:16 16 16 */ X X/* data type that holds a W-bit unsigned integer */ X#if W <= 16 X# define WTYPE unsigned short X#else X# define WTYPE unsigned long X#endif X X/* the number of bits per char: don't change it. */ X#define B 8 X Xstatic WTYPE crctab[1<<B] = /* as calculated by initcrctab() */ { X 0x0, 0xc0c1, 0xc181, 0x140, 0xc301, 0x3c0, 0x280, 0xc241, X 0xc601, 0x6c0, 0x780, 0xc741, 0x500, 0xc5c1, 0xc481, 0x440, X 0xcc01, 0xcc0, 0xd80, 0xcd41, 0xf00, 0xcfc1, 0xce81, 0xe40, X 0xa00, 0xcac1, 0xcb81, 0xb40, 0xc901, 0x9c0, 0x880, 0xc841, X 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, X 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, X 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, X 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, X 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, X 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, X 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, X 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, X 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, X 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, X 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, X 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, X 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, X 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, X 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, X 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, X 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, X 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, X 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, X 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, X 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, X 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, X 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, X 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, X 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, X 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, X 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, X 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, X}; X X Xvoid perror(); Xchar *strcpy(); Xvoid exit(); X XWTYPE Xupdcrc( icrc, icp, icnt ) XWTYPE icrc; Xunsigned char *icp; Xint icnt; X{ X register WTYPE crc = icrc; X register unsigned char *cp = icp; X register int cnt = icnt; X X while ( cnt--) { X#ifndef SWAPPED X crc = (crc << B) ^ crctab[(crc>>(W-B)) ^ *cp++]; X#else X crc = (crc >> B) ^ crctab[(crc & ((1<<B)-1)) ^ *cp++]; X#endif X } X X return( crc ); X} X X X#ifdef MAKETAB X X#include <stdio.h> Xmain() X{ X initcrctab(); X} X X Xinitcrctab() X{ X register int b, i; X WTYPE v; X X X for ( b = 0; b <= (1 << B) - 1; ++b ) { X#ifndef SWAPPED X for ( v = b << (W - B), i = B; --i >= 0; ) X v = v & ((WTYPE)1 << (W - 1)) ? (v << 1) ^ P : v << 1; X#else X for ( v = b, i = B; --i >= 0; ) X v = v & 1 ? (v >> 1) ^ P : v >> 1; X#endif X crctab[b] = v; X X (void) printf( "0x%lx,", v & ((1L << W) - 1L)); X if ( (b & 7) == 7 ) X (void) printf("\n" ); X else X (void) printf(" "); X } X} X X X#endif X X#ifdef TEST X X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <pwd.h> X#include <grp.h> X#define MAXBUF 4096 X X#ifndef S_IRGRP X#define S_IRGRP (S_IREAD >> 3) X#define S_IWGRP (S_IWRITE >> 3) X#define S_IXGRP (S_IEXEC >> 3) X#define S_IROTH (S_IREAD >> 6) X#define S_IWOTH (S_IWRITE >> 6) X#define S_IXOTH (S_IEXEC >> 6) X#endif X Xstruct stat stat_buf; Xint initial_crc = INIT_CRC; X Xextern char *optarg; Xextern int optind; Xextern int opterr; X Xmain( argc, argv ) Xint argc; Xchar **argv; X{ X int stats_flag = 0; X X int c; X X if (argc == 1) { X print_crc((char *)0, 0); X return 0; X } X X /* process all arguments */ X X while ((c = getopt(argc, argv, "VvI:i:")) != EOF) { X X switch (c) { X X case 'V': X case 'v': X stats_flag = 1; X break; X X case 'I': X case 'i': X initial_crc = atoi(optarg); X break; X X default: X (void) fprintf(stderr, "crc: -v (verbose listing)\n"); X (void) fprintf(stderr, " -i value (initial crc value)\n"); X exit(1); X } X } X X for (; optind < argc ; optind++) X print_crc(argv[optind], stats_flag); X X return 0; X} X X Xprint_crc(name, stat_flag) Xchar *name; Xint stat_flag; X{ X int fd; X int nr; X unsigned char buf[MAXBUF]; X WTYPE crc; X#ifdef MAGICCHECK X WTYPE crc2; X#endif X X fd = 0; X X /* quietly ignore files we can't stat */ X X if (name != NULL && stat(name, &stat_buf) != 0) X return; X X /* don't do a crc on strange files */ X X crc = nr = 0; X X if (name == NULL || (stat_buf.st_mode & S_IFMT) == S_IFREG) { X X /* open the file and do a crc on it */ X X if (name != NULL && (fd = open( name, O_RDONLY )) < 0 ) { X perror( name ); X exit( -1 ); X } X#ifdef MAGICCHECK X crc2 = X#endif X crc = initial_crc; X X while ( (nr = read( fd, (char *)buf, MAXBUF )) > 0 ) { X crc = updcrc(crc, buf, nr ); X } X (void) close(fd); X X } X if ( nr != 0 ) { X perror( "read error" ); X } else { X (void) printf("%4.4x", (unsigned) crc ); X if (stat_flag) X stats(name); X else X (void) printf("\n"); X X } X X#ifdef MAGICCHECK X /* tack one's complement of crc onto data stream, and X continue crc calculation. Should get a constant (magic number) X dependent only on P, not the data. X */ X crc2 = crc ^ -1L; X for ( nr = W - B; nr >= 0; nr -= B ) { X buf[0] = (crc2 >> nr); X crc = updcrc(crc, buf, 1); X } X X /* crc should now equal magic */ X buf[0] = buf[1] = buf[2] = buf[3] = 0; X (void) printf( "magic test: %lx =?= %lx\n", crc, updcrc((WTYPE) - 1, buf, W / B)); X#endif X X X} X X Xstats(name) Xchar *name; X{ X X struct passwd *entry; X struct group *group_entry; X static char owner[20]; X static char group[20]; X char a_time[50]; X X struct passwd *getpwuid(); X struct group *getgrgid(); X char *ctime(); X X static int prev_uid = -9999; X static int prev_gid = -9999; X X if (stat_buf.st_uid != prev_uid) { X entry = getpwuid((int)stat_buf.st_uid); X if (entry) X (void) strcpy(owner, entry->pw_name); X else X (void) sprintf(owner, "%d", stat_buf.st_uid); X prev_uid = stat_buf.st_uid; X } X if (stat_buf.st_gid != prev_gid) { X group_entry = getgrgid((int)stat_buf.st_gid); X if (group_entry) X (void) strcpy(group, group_entry->gr_name); X else X (void) sprintf(group, "%d", stat_buf.st_gid); X prev_gid = stat_buf.st_gid; X } X X (void) strcpy(a_time, ctime(&stat_buf.st_mtime)); X a_time[24] = '\0'; X X print_perm(stat_buf.st_mode); X X (void) printf(" %s\t%s\t%s %s\n", owner, group, a_time + 4, name); X X} X X Xprint_perm(perm) Xunsigned int perm; X{ X X char string[20]; X (void) strcpy(string, "----------"); X X switch (perm & S_IFMT) { X X case S_IFDIR: X string[0] = 'd'; X break; X X case S_IFBLK: X string[0] = 'b'; X break; X X case S_IFCHR: X string[0] = 'c'; X break; X X case S_IFIFO: X string[0] = 'p'; X break; X } X if (perm & S_IREAD) X string[1] = 'r'; X if (perm & S_IWRITE) X string[2] = 'w'; X if (perm & S_ISUID && perm & S_IEXEC) X string[3] = 's'; X else if (perm & S_IEXEC) X string[3] = 'x'; X else if (perm & S_ISUID) X string[3] = 'S'; X X if (perm & S_IRGRP) X string[4] = 'r'; X if (perm & S_IWGRP) X string[5] = 'w'; X if (perm & S_ISUID && perm & S_IXGRP) X string[6] = 's'; X else if (perm & S_IXGRP) X string[6] = 'x'; X else if (perm & S_ISUID) X string[6] = 'l'; X X if (perm & S_IROTH) X string[7] = 'r'; X if (perm & S_IWOTH) X string[8] = 'w'; X if (perm & S_ISVTX && perm & S_IXOTH) X string[9] = 't'; X else if (perm & S_IXOTH) X string[9] = 'x'; X else if (perm & S_ISVTX) X string[9] = 'T'; X X (void) printf(" %s", string); X} X X#endif X X SHAR_EOF chmod 0600 cops/src/crc.c || echo 'restore of cops/src/crc.c failed' Wc_c="`wc -c < 'cops/src/crc.c'`" test 9920 -eq "$Wc_c" || echo 'cops/src/crc.c: original size 9920, current size' "$Wc_c" fi true || echo 'restore of cops/src/crc_check.c failed' echo End of part 1, continue with part 2 exit 0