1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00
samba-mirror/source3/sockspy.c
Samba Release Account 97e3422f41 Initial version imported to CVS
(This used to be commit 65968b2943)
1996-05-04 07:50:45 +00:00

303 lines
7.0 KiB
C

/*
USAGE
sockspy desthost destservice
You install this program in /etc/inetd.conf and /etc/services
For example I have used these entries:
/etc/services:
spy 8001/tcp spy port
/etc/inetd.conf:
spy stream tcp nowait tridge /usr/local/smb/sockspy sockspy fjall netbios-ssn
This means any connection to port 8001 will be redirected to
netbios-ssn on fjall. By playing with these parameters you can easily
spy on most of the tcp protocols. All packets traversing the link will
be captured.
NOTE: This program is totally unsupported. I haven't used it for 2
years, and don't intend to fix the obvious bugs/limitations. I will,
however, accept contributed patches - or even a total rewrite :-)
*/
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <errno.h>
#include <sysexits.h>
int trans_num = 0;
#ifndef LOGIN
#define LOGIN "/tmp/spy.in"
#endif
#ifndef LOGOUT
#define LOGOUT "/tmp/spy.out"
#endif
#ifndef LOGCMD
#define LOGCMD "/tmp/spy.cmd"
#endif
FILE *cmd = NULL;
FILE *login = NULL;
FILE *logout = NULL;
#define STREQL(a, b) (strcmp(a, b) == 0)
#define NIL (0)
char DestHost[256]; /* Remote system to connect to */
char DestObj[256]; /* Remote object/service to connect to */
/* Signal handler for SIGPIPE (write on a disconnected socket) */
abort()
{
if (cmd)
{
fprintf(cmd,"writing to disconnected socket!\n");
fflush(cmd);
}
exit(1);
}
main(argc, argv)
int argc; /* # of command line arguments */
char *argv[]; /* the command line arguments */
{
int client, /* Socket connected to client */
server; /* Socket to use for server */
trans_num = 0;
#ifndef NOLOG
login = fopen(LOGIN,"w");
logout = fopen(LOGOUT,"w");
cmd = fopen(LOGCMD,"w");
#endif
if (cmd)
{
fprintf(cmd,"Started server\n");
fflush(cmd);
}
/* Check usage */
if(argc != 3)
return;
strcpy(DestHost,argv[1]);
strcpy(DestObj,argv[2]);
/* Time to attempt the connection */
server = inet_conn(DestHost, DestObj);
if( server < 0 ) {
exit(EX_CANTCREAT);
}
/* Just to make the code more readable */
client = 0;
/* We will abort gracefully when the client or remote system
goes away */
signal(SIGPIPE, abort);
/* Now just go and move raw data between client and
remote system */
dowork(client, server);
/* ... NEVER RETURNS ... */
}
dowork(client, server)
int client, server;
{
/* select(2) masks for client and remote */
int ClientMask, ServerMask;
/* Combined ClientMask and ServerMask */
int ReadMask;
/* Initialize select(2) masks */
ClientMask = 1<<client;
ServerMask = 1<<server;
ReadMask = ClientMask | ServerMask;
/* Now move raw data for the rest of our life between
client and remote */
for( ; ; ) {
/* Local Variables */
int SelectReadMask;/* select(2) mask modifiable by select(2) */
int nready; /* status return from select(2) */
do {
/* Intialize select(2) mask everytime
as select(2) always modifies it */
SelectReadMask = ReadMask;
/* Wait for data to be present to be moved */
errno = 0;
nready = select(32,&SelectReadMask,(int *)0,(int *)0,NIL);
} while( nready < 0 && errno == EINTR );
/* select(2) failed, shouldn't happen. Exit abnormally */
if( nready < 0 )
exit(EX_SOFTWARE);
/* Favor the client (for no particular reason)
if s/he is has data */
if( SelectReadMask & ClientMask )
{
if (cmd)
fprintf(cmd,"client %d\n",nready);
xfer(client, server,login);
}
/* Then check on the other guy */
if( SelectReadMask & ServerMask )
{
if (cmd)
fprintf(cmd,"server %d\n",nready);
xfer(server, client,logout);
}
}
/* NEVER REACHED */
}
#define BUFSIZE 20000 /* Max bytes to move at a time */
xfer(from, to,file)
int from, to; /* Move data from "from" to "to" */
FILE *file;
{
static char buf[BUFSIZE]; /* Buffer data to be moved */
int nready; /* # bytes readable */
int got; /* # bytes actually being moved */
int ret;
/* Query the system how many bytes are ready to be read */
ioctl(from, FIONREAD, &nready);
if (cmd)
fprintf(cmd,"nready = %d\n",nready);
/* Only try to get the smaller of nready and BUFSIZE */
got = read(from, buf, nready < BUFSIZE ? nready : BUFSIZE);
/* Zero bytes returned indicates end of stream, exit gracefully */
if( got == 0 )
{
if (cmd)
{
fprintf(cmd,"read 0 bytes exiting\n");
fflush(cmd);
}
if (login)
fclose(login);
if (logout)
fclose(logout);
if (cmd)
fclose(cmd);
exit(EX_OK);
}
if (file)
{
fprintf(file,"\nTransaction %d\n",trans_num);
fwrite(buf,got,1,file);
fflush(file);
}
trans_num++;
/* Now send it accross to the other side */
ret = write(to, buf, got);
if (cmd)
{
fprintf(cmd,"wrote %d\n",ret);
if (ret < 0)
fprintf(cmd,"error = %s\n",strerror(errno));
}
}
int
inet_conn(host, port)
char *host;
char *port;
{
/* Local Vars */
int sock; /* Socket to use for the connection */
struct hostent *hostent; /* Destination host entry */
struct servent *servent; /* Destination service entry */
struct sockaddr_in addr; /* Formated destination for connect */
/* Fetch the requested host and service entries */
hostent = gethostbyname(host);
if (isdigit(*port))
servent = getservbyport(80, "tcp");
else
servent = getservbyname(port, "tcp");
if (cmd)
{
fprintf(cmd,"inet_conn %s %s\n",host,port);
if (servent == NULL)
fprintf(cmd,"servent is NIL\n");
if (hostent == NULL)
fprintf(cmd,"hostent is NIL\n");
if (hostent->h_addrtype != AF_INET)
fprintf(cmd,"not inet type\n");
fflush(cmd);
}
/* No host entry, no service entry, or host is not
Internet, error! */
if( servent == NIL ||
hostent == NIL ||
hostent->h_addrtype != AF_INET )
return -1;
/* Get a socket from the system to use for the connection */
if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
return -1;
/* Make sure we start with a clean address structure ... */
bzero(&addr, sizeof(addr));
/* ... then fill in the required fields */
addr.sin_family = AF_INET;
addr.sin_port = servent->s_port;
bcopy(hostent->h_addr, &addr.sin_addr, hostent->h_length);
/* Now try to connection to the destination */
if( connect(sock, &addr, sizeof(addr)) < 0 ) {
/* No go, release the socket, and then return error! */
close(sock);
return -1;
}
/* Success. Return the connected socket descriptor */
if (cmd)
fprintf(cmd,"returning %d\n",sock);
return sock;
}