## 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] */