TUCoPS :: Linux :: Discontinued :: namescan.c

NameScan 1.2 DNS Mapping System DNS:

/* Namescan, DNS mapping system v1.2
   Bloodmask 1998 */

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <setjmp.h>

#define CHILD_NAME	"namescan"

#define ROOTTIMEOUT	120
#define USLEEP		100000

#define DEFTIMEOUT      15
#define DEFCONNECTIONS  5

#define FILENAME        "%s.query"
#define MERGENAME       "%s.scan"
#define DEEPNAME        "deep"

#define MAXSYSBUF       128
#define MAXFILEBUF      80
#define MAXDOMAINBUF    80

#define TEMPDIR         "/var/tmp/"
#define TEMPSIZE        8

#define OK              1
#define FAILED          0

#ifdef	PASSWORD_PROTECTED
#ifndef EXECPASSWORD
#define EXECPASSWORD    "ZFsZvwzEp7oBc"
#endif
#endif

#define COASTCLEAR      120

int options;
#define F_TIMEOUT       0x002
#define F_PARANOID      0x004
#define F_BACKGROUND    0x008
#define F_DEEPSCAN     0x010
#define F_HOSTNAMES	0x020

#define HASADDRESS	"has address "

int quite;
int timeout;

jmp_buf env;
void handleargs(int argc, char **argv, char *hostname);

int paranoid_coastclear(void);
int paranoid_lookout(void);

int findslot(int pid);
void free_children(void);

void sigchld_handler(int sig);
void sigalrm_handler(int sig);

void ignore_signals(void);

char *Strip(char *String);
int QueryDomain(char *Domain, char *Filename, int maxtimeout);
int ElaborateSCAN(char *Filename, int argc, char **argv);
long GetRandom(long Minimum, long Maximum);

char *GetTemp(void);

void Clean(char *String, int bytes);
void usage(void);
int Format(char *Filename_src, char *Filename_dst, int mode);

#ifdef PASSWORD_PROTECTED
int VerifyKEY(char *Accesskey);
#endif

void go_background(void);

int Linkregions(int argc, char **argv);
int addip(char *ip, char *Filename);

struct regionlist {

 struct regionlist *next, *last;
 char *region;

} *rootregion = NULL;

struct tree_node {

 char *string;
 struct tree_node *left;
 struct tree_node *right;

}; 

int dump_tree(struct tree_node *tree, FILE *dump);
int insert_string(struct tree_node **tree, char *string);
int free_tree(struct tree_node **tree);

long jump;

int *pids;
int free_slots, connections;
int paranoid_secs;

int main(int argc, char **argv)
{
 int Count;

 int option;
 int runloop;

 char *Sysbuf;
 char *Filename;
 char *password;
 char *Domainlist;

 FILE *Resultsfp;
 FILE *Domainlistfp;

 struct regionlist *loop_region;

 timeout = DEFTIMEOUT;
 connections = DEFCONNECTIONS;
 options = quite = runloop = jump = 0;

#ifdef PASSWORD_PROTECTED
 password = getpass("Password: ");
 if(!VerifyKEY(password)) exit(0);
#endif

 while( (option = getopt(argc, argv, "P:j:c:t:D:HMBQh")) != EOF)
  switch(option) {
   case		'H'	: options |= F_HOSTNAMES;
			  break;
   case         'j'     :
                          jump = atol(optarg);
                          if(jump < 1) {
                           fprintf(stderr,
                                   "Error: %s Invalid number of systems\n",
                                   optarg);
                           exit(1);
                          }
                          break;

   case         't'     :
                          timeout = atoi(optarg);
                          if(timeout < 1) {
                           fprintf(stderr, "Error: %s invalid timeout\n",
                                            optarg);
                           exit(1);
                          }
                          options |= F_TIMEOUT;
                          break;
   case         'c'     :
                          connections = atoi(optarg);
                          if(connections < 1) {
                           fprintf(stderr, "Error: %s invalid connections\n",
                                            optarg);
                          }
                          break; 
   case         'D'     :
                          Domainlist = (char *) malloc(strlen(optarg)+1);
                          strcpy(Domainlist, optarg);
                          options |= F_DEEPSCAN;
                          break;
   case         'Q'     :
                          quite++;
                          break;
   case         'B'     :
                          options |= F_BACKGROUND;
                          break;
   case         'P'     :
                          options |= F_PARANOID;
			  paranoid_secs = atoi(optarg);

                          break;

   default              : usage();
  }


 if( options & F_BACKGROUND ) {
  go_background();
  quite = 2;
 }


 Filename = (char *) malloc(MAXFILEBUF);

 if( options & F_DEEPSCAN ) {

  ElaborateSCAN(Domainlist, argc, argv);
  exit(0);
  
 }

 argc -= optind;
 argv += optind;

 if(argc < 1) 
  usage();

 Linkregions(argc, argv);

 argc += optind;
 argv -= optind;

 for(loop_region = rootregion; loop_region != NULL;
     loop_region = loop_region -> next) {

  sprintf(Filename, FILENAME, loop_region -> region);

  if(!QueryDomain(loop_region -> region, Filename, ROOTTIMEOUT)) {
   if( quite < 2 )
    fprintf(stderr, "Error: Couldn't lookup root domain [%s]\n",
            loop_region -> region);
   continue;
  } else if( quite < 2 )
          fprintf(stderr, "Successfully looked up root domain [%s]\n",
                  loop_region -> region);

   if(!ElaborateSCAN(Filename, argc, argv)) continue;

   if( quite < 2 )
    fprintf(stderr, "Finished querying root domain [%s]\n",
                     loop_region -> region);

 }

}

int Linkregions(int argc, char **argv)
{
 int Count;
 struct regionlist *loop_region;
 struct regionlist *tmpregion;

 for(Count = 0; Count<argc; Count++) {

  tmpregion = (struct regionlist *) malloc(sizeof(struct regionlist));
  tmpregion -> region = (char *) malloc(MAXDOMAINBUF);
  strncpy(tmpregion -> region, argv[Count], MAXDOMAINBUF - 1);
  tmpregion -> next = rootregion;
  if(rootregion != NULL)
   rootregion -> last = tmpregion;
  tmpregion -> last = NULL;
  rootregion = tmpregion;

 }

 return OK;
}

char *Strip(char *String)
{
 char *S_CH;

 if((S_CH = strchr(String, (int) '\r')) != NULL) *S_CH = '\0';
 if((S_CH = strchr(String, (int) '\n')) != NULL) *S_CH = '\0';

 return String;
}

long GetRandom(long Minimum, long Maximum)
{
 long RandomNumber;

 struct timeb tp;
 ftime(&tp);

 srand(tp.millitm);
 RandomNumber = Minimum + (long) 
                ( (float) (Maximum - Minimum) * random()/(RAND_MAX+1.0) );

 return RandomNumber;
}

char *GetTemp(void)
{
 int Count;
 char *Filename, *Directory;
 char *O_Ch, *D_Ch;

 Filename = (char *) malloc(80);
 bzero((char *)Filename, 80);

 sprintf(Filename, "%s", TEMPDIR);

 O_Ch = Filename + strlen(Filename);

 for( Count = 0; Count<TEMPSIZE; Count++) {
  usleep(GetRandom(10, 20) * 10);
  switch(GetRandom(1, 3)) {
   case 1        : *O_Ch = GetRandom( (int) 'a', (int) 'z' );
                    O_Ch++;
                    break;
   case 2        : *O_Ch = GetRandom( (int) 'A', (int) 'Z' );
                    O_Ch++;
                    break;
   case 3        : *O_Ch = GetRandom( (int) '0', (int) '9' );
                    O_Ch++;
                    break;
  }
 }

 return Filename;
}

void Clean(char *String, int bytes)
{
 bzero((char *)String, bytes);
}

int QueryDomain(char *Domain, char *Filename, int maxtimeout)
{
 int pid, child_pid, child_status;

 char *Temp = GetTemp();

 struct stat dummy;

 if(!(pid = fork())) {
  
  freopen(Temp, "w", stdout);
  freopen("/dev/null", "w", stderr); 
 
  execl("/usr/bin/host", "/usr/bin/host", "-l", Domain, NULL);
  fclose(stdout);
  exit(1);
 } else 
   if( pid != -1 ) {

    signal(SIGALRM, sigalrm_handler);
    alarm(maxtimeout);

    if(!setjmp(env)) {

     for(;;) {
      if(stat(Temp, &dummy) < 0) continue;
      if(dummy.st_size > 0) break;
      if((child_pid = waitpid(pid, &child_status, WNOHANG)) != -1 )
       if( WIFEXITED(child_status) || WIFSIGNALED(child_status) ) break;       
      usleep(USLEEP);
     } 

     alarm(0);
    } else {
       unlink(Temp);
       kill(pid, 9);
       waitpid(pid, &child_status, 0);
       return FAILED;
      }

    waitpid(pid, &child_status, 0);

    Format(Temp, Filename, 1);
    unlink(Temp);

    free(Temp); 
    return OK;
   }

 if(quite < 2)
  fprintf(stderr, "Error: Couldn't fork\n");

 return FAILED;
}

void usage(void)
{
 fprintf(stderr,
         "usage: namescan [-options] root-domain[s]\n"
         "Options:\n"
         "\t-Q\t\t\tQuite mode\n"
	 "\t-B\t\t\tSnap into background\n"
         "\t-P paranoid_secs\t\tSet delay between paranoid lookouts\n"
         "\t-t timeout\t\tDNS Timeout\n"
         "\t-c connections\t\tConnections per batch\n"
         "\t-j entries\t\tNumber of entries to jump\n"
         "\t-D domain.scan\t\tScan previous results one level deeper\n");
 exit(1);
}

void go_background(void)
{
 if(fork()) exit(0);
}

int ElaborateSCAN(char *Filename, int argc, char **argv)
{
 int i, ploop, Count;
 int pid, slot;
 long line_number;
 char *Domain, *Results, *F_CH;

 char *Mergename;
 FILE *Resultsfp;

 Mergename = (char *) malloc(MAXDOMAINBUF);
 Results = (char *) malloc(MAXDOMAINBUF);
 Domain = (char *) malloc(MAXDOMAINBUF);

 Domain[MAXDOMAINBUF - 1] = '\0';

 pids = (int *) malloc(connections*sizeof(int));
 for(i = 0; i<connections; i++) pids[i] = -1; 

 free_slots = connections;

 if( !(Resultsfp = fopen(Filename, "rt")) ) {
  if( quite < 2 )
   fprintf(stderr, "Error: unable to read from `%s'\n", Filename);
  return FAILED; 
 }

 strcpy(Mergename, Filename);
 strcpy(Results, FILENAME);
 F_CH = strstr(Mergename, &Results[2]);
 if(F_CH != NULL) {
  strcpy(Results, MERGENAME);
  sprintf(F_CH, "%s", &Results[2]);
 } else strcat(Mergename, DEEPNAME);

 for(Count = 0; Count<jump; Count++)
  if( fgets(Domain, MAXDOMAINBUF - 1, Resultsfp) == NULL ) {
   fprintf(stderr, "Error: Jump parameters out of bounds\n");
   exit(0);
  }

 ploop = line_number = 0;
 signal(SIGCHLD, sigchld_handler);

 while( fgets(Domain, MAXDOMAINBUF - 1, Resultsfp) != NULL ) {
  line_number++;
  Strip(Domain);

#ifdef DEBUG
  fprintf(stderr, "DEBUG: Handling `%s' from domainlist\n", Domain);
#endif

  if(inet_addr(Domain) != -1) {
   addip(Domain, Mergename);
   continue;
  }

repeat:

  while( !free_slots ) {
#ifdef DEBUG
   fprintf(stderr, "DEBUG: In the while loop, free_slots = %d\n",
           free_slots);
#endif

   free_children();
   usleep(USLEEP);

   if( options & F_PARANOID )
    if(!(ploop = (ploop+1)%((paranoid_secs*1000000)/USLEEP))) {
     if(paranoid_lookout()) {
      line_number -= connections;

      rewind(Resultsfp);
      for(i = 0; i<line_number; i++)
       if(!fgets( Domain, MAXDOMAINBUF - 1, Resultsfp )) break;
     }
    }

  }

  if((slot = findslot(-1)) < 0) goto repeat;

  switch((pid = fork())) {
 
   case  0 :  ignore_signals();
	      handleargs(argc, argv, Domain);

              if(!QueryDomain(Domain, Mergename, timeout) && quite < 1)
               fprintf(stderr, "Failed querying domain [%s]\n", Domain);
               else 
                if(quite < 1)
                 fprintf(stderr, "Successfully queried domain [%s]\n", Domain);

    	      exit(getpid() & 0xFF);

   default : 
              free_slots--;
              pids[slot] = pid;

#ifdef	DEBUG
	      fprintf(stderr, "DEBUG: new_proc, pid %d, domain %s\n",
		      pid, Domain);
#endif

  }
 }

#ifdef	DEBUG
 fprintf(stderr, "DEBUG: Finished extending domains\n");
#endif

 while( free_slots < connections ) {
  free_children();
  sleep(USLEEP);

  if( options & F_PARANOID )
   if(!(ploop = (ploop+1)%((paranoid_secs*1000000)/USLEEP)))
    paranoid_lookout();
 }

 fclose(Resultsfp);

 Clean(Domain, MAXDOMAINBUF); free(Domain);
 Clean((char *)pids, sizeof(int) * connections); free(pids);

 unlink(Filename);
 Format(Mergename, Filename, 0);
 unlink(Mergename);

 return OK;
}

void free_children(void)
{
 int slot, child_pid, child_status;

 for(slot = 0; slot<connections; slot++) {

  if(pids[slot] != -1)
   if((child_pid = waitpid(pids[slot], &child_status, WNOHANG)) != -1)
    if((WIFEXITED(child_status) &&
        WEXITSTATUS(child_status) == (pids[slot] & 0xFF)) ||
       (WIFSIGNALED(child_status) && WTERMSIG(child_status) == SIGKILL) ) {

     free_slots++;

#ifdef  DEBUG
     fprintf(stderr, "DEBUG: free_slots = %d\n", free_slots);
     fprintf(stderr, "DEBUG: free'd pid %d\n", pids[slot]);
#endif

     pids[slot] = -1;

    }
 }
}

int Format(char *Filename_src, char *Filename_dst, int mode)
{
 char *Line, *Address, *Pointer;
 FILE *SRC, *DST;

 struct tree_node *tree = NULL;

 Line = (char *) malloc(80);
 Address = (char *) malloc(80);

 bzero((char *)Address, sizeof(Address));
 bzero((char *)Line, sizeof(Line));

 if(!(SRC = fopen(Filename_src, "rt"))) return FAILED;
 if(!(DST = fopen(Filename_dst, "at"))) return FAILED;

 while( fgets(Line, 79, SRC) != NULL ) {

  if( mode && (Pointer = strstr(Line, HASADDRESS)) != NULL ) {
   Pointer += strlen(HASADDRESS);
   sscanf(Pointer, "%s", Address);
  } else sscanf(Line, "%s", Address);

  if(!mode) Strip(Address);
  insert_string(&tree, Address);

 }

  dump_tree(tree, DST);
  free_tree(&tree);

  free(Line);
  free(Address);

  fclose(DST);
  fclose(SRC);
}


int insert_string(struct tree_node **tree, char *string)
{
 int rc;
 struct tree_node *tmp;

 if(*tree == NULL) {

  tmp = (struct tree_node *)malloc(sizeof(struct tree_node));
  bzero((struct tree_node *)tmp, sizeof(struct tree_node));
  tmp->string = (char *)malloc(strlen(string)+1);
  strcpy(tmp->string, string);
  *tree = tmp;

  return OK;
 }

 rc = strcmp(string, (*tree)->string);
 if(rc<0)
 insert_string(&((*tree)->left), string);
  else if(rc>0) insert_string(&((*tree)->right), string);

 return OK;
}

int dump_tree(struct tree_node *tree, FILE *WRITE)
{

 if(tree != NULL ) {
  dump_tree(tree -> left, WRITE);
  fprintf(WRITE, "%s\n", tree -> string);
  dump_tree(tree -> right, WRITE);
 }

 return OK;
}

int free_tree(struct tree_node **tree)
{

 if( *tree != NULL ) {
  free_tree(&(*tree)->left);
  free_tree(&(*tree)->right);
  free((*tree)->string);
  free(*tree);
 }

}

int addip(char *IP, char *Filename)
{
 FILE *WRITE;

 if(!(WRITE = fopen(Filename, "at"))) return FAILED;
 fprintf(WRITE, "%s\n", IP);

 fclose(WRITE); 
 return OK;
}

void sigalrm_handler(int sig)
{
 signal(SIGALRM, SIG_IGN);
 alarm(0);

 longjmp(env, 1);
}

void sigchld_handler(int sig)
{
 int slot, child_pid, child_status;

 if((child_pid = wait(&child_status)) != -1) {
  if( (WIFEXITED(child_status) && 
       WEXITSTATUS(child_status) == (child_pid & 0xFF)) ||
      (WIFSIGNALED(child_status) && WTERMSIG(child_status) == SIGKILL)) {
   waitpid(child_pid, &child_status, WNOHANG);

   if( (slot = findslot(child_pid)) != -1 ) {
    free_slots++;
    pids[slot] = -1;
   }

#ifdef DEBUG
   fprintf(stderr, "DEBUG: caught sigchld from pid %d, free_slots = %d\n",
 		   child_pid, free_slots); 
#endif

  }
 }

 signal(SIGCHLD, sigchld_handler);
}

void ignore_signals(void)
{
 int i;
 for( i = 1; i<=31; i++ ) signal(i, SIG_IGN);
}

int findslot(int pid)
{
 int i;

 for(i = 0; i<connections; i++)
  if(pids[i] == pid) return i;

 return -1;
}

void handleargs(int argc, char **argv, char *Hostname)
{
 int i = 1;

 if( !(options & F_PARANOID) )
  sprintf(argv[0], "%s (%s)", CHILD_NAME, Hostname);
  else i = 0;

 for(; i<argc; i++) argv[i][0] = '\0';

}

int paranoid_coastclear(void)
{
 struct stat dummy;
 char *filename;
 const char *cpa, *cpb;

 const char tty[] = "/dev/tty";
 const char pty[] = "pqrS";
 const char order[] = "0123456789abcdef";

 filename = alloca(strlen(tty) + 3);
 strcpy(filename, tty);
 filename[strlen(tty) + 1] = '\0';

/* check console terminals */
 for(cpa = order; *cpa; cpa++) {
  filename[strlen(tty)] = *cpa;
  if( stat(filename, &dummy) < 0 ) break;
  if( (time(NULL) - dummy.st_atime) < COASTCLEAR ) return 0;
 }

/* check non-consoles */
 filename[strlen(tty) + 2] = '\0';
 for(cpa = pty; *cpa; cpa++) {
  filename[strlen(tty)] = *cpa;
  for(cpb = order; *cpb; cpb++) {
   filename[strlen(tty) + 1] = *cpb;
   if( stat(filename, &dummy) < 0 ) break;
   if( (time(NULL) - dummy.st_atime) < COASTCLEAR ) return 0;
  }
 }

 return 1;
}

int paranoid_lookout(void)
{
 int i;

#ifdef	DEBUG
  fprintf(stderr, "DEBUG: paranoid_lookout called\n");
#endif

 if(!paranoid_coastclear()) {
#ifdef  DEBUG
  fprintf(stderr, "DEBUG: PARANOID mode activated\n");
#endif

  for(i = 0; i<connections; i++) 
   if(pids[i] != -1) kill(pids[i], SIGKILL);

  while(free_slots < connections) { 
   usleep(USLEEP);
   free_children();
  }

  sleep(COASTCLEAR);
  while( !paranoid_coastclear() ) {

#ifdef  DEBUG
  fprintf(stderr, "DEBUG: coastclear returned 0, staying stealthy\n");
#endif

   sleep(paranoid_secs);
  }

#ifdef  DEBUG
  fprintf(stderr, "DEBUG: PARANOID mode deactivated\n");
#endif  DEBUG
  return 1;
 }

 return 0;
}

#ifdef PASSWORD_PROTECTED 
int VerifyKEY(char *Accesskey)
{
 int rv;

 char *CryptKEY, *CryptCODE;
 char Salt[2];

 CryptKEY = EXECPASSWORD;
 Salt[0] = CryptKEY[0];
 Salt[1] = CryptKEY[1];

 CryptCODE = crypt(Accesskey, Salt);
 rv = strncmp(CryptKEY, CryptCODE, 13);

 if( !rv )
  return OK;

 return FAILED;
}
#endif

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH