home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeEssential SNMPSearch this book

12.2. Who's Logging into My Machine? (I-Am-in)

When Unix users log in, the system automatically executes a profile; for users of the Bourne, Korn, or bash shells, the systemwide profile is named /etc/profile. There's a similar file for users of csh and tcsh (/etc/login). We can use SNMP to record logins by adding a trap to these profiles. By itself this isn't all that interesting, because Unix already keeps a log of user logins. But let's say that you're monitoring a few dozen machines and don't want to check each machine's log. Adding a trap to the systemwide profile lets you monitor logins to all your systems from one place. It also makes your logging more secure. It's not too difficult for an intelligent user to delete the wtmp file that stores Unix login records. Using SNMP to do the logging stores the information on another host, over which you should have better control.[64]

[64]Yes, a clever user could intercept and modify SNMP packets, or rewrite the shell profile, or do any number of things to defeat logging. We're not really interested in making it impossible to defeat logging; we just want to make it more difficult.

To generate the trap, invoke the external program /opt/local/mib_ programs/os/iamin in /etc/profile (you can call the same program within /etc/login). Here is the code for iamin:

#!/usr/local/bin/perl
#
# Filename: /opt/local/mib_programs/os/iamin 

chomp ($WHO = `/bin/who am i \| awk \{\'print \$1\'\}`);

exit 123 unless ($WHO ne '');

chomp ($WHOAMI = `/usr/ucb/whoami`);
chomp ($TTY = `/bin/tty`);
chomp ($FROM = `/bin/last \-1 $WHO \| /bin/awk \{\'print \$3\'\}`);

if ($FROM =~ /Sun|Mon|Tue|Wed|Thu|Fri|Sat/) { $FROM = "N/A"; }

# DEBUG BELOW
# print "WHO :$WHO:\n"; print "WHOAMI :$WHOAMI:\n"; print "FROM :$FROM:\n";

if ("$WHOAMI" ne "$WHO") { $WHO = "$WHO\-\>$WHOAMI"; }

# Sending a trap using Net-SNMP
#
system "/usr/local/bin/snmptrap nms public .1.3.6.1.4.1.2789.2500 '' 6 1502 '' 
.1.3.6.1.4.1.2789.2500.1502.1 s \"$WHO\" 
.1.3.6.1.4.1.2789.2500.1502.2 s \"$FROM\" 
.1.3.6.1.4.1.2789.2500.1502.3 s \"$TTY\"";

# Sending a trap using Perl
#
#use SNMP_util "0.54";  # This will load the BER and SNMP_Session for us
#snmptrap("public\@nms:162", ".1.3.6.1.4.1.2789.2500", mylocalhostname, 6, 1502, 
#".1.3.6.1.4.1.2789.2500.1502.1", "string", "$WHO", 
#".1.3.6.1.4.1.2789.2500.1502.2", "string", "$FROM", 
#".1.3.6.1.4.1.2789.2500.1502.3", "string", "$TTY");

# Sending a trap using OpenView's snmptrap
#
#system "/opt/OV/bin/snmptrap -c public nms .1.3.6.1.4.1.2789.2500 \"\" 6 1502 \"\" 
#.1.3.6.1.4.1.2789.2500.1502.1 octetstringascii \"$WHO\" 
#.1.3.6.1.4.1.2789.2500.1502.2 octetstringascii \"$FROM\" 
#.1.3.6.1.4.1.2789.2500.1502.3 octetstringascii \"$TTY\"";
#

#
print "\n##############\n";
print "#   NOTICE   \# - You have been logged: :$WHO: :$FROM: :$TTY: \n"; #
print "##############\n\n";
This script is a bit meatier than expected because we need to weed out a number of bogus entries. For instance, many programs run within a shell and hence invoke the same shell profiles. Therefore, we have to figure out whether the profile is being invoked by a human user; if not, we quit.[65] The next step is to figure out more about the user's identity; i.e., where she is logging in from and what her real identity is -- we don't want to be confused by someone who uses su to switch to another identity. The third part of the program sends the trap with all the newly found information (who the user is, the host from which she is logging in, and what TTY she is on). We've included trap-generation code using the Net-SNMP utilities, the native Perl module, and OpenView's utilities. Take your pick and use the version with which you're most comfortable. The last portion of this program tells the user that she has been logged.

[65]This will also fail if the user is su'ing to another user. In a well-designed environment, users really shouldn't have to su all that often -- using sudo or designing appropriate groups should greatly reduce the need to su.

This script isn't without its problems. The user can always break out of the script before it is done, bypassing logging. You can counter this attempt by using trap(1), which responds to different signals. This forces the user to complete this program, not letting her stop in midstream. This strategy creates its own problems, since the root user doesn't have any way to bypass the check. In a sense, this is good: we want to be particularly careful about root logins. But what happens if you're trying to investigate a network failure or DNS problem? In this case, the script will hang while DNS tries to look up the host from which you're logging in. This can be very frustrating. Before implementing a script like this, look at your environment and decide which profiles you should lock.

Any of the packages for receiving traps can be used to listen for the traps generated by this program.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.