1 | /***************************************
2 | $Revision: 1.12 $
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 | Author : ottrey@ripe.net
12 | OSs Tested : Solaris
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 | ******************/ /******************
19 | Copyright (c) 1999 RIPE NCC
20 |
21 | All Rights Reserved
22 |
23 | Permission to use, copy, modify, and distribute this software and its
24 | documentation for any purpose and without fee is hereby granted,
25 | provided that the above copyright notice appear in all copies and that
26 | both that copyright notice and this permission notice appear in
27 | supporting documentation, and that the name of the author not be
28 | used in advertising or publicity pertaining to distribution of the
29 | software without specific, written prior permission.
30 |
31 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
32 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
33 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
34 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
35 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 | ***************************************/
38 | #include <stdio.h>
39 | #include <stdlib.h>
40 | #include <unistd.h> /* crypt stuff */
41 | #include <time.h> /* Time stuff */
42 | #include <sys/ioctl.h> /* Terminal control stuff */
43 | #include <termio.h> /* Terminal control stuff */
44 |
45 | #include "mysql_driver.h"
46 | #include "constants.h"
47 | #include "properties.h"
48 | #include "thread.h"
49 | #include "protocol_config.h"
50 | #include "access_control.h"
51 | #include "socket.h"
52 |
53 | /*+ Each command has a +*/
54 | typedef struct _command {
55 | const char *name; /*+ Name to be invoked. +*/
56 | char *(*function)(char *, sk_conn_st *); /*+ Function to be invoked. +*/
57 | const char *help; /*+ Command help. +*/
58 | } Command;
59 |
60 | /*
61 | * Forward declarations
62 | */
63 | static char *command_help(char *input, sk_conn_st *condat);
64 | static char *command_quit(char *input, sk_conn_st *condat);
65 | static char *command_show(char *input, sk_conn_st *condat);
66 | static char *command_repeat(char *input, sk_conn_st *condat);
67 | static char *show_const(char *input, sk_conn_st *condat);
68 | static char *show_consts(char *input, sk_conn_st *condat);
69 | static char *show_props(char *input, sk_conn_st *condat);
70 | static char *show_thread(char *input, sk_conn_st *condat);
71 | static char *show_whois(char *input, sk_conn_st *condat);
72 | static char *show_access(char *input, sk_conn_st *condat);
73 | static char *show_acl(char *input, sk_conn_st *condat);
74 | static char *command_set(char *input, sk_conn_st *condat);
75 | static char *set_const(char *input, sk_conn_st *condat);
76 | static char *set_consts(char *input, sk_conn_st *condat);
77 | static char *set_props(char *input, sk_conn_st *condat);
78 | static char *command_sql(char *input, sk_conn_st *condat);
79 |
80 | /*+
81 | * Contains the command definitions
82 | +*/
83 | static struct _command command[] = {
84 | {"help" , command_help , HELP_HELP },
85 | {"quit" , command_quit , HELP_QUIT },
86 | {"show" , command_show , HELP_SHOW },
87 | {"repeat" , command_repeat , HELP_REPEAT },
88 | {"set" , command_set , HELP_SET },
89 | {"sql" , command_sql , HELP_SQL },
90 | {NULL , NULL , NULL }
91 | };
92 |
93 | /*+
94 | * Contains the show commands
95 | +*/
96 | static struct _command show[] = {
97 | {"const" , show_const , HELP_SHOW_CONST },
98 | {"consts" , show_consts , HELP_SHOW_CONSTS },
99 | {"props" , show_props , HELP_SHOW_PROPS },
100 | {"thread" , show_thread , HELP_SHOW_THREAD },
101 | {"whois" , show_whois , HELP_SHOW_WHOIS },
102 | {"access" , show_access , HELP_SHOW_ACCESS },
103 | {"acl" , show_acl , HELP_SHOW_ACL },
104 | {NULL , NULL , NULL }
105 | };
106 |
107 | /*+
108 | * Contains the set commands
109 | +*/
110 | static struct _command set[] = {
111 | {"const" , set_const , HELP_SET_CONST },
112 | {"consts" , set_consts , HELP_SET_CONSTS },
113 | {"props" , set_props , HELP_SET_PROPS },
114 | {NULL , NULL , NULL }
115 | };
116 |
117 | static int find_command(char *comm_name, Command *comm) {
118 | int i, index;
119 | char comm_buffer[STR_L];
120 |
121 | if (comm_name != NULL) {
122 | strcpy(comm_buffer, comm_name);
123 | strtok(comm_buffer, " \t");
124 | for (i=0, index=-1; comm[i].name != NULL; i++) {
125 | if ( strcmp(comm_buffer, comm[i].name) == 0) {
126 | index = i;
127 | break;
128 | }
129 | }
130 | }
131 | else {
132 | index = -2;
133 | }
134 |
135 | return index;
136 | } /* find_command() */
137 |
138 | static char *show_commands(Command *comm) {
139 | char *str;
140 | char help_buffer[STR_XL];
141 | char help_comm[STR_M];
142 | int i;
143 |
144 | sprintf(help_buffer, " commands are:\n\n");
145 | i = 0;
146 | while (comm[i].name != NULL) {
147 | sprintf(help_comm, "%s\t%s\n", comm[i].name, comm[i].help);
148 | strcat(help_buffer, help_comm);
149 | i++;
150 | }
151 |
152 | // str = (char *)calloc(1, strlen(help_buffer)+1);
153 | dieif( wr_malloc((void **)&str, strlen(help_buffer)+1) != UT_OK);
154 | strcpy(str, help_buffer);
155 |
156 | return str;
157 | } /* show_commands() */
158 |
159 |
160 | /*
161 | * Command functions
162 | */
163 | static char *command_help(char *input, sk_conn_st *condat) {
164 | char *str;
165 | char *str1;
166 | char output_buffer[STR_XXL];
167 | char *command_name;
168 | int index;
169 |
170 | strcpy(output_buffer, "");
171 |
172 | strtok(input, " \t");
173 | command_name = (char *)strtok(NULL, " \t");
174 |
175 | index = find_command(command_name, command);
176 |
177 | switch (index) {
178 | case -2:
179 | strcat(output_buffer, "Main");
180 | str1 = show_commands(command);
181 | strcat(output_buffer, str1);
182 | wr_free(str1);
183 | break;
184 |
185 | case -1:
186 | strcat(output_buffer, HELP_ERROR);
187 | strcat(output_buffer, command_name);
188 | break;
189 |
190 | default:
191 | strcat(output_buffer, command[index].help);
192 | }
193 |
194 | /*
195 | str = (char *)CopyString(output_buffer);
196 | */
197 | // str = (char *)calloc(1, strlen(output_buffer)+1);
198 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
199 | strcpy(str, output_buffer);
200 |
201 | return str;
202 | } /* command_help() */
203 |
204 | static char *command_quit(char *input, sk_conn_st *condat) {
205 | /* Administrator wishes to quit. */
206 | return NULL;
207 | } /* command_quit() */
208 |
209 | static char *show_const(char *input, sk_conn_st *condat) {
210 | /* Administrator wishes to show constants. */
211 | char *result;
212 | char *name;
213 | char *tmp_input;
214 |
215 | // tmp_input = (char *)calloc(1, strlen(input)+1);
216 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
217 | strcpy(tmp_input, input);
218 |
219 | /* The name will be the third token in stuff */
220 | strtok(tmp_input, " ");
221 | strtok(NULL, " ");
222 | name = (char *)strtok(NULL, " ");
223 |
224 | result = CO_const_to_string(name);
225 |
226 | wr_free(tmp_input);
227 | return result;
228 |
229 | } /* show_const() */
230 |
231 | static char *show_consts(char *input, sk_conn_st *condat) {
232 | /* Administrator wishes to show constants. */
233 | return CO_to_string();
234 |
235 | } /* show_consts() */
236 |
237 | static char *show_props(char *input, sk_conn_st *condat) {
238 | /* Administrator wishes to show properties. */
239 | return PR_to_string();
240 |
241 | } /* show_props() */
242 |
243 | static char *show_thread(char *input, sk_conn_st *condat) {
244 | /* Administrator wishes to show thread information. */
245 | return TH_to_string();
246 |
247 | } /* show_thread() */
248 |
249 | static char *show_whois(char *input, sk_conn_st *condat) {
250 | /* Administrator wishes to show whois query information. */
251 | return "WQ_to_string();";
252 |
253 | } /* show_whois() */
254 |
255 | static char *show_access(char *input, sk_conn_st *condat) {
256 | /* Administrator wishes to show whois query information. */
257 |
258 | char line[128];
259 | int cnt;
260 | er_ret_t err;
261 |
262 | if( act_runtime->top_ptr != NULL ) {
263 | cnt = rx_walk_tree(act_runtime->top_ptr, AC_rxwalkhook_print,
264 | RX_WALK_SKPGLU, /* print no glue nodes */
265 | 255, 0, 0, condat, &err);
266 | sprintf(line,"Found %d nodes\n", cnt);
267 | SK_cd_puts(condat,line);
268 | }
269 |
270 | return "";
271 |
272 | } /* show_access() */
273 |
274 | static char *show_acl(char *input, sk_conn_st *condat) {
275 | /* Administrator wishes to show access control list. */
276 |
277 | char line[128];
278 | int cnt;
279 | er_ret_t err;
280 |
281 | if( act_acl->top_ptr != NULL ) {
282 | cnt = rx_walk_tree(act_acl->top_ptr, AC_rxwalkhook_print_acl,
283 | RX_WALK_SKPGLU, /* print no glue nodes */
284 | 255, 0, 0, condat, &err);
285 | sprintf(line,"Found %d nodes\n", cnt);
286 | SK_cd_puts(condat,line);
287 | }
288 |
289 | return "";
290 |
291 | } /* show_acl() */
292 |
293 | static char *command_execute(char *input, char *comm_name,
294 | Command *comm, sk_conn_st *condat) {
295 | char *str;
296 | char *str1;
297 | char output_buffer[STR_XXL];
298 | char *name;
299 | int index;
300 | char *tmp_input;
301 |
302 | /* Make a copy of the input */
303 | // tmp_input = (char *)calloc(1, strlen(input)+1);
304 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
305 | strcpy(tmp_input, input);
306 |
307 | strtok(tmp_input, " \t");
308 | name = (char *)strtok(NULL, " \t");
309 |
310 | index = find_command(name, comm);
311 |
312 | switch (index) {
313 | case -2:
314 | str1 = show_commands(comm);
315 | sprintf(output_buffer, "%s%s", comm_name, str1);
316 | wr_free(str1);
317 | break;
318 |
319 | case -1:
320 | sprintf(output_buffer, "%s invalid command: %s", comm_name, name);
321 | break;
322 |
323 | default:
324 | sprintf(output_buffer, "%s", comm[index].function(input, condat));
325 | }
326 |
327 | /*
328 | str = (char *)CopyString(output_buffer);
329 | */
330 | // str = (char *)calloc(1, strlen(output_buffer)+1);
331 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
332 | strcpy(str, output_buffer);
333 |
334 | wr_free(tmp_input);
335 |
336 | return str;
337 | } /* command_execute() */
338 |
339 | static char *command_show(char *input, sk_conn_st *condat) {
340 | return command_execute(input, "Show", show, condat);
341 | } /* command_show() */
342 |
343 | static char *command_repeat(char *input, sk_conn_st *condat) {
344 | char *command_ptr;
345 |
346 | /* Goto the bit after "repeat n " */
347 | for (command_ptr=input+7; command_ptr[0] != ' ' || (command_ptr[0] >= '0' && command_ptr[0] <= '9'); command_ptr++);
348 |
349 | return command_ptr+1;
350 |
351 | } /* command_show() */
352 |
353 | static char *set_const(char *input, sk_conn_st *condat) {
354 | /* Administrator wishes to set a constant. */
355 | char *result;
356 | char result_buf[STR_M];
357 | char *tmp_input;
358 | char *name;
359 | char *value;
360 | int value_len;
361 | char *stuff;
362 | char *str;
363 |
364 | // tmp_input = (char *)calloc(1, strlen(input)+1);
365 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
366 | strcpy(tmp_input, input);
367 |
368 | stuff = (char *)strtok(tmp_input, "=");
369 |
370 | /* The value will be after the '=' */
371 | value = (char *)strtok(NULL, "=");
372 |
373 | /* The name will be the third token in stuff */
374 | strtok(stuff, " ");
375 | strtok(NULL, " ");
376 | name = (char *)strtok(NULL, " ");
377 |
378 | /* Remove any quotes */
379 | if (value[0] == '"') {
380 | value++;
381 | }
382 | value_len=strlen(value);
383 | if (value[value_len-1] == '"') {
384 | value[value_len-1]='\0';
385 | }
386 |
387 | printf("set_const name=(%s), value=(%s)\n", name, value);
388 | if (CO_set_const(name, value) == 0) {
389 | strcpy(result_buf, "Constant successfully set\n");
390 | }
391 | else {
392 | str = CO_const_to_string(name);
393 | sprintf(result_buf, "Constant not successfully set\nReverting to: %s=%s\n", name, str);
394 | wr_free(str);
395 | }
396 |
397 | // result = (char *)calloc(1, strlen(result_buf)+1);
398 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
399 | strcpy(result, result_buf);
400 |
401 | wr_free(tmp_input);
402 | return result;
403 | } /* set_const() */
404 |
405 | static char *set_consts(char *input, sk_conn_st *condat) {
406 | /* Administrator wishes to set constants. */
407 | return CO_set();
408 | } /* set_consts() */
409 |
410 | static char *set_props(char *input, sk_conn_st *condat) {
411 | /* Administrator wishes to set properties. */
412 | return PR_set();
413 | } /* set_props() */
414 |
415 | static char *command_set(char *input, sk_conn_st *condat) {
416 | return command_execute(input, "Set", set, condat);
417 | } /* command_set() */
418 |
419 | static char *command_sql(char *input, sk_conn_st *condat) {
420 | char *str;
421 | char output_buffer[STR_XXL];
422 | char *sql_str;
423 |
424 | char *res=NULL;
425 |
426 | SQ_result_set_t *sql_result=NULL;
427 | SQ_connection_t *sql_connection;
428 |
429 | sql_connection = SQ_get_connection(CO_get_host(), CO_get_database_port(), CO_get_database(), CO_get_user(), CO_get_password() );
430 |
431 | if (sql_connection == NULL) {
432 | printf("/* Check for errors */\n");
433 | }
434 |
435 | /* skip over the "sql" */
436 | sql_str = input+3;
437 | /* skip over white space */
438 | while (sql_str[0] == ' ') {
439 | sql_str++;
440 | }
441 |
442 | strcpy(output_buffer, "");
443 |
444 | if (sql_connection != NULL) {
445 | if (strcmp(sql_str, "status") == 0) {
446 | /* Get the status of the database */
447 | res = SQ_info_to_string(sql_connection);
448 | }
449 | else {
450 | if (strcmp(sql_str, "") == 0) {
451 | /* Execute the default query (from the properties file) */
452 | sql_result = SQ_execute_query(SQ_STORE, sql_connection, CO_get_query());
453 | }
454 | else {
455 | /* Execute an sql query */
456 | sql_result = SQ_execute_query(SQ_STORE, sql_connection, sql_str);
457 | }
458 | if (sql_result != NULL) {
459 | res = SQ_result_to_string(sql_result);
460 | }
461 | else {
462 | printf("no results\n");
463 | }
464 | }
465 | if (res != NULL) {
466 | sprintf(output_buffer, "%s", res);
467 | }
468 | else {
469 | printf("empty results\n");
470 | }
471 | }
472 | else {
473 | printf("Failed to make connection\n");
474 | }
475 |
476 | /*
477 | strcat(output_buffer, mysql_info(sql_connection));
478 | */
479 |
480 | strcat(output_buffer, "XXX Results from mysql_info(sql_connection) is meant to go here. But it's not working!");
481 |
482 | /*
483 | str = (char *)CopyString(output_buffer);
484 | */
485 | // str = (char *)calloc(1, strlen(output_buffer)+1);
486 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
487 | strcpy(str, output_buffer);
488 |
489 | wr_free(res);
490 | SQ_free_result(sql_result);
491 |
492 | SQ_close_connection(sql_connection);
493 |
494 | return str;
495 |
496 | } /* command_sql() */
497 |
498 |
499 | /* process_input() */
500 | /*++++++++++++++++++++++++++++++++++++++
501 |
502 | Process the input.
503 |
504 | sk_conn_st *condat connection data
505 |
506 | More:
507 | +html+ <PRE>
508 | Author:
509 | ottrey
510 | +html+ </PRE>
511 | ++++++++++++++++++++++++++++++++++++++*/
512 | static int process_input(char *input, sk_conn_st *condat) {
513 | int connected = 1;
514 | char *input_ptr;
515 | char *output;
516 | int index;
517 | int repeat=0;
518 |
519 | input_ptr = input;
520 |
521 | if (strncmp(input, "repeat", 6) == 0) {
522 | /* XXX This is a really dodgy call, that hopefully converts
523 | the string to the value of the first found integer. */
524 | repeat = atoi(input+7);
525 | input_ptr= command_repeat(input, condat);
526 | }
527 |
528 | index = find_command(input_ptr, command);
529 |
530 | do {
531 | switch (index) {
532 | case -1:
533 | /* Command not found */
534 | output = command_help(NULL, condat);
535 | break;
536 |
537 | default:
538 | output = command[index].function(input_ptr, condat);
539 | }
540 |
541 | if(output == NULL) {
542 | connected = 0;
543 | } else {
544 | /*
545 | printf("thread output=\n%s\n", output);
546 | */
547 | if ( CO_get_clear_screen() == 1 ) {
548 | SK_cd_puts(condat, CLEAR_SCREEN);
549 | }
550 | SK_cd_puts(condat, output);
551 | SK_cd_puts(condat, "\n");
552 | SK_cd_puts(condat, CO_get_prompt());
553 |
554 | wr_free(output);
555 | }
556 |
557 | if (repeat > 0) {
558 | repeat--;
559 | sleep(CO_get_sleep_time());
560 | }
561 |
562 | } while (repeat > 0);
563 |
564 | return connected;
565 |
566 | } /* process_input() */
567 |
568 | static void log_config(const char *user, const char *status) {
569 | FILE *logf;
570 | time_t now;
571 |
572 | time(&now);
573 |
574 | if (CO_get_config_logging() == 1) {
575 |
576 | if (strcmp(CO_get_config_logfile(), "stdout") == 0) {
577 | printf(LOG_CONFIG, TH_get_id(), user, status, ctime(&now));
578 | }
579 | else {
580 | logf = fopen(CO_get_config_logfile(), "a");
581 | fprintf(logf, LOG_CONFIG, TH_get_id(), user, status, ctime(&now));
582 | fclose(logf);
583 | }
584 | }
585 |
586 | } /* log_config() */
587 |
588 | /* XXX Doh! These only change the server's terminal. We need some
589 | tricky escape sequence to send over the socket.
590 | static void echo_off(int sock) {
591 | struct termio state;
592 |
593 | ioctl(0, TIOCGETP, &state);
594 | state.c_lflag &= ~ECHO;
595 | ioctl(0, TIOCSETP, &state);
596 | } echo_off() */
597 |
598 | /* XXX Doh! These only change the server's terminal. We need some
599 | tricky escape sequence to send over the socket.
600 | static void echo_on(int sock) {
601 | struct termio state;
602 |
603 | ioctl(0, TIOCGETP, &state);
604 | state.c_lflag |= ECHO;
605 | ioctl(0, TIOCSETP, &state);
606 | } echo_on() */
607 |
608 | static char *authenticate_user(sk_conn_st *condat) {
609 | char *user = NULL;
610 | const char Salt[2] = "DB";
611 | char input[MAX_INPUT_SIZE];
612 | int read_result;
613 | char *password=NULL;
614 | char *user_password=NULL;
615 | char user_buf[10];
616 |
617 | SK_cd_puts(condat, LOGIN_PROMPT);
618 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
619 |
620 | strncpy(user_buf, input, 10);
621 |
622 | SK_cd_puts(condat, PASSWD_PROMPT);
623 | /* XXX These aren't working.
624 | SK_puts(sock, ECHO_ON);
625 | echo_off(sock);
626 | */
627 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
628 | /* XXX These aren't working.
629 | echo_on(sock);
630 | SK_puts(sock, ECHO_OFF);
631 | */
632 |
633 | password = crypt(input, Salt);
634 |
635 | user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
636 |
637 | if (user_password != NULL) {
638 | if (strcmp(password, user_password) == 0) {
639 | //user = (char *)calloc(1, strlen(user_buf)+1);
640 | dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);
641 | strcpy(user, user_buf);
642 | }
643 | }
644 |
645 | if (user == NULL) {
646 | log_config(user_buf, "unsuccesful login attempt");
647 | }
648 |
649 | return user;
650 |
651 | } /* authenticate_user() */
652 |
653 | void PC_interact(int sock) {
654 | char input[MAX_INPUT_SIZE];
655 | int connected = 1;
656 | char *user=NULL;
657 | sk_conn_st condat;
658 |
659 | memset( &condat, 0, sizeof(condat));
660 | condat.sock = sock;
661 | SK_getpeerip(sock, &(condat.rIP));
662 | condat.ip = SK_getpeername(sock);
663 |
664 | /* Welcome the client */
665 | SK_cd_puts(&condat, CO_get_welcome());
666 |
667 | /* Authenticate the user */
668 | if (CO_get_authenticate() == 1) {
669 | user = authenticate_user(&condat);
670 | }
671 | else {
672 | user="nobody";
673 | }
674 |
675 | if (user != NULL) {
676 | /* Log admin logging on */
677 | log_config(user, "logged on");
678 |
679 | SK_cd_puts(&condat, CO_get_prompt());
680 |
681 | while (condat.rtc==0 && connected) {
682 | /* Read input */
683 | SK_cd_gets(&condat, input, MAX_INPUT_SIZE);
684 | connected = process_input(input, &condat);
685 | }
686 |
687 | /* Log admin logging off */
688 | log_config(user, "logged off");
689 | }
690 |
691 | /* Close the socket */
692 | SK_close(sock);
693 |
694 | } /* PC_interact() */
695 |