modules/pc/protocol_config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. find_command
  2. show_commands
  3. command_execute
  4. process_input
  5. authenticate_user
  6. PC_interact

   1 /***************************************
   2   $Revision: 1.39 $
   3 
   4   Protocol config module (pc).  This is the protocol that the admin uses to
   5   talk to the server.
   6 
   7   Status: NOT REVUED, NOT TESTED
   8 
   9   ******************/ /******************
  10   Filename            : protocol_config.c
  11   Authors             : ottrey@ripe.net - initial design
  12                         marek@ripe.net - restructured and rewritten
  13 
  14   To Do               : Add a facility to take callbacks instead of
  15                         hard-coding menu options.
  16                         Add in all the menu support provided by the GLib
  17                         libraries.
  18                         (Remove strtok if multiple threads are to be used.)
  19                         use gnu readline with expansion and history
  20   ******************/ /******************
  21   Copyright (c) 1999,2000,2001,2002               RIPE NCC
  22  
  23   All Rights Reserved
  24   
  25   Permission to use, copy, modify, and distribute this software and its
  26   documentation for any purpose and without fee is hereby granted,
  27   provided that the above copyright notice appear in all copies and that
  28   both that copyright notice and this permission notice appear in
  29   supporting documentation, and that the name of the author not be
  30   used in advertising or publicity pertaining to distribution of the
  31   software without specific, written prior permission.
  32   
  33   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  34   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  35   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  36   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  37   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  38   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  39   ***************************************/
  40 
  41 #define PC_IMPL
  42 #include "rip.h"
  43 
  44 #include <stdio.h>
  45 #include <stdlib.h>
  46 #include <time.h>
  47 #include <sys/ioctl.h>
  48 #include <glib.h>
  49 
  50 /*+ Maximum size of input that can be recieved from the client. +*/
  51 #define MAX_INPUT_SIZE  1024
  52 
  53 extern char* crypt(const char *, const char *);   /* crypt stuff */
  54 
  55 
  56 /*++++++++++++++++++++++++++++++++++++++
  57   
  58   Finds a command by name in the array of command function structures.
  59 
  60   int find_command     returns the index to the correct row of the array, or -1
  61                        if the command could not be found.
  62 
  63   char *comm_name      name of the command
  64 
  65   Command *comm        array of command function structures.
  66   ++++++++++++++++++++++++++++++++++++++*/
  67 static 
  68 int find_command(char *comm_name, Command *comm) 
     /* [<][>][^][v][top][bottom][index][help] */
  69 {
  70   int i;
  71   char *comm_buffer = wr_string(comm_name);
  72   char *token, *cursor;
  73   int index = -1;
  74   
  75   cursor = comm_buffer;
  76   if( (token = strsep(&cursor, " \t")) != NULL) {
  77     for (i=0; comm[i].name != NULL; i++) {
  78       if ( strcmp(token, comm[i].name) == 0) {
  79         index = i;
  80         break;
  81       }
  82     }
  83   }
  84   
  85   UT_free(comm_buffer);
  86 
  87   return index; /* returns -1 when command not found */
  88 } /* find_command() */
  89 
  90 
  91 int show_commands(Command *comm, char *comm_name, GString *output) 
     /* [<][>][^][v][top][bottom][index][help] */
  92 {
  93   int i = 0;
  94 
  95   g_string_sprintfa(output, "%scommands are:\n\n", comm_name);
  96   while (comm[i].name != NULL) {
  97     g_string_sprintfa(output, "%s\t%s\n", comm[i].name, comm[i].help);
  98     i++;
  99   }
 100 
 101   return 1;
 102 } /* show_commands() */
 103 
 104 
 105 /*++++++++++++++++++++++++++++++++++++++
 106 
 107   int command_execute 
 108                       executes a command from the given array, matching
 109                       given name. Passes input, output and condat to the
 110                       function found in the array. Command name is 
 111                       removed from the input line so only next words are
 112                       passed over to the function. 
 113 
 114                       returns the code of the last command. Code 
 115                       PC_RET_QUIT is reserved to indicate that the connection
 116                       should be closed.
 117 
 118   Command *comm       array of command function structures (defined in
 119                       protocol_config.h)
 120 
 121   char *comm_name     name of the command to be run
 122 
 123   char *input         rest of the command line
 124 
 125   GString *output     dynamically built output string
 126 
 127   sk_conn_st *condat  socket structure for this connection (some commands
 128                       use it directly instead of storing the output)
 129 
 130   ++++++++++++++++++++++++++++++++++++++*/
 131 int command_execute(Command *comm, char *comm_name,
     /* [<][>][^][v][top][bottom][index][help] */
 132                     char *input, GString *output, sk_conn_st *condat) 
 133 { 
 134   char *name, *next_word, *tmp_input;
 135   int index, result=0;
 136 
 137   /* find the command in the string - first whitespace delimited word */
 138   /* make a copy of the input */
 139   dieif( (tmp_input = wr_string(input)) == NULL );  
 140   next_word = tmp_input;
 141   
 142   /* find the first word and set the pointer to the rest of the string */
 143   name = strsep(&next_word, " \t");
 144   
 145   if( name != NULL && strlen(name) != 0 ) {
 146     index = find_command(name, comm);
 147     if( index != -1 ) {
 148       if( next_word != NULL ) {
 149         /* advance the input pointer to the next word */
 150         while(  *next_word != '\0' 
 151                 && isspace( *(unsigned char *)next_word) ) {
 152           next_word++;
 153         }
 154       }
 155       else {
 156         next_word = "";
 157       }
 158       
 159       /* run, Forrest, run...*/
 160       result = comm[index].function(next_word, output, condat);
 161     }
 162     else {          
 163       g_string_sprintfa(output, "invalid %scommand: %s\n", comm_name, name);
 164       show_commands(comm, comm_name, output);
 165       result = 2;
 166     }
 167   }  
 168   else {  
 169     show_commands(comm, comm_name, output);
 170     result = 2;
 171   }
 172   
 173   UT_free(tmp_input);
 174 
 175   return result;
 176 } /* command_execute() */
 177 
 178  
 179 
 180 
 181 
 182 
 183 
 184 /* proces_input() */
 185 /*++++++++++++++++++++++++++++++++++++++
 186 
 187   Process the input. Finds the proper command in the top level command
 188   array and invokes the function associated with it with the input and
 189   output data as arguments.
 190 
 191   int process_input          returns 1 if the connection is to be kept
 192                              or 0 when it should be finished - that is, 
 193                              when command_execute() returns PC_RET_QUIT.
 194 
 195   char *input                input (presumably a command)
 196 
 197   sk_conn_st *condat         connection data    
 198 
 199   More:
 200   +html+ <PRE>
 201   Author:
 202         ottrey
 203         marek - changes and documentation.
 204   +html+ </PRE>
 205   ++++++++++++++++++++++++++++++++++++++*/
 206 static 
 207 int process_input(char *input, sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 208 {
 209   int  index;
 210   int res=0;
 211   GString *output = g_string_new("");
 212 
 213   index = find_command(input, command);
 214 
 215   switch (index) {
 216   case -1:
 217     /* Command not found */
 218     command_help(NULL, output, condat);
 219     break;
 220     
 221   default: 
 222     res = command_execute(command, "", input, output, condat);
 223   }
 224   
 225   if(res != PC_RET_QUIT) {
 226     /*
 227       printf("thread output=\n%s\n", output);
 228     */
 229     if ( CO_get_clear_screen() == 1 ) {
 230       SK_cd_puts(condat, CLEAR_SCREEN);
 231     }
 232     SK_cd_puts(condat,  output->str);
 233     SK_cd_printf(condat, "\n\n=%d= %s", res, CO_get_prompt());
 234     
 235   }
 236   
 237   g_string_free( output, TRUE );
 238 
 239   /* the return value is the connection state: 1=still open, 0=to be closed
 240    */
 241 
 242   return (res != PC_RET_QUIT);
 243 } /* process_input() */
 244 
 245 
 246 /*++++++++++++++++++++++++++++++++++++++
 247   
 248   Authenticates the user - asks for password and checks it. The password is
 249   echoed by the tcp stack, to disable that one would have to attach a tty
 250   to this connection and switch to raw mode or try the hard way - renegotiate
 251   the telnet connection to switch to character mode (and, possibly, back).
 252   The latter has the drawback that to do it right it has to be able to check
 253   whether there's telnet on the other side - otherwise, if the connection
 254   is made by a program just connecting to the socket, garbage will result.
 255   However, in such case password checking might be not a good idea.
 256 
 257   sk_conn_st *condat
 258 
 259   More:
 260   +html+ <PRE>
 261   Author:
 262         ottrey
 263         marek - slight changes and documentation.
 264   +html+ </PRE>
 265   ++++++++++++++++++++++++++++++++++++++*/
 266 static 
 267 char *authenticate_user(sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 268 {
 269   char *user = NULL;
 270   const char Salt[2] = "DB";
 271   char input[MAX_INPUT_SIZE];
 272   int read_result;
 273   char *password=NULL;
 274   char *user_password=NULL;
 275   char user_buf[10];
 276 
 277   SK_cd_puts(condat, LOGIN_PROMPT);
 278   read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
 279 
 280   strncpy(user_buf, input, 10);
 281 
 282   SK_cd_puts(condat, PASSWD_PROMPT);
 283   /* XXX These aren't working.
 284   SK_puts(sock, ECHO_ON);
 285   echo_off(sock);
 286   */
 287   read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
 288   /* XXX These aren't working.
 289   echo_on(sock);
 290   SK_puts(sock, ECHO_OFF);
 291   */
 292 
 293   password = crypt(input, Salt);
 294 
 295   user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
 296 
 297   if (user_password != NULL) {
 298     if (strcmp(password, user_password) == 0) {
 299       user = UT_strdup(user_buf);
 300     }
 301   }
 302 
 303   
 304   return user;
 305 
 306 } /* authenticate_user() */
 307 
 308 
 309 
 310 /*++++++++++++++++++++++++++++++++++++++
 311   
 312   Main function that talks to the user connected on the given socket.
 313   Starts by authenticating the user (if this mode is active)
 314   and greeting her with the uptime data. Then it loops reading and executing
 315   commands until the "quit" command (or any other command that causes
 316   process_input to return 0).
 317 
 318   int sock        connected client socket
 319 
 320   ++++++++++++++++++++++++++++++++++++++*/
 321 void PC_interact(int sock) {
     /* [<][>][^][v][top][bottom][index][help] */
 322   char input[MAX_INPUT_SIZE];
 323   int connected = 1;
 324   char *user=NULL;
 325   sk_conn_st condat;
 326 
 327   memset( &condat, 0, sizeof(condat));
 328   condat.sock = sock;
 329   SK_getpeerip(sock, &(condat.rIP));
 330   condat.ip = SK_getpeername(sock); /* XXX *alloc involved */
 331   
 332   /* Welcome the client */
 333   SK_cd_puts(&condat, CO_get_welcome());
 334 
 335   /* Authenticate the user */
 336   if (CO_get_authenticate() == 1) {
 337     user = authenticate_user(&condat);
 338 
 339     if (user == NULL) {
 340       ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
 341                 "unsuccesful login attempt from %s", condat.ip );
 342     }
 343   }
 344   else {
 345     user="nobody";
 346   }
 347 
 348   if (user != NULL) {    
 349 
 350     /* Log admin logging on */
 351     ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
 352                 "user %s from %s logged on", user, condat.ip );
 353     
 354     {
 355       show_uptime("", NULL, &condat);
 356     }
 357     
 358     SK_cd_printf(&condat, "=0= %s", CO_get_prompt());
 359 
 360     while (condat.rtc==0 && connected) {
 361       char *icopy;
 362       
 363       /* Read input. Quit if no input (socket closed) */
 364       if( SK_cd_gets(&condat, input, MAX_INPUT_SIZE) <= 0 ) {
 365         break;
 366       }
 367 
 368       /* filter junk out: leading/trailing/redundant whitespaces */
 369       icopy = ut_string_compress( input );
 370       
 371       /* set thread accounting */
 372       TA_setactivity(icopy);
 373       TA_increment();
 374       
 375       /*      if( strlen(icopy) > 0 ) {*/
 376       {
 377         ER_inf_va(FAC_PC, ASP_PC_I_COMMAND, icopy);
 378                   
 379         connected = process_input(icopy, &condat);
 380       }
 381       
 382       TA_setactivity("");
 383       
 384       UT_free(icopy);
 385     }
 386     
 387     /* Log admin logging off */
 388     ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
 389                 "user %s from %s logged off", user, condat.ip );
 390     
 391   }
 392   
 393   UT_free(condat.ip);
 394 } /* PC_interact() */
 395 

/* [<][>][^][v][top][bottom][index][help] */