home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / sockspy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  6.6 KB  |  276 lines

  1. /*
  2.  USAGE
  3.    sockspy desthost destservice
  4.  
  5. You install this program in /etc/inetd.conf and /etc/services
  6.  
  7. For example I have used these entries:
  8.  
  9. /etc/services:
  10. spy        8001/tcp    spy port
  11.  
  12. /etc/inetd.conf:
  13. spy stream tcp nowait tridge /usr/local/smb/sockspy sockspy fjall netbios-ssn
  14.  
  15. This means any connection to port 8001 will be redirected to
  16. netbios-ssn on fjall. By playing with these parameters you can easily
  17. spy on most of the tcp protocols. All packets traversing the link will
  18. be captured.
  19.  
  20. NOTE: This program is totally unsupported. I haven't used it for 2
  21. years, and don't intend to fix the obvious bugs/limitations. I will,
  22. however, accept contributed patches - or even a total rewrite :-)
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <strings.h>
  27. #include <sys/types.h>
  28. #include <sys/dir.h>
  29. #include <sys/socket.h>
  30. #include <sys/ioctl.h>
  31. #include <netinet/in.h>
  32. #include <netdb.h>
  33.  
  34. #include <signal.h>
  35.  
  36. #include <errno.h>
  37. #include <sysexits.h>
  38.  
  39. int trans_num = 0;
  40.  
  41. #ifndef LOGIN
  42. #define LOGIN "/tmp/spy.in"
  43. #endif
  44.  
  45. #ifndef LOGOUT
  46. #define LOGOUT "/tmp/spy.out"
  47. #endif
  48.  
  49. #ifndef LOGCMD
  50. #define LOGCMD "/tmp/spy.cmd"
  51. #endif
  52.  
  53. FILE *cmd = NULL;
  54. FILE *login = NULL;
  55. FILE *logout = NULL;
  56.  
  57. #define      STREQL(a, b)        (strcmp(a, b) == 0)
  58. #define      NIL                 (0)
  59.  
  60. char      DestHost[256];    /* Remote system to connect to         */
  61. char      DestObj[256];     /* Remote object/service to connect to */
  62.  
  63. /* Signal handler for SIGPIPE (write on a disconnected socket) */
  64. abort()
  65. {
  66. fprintf(cmd,"writing to disconnected socket!\n");
  67. fflush(cmd);
  68.     exit(1);
  69. }
  70.  
  71.  
  72. main(argc, argv)
  73. int    argc;           /* # of command line arguments */
  74. char   *argv[];        /* the command line arguments  */
  75. {
  76.     int      client,       /* Socket connected to client  */
  77.              server;       /* Socket to use for server    */
  78.  
  79. trans_num = 0;
  80. login = fopen(LOGIN,"w");
  81. logout = fopen(LOGOUT,"w");
  82. cmd = fopen(LOGCMD,"w");
  83.  
  84. fprintf(cmd,"Started server\n");
  85. fflush(cmd);
  86.  
  87.     /* Check usage */
  88.     if(argc != 3)
  89.     {
  90.       return;
  91.     }
  92. else
  93.     {
  94.       strcpy(DestHost,argv[1]);
  95.       strcpy(DestObj,argv[2]);
  96.     }
  97.  
  98.     /* Time to attempt the connection */
  99.       server = inet_conn(DestHost, DestObj);
  100.  
  101.       if( server < 0 ) {
  102.           exit(EX_CANTCREAT);
  103.       }
  104.  
  105.     /* Just to make the code more readable */
  106.     client = 0;
  107.  
  108.     /* We will abort gracefully when the client or remote system 
  109.        goes away */
  110.     signal(SIGPIPE, abort);
  111.  
  112.     /* Now just go and move raw data between client and 
  113.        remote system */
  114.     dowork(client, server);
  115.     /* ... NEVER RETURNS ... */
  116. }
  117.  
  118. dowork(client, server)
  119. int    client, server;      
  120. {
  121.  
  122. /* select(2) masks for client and remote */
  123. int      ClientMask, ServerMask;
  124.  
  125. /* Combined ClientMask and ServerMask */
  126. int      ReadMask;
  127.  
  128.     /* Initialize select(2) masks */
  129.     ClientMask = 1<<client;
  130.     ServerMask = 1<<server;
  131.  
  132.     ReadMask = ClientMask | ServerMask;
  133.  
  134.     /* Now move raw data for the rest of our life between 
  135.        client and remote */
  136.     for( ; ; ) {
  137.       /* Local Variables */
  138.       int  SelectReadMask;/* select(2) mask modifiable by select(2) */
  139.       int  nready;        /* status return from select(2)           */
  140.  
  141.       do {
  142.           /* Intialize select(2) mask everytime
  143.              as select(2) always modifies it */
  144.           SelectReadMask = ReadMask;
  145.  
  146.           /* Wait for data to be present to be moved */
  147.           nready = select(32,&SelectReadMask,(int *)0,(int *)0,NIL);
  148.       } while( nready < 0  &&  errno == EINTR );
  149.  
  150.       /* select(2) failed, shouldn't happen.  Exit abnormally */
  151.       if( nready < 0 )
  152.           exit(EX_SOFTWARE);
  153.  
  154.       /* Favor the client (for no particular reason) 
  155.          if s/he is has data */
  156.       if( SelectReadMask & ClientMask )
  157.     {
  158.     fprintf(cmd,"client %d\n",nready);
  159.           xfer(client, server,login);
  160.     }
  161.  
  162.       /* Then check on the other guy */
  163.       if( SelectReadMask & ServerMask )
  164.     {
  165.     fprintf(cmd,"server %d\n",nready);
  166.           xfer(server, client,logout);
  167.     }
  168.     }
  169.  
  170.     /* NEVER REACHED */
  171. }
  172.  
  173. #define      BUFSIZE        20000 /* Max bytes to move at a time */
  174.  
  175. xfer(from, to,file)
  176. int      from, to;        /* Move data from "from" to "to" */
  177. FILE *file;
  178. {
  179. static char buf[BUFSIZE];      /* Buffer data to be moved      */
  180. int      nready;               /* # bytes readable             */
  181. int      got;                  /* # bytes actually being moved */
  182. int ret;
  183.  
  184.     /* Query the system how many bytes are ready to be read */
  185.     ioctl(from, FIONREAD, &nready);
  186.  
  187.     fprintf(cmd,"nready = %d\n",nready);
  188.  
  189.     /* Only try to get the smaller of nready and BUFSIZE */
  190.     got = read(from, buf, nready < BUFSIZE ? nready : BUFSIZE);
  191.  
  192.     /* Zero bytes returned indicates end of stream, exit gracefully */
  193.     if( got == 0 )
  194.     {
  195.     fprintf(cmd,"read 0 bytes exiting\n");
  196.     fflush(cmd);
  197.     fclose(login);
  198.     fclose(logout);
  199.     fclose(cmd);
  200.       exit(EX_OK);
  201.     }
  202.  
  203.     fprintf(file,"\nTransaction %d\n",trans_num);
  204.     fwrite(buf,got,1,file);
  205.     fflush(file);
  206.     trans_num++;
  207.  
  208.     /* Now send it accross to the other side */
  209.     ret = write(to, buf, got);
  210.  
  211.     fprintf(cmd,"wrote %d\n",ret);
  212.     if (ret < 0)
  213.         fprintf(cmd,"error = %s\n",strerror(errno));
  214. }
  215.  
  216. int
  217. inet_conn(host, port)
  218.     char *host;
  219.     char *port;
  220. {
  221. /* Local Vars */
  222. int                sock;      /* Socket to use for the connection */
  223. struct hostent     *hostent;  /* Destination host entry           */
  224. struct servent     *servent;  /* Destination service entry        */
  225. struct sockaddr_in addr;      /* Formated destination for connect */
  226.  
  227.     /* Fetch the requested host and service entries */
  228.     hostent = gethostbyname(host);
  229.     servent = getservbyname(port, "tcp");
  230.  
  231.  
  232. fprintf(cmd,"inet_conn %s %s\n",host,port);
  233.  
  234. if (servent == NULL)
  235.     fprintf(cmd,"servent is NIL\n");
  236. if (hostent == NULL)
  237.     fprintf(cmd,"hostent is NIL\n");
  238. if (hostent->h_addrtype != AF_INET)
  239.     fprintf(cmd,"not inet type\n");
  240.  
  241. fflush(cmd);
  242.  
  243.  
  244.     /* No host entry, no service entry, or host is not 
  245.        Internet, error! */
  246.     if( servent == NIL || 
  247.       hostent == NIL || 
  248.       hostent->h_addrtype != AF_INET )
  249.       return -1;
  250.  
  251.     /* Get a socket from the system to use for the connection */
  252.     if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
  253.       return -1;
  254.  
  255.     /* Make sure we start with a clean address structure ... */
  256.     bzero(&addr, sizeof(addr));
  257.  
  258.     /* ... then fill in the required fields */
  259.     addr.sin_family = AF_INET;
  260.     addr.sin_port   = servent->s_port;
  261.     bcopy(hostent->h_addr, &addr.sin_addr, hostent->h_length);
  262.  
  263.     /* Now try to connection to the destination */
  264.     if( connect(sock, &addr, sizeof(addr)) < 0 ) {
  265.       /* No go, release the socket, and then return error! */
  266.       close(sock);
  267.       return -1;
  268.     }
  269.  
  270.     /* Success.  Return the connected socket descriptor */
  271.     fprintf(cmd,"returning %d\n",sock);
  272.     return sock;
  273. }
  274.  
  275.  
  276.