/* 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>
#include <gtk/gtk.h>
#include "xstuff.h"
#include "comm.h"
#include "auth.h"
#include "attack.h"
#include "report.h"
#include "parser.h"
#include "report_file.h"
#include "error_dialog.h"
#include "sighand.h"
#include "preferences.h"
#include "prefs_dialog/prefs_dialog.h"

struct arglist * Plugins;
struct arglist * Scanners;
int PluginsNum;
int ScannersNum;
struct arglist * Hosts;
struct arglist * Prefs;
struct arglist * MainDialog;
struct arglist * ArgSock;
int GlobalSocket;
int F_show_pixmaps;
int F_quiet_mode;
int F_nessusd_running;


char * connect_to_nessusd(char *, int, char *, char *);
void init_globals();

/*
 * connect_to_nessusd
 *
 * This function establishes the connection between
 * nessus and nessusd, logs in and reads the plugin
 * list from the server.
 *
 */
char *
connect_to_nessusd(hostname, port, login, password)
	char * hostname;
	int port;
	char * login;
	char * password;
	
{
  int soc;
#ifndef USE_AF_INET
  struct sockaddr_un address;
  char * name = AF_UNIX_PATH;
#endif

  init_globals();
#ifdef USE_AF_INET
  soc = open_sock_tcp_hn(hostname, port);
  if(soc<0)
  	{
  	struct in_addr a = nn_resolve(hostname);
  	if(!a.s_addr)return("Host not found !");
  	else
  	return("Could not open a connection to the remote host");
  	}
#else
  if((soc = socket(AF_UNIX, SOCK_STREAM,0))==-1){
  	perror("socket ");
  	exit(1);
  	}
  bzero(&address, sizeof(struct sockaddr_un));
  address.sun_family = AF_UNIX;
  bcopy(name, address.sun_path, strlen(name));
  if(connect(soc, &address, sizeof(address))==-1){
  	return("Could not open a connection to the remote host");
  	}
#endif  
  GlobalSocket = soc;
  ArgSock = emalloc(sizeof(struct arglist));
  arg_add_value(ArgSock, "global_socket", ARG_INT, -1, (void *)GlobalSocket);
  if(comm_init(soc) || (auth_login(login, password)))
  	return("Remote host is not using NTP/1.1");
  	
  if(comm_get_pluginlist())return("Login failed");
  comm_get_preferences(Prefs);
  comm_get_rules(Prefs);
  return(NULL);
}

/*
 * init_globals
 *
 * initializes two main global variables : plugins and
 * hosts
 *
 */
void 
init_globals()
{
  Plugins = emalloc(sizeof(struct arglist));
  Scanners = emalloc(sizeof(struct arglist));
  Hosts = emalloc(sizeof(struct arglist));
}


void 
display_help()
{
 printf("nessus, version %s\n", NESSUS_VERSION);
#ifdef USE_AF_INET
 printf("\nusage : nessus [-vnh] [-q host port user password target result]\n\n");
#else
 printf("\nusage : nessus [-vnh] [-q user password target result]\n\n");
#endif
 printf("\tv : shows version number\n");
 printf("\th : shows this help\n"); 
 printf("\tn : No pixmaps\n");
 printf("\tq : quiet mode : nessus performs the test without displaying anything\n");
 printf("\t    to the screen.\n\n");
 printf("\tThe quiet mode arguments are :\n");
#ifdef USE_AF_INET
 printf("\t\thost     : nessusd host\n");
 printf("\t\tport     : nessusd host port\n");
#endif
 printf("\t\tuser     : user name\n");
 printf("\t\tpassword : user password\n");
 printf("\t\ttarget   : target host\n");
 printf("\t\tresult   : name of the file where \n\t\t\t   nessus will store the results\n");
}
 
 
int main(int argc, char * argv[])
{
  int i;
#ifndef DEBUG
  signal(SIGSEGV , sighand_sigsegv);
#endif
  preferences_init(&Prefs);
  PluginsNum = 0;
  ScannersNum = 0;
  ArgSock = NULL;
  GlobalSocket = -1;
  F_show_pixmaps = 1;
  F_quiet_mode = 0;
  while((i=getopt(argc, argv, "vhqn"))!=EOF)
  {
   switch(i)
   {
   
    case 'n' : 
    	F_show_pixmaps = 0;
        break;
    	
    case 'v' :
    	printf("nessus (%s) %s for %s -- (c) 1998 Renaud Deraison <deraison@worldnet.fr>\n", 
    			PROGNAME,NESSUS_VERSION, NESS_OS_NAME);
    	exit(0);
    	break;
    	
    case 'q' : 
        {
#ifdef USE_AF_INET      
        char * nessusd_host;
        char * port;
#endif
        char * username;
        char * password;
        char * target;
        char * fname;
        char * err;
        int j;
        
    	F_quiet_mode = 1;
#ifdef USE_AF_INET
    	for(j=0;j<6;j++)
#else
	for(j=0;j<3;j++)
#endif
    	{
    	 if(!argv[optind+j]){
    	 	display_help();
    	 	exit(0);
    	 	}
    	}
#ifdef USE_AF_INET
    	nessusd_host = argv[optind++];
    	port = argv[optind++];
#endif
    	username = argv[optind++];
        password = argv[optind++];
    	target = argv[optind++];
    	fname = argv[optind++];
#ifdef USE_AF_INET
	if((err = connect_to_nessusd(nessusd_host, atoi(port), username, password)))
#else
	if((err = connect_to_nessusd("localhost", 1, username, password)))
#endif	
	{
	 fprintf(stderr, "nessus : %s\n", err);
	 exit(0);
	}
	
	attack_host(target, Prefs);
	{
	 int finished = 0;
	 int type;
	 char * buf;
	 char * msg;
	 buf = emalloc(4096);
	 msg = emalloc(4096);
	 Hosts = emalloc(sizeof(struct arglist));
	 while(!finished)
	 {
	  network_gets(buf, 4095);
	  buf[strlen(buf)-1]=0;
	  if((type = parse_server_message(buf, Hosts, msg))==MSG_BYE)
	  	finished = 1;
	  bzero(msg, 4095);
	 }
	}
	arglist_to_file(Hosts, fname);
	exit(0);
	}
    default :
    	break;
    }
  }
  
  init_display(&argc, argv);
  F_nessusd_running = 0;
  
  /*
   * Set up the main window
   */
  prefs_dialog_setup(NULL, Prefs);
  
  
  /*
   * all the options have been taken in account... Now, the user may want us to
   * open a previously saved file
   */
  if(argc > 1)
  {
   int i;
   for(i=1;i<argc;i++)
   {
   char * fname = emalloc(strlen(argv[i])+1);
   struct arglist * h = emalloc(sizeof(struct arglist));
   
   strncpy(fname, argv[i], strlen(argv[i]));
   file_to_arglist(h, fname);
   efree(&fname);
   report_tests(h);
   }
  }  
  
  gtk_main();
  shutdown(GlobalSocket,2);
  close_display();
  exit(0);
  return(0);
}

 
