/* Yet Another Wingate Scanner (YAWS) Version 0.1
   (C) 1999 by tempus fugit, tempusf@gmx.net
   URL: tf.darpa.org
   You can freely distribute this stuff, but
   please let the copyright information intact
   and don't alter the code.

   Feel free to send my any comments or suggestions

   Features:
   - can read the hosts to check from a file
   - can scan subnets (class b and c)
   - has an extra flag to prevent intrusion detection systems from being activated
   - logs the results
   - logs successes in an extra file
   - you can enter the number of subprocesses
   - you can specify a timeout

   compile with gcc yaws.c -o yaws

*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <getopt.h>
#include <fcntl.h>

#define wgateport 23

void CheckForWingate (char *,int);
void init_rand ();
void DoLog (char *);
void LogSuccess (char *);
void usage ();
int sock, timeout=5;
char *logfile="yaws.log", *suclogfile="yaws.suc", *progname;

int main (int argc, char **argv) {
	static int forked=0;
	int forks=1, i, pid, dummy, scanned=0, toscan=0, j, k, extra=0, rnumber;
	char c, network[64]="none", class[]="z", inputfile[64]="", host[100];
	FILE *input;
	typedef char target[100];
	target *mytarget;
	progname=argv[0];
	while ((c = getopt (argc, argv, "vef:l:n:c:i:t:s:")) != -1) {
		switch (c) {
			case 'f': forks = atoi (optarg);
				  break;
			case 'e': extra = 1;
				  break;
			case 'l': logfile = optarg;
				  break;
			case 'n': strncpy (network, optarg, 64);
				  break;
			case 'c': strncpy (class, optarg, 1);
				  break;	
			case 'i': strncpy (inputfile, optarg, 64);
				  break;
			case 't': timeout = atoi (optarg);
				  break;
			case 's': suclogfile = optarg;
				  break;
			case 'v': usage ();
			case '?': usage ();
		}
	}
	
	if (argc < 2) {
		fprintf (stderr, "To few argumtens.\n");
		usage ();
	}
	
	if (forks < 1) {
		fprintf (stderr, "To little number of forks.\n");
		usage ();
	}
	
	DoLog ("YAWS 1999 by tempus fugit\n\n");
	
	if ((strcmp (network, "none")) && (strcmp (class, "z"))) {
		if ((!strcmp (class, "b")) && (extra == 0)) {	
			for (j=1; j<255; j++) {
				for (k=1; k<255; k++) {
					snprintf (host, 100, "%s.%d.%d", network, j, k);
					if ((pid = fork ()) == 0) {
						CheckForWingate (host, wgateport);
						kill(getpid(),9);
					}
					if (pid != 0) {
						forked++;
						if (forked >= forks) {
							wait (&dummy);
							forked--;
						}
					}
				}
			}
		}
		else if ((!strcmp(class, "c")) && (extra == 0)) {
			for (j=1; j<255; j++) {
				snprintf (host, 100, "%s.%d", network, j);
				if ((pid = fork ()) == 0) {
					CheckForWingate (host, wgateport);
					kill(getpid(),9);
				}
				if (pid != 0) {
					forked++;
					if (forked >= forks) {
						wait (&dummy);
						forked--;
					}
				}
						
			}
		}
		else if ((!strcmp(class, "b")) && (extra == 1)) {
			init_rand();
			mytarget = malloc ((254*254) * (sizeof (target)));
			if (mytarget == NULL) {
				fprintf (stderr, "Cannot allocate memory.\n");
				exit (1);
			}
			fprintf (stdout, "I am computing the random IPs, this may take a while.\n");			
			for (j=1; j<255; j++) {
				for (k=1; k<255; k++) {
				        marke:					
					rnumber = (int) ((254.0*254.0)*rand()/(RAND_MAX+1.0));
					if (strlen ((mytarget+rnumber)) > 1) goto marke;				
					snprintf ((mytarget+rnumber), 100, "%s.%d.%d", network, j, k);
					
				}
			}
			for (j=0; j<=(254*254); j++) {
				if ((pid = fork ()) == 0) {
					CheckForWingate ((mytarget+j), wgateport);
					kill(getpid(),9);
				}
				if (pid != 0) {
					forked++;
					if (forked >= forks) {
						wait (&dummy);
						forked--;
					}
				}
						
			}
		}
		
		else if ((!strcmp(class, "c")) && (extra == 1)) {
			init_rand();
			mytarget = malloc ((255) * (sizeof (target)));
			if (mytarget == NULL) {
				fprintf (stderr, "Cannot allocate memory.\n");
				exit (1);
			}
			for (j=1; j<255; j++) {
				        marke2:					
					rnumber = 1+(int) ((254.0)*rand()/(RAND_MAX+1.0));
					if (strlen ((mytarget+rnumber)) > 1) goto marke2;				
					snprintf ((mytarget+rnumber), 100, "%s.%d", network, j);						                   										
				
			}
			for (j=1; j<255; j++) {
				if ((pid = fork ()) == 0) {
					CheckForWingate ((mytarget+j), wgateport);
					kill(getpid(),9);
				}
				if (pid != 0) {
					forked++;
					if (forked >= forks) {
						wait (&dummy);
						forked--;
					}
				}			
			}
		}
			
		else
		{
			if ((class != "b") && (class != "c")) {
				printf ("You entered an unknown class or no network.\n");
				return 1;
			}
		}
	for (i=1; i <= forked; i++) wait (&dummy);
	return 0;
	}
		
	input = fopen (inputfile, "r");
	if (input == NULL) {
		fprintf (stderr, "Cannot open input file.\n");
		return 1;
	}
		
	while ((fscanf (input, "%s\n", host)) != EOF) {
		if ((pid = fork ()) == 0) {
			CheckForWingate (host, wgateport);
			kill(getpid(),9);
		}
		if (pid != 0) {
			forked++;
			if (forked >= forks) {
				wait (&dummy);
				forked--;
			}
		}
			
	}
	fclose (input);
	for (i=1; i <= forked; i++) wait (&dummy);

}

void alarm_handler (int sig) {
	close (sock);
	return;
}

void CheckForWingate (char *host, int port)
{
	int ret, conn, sel;
	char buffer[128], logmsg[1024];
	struct sockaddr_in sin;
	fd_set fd;
	struct timeval tv;
	struct hostent *he;
	
	if ((strlen (host)) == 0) exit (1);
	
	if (!(sock = socket (AF_INET, SOCK_STREAM, 0))) {
		fprintf (stderr, "Cannot create a socket.\n");
		exit (1);
	}
	
	if (inet_addr (host) == -1) {
		if ((he=gethostbyname (host)) == NULL) {
			snprintf (logmsg, 1024, "The host %s cannot be resolved.\n", host);
			DoLog (logmsg);
			return;
		} 		
		memcpy (&sin.sin_addr, he->h_addr,he->h_length);
	}
	else if ((sin.sin_addr.s_addr = inet_addr (host)) == -1) {
		snprintf (logmsg, 1024, "IP %s cannot be identified.\n", host);
		DoLog (logmsg);
		return;
	}
	sin.sin_family = AF_INET;
	sin.sin_port = htons (port);
	signal (SIGALRM, alarm_handler);
	alarm (timeout);
	conn = connect (sock, (struct sockaddr*)&sin, sizeof (sin));
	if (conn < 0) {
		snprintf (logmsg, 1024, "Cannot connect to host %s on port %d.\n", host, port);
		DoLog (logmsg);
		close (sock);
		return;
	}
	FD_ZERO (&fd);
	FD_SET (sock, &fd);
	tv.tv_sec = timeout;
	tv.tv_usec = 0;
	sel = select (sock+1, &fd, NULL, NULL, &tv);
	if (sel > 0) {
		if ((ret = recv (sock, buffer, 128, 0)) > 0) {
			if (!strcmp (buffer, "WinGate>")) {
				snprintf (logmsg, 1024, "Host %s is a wingate.\n", host);
				DoLog (logmsg);
				LogSuccess (logmsg);
			}
			else {
				snprintf (logmsg, 1024, "Host %s is no wingate.\n", host);
				DoLog (logmsg);
			}
		}
		
	}
	if (!sel) {
		snprintf (logmsg, 1024, "Host %s time out by search.\n", host);
		DoLog (logmsg);
	}
	if (sel == -1) {
		fprintf (stderr, "Select Error.\n");
		exit (1);
	}
	close (sock);
	return;
}

void init_rand() {
        int fd;
        unsigned n;
        fd = open("/dev/random", O_RDONLY);
        read(fd, &n, sizeof(n));
        close(fd);
        srand(n);
}

void DoLog (char *message) {
	FILE *file;
	file = fopen (logfile, "a");
	if (file == NULL) {
		fprintf (stderr, "File Error.\n");
		exit (1);
	}
	fprintf (file,"%s", message);
	fclose (file);
}

void LogSuccess (char *message) {
	FILE *file;
	file = fopen (suclogfile, "a");
	if (file == NULL) {
		fprintf (stderr, "File Error.\n");
		exit (1);
	}
	fprintf (file, "** SUCCESS: **  ");
	fprintf (file, "%s", message);
	fclose (file);
}

void usage () {
	printf ("[YAWS] Yet Another Wingate Scanner Version 0.1 1999 by tempus fugit\n");
	printf ("mail: tempusf@gmx.net\n");
	printf ("URL: http://tf.darpa.org\n\n");
	printf ("Usage: %s -v -l <logfile> -f <forks> -t <timeout> -n <network> -c <network-class> -i <input file> -s <success-logfile>\n", progname);
	printf ("\tlogfile: the name of the file where the scanning results are stored.\n");
	printf ("\tforks  : the number of forks the program is allowed to create.\n");
	printf ("\ttimeout: timeout of search-process in seconds.\n");
	printf ("\tnetwork: you can enter network that will be checked for wingates.\n");
	printf ("\tnetwork: can be <X.X> or <X.X.X> if class is\n");
	printf ("\t                  b   or    c\n");
	printf ("\tinput-file: you can specify an input-file from which the hosts to checked are extraced.\n");
	printf ("\tsuccess-logfile: success messages are written in this file.\n");
	printf ("\tif you choose an input-file, the network and class options are ignored.\n");
	printf ("Example: %s -l mylogs -n 200.10 -c b -s wow\n", progname);
	exit (0);
}
		
		
	
		
	
	
		

