Logo Search packages:      
Sourcecode: nessus-core version File versions

ntp_11.c

/* Nessus
 * Copyright (C) 1998 - 2004 Renaud Deraison
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation
 *
 * 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.
 *
 *
 * Nessus Communication Manager -- it manages the Nessus Transfer Protocol, 
 * version 1.1 and 1.2
 *
 */ 
 
#include <includes.h>
#include <corevers.h>
#ifdef USE_AF_UNIX
#undef NESSUS_ON_SSL
#endif


#include "ntp.h"
#include "ntp_11.h"
#include "comm.h"
#include "auth.h"
#include "rules.h"
#include "log.h"
#include "users.h"
#include "utils.h"
#include "pluginupload.h"
#include "save_tests.h"
#include "detached.h"
#include "preferences.h"
#include "hosts.h"

#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x):(y))
#endif


#ifndef DEBUG_SSL
# define DEBUG_SSL      1
#endif


static int ntp_11_prefs(struct arglist *);
static int ntp_11_read_prefs(struct arglist *);
static void ntp_11_send_prefs_errors(struct arglist *);
static int ntp_11_rules(struct arglist *);
static int ntp_11_new_attack(struct arglist *, char *);
static int ntp_11_long_attack(struct arglist *, char *);
static int ntp_11_recv_file(struct arglist*);

#ifdef ENABLE_SAVE_TESTS
static int ntp_11_list_sessions(struct arglist*);
static int ntp_11_delete_session(struct arglist*, char*);
static int ntp_11_restore_session(struct arglist*, char*);

static int ntp_11_list_detached_sessions(struct arglist *, char *);
static int ntp_11_stop_detached_session(struct arglist*, char*);
#endif
/*
 * Parses the input sent by the client before
 * the NEW_ATTACK message.
 */
int ntp_11_parse_input(globals, input)
   struct arglist * globals;
   char * input;
{
 char * str;
 int input_len = strlen(input);
 char * orig = emalloc(input_len + 1);

 strncpy(orig, input, input_len);
 
 str = strstr(input, " <|> ");
 if( str == NULL )
      {
      efree(&orig);
      return 1;
      }

 str[0] = '\0';
 if( strcmp(input, "CLIENT") == 0 )
 {
  input = str + 5;
  str = strchr(input, ' ');
  if(str != NULL )
      str[0] = '\0';

  if(input[strlen(input) - 1] == '\n')
      input[strlen(input) - 1] = '\0';
  
#ifdef ENABLE_SAVE_TESTS
  if(!strcmp(input, "SESSIONS_LIST")){
      ntp_11_list_sessions(globals);
      efree(&orig);
      return 1;
      }
  if(!strcmp(input, "SESSION_DELETE")) {
      ntp_11_delete_session(globals, orig);
      efree(&orig);
      return 1;
      }
      
  if(!strcmp(input, "SESSION_RESTORE")) {
       int n = ntp_11_restore_session(globals, orig);
       efree(&orig);
       return n;
      }
      
  if(!strcmp(input, "STOP_DETACHED")) {
      ntp_11_stop_detached_session(globals, orig);
      efree(&orig);
      return 1;
      }
  if(!strcmp(input, "NESSUS_VERSION")) {
      auth_printf(globals, "SERVER <|> NESSUS_VERSION <|> %s <|> SERVER\n", NESSUS_VERSION);
      return 1;
      }
  if(!strcmp(input, "ATTACHED_FILE")) {
      ntp_11_recv_file(globals);
      efree(&orig);
      return 1;
      }
  if(!strcmp(input, "ATTACHED_PLUGIN")) {
      plugin_recv(globals);
      return 1;
      }
  if(!strcmp(input, "PLUGIN_INFO")) {
      char * t, *s;
      t = strstr(&(str[1]), " <|> ");
      if( t == NULL )
            return -1;

      s = t + 5;
      plugin_send_infos(globals, atoi(s));
      return 1;
      }
  if(!strcmp(input, "DETACHED_SESSIONS_LIST")) {
      ntp_11_list_detached_sessions(globals, orig);
      efree(&orig);
      return 1;
      }
#endif
  if(!strcmp(input, "LONG_ATTACK")){
      int code = ntp_11_long_attack(globals, orig);
      efree(&orig);
      return code;
      }
  if(!strcmp(input, "PREFERENCES")){
      ntp_11_prefs(globals);
      efree(&orig);
        return 1;
        }
  if(!strcmp(input, "RULES")){
      ntp_11_rules(globals);
      efree(&orig);
        return 1;
        }
  if(!strcmp(input, "HUP_FATHER")) {
            if(preferences_user_is_admin(globals, arg_get_value(globals,
            "preferences")))
                  kill(getppid(), SIGHUP);
            return 1;
  }
  if(!strcmp(input, "NEW_ATTACK")){
            int n = ntp_11_new_attack(globals, orig);
            efree(&orig);
            return n;
  }
  if(!strcmp(input, "STOP_WHOLE_TEST")){
            log_write("Stopping the whole test (requested by client)");
            hosts_stop_all();
            efree(&orig);
            return NTP_STOP_WHOLE_TEST;
            }
  if(!strcmp(input, "STOP_ATTACK")) {
            char * t, *s;
            char * user = (char*)arg_get_value(globals, "user");
            s = str + 5;      
            t = strstr(s, " <|> ");
            if(t == NULL)
             return -1;
            t[0] = '\0';
            log_write("user %s : stopping attack against %s\n",  user, s);
            hosts_stop_host(globals, s);
            ntp_1x_timestamp_host_scan_interrupted(globals, s);
            ntp_11_show_end(globals, s, 0);
            }
            
  efree(&orig);
  return 1;
 }
 efree(&orig);
 return 1;
}

static int 
ntp_11_long_attack(globals, orig)
 struct arglist * globals;
 char * orig;
{
 struct arglist * preferences = arg_get_value(globals, "preferences");
 int soc = (int)arg_get_value(globals, "global_socket");
 char input[16384];
 int size;
 char * target;
 char * plugin_set;
 int n;
 
  n = recv_line(soc, input, sizeof(input) - 1);
  if(n <= 0)
   return -1;
   
#if DEBUGMORE
  printf("long_attack :%s\n", input);
#endif
  if(!strncmp(input, "<|> CLIENT", sizeof("<|> CLIENT")))
   return 1; 
  size = atoi(input);
  target = emalloc(size+1);
  
  n = 0;
  while(n < size)
  {
   int e;
   e = nrecv(soc, target+n, size-n, 0);
   if(e > 0)n+=e;
   else return -1;
  }
 plugin_set = arg_get_value(preferences, "plugin_set");
 if(!plugin_set || plugin_set[0] == '\0' )
 {
  plugin_set = emalloc(3);
  sprintf(plugin_set, "-1");
  if(!arg_get_value(preferences, "plugin_set")) 
   arg_add_value(preferences, "plugin_set", ARG_STRING, strlen(plugin_set), plugin_set);
  else
   arg_set_value(preferences, "plugin_set", strlen(plugin_set), plugin_set);
 }
 
 comm_setup_plugins(globals, plugin_set);
 if(arg_get_value(preferences, "TARGET"))
  {
  char * old = arg_get_value(preferences, "TARGET");
  efree(&old);
  arg_set_value(preferences, "TARGET", strlen(target), target);
  }
 else
  arg_add_value(preferences, "TARGET", ARG_STRING, strlen(target), target);
 return 0;
} 
static int ntp_11_prefs(globals)
 struct arglist * globals;
{
 int problem;
 ntp_caps * caps;
 struct arglist * prefs;
 char * value;

 problem = ntp_11_read_prefs(globals);
 if(!problem)ntp_11_send_prefs_errors(globals);
 caps = arg_get_value(globals, "ntp_caps");
 prefs = arg_get_value(globals, "preferences");
 value = arg_get_value(prefs, "ntp_escape_crlf");
 if(value)caps->escape_crlf = 1;
 return(problem);
}



static int 
ntp_11_read_prefs(globals)
 struct arglist * globals;
{
 struct arglist *  preferences = arg_get_value(globals, "preferences");
 int soc = (int)arg_get_value(globals, "global_socket");
 char * input;
 int input_sz = 65535;
 int n;

 input = emalloc(input_sz);
 for (;;) {
   bzero(input, input_sz);
#if defined NESSUS_ON_SSL && DEBUG_SSL > 2
   fprintf(stderr, "ntp_11_read_prefs > soc=%d\n", soc);
#endif
   n = recv_line (soc, input, input_sz - 1);

  if (n < 0 || input [0] == '\0') {
    log_write ("Empty data string -- closing comm. channel\n");
    EXIT(0);
  }

  if(strstr(input, "<|> CLIENT") != NULL ) /* finished = 1; */
    break ;
  /* else */
  
  {
   char * pref;
   char * value;
   char * v;
   char * old;
    pref = input;
    v = strchr(input, '<');
    if(v)
    { v-=1;
      v[0] = 0;
    
      value = v + 5;
      /*
       * "system" prefs can't be changed
       */
      if(!strcmp(pref, "logfile")           ||
         !strcmp(pref, "config_file")       ||
         !strcmp(pref, "plugins_folder")    ||
       !strcmp(pref, "dumpfile")          ||
       !strcmp(pref, "users")             ||
       !strcmp(pref, "rules")             ||
       !strncmp(pref, "peks_", 5)         ||
       !strcmp(pref, "negot_timeout")     ||
       !strcmp(pref, "cookie_logpipe")    ||
       !strcmp(pref, "force_pubkey_auth") ||
       !strcmp(pref, "log_while_attack")  ||
       !strcmp(pref, "ca_file")         ||
       !strcmp(pref, "key_file")        ||
       !strcmp(pref, "cert_file")       ||
       !strcmp(pref, "be_nice")         ||
       !strcmp(pref, "log_plugins_name_at_load") ||
       !strcmp(pref, "plugin_upload")     ||
       !strcmp(pref, "plugin_upload_suffixes") ||
       !strcmp(pref, "admin_user") ||
         !strcmp(pref, "nasl_no_signature_check"))
            continue;
      
      old = arg_get_value(preferences, pref);
#ifdef DEBUGMORE     
      printf("%s - %s (old : %s)\n", pref, value, old);
#endif     
      if ( value[0] != '\0' )value[strlen(value)-1]='\0';
    
      if( old != NULL )
      {
       if( strcmp(old, value) != 0 )
        {
       efree(&old); 
         v = estrdup(value);
       arg_set_value(preferences, pref, strlen(v), v);
      }
      }
      else
      {
       v = estrdup(value);
       arg_add_value(preferences, pref, ARG_STRING, strlen(v), v);
      }
    }
  }
 }

 efree(&input);
 return(0);
}


static void ntp_11_send_prefs_errors(globals)
 struct arglist * globals;
{
 /* not implemented yet */
 auth_printf(globals, "SERVER <|> PREFERENCES_ERRORS <|>\n");
 auth_printf(globals, "<|> SERVER\n");
}



static int 
ntp_11_rules(globals)
 struct arglist * globals;
{
 struct nessus_rules * user_rules = emalloc(sizeof(*user_rules));
 struct nessus_rules * rules = arg_get_value(globals, "rules");
 char * buffer;
 int finished = 0;
 struct sockaddr_in * soca;
 
 buffer = emalloc(4096); 
 while(!finished)
 {
  auth_gets(globals, buffer, 4095);
  if( buffer[0] == '\0' )
    {
      log_write("Empty buffer - exiting\n");
      EXIT(0);
    }

  if( strstr(buffer, "<|> CLIENT") != NULL )
      finished = 1;
  else 
  {
#ifdef DEBUG_RULES
    printf("User adds %s\n", buffer);
#endif
    users_add_rule(user_rules, buffer);
  }
 }
 efree(&buffer);
 rules_add(&rules, &user_rules, arg_get_value(globals, "user"));
 rules_free(user_rules);
 soca = arg_get_value(globals, "client_address");
 rules_set_client_ip(rules, soca->sin_addr);
 arg_set_value(globals, "rules", -1, rules);
 return(0);
}



static int ntp_11_new_attack(globals, input)
        struct arglist * globals;
      char * input;
      
{
 char * target = emalloc(strlen(input)+1);
 char * clean_target;
 char * plugin_set;
 struct arglist * preferences = arg_get_value(globals, "preferences");
 int len;
 
 sscanf(input, "CLIENT <|> NEW_ATTACK <|> %s <|> CLIENT\n", target);
 if(target[0] == '\0'){
  efree(&target);
  return(1);
 }
 len = strlen(target);
 clean_target = emalloc(len+1);
 strncpy(clean_target, target, len);
 plugin_set = arg_get_value(preferences, "plugin_set");
 if(!plugin_set || plugin_set[0] == '\0')
 {
  if(plugin_set != NULL)
   efree(&plugin_set);
  
  plugin_set = emalloc(3);
  sprintf(plugin_set, "-1");
  if( arg_get_value(preferences, "plugin_set") == NULL ) 
   arg_add_value(preferences, "plugin_set", ARG_STRING, strlen(plugin_set), plugin_set);
  else
   arg_set_value(preferences, "plugin_set", strlen(plugin_set), plugin_set);
 }
 comm_setup_plugins(globals, plugin_set);
 if(arg_get_value(preferences, "TARGET"))
  arg_set_value(preferences, "TARGET", strlen(clean_target), clean_target);
 else
  arg_add_value(preferences, "TARGET", ARG_STRING, strlen(clean_target), clean_target);
 efree(&target);
 return(0);
}


void 
ntp_11_show_end(globals, name, internal)
 struct arglist*  globals;
 char * name;
 int internal;
{ 
 int soc = (int)arg_get_value( globals, "global_socket");
 char buf[1024];
 snprintf(buf, sizeof(buf), "SERVER <|> FINISHED <|> %s <|> SERVER\n", name);
 if ( internal )
      internal_send(soc, buf, INTERNAL_COMM_MSG_TYPE_DATA);
 else
      auth_printf(globals, "%s", buf);
}


static void
files_add_translation(globals, remotename, localname)
 struct arglist * globals;
 char * remotename;
 char * localname;
{
 harglst * trans = arg_get_value(globals, "files_translation");
#if 0
 fprintf(stderr, "files_add_translation: R=%s\tL=%s\n", remotename, localname);
#endif
 if( trans == NULL )
 {
  trans = harg_create(10);
  arg_add_value(globals, "files_translation", ARG_PTR, -1, trans);
 }
 
 if( harg_get_string(trans, remotename) == NULL )
      harg_add_string(trans, remotename, localname);
 else
      harg_set_string(trans, remotename, localname);
}



int
ntp_11_recv_file(globals)
 struct arglist * globals;
{
 int soc = (int)arg_get_value(globals, "global_socket");
 char input[4096];
 char * origname, * localname = temp_file_name();
 int n;
 long bytes = 0;
 long tot = 0;
 int fd;
 
#if 0
 fprintf(stderr, "ntp_11_recv_file\n");
#endif
 n = recv_line(soc, input, sizeof(input) - 1);
 if(n <= 0)
  return -1;
  
 if( strncmp(input, "name: ", strlen("name: ")) == 0 )
 {
  origname = estrdup(input + sizeof("name: ")-1);
  if(origname[strlen(origname) - 1] == '\n')
   origname[strlen(origname) - 1] = '\0';
 }
 else 
   return -1;
 
 n = recv_line(soc, input, sizeof(input) - 1);
 if(n <= 0)
  return -1;
 /* XXX content: message. Ignored for the moment */
 
 n = recv_line(soc, input, sizeof(input) - 1);
 if(n <= 0)

  return -1;
  
 if( strncmp(input, "bytes: ", sizeof("bytes: ")-1) == 0 )
 {
  char * t = input + sizeof("bytes: ")-1;
  bytes = atol(t);
 }
 else 
  return -1;
  
 /*
  * Ok. We now know that we have to read <bytes> bytes from the
  * remote socket.
  */
  
  fd = open(localname, O_CREAT|O_WRONLY|O_TRUNC, 0600);
  if(fd < 0)
  {
   perror("ntp_11_recv_file: open() ");
   return -1;
  }
#if 0
  fprintf(stderr, "ntp_11_recv_file: localname=%s\n", localname);
#endif  
  while(tot < bytes)
  {
   bzero(input, sizeof(input));
   n = nrecv(soc, input, MIN(sizeof(input)-1, bytes - tot), 0);
   if(n  < 0)
   {
     char   s[80];
     sprintf(s, "11_recv_file: nrecv(%d)", soc);
    perror(s);
    break;
   }
   else
   {
    write(fd, input, n);
    tot += n;
   }
  }
  /*
   * Add the fact that what the remote client calls
   * <filename> is actually <localname> here
   */
  auth_printf(globals, "SERVER <|> FILE_ACCEPTED <|> SERVER\n"); 
  files_add_translation(globals, origname, localname);
  efree(&localname);
  close(fd);
  return 0;
}
#ifdef ENABLE_SAVE_TESTS
static char*
extract_session_key_from_session_msg(globals, orig)
 struct arglist * globals;
 char * orig;
{
 char * t;
 int i, len;

 t = strrchr(orig, '<');
 if(!t)return NULL;
 t[0] = 0;
 
 t = strrchr(orig, '>');
 if(!t)return NULL;

 t++;
 while(t[0]==' ')t++;
 len = strlen(t);
 while(t[len-1]==' ')
  {
      t[len-1]= '\0';
      len --;
  } 
 /*
  * Sanity check. All sessions name are under the form
  * <year><month><day>-<hour><minute><second>
  * (ie: 20000718-124427). If we see something else, then
  * our current user is trying to do something evil. or something.
  */
 for(i=0;i<len;i++)
  if(!isdigit(t[i]) && t[i]!='-'){
      log_write("user %s : supplied an incorrect session name (%s)",
                  (char*)arg_get_value(globals, "user"),
                  t);
      return NULL;
      }
 return strdup(t);
 
}


static int
extract_detached_session_key_from_session_msg(globals, orig)
 struct arglist * globals;
 char * orig;
{
 char * t;
 int i, len;

 t = strrchr(orig, '<');
 if(!t)return -1;
 t[0] = 0;
 
 t = strrchr(orig, '>');
 if(!t)return -1;

 t++;
 while(t[0]==' ')t++;
 len = strlen(t);
 while(t[len-1]==' ')
 {
  t[len-1]=0;
  len --;
 }
 /*
  * Sanity check. All detached sessions name are under the form
  * of a pid.
  */
 for(i=0;i<len;i++)
  if(!isdigit(t[i])){
      log_write("user %s : supplied an incorrect detached session name (%s)",
                  (char*)arg_get_value(globals, "user"),
                  t);
      return -1;
      }
 return atoi(t);
}



static int
ntp_11_stop_detached_session(globals, orig)
 struct arglist * globals;
 char * orig;
{
 int session = 0;
 int ret;
 
 session = extract_detached_session_key_from_session_msg(globals, orig);
 if(session < 0)return -1;
 log_write("user %s : stopping session %d",
            (char*)arg_get_value(globals, "user"),
            session);
            
 ret = detached_delete_session(globals, session);
 return 0;
}

static int
ntp_11_list_detached_sessions(globals, orig)
 struct arglist * globals;
 char * orig;
{
 auth_printf(globals, "SERVER <|> DETACHED_SESSIONS_LIST\n");
 detached_send_sessions(globals);
 auth_printf(globals, "<|> SERVER\n");
 return 0;
}


static int
ntp_11_delete_session(globals, orig)
 struct arglist * globals;
 char * orig;
{
 char * session = NULL;
 int ret;
 
 session = extract_session_key_from_session_msg(globals, orig);
 if(!session)return -1;
  
 ret = save_tests_delete(globals, session);
 efree(&session);

 return ret;
}


static int
ntp_11_restore_session(globals, orig)
 struct arglist * globals;
 char * orig;
{
 char * session;
 
 session = extract_session_key_from_session_msg(globals, orig);
 if(!session)return -1;
 
 save_tests_setup_playback(globals, session);
 efree(&session);
 return 0;
}

static int 
ntp_11_list_sessions(globals)
 struct arglist * globals;
{
 auth_printf(globals, "SERVER <|> SESSIONS_LIST\n");
 save_tests_send_list(globals);
 auth_printf(globals, "<|> SERVER\n");
 return 0;
}

#endif /* ENABLE_SAVE_TESTS */


/*----------------------------------------------------------

   Communication protocol: timestamps
 
 ----------------------------------------------------------*/


static int
__ntp_1x_timestamp_scan(globals, msg)
 struct arglist * globals;
 char * msg;
{
 ntp_caps * caps = arg_get_value(globals, "ntp_caps");
 if(caps->timestamps)
  {
  char timestr[1024];
  char * tmp;
  time_t t;
  int len;
  
  t = time(NULL);
  tmp = ctime(&t);
  timestr[sizeof ( timestr ) - 1 ] = '\0';
  strncpy(timestr, tmp, sizeof(timestr) - 1);
  len = strlen(timestr);
  if( timestr[len - 1 ] == '\n' )
         timestr[len - 1 ] = '\0';

  auth_printf(globals, "SERVER <|> TIME <|> %s <|> %s <|> SERVER\n",msg, timestr);
  }
  return 0;
}


static int
__ntp_1x_timestamp_scan_host(globals, msg, host)
 struct arglist * globals;
 char * msg;
 char * host;
{
 ntp_caps * caps = arg_get_value(globals, "ntp_caps");
 if(caps->timestamps)
  {
  char timestr[1024];
  char * tmp;
  time_t t;
  int len;
  char buf[1024];
  int soc;
  
  t = time(NULL);
  tmp = ctime(&t);
  timestr [ sizeof(timestr) - 1] = '\0';
  strncpy(timestr, tmp, sizeof(timestr) - 1);
  len = strlen(timestr);
  if( timestr[len - 1 ] == '\n' )
         timestr[len - 1 ] = '\0';

   soc = (int)arg_get_value(globals, "global_socket");
   
   snprintf(buf, sizeof(buf), "SERVER <|> TIME <|> %s <|> %s <|> %s <|> SERVER\n", msg, host, timestr);
   
   internal_send(soc, buf, INTERNAL_COMM_MSG_TYPE_DATA); 
  }
  return 0;
}



int
ntp_1x_timestamp_scan_starts(globals)
 struct arglist * globals;
{
 return __ntp_1x_timestamp_scan(globals, "SCAN_START");
}

int
ntp_1x_timestamp_scan_ends(globals)
 struct arglist * globals;
{
 return __ntp_1x_timestamp_scan(globals, "SCAN_END");
}

int
ntp_1x_timestamp_host_scan_starts(globals, host)
 struct arglist * globals;
 char * host;
{
 return __ntp_1x_timestamp_scan_host(globals, "HOST_START", host);
}
 

int
ntp_1x_timestamp_host_scan_ends(globals, host)
      struct arglist * globals;
      char * host;
{
 return __ntp_1x_timestamp_scan_host(globals, "HOST_END", host);
}

int
ntp_1x_timestamp_host_scan_interrupted(globals, host)
      struct arglist * globals;
      char * host;
{
 return __ntp_1x_timestamp_scan_host(globals, "HOST_INTERRUPTED", host);
}





/*--------------------------------------------------------------------------------------------*/
static int qsort_cmp( const void * a, const void * b )
{
 struct arglist ** plugin_a, ** plugin_b;

 plugin_a = (struct arglist ** ) a;
 plugin_b = (struct arglist ** ) b;

 return strcmp((*plugin_a)->name, (*plugin_b)->name);
}


static char * _find_plugin(struct arglist ** array, char * fname, int start, int end, int rend )
{
 int mid;
 struct arglist * plugin;
 int e;

 if ( start >= rend )
      return NULL;

 if ( start == end )
 {
  plugin = array[start];
 
  if ( strcmp(fname, plugin->name) == 0 )
      return plug_get_name(plugin->value);
   else
      return NULL;
 }

 mid = ( start + end ) / 2;
 plugin = array[mid];
 e = strcmp( plugin->name, fname );
 if ( e > 0 )
      return _find_plugin(array, fname, start, mid, rend);
  else if ( e < 0 )
      return _find_plugin(array, fname, mid + 1, end, rend);
 else
      return plug_get_name(plugin->value);
}



static char * find_plugin(struct arglist ** array, char * fname, int num_plugins )
{
 return _find_plugin ( array, fname, 0, num_plugins, num_plugins);
}


int 
ntp_1x_send_dependencies(globals)
      struct arglist * globals;
{
 struct arglist * p = arg_get_value(globals, "plugins");
 struct arglist * plugins = p;
 struct arglist ** array;
 int num_plugins = 0;
 char * buf;
 int buf_size = 1024;
 int i = 0;


 if(plugins == NULL)
 {
  fprintf(stderr, "%s:%d: no plugins\n", __FILE__, __LINE__);
  return -1;
 }
 
 while ( p->next != NULL ) 
 {
   num_plugins ++;
   p = p->next;
 }

 /* Store the plugins in an array index by filename */
 array = emalloc ( num_plugins * sizeof(struct arglist * ));
 p = plugins;
 while ( p->next != NULL )
 {
   array[i++] = p;
   p = p->next;
 }

 qsort ( array, num_plugins, sizeof(struct arglist *), qsort_cmp);
 
 auth_printf(globals, "SERVER <|> PLUGINS_DEPENDENCIES\n");
  
 buf = emalloc(buf_size);
 
 while(plugins->next)
 {
  struct arglist * args = plugins->value;
  struct arglist * d, * deps;
  if(!args)
      goto nxt;
  
  d = deps = plug_get_deps(args);
  if(deps == NULL )
    goto nxt;
      
 
  strncat(buf, plug_get_name(args), buf_size);
  strncat(buf, " <|> ", buf_size);
  while(deps->next)
  {
   char * fname = find_plugin(array, deps->name, num_plugins);
   if( fname == NULL )
   {
    deps = deps->next;
    continue;
   }
   if(strlen(fname) + strlen(buf) + 6 > buf_size)
   {
    buf_size *= 2;
    buf = erealloc(buf, buf_size);
   }
   strncat(buf, fname, buf_size);
   strncat(buf, " <|> ", buf_size);
   deps = deps->next;
  }
  arg_free_all(d);
  
  auth_printf(globals, "%s\n", buf);
   
  nxt: 
      bzero(buf, buf_size);
      plugins = plugins->next;
 }
 auth_printf(globals, "<|> SERVER\n");
 efree(&buf);
 efree(&array);
 return 0;
}

Generated by  Doxygen 1.6.0   Back to index