diff --git a/config.c b/config.c
index ef31489..2d36301 100644
--- a/config.c
+++ b/config.c
@@ -15,6 +15,11 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+
+/* TODO:
+ * - Have each event protocol definition get its own configuration directives
+ */
+
#include "includes.h"
/* My global state */
@@ -23,6 +28,10 @@ const char *process_name = NULL;
struct rsa_public_key *public_key = NULL;
struct rsa_private_key *private_key = NULL;
+configuration *get_modifiable_conf(void) {
+ return conf;
+}
+
const configuration *get_conf(void) {
return conf;
}
@@ -51,100 +60,107 @@ STATUS set_rsa_keys(struct rsa_public_key *pub, struct rsa_private_key *priv) {
return ST_OK;
}
+STATUS read_rsa_keys(void) {
+ int res;
+ FILE *file;
+ uint8_t buf[1024];
+ struct rsa_private_key *priv;
+ struct rsa_public_key *pub;
+ uint8_t *buffer = NULL;
+ size_t n, size=0;
+
+ priv = talloc(conf, struct rsa_private_key);
+ pub = talloc(conf, struct rsa_public_key);
+
+ rsa_public_key_init (pub);
+ rsa_private_key_init (priv);
+
+ file = fopen(conf->rsa_key_file, "r");
+ if (file == NULL) {
+ DEBUG(0, "Can't open configured rsa key file: %s", conf->rsa_key_file);
+ exit(ST_CONFIGURATION_ERROR);
+ }
+
+ while (1) {
+ n = fread(&buf, 1, 1024, file);
+ buffer = talloc_realloc(conf, buffer, uint8_t, size + n);
+ memcpy(buffer + size, buf, n);
+ size += n;
+ if (n < 1024)
+ break;
+ }
+
+ fclose(file);
+
+ res = rsa_keypair_from_sexp(pub, priv, 0, size, buffer);
+
+ conf->public_key = pub;
+ conf->private_key = priv;
+
+ return res;
+}
STATUS read_configuration_file(TALLOC_CTX *mem_ctx)
{
GError *error = NULL;
- GKeyFile *keyfile = g_key_file_new ();
-
- if (!g_key_file_load_from_file (keyfile, CONFIGFILE, 0, &error)) {
- g_error (error->message);
- return ST_CONFIGURATION_ERROR;
- }
+ char *buf, *ptr;
conf = talloc(mem_ctx, configuration);
NO_MEM_RETURN(conf);
- conf->database_host = g_key_file_get_string(keyfile, "database",
- "host", &error);
- if (error) {
- fprintf(stderr, "No database host supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->database_name = g_key_file_get_string(keyfile, "database",
- "name", &error);
- if (error) {
- fprintf(stderr, "No database name supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->database_driver = g_key_file_get_string(keyfile, "database",
- "driver", &error);
- if (error) {
- fprintf(stderr, "No database driver supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->database_username = g_key_file_get_string(keyfile, "database",
- "username", &error);
- if (error) {
- fprintf(stderr, "No database username supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->database_password = g_key_file_get_string(keyfile, "database",
- "password", &error);
- if (error) {
- fprintf(stderr, "No database password supplied in the configuration.\n");
+ conf->keyfile = g_key_file_new ();
+
+ if (!g_key_file_load_from_file (conf->keyfile, CONFIGFILE, 0, &error)) {
+ g_error (error->message);
return ST_CONFIGURATION_ERROR;
}
- conf->log_file = g_key_file_get_string(keyfile, "siahsd", "log file", &error);
+ buf = g_key_file_get_string(conf->keyfile, "siahsd", "event handlers", &error);
if (error) {
fprintf(stderr, "No log file supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
- conf->log_level = g_key_file_get_integer(keyfile, "siahsd", "log level", &error);
+
+ DEBUG(0, "%s\n", buf);
+ /* Initialize the required event handler backends */
+ ptr = strtok(buf, " ");
+ if (ptr != NULL) {
+ do {
+ DEBUG(0, "%s\n", ptr);
+ if (strcmp(ptr, "database") == 0) {
+ database_init();
+ } else if (strcmp(ptr, "jsonbot") == 0) {
+ jsonbot_init();
+ }
+ } while((ptr = strtok(NULL, " ")) != NULL);
+ }
+
+ conf->log_file = g_key_file_get_string(conf->keyfile, "siahsd", "log file", &error);
+ if (error) {
+ fprintf(stderr, "No log file supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->log_level = g_key_file_get_integer(conf->keyfile, "siahsd", "log level", &error);
if (error) {
fprintf(stderr, "No log level supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
- conf->pid_file = g_key_file_get_string(keyfile, "siahsd", "pid file", &error);
+ conf->pid_file = g_key_file_get_string(conf->keyfile, "siahsd", "pid file", &error);
if (error) {
fprintf(stderr, "No pid file supplied in the configuration.\n");
return ST_CONFIGURATION_ERROR;
}
- conf->jsonbot_address = g_key_file_get_string(keyfile, "jsonbot", "address", &error);
- if (error) {
- fprintf(stderr, "No jsonbot address supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->jsonbot_port = g_key_file_get_integer(keyfile, "jsonbot", "port", &error);
- if (error) {
- fprintf(stderr, "No jsonbot port supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->jsonbot_aeskey = g_key_file_get_string(keyfile, "jsonbot", "aes key", &error);
- if (error) {
- fprintf(stderr, "No jsonbot aes key supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->jsonbot_password = g_key_file_get_string(keyfile, "jsonbot", "password", &error);
- if (error) {
- fprintf(stderr, "No jsonbot password supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->jsonbot_privmsg_to = g_key_file_get_string(keyfile, "jsonbot", "privmsg to", &error);
- if (error) {
- fprintf(stderr, "No jsonbot privsmg to supplied in the configuration.\n");
- return ST_CONFIGURATION_ERROR;
- }
- conf->foreground = g_key_file_get_boolean(keyfile, "siahsd", "foreground", &error);
+
+ conf->foreground = g_key_file_get_boolean(conf->keyfile, "siahsd", "foreground", &error);
if (error) {
conf->foreground = false;
}
- /* Optional parameters are protocol-specific */
- conf->siahs_port = g_key_file_get_integer(keyfile, "siahs", "port", &error);
- conf->secip_port = g_key_file_get_integer(keyfile, "secip", "port", &error);
- conf->rsa_key_file = g_key_file_get_string(keyfile, "secip", "rsa key file", &error);
+ /* Optional parameters are protocol-specific */
+ /* FIXME Warn the user when these aren't configured */
+ conf->siahs_port = g_key_file_get_integer(conf->keyfile, "siahs", "port", &error);
+ conf->secip_port = g_key_file_get_integer(conf->keyfile, "secip", "port", &error);
+ conf->rsa_key_file = g_key_file_get_string(conf->keyfile, "secip", "rsa key file", &error);
return ST_OK;
}
diff --git a/config.h b/config.h
index 9e3e65b..041b7ad 100644
--- a/config.h
+++ b/config.h
@@ -18,30 +18,49 @@
#define CONFIGFILE "/etc/siahsd.conf"
+typedef STATUS (*event_function)(TALLOC_CTX *mem_ctx, const char *prom, const char *code, const char *description);
+
typedef struct {
+ /* Global configuration */
+ char *log_file;
+ gint log_level;
+ gboolean foreground;
+ char *pid_file; /* FIXME Apparently the same for siahs and secip.. for now */
+
+ /* Alphatronics SIA-HS configuration */
+ gint siahs_port;
+
+ /* Vebon SecIP configuration */
+ gint secip_port;
+ char *rsa_key_file;
+
+ /* Database client configuration */
char *database_host;
char *database_username;
char *database_password;
char *database_name;
char *database_driver;
- gint siahs_port;
- char *log_file;
- gint log_level;
- gboolean foreground;
- char *pid_file;
- gint secip_port;
- char *rsa_key_file;
+
+ /* JSONbot client configuration */
char *jsonbot_address;
gint jsonbot_port;
char *jsonbot_aeskey;
char *jsonbot_password;
char *jsonbot_privmsg_to;
+
+ /* Global configuration based state */
+ GKeyFile *keyfile;
+ uint8_t event_handler_cnt;
+ event_function *event_handlers;
+ struct rsa_public_key *public_key;
+ struct rsa_private_key *private_key;
} configuration;
const configuration *get_conf(void);
-STATUS get_rsa_keys(struct rsa_public_key **pub, struct rsa_private_key **priv);
-STATUS set_rsa_keys(struct rsa_public_key *pub, struct rsa_private_key *priv);
+configuration *get_modifiable_conf(void);
+
+STATUS read_rsa_keys(void);
const char *get_process_name(void);
STATUS set_process_name(const char *name);
diff --git a/database.c b/database.c
index ca90b92..ae919d3 100644
--- a/database.c
+++ b/database.c
@@ -18,6 +18,8 @@
#include "includes.h"
+static dbi_conn conn;
+
/*
* talloc_quoted_string escapes quotes in a string and encapsulates it in quotes.
* It returns a pointer to talloc'ed memory, the quoted string.
@@ -45,7 +47,7 @@ static char *talloc_quoted_string(TALLOC_CTX *mem_ctx, const char *string) {
return ret;
}
-STATUS log_event_to_database(TALLOC_CTX *mem_ctx, dbi_conn conn, const char *prom, const char *code, const char *description) {
+STATUS log_event_to_database(TALLOC_CTX *mem_ctx, const char *prom, const char *code, const char *description) {
char *quoted_prom;
char *quoted_code;
char *quoted_long_code;
@@ -73,22 +75,60 @@ STATUS log_event_to_database(TALLOC_CTX *mem_ctx, dbi_conn conn, const char *pro
return ST_OK;
}
-STATUS connect_to_database(dbi_conn *conn)
+
+
+STATUS database_init(void)
{
- const configuration *conf = get_conf();
+ configuration *conf = get_modifiable_conf();
+ GError *error = NULL;
+
+ conf->database_host = g_key_file_get_string(conf->keyfile, "database",
+ "host", &error);
+ if (error) {
+ fprintf(stderr, "No database host supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->database_name = g_key_file_get_string(conf->keyfile, "database",
+ "name", &error);
+ if (error) {
+ fprintf(stderr, "No database name supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->database_driver = g_key_file_get_string(conf->keyfile, "database",
+ "driver", &error);
+ if (error) {
+ fprintf(stderr, "No database driver supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->database_username = g_key_file_get_string(conf->keyfile, "database",
+ "username", &error);
+ if (error) {
+ fprintf(stderr, "No database username supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->database_password = g_key_file_get_string(conf->keyfile, "database",
+ "password", &error);
+ if (error) {
+ fprintf(stderr, "No database password supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+
+ conf->event_handlers = talloc_realloc(conf, conf->event_handlers, event_function, conf->event_handler_cnt+1);
+ conf->event_handlers[conf->event_handler_cnt] = log_event_to_database;
+ conf->event_handler_cnt++;
DEBUG(1, "Connecting to %s database %s at %s as user %s", conf->database_driver,
conf->database_name, conf->database_host, conf->database_username);
dbi_initialize(NULL);
- *conn = dbi_conn_new(conf->database_driver);
- dbi_conn_set_option(*conn, "host", conf->database_host);
- dbi_conn_set_option(*conn, "username", conf->database_username);
- dbi_conn_set_option(*conn, "password", conf->database_password);
- dbi_conn_set_option(*conn, "dbname", conf->database_name);
- dbi_conn_set_option(*conn, "encoding", "UTF-8");
+ conn = dbi_conn_new(conf->database_driver);
+ dbi_conn_set_option(conn, "host", conf->database_host);
+ dbi_conn_set_option(conn, "username", conf->database_username);
+ dbi_conn_set_option(conn, "password", conf->database_password);
+ dbi_conn_set_option(conn, "dbname", conf->database_name);
+ dbi_conn_set_option(conn, "encoding", "UTF-8");
- if (dbi_conn_connect(*conn) < 0) {
+ if (dbi_conn_connect(conn) < 0) {
DEBUG(0, "Could not connect to the database");
return ST_DATABASE_FAILURE;
}
diff --git a/database.h b/database.h
index 9daf99d..c5be413 100644
--- a/database.h
+++ b/database.h
@@ -16,5 +16,5 @@
along with this program. If not, see .
*/
-STATUS log_event_to_database(TALLOC_CTX *mem_ctx, dbi_conn conn, const char *prom, const char *code, const char *description);
-STATUS connect_to_database(dbi_conn *conn);
+STATUS log_event_to_database(TALLOC_CTX *mem_ctx, const char *prom, const char *code, const char *description);
+STATUS database_init(void);
diff --git a/jsonbot.c b/jsonbot.c
index 8e39d7a..ce11fa1 100644
--- a/jsonbot.c
+++ b/jsonbot.c
@@ -21,7 +21,7 @@
#include
-STATUS jsonbot_notify(TALLOC_CTX *mem_ctx, dbi_conn conn, const char *prom, const char *code, const char *description)
+STATUS jsonbot_notify(TALLOC_CTX *mem_ctx, const char *prom, const char *code, const char *description)
{
int sockfd;
struct sockaddr_in servaddr;
@@ -77,3 +77,40 @@ STATUS jsonbot_notify(TALLOC_CTX *mem_ctx, dbi_conn conn, const char *prom, cons
return ST_OK;
}
+
+STATUS jsonbot_init(void) {
+ GError *error = NULL;
+ configuration *conf = get_modifiable_conf();
+
+ conf->jsonbot_address = g_key_file_get_string(conf->keyfile, "jsonbot", "address", &error);
+ if (error) {
+ fprintf(stderr, "No jsonbot address supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->jsonbot_port = g_key_file_get_integer(conf->keyfile, "jsonbot", "port", &error);
+ if (error) {
+ fprintf(stderr, "No jsonbot port supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->jsonbot_aeskey = g_key_file_get_string(conf->keyfile, "jsonbot", "aes key", &error);
+ if (error) {
+ fprintf(stderr, "No jsonbot aes key supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->jsonbot_password = g_key_file_get_string(conf->keyfile, "jsonbot", "password", &error);
+ if (error) {
+ fprintf(stderr, "No jsonbot password supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+ conf->jsonbot_privmsg_to = g_key_file_get_string(conf->keyfile, "jsonbot", "privmsg to", &error);
+ if (error) {
+ fprintf(stderr, "No jsonbot privsmg to supplied in the configuration.\n");
+ return ST_CONFIGURATION_ERROR;
+ }
+
+ conf->event_handlers = talloc_realloc(conf, conf->event_handlers, event_function, conf->event_handler_cnt+1);
+ conf->event_handlers[conf->event_handler_cnt] = jsonbot_notify;
+ conf->event_handler_cnt++;
+
+ return ST_OK;
+}
diff --git a/jsonbot.h b/jsonbot.h
index f1df4c0..caa0848 100644
--- a/jsonbot.h
+++ b/jsonbot.h
@@ -18,4 +18,5 @@
*/
-STATUS jsonbot_notify(TALLOC_CTX *mem_ctx, dbi_conn conn, const char *prom, const char *code, const char *description);
+STATUS jsonbot_notify(TALLOC_CTX *mem_ctx, const char *prom, const char *code, const char *description);
+STATUS jsonbot_init(void);
diff --git a/secipd.c b/secipd.c
index 236fe1a..067b2ab 100644
--- a/secipd.c
+++ b/secipd.c
@@ -18,55 +18,15 @@
#include "includes.h"
#include "build/ndr_secip.h"
-static int read_rsa_keys(void) {
- int res;
- FILE *file;
- uint8_t buf[1024];
- struct rsa_private_key *priv;
- struct rsa_public_key *pub;
- const configuration *conf = get_conf();
- uint8_t *buffer = NULL;
- size_t n, size=0;
- priv = talloc(conf, struct rsa_private_key);
- pub = talloc(conf, struct rsa_public_key);
-
- rsa_public_key_init (pub);
- rsa_private_key_init (priv);
-
- file = fopen(conf->rsa_key_file, "r");
- if (file == NULL) {
- DEBUG(0, "Can't open configured rsa key file: %s", conf->rsa_key_file);
- exit(ST_CONFIGURATION_ERROR);
- }
-
- while (1) {
- n = fread(&buf, 1, 1024, file);
- buffer = talloc_realloc(conf, buffer, uint8_t, size + n);
- memcpy(buffer + size, buf, n);
- size += n;
- if (n < 1024)
- break;
- }
-
- fclose(file);
-
- res = rsa_keypair_from_sexp(pub, priv, 0, size, buffer);
-
- set_rsa_keys(pub, priv);
-
- return res;
-}
-
-STATUS send_ppk_com(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
+static STATUS send_ppk_com(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, struct secip_packet *pkt) {
struct secip_setup_packet *setup_pkt;
struct secip_out_packet *ppk_com;
DATA_BLOB raw_pkt, raw_setup_pkt;
enum ndr_err_code ndr_err;
size_t n;
- struct rsa_private_key *priv;
- struct rsa_public_key *pub;
size_t count;
+ const configuration *conf = get_conf();
setup_pkt = talloc_zero(mem_ctx, struct secip_setup_packet);
@@ -78,9 +38,7 @@ STATUS send_ppk_com(TALLOC_CTX *mem_ctx, int sock, struct sockaddr_in from, stru
memcpy(ppk_com->device_id, "MyFirstAlarm[TM]", strlen("MyFirstAlarm[TM]"));
ppk_com->msg.ppk_com.session_id = 0;
- get_rsa_keys(&pub, &priv);
-
- mpz_export(&ppk_com->msg.ppk_com.rsa_key, &count, 1, 4, 1, 0, pub->n);
+ mpz_export(&ppk_com->msg.ppk_com.rsa_key, &count, 1, 4, 1, 0, conf->public_key->n);
DEBUG(0, "RSA Words written: %u", count);
printf("%s\n", ndr_print_struct_string(pkt,(ndr_print_fn_t)ndr_print_secip_out_packet, "ppk_com packet", ppk_com));
@@ -116,7 +74,6 @@ int main (int argc, char **argv) {
struct sockaddr_in server;
struct sockaddr_in from;
TALLOC_CTX *mem_ctx;
- dbi_conn conn;
STATUS rv;
FILE *pidfile;
pid_t pid;
@@ -176,11 +133,6 @@ int main (int argc, char **argv) {
DEBUG(0, "Started %s and waiting for SecIP packets on port %d",
get_process_name(), conf->secip_port);
- /* Open a connection to the database */
- rv = connect_to_database(&conn);
- if (rv != ST_OK)
- return rv;
-
/*
* Wait for packets
*/
diff --git a/siahsd.c b/siahsd.c
index b6477a4..8375609 100644
--- a/siahsd.c
+++ b/siahsd.c
@@ -34,12 +34,14 @@
* and writes the event to the database.
* It returns nothing.
*/
-STATUS parse_message(TALLOC_CTX *mem_ctx, dbi_conn conn, struct siahs_packet *pkt) {
+STATUS parse_message(TALLOC_CTX *mem_ctx, struct siahs_packet *pkt) {
char *message = talloc_strdup(mem_ctx, pkt->message + strlen("MESSAGE "));
char *ptr = message;
char *prom = ptr;
char *pkt_prom;
char *code;
+ const configuration *conf = get_conf();
+ uint8_t i;
NO_MEM_RETURN(message);
@@ -75,8 +77,10 @@ STATUS parse_message(TALLOC_CTX *mem_ctx, dbi_conn conn, struct siahs_packet *pk
return ST_OK;
}
- log_event_to_database(message, conn, prom, code, ptr);
- jsonbot_notify(message, conn, prom, code, ptr);
+ /* Dispatch all configured event handlers */
+ for (i = 0; conf->event_handlers[i] != NULL; i++) {
+ conf->event_handlers[i](message, prom, code, ptr);
+ }
talloc_free(message);
@@ -156,7 +160,6 @@ int main(int argc, char **argv) {
struct sockaddr_in server;
struct sockaddr_in from;
TALLOC_CTX *mem_ctx;
- dbi_conn conn;
STATUS rv;
FILE *pidfile;
pid_t pid;
@@ -216,11 +219,6 @@ int main(int argc, char **argv) {
DEBUG(0, "Started %s and waiting for SIA-HS packets on port %d",
get_process_name(), conf->siahs_port);
- /* Open a connection to the database */
- rv = connect_to_database(&conn);
- if (rv != ST_OK)
- return rv;
-
/*
* Wait for packets
*/
@@ -306,7 +304,7 @@ int main(int argc, char **argv) {
} else if (strncmp(pkt->message, "MESSAGE ", strlen("MESSAGE ")) == 0) {
send_reply(pkt, sock, from, pkt, "ACKNOWLEDGE MESSAGE");
- parse_message(pkt, conn, pkt);
+ parse_message(pkt, pkt);
} else {
DEBUG(0, "Could not parse this message:\n"
diff --git a/siahsd.conf b/siahsd.conf
index 73a95f8..5b6ddaf 100644
--- a/siahsd.conf
+++ b/siahsd.conf
@@ -3,6 +3,7 @@ pid file = /var/run/siahsd.pid
log file = /var/log/siahsd/siahsd.log
log level = 3
foreground = 1
+event handlers = database jsonbot
[database]
driver = mysql
diff --git a/status.c b/status.c
index 5b3c05f..e1c693e 100644
--- a/status.c
+++ b/status.c
@@ -33,8 +33,11 @@ STATUS debug(int loglevel, const char *location, const char *function, ...)
}
logfile = fopen(conf->log_file, "a");
- if (logfile == NULL && conf->foreground) {
- fprintf(stderr, "Error opening log file: %s\n", strerror(errno));
+ if (logfile == NULL) {
+ if (conf->foreground) {
+ fprintf(stderr, "Error opening log file: %s\n", strerror(errno));
+ }
+ return ST_GENERAL_FAILURE;
}
time(&rawtime);
diff --git a/wscript b/wscript
index 62b66f4..1d95917 100644
--- a/wscript
+++ b/wscript
@@ -90,7 +90,7 @@ def configure(conf):
def build(bld):
bld.stlib(source="database.c", target="database", use='glib-2.0')
bld.stlib(source="status.c", target="status", use='glib-2.0')
- bld.stlib(source="config.c", target="config", use='glib-2.0')
+ bld.stlib(source="config.c", target="config", use='glib-2.0 database jsonbot')
bld.stlib(source="sia.c", target="sia", use='glib-2.0')
bld.stlib(source="jsonbot.c", target="jsonbot", use='glib-2.0')