diff --git a/audisp/plugins/af_unix/Makefile.am b/audisp/plugins/af_unix/Makefile.am index 501b35d43..e8faec7df 100644 --- a/audisp/plugins/af_unix/Makefile.am +++ b/audisp/plugins/af_unix/Makefile.am @@ -25,7 +25,8 @@ CONFIG_CLEAN_FILES = *.rej *.orig CONF_FILES = af_unix.conf EXTRA_DIST = $(CONF_FILES) $(man_MANS) -AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/lib -I${top_srcdir}/common +AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/lib -I${top_srcdir}/common -I${top_srcdir}/audisp +LIBS = ${top_builddir}/lib/libaudit.la prog_confdir = $(sysconfdir)/audit plugin_confdir=$(prog_confdir)/plugins.d plugin_conf = af_unix.conf diff --git a/audisp/plugins/af_unix/audisp-af_unix.c b/audisp/plugins/af_unix/audisp-af_unix.c index ffbf2ac07..d85f15f8a 100644 --- a/audisp/plugins/af_unix/audisp-af_unix.c +++ b/audisp/plugins/af_unix/audisp-af_unix.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -43,16 +44,19 @@ #endif #include "libaudit.h" #include "common.h" +#include "audispd-pconfig.h" #define DEFAULT_PATH "/var/run/audispd_events" +#define MAX_AUDIT_EVENT_FRAME_SIZE (sizeof(struct audit_dispatcher_header) + MAX_AUDIT_MESSAGE_LENGTH) //#define DEBUG /* Global Data */ static volatile int stop = 0, hup = 0; -char rx_buf[MAX_AUDIT_MESSAGE_LENGTH]; +char rx_buf[MAX_AUDIT_EVENT_FRAME_SIZE+1]; int sock = -1, conn = -1, client = 0; struct pollfd pfd[3]; unsigned mode = 0; +format_t format = -1; char *path = NULL; /* @@ -119,77 +123,150 @@ int create_af_unix_socket(const char *spath, int mode) int setup_socket(int argc, char *argv[]) { - if (argc != 3) { - syslog(LOG_ERR, "Missing arguments, using defaults"); - mode = 0640; - path = DEFAULT_PATH; - } else { - int i; - for (i=1; i < 3; i++) { - if (isdigit((unsigned char)argv[i][0])) { - errno = 0; - mode = strtoul(argv[i], NULL, 8); - if (errno) { - syslog(LOG_ERR, - "Error converting %s (%s)", - argv[i], strerror(errno)); - mode = 0; - } - } else { - char *base; - path = argv[i]; - // Make sure there are directories - base = strchr(path, '/'); - if (base) { - DIR *d; - char *dir = strdup(path); - base = dirname(dir); - d = opendir(base); - if (d) { - closedir(d); - unlink(path); - free(dir); - } else { - syslog(LOG_ERR, - "Couldn't open %s (%s)", - base, strerror(errno)); - free(dir); - exit(1); - } - + for (int i = 1; i < argc; i++) { + char *arg = argv[i]; + if (isdigit((unsigned char)arg[0])) { + // parse mode + errno = 0; + mode = strtoul(arg, NULL, 8); + if (errno) { + syslog(LOG_ERR, + "Error converting %s (%s)", + arg[i], strerror(errno)); + mode = 0; + } + } else if (strchr(arg, '/') != NULL) { + // parse path + char* base; + path = arg; + // Make sure there are directories + base = strchr(path, '/'); + if (base) { + DIR* d; + char* dir = strdup(path); + base = dirname(dir); + d = opendir(base); + if (d) { + closedir(d); + unlink(path); + free(dir); } else { - syslog(LOG_ERR, "Malformed path %s", - path); + syslog(LOG_ERR, + "Couldn't open %s (%s)", + base, strerror(errno)); + free(dir); exit(1); } + + } else { + syslog(LOG_ERR, "Malformed path %s", + path); + exit(1); } - } - if (mode == 0 || path == NULL) { - syslog(LOG_ERR, "Bad arguments, using defaults"); - mode = 0640; - path = DEFAULT_PATH; + } else { + if (strcmp(arg, "string") == 0) + format = F_STRING; + else if (strcmp(arg, "binary") == 0) + format = F_BINARY; + else + syslog(LOG_ERR, "Invalid format detected"); } } + + if (mode == 0 || path == NULL || format == -1) { + syslog(LOG_ERR, "Bad or not enough arguments, using defaults"); + mode = 0640; + path = DEFAULT_PATH; + format = F_STRING; + } + return create_af_unix_socket(path, mode); } +static int event_to_string(struct audit_dispatcher_header *hdr, char *data, char **out, int *outlen) +{ + char *v = NULL, *ptr, unknown[32]; + int len; + + if (hdr->ver == AUDISP_PROTOCOL_VER) { + const char *type; + + /* Get the event formatted */ + type = audit_msg_type_to_name(hdr->type); + if (type == NULL) { + snprintf(unknown, sizeof(unknown), + "UNKNOWN[%u]", hdr->type); + type = unknown; + } + len = asprintf(&v, "type=%s msg=%.*s\n", + type, hdr->size, data); + // Protocol 2 events are already formatted + } else if (hdr->ver == AUDISP_PROTOCOL_VER2) { + len = asprintf(&v, "%.*s\n", hdr->size, data); + } else + len = 0; + if (len <= 0) { + *out = NULL; + *outlen = 0; + return -1; + } + + /* Strip newlines from event record */ + ptr = v; + while ((ptr = strchr(ptr, 0x0A)) != NULL) { + if (ptr != &v[len-1]) + *ptr = ' '; + else + break; /* Done - exit loop */ + } + + *out = v; + *outlen = len; + return 1; +} + void read_audit_record(int ifd) { do { int len; // Read stdin - if ((len = audit_fgets(rx_buf, sizeof(rx_buf), ifd)) > 0) { + if ((len = audit_fgets(rx_buf, MAX_AUDIT_EVENT_FRAME_SIZE + 1, ifd)) > 0) { #ifdef DEBUG write(1, rx_buf, len); #else + struct audit_dispatcher_header *hdr = (struct audit_dispatcher_header *)rx_buf; + char *data = rx_buf + sizeof(struct audit_dispatcher_header); if (client) { // Send it to the client int rc; - do { - rc = write(conn, rx_buf, len); - } while (rc < 0 && errno == EINTR); + if (format == F_STRING) { + + char *str = NULL; + int str_len = 0; + if (event_to_string(hdr, data, &str, &str_len) < 0) { + // what to do with error? + continue; + } + + do { + rc = write(conn, str, str_len); + } while (rc < 0 && errno == EINTR); + } else if (format == F_BINARY) { + struct iovec vec[2]; + + vec[0].iov_base = hdr; + vec[0].iov_len = sizeof(struct audit_dispatcher_header); + + vec[1].iov_base = data; + vec[1].iov_len = MAX_AUDIT_MESSAGE_LENGTH; + + do { + rc = writev(conn, vec, 2); + } while (rc < 0 && errno == EINTR); + } + if (rc < 0 && errno == EPIPE) { close(conn); conn = -1; @@ -203,7 +280,7 @@ void read_audit_record(int ifd) #endif } else if (audit_fgets_eof()) stop = 1; - } while (audit_fgets_more(sizeof(rx_buf))); + } while (audit_fgets_more(MAX_AUDIT_EVENT_FRAME_SIZE)); } void accept_connection(void)