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 |