cfingerd-1.4.3/0040755000076500001440000000000006774336501012211 5ustar joeyuserscfingerd-1.4.3/docs/0040755000076500001440000000000006774336471013147 5ustar joeyuserscfingerd-1.4.3/docs/Makefile0100644000076500001440000000052106762270714014574 0ustar joeyusers# CFINGERD Documentation Installation # by Ken Hollis, Martin Schulze include ../Makefile.cfg install: install -m 644 -o $(MAN_OWNER) -g $(MAN_GROUP) cfingerd.8 $(MANDIR)/man8 install -m 644 -o $(MAN_OWNER) -g $(MAN_GROUP) cfingerd.conf.5 $(MANDIR)/man5 install -m 644 -o $(MAN_OWNER) -g $(MAN_GROUP) cfingerd.text.5 $(MANDIR)/man5 cfingerd-1.4.3/docs/cfingerd.80100644000076500001440000002666006764317640015024 0ustar joeyusers.TH CFINGERD 8 "18 Dec 1998" "cfingerd 1.4.2" "Configurable Finger Daemon" .SH NAME cfingerd \- Configurable finger daemon. .br .SH SYNOPSIS .B cfingerd .RB [\ \-c\ |\ \-e\ |\ \-o\ |\ \-v\ ] \-c : Check configuration \-e : Emulate local finger w/o inetd \-o : Turn off all finger queries \-v : Request version information .br .sp \-c checks your installed configuration. This makes sure there are no existing errors in the current .I cfingerd.conf file. .PP \-e allows you to emulate a local finger on a user that exists on your system. This lets you test cfingerd on your system before installing it. Using the "\-e" directive is the same as installing the software, typing "finger username@" and getting the output. Using "\-e username" does the same. .PP \-o turns off all finger queries. This makes it so that no one can finger your system \- no matter what they try to do. Unlike the other options, this option is used in inetd.conf, not on the command line. .PP \-v requests cfingerd version information. .br .SH DESCRIPTION .B CFINGERD is a totally new, and totally configurable finger daemon \- one of the first. It listenes on the finger port (port 79) to provide useful information about each user that is on your system according to the finger protocol as described in RFC 1228. Only thing is, cfingerd provides a unique twist. .PP .B CFINGERD was designed for the sole purpose of making output on finger queries configurable. If you want to change any text that is displayed during finger queries, you can configure the finger daemon to display just about anything you want. .PP .B CFINGERD also takes into account any security breaches, and attempts to close them. With the added bonus of creating ".nofinger" files, this is displayed instead of finger information, making it possible for users to keep themselves relatively anonymous from outside users. For a maximum of users privacy you should place an exact copy of .I /etc/cfingerd/nouser_banner.txt in your .I .nofinger file. .br .SH "WHY WAS IT DONE?" The answer is simple. Security. Many sites turn off finger for the reason that they don't want outside users to see who's on their system, or get information about a specific user on their system. This seemed unfair to the rest of the users out there, so this program was created. Besides, those sites were waiting for this type of program. Many sites that originally had their finger turned off turned them back on because of cfingerd. .PP Many sites have complained that they wanted the ability to create a "fake\-user", or a user that doesn't exist but calls a pre\-written shell script. .B CFINGERD has taken this into account, and provides the best method possible for creating such scripts. (See cfingerd.conf(5) for more information on the configuration file.) .br .SH "FEATURES CFINGERD PROVIDES, AND DESCRIPTIONS OF EACH" .B CFINGERD was totally rewritten. Why is this? Well, the older version of cfingerd had quite a few bugs, and it didn't quite do all of the things that cfingerd now does. This new version was totally revamped, and most of the bugs that were in the older version of cfingerd were removed in this one. Besides, the code in here was more compact. .PP .B Header and footer displays were a very big part of the original release of cfingerd, and shall continue to remain in all versions. Headers and footers are only displays at the beginning and ending of all finger displays, and are used as unique little "advertisements" or such. .PP .B Last time displayed is always a critical issue. It's covered in cfingerd. Cfingerd simply shows how many times this user is connected, what their idle time is on each TTY they're connected to, and whether or not they are accepting messages. If they're not accepting messages, a "[MESG-N]" display will be shown if this is the case. This display also shows the last time mail was read, and whether or not this user has mail. If this is still too much for your taste, each of these items can be disabled system wide. .PP .B Stand-alone and INETD support is compiled into the program, but only INETD support is given for the time being. The reason being is that I have not yet added the code for stand-alone daemon mode. .PP .B .nofinger files are used when a user wishes to remain anonymous. These files should be placed in their home directories, and can display anything they want. There's just a few restrictions. These .IR .nofinger display files cannot be character devices, directories, fifos, soft or hard links, or anything else of that caliber. They must only be normal files. .PP .B Fakeusers were supported for the simple fact that many sites want to create users that don't exist, and make them execute a shell. If you want this done, then install a fake user. Read up in .BR cfingerd.conf (5) for more information on these useful options. .PP .B Service listings were used to show what fakeusers you have installed on your system. These can be formatted however you wish, and are explained (once again) in .BR cfingerd.conf (5). .PP .B Searching for usernames is a very powerful feature that .B cfingerd takes full advantage of. If you are looking for a specific username on the system, or don't know what their name is, simply use the .RB " search.pattern " directive with .B cfingerd will search for all users containing pattern in their real name or username on that system. .PP Searching for usernames is NOT case sensitive. You may search for a specific username or real name, for part of the username or real ame, or for a pattern matching the entire username or the entire real ame. If you search for part of a user's name, chances are, it'll be displayed. .PP .B Warning searching will currently return the names of daemon users and users and you will be able to search for a user on your system. .PP .B Security is a given. If you don't want to show someone something, then it won't display what you don't want. Simply edit the cfingerd.conf file and make changes. It's that simple. .PP Searching for usernames is NOT case sensitive. If you are searching for a specific username, or part of the user's name. If you search for part of a user's name or username, chances are, it'll be displayed. .PP .B Not just PLAN, or PROJECT but there's also an option to display your public PGP key, if you have one. This is very useful if you want to keep your mail or other information secret to yourself, and don't want "big brother" watching over your shoulder as you talk amongst yourselves. (Thanks to Andy Smith for this patch). (For your info, the standard plan file is .IR .plan , project is .IR .project , PGP info is .IR .pgpkey , and XFace icon information is .IR .xface ) .PP Remember, any or all of these options stated above, can be turned on or off at will. If you want a specific option turned off, turn it off. :) .br .SH "FULL LIST OF BUILTIN USER NAMES" .B cfingerd provides a set of builtin fake users. Two of them are also used internally by .BR cfingerd . .PP .TP .B @ List logged on users without .I .nofinger file. If the .B system_list_sites option is used in the main configuration file .B cfingerd will try to gather information from all listed hosts. .TP .B userlist@ Same as .BR @ , except that it only lists people who are idle no longer than one day. This is intended to give a better overview of who's really online at the moment of fingering. .TP .B userlist-only@ List logged on users without .I .nofinger file - without headers and footers. This fake user is used internally to gather system information from remote hosts for .BR @ . .TP .B userlist-online@ List logged on users without .I .nofinger file - without headers and footers. Only users will be listed who are idle no longer than a day. This fake user is used internally to gather system information from remote hosts for .BR userlist@ . .TP .B version@ Display version information for .BR cfingerd . .TP .B services@ List all fake users. .TP .B search.pattern@ Search for users using the GCOS field in .IR /etc/passwd . Only users will be displayed who don't have a .IR .nofinger -file. .TP .B help@ Help text listing all of these. .PP These can be disabled in cfingerd.conf(5) as follows .TP .BR @ " and " userlist@ Set SYSTEM_LIST to FALSE. .TP .BR userlist-only@ " and " userlist-online@ Disable ALLOW_USERLIST_ONLY (i.e. prefix it with a minus sign) or disable SYSTEM_LIST. .TP .B version@ Disable ALLOW_CONFESSION (i.e. prefix it with a minus sign). .TP .B services@ Disable ALLOW_FAKEUSER_FINGER (i.e. prefix it with a minus sign). .TP .B search.pattern@ Disable ALLOW_SEARCHABLE_FINGER (i.e. prefix it with a minus sign). .TP .B help@ Disable ALLOW_CONFESSION (i.e. prefix it with a minus sign). .SH "ERROR MESSAGES" Any error messages that result are fairly easy to debug if you know what to look for. .PP .B Segmentation Violations don't always occur, but if they ever do, you can pretty easily figure out what's going on. Unfortunately, .B cfingerd doesn't have any compatibility with older .I cfingerd.conf files, so if you get a Segmentation Violation, this (usually) means that your .I cfingerd.conf file needs to be replaced. .PP .B Timeouts usually mean that a script has timed out, or a connection to another site timed out. .br .SH "SYSLOGGING MESSAGES" Well, there's no real way to describe SYSLOG messages since they can be changed as the system administrator chooses. Although, examples can be given based on the standard configuration that was distributed. .PP If any IP addresses cannot be matched to a name it will display a "IP: Hostname not matched". .PP If the renice fails (to make the program run at the highest priority) then it will display "Fatal - Nice died: (reason)". .PP If there is no buffer information waiting in the STDIN buffer, it will display "STDIN contains no data". .PP If a trusted host fingers your site, a "<- Trusted" will appear. .PP If a rejected host fingers your site, a "<- Rejected" will appear. .PP If root is fingered on your site, it will display "Root". .PP If a service listing was fingered on your site, it will display "Service listing". .PP If a user listing was requested, it will display "User listing". .PP If a fake user was requested, it will display "Fake user". .PP If "whois" data was requested, it will display "Whois request". (Note, whois was not implemented in this release, since it wasn't 'RFC' compliant.) .PP Any extra information pertaining to the incoming finger is displayed in the syslogging area. (It's also recommended that you reconfigure .BR syslog.conf (5) to display to an unused VT. :) .br .\" .SH BUGS .\" On ELF-specific systems, services usually lists a bit of garbage at .\" the beginning of the finger display. This doesn't appear to be a problem .\" on a.out systems, so if you have ELF, you may want to compile cfingerd as .\" a.out if this becomes a problem. .\" .br .SH PLANS Any other options or improvements will probably come from user suggestions. :) .PP Later plans will make it so that you can define your own display formats for the finger display. This means that you can re\-define how you want your finger display to look. .br .SH CONTACTING If you like the software, and you want to learn more about the software, or want to see a feature added to it that isn't already here, then please write to cfingerd@infodrom.north.de. The project's webpage is at http://www.infodrom.north.de/cfingerd/ . .PP .SH "SEE ALSO" .BR cfingerd.conf (5), .BR cfingerd.text (5), .BR finger (1), .BR userlist (1), .BR syslog.conf (5). cfingerd-1.4.3/docs/cfingerd.conf.50100644000076500001440000006047006764317640015742 0ustar joeyusers.TH CFINGERD.CONF 5 "19 Dec 1998" "1.4.2" "Configurable Finger Daemon" .SH NAME cfingerd.conf \- configurable finger daemon configuration file. .br .SH SYNOPSIS .B /etc/cfingerd.conf .br .SH DESCRIPTION .I cfingerd.conf is the configuration file for cfingerd. +.I cfingerd +has been totally rewritten to support a more readable configuration file. This version of the new configuration file is .B NOT compatible with the older versions from 1.0.3 or below. .PP The configuration file is split into sections of three general types: .B FILES, CONFIG, and .B HOSTS. .PP Each one of those sections is split into subsections, which will be explained next. .PP Subtext of each option is either boolean options, string options, or switchable options, all changable by the system administrator. .PP Each section is split into a series of sections that resembles C type definition; not exact, but close enough to be familiar with it. :) There's only one exception - these are not case sensitive. Any casing will do, as long as the option is legal. .PP Thus, each section is formatted like this: .sp OPTION section_name = { (tab/space) string_option = "string_format", (tab/space) +/\-boolean_pair_option = [BOOL, BOOL], (tab/space) +/\-internal_config_option (tab/space) host.name.here } .\" FIXME .\" Tabs/spaces optional .PP This illustrates that string options are strings put into "quotes", boolean options are given as TRUE and FALSE, switchable options are given with the + or \- directive, and hostnames are used as substrings, so that wildcards are not necessary. .PP A few sections simply contain a block of text to be used as the value of a single option, which one is indicated by the section name itself. .PP You may add comments using the hash mark ``#'' at the beginning of the line. Please note that no comments are allowed inside of a section. .br .SH "DISPLAY FILES SECTION (FILES display_files)" Each option here is a string option. The first 6 options are relative to the home directory of whatever user was fingered, the remaining are absolute and should start with a "/". .PP .B PLAN is the optional plan file which contains the text displayed as the users plan. The default is .IR ".plan" . .PP .B PROJECT is the optional project file that is used when displaying a project description. The standard here is .IR ".project" . .PP .B PGP_KEY is the optional "Pretty\-Good\-Privacy" file that is shown when displaying a public or private key. The standard here is .IR ".pgpkey" . .PP .B XFACE is the optional file that shows the user's face. (This is commonly used in E-Mail messages.) The standard here is .IR ".xface" . .PP .B NO_FINGER is the optional file that is shown when a user wishes to remain anonymous. This is usually the case with root users (which should be standard, anyway). In order to hide the user this file should be an exact copy of the nouser_banner.txt file. The standard here is .IR ".nofinger" . This file can only be a standard displayable file. This option will also hide the user from a "search.pattern" query. If any user can read this file it will also be honored by a userlist (@host) query. This is done by a non-priviliged program so the uid can't be changed. .PP .B USERLOG is the optional file in which all attempts to finger a user are logged for the users own reference. If ALLOW_USERLOG is not enabled this file is completely ignored. If ONLY_CREATE_FINGERLOG_IF_FILE_EXISTS is enabled .B cfingerd will only document finger requests if this file already exists in the users home directory. The default name is .IR ".fingerlog" . .PP .B MAILBOX is the file that is checked to see where the user's mailbox is. If you are using a regular Unix mail transport agent (such as .BR sendmail (1), .BR smail (1) or .BR exim (1)), you would use .I /usr/spool/mail/$USER here. If you are using something like qmail, you would use .IR $HOME/Mailbox . The path must be given as well as the filename to check for. .I $USER will expand to the proper username. .I $HOME will expand to the proper home directory for that very user. If .B MAILBOX is set to``QMAIL'' cfingerd assumes that Qmail is used on the local system and therefore will read .I ~/.qmail files instead of common mailbox files. .PP .B LOGFILE is the file that is used to keep logs of everything that happens to your finger program. These logs are kept as backups for your finger file, and can be used to guard against attacks against your system if a finger attack occurs. By keeping .I cfingerd.conf readable only by root the logfile should be kept in a safe, hidden place. .PP .B HEADER_DISPLAY is the file that is displayed at the top of each finger reply. The standard here is .IR "/etc/cfingerd/top_finger.txt" . .PP .B FOOTER_DISPLAY is the file that is displayed at the end of each finger reply. The standard here is .IR "/etc/cfingerd/bottom_finger.txt" . .PP .B NO_USER_BANNER is the file that is displayed if the user doesn't exist. The standard here is .IR "/etc/cfingerd/nouser_banner.txt" . .PP .B NO_NAME_BANNER is the file that is displayed if no name was specified in a finger request if a system listing is not allowed by the .B SYSTEM_LIST option (explained later). The standard here is .IR "/etc/cfingerd/noname_banner.txt" . .PP .B REJECTED_BANNER is the file that is displayed if a rejected host tries to finger your system for any reason. The standard here is .IR "/etc/cfingerd/rejected_banner.txt" . .br .SH "FINGER DISPLAY CONFIGURE SECTION (CONFIG finger_display)" Each option in this section is boolean. The way this works is as follows: The first boolean option is the setting for a remote host, or a host that fingers you from the outside. The second boolean option is the setting for the local host, or trusted host. This is what people from your own system will see. .PP TRUE means that this item is included in the cfingerd reply. FALSE means it is omitted. Unless otherwise specified these items only appear if an existing user is fingered. .PP Each option has a "\-" or "+" option. This is for user\-overridable options, which will be in the next release of .BR cfingerd . These will allow each user to manipulate if this information is displayed when that specific user is fingered. .PP .B HEADER_FILE displays the header file at the beginning of each finger reply. .PP .B FOOTER_FILE displays the footer file at the end of each finger reply. .PP .B LOGIN_ID displays the login ID of that particular user. .PP .B REAL_NAME displays the real name of that particular user. .PP .B DIRECTORY displays the user's directory. .PP .B SHELL displays the user's shell. .PP .B ROOM_NUMBER displays the user's room number. .PP .B WORK_NUMBER displays the user's work phone number. .PP .B HOME_NUMBER displays the user's home phone number. .PP .B OTHER displays the user's other information. .PP .B LAST_TIME_ON displays the last time the user has logged into the fingered system. .PP .B IF_ONLINE displays whether or not the user is currently logged into the fingered system. .PP .B TIME_MAIL_READ displays the last time that the fingered user has read mail. .PP .B DAY_MAIL_READ displays the last day that the fingered user read his/her mail. .PP .B ORIGINATION displays the site from which the user logged in (if applicable.) .PP .B PLAN displays the user's plan file. .PP .B PROJECT displays the user's project file. .PP .B PGP displays the user's Pretty\-Good\-Privacy key file. .PP .B XFACE displays the user's XFACE file. .PP .B NO_NAME_BANNER displays the banner if no username was given. .PP .B REJECTED_BANNER displays the rejected banner file if the site fingering your system was in the banned\-site listing. .PP .B SYSTEM_LIST displays the system list if one was requested. .PP .B NO_NAME displays the NO_USER_BANNER file if no user was selected. .br .SH "INTERNAL CONFIG SECTION (CONFIG internal_config)" Each item in this section is a switchable option. This means that a "+" before the item enables it while a "\-" before the item turns it off. .PP .B ALLOW_MULTIPLE_FINGER_DISPLAY tells .B cfingerd to add the system finger information from the hosts listed in the system_list_sites instead of only the localhost. This is useful when you have more than one ISP machine, located in different cities, or even states. .PP .B ALLOW_SEARCHABLE_FINGER allows you to let others outside of your system (or within it) to search for a specific username by using the "search.pattern" directive. .PP .B ALLOW_NO_IP_MATCH_FINGER allows you to let sites finger your system if a hostname could not be matched to their IP address successfully. .PP .B ALLOW_USER_OVERRIDE will allow your users to override specific options in the .B FINGER DISPLAY section that you enable. This is not yet implemented. .PP .B ALLOW_USERLIST_ONLY will allow other sites to get a shortened form of the "finger @hostname" response by issuing "finger userlist-only@hostname". The shortened form does not merge in other computers even if .B ALLOW_MULTIPLE_FINGER_DISPLAY is enabled, and omits the usual headers and footers. This listing is only available if the remote user is allowed to query for a regular system list, so .B SYSTEM_LIST from the finger_display section needs to be enabled, too. .PP .B ALLOW_FINGER_FORWARDING will allow other sites to forward finger requests to a different machine if the user could not be located on the current machine. (In order to use this option, you .B MUST have the .B HOSTS finger_forward option set, and have other sites in there.) .PP .B ALLOW_STRICT_FORMATTING makes the finger display remove all returns between display options. This makes the finger display look horrible (as with GNU Finger or the other generic fingers) and makes your system look, well, "generic". :) .PP .B ALLOW_VERBOSE_TIMESTAMPING makes the timestamp that is displayed (at any place) very verbose. For instance, where it used to say: .sp On since Sat Aug 12 03:43PM (PDT) .PP would now be shown as: .sp On since Sat Aug 12, 1995 03:43PM (PDT) .PP (Basically, ALLOW_VERBOSE_TIMESTAMPING just takes up more room on the display field.) .PP .B ALLOW_NONIDENT_ACCESS lets .B cfingerd also accept connections from sites that don't run the IDENT daemon (or RFC1413-compliant program.) This is for security sake, and is a good measure against unknown users trying to finger your system. If this option is enabled, users that do not have identd running on their system (ala Windows users) will be able to finger your system. Systems NOT running identd will return "unknown" as the user ID, and will thusly not be permitted to finger a user on your system. .PP .B ALLOW_FINGER_LOGGING enables .B cfingerd to use the \fBLOGFILE\fP file to store any logs of activity that happen to your system via finger. .PP .B ALLOW_LINE_PARSING makes .B cfingerd parse each line of every display file (including the plan, project, and pgp files) for any cfingerd-specific "$" commands. If any are found, cfingerd will parse these commands and display correct information accordingly. Otherwise, if this is turned off, the display will appear without parsed commands. .PP .B ALLOW_EXECUTION will allow users to execute scripts in place of their .IR .plan ", " .project ", and " .pgp files. This is used to display the standard output of another program directly to the screen of the user. Keep in mind that this is a HUGE security risk, should you choose to use it. It's normally suggested that this remain off, but you can turn it on if necessary. Nevertheless these programs are called as nobody.nogroup as effective user (while the real user will still be root, but a called program won't be able to change this back). .PP .B ALLOW_FAKEUSER_FINGER turns on or off the fake user option in .BR cfingerd . If you want fake users to be defined, and available to be fingered, you will want to enable this option. This can be a security risk in some instances if you allow for searchable fingers, and your script calls an execute routine on that variable... But chances are, that'll never happen. .PP .B ALLOW_USERLOG will allow users to keep track of who has fingered them, and at what time. The default name of this user logfile is .IR ".fingerlog" . .PP .B ALLOW_CONFESSION enables two fakeusers "help" and "version" that provide information about the system running. Some people don't like that so you can turn it off. When fingered the requestor will only see the NO_USER_BANNER so he can't guess that the fakeuser is supported. .PP .B ONLY_SHOW_HEADERS_IF_FILE_EXISTS will only show the header of the .plan, .project, etc. files if they exist. If the file doesn't exist, the header will not be shown. This saves space on the final output of the finger data. .PP .B ONLY_CREATE_FINGERLOG_IF_FILE_EXISTS will only create a .fingerlog file in the fingered user's home directory if one exists (and is read/writable by the user.) This is to cut down on hard drive space if they don't want a .fingerlog file. .br .SH "SYSTEM LIST SITES SECTION (CONFIG system_list_sites)" This is just a series of hostnames that you want to finger when displaying a userlist query (finger @localhost) . If you have more than one system that you want to show, simply put their hostnames in this list, separated on a line by itself. .PP A good example of the way this works is this: If you have a separate ISP system that you are running on the side, say "chatlink.com", then I would change my configuration to say: .sp CONFIG system_list_sites = { chatlink.com, localhost } .PP Remember, if you are listing only a couple of sites, list the sites you will want to have listed (in order) first. These sites are required to run .B cfingerd as well and they must not be offline while fingering. The ending entry .B MUST be the localhost, or the finger listing will not include your site. If you include localhost anywhere else in the list, it will stop once it has reached the localhost entry, so remember to list it last! .PP For the simple fact that I want to get a user listing from my own machine, and from chatlink.com's system. This would be automatically formatted nicely (ie. sorted and parsed) and would display on the screen in sorted order. This program is usually used in tandem with the supplied .BR userlist (1) program. .PP If no system list sites are specified, multiple system sites will not be specified. .br .SH "TRUSTED HOST SECTION (HOSTS trusted)" This is a listing of the sites that you allow to finger your system exclusively, giving them the same access that your local users would get. In other words, they are treated as "localhost" users. .PP Each site that you list in this section should be separated by using the "," character. You can include up to 80 sites in this listing. .PP Wildcards are supported in this section, and you may use them in the regex format as well. Any wildcards with "*", "?", or any other regex wildcard matching character will work. IP addresses will also work. Hostnames are compared case insensitive. .br .SH "REJECTED HOST SECTION (HOSTS rejected)" This is a listing of the sites that you do not allow to finger your system. These sites don't get to finger anyone (or anything for that matter) on your system, regardless of what they try to do. In essence, finger is cut off to those particular systems. .PP Each site that you list in this section should be separated by using the "," character. You can include up to 80 sites in this listing. .PP Wildcards are supported in this section, and you may use them in the regex format as well. Any wildcards with "*", "?", or any other regex wildcard matching character will work. IP addresses will also work. Hostnames are compared case insensitive. .br .SH "FORWARDED HOST SECTION (HOSTS finger_forward)" This is a listing of sites that are used to forward a finger query to when a finger request was processed, but that particular user was not found on the associated system. It will step through this listing, and it will search for the user in question. If the user could not be found, then it will step through to the next host, and the next, until it finds one. .PP Each site that you list in this section should be separated by using the "," character. You can include up to 80 sites in this listing. .PP Wildcards are supported in this section, and you may use them in the regex format as well. Any wildcards with "*", "?", or any other regex wildcard matching character will work. Hostnames are compared case insensitive. .PP If you do not specify any forwarding sites in this section, finger forwarding will be disabled for your system. .br .SH "FINGER STRINGS SECTION (CONFIG finger_strings)" Each option in this section is a string that can be changed to fit your needs when displaying finger information. These strings are limited to about 20 characters on the display. (If you use more than 20, the finger display will end up looking strange.) .PP .B USER_NAME is the string that is displayed when the user's username is shown. .PP .B REAL_NAME is the string that is displayed when the user's real name is shown. .PP .B DIRECTORY is the string that is displayed when the user's directory is shown. .PP .B SHELL is the string that is displayed when the user's shell is shown. .PP .B ROOM_NUMBER is the string that is displayed when the user's room number is shown. .PP .B WORK_NUMBER is the string that is displayed when the user's work phone number is shown. .PP .B HOME_NUMBER is the string that is displayed when the user's home phone number is shown. .PP .B OTHER is the string that is displayed when the user's other display information is show. .PP .B PLAN is the string that is displayed when the user's plan is shown. .PP .B PROJECT is the string that is displayed when the user's project is shown. .PP .B PGPKEY is the string that is displayed when the user's PGP Key is shown. .PP .B XFACE is the string that is displayed when the user's XFACE file is shown. .PP .B NO_PLAN is the string that is displayed if the user doesn't have a plan file to show you and .B ONLY_SHOW_HEADERS_IF_FILE_EXISTS is not enabled. .PP .B NO_PROJECT is the string that is displayed if the user doesn't have a project file to show you and .B ONLY_SHOW_HEADERS_IF_FILE_EXISTS is not enabled. .PP .B NO_PGP is the string that is displayed if the user doesn't have a PGP Key file to show you and .B ONLY_SHOW_HEADERS_IF_FILE_EXISTS is not enabled. .PP .B NO_XFACE is the string that is displayed if the user doesn't have an xface file to show you and .B ONLY_SHOW_HEADERS_IF_FILE_EXISTS is not enabled. .PP .B WAIT is the string that is shown when the system gathers information from other sites for a user listing. .br .SH "INTERNAL STRINGS SECTION (CONFIG internal_strings)" These strings are changable, and can be any length you want (within reason). These strings are concattenated into the syslogging display when the appropriate finger has been issued. This section also includes error messages that may occur. .PP .B NO_IP_HOST is shown when there is no hostname that matches the incoming IP address. This usually indicates that either the site didn't register their IP address with the InterNIC, or they are coming from a hacked site. .PP .B RENICE_FATAL is shown when the system failed to change the execution priority on the current process of cfingerd. .PP .B STDIN_EMPTY is shown when the input buffer on the CFINGERD port is empty. (This should never really happen; it's here for sanity.) .PP .B TRUSTED_HOST is shown when a trusted host fingers your system. If you do not specify a trusted host, cfingerd will insert "localhost" into this field. .PP .B REJECTED_HOST is shown when a rejected host fingers your system. If you do not specify a rejected host, cfingerd will insert "0.0.0.0" into this field. .PP .B ROOT_FINGER is shown when a user fingers root. .PP .B SERVICE_FINGER is shown when a user requests fake user services from your system. .PP .B USER_LIST is shown when a user requests a system user listing from your system. .PP .B FAKE_USER is shown when a user fingers a fake user from your system. .PP .B WHOIS_USER is shown when a user fingers a user with a "WHOIS" query. (This option is not yet available at the time of this writing.) .PP .B FINGER_DENY is shown when a user tries to finger with a forward request like user@host1@host2. This is not supported as it could result in finger loops and lots of traffic. .br .SH "SIGNAL STRINGS CONFIGURE SECTION (CONFIG signal_strings)" This section is used in changing the output that is given when a system crashes, or a signal is caught, and reported to the finger output. .PP The supported caught signals are as follows: .PP SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH .br .SH "FINGER PROGRAMS FILES SECTION (FILES finger_programs)" These are the programs that are called when a specific action is take on the finger display. .PP .B FINGER is the file that is used when a system user listing is requested from your machine. This is used in the standard user list and in the sorted user list, so it is wise to use the standard here; this being .IR "/usr/sbin/userlist" . .PP .B WHOIS is the program that is used when a "whois" request is done on a specific user. This is currently not used. .br .SH "FINGER FAKEUSERS FILES SECTION (FILES finger_fakeusers)" These are the ever\-popular fake users that you can create on your system. These users are ones that don't exist (and should not, for that matter.) These are, instead, treated as normal scripts that can be called for your use. .PP The format is as follows for fake users: .sh "fake_username", "Script name", SEARCHBOOL, "script" .PP where... .PP .B fake_username is the name of the fake user you want to request. Make sure that this is a user that DOES NOT exist on your system. Keep in mind that if you create a fake username, and that user already exists, the fake username will be shown. If you prepend '-' before the username, the fake user will not be shown on the list of services. .PP .B Script name is the standard name of your script. This is used in the display of your services listing. .PP .B SEARCHBOOL specifies whether or not parameters can be sent to that specific fake user. If you decide to use the SEARCHBOOL option (ie. TRUE in this case), the passed variables are: .sp $1 \- First passed option, $2 \- Second passed option, $3 \- Third passed option, and $4 \- Fourth passed option. .PP (If more than four options were passed to this, the request will be ignored, and an error message will be returned to the user that requested the finger request.) .PP .B script is the location of your script. It should be .B chmod 700 and readable only by root. .PP If you do not specify any fake users, a fake user called "None" will be created. This is a fake user that does nothing, and calls "/dev/null" for the script. .br .SH "SERVICES HEADER CONFIGURE SECTION (CONFIG services_header)" This is the display that is given during a services finger. It should be formatted the same way that you want it to display on the screen. .PP When specifying the finger formatted options, you should specify them as C formatted strings as well, with the standard options. This should always be given last in the display. .PP An example of this would be: .sp Welcome to this system's services! User: Service name: Searchable: -------- -------------------- ----------- %-8s %-20s %-s .PP Where this would display the above string. Remember to keep the format string last, or a .B SIGSEGV will result. .br .SH "SERVICES POSITIONS CONFIGURE SECTION (CONFIG services_positions)" This specifies where in the above display string that the information from a service listing is to go. These numbers can be anywhere between 1 and 3. .PP .B USER specifies the position of the username listing. .PP .B SERVICE specifies the position of the service full\-name listing. .PP .B SEARCH specifies the position of the boolean search display. .br .SH CONTACTING If you like the software, and you want to learn more about the software, or want to see a feature added to it that isn't already here, then please write to cfingerd@infodrom.north.de. The project's webpage is at http://www.infodrom.north.de/cfingerd/ . .PP As always, I appreciate any suggestions, or bug reports you may have, so if you have suggestions or bug reports, BRING 'EM ON! :) .br .SH "SEE ALSO" .BR cfingerd (8), .BR cfingerd.text (5), .BR userlist (1), .BR finger (1), .BR regex (3), .BR regexp (3). cfingerd-1.4.3/docs/cfingerd.text.50100644000076500001440000000475206764317640016002 0ustar joeyusers.TH CFINGERD.TEXT 5 "7 Aug 1999" "1.4.2" "Configurable Finger Daemon" .SH NAME cfingerd text rules .br .SH "EXPLANATION" .B cfingerd offers different commands that can be placed in text files to display corresponding information. Each command used with .B cfingerd in text files begins with a dollar-sign (or a "$"). This usually indicates to .B cfingerd that when it's displaying a file, it issues the command given directly after that character and inserts its output. .PP If you want to display a raw "$" sign, simply put two "$" signs together, or "$$". .PP Text commands are only parsed if ALLOW_LINE_PARSING is enabled in /etc/cfingerd/cfingerd.conf(5). If it is disabled the text files will be sent as is, complete with any single or double dollar signs they may contain. .br .SH "TEXT COMMANDS" The following is a list of text commands and what they do. They are checked case insensitively. .PP .B $CENTER will display the entire contents of the line. This command must start at the beginning of the line. This is a very common command. .PP .B $DATE displays the current system date in the format of MM/DD/YY. .PP .B $TIME displays the current system time in the format HH:MM A/PM (timezone). .PP .B $IDENT displays the identity of the current person fingering your system. .PP .B $COMPILE_DATETIME displays the date and time of which the current issue of .B cfingerd was compiled on your system. .PP .B $VERSION displays the current version of .BR cfingerd . .PP .B $EXEC executes the rest of the line as a system command and send the output to the fingering user. Pipes, parameters etc. are available. The .B $EXEC command must be on a line by itself in order to function properly. The command is executed as nobody.nogroup if used in a system file. If used in a user file (e.g. .IR .plan ) the command is executed as that particular user. .B cfingerd will fork() before executing the new command and will drop all priviledges so this is safe. .PP This feature is only available if .B ALLOW_EXECUTION is enabled in cfingerd.conf. The program may prodeuce a maximum of 10MB of output. .br .SH CONTACTING If you like the software, and you want to learn more about the software, or want to see a feature added to it that isn't already here, then please write to cfingerd@infodrom.north.de. The project's webpage is at http://www.infodrom.north.de/cfingerd/ . .SH "SEE ALSO" .BR cfingerd (8), .BR cfingerd.conf (5), .BR finger (1), .BR userlist (1), any of the included docs with the standard cfingerd distribution. cfingerd-1.4.3/CHANGES0100644000076500001440000004124006774335641013206 0ustar joeyusersCFINGERD 1.4.3 09/29/99 - Security update, fixes buffer overflows introduced with sscanf(), exploitable under FreeBSD CFINGERD 1.4.2 09/05/99 - Bugfix release - Corrected build system for FreeBSD, thank Alexey CFINGERD 1.4.1 08/29/99 - Path for cfingerd.conf is now configurable via --conf= (Configure) - Corrected read code - Disabled DAEMON_MODE again - Max. 10MB of output will be used from external programs - If nobody's logged in, that's displayed, instead of a header. - Support for FreeBSD CFINGERD 1.4.0 08/09/99 - New source maintainer - Several bugfixes - Use tail +2 for userlist - Fixed silly bug in src/search.c - src/search.c: If the internal search.*@ is used the whole GCOS field won't be sent out anymore. - Fixed string bugs in standard.c. - Ignore empty lines when collecting remote data - Flagged SIGPIPE as fatal - Corrected logfile writing as user, thanks to Thomas Gebhardt - Corrected search_fake() which depended on 80 char strings but received a 100 character one. (most recent on bugtraq, fixed on 12 May 1998) - Corrected RFC1413 code - Corrected check_illegal() for .nofinger - Corrected wrong calls for check_illegal() - Fixed a security hole in privs.h. - Fixed typo in userlist/display.c which crashed userlist - Proper exception if ident doesn't provide useful info - Added patch to support Qmail mailboxes, thanks to Russell Coker - Removed investigation of the hostname within Configure script - src/main.c: Added support for /W, actually it's ignored... - Added define HAVE_TTY_GROUP so add support for non-world-writable tty's owned by group tty - Used config option for .nofinger file instad of static ".nofinger" - Added space before [MSG-N] - Reworked search.* routine. - Documentation update - Restricted length of username, fixes possible overflow in show_search() and handle_fakeuser() - Converted all dangerous occurrances of strcpy() to strncpy() - More updates wrt. sane permissions when opening files - Increased limit of tty per user, now I'm fingerable again. :) - cfingerd now uses the same IP number on which it receives a request to connect to a remote ident server. Thanks for help from Torsten Landschoff - cfingerd now honors broken or negative ident answers - Support for SunOS by Piotr Klaban - Support 24h clocks, inspired by Piotr Klaban - Removed ACTUAL_HOSTNAME since it has been superseeded by calls to gethostname() - Experimental code for standalone cfingerd, inspired by Piotr Klaban - Fixed userlist that crashed at too many users and too long hostnames - Fixed non-working userlist-only - Added ALLOW_CONFESSION to provide "help" and "version" information - Added support for userlist@ (and userlist-online@ internally) as modification of @ (system list) that displays only non-idle users. - Fixed security bug that caused external programs to gain root access. - Adjusted search facility, you can't get a userlisting anymore CFINGERD 1.3.2 12/17/96 - Added two new options: ONLY_SHOW_HEADERS_IF_FILE_EXISTS, and ONLY_CREATE_FINGERLOG_IF_FILE_EXISTS (see man pages for more details) - Fixed fakeuser (and other) entries to allow commenting at the beginning of each entry line if they want to be commented out - Fixed check_illegal routine to use lstat instead of its old method - Updated the FAQ, README, and other supporting documentation - Updated cfingerd.conf documentation for the MAILBOX addition - Made minor cosmetic changes to Configure and Install CFINGERD 1.3.1 09/20/96 - Updated the Configure script and supporting libraries to make it compatible with Perl 4.036 - Added support for ignoring the "/W or -L" options that some fingers send - Added "MAILBOX" entry to display_files section of cfingerd.conf - Added replacement strings for RFC1413 error related messages - Added safe_exec routine to run *ALL* programs via popen with nobody privs (see the util.c source) - Added checks to make sure *everything* is run as root after a file open, or other file activity - Changed file handles to open files as root (READ-ONLY) and have them read from the open file handle as "nobody" - Changed redirection of executed files to no redirection (no writing to any files on execution) - Changed "There are (users) total" to "This is a list of (total) sites" - Changed up the Makefiles a little bit to run smoother CFINGERD 1.3.0 08/03/96 - Updated the configuration script some more - Made some fixes to the userlist program (clearing initial variables) - Made some major upgrades in source (uses "-" to hide hidden fakeusers) - Fixed show_file routines to show files owned by "user" CFINGERD 1.2.3 07/28/96 ** YEAR ANIVERSARY FOR CFINGERD ** - Fixed up the Configuration file to check for a Clean makefile - Fixed up the FAQ (updated to version 0.5 now) - Fixed search list from a limit of 100 entries to 500 entries (will soon make it a linked list) - Fixed userlist to show correct display with PRIV_ROOT_START/END macros - Added patches to source from "Stig" (stig@hackvan.com) - Added security breach finger check for "search.*" - Added more secure become_nobody macros - Removed become_nobody and become_user routines - Changed Install script to say "1.2.x" instead of "1.2.0" - Updated the FAQ CFINGERD 1.2.2 05/13/96 - Added XFACE option to cfingerd (to display an .xface line if present) - Added "XFACE" and "NO_XFACE" options to cfingerd.conf and to display routines - Fixed finger-forward recursion bug (thanks to Larry Daffner) - Added patches to ident/auth, and lastlog - Added patches to main, userlist, and some others based on Michael Jarvis' advise and opinions - Added Kevin Rosenberg's BSD patches - Added LICENSE file to make CFINGERD officially GPL'ed - Added the license information to each source file that was applicable - Removed the lastlog.h file - Updated the FAQ and supporting README file CFINGERD 1.2.1 03/15/96 - Added error reporting to configuration file - Added usage of space instead of tab in configuration file indentions - Added replacements for options in case the sysadmin keeps them blank (in the cfingerd.conf file) - Added HAS_SHADOW option to config.h - Added a new lastlog.h file for Shadow compatibility - Added ALLOW_FAKEUSER_FINGER option to turn on or off fakeuser ability - Added documentation on ALLOW_USERLOG (forgot to add it ... oops) - Updated documentation (cfingerd.conf.5 man page) - Fixed userlist to actually work now - Fixed Configure script to accept a specified domain name - Changed root.wheel to root.root on the userlist installation Makefile CFINGERD 1.2.0 02/19/96 - Added a log item when an illegal user was fingered - Added automatic check for domain name (thanks to Linus Torvald's Makefile) - Added comments to Makefiles to give a little more verbose input - Added scripting commands to any text files (see cfingerd.script.5) - Added cfingerd.text.5 manual page describing text commands - Added trusted and rejected checking of IP addresses now - Added "make instdocs" option to force (re)installation of cfingerd docs - Added userlog files for users to keep track of who fingers them - Added "ALLOW_EXECUTION" option for executable programs within display files - Added "WTMP_FILE" define to change the WTMP file that is used - Added lastlog parsing routine to speed up last login information by 1000% - Updated some formatting problems in finger output - Fixed a bug with "IF_ONLINE" displaying info even if it's set to FALSE - Changed .project, .plan, and .pgp to show files via the element parser - Changed Configure to auto-find /var/adm/wtmp or /var/adm/lastlog - Changed order of PROJECT/PLAN file display in standard.c CFINGERD 1.1.1 01/04/96 - Added ident information to logging - Added 5 second alarm timeout in rfc1413 routine, and a return of "unknown@alarm.signal" if an alarm was caught - Fixed userlist routine to show specialized header only if userlist is used - Fixed a log bug with normal user fingers - Fixed a log configuration and display bug (reported by Kevin Rosenberg) - Created a FAQ (started one, at least) - Changed user finger display to show the ident data when a user fingers another user on your system - Changed rfc1413 routine to return unknown@user.site.here if any part of the rfc1413 fails (all except for an alarm.) (Thanks to Andrew Smith) - Officially released CFINGERD 1.1.1B4 12/30/95 - Fixed up the rfc1413 routine to run about 50% faster - Added logging and logfile definition for logs of any errors or actions CFINGERD 1.1.1B3 12/29/95 - Added wildcard host matching thanks to Rich $alz - Added wildcard matching in the user search routines - Added RFC1413 implementation for ident authentication - Added "No realname field available" if no realname field is available when displaying a search - Added rejection of fingers (configurable) if ident reports "unknown" - Fixed a bug in search routine where multiple appearances of the same user- name would appear - I failed to use bzero... :/ CFINGERD 1.1.1B2 12/10/95 - Fixed a bug that displayed "root" fingered if a user with 4 characters was fingered. (Thanks to Jon Mitchell) CFINGERD 1.1.1B1 12/01/95 - Added some changes in the Configuration script to make it more compatible CFINGERD 1.1.1A2 11/23/95 - Added Kevin Rosenberg's patches for BSD/OS compilation - Fixed some stupid bugs (mistypings on my part) to fix Kevin's fixes... :) CFINGERD 1.1.1A1 11/20/95 - Added "ALLOW_FINGER_FORWARDING" option in cfingerd.conf - Added "HOSTS finger_forward" option in cfingerd.conf - Added "ALLOW_USERLIST_ONLY" option in cfingerd.conf (was a security hole) - Fixed Install script to force copy in.cfingerd at the end - Added multiple site forwarding (from the forward option) - Added change so that nice actually changes priority of the program now CFINGERD 1.1.0 11/20/95 - Officially released to the public as 1.1.0 - the new, spiffy version CFINGERD 1.1.0B5 11/19/95 - Fixed a bug in userlist routine so it now shows the no-name user banner - Made slight rewording changes in the Configure script - Added comments to each routine CFINGERD 1.1.0B4 10/01/95 - Fixed checksite routine to actually work this time - Fixed userlist routine to work correctly (was showing invalid idletimes) - Updated makefiles and moved source to src directory - Updated documentation CFINGERD 1.1.0B3 08/26/95 - Touched up some formatting problems - Touched up the documentation a bit - Removed wildcard checking - Removed all occurances of wildcards in all code - Fixed userlist to run as root (was causing problems running as nobody) - Fixed finger routines to switch to UID/GID of fingering user instead of becoming nobody - Fixed userlist to actually use the "FINGER" option when requesting a userlist - Fixed userlist to cut off all string delimiters in utmp routines - Fixed up some scripts to work a little nicer (and more configurable) CFINGERD 1.1.0B2 08/26/95 - Touched up the manual pages a bit - Took out the entire "config" directory - Fixed file stat reporting from using stat to using ls -al (reported by David Storey) - Fixed all files to go through the stat check (especially .files) - Added a check for config.h in Makefile - Added Install script - Added "become_nobody" routine to change to the nobody UID/GID for security purposes CFINGERD 1.1.0B1 08/13/95 - Took out "ERRORS" variable in errors.c - Made options in cfingerd.conf no longer case sensitive - Optimized a little bit of the main code, removed case sensitivity in site names - Fixed showing "User has no mail" if the user has no mail spool - Fixed "other" field so that garbage no longer appears -- SWITCHED TO BETA ON 08/13/95 -- CFINGERD 1.1.0A12 08/13/95 - Changed PGP Key standard from ".pgp" to ".pgpkey" based on a betatester's devine observation - Changed configure.c so it uses structures to hold info instead of typing everything in manually - made the size drop about 10K - Added check for SHOW_WILDCARD - Added check for SHOW_MULTFING, and added nicer spaced formatting in the userlist display routines - Added check for SHOW_SEARCHFING - Added check for SHOW_IP_MATCH - Added sanity check on startup (clear out all structures) CFINGERD 1.1.0A11 08/13/95 - Fixed a bug that wouldn't show if a user never logged in - now shows correctly (Thanks to a betatester .. again!) - Fixed a bug that showed "file is a directory" if the file doesn't exist or stat returns EBADF or ENOENT - Fixed up the Configure script so it doesn't use "hostname --fqdn" anymore - Fixed up the Makefile for both cfingerd and userlist - Added an option to show PGPKEYs (Thanks to Andrew Smith) - Added cfingerd.5 manual page - Added cfingerd.conf.5 manual page - Added userlist/userlist.1 manual page - Added more verbose error reporting in configure.c - Added allowance for "," character in fingering - Added "trace" script to the installable scripts CFINGERD 1.1.0A10 08/08/95 - Fixed a bug in search routines (when reading /etc/passwd) - Fixed some bugs in search routines pertaining to load - Fixed search routine so that they can't do a search for a blank - Fixed a bug when doing emulated local fingers from the command line - would display garbage in the syslog - Fixed configure module to actually load in the new signal_strings - Changed Configure script to get the fully qualified domain name with the command "hostname --fqdn" - Added PID display in syslogging display - Added case insensitive searching in the search routines - Added a check to standard displaying so that a sneaky user can't create a strange file (ie. block device, socket, symbolic link, fifo, dir, or char device - only a readable file) - Added syslogging if any illegal .nofinger files are detected during a finger - Added "[MSG-N]" display if messages are turned off on that console CFINGERD 1.1.0A9 08/07/95 - Changed signal routine to use loaded signal strings instead of pre-made ones - Removed "%" from search standard - too wacky; changed to "." instead - Added CONFIG signal_strings section to cfingerd.conf - Added (and checked) all user-defined syslog messages - Added searchable finger routine to give nice output on search results (fully tested - it works. REALLY!) CFINGERD 1.1.0A8 08/07/95 - Fixed a bug with junk displayed in the "last seen" display - Fixed formatting in userlist display a little - Fixed user-listings between sites to use userlist-only finger - Fixed a looping problem with fingering for sorted userlists (BIG problem) - Fixed output from fakeuser if too many options are given (beautified) - Added Configure script - Added "has unread mail since" display (per suggestion from a betatester) - Added trusted hosts and trusted host display in syslog - Added rejected hosts, rejected host display in syslog, and rejected file display - Added "userlist-only" for only listing userlists (in gathering userlists between machines and sites) CFINGERD 1.1.0A7 08/05/95 - Fixed a bug that made mail turn to "old-mail" state when you were fingered and had new mail. (Now uses the stat structure - wasn't quite fixed in A6 either!) - Fixed a bug that display junk after login names - Fixed a bug in display formatting with ALLOW_STRICT_FORMATTING enabled - Added idle time display in both cfingerd and in the userlist - Added ALLOW_VERBOSE_TIMESTAMPING for verbose idle time display (using words instead of numbers alone) - Added syslogging (minimal) display support ... more later - Added examples in the userlist directory for future use CFINGERD 1.1.0A6 08/03/95 - Added ALLOW_STRICT_FORMATTING to make formatting more like SysV. :) - Fixed the routine to show whether or not a user has mail (wasn't quite fixed in A5...) CFINGERD 1.1.0A5 07/31/95 - Removed AUTH_* identifiers ... no need for 'em anymore - Added fakeuser stuff - Made userlist now exclude any users that have a ".nofinger" file in their home directory (Tested - it works.) - Added support to display user services lists - Fixed a bug that reports if a user has mail (checking a FILE struct instead of an int struct...) - Added a wildcard routine that only supports the "?" wildcard so far CFINGERD 1.1.0A4 07/28/95 - Added .nofinger display routine - Changed the userlist finger display a little so it looks better and now has a header... - Completed the userlist program ... all that remains is the idle time. :) - Added command line options to userlist (not yet functional except -c!) CFINGERD 1.1.0A3 - CFINGERD 1.1.0A0 - UNDOCUMENTED CHANGES (oops) cfingerd-1.4.3/COPYING0100644000076500001440000003031006351024420013217 0ustar joeyusers GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! cfingerd-1.4.3/CREDITS0100644000076500001440000000423206762270710013223 0ustar joeyusersCFINGERD Credits Listing Okay, I have to give credit to people where credit is due. Therefore, this file is here to give that credit to the people who helped contribute something to make CFINGERD what it is today. The current maintainer of this package is Martin Schulze . He maintains a public mailing list cfingerd@infodrom.north.de. Please direct comments to this list. --- Ken Hollis - Original author, started the project - General design Kevin Rosenberg - BSD/OS conversion and compatibility additions to source - Fixed up Configure script for BSD/OS - BSD/OS official testing and bug reports Martin Mares - fslist.pid patch - Various bug fixes Martin Schulze - Made various patches to ensure security on file operations - Added code to switch uids - Fixed quite a few bugs here and there Michael Jarvis - Various patches to remove system calls - Memory allocation advice - Help with finding bugs here and there Danek Duvall - ident/auth (RFC1413) patch - Lastlog patch Andrew Smith - PGP finger display idea and request [practically coded the damn option himself... :] - Endless amounts of bug testing and reporting Dan Hollis - Bug reports up the wazoo - Shadow password testing - Secure (NOBODY PATCH) finger help cc@spork.neonexus.com - Finger forwarding idea Rich Salz - Wildmat routine for matching strings (MANY, MANY thanks!) Thomas Gebhardt - Corrected writing logfiles as user Russell Coker - Support for Qmail mailboxes John Goerzen - Fixed a security hole Torsten Landschoff - Fixing RFC1413 code wrt. multi-IP setup Piotr Klaban - Support for Solaris Tadek Knapik - Documentation updates - Help with finding bugs here and there - Exploited a severe security problem Alexey M. Zelkin - Support for FreeBSD cfingerd-1.4.3/Configure0100755000076500001440000001473706764317634014076 0ustar joeyusers#!/usr/bin/perl # # CFINGERD Configuration Script # # $Id$ # # Copyright (c) 1996, Bitgate Software. # Copyright (c) 1998-9, Infodrom Oldenburg, Martin Schulze # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 1, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. require 'perl/question.pl'; require 'perl/filemagic.pl'; require 'perl/gethost.pl'; require 'perl/generic.pl'; $VERSION = "1.4.2"; $| = 1; $config{'config'} = "/etc/cfingerd.conf"; sub show_header { &disp_file("config/header"); } sub show_footer { &disp_file("config/footer"); if ($config{'os_type'} eq "FREEBSD") { print "*** NOTE: cfingerd is building using GNU make! On a BSD system\n"; print "*** you need to install \"gmake\" before compiling cfingred.\n"; } } sub make_userlist { print "Creating userlist/config.h ... "; open(CF, "userlist/config.h.in"); open(CFO, ">userlist/config.h"); while() { print CFO; } if ($config{'os_type'} eq 'SUNOS') { print CFO $define_sunos; } elsif ($config{'make'} eq "gmake") { print CFO $define_bsd; } close(CFO); close(CF); print "created.\n"; } sub make_config { print "Creating src/config.h ... "; $ENV{'LC_TIME'} = "C"; local($dateandtime) = `date`; chop($dateandtime); open(CF, "src/config.h.in"); open(CFO, ">src/config.h"); while() { chop; s/\@CFINGERD_CONF\@/#define\tCFINGERD_CONF\t\t\"$config{'config'}\"/; s/\@NOBODY_UID\@/#define\tNOBODY_UID\t\t$config{'nobody_uid'}/; s/\@NOBODY_GID\@/#define\tNOBODY_GID\t\t$config{'nobody_gid'}/; s/\@COMPILE_DT\@/#define\tCOMPILE_DT\t\t\"$dateandtime\"/; s/\@WTMPFILE\@/#define\tWTMPFILE\t\t"$config{'lastlog'}"/; s/\@MAIL_SPOOL_DIR\@/#define\tMAIL_SPOOL_DIR\t\t"$config{'mailspool'}"/; if (!$config{'lastlog'}) { s/\@USE_LASTLOG\@/#undef\tUSE_LASTLOG/; } else { s/\@USE_LASTLOG\@/#define\tUSE_LASTLOG\t\t1/; } if ($shadow eq "Y") { s/\@HAS_SHADOW\@/#define\tHAS_SHADOW\t\t1/; } else { s/\@HAS_SHADOW\@/#undef\tHAS_SHADOW/; } if (getgrnam("tty")) { s/\@HAS_TTY_GROUP\@/#define\tHAS_TTY_GROUP\t\t1/; } else { s/\@HAS_TTY_GROUP\@/#undef\tHAS_TTY_GROUP/; } print CFO "$_\n"; } if ($config{'os_type'} eq 'SUNOS') { print CFO $define_sunos; } elsif ($config{'make'} eq "gmake") { print CFO $define_bsd; } close(CFO); close(CF); print "created.\n"; } sub make_makefile { print "Creating Makefile.cfg ... "; open(CF, "Makefile.cfg.in"); open(CFO, ">Makefile.cfg"); while() { chop; s/__OS_TYPE__/$config{'ostype'}/; s/__MAKE__/$config{'make'}/; s/__LDFLAGS__/$config{'ldflags'}/; s/__CFLAGS__/$config{'cflags'}/; s/__MANDIR__/$config{'mandir'}/; s/__MAN_OWNER__/$config{'man_owner'}/; s/__MAN_GROUP__/$config{'man_group'}/; s/__BIN_OWNER__/$config{'bin_owner'}/; s/__BIN_GROUP__/$config{'bin_group'}/; print CFO "$_\n"; } close(CF); close(CFO); print "created.\n"; } sub configure { unlink("src/config.h"); $go_on = &check_exist("1", "./Makefile.cfg", "totally clean installation", "config/makewarn"); if ($go_on && $go_on ne "Y") { &disp_file("config/cancelled"); exit; } system("cp -p Makefile.in Makefile"); ($config{'os_type'},$os_ver) = &get_os; $os_ver =~ s/\.//g; $config{'lastlog'} = &get_lastlog ($config{'lastlog'}); $nobody = &get_nobody ($config{'nobody_uid'},$config{'nobody_gid'}); ($config{'nobody_uid'},$config{'nobody_gid'}) = split(',', $nobody); $shadow = &has_shadow; $config{'mailspool'} = &get_mailspool ($config{'mailspool'}); $config{'mandir'} = &get_mandir ($config{'mandir'}); if ($config{'os_type'} eq "LINUX") { $config{'make'} = "make" if (!exists $config{'make'}); $config{'ldflags'} = "" if (!exists $config{'ldflags'}); $config{'cflags'} = "-g -O2 -Wall" if (!exists $config{'cflags'}); $config{'bin_owner'} = "root" if (!exists $config{'bin_owner'}); $config{'bin_group'} = "root" if (!exists $config{'bin_group'}); $config{'man_owner'} = "man" if (!exists $config{'man_owner'}); $config{'man_group'} = "man" if (!exists $config{'man_group'}); } elsif ($config{'os_type'} eq "SUNOS") { $config{'make'} = "gmake" if (!exists $config{'make'}); $config{'ldflags'} = "-lsocket -lnsl" if (!exists $config{'ldflags'}); $config{'cflags'} = "" if (!exists $config{'cflags'}); $config{'bin_owner'} = "bin" if (!exists $config{'bin_owner'}); $config{'bin_group'} = "bin" if (!exists $config{'bin_group'}); $config{'man_owner'} = "bin" if (!exists $config{'man_owner'}); $config{'man_group'} = "bin" if (!exists $config{'man_group'}); } elsif ($config{'os_type'} eq "FREEBSD") { $config{'make'} = "gmake" if (!exists $config{'make'}); $config{'ldflags'} = "" if (!exists $config{'ldflags'}); $config{'cflags'} = "" if (!exists $config{'cflags'}); $config{'bin_owner'} = "root" if (!exists $config{'bin_owner'}); $config{'bin_group'} = "wheel" if (!exists $config{'bin_group'}); $config{'man_owner'} = "man" if (!exists $config{'man_owner'}); $config{'man_group'} = "man" if (!exists $config{'man_group'}); } else { $config{'make'} = "gmake" if (!exists $config{'make'}); $config{'ldflags'} = "" if (!exists $config{'ldflags'}); $config{'cflags'} = "" if (!exists $config{'cflags'}); $config{'bin_owner'} = "root" if (!exists $config{'bin_owner'}); $config{'bin_group'} = "root" if (!exists $config{'bin_group'}); $config{'man_owner'} = "root" if (!exists $config{'man_owner'}); $config{'man_group'} = "root" if (!exists $config{'man_group'}); } print "\n"; $define_bsd = "\n#ifndef BSD\n#define BSD 1\n#endif\n"; $define_sunos = "\n#ifndef SUNOS\n#define SUNOS $os_ver\n#endif\n"; &make_config; &make_userlist; &make_makefile; } # Parse arguments $i = 0; while ($i <= $#ARGV) { if ($ARGV[$i] eq "-h" || $ARGV[$i] eq "--help") { printf "./Configure [-c foo=bar] [-h]\n"; foreach $foo (('make','cflags','ldflags','config','nobody_uid','nobody_gid','lastlog','mailspool','mandir')) { printf "\t%s=\n", $foo; } exit 0; } elsif ($ARGV[$i] eq "-c") { if ($i+1 <= $#ARGV && ($ARGV[$i+1] =~ /(.+)=['"]?(.+)['"]?/)) { $config{$1} = $2; $i++; } } else { print STDERR "Unknown argument '$ARGV[$i]'.\n"; } $i++; } &show_header; &configure; &show_footer; cfingerd-1.4.3/FAQ0100644000076500001440000003277606747301205012550 0ustar joeyusers #### ###### ###### ## ## ##### ###### ##### ##### ###### #### #### ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## ## ## ## #### ## ###### ## ### #### ##### ## ## #### ###### ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## ## ## #### ## ###### ## ## ##### ###### ## ## ##### ## ## ## ## ## The CFINGERD FAQ version 1.0.2 by Ken Hollis Martin Schulze * This FAQ is provided to give information about the cfingerd daemon program, and to answer some frequently answered questions. These are some of the questions I get asked frequently, and some of the questions I figured I should clear up. * CFINGERD is a free finger daemon replacement for standard finger daemons such as GNU Finger, MIT Finger, or KFINGERD. CFINGERD is highly becoming a respected standard as the finger daemon to use. If you are unsure about which finger daemon to get, please read over this document before re-enabling your finger daemon! -- WHAT IS FINGER? FINGER is a program that was originally created by MIT to offer user information about someone on another machine somewhere else on the Internet. The protocol is defined in RFC 1228. Finger provides information about who you are, what you do, when you last logged in, when you last read mail, and many more features. Unfortunately, however, many sites turn off the finger daemon because it's a security risk. That's unfortunate, as the finger program is very valuable, and very helpful for friends and other users on the Internet. WHAT WILL CFINGERD PROVIDE OVER NORMAL FINGER? CFINGERD is a program that provides a nicely formatted user information display. CFINGERD was programmed with to help System Administrator with improving security while not disabling the finger service. Many sites will receive a root finger before they are attacked. With this finger program, you can now turn off the ability to have root fingered by adding a ".nofinger" file, or a file that doesn't allow for fingering of that user (or anonymity). It also is highly configurable when it comes to the question what user info to display. In two levels - first the Administrator determines cfingerd's behaviour along with display configuration, then users may change things concerning displaying their info, as much of it as the Administrator lets them. Aside from being security conscious, CFINGERD also offers a great deal of other features that normal finger just couldn't provide. Among these are the ability emulate users with scripts, log any finger requests either by user or globally, offer custom finger services, display header and footer advertisements, and a nicely formatted user display to name a few. Not only this, but cfingerd allows you to provide fingerable services, which allows for users outside of your system to find out more information about things you provide; such as information about your ISP, your rates, or other things of this nature. CFINGERD's fingerable services also provide the ability to run scripts to display extra information, such as a traceroute outside of your area. The possibilities are endless. Of course, you could get GNU's CFINGERD, which is ten times larger, harder to configure, and requires more work to do what you could do with CFINGERD in just five minutes. Read over this FAQ. After you're done, read the "README" file, and follow the directions. WHERE CAN I GET CFINGERD? CFINGERD's main archive is available on ftp.infodrom.north.de and may be downloaded from the /pub/people/joey/cfingerd/ directory. You will want to check this directory on a periodic basis if any announcements are given regarding program updates. Non-official updates (or BETA versions) are also available on this site. You may want to check the site once a week or so to check on new updates. Usually, the betas are in testing, and will not be given tech support, so be warned. The alternative is to get CFINGERD from metalab.unc.edu in the directory /pub/Linux/system/Network/finger. This is the main upload site for any updates after they become official. Since the current maintainer of cfingerd is also a member of the Debian Project many patches are available in the Debian version of cfingerd before the next official version of cfingerd is released. The diff file can be found on the same FTP site in /pub/people/joey/debian/ . WHO MAINTAINS CFINGERD? The cfingerd program was started by Ken Hollis who has done a great job implementing this daemon and maintaining it. From 1998 on he decided to work on other projects and handed maintainerhip over to Martin Schulze who has worked on other projects before. IS THERE A MAILING LIST FOR UPDATES? Joey has set up a mailing list cfingerd@infodrom.north.de to provide a forum for discussions about cfingerd. If you want to share new ideas or patches please contact this list. You probably want to subscribe yourself by sending a mail to majordomo@infodrom.north.de with "subscribe cfingerd" in the mail body. HOW DO I INSTALL CFINGERD ONCE I GET IT? The answer is simple. Simply type "Configure" and answer the questions the configuration script prompts you for. Once that's done, simply edit the necessary files, or type "make all" and you will be on your way to a complete install of cfingerd. You will also need to add a line to inetd.conf (or at least change one.) Those instructions are in the included "README" file with the standard distribution. WHAT OPERATING SYSTEMS ARE COMPATIBLE WITH CFINGERD? Currently, only Linux, BSD and Solaris are supported. If you use another flavour of Unix, and know enough about C and the system to provide a patch, please contact the list mentioned above. I HAVE A PATCH - HOW DO I SUBMIT THE PATCH? Patches are always appreciated. This is how free software works and gets developed. If you want to submit a patch for inclusion in the next release please send the patch with a detailed description to the list mentioned above. Please keep in mind that a patch can only be applied if the maintainer of cfingerd is able to understand it. Please ensure to tell us on which version your patch is based so we have a chance to apply it. WHAT ABOUT A WEB PAGE? There will be a web page in the future, but it won't be able to provide more information than files within the source tarball. -- Commonly asked questions: Q. WHY DOES THIS PROGRAM RUN AS ROOT??? A. Although it may not make sense to you at first glance, the daemon runs as root for many security reasons. First off, the cfingerd.conf file itself should be root read-only, so other users can't see how you have cfingerd set up. Secondly, in order for cfingerd to change to the User ID and Group ID of the user someone fingered, it must run as root. If you run it as nobody, and finger someone with their home directory of mode 700, you will NOT be able to read the .plan or .project files, REGARDLESS. Don't worry, though. The Configure script locates your nobody UID/GID automatically, and uses this whenever it performs most of its work. It also executes programs as nobody or as user to ensure total security. However in order not to allow random programs being executed by a finger procedure you should turn -ALLOW_EXECUTION off in the internal configuration section in the cfingerd.conf file. Also, keep in mind that all of the UID/GIDs get changed to the NOBODY UID/GID *immediately* after file opens, executions of programs, or whatever else. NO PROGRAMS ARE STARTED OR READ AS ROOT! """""""""""""""""""""""""""""""""""""""" Q. I've seen a patch laying around known as "cfingerd-1.3.0-noroot". Should I use this instead of this version? A. You can if you want, I'm not stopping you. :) Actually, the reason this file was released was because the security holes in cfingerd were not completely removed. (No program is perfect; take sendmail's security holes for instance.) These are addressed in the release 1.3.1. The new version 1.4.0 is even more pickier about security and user IDs. Q. Do you need to have cfingerd run with tcpd? A. No. RFC1413 (Host identification) has been put into CFINGERD as an accepted standard. RFC1413 does not provide security for your system, but it also identifies who's accessing your system at a given time. Since RFC1413 support is internal, there's no reason to run the tcpd wrapper around the program. Think of it as an extra security measure. However, if you want to be able to restrict access to your finger service to certain addresses or want to keep some others off you'll need to run it through the tcpd wrapper. The standalone version of CFINGERD will also make use of it. Q. When someone fingers my machine, it loops around and keeps spawning finger processes on my machine! Help! A. The reason this is happening is most likely because you have a finger forward that forwards to another system which is pointing back to your own originating system. This will cause an endless loop. CFINGERD will fix this in a later revision (hopefully.) Another cause could be that you've got multiple finger list sites that are pointing to each other. For instance, you set up one finger site on one system, and another on one other computer. On computer "A", it points to "foo.com", and "foo.com" points to "bleah.com". Well, since they will both ask the other one if they don't know the answer, they will keep looping and looping, and looping. The way to stop this is to set system_list_sites to one entry, and make that entry "localhost". There are many solutions to this problem. The best one that comes to mind may be the fact that you have ALLOW_FINGER_FORWARDING turned on, and no entries in the finger_forward listing of hosts. Having an entry of localhost alone in this section will make the processes spawn over-and-over again. Q. When a site fingers my system, I get a syslog entry that says "unknown@alarm.signal". A. This simply means that the site that fingered your system failed to respond to an RFC1413 client query, and thusly timed out, returning a standard unknown response. Q. When someone fingers my system, I get "illegal character in username". A. Their finger program may be sending a "-L" or a "/W" command when fingering the system. Older versions of cfingerd did not support the long formatted display of normal GNU finger. Cfingerd now simply ignores this, to conform with RFC1288. The remedy is thus to get the latest patch to cfingerd, currently available as a Debian package. Q. My header files aren't being displayed properly. cfingerd's not intercepting the commands. A. Try adding the line "+ALLOW_LINE_PARSING" to your internal_config section. That usually helps. Q. The no-name banner isn't showing, and I have it set to true! A. Make sure system_list is set to FALSE for remote systems. If it's not, the SYSTEM_LIST variable (if set to true) will override the NO_NAME_BANNER option. Q. I have a big site, and I'm trying to list users that are on that site! It's not working, and I'm sure I've set it up correctly! A. Make sure that "+ALLOW_USERLIST_ONLY" is set in the internal_config section. Also, make sure that "localhost" is the last entry in the system_list_sites configuration section. If it's placed anywhere else in that section, it will stop at that entry. "localhost" is considered to be the ending entry. Q. When I finger someone on the system, it says "This daemon must be run as root!" A. The way to fix this is to change the inetd.conf entry from "daemon" to "root" permissions. This can be done by using the following entry in your inetd.conf file: finger stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.cfingerd Save that, then reboot your inetd program. (This can be done by typing "killall -HUP inetd"). Then, finger away! Q. If I have a bug, what do I do? A. We have received messages that simply have the entry "SIGSEGV Received!" and nothing else was sent. This probably is not helpful for finding the real source of the problem. We have had lots of people modifying the cfingerd.conf file, adding spaces here and there, or tabs here and there. DO NOT change the format, only the ASCII chars. DO NOT SUBSTITUTE SPACES FOR TABS. If all else fails, backup your cfingerd.conf, re-copy the original cfingerd.conf file into your /etc directory and apply all changes you've made before watching what happens. Chances are, something got messed up during the modification. If you expect to get a helping hand from other cfingerd users or its maintainers, please at least attach your cfingerd.conf file. Q. I see ".fingerlog (Operation not permitted)" in my syslog! What now? A. Most likely, you were running an older version of cfingerd that had root access to that file. Former versions of cfingerd didn't change the effective user id to the user before accessing the logfile. To fix this, type: "chown user.group .fingerlog", where user.group is whoever has that directory as home directory, and all will be well. cfingerd-1.4.3/Install0100755000076500001440000000703406762167777013564 0ustar joeyusers#!/usr/bin/perl # # Installation script for CFINGERD # version 2.0.0 by Ken Hollis $cfgpath = "/etc/cfingerd.conf"; if (open (C, "src/config.h")) { while () { /^#define\s+CFINGERD_CONF\s+(.*)$/ && ($cfgpath = $1); } close (C); } else { print "Can't read src/config.h, using defaults.\n"; } system("clear"); print "Welcome to Install for cfingerd 1.4.x.\n\n"; if ($ARGV[0] eq "-docs") { print "Force documentation install detected.\n\n"; } if ($ARGV[0] ne "-docs") { if (-e "Makefile") { if (-e $cfgpath) { print <<"EOT"; You already have a version of cfingerd.conf in the proper directory, which is where the normal configuration file is stored. If you like, install will create a new configuration file for you, and save the old cfingerd.conf file as \"cfingerd.conf-old\" in case you need it for reference. If you've previously had version 1.0.0 or below of cfingerd, this new cfingerd.conf file will be incompatible. EOT print "\nInstall new cfingerd.conf [Y]: "; $doinst = ; chop($doinst); $doinst =~ tr/a-z/A-Z/; if (($doinst eq "Y") || ($doinst eq "YE") || ($doinst eq "YES") || ($doinst eq "")) { system("mv $cfgpath $cfgpath-old"); system("cp -f cfingerd.conf $cfgpath"); print "\nOkay, it's been copied, and the old one was copied to \"cfingerd.conf.old\".\n"; } else { print "Skipped.\n"; } } else { print "Installing cfingerd.conf.\n"; system("cp -f cfingerd.conf $cfgpath"); } } else { print "You need to compile cfingerd first! Type \"Configure\" if you've not\n"; print "already done so, then switch to root, and type \"make install\".\n"; print "\nBesides, this script is automatically called from within the Makefile,\n"; print "so there's no need for you to type it in manually.\n\n"; exit; } system("rm -f /usr/man/man1/cfingerd.1"); system("rm -f /usr/man/man1/cfingerd.conf.1"); print "\nRemoved cfingerd and cfingerd.conf man pages from section 1 in case\n"; print "they existed on your system. (This may have been left over from an older\n"; print "version.) Old versions of cfingerd stored the manual pages in section 1.\n\n"; } if ((-e "/etc/cfingerd") && ($ARGV[0] ne "-docs")) { print "Skipping the creation of your /etc/cfingerd directory, since it already\n"; print "exists. If you want, copy everything out of the texts directory into\n"; print "the /etc/cfingerd root directory, and everything out of the scripts\n"; print "directory into the /etc/cfingerd/scripts directory.\n"; } else { print "Creating /etc/cfingerd directory...\n"; system("mkdir /etc/cfingerd"); system("chmod 700 /etc/cfingerd"); print "Copying over text files to the new directory...\n"; system("cp -f texts/* /etc/cfingerd"); print "Creating /etc/cfingerd/scripts directory...\n"; system("mkdir /etc/cfingerd/scripts"); system("chmod 700 /etc/cfingerd/scripts"); print "Copying over the new scripts...\n"; system("cp -f scripts/* /etc/cfingerd/scripts"); system("chmod 700 /etc/cfingerd/scripts/*"); } system("cp -f src/cfingerd /usr/sbin/in.cfingerd"); if ($ARGV[0] ne "-docs") { print "\nThat completes the installation. Check the \"INSTALL\" file for information\n"; print "on how to put cfingerd in your inetd.conf file. If it's already there, it\n"; print "should work fine. With that in mind, simply test it with a \"finger @\".\n"; print "\n"; print "Hit [RETURN]: "; ; print "\n"; } else { print "\nDocumentation installation complete.\n"; } cfingerd-1.4.3/Makefile0100644000076500001440000000055606613613757013657 0ustar joeyusers# Makefile for a totally clean installation all clean: @echo @echo "You need to type \"Configure\"." @echo @echo "Suggested reading:" @echo " FAQ - Gives some helpful information about CFINGERD" @echo " README - Gives information on how to install CFINGERD" @echo " RECOMMEND - Gives suggestions on what to do after CFINGERD is installed" @echo cfingerd-1.4.3/Makefile.cfg.in0100644000076500001440000000233706762622766015026 0ustar joeyusers# CFINGERD - Main Makefile configuration # # $Id: Makefile.cfg.in,v 1.4 1999/08/31 00:46:46 joey Exp $ # # Copyright (c) 1999 by Martin Schulze # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 1, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # Do not edit this file, it is controlled through ./Configure # Operating system # OS_TYPE = __OS_TYPE__ # Owner and group for installed binaries # BIN_OWNER = __BIN_OWNER__ BIN_GROUP = __BIN_GROUP__ export BIN_OWNER export BIN_GROUP # Root directory, owner and group for installed manpages # MANDIR = __MANDIR__ MAN_OWNER = __MAN_OWNER__ MAN_GROUP = __MAN_GROUP__ export MAN_OWNER export MAN_GROUP export MANDIR # Your make program # MAKE = __MAKE__ export MAKE # Additional compiler flags # CFLAGS = __CFLAGS__ export CFLAGS # Additional linker flags # LDFLAGS = __LDFLAGS__ export LDFLAGS cfingerd-1.4.3/Makefile.clean0100644000076500001440000000055606351232574014731 0ustar joeyusers# Makefile for a totally clean installation all clean: @echo @echo "You need to type \"Configure\"." @echo @echo "Suggested reading:" @echo " FAQ - Gives some helpful information about CFINGERD" @echo " README - Gives information on how to install CFINGERD" @echo " RECOMMEND - Gives suggestions on what to do after CFINGERD is installed" @echo cfingerd-1.4.3/Makefile.in0100644000076500001440000000210206762270710014242 0ustar joeyusers# CFINGERD by Ken Hollis # Released under the GPL include Makefile.cfg export CC ewps: @echo @echo "Options are:" @echo @echo "make clean - clean all remaining object/make files" @echo "make install - make and install cfingerd, userlist and docs" @echo "make instbin - make and only install the binaries" @echo "make instdocs - make and only install the documentation" @echo "make all - make cfingerd and userlist" @echo Makefile.cfg: ./Configure cfingerd: Makefile.cfg @echo @echo "Compiling cfingerd, one moment." @echo cd src ; $(MAKE) cfingerd userlist: Makefile.cfg userlist/userlist userlist/userlist: @echo @echo "Compiling userlist, one moment." @echo cd userlist ; $(MAKE) userlist clean: @echo @echo "Cleaning out directories..." @echo cd src ; $(MAKE) clean cd userlist ; $(MAKE) clean rm -f Makefile Makefile.cfg cp -p Makefile.clean Makefile install: instbin instdocs instbin: all ./Install cd userlist ; $(MAKE) install instdocs: ./Install -docs cd docs ; $(MAKE) install all: cfingerd userlist cfingerd-1.4.3/README0100644000076500001440000000512606747301205013063 0ustar joeyusersCFINGERD Release documents by Ken Hollis and others INSTALLATION GUIDE: """"""""""""""""""" *********************************************************************** *** PLEASE READ THE FAQ FILE COMPLETELY. UNANSWERED QUESTIONS MAY *** *** BE COVERED THERE, AND YOU MAY LEARN SOME INTERESTING NEW TIPS *** *********************************************************************** Type "./Configure". This will ask you a few questions on what setup your system has. You will be prompted a couple of questions. Simply answer them, and you should be set. (Any wrong data in the setup could lead to a strangely performing finger daemon.) Type "make all". This will start creating the new finger daemon for your system, and should compile through just fine. (Ignore any warnings if there are any on your system.) Become superuser. (This can be done by typing "su". :) Type "make install". This will install the package on your system using the information specified before. ************************************************************************ *** READ THIS NEXT SET OF LINES CAREFULLY! FAILURE TO ADD THIS LINE *** *** TO YOUR INETD.CONF FILE WILL NOT CHANGE YOUR CURRENT FINGER!!!!! *** ************************************************************************ Now, edit /etc/inetd.conf with your favorite text editor. You need to insert the following line: finger stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.cfingerd (The reason the configuration script does NOT do this is because many versions of inetd.conf can vary greatly.) If you wish to run cfingerd without any root priviledges, enter this one instead of the upper one: finger stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/in.cfingerd and look at README.noroot for some notes. Save your new inetd.conf file, and restart it. This can be accomplished by typing "killall -HUP inetd". Now, type "finger @localhost". This will spawn cfingerd through inetd as another user would see it from within your domain. To test what it would look like from another domain, simply telnet to another machine, and finger your system from that machine. After you've noted what you want changed, simply edit /etc/cfingerd.conf, or wherever you moved the file. Now, you can make the necessary modifications to the file as you need. If you wish to join the cfingerd mailing list, please write a message to majordomo@infodrom.north.de, with "subscribe cfingerd" in the message body body of your message. You will then be subscribed to the mailing list. cfingerd-1.4.3/README.noroot0100644000076500001440000000443006752661137014410 0ustar joeyusersRun from nobody and other security issues that came to my mind If you want run CFINGERD with no root priviledges at all (for security's sake - you are wise and do not trust programmers), you are free to do it. Just edit your inetd.conf and run it as nobody. finger stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/in.cfingerd Of course you should take care about a few more things. CFINGERD will need to read its config files. So you have to set their modes accordingly (i.e. world readable) Alternatively they could be owned by nobody, but no file should be owned by nobody). You will probably want to turn off some of ALLOW_USERLOG, ALLOW_FINGER_LOGGING, ONLY_CREATE_FINGERLOG_IF_FILE_EXISTS. Bear in mind that CFINGERD tries to write to several files if you leave something enabled. These files would need to be owned by nobody or be world writable. Both should be avoided. If CFINGERD runs as root all priviledges are droppped before displaying user files. if ALLOW_EXECUTION is set, programs called from user files are executed as that particular user, programs called from within system files are executed as user "nobody". files are parsed to be executed - as that user. In global files priviledges are also dropped before execution. If you don't like this and want some fancy headers with actual date and time and weather forecast for the day, you should set ALLOW_ROOT_EXEC. You still can use $time, $date, $ident etc. Just don't use external programs. If you are very picky about security and like "security through obscurity" you want to turn off ALLOW_CONFESSION. It might be more verbose than you want (you know, help@, version@ etc), imho, but it is still your choice. ALLOW_CONFESSION is enabled in the default cfingerd.conf. There were some "noroot" versions of CFINNGERD 1.3.2. The original noroot patch probably did nothing but changing comments and macro names, if you look at it. It run as nobody, though, so nothing more was needed. More "noroot" patches were part of Debian patch fighting the $exec design flaw - the first time CFINGERD thought it is putting back root privs, it really dropeed it away. This came with some flaws since more than nobody's privs are needed to read .cfingerrc files, assuming normal operations. Tadek Knapik and Joey cfingerd-1.4.3/RECOMMEND0100644000076500001440000000262306351024420013426 0ustar joeyusersCFINGERD Recommended setups After running cfingerd for quite a while, I have found that if you make the cfingerd setup the most secure, you will have the least problems. CFINGERD currently stops all files from being symbolic links, char devices, block devices, etc. Basically, each file has to be a normal file in order to be read by cfingerd. With that in mind, you should keep all files (whether or not they are read by root) as normal files. This will stop any problems in the future you may have. ROOT SHOULD ALWAYS HAVE A .nofinger FILE IN HIS/HER DIRECTORY! This is only natural, since most System Admins don't like to be fingered. IT IS HIGHLY RECOMMENDED that you install identd on your system. The installation process of identd is very painless and only takes minutes to accomplish. It's a great security program, and works very well. Install it. Besides, if you don't, RFC1413 compliance won't be present on your system if someone from localhost fingers your system. If you have multiple systems that you are running for ISP systems, it is recommended that you install cfingerd on all those systems, and put the resulting systems in the "system_list_sites" section of cfingerd.conf. This will make it so that you have a sorted output of systems when a user fingers your system. Don't use strange programs when getting a userlist output - it will only make the final output look strange. cfingerd-1.4.3/TODO0100644000076500001440000000165406753236340012701 0ustar joeyusersTodo (for next major release): . .cfingerrc files for individual users. . userlist-only routines use password-protected keys for multi-system fingers. (Perhaps even private key stuff) . Update RFC1413 routine to include "" if a connection was refused during ident, or "" if illegal data was received. (Or even make these configurable! :) . Add ability to handle multiple hosts in configuration. . Rewrite a non-pedantic type configuration reader... . Recursion checking in cfingerd "@" list requests. . Add ability to specify Mailbox instead of a defined one. . Check *all* occurrences of sscanf() against possible buffer overflows. This is a favourite problem when passing arguments to tons of routines for parsing and reacting. . Are 80 characters enough for a username? . Use correct CRLF for linefeeds. . Use autoconf . Error message for search should be configurable cfingerd-1.4.3/cfingerd.conf0100644000076500001440000001742606750257730014650 0ustar joeyusers############################################################################ ## ## Configurable Finger Daemon CONFIGURATION FILE version 1.50 ## by Ken Hollis (khollis@bitgate.com) ## Dated December 17, 1996 ## ## IMPORTANT NOTICE: DO NOT substitute spaces for tabs. You will corrupt ## cfingerd.conf, and will most likely cause a SIGSEGV. Only change the ## text of the option, DO NOT rewrite the option, or the name. ## ############################################################################ ## These are the files that are used in displaying specific finger-query ## information. These may be changed at the System Administrator's ## disgression only. FILES display_files = { PLAN = ".plan", PROJECT = ".project", PGP_KEY = ".pgpkey", XFACE = ".xface", NO_FINGER = ".nofinger", USERLOG = ".fingerlog", MAILBOX = "/usr/spool/mail/$USER", LOGFILE = "/var/log/cfingerd.log", HEADER_DISPLAY = "/etc/cfingerd/top_finger.txt", FOOTER_DISPLAY = "/etc/cfingerd/bottom_finger.txt", NO_NAME_BANNER = "/etc/cfingerd/noname_banner.txt", NO_USER_BANNER = "/etc/cfingerd/nouser_banner.txt", REJECTED_BANNER = "/etc/cfingerd/rejected_banner.txt" } ## These are the finger display options that are used for local, and remote ## hosts. The first option is for remote hosts, the second is for local. ## ## If "ALLOW_USER_OVERRIDE" is available, these are the only options that ## can be enabled/disabled on a per user basis. Options that a user may ## configure himself are prefixed with a plus `+' sign. CONFIG finger_display = { -HEADER_FILE = [TRUE, FALSE], -FOOTER_FILE = [TRUE, FALSE], +LOGIN_ID = [TRUE, TRUE], +REAL_NAME = [TRUE, TRUE], +DIRECTORY = [FALSE, TRUE], +SHELL = [FALSE, TRUE], +ROOM_NUMBER = [FALSE, TRUE], +WORK_NUMBER = [FALSE, TRUE], +HOME_NUMBER = [FALSE, TRUE], +OTHER = [FALSE, TRUE], +LAST_TIME_ON = [FALSE, TRUE], +IF_ONLINE = [FALSE, TRUE], +TIME_MAIL_READ = [FALSE, TRUE], +DAY_MAIL_READ = [FALSE, TRUE], +ORIGINATION = [FALSE, TRUE], +PLAN = [TRUE, TRUE], +PROJECT = [TRUE, TRUE], +PGP = [TRUE, TRUE], +XFACE = [TRUE, TRUE], -NO_NAME_BANNER = [TRUE, TRUE], -REJECTED_BANNER = [TRUE, TRUE], -SYSTEM_LIST = [FALSE, TRUE], -CLOCK24 = [FALSE, FALSE], -NO_USER = [TRUE, TRUE] } ## These are the internal configuration options that cfingerd uses to ## determine how to handle finger-queries. Note that each item that you ## want to enable or disable is used with a "+" to enable, and a "-" to ## disable. If you don't have the option listed, it is assumed to be ## enabled. CONFIG internal_config = { +ALLOW_MULTIPLE_FINGER_DISPLAY, +ALLOW_SEARCHABLE_FINGER, +ALLOW_NO_IP_MATCH_FINGER, +ALLOW_USER_OVERRIDE, +ALLOW_USERLIST_ONLY, -ALLOW_FINGER_FORWARDING, -ALLOW_STRICT_FORMATTING, -ALLOW_VERBOSE_TIMESTAMPING, +ALLOW_NONIDENT_ACCESS, +ALLOW_FINGER_LOGGING, +ALLOW_LINE_PARSING, +ALLOW_USERLOG, -ALLOW_EXECUTION, +ALLOW_FAKEUSER_FINGER, +ALLOW_CONFESSION, +ONLY_SHOW_HEADERS_IF_FILE_EXISTS, +ONLY_CREATE_FINGERLOG_IF_FILE_EXISTS } ## These are the sites that are queried for an entire listing when the ## user listing is requested. The sites listed below are fingered, and the ## entire listing is then sorted, and a final output is displayed. ## ## For the time being, if you want your site to display finger information ## in the userlisting, you *MUST* include the line below. This will soon ## (hopefully) change. CONFIG system_list_sites = { localhost } ## These are hosts that can finger your site and act as local-access hosts. ## In other words, these sites get the same displayed output that normal ## users on the localhost get. You can trust all sites by using a "*". HOSTS trusted = { } ## These are sites that are not allowed to finger your system, and they ## are displayed corresponding files. You can reject all systems using ## "*". HOSTS rejected = { } ## These are the forwarded hosts that are used when doing a finger-forward. ## This lets you forward a user to another system if the username could ## not be located on this system. HOSTS finger_forward = { } ## These are the strings that are displayed in the actual finger display. ## These strings get displayed in the correct positions based on what ## information you have allowed to be released. CONFIG finger_strings = { USER_NAME = "Username: ", REAL_NAME = "In real life: ", DIRECTORY = "Home directory: ", SHELL = "Shell: ", ROOM_NUMBER = "Room: ", WORK_NUMBER = "Work phone: ", HOME_NUMBER = "Home phone: ", OTHER = "Other: ", PLAN = "Plan:", PROJECT = "Project:", PGPKEY = "PGP Public Key:", NO_PLAN = "This user has no plan.", NO_PROJECT = "This user has no project.", NO_PGP = "This user has no PGP public key.", WAIT = "Gathering system data...", XFACE = "XFace:", NO_XFACE = "This user has no xface file." } ## These strings are displayed in syslogging. CONFIG internal_strings = { NO_IP_HOST = "IP: Hostname not matched", RENICE_FATAL = "Fatal - Nice died: ", STDIN_EMPTY = "STDIN contains no data", TRUSTED_HOST = "<- Trusted", REJECTED_HOST = "<- Rejected", ROOT_FINGER = "Root", SERVICE_FINGER = "Service listing", USER_LIST = "User listing", FAKE_USER = "Fake user", WHOIS_USER = "Whois request", FORWARD_DENY = "Finger forwarding service denied.", IDENT_CONREF = "", IDENT_ILLEGAL = "", IDENT_TIMEOUT = "" } ## These are the strings that you can change for display when a signal ## is encountered. Only these strings and associated signals are displayed ## or detected. If you don't know what you're doing, don't change these ## signal text displays. CONFIG signal_strings = { SIGHUP = "Hangup signal", SIGINT = "Keyboard interruption signal", SIGQUIT = "Keyboard quit signal", SIGILL = "Illegal instruction", SIGTRAP = "Trace/Breakpoint reached", SIGABRT = "Aborted", SIGFPE = "Floating Point Exception", SIGUSR1 = "User-defined", SIGSEGV = "Segmentation violation", SIGUSR2 = "User-defined", SIGPIPE = "Write to pipe w/o headers", SIGALRM = "Script or program timed out", SIGTERM = "Terminated", SIGCONT = "Continued from stopped job", SIGTSTP = "Stopped at TTY (Inetd-related?)", SIGTTIN = "TTY input from bgnd process (Inetd-related?)", SIGTTOU = "TTY output from bgnd process (Inetd-related?)", SIGIO = "I/O Error (on socket/non-socket)", SIGXCPU = "CPU Time limit exceeded", SIGXFSZ = "File size limit exceeded", SIGVTALRM = "Virtual timer alarm", SIGPROF = "Profiler", SIGWINCH = "VT/X Window size changed" } ## These are the programs that are called when a finger or whois command ## needs to be called. These are local programs, so they can be whatever ## you want. (Remember, this is a daemon, not a client.) FILES finger_programs = { FINGER = "/usr/sbin/userlist", WHOIS = "/usr/bin/whois" } ## These are the users that don't exist on your system, but can be called ## on as scripts. Read over cfingerd.conf(5) for more details on these ## options. '-' can be prepended to avoid displaying on the service list. FILES finger_fakeusers = { # "uptime", "System Uptime", FALSE, "/etc/cfingerd/scripts/uptime", # "test", "Test Script", TRUE, "/etc/cfingerd/scripts/test", # "trace", "Trace route", TRUE, "/etc/cfingerd/scripts/trace" } ## THIS PART OF THE CONFIGURATION FILE IS OPTIONAL! YOU DO NOT HAVE TO ## CHANGE ANYTHING BELOW THIS LINE UNLESS YOU WANT TO CHANGE THE FORMAT ## OF THE SERVICES LISTING. SEE DOCS FOR MORE DETAILS! ## This is the header that is displayed at the top of your services display. CONFIG services_header = { *** Services provided by this system *** User: Service name: Searchable: -------- -------------------- ----------- %-8s %-20s %-s } ## These are the positions of the actual items in the header. CONFIG services_positions = { USER = 1, SERVICE = 2, SEARCH = 3 } cfingerd-1.4.3/config/0040755000076500001440000000000006774336471013464 5ustar joeyuserscfingerd-1.4.3/config/cancelled0100644000076500001440000000023506351024422015273 0ustar joeyusers ------------------------------------------------------------------------------- *** Operation cancelled. Type "make clean" or "Configure" to start again. cfingerd-1.4.3/config/footer0100644000076500001440000000053506762270711014674 0ustar joeyusers ------------------------------------------------------------------------------- *** Configuration completed. If you need to please, edit "src/config.h" and *** "Makefile.cfg" to check for any changes you may need to make manually. *** If no changes need to be made, please type "make all" and "make install". *** DON'T FORGET TO READ THE FAQ!!! cfingerd-1.4.3/config/header0100644000076500001440000000152606764317635014640 0ustar joeyusers #### ###### ###### ## ## #### ###### ##### ##### ## ## ## ## ### ## ## ## ## ## ## ## ## #### ## ###### ## ### #### ##### ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## #### ## ###### ## ## #### ###### ## ## ##### 1.4.2 +- Configurable Finger Daemon Installation Script -+ -- HIT [RETURN] ON ANY ITEMS YOU WISH TO KEEP THE SAME -- ------------------------------------------------------------------------------- *** If any part of this script doesn't work, please try to make the changes *** yourself. If you can't make the changes, please send an e-mail to *** cfingerd@infodrom.north.de for any problems you encounter. ------------------------------------------------------------------------------- cfingerd-1.4.3/config/makewarn0100644000076500001440000000052106351024422015164 0ustar joeyusers You already have a previously created Makefile, meaning you have run this configuration script once before. If you want to go ahead and re-run the configuration script, simply reply with "Y" to continue and re-make the makefile. Otherwise, reply with "N" and type "make clean" manually before running the Configuration script again. cfingerd-1.4.3/perl/0040755000076500001440000000000006774336472013162 5ustar joeyuserscfingerd-1.4.3/perl/README0100644000076500001440000000027606351024422014020 0ustar joeyusersThese are the supporting functions for the Configuration script. If you want to make any changes to these scripts, please E-Mail the patches or new pieces of code to khollis@bitgate.com. cfingerd-1.4.3/perl/filemagic.pl0100644000076500001440000000130706351024422015411 0ustar joeyusers## File Magic Parser ## by Ken Hollis ## ## This program is GPLed. Please read the LICENSE file for more information. ## Copyright (C) 1996, Bitgate Software. sub check_exist { local($type, $filename, $checkfor, $cfile) = @_; if ($type eq "2") { if (-e $filename) { return 1; } else { return 0; } } if ($type eq "1") { if (-e $filename) { $clean = 0; open(IF, $filename); while() { chop; if (/$checkfor/) { $clean = 1; last; } } close(IF); if (!$clean) { &disp_file($cfile); return &ask_question("Go ahead?", "N", BOOLEAN_QUESTION, $cfile); } else { return "Y"; } } else { return "0"; } } } 1; cfingerd-1.4.3/perl/generic.pl0100644000076500001440000000373006762622766015134 0ustar joeyusers## Generic/Standard routines ## by Ken Hollis ## ## This program is GPLed. Please read "LICENSE" for more information. ## Copyright (C) 1996, Bitgate Software. sub get_os { local ($uname); local ($ver); print "Operating system ... "; $uname = `uname`; chop($uname); $uname =~ tr/a-z/A-Z/; $ver = `uname -r`; chop($ver); print "$uname\n"; return ($uname,$ver); } sub get_lastlog { my $ll = shift; print "Lastlog ... "; if (!$ll) { if (-e "/var/log/lastlog") { $ll = "/var/log/lastlog"; } elsif (-e "/var/adm/lastlog") { $ll = "/var/adm/lastlog"; } else { $ll = "/var/adm/wtmp"; } } print "$ll\n"; return $ll; } sub get_nobody { my $uid = shift; my $gid = shift; my @foo; print "Nobody UID/GID ... "; if (($uid eq "") || ($gid eq "")) { if (open (PW, "/etc/passwd")) { while () { next unless (/^nobody:/); @foo = split (/:/); $uid = $foo[2] if (!$uid); $gid = $foo[3] if (!$gid); } close (PW); } } if (($uid eq "") || ($gid eq "")) { $uid = 65535; $gid = 65535; } print "$uid, $gid\n"; return "$uid,$gid"; } sub has_shadow { local($shad); print "Shadow passwords ... "; if (-e "/etc/shadow") { $shad = "Y"; } else { $shad = "N"; } print (($shad eq "Y") ? "/etc/shadow\n" : "No shadow\n"); return $shad; } sub get_mailspool { my $spool = shift; print "Mail spool directory ... "; if (!$spool) { if (-d "/var/spool/mail") { $spool = "/var/spool/mail"; } elsif (-d "/var/mail") { $spool = "/var/mail"; } else { print "Not found. Assuming "; $spool = "/var/spool/mail"; } } print "$spool\n"; return $spool; } sub get_mandir { my $dir = shift; print "Manpages root directory ... "; if (!$dir) { if (-d "/usr/share/man") { $dir = "/usr/share/man"; } elsif (-d "/usr/man") { $dir = "/usr/man"; } else { print "Not found. Assuming "; $dir = "/usr/man"; } } print "$dir\n"; return $dir; } 1; cfingerd-1.4.3/perl/gethost.pl0100644000076500001440000000125506351024422015150 0ustar joeyusers## Get Fully Qualified Domain Name ## by Ken Hollis ## ## This program is GPLed. Please read the LICENSE file for more information. ## Copyright (C) 1996, Bitgate Software. sub get_fqdn { local($question, $config) = @_; &disp_file($config); local($hostname) = `hostname`; chop($hostname); local($domainname) = `domainname`; chop($domainname); if (($hostname ne "(none)") && ($domainname ne "(none)")) { local($fqdn) = $hostname . "." . $domainname; } elsif ($hostname eq "(none)") { local($fqdn) = $domainname; } elsif ($domainname eq "(none)") { local($fqdn) = $hostname; } $fqdn = &ask_question($question, $fqdn, STRING_QUESTION); } 1; cfingerd-1.4.3/perl/question.pl0100644000076500001440000000224706351024422015344 0ustar joeyusers## Ask question script ## by Ken Hollis ## ## This has been tested in JigModIRC2.8.21, and XIRC. It also includes ## a routine to display text files. ## ## This program is GPLed. Please read LICENSE for more information. ## Copyright (C) 1996, Bitgate Software. ## ## Directions for inclusion: ## Include "require 'question.pl'" in your Perl program, and call ## ask_question to ask your question. sub ask_question { local($question, $value, $type, $cfile) = @_; repeat_ask: print "$question "; if ($type eq "1") { $value =~ tr/a-z/A-Z/; print (($value eq "Y") ? "[Y/n/?] " : "[y/N/?] "); } elsif ($type eq "2") { print "[$value] "; } elsif ($type eq "3") { print "$value "; } $entry = ; chop($entry); if ($type eq "1") { $entry =~ tr/a-z/A-Z/; if ($entry eq "") { $entry = $value; } elsif ($entry eq "Y") { $entry = "Y"; } elsif ($entry eq "N") { $entry = "N"; } else { &disp_file($cfile); goto repeat_ask; } } elsif (($type eq "2") || ($type eq "3")) { if ($entry eq "") { $entry = $value; } } return $entry; } sub disp_file { open(FL, "$_[0]") || die "$_[0]: $!\n"; print $_ while (); } 1; cfingerd-1.4.3/scripts/0040755000076500001440000000000006774336472013707 5ustar joeyuserscfingerd-1.4.3/scripts/test0100755000076500001440000000046406351024420014567 0ustar joeyusers#!/bin/sh # # Test script for CFINGERD # Version 1.1 by Ken Hollis echo Test script for `uname -n` echo echo Your options that were passed are: echo $1 echo $2 echo $3 echo $4 echo echo "Thank you for using `uname -n`'s finger system!" echo "Have a nice day .. or something. :)" echo cfingerd-1.4.3/scripts/trace0100755000076500001440000000157606513623621014723 0ustar joeyusers#!/usr/bin/perl # # Nice little script to do a traceroute to someone else's site... # Version 1.0.1 by Ken Hollis (khollis@bitgate.com) # Turn non-buffered input/output on $| = 1; # Get our site that we want a traceroute to be performed for $tracesite = $ARGV[0]; $tracesite =~ tr/,/./; # Set maximum timeout duration (default is 3) $wait_time = "-w 3"; # Set maximum number of hops per traceroute request (default is 30) $max_hops = "-m 30"; # And check to make sure they entered a site if ($tracesite) { print "Performing a traceroute to $tracesite ... \n\n"; system("/usr/sbin/traceroute $wait_time $max_hops $tracesite"); print "\nDone.\n"; } else { print <<"EOT"; Traceroute script 0.0.1 by Ken Hollis Please finger \"site.whatever\" with your \".\" marks converted to \",\" marks instead. This is because the finger daemon separates all options by a \".\". EOT } cfingerd-1.4.3/scripts/uptime0100755000076500001440000000020106351024420015100 0ustar joeyusers#!/bin/sh # # Uptime script # version 1.1 by Ken Hollis echo "System statistical information:" echo uptime echo -n " " uname -a cfingerd-1.4.3/src/0040755000076500001440000000000006774336472013007 5ustar joeyuserscfingerd-1.4.3/src/Makefile0100644000076500001440000000072306762270720014434 0ustar joeyusers# CFINGERD by Ken Hollis # # Released under the GPL include ../Makefile.cfg OBJS = main.o options.o version.o util.o errors.o strmcpy.o \ parse.o configure.o internal.o signal.o standard.o \ userlist.o fakeuser.o search.o getutent.o rfc1413.o \ wildmat.o log.o cfingerd: $(OBJS) $(CC) -o $@ $^ $(LDFLAGS) install: cfingerd install -m 755 -o $(BIN_OWNER) -g $(BIN_GROUP) -s cfingerd /usr/sbin/cfingerd clean: rm -f *.o cfingerd rm -f config.h cfingerd-1.4.3/src/cfingerd.h0100644000076500001440000003054006762173065014732 0ustar joeyusers/* * CFINGERD - Configurable Finger-Query Daemon * Header File * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _CFINGERD_H_ #define _CFINGERD_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #ifdef SUNOS #include #include #define utmp utmpx #define ut_time ut_xtime #define getutent getutxent #define _PATH_UTMP UTMPX_FILE #if (SUNOS == 55) #define snprintf __snprintf #endif #else #include #endif #if !defined(UT_USERSIZE) || !defined(UT_HOSTSIZE) || !defined(UT_LINESIZE) || !defined(UT_NAMESIZE) struct utmp foo_utmp; #endif #ifndef UT_USERSIZE #define UT_USERSIZE sizeof(foo_utmp.ut_name) #endif #ifndef UT_HOSTSIZE #define UT_HOSTSIZE sizeof(foo_utmp.ut_host) #endif #ifndef UT_LINESIZE #define UT_LINESIZE sizeof(foo_utmp.ut_line) #endif #ifndef UT_NAMESIZE #define UT_NAMESIZE sizeof(foo_utmp.ut_user) #endif #define BOOL int #define TRUE 1 #define FALSE 0 #define MAX_POPEN_BUF 10 * 1024 * 1024 /* max. 10 MB buffer */ /* First configuration option bit pair */ #define SHOW_SYSLOG 0x0001 /* Log all errors to the syslog daemon */ #define SHOW_TOP 0x0002 /* Show the top file on a finger req. */ #define SHOW_BOTTOM 0x0004 /* Show the bottom file on a finger req.*/ #define SHOW_UNAME 0x0008 /* Show the user's login name */ #define SHOW_REALNAME 0x0010 /* Show the user's real name */ #define SHOW_DIR 0x0020 /* Show the user's home directory */ #define SHOW_SHELL 0x0040 /* Show the user's shell program */ #define SHOW_ROOM 0x0080 /* Show the user's room number */ #define SHOW_WPHONE 0x0100 /* Show the user's work phone number */ #define SHOW_HPHONE 0x0200 /* Show the user's home phone number */ #define SHOW_OTHER 0x0400 /* Show the user's other information */ #define SHOW_LTON 0x0800 /* Show the last time this user was on */ #define SHOW_IFON 0x1000 /* Show if this user is currently on */ #define SHOW_LRMAIL 0x2000 /* Show the last time mail was read */ #define SHOW_MRDATE 0x4000 /* Show the last day that mail was read */ #define SHOW_FROM 0x8000 /* Show where the last login originated */ /* Second configuration option bit pair */ #define SHOW_PLAN 0x0001 /* Show the user's plan file */ #define SHOW_PROJECT 0x0002 /* Show the user's project file */ #define SHOW_PGPKEY 0x0004 /* Show the user's PGP key file */ #define SHOW_NN_BANNER 0x0008 /* Show banner if no name specified */ #define SHOW_REJECTED 0x0010 /* Show the rejected file if wanted */ #define SHOW_SYSTEMLIST 0x0020 /* Show the user listing if wanted */ #define SHOW_IP_MATCH 0x0040 /* Show if Hostname not found from IP */ #define SHOW_NOUSER 0x0080 /* Show no-user matched banner */ #define SHOW_MULTFING 0x0100 /* Allow for multiple finger displays */ #define SHOW_SEARCHFING 0x0200 /* Allow for searchable finger queries */ #define SHOW_OVERRIDE 0x0400 /* Allow for user-overridable options */ #define SHOW_STRICTFMT 0x0800 /* Allow for strict formatting output */ #define SHOW_TIMESTAMP 0x1000 /* Allow for verbose timestamps */ #define SHOW_FINGERFWD 0x2000 /* Allow for forwardable fingers */ #define SHOW_ULISTONLY 0x4000 /* Allow for "userlist-only" fingers */ #define SHOW_NOBODY1413 0x8000 /* Allow for non-ident users to finger */ /* Third row of configuration bits -- ALWAYS room for improvement */ #define SHOW_LOG 0x0001 /* Allow for logging of all fingers */ #define SHOW_PARSING 0x0002 /* Allow for text line data parsing */ #define SHOW_USERLOG 0x0004 /* Allow for userlogging of all fingers */ #define SHOW_EXEC 0x0008 /* Allow for users to execute programs */ #define SHOW_FAKEUSER 0x0010 /* Allow fakeusers to be fingered */ #define SHOW_XFACE 0x0020 /* Allow display of xface files */ #define SHOW_HEADERS_FE 0x0040 /* Show headers if file exists */ #define SHOW_CREATE_FLG 0x0080 /* Create fingerlog file if file exists */ #define SHOW_CLOCK24 0x0100 /* Show time in clock 24 format */ #define SHOW_CONFESSION 0x0200 /* */ /* Program exit states */ #define PROGRAM_OKAY 0 /* Program exited fine */ #define PROGRAM_SYSLOG 1 /* Program exited after a syslog report */ #define PROGRAM_BUG 2 /* Program exited because of a bug */ /* Display strings (This could increase shortly) */ #define D_USERNAME 0 /* Username string */ #define D_REALNAME 1 /* Realname string */ #define D_DIRECTORY 2 /* Directory string */ #define D_SHELL 3 /* Shell string */ #define D_ROOM 4 /* Room number string */ #define D_WORK_PHONE 5 /* Work phone number string */ #define D_HOME_PHONE 6 /* Home phone number string */ #define D_OTHER 7 /* Other string */ #define D_IP_NO_MATCH 8 /* No hostname matches IP string */ #define D_NICE_FATAL 9 /* Nice-routine fatality string */ #define D_STDIN_EMPTY 10 /* STDIN empty string */ #define D_TRUST_HOST 11 /* Trusted host display string */ #define D_REJECT_HOST 12 /* Rejected host display string */ #define D_ROOT_FINGER 13 /* Root finger display string */ #define D_SVC_FINGER 14 /* Service finger display string */ #define D_ULIST_FINGER 15 /* Userlist finger display string */ #define D_FAKE_USER 16 /* Fake user display string */ #define D_WHOIS_USER 17 /* Whois user display string */ #define D_PLAN 18 /* Plan display string */ #define D_PROJECT 19 /* Project display string */ #define D_PGPKEY 20 /* PGP key display string */ #define D_NO_PLAN 21 /* No plan file display string */ #define D_NO_PROJECT 22 /* No project file display string */ #define D_NO_PGPKEY 23 /* No PGP key display string */ #define D_WAIT 24 /* "Wait while I do something" string */ #define D_XFACE 25 /* XFace display string */ #define D_NO_XFACE 26 /* No XFace file display string */ #define D_FORWARD_DENY 27 /* No Forwarding string */ #define D_IDENT_CONREF 28 /* Connection refused for RFC1413 report*/ #define D_IDENT_ILLEGAL 29 /* Illegal data in RFC1413 report */ #define D_IDENT_TIMEOUT 30 /* RFC1413 report timed out */ /* General program errors */ #define E_STANDALONE 1 /* Cannot run in standalone mode */ #define E_NONROOT 2 /* Must be root to run */ #define E_INETD 3 /* Must be run in inetd */ #define E_CONFIG 4 /* Configuration file error */ #define E_SIGSEGV 5 /* SIGSEGV detected */ #define E_SUIDROOT 6 /* Cannot be suid root */ #define E_COMMANDLINE 7 /* Wrong number of command line options */ #define E_FINGEROFF 8 /* Turn off all incoming fingers */ #define E_WILDCARD 9 /* Wildcard settings contradict */ #define E_SEARCH 10 /* Search settings turned off */ #define E_NOIP 11 /* No DNS entry found for IP address */ /* Processed username return values */ #define U_ILLEGAL -1 /* Illegal username was encountered */ #define U_STANDARD 1 /* User is not fake and not internal */ #define U_FAKEUSER 2 /* User is a fake user (user-defined) */ #define U_INTERNAL 3 /* User is an internal-defined username */ #define U_USERLIST 4 /* User is requesting a userlist */ #define U_FORWARD 8 /* User is a forward request */ /* Standard signals for use within the program */ #define S_SIGHUP 1 /* Hangup signal */ #define S_SIGINT 2 /* Interruption signal */ #define S_SIGQUIT 3 /* Quit signal */ #define S_SIGILL 4 /* Illegal exception signal */ #define S_SIGTRAP 5 /* Trap/Breakpoint signal */ #define S_SIGABRT 6 /* Abort signal */ #define S_SIGFPE 7 /* Floating point exception signal */ #define S_SIGUSR1 8 /* User defined signal #1 */ #define S_SIGSEGV 9 /* Segmentation violation signal */ #define S_SIGUSR2 10 /* User defined signal #2 */ #define S_SIGPIPE 11 /* Broken pipe signal */ #define S_SIGALRM 12 /* Alarm timeout signal */ #define S_SIGTERM 13 /* Termination signal */ #define S_SIGCONT 14 /* Continue signal */ #define S_SIGTSTP 15 /* TTY Stopped signal */ #define S_SIGTTIN 16 /* TTY Input stopped signal */ #define S_SIGTTOU 17 /* TTY Output stopped signal */ #define S_SIGIO 18 /* Input/output stopped signal */ #define S_SIGXCPU 19 /* CPU Exception signal */ #define S_SIGXFSZ 20 /* Exceeded file size signal */ #define S_SIGVTALRM 21 /* Virtual Alarm signal */ #define S_SIGPROF 22 /* Prof (??) signal */ #define S_SIGWINCH 23 /* Window size change signal */ /* This was defined in syslog ... I'm using it for my own use. */ #undef LOG_USER /* Logging defines */ #define LOG_IDENT 1 #define LOG_REJECTED 2 #define LOG_WARN 3 #define LOG_USER 4 #define LOG_ERROR 5 typedef struct { char *user; /* Fake username */ char *script; /* Fake user's corresponding script */ char *description; /* Script description */ BOOL searchable; /* Searchable boolean ... are we searchable? */ } FAKEUSERS; typedef struct { char *header[20]; /* Five headers for the top display */ char *display_string; /* Display string in printf format */ int name_pos; /* Position in the string to display name */ int service_pos; /* Position in the string to display service */ int search_pos; /* Position in the string to display search */ } SERVICES; typedef struct { char *top_display_file; /* Displayed at the top of the listing */ char *bottom_display_file; /* Displayed at the close of the listing */ char *plan_file; /* The generic plan file to use */ char *project_file; /* The generic project file to use */ char *pgpkey_file; /* The generic PGP file to use */ char *xface_file; /* The generic XFACE file to use */ char *log_file; /* The generic log file to use */ char *userlog_file; /* The generic user log file to use */ char *mailbox_file; /* The mail box that is used for checking */ char *no_name_banner_file; /* Banner file used if no name specified */ char *no_user_banner_file; /* Banner file used if no user is matched */ char *no_finger_file; /* File used if no finger is wanted */ char *identd_banner_file; /* Banner file used if identd is unknown */ char *rejected_file; /* Rejected host text file display */ char *syslog_file; /* Syslog output file */ char *finger_program; /* Program to run when no name is queried */ char *whois_program; /* Program to run when /W name is queried */ char *rejected[80]; /* Rejected hosts */ char *trusted[80]; /* Trusted hosts */ char *forward[80]; /* Forwarded hosts */ char *p_strings[80]; /* Program-related context print strings */ char *finger_sites[80]; /* Finger sites that are queried */ char *siglist[24]; /* Signal names and their errors */ char stime_format[25]; /* Short time format string */ char ltime_format[25]; /* Long time format string */ FAKEUSERS fusers[40]; /* Fake user name listings */ SERVICES services; /* Services configuration display */ int config_bits1; /* First row of configuration bits */ int config_bits2; /* Second row of configuration bits */ int config_bits3; /* Third row of configuration bits */ int local_config_bits1; /* Local first row of config bits */ int local_config_bits2; /* Local second row of config bits */ int local_config_bits3; /* Local third row of config bits */ int override_bits1; /* Configuration bits pair #1 */ int override_bits2; /* Configuration bits pair #2 */ int override_bits3; /* Configuration bits pair #3 */ } CONFIG; typedef struct ecruft { char *error; /* Error text */ int dummy; /* Some dummy cruft to make it all work */ } ECRUFT; extern CONFIG prog_config; extern ECRUFT errors[]; extern char *remote_addr, *localhost, *ident_user, *ip_address; extern int trusted_host_num, rejected_host_num, forward_host_num, fakeuser_num, num_finger_sites, num_headers, local_port, remote_port, can_log; extern FILE *top_display, *bottom_display, *noname_display, *nouser_display, *rejected_display, *identd_display; extern BOOL local_finger, emulated; extern FILE *logfile; #ifdef DAEMON_MODE extern unsigned short listen_port; extern unsigned long listen_addr; #endif #include "defines.h" #endif _CFINGERD_H_ cfingerd-1.4.3/src/config.h.in0100644000076500001440000000604706754553437015036 0ustar joeyusers/* * CFINGERD * Configuration file * * Make any modifications you need to this file. You may change any of the * options in this file. If you're unsure about one of the options, simply * leave it as the standard that is already there. It will save you lots * of headache in the long run. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ /*****************************************************************************/ /* * CFINGERD_CONF * * This is the name of your cfingerd configuration file. */ @CFINGERD_CONF@ /* * USER_CONF * * These are the names of the files that users have access to in order to * turn on or off options that they don't want displayable in their finger * queries. */ #define USER_CONF ".cfingerrc" /* * MAIL_SPOOL_DIR * * This is the mail spooling directory. This is the place where all of * the users' mail is housed. */ @MAIL_SPOOL_DIR@ /* * NOBODY_UID * * This is the value of the nobody user ID on your system. It is not * recommended that you change this, as it is configured at make time. */ @NOBODY_UID@ /* * NOBODY_GID * * Same as the above, only for the group ID. */ @NOBODY_GID@ /* * COMPILE_DT * * This is the compilation date and time. Please don't mess with this, * as this should remain internal. */ @COMPILE_DT@ /* * WTMPFILE * * This is the file that is used to find out when the last time a user * has logged in. If "wtmp" is used here, it can make cfingerd a little * slower if you have a large wtmp file. If "lastlog" is used, it speeds * up performance dramatically. But, not every system has "lastlog". */ @WTMPFILE@ /* * USE_LASTLOG * * This variable tells cfingerd that we are using lastlog, and since lastlog * has a different format than wtmp does, it requires different code. */ @USE_LASTLOG@ /* * HAS_SHADOW * * If you have shadow passwords compiled into your system, lastlog format will * have changed by 4 bytes. (Why, I have no idea.) This is here for * shadow password compatibility. */ @HAS_SHADOW@ /* * HAS_TTY_GROUP * * On modern systems the used tty's (/dev/tty*) doesn't need to be world * writable anymore to allow to write(1) to it. To be honest it is a * security hole if the tty is world writable. On newer systems the tty's * are owned by group tty which is allowed to write to it if mesg is set * to y. This define ensures that it will be detected properly. */ @HAS_TTY_GROUP@ /* * DAEMON_MODE * * This adds experimental support to run cfingerd as standalone * daemon. It will bind to the finger/tcp port on any IP address. * Start with `-d' to make cfingerd run as daemon. */ /* #define DAEMON_MODE 1 */ cfingerd-1.4.3/src/configure.c0100644000076500001440000005142306754553451015132 0ustar joeyusers/* * CFINGERD * Configuration script * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #include "privs.h" /* These are defines for the less than perfect configuration script parser */ #define DISPLAY_FILES 1 #define FINGER_PROGRAMS 2 #define FINGER_FAKEUSERS 3 /* Hosts */ #define TRUSTED 1 #define REJECTED 2 #define FORWARD 3 #define FINGER_DISPLAY 1 #define INTERNAL_CONFIG 2 #define SYSTEM_LIST_SITES 3 #define FINGER_STRINGS 4 #define INTERNAL_STRINGS 5 #define SERVICES_HEADER 6 #define SERVICES_POSITIONS 7 #define SIGNAL_STRINGS 8 typedef struct { char *item; int value, section; } TYPEVAL; TYPEVAL finger_display[] = { { "HEADER_FILE", SHOW_TOP, 1 }, { "FOOTER_FILE", SHOW_BOTTOM, 1 }, { "LOGIN_ID", SHOW_UNAME, 1 }, { "REAL_NAME", SHOW_REALNAME, 1 }, { "DIRECTORY", SHOW_DIR, 1 }, { "SHELL", SHOW_SHELL, 1 }, { "ROOM_NUMBER", SHOW_ROOM, 1 }, { "WORK_NUMBER", SHOW_WPHONE, 1 }, { "HOME_NUMBER", SHOW_HPHONE, 1 }, { "OTHER", SHOW_OTHER, 1 }, { "LAST_TIME_ON", SHOW_LTON, 1 }, { "IF_ONLINE", SHOW_IFON, 1 }, { "TIME_MAIL_READ", SHOW_LRMAIL, 1 }, { "DAY_MAIL_READ", SHOW_MRDATE, 1 }, { "ORIGINATION", SHOW_FROM, 1 }, { "PLAN", SHOW_PLAN, 2 }, { "PROJECT", SHOW_PROJECT, 2 }, { "PGP", SHOW_PGPKEY, 2 }, { "NO_NAME_BANNER", SHOW_NN_BANNER, 2 }, { "REJECTED_BANNER", SHOW_REJECTED, 2 }, { "SYSTEM_LIST", SHOW_SYSTEMLIST, 2 }, { "NO_USER", SHOW_NOUSER, 2 }, { "CLOCK24", SHOW_CLOCK24, 3}, { "XFACE", SHOW_XFACE, 3 }, { NULL, 0, 0 } }; TYPEVAL internal_config[] = { { "ALLOW_MULTIPLE_FINGER_DISPLAY", SHOW_MULTFING, 2 }, { "ALLOW_SEARCHABLE_FINGER", SHOW_SEARCHFING, 2 }, { "ALLOW_NO_IP_MATCH_FINGER", SHOW_IP_MATCH, 2 }, { "ALLOW_USER_OVERRIDE", SHOW_OVERRIDE, 2 }, { "ALLOW_STRICT_FORMATTING", SHOW_STRICTFMT, 2 }, { "ALLOW_VERBOSE_TIMESTAMPING", SHOW_TIMESTAMP, 2 }, { "ALLOW_FINGER_FORWARDING", SHOW_FINGERFWD, 2 }, { "ALLOW_USERLIST_ONLY", SHOW_ULISTONLY, 2 }, { "ALLOW_NONIDENT_ACCESS", SHOW_NOBODY1413, 2 }, { "ALLOW_FINGER_LOGGING", SHOW_LOG, 3 }, { "ALLOW_LINE_PARSING", SHOW_PARSING, 3 }, { "ALLOW_USERLOG", SHOW_USERLOG, 3 }, { "ALLOW_EXECUTION", SHOW_EXEC, 3 }, { "ALLOW_FAKEUSER_FINGER", SHOW_FAKEUSER, 3 }, { "ALLOW_CONFESSION", SHOW_CONFESSION, 3 }, { "ONLY_SHOW_HEADERS_IF_FILE_EXISTS", SHOW_HEADERS_FE, 3 }, { "ONLY_CREATE_FINGERLOG_IF_FILE_EXISTS", SHOW_CREATE_FLG, 3 }, { NULL, 0, 0 } }; TYPEVAL finger_strings[] = { { "USER_NAME", D_USERNAME, 0 }, { "REAL_NAME", D_REALNAME, 0 }, { "DIRECTORY", D_DIRECTORY, 0 }, { "SHELL", D_SHELL, 0 }, { "ROOM_NUMBER", D_ROOM, 0 }, { "WORK_NUMBER", D_WORK_PHONE, 0 }, { "HOME_NUMBER", D_HOME_PHONE, 0 }, { "OTHER", D_OTHER, 0 }, { "PLAN", D_PLAN, 0 }, { "PROJECT", D_PROJECT, 0 }, { "NO_PLAN", D_NO_PLAN, 0 }, { "NO_PROJECT", D_NO_PROJECT, 0 }, { "NO_PGP", D_NO_PGPKEY, 0 }, { "PGPKEY", D_PGPKEY, 0 }, { "WAIT", D_WAIT, 0 }, { "XFACE", D_XFACE, 0 }, { "NO_XFACE", D_NO_XFACE, 0 }, { NULL, 0, 0 } }; TYPEVAL internal_strings[] = { { "NO_IP_HOST", D_IP_NO_MATCH, 0 }, { "RENICE_FATAL", D_NICE_FATAL, 0 }, { "STDIN_EMPTY", D_STDIN_EMPTY, 0 }, { "TRUSTED_HOST", D_TRUST_HOST, 0 }, { "REJECTED_HOST", D_REJECT_HOST, 0 }, { "ROOT_FINGER", D_ROOT_FINGER, 0 }, { "SERVICE_FINGER", D_SVC_FINGER, 0 }, { "USER_LIST", D_ULIST_FINGER, 0 }, { "FAKE_USER", D_FAKE_USER, 0 }, { "WHOIS_USER", D_WHOIS_USER, 0 }, { "FORWARD_DENY", D_FORWARD_DENY, 0 }, { "IDENT_CONREF", D_IDENT_CONREF, 0 }, { "IDENT_ILLEGAL", D_IDENT_ILLEGAL, 0 }, { "IDENT_TIMEOUT", D_IDENT_TIMEOUT, 0 }, { NULL, 0, 0 } }; TYPEVAL signal_strings[] = { { "SIGHUP", S_SIGHUP, 0 }, { "SIGINT", S_SIGINT, 0 }, { "SIGQUIT", S_SIGQUIT, 0 }, { "SIGILL", S_SIGILL, 0 }, { "SIGTRAP", S_SIGTRAP, 0 }, { "SIGABRT", S_SIGABRT, 0 }, { "SIGFPE", S_SIGFPE, 0 }, { "SIGUSR1", S_SIGUSR1, 0 }, { "SIGSEGV", S_SIGSEGV, 0 }, { "SIGUSR2", S_SIGUSR2, 0 }, { "SIGPIPE", S_SIGPIPE, 0 }, { "SIGALRM", S_SIGALRM, 0 }, { "SIGTERM", S_SIGTERM, 0 }, { "SIGCONT", S_SIGCONT, 0 }, { "SIGTSTP", S_SIGTSTP, 0 }, { "SIGTTIN", S_SIGTTIN, 0 }, { "SIGTTOU", S_SIGTTOU, 0 }, { "SIGIO", S_SIGIO, 0 }, { "SIGXCPU", S_SIGXCPU, 0 }, { "SIGXFSZ", S_SIGXFSZ, 0 }, { "SIGVTALRM", S_SIGVTALRM, 0 }, { "SIGPROF", S_SIGPROF, 0 }, { "SIGWINCH", S_SIGWINCH, 0 }, { NULL, 0, 0 } }; int trusted_host_num; int rejected_host_num; int forward_host_num; int fakeuser_num; int num_finger_sites; int num_headers, can_log; FILE *file, *logfile; /* * DO_FILES * * This routine simply takes the parsed string, and handles all filenames, * putting them into the correct place in the files structure. */ void do_files(char *str) { char *line; int done = 0, type = 0, errors = 0; line = (char *) malloc(80); sscanf(str, "FILES %[^ =] = {\r\n", line); if (!(strncasecmp(line, "display_files", 13))) type = DISPLAY_FILES; else if (!(strncasecmp(line, "finger_programs", 15))) type = FINGER_PROGRAMS; else if (!(strncasecmp(line, "finger_fakeusers", 16))) type = FINGER_FAKEUSERS; free(line); while(!done) { line = (char *) malloc(80); fscanf(file, "%[^\r\n]\r\n", line); if (!(strncmp(line, "}", 1))) done++; else if (line[0] != '#') { if (type == DISPLAY_FILES) { char *element, *filename; element = (char *) malloc(80); filename = (char *) malloc(80); sscanf(line, "\t%[^\t]\t= \"%[^\",]\",\r\n", element, filename); /* Erk - this needs to be optimized... :/ */ if (!(strncasecmp(element, "PLAN", 4))) strmcpy(&prog_config.plan_file, (char *) filename); else if (!(strncasecmp(element, "PROJECT", 7))) strmcpy(&prog_config.project_file, (char *) filename); else if (!(strncasecmp(element, "PGP_KEY", 7))) strmcpy(&prog_config.pgpkey_file, (char *) filename); else if (!(strncasecmp(element, "XFACE", 5))) strmcpy(&prog_config.xface_file, (char *) filename); else if (!(strncasecmp(element, "NO_FINGER", 9))) strmcpy(&prog_config.no_finger_file, (char *) filename); else if (!(strncasecmp(element, "LOGFILE", 7))) { strmcpy(&prog_config.log_file, (char *) filename); PRIV_ROOT_START logfile = fopen(filename, "a+"); PRIV_ROOT_END if (logfile) can_log = TRUE; else { syslog(LOG_ERR, "Cannot log to %s: %s", filename, strerror(errno)); can_log = FALSE; } } else if (!(strncasecmp(element, "HEADER_DISPLAY", 14))) strmcpy(&prog_config.top_display_file, (char *) filename); else if (!(strncasecmp(element, "FOOTER_DISPLAY", 14))) strmcpy(&prog_config.bottom_display_file, (char *) filename); else if (!(strncasecmp(element, "NO_NAME_BANNER", 14))) strmcpy(&prog_config.no_name_banner_file, (char *) filename); else if (!(strncasecmp(element, "NO_USER_BANNER", 14))) strmcpy(&prog_config.no_user_banner_file, (char *) filename); else if (!(strncasecmp(element, "REJECTED_BANNER", 15))) strmcpy(&prog_config.rejected_file, (char *) filename); else if (!(strncasecmp(element, "USERLOG", 7))) strmcpy(&prog_config.userlog_file, (char *) filename); else if (!(strncasecmp(element, "MAILBOX", 7))) strmcpy(&prog_config.mailbox_file, (char *) filename); else if (element[0] == '#') { /* Ignore commented out lines */ } else { errors++; printf("Option %s unknown in display_files.\n", element); } free(element); free(filename); } else if (type == FINGER_PROGRAMS) { char *element, *filename; if (line[0] != '#') { element = (char *) malloc(80); filename = (char *) malloc(80); sscanf(line, "\t%[^\t]\t= \"%[^\",]\",\r\n", element, filename); if (!(strncasecmp(element, "FINGER", 6))) strmcpy(&prog_config.finger_program, (char *) filename); else if (!(strncasecmp(element, "WHOIS", 5))) strmcpy(&prog_config.whois_program, (char *) filename); else { errors++; printf("Option %s unknown in finger_programs.\n", element); } free(element); free(filename); } } else if (type == FINGER_FAKEUSERS) { char *element, *fakename, *boolean, *filename; element = (char *) malloc(80); fakename = (char *) malloc(80); boolean = (char *) malloc(80); filename = (char *) malloc(80); sscanf(line, "\t\"%[^\"]\", \"%[^\"]\", %[^,], \"%[^\"]\",\r\n", element, fakename, boolean, filename); strmcpy(&prog_config.fusers[fakeuser_num].user, (char *) element); strmcpy(&prog_config.fusers[fakeuser_num].script, (char *) filename); strmcpy(&prog_config.fusers[fakeuser_num].description, (char *) fakename); if (!(strncasecmp(boolean, "TRUE", 4))) prog_config.fusers[fakeuser_num].searchable = TRUE; else if (!(strncasecmp(boolean, "FALSE", 5))) prog_config.fusers[fakeuser_num].searchable = FALSE; else { printf("Wrong boolean in FAKEUSERS!\n"); fflush(stdout); exit(-1); } fakeuser_num++; free(element); free(fakename); free(boolean); free(filename); } } free(line); } if (errors != 0) { printf("%d error%sw%s found in FILES section. Please fix %s.\n\n", errors, (errors == 1) ? " " : "s ", (errors == 1) ? "as" : "ere", (errors == 1) ? "it" : "them"); exit(0); } } /* * HAS * * This routine simply returns a TRUE or FALSE as to whether or not the * specified STRing has the SEARCH character in it. */ int has(char *str, char search) { int i; for (i = 0; i < strlen(str); i++) if (str[i] == search) return 1; return 0; } /* * DO_HOSTS * * Like the DO_FILES routine, this routine simply takes any hosts that * are listed as rejected or trusted, and places them in their correct * spots in the memory tree. */ void do_hosts(char *str) { char *line; int done = 0, type = 0; char *cp; line = (char *) malloc(80); sscanf(str, "HOSTS %[^ =] = {\r\n", line); if (!(strncmp(line, "trusted", 7))) type = TRUSTED; else if (!(strncmp(line, "rejected", 8))) type = REJECTED; else if (!(strncmp(line, "finger_forward", 14))) type = FORWARD; free(line); while(!done) { line = (char *) malloc(80); fscanf(file, "%[^\r\n]\r\n", line); if (!(strncmp(line, "}", 1))) done++; else if (line[0] != '#') { char *host; host = (char *) malloc(80); sscanf(line, "\t%[^,\r\n],\r\n", host); for (cp=host; *cp; cp++) if (isupper(*cp)) *cp = tolower (*cp); if (type == TRUSTED) strmcpy(&prog_config.trusted[trusted_host_num++], host); else if (type == REJECTED) strmcpy(&prog_config.rejected[rejected_host_num++], host); else if (type == FORWARD) strmcpy(&prog_config.forward[forward_host_num++], host); free(host); } } } /* * DO_CONFIG * * This routine simply takes a string, and reads through the configuration * file for the configurations that are needed. */ void do_config(char *str) { char *line; int done = 0, type = 0, errors = 0; line = (char *) malloc(80); sscanf(str, "CONFIG %[^ =] = {\r\n", line); /* Argh - I need to optimize THIS too! */ if (!(strncasecmp(line, "finger_display", 14))) type = FINGER_DISPLAY; else if (!(strncasecmp(line, "internal_config", 15))) type = INTERNAL_CONFIG; else if (!(strncasecmp(line, "system_list_sites", 17))) type = SYSTEM_LIST_SITES; else if (!(strncasecmp(line, "finger_strings", 14))) type = FINGER_STRINGS; else if (!(strncasecmp(line, "internal_strings", 16))) type = INTERNAL_STRINGS; else if (!(strncasecmp(line, "services_header", 15))) type = SERVICES_HEADER; else if (!(strncasecmp(line, "services_positions", 18))) type = SERVICES_POSITIONS; else if (!(strncasecmp(line, "signal_strings", 14))) type = SIGNAL_STRINGS; free(line); while(!done) { line = (char *) malloc(80); fgets(line, 80, file); if (!(strncmp(line, "}", 1))) done++; else if (line[0] != '#') { if (type == FINGER_DISPLAY) { char *element, *opt1, *opt2, *opt3; int x, found = FALSE; element = (char *) malloc(80); opt1 = (char *) malloc(80); opt2 = (char *) malloc(80); opt3 = (char *) malloc(80); sscanf(line, "\t%[+-]%[^\t =]\t = \133%[^,], %[^\135,]\135,", opt3, element, opt1, opt2); for (x = 0; ((finger_display[x].item != NULL) && (!found)); x++) { if (!(strncasecmp(element, finger_display[x].item, strlen(finger_display[x].item)))) { if (!(strncasecmp(opt1, "TRUE", 4))) { if (finger_display[x].section == 1) prog_config.config_bits1 |= finger_display[x].value; else if (finger_display[x].section == 2) prog_config.config_bits2 |= finger_display[x].value; else prog_config.config_bits3 |= finger_display[x].value; found = TRUE; } if (!(strncasecmp(opt2, "TRUE", 4))) { if (finger_display[x].section == 1) prog_config.local_config_bits1 |= finger_display[x].value; else if (finger_display[x].section == 2) prog_config.local_config_bits2 |= finger_display[x].value; else prog_config.local_config_bits3 |= finger_display[x].value; found = TRUE; } if (!(strncasecmp(opt1, "FALSE", 5))) found = TRUE; if (!(strncasecmp(opt2, "FALSE", 5))) found = TRUE; if (opt3[0] == '+') { if (finger_display[x].section == 1) prog_config.override_bits1 |= finger_display[x].value; else if (finger_display[x].section == 2) prog_config.override_bits2 |= finger_display[x].value; else prog_config.override_bits3 |= finger_display[x].value; found = TRUE; } } } if (!found) { errors++; printf("Option %s unknown in finger_display.\n", element); } free(element); free(opt1); free(opt2); free(opt3); } else if (type == INTERNAL_CONFIG) { char *element, *opt; int x, found = FALSE; element = (char *) malloc(80); opt = (char *) malloc(2); sscanf(line, "\t%[+-]%[^,\r\n],\r\n", opt, element); for (x = 0; ((internal_config[x].item != NULL) && (!found)); x++) { if (!(strncasecmp(element, internal_config[x].item, strlen(internal_config[x].item)))) { if (opt[0] == '+') { if (internal_config[x].section == 1) prog_config.config_bits1 |= internal_config[x].value; else if (internal_config[x].section == 2) prog_config.config_bits2 |= internal_config[x].value; else if (internal_config[x].section == 3) prog_config.config_bits3 |= internal_config[x].value; } found = TRUE; } } if (!found) { errors++; printf("Option %s unknown in internal_config.\n", element); } free(element); free(opt); } else if (type == SYSTEM_LIST_SITES) { char *element; element = (char *) malloc(80); sscanf(line, "\t%[^,\r\n],\r\n", element); strmcpy(&prog_config.finger_sites[num_finger_sites++], element); free(element); } else if (type == FINGER_STRINGS) { char *element, *string; int x, found = FALSE; element = (char *) malloc(80); string = (char *) malloc(80); sscanf(line, "\t%[^\t=] = \"%[^\",\r\n]\",\r\n", element, string); for (x = 0; ((finger_strings[x].item != NULL) && (!found)); x++) { if (!(strncasecmp(element, finger_strings[x].item, strlen(finger_strings[x].item)))) { strmcpy(&prog_config.p_strings[finger_strings[x].value], string); found = TRUE; } } if (!found) { errors++; printf("Option %s unknown in finger_strings.\n", element); } free(element); free(string); } else if (type == INTERNAL_STRINGS) { char *element, *string; int x, found = FALSE; element = (char *) malloc(80); string = (char *) malloc(80); sscanf(line, "\t%[^\t=] = \"%[^\",\r\n]\",\r\n", element, string); for (x = 0; ((internal_strings[x].item != NULL) && (!found)); x++) { if (!(strncasecmp(element, internal_strings[x].item, strlen(internal_strings[x].item)))) { strmcpy(&prog_config.p_strings[internal_strings[x].value], string); found = TRUE; } } if (!found) { errors++; printf("Option %s unknown in internal_strings.\n", element); } free(element); free(string); } else if (type == SERVICES_HEADER) { char *element; int counter; element = (char *) malloc(80); sscanf(line, "%[^\r\n]\r\n", element); if (strlen(element) > 3) { counter = strlen(element); if (!has(element, '%')) { element[counter++] = '\n'; element[counter] = '\0'; } if (!has(element, '%')) { if (element[0] != 0) strmcpy(&prog_config.services.header[num_headers++], element); else strmcpy(&prog_config.services.header[num_headers++], " "); } else strmcpy(&prog_config.services.display_string, element); free(element); } else prog_config.services.header[num_headers++] = " \n"; } else if (type == SERVICES_POSITIONS) { char *element, *num; element = (char *) malloc(80); num = (char *) malloc(80); sscanf(line, "\t%[^\t=] = %[^,\r\n],\r\n", element, num); if (!(strncasecmp(element, "USER", 4))) prog_config.services.name_pos = atoi(num); else if (!(strncasecmp(element, "SERVICE", 7))) prog_config.services.service_pos = atoi(num); else if (!(strncasecmp(element, "SEARCH", 6))) prog_config.services.search_pos = atoi(num); else { errors++; printf("Option %s unknown in services_positions.\n", element); } free(element); free(num); } else if (type == SIGNAL_STRINGS) { char *element, *string; int x, found = FALSE; element = (char *) malloc(80); string = (char *) malloc(80); sscanf(line, "\t%[^\t=] = \"%[^\",\r\n]\",\r\n", element, string); for (x = 0; ((signal_strings[x].item != NULL) && (!found)); x++) { if (!(strncasecmp(element, signal_strings[x].item, strlen(signal_strings[x].item)))) { strmcpy(&prog_config.siglist[signal_strings[x].value], string); found = TRUE; } } if (!found) { errors++; printf("Option %s unknown in signal_strings.\n", element); } } } } if (errors != 0) { printf("%d error%sw%s found in CONFIG section. Please fix %s.\n\n", errors, (errors == 1) ? " " : "s ", (errors == 1) ? "as" : "ere", (errors == 1) ? "it" : "them"); exit(0); } } /* * READ_CONFIGURATION * * This routine reads the configuration file. */ void read_configuration(void) { PRIV_ROOT_START file = fopen(CFINGERD_CONF, "r"); PRIV_ROOT_END trusted_host_num = rejected_host_num = fakeuser_num = num_finger_sites = 0; forward_host_num = 0; num_headers = 1; if (file) while(!feof(file)) { char *line, ch = fgetc(file); /* Patch by Kevin Rosenberg 10/21/95 */ if (ch == EOF) break; ungetc(ch, file); line = (char *) malloc(80); if ((ch != '#') && (ch != '\'')) { fgets(line, 80, file); if (!(strncasecmp(line, "FILES ", 6))) { do_files(line); } else if (!(strncasecmp(line, "HOSTS ", 6))) { do_hosts(line); } else if (!(strncasecmp(line, "CONFIG ", 7))) { do_config(line); } } else fgets(line, 80, file); free(line); } else { printf("No cfingerd.conf file present. Check your setup.\n"); exit(1); } } void check_blank_configurations(void) { if (trusted_host_num == 0) { trusted_host_num = 1; prog_config.trusted[0] = (char *) malloc(10); sprintf(prog_config.trusted[0], "localhost"); } if (rejected_host_num == 0) { rejected_host_num = 1; prog_config.rejected[0] = (char *) malloc(8); sprintf(prog_config.rejected[0], "0.0.0.0"); } if (forward_host_num == 0) { forward_host_num = 1; prog_config.forward[0] = (char *) malloc(10); sprintf(prog_config.forward[0], "localhost"); /* Patch by Larry Daffner (vizzie@airmail.net) */ if (prog_config.config_bits2 & SHOW_FINGERFWD) prog_config.config_bits2 &= ~SHOW_FINGERFWD; } if (fakeuser_num == 0) { prog_config.fusers[fakeuser_num].user = (char *) malloc(5); prog_config.fusers[fakeuser_num].script = (char *) malloc(10); prog_config.fusers[fakeuser_num].description = (char *) malloc(5); sprintf(prog_config.fusers[fakeuser_num].user, "None"); sprintf(prog_config.fusers[fakeuser_num].script, "/dev/null"); sprintf(prog_config.fusers[fakeuser_num].description, "None"); prog_config.fusers[fakeuser_num].searchable = FALSE; fakeuser_num = 1; } if (num_finger_sites == 0) { prog_config.finger_sites[num_finger_sites] = (char *) malloc(10); sprintf(prog_config.finger_sites[num_finger_sites], "localhost"); num_finger_sites = 1; } if (prog_config.mailbox_file == NULL) { prog_config.mailbox_file = (char *) malloc(sizeof(MAIL_SPOOL_DIR)+7); sprintf(prog_config.mailbox_file, "%s/$USER", MAIL_SPOOL_DIR); } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/defines.h0100644000076500001440000000200406525707252014556 0ustar joeyusers/* * CFINGERD * Global defines * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _DEFINES_H_ #define _DEFINES_H_ /* Error handler... Or what seems to be. :) */ #define CF_ERROR(x) { \ printf("\n"); \ printf(errors[x].error); \ printf("\n"); \ fflush(stdout); \ exit(PROGRAM_SYSLOG); \ } /* Some defines to make adding in carriage returns easier... */ #define SEND_RAW_RETURN { printf("\n"); fflush(stdout); } #define SEND_RAW_RETURN_NO_FLUSH printf("\n"); #define ERRORS_TO "cfingerd@infodrom.north.de" #endif /* _DEFINES_H_ */ cfingerd-1.4.3/src/errors.c0100644000076500001440000000420506612161615014447 0ustar joeyusers/* * CFINGERD * Verbose error handler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" /* Error messages */ ECRUFT errors[] = { { NULL, 0 }, {"This daemon cannot be run in stand-alone mode. Please read the\n" "documentation pertaining to the -s option\n", 0}, {"This daemon must be run as root!\n", 0}, {"This daemon must be run inside INETD with this option!\n", 0}, {"Please edit your cfingerd.conf file. An error was detected.\n", 0}, {"This program just died on a segmentation violation. Please report\n" "this to the programmer, " ERRORS_TO " if you can reproduce it.\n", 0}, {"This program should not be run as mode 1755 or the like with a\n" "1000 chmod (suid). Please change it to 0755 (recommended.)\n", 0}, {"Sorry, you indicated the wrong number of arguments for this\n" "command line option.\n", 0}, {"Sorry, the owner of this system has temporarily shut off all\n" "finger requests. Please try querying this system at a later date.\n", 0}, {"Settings in cfingerd.conf contradict themselves.\n" "You cannot have sites in trusted/rejected listings containing wildcards\n" "if you have ALLOW_HOSTNAME_WILDCARDS disabled, as you do in cfingerd.conf.\n" "If you want to have wildcards allowed, please enable this option.\n", 0}, {"Sorry, the owner of this site has turned off all searchable finger\n" "queries to this system.\n", 0}, {"Sorry, no DNS entry was found matching your IP address, and this site\n" "does not allow fingers from sites with non-matched DNS entries.\n", 0} }; /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/fakeuser.c0100644000076500001440000000725206774334770014762 0ustar joeyusers/* * CFINGERD * Fakeuser display routine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" /* * GET_PARMS * * This routine counts the number of parameters that are sent to the * fake user. */ int get_parms(char *username) { int i = 0, x = 0; for (i = 0; i < strlen(username); i++) x += (username[i] == '.') ? 1 : 0; return(x); } /* * SEARCH_FAKE_POS * * This returns the position in the fake user structure that this fake user * lies. If the fake user was not found in the structure, it returns a * "-1", meaning that the user doesn't exist. */ int search_fake_pos(char *username) { int i, len; len = strlen((char *) username); for (i = 0; i < fakeuser_num; i++) { char *k = prog_config.fusers[i].user; if (*k == '-') k++; if (!strcmp(username, k)) return(i); } return(-1); } /* * HANDLE_FAKEUSER * * This routine simply handles the username specified, and handles all of * the scripting information. */ void handle_fakeuser(char *username) { char *data[5]; int num_parms = 0, i, funum; char *buf; show_top(); num_parms = get_parms(username); num_parms++; if (prog_config.config_bits3 & SHOW_FAKEUSER) { if (num_parms > 5) { printf("\n Sorry, you specified too many options.\n\n"); fflush(stdout); show_bottom(); log(LOG_WARN, "Too many options specified in fake user finger", NULL); return; } /* Clear out any garbage */ for (i = 0; i < 5; i++) data[i] = NULL; /* And allocate our garbage. :) */ /* FIXME: correct lengths for data[] */ for (i = 0; i < num_parms; i++) data[i] = (char *) malloc(strlen(username)+1); if (num_parms == 1) sscanf(username, "%[^\r\n]\r\n", data[0]); else if (num_parms == 2) sscanf(username, "%[^.].%[^\r\n]\r\n", data[0], data[1]); else if (num_parms == 3) sscanf(username, "%[^.].%[^.].%[^\r\n]\r\n", data[0], data[1], data[2]); else if (num_parms == 4) sscanf(username, "%[^.].%[^.].%[^.].%[^\r\n]\r\n", data[0], data[1], data[2], data[3]); else if (num_parms == 5) sscanf(username, "%[^.].%[^.].%[^.].%[^.].%[^\r\n]\r\n", data[0], data[1], data[2], data[3], data[4]); log(LOG_USER, "Fakeuser: ", username); funum = search_fake_pos(data[0]); /* FUNUM should NEVER reach -1 ... we already checked this internally! */ if (funum != -1) { char send_string[80]; if (prog_config.fusers[funum].searchable) snprintf(send_string, sizeof(send_string), "%s %s %s %s %s", prog_config.fusers[funum].script, (data[1] != NULL) ? data[1] : "", (data[2] != NULL) ? data[2] : "", (data[3] != NULL) ? data[3] : "", (data[4] != NULL) ? data[4] : ""); else snprintf(send_string, sizeof(send_string), "%s", prog_config.fusers[funum].script); if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, send_string)) != NULL) { printf ("%s", buf); fflush (stdout); free (buf); } } } else { printf("\n"); printf(" Sorry, this system does not have any fake users enabled!\n\n"); log(LOG_WARN, "Fake user requested, but rejected - disabled.", " "); } show_bottom(); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/getutent.c0100644000076500001440000000446206762622766015016 0ustar joeyusers/* * Get UTMP file entries for BSD compatibility * by Kevin Rosenberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "config.h" #ifdef BSD #include #include #include #include #include #include #include #include #include #include "getutent.h" #ifndef __FreeBSD__ char *getdomainname(char *dname, size_t maxsize) { struct utsname st_uname; char *p; int len; if (uname (&st_uname) < 0) { fprintf( stderr, "Error calling uname\n"); exit(1); fprintf( stderr, "Error calling uname\n"); exit(1); } /* printf ("node name: %s\n", st_uname.nodename); */ dname[0] = EOF; for (p = st_uname.nodename; *p; ++p) if (*p == '.') { ++p; for (len = 0; *p && len < maxsize-1; len++) dname[len] = *p++; dname[len] = 0; break; } /* printf ("domainname: %s\n", dname); */ return dname; } #endif /* !__FreeBSD__ */ static int utmp_fd = -1; void setutent() { if (utmp_fd < 0) if ((utmp_fd = open(_PATH_UTMP, O_RDONLY)) < 0) { fprintf(stderr, "Can't open /var/run/utmp\n"); exit(1); } lseek(utmp_fd, (off_t) 0, SEEK_SET); } void endutent() { if (utmp_fd > 0) close(utmp_fd); utmp_fd = -1; } struct utmp *getutent() /* returns next utmp file entry */ { static struct utmp s_utmp; int readval; if (utmp_fd < 0) setutent(); if ((readval = read(utmp_fd, &s_utmp, sizeof(s_utmp))) < sizeof(s_utmp)) { if (readval == 0) return NULL; else if (readval < 0) { fprintf(stderr, "Error reading %s\n", _PATH_UTMP); exit(1); } else { fprintf(stderr, "Partial record in %s [%d bytes]\n", _PATH_UTMP, readval ); exit(1); } } return &s_utmp; } #endif /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/getutent.h0100644000076500001440000000035406762270720015004 0ustar joeyusers#ifndef __GETUTENT_H__ #define __GETUTENT_H__ #ifdef BSD struct utmp *getutent(); /* returns next utmp file entry */ void setutent(); #ifndef __FreeBSD__ char *getdomainname(char *, size_t); #endif /* !__FreeBSD__ */ #endif #endif cfingerd-1.4.3/src/internal.c0100644000076500001440000000706306762173065014764 0ustar joeyusers/* * CFINGERD * Internal finger handler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" /* * SHOW_SERVICES * * This routine simply shows the available services that your system * provides. */ void show_services(void) { int i; show_top(); for (i = 0; i < num_headers; i++) if (prog_config.services.header[i] != NULL) printf("%s", prog_config.services.header[i]); for (i = 0; i < fakeuser_num; i++) if (prog_config.fusers[i].user[0] != '-') { printf(prog_config.services.display_string, (prog_config.services.name_pos == 1) ? prog_config.fusers[i].user : (prog_config.services.service_pos == 1) ? prog_config.fusers[i].description : (prog_config.services.search_pos == 1) ? (prog_config.fusers[i].searchable ? "TRUE" : "FALSE") : " ", (prog_config.services.name_pos == 2) ? prog_config.fusers[i].user : (prog_config.services.service_pos == 2) ? prog_config.fusers[i].description : (prog_config.services.search_pos == 2) ? (prog_config.fusers[i].searchable ? "TRUE" : "FALSE") : " ", (prog_config.services.name_pos == 3) ? prog_config.fusers[i].user : (prog_config.services.service_pos == 3) ? prog_config.fusers[i].description : (prog_config.services.search_pos == 3) ? (prog_config.fusers[i].searchable ? "TRUE" : "FALSE") : " "); printf("\n"); } fflush(stdout); show_bottom(); } /* * HANDLE_INTERNAL * * This routine handles the internal fingernames. If CFINGERD detects a * U_INTERNAL finger type, it calls this routine automatically. Pretty * nice. :) */ void handle_internal(char *username) { char *buf; if (!strncmp(username, "version", 7)) show_version_info(); else if (!strncmp(username, "services", 8)) { show_services(); syslog(LOG_NOTICE, "%s", prog_config.p_strings[D_SVC_FINGER]); log(LOG_USER, "Service request", " "); exit(PROGRAM_OKAY); } else if (!strncmp(username, "search", 6)) { show_search(username); exit(PROGRAM_OKAY); } else if (!strncmp(username, "userlist-only", 13)) { if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, "/usr/sbin/userlist | /usr/bin/tail +2")) != NULL) { printf ("%s", buf); fflush(stdout); free (buf); } log(LOG_USER, "Userlist-only", " "); exit(PROGRAM_OKAY); } else if (!strncmp(username, "userlist-online", 15)) { if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, "/usr/sbin/userlist -c -n | /usr/bin/tail +2")) != NULL) { printf ("%s", buf); fflush(stdout); free (buf); } log(LOG_USER, "Userlist-only", " "); exit(PROGRAM_OKAY); } else if (!strncmp(username, "help", 4)) { show_top(); printf("\ncfingerd Internal Usernames Help\n\n"); printf("Finger \"version\" for version information.\n"); printf("Finger \"services\" to list services this system provides.\n"); printf("Finger \"search\" to search for a username.\n"); printf("Finger \"userlist-only\" to get only a userlist of who's on.\n"); printf("Finger \"help\" gives you this help list.\n\n"); show_bottom(); fflush(stdout); syslog(LOG_NOTICE, "Help fingered"); exit(PROGRAM_OKAY); } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/log.c0100644000076500001440000000456206740760102013720 0ustar joeyusers/* * CFINGERD * Logging module * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #include "privs.h" void log(int logtype, char *msg, char *user) { if (can_log && (prog_config.config_bits3 & SHOW_LOG)) { time_t tim = time(NULL); fprintf(logfile, "Log from %s at %s", ident_user?ident_user:"unknown", ctime(&tim)); switch(logtype) { case LOG_IDENT: fprintf(logfile, "\tIDENT: %s%s\n\n", msg, user); break; case LOG_REJECTED: fprintf(logfile, "\tREJECTED: %s%s\n\n", msg, user); break; case LOG_WARN: fprintf(logfile, "\tWARNING: %s\n\n", msg); break; case LOG_USER: fprintf(logfile, "\tUSER: %s%s\n\n", msg, user); break; case LOG_ERROR: fprintf(logfile, "\tERROR: %s%s\n\n", msg, user); break; } fflush(logfile); } } void userlog(uid_t uid, gid_t gid, char *dir, char *user) { FILE *file = NULL; char filename[80]; memset(filename, 0, 80); snprintf(filename, sizeof(filename), "%s/%s", dir, prog_config.userlog_file); fflush(stdout); USER_PRIVS(uid,gid) /* * If the file doesn't already exist, check to make sure we can * create it (if the sysadmin allows it). If the file was created, * then they want a finger log, and thus, should show the log here. */ if (!exist(filename)) { if (!(prog_config.config_bits3 & SHOW_CREATE_FLG)) file = fopen(filename, "w"); } else file = fopen(filename, "a+"); NOBODY_PRIVS if (file) { time_t tim = time(NULL); USER_PRIVS(uid,gid) fprintf(file, "Finger from %s at %s", user, ctime(&tim)); fflush(file); fclose(file); NOBODY_PRIVS } else { if (!(prog_config.config_bits3 & SHOW_CREATE_FLG)) { syslog(LOG_WARNING, "Userlog: %s (%s)", filename, strerror(errno)); log(LOG_ERROR, "Cannot write to userlog: ", strerror(errno)); } } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/main.c0100644000076500001440000002012506752652262014066 0ustar joeyusers/* * CFINGERD * Main Routine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #define MAIN #include "privs.h" CONFIG prog_config; char *remote_addr, *localhost, *ident_user, *ip_address; FILE *top_display, *bottom_display, *noname_display, *nouser_display, *rejected_display, *identd_display; BOOL local_finger, emulated; int local_port, remote_port; unsigned short listen_port; unsigned long listen_addr; /* * HAS_MATCH * * Check to see if there's an occurance of "match" within "string". You're * probably saying that I could have used strncmp, or something else * similar. Not true - because I'd need about 3 calls in here, and this * routine does everything I need in *1* routine. :) */ BOOL has_match(char *string, char *match) { int i, x; for (i = 0; i < strlen(string); i++) for (x = 0; x < strlen(match); x++) if (string[i] == match[x]) return TRUE; return FALSE; } /* * MAIN * * The main dispatcher for cfingerd. */ int main(int argc, char *argv[]) { /* * The length restrictions are limited. If lengths are changed all * subsequent routines need to be investigated. */ char line[100], username[80], syslog_str[200]; int un_type; char *cp; struct sockaddr_in local_addr; struct servent *serv; if ((serv = getservbyname("finger","tcp")) != NULL) listen_port = serv->s_port; else listen_port = htons(79); listen_addr = htonl(INADDR_ANY); /* Initialize CFINGERD */ start_handler(); start_cfingerd(); /* Clear any extraneous bits that should be cleared */ can_log = FALSE; memset(line, 0, sizeof(line)); memset(username, 0, sizeof(username)); memset(syslog_str, 0, sizeof(syslog_str)); /* Check for any command-line options */ if (argc > 1) { (void) check_options(argc, argv); if (argc > 2) strncpy(username, argv[2], sizeof(username)); } /* Read the configuration, and check status of the program so far */ read_configuration(); check_blank_configurations(); check_stats(); open_initial_files(); /* * Okay, now that all of the standard processing has taken place, we * can switch to the NOBODY UID/GID and run everything else as nobody * (to a certain degree.) Remembering, of course, if we must switch * to a user that's being fingered, we MUST call USER_PRIVS(UID,GID) * to obtain privileges as that user. (Read the FAQ for more info.) */ NOBODY_PRIVS; /* Make sure there is actually data waiting in the finger port */ if (!emulated) { if (!fgets(username, sizeof(username), stdin)) { if (remote_addr != NULL) { syslog(LOG_ERR, "Null query from %s: %m", remote_addr); log(LOG_ERROR, remote_addr, strerror(errno)); } else { syslog(LOG_ERR, "Null query: %m"); log(LOG_ERROR, strerror(errno), strerror(0)); } closelog(); exit(PROGRAM_SYSLOG); } } /* * RFC 1288 * * 2.5.4. /W query token * * The token /W in the {Q1} or {Q2} query types SHOULD at best be * interpreted at the last RUIP to signify a higher level of verbosity * in the user information output, or at worst be ignored. * * As the normal behaviour of cfingerd is to show all information we * can't set a higher level of verbosity - therefore this parameter * is being ignored. */ if ( strlen(username) && !strncmp(username, "/W ", 3) ) { cp = username; cp += 3; strcpy (line, cp); strcpy (username, line); } /* If there's a username, trim the CRLF pair */ if (!emulated) sscanf(username, "%[^\r\n]\r\n", username); /* If we're not doing emulated stuff, we can assume that we are running either as a daemon, or under INETD. In that case... */ if (!emulated) { struct sockaddr_in socket_addr; struct hostent *host_ent; int psize = 0; /* Can't run from command line (but this should already be checked) */ psize = sizeof(socket_addr); if (getsockname(0, (struct sockaddr *) &local_addr, &psize)) { syslog(LOG_WARNING, "getsockname: %s", strerror(errno)); local_port = 0; } else local_port = ntohs(local_addr.sin_port); if (getpeername(0, (struct sockaddr *) &socket_addr, &psize)) { printf("Internal error - not running as either a daemon or under INETD.\n"); printf("Fatal - getpeername: %s\n", strerror(errno)); closelog(); log(LOG_ERROR, "getpeername: ", strerror(errno)); exit(PROGRAM_BUG); } else remote_port = ntohs(socket_addr.sin_port); ip_address = inet_ntoa (socket_addr.sin_addr); /* Get our host entry */ host_ent = (struct hostent *) gethostbyaddr((char *) &socket_addr.sin_addr, sizeof(socket_addr.sin_addr), AF_INET); /* And get our local-host name */ #ifndef ACTUAL_HOSTNAME localhost = get_localhost(); #else localhost = ACTUAL_HOSTNAME; #endif /* Make sure we can get the remote host's address name */ if (host_ent == NULL) { remote_addr = inettos(socket_addr.sin_addr.s_addr); syslog(LOG_WARNING, "%s %s", prog_config.p_strings[D_IP_NO_MATCH], remote_addr); if (!(prog_config.config_bits2 & SHOW_IP_MATCH)) CF_ERROR(E_NOIP); } else remote_addr = (char *) host_ent->h_name; /* Convert any uppercase letters in the hostname to lowercase */ for (cp = remote_addr; *cp; cp++) if (isupper(*cp)) *cp = tolower(*cp); /* And find out if this is a local finger */ if (!strncasecmp(remote_addr, "127.0.0.1", 9) || !strncasecmp(remote_addr, "localhost", 9) || !strncasecmp(remote_addr, "127.0.0.0", 9) || /* KTH 07/26/96 */ !strncasecmp(remote_addr, localhost, strlen(localhost))) local_finger = TRUE; else local_finger = FALSE; ident_user = get_rfc1413_data(local_addr); set_time_format(); } else local_finger = TRUE; /* We're emulated, so assume we're fingering from loopback */ if (emulated) { local_finger = TRUE; ident_user = (char *)malloc(sizeof("emulated")+1); memset (ident_user, 0, sizeof (ident_user)); strcpy (ident_user, "emulated"); #ifndef ACTUAL_LOOPBACK remote_addr = "127.0.0.1"; #else remote_addr = ACTUAL_LOOPBACK; #endif } /* Now, let's check to make sure this site is trusted */ if ((!local_finger) && !emulated) local_finger = check_trusted(remote_addr); if ((!local_finger) && !emulated) check_rejected(remote_addr); /* Check the finger information coming in and return its type */ un_type = process_username(username); /* And check the process the information here. */ switch(un_type) { case U_INTERNAL: if (!emulated) { snprintf(syslog_str, sizeof(syslog_str), "%s fingered (internal) from %s", username, ident_user); syslog(LOG_NOTICE, (char *) syslog_str); } handle_internal(username); break; case U_STANDARD: if (!emulated) { if (strncmp(username, "root", 4)) snprintf(syslog_str, sizeof(syslog_str), "%s fingered from %s", username, ident_user); else snprintf(syslog_str, sizeof(syslog_str), "%s fingered from %s", prog_config.p_strings[D_ROOT_FINGER], ident_user); syslog(LOG_NOTICE, (char *) syslog_str); } handle_standard(username); break; case U_FAKEUSER: if (!emulated) { snprintf(syslog_str, sizeof(syslog_str), "%s %s from %s", username, prog_config.p_strings[D_FAKE_USER], ident_user); syslog(LOG_NOTICE, (char *) syslog_str); } handle_fakeuser(username); break; case U_USERLIST: if (!emulated) syslog(LOG_NOTICE, "%s from %s", prog_config.p_strings[D_ULIST_FINGER], ident_user); handle_userlist(username); break; } return(0); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/options.c0100644000076500001440000001114306762270720014631 0ustar joeyusers/* * CFINGERD * Starting option routines * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #include "version.h" /* * SET_DAEMON_MODE * * Eventually, this will bind to the finger socket, and stay running as a * true daemon. For the time being, though, it is only INETD compliant. */ void set_daemon_mode(void) { #ifdef DAEMON_MODE pid_t pid; int i, lsock, fd, clen; int oval = 1; struct sockaddr caddr; struct sockaddr_in laddr; if ((lsock = socket (AF_INET, SOCK_STREAM, 0)) < 0) { syslog (LOG_ERR,"can't open socket: %m"); exit (1); } if (setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&oval, sizeof(oval)) < 0) { syslog (LOG_ERR,"can't setsockopt(SO_REUSEADDR): %m"); exit (1); } laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = listen_addr; laddr.sin_port = listen_port; if (bind (lsock, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) { syslog (LOG_ERR,"can't bind: %m"); exit (1); } if ((pid = fork()) < 0) { syslog (LOG_ERR, "can't fork(): %m"); exit (1); } else if (pid != 0) exit (0); syslog(LOG_NOTICE, "Daemon mode initiated"); setsid(); for (i = 0; i < 3; i++) { close(i); fd = open ("/dev/null", O_RDWR); if (fd != i) { dup2 (fd, i); close (fd); } } listen (lsock,20); clen = sizeof (caddr); while (1) { fd = accept (lsock, &caddr, &clen); if (fd < 0) { #ifndef __FreeBSD__ if (errno == EPROTO) { #else if (errno == EPROTOTYPE) { #endif /* !__FreeBSD__ */ remote_addr = inet_ntoa (((struct sockaddr_in *)&caddr)->sin_addr); syslog(LOG_ERR,"failed connect (possible port scan) from %s: %m", remote_addr); } continue; } remote_addr = inet_ntoa (((struct sockaddr_in *)&caddr)->sin_addr); /* * FIXME: Support for tcp wrapper via hosts.allow and .deny is missing */ for (i = 0; (pid = fork ()) < 0; ++i) { if (i == 5) { syslog (LOG_ERR,"terminate; can't fork client: %m"); continue; } syslog (LOG_ERR,"waiting; can't fork client: %m"); sleep (1); } if (pid != 0) { close (fd); continue; } else { /* * Now we're in cfingerd child. */ close (lsock); dup2 (fd,0); close (fd); dup2 (0,1); dup2 (0,2); signal (SIGCHLD, SIG_DFL); return; } } #else printf("CFINGERD %s daemon mode starting.\n", VERSION); printf("\nSorry, daemon mode for cfingerd is not compiled in. Uncomment\n"); printf("DAEMON_MODE in src/config.h.\n\n"); fflush(stdout); exit(0); #endif } /* * GIVE_HELP * * This gives help about command line options under cfingerd. */ void give_help(void) { printf("\nCFINGERD command line options:\n\n"); printf("\t-c\t\tChecks the configuration to make sure it's okay\n"); printf("\t-d\t\tRuns the daemon as stand-alone (non-inetd)\n"); printf("\t-e [user]\tEmulates a local finger from the command line\n"); printf("\t-o\t\tTurn off all incoming finger queries\n"); printf("\t-v\t\tRetrieves daemon version information\n\n"); printf("Any other options will give you this screen. Commands are not\n"); printf("case sensitive.\n\n"); fflush(stdout); exit(PROGRAM_OKAY); } /* * CHECK_OPTIONS * * This is called at runtime (and is usually the first option). This takes * in the argv pointer, and verifies the options passed. */ void check_options(int argc, char *argv[]) { if (!strncasecmp(argv[1], "-d", 2)) { set_daemon_mode(); return; } else if (!strncasecmp(argv[1], "-v", 2)) show_version_info(); else if (!strncasecmp(argv[1], "-e", 2)) { if (argc > 2) { emulated = TRUE; syslog(LOG_NOTICE, "Emulated: \"%s\"", (char *) argv[2]); printf("[127.0.0.1 : Username: %s]\n", (char *) argv[2]); fflush(stdout); return; } else CF_ERROR(E_COMMANDLINE); } else if (!strncasecmp(argv[1], "-o", 2)) { CF_ERROR(E_FINGEROFF); } else if (!strncasecmp(argv[1], "-c", 2)) { read_configuration(); printf("\nConfiguration okay.\n\n"); fflush(stdout); exit(PROGRAM_OKAY); } give_help(); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/parse.c0100644000076500001440000001106306774334770014262 0ustar joeyusers/* * CFINGERD * Parsing routines * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" /* * SEARCH_ILLEGAL * * This searches for any illegal characters in a user's name. If there are * any found, it returns a U_ILLEGAL, otherwise it returns a 0. */ int search_illegal(char *str) { int i; if (str != NULL) { for (i = 0; i < strlen(str); i++) if (str[i] == '@') return U_FORWARD; else if (!isalpha(str[i]) && !isdigit(str[i]) && (str[i] != '.') && (str[i] != '_') && (str[i] != '-') && (str[i] != ',') && (str[i] != '?') && (str[i] != '*') && (str[i] != '/')) return U_ILLEGAL; } return 0; } /* * INTERNAL_CHECK * * This checks the username up against an internal username template, * for use with cfingerd testing, debugging, and/or other information * retrieval. Please don't disable this routine - this should be * included with all of the cfingerd distributions. * * Returns U_INTERNAL if the username matches an internal username, * otherwise, it returns a 0. */ int internal_check(char *username) { int length = strlen(username); if (!strncmp(username, "version", 7) && length == 7 && prog_config.config_bits3 & SHOW_CONFESSION) return(U_INTERNAL); else if (!strncmp(username, "help", 4) && length == 4 && prog_config.config_bits3 & SHOW_CONFESSION) return(U_INTERNAL); else if (!strncmp(username, "services", 8) && length == 8 && prog_config.config_bits3 & SHOW_FAKEUSER) return(U_INTERNAL); else if (!strncmp(username, "search", 6) && prog_config.config_bits2 & SHOW_SEARCHFING) return(U_INTERNAL); else if (((!strncmp(username, "userlist-only", 13) && length == 13) || (!strncmp(username, "userlist-online", 15) && length == 15)) && (prog_config.config_bits2 & SHOW_ULISTONLY) && ((local_finger && prog_config.local_config_bits2 & SHOW_SYSTEMLIST) || (!local_finger && prog_config.config_bits2 & SHOW_SYSTEMLIST))) return(U_INTERNAL); return(0); } /* * SEARCH_FAKE * * Search for a fake user. Returns U_FAKEUSER if the user is fake, and * 0 if it is not. */ int search_fake(char *username) { char *parsed; char *cp; if ((cp = index (username, '.')) != NULL) *cp='\0'; if ((parsed = (char *)malloc (strlen(username)+1)) != NULL) { memset (parsed, 0, strlen(username)+1); strcpy (parsed, username); } if (cp != NULL) *cp='.'; if (parsed != NULL) { if (search_fake_pos(parsed) >= 0) { free (parsed); return(U_FAKEUSER); } } if (parsed) free (parsed); return(0); } /* * PROCESS_USERNAME * * This is the grand-daddy of them all. This routine does all of the * sanity checks against the username to make sure it's a legal username. * If the username doesn't exist, it returns the proper error message * back to the user, and skips the finger-query request altogether. Other- * wise, it returns: * * U_ILLEGAL: Username was illegal in checking * U_FORWARD: Username is a forward request (contains `@') * U_STANDARD: Username is a standard (non-fake) username * U_FAKEUSER: Username matches a fake user * U_INTERNAL: Username matches an internal (defined) username * U_USERLIST: Username is not present - it's a userlisting */ int process_username(char *username) { int ret = 0; if ((username[0] == 13) || (username[0] == 10) || (username[1] == 13) || (username[1] == 10)) ret = U_USERLIST; else if (!strncmp (username, "userlist", 8) && strlen (username) == 8) ret = U_USERLIST; if (ret != U_USERLIST) { ret = search_illegal(username); if (ret == U_FORWARD) { printf("%s\n", prog_config.p_strings[D_FORWARD_DENY]); fflush(stdout); log(LOG_USER, "Denied forward: ", username); exit(1); } if (ret == U_ILLEGAL) { printf("Illegal character in username.\n"); fflush(stdout); log(LOG_USER, "Illegal: ", username); exit(1); } ret = internal_check(username); if (ret != U_INTERNAL) ret = search_fake(username); if (ret == 0) ret = U_STANDARD; } return(ret); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/privs.h0100644000076500001440000001033406752652262014313 0ustar joeyusers/* * privs.h - header for privileged operations * Copyright (c) 1993 Thomas Koenig (ig25@rz.uni-karlsruhe.de) * Copyright (c) 1996 Martin Schulze (joey@infodrom.north.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Modified by Martin Schulze (joey@infodrom.north.de) to fit with * cfingerd. */ #ifndef _PRIVS_H_ #define _PRIVS_H_ #include "cfingerd.h" #ifndef _USE_BSD #define _USE_BSD 1 #include #include #undef _USE_BSD #else #include #endif /* Relinquish privileges temporarily for a setuid or setgid program * with the option of getting them back later. This is done by swapping * the real and effective userid BSD style. Call RELINQUISH_PRIVS once * at the beginning of the main program. This will cause all operations * to be executed with the real userid. When you need the privileges * of the setuid/setgid invocation, call PRIV_START; when you no longer * need it, call PRIV_END. Note that it is an error to call PRIV_START * and not PRIV_END within the same function. * * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running * as root, and you want to drop back the effective userid to a * and the effective group id to b, with the option to get them back * later. * * If you no longer need root privileges, but those of some other * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective * is the user's. * * Problems: Do not use return between PRIV_START and PRIV_END; this * will cause the program to continue running in an unprivileged * state. * * It is NOT safe to call exec(), system() or popen() with a user- * supplied program (i.e. without carefully checking PATH and any * library load paths) with relinquished privileges; the called program * can aquire them just as easily. Set both effective and real userid * to the real userid before calling any of them. */ #ifndef MAIN extern #endif uid_t real_uid, effective_uid; #ifndef MAIN extern #endif gid_t real_gid, effective_gid; #ifndef MAIN extern #endif gid_t grouplist[1]; #define NOBODY_PRIVS USER_PRIVS (NOBODY_UID,NOBODY_GID) /* * Switches real and effective uid/gid. */ #define RELINQUISH_PRIVS { \ real_uid = getuid(); \ effective_uid = geteuid(); \ real_gid = getgid(); \ effective_gid = getegid(); \ setregid(effective_gid, real_gid); \ setreuid(effective_uid, real_uid); \ } /* * Restores saved real and effective uid/gid. */ #define PRIV_ROOT_START {\ setreuid(real_uid, 0); \ setregid(real_gid, 0); /* * Switches real and effective uid/gid back. */ #define PRIV_ROOT_END \ setregid(0, real_gid); \ setreuid(0, real_uid); \ } /* * Switches to non priviliged uid/gid. This is done by first * switching back to priviliged uid/gid. This means that real_uid and * real_gid need to contain root uid/gid. Only the effective uid is * switched to non-priviliged. */ #define USER_PRIVS(a,b) {\ setreuid(real_uid, 0); \ setregid(real_gid, 0); \ effective_uid = (a); \ effective_gid = (b); \ grouplist[0] = effective_gid; \ setgroups(1, grouplist); \ setregid(real_gid, effective_gid); \ setreuid(real_uid, effective_uid); \ } #define DROP_ALL_PRIVS(a,b) {\ setreuid(real_uid, 0); \ setregid(real_gid, 0); \ effective_uid = (a); \ effective_gid = (b); \ grouplist[0] = effective_gid; \ setgroups(1, grouplist); \ setregid(effective_gid, effective_gid); \ setreuid(effective_uid, effective_uid); \ } #endif /* _PRIVS_H_ */ cfingerd-1.4.3/src/proto.h0100644000076500001440000000342006762173066014312 0ustar joeyusers/* * CFINGERD * Prototypes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ void check_options(int, char *argv[]); void start_cfingerd(void); void show_version_info(void); int send_ident(unsigned short, unsigned short); int get_ident(int, char **); char *process_ident(void); void show_auth_info(void); void check_stats(void); void set_time_format(void); int process_username(char *); void strmcpy(char **, const char *); void read_configuration(void); void handle_internal(char *); void start_handler(void); void show_top(void); void handle_standard(char *); void display_file(uid_t, gid_t, FILE *); BOOL check_exist(char *); BOOL check_exist_alias(char *); BOOL exist(char *); void show_notexist(void); void show_bottom(void); char *inettos(long addr); char *get_localhost(void); void handle_userlist(char *); void handle_fakeuser(char *); BOOL check_trusted(char *); void check_rejected(char *); void show_search(char *); void become_nobody(void); void become_user(char *); int wildmat(char *, char *); char *get_rfc1413_data(struct sockaddr_in ); void check_unknown(char *); void log(int, char *, char *); void userlog(uid_t, gid_t, char *, char *); void check_blank_configurations(void); int search_fake_pos(char *); char *safe_exec(uid_t uid, gid_t gid, char *); void open_initial_files(void); BOOL check_illegal(char *, char *); FILE *open_file(char *); cfingerd-1.4.3/src/rfc1413.c0100644000076500001440000000641206762222041014215 0ustar joeyusers/* * CFINGERD * RFC1413 implementation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" void rfc1413_alarm(int signal) { if (signal == SIGALRM) ident_user = "unknown@alarm.signal"; } /* Self contained RFC1413 implementation. Thanks to Joel Katz for parts of * the implementation. Completely rewritten by yours truly to be self- * contained in a single program. Simple, easy to use. */ #define BUFLEN 256 char *get_rfc1413_data( struct sockaddr_in local_addr ) { int i, j; struct sockaddr_in sin; char buffer[1024], buf[BUFLEN], uname[64], *bleah; char *cp, *xp; struct servent *serv; bleah = (char *) malloc(BUFLEN); memset(bleah, 0, BUFLEN); j = socket(AF_INET, SOCK_STREAM, 0); if (j < 2) { snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); syslog(LOG_ERR, "rfc1413-socket: %s", strerror(errno)); return(bleah); } sin.sin_family = AF_INET; sin.sin_addr.s_addr = local_addr.sin_addr.s_addr; sin.sin_port = 0; i = bind(j, (struct sockaddr *) &sin, sizeof(sin)); if (i < 0) { snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); syslog(LOG_ERR, "rfc1413-socket: %s", strerror(errno)); return(bleah); } sin.sin_family = AF_INET; if ((serv = getservbyname("auth","tcp")) != NULL) sin.sin_port = serv->s_port; else sin.sin_port = htons(113); sin.sin_addr.s_addr = inet_addr(ip_address); signal(SIGALRM, rfc1413_alarm); alarm(5); i = connect(j, (struct sockaddr *) &sin, sizeof(sin)); if (i < 0) { syslog(LOG_ERR, "rfc1413-connect: %s", strerror(errno)); close(j); snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); alarm(0); return(bleah); } snprintf(buffer, sizeof(buffer), "%d,%d\n", remote_port, local_port); write(j, buffer, strlen(buffer)); memset(buf, 0, sizeof(buf)); if (read(j, buf, 256) <= 0) { snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); } else { /* * The response should look like * 23640 , 60179 : USERID : UNIX : joey^M */ if ((cp = strchr(buf, ':')) == NULL) snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); else if ((cp = strchr(++cp, ':')) == NULL) snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); else if ((cp = strchr(++cp, ':')) == NULL) snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); if (!cp) { close(j); alarm(0); return (bleah); } if (*(++cp) == ' ') cp++; memset(uname, 0, sizeof(uname)); for (xp=uname; *cp != '\0' && *cp!='\r'&&*cp!='\n'&&strlen(uname) 0) { int i; printf("\n %d match%sfound regarding your search criteria:\n\n", num_searches, (num_searches > 1) ? "es " : " "); printf(" Username: Realname:\n"); printf(" -------------- --------------------------------------------------------------\n"); for(i = 0; i < num_searches; i++) { printf(" %-14.14s %-61.61s\n", searches[i].username, (searches[i].realname[0] != 0) ? searches[i].realname : "No realname field available"); } fflush(stdout); } else { printf("\n No matches found regarding your search criteria.\n"); fflush(stdout); } SEND_RAW_RETURN; show_bottom(); free (searchname); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/signal.c0100644000076500001440000000773206612161615014420 0ustar joeyusers/* * CFINGERD * Signal handler version 1.10 * * Fixed a bit for POSIX compliance * Removed SIGUNUSED and SIGSTKFLT (since they're never used, anyway) * Removed SIGCHLD -- caused too many problems on other OSes * Removed SIGKILL -- you can't trap it * Changed signal installation to work better and be easier to read * Added prog_config strings here for signal names * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" typedef struct { int value; char *sigtype; int sigvalue; int fatal; } SLIST; #define NUM_SIGS 23 /* Our trapped signals */ SLIST siglist[] = { {SIGHUP, "SIGHUP", S_SIGHUP, FALSE}, {SIGINT, "SIGINT", S_SIGINT, TRUE}, {SIGQUIT, "SIGQUIT", S_SIGQUIT, TRUE}, {SIGILL, "SIGILL", S_SIGILL, TRUE}, {SIGTRAP, "SIGTRAP", S_SIGTRAP, FALSE}, {SIGABRT, "SIGABRT", S_SIGABRT, TRUE}, {SIGFPE, "SIGFPE", S_SIGFPE, TRUE}, {SIGUSR1, "SIGUSR1", S_SIGUSR1, FALSE}, {SIGSEGV, "SIGSEGV", S_SIGSEGV, TRUE}, {SIGUSR2, "SIGUSR2", S_SIGUSR2, FALSE}, {SIGPIPE, "SIGPIPE", S_SIGPIPE, TRUE}, {SIGALRM, "SIGALRM", S_SIGALRM, FALSE}, {SIGTERM, "SIGTERM", S_SIGTERM, TRUE}, {SIGCONT, "SIGCONT", S_SIGCONT, FALSE}, {SIGTSTP, "SIGTSTP", S_SIGTSTP, FALSE}, {SIGTTIN, "SIGTTIN", S_SIGTTIN, FALSE}, {SIGTTOU, "SIGTTOU", S_SIGTTOU, FALSE}, {SIGIO, "SIGIO", S_SIGIO, TRUE}, {SIGXCPU, "SIGXCPU", S_SIGXCPU, TRUE}, {SIGXFSZ, "SIGXFSZ", S_SIGXFSZ, TRUE}, {SIGVTALRM, "SIGVTALRM", S_SIGVTALRM, FALSE}, {SIGPROF, "SIGPROF", S_SIGPROF, FALSE}, {SIGWINCH, "SIGWINCH", S_SIGWINCH, FALSE} }; /* * INT_HANDLER * * This is the main signal handler, catching any signals that are made, and * ending the program if the program needs to be stopped. */ void int_handler(int signo) { int i; BOOL caught = FALSE; for (i = 0; i < NUM_SIGS; i++) { if (signo == siglist[i].value) { printf("Signal \"%s\": %s signal\n", siglist[i].sigtype, prog_config.siglist[siglist[i].sigvalue]); syslog(LOG_ERR, "\"%s\" caught", siglist[i].sigtype); caught = TRUE; if (siglist[i].fatal) { printf("\nPlease report this bug to %s!\n", ERRORS_TO); log(LOG_ERROR, "Signal (fatal): ", siglist[i].sigtype); } else { if (siglist[i].value == SIGALRM) { printf("Ooh, you caught an alarm signal. This may be a cause from either not\n"); printf("having GCC 2.5.8 used with compilation, or your script simply timed\n"); printf("out on you. May want to check this. :)\n\n"); } log(LOG_WARN, "Signal: Alarm signal", " "); printf("Non-fatal; continuing.\n"); } (void) fflush(stdout); if (siglist[i].fatal) exit(PROGRAM_BUG); else log(LOG_WARN, "Signal (non-fatal): ", siglist[i].sigtype); } } if (!caught) { printf("Whoops, the program crashed. Could not catch the signal type.\n"); printf("Please report this to %s.\n\n", ERRORS_TO); syslog(LOG_ERR, "SIGUNKNOWN caught"); (void) fflush(stdout); log(LOG_ERROR, "Signal: Unknown signal", " "); exit(PROGRAM_BUG); } } /* * START_HANDLER * * This simply starts the signal handler */ void start_handler(void) { int sigs = 24, i = 0; int signals[] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH }; /* BSD/OS sends these... */ signal(SIGCHLD, SIG_IGN); for (i = 0; i < sigs; i++) signal(signals[i], int_handler); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/standard.c0100644000076500001440000006026006774334770014753 0ustar joeyusers/* * CFINGERD * Standard finger handler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #ifdef BSD #include "getutent.h" #endif #ifndef __FreeBSD__ #include #endif /* !__FreeBSD__ */ #include #include #include "privs.h" int columns; int times_on; typedef struct { char tty[UT_LINESIZE]; char locale[UT_HOSTSIZE]; long ip_addr; time_t time; BOOL writable; } TTY_FROM; #define MAX_TTYS 64 TTY_FROM tty_list[MAX_TTYS]; static int uid, nuid, ngid; /* * DO_COLUMNS * * This simply sends a carriage return if there was more than one column * already displayed on the screen. */ void do_columns(void) { if (columns > 1) { printf("\n"); columns = 0; } } /* * CHECK_ILLEGAL * * Check to make sure that the specified file given for the user * isn't an illegal file. */ BOOL check_illegal(char *str, char *user) { struct stat statbuf; if ((lstat(str, (struct stat *) &statbuf)) < 0) return(FALSE); if (!S_ISREG(statbuf.st_mode)) { syslog(LOG_NOTICE, "%s's file %s is NOT A REGULAR FILE.", user, str); return(FALSE); } return(TRUE); } /* * SHOW_STUFF * * This shows data that is parsed correctly to the number of characters * specified in t2. T1 is the actual bit that is checked for. */ void show_stuff(char *user, int t1, int t2) { BOOL can_show = FALSE; char formatter[80]; if (local_finger) { if (prog_config.local_config_bits1 & t1) can_show = TRUE; } else { if (prog_config.config_bits1 & t1) can_show = TRUE; } if (can_show) { columns++; snprintf(formatter, sizeof(formatter), "%%s%%-%d.%ds", (36 - strlen(prog_config.p_strings[t2])), 36); printf(formatter, prog_config.p_strings[t2], user?user:""); do_columns(); } } /* * EXIST * * Check whether the specified filename exists or not. */ BOOL exist(char *filename) { FILE *f; if (!filename) return(FALSE); f = fopen(filename, "r"); if (f) { fclose(f); return(TRUE); } else return(FALSE); } /* * SHOW_PFILE * * This simply shows specified data for each option that users would * normally expect. (What else was I supposed to say? :) */ void show_pfile(uid_t uid, gid_t gid, int t1, int t2, int t3, char *dir, char *disp, BOOL send_ret) { BOOL can_show = FALSE; FILE *file = NULL; if (local_finger) { if (prog_config.local_config_bits2 & t1) can_show = TRUE; } else { if (prog_config.config_bits2 & t1) can_show = TRUE; } if (can_show) { char d[128]; memset(d, 0, 128); snprintf(d, sizeof(d), "%s/%s", dir, disp); if (!(prog_config.config_bits3 & SHOW_HEADERS_FE)) { printf("%s\n", prog_config.p_strings[t2]); fflush(stdout); } if (exist(d)) { NOBODY_PRIVS; if (prog_config.config_bits3 & SHOW_HEADERS_FE) { printf("%s\n", prog_config.p_strings[t2]); fflush(stdout); } if ((file = open_file(d)) != NULL) display_file(uid, gid, file); } else { if (!(prog_config.config_bits3 & SHOW_HEADERS_FE)) printf("%s\n", prog_config.p_strings[t3]); else send_ret = 0; } } if (send_ret) SEND_RAW_RETURN; } /* * SHOW_PFILE2 * * This simply shows specified data for each option that users would * normally expect. (What else was I supposed to say? :) */ void show_pfile2(uid_t uid, gid_t gid, int t1, int t2, int t3, char *dir, char *disp, BOOL send_ret) { BOOL can_show = FALSE; FILE *file = NULL; if (local_finger) { if (prog_config.local_config_bits3 & t1) can_show = TRUE; } else { if (prog_config.config_bits3 & t1) can_show = TRUE; } if (can_show) { char d[128]; snprintf(d, sizeof(d), "%s/%s", dir, disp); if (!(prog_config.config_bits3 & SHOW_HEADERS_FE)) { printf("%s\n", prog_config.p_strings[t2]); fflush(stdout); } if (exist(d)) { NOBODY_PRIVS; if (prog_config.config_bits3 & SHOW_HEADERS_FE) { printf("%s\n", prog_config.p_strings[t2]); fflush(stdout); } if ((open_file (d)) != NULL) display_file(uid, gid, file); } else { if (!(prog_config.config_bits3 & SHOW_HEADERS_FE)) printf("%s\n", prog_config.p_strings[t3]); } } if (send_ret) SEND_RAW_RETURN; } /* * SHOW_LASTTIME_ON * * This routine simply shows the last time "user" was on. */ void show_lasttime_on(char *user) { int fd; BOOL found = FALSE, can_show_orig = FALSE; char formatted[80]; #ifndef USE_LASTLOG struct utmp ut; #else struct lastlog lastlog; #endif TTY_FROM last_tty; NOBODY_PRIVS; fd = open(WTMPFILE, O_RDONLY); #ifndef USE_LASTLOG if (fd != -1) { while (!found) { if (read(fd, &ut, sizeof(struct utmp)) != sizeof (struct utmp)) found = TRUE; #ifdef BSD if (!strncmp(user, (char *) ut.ut_name, strlen(user))) { last_tty.ip_addr = 0; #else if (!strncmp(user, (char *) ut.ut_user, strlen(user))) { strncpy(last_tty.tty, ut.ut_line, UT_LINESIZE - 1); last_tty.tty[UT_LINESIZE - 1] = 0; #endif strncpy(last_tty.locale, ut.ut_host, UT_HOSTSIZE - 1); last_tty.locale[UT_HOSTSIZE - 1] = 0; #ifdef SUNOS last_tty.ip_addr = 0; #else last_tty.ip_addr = ut.ut_addr; #endif last_tty.time = ut.ut_time; } } } #else if (fd != -1) { /* Since in lastlog, you can seek to the user's UID and get info, we do that here. */ if (lseek(fd, (sizeof(lastlog) * uid), SEEK_SET) == -1) { printf("Seek: %s\n", strerror(errno)); fflush(stdout); } if (read(fd, &lastlog, sizeof(lastlog)) == sizeof(lastlog)) { found = TRUE; strncpy(last_tty.tty, lastlog.ll_line, UT_LINESIZE - 1); last_tty.tty[UT_LINESIZE - 1] = 0; strncpy(last_tty.locale, lastlog.ll_host, UT_HOSTSIZE - 1); last_tty.locale[UT_HOSTSIZE - 1] = 0; last_tty.time = lastlog.ll_time; } } #endif close(fd); if (local_finger) { if (prog_config.local_config_bits1 & SHOW_FROM) can_show_orig = TRUE; } else { if (prog_config.config_bits1 & SHOW_FROM) can_show_orig = TRUE; } if (last_tty.time > 0L) { strftime(formatted, 80, prog_config.ltime_format, localtime(&last_tty.time)); printf("Last seen %s", (char *) formatted); } else { printf("This user has never logged in."); } if ((can_show_orig) && (last_tty.time > 0L)) printf("%s %s", (strlen((char *) last_tty.locale) > 1) ? " from" : " ", (strlen((char *) last_tty.locale) > 1) ? (char *) last_tty.locale : " "); if (!(prog_config.config_bits2 & SHOW_STRICTFMT)) printf("\n"); fflush(stdout); } /* * SHOW_NOT_ONLINE * * This shows whether or not the user is online. */ void show_not_online(char *user) { BOOL can_show = FALSE, can_show_lasttime = FALSE; NOBODY_PRIVS; if (local_finger) { if (prog_config.local_config_bits1 & SHOW_IFON) can_show = TRUE; } else { if (prog_config.config_bits1 & SHOW_IFON) can_show = TRUE; } if (local_finger) { if (prog_config.local_config_bits1 & SHOW_LTON) can_show_lasttime = TRUE; } else { if (prog_config.config_bits1 & SHOW_LTON) can_show_lasttime = TRUE; } if (can_show) { if (can_show_lasttime) show_lasttime_on(user); else { printf("This user is not currently logged in.\n"); fflush(stdout); } } } /* * SHOW_IDLE * * This routine shows how long the user has been idle on the "tty" */ void show_idle(char *tty) { struct stat buf; time_t cur_time; long diff_time; int sec, min, hour, day, has; char dev_file[80]; sprintf(dev_file, "/dev/%s", tty); USER_PRIVS(nuid, ngid); stat((char *) dev_file, &buf); NOBODY_PRIVS; cur_time = time(NULL); diff_time = (long) cur_time - (long) buf.st_mtime; sec = min = hour = day = has = 0; if (diff_time > 86400) day = hour = has = 1; else if (diff_time > 3600) hour = min = has = 1; else if (diff_time > 59) min = sec = has = 1; else if (diff_time > 0) sec = has = 1; if (has) printf(" Idle "); if (day) { day = diff_time / 86400; diff_time -= day * 86400; printf("%d %s ", day, (day > 1) ? "days" : "day"); } if (hour) { hour = diff_time / 3600; diff_time -= hour * 3600; if (prog_config.config_bits2 & SHOW_TIMESTAMP) printf("%d %s ", hour, (hour > 1) ? "hours" : "hour"); else printf("%02d:", hour); } else if (!(prog_config.config_bits2 & SHOW_TIMESTAMP) && has) printf("00:"); if (min) { min = diff_time / 60; diff_time -= min * 60; if (prog_config.config_bits2 & SHOW_TIMESTAMP) printf("%d %s ", min, (min > 1) ? "minutes" : "minute"); else printf("%02d:", min); } else if (!(prog_config.config_bits2 & SHOW_TIMESTAMP) && has) printf("00:"); if (sec) { sec = diff_time; if (prog_config.config_bits2 & SHOW_TIMESTAMP) printf("%d %s", sec, (sec > 1) ? "seconds" : "second"); else printf("%02d", sec); } else if (!(prog_config.config_bits2 & SHOW_TIMESTAMP) && has) printf("00"); } /* * SHOW_TIMES_ON * * This shows the number of times the user has logged in, and how long the * user has been on on each TTY. Don't ask why it was a void routine. */ void show_times_on(void) { int i; BOOL can_show = FALSE, can_show_orig = FALSE; NOBODY_PRIVS; if (local_finger) { if (prog_config.local_config_bits1 & SHOW_IFON) can_show = TRUE; } else { if (prog_config.config_bits1 & SHOW_IFON) can_show = TRUE; } if (local_finger) { if (prog_config.local_config_bits1 & SHOW_FROM) can_show_orig = TRUE; } else { if (prog_config.config_bits1 & SHOW_FROM) can_show_orig = TRUE; } if (can_show) { if (!(prog_config.config_bits2 & SHOW_STRICTFMT)) SEND_RAW_RETURN; for (i = 0; (i < times_on) && (i < MAX_TTYS) ; i++) { char formatted[80]; strftime(formatted, 80, prog_config.ltime_format, localtime(&tty_list[i].time)); printf("On since %s on %s", formatted, (char *) tty_list[i].tty); show_idle((char *) tty_list[i].tty); if (can_show_orig) printf("%s %s", (strlen((char *) tty_list[i].locale) > 1) ? " from" : "", (strlen((char *) tty_list[i].locale) > 1) ? (char *) tty_list[i].locale : ""); if (!(tty_list[i].writable)) printf(" [MSG-N]"); SEND_RAW_RETURN_NO_FLUSH; } } fflush(stdout); } /* * SHOW_LOGIN_STATUS * * This shows the login status of the specified user, showing how many times * they are logged in, how long they've been idle, and other necessities. */ void show_login_stats(char *user) { struct utmp *ut; times_on = 0; while((ut = getutent()) != NULL) { #ifdef BSD if (!strncmp(user, (char *) ut->ut_name, strlen(user)) && (strlen((char *) ut->ut_name) == strlen(user))) { #else if (ut->ut_type == USER_PROCESS) if (!strncmp(user, (char *) ut->ut_user, strlen(user)) && (strlen((char *) ut->ut_user) == strlen(user))) { #endif struct stat buf; char devfile[80]; if (times_on < MAX_TTYS) { strncpy(tty_list[times_on].tty, (char *) ut->ut_line, sizeof(tty_list[times_on].tty)); strncpy(tty_list[times_on].tty, (char *) ut->ut_line, UT_LINESIZE - 1); tty_list[times_on].tty[UT_LINESIZE-1] = 0; sprintf(devfile, "/dev/%s", (char *) ut->ut_line); USER_PRIVS(nuid, ngid); stat(devfile, &buf); NOBODY_PRIVS; #ifdef HAS_TTY_GROUP if (buf.st_mode & S_IWGRP) #else if ((buf.st_mode & S_IWGRP) && (buf.st_mode & S_IWOTH)) #endif tty_list[times_on].writable = TRUE; else tty_list[times_on].writable = FALSE; #if defined(BSD) || defined(SUNOS) tty_list[times_on].ip_addr = 0; #else tty_list[times_on].ip_addr = ut->ut_addr; #endif strncpy(tty_list[times_on].locale, (char *) ut->ut_host, UT_HOSTSIZE - 1); tty_list[times_on].locale[UT_HOSTSIZE - 1] = 0; tty_list[times_on].time = ut->ut_time; } times_on++; } } if (times_on > 0) { show_times_on(); if (!(prog_config.config_bits2 & SHOW_STRICTFMT)) SEND_RAW_RETURN; } else { show_not_online(user); if (!(prog_config.config_bits2 & SHOW_STRICTFMT)) SEND_RAW_RETURN; } fflush(stdout); } /* * SHOW_MAIL_STATS * * This shows whether the specified user has mail, and how long ago the * user read mail. */ void show_mail_stats(char *user) { struct stat buf; char mailfile[200]; BOOL can_show = FALSE, can_show_date = FALSE; if (local_finger) { if (prog_config.local_config_bits1 & SHOW_LRMAIL) can_show = TRUE; } else { if (prog_config.config_bits1 & SHOW_LRMAIL) can_show = TRUE; } if (local_finger) { if (prog_config.local_config_bits1 & SHOW_MRDATE) can_show_date = TRUE; } else { if (prog_config.config_bits1 & SHOW_MRDATE) can_show_date = TRUE; } if (can_show) { char formatted[80]; int fm; char *cp, *xp, *yp; struct passwd *pwent = NULL; /* * Expand mailbox, $HOME and $USER are supported. */ memset (mailfile, 0, sizeof(mailfile)); for (cp=prog_config.mailbox_file,xp=mailfile;*cp&&strlen(mailfile)pw_dir;*yp&&strlen(mailfile) buf.st_atime) { char formatted2[80]; strftime(formatted2, 80, prog_config.ltime_format, localtime(&buf.st_mtime)); printf("This user has unread mail since %s\n", (char *) formatted2); } } } else printf("This user has no mail or mail spool.\n"); } } /* * SHOW_QMAIL_STATS * * This shows whether the specified user has mail, and how long ago the * user read mail. */ void show_qmail_stats(char *user, char *homedir, char *alias) { struct stat newbuf; struct stat tmpbuf; char mailfile[80]; BOOL can_show = FALSE, can_show_date = FALSE; char *nomailmsg = "This user has no mail or mail spool.\n"; if (local_finger) { if (prog_config.local_config_bits1 & SHOW_LRMAIL) can_show = TRUE; } else { if (prog_config.config_bits1 & SHOW_LRMAIL) can_show = TRUE; } if (local_finger) { if (prog_config.local_config_bits1 & SHOW_MRDATE) can_show_date = TRUE; } else { if (prog_config.config_bits1 & SHOW_MRDATE) can_show_date = TRUE; } if (can_show) { char formatted[80]; char line[80]; int fm; FILE *qmf = NULL; /* open ~/.qmail-alias or ~/.qmail */ if(alias != NULL) snprintf(mailfile, sizeof(mailfile), "%s/.qmail-%s", homedir, alias); else snprintf(mailfile, sizeof(mailfile), "%s/.qmail", homedir); USER_PRIVS(nuid, ngid); qmf = fopen(mailfile, "r"); NOBODY_PRIVS; if(qmf == NULL) { printf("No .qmail file.\n"); return; } line[0] = '\0'; /* We get the first line starting with '.' or '/' */ USER_PRIVS(nuid, ngid); while(qmf != NULL && fgets(line, sizeof(line), qmf)) { if(line[0] != '.' && line[0] != '/') line[0] = '\0'; else break; } fclose(qmf); NOBODY_PRIVS; if(line[0] == '\0') { printf("No local mail storage.\n"); return; } /* chdir() to home dir for paths relative to ~ */ if(chdir(homedir) == -1) return; if(line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; /* If the last char is not '/' then it's a sendmail format mail file and we use the old routines. */ if(line[strlen(line) - 1] != '/') { USER_PRIVS(nuid, ngid); fm = stat(line, &newbuf); NOBODY_PRIVS; if (fm != -1) { if (can_show_date) { strftime(formatted, 80, prog_config.ltime_format, localtime(&newbuf.st_atime)); } else { strftime(formatted, 80, prog_config.stime_format, localtime(&newbuf.st_atime)); } if ((int) newbuf.st_size == 0) printf("This user has no mail.\n"); else { printf("This user last read mail %s\n", (char *) formatted); if (newbuf.st_mtime > newbuf.st_atime) { char formatted2[80]; strftime(formatted2, 80, prog_config.ltime_format, localtime(&newbuf.st_mtime)); printf("This user has unread mail since %s\n", (char *) formatted2); } } } else printf(nomailmsg); } else { snprintf(mailfile, sizeof(mailfile), "%snew", line); USER_PRIVS(nuid, ngid); fm = stat(mailfile, &newbuf); if(fm == -1) { printf(nomailmsg); return; } snprintf(mailfile, sizeof(mailfile), "%stmp", line); fm = stat(mailfile, &tmpbuf); if(fm == -1) { printf(nomailmsg); return; } NOBODY_PRIVS; if (can_show_date) { strftime(formatted, 80, prog_config.ltime_format, localtime(&tmpbuf.st_atime)); } else { strftime(formatted, 80, prog_config.stime_format, localtime(&tmpbuf.st_atime)); } if ((int) newbuf.st_size == 0) printf("This user has no mail.\n"); else { printf("This user last read mail %s\n", (char *) formatted); if (newbuf.st_mtime > tmpbuf.st_atime) { char formatted2[80]; strftime(formatted2, 80, prog_config.ltime_format, localtime(&newbuf.st_mtime)); printf("This user has unread mail since %s\n", (char *) formatted2); } } } } } /* * SHOW_FINGERINFO * * This shows correct finger information for the specified "user" */ void show_fingerinfo(char *user) { struct passwd *pwent; FILE *file; char *username=NULL, *room=NULL, *work_phone=NULL, *home_phone=NULL, *other=NULL; char fn[80]; BOOL qmail; char acctname[100]; char *alias = NULL; char *cp, *x; columns = 0; qmail = ( strcasecmp(prog_config.mailbox_file, "QMAIL") == 0); if(qmail) { strncpy(acctname, user, sizeof(acctname) -1); acctname[sizeof(acctname) -1] = '\0'; strtok(acctname, "-"); alias = strtok(NULL, "-"); pwent = getpwnam(acctname); } else { pwent = getpwnam(user); } /* Do a quick/dirty sanity check. */ if(pwent == NULL) { show_bottom(); return; } uid = pwent->pw_uid; /* For changing to the correct UID/GID */ nuid = pwent->pw_uid; ngid = pwent->pw_gid; cp = pwent->pw_gecos; if ((x = index (cp, ',')) != NULL) { /* username */ if ((username = (char *)malloc (x-cp+1)) != NULL) { memset (username, 0, x-cp+1); strncpy (username, cp, x-cp); } cp = ++x; if ((x = index (cp, ',')) != NULL) { /* room */ if ((room = (char *)malloc (x-cp+1)) != NULL) { memset (room, 0, x-cp+1); strncpy (room, cp, x-cp); } cp = ++x; if ((x = index (cp, ',')) != NULL) { /* work phone */ if ((work_phone = (char *)malloc (x-cp+1)) != NULL) { memset (work_phone, 0, x-cp+1); strncpy (work_phone, cp, x-cp); } cp = ++x; if ((x = index (cp, ',')) != NULL) { /* home phone */ if ((home_phone = (char *)malloc (x-cp+1)) != NULL) { memset (home_phone, 0, x-cp+1); strncpy (home_phone, cp, x-cp); } cp = ++x; if ((x = index (cp, ',')) != NULL) /* other */ *x = '\0'; if ((other = (char *)malloc (strlen(cp)+1)) != NULL) { memset (other, 0, strlen(cp)+1); strcpy (other, cp); } } else { /* no comma, thus string is home phone */ if ((home_phone = (char *)malloc (strlen(cp)+1)) != NULL) { memset (home_phone, 0, strlen(cp)+1); strcpy (home_phone, cp); } } } } } else { /* no comma, thus whole string is username */ if ((username = (char *)malloc (strlen(cp)+1)) != NULL) { memset (username, 0, strlen(cp)+1); strcpy (username, cp); } } if ((prog_config.no_finger_file != NULL) && (strlen(pwent->pw_dir)+strlen(prog_config.no_finger_file)+1 < sizeof(fn))) sprintf(fn, "%s/%s", pwent->pw_dir, prog_config.no_finger_file); else if (strlen(pwent->pw_dir)+10 < sizeof(fn)) sprintf(fn, "%s/.nofinger", pwent->pw_dir); else fn[0] = '\0'; if (exist(fn)) { if (!check_illegal((char *) fn, user)) { show_bottom(); exit(PROGRAM_SYSLOG); } } USER_PRIVS(nuid, ngid); if ((file = fopen(fn, "r")) != NULL) { NOBODY_PRIVS; display_file(nuid, ngid, file); } else { NOBODY_PRIVS; show_stuff(user, SHOW_UNAME, D_USERNAME); show_stuff(username, SHOW_REALNAME, D_REALNAME); show_stuff(pwent->pw_dir, SHOW_DIR, D_DIRECTORY); show_stuff(pwent->pw_shell, SHOW_SHELL, D_SHELL); show_stuff((char *) room, SHOW_ROOM, D_ROOM); show_stuff((char *) work_phone, SHOW_WPHONE, D_WORK_PHONE); show_stuff((char *) home_phone, SHOW_HPHONE, D_HOME_PHONE); show_stuff((char *) other, SHOW_OTHER, D_OTHER); if ((prog_config.config_bits3 & SHOW_USERLOG) && (prog_config.userlog_file != NULL)) userlog(pwent->pw_uid, pwent->pw_gid, pwent->pw_dir, ident_user); /* For sanity sake, and to make the display look prettier... */ columns++; do_columns(); if (!(prog_config.config_bits2 & SHOW_STRICTFMT)) SEND_RAW_RETURN; if(qmail) show_qmail_stats(acctname, pwent->pw_dir, alias); else show_mail_stats(user); show_login_stats(user); if (prog_config.config_bits2 & SHOW_STRICTFMT) SEND_RAW_RETURN; show_pfile(nuid, ngid, SHOW_PROJECT, D_PROJECT, D_NO_PROJECT, pwent->pw_dir, prog_config.project_file, (prog_config.config_bits2 & SHOW_STRICTFMT) ? FALSE : TRUE); show_pfile(nuid, ngid, SHOW_PLAN, D_PLAN, D_NO_PLAN, pwent->pw_dir, prog_config.plan_file, (prog_config.config_bits2 & SHOW_STRICTFMT) ? FALSE : TRUE); /* Thanks to Andy Smith */ show_pfile(nuid, ngid, SHOW_PGPKEY, D_PGPKEY, D_NO_PGPKEY, pwent->pw_dir, prog_config.pgpkey_file, (prog_config.config_bits2 & SHOW_STRICTFMT) ? FALSE : TRUE); show_pfile2(nuid, ngid, SHOW_XFACE, D_XFACE, D_NO_XFACE, pwent->pw_dir, prog_config.xface_file, FALSE); } } /* * HANDLE_STANDARD * * This handles the standard fingering of a user, and checks whether or not * the user actually exists. */ void handle_standard(char *username) { char uname[600]; int nums = 0; char *buf; /* ** Support to change the "/W" or "-L" listings from Microsoft's ** bloated finger program. This combats their options, and ignores ** them. ** ** Ken Hollis 08/06/96 */ if (username[0] == '/' || username[0] == '-') { nums=1; if (username[2] == ' ') nums++; strcpy(uname, username + nums); strcpy(username, uname); } if ((!(prog_config.config_bits2 & SHOW_FINGERFWD)) || check_exist(username)) show_top(); if( !( strcmp(prog_config.mailbox_file, "QMAIL") == 0 && check_exist_alias(username) ) && !check_exist(username)) { if (prog_config.config_bits2 & SHOW_FINGERFWD) { while(prog_config.forward[nums] != NULL) { memset(uname, 0, 600); printf("\nChecking site %s for the specified user.\n", prog_config.forward[nums]); fflush(stdout); snprintf(uname, sizeof(uname), "/usr/bin/finger \"%s\100%s\" | /usr/bin/tail +2", username, prog_config.forward[nums]); if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, uname)) != NULL) { printf ("%s", buf); fflush(stdout); free (buf); } nums++; log(LOG_USER, "Forwarded: ", username); } } else { show_notexist(); } } else { show_fingerinfo(username); log(LOG_USER, "Normal: ", username); } if ((!(prog_config.config_bits2 & SHOW_FINGERFWD)) || check_exist(username)) { show_bottom(); } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/strmcpy.c0100644000076500001440000000217206612161615014635 0ustar joeyusers/* * CFINGERD * String copy with automatic memory allocation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include /* * STRMCPY * * DO NOT PREVIOUSLY ALLOCATE MEMORY! This routine will automatically do * the memory allocations for you. This is an advanced version of strcpy, * but returns memory allocation. Very handy. */ void strmcpy(char **t, const char *s) { if (*t != NULL) free(*t); *t = malloc(strlen(s) + 1); if (*t == NULL) { syslog(LOG_ERR, "strmcpy: alloc error"); exit(1); } (void) strcpy(*t, s); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/userlist.c0100644000076500001440000000770606762202005015011 0ustar joeyusers/* * CFINGERD * Userlist handler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #include "privs.h" /* * HANDLE_USERLIST * * This routine simply handles the displaying of the userlist. */ void handle_userlist(char *username) { BOOL can_show = FALSE; char *buf; int head = 0; if (local_finger) { if (prog_config.local_config_bits2 & SHOW_SYSTEMLIST) can_show = TRUE; } else { if (prog_config.config_bits2 & SHOW_SYSTEMLIST) can_show = TRUE; } show_top(); if (can_show) { int i; char cmdline[128]; if ((num_finger_sites > 1) && prog_config.config_bits2 & SHOW_MULTFING) { printf("%s\n", prog_config.p_strings[D_WAIT]); fflush(stdout); } NOBODY_PRIVS; if (prog_config.config_bits2 & SHOW_MULTFING) { for (i = 0; i < num_finger_sites; i++) { if (!strncmp(prog_config.finger_sites[i], "localhost", 9)) { if (!strcmp (username, "userlist")) snprintf(cmdline, sizeof (cmdline), "%s -n | /usr/bin/tail +2", prog_config.finger_program); else snprintf(cmdline, sizeof (cmdline), "%s | /usr/bin/tail +2", prog_config.finger_program); if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, cmdline)) != NULL) { if (!head) { printf ("Username Real name Idletime TTY Remote console location\n"); head = 1; } printf ("%s", buf); fflush(stdout); free (buf); } } else { if (!strcmp (username, "userlist")) snprintf(cmdline, sizeof(cmdline), "/usr/bin/finger userlist-online@%s | tail +2 | grep -v '^$'", prog_config.finger_sites[i]); else snprintf(cmdline, sizeof(cmdline), "/usr/bin/finger userlist-only@%s | tail +2 | grep -v '^$'", prog_config.finger_sites[i]); if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, cmdline)) != NULL) { if (!head) { printf ("Username Real name Idletime TTY Remote console location\n"); head = 1; } printf ("%s", buf); fflush(stdout); free (buf); } } } } else { if ((!strstr(prog_config.finger_program, "finger")) && (!strstr(prog_config.finger_program, "w"))) snprintf(cmdline, sizeof(cmdline), "%s | /usr/bin/tail +2", prog_config.finger_program); else snprintf(cmdline, sizeof(cmdline), "%s", prog_config.finger_program); if ((buf = safe_exec(NOBODY_UID, NOBODY_GID, cmdline)) != NULL) { if (!head) { printf("Username Real name Idletime TTY Remote console location\n"); head = 1; } printf ("%s", buf); fflush(stdout); free (buf); } } if (!head) printf ("Nobody logged in.\n"); if ((num_finger_sites > 1) && prog_config.config_bits2 & SHOW_MULTFING) printf("\n**> This is the complete listing of %d sites total.\n", num_finger_sites); if ((num_finger_sites > 1) && prog_config.config_bits2 & SHOW_MULTFING) SEND_RAW_RETURN; fflush(stdout); /* if ((num_finger_sites > 1) && prog_config.config_bits2 & SHOW_MULTFING) { printf("*** This is a list of %dsystems.\n",num_finger_sites); } */ } else { can_show = FALSE; if (local_finger) { if (prog_config.local_config_bits2 & SHOW_NN_BANNER) can_show = TRUE; } else { if (prog_config.config_bits2 & SHOW_NN_BANNER) can_show = TRUE; } if (can_show) display_file(NOBODY_UID, NOBODY_GID, noname_display); } show_bottom(); log(LOG_USER, "Userlist request", " "); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/util.c0100644000076500001440000003541206774334770014131 0ustar joeyusers/* * CFINGERD * Utilities * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #include "version.h" #ifdef BSD #include "getutent.h" #endif #include "privs.h" #include /* * CLEAR_CFINGERD_VARS * * This clears out memory for the program configuration variables. */ void clear_cfingerd_vars(void) { int i; prog_config.top_display_file = NULL; prog_config.bottom_display_file = NULL; prog_config.plan_file = NULL; prog_config.project_file = NULL; prog_config.pgpkey_file = NULL; prog_config.xface_file = NULL; prog_config.userlog_file = NULL; prog_config.mailbox_file = NULL; prog_config.no_name_banner_file = NULL; prog_config.no_user_banner_file = NULL; prog_config.no_finger_file = NULL; prog_config.identd_banner_file = NULL; prog_config.rejected_file = NULL; prog_config.syslog_file = NULL; prog_config.finger_program = NULL; prog_config.whois_program = NULL; for (i = 0; i < 80; i++) { prog_config.rejected[i] = NULL; prog_config.trusted[i] = NULL; prog_config.forward[i] = NULL; prog_config.p_strings[i] = NULL; prog_config.finger_sites[i] = NULL; } for (i = 0; i < 24; i++) prog_config.siglist[i] = NULL; memset (prog_config.stime_format, 0, sizeof (prog_config.stime_format)); memset (prog_config.ltime_format, 0, sizeof (prog_config.ltime_format)); for (i = 0; i < 40; i++) { prog_config.fusers[i].user = NULL; prog_config.fusers[i].script = NULL; prog_config.fusers[i].description = NULL; prog_config.fusers[i].searchable = FALSE; } for (i = 0; i < 20; i++) prog_config.services.header[i] = NULL; prog_config.services.display_string = NULL; prog_config.services.name_pos = 0; prog_config.services.service_pos = 0; prog_config.services.search_pos = 0; prog_config.config_bits1 = 0; prog_config.config_bits2 = 0; prog_config.config_bits3 = 0; prog_config.local_config_bits1 = 0; prog_config.local_config_bits2 = 0; prog_config.local_config_bits3 = 0; prog_config.override_bits1 = 0; prog_config.override_bits2 = 0; } /* * START_CFINGERD * * This simply clears out memory, and changes the program ID name for * syslog. */ void start_cfingerd(void) { int pid = getpid(); char *proc; proc = (char *) malloc(20); sprintf(proc, "cfingerd[%d]", pid); openlog(proc, LOG_NDELAY, LOG_DAEMON); clear_cfingerd_vars(); } /* * SET_TIME_FORMAT * * Sets two format strings for time formatting, according to clock24. */ void set_time_format() { if (((local_finger) && (prog_config.local_config_bits3 & SHOW_CLOCK24)) || ((!local_finger) && (prog_config.config_bits3 & SHOW_CLOCK24))) { strncpy (prog_config.stime_format, "%H:%M (%Z)", sizeof (prog_config.stime_format)); strncpy (prog_config.ltime_format, "%a %b %d %H:%M (%Z)", sizeof (prog_config.ltime_format)); } else { strncpy (prog_config.stime_format, "%I:%M %p (%Z)", sizeof (prog_config.stime_format)); strncpy (prog_config.ltime_format, "%a %b %d %I:%M %p (%Z)", sizeof (prog_config.ltime_format)); } } /* * CHECK_STATS * * This program checks statistics on the program to make sure the settings * on the program are correct. */ void check_stats() { if (!emulated) { if (isatty(0)) { syslog(LOG_ERR, "cfingerd run from command line/daemon"); CF_ERROR(E_INETD); } } } /* * PARSE_LINE * * This routine simply parses a string given to the routine, and displays * information accordingly. */ #define DISPLEN 160 void parse_line(uid_t uid, gid_t gid, char *line) { int pos = 0, newpos = 0, done = FALSE, center_flag = FALSE, exec_line = FALSE; char command[80], *displine; char *buf; displine = (char *) malloc(DISPLEN); memset(displine, 0, DISPLEN); while(pos < strlen(line)) { if (line[pos] != '$') { if (!exec_line) { if (center_flag) { char allocation[2]; memset(allocation, 0, 2); allocation[0] = line[pos]; displine = strncat(displine, (char *) allocation, DISPLEN); } else printf("%c", line[pos]); } pos++; } else { done = FALSE; newpos = 0; memset(command, 0, 80); pos++; while((line[pos] != ' ') && (!done)) { command[newpos] = line[pos]; if (line[pos] == ' ') done = TRUE; if (pos >= strlen(line)) done = TRUE; newpos++; pos++; if (command[0] == '$') { if (center_flag) displine = strncat(displine, "$", DISPLEN); else printf("$"); done = TRUE; } if (strlen(command) >= 4) { if ((!strncasecmp(command, "time", 4)) && (strlen(command) == 4)) { time_t tim = time(NULL); char bleah[80]; strftime(bleah, 80, prog_config.stime_format, localtime(&tim)); if (center_flag) displine = strncat(displine, (char *) bleah, DISPLEN); else printf((char *) bleah); done = TRUE; } if ((!strncasecmp(command, "date", 4)) && (strlen(command) == 4)) { time_t tim = time(NULL); char bleah[80]; strftime(bleah, 80, "%a %b %d", localtime(&tim)); if (center_flag) displine = strncat(displine, (char *) bleah, DISPLEN); else printf((char *) bleah); done = TRUE; } if ((!strncasecmp(command, "ident", 5)) && (strlen(command) == 5)) { if (center_flag) displine = strncat(displine, ident_user, DISPLEN); else printf("%s", ident_user); done = TRUE; } if ((!strncasecmp(command, "center", 6)) && (strlen(command) == 6)) { center_flag = TRUE; done = TRUE; } if ((!strncasecmp(command, "compile_datetime", 16)) && (strlen(command) == 16)) { if (center_flag) displine = strncat(displine, (char *) COMPILE_DT, DISPLEN); else printf("%s", (char *) COMPILE_DT); done = TRUE; } if ((!strncasecmp(command, "version", 7)) && (strlen(command) == 7)) { if (center_flag) displine = strncat(displine, (char *) VERSION, DISPLEN); else printf("%s", (char *) VERSION); done = TRUE; } if ((!strncasecmp(command, "exec", 4)) && (strlen(command) == 4) && (prog_config.config_bits3 & SHOW_EXEC)) { char *cp; cp=line; cp+=6; /* forward "$exec " */ exec_line = TRUE; if ((buf = safe_exec (uid, gid, cp)) != NULL) { printf ("%s", buf); fflush(stdout); free (buf); } done = TRUE; } } } } } if (center_flag) { int center_dist = 40 - (strlen(displine) / 2) - 1; int x; if (center_dist > 0) for(x = 0; x < center_dist; x++) printf(" "); printf(displine); free(displine); } } /* * DISPLAY_FILE * * This displays the file specified. */ void display_file(uid_t uid, gid_t gid, FILE *file_ent) { char line[128]; int bsize = sizeof(line); if (file_ent) { while(fgets(line, bsize, file_ent)) { if (prog_config.config_bits3 & SHOW_PARSING) parse_line(uid, gid, line); else fputs(line, stdout); } fflush(stdout); fclose(file_ent); } } /* * SHOW_TOP * * This shows the top (or header) file. */ void show_top(void) { BOOL can_show = FALSE; if (local_finger) { if (prog_config.local_config_bits1 & SHOW_TOP) can_show = TRUE; } else { if (prog_config.config_bits1 & SHOW_TOP) can_show = TRUE; } if (can_show) display_file(NOBODY_UID, NOBODY_GID, top_display); } /* * CHECK_EXIST * * Check whether a username exists. */ BOOL check_exist(char *username) { struct passwd *pwent; pwent = getpwnam(username); return((pwent != NULL) ? TRUE : FALSE); } /* * CHECK_EXIST_ALIAS * * Check whether a Qmail user alias exists. */ BOOL check_exist_alias(char *username) { struct passwd *pwent; char acctname[100]; strncpy(acctname, username, 100); acctname[sizeof(acctname) - 1] = '\0'; strtok(acctname, "-"); pwent = getpwnam(acctname); if(pwent) { char qmfile[1024]; snprintf(qmfile, 1024, "%s/.qmail-%s", pwent->pw_dir , &acctname[strlen(acctname) + 1]); return exist(qmfile); } return FALSE; } /* * SHOW_NOTEXIST * * Show the nouser banner if the user doesn't exist. */ void show_notexist(void) { BOOL can_show = FALSE; if (local_finger) { if (prog_config.local_config_bits2 & SHOW_NOUSER) can_show = TRUE; } else { if (prog_config.config_bits2 & SHOW_NOUSER) can_show = TRUE; } if (can_show) display_file(NOBODY_UID, NOBODY_GID, nouser_display); } /* * SHOW_BOTTOM * * Show the bottom (or footer) file. */ void show_bottom(void) { BOOL can_show = FALSE; if (local_finger) { if (prog_config.local_config_bits1 & SHOW_BOTTOM) can_show = TRUE; } else { if (prog_config.config_bits1 & SHOW_BOTTOM) can_show = TRUE; } if (can_show) display_file(NOBODY_UID, NOBODY_GID, bottom_display); } /* * INETTOS * * Change INET address string to the "dot" ordered pair. */ char *inettos(long addr) { char *ret; int pair1, pair2, pair3, pair4; ret = (char *) malloc(20); pair1 = (addr & 0x000000FF); pair2 = (addr & 0x0000FF00) >> 8; pair3 = (addr & 0x00FF0000) >> 16; pair4 = (addr & 0xFF000000) >> 24; sprintf(ret, "%d.%d.%d.%d", pair1, pair2, pair3, pair4); return(ret); } /* * GET_LOCALHOST * * Get the name of the local host computer. */ char *get_localhost(void) { char *ret; char hostname[80], domname[80]; gethostname((char *) hostname, (size_t) 80); getdomainname((char *) domname, (size_t) 80); ret = (char *) malloc(strlen((char *) hostname) + strlen((char *) domname) + 2); snprintf(ret, sizeof(ret), "%s.%s", (char *) hostname, (char *) domname); return(ret); } /* * CHECK_UNKNOWN * * This routine checks if the ident username is unknown, and processes the * data as it should normally. */ void check_unknown(char *host) { if ((!(prog_config.config_bits2 & SHOW_NOBODY1413)) && !strncmp(ident_user,"unknown@", 8)) { syslog(LOG_NOTICE, "Finger from %s %s", host, prog_config.p_strings[D_REJECT_HOST]); if (prog_config.config_bits2 & SHOW_REJECTED) display_file(NOBODY_UID, NOBODY_GID, rejected_display); log(LOG_IDENT, "Unknown not allowed from ", host); exit(PROGRAM_OKAY); } } /* * CHECK_TRUSTED * * This routine returns a TRUE or FALSE, depending on if the passed host is * in the trusted host array. * * Additional: This module now checks against the ident username. If it's * unknown, and unknown ident fingers are NOT allowed, it rejects the * connection. */ BOOL check_trusted(char *host) { int i; check_unknown(host); for (i = 0; i < trusted_host_num; i++) if ((wildmat(host, prog_config.trusted[i])) || (wildmat(ip_address, prog_config.trusted[i]))) { syslog(LOG_NOTICE, "Finger from %s %s", host, prog_config.p_strings[D_TRUST_HOST]); return(TRUE); } return(FALSE); } /* * CHECK_REJECTED * * This routine simply checks whether or not the listed host is part of the * list of rejected hosts. If it's matched, it displays the rejected list * file and quits completely. */ void check_rejected(char *host) { int i; check_unknown(host); for (i = 0; i < rejected_host_num; i++) if ((wildmat(host, prog_config.rejected[i])) || (wildmat(ip_address, prog_config.rejected[i]))) { syslog(LOG_NOTICE, "Finger from %s %s", host, prog_config.p_strings[D_REJECT_HOST]); if (prog_config.config_bits2 & SHOW_REJECTED) display_file(NOBODY_UID, NOBODY_GID, rejected_display); log(LOG_REJECTED, "Rejected host finger detected to ", host); exit(PROGRAM_OKAY); } } /* * SAFE_EXEC * * This is a safe version of the "system", "exec" or "popen" command. This * simply takes on the UID/GID of the NOBODY (or apparent NOBODY UID/GID), * and runs the specified program as that user. If it ever fails, it will * display in syslog the reason WHY it failed, along with a semi-detailed * message of the failure. * * * After an exec() system call, the saved uid is lost. Therefore, a child * program cannot use it to regain suid root permissions. * * W. Richard Stevens, Advanced Programming in the Unix Environment, page * 213: "The saved set-user-ID is copied from the effective user ID by exec." * */ char *safe_exec (uid_t uid, gid_t gid, char *cmd) { FILE *file; char line[600]; int fd[2]; int pid; char *result = NULL; unsigned long size = 0; if (pipe (fd) != 0) { syslog(LOG_ERR, "pipe() failed, %s.", strerror(errno)); return NULL; } if ((pid = fork()) < 0) { syslog(LOG_ERR, "fork() failed, %s.", strerror(errno)); return NULL; } if (pid > 0) { /* father */ close (fd[1]); /* for writing */ if ((result = (char *) malloc (1)) == NULL) return NULL; *result = '\0'; memset (line, 0, 600); while ((read (fd[0], line, sizeof (line)-1)) > 0) { if ((size += strlen (line)) < MAX_POPEN_BUF) { syslog (LOG_INFO, "Reallocating %d bytes", size); if ((result = (char *) realloc (result, size+1)) == NULL) { return NULL; } strcat (result, line); memset (line, 0, 600); } else { /* buffer limit reached */ close (fd[0]); return result; } } } else { /* child */ close (fd[0]); /* for reading */ DROP_ALL_PRIVS(uid, gid); file = popen(cmd, "r"); if (file) { while (!feof (file)) { memset (line, 0, 600); fgets (line, 600, file); write (fd[1], line, strlen (line)); } } else { close (fd[0]); close (fd[1]); syslog(LOG_ERR, "safe_exec failed on %s: %s", cmd, strerror(errno)); } close (fd[1]); exit (0); } if (!strlen (result)) { free (result); result = NULL; } return result; } /* * OPEN_FILE * * Quick way to open files and check for errors at the same time. */ FILE *open_file(char *filename) { if (check_illegal (filename, "CFINGERD")) return (fopen (filename, "r")); return NULL; } /* * OPEN_INITIAL_FILES * * This safely opens all files that are specified at startup. This allows * the files to be read, after they have been opened with root access. */ void open_initial_files(void) { top_display = open_file (prog_config.top_display_file); bottom_display = open_file (prog_config.bottom_display_file); noname_display = open_file (prog_config.no_name_banner_file); nouser_display = open_file (prog_config.no_user_banner_file); rejected_display = open_file (prog_config.rejected_file); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/version.c0100644000076500001440000000353706750257757014647 0ustar joeyusers/* * CFINGERD * Version information * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cfingerd.h" #include "proto.h" #include "version.h" /* * SHOW_VERSION_INFO * * Show program version information. */ void show_version_info(void) { syslog(LOG_NOTICE, "Version info"); printf("\nThis site is running the Configurable Finger-Query Daemon version %s,\n", VERSION); printf("available at ftp://ftp.infodrom.north.de/pub/people/joey/cfingerd/\n"); printf("or ftp://metalab.unc.edu/pub/Linux/system/network/finger/ .\n\n"); printf("For more information, or if you have any questions about the software\n"); printf("daemon, please contact http://www.infodrom.north.de/cfingerd/ .\n\n"); #ifdef IN_TESTING printf("This version of CFINGERD is currently undergoing either extensive\n"); printf("testing, or it is being worked on. If you see this message, it probably\n"); printf("means this program is being tested. If you see any bug reports in\n"); printf("this phase of development and it still appears after a day, please let\n"); printf("the programmer know.\n\n"); #endif #ifdef LAST_STABLE_RELEASE printf("The last stable version of CFINGERD is %s\n\n", LAST_STABLE_RELEASE); #endif log(LOG_USER, "Version information", " "); fflush(stdout); exit(PROGRAM_OKAY); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/src/version.h0100644000076500001440000000115706764317641014642 0ustar joeyusers/* * CFINGERD * Version information * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define VERSION "1.4.2" #define LAST_STABLE_RELEASE "1.4.2" /* #define IN_TESTING 1 */ cfingerd-1.4.3/src/wildmat.c0100644000076500001440000000776706612161615014614 0ustar joeyusers/* Added December 29, 1995 by Ken Hollis (khollis@bitgate.com). ** Thanks to Rich $alz for the failsafe regex routine */ /* $Revision: 1.4 $ ** ** Do shell-style pattern matching for ?, \, [], and * characters. ** Might not be robust in face of malformed patterns; e.g., "foo[a-" ** could cause a segmentation violation. It is 8bit clean. ** ** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. ** Rich $alz is now . ** April, 1991: Replaced mutually-recursive calls with in-line code ** for the star character. ** ** Special thanks to Lars Mathiesen for the ABORT code. ** This can greatly speed up failing wildcard patterns. For example: ** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-* ** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1 ** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1 ** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without ** the ABORT, then it takes 22310 calls to fail. Ugh. The following ** explanation is from Lars: ** The precondition that must be fulfilled is that DoMatch will consume ** at least one character in text. This is true if *p is neither '*' nor ** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic ** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With ** FALSE, each star-loop has to run to the end of the text; with ABORT ** only the last one does. ** ** Once the control of one instance of DoMatch enters the star-loop, that ** instance will return either TRUE or ABORT, and any calling instance ** will therefore return immediately after (without calling recursively ** again). In effect, only one star-loop is ever active. It would be ** possible to modify the code to maintain this context explicitly, ** eliminating all recursive calls at the cost of some complication and ** loss of clarity (and the ABORT stuff seems to be unclear enough by ** itself). I think it would be unwise to try to get this into a ** released version unless you have a good test data base to try it out ** on. */ #define TRUE 1 #define FALSE 0 #define ABORT -1 /* What character marks an inverted character class? */ #define NEGATE_CLASS '^' /* Is "*" a common pattern? */ #define OPTIMIZE_JUST_STAR /* Do tar(1) matching rules, which ignore a trailing slash? */ #undef MATCH_TAR_PATTERN /* ** Match text and p, return TRUE, FALSE, or ABORT. */ static int DoMatch(text, p) register char *text; register char *p; { register int last; register int matched; register int reverse; for ( ; *p; text++, p++) { if (*text == '\0' && *p != '*') return ABORT; switch (*p) { case '\\': /* Literal match with following character. */ p++; /* FALLTHROUGH */ default: if (*text != *p) return FALSE; continue; case '?': /* Match anything. */ continue; case '*': while (*++p == '*') /* Consecutive stars act just like one. */ continue; if (*p == '\0') /* Trailing star matches everything. */ return TRUE; while (*text) if ((matched = DoMatch(text++, p)) != FALSE) return matched; return ABORT; case '[': reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE; if (reverse) /* Inverted character class. */ p++; for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p) /* This next line requires a good C compiler. */ if (*p == '-' ? *text <= *++p && *text >= last : *text == *p) matched = TRUE; if (matched == reverse) return FALSE; continue; } } #ifdef MATCH_TAR_PATTERN if (*text == '/') return TRUE; #endif /* MATCH_TAR_ATTERN */ return *text == '\0'; } /* ** User-level routine. Returns TRUE or FALSE. */ int wildmat(text, p) char *text; char *p; { #ifdef OPTIMIZE_JUST_STAR if (p[0] == '*' && p[1] == '\0') return TRUE; #endif /* OPTIMIZE_JUST_STAR */ return DoMatch(text, p) == TRUE; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/texts/0040755000076500001440000000000006774336472013367 5ustar joeyuserscfingerd-1.4.3/texts/bottom_finger.txt0100644000076500001440000000032206351024421016733 0ustar joeyusers ----------------------------------------------------------------------------- If that scrolled by your screen too fast, please put a "| more" at the end of your finger command. cfingerd-1.4.3/texts/noname_banner.txt0100644000076500001440000000115406351024421016703 0ustar joeyusers ----------------------------------------------------------------------------- $center Bitgate Software Configurable Finger Service $center Version $version by Ken Hollis, compiled $compile_datetime $center Local time and date are $time $date $center Greetings, $ident. $center Sorry, this system does not allow finger query requests without supplying $center a valid username. If you know the party you're looking for but do not $center know their E-Mail address, try using "search.username" on your next $center finger-query. Thanks. ----------------------------------------------------------------------------- cfingerd-1.4.3/texts/nouser_banner.txt0100644000076500001440000000030006351024421016731 0ustar joeyusers ---------------------------------------------------------------------- $center Sorry, that user doesn't exist. ---------------------------------------------------------------------- cfingerd-1.4.3/texts/rejected_banner.txt0100644000076500001440000000145506351024421017217 0ustar joeyusers .a888b .a888b .a888b d88888P .a888b .a888b d8P"d8P d8P"d8P d8P"d8P d8P d8P" VP d8P" VP d88888P d8P d8P d8888P V888b V888b d8P d8P d8P.a8P d8P.a8P d8P dP .d8P dP .d8P d8P d8P V8888" V8888" d88888P V888P" V888P" d8888b d88888P d8P d8P d88888P d88888P d8888b d8P"d8P d8P d88ad8P d8P d8P d8P"d8P d8P d8P d8888P d88888P d8P d8888P d8P d8P d8P.a8P d8P d8PI88P d8P d8P d8P.a8P d8888P" d88888P d8P d8P d88888P d88888P d8888P" $center <<< Sorry, you can't finger this system >>> $center If you were rejected for not running IDENTD, please tell your $center system administrator to install it. cfingerd-1.4.3/texts/top_finger.txt0100644000076500001440000000057006351024421016236 0ustar joeyusers ----------------------------------------------------------------------------- $center **> Welcome to this host's finger system, $ident <** $center This site is running cfingerd $version. ----------------------------------------------------------------------------- $center Finger "services@this.host" to get a listing of finger query services $center this system provides. cfingerd-1.4.3/userlist/0040755000076500001440000000000006774336472014072 5ustar joeyuserscfingerd-1.4.3/userlist/Makefile0100644000076500001440000000072006762622766015527 0ustar joeyusers# Makefile for the custom userlisting display # # Part of the CFINGERD distribution # Released under the GPL. include ../Makefile.cfg OBJS = main.o initialize.o display.o options.o idle.o ../src/getutent.o userlist: $(OBJS) $(CC) -o $@ $^ clean: rm -f *.o userlist rm -f config.h install: userlist install -m 755 -o $(BIN_OWNER) -g $(BIN_GROUP) -s userlist /usr/sbin/userlist install -m 644 -o $(MAN_OWNER) -g $(MAN_GROUP) userlist.1 $(MANDIR)/man1 cfingerd-1.4.3/userlist/TODO0100644000076500001440000000012106351024421014524 0ustar joeyusersUSERLIST TODO Listing o Add different display methods to emulate different OSes cfingerd-1.4.3/userlist/config.h.in0100644000076500001440000000062506762437635016115 0ustar joeyusers/* * USERLIST * Configuration module */ /*****************************************************************************/ /* * MAX_TTYS * * This is the maximum number of login sessions your system will ever have. * Most only allow a maximum of 32 on a single CPU for slower machines (ie. * Linux 486/100 systems). For faster machines (such as an Alpha), try * 64 or 96. */ #define MAX_TTYS 256 cfingerd-1.4.3/userlist/display.c0100644000076500001440000000521606774334770015703 0ustar joeyusers/* * USERLIST * Display management routines */ #include "userlist.h" #include "proto.h" char *inettos(long addr) { char *ret; int p1, p2, p3, p4; ret = (char *) malloc(20); p1 = (addr & 0x000000FF); p2 = (addr & 0x0000FF00) >> 8; p3 = (addr & 0x00FF0000) >> 16; p4 = (addr & 0xFF000000) >> 24; sprintf(ret, "%d.%d.%d.%d", p1, p2, p3, p4); return(ret); } char *get_localhost(void) { #ifndef LOCAL_NAME char *ret; char hostname[STRLEN]; char *p; memset(hostname, 0, STRLEN); gethostname((char *) hostname, (size_t) STRLEN); if ((p = index(hostname, '.')) != NULL) *p = '\0'; ret = (char *) malloc(strlen((char *) hostname) + 1); sprintf(ret, "%s", (char *) hostname); return(ret); #else return(LOCAL_NAME); #endif } int exist(const char *filename) { FILE *file; file = fopen(filename, "r"); if (file) { fclose(file); return(1); } else return(0); } void process_display(void) { int i; char *our_host; char *idle; our_host = get_localhost(); if (times_on == 0) { printf ("Nobody logged in.\n"); return; } else printf ("USERNAME Real name Idletime TTY Remote console location\n"); for (i = 0; (i < times_on) && (i < MAX_TTYS); i++) { char console[30]; struct passwd *pwent; if (strlen((char *) tty_list[i].locale) == 0) snprintf(console, sizeof(console), "(%s)", our_host); else snprintf(console, sizeof(console), "(%s)", tty_list[i].locale); if (strlen((char *) tty_list[i].username) > 1) { char *username=NULL; char ru[8], fn[STRLEN]; memset(ru, 0, sizeof (ru)); memset(fn, 0, sizeof (fn)); strncpy(ru, tty_list[i].username, sizeof(ru)-1); pwent = getpwnam((char *) ru); if (pwent) { cp = pwent->pw_gecos; if ((x = index (pwent->pw_gecos, ',')) != NULL) /* username */ *x = '\0'; if ((username = (char *)malloc (strlen(cp)+1)) != NULL) { memset (username, 0, strlen(cp)+1); strcpy (username, cp); } snprintf(fn, sizeof(fn), "%s/.nofinger", pwent->pw_dir); } idle = calc_idle((char *) tty_list[i].line); if (pwent) { if (!exist((char *) fn)) { if (idle) { printf("%-8.8s %-30.30s %8.8s ", ru, username?username:"", idle); printf("%3.3s %-25.25s\n", (char *) tty_list[i].tty, console); } } } else { if (idle) { printf("%-8.8s %-30.30s %8.8s ", ru, ru, idle); printf("%3.3s %-25.25s\n", (char *) tty_list[i].tty, console); } } } fflush(stdout); } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/userlist/idle.c0100644000076500001440000000255606752412665015153 0ustar joeyusers/* * USERLIST * Show user idletime */ #include "userlist.h" #include "proto.h" #include #include #include char *calc_idle(char *tty) { struct stat buf; time_t cur_time; long diff_time; int min, hour, day; static char idledisp[STRLEN]; char dev_file[STRLEN]; memset(idledisp, 0, sizeof (idledisp)); memset(dev_file, 0, sizeof (dev_file)); snprintf(dev_file, sizeof (dev_file), "/dev/%s", tty); stat((char *) dev_file, &buf); cur_time = time(NULL); diff_time = (long) cur_time - (long) buf.st_mtime; min = hour = day = 0; if (diff_time > 86400) day = hour = 1; else if (diff_time > 3600) hour = min = 1; else if (diff_time > 59) min = 1; if (day) { day = diff_time / 86400; diff_time -= day * 86400; } if (day) { if (no_idle) return NULL; snprintf(idledisp, sizeof (idledisp), "%1dd ", day); return idledisp; } if (hour) { hour = diff_time / 3600; diff_time -= hour * 3600; } if (min) { min = diff_time / 60; diff_time -= min * 60; } if (hour || min) { if (day) snprintf(idledisp, sizeof (idledisp), "%02d:%02d", hour, min); else snprintf(idledisp, sizeof (idledisp), "%d:%02d", hour, min); } return idledisp; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/userlist/initialize.c0100644000076500001440000000423706747654730016402 0ustar joeyusers/* * USERLIST * Initialization routines */ #include "userlist.h" #include "proto.h" #include "config.h" #ifdef BSD #include "../src/getutent.h" #endif #include TTY_FROM tty_list[MAX_TTYS]; int times_on; char *remove_crap(char *str) { char *ret; int i, x = 0; ret = (char *) malloc(strlen(str)); for (i = 0; i < strlen(str); i++) if (isalnum(str[i]) || (str[i] == '.') || (str[i] == '-')) ret[x++] = str[i]; return(ret); } #ifdef BSD #define ULIST_UNAME 16 #else #define ULIST_UNAME 8 #endif #define ULIST_TTY 2 #define ULIST_LOCALE 16 #define ULIST_LINE 12 void initialize_userlist(void) { struct utmp *ut; char *cp; times_on = 0; while(((ut = getutent()) != NULL) && (times_on < MAX_TTYS)) #ifdef BSD { #else if (ut->ut_type == USER_PROCESS) { #endif tty_list[times_on].username = malloc(ULIST_UNAME+1); tty_list[times_on].tty = malloc(ULIST_TTY+1); tty_list[times_on].locale = malloc(ULIST_LOCALE+1); tty_list[times_on].line = malloc(ULIST_LINE+1); memset (tty_list[times_on].username, 0, ULIST_UNAME+1); memset (tty_list[times_on].tty, 0, ULIST_TTY+1); memset (tty_list[times_on].locale, 0, ULIST_LOCALE+1); memset (tty_list[times_on].line, 0, ULIST_LINE+1); #ifdef BSD strncpy(tty_list[times_on].username, (char *) ut->ut_name, ULIST_UNAME); #else strncpy(tty_list[times_on].username, (char *) ut->ut_user, ULIST_UNAME); cp = (char *) ut->ut_line; if (!strncmp(cp, "tty", 3)) cp+=3; /* strip ^tty */ strncpy(tty_list[times_on].tty, cp, ULIST_TTY); #ifdef SUNOS tty_list[times_on].ip_addr = 0; #else /* SUNOS */ tty_list[times_on].ip_addr = ut->ut_addr; #endif /* SUNOS */ #endif cp = ut->ut_host; if (*cp == ':') cp++; strncpy(tty_list[times_on].locale, cp, ULIST_LOCALE); if (strlen ((char *) ut->ut_host) > ULIST_LINE) if ((cp = strrchr(tty_list[times_on].locale, '.')) != NULL) *cp = '\0'; strncpy(tty_list[times_on].line, (char *) ut->ut_line, ULIST_LINE); tty_list[times_on].time = ut->ut_time; times_on++; } } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/userlist/main.c0100644000076500001440000000063406762270722015152 0ustar joeyusers/* * USERLIST * version 1.0.0 * * by Ken Hollis for CFINGERD * * Released under the GPL for public/private use. */ #include "userlist.h" #include "proto.h" int main(int argc, char *argv[]) { initialize_userlist(); if (argc > 1) handle_options(argc, argv); process_display(); return 0; } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 8 * End: */ cfingerd-1.4.3/userlist/options.c0100644000076500001440000000224006762177120015712 0ustar joeyusers/* * USERLIST * Command line options */ #include "userlist.h" #include "proto.h" int display_type; int no_idle = 0; void give_help(void) { printf("\nUSERLIST command line options\n\n"); printf("A number of options selects the emulated OS display type for finger output.\n\n"); /* printf("\t-b\tGive BSD/OS-type finger output\n"); */ printf("\t-c\tGive standard CFINGERD (custom) output\n"); printf("\t-n\tList only people idle less than one day\n"); /* printf("\t-g\tGive GNU-FINGER display output\n"); printf("\t-l\tGive standard LINUX finger output (as if there is any)\n"); printf("\t-r\tGive standard STRICT RFC1288 compilant output\n"); printf("\t-u\tGive Unix System V finger output\n\n"); */ printf("Userlist for CFINGERD version 1.2.1\n\n"); fflush(stdout); exit(1); } void handle_options(int argc, char *argv[]) { int i; for (i=1;i #include #include #include #include #include #include #include #include #include #include #define BOOL int #define TRUE 1 #define FALSE 0 #define STRLEN 80 /* Display types */ #define DISPLAY_CFINGERD 1 #define DISPLAY_RFC1288 2 #define DISPLAY_LINUX 3 #define DISPLAY_GNU 4 #define DISPLAY_BSDOS 5 #define DISPLAY_UNIX5 6 typedef struct { char *username; char *tty; char *locale; char *line; long ip_addr; time_t time; } TTY_FROM; #include "config.h" #ifdef SUNOS #include #include #define utmp utmpx #define ut_time ut_xtime #define getutent getutxent #define _PATH_UTMP UTMPX_FILE #if (SUNOS == 55) #define snprintf __snprintf #endif #else #include #endif #if !defined(UT_USERSIZE) || !defined(UT_HOSTSIZE) || !defined(UT_LINESIZE) || !defined(UT_NAMESIZE) struct utmp foo_utmp; #endif #ifndef UT_USERSIZE #define UT_USERSIZE sizeof(foo_utmp.ut_name) #endif #ifndef UT_HOSTSIZE #define UT_HOSTSIZE sizeof(foo_utmp.ut_host) #endif #ifndef UT_LINESIZE #define UT_LINESIZE sizeof(foo_utmp.ut_line) #endif #ifndef UT_NAMESIZE #define UT_NAMESIZE sizeof(foo_utmp.ut_user) #endif extern TTY_FROM tty_list[MAX_TTYS]; extern int times_on, display_type; extern int no_idle; cfingerd-1.4.3/userlist/examples/0040755000076500001440000000000006774336472015710 5ustar joeyuserscfingerd-1.4.3/userlist/examples/escape.com0100644000076500001440000000650306351024421017624 0ustar joeyusers[escape.com] Login Name Tty Idle Login Time Office Office Phone bbs BBS System p8 6 Aug 5 03:44 bbs BBS System q2 1:30 Aug 5 03:27 blaknite BlakNight r1 Aug 5 03:24 digital Shrihari Pandit *p0 19:52 Aug 3 19:34 digital Shrihari Pandit *p9 5:55 Aug 1 18:33 digital Shrihari Pandit *pe 6:20 Aug 2 16:38 digital Shrihari Pandit *re 5:58 Aug 3 13:16 digital Shrihari Pandit s2 5:57 Aug 3 20:33 emunster Eddy Munster q6 Aug 5 05:01 emunster Eddy Munster qa 32 Aug 5 05:01 justme Ya 7abebi ya 3beer e u1 11:52 Aug 4 17:36 kenster KEn Thomas q3 Aug 5 04:38 klasp Mental Patient HaBiB qd Aug 5 04:46 legend The Legend Lives For s0 Aug 5 02:29 marka Mark Anderson sb 17:47 Aug 4 11:46 marko razzle dazzle root b *pb 20 Aug 5 04:19 mikh Max Mikhanosha r4 2:09 Aug 4 23:08 mikh Max Mikhanosha r5 5:52 Aug 4 23:08 neeraj Neeraj *s8 Aug 5 03:01 ozerk Ozerk Alpay rb Aug 5 03:17 pieman The PieMaN The P.I.T qe 21 Aug 4 18:44 prophet1 Prophet -/\/- RiSC - ra 3 Aug 5 02:58 -/\/- RiSC redz in a villianous voic r8 5 Aug 5 05:24 simonsez Simon Chiu t4 3:52 Aug 5 01:19 sonic q4 58 Aug 4 23:55 wab q9 4 Aug 5 04:38 wab qb 6 Aug 5 04:38 wab qc 29 Aug 5 04:39 will William Seiber p3 1:28 Aug 5 04:00 windex Sejin Oh p5 Aug 5 05:20 windex Sejin Oh pf 11 Aug 5 04:58 yuen_tai Yuen Tai p1 7 Aug 5 01:04 SLIP / PPP USERS Login Full Name What Where Login Time Hostname ------------------------------------------------------------------------------ kool-ken Kenny Rishty PPP pm1:4 Aug 3 21:11 shetler.escape.com nyo nyo PPP pm2:26 Aug 4 09:19 slip/ppp-3-147.escape. tol tol PPP pm2:27 Aug 4 12:09 zero.tolerance.org romdog romdog PPP pm2:21 Aug 4 15:49 romdog.com digital Shrihari Pandit PPP pm1:20 Aug 4 17:41 nsa.net lance Lance G. SLIP pm2:28 Aug 4 22:58 slip/ppp-2-28.escape.c dima ??? PPP pm3:3 Aug 4 23:38 dima.escape.com piyo LeiShunUmuttYeahAhh PPP pm1:5 Aug 5 01:04 slip/ppp-2-238.escape. mac mac PPP pm2:24 Aug 5 01:25 slip/ppp-2-114.escape. sonic PPP pm2:5 Aug 5 01:42 slip/ppp-3-29.escape.c ajoib Adrian PPP pm2:1 Aug 5 03:13 anon.escape.com mikh Max Mikhanosha PPP pm1:14 Aug 5 03:21 mikh.escape.com shuriken White Knight PPP pm1:1 Aug 5 05:13 slip/ppp-4-78.escape.c jalexd Jonathan Alexander D PPP pm1:11 Aug 5 05:30 204.183.126.236 cfingerd-1.4.3/userlist/examples/netcom.com0100644000076500001440000015500706351024421017655 0ustar joeyusers[netcom.com] User Real Name Idle TTY Host Console Location aaronm Aaron D. McClure 0:10 t2 netcom16 (NETCOM-pa11.netc) aasmok Kristian D. Aasmo q0 netcom7 (NETCOM-dc6-1.net) achilles Who Cares? 0:24 *p7 netcom22 (205.199.152.104) acmorton Ann Morton pa netcom16 (NETCOM-wc1.netco) acoustic Yee On Lo t2 netcom9 (NETCOM-pa1.netco) action Don Lawrence pb netcom12 (NETCOM-la19.netc) addison Michael Addison Reed qb netcom17 (NETCOM-la19.netc) agok ali gok p6 netcom4 (NETCOM-sj19.netc) akama Tae Ho Kim qf netcom17 (NETCOM-sj10.netc) albertc Albert Cheng qf netcom19 (NETCOM-sj24.netc) aldridge J Aldridge pb netcom6 (NETCOM-pl1.netco) aldridge J Aldridge pd netcom3 (NETCOM-pl2.netco) alegado Eric F. Alegado q2 netcom13 (NETCOM-pas12.net) alive Singer of Songs q5 netcom11 (NETCOM-wc6.netco) amaslam Ahmed Aslam pf netcom20 (NETCOM-nyc14.net) amethyst Gerrit Kruidhof 0:02 p4 netcom6 (NETCOM-pa6.netco) amuro Dickinson Lo qa netcom22 (NETCOM-ir15.netc) amyn Amy N. pb netcom2 (NETCOM-sj10.netc) animale * r8 netcom10 (NETCOM-sd9.netco) apn Advanced Prion Nomostatics t7 netcom17 (NETCOM-sj18.netc) arbuss Steve Arbuss 0:19 q1 netcom16 (NETCOM-la18.netc) arithmos Arithmos Inc qb netcom4 (NETCOM-pa4.netco) armyman Umar I Mallic s2 netcom21 (NETCOM-lb8.netco) ataru Mark Bradley qb netcom23 (NETCOM-clv1.netc) aturco Art Turco 0:01 q2 netcom10 (NETCOM-ir15.netc) awells Adam B. Wells *pa netcom9 (NETCOM-sj11.netc) b222527 Kevin q4 netcom3 (NETCOM-lb5.netco) babylon5 Richard Krider q3 netcom5 (NETCOM-sf13.netc) badboy Jay Keller 1:09 q3 netcom23 (netcom12) badboy Jay Keller qf netcom12 (NETCOM-sj23.netc) badkarma q6 netcom14 (NETCOM-pl4.netco) baily Richard "Dr." Baily 0:06 p5 netcom3 (NETCOM-pas12.net) banquo sean stephens 1:09 q3 netcom19 (NETCOM-lb5.netco) barce James Barcelona p4 netcom2 (NETCOM-sf5.netco) bartfai Zsuzsanna Ba'rtfai r9 netcom5 (NETCOM-sj21.netc) batesole UNIX System Administration r0 netcom19 (NETCOM-sj13.netc) bauman Blake Bauman pf netcom17 (NETCOM-la20.netc) bblp1 Big Bird 0:11 p5 netcom7 (NETCOM-pas11.net) bbs berzinas q5 netcom9 (NETCOM-sac4.netc) bc1 Bob Campbell s0 netcom13 (NETCOM-atl15.net) bckdrmn Dave Gotwisner q5 netcom15 (NETCOM-pl5.netco) bcre8ive Alex Lam 0:31 p5 netcom17 (NETCOM-sac5.netc) beetle Beetle *s7 netcom3 (NETCOM-pas10.net) beker Brian Beker 2:10 pa netcom23 (NETCOM-la1.netco) beoj Joseph Embree q9 netcom13 (NETCOM-den10.net) beowulfs michael ellis p2 netcom9 (NETCOM-cin1.netc) besnode Paul and Michele sd netcom3 (NETCOM-pas11.net) betts Jonathan Betts 3:02 p8 netcom15 (204.152.97.90) bhayes Bill Hayes r2 netcom4 (NETCOM-pl4.netco) bilbo HeAdChEesE p4 netcom14 (NETCOM-sj25.netc) bishpnc david shaffer 0:03 p9 netcom6 (netcom11) bishpnc david shaffer 0:06 p9 netcom11 (NETCOM-sd8.netco) blade Dwight Mcgowen/Tracy Brown pf netcom2 (NETCOM-sj16.netc) blair5 Blair Family r7 netcom13 (NETCOM-wc7.netco) blamar Blake and/or Marla 0:01 p3 netcom (camad1.camosun.b) blckflag Black Flag td netcom4 (NETCOM-aus2.netc) blevin Bryan Levin *qb netcom19 (NETCOM-pa9.netco) bloke Bloke 1:16 sb netcom12 (NETCOM-den10.net) bluejay Thomas Burnfin 0:17 q4 netcom15 (NETCOM-sf6.netco) bmf Kenneth Lu pf netcom14 (NETCOM-al6.netco) bmfrosty Bad Mr. Frosty *qc netcom5 (NETCOM-al2.netco) bmfrosty Bad Mr. Frosty *p4 netcom7 (netcom5) bnorvell Brock Norvell p7 netcom3 (NETCOM-den13.net) bnunes Brian Nunes *p1 netcom23 (NETCOM-la18.netc) bobrow Jordan Bobrow q6 netcom17 (NETCOM-pa6.netco) bobster Robert Mosher 0:04 p5 netcom9 (NETCOM-or10.netc) bolan Don Carroll s2 netcom19 (NETCOM-ir15.netc) boojum Jeffrey J. Mancebo rc netcom3 (NETCOM-sj22.netc) bored Atreides p4 netcom22 (NETCOM-lv6.netco) boserj Jeffrey Boser *qb netcom12 (NETCOM-lv3.netco) bradleym Bradley *q4 netcom12 (NETCOM-pl8.netco) bradleym Bradley *r6 netcom14 (netcom12) breadstx Chris Ogle pa netcom5 (NETCOM-aus2.netc) breon breon moore q7 netcom17 (NETCOM-sf16.netc) brg Bruce R. Gilson r9 netcom17 (NETCOM-dc6-1.net) briden AMB qa netcom19 (NETCOM-den13.net) browder Dustin Browder p3 netcom3 (NETCOM-la3.netco) bryant Bryant *r7 netcom18 (NETCOM-sj28.netc) bsanders Brian Sanders 0:02 *pd netcom16 (NETCOM-pl1.netco) bstern Betsy Stern p6 netcom8 (NETCOM-al3.netco) btm Brent Matthews q6 netcom7 (NETCOM-sj26.netc) bub Joseph Leigh p7 netcom23 (NETCOM-sj13.netc) buffy Cheryl Qualls p5 netcom11 (NETCOM-atl6.netc) burnout Cory Fasbender 1:30 u5 netcom6 (NETCOM-pa11.netc) busgirl Martha *p4 netcom13 (NETCOM-al3.netco) bytelock todd k. kramer pe netcom6 (NETCOM-den10.net) cajun Seth Shealer r7 netcom7 (NETCOM-mia1.netc) caliph John Luzar qb netcom6 (NETCOM-pl2.netco) carrs Amethyst *q6 netcom8 (NETCOM-lv3.netco) carterg Gil Carter pc netcom (129.72.60.2) casas Robert Casas q8 netcom11 (NETCOM-chi12-1.n) caslis Russell Caslis pe netcom20 (NETCOM-sj30.netc) cass Cassandra 1:23 ra netcom13 (NETCOM-dc15-1.ne) catshous Bob Walker p4 netcom19 (NETCOM-sd9.netco) cawhite Carl White 0:04 p8 netcom21 (ottgate.bnr.ca) cb12 Christopher Blome 0:05 p6 netcom2 (NETCOM-dfw9.netc) cdavis Chris Davis p5 netcom14 (NETCOM-aus2.netc) cdavis Chris Davis pa netcom8 (netcom14) ceichert Carl J. Eichert 0:05 p5 netcom4 (NETCOM-lb8.netco) cfr1 Christopher Randall qb netcom2 (NETCOM-pa9.netco) cfrancis Charles Francis 1:34 sc netcom4 (NETCOM-mia2.netc) cfwong Chun Wong qe netcom18 (NETCOM-sj10.netc) chaglund Cat Haglund (ftoast) q1 netcom3 (NETCOM-al2.netco) chalky John McCauley 7:58 t0 netcom19 (office2.netcom.c) chamw Chamindra Weerasinghe q1 netcom (netcom4) chamw Chamindra Weerasinghe q1 netcom4 (NETCOM-sj21.netc) chewy Chewy pa netcom11 (NETCOM-dfw10.net) chuckm Charles Montague pe netcom14 (NETCOM-dc6-1.net) ckerr Chris Kerr qd netcom17 (NETCOM-sd6.netco) clas Charles L. Arnold pe netcom16 (NETCOM-sd8.netco) clb Charles L. Brost q1 netcom22 (NETCOM-sd8.netco) cnishida Craig H. Nishida q8 netcom9 (NETCOM-sf17.netc) cnwong carolyn wong s4 netcom13 (NETCOM-pl3.netco) coan John Coan p5 netcom8 (NETCOM-rtp4.netc) cobalt Laura Torrano pb netcom21 (NETCOM-prn1.netc) colinr Colin Robertson 0:02 q2 netcom16 (NETCOM-sea5.netc) comtec sd netcom16 (NETCOM-ir15.netc) consult consult s9 netcom9 (NETCOM-pa9.netco) coop The Real Coop *q2 netcom20 (NETCOM-aus2.netc) cosmos Gerald Penaflor pc netcom11 (NETCOM-sj11.netc) cptater James Sucky r5 netcom18 (NETCOM-col1.netc) cpugh Chris Pugh rf netcom5 (NETCOM-sj13.netc) creol Fred Chavez s1 netcom6 (NETCOM-al11.netc) cricket Tod Owens s8 netcom6 (NETCOM-lv3.netco) crincon chris rincon 0:01 qa netcom14 (NETCOM-sj14.netc) croyston Chris Royston 0:26 p4 netcom15 (NETCOM-sac10.net) cst Christian Tice r3 netcom3 (NETCOM-sj27.netc) ctk Chris Kaiser p9 netcom19 (NETCOM-dc7-1.net) ctseitz Christin Seitc qe netcom17 (NETCOM-sj34.netc) cuehara Christian Uehara rf netcom8 (NETCOM-sj24.netc) cuffs vanessa zenzmaier 4:04 q2 netcom17 (NETCOM-dfw9.netc) cyrillv Cyrill Vatomsky *td netcom13 (NETCOM-sc5.netco) dabronx Karen Greene p2 netcom13 (NETCOM-al6.netco) dadams Dean Adams 0:02 s0 netcom16 (NETCOM-wh6.netco) daemon9 Route q0 netcom10 (NETCOM-lv3.netco) danhuver Dan Huver p1 netcom20 (NETCOM-sj13.netc) danny7 Jeong-Gi Cho p3 netcom15 (NETCOM-ir14.netc) danos Dan Osterlund 0:08 s8 netcom12 (NETCOM-nyc5.netc) daveap David Peterson 0:03 pf netcom15 (NETCOM-sea7.netc) daverich David Richards q6 netcom4 (NETCOM-ir14.netc) davidher david her q3 netcom3 (NETCOM-pl4.netco) davidsc David S. Collett p2 netcom (comnet.ksc.net.t) daw Daniel Weinstein p4 netcom10 (NETCOM-wc1.netco) dbakin David S. Bakin 0:01 t0 netcom15 (NETCOM-sf9.netco) dbongard Dan Bongard 0:01 p2 netcom18 (NETCOM-sd8.netco) dcanada BoYz FrOm Da HoOd! p8 netcom10 (NETCOM-pl1.netco) dcoakley dorothy coakley pd netcom2 (NETCOM-al6.netco) dcohen David Cohen pd netcom4 (NETCOM-la21.netc) ddavid Dennis David 11:10 s2 netcom8 (dida.netcom.com) deang Dean Grandquist 4:02 qb netcom16 (NETCOM-pl5.netco) debbie debbie ann p2 netcom12 (NETCOM-sf5.netco) del David Whittemore 9:23 r8 netcom22 (vergiftung.netco) del David Whittemore 9:05 qd netcom (vergiftung.netco) demon666 666 u1 netcom20 (NETCOM-bos9.netc) derald Derald Sue tc netcom15 (NETCOM-al12.netc) design Design and Delivery r3 netcom15 (NETCOM-al3.netco) despair despair p9 netcom3 (NETCOM-den10.net) devtrix Matthew B. Wood 0:02 ra netcom21 (nyquist.noc.netc) dewshine Sh'k'anna Korra'ti ra netcom18 (NETCOM-sea4.netc) dfd David Charlton q9 netcom14 (NETCOM-pas11.net) dfwnero Robert Shaun Bartoo 0:01 pd netcom15 (NETCOM-dfw12.net) dhl1 David Hugh Lewis p8 netcom (einstein.technet) dimitri Dimitri I. Rakitine t3 netcom18 (NETCOM-sr3.netco) diony Ayse r9 netcom12 (office4.netcom.c) dis Kurt Jacobsen 12:24 r4 netcom3 (NETCOM-wh3.netco) dizy Major D 0:02 q4 netcom2 (NETCOM-sd9.netco) dkershaw Dan Kershaw 8:25 ta netcom20 (NETCOM-sr3.netco) dlam The_Lonely_One qd netcom21 (NETCOM-sj35.netc) dleong David Leong 0:02 *q5 netcom21 (NETCOM-sj34.netc) dmessiah Evan Brewerr *ra netcom20 (NETCOM-wc1.netco) dmp D and M Products qf netcom14 (NETCOM-pl3.netco) dna David Altekruse *pd netcom5 (NETCOM-pa7.netco) dobe lynn petrangelo pf netcom22 (NETCOM-wc7.netco) doccon judi stutz *pd netcom7 (NETCOM-ir13.netc) dorlic Dan Orlic q4 netcom (VMS1.TAMU.EDU) douglasw Douglas Wallace 0:15 pc netcom18 (NETCOM-nyc11.net) draperm Rulon Anderson q0 netcom15 (NETCOM-pl1.netco) drd3524 David Diaz 0:01 p8 netcom20 (NETCOM-dfw10.net) drdoom Dr. DooM *qb netcom9 (netcom23) drdoom Dr. DooM *q5 netcom4 (NETCOM-lv6.netco) drdoom Dr. DooM 0:08 *q7 netcom23 (netcom4) dreed David Reed qc netcom4 (NETCOM-sj12.netc) dregg Cyrus H. Lendvay q9 netcom6 (NETCOM-sac4.netc) dricket Doug Ricket t3 netcom21 (NETCOM-sj26.netc) drkhoe Dr. Mosh q9 netcom16 (NETCOM-lb6.netco) dror Oz Dror 0:02 *p0 netcom15 (NETCOM-la21.netc) dshih David Shih (Shy) 0:04 r7 netcom12 (NETCOM-pa3.netco) dsickler Doug Sickler p0 netcom8 (NETCOM-sac7.netc) dsnakao David 0:04 q0 netcom5 (netcom11) dsnakao David p2 netcom11 (netcom4) dsnakao David *pa netcom4 (NETCOM-lb6.netco) dynamic John D. D. Keighley qa netcom9 (NETCOM-la22.netc) eamon Chuck Taggart p3 netcom14 (NETCOM-wc3.netco) eblade Who the Hell are you? 0:02 q4 netcom5 (pm041-kz.mich.ne) edry Edward Dry q3 netcom9 (NETCOM-la2.netco) edwink Edwin Khachatourian qc netcom2 (netcom2) edwink Edwin Khachatourian p2 netcom21 (NETCOM-pas10.net) elmopons Elmo Ponsdomenech 0:01 q9 netcom11 (NETCOM-la21.netc) emegas Megas of Vecanti p8 netcom19 (NETCOM-la3.netco) emir God is Awesome *r0 netcom14 (cyber.net) emoor Ernie Moor q9 netcom2 (NETCOM-pl2.netco) epk Edward P. Krauss 1:25 *p3 netcom20 (NETCOM-al6.netco) equitz1 Will Equitz 0:21 qe netcom15 (NETCOM-pa8.netco) equitz1 Will Equitz p8 netcom4 (NETCOM-pa7.netco) estero Aura Herring q1 netcom15 (NETCOM-pas12.net) eugenia Peter Chen pe netcom17 (NETCOM-pl5.netco) exeter John Chernoff qb netcom22 (NETCOM-sj13.netc) exorder Wanna play }=> 0:05 *s1 netcom16 (NETCOM-sac4.netc) factor Robert Walsh q7 netcom10 (NETCOM-sf11.netc) falstaff anthony m. vervoort 0:21 q8 netcom5 (NETCOM-sc5.netco) farinaz Farinaz Raissi q7 netcom15 (NETCOM-sj21.netc) fariss Gary B. Fariss *q1 netcom14 (NETCOM-sj24.netc) farooq Farooq S. Khan 0:11 pd netcom23 (paknet.vip.best.) farrago D'Maris D. Coffman 0:08 q7 netcom21 (SHDH116-W16.WHAR) fdd Ford Davies pa netcom18 (NETCOM-sac6.netc) fdp Ciccio qa netcom12 (NETCOM-wc6.netco) feedee Karen P. Jones pa netcom20 (NETCOM-den10.net) ferrett Rene Martinez pd netcom20 (NETCOM-mia1.netc) firekat Kathryn Hormann tc netcom22 (NETCOM-sf12.netc) fizz FIZZ *qf netcom13 (NETCOM-sj34.netc) fizz FIZZ *p8 netcom12 (netcom13) flux9 0:01 q9 netcom10 (NETCOM-or11.netc) foont Uber Fonken q5 netcom17 (NETCOM-atl10.net) fopp jeff lindsey 0:02 *p0 netcom16 (NETCOM-lv4.netco) forever Greenwood Forever! p1 netcom21 (NETCOM-nyc13.net) fork Foobar qd netcom7 (NETCOM-wp1.netco) foxtx Josh Busby pa netcom (jbusby.ICSI.Net) freedom Steve Legasto pf netcom6 (NETCOM-al6.netco) fritzy Brent Whisenant pd netcom18 (NETCOM-atl6.netc) fshmongr Jon Haug 0:02 p7 netcom5 (NETCOM-al6.netco) fstclair Frank St. Claire 0:01 p2 netcom22 (NETCOM-dfw9.netc) fur Peter Formica q0 netcom2 (NETCOM-sj29.netc) fvlaming frank vlamings q7 netcom7 (NETCOM-pl3.netco) galend Galen Davis 0:02 p0 netcom6 (NETCOM-aus3.netc) gam Gordon Moffett r0 netcom17 (NETCOM-or11.netc) gasman Daniel Kaminsky *p9 netcom15 (NETCOM-sf8.netco) geeze Kiley Clark pf netcom18 (NETCOM-sd10.netc) genechen Gene Chen q5 netcom6 (NETCOM-pas10.net) genj rick aulp q5 netcom8 (NETCOM-sj26.netc) gentile Don Gentile 0:01 *p4 netcom12 (NETCOM-sj13.netc) george11 George Stamatopoulos q4 netcom20 (NETCOM-sf7.netco) gerber Trevor Tarr pc netcom22 (NETCOM-pas11.net) ghost16 Troy Jackson p3 netcom21 (NETCOM-phi3.netc) gif Gifka Sovereign r9 netcom14 (NETCOM-la21.netc) gilles Gilles Bacon pc netcom13 (NETCOM-nyc9.netc) gking Stephen Clark p8 netcom14 (NETCOM-wc1.netco) gmarquez Richard Marquez p7 netcom17 (NETCOM-sf10.netc) gnas Peter Gnas p1 netcom13 (NETCOM-lv4.netco) gndrflx Billie Jean p8 netcom16 (NETCOM-sac5.netc) godfther godfather 4:10 r3 netcom8 (netcom14) godfther godfather 4:15 qe netcom14 (NETCOM-dfw14.net) goshen Shmuel Goshen p4 netcom20 (NETCOM-pa1.netco) gradubid Claire Normand q6 netcom5 (NETCOM-pa6.netco) grain Peter Ehrlich qf netcom4 (NETCOM-la19.netc) greggwb Gregory W. Blas qc netcom22 (greggwb.slip.net) gregoire Greg B. q2 netcom15 (NETCOM-lb7.netco) grey Grey Death - Digital Targe p8 netcom6 (NETCOM-mon5.netc) grindoom Daryth Kendrickson 0:03 rf netcom14 (rocky.ucdavis.ed) grip pa netcom7 (NETCOM-sj21.netc) groo Kiran Wagle q4 netcom10 (NETCOM-dc7-1.net) guardian Andrew Denton q2 netcom11 (NETCOM-sc6.netco) guardian Andrew Denton qd netcom19 (netcom11) gwolfe Graham Wolfe q0 netcom3 (NETCOM-al11.netc) haag Stephanie Haag pc netcom4 (NETCOM-tam2.netc) hager Sean Hager s2 netcom15 (NETCOM-atl16.net) haku kevin Perreira qc netcom12 (NETCOM-wc1.netco) halanker Hal Anker pb netcom3 (NETCOM-sd10.netc) halex Alexander Hurwitz p7 netcom10 (NETCOM-pa1.netco) halo Alex Huang r5 netcom5 (NETCOM-pa1.netco) hammitt James A. Hammitt t1 netcom12 (NETCOM-lb8.netco) hammonds Kenneth Hammonds 0:11 p0 netcom10 (NETCOM-la19.netc) hanagar Dave Brombaugh r3 netcom12 (NETCOM-sea7.netc) hanson Hanson T. p5 netcom22 (werple.mira.net.) harmony Tara Lynch p9 netcom12 (NETCOM-pa4.netco) haroon Omar Haroon p4 netcom16 (NETCOM-la1.netco) harta Adam Hart pc netcom8 (NETCOM-wc7.netco) hary Jim Rhoads pb netcom9 (NETCOM-lv3.netco) hausmanc TheFixer p5 netcom6 (NETCOM-pa4.netco) hawk2 hawky 0:40 *p6 netcom6 (somebody.punk.ne) heathn Heath Newburn s4 netcom4 (NETCOM-aus3.netc) hhannam holly hannam sf netcom2 (NETCOM-ir5.netco) hogaboam Andrew Hogaboam 1:54 q2 netcom22 (ix-sj24-28.ix.ne) holl Ignatz the Horrible s5 netcom15 (NETCOM-sj14.netc) hoodr Robert Hood 0:02 *t6 netcom9 (admin.noc.netcom) hozey Howard Jones r7 netcom19 (NETCOM-sf6.netco) hsing johnny wang t3 netcom14 (NETCOM-sf17.netc) htoo 0:03 q7 netcom6 (NETCOM-wc1.netco) huangjac Jason Huang q8 netcom12 (NETCOM-la20.netc) ia Litton Industrial p1 netcom5 (NETCOM-pl8.netco) igorg Igor Gurovich 0:12 r9 netcom18 (NETCOM-sf17.netc) imagine Michael Tenery 7:55 s5 netcom7 (NETCOM-atl10.net) ine Emily Chhor p7 netcom20 (NETCOM-la20.netc) ine Emily Chhor pb netcom7 (NETCOM-la21.netc) inf8ltd Benjamin Wang p1 netcom15 (NETCOM-lb9.netco) ironic Fruits Of Nature...aka cIV q3 netcom14 (NETCOM-lb5.netco) jackkolb Jack Kolb q2 netcom2 (NETCOM-la1.netco) jacobe Gail Kenner p0 netcom18 (NETCOM-sac5.netc) jaegerms jaegerms@netcom.com *p4 netcom (bighorn.accessnv) jagatai Lars Jagatai Bunch q0 netcom20 (NETCOM-pas12.net) jakala henry jakala pe netcom21 (NETCOM-chi13-1.n) jamesbur Robert Burnett q4 netcom4 (NETCOM-sj16.netc) jamwal A J r1 netcom20 (NETCOM-sj12.netc) jaraq Brian Haines p9 netcom21 (NETCOM-cin4.netc) jau Jennifer Au s5 netcom11 (NETCOM-lb5.netco) jaycheng SHOU-JEI CHENG p9 netcom7 (NETCOM-pl2.netco) jbeheler Joey Beheler 0:10 pf netcom7 (NETCOM-pa4.netco) jch Chia-Hwong Hwang qa netcom3 (NETCOM-sj34.netc) jchap John Chappelear *t2 netcom3 (NETCOM-sac5.netc) jconklin J.T. Conklin *q9 netcom4 (NETCOM-sf6.netco) jeffml Jeff Lightfoot p3 netcom17 (131.36.128.128) jeffsyl *Unknown* qd netcom5 (NETCOM-sea4.netc) jeffx Jeff Crilly q8 netcom19 (NETCOM-pa3.netco) jend Jennifer M. Douglas 1:43 r0 netcom (ix-sc5-24.ix.net) jerel Jerel E. Ellison 0:54 p2 netcom19 (NETCOM-sj23.netc) jermsnap Jermsnap rb netcom9 (NETCOM-pl10.netc) jfbrewer jeremy brewer r1 netcom2 (NETCOM-sd10.netc) jferra JJ Ferra q7 netcom11 (NETCOM-pl3.netco) jhoffman John Hoffman 0:02 pc netcom21 (office4.netcom.c) jimlynch Jim Lynch *qc netcom20 (NETCOM-al6.netco) jina FireStorm/DarkStar2 qf netcom23 (lennon.pub.csufr) jkabakov Joel Kabakov 9:10 ra netcom10 (NETCOM-ir6.netco) jkumarr Soulman 0:01 *q7 netcom14 (leonis.nus.sg) jliang Jimmy Liang *p1 netcom19 (NETCOM-sj16.netc) jlk Gerald Koenig pb netcom13 (NETCOM-la21.netc) jmclark James M. Clark qa netcom11 (NETCOM-al3.netco) jmv John Maguire 0:01 r2 netcom14 (NETCOM-sj26.netc) jnishina John Nishinaga *qb netcom13 (NETCOM-la2.netco) joelyons Shibumi 0:10 sb netcom19 (NETCOM-la20.netc) joeshea Joe Shea 0:19 q7 netcom20 (NETCOM-pas10.net) johne john eisenberg p9 netcom17 (NETCOM-pas12.net) jondr Whatever makes you happy p2 netcom14 (NETCOM-dfw11.net) jony pd netcom6 (NETCOM-lb8.netco) jordan Jordan Bortz 0:03 q5 netcom (165.227.93.5) joshk joshk@netcom.com 2:41 t3 netcom2 (NETCOM-la20.netc) jpdavid John Kordic q3 netcom15 (NETCOM-la18.netc) jpenrose James Penrose pa netcom17 (NETCOM-ir13.netc) jpf Jonathan P. Finnecy q3 netcom10 (NETCOM-la18.netc) jreque Martin Won pb netcom14 (NETCOM-pa7.netco) jthill Jim Hill 0:01 *q6 netcom2 (NETCOM-pa7.netco) jthomps Jeff Thompson q4 netcom13 (netcom15) jthomps Jeff Thompson pe netcom15 (NETCOM-den11.net) jtthomas Janice T. Thomas r4 netcom10 (NETCOM-sj35.netc) jules SnowBuny--Southern Califor 4:51 *pf netcom9 (NETCOM-ir2.netco) jurassic 0:05 p2 netcom20 (NETCOM-pa7.netco) jux marcellus' wife *q7 netcom19 (NETCOM-al1.netco) jwagner3 John Wagner q8 netcom4 (NETCOM-sf5.netco) karlb Karl Buiter 0:23 pd netcom11 (NETCOM-al6.netco) kaupe Raelani! and Teri p3 netcom16 (NETCOM-sc5.netco) kay Karen Heyman rb netcom (ix-wh6-26.ix.net) keno Ken O'Connor *s6 netcom11 (NETCOM-dfw11.net) ker Keith E. Rowland 0:01 p5 netcom2 (140.174.162.102) kglady Korene Geffen p2 netcom15 (NETCOM-den5.netc) khkwong Kelvin Kwong 0:03 re netcom20 (netcom23) khkwong Kelvin Kwong 0:03 pa netcom21 (NETCOM-sf14.netc) khkwong Kelvin Kwong q4 netcom23 (netcom20) killer8 jong-il kin pa netcom2 (NETCOM-slc3.netc) kilty Kathleen Richards s9 netcom16 (NETCOM-ont4.netc) kjames Kevin R. James p0 netcom22 (NETCOM-sd9.netco) kkrebs Ken Krebs 0:33 p0 netcom3 (NETCOM-sj18.netc) klutz Kenneth Lu ra netcom17 (NETCOM-sj22.netc) kma Kevin Archibald p2 netcom10 (NETCOM-pa7.netco) kman The_Multimedia_Maddman 1:30 r2 netcom15 (NETCOM-dfw9.netc) kmg1 q8 netcom10 (NETCOM-har5.netc) kmodemod .teklordZ.epinicion. pb netcom11 (NETCOM-sac4.netc) kmorgan Kevin Morgan q5 netcom2 (NETCOM-sj18.netc) kodiak Chris D Koeberle p0 netcom9 (NETCOM-dfw10.net) koster q0 netcom17 (NETCOM-sj9.netco) koz cole maddox *pa netcom19 (NETCOM-atl6.netc) krist kristina 3.2 p7 netcom12 (NETCOM-ir13.netc) ksparger *p4 netcom9 (NETCOM-hou5.netc) ksparger 0:03 *qf netcom21 (netcom9) kutter Joe Judd r1 netcom5 (NETCOM-den13.net) kvie KVIE p6 netcom (ppp3.ns.net) kylec kyle cummings 0:21 qb netcom14 (NETCOM-sac4.netc) kymer J Kymer p6 netcom22 (NETCOM-la2.netco) kyoshiro Salamandrina pe netcom9 (NETCOM-mon5.netc) lament Jason Ernsberger p1 netcom4 (NETCOM-sd9.netco) lasher James LLasher Suzanne C Cl p2 netcom23 (NETCOM-sea6.netc) lcypher Louis Cypher p1 netcom3 (NETCOM-hou5.netc) lda Leonard D Atkinson II 0:08 qd netcom8 (NETCOM-wc1.netco) lede charles chapman p1 netcom11 (NETCOM-la2.netco) lemming Nathan Clark pf netcom21 (NETCOM-lv5.netco) lenr Leonard Rosenzweig 0:01 q6 netcom23 (NETCOM-la20.netc) leper Mortensen q5 netcom20 (NETCOM-or10.netc) lestat25 Christian Dion qf netcom20 (NETCOM-sj10.netc) lewiz Lewis De Payne pb netcom16 (NETCOM-pas12.net) lewrose Lewis Rose p9 netcom14 (NETCOM-dc7-1.net) licon Lord Icon qc netcom14 (NETCOM-sj10.netc) lii Listen to Him *p1 netcom12 (cyber.net) lim Lonnie Itzkovich q7 netcom9 (NETCOM-nyc9.netc) limj Jack Lim 0:02 qe netcom5 (NETCOM-al6.netco) lincmad Linc Madison *p2 netcom17 (NETCOM-sf17.netc) ljp Lee J. Papageorge 0:01 p4 netcom5 (NETCOM-la21.netc) llarrow Lynn Larrow q1 netcom18 (NETCOM-sf9.netco) llm Ajeh 0:42 qd netcom12 (NETCOM-clv2.netc) lmy Leonid M. Yaroslavsky pd netcom17 (NETCOM-sea4.netc) longh Hoang r1 netcom17 (NETCOM-sj10.netc) looser Sean Bettencourt 0:04 pf netcom4 (NETCOM-sj12.netc) lordr william woodburn jr. q8 netcom7 (NETCOM-sea6.netc) lorenz John Lorenz 0:01 p0 netcom14 (NETCOM-sea5.netc) lorenz John Lorenz r0 netcom9 (netcom14) lorindel Lorindel 1:18 *qc netcom23 (140.145.250.170) lsaid Loai Said qc netcom6 (NETCOM-la18.netc) ltd Larry Drebes 2:17 sb netcom22 (rush.drebes.com) lynx Conrad Wong 0:01 pb netcom17 (NETCOM-pa7.netco) machida Eileen Machida r5 netcom16 (NETCOM-sf6.netco) mackdaly Bill Daly q1 netcom8 (NETCOM-atl7.netc) mackn Mack Nagashima qe netcom11 (NETCOM-pas10.net) macnevin Brian MacNevin pc netcom3 (NETCOM-ir16.netc) macronix Macronix p3 netcom5 (NETCOM-sj16.netc) mage Krista Landon qb netcom18 (pm011-03.dialip.) maggie Maggie MacDonald t3 netcom19 (NETCOM-sd8.netco) malakar Gary Larsen pc netcom7 (NETCOM-atl8.netc) manfred John Slane q4 netcom18 (NETCOM-col3.netc) mapenzi Brett Stewart 0:01 p7 netcom13 (NETCOM-sf10.netc) margali Deird'Re M. Brooks q4 netcom19 (NETCOM-or11.netc) margeb CJB 0:13 p2 netcom16 (NETCOM-orl1.netc) martinak Martina Koldewey p3 netcom4 (NETCOM-sf11.netc) masegian John Daniel Masegian p5 netcom16 (NETCOM-sj25.netc) mchoe Michael Choe 0:03 q8 netcom14 (NETCOM-sac5.netc) mcstout Mark C. Stout ra netcom8 (NETCOM-sac4.netc) mdavies Mark Davies r4 netcom22 (NETCOM-sr4.netco) medea Medea p3 netcom6 (NETCOM-phx3.netc) megans gasp 0:08 q2 netcom4 (203.12.112.4) memcr qb netcom5 (NETCOM-la18.netc) metal69 Pramod Pottayil td netcom19 (NETCOM-nyc11.net) mgong Michael Gong p0 netcom (netcom17) mgong Michael Gong r4 netcom17 (NETCOM-sd8.netco) migrnd MR 0:01 p8 netcom22 (NETCOM-sj34.netc) mikehell Kontrol Faktory q4 netcom21 (NETCOM-pas12.net) mikeoo Linda MacGowan q8 netcom22 (NETCOM-sea4.netc) milkbone B Tunick r1 netcom8 (NETCOM-sj11.netc) mingo steven clark 0:06 pf netcom16 (NETCOM-al2.netco) mirowall Andrew Hahn q0 netcom4 (NETCOM-lb5.netco) mirsasha Miri p8 netcom17 (NETCOM-aus2.netc) mister Eben Ozen *qa netcom4 (NETCOM-lb5.netco) mistyros Super Brat!! 0:09 r5 netcom12 (NETCOM-ir5.netco) mizag Manuel Izaguirre p8 netcom23 (NETCOM-ir16.netc) mjclark Sensei q1 netcom20 (NETCOM-sd10.netc) mjimenez michael jimenez q6 netcom10 (NETCOM-pa6.netco) mjn Marc Neuberger p6 netcom16 (NETCOM-bos5.netc) mmm3 Mark Mayeda r3 netcom9 (NETCOM-al3.netco) mmosko Marc E. Mosko q7 netcom8 (NETCOM-sf13.netc) mmsiwest Bart Pinto q9 netcom20 (NETCOM-wc7.netco) mnelson Michael Nelson p1 netcom7 (NETCOM-sj12.netc) modemboy MoDeMbOy 0:12 *pe netcom18 (NETCOM-den10.net) mont Mont Pierce se netcom10 (NETCOM-pl10.netc) monterey David Wong p6 netcom21 (localhost) monty1 monty Kane q0 netcom12 (NETCOM-sf10.netc) moredhel Duncan Idaho 0:13 p1 netcom (wcsub.ctstateu.e) moto Moto 0:03 pb netcom10 (NETCOM-aus3.netc) motofuji Richard Motofuji q6 netcom9 (NETCOM-al3.netco) moxie subPerignon 2:41 u4 netcom4 (NETCOM-phi1.netc) mperez Manuel Perez-Pabon 0:01 p6 netcom11 (NETCOM-ir13.netc) mpr MPR Associates Inc 0:02 p3 netcom7 (netcom15) mpr MPR Associates Inc 0:02 pc netcom15 (NETCOM-al6.netco) mrclean Thx1138 0:01 q1 netcom5 (NETCOM-sj11.netc) mre john smith 0:01 q5 netcom16 (NETCOM-nwk11.net) mriddell mr p8 netcom5 (NETCOM-sea4.netc) mrmacky John MacMaster p5 netcom20 (NETCOM-atl6.netc) mrmarks Henry Stauf p7 netcom16 (NETCOM-kc5.netco) mrose martin rosenberg 0:08 qd netcom9 (NETCOM-pl2.netco) msako Mitch Sako rb netcom18 (NETCOM-sj10.netc) msamett Michael Samett p0 netcom11 (NETCOM-la18.netc) msilva "Murder was the Case" q3 netcom17 (NETCOM-sj13.netc) mskathy MsKathy 0:57 *s6 netcom22 (office3) mtuxford Mike Tuxford t2 netcom20 (NETCOM-phx3.netc) mtuxford Mike Tuxford s9 netcom21 (netcom20) multitek Daron J. Wilson r6 netcom9 (NETCOM-sea5.netc) mundsack Jon Mundsack 1:19 p8 netcom11 (NETCOM-chi11-1.n) munin p4 netcom11 (NETCOM-sj13.netc) murphyc C. Murphy r7 netcom22 (NETCOM-la19.netc) musicman Bruce Berns pd netcom14 (NETCOM-la18.netc) mwalker maria walker s0 netcom11 (NETCOM-wp1.netco) n9s6m sub numin viget r1 netcom9 (NETCOM-nyc14.net) nancydrw Thaddeus R. Croyle (Girl S q7 netcom16 (NETCOM-sf9.netco) narwhal Narwhal s7 netcom8 (NETCOM-la21.netc) nc0015 John M. Wu *qe netcom20 (manofpower.netco) nc0096 0:02 pd netcom21 (madras.netcom.co) nc0118 0:03 u2 netcom16 (voyeur.noc.netco) nc0147 nc0147 p7 netcom15 (NETCOM-sj34.netc) nc0147 nc0147 0:02 p3 netcom22 (solar.netcom.com) nc0150 q6 netcom20 (office3) nc0150 0:02 qc netcom21 (office3) nc0150 0:02 q0 netcom22 (office3) nc0256 Tech Support -- Cera 0:09 q5 netcom5 (netcom16) nc0256 Tech Support -- Cera ra netcom16 (office4.netcom.c) ncohen Nicholas Cohen 0:02 qc netcom15 (NETCOM-lb5.netco) necron99 Robert French p4 netcom23 (NETCOM-sf10.netc) necron99 Robert French p7 netcom9 (NETCOM-sf5.netco) nee Cheng-Lee Nee 0:03 q8 netcom2 (NETCOM-sj30.netc) neilt Neil Taneja p3 netcom2 (NETCOM-pas11.net) netnews USENET Administration *pe netcom19 (rancor) nevers Nick Evers 0:14 r1 netcom4 (NETCOM-phx3.netc) newsntwk MQM Information Services N r0 netcom11 (NETCOM-sj26.netc) nfe Nathan Estey q0 netcom19 (NETCOM-dc10-1.ne) nielsen Dale Nielsen q5 netcom14 (NETCOM-wh6.netco) nil Neil T. Nakao q6 netcom12 (NETCOM-ir14.netc) ninthwav Waves That Meet 0:01 s4 netcom11 (NETCOM-den14.net) nmsison Nina Sison 0:16 p4 netcom18 (NETCOM-lv6.netco) nont Nont Chiranand *pb netcom19 (NETCOM-dfw10.net) norinm Michael P. Norin r3 netcom20 (NETCOM-la24.netc) normedw Norman Edwards pf netcom12 (NETCOM-atl6.netc) ogre Mr. Ogre p8 netcom2 (NETCOM-ir13.netc) omen Jr. 0:03 p9 netcom13 (netcom17) omen Jr. 0:06 rd netcom17 (NETCOM-sac5.netc) orphy A Retired Unix Sys. Admin. 0:01 r0 netcom16 (NETCOM-stl3.netc) oscarc The Doctor Is In pa netcom15 (NETCOM-pl4.netco) pacifica Russell q5 netcom18 (NETCOM-pas12.net) padma Padma Rao 0:31 r9 netcom15 (NETCOM-atl9.netc) pagli [flaco] 5:24 ra netcom5 (NETCOM-dc6-1.net) paranoia Tyler Walden p8 netcom18 (NETCOM-or10.netc) park Bill Park qa netcom6 (NETCOM-pa1.netco) party Rick 0:09 r3 netcom21 (office4.netcom.c) paseo casey cho q4 netcom16 (NETCOM-la2.netco) path path 0:01 qf netcom9 (NETCOM-pa6.netco) pauley Paul Willett v0 netcom8 (NETCOM-den7.netc) pauljo Paul Johnson q0 netcom13 (NETCOM-wh5.netco) pch peter hun sd netcom2 (NETCOM-lb8.netco) pcheng01 Poyuan Cheng q6 netcom6 (NETCOM-sj11.netc) pchin Midknight pe netcom7 (NETCOM-nyc14.net) pcspec Elaine Sampson qc netcom13 (NETCOM-sd8.netco) peachez Life Is Just PeAcHy 0:06 p7 netcom2 (NETCOM-nyc5.netc) pegges Paul Egges *qa netcom10 (NETCOM-den6.netc) pepsiman Pepsiman/of netcom.com *qf netcom2 (NETCOM-nyc10.net) perez ralph perez r9 netcom6 (NETCOM-la21.netc) pettefer Matt Pettefer p6 netcom15 (NETCOM-atl13.net) pfarrell Pat Farrell q3 netcom18 (NETCOM-dc7-1.net) pfisher Paul Fisher q4 netcom22 (NETCOM-hou5.netc) pfnguyen Perry F Nguyen *pb netcom4 (NETCOM-al6.netco) pgraham Paul Graham qe netcom12 (NETCOM-atl7.netc) phao David Emery r3 netcom2 (NETCOM-sea6.netc) phylo Olav Phillips p6 netcom18 (NETCOM-wc6.netco) phylo Olav Phillips *r1 netcom19 (netcom18) pimentel Wide Awake *p5 netcom15 (NETCOM-la19.netc) pjr Paul Rank qc netcom11 (NETCOM-sj11.netc) pleh David Hopman q9 netcom12 (NETCOM-pa7.netco) ponyboy Bucky pa netcom3 (NETCOM-wc7.netco) poyang Po-Yang Shih *q5 netcom22 (stucco.cco.calte) prburgos *umop-ap!sdn 6u!6uey* rc netcom8 (NETCOM-nyc14.net) preacher Paul 0:06 *q1 netcom13 (NETCOM-la24.netc) prefect prefect s5 netcom16 (NETCOM-dc14-1.ne) profile Profile Software r3 netcom7 (NETCOM-sf5.netco) pug Charles Peri se netcom15 (NETCOM-sac8.netc) puppy W.E.L.T. p8 netcom3 (NETCOM-sea4.netc) pwrbomb VEE JAY pe netcom12 (NETCOM-sf5.netco) pwt Peter Thornton 3:34 r3 netcom (maple.circa.ufl.) question ??? pd netcom19 (NETCOM-la22.netc) quintrel Fred Quintrell p6 netcom23 (NETCOM-pas10.net) quozl D.M. "Quozl" Falk p1 netcom17 (redwood.northcoa) raheeb Raheeb Rahman 1:52 *pf netcom (ix-wh6-02.ix.net) ralph Ralph Warren Pearson 0:03 s0 netcom21 (mola.org) ramia Sean Ramia p9 netcom2 (NETCOM-pl4.netco) ranmas RuGal pc netcom12 (NETCOM-pl1.netco) ransacks Maureen C. Blair q1 netcom17 (NETCOM-dfw10.net) ratcat Smitten 0:01 p2 netcom8 (NETCOM-sf5.netco) rattle jack 0:01 p0 netcom20 (NETCOM-sf10.netc) ravenna monique Saltik t1 netcom14 (163.179.12.14) rbh00 Richard Hitt r0 netcom5 (NETCOM-pa7.netco) rblees robert blees qe netcom10 (NETCOM-sf6.netco) realpro Realpro BBS 0:02 pa netcom14 (NETCOM-lv6.netco) rei Lupa p6 netcom20 (NETCOM-la19.netc) rei Lupa pe netcom3 (NETCOM-la19.netc) rere rere p2 netcom7 (NETCOM-dfw11.net) reznor r6 netcom7 (NETCOM-sf12.netc) rhardin richard hardin 0:03 qa netcom5 (NETCOM-sd8.netco) rhardin richard hardin 0:02 q3 netcom4 (NETCOM-sd8.netco) rhiana Ruth Gardner q5 netcom3 (NETCOM-dc10-1.ne) rhinewhn Mr Self Destruction u0 netcom11 (NETCOM-sac7.netc) rhosono 4:50 *qe netcom22 (NETCOM-sd10.netc) ricep q4 netcom14 (NETCOM-pa4.netco) richardc Richard 13:37 *q8 netcom6 (netcom5) richgold Richard Goldstein 0:04 q0 netcom (NETCOM-bos5.netc) richh richh 0:08 p9 netcom8 (163.179.37.13) richie Richard Collins r5 netcom3 (NETCOM-wc1.netco) rickynew Ricky New p3 netcom12 (NETCOM-sf9.netco) rivethed Placebozoid 0:06 q2 netcom5 (NETCOM-mon5.netc) rlee Robert Lee r2 netcom12 (NETCOM-ir15.netc) rleung Ryan 0:09 rd netcom3 (NETCOM-pl8.netco) rng Ronald Ng p7 netcom11 (NETCOM-pas10.net) robertle Leung re netcom5 (NETCOM-sj18.netc) robertp Flashback sc netcom2 (NETCOM-chi11-1.n) robrt Robert Eliason 0:16 t4 netcom19 (NETCOM-wc7.netco) robwong Robert Wong 0:03 q2 netcom12 (NETCOM-dc7-1.net) rodthomp Roderick Thompson r1 netcom13 (NETCOM-sac10.net) roessler Robert Roessler r3 netcom13 (NETCOM-ir15.netc) rogaine Christopher Roe q1 netcom7 (NETCOM-pa6.netco) rogeorge R. LaMont George p2 netcom6 (NETCOM-den12.net) rosewood Shankar Khadye p5 netcom13 (NETCOM-sj24.netc) rriggs Robert Riggs sb netcom18 (NETCOM-den12.net) rrward Richard Ward p7 netcom21 (jdc-p1-30.alaska) rsf Raul Fernandez q6 netcom18 (NETCOM-la18.netc) rsh Roy Ho q7 netcom13 (NETCOM-sj14.netc) rsummers ron summers p0 netcom7 (NETCOM-wc7.netco) rune Rune ShadowMaster pc netcom9 (NETCOM-nyc12.net) rupa Rupa Schomaker *pf netcom3 (NETCOM-la20.netc) russh russell hull p7 netcom14 (NETCOM-dfw9.netc) rustman Rusty H. Hodge ta netcom3 (NETCOM-sf13.netc) rut Ruth Caspary 0:06 q5 netcom10 (NETCOM-pas11.net) rzs Vlad Shmunis q8 netcom15 (NETCOM-sf10.netc) rzussman Ronald Zussman q0 netcom21 (NETCOM-nyc14.net) sabbat Heidi Hill 0:01 r5 netcom (ix-fre-ca1-13.ix) sabeena Sabeena qd netcom20 (NETCOM-slc4.netc) sacker Charles M. Solen q0 netcom23 (NETCOM-lv5.netco) sagent For Your Eye's Only! 0:05 q8 netcom8 (NETCOM-lb6.netco) samkho Samuel P Kho pa netcom6 (NETCOM-pa7.netco) sang Lee Sang Jun p1 netcom10 (NETCOM-mon5.netc) saotome Toshiya Mogi Saotome 0:01 p3 netcom9 (NETCOM-phi2.netc) sappel Shannon Appel p4 netcom17 (soda.CSUA.Berkel) sarajevo Miroslav Curac 2:07 qd netcom13 (NETCOM-lb6.netco) savdrag Raw Raw like I got Cerebal q6 netcom11 (NETCOM-or11.netc) sbrindle Stephen Thomas Brindle *pe netcom11 (NETCOM-al11.netc) scandal Peace Frog... pe netcom13 (NETCOM-dfw11.net) schizo p9 netcom20 (NETCOM-sj34.netc) schuyler Gabriel M. Schuyler t2 netcom15 (NETCOM-sf17.netc) schuyler Gabriel M. Schuyler q5 netcom23 (netcom15) sdabbs Steve Dabbs rc netcom17 (NETCOM-atl14.net) sdy Shahrokh Yadegari p3 netcom18 (NETCOM-la19.netc) select The Unknown q4 netcom7 (NETCOM-al11.netc) sergeyk Sergey Kirshner qd netcom2 (NETCOM-sf10.netc) sergiohv Sergio H. Villalba r8 netcom12 (NETCOM-la18.netc) serpent Pat Coleman p1 netcom2 (NETCOM-atl6.netc) setsuna Setsuna Meioh p0 netcom5 (NETCOM-lb6.netco) sfb sfb p1 netcom18 (NETCOM-hou5.netc) sfd Scott Drellishak q2 netcom21 (drellishak.com) sharons *p3 netcom23 (NETCOM-atl6.netc) shaunski Shaun Leavold s1 netcom20 (NETCOM-sj19.netc) shawn Shawn Hayes 0:28 q0 netcom18 (netcom17) shawn Shawn Hayes 0:28 r8 netcom17 (NETCOM-atl9.netc) sheri q4 netcom6 (ferd.sco.COM) shkim Tony Sison r8 netcom5 (NETCOM-sj12.netc) shoryken [PsYcHo CrUsHeR] *pd netcom10 (NETCOM-atl8.netc) sima Rikke Stanger tf netcom12 (kendaco.telebyte) sjoboat Gary Sjobakken pb netcom18 (NETCOM-lb6.netco) sjohnson Rashama Johnson 0:01 p5 netcom (netcom19) sjohnson Rashama Johnson pc netcom19 (NETCOM-pas12.net) skylar mike atchley r3 netcom10 (NETCOM-dc14-1.ne) slayer Neil Stewart/Dayvid Iannac q8 netcom13 (NETCOM-la23.netc) slo Stephen Lo *qe netcom13 (NETCOM-pas10.net) small q0 netcom14 (netcom18) small sf netcom18 (NETCOM-sf14.netc) smithajj Aaron Smith r5 netcom6 (NETCOM-pa6.netco) smithtom p1 netcom14 (NETCOM-or10.netc) smryan Steven Ryan p2 netcom3 (NETCOM-sj19.netc) smryan Steven Ryan 0:09 pf netcom10 (NETCOM-sj11.netc) smutrbfn Jamie pc netcom10 (NETCOM-sj13.netc) snakee Jake the Snake 1:31 *sc netcom17 (NETCOM-ir6.netco) snap re netcom17 (NETCOM-mon5.netc) snoddy Robert Snodgrass p8 netcom9 (NETCOM-ir13.netc) snoflo Spencer Weise p3 netcom10 (NETCOM-dfw9.netc) soong soong park p0 netcom19 (NETCOM-sj10.netc) source David Harmon qe netcom21 (NETCOM-la3.netco) spector DH rc netcom6 (NETCOM-sac10.net) sphariss steve phariss re netcom15 (NETCOM-sac7.netc) spond Kurt Chirhart p1 netcom22 (NETCOM-atl6.netc) spsycho Satanic Psycho p5 netcom5 (NETCOM-atl7.netc) spyrus SPYRUS pc netcom2 (NETCOM-pl1.netco) ssmith Steve q4 netcom17 (NETCOM-la20.netc) stangel p3 netcom11 (NETCOM-wc2.netco) starbrdg Sky Gifs qa netcom15 (NETCOM-sea4.netc) stedman Scrounger q5 netcom13 (NETCOM-la5.netco) stefan Kay Schmelzenbach p0 netcom12 (NETCOM-or11.netc) steffen David Steffen pe netcom10 (NETCOM-ir14.netc) stellar David Weinstein q9 netcom15 (NETCOM-wc7.netco) stephg Stephanie Grusch qe netcom16 (NETCOM-pa7.netco) sternkin Mike Stern pf netcom11 (NETCOM-wh5.netco) stonem PWA '95 t1 netcom6 (NETCOM-la24.netc) stormk Storm A. King r3 netcom16 (NETCOM-pa1.netco) straedey Richard Straedey p4 netcom4 (NETCOM-la18.netc) stripey Stripey rc netcom5 (NETCOM-sj30.netc) succeed George Galustian p1 netcom8 (NETCOM-wh3.netco) sulaco Sulaco pc netcom16 (NETCOM-pas10.net) sylys Mark Merlino q9 netcom5 (NETCOM-ir16.netc) tara erin grady rd netcom5 (NETCOM-sd9.netco) tarbush Joe 0:01 s9 netcom13 (NETCOM-lv4.netco) taylorp Patrick Taylor q2 netcom14 (NETCOM-pas10.net) teac Jason Jenkins p6 netcom13 (NETCOM-lv5.netco) techknow Mark Goetze 0:03 rf netcom3 (netcom8) techknow Mark Goetze 0:01 p4 netcom8 (NETCOM-sd10.netc) tessien Chris Kroninger pb netcom5 (NETCOM-sj34.netc) thanos Lupe God of Spam qb netcom15 (NETCOM-sac5.netc) tharper Tupshin Harper pb netcom23 (163.176.32.103) thechous q7 netcom2 (NETCOM-al6.netco) therat Wade P Evans q7 netcom12 (NETCOM-sc5.netco) thwack Chris Clarke p0 netcom17 (NETCOM-pas10.net) thwack Chris Clarke p9 netcom22 (NETCOM-pas12.net) timbol Mike Timbol p4 netcom3 (NETCOM-sc5.netco) tismb jason saliba 7:08 r9 netcom10 (NETCOM-clv2.netc) tjmiles Terry Miles r2 netcom17 (NETCOM-lv4.netco) tnt Terry Turner r2 netcom3 (NETCOM-pa3.netco) tori Paul Nagai pa netcom13 (NETCOM-sj34.netc) totoro1 Totoro q1 netcom6 (NETCOM-sf4.netco) tozun orhan tozun q1 netcom2 (NETCOM-sj12.netc) tpstrain Dan Caldwell pc netcom5 (NETCOM-la20.netc) tristan Turner Morgan q0 netcom6 (NETCOM-sf16.netc) tsalagi *q0 netcom11 (NETCOM-sac5.netc) tsalagi 0:01 *q6 netcom3 (netcom11) tsn Susan Bryant p9 netcom (emerald.cybergat) tspence Ted Spence p7 netcom6 (NETCOM-pas10.net) turk pe netcom (terminus.dcn.dav) twfic Ty Fairchild 0:03 p7 netcom18 (NETCOM-wh6.netco) tygger Tygger 0:02 pa netcom12 (NETCOM-sd11.netc) unicon Roger Kuperways sb netcom4 (NETCOM-nyc11.net) uptime Uptime Computer Solutions r3 netcom17 (NETCOM-sf14.netc) vailikit Toma Vailikit p9 netcom9 (NETCOM-dc8-1.net) victoria Victoria Vogt pe netcom4 (NETCOM-ont4.netc) vinh Vinh Luu p6 netcom10 (NETCOM-sf12.netc) vinhle Vinh Le 0:02 *q1 netcom21 (NETCOM-la18.netc) voyagers mike myers *p7 netcom4 (NETCOM-sc1.netco) vrotney William Paul Vrotney qd netcom6 (NETCOM-sj28.netc) vsclyne V Shannon Clyne pd netcom9 (NETCOM-sc5.netco) vvw Ville V Walveranta p9 netcom5 (NETCOM-al3.netco) vychin Vincent Y. Chin r3 netcom11 (NETCOM-sf5.netco) walkerk Kent Walker *qe netcom6 (NETCOM-sf5.netco) wanderer Todd Gionet tb netcom8 (NETCOM-ir13.netc) warrior Metallic Warrior 0:04 p3 netcom8 (NETCOM-sd9.netco) warwick1 warwick1 0:07 p6 netcom7 (NETCOM-lb6.netco) wb6mlc ken chong p2 netcom4 (NETCOM-pl1.netco) wbacon william bacon p9 netcom16 (NETCOM-or10.netc) wbristow Walter Bristow p1 netcom6 (NETCOM-or10.netc) wbuckley william buckley p5 netcom18 (NETCOM-ont3.netc) weasle G. Douglas Green q8 netcom (205.162.63.245) webbwj William Webb 0:03 s9 netcom3 (NETCOM-clv1.netc) webbwj William Webb 0:01 q6 netcom (netcom3) werecat WereCat p7 netcom19 (gumbo-ppp-e6.no.) wgg William Greathouse 0:03 p4 netcom21 (NETCOM-clv2.netc) whome wHoIZmE THa_FeLoN 0:01 p6 netcom12 (NETCOM-lb5.netco) whytock Donald Whytock r8 netcom3 (NETCOM-dc8-1.net) williamb richard belcher q6 netcom15 (NETCOM-or11.netc) wilweb William Weber q0 netcom8 (NETCOM-sj35.netc) wing Benjamin P. Wing p3 netcom13 (NETCOM-al12.netc) wjcandee William Candee 0:27 pf netcom19 (NETCOM-lb6.netco) wje William J. Evans p2 netcom2 (NETCOM-ir16.netc) wkunz William E. Kunz 0:03 pc netcom17 (NETCOM-pa1.netco) wlmcgr W.L. McGraw 0:01 pc netcom14 (NETCOM-or11.netc) wraveth .oO Wraveth / The Sage Oo. 2:03 u1 netcom4 (NETCOM-den5.netc) wtsui Willie Tsui q1 netcom19 (NETCOM-lv4.netco) xamfear Dr. Nightmare 0:01 p0 netcom13 (NETCOM-atl7.netc) xina Christina 0:08 rb netcom2 (NETCOM-al6.netco) xyzom Da Xyz u2 netcom17 (NETCOM-col1.netc) yeehang Anthony Chan q8 netcom3 (NETCOM-pl1.netco) yokosima Wing H. Yi ub netcom14 (NETCOM-nyc5.netc) yspark Yongsik Park qd netcom4 (NETCOM-la1.netco) yvette blossom 5:04 *qc netcom17 (NETCOM-har6.netc) zaneb Zane Brown p3 netcom19 (NETCOM-wc7.netco) zap Paul Eastham p6 netcom19 (NETCOM-pa1.netco) zio James Elkinton p6 netcom14 (NETCOM-sj11.netc) zrath Eric Alexander Bitton s1 netcom21 (NETCOM-la21.netc) 748 active login sessions.