/* 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.
 *
 * Preferences  -- maps the content of the nessusd.conf file to memory
 *
 */
 
#include <includes.h>
#ifdef NESSUSNT
#include "wstuff.h"
#endif /* defined(NESSUSNT) */

#include "preferences.h"
#include "log.h"
#include "utils.h"
#include "hostloop.h"

/* 
 * Initializes the preferences structure 
 */
int preferences_init(config_file, prefs)
	char * config_file;
	struct arglist ** prefs;
{
  int result;
  *prefs = emalloc(sizeof(struct arglist));
  result = preferences_process(config_file, *prefs);
  return(result);
}

 
/*
 * Creates a new preferences file
 */
int preferences_new(char * name)
{
#ifndef NESSUSNT
  int fd;
#else
  FILE * fd;
#endif
  char * buf;
  char * hn;

#ifndef NESSUSNT
  if((fd = open(name, O_CREAT | O_RDWR | O_EXCL, 0660))<0){
    perror("open ");
    return(-1);
  }
#else
  if((fd = fopen(name, "w"))==NULL){
	 print_error("Could not create %s", name);
	 return(-1);
	 }
#endif
  
  hn = emalloc(255);
  gethostname(hn, 254);
  buf = emalloc(1024+strlen(hn)+strlen(PLUGINS_DIR)+strlen(NESSUSD_MESSAGES)+
  	strlen(NESSUSD_RULES)+strlen(NESSUSD_USERS)+1);
  sprintf(buf,
"# Nessus's Default Setup\n#\n\
# Every line begining with a '#' is a comment\n#\n\n\
plugins_folder = %s\n\n\
email = root@%s\n\
max_threads = 15\n\
logfile = %s\n\
rules = %s\n\
# Users database (read doc/sample.users for details)\n\
users = %s\n\
# Remote file that the plugins will try to read :\n\
test_file = /etc/passwd\n\
# ping hosts before to scan them\n\
ping_hosts = yes\n\
# only test the ips that can be reversely looked up :\n\
reverse_lookup = no\n\
# host expansion :\n\
# dns : performs and AXFR on the remote name server\n\
#       and test the host obtained\n\
# nfs : test hosts that have the right to mount the\n\
#       filesystems exported by the remote host\n\
# ip  : scan the entire subnet\n\
host_expansion = dns;ip\n\
subnet_class = C\n\
port_range = 1-8000\n\
max_hosts = -1\n\
scan_level = normal\n\
outside_firewall = no\n\
\n\
# end.", PLUGINS_DIR, hn, NESSUSD_MESSAGES, NESSUSD_RULES, NESSUSD_USERS);
  efree(&hn);
#ifndef NESSUSNT
  write(fd, buf, strlen(buf));
#else
  fprintf(fd, buf);
#endif
  efree(&buf);
#ifndef NESSUSNT
  close(fd);
#else
  fclose(fd);
#endif
  return(0);
}


/*
 * Copies the content of the prefs file to
 * a special arglist
 */
int preferences_process(filename,prefs)
     char * filename;
     struct arglist * prefs;
{
  FILE * fd;
  char * buffer;
  char * opt, *value;
    if(filename)
      {
        check_symlink(filename);
	if(!(fd = fopen(filename, "r"))) {
#ifndef NESSUSNT
	 if(errno == EACCES)
	 {
	  print_error(
	  	"The Nessus daemon doesn't have the right to read %s\n", filename);
	  DO_EXIT(1);
	 }
#endif

#ifdef DEBUG
	  print_error("Couldn't find any prefs file... Creating a new one...\n");
#endif 
	  if(preferences_new(filename)){
	    print_error("Error creating %s\n", filename);
	    arg_add_value(prefs, "plugins_folder", ARG_STRING,
			  strlen("./plugins"), "./plugins");
	    return(1);
	  }
	  else
	    if(!(fd = fopen(filename, "r")))
	      {
	        perror("open ");
		print_error("Could not open %s -- now quitting\n", filename);
		DO_EXIT(2);
	      }
	}
	buffer = emalloc(255);
	while(!feof(fd) && fgets(buffer, 254,fd))
	  {
	   char * t;
	  if(buffer[strlen(buffer)-1]=='\n')buffer[strlen(buffer)-1]=0;
	    if(buffer[0]=='#')continue;
	    opt = buffer;
	    t = strchr(buffer, '=');
	    if(!t)continue;
	    else {
	      t[0]=0;
	      t+=sizeof(char);
	      while(t[0]==' ')t+=sizeof(char);
	      while(opt[strlen(opt)-1]==' ')opt[strlen(opt)-1]=0;
	      value=emalloc(strlen(t)+1);
	      strncpy(value, t, strlen(t));
	      arg_add_value(prefs, opt, ARG_STRING, strlen(value), value);
#ifdef DEBUGMORE
	      printf("%s = %s\n", opt, value);
#endif
	    }
     	 }
    return(0);
    }
   else return(1);
}
 
 
int preferences_get_host_expansion(preferences)
	struct arglist * preferences;
{
 char * pref;
 int ret = 0;
 
 pref = arg_get_value(preferences, "host_expansion");
 if(!pref)return(HL_DNS);

 if(strstr(pref, "dns"))ret = ret | HL_DNS;
 if(strstr(pref, "nfs"))ret = ret | HL_NFS;
 if(strstr(pref, "ip"))ret = ret | HL_IP;
 
 pref = arg_get_value(preferences, "ping_hosts");
 if(pref && strstr(pref, "yes"))ret = ret | HL_PING;
 
 pref = arg_get_value(preferences, "reverse_lookup");
 if(pref && strstr(pref, "yes"))ret = ret | HL_REVLOOKUP;
 return(ret);
}

int preferences_get_subnet_class(preferences)
        struct arglist * preferences;
{
 char * pref;
 
 pref = arg_get_value(preferences, "subnet_class");
 if(pref)
 {
  if(pref[0]=='A')return(HL_SUBNET_CLASS_A);
  if(pref[0]=='B')return(HL_SUBNET_CLASS_B);
 }
 return(HL_SUBNET_CLASS_C);
}
