/* Nessus
 * Copyright (C) 1998 Renaud Deraison
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 */
 
#include <includes.h>
#ifdef NESSUSNT
#include "wstuff.h"
#endif


#include "log.h"
#include "ntp.h"
#include "threads.h"
#include "auth.h"


/*
 * Sort the plugins by type (GATHER_INFO, ATTACK and DENIAL)
 */
struct arglist * sort_plugins_by_type(lplugs)
 struct arglist * lplugs;
{
 struct arglist * plugins = lplugs;
 struct arglist * ret;
 struct arglist * tplugs = emalloc(sizeof(struct arglist));
 int i;
 ret = tplugs;
 for(i=ACT_GATHER_INFO;i<=ACT_DENIAL;i++)
    {
      while(lplugs && lplugs->next)
	{
	  struct arglist * args;
	  
	  args = arg_get_value(lplugs->value, "plugin_args");
	  if(args && ((int)arg_get_value(args, "CATEGORY")==i))
	    {             
	      tplugs->value = lplugs->value;
	      tplugs->name = lplugs->name;
	      tplugs->type = lplugs->type;
	      tplugs->length = lplugs->length;
	      tplugs->next = emalloc(sizeof(struct arglist));
	      tplugs = tplugs->next;
	    }
	  lplugs = lplugs->next;
	}
      lplugs = plugins;
    }
   return(ret);
}

/* 
 * Get the max number of threads that
 * the user allowed us to use. If it's not
 * set correctly, we return 5
 */
int get_max_thread_number(preferences)
 struct arglist * preferences;
{
  int max_threads;
  if(arg_get_value(preferences, "max_threads"))
    {
      max_threads = atoi(arg_get_value(preferences, "max_threads"));
      if(max_threads<=0)
	{
	  log_write("Error ! max_threads = %d -- check %s\n", 
		    max_threads, (char *)arg_get_value(preferences, "config_file"));
	  max_threads = 1;
	}
    }
  else max_threads = 5;
  return(max_threads);
}


/*
 * Returns the number of plugins that will be launched
 */
int 
get_active_plugins_number(plugins)
 struct arglist *  plugins;
{
  int i = 0;
  while(plugins && plugins->next)
    { 
      if(plug_get_launch(plugins->value))i++;
      plugins = plugins->next;
    }
 return(i);
}


void send_plugin_order(globals, plugins)
 struct arglist * globals;
 struct arglist * plugins;
{
 int num; 
 char * str;
 

  num = get_active_plugins_number(plugins);
  str = emalloc(num*4);
  while(plugins && plugins->next)
  {
    char * sp;
    
    if(plug_get_launch(plugins->value))
     {
      struct arglist *v = arg_get_value(plugins->value, "plugin_args");
      sp = emalloc(9);
      sprintf(sp, "%d", (int)arg_get_value(v, "ID"));
      strcat(str, sp);
      efree(&sp);
      strcat(str, ";");
     }
     plugins = plugins->next;
   }
  auth_printf(globals, "SERVER <|> PLUGINS_ORDER <|> %s <|> SERVER\n",
  		str);
  efree(&str);
 
}


void plugins_set_ntp_version(plugins, version)
 struct arglist * plugins;
 int version;
{
 while(plugins && plugins->next)
 {
  struct arglist * v;
  
  v = arg_get_value(plugins->value, "plugin_args");
  if(v)arg_add_value(v, "NTP_VERSION", ARG_INT, sizeof(int), (void *)version);
  plugins = plugins->next;
 }
}


void check_client_input(globals)
 struct arglist * globals;
{
 int soc = (int)arg_get_value(globals, "global_socket");
 unsigned long i = 0;
 
 ioctl(soc, FIONREAD, &i);
 if(i)
 {
  struct nessusd_threads * threads = arg_get_value(globals, "threads");
  char * buf = emalloc(4096);
  char * t, * t2;
  auth_gets(globals, buf, 4095);
  
  if((t = strstr(buf, "STOP_ATTACK")))
  {  
    t2 = strstr(t, "<|> ");
    if(!t2)return;
    t2+=strlen("<|> ");
    t = strstr(t2, " <|>");
    if(!t)return;
    t[0] = 0;
    nessusd_thread_kill_by_name(&threads, threads, t2);
    t[0] = ' ';
   } else if((t = strstr(buf,"STOP_WHOLE_TEST"))){
        log_write("stopping the whole test (requested by client)");
        nessusd_thread_kill_all(threads);
        exit(0);
        }
   efree(&buf);
   arg_set_value(globals, "threads", -1, threads);
 }
}


void
check_client_input_thread(globals)
 struct arglist * globals;
{
 while(1)check_client_input(globals);
}


int
is_symlink(name)
 char * name;
{
#ifndef NESSUSNT
 struct stat sb;
 if(stat(name, &sb))return(0);
 return(S_ISLNK(sb.st_mode));
#else
 return(0);
#endif
}

void check_symlink(name)
 char * name;
{
 if(is_symlink(name))
 { 
  fprintf(stderr, "The file %s is a symlink -- can't continue\n", name);
  DO_EXIT(0);
 }
}
