From 8a5b02b30e67d47b354ecaef0e93b76ad425785d Mon Sep 17 00:00:00 2001 From: laforge Date: Sat, 24 Apr 2004 22:50:55 +0000 Subject: - add .init and .fini member to output plugin - defer file opens + other initialization until after setuid() was called - cosmetic cleanup (no _ in static functions, use 'static' whenever possible) --- TODO | 1 + extensions/ulogd_LOGEMU.c | 36 ++++++++++++++------- extensions/ulogd_OPRINT.c | 47 +++++++++++++++------------- extensions/ulogd_SYSLOG.c | 27 +++++++++++++--- include/ulogd/ulogd.h | 6 +++- mysql/ulogd_MYSQL.c | 43 +++++++++++++++++--------- pcap/ulogd_PCAP.c | 45 ++++++++++++++------------- pgsql/ulogd_PGSQL.c | 36 ++++++++++++++------- ulogd.c | 79 ++++++++++++++++++++++++++++++++++++++++------- 9 files changed, 223 insertions(+), 97 deletions(-) diff --git a/TODO b/TODO index 919d31b..3ab6194 100644 --- a/TODO +++ b/TODO @@ -31,6 +31,7 @@ X pcap output plugin (to use ethereal/tcpdump/... for the logs) used by any of the running output plugins - issues with ulogd_BASE and partially copied packets (--ulog-cprange) - problem wrt. ulogd_BASE and fragments +- implement extension SIGHUP handlers (including config re-parse) conffile: - rewrite parser. This stuff is a real mess. Anybody interested? diff --git a/extensions/ulogd_LOGEMU.c b/extensions/ulogd_LOGEMU.c index d8a9b5f..049bcd4 100644 --- a/extensions/ulogd_LOGEMU.c +++ b/extensions/ulogd_LOGEMU.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: ulogd_LOGEMU.c,v 1.15 2003/09/28 15:19:26 laforge Exp $ + * $Id$ * */ @@ -57,7 +57,7 @@ static config_entry_t syslsync_ce = { &syslogf_ce, "sync", static FILE *of = NULL; -int _output_logemu(ulog_iret_t *res) +static int _output_logemu(ulog_iret_t *res) { static char buf[4096]; @@ -71,7 +71,7 @@ int _output_logemu(ulog_iret_t *res) return 0; } -void sighup_handler_logemu(int signal) +static void signal_handler_logemu(int signal) { switch (signal) { case SIGHUP: @@ -90,14 +90,7 @@ void sighup_handler_logemu(int signal) } -static ulog_output_t logemu_op = - { NULL, "syslogemu", &_output_logemu, &sighup_handler_logemu }; - -void _init(void) -{ - /* FIXME: error handling */ - config_parse_file("LOGEMU", &syslsync_ce); - +static int init_logemu(void) { #ifdef DEBUG_LOGEMU of = stdout; #else @@ -112,5 +105,26 @@ void _init(void) ulogd_log(ULOGD_ERROR, "can't resolve all keyhash id's\n"); } + return 1; +} + +static void fini_logemu(void) { + if (of != stdout) + fclose(of); +} + +static ulog_output_t logemu_op = { + .name = "syslogemu", + .init = &init_logemu, + .fini = &fini_logemu, + .output = &_output_logemu, + .signal = &signal_handler_logemu, +}; + +void _init(void) +{ + /* FIXME: error handling */ + config_parse_file("LOGEMU", &syslsync_ce); + register_output(&logemu_op); } diff --git a/extensions/ulogd_OPRINT.c b/extensions/ulogd_OPRINT.c index fdee135..186e3c9 100644 --- a/extensions/ulogd_OPRINT.c +++ b/extensions/ulogd_OPRINT.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: ulogd_OPRINT.c,v 1.9 2002/12/09 14:42:43 laforge Exp $ + * $Id$ * */ @@ -45,7 +45,7 @@ static FILE *of = NULL; -int _output_print(ulog_iret_t *res) +static int _output_print(ulog_iret_t *res) { ulog_iret_t *ret; @@ -83,7 +83,7 @@ static config_entry_t outf_ce = { NULL, "file", CONFIG_TYPE_STRING, CONFIG_OPT_NONE, 0, { string: ULOGD_OPRINT_DEFAULT } }; -void sighup_handler_print(int signal) +static void sighup_handler_print(int signal) { switch (signal) { @@ -102,22 +102,7 @@ void sighup_handler_print(int signal) } } -static ulog_output_t base_op[] = { - { NULL, "oprint", &_output_print, &sighup_handler_print }, - { NULL, "", NULL, NULL }, -}; - - -static void _base_reg_op(void) -{ - ulog_output_t *op = base_op; - ulog_output_t *p; - - for (p = op; p->output; p++) - register_output(p); -} - -void _init(void) +static int oprint_init(void) { #ifdef DEBUG of = stdout; @@ -131,6 +116,26 @@ void _init(void) exit(2); } #endif - - _base_reg_op(); + return 0; +} + +static void oprint_fini(void) +{ + if (of != stdout) + fclose(of); + + return; +} + +static ulog_output_t oprint_op = { + .name = "oprint", + .output = &_output_print, + .signal = &sighup_handler_print, + .init = &oprint_init, + .fini = &oprint_fini, +}; + +void _init(void) +{ + register_output(&oprint_op); } diff --git a/extensions/ulogd_SYSLOG.c b/extensions/ulogd_SYSLOG.c index 1be22d7..cb87fa9 100644 --- a/extensions/ulogd_SYSLOG.c +++ b/extensions/ulogd_SYSLOG.c @@ -57,7 +57,7 @@ static config_entry_t level_ce = { static int syslog_level, syslog_facility; -int _output_syslog(ulog_iret_t *res) +static int _output_syslog(ulog_iret_t *res) { static char buf[4096]; @@ -67,11 +67,8 @@ int _output_syslog(ulog_iret_t *res) return 0; } -static ulog_output_t syslog_op = { NULL, "syslog", &_output_syslog, NULL }; - -void _init(void) +static int syslog_init(void) { - /* FIXME: error handling */ config_parse_file("SYSLOG", &level_ce); @@ -125,6 +122,26 @@ void _init(void) exit(2); } + openlog("ulogd", LOG_NDELAY|LOG_PID, syslog_facility); + + return 0; +} + +static void syslog_fini(void) +{ + closelog(); +} + +static ulog_output_t syslog_op = { + .name = "syslog", + .init = &syslog_init, + .fini = &syslog_fini, + .output &_output_syslog +}; + + +void _init(void) +{ if (printpkt_init()) ulogd_log(ULOGD_ERROR, "can't resolve all keyhash id's\n"); diff --git a/include/ulogd/ulogd.h b/include/ulogd/ulogd.h index 8ad1692..d79fbba 100644 --- a/include/ulogd/ulogd.h +++ b/include/ulogd/ulogd.h @@ -9,7 +9,7 @@ * * this code is released under the terms of GNU GPL * - * $Id: ulogd.h,v 1.16 2002/06/13 12:55:59 laforge Exp $ + * $Id$ */ #include @@ -107,6 +107,10 @@ typedef struct ulog_output { struct ulog_output *next; /* name of this ouput plugin */ char name[ULOGD_MAX_KEYLEN]; + /* callback for initialization */ + int (*init)(void); + /* callback for de-initialization */ + void (*fini)(void); /* callback function */ int (*output)(ulog_iret_t *ret); /* callback function for signals (SIGHUP, ..) */ diff --git a/mysql/ulogd_MYSQL.c b/mysql/ulogd_MYSQL.c index 64405c3..74e033b 100644 --- a/mysql/ulogd_MYSQL.c +++ b/mysql/ulogd_MYSQL.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: ulogd_MYSQL.c,v 1.15 2003/09/29 11:02:40 laforge Exp $ + * $Id$ * * 15 May 2001, Alex Janssen : * Added a compability option for older MySQL-servers, which @@ -86,7 +86,7 @@ static config_entry_t table_ce = { &pass_ce, "table", CONFIG_TYPE_STRING, { } }; /* our main output function, called by ulogd */ -static int _mysql_output(ulog_iret_t *result) +static int mysql_output(ulog_iret_t *result) { struct _field *f; ulog_iret_t *res; @@ -199,7 +199,7 @@ static int _mysql_output(ulog_iret_t *result) #define MYSQL_VALSIZE 100 /* create the static part of our insert statement */ -static int _mysql_createstmt(void) +static int mysql_createstmt(void) { struct _field *f; unsigned int size; @@ -251,7 +251,7 @@ static int _mysql_createstmt(void) } /* find out which columns the table has */ -static int _mysql_get_columns(const char *table) +static int mysql_get_columns(const char *table) { MYSQL_RES *result; MYSQL_FIELD *field; @@ -300,7 +300,7 @@ static int _mysql_get_columns(const char *table) } /* make connection and select database */ -static int _mysql_open_db(char *server, char *user, char *pass, char *db) +static int mysql_open_db(char *server, char *user, char *pass, char *db) { dbh = mysql_init(NULL); if (!dbh) @@ -312,25 +312,40 @@ static int _mysql_open_db(char *server, char *user, char *pass, char *db) return 0; } -static ulog_output_t _mysql_plugin = { NULL, "mysql", &_mysql_output, NULL }; - -void _init(void) +static int mysql_init(void) { /* have the opts parsed */ config_parse_file("MYSQL", &table_ce); - if (_mysql_open_db(host_ce.u.string, user_ce.u.string, + if (mysql_open_db(host_ce.u.string, user_ce.u.string, pass_ce.u.string, db_ce.u.string)) { ulogd_log(ULOGD_ERROR, "can't establish database connection\n"); - return; + return -1; } /* read the fieldnames to know which values to insert */ - if (_mysql_get_columns(table_ce.u.string)) { + if (mysql_get_columns(table_ce.u.string)) { ulogd_log(ULOGD_ERROR, "unable to get mysql columns\n"); - return; + return -1; } - _mysql_createstmt(); - register_output(&_mysql_plugin); + mysql_createstmt(); + + return 0; +} + +static void mysql_fini(void) +{ + mysql_close(dbh); +} + +static ulog_output_t mysql_plugin = { + .name = "mysql", + .output = &mysql_output, + .init = &mysql_init, + .fini = &mysql_fini, +}; +void _init(void) +{ + register_output(&mysql_plugin); } diff --git a/pcap/ulogd_PCAP.c b/pcap/ulogd_PCAP.c index 32bd09e..e8af941 100644 --- a/pcap/ulogd_PCAP.c +++ b/pcap/ulogd_PCAP.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: ulogd_PCAP.c,v 1.7 2003/10/16 12:56:59 laforge Exp $ + * $Id$ * */ @@ -77,7 +77,7 @@ static struct intr_id intr_ids[INTR_IDS] = { #define GET_VALUE(x) ulogd_keyh[intr_ids[x].id].interp->result[ulogd_keyh[intr_ids[x].id].offset].value #define GET_FLAGS(x) ulogd_keyh[intr_ids[x].id].interp->result[ulogd_keyh[intr_ids[x].id].offset].flags -int _output_pcap(ulog_iret_t *res) +static int pcap_output(ulog_iret_t *res) { struct pcap_pkthdr pchdr; @@ -182,7 +182,7 @@ void append_create_outfile(void) { } } -void sighup_handler_pcap(int signal) +static void pcap_signal_handler(int signal) { switch (signal) { case SIGHUP: @@ -194,24 +194,8 @@ void sighup_handler_pcap(int signal) break; } } - -static ulog_output_t logemu_op[] = { - { NULL, "pcap", &_output_pcap, &sighup_handler_pcap }, - { NULL, "", NULL, NULL }, -}; - -/* register output plugin with ulogd */ -static void _logemu_reg_op(void) -{ - ulog_output_t *op = logemu_op; - ulog_output_t *p; - - for (p = op; p->output; p++) - register_output(p); -} - -void _init(void) +static int pcap_init(void) { /* FIXME: error handling */ config_parse_file("PCAP", &pcapsync_ce); @@ -221,9 +205,28 @@ void _init(void) #else append_create_outfile(); #endif + return 0; +} + +static void pcap_fini(void) +{ + if (of) + fclose(of); +} + +static ulog_output_t pcap_op = { + .name = "pcap", + .init = &pcap_init, + .fini = &pcap_fini, + .output = &pcap_output, + .signal = &pcap_signal_handler, +}; + +void _init(void) +{ if (get_ids()) { ulogd_log(ULOGD_ERROR, "can't resolve all keyhash id's\n"); } - _logemu_reg_op(); + register_output(&pcap_op); } diff --git a/pgsql/ulogd_PGSQL.c b/pgsql/ulogd_PGSQL.c index eb87c59..5a1551d 100644 --- a/pgsql/ulogd_PGSQL.c +++ b/pgsql/ulogd_PGSQL.c @@ -66,7 +66,7 @@ static config_entry_t table_ce = { &pass_ce, "table", CONFIG_TYPE_STRING, { } }; /* our main output function, called by ulogd */ -static int _pgsql_output(ulog_iret_t *result) +static int pgsql_output(ulog_iret_t *result) { struct _field *f; ulog_iret_t *res; @@ -167,7 +167,7 @@ static int _pgsql_output(ulog_iret_t *result) #define PGSQL_VALSIZE 100 /* create the static part of our insert statement */ -static int _pgsql_createstmt(void) +static int pgsql_createstmt(void) { struct _field *f; unsigned int size; @@ -219,7 +219,7 @@ static int _pgsql_createstmt(void) } /* find out which columns the table has */ -static int _pgsql_get_columns(const char *table) +static int pgsql_get_columns(const char *table) { PGresult *result; char buf[ULOGD_MAX_KEYLEN]; @@ -287,7 +287,7 @@ int exit_nicely(PGconn *conn) } /* make connection and select database */ -static int _pgsql_open_db(char *server, char *user, char *pass, char *db) +static int pgsql_open_db(char *server, char *user, char *pass, char *db) { char connstr[80]; char * sql; @@ -313,26 +313,38 @@ static int _pgsql_open_db(char *server, char *user, char *pass, char *db) return 0; } - -static ulog_output_t _pgsql_plugin = { NULL, "pgsql", &_pgsql_output, NULL }; - -void _init(void) +static int pgsql_init(void) { /* have the opts parsed */ config_parse_file("PGSQL", &table_ca); - if (_pgsql_open_db(host_ce.u.string, user_ce.u.string, + if (pgsql_open_db(host_ce.u.string, user_ce.u.string, pass_ce.u.string, db_ce.u.string)) { ulogd_log(ULOGD_ERROR, "can't establish database connection\n"); return; } /* read the fieldnames to know which values to insert */ - if (_pgsql_get_columns(table_ce.u.string)) { + if (pgsql_get_columns(table_ce.u.string)) { ulogd_log(ULOGD_ERROR, "unable to get pgsql columns\n"); return; } - _pgsql_createstmt(); - register_output(&_pgsql_plugin); + pgsql_createstmt(); +} +static void pgsql_fini(void) +{ + PQfinish(dbh); +} + +static ulog_output_t pgsql_plugin = { + .name = "pgsql", + .output = &pgsql_output, + .init = &pgsql_init, + .fini = &pgsql_fini, +}; + +void _init(void) +{ + register_output(&pgsql_plugin); } diff --git a/ulogd.c b/ulogd.c index db6ecd8..27c10cd 100644 --- a/ulogd.c +++ b/ulogd.c @@ -32,6 +32,9 @@ * * 09 Sep 2003 Magnus Boden * - added support for more flexible multi-section conffile + * + * 20 Apr 2004 Nicolas Pougetoux + * - added suppurt for seteuid() */ #define ULOGD_VERSION "1.20" @@ -48,6 +51,8 @@ #include #include #include +#include +#include #include #include #include @@ -581,13 +586,15 @@ static void print_usage(void) { /* FIXME */ printf("ulogd Version %s\n", ULOGD_VERSION); - printf("Copyright (C) 2000-2003 Harald Welte " - "\n\n"); - printf("Paramters:\n"); + printf("Copyright (C) 2000-2004 Harald Welte " + "\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); + printf("Parameters:\n"); printf("\t-h --help\tThis help page\n"); printf("\t-V --version\tPrint version information\n"); printf("\t-d --daemon\tDaemonize (fork into background)\n"); printf("\t-c --configfile\tUse alternative Configfile\n"); + printf("\t-u --uid\tChange UID/GID\n"); } static struct option opts[] = { @@ -595,6 +602,7 @@ static struct option opts[] = { { "daemon", 0, NULL, 'd' }, { "help", 0, NULL, 'h' }, { "configfile", 1, NULL, 'c'}, + { "uid", 1, NULL, 'u' }, { 0 } }; @@ -603,9 +611,15 @@ int main(int argc, char* argv[]) int len; int argch; int daemonize = 0; + int change_uid = 0; + char *user = NULL; + struct passwd *pw; + uid_t uid = 0; + gid_t gid = 0; ulog_packet_msg_t *upkt; - while ((argch = getopt_long(argc, argv, "c:dh::V", opts, NULL)) != -1) { + + while ((argch = getopt_long(argc, argv, "c:dh::Vu:", opts, NULL)) != -1) { switch (argch) { default: case '?': @@ -633,6 +647,18 @@ int main(int argc, char* argv[]) case 'c': ulogd_configfile = optarg; break; + case 'u': + change_uid = 1; + user = strdup(optarg); + pw = getpwnam(user); + if (!pw) { + printf("Unknown user %s.\n", user); + free(user); + exit(1); + } + uid = pw->pw_uid; + gid = pw->pw_gid; + break; } } @@ -648,14 +674,6 @@ int main(int argc, char* argv[]) exit(1); } - logfile_open(logf_ce.u.string); - -#ifdef DEBUG - /* dump key and interpreter hash */ - interh_dump(); - keyh_dump(); -#endif - /* allocate a receive buffer */ libulog_buf = (unsigned char *) malloc(bufsiz_ce.u.value); @@ -677,6 +695,43 @@ int main(int argc, char* argv[]) exit(1); } + + if (change_uid) { + ulogd_log(ULOGD_NOTICE, "Changing UID / GID\n"); + if (setgid(gid)) { + ulogd_log(ULOGD_FATAL, "can't set GID\n"); + ipulog_perror(NULL); + exit(1); + } + if (setegid(gid)) { + ulogd_log(ULOGD_FATAL, "can't sett effective GID\n"); + ipulog_perror(NULL); + exit(1); + } + if (initgroups(user, gid)) { + ulogd_log(ULOGD_FATAL, "can't set user secondary GID\n"); + ipulog_perror(NULL); + exit(1); + } + if (setuid(uid)) { + ulogd_log(ULOGD_FATAL, "can't set UID\n"); + ipulog_perror(NULL); + exit(1); + } + if (seteuid(uid)) { + ulogd_log(ULOGD_FATAL, "can't set effective UID\n"); + ipulog_perror(NULL); + exit(1); + } + } + + logfile_open(logf_ce.u.string); + +#ifdef DEBUG + /* dump key and interpreter hash */ + interh_dump(); + keyh_dump(); +#endif if (daemonize){ if (fork()) { exit(0); -- cgit v1.2.3