From:    cons@mercury.cern.ch (Lionel Cons)
Subject: Re: how to log userids from rsh, rlogin, etc.?
Date:    Fri, 05 Aug 1994 07:22:40 +0000

In article <Ctz3t4.Dr8@rahul.net> Rahul Dhesi <dhesi@rahul.net> writes:

   The trick is to convince the server at your end to log the username
   received from the client.  Try recording debug.* syslog messages --
   perhaps your server is already logging the information you need.  If
   not, you will need to hack the sources.

I've written a Perl script that acts as a fake r* daemon and log the
attempt is syslog. Enjoy...

#!/usr/local/bin/perl
#+#############################################################################
#
#                                                                              
#
# File: rsucker                                                                
#
#                                                                              
#
# Description: Byte sucker for r* commands, log attempts with syslog.          
#
#                                                                              
#
#-#############################################################################
#

# @(#)rsucker	1.2	02/01/93	Written by Lionel Cons

# supported protocols:
#
# rexecd:
#  remote execute server:
#       [port]\0      ??? error in rexecd.c doc ???
#       username\0
#       password\0
#       command\0
#       data
#
# rlogind:
#  remote login server:
# 	\0
# 	remuser\0
# 	locuser\0
# 	terminal_type/speed\0
#  	data
#
# rshd/remshd/rcp:
#  remote shell server:
# 	[port]\0
# 	remuser\0
# 	locuser\0
# 	command\0
# 	data

# inetd.conf samples:
#
#  login        stream tcp nowait root /usr/local/etc/rsucker rsucker login
#  shell        stream tcp nowait root /usr/local/etc/rsucker rsucker sh
#  exec         stream tcp nowait root /usr/local/etc/rsucker rsucker rexec

#
# security enforcement
#
$SIG{'INT'} = 'DEFAULT';
$SIG{'QUIT'} = 'DEFAULT';
$SIG{'TERM'} = 'DEFAULT';
$SIG{'TTOU'} = 'IGNORE';
delete $ENV{'IFS'};
$ENV{'PATH'} = '/bin:/usr/bin';
delete $ENV{'PERLLIB'};

#
# constants
#
$sockaddr = 'S n a4 x8';
$AF_INET = 2;
$SOCK_STREAM = 1;
$EADDRINUSE = 226;
$IPPORT_RESERVED = 1024;

#
# init
#
require '/usr/local/etc/syslog.pl';
($progname = $0) =~ s#.*/##;
$type = $progname;
if (@ARGV > 0) {
    $type = shift;
    if ($type =~ /login/) {
	$type = 'rlogind';
    } elsif ($type =~ /exec/) {
	$type = 'rexecd';
    } elsif ($type =~ /sh/) {
	$type = 'rshd';
    } else {
	$type = $progname;
    }
}
&openlog($type . "[$$]", 'auth');
$error = 0;
$socket = 0;

#
# get connection informations
#
$addr = getpeername(STDIN);
&suicide() unless $addr;
($af, $nport, $inetaddr) = unpack($sockaddr, $addr);
@inetaddr = unpack('C4', $inetaddr);
$inetname = join('.', @inetaddr);
$remhost = "$inetname.$nport";
&syslog('warning', "attempt from $remhost");

#
# read data
#
$SIG{'ALRM'} = timeout;
alarm(60);
$output = "bad protocol";
$port = $remuser = $locuser = $info = '?';
if ($type eq 'rexecd') { # cf. rexecd.c
    $port = &getstr() unless $error;
    unless ($error) {
	if ($port) {
	    if (socket(SOCKET, $AF_INET, $SOCK_STREAM, 0)) {
		$socket = 1;
		$naddr = pack($sockaddr, $AF_INET, $port, "\0\0\0\0");
		if (bind(SOCKET, $naddr)) {
		    $naddr = pack($sockaddr, $AF_INET, $port, $inetaddr);
		    unless (connect(SOCKET, $naddr)) {
			$error = 1;
			$output = "can't connect ($!)";
		    }
		} else {
		    $error = 1;
		    $output = "can't bind socket ($!)";
		}
	    } else {
		$error = 1;
		$output = "can't create socket ($!)";
	    }
	}
	unless ($error) {
	    $name = &getstr() unless $error;
	    $pass = &getstr() unless $error;
	    $cmd = &getstr() unless $error;
	    $output = "u=$name, p=$pass, cmd=$cmd";
	}
    }
} elsif ($type eq 'rlogind') { # cf. rlogind.c
    $port = &getstr() unless $error;
    unless ($error) {
	if ($port) {
	    $error = 1;
	    $output = "unexpected port option";
	} else {
	    $remuser = &getstr() unless $error;
	    $locuser = &getstr() unless $error;
	    $info = &getstr() unless $error;
	    $output = "ru=$remuser, lu=$locuser, t=$info";
	}
    }
} elsif ($type eq 'rshd') { # cf. rshd.c
    $port = &getstr() unless $error;
    if ($port) {
	$lport = $IPPORT_RESERVED - 1;
	if (&rresvport($lport)) {
	    $socket = 1;
	    $naddr = pack($sockaddr, $AF_INET, $port, $inetaddr);
	    unless (connect(SOCKET, $naddr)) {
		$error = 1;
		$output = "can't connect ($!)";
	    }
	} else {
	    $error = 1;
	    $output = "can't reserve port ($!)";
	}
    }
    unless ($error) {
	$remuser = &getstr() unless $error;
	$locuser = &getstr() unless $error;
	$info = &getstr() unless $error;
	if ($port) {
	    $output = "p=$port, ru=$remuser, lu=$locuser, cmd=$info";
	} else {
	    $output = "ru=$remuser, lu=$locuser, cmd=$info";
	}
    }
}

#
# log the attempt
#
if ($error) {
    &syslog('err', "error: $output");
} else {
    &syslog('warning', "$output");
}

#
# close connection
#
&suicide();
exit(1); # just in case

###############################################################################
#

sub timeout {
    &syslog('err', "error: timeout occured");
    &suicide();
}

sub suicide {
    print STDERR "\001Permission denied.\r\n";
    shutdown(STDIN, 2);
    close(SOCKET) if $socket;
    &closelog();
    exit(1);
}

sub string2ascii {
    local($string) = @_;
    local($ascii, $_);

    $ascii = '';
    for (split(//, $string)) {
        if (/[\000-\037\177-\377]/) {
            $ascii .= sprintf("\\%03o", ord($_));
        } else {
            $ascii .= $_;
        }
    }
    return($ascii);
}

sub getstr {
    local($res, $c);

    $res = '';
    $error = 1, return(undef) if (read(STDIN, $c, 1) != 1);
    while (ord($c)) {
	$res .= $c;
	$error = 1, return(undef) if (read(STDIN, $c, 1) != 1);
    }
    return(&string2ascii($res));
}

sub rresvport { # cf. libc/net/rcmd.c
    local($alport) = @_;
    local($addr);

    socket(SOCKET, $AF_INET, $SOCK_STREAM, 0) || return(0);
    while (1) {
	$addr = pack($sockaddr, $AF_INET, $alport, "\0\0\0\0");
	return(1) if (bind(SOCKET, $addr));
	if ($! != $EADDRINUSE) {
	    close(SOCKET);
	    return(0);
	}
	$alport--;
	if ($alport == $IPPORT_RESERVED/2) {
	    close(SOCKET);
	    return(0);
	}
    }
}

--
Lionel Cons

+------- CERN - European Laboratory for Particle Physics -------+
| E-mail: Lionel.Cons@cern.ch                                   |
| Earth-mail: CN/DCI/UWS, CERN, CH-1211 GENEVE 23, Switzerland  |
| Phone: + (41 22) 767 49 13           Fax: + (41 22) 767 71 55 |
+---------------------------------------------------------------+

Murphy's Second Law:
	Everything takes longer than you think.


