modules/pc/protocol_config.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- find_command
- show_commands
- command_help
- command_quit
- show_const
- show_consts
- show_props
- show_thread
- show_whois
- show_access
- show_acl
- command_execute
- command_show
- command_repeat
- set_const
- set_consts
- set_props
- set_ban
- command_set
- command_sql
- process_input
- log_config
- authenticate_user
- PC_interact
/***************************************
$Revision: 1.17 $
Protocol config module (pc). This is the protocol that the admin uses to
talk to the server.
Status: NOT REVUED, NOT TESTED
******************/ /******************
Filename : protocol_config.c
Authors : ottrey@ripe.net
marek@ripe.net
To Do : Add a facility to take callbacks instead of
hard-coding menu options.
Add in all the menu support provided by the GLib
libraries.
(Remove strtok if multiple threads are to be used.)
use gnu readline with expansion and history
******************/ /******************
Copyright (c) 1999 RIPE NCC
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the author not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
***************************************/
#include <stdio.h>
#include <stdlib.h>
/*** solaris' header file doesn't contain the crypt definition...
#include <unistd.h> */
extern char* crypt(const char *, const char *); /* crypt stuff */
#include <time.h> /* Time stuff */
#include <sys/ioctl.h> /* Terminal control stuff */
#include <termio.h> /* Terminal control stuff */
#include "mysql_driver.h"
#include "constants.h"
#include "properties.h"
#include "thread.h"
#include "protocol_config.h"
#include "access_control.h"
#include "socket.h"
/*+ Each command has a +*/
typedef struct _command {
const char *name; /*+ Name to be invoked. +*/
char *(*function)(char *, sk_conn_st *); /*+ Function to be invoked. +*/
const char *help; /*+ Command help. +*/
} Command;
/*
* Forward declarations
*/
static char *command_help(char *input, sk_conn_st *condat);
static char *command_quit(char *input, sk_conn_st *condat);
static char *command_show(char *input, sk_conn_st *condat);
static char *command_repeat(char *input, sk_conn_st *condat);
static char *show_const(char *input, sk_conn_st *condat);
static char *show_consts(char *input, sk_conn_st *condat);
static char *show_props(char *input, sk_conn_st *condat);
static char *show_thread(char *input, sk_conn_st *condat);
static char *show_whois(char *input, sk_conn_st *condat);
static char *show_access(char *input, sk_conn_st *condat);
static char *show_acl(char *input, sk_conn_st *condat);
static char *command_set(char *input, sk_conn_st *condat);
static char *set_const(char *input, sk_conn_st *condat);
static char *set_consts(char *input, sk_conn_st *condat);
static char *set_props(char *input, sk_conn_st *condat);
static char *command_sql(char *input, sk_conn_st *condat);
static char *set_ban(char *input, sk_conn_st *condat);
/*+
* Contains the command definitions
+*/
static struct _command command[] = {
{"help" , command_help , HELP_HELP },
{"quit" , command_quit , HELP_QUIT },
{"show" , command_show , HELP_SHOW },
{"repeat" , command_repeat , HELP_REPEAT },
{"set" , command_set , HELP_SET },
{"sql" , command_sql , HELP_SQL },
{NULL , NULL , NULL }
};
/*+
* Contains the show commands
+*/
static struct _command show[] = {
{"const" , show_const , HELP_SHOW_CONST },
{"consts" , show_consts , HELP_SHOW_CONSTS },
{"props" , show_props , HELP_SHOW_PROPS },
{"thread" , show_thread , HELP_SHOW_THREAD },
{"whois" , show_whois , HELP_SHOW_WHOIS },
{"access" , show_access , HELP_SHOW_ACCESS },
{"acl" , show_acl , HELP_SHOW_ACL },
{NULL , NULL , NULL }
};
/*+
* Contains the set commands
+*/
static struct _command set[] = {
{"const" , set_const , HELP_SET_CONST },
{"consts" , set_consts , HELP_SET_CONSTS },
{"props" , set_props , HELP_SET_PROPS },
{"ban" , set_ban , HELP_SET_BAN },
{NULL , NULL , NULL }
};
static int find_command(char *comm_name, Command *comm) {
/* [<][>][^][v][top][bottom][index][help] */
int i, index;
char comm_buffer[STR_L];
if (comm_name != NULL) {
strcpy(comm_buffer, comm_name);
strtok(comm_buffer, " \t");
for (i=0, index=-1; comm[i].name != NULL; i++) {
if ( strcmp(comm_buffer, comm[i].name) == 0) {
index = i;
break;
}
}
}
else {
index = -2;
}
return index;
} /* find_command() */
static char *show_commands(Command *comm) {
/* [<][>][^][v][top][bottom][index][help] */
char *str;
char help_buffer[STR_XL];
char help_comm[STR_M];
int i;
sprintf(help_buffer, " commands are:\n\n");
i = 0;
while (comm[i].name != NULL) {
sprintf(help_comm, "%s\t%s\n", comm[i].name, comm[i].help);
strcat(help_buffer, help_comm);
i++;
}
/* str = (char *)calloc(1, strlen(help_buffer)+1); */
dieif( wr_malloc((void **)&str, strlen(help_buffer)+1) != UT_OK);
strcpy(str, help_buffer);
return str;
} /* show_commands() */
/*
* Command functions
*/
static char *command_help(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
char *str;
char *str1;
char output_buffer[STR_XXL];
char *command_name;
int index;
strcpy(output_buffer, "");
strtok(input, " \t");
command_name = (char *)strtok(NULL, " \t");
index = find_command(command_name, command);
switch (index) {
case -2:
strcat(output_buffer, "Main");
str1 = show_commands(command);
strcat(output_buffer, str1);
wr_free(str1);
break;
case -1:
strcat(output_buffer, HELP_ERROR);
strcat(output_buffer, command_name);
break;
default:
strcat(output_buffer, command[index].help);
}
/*
str = (char *)CopyString(output_buffer);
*/
/* str = (char *)calloc(1, strlen(output_buffer)+1); */
dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
strcpy(str, output_buffer);
return str;
} /* command_help() */
static char *command_quit(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to quit. */
return NULL;
} /* command_quit() */
static char *show_const(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show constants. */
char *result;
char *name;
char *tmp_input;
/* tmp_input = (char *)calloc(1, strlen(input)+1); */
dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
strcpy(tmp_input, input);
/* The name will be the third token in stuff */
strtok(tmp_input, " ");
strtok(NULL, " ");
name = (char *)strtok(NULL, " ");
result = CO_const_to_string(name);
wr_free(tmp_input);
return result;
} /* show_const() */
static char *show_consts(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show constants. */
return CO_to_string();
} /* show_consts() */
static char *show_props(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show properties. */
return PR_to_string();
} /* show_props() */
static char *show_thread(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show thread information. */
return TH_to_string();
} /* show_thread() */
static char *show_whois(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show whois query information. */
return wr_string("WQ_to_string();");
} /* show_whois() */
static char *show_access(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show whois query information. */
char line[128];
int cnt;
er_ret_t err;
if( act_runtime->top_ptr != NULL ) {
char *header = AC_to_string_header();
/* print header */
SK_cd_puts(condat,header);
wr_free(header);
cnt = rx_walk_tree(act_runtime->top_ptr, AC_rxwalkhook_print,
RX_WALK_SKPGLU, /* print no glue nodes */
255, 0, 0, condat, &err);
sprintf(line,"Found %d nodes\n", cnt);
SK_cd_puts(condat,line);
}
return wr_string("");
} /* show_access() */
static char *show_acl(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to show access control list. */
char line[128];
int cnt;
er_ret_t err;
if( act_acl->top_ptr != NULL ) {
char *header = AC_acl_to_string_header();
/* print header */
SK_cd_puts(condat,header);
wr_free(header);
cnt = rx_walk_tree(act_acl->top_ptr, AC_rxwalkhook_print_acl,
RX_WALK_SKPGLU, /* print no glue nodes */
255, 0, 0, condat, &err);
sprintf(line,"Found %d nodes\n", cnt);
SK_cd_puts(condat,line);
}
return wr_string("");
} /* show_acl() */
static char *command_execute(char *input, char *comm_name,
/* [<][>][^][v][top][bottom][index][help] */
Command *comm, sk_conn_st *condat) {
char *str;
char *str1;
char output_buffer[STR_XXL];
char *name;
int index;
char *tmp_input;
/* Make a copy of the input */
/* tmp_input = (char *)calloc(1, strlen(input)+1); */
dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
strcpy(tmp_input, input);
strtok(tmp_input, " \t");
name = (char *)strtok(NULL, " \t");
index = find_command(name, comm);
switch (index) {
case -2:
str1 = show_commands(comm);
sprintf(output_buffer, "%s%s", comm_name, str1);
wr_free(str1);
break;
case -1:
sprintf(output_buffer, "%s invalid command: %s", comm_name, name);
break;
default:
sprintf(output_buffer, "%s", comm[index].function(input, condat));
}
/*
str = (char *)CopyString(output_buffer);
*/
/* str = (char *)calloc(1, strlen(output_buffer)+1); */
dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
strcpy(str, output_buffer);
wr_free(tmp_input);
return str;
} /* command_execute() */
static char *command_show(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
return command_execute(input, "Show", show, condat);
} /* command_show() */
static char *command_repeat(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
char *command_ptr;
/* Goto the bit after "repeat n " */
for (command_ptr=input+7; command_ptr[0] != ' ' || (command_ptr[0] >= '0' && command_ptr[0] <= '9'); command_ptr++);
return command_ptr+1;
} /* command_show() */
static char *set_const(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to set a constant. */
char *result;
char result_buf[STR_M];
char *tmp_input;
char *name;
char *value;
int value_len;
char *stuff;
char *str;
/* tmp_input = (char *)calloc(1, strlen(input)+1); */
dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
strcpy(tmp_input, input);
stuff = (char *)strtok(tmp_input, "=");
/* The value will be after the '=' */
value = (char *)strtok(NULL, "=");
/* The name will be the third token in stuff */
strtok(stuff, " ");
strtok(NULL, " ");
name = (char *)strtok(NULL, " ");
/* Remove any quotes */
if (value[0] == '"') {
value++;
}
value_len=strlen(value);
if (value[value_len-1] == '"') {
value[value_len-1]='\0';
}
printf("set_const name=(%s), value=(%s)\n", name, value);
if (CO_set_const(name, value) == 0) {
strcpy(result_buf, "Constant successfully set\n");
}
else {
str = CO_const_to_string(name);
sprintf(result_buf, "Constant not successfully set\nReverting to: %s=%s\n", name, str);
wr_free(str);
}
/* result = (char *)calloc(1, strlen(result_buf)+1); */
dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
strcpy(result, result_buf);
wr_free(tmp_input);
return result;
} /* set_const() */
static char *set_consts(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to set constants. */
return CO_set();
} /* set_consts() */
static char *set_props(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
/* Administrator wishes to set properties. */
return PR_set();
} /* set_props() */
static char *set_ban(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
int flag;
char addrstr[128];
if( sscanf(input,"set ban %d %127s", &flag, addrstr) < 2) {
return wr_string("Invalid arguments");
}
else {
if( ! NOERR( AC_asc_ban_set( addrstr, "Manual", (flag!=0) ))) {
return wr_string("Error\n");
}
else {
return wr_string("OK");
}
}
}
static char *command_set(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
return command_execute(input, "Set", set, condat);
} /* command_set() */
static char *command_sql(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
char *str;
char output_buffer[STR_XXL];
char *sql_str;
char *res=NULL;
SQ_result_set_t *sql_result=NULL;
SQ_connection_t *sql_connection;
sql_connection = SQ_get_connection(CO_get_host(), CO_get_database_port(), CO_get_database(), CO_get_user(), CO_get_password() );
if (sql_connection == NULL) {
printf("/* Check for errors */\n");
}
/* skip over the "sql" */
sql_str = input+3;
/* skip over white space */
while (sql_str[0] == ' ') {
sql_str++;
}
strcpy(output_buffer, "");
if (sql_connection != NULL) {
if (strcmp(sql_str, "status") == 0) {
/* Get the status of the database */
res = SQ_info_to_string(sql_connection);
}
else {
if (strcmp(sql_str, "") == 0) {
/* Execute the default query (from the properties file) */
SQ_execute_query(sql_connection, CO_get_query(), &sql_result);
}
else {
/* Execute an sql query */
SQ_execute_query(sql_connection, sql_str, &sql_result);
}
if (sql_result != NULL) {
res = SQ_result_to_string(sql_result);
}
else {
printf("no results\n");
}
}
if (res != NULL) {
sprintf(output_buffer, "%s", res);
}
else {
printf("empty results\n");
}
}
else {
printf("Failed to make connection\n");
}
/*
strcat(output_buffer, mysql_info(sql_connection));
*/
strcat(output_buffer, "XXX Results from mysql_info(sql_connection) is meant to go here. But it's not working!");
/*
str = (char *)CopyString(output_buffer);
*/
/* str = (char *)calloc(1, strlen(output_buffer)+1); */
dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
strcpy(str, output_buffer);
wr_free(res);
SQ_free_result(sql_result);
SQ_close_connection(sql_connection);
return str;
} /* command_sql() */
/* process_input() */
/*++++++++++++++++++++++++++++++++++++++
Process the input.
sk_conn_st *condat connection data
More:
+html+ <PRE>
Author:
ottrey
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
static int process_input(char *input, sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
int connected = 1;
char *input_ptr;
char *output;
int index;
int repeat=0;
input_ptr = input;
if (strncmp(input, "repeat", 6) == 0) {
/* XXX This is a really dodgy call, that hopefully converts
the string to the value of the first found integer. */
repeat = atoi(input+7);
input_ptr= command_repeat(input, condat);
}
index = find_command(input_ptr, command);
do {
switch (index) {
case -1:
/* Command not found */
output = command_help(NULL, condat);
break;
default:
output = command[index].function(input_ptr, condat);
}
if(output == NULL) {
connected = 0;
} else {
/*
printf("thread output=\n%s\n", output);
*/
if ( CO_get_clear_screen() == 1 ) {
SK_cd_puts(condat, CLEAR_SCREEN);
}
SK_cd_puts(condat, output);
SK_cd_puts(condat, "\n");
SK_cd_puts(condat, CO_get_prompt());
wr_free(output);
}
if (repeat > 0) {
repeat--;
sleep(CO_get_sleep_time());
}
} while (repeat > 0);
return connected;
} /* process_input() */
static void log_config(const char *user, const char *status) {
/* [<][>][^][v][top][bottom][index][help] */
FILE *logf;
time_t now;
char timebuf[26];
time(&now);
if (CO_get_config_logging() == 1) {
if (strcmp(CO_get_config_logfile(), "stdout") == 0) {
printf(LOG_CONFIG, TH_get_id(), user, status, ctime_r(&now, timebuf));
}
else {
logf = fopen(CO_get_config_logfile(), "a");
fprintf(logf, LOG_CONFIG, TH_get_id(), user, status, ctime_r(&now, timebuf));
fclose(logf);
}
}
} /* log_config() */
/* XXX Doh! These only change the server's terminal. We need some
tricky escape sequence to send over the socket.
static void echo_off(int sock) {
struct termio state;
ioctl(0, TIOCGETP, &state);
state.c_lflag &= ~ECHO;
ioctl(0, TIOCSETP, &state);
} echo_off() */
/* XXX Doh! These only change the server's terminal. We need some
tricky escape sequence to send over the socket.
static void echo_on(int sock) {
struct termio state;
ioctl(0, TIOCGETP, &state);
state.c_lflag |= ECHO;
ioctl(0, TIOCSETP, &state);
} echo_on() */
static char *authenticate_user(sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
char *user = NULL;
const char Salt[2] = "DB";
char input[MAX_INPUT_SIZE];
int read_result;
char *password=NULL;
char *user_password=NULL;
char user_buf[10];
SK_cd_puts(condat, LOGIN_PROMPT);
read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
strncpy(user_buf, input, 10);
SK_cd_puts(condat, PASSWD_PROMPT);
/* XXX These aren't working.
SK_puts(sock, ECHO_ON);
echo_off(sock);
*/
read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
/* XXX These aren't working.
echo_on(sock);
SK_puts(sock, ECHO_OFF);
*/
password = crypt(input, Salt);
user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
if (user_password != NULL) {
if (strcmp(password, user_password) == 0) {
/*user = (char *)calloc(1, strlen(user_buf)+1);*/
dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);
strcpy(user, user_buf);
}
}
if (user == NULL) {
log_config(user_buf, "unsuccesful login attempt");
}
return user;
} /* authenticate_user() */
void PC_interact(int sock) {
/* [<][>][^][v][top][bottom][index][help] */
char input[MAX_INPUT_SIZE];
int connected = 1;
char *user=NULL;
sk_conn_st condat;
memset( &condat, 0, sizeof(condat));
condat.sock = sock;
SK_getpeerip(sock, &(condat.rIP));
condat.ip = SK_getpeername(sock);
/* Welcome the client */
SK_cd_puts(&condat, CO_get_welcome());
/* Authenticate the user */
if (CO_get_authenticate() == 1) {
user = authenticate_user(&condat);
}
else {
user="nobody";
}
if (user != NULL) {
/* Log admin logging on */
log_config(user, "logged on");
SK_cd_puts(&condat, CO_get_prompt());
while (condat.rtc==0 && connected) {
/* Read input */
SK_cd_gets(&condat, input, MAX_INPUT_SIZE);
connected = process_input(input, &condat);
}
/* Log admin logging off */
log_config(user, "logged off");
}
/* Close the socket */
SK_close(sock);
} /* PC_interact() */