Article 2803 of comp.sources.unix:
Submitted-By: peter@ifm.liu.se (Peter Eriksson)
Posting-Number: Volume 29, Issue 127
Archive-Name: pidentd-2.7/part04

#!/bin/sh
# This is part 04 of a multipart archive.
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh08724; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= pidentd-2.7/src/crypto.c ==============
if test ! -d 'pidentd-2.7'; then
  $echo 'x -' 'creating directory' 'pidentd-2.7'
  mkdir 'pidentd-2.7'
fi
if test ! -d 'pidentd-2.7/src'; then
  $echo 'x -' 'creating directory' 'pidentd-2.7/src'
  mkdir 'pidentd-2.7/src'
fi
if test -f 'pidentd-2.7/src/crypto.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/crypto.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/crypto.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/crypto.c' &&
/*
** crypto.c                                  Crypto extension to pidentd.
**
** This file is in the public domain. -- Planar 1994.02.21
**
** Crypto routines.
*/
X
#ifdef INCLUDE_CRYPT
X
#ifdef NeXT31
#  include <libc.h>
#endif
X
#include <stdio.h>
X
#include <sys/types.h>
#include <netinet/in.h>
X
#ifndef HPUX7
#  include <arpa/inet.h>
#endif
X
#include <sys/stat.h>
#include <sys/time.h>
X
#include <des.h>
X
typedef unsigned short int_16;
typedef unsigned int   int_32;
X
struct info
{
X  int_32 checksum;
X  int_16 random;
X  int_16 uid;
X  int_32 date;
X  int_32 ip_local;
X  int_32 ip_remote;
X  int_16 port_local;
X  int_16 port_remote;
};
X
typedef union data
{
X  struct info   fields;
X  int_32        longs[6];
X  unsigned char chars[24];
} data;
X
static char result[33];
des_key_schedule sched;
X
char to_asc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
X
char to_bin[] =
{
X    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f,
X    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
X    0x3c, 0x3d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
X    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
X    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
X    0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80,
X    0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
X    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
X    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
X    0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80,
};
X
X
void init_encryption(key_text)
X    char *key_text;
{
X    des_cblock key_bin;
X    
X    des_string_to_key(key_text, key_bin);
X    des_set_key(key_bin, sched);
}
X
char *make_packet(uid, laddr, lport, faddr, fport)
X    int uid;
X    struct in_addr *laddr, *faddr;
X    int lport, fport;
{
X    struct timeval tv;
X    union data r;
X    int res, i, j;
X    
X    res = gettimeofday(&tv, NULL);
X    srand(tv.tv_usec);
X    
X    r.fields.random = rand();
X    r.fields.uid = htons(uid);
X    if (res == 0)
X    {
X	r.fields.date = htonl(tv.tv_sec);
X    }
X    else
X    {
X	r.fields.date = htonl(0);
X    }
X    
X    r.fields.ip_local = laddr->s_addr;
X    r.fields.ip_remote = faddr->s_addr;
X    r.fields.port_local = htons(lport);
X    r.fields.port_remote = htons(fport);
X
X    r.fields.checksum = 0;
X    for (i = 1; i < 6; i++)
X    {
X	r.longs[0] ^= r.longs[i];
X    }
X
X    des_ecb_encrypt((des_cblock *)&(r.longs[0]), (des_cblock *)&(r.longs[0]),
X		    sched, DES_ENCRYPT);
X    r.longs[2] ^= r.longs[0];
X    r.longs[3] ^= r.longs[1];
X    
X    des_ecb_encrypt((des_cblock *)&(r.longs[2]), (des_cblock *)&(r.longs[2]),
X		    sched, DES_ENCRYPT);
X    r.longs[4] ^= r.longs[2];
X    r.longs[5] ^= r.longs[3];
X    
X    des_ecb_encrypt((des_cblock *)&(r.longs[4]), (des_cblock *)&(r.longs[4]),
X		    sched, DES_ENCRYPT);
X
X    for (i = 0, j = 0; i < 24; i+=3, j+=4)
X    {
X	result[j  ] = to_asc[63 & (r.chars[i  ] >> 2)];
X	result[j+1] = to_asc[63 & ((r.chars[i  ] << 4) + (r.chars[i+1] >> 4))];
X	result[j+2] = to_asc[63 & ((r.chars[i+1] << 2) + (r.chars[i+2] >> 6))];
X	result[j+3] = to_asc[63 & (r.chars[i+2])];
X    }
X    result[32] = '\0';
X
X    return result;
}
X
#define MAX_KEYS 1024
X
static des_cblock keys[MAX_KEYS];
static int num_keys;
X
void init_decryption(key_file)
X    FILE *key_file;
{
X    char buf[1024];
X
X    num_keys = 0;
X    
X    while (fgets(buf, 1024, key_file) != NULL && num_keys < MAX_KEYS)
X    {
X	des_string_to_key(buf, keys[num_keys++]);
X    }
X    
X    des_set_key (keys [0], sched);
}
X
X
static char readable[75];
X
char *decrypt_packet(packet)
X    char *packet;
{
X    union data r;
X    int i, j, k;
X    time_t date_in_sec;
X    char *date_in_ascii;
X
X    for (k = -1; k < num_keys; k++)
X    {
X	if (k >= 0)
X	    des_set_key(keys [k], sched);
X	
X	for(i = 0, j = 0; i < 24; i+=3, j+=4)
X	{
X	    r.chars[i  ] = (to_bin[packet[j  ]]<<2)+(to_bin[packet[j+1]]>>4);
X	    r.chars[i+1] = (to_bin[packet[j+1]]<<4)+(to_bin[packet[j+2]]>>2);
X	    r.chars[i+2] = (to_bin[packet[j+2]] << 6) + (to_bin[packet[j+3]]);
X	}
X    
X	des_ecb_encrypt((des_cblock *)&(r.longs[4]),
X			(des_cblock *)&(r.longs[4]),
X			sched, DES_DECRYPT);
X	r.longs[4] ^= r.longs[2];
X	r.longs[5] ^= r.longs[3];
X	
X	des_ecb_encrypt((des_cblock *)&(r.longs[2]),
X			(des_cblock *)&(r.longs[2]),
X			sched, DES_DECRYPT);
X	
X	r.longs[2] ^= r.longs[0];
X	r.longs[3] ^= r.longs[1]; 
X	des_ecb_encrypt((des_cblock *)&(r.longs[0]),
X			(des_cblock *)&(r.longs[0]),
X			sched, DES_DECRYPT);
X
X	for (i = 1; i < 6; i++)
X	{
X	    r.longs[0] ^= r.longs[i];
X	}
X	
X	if (r.fields.checksum == 0)
X	    goto GoodKey;
X    }
X    return NULL;
X
X  GoodKey:
X    date_in_sec = ntohl(r.fields.date);
X    date_in_ascii = ctime(&date_in_sec);
X    
X    sprintf(readable, "%24.24s %u %u.%u.%u.%u %u %u.%u.%u.%u %u",
X	    date_in_ascii, ntohs(r.fields.uid),
X	    ((unsigned char *) &r.fields.ip_local)[0],
X	    ((unsigned char *) &r.fields.ip_local)[1],
X	    ((unsigned char *) &r.fields.ip_local)[2],
X	    ((unsigned char *) &r.fields.ip_local)[3],
X	    (unsigned) ntohs(r.fields.port_local),
X	    ((unsigned char *) &r.fields.ip_remote)[0],
X	    ((unsigned char *) &r.fields.ip_remote)[1],
X	    ((unsigned char *) &r.fields.ip_remote)[2],
X	    ((unsigned char *) &r.fields.ip_remote)[3],
X	    (unsigned) ntohs(r.fields.port_remote));
X    
X    return readable;
}
X
#else
X
#ifndef NeXT31
int dummy = 0;   /* Just here to make some compilers shut up :-) */
#endif
X
#endif
SHAR_EOF
  $shar_touch -am 0811212996 'pidentd-2.7/src/crypto.c' &&
  chmod 0644 'pidentd-2.7/src/crypto.c' ||
  $echo 'restore of' 'pidentd-2.7/src/crypto.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/crypto.c:' 'MD5 check failed'
9c200c9560b564b49094a3b9bd4755b9  pidentd-2.7/src/crypto.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/crypto.c'`"
    test 5598 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/crypto.c:' 'original size' '5598,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/crypto.h ==============
if test -f 'pidentd-2.7/src/crypto.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/crypto.h' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/crypto.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/crypto.h' &&
/* Crypto extension to pidentd.
X   This file is in the public domain. -- Planar 1994.02.22
X
X   Description of the crypto routines.
*/
X
extern void init_encryption ();
extern char *make_packet ();
extern void init_decryption ();
extern char *decrypt_packet ();
SHAR_EOF
  $shar_touch -am 0223221794 'pidentd-2.7/src/crypto.h' &&
  chmod 0644 'pidentd-2.7/src/crypto.h' ||
  $echo 'restore of' 'pidentd-2.7/src/crypto.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/crypto.h:' 'MD5 check failed'
53095ade43dc44c261109819928193c1  pidentd-2.7/src/crypto.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/crypto.h'`"
    test 260 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/crypto.h:' 'original size' '260,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/error.h ==============
if test -f 'pidentd-2.7/src/error.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/error.h' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/error.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/error.h' &&
/*
** error.h                                               Error handling macros
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 19 Aug 1992
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#ifndef __ERROR_H__
#define __ERROR_H__
X
#include <syslog.h>
X
#define ERROR(fmt) \
X    ((syslog_flag ? (syslog(LOG_ERR, fmt),0) : 0), \
X     (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
X			    lport, fport), \
X		    fprintf(stderr, fmt), perror(": "), 0) : \
X      (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
X     fflush(stdout), fflush(stderr), exit(1), 0)
X
X
#define ERROR1(fmt,v1) \
X    ((syslog_flag ? (syslog(LOG_ERR, fmt, v1),0) : 0), \
X     (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
X			    lport, fport), \
X		    fprintf(stderr, fmt, v1), perror(": "), 0) : \
X      (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
X     fflush(stdout), fflush(stderr), exit(1), 0)
X
#define ERROR2(fmt,v1,v2) \
X    ((syslog_flag ? (syslog(LOG_ERR, fmt, v1, v2),0) : 0), \
X     (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \
X			    lport, fport), \
X		    fprintf(stderr, fmt, v1, v2), perror(": "), 0) : \
X      (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \
X     fflush(stdout), fflush(stderr), exit(1), 0)
X
#endif
SHAR_EOF
  $shar_touch -am 1020144692 'pidentd-2.7/src/error.h' &&
  chmod 0644 'pidentd-2.7/src/error.h' ||
  $echo 'restore of' 'pidentd-2.7/src/error.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/error.h:' 'MD5 check failed'
0061f9794335c5301ab7c0e3f0747e88  pidentd-2.7/src/error.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/error.h'`"
    test 1416 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/error.h:' 'original size' '1416,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/idecrypt.c ==============
if test -f 'pidentd-2.7/src/idecrypt.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/idecrypt.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/idecrypt.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/idecrypt.c' &&
/*
** idecrypt.c                                     Crypto extension to pidentd.
**
** This file is in the public domain. -- Planar 1994.02.22
**
** Decryption utility.
*/
X
#ifdef INCLUDE_CRYPT
X
#include <stdio.h>
#include "paths.h"
#include "crypto.h"
X
char is_base_64 [] =
{
X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
X    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
X    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
};
X
X
void decrypt_file (f)
X    FILE *f;
{
X    int c;
X    int i;
X    char buf[32];
X    char *cleartext;
X
X    while (1)
X    {
X	c = getc(f);
X	
X      Same:
X	if (c == EOF)
X	    return;
X	
X	if (c != '[')
X	{
X	    putchar(c);
X	    continue;
X	}
X	
X	for (i = 0; i < 32; i++)
X	{
X	    c = getc(f);
X	    if (c == EOF)
X		break;
X	    if (!is_base_64[c])
X		break;
X	    buf [i] = c;
X	}
X	
X	if (i == 32)
X	    c = getc(f);
X	
X	if (i < 32 || c != ']')
X	{
X	    putchar('[');
X	    fwrite(buf, 1, i, stdout);
X	    goto Same;
X	}
X	
X	cleartext = decrypt_packet(buf);
X	if (cleartext == NULL)
X	{
X	    putchar('[');
X	    fwrite(buf, 1, 32, stdout);
X	    putchar(']');
X	}
X	else
X	{
X	    printf("%s", cleartext);
X	}
X    }
}
X
main (argc, argv)
X     int argc;
X     char **argv;
{
X    int i;
X    FILE *f;
X    FILE *key_file;
X    
X    key_file = fopen(PATH_DESKEY, "r");
X    if (key_file == NULL)
X    {
X	fprintf(stderr, "idecrypt: cannot open key file: ");
X	perror(PATH_DESKEY);
X	exit (3);
X    }
X    
X    init_decryption(key_file);
X    close(key_file);
X    
X    if (argc < 2)
X    {
X	decrypt_file(stdin);
X    }
X    else
X    {
X	for (i = 1; i < argc; i++)
X	{
X	    if (!strcmp(argv [i], "-"))
X	    {
X		decrypt_file(stdin);
X		continue;
X	    }
X	    
X	    f = fopen(argv [i], "r");
X	    if (f == NULL)
X	    {
X		perror(argv [i]);
X		continue;
X	    }
X	    
X	    decrypt_file(f);
X	    fclose(f);
X	}
X    }
X    
X    exit(0);
}
X
#else /* no INCLUDE_CRYPT */
X
#include <stdio.h>
X
int main ()
{
X    fprintf(stderr, "idecrypt: compiled without encryption\n");
X    exit(2);
}
X
#endif
SHAR_EOF
  $shar_touch -am 1103091994 'pidentd-2.7/src/idecrypt.c' &&
  chmod 0644 'pidentd-2.7/src/idecrypt.c' ||
  $echo 'restore of' 'pidentd-2.7/src/idecrypt.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/idecrypt.c:' 'MD5 check failed'
472bbd6e8e746c2f6ee9364bd82ccd12  pidentd-2.7/src/idecrypt.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/idecrypt.c'`"
    test 2220 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/idecrypt.c:' 'original size' '2220,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/identd.c ==============
if test -f 'pidentd-2.7/src/identd.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/identd.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/identd.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/identd.c' &&
/*
** identd.c                       A TCP/IP link identification protocol server
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 7 Oct 1993
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#if defined(IRIX) || defined(SVR4) || defined(NeXT) || (defined(sco) && sco >= 42) || defined(_AIX4) || defined(__FreeBSD__)
#  define SIGRETURN_TYPE void
#  define SIGRETURN_TYPE_IS_VOID
#else
#  define SIGRETURN_TYPE int
#endif
X
#ifdef SVR4
#  define STRNET
#endif
X
#ifdef NeXT31
#  include <libc.h>
#endif
X
#ifdef sco
#  define USE_SIGALARM
#endif
X
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <fcntl.h>
X
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifndef _AUX_SOURCE
#  include <sys/file.h>
#endif
#include <sys/time.h>
#include <sys/wait.h>
X
#include <pwd.h>
#include <grp.h>
X
#include <netinet/in.h>
X
#ifndef HPUX7
#  include <arpa/inet.h>
#endif
X
#ifdef _AIX32
# include <sys/select.h>
#endif
X
#if defined(MIPS) || defined(BSD43)
extern int errno;
#endif
X
#if defined(SOLARIS) || defined(__FreeBSD__)
#  include <unistd.h>
#  include <stdlib.h>
#  include <string.h>
#endif
X
#include "identd.h"
#include "error.h"
#include "paths.h"
#include "crypto.h"
X
/* Antique unixes do not have these things defined... */
#ifndef FD_SETSIZE
#  define FD_SETSIZE 256
#endif
X
#ifndef FD_SET
#  ifndef NFDBITS
#    define NFDBITS   	(sizeof(int) * NBBY)  /* bits per mask */
#  endif
#  define FD_SET(n, p)  ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#endif
X
#ifndef FD_ZERO
#  define FD_ZERO(p)        bzero((char *)(p), sizeof(*(p)))
#endif
X
X
extern void *calloc();
extern void *malloc();
X
X
char *path_unix = NULL;
char *path_kmem = NULL;
X
int verbose_flag = 0;
int debug_flag   = 0;
int syslog_flag  = 0;
int multi_flag   = 0;
int other_flag   = 0;
int unknown_flag = 0;
int noident_flag = 0;
int crypto_flag  = 0;
X
int lport = 0;
int fport = 0;
X
char *charset_name = NULL;
char *indirect_host = NULL;
char *indirect_password = NULL;
X
#ifdef ALLOW_FORMAT
X    int format_flag = 0;
X    char *format = "%u";
#endif
X
static int child_pid;
X
#ifdef LOG_DAEMON
static int syslog_facility = LOG_DAEMON;
#endif
X
/*
** The structure passing convention for GCC is incompatible with
** Suns own C compiler, so we define our own inet_ntoa() function.
** (This should only affect GCC version 1 I think, a well, this works
** for version 2 also so why bother.. :-)
*/
#if defined(__GNUC__) && defined(__sparc__) && !defined(NeXT)
X
#ifdef inet_ntoa
#undef inet_ntoa
#endif
X
char *inet_ntoa(ad)
X    struct in_addr ad;
{
X    unsigned long int s_ad;
X    int a, b, c, d;
X    static char addr[20];
X    
X    s_ad = ad.s_addr;
X    d = s_ad % 256;
X    s_ad /= 256;
X    c = s_ad % 256;
X    s_ad /= 256;
X    b = s_ad % 256;
X    a = s_ad / 256;
X    sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
X    
X    return addr;
}
#endif
X
static int comparemem(p1, p2, len)
X    unsigned char *p1;
X    unsigned char *p2;
X    int len;
{
X    int c;
X
X    while (len-- > 0)
X	if ((c = (int) *p1++ - (int) *p2++) != 0)
X	    return c;
X
X    return 0;
}
X
/*
** Return the name of the connecting host, or the IP number as a string.
*/
char *gethost(addr)
X    struct in_addr *addr;
{
X    int i;
X    struct hostent *hp;
X
X  
X    hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET);
X    if (hp)
X    {
X	/* Found a IP -> Name match, now try the reverse for security reasons */
X	hp = gethostbyname(hp->h_name);
X	if (hp)
#ifdef h_addr
X	    for (i = 0; hp->h_addr_list[i]; i++)
X		if (comparemem(hp->h_addr_list[i],
X			       (unsigned char *) addr,
X			       sizeof(struct in_addr)) == 0)
X		    return (char *) hp->h_name;
#else
X	if (comparemem(hp->h_addr, addr, sizeof(struct in_addr)) == 0)
X	    return hp->h_name;
#endif
X  }
X
X  return inet_ntoa(*addr);
}
X
#ifdef USE_SIGALARM
/*
** Exit cleanly after our time's up.
*/
static SIGRETURN_TYPE
alarm_handler(int s)
{
X    if (syslog_flag)
X	syslog(LOG_DEBUG, "SIGALRM triggered, exiting");
X    
X    exit(0);
}
#endif
X
X
#if !defined(hpux) && !defined(__hpux) && !defined(SVR4) && \
X    !defined(_CRAY) && !defined(sco) && !defined(LINUX)
/*
** This is used to clean up zombie child processes
** if the -w or -b options are used.
*/
static SIGRETURN_TYPE
child_handler()
{
#if defined(NeXT) || (defined(__sgi) && defined(__SVR3))
X    union wait status;
#else
X    int status;
#endif
X
X    while (wait3(&status, WNOHANG, NULL) > 0)
X	;
X  
#ifndef SIGRETURN_TYPE_IS_VOID
X    return 0;
#endif
}
#endif
X
X
char *clearmem(bp, len)
X    char *bp;
X    int len;
{
X    char *cp;
X
X    cp = bp;
X    while (len-- > 0)
X	*cp++ = 0;
X    
X    return bp;
}
X
X
/*
** Main entry point into this daemon
*/
int main(argc,argv)
X    int argc;
X    char *argv[];
{
X    int i, len;
X    struct sockaddr_in sin;
X    struct in_addr laddr, faddr;
#ifndef USE_SIGALARM
X    struct timeval tv;
#endif
X    int one = 1;
X
X    int background_flag = 0;
X    int timeout = 0;
X    char *portno = "113";
X    char *bind_address = NULL;
X    int set_uid = 0;
X    int set_gid = 0;
X    int inhibit_default_config = 0;
X    int opt_count = 0;		/* Count of option flags */
X  
#ifdef __convex__
X    argc--;    /* get rid of extra argument passed by inetd */
#endif
X
X
X    if (isatty(0))
X	background_flag = 1;
X    
X    /*
X    ** Prescan the arguments for "-f<config-file>" switches
X    */
X    inhibit_default_config = 0;
X    for (i = 1; i < argc && argv[i][0] == '-'; i++)
X	if (argv[i][1] == 'f')
X	    inhibit_default_config = 1;
X    
X    /*
X    ** Parse the default config file - if it exists
X    */
X    if (!inhibit_default_config)
X	parse_config(NULL, 1);
X  
X    /*
X    ** Parse the command line arguments
X    */
X    for (i = 1; i < argc && argv[i][0] == '-'; i++) {
X	opt_count++;
X	switch (argv[i][1])
X	{
X	  case 'b':    /* Start as standalone daemon */
X	    background_flag = 1;
X	    break;
X	    
X	  case 'w':    /* Start from Inetd, wait mode */
X	    background_flag = 2;
X	    break;
X	    
X	  case 'i':    /* Start from Inetd, nowait mode */
X	    background_flag = 0;
X	    break;
X	    
X	  case 't':
X	    timeout = atoi(argv[i]+2);
X	    break;
X	    
X	  case 'p':
X	    portno = argv[i]+2;
X	    break;
X	    
X	  case 'a':
X	    bind_address = argv[i]+2;
X	    break;
X	    
X	  case 'u':
X	    if (isdigit(argv[i][2]))
X		set_uid = atoi(argv[i]+2);
X	    else
X	    {
X		struct passwd *pwd;
X		
X		pwd = getpwnam(argv[i]+2);
X		if (!pwd)
X		    ERROR1("no such user (%s) for -u option", argv[i]+2);
X		else
X		{
X		    set_uid = pwd->pw_uid;
X		    set_gid = pwd->pw_gid;
X		}
X	    }
X	    break;
X	    
X	  case 'g':
X	    if (isdigit(argv[i][2]))
X		set_gid = atoi(argv[i]+2);
X	    else
X	    {
X		struct group *grp;
X		
X		grp = getgrnam(argv[i]+2);
X		if (!grp)
X		    ERROR1("no such group (%s) for -g option", argv[i]+2);
X		else
X		    set_gid = grp->gr_gid;
X	    }
X	    break;
X	    
X	  case 'c':
X	    charset_name = argv[i]+2;
X	    break;
X	    
X	  case 'r':
X	    indirect_host = argv[i]+2;
X	    break;
X	    
X	  case 'l':    /* Use the Syslog daemon for logging */
X	    syslog_flag++;
X	    break;
X	    
X	  case 'o':
X	    other_flag = 1;
X	    break;
X	    
X	  case 'e':
X	    unknown_flag = 1;
X	    break;
X	    
X	  case 'V':    /* Give version of this daemon */
X	    printf("[in.identd, version %s]\r\n", version);
X	    exit(0);
X	    break;
X	    
X	  case 'v':    /* Be verbose */
X	    verbose_flag++;
X	    break;
X	    
X	  case 'd':    /* Enable debugging */
X	    debug_flag++;
X	    break;
X	    
X	  case 'm':    /* Enable multiline queries */
X	    multi_flag++;
X	    break;
X	    
X	  case 'N':    /* Enable users ".noident" files */
X	    noident_flag++;
X	    break;
X	    
#ifdef INCLUDE_CRYPT
X          case 'C':    /* Enable encryption. */
X	    {
X		FILE *keyfile;
X		
X		if (argv[i][2])
X		    keyfile = fopen(argv[i]+2, "r");
X		else
X		    keyfile = fopen(PATH_DESKEY, "r");
X		
X		if (keyfile == NULL)
X		{
X		    ERROR("cannot open key file for option -C");
X		}
X		else
X		{
X		    char buf[1024];
X		    
X		    if (fgets(buf, 1024, keyfile) == NULL)
X		    {
X			ERROR("cannot read key file for option -C");
X		    }
X		    else
X		    {
X			init_encryption(buf);
X			crypto_flag++;
X		    }
X		    fclose(keyfile);
X		}
X	    }
X            break;
#endif
X
#ifdef ALLOW_FORMAT
X	  case 'n': /* Compatibility flag - just send the user number */
X	    format_flag = 1;
X	    format = "%U";
X	    break;
X	    
X          case 'F':    /* Output format */
X	    format_flag = 1;
X	    format = argv[i]+2;
X	    break;
#endif
X
X	  default:
X	    ERROR1("Bad option %s", argv[i]);
X	    break;
X	}
X    }
X
#if defined(_AUX_SOURCE) || defined (SUNOS35)
X    /* A/UX 2.0* & SunOS 3.5 calls us with an argument XXXXXXXX.YYYY
X    ** where XXXXXXXXX is the hexadecimal version of the callers
X    ** IP number, and YYYY is the port/socket or something.
X    ** It seems to be impossible to pass arguments to a daemon started
X    ** by inetd.
X    **
X    ** Just in case it is started from something else, then we only
X    ** skip the argument if no option flags have been seen.
X    */
X    if (opt_count == 0)
X	argc--;
#endif
X
X    /*
X    ** Path to kernel namelist file specified on command line
X    */
X    if (i < argc)
X	path_unix = argv[i++];
X
X    /*
X    ** Path to kernel memory device specified on command line
X    */
X    if (i < argc)
X	path_kmem = argv[i++];
X
X
X    if (i < argc)
X	ERROR1("Too many arguments: ignored from %s", argv[i]);
X
X
X    /*
X    ** We used to call k_open here. But then the file descriptor
X    ** kd->fd open on /dev/kmem is shared by all child processes.
X    ** From the fork(2) man page:
X    **      o  The child process has its own copy of the parent's descriptors.  These
X    **         descriptors reference the same underlying objects.  For instance, file
X    **         pointers in file objects are shared between the child and the parent
X    **         so that an lseek(2) on a descriptor in the child process can affect a
X    **         subsequent read(2) or write(2) by the parent.
X    ** Thus with concurrent (simultaneous) identd client processes,
X    ** they step on each other's toes when they use kvm_read.
X    ** 
X    ** Calling k_open here was a mistake for another reason too: we
X    ** did not yet honor -u and -g options. Presumably we are
X    ** running as root (unless the in.identd file is setuid), and
X    ** then we can open kmem regardless of -u and -g values.
X    ** 
X    ** 
X    ** Open the kernel memory device and read the nlist table
X    ** 
X    **     if (k_open() < 0)
X    ** 		ERROR("main: k_open");
X    */
X    
X    /*
X    ** Do the special handling needed for the "-b" flag
X    */
X    if (background_flag == 1)
X    {
X	struct sockaddr_in addr;
X	struct servent *sp;
X	int fd;
X	
X
X	if (!debug_flag)
X	{
X	    if (fork())
X		exit(0);
X	    
X	    close(0);
X	    close(1);
X	    close(2);
X	    
X	    if (fork())
X		exit(0);
X	}
X	
X	fd = socket(AF_INET, SOCK_STREAM, 0);
X	if (fd == -1)
X	    ERROR("main: socket");
X	
X	if (fd != 0)
X	    dup2(fd, 0);
X	
X	clearmem((unsigned char *) &addr, sizeof(addr));
X	
X	addr.sin_family = AF_INET;
X	if (bind_address == NULL)
X	    addr.sin_addr.s_addr = htonl(INADDR_ANY);
X	else
X	{
X	    if (isdigit(bind_address[0]))
X		addr.sin_addr.s_addr = inet_addr(bind_address);
X	    else
X	    {
X		struct hostent *hp;
X		
X		hp = gethostbyname(bind_address);
X		if (!hp)
X		    ERROR1("no such address (%s) for -a switch", bind_address);
X		
X		/* This is ugly, should use memcpy() or bcopy() but... */
X		addr.sin_addr.s_addr = * (unsigned long *) (hp->h_addr);
X	    }
X	}
X	
X	if (isdigit(portno[0]))
X	    addr.sin_port = htons(atoi(portno));
X	else
X	{
X	    sp = getservbyname(portno, "tcp");
X	    if (sp == NULL)
X		ERROR1("main: getservbyname: %s", portno);
X	    addr.sin_port = sp->s_port;
X	}
X
#ifdef SO_REUSEADDR
X	setsockopt(0, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one));
#endif
X
X	if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
X	    ERROR("main: bind");
X	
X	if (listen(0, 3) < 0)
X	    ERROR("main: listen");
X    }
X    
X    if (set_gid)
X    {
X	if (setgid(set_gid) == -1)
X	    ERROR("main: setgid");
X	/* Call me paranoid... PSz */
X	if (getgid() != set_gid)
X	    ERROR2("main: setgid failed: wanted %d, got GID %d", set_gid, getgid());
X	if (getegid() != set_gid)
X	    ERROR2("main: setgid failed: wanted %d, got EGID %d", set_gid, getegid());
X    }
X    
X    if (set_uid)
X    {
X	if (setuid(set_uid) == -1)
X	    ERROR("main: setuid");
X	/* Call me paranoid... PSz */
X	if (getuid() != set_uid)
X	    ERROR2("main: setuid failed: wanted %d, got UID %d", set_uid, getuid());
X	if (geteuid() != set_uid)
X	    ERROR2("main: setuid failed: wanted %d, got EUID %d", set_uid, geteuid());
X    }
X    
X    /*
X    ** Do some special handling if the "-b" or "-w" flags are used
X    */
X    if (background_flag)
X    {
X	int nfds, fd;
X	fd_set read_set;
X	struct sockaddr sad;
X	int sadlen;
X	
X	
X	/*
X	** Set up the SIGCHLD signal child termination handler so
X	** that we can avoid zombie processes hanging around and
X	** handle childs terminating before being able to complete the
X	** handshake.
X	*/
#if (defined(SVR4) || defined(hpux) || defined(__hpux) || defined(IRIX) || \
X     defined(_CRAY) || defined(_AUX_SOURCE)) || defined(sco) || defined(LINUX)
X	signal(SIGCHLD, SIG_IGN);
#else
X	signal(SIGCHLD, (SIGRETURN_TYPE (*)()) child_handler);
#endif
X    
X	/*
X	** Loop and dispatch client handling processes
X	*/
X	do
X	{
#ifdef USE_SIGALARM
X	    /*
X	    ** Terminate if we've been idle for 'timeout' seconds
X	    */
X	    if (background_flag == 2 && timeout)
X	    {
X		signal(SIGALRM, alarm_handler);
X		alarm(timeout);
X	    }
#endif
X      
X	    /*
X	    ** Wait for a connection request to occur.
X	    ** Ignore EINTR (Interrupted System Call).
X	    */
X	    do
X	    {
X		FD_ZERO(&read_set);
X		FD_SET(0, &read_set);
X		
#ifndef USE_SIGALARM
X		if (timeout)
X		{
X		    tv.tv_sec = timeout;
X		    tv.tv_usec = 0;
#ifdef __hpux
X		    nfds = select(FD_SETSIZE,
X				  (int *) &read_set, NULL, NULL, &tv);
#else
X		    nfds = select(FD_SETSIZE, &read_set, NULL, NULL, &tv);
#endif
X		}
X		else
#endif
X
#ifdef __hpux
X		nfds = select(FD_SETSIZE, (int *) &read_set, NULL, NULL, NULL);
#else
X		nfds = select(FD_SETSIZE, &read_set, NULL, NULL, NULL);
#endif
X	    } while (nfds < 0  && errno == EINTR);
X	    
X	    /*
X	    ** An error occured in select? Just die
X	    */
X	    if (nfds < 0)
X		ERROR("main: select");
X	    
X	    /*
X	    ** Timeout limit reached. Exit nicely
X	    */
X	    if (nfds == 0)
X		exit(0);
X      
#ifdef USE_SIGALARM
X	    /*
X	    ** Disable the alarm timeout
X	    */
X	    alarm(0);
#endif
X      
X	    /*
X	    ** Accept the new client
X	    */
X	    sadlen = sizeof(sad);
X	    errno = 0;
X	    fd = accept(0, &sad, &sadlen);
X	    if (fd == -1)
X		ERROR1("main: accept. errno = %d", errno);
X      
X	    /*
X	    ** And fork, then close the fd if we are the parent.
X	    */
X	    child_pid = fork();
X	} while (child_pid && (close(fd), 1));
X
X	/*
X	** We are now in child, the parent has returned to "do" above.
X	*/
X	if (dup2(fd, 0) == -1)
X	    ERROR("main: dup2: failed fd 0");
X	
X	if (dup2(fd, 1) == -1)
X	    ERROR("main: dup2: failed fd 1");
X	
X	if (dup2(fd, 2) == -1)
X	    ERROR("main: dup2: failed fd 2");
X    }
X    
X    /*
X    ** Get foreign internet address
X    */
X    len = sizeof(sin);
X    if (getpeername(0, (struct sockaddr *) &sin, &len) == -1)
X    {
X	/*
X	** A user has tried to start us from the command line or
X	** the network link died, in which case this message won't
X	** reach to other end anyway, so lets give the poor user some
X	** errors.
X	*/
X	perror("in.identd: getpeername()");
X	exit(1);
X    }
X    
X    faddr = sin.sin_addr;
X    
X    
X    /*
X    ** Open the connection to the Syslog daemon if requested
X    */
X    if (syslog_flag)
X    {
#ifdef LOG_DAEMON
X	openlog("identd", LOG_PID, syslog_facility);
#else
X	openlog("identd", LOG_PID);
#endif
X
#ifndef STRONG_LOG
X	syslog(LOG_INFO, "Connection from %s", gethost(&faddr));
#endif
X    }
X  
X
X    /*
X    ** Get local internet address
X    */
X    len = sizeof(sin);
#ifdef ATTSVR4
X    if (t_getsockname(0, (struct sockaddr *) &sin, &len) == -1)
#else
X    if (getsockname(0, (struct sockaddr *) &sin, &len) == -1)
#endif
X    {
X	/*
X	** We can just die here, because if this fails then the
X	** network has died and we haven't got anyone to return
X	** errors to.
X	*/
X	exit(1);
X    }
X    laddr = sin.sin_addr;
X    
X
X    /*
X    ** Get the local/foreign port pair from the luser
X    */
X    parse(stdin, &laddr, &faddr);
X
X    exit(0);
}
SHAR_EOF
  $shar_touch -am 0527153496 'pidentd-2.7/src/identd.c' &&
  chmod 0644 'pidentd-2.7/src/identd.c' ||
  $echo 'restore of' 'pidentd-2.7/src/identd.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/identd.c:' 'MD5 check failed'
9b8790698ae70162721b4dc327050059  pidentd-2.7/src/identd.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/identd.c'`"
    test 16394 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/identd.c:' 'original size' '16394,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/parse.c ==============
if test -f 'pidentd-2.7/src/parse.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/parse.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/parse.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/parse.c' &&
/*
** parse.c                         This file contains the protocol parser
**
** This program is in the public domain and may be used freely by anyone
** who wants to.
**
** Last update: 23 Feb 1994
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#ifdef NeXT31
#  include <libc.h>
#endif
X
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <pwd.h>
#ifdef ALLOW_FORMAT
#  include <grp.h>
#endif
X
#include <sys/types.h>
#include <netinet/in.h>
X
#ifndef HPUX7
#  include <arpa/inet.h>
#endif
X
#ifdef HAVE_KVM
#  include <kvm.h>
#else
#  include "kernel/kvm.h"
#endif
X
#include <sys/types.h>
#include <sys/stat.h>
X
#if defined(MIPS) || defined(BSD43)
extern int errno;
#endif
X
#ifdef SOLARIS
#  include <string.h>
#  include <stdlib.h>
#endif
X
#include "identd.h"
#include "error.h"
#include "crypto.h"
X
extern void *malloc();
X
/*
** This function will eat whitespace characters until
** either a non-whitespace character is read, or EOF
** occurs. This function is only used if the "-m" option
** is enabled.
*/
static int eat_whitespace()
{
X  int c;
X
X
X  while ((c = getchar()) != EOF &&
X	 !(c == '\r' || c == '\n'))
X    ;
X
X  if (c != EOF)
X    while ((c = getchar()) != EOF &&
X	   (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
X      ;
X
X  if (c != EOF)
X    ungetc(c, stdin);
X
X  return (c != EOF);
}
X
X
#ifdef INCLUDE_EXTENSIONS
/*
** Validate an indirect request
*/
static int valid_fhost(faddr, password)
X  struct in_addr *faddr;
X  char *password;
{
X  if (indirect_host == NULL)
X    return 0;
X
X  if (strcmp(indirect_host, "*") != 0)
X  {
X    if (isdigit(indirect_host[0]))
X    {
X      if (strcmp(inet_ntoa(*faddr), indirect_host))
X      {
X	syslog(LOG_NOTICE, "valid_fhost: Access Denied for: %s",
X	       gethost(faddr));
X	return 0;
X      }
X    }
X    else
X    {
X      if (strcmp(gethost(faddr), indirect_host))
X      {
X	syslog(LOG_NOTICE, "valid_fhost: Access Denied for: %s",
X	       gethost(faddr));
X	return 0;
X      }
X    }
X  }
X
X  if (indirect_password == NULL)
X    return 1;
X
X  if (strcmp(password, indirect_password))
X  {
X    syslog(LOG_NOTICE, "valid_fhost: Invalid password from: %s",
X	   gethost(faddr));
X    return 0;
X  }
X
X  return 1;
}
#endif
X
/*
** A small routine to check for the existance of the ".noident"
** file in a users home directory.
*/
static int check_noident(homedir)
X  char *homedir;
{
X  char *tmp_path;
X  struct stat sbuf;
X  int rcode;
X
X
X  if (!homedir)
X    return 0;
X
X  tmp_path = (char *) malloc(strlen(homedir) + sizeof("/.noident") + 1);
X  if (!tmp_path)
X    return 0;
X
X  strcpy(tmp_path, homedir);
X  strcat(tmp_path, "/.noident");
X
X  rcode = stat(tmp_path, &sbuf);
X  free(tmp_path);
X
X  return (rcode == 0);
}
X
X
int parse(fp, laddr, faddr)
X  FILE *fp;
X  struct in_addr *laddr, *faddr;
{
X  int uid, try, rcode;
X  struct passwd *pwp;
#ifdef ALLOW_FORMAT
X  int pid;
X  char *cmd, *cmd_and_args;
X  struct group *grp;
X  char grname[128];
#endif
X  char lhostaddr[16];
X  char fhostaddr[16];
X  char password[33];
#if defined(INCLUDE_EXTENSIONS) || defined(STRONG_LOG)
X  char arg[33];
#endif
#ifdef INCLUDE_EXTENSIONS
X  extern int proxy();
X  int c;
#endif
X  struct in_addr laddr2;
X  struct in_addr faddr2;
X  int k_opened;
X
X  k_opened = 0;
X
X
X  if (debug_flag && syslog_flag)
X    syslog(LOG_DEBUG, "In function parse()");
X
X
X  /*
X  ** Get the local/foreign port pair from the luser
X  */
X  do
X  {
X    if (debug_flag && syslog_flag)
X      syslog(LOG_DEBUG, "  Before fscanf()");
X
X    faddr2 = *faddr;
X    laddr2 = *laddr;
X    lport = fport = 0;
X    lhostaddr[0] = fhostaddr[0] = password[0] = '\0';
X
X
X    /* Read query from client */
X    rcode = fscanf(fp, " %d , %d", &lport, &fport);
X
#ifdef INCLUDE_EXTENSIONS
X    /*
X    ** Do additional parsing in case of extended request
X    */
X    if (rcode == 0)
X    {
X      rcode = fscanf(fp, "%32[^ \t\n\r:]", arg);
X
X      /* Skip leading space up to EOF, EOL or non-space char */
X      while ((c = getc(fp)) == ' ' || c == '\t')
X	;
X
X      if (rcode <= 0)
X      {
#ifdef STRONG_LOG
X	if (syslog_flag)
X	      syslog(LOG_NOTICE, "from: %s (%s) INVALID REQUEST",
X		     inet_ntoa(*faddr), gethost(faddr));
#endif
X	printf("%d , %d : ERROR : %s\r\n",
X	       lport, fport,
X	       unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
X	continue;
X      }
X
X      /*
X      ** Non-standard extended request, returns with Pidentd
X      ** version information
X      */
X      if (strcmp(arg, "VERSION") == 0)
X      {
#ifdef STRONG_LOG
X	  if (syslog_flag)
X	      syslog(LOG_NOTICE, "from: %s (%s) VERSION REQUEST",
X		     inet_ntoa(*faddr), gethost(faddr));
#endif
#if defined(__TIME__) && defined(__DATE__)
X	printf("%d , %d : X-VERSION : %s (Compiled: %s %s)\r\n", lport, fport,
X	       version, __TIME__, __DATE__);
#else
X	printf("%d , %d : X-VERSION : %s\r\n", lport, fport,
X	       version);
#endif
X	continue;
X      }
X
X      /*
X      ** Non-standard extended proxy request
X      */
X      else if (strcmp(arg, "PROXY") == 0 && c == ':')
X      {
X	/* We have a colon char, check for port numbers */
X	rcode = fscanf(fp, " %d , %d : %15[0-9.] , %15[0-9.]",
X		       &lport, &fport, fhostaddr, lhostaddr);
X
X	if (!(rcode == 3 || rcode == 4))
X	{
#ifdef STRONG_LOG
X	    if (syslog_flag)
X		syslog(LOG_NOTICE, "from: %s (%s) INVALID PROXY REQUEST",
X		       inet_ntoa(*faddr), gethost(faddr));
#endif
X
X	  printf("%d , %d : ERROR : %s\r\n",
X		 lport, fport,
X		 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
X	  continue;
X	}
X
X	if (rcode == 4)
X	  laddr2.s_addr = inet_addr(lhostaddr);
X
X	faddr2.s_addr = inet_addr(fhostaddr);
X
#ifdef STRONG_LOG
X	if (syslog_flag)
X	{
X	    char a1[64], a2[64], a3[64];
X
X	    strcpy(a1, inet_ntoa(*faddr));
X	    strcpy(a2, inet_ntoa(faddr2));
X	    strcpy(a3, inet_ntoa(laddr2));
X
X	    syslog(LOG_NOTICE,
X		   "from: %s (%s) PROXY REQUEST for %d, %d between %s and %s",
X		   a1, gethost(faddr), lport, fport, a2, a3);
X	}
#endif
X
X	proxy(&laddr2, &faddr2, lport, fport, NULL);
X	continue;
X      }
X
X      /*
X      ** Non-standard extended remote indirect request
X      */
X      else if (strcmp(arg, "REMOTE") == 0 && c == ':')
X      {
X	/* We have a colon char, check for port numbers */
X	rcode = fscanf(fp, " %d , %d", &lport, &fport);
X
X	/* Skip leading space up to EOF, EOL or non-space char */
X	while ((c = getc(fp)) == ' ' || c == '\t')
X	  ;
X
X	if (rcode != 2 || c != ':')
X	{
#ifdef STRONG_LOG
X	    if (syslog_flag)
X		syslog(LOG_NOTICE, "from: %s (%s) INVALID REMOTE REQUEST",
X		       inet_ntoa(*faddr), gethost(faddr));
#endif
X
X	  printf("%d , %d : ERROR : %s\r\n",
X		 lport, fport,
X		 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
X	  continue;
X	}
X
X	/* We have a colon char, check for addr and password */
X	rcode = fscanf(fp, " %15[0-9.] , %32[^ \t\r\n]",
X		       fhostaddr, password);
X	if (rcode > 0)
X	  rcode += 2;
X	else
X	{
#ifdef STRONG_LOG
X	    if (syslog_flag)
X		syslog(LOG_NOTICE,
X		       "from: %s (%s) INVALID REMOTE REQUEST for %d, %d",
X		       inet_ntoa(*faddr), gethost(faddr), lport, fport);
#endif
X	    printf("%d , %d : ERROR : %s\r\n",
X		   lport, fport,
X		   unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
X	    continue;
X	}
X
X	/*
X	** Verify that the host originating the indirect request
X	** is allowed to do that
X	*/
X	if (!valid_fhost(faddr, password))
X	{
#ifdef STRONG_LOG
X	    if (syslog_flag)
X		syslog(LOG_NOTICE,
X       "from: %s (%s) REJECTED REMOTE REQUEST for %d, %d with password %s",
X		       inet_ntoa(*faddr), gethost(faddr), lport, fport,
X		       password);
#endif
X	    printf("%d , %d : ERROR : %s\r\n",
X		   lport, fport,
X		   unknown_flag ? "UNKNOWN-ERROR" : "X-ACCESS-DENIED");
X	    continue;
X	}
X
X	faddr2.s_addr = inet_addr(fhostaddr);
#ifdef STRONG_LOG
X	if (syslog_flag)
X	{
X	    char a1[64];
X
X	    strcpy(a1, inet_ntoa(*faddr));
X
X	    syslog(LOG_INFO,
X	   "from: %s (%s) REMOTE REQUEST for %d, %d from %s with password %s",
X		   a1, gethost(faddr), lport, fport,
X		   inet_ntoa(faddr2), password);
X	}
#endif
X    }
X
X      else
X      {
#ifdef STRONG_LOG
X	  if (syslog_flag)
X	      syslog(LOG_NOTICE, "from: %s (%s) UNKNOWN REQUEST: %s",
X		     inet_ntoa(*faddr), gethost(faddr), arg);
#endif
X
X	  printf("%d , %d : ERROR : %s\r\n",
X		 lport, fport,
X		 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
X	  continue;
X      }
X    }
#endif /* EXTENSIONS */
X
X    if (rcode < 2 || lport < 1 || lport > 65535 || fport < 1 || fport > 65535)
X    {
#ifdef STRONG_LOG
X	if (syslog_flag)
X	{
X	    if (rcode > 0)
X		/* we have scanned at least one correct port */
X		syslog(LOG_NOTICE,
X		       "from: %s (%s) for invalid-port(s): %d , %d",
X		       inet_ntoa(*faddr), gethost(faddr), lport, fport);
X	    else
X	    {
X		/* we have scanned nothing at all so try to get the rest */
X		if (fscanf(fp, "%32[^\n\r]", arg) <= 0)
X		    syslog(LOG_NOTICE, "from: %s (%s) EMPTY REQUEST",
X			   inet_ntoa(*faddr), gethost(faddr));
X		else
X		    syslog(LOG_NOTICE, "from: %s (%s) INVALID REQUEST: %s",
X			   inet_ntoa(*faddr), gethost(faddr), arg);
X	    }
X	}
#else
X	if (syslog_flag && rcode > 0)
X	    syslog(LOG_NOTICE, "scanf: invalid-port(s): %d , %d from %s",
X		   lport, fport, gethost(faddr));
#endif
X
X      printf("%d , %d : ERROR : %s\r\n",
X	     lport, fport,
X	     unknown_flag ? "UNKNOWN-ERROR" : "INVALID-PORT");
X      continue;
X    }
X
#ifdef STRONG_LOG
X      if (syslog_flag)
X      {
X	  syslog(LOG_INFO, "from: %s ( %s ) for: %d, %d",
X		 inet_ntoa(*faddr), gethost(faddr), lport, fport);
X      }
#endif
X
X    if (debug_flag && syslog_flag)
X      syslog(LOG_DEBUG, "  After fscanf(), before k_open()");
X
X
X    if (! k_opened)
X    {
X      /*
X      ** Open the kernel memory device and read the nlist table
X      ** 
X      ** Of course k_open should not call ERROR (which then exits)
X      ** but maybe use syslog(LOG_ERR) and return non-zero. But I am
X      ** too lazy to change them all ...
X      */
X      if (k_open() != 0)
X      {
X	if (syslog_flag) syslog(LOG_ERR, "k_open call failed");
X	printf("%d , %d : ERROR : %s\r\n",
X	     lport, fport,
X	     unknown_flag ? "UNKNOWN-ERROR" : "X-CANNOT-OPEN-KMEM");
X	continue;
X      }
X      k_opened = 1;
X    }
X
X
X    if (debug_flag && syslog_flag)
X      syslog(LOG_DEBUG, "  After k_open(), before k_getuid()");
X
X
X    /*
X    ** Get the specific TCP connection and return the uid - user number.
X    */
X
#ifdef ALLOW_FORMAT
X    /* Initialize values, for architectures that do not set it */
X    pid = 0;
X    cmd = "";
X    cmd_and_args = "";
#endif
X
#define MAX_RETRY 20
X    /*
X    ** Try to fetch the information MAX_RETRY times in case the
X    ** kernel changed beneath us and we missed or took a fault.
X    **
X    ** Why would we ever fail? Is not there a reliable way for the
X    ** kernel to identify its sockets? Cannot we use that interface?
X    **
X    ** Used to be 5 times, but often this is not enough on Alpha OSF.
X    */
/* #define SLEEP_BETWEEN_RETRIES 1 */
X    /*
X    ** If we failed in k_getuid, that is presumably because the OS was
X    ** busy creating or destroying processes. We may want to sleep for
X    ** a random time between retries, hoping for peace and quiet.
X    */
X
/* k_getuid returns 0 on success, any non-zero on failure. */
X
X    for (try = 0;
X	 (try < MAX_RETRY &&
X	   k_getuid(&faddr2, htons(fport), laddr, htons(lport), &uid
#ifdef ALLOW_FORMAT
X		    , &pid, &cmd, &cmd_and_args
#endif
X		    ) != 0);
X	 try++)
#ifdef SLEEP_BETWEEN_RETRIES
X      {
X	/* Seed the generator: lport should be unique (among other concurrent identd's) */
X	if (try < 1) srandom(lport);
X	/* This gives a max sleep of 0xffff = 65535 microsecs, about 32millisec average */
X	usleep(random()&0x00ffff);
X      }
#else
X      ;
#endif
X
X    if (try >= MAX_RETRY)
X    {
X      if (syslog_flag)
X	syslog(LOG_INFO, "Returned: %d , %d : NO-USER", lport, fport);
X
X      printf("%d , %d : ERROR : %s\r\n",
X	     lport, fport,
X	     unknown_flag ? "UNKNOWN-ERROR" : "NO-USER");
X      continue;
X    }
X
X    if (try > 0 && syslog_flag)
X      syslog(LOG_NOTICE, "k_getuid retries: %d", try);
X
X    if (debug_flag && syslog_flag)
X      syslog(LOG_DEBUG, "  After k_getuid(), before getpwuid()");
X
X    /*
X    ** Then we should try to get the username. If that fails we
X    ** return it as an OTHER identifier
X    */
X    pwp = getpwuid(uid);
X
X    if (!pwp || uid != pwp->pw_uid)
X    {
X      if (syslog_flag)
X	syslog(LOG_WARNING, "getpwuid() could not map uid (%d) to name",
X	       uid);
X
X      printf("%d , %d : USERID : OTHER%s%s : %d\r\n",
X	     lport, fport,
X	     charset_name ? " , " : "",
X	     charset_name ? charset_name : "",
X	     uid);
X      continue;
X    }
X
#ifdef ALLOW_FORMAT
X    grp = getgrgid(pwp->pw_gid);
X    if (!grp || pwp->pw_gid != grp->gr_gid)
X    {
X      if (syslog_flag)
X	syslog(LOG_WARNING, "getgrgid() could not map gid (%d) to name (for uid %d, name %s)",
X	       pwp->pw_gid, uid, pwp->pw_name);
X
X      printf("%d , %d : USERID : OTHER%s%s : %d\r\n",
X	     lport, fport,
X	     charset_name ? " , " : "",
X	     charset_name ? charset_name : "",
X	     uid);
X      continue;
X    }
X    sprintf (grname, "%.99s", grp->gr_name);
#endif
X
X    /*
X    ** Hey! We finally made it!!!
X    */
#ifdef ALLOW_FORMAT
X    if (syslog_flag)
X      syslog(LOG_DEBUG, "Successful lookup: %d , %d : %s.%s\n",
X	     lport, fport, pwp->pw_name, grname);
#else
X    if (syslog_flag)
X      syslog(LOG_DEBUG, "Successful lookup: %d , %d : %s\n",
X	     lport, fport, pwp->pw_name);
#endif
X
X    if (noident_flag && check_noident(pwp->pw_dir))
X    {
X      if (syslog_flag)
X	syslog(LOG_NOTICE, "User %s requested HIDDEN-USER for host %s: %d, %d",
X	       pwp->pw_name,
X	       gethost(faddr),
X	       lport, fport);
X
X      printf("%d , %d : ERROR : HIDDEN-USER\r\n",
X	   lport, fport);
X      continue;
X    }
X
#ifdef INCLUDE_CRYPT
X    if (crypto_flag)
X      printf("%d , %d : USERID : OTHER%s%s : [%s]\r\n",
X	     lport, fport,
X	     charset_name ? " , " : "",
X	     charset_name ? charset_name : "",
X	     make_packet (pwp->pw_uid, laddr, lport, faddr, fport));
X    else
#endif
#ifdef ALLOW_FORMAT
X    if (format_flag)
X    {
X      char* cp;
X      char** gmp;
X      long bp;
X      char buff[512];
X      for (cp = format, bp = 0; *cp != 0; cp++)
X      {
X	if (*cp == '%')
X	{
X	  cp++;
X	  if (*cp == 0) break;
X	  else if (*cp == 'u') sprintf (&buff[bp], "%.*s", 490-bp, pwp->pw_name);
X	  else if (*cp == 'U') sprintf (&buff[bp], "%d",           pwp->pw_uid);
X	  else if (*cp == 'g') sprintf (&buff[bp], "%.*s", 490-bp, grname);
X	  else if (*cp == 'G') sprintf (&buff[bp], "%d",           pwp->pw_gid);
X	  else if (*cp == 'c') sprintf (&buff[bp], "%.*s", 490-bp, cmd);
X	  else if (*cp == 'C') sprintf (&buff[bp], "%.*s", 490-bp, cmd_and_args);
X	  else if (*cp == 'l') {
X	    sprintf (&buff[bp], "%.*s", 490-bp, grname);
X	    bp += strlen(&buff[bp]); if (bp >= 490) break;
X	    setgrent();
X	    while (grp = getgrent()) {
X	      if (grp->gr_gid == pwp->pw_gid) continue;
X	      for (gmp = grp->gr_mem; *gmp && **gmp; gmp++) {
X		if (! strcmp(*gmp, pwp->pw_name)) {
X		  sprintf (&buff[bp], ",%.*s", 490-bp, grp->gr_name);
X		  bp += strlen(&buff[bp]);
X		  break;
X		}
X	      }
X	      if (bp >= 490) break;
X	    }
X	    endgrent();
X	  }
X	  else if (*cp == 'L') {
X	    sprintf (&buff[bp], "%d", pwp->pw_gid);
X	    bp += strlen(&buff[bp]); if (bp >= 490) break;
X	    setgrent();
X	    while (grp = getgrent()) {
X	      if (grp->gr_gid == pwp->pw_gid) continue;
X	      for (gmp = grp->gr_mem; *gmp && **gmp; gmp++) {
X		if (! strcmp(*gmp, pwp->pw_name)) {
X		  sprintf (&buff[bp], ",%d", grp->gr_gid);
X		  bp += strlen(&buff[bp]);
X		  break;
X		}
X	      }
X	      if (bp >= 490) break;
X	    }
X	    endgrent();
X	  }
X	  else if (*cp == 'p') sprintf (&buff[bp], "%d", pid);
X	  else { buff[bp] = *cp; buff[bp+1] = 0; }
X	  bp += strlen(&buff[bp]); if (bp >= 490) break;
X	}
X	else { buff[bp++] = *cp; if (bp >= 490) break; }
X      }
X      if (bp >= 490) { sprintf(&buff[490], "..."); bp = 493; }
X      buff[bp] = 0;
X      printf("%d , %d : USERID : %s%s%s :%s\r\n",
X	     lport, fport,
X	     other_flag ? "OTHER" : "UNIX",
X	     charset_name ? " , " : "",
X	     charset_name ? charset_name : "",
X	     buff);
X    }
X    else
#endif
X      printf("%d , %d : USERID : %s%s%s :%s\r\n",
X	     lport, fport,
X	     other_flag ? "OTHER" : "UNIX",
X	     charset_name ? " , " : "",
X	     charset_name ? charset_name : "",
X	     pwp->pw_name);
X
X  } while(fflush(stdout), fflush(stderr), multi_flag && eat_whitespace());
X
X  return 0;
}
SHAR_EOF
  $shar_touch -am 0811215696 'pidentd-2.7/src/parse.c' &&
  chmod 0644 'pidentd-2.7/src/parse.c' ||
  $echo 'restore of' 'pidentd-2.7/src/parse.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/parse.c:' 'MD5 check failed'
d747a642aa66f88d432f7548107018cd  pidentd-2.7/src/parse.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/parse.c'`"
    test 16271 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/parse.c:' 'original size' '16271,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/identd.h ==============
if test -f 'pidentd-2.7/src/identd.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/identd.h' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/identd.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/identd.h' &&
/*
** identd.h                 Common variables for the Pidentd daemon
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 6 Dec 1992
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#ifndef __IDENTD_H__
#define __IDENTD_H__
X
extern char version[];
X
extern char *path_unix;
extern char *path_kmem;
X
extern int verbose_flag;
extern int debug_flag;
extern int syslog_flag;
extern int multi_flag;
extern int other_flag;
extern int unknown_flag;
extern int noident_flag;
extern int crypto_flag;
X
extern char *charset_name;
extern char *indirect_host;
extern char *indirect_password;
X
#ifdef ALLOW_FORMAT
extern int format_flag;
extern char *format;
#endif
X
extern int lport;
extern int fport;
X
extern char *gethost();
X
extern int k_open();
extern int k_getuid();
extern int parse();
extern int parse_config();
X
#endif
SHAR_EOF
  $shar_touch -am 1127003895 'pidentd-2.7/src/identd.h' &&
  chmod 0644 'pidentd-2.7/src/identd.h' ||
  $echo 'restore of' 'pidentd-2.7/src/identd.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/identd.h:' 'MD5 check failed'
4a88f8d63ea1e6a5342fc4f05c0b394d  pidentd-2.7/src/identd.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/identd.h'`"
    test 910 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/identd.h:' 'original size' '910,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/itest.c ==============
if test -f 'pidentd-2.7/src/itest.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/itest.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/itest.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/itest.c' &&
/*
X * Simple but effective hack to test the kernel.o file.
X * It takes on stdin the output from "netstat -f inet -n | grep ESTAB"
X * in either Solaris 2.x (non-standard formats can easily be converted
X * to this)
X *	laddr.lport faddr.fport .....
X * or BSD 4.x (the defacto standard netstat output):
X *	tcp <num> <num>  laddr.lport faddr.fport
X * format.
X *
X * The output must be numeric, as non-numeric output is truncated when
X * hostnames get too long and ambiguous.  And we don't want netstat to
X * first convert numbers to names and then this program to convert
X * names back to numbers.
X *
X * Casper Dik (casper@fwi.uva.nl)
X */
#include <stdio.h>
#include <ctype.h>
#ifdef sequent
#include <strings.h>
#define strrchr rindex
#else
#include <string.h>
#include <stdlib.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pwd.h>
X
#include "identd.h"
#include "error.h"
X
X
#ifdef LOG_DAEMON
static int syslog_facility = LOG_DAEMON;
#endif
X
/*
X * To resolve external references that are usually resolved
X * from identd.c
X */
char *path_unix = NULL;
char *path_kmem = NULL;
int lport = 0;
int fport = 0;
X
int debug_flag = 1;
int syslog_flag = 1;
X
X
#ifdef sequent
char *strtok(str, dels)
X    char *str;
X    char *dels;
{
X  static char *bufp;
X  
X
X  if (str)
X    bufp = str;
X
X  if (!bufp || !*bufp)
X    return (char *) 0;;
X
X  while (*bufp && index(dels, *bufp) != (char *) 0)
X    ++bufp;
X
X  str = bufp;
X  
X  while (*bufp && index(dels, *bufp) == (char *) 0)
X    ++bufp;
X  
X  if (*bufp)
X    *bufp++ = '\0';
X
X  return str;
}
#endif
X
int
main()
{
X    char buf[500];
X
X    /*
X    ** Open the connection to the Syslog daemon if requested
X    */
X    if (syslog_flag)
X    {
#ifdef LOG_DAEMON
X	openlog("identd_test", LOG_PID, syslog_facility);
#else
X	openlog("identd_test", LOG_PID);
#endif
X    }
X
X
X    if (k_open() < 0) {
X	fprintf(stderr,"k_open failed\n");
X	exit(1);
X    }
X    while (fgets(buf,sizeof(buf),stdin)) {
X	char *loc, *rem, *tmp;
X	unsigned short lport, fport;
X	struct in_addr faddr, laddr;
X	int uid;
#ifdef ALLOW_FORMAT
X	int pid;
X	char *cmd, *cmd_and_args;
#endif
X	struct passwd *pwd;
X	char buf2[sizeof(buf)];
X
X	strcpy(buf2,buf);
X
X	loc = strtok(buf, " \t");
X	if (strcmp(loc,"tcp") == 0) {
X	    int i;
X	    for (i = 0; i < 3; i++)
X		loc = strtok(NULL, " \t");
X	}
X	rem = strtok(NULL, " \t");
X	if (loc == NULL || rem == NULL) {
X	    fprintf(stderr,"Malformed line: %s\n", buf2);
X	    continue;
X	}
X	/* parse remote, local address */
X	tmp = strrchr(loc,'.');
X	if (tmp == NULL) {
X	    fprintf(stderr,"Malformed line: %s\n", buf2);
X	    continue;
X	}
X	*tmp++ ='\0';
X	laddr.s_addr = inet_addr(loc);
X	lport = atoi(tmp);
X
X	tmp = strrchr(rem,'.');
X	if (tmp == NULL) {
X	    fprintf(stderr,"Malformed line: %s\n", buf2);
X	    continue;
X	}
X	*tmp++ ='\0';
X	fport = atoi(tmp);
X	faddr.s_addr = inet_addr(rem);
X
X	uid = -1;
#ifdef ALLOW_FORMAT
X	pid = 0;
X	cmd = "unknown";
X	cmd_and_args = "unknown";
#endif
X
X	if (k_getuid(&faddr, htons(fport), &laddr, htons(lport), &uid
#ifdef ALLOW_FORMAT
X		, &pid
X		, &cmd
X		, &cmd_and_args
#endif
X		) != 0) {
X	    fprintf(stderr,"*unknown*\t%s\t%d\t\t%s\t%d\n", loc, lport, rem, fport);
X	    continue;
X	}
X
X	pwd = getpwuid(uid);
X	if (pwd)
X	    printf("%-8.8s", pwd->pw_name);
X	else
X	    printf("%-8.8d", uid);
#ifdef ALLOW_FORMAT
X	printf (" \t%-13s\t%-4d\t%-13s\t%-4d\tPID=%d\tCMD=%s\tCMD+ARG=%s\n", loc, lport, rem, fport, pid, cmd, cmd_and_args);
#else
X	printf(" \t%s\t%d\t\t%s\t%d\n", loc, lport, rem, fport);
#endif
X    }
X
X    return 0;
}
SHAR_EOF
  $shar_touch -am 0514014196 'pidentd-2.7/src/itest.c' &&
  chmod 0644 'pidentd-2.7/src/itest.c' ||
  $echo 'restore of' 'pidentd-2.7/src/itest.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/itest.c:' 'MD5 check failed'
39e0f4b60eb8dbeec16e46a6b239f86e  pidentd-2.7/src/itest.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/itest.c'`"
    test 3541 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/itest.c:' 'original size' '3541,' 'current size' "$shar_count!"
  fi
fi
# ============= pidentd-2.7/src/kernel/386bsd.c ==============
if test ! -d 'pidentd-2.7/src/kernel'; then
  $echo 'x -' 'creating directory' 'pidentd-2.7/src/kernel'
  mkdir 'pidentd-2.7/src/kernel'
fi
if test -f 'pidentd-2.7/src/kernel/386bsd.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'pidentd-2.7/src/kernel/386bsd.c' '(file already exists)'
else
  $echo 'x -' extracting 'pidentd-2.7/src/kernel/386bsd.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'pidentd-2.7/src/kernel/386bsd.c' &&
/*
** kernel/386bsd.c		Low level kernel access functions for 386BSD
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 17 March 1993
**
** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
*/
X
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <nlist.h>
#include <pwd.h>
#include <signal.h>
#include <syslog.h>
X
#include "kvm.h"
X
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
X
#include <sys/socketvar.h>
X
#define KERNEL
X
#include <sys/file.h>
X
#undef KERNEL
#include <sys/kinfo.h>
X
#include <fcntl.h>
X
#include <sys/user.h>
X
#include <sys/wait.h>
X
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
X
#include <netinet/in_systm.h>
#include <netinet/ip.h>
X
#include <netinet/in_pcb.h>
X
#include <netinet/tcp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
X
#include <arpa/inet.h>
X
#include "identd.h"
#include "error.h"
X
X
extern void *calloc();
extern void *malloc();
X
X
struct nlist nl[] =
{
#define N_FILE 0
#define N_NFILE 1
#define N_TCB 2
X      
X  { "_filehead" },
X  { "_nfiles" },
X  { "_tcb" },
X  { "" }
};
X
X
static struct file *xfile;
static int nfile;
X
static struct inpcb tcb;
X
#ifdef	__bsdi__
static kvm_t *kd;
X
int k_open()
{
X  
X  /*
X  ** Open the kernel memory device
X  */
X  if ((kd = kvm_openfiles(path_unix, path_kmem, NULL, O_RDONLY)) == 0)
X    ERROR("main: kvm_open");
X  
X  /*
X  ** Extract offsets to the needed variables in the kernel
X  */
X  if (kvm_nlist(kd, nl) < 0)
X    ERROR("main: kvm_nlist");
X
X  return 0;
}
#else
int k_open()
{
X  int kd;
X  
X  /*
X  ** Open the kernel memory device
X  */
X  if ((kd = kvm_openfiles(path_unix, path_kmem, NULL)))
X    ERROR("main: kvm_open");
X  
X  /*
X  ** Extract offsets to the needed variables in the kernel
X  */
X  if (kvm_nlist(nl) < 0)
X    ERROR("main: kvm_nlist");
X
X  return 0;
}
#endif
X
/*
** Get a piece of kernel memory with error handling.
** Returns 1 if call succeeded, else 0 (zero).
*/
static int getbuf(addr, buf, len, what)
X  long addr;
X  char *buf;
X  int len;
X  char *what;
{
#ifdef	__bsdi__
X  if (kvm_read(kd, addr, buf, len) < 0)
#else
X  if (kvm_read(addr, buf, len) < 0)
#endif
X  {
X    if (syslog_flag)
X      syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
X	     addr, len, what);
X
X    return 0;
X  }
X  
X  return 1;
}
X
X
X
/*
** Traverse the inpcb list until a match is found.
** Returns NULL if no match.
*/
static struct socket *
X    getlist(pcbp, faddr, fport, laddr, lport)
X  struct inpcb *pcbp;
X  struct in_addr *faddr;
X  int fport;
X  struct in_addr *laddr;
X  int lport;
{
X  struct inpcb *head;
X
X  if (!pcbp)
X    return NULL;
X
X  
X  head = pcbp->inp_prev;
X  do 
X  {
X    if ( pcbp->inp_faddr.s_addr == faddr->s_addr &&
X	 pcbp->inp_laddr.s_addr == laddr->s_addr &&
X	 pcbp->inp_fport        == fport &&
X	 pcbp->inp_lport        == lport )
X      return pcbp->inp_socket;
X  } while (pcbp->inp_next != head &&
X	   getbuf((long) pcbp->inp_next,
X		  pcbp,
X		  sizeof(struct inpcb),
X		  "tcblist"));
X
X  return NULL;
}
X
X
X
/*
** Return the user number for the connection owner
*/
int k_getuid(faddr, fport, laddr, lport, uid)
X  struct in_addr *faddr;
X  int fport;
X  struct in_addr *laddr;
X  int lport;
X  int *uid;
{
X  long addr;
X  struct socket *sockp;
X  int i;
X  struct ucred ucb;
X  
X  /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
X  if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile"))
X    return -1;
X  
X  if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file"))
X    return -1;
X
X  {
X    int siz = (nfile+10)*sizeof(struct file);
X    xfile = (struct file *) calloc(nfile+10, sizeof(struct file));
X    if (!xfile)
X      ERROR2("k_getuid: calloc(%d,%d)", nfile+10, sizeof(struct file));
X
X    if (!getkerninfo(KINFO_FILE, xfile, &siz, 0))
X    {
X      ERROR("k_getuid: getkerninfo");
X      return -1;
X    }
X    xfile = (struct file *)((char *)xfile + sizeof(filehead));
X  }
X  
X  /* -------------------- TCP PCB LIST -------------------- */
X  if (!getbuf(nl[N_TCB].n_value, &tcb, sizeof(tcb), "tcb"))
X    return -1;
X  
X  tcb.inp_prev = (struct inpcb *) nl[N_TCB].n_value;
X  sockp = getlist(&tcb, faddr, fport, laddr, lport);
X  
X  if (!sockp)
X    return -1;
X
X  /*
X  ** Locate the file descriptor that has the socket in question
X  ** open so that we can get the 'ucred' information
X  */
X  for (i = 0; i < nfile; i++)
X  {
X    if (xfile[i].f_count == 0)
X      continue;
X    
X    if (xfile[i].f_type == DTYPE_SOCKET &&
X	(struct socket *) xfile[i].f_data == sockp)
X    {
X      if (!getbuf(xfile[i].f_cred, &ucb, sizeof(ucb), "ucb"))
X	return -1;
X
X      *uid = ucb.cr_uid;
X      return 0;
X    }
X  }
X
X  return -1;
}
X
SHAR_EOF
  $shar_touch -am 1119131693 'pidentd-2.7/src/kernel/386bsd.c' &&
  chmod 0644 'pidentd-2.7/src/kernel/386bsd.c' ||
  $echo 'restore of' 'pidentd-2.7/src/kernel/386bsd.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'pidentd-2.7/src/kernel/386bsd.c:' 'MD5 check failed'
b1f9922b38cc368eee444d683e3deaf5  pidentd-2.7/src/kernel/386bsd.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'pidentd-2.7/src/kernel/386bsd.c'`"
    test 4742 -eq "$shar_count" ||
    $echo 'pidentd-2.7/src/kernel/386bsd.c:' 'original size' '4742,' 'current size' "$shar_count!"
  fi
fi
: || $echo 'restore of' 'pidentd-2.7/src/kernel/4.3bsd.c' 'failed'
$echo 'End of part' '4,' 'continue with part' '5'
exit 0


