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 |