modules/pc/protocol_config.c

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

FUNCTIONS

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.37 $
   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                              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 #include <stdio.h>
  41 #include <stdlib.h>
  42 /*** solaris' header file doesn't contain the crypt definition...
  43      #include <unistd.h> */
  44 
  45 extern char* crypt(const char *, const char *);   /* crypt stuff */
  46 #include <time.h>       /* Time stuff */
  47 #include <sys/ioctl.h>  /* Terminal control stuff */
  48 
  49 #include "thread.h"
  50 #include "constants.h"
  51 #include "properties.h"
  52 #include <glib.h>
  53 
  54 #include "sk.h"
  55 #include "ta.h"
  56 
  57 #include "ut_string.h"
  58 #include "memwrap.h"
  59 
  60 #include "pc_commands.h"
  61 
  62 #define PC_IMPL
  63 #include "protocol_config.h"
  64 
  65 
  66 /*++++++++++++++++++++++++++++++++++++++
  67   
  68   Finds a command by name in the array of command function structures.
  69 
  70   int find_command     returns the index to the correct row of the array, or -1
  71                        if the command could not be found.
  72 
  73   char *comm_name      name of the command
  74 
  75   Command *comm        array of command function structures.
  76   ++++++++++++++++++++++++++++++++++++++*/
  77 static 
  78 int find_command(char *comm_name, Command *comm) 
     /* [<][>][^][v][top][bottom][index][help] */
  79 {
  80   int i;
  81   char *comm_buffer = wr_string(comm_name);
  82   char *token, *cursor;
  83   int index = -1;
  84   
  85   cursor = comm_buffer;
  86   if( (token = strsep(&cursor, " \t")) != NULL) {
  87     for (i=0; comm[i].name != NULL; i++) {
  88       if ( strcmp(token, comm[i].name) == 0) {
  89         index = i;
  90         break;
  91       }
  92     }
  93   }
  94   
  95   wr_free(comm_buffer);
  96 
  97   return index; /* returns -1 when command not found */
  98 } /* find_command() */
  99 
 100 
 101 int show_commands(Command *comm, char *comm_name, GString *output) 
     /* [<][>][^][v][top][bottom][index][help] */
 102 {
 103   int i = 0;
 104 
 105   g_string_sprintfa(output, "%scommands are:\n\n", comm_name);
 106   while (comm[i].name != NULL) {
 107     g_string_sprintfa(output, "%s\t%s\n", comm[i].name, comm[i].help);
 108     i++;
 109   }
 110 
 111   return 1;
 112 } /* show_commands() */
 113 
 114 
 115 /*++++++++++++++++++++++++++++++++++++++
 116 
 117   int command_execute 
 118                       executes a command from the given array, matching
 119                       given name. Passes input, output and condat to the
 120                       function found in the array. Command name is 
 121                       removed from the input line so only next words are
 122                       passed over to the function. 
 123 
 124                       returns the code of the last command. Code 
 125                       PC_RET_QUIT is reserved to indicate that the connection
 126                       should be closed.
 127 
 128   Command *comm       array of command function structures (defined in
 129                       protocol_config.h)
 130 
 131   char *comm_name     name of the command to be run
 132 
 133   char *input         rest of the command line
 134 
 135   GString *output     dynamically built output string
 136 
 137   sk_conn_st *condat  socket structure for this connection (some commands
 138                       use it directly instead of storing the output)
 139 
 140   ++++++++++++++++++++++++++++++++++++++*/
 141 int command_execute(Command *comm, char *comm_name,
     /* [<][>][^][v][top][bottom][index][help] */
 142                     char *input, GString *output, sk_conn_st *condat) 
 143 { 
 144   char *name, *next_word, *tmp_input;
 145   int index, result=0;
 146 
 147   /* find the command in the string - first whitespace delimited word */
 148   /* make a copy of the input */
 149   dieif( (tmp_input = wr_string(input)) == NULL );  
 150   next_word = tmp_input;
 151   
 152   /* find the first word and set the pointer to the rest of the string */
 153   name = strsep(&next_word, " \t");
 154   
 155   if( name != NULL && strlen(name) != 0 ) {
 156     index = find_command(name, comm);
 157     if( index != -1 ) {
 158       if( next_word != NULL ) {
 159         /* advance the input pointer to the next word */
 160         while(  *next_word != '\0' 
 161                 && isspace( *(unsigned char *)next_word) ) {
 162           next_word++;
 163         }
 164       }
 165       else {
 166         next_word = "";
 167       }
 168       
 169       /* run, Forrest, run...*/
 170       result = comm[index].function(next_word, output, condat);
 171     }
 172     else {          
 173       g_string_sprintfa(output, "invalid %scommand: %s\n", comm_name, name);
 174       show_commands(comm, comm_name, output);
 175       result = 2;
 176     }
 177   }  
 178   else {  
 179     show_commands(comm, comm_name, output);
 180     result = 2;
 181   }
 182   
 183   free(tmp_input);
 184 
 185   return result;
 186 } /* command_execute() */
 187 
 188  
 189 
 190 
 191 
 192 
 193 
 194 /* proces_input() */
 195 /*++++++++++++++++++++++++++++++++++++++
 196 
 197   Process the input. Finds the proper command in the top level command
 198   array and invokes the function associated with it with the input and
 199   output data as arguments.
 200 
 201   int process_input          returns 1 if the connection is to be kept
 202                              or 0 when it should be finished - that is, 
 203                              when command_execute() returns PC_RET_QUIT.
 204 
 205   char *input                input (presumably a command)
 206 
 207   sk_conn_st *condat         connection data    
 208 
 209   More:
 210   +html+ <PRE>
 211   Author:
 212         ottrey
 213         marek - changes and documentation.
 214   +html+ </PRE>
 215   ++++++++++++++++++++++++++++++++++++++*/
 216 static 
 217 int process_input(char *input, sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 218 {
 219   int  index;
 220   int res=0;
 221   GString *output = g_string_new("");
 222 
 223   index = find_command(input, command);
 224 
 225   switch (index) {
 226   case -1:
 227     /* Command not found */
 228     command_help(NULL, output, condat);
 229     break;
 230     
 231   default: 
 232     res = command_execute(command, "", input, output, condat);
 233   }
 234   
 235   if(res != PC_RET_QUIT) {
 236     /*
 237       printf("thread output=\n%s\n", output);
 238     */
 239     if ( CO_get_clear_screen() == 1 ) {
 240       SK_cd_puts(condat, CLEAR_SCREEN);
 241     }
 242     SK_cd_puts(condat,  output->str);
 243     SK_cd_printf(condat, "\n\n=%d= %s", res, CO_get_prompt());
 244     
 245   }
 246   
 247   g_string_free( output, TRUE );
 248 
 249   /* the return value is the connection state: 1=still open, 0=to be closed
 250    */
 251 
 252   return (res != PC_RET_QUIT);
 253 } /* process_input() */
 254 
 255 
 256 /*++++++++++++++++++++++++++++++++++++++
 257   
 258   Authenticates the user - asks for password and checks it. The password is
 259   echoed by the tcp stack, to disable that one would have to attach a tty
 260   to this connection and switch to raw mode or try the hard way - renegotiate
 261   the telnet connection to switch to character mode (and, possibly, back).
 262   The latter has the drawback that to do it right it has to be able to check
 263   whether there's telnet on the other side - otherwise, if the connection
 264   is made by a program just connecting to the socket, garbage will result.
 265   However, in such case password checking might be not a good idea.
 266 
 267   sk_conn_st *condat
 268 
 269   More:
 270   +html+ <PRE>
 271   Author:
 272         ottrey
 273         marek - slight changes and documentation.
 274   +html+ </PRE>
 275   ++++++++++++++++++++++++++++++++++++++*/
 276 static 
 277 char *authenticate_user(sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 278 {
 279   char *user = NULL;
 280   const char Salt[2] = "DB";
 281   char input[MAX_INPUT_SIZE];
 282   int read_result;
 283   char *password=NULL;
 284   char *user_password=NULL;
 285   char user_buf[10];
 286 
 287   SK_cd_puts(condat, LOGIN_PROMPT);
 288   read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
 289 
 290   strncpy(user_buf, input, 10);
 291 
 292   SK_cd_puts(condat, PASSWD_PROMPT);
 293   /* XXX These aren't working.
 294   SK_puts(sock, ECHO_ON);
 295   echo_off(sock);
 296   */
 297   read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
 298   /* XXX These aren't working.
 299   echo_on(sock);
 300   SK_puts(sock, ECHO_OFF);
 301   */
 302 
 303   password = crypt(input, Salt);
 304 
 305   user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
 306 
 307   if (user_password != NULL) {
 308     if (strcmp(password, user_password) == 0) {
 309       /*user = (char *)calloc(1, strlen(user_buf)+1);*/
 310       dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);  
 311       strcpy(user, user_buf);
 312     }
 313   }
 314 
 315   
 316   return user;
 317 
 318 } /* authenticate_user() */
 319 
 320 
 321 
 322 /*++++++++++++++++++++++++++++++++++++++
 323   
 324   Main function that talks to the user connected on the given socket.
 325   Starts by authenticating the user (if this mode is active)
 326   and greeting her with the uptime data. Then it loops reading and executing
 327   commands until the "quit" command (or any other command that causes
 328   process_input to return 0).
 329 
 330   int sock        connected client socket
 331 
 332   ++++++++++++++++++++++++++++++++++++++*/
 333 void PC_interact(int sock) {
     /* [<][>][^][v][top][bottom][index][help] */
 334   char input[MAX_INPUT_SIZE];
 335   int connected = 1;
 336   char *user=NULL;
 337   sk_conn_st condat;
 338 
 339   memset( &condat, 0, sizeof(condat));
 340   condat.sock = sock;
 341   SK_getpeerip(sock, &(condat.rIP));
 342   condat.ip = SK_getpeername(sock); /* XXX *alloc involved */
 343   
 344   /* Welcome the client */
 345   SK_cd_puts(&condat, CO_get_welcome());
 346 
 347   /* Authenticate the user */
 348   if (CO_get_authenticate() == 1) {
 349     user = authenticate_user(&condat);
 350 
 351     if (user == NULL) {
 352       ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
 353                 "unsuccesful login attempt from %s", condat.ip );
 354     }
 355   }
 356   else {
 357     user="nobody";
 358   }
 359 
 360   if (user != NULL) {    
 361 
 362     /* Log admin logging on */
 363     ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
 364                 "user %s from %s logged on", user, condat.ip );
 365     
 366     {
 367       show_uptime("", NULL, &condat);
 368     }
 369     
 370     SK_cd_printf(&condat, "=0= %s", CO_get_prompt());
 371 
 372     while (condat.rtc==0 && connected) {
 373       char *icopy;
 374       
 375       /* Read input. Quit if no input (socket closed) */
 376       if( SK_cd_gets(&condat, input, MAX_INPUT_SIZE) <= 0 ) {
 377         break;
 378       }
 379 
 380       /* filter junk out: leading/trailing/redundant whitespaces */
 381       icopy = ut_string_compress( input );
 382       
 383       /* set thread accounting */
 384       TA_setactivity(icopy);
 385       TA_increment();
 386       
 387       /*      if( strlen(icopy) > 0 ) {*/
 388       {
 389         ER_inf_va(FAC_PC, ASP_PC_I_COMMAND, icopy);
 390                   
 391         connected = process_input(icopy, &condat);
 392       }
 393       
 394       TA_setactivity("");
 395       
 396       free(icopy);
 397     }
 398     
 399     /* Log admin logging off */
 400     ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
 401                 "user %s from %s logged off", user, condat.ip );
 402     
 403   }
 404   
 405   wr_free(condat.ip);
 406 } /* PC_interact() */
 407 

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