1    | /***************************************
2    |   $Revision: 1.29 $
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
12   |                         marek@ripe.net
13   |   To Do               : Add a facility to take callbacks instead of
14   |                         hard-coding menu options.
15   |                         Add in all the menu support provided by the GLib
16   |                         libraries.
17   |                         (Remove strtok if multiple threads are to be used.)
18   | 			use gnu readline with expansion and history
19   |   ******************/ /******************
20   |   Copyright (c) 1999                              RIPE NCC
21   |  
22   |   All Rights Reserved
23   |   
24   |   Permission to use, copy, modify, and distribute this software and its
25   |   documentation for any purpose and without fee is hereby granted,
26   |   provided that the above copyright notice appear in all copies and that
27   |   both that copyright notice and this permission notice appear in
28   |   supporting documentation, and that the name of the author not be
29   |   used in advertising or publicity pertaining to distribution of the
30   |   software without specific, written prior permission.
31   |   
32   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
33   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
34   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
35   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
36   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38   |   ***************************************/
39   | #include <stdio.h>
40   | #include <stdlib.h>
41   | /*** solaris' header file doesn't contain the crypt definition...
42   |      #include <unistd.h> */
43   | 
44   | extern char* crypt(const char *, const char *);   /* crypt stuff */
45   | #include <time.h>       /* Time stuff */
46   | #include <sys/ioctl.h>  /* Terminal control stuff */
47   | #include <termio.h>     /* Terminal control stuff */
48   | #include "thread.h"
49   | #include "constants.h"
50   | #include "properties.h"
51   | #include <glib.h>
52   | 
53   | #include "sk.h"
54   | #include "ta.h"
55   | 
56   | #include "pc_commands.h"
57   | 
58   | #define PC_IMPL
59   | #include "protocol_config.h"
60   | 
61   | static 
62   | int find_command(char *comm_name, Command *comm) 
63   | {
64   |   int i;
65   |   char *comm_buffer = wr_string(comm_name);
66   |   char *token, *cursor;
67   |   int index = -1;
68   |   
69   |   cursor = comm_buffer;
70   |   if( (token = strsep(&cursor, " \t")) != NULL) {
71   |     for (i=0; comm[i].name != NULL; i++) {
72   |       if ( strcmp(token, comm[i].name) == 0) {
73   | 	index = i;
74   | 	break;
75   |       }
76   |     }
77   |   }
78   |   
79   |   wr_free(comm_buffer);
80   | 
81   |   return index; /* returns -1 when command not found */
82   | } /* find_command() */
83   | 
84   | static 
85   | int show_commands(Command *comm, char *comm_name, GString *output) 
86   | {
87   |   int i = 0;
88   | 
89   |   g_string_sprintfa(output, "%scommands are:\n\n", comm_name);
90   |   while (comm[i].name != NULL) {
91   |     g_string_sprintfa(output, "%s\t%s\n", comm[i].name, comm[i].help);
92   |     i++;
93   |   }
94   | 
95   |   return 1;
96   | } /* show_commands() */
97   | 
98   | 
99   | int command_execute(Command *comm, char *comm_name,
100  | 		    char *input, GString *output, sk_conn_st *condat) 
101  | { 
102  |   char *name, *next_word, *tmp_input;
103  |   int index, result=0;
104  | 
105  |   /* find the command in the string - first whitespace delimited word */
106  |   /* make a copy of the input */
107  |   dieif( (tmp_input = wr_string(input)) == NULL );  
108  |   next_word = tmp_input;
109  |   
110  |   /* find the first word and set the pointer to the rest of the string */
111  |   name = strsep(&next_word, " \t");
112  |   
113  |   if( name != NULL && strlen(name) != 0 ) {
114  |     index = find_command(name, comm);
115  |     if( index != -1 ) {
116  |       if( next_word != NULL ) {
117  | 	/* advance the input pointer to the next word */
118  | 	while(  *next_word != '\0' && isspace(*next_word) ) {
119  | 	  next_word++;
120  | 	}
121  |       }
122  |       else {
123  | 	next_word = "";
124  |       }
125  |       
126  |       /* run, Forrest, run...*/
127  |       result = comm[index].function(next_word, output, condat);
128  |     }
129  |     else {	    
130  |       g_string_sprintfa(output, "invalid %scommand: %s\n", comm_name, name);
131  |       show_commands(comm, comm_name, output);
132  |       result = 2;
133  |     }
134  |   }  
135  |   else {  
136  |     show_commands(comm, comm_name, output);
137  |     result = 2;
138  |   }
139  |   
140  |   free(tmp_input);
141  | 
142  |   return result;
143  | } /* command_execute() */
144  | 
145  | 
146  | static 
147  | int command_help(char *input, GString *output, sk_conn_st *condat) 
148  | {
149  |   /* by the time it came here, the "help" bit is already taken away. */
150  |   return show_commands(command, "", output);
151  | 
152  | }
153  | 
154  | 
155  | 
156  | 
157  | 
158  | 
159  | /* proces_input() */
160  | /*++++++++++++++++++++++++++++++++++++++
161  | 
162  |   Process the input.
163  | 
164  |   sk_conn_st *condat         connection data    
165  | 
166  |   More:
167  |   +html+ <PRE>
168  |   Author:
169  |         ottrey
170  |   +html+ </PRE>
171  |   ++++++++++++++++++++++++++++++++++++++*/
172  | static 
173  | int process_input(char *input, sk_conn_st *condat) 
174  | {
175  |   int  index;
176  |   int res=0;
177  |   GString *output = g_string_new("");
178  | 
179  |   index = find_command(input, command);
180  | 
181  |   switch (index) {
182  |   case -1:
183  |     /* Command not found */
184  |     command_help(NULL, output, condat);
185  |     break;
186  |     
187  |   default: 
188  |     res = command_execute(command, "", input, output, condat);
189  |   }
190  |   
191  |   if(res != PC_RET_QUIT) {
192  |     /*
193  |       printf("thread output=\n%s\n", output);
194  |     */
195  |     if ( CO_get_clear_screen() == 1 ) {
196  |       SK_cd_puts(condat, CLEAR_SCREEN);
197  |     }
198  |     SK_cd_puts(condat,  output->str);
199  |     SK_cd_printf(condat, "\n\n=%d= %s", res, CO_get_prompt());
200  |     
201  |   }
202  |   
203  |   g_string_free( output, TRUE );
204  | 
205  |   /* the return value is the connection state: 1=still open, 0=to be closed
206  |    */
207  | 
208  |   return (res != PC_RET_QUIT);
209  | } /* process_input() */
210  | 
211  | 
212  | static 
213  | char *authenticate_user(sk_conn_st *condat) 
214  | {
215  |   char *user = NULL;
216  |   const char Salt[2] = "DB";
217  |   char input[MAX_INPUT_SIZE];
218  |   int read_result;
219  |   char *password=NULL;
220  |   char *user_password=NULL;
221  |   char user_buf[10];
222  | 
223  |   SK_cd_puts(condat, LOGIN_PROMPT);
224  |   read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
225  | 
226  |   strncpy(user_buf, input, 10);
227  | 
228  |   SK_cd_puts(condat, PASSWD_PROMPT);
229  |   /* XXX These aren't working.
230  |   SK_puts(sock, ECHO_ON);
231  |   echo_off(sock);
232  |   */
233  |   read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
234  |   /* XXX These aren't working.
235  |   echo_on(sock);
236  |   SK_puts(sock, ECHO_OFF);
237  |   */
238  | 
239  |   password = crypt(input, Salt);
240  | 
241  |   user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
242  | 
243  |   if (user_password != NULL) {
244  |     if (strcmp(password, user_password) == 0) {
245  |       /*user = (char *)calloc(1, strlen(user_buf)+1);*/
246  |       dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);  
247  |       strcpy(user, user_buf);
248  |     }
249  |   }
250  | 
251  |   
252  |   return user;
253  | 
254  | } /* authenticate_user() */
255  | 
256  | void PC_interact(int sock) {
257  |   char input[MAX_INPUT_SIZE];
258  |   int connected = 1;
259  |   char *user=NULL;
260  |   sk_conn_st condat;
261  | 
262  |   memset( &condat, 0, sizeof(condat));
263  |   condat.sock = sock;
264  |   SK_getpeerip(sock, &(condat.rIP));
265  |   condat.ip = SK_getpeername(sock); /* XXX *alloc involved */
266  |   
267  |   /* Welcome the client */
268  |   SK_cd_puts(&condat, CO_get_welcome());
269  | 
270  |   /* Authenticate the user */
271  |   if (CO_get_authenticate() == 1) {
272  |     user = authenticate_user(&condat);
273  | 
274  |     if (user == NULL) {
275  |       ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
276  | 		"unsuccesful login attempt from %s", condat.ip );
277  |     }
278  |   }
279  |   else {
280  |     user="nobody";
281  |   }
282  | 
283  |   if (user != NULL) {    
284  | 
285  |     /* Log admin logging on */
286  |     ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
287  | 		"user %s from %s logged on", user, condat.ip );
288  |     
289  |     {
290  |       char timestring[26];
291  |       extern time_t SV_starttime;
292  |       
293  |       ctime_r(&SV_starttime, timestring); 
294  |       SK_cd_printf(&condat, 
295  | 		   "System running since %sUptime in seconds: %ld \n\n",
296  | 		   timestring,		  
297  | 		   time(NULL) - SV_starttime);
298  |     }
299  |     
300  |     SK_cd_puts(&condat, CO_get_prompt());
301  | 
302  |     while (condat.rtc==0 && connected) {
303  |       char *ichr;
304  |       char *icopy;
305  |       char *chr;
306  |       /* Read input. Quit if no input (socket closed) */
307  |       if( SK_cd_gets(&condat, input, MAX_INPUT_SIZE) <= 0 ) {
308  | 	break;
309  |       }
310  | 
311  |       /* filter junk out: leading/trailing whitespaces */
312  |       
313  |       
314  | 
315  |       /* 1. advance to non-whitespace */
316  |       for(ichr=input; *ichr != 0 && isspace(*ichr); ichr++) {
317  | 	/* EMPTY */
318  |       }
319  | 
320  |       /* 2. copy the rest (even if empty) */
321  |       dieif( (icopy = strdup(ichr)) == NULL);
322  |       
323  |       if( *ichr != '\0') {
324  | 	/* 3. chop trailing spaces */
325  | 	for( chr = icopy + strlen(icopy)-1 ; 
326  | 	     chr != icopy && isspace(*chr);
327  | 	     chr--) {
328  | 	  *chr = 0;
329  | 	}
330  |       }
331  |       
332  |       /* set thread accounting */
333  |       TA_setactivity(icopy);
334  |       TA_increment();
335  |       
336  |       /*      if( strlen(icopy) > 0 ) {*/
337  |       {
338  | 	ER_inf_va(FAC_PC, ASP_PC_I_COMMAND, icopy);
339  | 		  
340  | 	connected = process_input(icopy, &condat);
341  |       }
342  |       
343  |       TA_setactivity("");
344  |       
345  |       free(icopy);
346  |     }
347  |     
348  |     /* Log admin logging off */
349  |     ER_inf_va(FAC_PC, ASP_PC_I_SESSION, 
350  | 		"user %s from %s logged off", user, condat.ip );
351  |     
352  |   }
353  |   
354  |   /* Close the socket */
355  |   SK_close(sock);
356  | 
357  |   wr_free(condat.ip);
358  | } /* PC_interact() */
359  |