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