/* Nessuslib -- the Nessus Library
 * Copyright (C) 1998 Renaud Deraison
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Plugutils -- plugin-specific stuff
 */

#define EXPORTING
#include <includes.h>
		

ExtFunc
void plug_set_family(desc, family)
 struct arglist * desc; 
 const char * family;
{
  if(family)
    arg_add_value(desc, "FAMILY", ARG_STRING,
    			strlen(family), estrdup(family));
}


ExtFunc
void plug_set_timeout(desc, timeout)
 struct arglist * desc; 
 int timeout;
{
    arg_add_value(desc, "TIMEOUT", ARG_INT,
    			sizeof(int), (void *)timeout);
}

ExtFunc
void plug_request_libpcap(desc)
 struct arglist * desc;
{
 arg_add_value(desc, "LIBPCAP", ARG_INT, sizeof(int), (void*)1);
}

ExtFunc
const char * plug_get_family(desc)
 struct arglist * desc;
{
 return(arg_get_value(desc, "FAMILY"));
}
		

ExtFunc
void plug_set_launch(desc, launch)
 struct arglist * desc;
 int launch;
{
  if(arg_set_value(desc, "ENABLED", sizeof(int), (void *)launch))
  {
   arg_add_value(desc, "ENABLED", ARG_INT, sizeof(int), (void *)launch);
  }
}


ExtFunc
int plug_get_launch(desc)
 struct arglist * desc;
{
 return((int)arg_get_value(desc, "ENABLED"));
}	
	
	
ExtFunc
void plug_set_name(desc, name)
 struct arglist * desc; 
 const char * name; 
{	
  if(name)
    arg_add_value(desc, "NAME", ARG_STRING,
    			strlen(name), estrdup(name));
}


ExtFunc
void plug_set_summary(desc, summary)
 struct arglist * desc;
 const char * summary;
{
  if(summary)
    arg_add_value(desc, "SUMMARY", ARG_STRING,
    			strlen(summary), estrdup(summary));
}


ExtFunc
void plug_set_description(desc, description)
 struct arglist * desc;
 const char * description;
{
  if(description)
    arg_add_value(desc, "DESCRIPTION", ARG_STRING,
    			strlen(description), estrdup(description));
}


ExtFunc
void plug_set_copyright(desc, copyright)
 struct arglist * desc;
 const char * copyright;
{
  if(copyright)
    arg_add_value(desc, "COPYRIGHT", ARG_STRING,
  		  strlen(copyright), estrdup(copyright));
}


ExtFunc
void plug_set_category(desc, category)
 struct arglist * desc;
 int category;
{
       arg_add_value(desc, "CATEGORY", ARG_INT, sizeof(int), (void *)category);
}


ExtFunc
void plug_set_attacklevel(desc, attacklevel)
 struct arglist * desc;
 int attacklevel;
{
	arg_add_value(desc, "ATTACKLEVEL", ARG_INT, sizeof(int), (void *)attacklevel);
}


ExtFunc
void plug_add_host(desc, hostname)
 struct arglist * desc;
 struct arglist * hostname;
{
	struct arglist * h;
	
	h = arg_get_value(desc, "HOSTNAME");
	if(!h)arg_add_value(desc, "HOSTNAME", ARG_ARGLIST, sizeof(hostname), hostname);
	else arg_set_value(desc, "HOSTNAME", sizeof(hostname), hostname);
}


ExtFunc
void host_add_port(hostdata, portnum, state, banner)
 struct arglist * hostdata;
 int portnum;
 int state;
 const char * banner;
{
 struct arglist * port ;
 struct arglist * portlist;
 char * port_s = emalloc(8);
 char * l_banner = emalloc(banner ? strlen(banner)+1:0);
 sprintf(port_s, "%d", portnum);
 
 if(banner)strncpy(l_banner, banner, strlen(banner));
 port = emalloc(sizeof(struct arglist));
 if(hostdata)
 	 portlist = arg_get_value(hostdata, "PORTS");
 else return;
 if(!portlist)
 {
#ifdef DEBUGMORE
  printf("!portlist\n");
  printf("allocating a new one...");
#endif
  portlist = emalloc(sizeof(struct arglist));
  arg_add_value(hostdata, "PORTS", ARG_ARGLIST, sizeof(portlist), portlist);
#ifdef DEBUGMORE
  printf("Done!\n");
#endif
 }

 arg_add_value(port, "STATE", ARG_INT, sizeof(int), (void *)state);
 arg_add_value(port, "BANNER", ARG_STRING, banner ? strlen(l_banner):0, l_banner);
 arg_add_value(portlist, port_s, ARG_ARGLIST, sizeof(port), port);
#ifdef DEBUGMORE
 printf("Port added for %s\n", (char *)arg_get_value(hostdata, "FQDN"));
#endif
}


ExtFunc
int host_get_port_state(plugdata, portnum)
 struct arglist * plugdata;
 int portnum;
{ 
 struct arglist * hostdata = arg_get_value(plugdata, "HOSTNAME");
 struct arglist * ports;
 struct arglist * port;
 char * port_s;
 int * range;
 int i,flag;
 
 /* Check that we actually scanned the port */
 if(!arg_get_value(hostdata, "scanned"))return(1);
 range = arg_get_value(hostdata, "SCAN_RANGE");
 if(!range)return(1);
 for(i=0,flag=0;((range[i])&&(!flag));i++)
 	if(range[i]==portnum)flag=1;
 if(!flag)return(1);
 
 /* Ok, we scanned it. What is its state ? */
 port_s = emalloc(8);
 
 sprintf(port_s, "%d", portnum);
 if(!hostdata)return(0);
 ports = arg_get_value(hostdata, "PORTS");
 if(!ports)return(0);
 port = arg_get_value(ports, port_s);
 if(!port)return(0);
 return((int)arg_get_value(port, "STATE"));
}


ExtFunc
char * host_get_port_banner(plugdata, portnum)
 struct arglist * plugdata;
 int portnum;
{
  struct arglist * hostdata = arg_get_value(plugdata, "HOSTNAME");
  struct arglist * ports;
  struct arglist * port;
  char * port_s = emalloc(8);
  
  sprintf(port_s, "%d", portnum);
  if(!hostdata)return(NULL);
  ports = arg_get_value(hostdata, "PORTS");
  if(!ports)return(NULL);
  port = arg_get_value(ports, port_s);
  if(!port)return(NULL);
  return((char *)arg_get_value(port, "BANNER"));
}


ExtFunc
const char * plug_get_hostname(desc)
 struct arglist * desc;
{
 struct arglist * hinfos = arg_get_value(desc, "HOSTNAME");
 if(hinfos)return((char*)arg_get_value(hinfos, "FQDN"));
 else return(NULL);
}


ExtFunc
struct in_addr * plug_get_host_ip(desc)
 struct arglist * desc;
{
 struct arglist * hinfos = arg_get_value(desc, "HOSTNAME");
 if(hinfos)return((struct in_addr*)arg_get_value(hinfos, "IP"));
 else return(NULL);
}


ExtFunc
void proto_post_hole(desc, port, proto, action)
 struct arglist * desc;
 int port;
 const char * proto;
 const char * action;
{

 char *t;
 char * buffer;
 int socket;
 register struct arglist * hostdata;
 char c;
 char * naction;
 int ntp_version = (int)arg_get_value(desc, "NTP_VERSION");
 c = (char)13;
 
 hostdata = arg_get_value(desc, "HOSTNAME");
 if(!action)return;
 naction = emalloc(strlen(action)+1);
 strncpy(naction, action, strlen(action));
 while((t=strchr(naction, '\n'))||(t=strchr(naction, c)))t[0]=';';
 buffer=emalloc(255+strlen(naction));
 if(ntp_version <= 10)
 {
 sprintf(buffer, "SERVER <|> HOLE <|> %s <|> %d:%s <|> SERVER\n", 
 	(char *)arg_get_value(hostdata, "FQDN"), port, naction);
 }
 else
 {
  struct servent * service = getservbyport(htons((unsigned short)port), proto);
  if(port>0){
        sprintf(buffer, "SERVER <|> HOLE <|> %s <|> %s (%d/%s) <|> %s <|> SERVER\n",
  	(char *)arg_get_value(hostdata, "FQDN"),
        service ? service->s_name:"unknown",
        port, proto, naction);
        }
  else sprintf(buffer, "SERVER <|> HOLE <|> %s <|> general/%s <|> %s <|> SERVER\n",
  	(char *)arg_get_value(hostdata, "FQDN"), 
        proto, naction);
 }
 socket = (int)arg_get_value(desc, "SOCKET");
 send(socket, buffer, strlen(buffer), 0);
 efree(&buffer);
 efree(&naction);
 return;
}


ExtFunc
void post_hole(desc, port, action)
 struct arglist * desc;
 int port;
 const char * action;
{
  proto_post_hole(desc, port, "tcp", action);
} 


ExtFunc
void post_hole_udp(desc, port, action)
 struct arglist * desc;
 int port;
 const char * action;
{
 proto_post_hole(desc, port, "udp", action);
}


ExtFunc
void post_info(desc, port, action)
 struct arglist * desc;
 int port;
 const char * action;
{
  proto_post_info(desc, port, "tcp", action);
} 


ExtFunc
void post_info_udp(desc, port, action)
 struct arglist * desc;
 int port;
 const char * action;
{
 proto_post_info(desc, port, "udp", action);
}


ExtFunc
void proto_post_info(desc, port, proto, action)
 struct arglist * desc;
 int port;
 const char * proto;
 const char * action;
{
 char *t;
 char * buffer;
 int socket;
 register struct arglist * hostdata;
 char c;
 char * naction;
 int ntp_version = (int)arg_get_value(desc, "NTP_VERSION");
 c = (char)13;
 
 hostdata = arg_get_value(desc, "HOSTNAME");
 if(!action)return;
 naction = emalloc(strlen(action)+1);
 strncpy(naction, action, strlen(action));
 while((t=strchr(naction, '\n'))||(t=strchr(naction, c)))t[0]=';';
 buffer=emalloc(255+strlen(naction));
 if(ntp_version <= 10)
 {
 sprintf(buffer, "SERVER <|> INFO <|> %s <|> %d:%s <|> SERVER\n", 
 	(char *)arg_get_value(hostdata, "FQDN"), port, naction);
 }
 else
 {
  struct servent * service;
  if(port>0){
  	service = getservbyport(htons((unsigned short)port), proto);
        sprintf(buffer, "SERVER <|> INFO <|> %s <|> %s (%d/%s) <|> %s <|> SERVER\n",
  	(char *)arg_get_value(hostdata, "FQDN"),
        service ? service->s_name:"unknown",
        port, proto, naction);
        }
  else sprintf(buffer, "SERVER <|> INFO <|> %s <|> general/%s <|> %s <|> SERVER\n",
  	(char *)arg_get_value(hostdata, "FQDN"), proto, naction);
        
 }
 socket = (int)arg_get_value(desc, "SOCKET");
 send(socket, buffer, strlen(buffer), 0);
 efree(&buffer);
 efree(&naction);
 return;
} 


ExtFunc
void l_post_hole(desc, port, action)
 struct arglist * desc;
 const char * port;
 const char * action;
{
 struct arglist * ports;
 struct arglist * pport;
 struct arglist * report;
 char * comm;
 
 if(!action)return;
 comm = emalloc(strlen(action)+1);
 strncpy(comm, action, strlen(action));
 ports = arg_get_value(desc, "PORTS");
 if(!ports)
 {
  ports = emalloc(sizeof(struct arglist));
  arg_add_value(desc, "PORTS", ARG_ARGLIST, -1, ports);
 }
 pport = arg_get_value(ports, port);
 
 if(!pport){
 	pport = emalloc(sizeof(struct arglist));
 	arg_add_value(ports, port, ARG_ARGLIST, -1, pport);
 	arg_add_value(pport, "STATE", ARG_INT, sizeof(int),(void *)1);
 	}
 report = arg_get_value(pport, "REPORT");
 if(!report)
 {
  report = emalloc(sizeof(struct arglist));
  arg_add_value(pport, "REPORT", ARG_ARGLIST, -1, report);
 }
 while(report && report->next)report = report->next;
 arg_add_value(report, "HOLE", ARG_STRING, strlen(comm), comm);
 return;
} 


ExtFunc
void l_post_info(desc, port, action)
 struct arglist * desc;
 const char * port;
 const char * action;
{
 struct arglist * ports;
 struct arglist * pport;
 struct arglist * report;
 char * comm;
 
 if(!action)return;
 comm = emalloc(strlen(action)+1);
 strncpy(comm, action, strlen(action));
 ports = arg_get_value(desc, "PORTS");
 if(!ports)
 {
  ports = emalloc(sizeof(struct arglist));
  arg_add_value(desc, "PORTS", ARG_ARGLIST, -1, ports);
 }
 pport = arg_get_value(ports, port);
 
 if(!pport){
 	pport = emalloc(sizeof(struct arglist));
 	arg_add_value(ports, port, ARG_ARGLIST, -1, pport);
 	arg_add_value(pport, "STATE", ARG_INT, sizeof(int),(void *)1);
 	}
 report = arg_get_value(pport, "INFO");
 if(!report)
 {
  report = emalloc(sizeof(struct arglist));
  arg_add_value(pport, "INFO", ARG_ARGLIST, -1, report);
 }
 while(report && report->next)report = report->next;
 arg_add_value(report, "INFO", ARG_STRING, strlen(comm), comm);
 return;
} 
 
 
ExtFunc
char * get_preference(desc, name)
 struct arglist *desc;
 const char * name;
{
 struct arglist * prefs;
 prefs = arg_get_value(desc, "preferences");
 if(!prefs)return(NULL);
 return((char *)arg_get_value(prefs, name));
}


ExtFunc
void add_plugin_preference(desc, name, type, defaul)
 struct arglist *desc;
 const char * name;
 const char * type;
 const char * defaul;
{
 struct arglist * prefs = arg_get_value(desc, "preferences");
 char * p_name = arg_get_value(desc, "NAME");
 char * pref;
 
 if(!prefs || !p_name)return;
 pref = emalloc(strlen(p_name)+10+strlen(type)+strlen(defaul));
 sprintf(pref, "%s[%s]:%s", p_name, type, name);
 arg_add_value(prefs, pref, ARG_STRING, strlen(defaul), estrdup(defaul));
 efree(&pref);
}


ExtFunc
char * get_plugin_preference(desc, name)
  struct arglist * desc;
  const char * name;
{
 struct arglist * prefs = arg_get_value(desc, "preferences");
 while(prefs && prefs->next)
 {
  char * a= NULL, *b = NULL;
  int c = 0;
  
  a = strchr(prefs->name, '[');
  if(a)b=strchr(prefs->name, ']');
  if(b)c=(b[1]==':');
  
  if(c)
  {
   b+=2*sizeof(char);
   if(!strcmp(name, b))return(prefs->value);
  }
  prefs = prefs->next;
 }
 return(NULL);
}


ExtFunc
void plug_set_key(args, name, type, value)
 struct arglist * args;
 char * name;
 int type;
 void * value;
{
 int pip = (int)arg_get_value(args, "pipe");
 char * str = NULL;
 if(!pip)return;
 switch(type)
 {
  case ARG_STRING :
   str = emalloc(strlen(name)+1+strlen(value)+1+1);
   sprintf(str, "%d %s=%s\n", type, name, (char *)value);
   break;
  case ARG_INT :
   str = emalloc(strlen(name)+10);
   sprintf(str, "%d %s=%d\n", type, name, (int)value);
   break;
  case ARG_ARGLIST :
   {
    struct arglist * t = (struct arglist *)value;
    str = emalloc(20+strlen(name));
    sprintf(str, "%d %s/START_AL\n", type, name);
    write(pip, str, strlen(str));
    while(t && t->next){
    	plug_set_key(args, t->name, t->type, t->value);
        t = t->next;
        }
    sprintf(str, "%d %s/END_AL\n",type, name);
   }
   break;
 }
 if(str)
 {
   write(pip, str, strlen(str));
   efree(&str);
 }
} 


void * plug_get_key(args, name)
 struct arglist * args;
 char * name;
{
 struct arglist * key = (struct arglist *)arg_get_value(args, "key");
 if(!key)return(NULL);
 return(arg_get_value(key, name));
}
       
 

