aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/audisp/plugins/remote
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/audisp/plugins/remote')
-rw-r--r--framework/src/audit/audisp/plugins/remote/Makefile.am51
-rw-r--r--framework/src/audit/audisp/plugins/remote/au-remote.conf12
-rw-r--r--framework/src/audit/audisp/plugins/remote/audisp-remote.834
-rw-r--r--framework/src/audit/audisp/plugins/remote/audisp-remote.c1486
-rw-r--r--framework/src/audit/audisp/plugins/remote/audisp-remote.conf31
-rw-r--r--framework/src/audit/audisp/plugins/remote/audisp-remote.conf.5211
-rw-r--r--framework/src/audit/audisp/plugins/remote/notes.txt31
-rw-r--r--framework/src/audit/audisp/plugins/remote/queue.c574
-rw-r--r--framework/src/audit/audisp/plugins/remote/queue.h66
-rw-r--r--framework/src/audit/audisp/plugins/remote/remote-config.c780
-rw-r--r--framework/src/audit/audisp/plugins/remote/remote-config.h78
-rw-r--r--framework/src/audit/audisp/plugins/remote/remote-fgets.c123
-rw-r--r--framework/src/audit/audisp/plugins/remote/remote-fgets.h33
-rw-r--r--framework/src/audit/audisp/plugins/remote/test-queue.c367
14 files changed, 0 insertions, 3877 deletions
diff --git a/framework/src/audit/audisp/plugins/remote/Makefile.am b/framework/src/audit/audisp/plugins/remote/Makefile.am
deleted file mode 100644
index 8440e908..00000000
--- a/framework/src/audit/audisp/plugins/remote/Makefile.am
+++ /dev/null
@@ -1,51 +0,0 @@
-# Makefile.am --
-# Copyright 2008-2009,2011,2015 Red Hat Inc., Durham, North Carolina.
-# All Rights Reserved.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Authors:
-# Steve Grubb <sgrubb@redhat.com>
-#
-
-CONFIG_CLEAN_FILES = *.loT *.rej *.orig
-EXTRA_DIST = au-remote.conf audisp-remote.conf notes.txt $(man_MANS)
-AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/lib
-prog_confdir = $(sysconfdir)/audisp
-prog_conf = audisp-remote.conf
-plugin_confdir=$(prog_confdir)/plugins.d
-plugin_conf = au-remote.conf
-sbin_PROGRAMS = audisp-remote
-noinst_HEADERS = remote-config.h queue.h remote-fgets.h
-man_MANS = audisp-remote.8 audisp-remote.conf.5
-check_PROGRAMS = test-queue
-TESTS = $(check_PROGRAMS)
-
-audisp_remote_SOURCES = audisp-remote.c remote-config.c queue.c remote-fgets.c
-audisp_remote_CFLAGS = -fPIE -DPIE -g -D_REENTRANT -D_GNU_SOURCE -Wundef
-audisp_remote_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now $(gss_libs)
-audisp_remote_LDADD = $(CAPNG_LDADD)
-
-test_queue_SOURCES = queue.c test-queue.c
-
-install-data-hook:
- mkdir -p -m 0750 ${DESTDIR}${plugin_confdir}
- $(INSTALL_DATA) -D -m 640 ${srcdir}/$(plugin_conf) ${DESTDIR}${plugin_confdir}
- $(INSTALL_DATA) -D -m 640 ${srcdir}/$(prog_conf) ${DESTDIR}${prog_confdir}
-
-uninstall-hook:
- rm ${DESTDIR}${plugin_confdir}/$(plugin_conf)
- rm ${DESTDIR}${prog_confdir}/$(prog_conf)
-
diff --git a/framework/src/audit/audisp/plugins/remote/au-remote.conf b/framework/src/audit/audisp/plugins/remote/au-remote.conf
deleted file mode 100644
index e0adf96c..00000000
--- a/framework/src/audit/audisp/plugins/remote/au-remote.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-
-# This file controls the audispd data path to the
-# remote event logger. This plugin will send events to
-# a remote machine (Central Logger).
-
-active = no
-direction = out
-path = /sbin/audisp-remote
-type = always
-#args =
-format = string
-
diff --git a/framework/src/audit/audisp/plugins/remote/audisp-remote.8 b/framework/src/audit/audisp/plugins/remote/audisp-remote.8
deleted file mode 100644
index 6f3b5fe6..00000000
--- a/framework/src/audit/audisp/plugins/remote/audisp-remote.8
+++ /dev/null
@@ -1,34 +0,0 @@
-.TH AUDISP-REMOTE: "8" "Apr 2011" "Red Hat" "System Administration Utilities"
-.SH NAME
-audisp-remote \- plugin for remote logging
-.SH SYNOPSIS
-.B audisp-remote
-.SH DESCRIPTION
-\fBaudisp-remote\fP is a plugin for the audit event dispatcher daemon, audispd, that preforms remote logging to an aggregate logging server.
-
-.SH TIPS
-If you are aggregating multiple machines, you should enable node information in the audit event stream. You can do this in one of two places. If you want computer node names written to disk as well as sent in the realtime event stream, edit the name_format option in /etc/audit/auditd.conf. If you only want the node names in the realtime event stream, then edit the name_format option in /etc/audisp/audispd.conf. Do not enable both as it will put 2 node fields in the event stream.
-
-.SH SIGNALS
-.TP
-SIGUSR1
-Causes the audisp-remote program to write the value of some of its internal flags to syslog. The
-.IR suspend
-flag tells whether or not logging has been suspended. The
-.IR transport_ok
-flag tells whether or not the connection to the remote server is healthy. The
-.IR queue_size
-tells how many records are enqueued to be sent to the remote server.
-.TP
-SIGUSR2
-Causes the audisp-remote program to resume logging if it were suspended due to an error.
-
-.SH FILES
-/etc/audisp/plugins.d/au-remote.conf, /etc/audit/auditd.conf, /etc/audisp/audispd.conf, /etc/audisp/audisp-remote.conf
-.SH "SEE ALSO"
-.BR audispd (8),
-.BR auditd.conf(8),
-.BR audispd.conf(8),
-.BR audisp-remote.conf(5).
-.SH AUTHOR
-Steve Grubb
diff --git a/framework/src/audit/audisp/plugins/remote/audisp-remote.c b/framework/src/audit/audisp/plugins/remote/audisp-remote.c
deleted file mode 100644
index 2585c78c..00000000
--- a/framework/src/audit/audisp/plugins/remote/audisp-remote.c
+++ /dev/null
@@ -1,1486 +0,0 @@
-/* audisp-remote.c --
- * Copyright 2008-2012 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- *
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <signal.h>
-#include <syslog.h>
-#include <string.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <time.h>
-#include <fcntl.h>
-#include <sys/select.h>
-#include <poll.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#ifdef USE_GSSAPI
-#include <gssapi/gssapi.h>
-#include <gssapi/gssapi_generic.h>
-#include <krb5.h>
-#endif
-#ifdef HAVE_LIBCAP_NG
-#include <cap-ng.h>
-#endif
-#include "libaudit.h"
-#include "private.h"
-#include "remote-config.h"
-#include "queue.h"
-#include "remote-fgets.h"
-
-#define CONFIG_FILE "/etc/audisp/audisp-remote.conf"
-#define BUF_SIZE 32
-
-/* MAX_AUDIT_MESSAGE_LENGTH, aligned to 4 KB so that an average q_append() only
- writes to two disk disk blocks (1 aligned data block, 1 header block). */
-#define QUEUE_ENTRY_SIZE (3*4096)
-
-/* Error types */
-#define ET_SUCCESS 0
-#define ET_PERMANENT -1
-#define ET_TEMPORARY -2
-
-/* Global Data */
-static volatile int stop = 0;
-static volatile int hup = 0;
-static volatile int suspend = 0;
-static volatile int dump = 0;
-static volatile int transport_ok = 0;
-static volatile int sock=-1;
-static volatile int remote_ended = 0, quiet = 0;
-static int ifd;
-remote_conf_t config;
-
-/* Constants */
-static const char *SINGLE = "1";
-static const char *HALT = "0";
-static const char *INIT_PGM = "/sbin/init";
-static const char *SPOOL_FILE = "/var/spool/audit/remote.log";
-
-/* Local function declarations */
-static int check_message(void);
-static int relay_event(const char *s, size_t len);
-static int init_transport(void);
-static int stop_transport(void);
-static int ar_read (int, void *, int);
-static int ar_write (int, const void *, int);
-
-#ifdef USE_GSSAPI
-/* We only ever talk to one server, so we don't need per-connection
- credentials. These are the ones we talk to the server with. */
-gss_ctx_id_t my_context;
-
-#define REQ_FLAGS GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG
-#define USE_GSS (config.enable_krb5)
-#endif
-
-/* Compile-time expression verification */
-#define verify(E) do { \
- char verify__[(E) ? 1 : -1]; \
- (void)verify__; \
- } while (0)
-
-/*
- * SIGTERM handler
- */
-static void term_handler( int sig )
-{
- stop = 1;
-}
-
-/*
- * SIGHUP handler: re-read config
- */
-static void hup_handler( int sig )
-{
- hup = 1;
-}
-
-static void reload_config(void)
-{
- stop_transport(); // FIXME: We should only stop transport if necessary
- hup = 0;
-}
-
-/*
- * SIGSUR1 handler: dump stats
- */
-static void user1_handler( int sig )
-{
- dump = 1;
-}
-
-static void dump_stats(struct queue *queue)
-{
- syslog(LOG_INFO, "suspend=%s, transport_ok=%s, queue_size=%zu",
- suspend ? "yes" : "no",
- transport_ok ? "yes" : "no",
- q_queue_length(queue));
- dump = 0;
-}
-
-/*
- * SIGSUR2 handler: resume logging
- */
-static void user2_handler( int sig )
-{
- suspend = 0;
-}
-
-/*
- * SIGCHLD handler: reap exiting processes
- */
-static void child_handler(int sig)
-{
- while (waitpid(-1, NULL, WNOHANG) > 0)
- ; /* empty */
-}
-
-/*
- * Handlers for various events coming back from the remote server.
- * Return -1 if the remote dispatcher should exit.
- */
-
-/* Loss of sync - got an invalid response. */
-static int sync_error_handler (const char *why)
-{
- /* "why" has human-readable details on why we've lost (or will
- be losing) sync. Sync errors are transient - if a retry
- doesn't fix it, we eventually call network_failure_handler
- which has all the user-tweakable actions. */
- syslog (LOG_ERR, "lost/losing sync, %s", why);
- return 0;
-}
-
-static void change_runlevel(const char *level)
-{
- char *argv[3];
- int pid;
-
- pid = fork();
- if (pid < 0) {
- syslog(LOG_ALERT,
- "audisp-remote failed to fork switching runlevels");
- return;
- }
- if (pid) /* Parent */
- return;
-
- /* Child */
- argv[0] = (char *)INIT_PGM;
- argv[1] = (char *)level;
- argv[2] = NULL;
- execve(INIT_PGM, argv, NULL);
- syslog(LOG_ALERT, "audisp-remote failed to exec %s", INIT_PGM);
- exit(1);
-}
-
-static void safe_exec(const char *exe, const char *message)
-{
- char *argv[3];
- int pid;
-
- if (exe == NULL) {
- syslog(LOG_ALERT,
- "Safe_exec passed NULL for program to execute");
- return;
- }
-
- pid = fork();
- if (pid < 0) {
- syslog(LOG_ALERT,
- "audisp-remote failed to fork doing safe_exec");
- return;
- }
- if (pid) /* Parent */
- return;
-
- /* Child */
- argv[0] = (char *)exe;
- argv[1] = (char *)message;
- argv[2] = NULL;
- execve(exe, argv, NULL);
- syslog(LOG_ALERT, "audisp-remote failed to exec %s", exe);
- exit(1);
-}
-
-static int do_action (const char *desc, const char *message,
- int log_level,
- failure_action_t action, const char *exe)
-{
- switch (action)
- {
- case FA_IGNORE:
- return 0;
- case FA_SYSLOG:
- syslog (log_level, "%s, %s", desc, message);
- return 0;
- case FA_EXEC:
- safe_exec (exe, message);
- return 0;
- case FA_SUSPEND:
- syslog (log_level,
- "suspending remote logging due to %s", desc);
- suspend = 1;
- return 0;
- case FA_RECONNECT:
- syslog (log_level,
- "remote logging disconnected due to %s, will attempt reconnection",
- desc);
- return 0;
- case FA_SINGLE:
- syslog (log_level,
- "remote logging is switching system to single user mode due to %s",
- desc);
- change_runlevel(SINGLE);
- return -1;
- case FA_HALT:
- syslog (log_level,
- "remote logging halting system due to %s", desc);
- change_runlevel(HALT);
- return -1;
- case FA_STOP:
- syslog (log_level, "remote logging stopping due to %s, %s",
- desc, message);
- stop = 1;
- return -1;
- }
- syslog (log_level, "unhandled action %d for %s", action, desc);
- return -1;
-}
-
-static int network_failure_handler (const char *message)
-{
- return do_action ("network failure", message,
- LOG_WARNING,
- config.network_failure_action,
- config.network_failure_exe);
-}
-
-static int remote_disk_low_handler (const char *message)
-{
- return do_action ("remote server is low on disk space", message,
- LOG_WARNING,
- config.disk_low_action, config.disk_low_exe);
-}
-
-static int remote_disk_full_handler (const char *message)
-{
- return do_action ("remote server's disk is full", message,
- LOG_ERR,
- config.disk_full_action, config.disk_full_exe);
-}
-
-static int remote_disk_error_handler (const char *message)
-{
- return do_action ("remote server has a disk error", message,
- LOG_ERR,
- config.disk_error_action, config.disk_error_exe);
-}
-
-static int remote_server_ending_handler (const char *message)
-{
- stop_transport();
- remote_ended = 1;
- return do_action ("remote server is going down", message,
- LOG_NOTICE,
- config.remote_ending_action,
- config.remote_ending_exe);
-}
-
-static int generic_remote_error_handler (const char *message)
-{
- return do_action ("unrecognized remote error", message,
- LOG_ERR, config.generic_error_action,
- config.generic_error_exe);
-}
-
-static int generic_remote_warning_handler (const char *message)
-{
- return do_action ("unrecognized remote warning", message,
- LOG_WARNING,
- config.generic_warning_action,
- config.generic_warning_exe);
-}
-
-/* Report and handle a queue error, using errno. */
-static void queue_error(void)
-{
- char *errno_str;
-
- errno_str = strerror(errno);
- do_action("queue error", errno_str, LOG_ERR, config.queue_error_action,
- config.queue_error_exe);
-}
-
-static void send_heartbeat (void)
-{
- relay_event (NULL, 0);
-}
-
-static void do_overflow_action(void)
-{
- switch (config.overflow_action)
- {
- case OA_IGNORE:
- break;
- case OA_SYSLOG:
- syslog(LOG_ERR, "queue is full - dropping event");
- break;
- case OA_SUSPEND:
- syslog(LOG_ALERT,
- "Audisp-remote is suspending event processing due to overflowing its queue.");
- suspend = 1;
- break;
- case OA_SINGLE:
- syslog(LOG_ALERT,
- "Audisp-remote is now changing the system to single user mode due to overflowing its queue");
- change_runlevel(SINGLE);
- break;
- case OA_HALT:
- syslog(LOG_ALERT,
- "Audisp-remote is now halting the system due to overflowing its queue");
- change_runlevel(HALT);
- break;
- default:
- syslog(LOG_ALERT, "Unknown overflow action requested");
- break;
- }
-}
-
-/* Initialize and return a queue depending on user's configuration.
- On error return NULL and set errno. */
-static struct queue *init_queue(void)
-{
- const char *path;
- int q_flags;
-
- if (config.queue_file != NULL)
- path = config.queue_file;
- else
- path = SPOOL_FILE;
- q_flags = Q_IN_MEMORY;
- if (config.mode == M_STORE_AND_FORWARD)
- /* FIXME: let user control Q_SYNC? */
- q_flags |= Q_IN_FILE | Q_CREAT | Q_RESIZE;
- verify(QUEUE_ENTRY_SIZE >= MAX_AUDIT_MESSAGE_LENGTH);
- return q_open(q_flags, path, config.queue_depth, QUEUE_ENTRY_SIZE);
-}
-
-/* Send a record from QUEUE to the remote system */
-static void send_one(struct queue *queue)
-{
- char event[MAX_AUDIT_MESSAGE_LENGTH];
- int len;
-
- if (suspend || !transport_ok)
- return;
-
- len = q_peek(queue, event, sizeof(event));
- if (len == 0)
- return;
- if (len < 0) {
- queue_error();
- return;
- }
-
- /* We send len -1 to remove trailing \n */
- if (relay_event(event, len-1) < 0)
- return;
-
- if (q_drop_head(queue) != 0)
- queue_error();
-}
-
-int main(int argc, char *argv[])
-{
- struct sigaction sa;
- struct queue *queue;
- int rc;
- size_t q_len;
-
- /* Register sighandlers */
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- /* Set handler for the ones we care about */
- sa.sa_handler = term_handler;
- sigaction(SIGTERM, &sa, NULL);
- sa.sa_handler = hup_handler;
- sigaction(SIGHUP, &sa, NULL);
- sa.sa_handler = user1_handler;
- sigaction(SIGUSR1, &sa, NULL);
- sa.sa_handler = user2_handler;
- sigaction(SIGUSR2, &sa, NULL);
- sa.sa_handler = child_handler;
- sigaction(SIGCHLD, &sa, NULL);
- if (load_config(&config, CONFIG_FILE))
- return 6;
-
- (void) umask( umask( 077 ) | 027 );
- // ifd = open("test.log", O_RDONLY);
- ifd = 0;
- fcntl(ifd, F_SETFL, O_NONBLOCK);
-
- /* We fail here if the transport can't be initialized because of some
- * permanent (i.e. operator) problem, such as misspelled host name. */
- rc = init_transport();
- if (rc == ET_PERMANENT)
- return 1;
- queue = init_queue();
- if (queue == NULL) {
- syslog(LOG_ERR, "Error initializing audit record queue: %m");
- return 1;
- }
-
-#ifdef HAVE_LIBCAP_NG
- // Drop capabilities
- capng_clear(CAPNG_SELECT_BOTH);
- if (config.local_port && config.local_port < 1024)
- capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
- CAP_NET_BIND_SERVICE);
- capng_apply(CAPNG_SELECT_BOTH);
-#endif
- syslog(LOG_NOTICE, "Audisp-remote started with queue_size: %zu",
- q_queue_length(queue));
-
- while (stop == 0) { //FIXME break out when socket is closed
- fd_set rfd, wfd;
- struct timeval tv;
- char event[MAX_AUDIT_MESSAGE_LENGTH];
- int n, fds = ifd + 1;
-
- /* Load configuration */
- if (hup)
- reload_config();
-
- if (dump)
- dump_stats(queue);
-
- /* Setup select flags */
- FD_ZERO(&rfd);
- FD_SET(ifd, &rfd); // input fd
- FD_ZERO(&wfd);
- if (sock > 0) {
- // Setup socket to read acks from server
- FD_SET(sock, &rfd); // remote socket
- if (sock > ifd)
- fds = sock + 1;
- // If we have anything in the queue,
- // find out if we can send it
- if (q_queue_length(queue) && !suspend && transport_ok)
- FD_SET(sock, &wfd);
- }
-
- if (config.heartbeat_timeout > 0) {
- tv.tv_sec = config.heartbeat_timeout;
- tv.tv_usec = 0;
- n = select(fds, &rfd, &wfd, NULL, &tv);
- } else
- n = select(fds, &rfd, &wfd, NULL, NULL);
- if (n < 0)
- continue; // If here, we had some kind of problem
-
- if ((config.heartbeat_timeout > 0) && n == 0 && !remote_ended) {
- /* We attempt a hearbeat if select fails, which
- * may give us more heartbeats than we need. This
- * is safer than too few heartbeats. */
- quiet = 1;
- send_heartbeat();
- quiet = 0;
- continue;
- }
-
- // See if we got a shutdown message from the server
- if (sock > 0 && FD_ISSET(sock, &rfd))
- check_message();
-
- // If we broke out due to one of these, cycle to start
- if (hup != 0 || stop != 0)
- continue;
-
- // See if input fd is also set
- if (FD_ISSET(ifd, &rfd)) {
- do {
- if (remote_fgets(event, sizeof(event), ifd)) {
- if (!transport_ok && remote_ended &&
- config.remote_ending_action ==
- FA_RECONNECT) {
- quiet = 1;
- if (init_transport() ==
- ET_SUCCESS)
- remote_ended = 0;
- quiet = 0;
- }
- /* Strip out EOE records */
- if (*event == 't') {
- if (strncmp(event,
- "type=EOE", 8) == 0)
- continue;
- } else {
- char *ptr = strchr(event, ' ');
- if (ptr) {
- ptr++;
- if (strncmp(ptr,
- "type=EOE",
- 8) == 0)
- continue;
- } else
- continue; //malformed
- }
- if (q_append(queue, event) != 0) {
- if (errno == ENOSPC)
- do_overflow_action();
- else
- queue_error();
- }
- } else if (remote_fgets_eof())
- stop = 1;
- } while (remote_fgets_more(sizeof(event)));
- }
- // See if output fd is also set
- if (sock > 0 && FD_ISSET(sock, &wfd)) {
- // If so, try to drain backlog
- while (q_queue_length(queue) && !suspend &&
- !stop && transport_ok)
- send_one(queue);
- }
- }
- if (sock >= 0) {
- shutdown(sock, SHUT_RDWR);
- close(sock);
- }
- free_config(&config);
- q_len = q_queue_length(queue);
- q_close(queue);
- if (stop)
- syslog(LOG_NOTICE, "audisp-remote is exiting on stop request, queue_size: %zu", q_len);
-
- return q_len ? 1 : 0;
-}
-
-#ifdef USE_GSSAPI
-
-/* Communications under GSS is done by token exchanges. Each "token" may
- contain a message, perhaps signed, perhaps encrypted. The messages within
- are what we're interested in, but the network sees the tokens. The
- protocol we use for transferring tokens is to send the length first,
- four bytes MSB first, then the token data. We return nonzero on error. */
-static int recv_token(int s, gss_buffer_t tok)
-{
- int ret;
- unsigned char lenbuf[4];
- unsigned int len;
-
- ret = ar_read(s, (char *) lenbuf, 4);
- if (ret < 0) {
- syslog(LOG_ERR, "GSS-API error reading token length");
- return -1;
- } else if (!ret) {
- return 0;
- } else if (ret != 4) {
- syslog(LOG_ERR, "GSS-API error reading token length");
- return -1;
- }
-
- len = ( ((uint32_t)(lenbuf[0] & 0xFF) << 24)
- | ((uint32_t)(lenbuf[1] & 0xFF) << 16)
- | ((uint32_t)(lenbuf[2] & 0xFF) << 8)
- | (uint32_t)(lenbuf[3] & 0xFF));
-
- if (len > MAX_AUDIT_MESSAGE_LENGTH) {
- syslog(LOG_ERR,
- "GSS-API error: event length excedes MAX_AUDIT_LENGTH");
- return -1;
- }
- tok->length = len;
- tok->value = (char *) malloc(tok->length ? tok->length : 1);
- if (tok->length && tok->value == NULL) {
- syslog(LOG_ERR, "Out of memory allocating token data %zd %zx",
- tok->length, tok->length);
- return -1;
- }
-
- ret = ar_read(s, (char *) tok->value, tok->length);
- if (ret < 0) {
- syslog(LOG_ERR, "GSS-API error reading token data");
- free(tok->value);
- return -1;
- } else if (ret != (int) tok->length) {
- syslog(LOG_ERR, "GSS-API error reading token data");
- free(tok->value);
- return -1;
- }
-
- return 0;
-}
-
-/* Same here. */
-int send_token(int s, gss_buffer_t tok)
-{
- int ret;
- unsigned char lenbuf[4];
- unsigned int len;
-
- if (tok->length > 0xffffffffUL)
- return -1;
-
- len = tok->length;
- lenbuf[0] = (len >> 24) & 0xff;
- lenbuf[1] = (len >> 16) & 0xff;
- lenbuf[2] = (len >> 8) & 0xff;
- lenbuf[3] = len & 0xff;
-
- ret = ar_write(s, (char *) lenbuf, 4);
- if (ret < 0) {
- syslog(LOG_ERR, "GSS-API error sending token length");
- return -1;
- } else if (ret != 4) {
- syslog(LOG_ERR, "GSS-API error sending token length");
- return -1;
- }
-
- ret = ar_write(s, tok->value, tok->length);
- if (ret < 0) {
- syslog(LOG_ERR, "GSS-API error sending token data");
- return -1;
- } else if (ret != (int) tok->length) {
- syslog(LOG_ERR, "GSS-API error sending token data");
- return -1;
- }
-
- return 0;
-}
-
-static void gss_failure_2 (const char *msg, int status, int type)
-{
- OM_uint32 message_context = 0;
- OM_uint32 min_status = 0;
- gss_buffer_desc status_string;
-
- do {
- gss_display_status (&min_status,
- status,
- type,
- GSS_C_NO_OID,
- &message_context,
- &status_string);
-
- syslog (LOG_ERR, "GSS error: %s: %s",
- msg, (char *)status_string.value);
-
- gss_release_buffer(&min_status, &status_string);
- } while (message_context != 0);
-}
-
-static void gss_failure (const char *msg, int major_status, int minor_status)
-{
- gss_failure_2 (msg, major_status, GSS_C_GSS_CODE);
- if (minor_status)
- gss_failure_2 (msg, minor_status, GSS_C_MECH_CODE);
-}
-
-#define KCHECK(x,f) if (x) { \
- syslog (LOG_ERR, "krb5 error: %s in %s\n", krb5_get_error_message (kcontext, x), f); \
- return -1; }
-
-#define KEYTAB_NAME "/etc/audisp/audisp-remote.key"
-#define CCACHE_NAME "MEMORY:audisp-remote"
-
-/* Each time we connect to the server, we negotiate a set of credentials and
- a security context. To do this, we need our own credentials first. For
- other Kerberos applications, the user will have called kinit (or otherwise
- authenticated) first, but we don't have that luxury. So, we implement part
- of kinit here. When our tickets expire, the usual close/open/retry logic
- has us calling here again, where we re-init and get new tickets. */
-static int negotiate_credentials (void)
-{
- gss_buffer_desc empty_token_buf = { 0, (void *) "" };
- gss_buffer_t empty_token = &empty_token_buf;
- gss_buffer_desc send_tok, recv_tok, *token_ptr;
- gss_ctx_id_t *gss_context = &my_context;
- gss_buffer_desc name_buf;
- gss_name_t service_name_e;
- OM_uint32 major_status, minor_status, init_sec_min_stat;
- OM_uint32 ret_flags;
-
- /* Getting an initial ticket is outside the scope of GSS, so
- we use Kerberos calls here. */
-
- int krberr;
- krb5_context kcontext = NULL;
- char *realm_name;
- krb5_principal audit_princ;
- krb5_ccache ccache = NULL;
- krb5_creds my_creds;
- krb5_get_init_creds_opt options;
- krb5_keytab keytab = NULL;
- const char *krb5_client_name;
- char *slashptr;
- char host_name[255];
- struct stat st;
- const char *key_file;
-
- token_ptr = GSS_C_NO_BUFFER;
- *gss_context = GSS_C_NO_CONTEXT;
- recv_tok.value = NULL;
-
- krberr = krb5_init_context (&kcontext);
- KCHECK (krberr, "krb5_init_context");
-
- if (config.krb5_key_file)
- key_file = config.krb5_key_file;
- else
- key_file = KEYTAB_NAME;
- unsetenv ("KRB5_KTNAME");
- setenv ("KRB5_KTNAME", key_file, 1);
-
- if (stat (key_file, &st) == 0) {
- if ((st.st_mode & 07777) != 0400) {
- if (!quiet)
- syslog (LOG_ERR,
- "%s is not mode 0400 (it's %#o) - compromised key?",
- key_file, st.st_mode & 07777);
- return -1;
- }
- if (st.st_uid != 0) {
- if (!quiet)
- syslog (LOG_ERR,
- "%s is not owned by root (it's %d) - compromised key?",
- key_file, st.st_uid);
- return -1;
- }
- }
-
- /* This looks up the default real (*our* realm) from
- /etc/krb5.conf (or wherever) */
- krberr = krb5_get_default_realm (kcontext, &realm_name);
- KCHECK (krberr, "krb5_get_default_realm");
-
- krb5_client_name = config.krb5_client_name ?
- config.krb5_client_name : "auditd";
- if (gethostname(host_name, sizeof(host_name)) != 0) {
- if (!quiet)
- syslog (LOG_ERR,
- "gethostname: host name longer than %ld characters?",
- sizeof (host_name));
- return -1;
- }
-
- syslog (LOG_ERR, "kerberos principal: %s/%s@%s\n",
- krb5_client_name, host_name, realm_name);
- /* Encode our own "name" as auditd/remote@EXAMPLE.COM. */
- krberr = krb5_build_principal (kcontext, &audit_princ,
- strlen(realm_name), realm_name,
- krb5_client_name, host_name, NULL);
- KCHECK (krberr, "krb5_build_principal");
-
- /* Locate our machine's key table, where our private key is
- * held. */
- krberr = krb5_kt_resolve (kcontext, key_file, &keytab);
- KCHECK (krberr, "krb5_kt_resolve");
-
- /* Identify a cache to hold the key in. The GSS wrappers look
- up our credentials here. */
- krberr = krb5_cc_resolve (kcontext, CCACHE_NAME, &ccache);
- KCHECK (krberr, "krb5_cc_resolve");
-
- setenv("KRB5CCNAME", CCACHE_NAME, 1);
-
- memset(&my_creds, 0, sizeof(my_creds));
- memset(&options, 0, sizeof(options));
- krb5_get_init_creds_opt_set_address_list(&options, NULL);
- krb5_get_init_creds_opt_set_forwardable(&options, 0);
- krb5_get_init_creds_opt_set_proxiable(&options, 0);
- krb5_get_init_creds_opt_set_tkt_life(&options, 24*60*60);
-
- /* Load our credentials from the key table. */
- krberr = krb5_get_init_creds_keytab(kcontext, &my_creds, audit_princ,
- keytab, 0, NULL,
- &options);
- KCHECK (krberr, "krb5_get_init_creds_keytab");
-
- /* Create the cache... */
- krberr = krb5_cc_initialize(kcontext, ccache, audit_princ);
- KCHECK (krberr, "krb5_cc_initialize");
-
- /* ...and store our credentials in it. */
- krberr = krb5_cc_store_cred(kcontext, ccache, &my_creds);
- KCHECK (krberr, "krb5_cc_store_cred");
-
- /* The GSS code now has a set of credentials for this program.
- I.e. we know who "we" are. Now we talk to the server to
- get its credentials and set up a security context for encryption. */
- if (config.krb5_principal == NULL) {
- const char *name = config.krb5_client_name ?
- config.krb5_client_name : "auditd";
- config.krb5_principal = (char *) malloc (strlen (name) + 1
- + strlen (config.remote_server) + 1);
- sprintf((char *)config.krb5_principal, "%s@%s",
- name, config.remote_server);
- }
- slashptr = strchr (config.krb5_principal, '/');
- if (slashptr)
- *slashptr = '@';
-
- name_buf.value = (char *)config.krb5_principal;
- name_buf.length = strlen(name_buf.value) + 1;
- major_status = gss_import_name(&minor_status, &name_buf,
- (gss_OID) gss_nt_service_name, &service_name_e);
- if (major_status != GSS_S_COMPLETE) {
- gss_failure("importing name", major_status, minor_status);
- return -1;
- }
-
- /* Someone has to go first. In this case, it's us. */
- if (send_token(sock, empty_token) < 0) {
- (void) gss_release_name(&minor_status, &service_name_e);
- return -1;
- }
-
- /* The server starts this loop with the token we just sent
- (the empty one). We start this loop with "no token". */
- token_ptr = GSS_C_NO_BUFFER;
- *gss_context = GSS_C_NO_CONTEXT;
-
- do {
- /* Give GSS a chance to digest what we have so far. */
- major_status = gss_init_sec_context(&init_sec_min_stat,
- GSS_C_NO_CREDENTIAL, gss_context,
- service_name_e, NULL, REQ_FLAGS, 0,
- NULL, /* no channel bindings */
- token_ptr, NULL, /* ignore mech type */
- &send_tok, &ret_flags, NULL); /* ignore time_rec */
-
- if (token_ptr != GSS_C_NO_BUFFER)
- free(recv_tok.value);
-
- /* Send the server any tokens requested of us. */
- if (send_tok.length != 0) {
- if (send_token(sock, &send_tok) < 0) {
- (void) gss_release_buffer(&minor_status,
- &send_tok);
- (void) gss_release_name(&minor_status,
- &service_name_e);
- return -1;
- }
- }
- (void) gss_release_buffer(&minor_status, &send_tok);
-
- if (major_status != GSS_S_COMPLETE
- && major_status != GSS_S_CONTINUE_NEEDED) {
- gss_failure("initializing context", major_status,
- init_sec_min_stat);
- (void) gss_release_name(&minor_status, &service_name_e);
- if (*gss_context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&minor_status,
- gss_context, GSS_C_NO_BUFFER);
- return -1;
- }
-
- /* Now get any tokens the sever sends back. We use
- these back at the top of the loop. */
- if (major_status == GSS_S_CONTINUE_NEEDED) {
- if (recv_token(sock, &recv_tok) < 0) {
- (void) gss_release_name(&minor_status,
- &service_name_e);
- return -1;
- }
- token_ptr = &recv_tok;
- }
- } while (major_status == GSS_S_CONTINUE_NEEDED);
-
- (void) gss_release_name(&minor_status, &service_name_e);
-
-#if 0
- major_status = gss_inquire_context (&minor_status, &my_context, NULL,
- &service_name_e, NULL, NULL,
- NULL, NULL, NULL);
- if (major_status != GSS_S_COMPLETE) {
- gss_failure("inquiring target name", major_status, minor_status);
- return -1;
- }
- major_status = gss_display_name(&minor_status, service_name_e,
- &recv_tok, NULL);
- gss_release_name(&minor_status, &service_name_e);
- if (major_status != GSS_S_COMPLETE) {
- gss_failure("displaying name", major_status, minor_status);
- return -1;
- }
- syslog(LOG_INFO, "GSS-API Connected to: %s",
- (char *)recv_tok.value);
-#endif
- return 0;
-}
-#endif
-
-static int stop_sock(void)
-{
- if (sock >= 0) {
- shutdown(sock, SHUT_RDWR);
- close(sock);
- }
- sock = -1;
- transport_ok = 0;
-
- return 0;
-}
-
-static int stop_transport(void)
-{
- int rc;
-
- switch (config.transport)
- {
- case T_TCP:
- rc = stop_sock();
- break;
- default:
- rc = -1;
- break;
- }
- return rc;
-}
-
-static int init_sock(void)
-{
- int rc;
- struct addrinfo *ai;
- struct addrinfo hints;
- char remote[BUF_SIZE];
- int one=1;
-
- if (sock >= 0) {
- syslog(LOG_NOTICE, "socket already setup");
- transport_ok = 1;
- return ET_SUCCESS;
- }
- memset(&hints, '\0', sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG|AI_NUMERICSERV;
- hints.ai_socktype = SOCK_STREAM;
- snprintf(remote, BUF_SIZE, "%u", config.port);
- rc = getaddrinfo(config.remote_server, remote, &hints, &ai);
- if (rc) {
- if (!quiet)
- syslog(LOG_ERR,
- "Error looking up remote host: %s - exiting",
- gai_strerror(rc));
- if (rc == EAI_NONAME || rc == EAI_NODATA)
- return ET_PERMANENT;
- else
- return ET_TEMPORARY;
- }
- sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sock < 0) {
- if (!quiet)
- syslog(LOG_ERR, "Error creating socket: %s",
- strerror(errno));
- freeaddrinfo(ai);
- return ET_TEMPORARY;
- }
-
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (int));
-
- if (config.local_port != 0) {
- struct sockaddr_in address;
-
- memset (&address, 0, sizeof(address));
- address.sin_family = AF_INET;
- address.sin_port = htons(config.local_port);
- address.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if (bind(sock, (struct sockaddr *)&address, sizeof(address))) {
- if (!quiet)
- syslog(LOG_ERR,
- "Cannot bind local socket to port %d",
- config.local_port);
- stop_sock();
- freeaddrinfo(ai);
- return ET_TEMPORARY;
- }
-
- }
- if (connect(sock, ai->ai_addr, ai->ai_addrlen)) {
- if (!quiet)
- syslog(LOG_ERR, "Error connecting to %s: %s",
- config.remote_server, strerror(errno));
- freeaddrinfo(ai);
- stop_sock();
- return ET_TEMPORARY;
- }
-
- freeaddrinfo(ai);
- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof (int));
-
- /* The idea here is to minimize the time between the message
- and the ACK, assuming that individual messages are
- infrequent enough that we can ignore the inefficiency of
- sending the header and message in separate packets. */
- if (config.format == F_MANAGED)
- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- (char *)&one, sizeof (int));
-
-#ifdef USE_GSSAPI
- if (USE_GSS) {
- if (negotiate_credentials ())
- return ET_PERMANENT;
- }
-#endif
-
- transport_ok = 1;
- syslog(LOG_NOTICE, "Connected to %s", config.remote_server);
- return ET_SUCCESS;
-}
-
-static int init_transport(void)
-{
- int rc;
-
- switch (config.transport)
- {
- case T_TCP:
- rc = init_sock();
- // We set this so that it will retry the connection
- if (rc == ET_TEMPORARY)
- remote_ended = 1;
- break;
- default:
- rc = ET_PERMANENT;
- break;
- }
- return rc;
-}
-
-static int ar_write (int sk, const void *buf, int len)
-{
- int rc = 0, r;
- while (len > 0) {
- do {
- r = write(sk, buf, len);
- } while (r < 0 && errno == EINTR);
- if (r < 0) {
- if (errno == EPIPE)
- stop_sock();
- return r;
- }
- if (r == 0)
- break;
- rc += r;
- buf = (void *)((char *)buf + r);
- len -= r;
- }
- return rc;
-}
-
-static int ar_read (int sk, void *buf, int len)
-{
- int rc = 0, r, timeout = config.max_time_per_record * 1000;
- struct pollfd pfd;
-
- pfd.fd=sk;
- pfd.events=POLLIN | POLLPRI | POLLHUP | POLLERR | POLLNVAL;
- while (len > 0) {
- do {
- // reads can hang if cable is disconnected
- int prc = poll(&pfd, (nfds_t) 1, timeout);
- if (prc <= 0)
- return -1;
- r = read(sk, buf, len);
- } while (r < 0 && errno == EINTR);
- if (r < 0) {
- if (errno == EPIPE)
- stop_sock();
- return r;
- }
- if (r == 0)
- break;
- rc += r;
- buf = (void *)((char *)buf + r);
- len -= r;
- }
- return rc;
-}
-
-static int relay_sock_ascii(const char *s, size_t len)
-{
- int rc;
-
- if (len == 0)
- return 0;
-
- if (!transport_ok) {
- if (init_transport ())
- return -1;
- }
-
- rc = ar_write(sock, s, len);
- if (rc <= 0) {
- stop = 1;
- syslog(LOG_ERR,"Connection to %s closed unexpectedly - exiting",
- config.remote_server);
- return -1;
- }
-
- return 0;
-}
-
-#ifdef USE_GSSAPI
-
-/* Sending an encrypted message is pretty simple - wrap the message in
- a token, and send the token. The server unwraps it to get the
- original message. */
-static int send_msg_gss (unsigned char *header, const char *msg, uint32_t mlen)
-{
- OM_uint32 major_status, minor_status;
- gss_buffer_desc utok, etok;
- int rc;
-
- utok.length = AUDIT_RMW_HEADER_SIZE + mlen;
- utok.value = malloc (utok.length);
-
- memcpy (utok.value, header, AUDIT_RMW_HEADER_SIZE);
-
- if (msg != NULL && mlen > 0)
- memcpy (utok.value+AUDIT_RMW_HEADER_SIZE, msg, mlen);
-
- major_status = gss_wrap (&minor_status,
- my_context,
- 1,
- GSS_C_QOP_DEFAULT,
- &utok,
- NULL,
- &etok);
- if (major_status != GSS_S_COMPLETE) {
- gss_failure("encrypting message", major_status, minor_status);
- free (utok.value);
- return -1;
- }
- rc = send_token (sock, &etok);
- free (utok.value);
- (void) gss_release_buffer(&minor_status, &etok);
-
- return rc ? -1 : 0;
-}
-
-/* Likewise here. */
-static int recv_msg_gss (unsigned char *header, char *msg, uint32_t *mlen)
-{
- OM_uint32 major_status, minor_status;
- gss_buffer_desc utok, etok;
- int hver, mver, rc;
- uint32_t type, rlen, seq;
-
- rc = recv_token (sock, &etok);
- if (rc)
- return -1;
-
- major_status = gss_unwrap (&minor_status, my_context, &etok,
- &utok, NULL, NULL);
- if (major_status != GSS_S_COMPLETE) {
- gss_failure("decrypting message", major_status, minor_status);
- free (utok.value);
- return -1;
- }
-
- if (utok.length < AUDIT_RMW_HEADER_SIZE) {
- sync_error_handler ("message too short");
- return -1;
- }
- memcpy (header, utok.value, AUDIT_RMW_HEADER_SIZE);
-
- if (! AUDIT_RMW_IS_MAGIC (header, AUDIT_RMW_HEADER_SIZE)) {
- sync_error_handler ("bad magic number");
- return -1;
- }
-
- AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq);
-
- if (rlen > MAX_AUDIT_MESSAGE_LENGTH) {
- sync_error_handler ("message too long");
- return -1;
- }
-
- memcpy (msg, utok.value+AUDIT_RMW_HEADER_SIZE, rlen);
-
- *mlen = rlen;
-
- return 0;
-}
-#endif
-
-static int send_msg_tcp (unsigned char *header, const char *msg, uint32_t mlen)
-{
- int rc;
-
- rc = ar_write(sock, header, AUDIT_RMW_HEADER_SIZE);
- if (rc <= 0) {
- syslog(LOG_ERR, "send to %s failed", config.remote_server);
- return 1;
- }
-
- if (msg != NULL && mlen > 0) {
- rc = ar_write(sock, msg, mlen);
- if (rc <= 0) {
- syslog(LOG_ERR, "send to %s failed",
- config.remote_server);
- return 1;
- }
- }
- return 0;
-}
-
-static int recv_msg_tcp (unsigned char *header, char *msg, uint32_t *mlen)
-{
- int hver, mver, rc;
- uint32_t type, rlen, seq;
-
- rc = ar_read (sock, header, AUDIT_RMW_HEADER_SIZE);
- if (rc < 16) {
- syslog(LOG_ERR, "read from %s failed", config.remote_server);
- return -1;
- }
-
- if (! AUDIT_RMW_IS_MAGIC (header, AUDIT_RMW_HEADER_SIZE)) {
- /* FIXME: the right thing to do here is close the socket
- * and start a new one. */
- sync_error_handler ("bad magic number");
- return -1;
- }
-
- AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq);
-
- if (rlen > MAX_AUDIT_MESSAGE_LENGTH) {
- sync_error_handler ("message too long");
- return -1;
- }
-
- if (rlen > 0 && ar_read (sock, msg, rlen) < rlen) {
- sync_error_handler ("ran out of data reading reply");
- return -1;
- }
- return 0;
-}
-
-static int check_message_managed(void)
-{
- unsigned char header[AUDIT_RMW_HEADER_SIZE];
- int hver, mver;
- uint32_t type, rlen, seq;
- char msg[MAX_AUDIT_MESSAGE_LENGTH+1];
-
-#ifdef USE_GSSAPI
- if (USE_GSS) {
- if (recv_msg_gss (header, msg, &rlen)) {
- stop_transport();
- return -1;
- }
- } else
-#endif
- if (recv_msg_tcp(header, msg, &rlen)) {
- stop_transport();
- return -1;
- }
-
- AUDIT_RMW_UNPACK_HEADER(header, hver, mver, type, rlen, seq);
- msg[rlen] = 0;
-
- if (type == AUDIT_RMW_TYPE_ENDING)
- return remote_server_ending_handler(msg);
- if (type == AUDIT_RMW_TYPE_DISKLOW)
- return remote_disk_low_handler(msg);
- if (type == AUDIT_RMW_TYPE_DISKFULL)
- return remote_disk_full_handler(msg);
- if (type == AUDIT_RMW_TYPE_DISKERROR)
- return remote_disk_error_handler(msg);
- return -1;
-}
-
-/* This is to check for async notification like server is shutting down */
-static int check_message(void)
-{
- int rc;
-
- switch (config.format)
- {
- case F_MANAGED:
- rc = check_message_managed();
- break;
-/* case F_ASCII:
- rc = check_message_ascii();
- break; */
- default:
- rc = -1;
- break;
- }
-
- return rc;
-}
-
-static int relay_sock_managed(const char *s, size_t len)
-{
- static int sequence_id = 1;
- unsigned char header[AUDIT_RMW_HEADER_SIZE];
- int hver, mver;
- uint32_t type, rlen, seq;
- char msg[MAX_AUDIT_MESSAGE_LENGTH+1];
- int n_tries_this_message = 0;
- time_t now, then = 0;
-
- sequence_id ++;
-
-try_again:
- time (&now);
- if (then == 0)
- then = now;
-
- /* We want the first retry to be quick, in case the network
- failed for some fail-once reason. In this case, it goes
- "failure - reconnect - send". Only if this quick retry
- fails do we start pausing between retries to prevent
- swamping the local computer and the network. */
- if (n_tries_this_message > 1)
- sleep (config.network_retry_time);
-
- if (n_tries_this_message > config.max_tries_per_record) {
- network_failure_handler ("max retries exhausted");
- return -1;
- }
- if ((now - then) > config.max_time_per_record) {
- network_failure_handler ("max retry time exhausted");
- return -1;
- }
-
- n_tries_this_message ++;
-
- if (!transport_ok) {
- if (init_transport ())
- goto try_again;
- }
-
- type = (s != NULL) ? AUDIT_RMW_TYPE_MESSAGE : AUDIT_RMW_TYPE_HEARTBEAT;
- AUDIT_RMW_PACK_HEADER (header, 0, type, len, sequence_id);
-
-#ifdef USE_GSSAPI
- if (USE_GSS) {
- if (send_msg_gss (header, s, len)) {
- stop_transport ();
- goto try_again;
- }
- } else
-#endif
- if (send_msg_tcp (header, s, len)) {
- stop_transport ();
- goto try_again;
- }
-
-#ifdef USE_GSSAPI
- if (USE_GSS) {
- if (recv_msg_gss (header, msg, &rlen)) {
- stop_transport ();
- goto try_again;
- }
- } else
-#endif
- if (recv_msg_tcp (header, msg, &rlen)) {
- stop_transport ();
- goto try_again;
- }
-
- AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq);
- msg[rlen] = 0;
-
- /* Handle this first. It doesn't matter if seq compares or not
- * since the other end is going down...deal with it. */
- if (type == AUDIT_RMW_TYPE_ENDING)
- return remote_server_ending_handler (msg);
-
- if (seq != sequence_id) {
- /* FIXME: should we read another header and
- see if it matches? If so, we need to deal
- with timeouts. */
- if (sync_error_handler ("mismatched response"))
- return -1;
- stop_transport();
- goto try_again;
- }
-
- /* Specific errors we know how to deal with. */
- if (type == AUDIT_RMW_TYPE_DISKLOW)
- return remote_disk_low_handler (msg);
- if (type == AUDIT_RMW_TYPE_DISKFULL)
- return remote_disk_full_handler (msg);
- if (type == AUDIT_RMW_TYPE_DISKERROR)
- return remote_disk_error_handler (msg);
-
- /* Generic errors. */
- if (type & AUDIT_RMW_TYPE_FATALMASK)
- return generic_remote_error_handler (msg);
- if (type & AUDIT_RMW_TYPE_WARNMASK)
- return generic_remote_warning_handler (msg);
-
- return 0;
-}
-
-static int relay_sock(const char *s, size_t len)
-{
- int rc;
-
- switch (config.format)
- {
- case F_MANAGED:
- rc = relay_sock_managed (s, len);
- break;
- case F_ASCII:
- rc = relay_sock_ascii (s, len);
- break;
- default:
- rc = -1;
- break;
- }
-
- return rc;
-}
-
-/* Send audit event to remote system */
-static int relay_event(const char *s, size_t len)
-{
- int rc;
-
- switch (config.transport)
- {
- case T_TCP:
- rc = relay_sock(s, len);
- break;
- default:
- rc = -1;
- break;
- }
-
- return rc;
-}
-
diff --git a/framework/src/audit/audisp/plugins/remote/audisp-remote.conf b/framework/src/audit/audisp/plugins/remote/audisp-remote.conf
deleted file mode 100644
index 70d8a992..00000000
--- a/framework/src/audit/audisp/plugins/remote/audisp-remote.conf
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# This file controls the configuration of the audit remote
-# logging subsystem, audisp-remote.
-#
-
-remote_server =
-port = 60
-##local_port =
-transport = tcp
-queue_file = /var/spool/audit/remote.log
-mode = immediate
-queue_depth = 2048
-format = managed
-network_retry_time = 1
-max_tries_per_record = 3
-max_time_per_record = 5
-heartbeat_timeout = 0
-
-network_failure_action = stop
-disk_low_action = ignore
-disk_full_action = ignore
-disk_error_action = syslog
-remote_ending_action = reconnect
-generic_error_action = syslog
-generic_warning_action = syslog
-overflow_action = syslog
-
-##enable_krb5 = no
-##krb5_principal =
-##krb5_client_name = auditd
-##krb5_key_file = /etc/audisp/audisp-remote.key
diff --git a/framework/src/audit/audisp/plugins/remote/audisp-remote.conf.5 b/framework/src/audit/audisp/plugins/remote/audisp-remote.conf.5
deleted file mode 100644
index 55efabfc..00000000
--- a/framework/src/audit/audisp/plugins/remote/audisp-remote.conf.5
+++ /dev/null
@@ -1,211 +0,0 @@
-.TH AUDISP-REMOTE.CONF: "5" "Mar 2011" "Red Hat" "System Administration Utilities"
-.SH NAME
-audisp-remote.conf \- the audisp-remote configuration file
-.SH DESCRIPTION
-\fBaudisp-remote.conf\fP is the file that controls the configuration of the audit remote logging subsystem. The options that are available are as follows:
-
-.TP
-.I remote_server
-This is a one word character string that is the remote server hostname or address that this plugin will send log information to. This can be the numeric address or a resolvable hostname.
-.TP
-.I port
-This option is an unsigned integer that indicates what port to connect to on the remote machine.
-.TP
-.I local_port
-This option is an unsigned integer that indicates what local port to
-connect from on the local machine. If unspecified (the default) or
-set to the word
-.I any
-then any available unpriviledged port is used. This is a security mechanism to prevent untrusted user space apps from injecting events into the audit daemon. You should set it to an unused port < 1024 to ensure that only privileged users can bind to that port. Then also set the tcp_client_ports in the aggregating auditd.conf file to match the ports that clients are sending from.
-.TP
-.I transport
-This parameter tells the remote logging app how to send events to the remote system. The only valid value right now is
-.IR tcp ".
-If set to
-.IR tcp ,
-the remote logging app will just make a normal clear text connection to the remote system. This is not used if kerberos is enabled.
-.TP
-.I mode
-This parameter tells the remote logging app what strategy to use getting records to the remote system. Valid values are
-.IR immediate ", and " forward " .
-If set to
-.IR immediate ,
-the remote logging app will attempt to send events immediately after getting them.
-.I forward
-means that it will store the events to disk and then attempt to send the records. If the connection cannot be made, it will queue records until it can connect to the remote system. The depth of the queue is controlled by the
-.I queue_depth
-option.
-.TP
-.I queue_file
-Path of a file used for the event queue if
-.I mode
-is set to \fIforward\fP. The default is \fB/var/spool/audit/remote.log\fP.
-.TP
-.I queue_depth
-This option is an unsigned integer that determines how many records can be buffered to disk or in memory before considering it to be a failure sending. This parameter affects the
-.I forward
-mode of the
-.I mode
-option and internal queueing for temporary network outtages. The default depth is 2048.
-.TP
-.I format
-This parameter tells the remote logging app what data format will be
-used for the messages sent over the network. The default is
-.I managed
-which adds some overhead to ensure each message is properly handled on
-the remote end, and to receive status messages from the remote server.
-If
-.I ascii
-is given instead, each message is a simple ASCII text line with no
-overhead at all. If
-.I mode
-is set to \fIforward\fP,
-.I format
-must be \fImanaged\fP.
-.TP
-.I network_retry_time
-The time, in seconds, between retries when a network error is
-detected. Note that this pause applies starting after the second
-attempt, so as to avoid unneeded delays if a reconnect is sufficient
-to fix the problem. The default is 1 second.
-.TP
-.I max_tries_per_record
-The maximum number of times an attempt is made to deliver each
-message. The minimum value is one, as even a completely successful
-delivery requires at least one try. If too many attempts are made,
-the network_failure_action action is performed. The default is 3.
-.TP
-.I max_time_per_record
-The maximum amount of time, in seconds, spent attempting to deliver
-each message. Note that both this and
-.I max_tries_per_record
-should be set, as each try may take a long time to time out. The
-default value is 5 seconds. If too much time is used on a message,
-the network_failure_action action is performed.
-.TP
-.I heartbeat_timeout
-This parameter determines how often in seconds the client should send a heartbeat event to the remote server. This is used to let both the client and server know that each end is alive and has not terminated in a way that it did not shutdown the connection uncleanly. This value must be coordinated with the server's
-.I tcp_client_max_idle
-setting. The default value is 0 which disables sending a heartbeat.
-.TP
-.I network_failure_action
-This parameter tells the system what action to take whenever there is an error
-detected when sending audit events to the remote system. Valid values are
-.IR ignore ", " syslog ", " exec ", " suspend ", " single ", " halt ", and " stop .
-If set to
-.IR ignore ,
-the remote logging app does nothing.
-.I Syslog
-means that it will issue a warning to syslog. This is the default.
-.I exec
-/path-to-script will execute the script. You cannot pass parameters to the script.
-.I Suspend
-will cause the remote logging app to stop sending records to the remote system. The logging app will still be alive. The
-.I single
-option will cause the remote logging app to put the computer system in single user mode. The
-.I stop
-option will cause the remote logging app to exit, but leave other plugins running. The
-.I halt
-option will cause the remote logging app to shutdown the computer system.
-.TP
-.I disk_low_action
-Likewise, this parameter tells the system what action to take if the
-remote end signals a disk low error. The default is to ignore it.
-.TP
-.I disk_full_action
-Likewise, this parameter tells the system what action to take if the
-remote end signals a disk full error. The default is to ignore it.
-.TP
-.I disk_error_action
-Likewise, this parameter tells the system what action to take if the
-remote end signals a disk error. The default is to log it to syslog.
-.TP
-.I remote_ending_action
-Likewise, this parameter tells the system what action to take if the
-remote end signals a disk error. This action has one additional option,
-.I reconnect
-which tells the remote plugin to attempt to reconnect to the server upon receipt of the next audit record. If it is unsuccessful, the audit record could be lost. The default is to reconnect.
-.TP
-.I generic_error_action
-Likewise, this parameter tells the system what action to take if the
-remote end signals an error we don't recognize. The default is to log
-it to syslog.
-.TP
-.I generic_warning_action
-Likewise, this parameter tells the system what action to take if the
-remote end signals a warning we don't recognize. The default is to
-log it to syslog.
-.TP
-.I queue_error_action
-Likewise, this parameter tells the system what action to take if there
-is a problem working with a local record queue. The default is to exit.
-.TP
-.I overflow_action
-This parameter tells the system what action to take if the
-internal event queue overflows. Valid values are
-.IR ignore ", " syslog ", " suspend ", " single ", and " halt " .
-If set to
-.IR ignore ,
-the remote logging app does nothing.
-.I Syslog
-means that it will issue a warning to syslog. This is the default.
-.I Suspend
-will cause the remote logging app to stop sending records to the remote system. The logging app will still be alive. The
-.I single
-option will cause the remote logging app to put the computer system in single user mode. The
-.I halt
-option will cause the remote logging app to shutdown the computer system.
-.TP
-.I enable_krb5
-If set to "yes", Kerberos 5 will be used for authentication and
-encryption. Default is "no". Note that encryption can only be used
-with managed connections, not plain ASCII.
-.TP
-.I krb5_principal
-If specified, This is the expected principal for the server. The
-client and server will use the specified principal to negotiate the
-encryption. The format for the
-.I krb5_principal
-is like somename/hostname, see the auditd.conf man page for
-details. If not specified, the krb5_client_name and remote_server values
-are used.
-.TP
-.I krb5_client_name
-This specifies the name portion of the client's own principal. If
-unspecified, the default is "auditd". The remainder of the principal
-will consist of the host's fully qualified domain name and the default
-Kerberos realm, like this:
-.I auditd/host14.example.com@EXAMPLE.COM
-(assuming you gave "auditd" as the krb_client_name). Note that the
-client and server must have the same principal name and realm.
-.TP
-.I krb5_key_file
-Location of the key for this client's principal.
-Note that the key file must be owned by root and mode 0400.
-The default is
-.I /etc/audisp/audisp-remote.key
-
-
-.SH "NOTES"
-Specifying a local port may make it difficult to restart the audit
-subsystem due to the previous connection being in a TIME_WAIT state,
-if you're reconnecting to and from the same hosts and ports as before.
-
-The network failure logic works as follows: The first attempt to
-deliver normally "just works". If it doesn't, a second attempt is
-immediately made, perhaps after reconnecting to the server. If
-the second attempt also fails,
-.I audispd-remote
-pauses for the configured time and tries again. It continues to pause
-and retry until either too many attempts have been made or the allowed
-time expires. Note that these times govern the maximum amount of time
-the remote server is allowed in order to reboot, if you want to
-maintain logging across a reboot.
-
-.SH "SEE ALSO"
-.BR audispd (8),
-.BR audisp-remote(8),
-.BR auditd.conf(5).
-.SH AUTHOR
-Steve Grubb
-
diff --git a/framework/src/audit/audisp/plugins/remote/notes.txt b/framework/src/audit/audisp/plugins/remote/notes.txt
deleted file mode 100644
index 1cd46193..00000000
--- a/framework/src/audit/audisp/plugins/remote/notes.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-The queue data structure can keep data only in memory, only on disk
-(writing it to disk and reading from disk), or in both (writing everything
-to disk, but reading from disk only data stored in a previous run).
-audisp-remote will use the last option for performance.
-
-The queue file format starts with a fixed header, followed by an array
-of slots for strings. Due to the fixed size of each slot the file format
-is rather inefficient, but it is also very simple.
-
-The file is preallocated and the string slots will be aligned to a 4KB
-boundary, so it should be necessary to only write one block to disk
-when audisp-remote receives a (short) audit record.
-
-With the default queue size of 200 items the file will be about 2.4
-megabytes large, which is probably not really worth worrying about.
-
-If necessary, the space utilization could be improved by storing strings
-consecutively instead of using pre-arranged slots.
-
-The queue file format is intended to be resilient against unexpected
-termination of the process, and should be resilient against unexpected
-system crash as long as the OS does not reorder writes (the string data
-is written before the header that indicates that it is present) - but
-ultimately resiliency against such failures is limited by other
-links in the audit record transmission chain - if the record is lost
-within auditd or audispd, having a resilient queue file format does
-not help; audit records generated within the kernel are necessarily
-lost if the system crashes before they are read by auditd because
-the kernel will not be able to regenerate/retransmit them after the next
-boot.
-
diff --git a/framework/src/audit/audisp/plugins/remote/queue.c b/framework/src/audit/audisp/plugins/remote/queue.c
deleted file mode 100644
index 971e4e46..00000000
--- a/framework/src/audit/audisp/plugins/remote/queue.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/* queue.c - a string queue implementation
- * Copyright 2009, 2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- * Miloslav Trmač <mitr@redhat.com>
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include "queue.h"
-
-struct queue
-{
- int flags; /* Q_* */
- int fd; /* -1 if !Q_IN_FILE */
- /* NULL if !Q_IN_MEMORY. [i] contains a memory copy of the queue entry
- "i", if known - it may be NULL even if entry exists. */
- unsigned char **memory;
- size_t num_entries;
- size_t entry_size;
- size_t queue_head;
- size_t queue_length;
- unsigned char buffer[]; /* Used only locally within q_peek() */
-};
-
-/* Infrastructure */
-
-/* Compile-time expression verification */
-#define verify(E) do { \
- char verify__[(E) ? 1 : -1]; \
- (void)verify__; \
- } while (0)
-
-/* Like pread(), except that it handles partial reads, and returns 0 on
- success. */
-static int full_pread(int fd, void *buf, size_t size, off_t offset)
-{
- while (size != 0) {
- ssize_t run, res;
-
- if (size > SSIZE_MAX)
- run = SSIZE_MAX;
- else
- run = size;
- res = pread(fd, buf, run, offset);
- if (res < 0)
- return -1;
- if (res == 0) {
- errno = ENXIO; /* Any better value? */
- return -1;
- }
- buf = (unsigned char *)buf + res;
- size -= res;
- offset += res;
- }
- return 0;
-}
-
-/* Like pwrite(), except that it handles partial writes, and returns 0 on
- success. */
-static int full_pwrite(int fd, const void *buf, size_t size, off_t offset)
-{
- while (size != 0) {
- ssize_t run, res;
-
- if (size > SSIZE_MAX)
- run = SSIZE_MAX;
- else
- run = size;
- res = pwrite(fd, buf, run, offset);
- if (res < 0)
- return -1;
- if (res == 0) {
- errno = ENXIO; /* Any better value? */
- return -1;
- }
- buf = (const unsigned char *)buf + res;
- size -= res;
- offset += res;
- }
- return 0;
-}
-
-/* File format and utilities */
-
-/* The mutable part of struct file_header */
-struct fh_state {
- uint32_t queue_head; /* 0-based index of the first non-empty entry */
- uint32_t queue_length; /* [0, num_entries] */
-};
-
-/* All integer values are in network byte order (big endian) */
-struct file_header
-{
- uint8_t magic[14]; /* See fh_magic below */
- uint8_t version; /* File format version, see FH_VERSION* below */
- uint8_t reserved; /* Must be 0 */
- /* Total file size is (num_entries + 1) * entry_size. This must fit
- into SIZE_MAX because the "len" parameter of posix_fallocate has
- a size_t type. */
- uint32_t num_entries; /* Total number of entries allocated */
- uint32_t entry_size;
- struct fh_state s;
-};
-
-/* Contains a '\0' byte to unambiguously mark the file as a binary file. */
-static const uint8_t fh_magic[14] = "\0audisp-remote";
-#define FH_VERSION_0 0x00
-
-/* Return file position for ENTRY in Q */
-static size_t entry_offset (const struct queue *q, size_t entry)
-{
- return (entry + 1) * q->entry_size;
-}
-
-/* Synchronize Q if required and return 0.
- On error, return -1 and set errno. */
-static int q_sync(struct queue *q)
-{
- if ((q->flags & Q_SYNC) == 0)
- return 0;
- return fdatasync(q->fd);
-}
-
-/* Sync file's fh_state with Q, q_sync (Q), and return 0.
- On error, return -1 and set errno. */
-static int sync_fh_state (struct queue *q)
-{
- struct fh_state s;
-
- if (q->fd == -1)
- return 0;
-
- s.queue_head = htonl(q->queue_head);
- s.queue_length = htonl(q->queue_length);
- if (full_pwrite(q->fd, &s, sizeof(s), offsetof(struct file_header, s))
- != 0)
- return -1;
- return q_sync(q);
-}
-
-/* Queue implementation */
-
-/* Open PATH for Q, update Q from it, and return 0.
- On error, return -1 and set errno; Q->fd may be set even on error. */
-static int q_open_file(struct queue *q, const char *path)
-{
- int open_flags, fd_flags;
- struct stat st;
- struct file_header fh;
-
- open_flags = O_RDWR;
- if ((q->flags & Q_CREAT) != 0)
- open_flags |= O_CREAT;
- if ((q->flags & Q_EXCL) != 0)
- open_flags |= O_EXCL;
- q->fd = open(path, open_flags, S_IRUSR | S_IWUSR);
- if (q->fd == -1)
- return -1;
-
- fd_flags = fcntl(q->fd, F_GETFD);
- if (fd_flags < 0)
- return -1;
- if (fcntl(q->fd, F_SETFD, fd_flags | FD_CLOEXEC) == -1)
- return -1;
-
- /* File locking in POSIX is pretty much broken... let's hope nobody
- attempts to open a single file twice within the same process.
- open() above has initialized the file offset to 0, so the lockf()
- below affects the whole file. */
- if (lockf(q->fd, F_TLOCK, 0) != 0) {
- if (errno == EACCES || errno == EAGAIN)
- errno = EBUSY; /* This makes more sense... */
- return -1;
- }
-
- if (fstat(q->fd, &st) != 0)
- return -1;
- if (st.st_size == 0) {
- verify(sizeof(fh.magic) == sizeof(fh_magic));
- memcpy(fh.magic, fh_magic, sizeof(fh.magic));
- fh.version = FH_VERSION_0;
- fh.reserved = 0;
- fh.num_entries = htonl(q->num_entries);
- fh.entry_size = htonl(q->entry_size);
- fh.s.queue_head = htonl(0);
- fh.s.queue_length = htonl(0);
- if (full_pwrite(q->fd, &fh, sizeof(fh), 0) != 0)
- return -1;
- if (q_sync(q) != 0)
- return -1;
-#ifdef HAVE_POSIX_FALLOCATE
- if (posix_fallocate(q->fd, 0,
- (q->num_entries + 1) * q->entry_size) != 0)
- return -1;
-#endif
- } else {
- uint32_t file_entries;
- if (full_pread(q->fd, &fh, sizeof(fh), 0) != 0)
- return -1;
- if (memcmp(fh.magic, fh_magic, sizeof(fh.magic)) != 0
- || fh.version != FH_VERSION_0 || fh.reserved != 0
- || fh.entry_size != htonl(q->entry_size)) {
- errno = EINVAL;
- return -1;
- }
- file_entries = ntohl(fh.num_entries);
- if (file_entries > SIZE_MAX / q->entry_size - 1
- || ((uintmax_t)st.st_size
- != (file_entries + 1) * q->entry_size)) {
- errno = EINVAL;
- return -1;
- }
- }
- /* Note that this may change q->num_entries! */
- q->num_entries = ntohl(fh.num_entries);
- q->queue_head = ntohl(fh.s.queue_head);
- q->queue_length = ntohl(fh.s.queue_length);
- if (q->queue_head >= q->num_entries
- || q->queue_length > q->num_entries) {
- errno = EINVAL;
- return -1;
- }
- return 0;
-}
-
-/* Like q_open(), but does not handle Q_RESIZE, and NUM_ENTRIES is only used
- when creating a new file. */
-static struct queue *q_open_no_resize(int q_flags, const char *path,
- size_t num_entries, size_t entry_size)
-{
- struct queue *q;
- int saved_errno;
-
- if ((q_flags & (Q_IN_MEMORY | Q_IN_FILE)) == 0) {
- errno = EINVAL;
- return NULL;
- }
- if (num_entries == 0 || num_entries > UINT32_MAX
- || entry_size < 1 /* for trailing NUL */
- || entry_size < sizeof(struct file_header) /* for Q_IN_FILE */
- /* to allocate "struct queue" including its buffer*/
- || entry_size > UINT32_MAX - sizeof(struct queue)) {
- errno = EINVAL;
- return NULL;
- }
- if (entry_size > SIZE_MAX
- || num_entries > SIZE_MAX / entry_size - 1 /* for Q_IN_FILE */
- || num_entries > SIZE_MAX / sizeof(*q->memory)) {
- errno = EINVAL;
- return NULL;
- }
-
- q = malloc(sizeof(*q) + entry_size);
- if (q == NULL)
- return NULL;
- q->flags = q_flags;
- q->fd = -1;
- q->memory = NULL;
- q->num_entries = num_entries;
- q->entry_size = entry_size;
- q->queue_head = 0;
- q->queue_length = 0;
-
- if ((q_flags & Q_IN_MEMORY) != 0) {
- size_t sz = num_entries * sizeof(*q->memory);
-
- q->memory = malloc(sz);
- if (q->memory == NULL)
- goto err;
- memset(q->memory, 0, sz);
- }
-
- if ((q_flags & Q_IN_FILE) != 0 && q_open_file(q, path) != 0)
- goto err;
-
- return q;
-
-err:
- saved_errno = errno;
- if (q->fd != -1)
- close(q->fd);
- free(q->memory);
- free(q);
- errno = saved_errno;
- return NULL;
-}
-
-void q_close(struct queue *q)
-{
- if (q->fd != -1)
- close(q->fd); /* Also releases the file lock */
- if (q->memory != NULL) {
- size_t i;
-
- for (i = 0; i < q->num_entries; i++)
- free(q->memory[i]);
- free(q->memory);
- }
- free(q);
-}
-
-/* Internal use only: add DATA to Q, but don't update fh_state. */
-static int q_append_no_sync_fh_state(struct queue *q, const char *data)
-{
- size_t data_size, entry_index;
- unsigned char *copy;
-
- if (q->queue_length == q->num_entries) {
- errno = ENOSPC;
- return -1;
- }
-
- data_size = strlen(data) + 1;
- if (data_size > q->entry_size) {
- errno = EINVAL;
- return -1;
- }
-
- entry_index = (q->queue_head + q->queue_length) % q->num_entries;
- if (q->memory != NULL) {
- if (q->memory[entry_index] != NULL) {
- errno = EIO; /* This is _really_ unexpected. */
- return -1;
- }
- copy = malloc(data_size);
- if (copy == NULL)
- return -1;
- memcpy(copy, data, data_size);
- } else
- copy = NULL;
-
- if (q->fd != -1) {
- size_t offset;
-
- offset = entry_offset(q, entry_index);
- if (full_pwrite(q->fd, data, data_size, offset) != 0) {
- int saved_errno;
-
- saved_errno = errno;
- if (copy != NULL)
- free(copy);
- errno = saved_errno;
- return -1;
- }
- }
-
- if (copy != NULL)
- q->memory[entry_index] = copy;
-
- q->queue_length++;
-
- return 0;
-}
-
-int q_append(struct queue *q, const char *data)
-{
- int r;
-
- r = q_append_no_sync_fh_state(q, data);
- if (r != 0)
- return r;
-
- return sync_fh_state(q); /* Calls q_sync() */
-}
-
-int q_peek(struct queue *q, char *buf, size_t size)
-{
- const unsigned char *data;
- size_t data_size;
-
- if (q->queue_length == 0)
- return 0;
-
- if (q->memory != NULL && q->memory[q->queue_head] != NULL) {
- data = q->memory[q->queue_head];
- data_size = strlen((char *)data) + 1;
- } else if (q->fd != -1) {
- const unsigned char *end;
-
- if (full_pread(q->fd, q->buffer, q->entry_size,
- entry_offset(q, q->queue_head)) != 0)
- return -1;
- data = q->buffer;
- end = memchr(q->buffer, '\0', q->entry_size);
- if (end == NULL) {
- /* FIXME: silently drop this entry? */
- errno = EBADMSG;
- return -1;
- }
- data_size = (end - data) + 1;
-
- if (q->memory != NULL) {
- unsigned char *copy;
-
- copy = malloc(data_size);
- if (copy != NULL) { /* Silently ignore failures. */
- memcpy(copy, data, data_size);
- q->memory[q->queue_head] = copy;
- }
- }
- } else {
- errno = EIO; /* This is _really_ unexpected. */
- return -1;
- }
-
- if (size < data_size) {
- errno = ERANGE;
- return -1;
- }
- memcpy(buf, data, data_size);
- return data_size;
-}
-
-/* Internal use only: drop head of Q, but don't write this into the file */
-static int q_drop_head_memory_only(struct queue *q)
-{
- if (q->queue_length == 0) {
- errno = EINVAL;
- return -1;
- }
-
- if (q->memory != NULL) {
- free(q->memory[q->queue_head]);
- q->memory[q->queue_head] = NULL;
- }
-
- q->queue_head++;
- if (q->queue_head == q->num_entries)
- q->queue_head = 0;
- q->queue_length--;
- return 0;
-}
-
-int q_drop_head(struct queue *q)
-{
- int r;
-
- r = q_drop_head_memory_only(q);
- if (r != 0)
- return r;
-
- return sync_fh_state(q); /* Calls q_sync() */
-}
-
-size_t q_queue_length(const struct queue *q)
-{
- return q->queue_length;
-}
-
-struct queue *q_open(int q_flags, const char *path, size_t num_entries,
- size_t entry_size)
-{
- struct queue *q, *q2;
- char *tmp_path, *buf;
- size_t path_len;
- int saved_errno, fd;
-
- q = q_open_no_resize(q_flags, path, num_entries, entry_size);
- if (q == NULL || q->num_entries == num_entries)
- return q;
-
- if ((q->flags & Q_RESIZE) == 0) {
- saved_errno = EINVAL;
- goto err_errno_q;
- }
-
- if (q->queue_length > num_entries) {
- saved_errno = ENOSPC;
- goto err_errno_q;
- }
-
- buf = malloc(entry_size);
- if (buf == NULL) {
- saved_errno = errno;
- goto err_errno_q;
- }
-
- path_len = strlen(path);
- tmp_path = malloc(path_len + 7);
- if (tmp_path == NULL) {
- saved_errno = errno;
- goto err_errno_buf;
- }
- memcpy(tmp_path, path, path_len);
- memcpy(tmp_path + path_len, "XXXXXX", 7);
- /* We really want tmpnam() here (safe due to the Q_EXCL below), but gcc
- warns on any use of tmpnam(). */
- fd = mkstemp(tmp_path);
- if (fd == -1) {
- saved_errno = errno;
- goto err_errno_tmp_path;
- }
- if (close(fd) != 0 || unlink(tmp_path) != 0) {
- saved_errno = errno;
- goto err_errno_tmp_file;
- }
-
- q2 = q_open_no_resize(q_flags | Q_CREAT | Q_EXCL, tmp_path, num_entries,
- entry_size);
- if (q2 == NULL) {
- saved_errno = errno;
- goto err_errno_tmp_file;
- }
- if (q2->num_entries != num_entries) {
- errno = EIO; /* This is _really_ unexpected. */
- goto err_q2;
- }
-
- for (;;) {
- int r;
-
- r = q_peek(q, buf, entry_size);
- if (r == 0)
- break;
- if (r < 0)
- goto err_q2;
-
- if (q_append_no_sync_fh_state(q2, buf) != 0)
- goto err_q2;
- if (q_drop_head_memory_only(q) != 0)
- goto err_q2;
- }
- if (sync_fh_state(q2) != 0)
- goto err_q2;
-
- if (rename(tmp_path, path) != 0)
- goto err_q2;
-
- q_close(q);
- free(buf);
- free(tmp_path);
- return q2;
-
-err_q2:
- saved_errno = errno;
- q_close(q2);
-err_errno_tmp_file:
- unlink(tmp_path);
-err_errno_tmp_path:
- free(tmp_path);
-err_errno_buf:
- free(buf);
-err_errno_q:
- q_close(q);
- errno = saved_errno;
- return NULL;
-}
diff --git a/framework/src/audit/audisp/plugins/remote/queue.h b/framework/src/audit/audisp/plugins/remote/queue.h
deleted file mode 100644
index 5f5ef647..00000000
--- a/framework/src/audit/audisp/plugins/remote/queue.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* queue.h -- a queue abstraction
- * Copyright 2009, 2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- * Miloslav Trmač <mitr@redhat.com>
- */
-
-#ifndef QUEUE_HEADER
-#define QUEUE_HEADER
-
-#include <sys/types.h>
-
-struct queue;
-
-enum {
- // Queue storage. Both options can be set at the same time.
- Q_IN_MEMORY = 1 << 0, // Keep a copy of the queue in memory
- Q_IN_FILE = 1 << 1, // Store the queue in a file
- // Other flags for use with Q_IN_FILE
- Q_CREAT = 1 << 2, // Create the queue if it does not exist
- Q_EXCL = 1 << 3, // With Q_CREAT, don't open an existing queue
- Q_SYNC = 1 << 4, // fdatasync() after each operation
- Q_RESIZE = 1 << 5, // resize the queue if needed
-};
-
-/* Open a queue using Q_FLAGS and return it. If Q_IN_FILE: use PATH for the
- * file, NUM_ENTRIES must be the same for all users of the file unless Q_RESIZE
- * is set. ENTRY_SIZE is the maximum length of a stored string, including the
- * trailing NUL. If Q_IN_FILE, it must be the same for all users of the file.
- * On error, return NULL and set errno. */
-struct queue *q_open(int q_flags, const char *path, size_t num_entries,
- size_t entry_size);
-/* Close Q. */
-void q_close(struct queue *q);
-
-/* Add DATA to tail of Q. Return 0 on success, -1 on error and set errno. */
-int q_append(struct queue *q, const char *data);
-
-/* Peek at head of Q, storing it into BUF of SIZE. Return 1 if an entry
- * exists, 0 if queue is empty. On error, return -1 and set errno. */
-int q_peek(struct queue *q, char *buf, size_t size);
-
-/* Drop head of Q and return 0. On error, return -1 and set errno. */
-int q_drop_head(struct queue *q);
-
-/* Return the number of entries in Q. */
-size_t q_queue_length(const struct queue *q);
-
-#endif
-
diff --git a/framework/src/audit/audisp/plugins/remote/remote-config.c b/framework/src/audit/audisp/plugins/remote/remote-config.c
deleted file mode 100644
index 841a1ed3..00000000
--- a/framework/src/audit/audisp/plugins/remote/remote-config.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/* remote-config.c --
- * Copyright 2008,2009,2011,2015 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- *
- */
-
-#include "config.h"
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <ctype.h>
-#include <limits.h>
-#include "remote-config.h"
-
-/* Local prototypes */
-struct nv_pair
-{
- const char *name;
- const char *value;
- const char *option;
-};
-
-struct kw_pair
-{
- const char *name;
- int (*parser)(struct nv_pair *, int, remote_conf_t *);
- int max_options;
-};
-
-struct nv_list
-{
- const char *name;
- int option;
-};
-
-static char *get_line(FILE *f, char *buf);
-static int nv_split(char *buf, struct nv_pair *nv);
-static const struct kw_pair *kw_lookup(const char *val);
-static int server_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int port_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int local_port_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int transport_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int mode_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int queue_file_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int depth_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int format_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int heartbeat_timeout_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int enable_krb5_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int krb5_principal_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int krb5_client_name_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int krb5_key_file_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int network_retry_time_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int max_tries_per_record_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int max_time_per_record_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-#define AP(x) static int x##_action_parser(struct nv_pair *nv, int line, \
- remote_conf_t *config);
-AP(network_failure)
-AP(disk_low)
-AP(disk_full)
-AP(disk_error)
-AP(generic_error)
-AP(generic_warning)
-AP(queue_error)
-#undef AP
-static int remote_ending_action_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int overflow_action_parser(struct nv_pair *nv, int line,
- remote_conf_t *config);
-static int sanity_check(remote_conf_t *config, const char *file);
-
-static const struct kw_pair keywords[] =
-{
- {"remote_server", server_parser, 0 },
- {"port", port_parser, 0 },
- {"local_port", local_port_parser, 0 },
- {"transport", transport_parser, 0 },
- {"mode", mode_parser, 0 },
- {"queue_file", queue_file_parser, 0 },
- {"queue_depth", depth_parser, 0 },
- {"format", format_parser, 0 },
- {"network_retry_time", network_retry_time_parser, 0 },
- {"max_tries_per_record", max_tries_per_record_parser, 0 },
- {"max_time_per_record", max_time_per_record_parser, 0 },
- {"heartbeat_timeout", heartbeat_timeout_parser, 0 },
- {"enable_krb5", enable_krb5_parser, 0 },
- {"krb5_principal", krb5_principal_parser, 0 },
- {"krb5_client_name", krb5_client_name_parser, 0 },
- {"krb5_key_file", krb5_key_file_parser, 0 },
- {"network_failure_action", network_failure_action_parser, 1 },
- {"disk_low_action", disk_low_action_parser, 1 },
- {"disk_full_action", disk_full_action_parser, 1 },
- {"disk_error_action", disk_error_action_parser, 1 },
- {"remote_ending_action", remote_ending_action_parser, 1 },
- {"generic_error_action", generic_error_action_parser, 1 },
- {"generic_warning_action", generic_warning_action_parser, 1 },
- {"queue_error_action", queue_error_action_parser, 1 },
- {"overflow_action", overflow_action_parser, 1 },
- { NULL, NULL, 0 }
-};
-
-static const struct nv_list transport_words[] =
-{
- {"tcp", T_TCP },
- { NULL, 0 }
-};
-
-static const struct nv_list mode_words[] =
-{
- {"immediate", M_IMMEDIATE },
- {"forward", M_STORE_AND_FORWARD },
- { NULL, 0 }
-};
-
-static const struct nv_list fail_action_words[] =
-{
- {"ignore", FA_IGNORE },
- {"syslog", FA_SYSLOG },
- {"exec", FA_EXEC },
- {"suspend", FA_SUSPEND },
- {"single", FA_SINGLE },
- {"halt", FA_HALT },
- {"stop", FA_STOP },
- { NULL, 0 }
-};
-
-static const struct nv_list overflow_action_words[] =
-{
- {"ignore", OA_IGNORE },
- {"syslog", OA_SYSLOG },
- {"suspend", OA_SUSPEND },
- {"single", OA_SINGLE },
- {"halt", OA_HALT },
- { NULL, 0 }
-};
-
-static const struct nv_list format_words[] =
-{
- {"ascii", F_ASCII },
- {"managed", F_MANAGED },
- { NULL, 0 }
-};
-
-#ifdef USE_GSSAPI
-static const struct nv_list enable_krb5_values[] =
-{
- {"yes", 1 },
- {"no", 0 },
- { NULL, 0 }
-};
-#endif
-
-/*
- * Set everything to its default value
-*/
-void clear_config(remote_conf_t *config)
-{
- config->remote_server = NULL;
- config->port = 60;
- config->local_port = 0;
- config->transport = T_TCP;
- config->mode = M_IMMEDIATE;
- config->queue_file = NULL;
- config->queue_depth = 2048;
- config->format = F_MANAGED;
-
- config->network_retry_time = 1;
- config->max_tries_per_record = 3;
- config->max_time_per_record = 5;
- config->heartbeat_timeout = 0;
-
-#define IA(x,f) config->x##_action = f; config->x##_exe = NULL
- IA(network_failure, FA_STOP);
- IA(disk_low, FA_IGNORE);
- IA(disk_full, FA_IGNORE);
- IA(disk_error, FA_SYSLOG);
- IA(remote_ending, FA_RECONNECT);
- IA(generic_error, FA_SYSLOG);
- IA(generic_warning, FA_SYSLOG);
- IA(queue_error, FA_STOP);
-#undef IA
- config->overflow_action = OA_SYSLOG;
-
- config->enable_krb5 = 0;
- config->krb5_principal = NULL;
- config->krb5_client_name = NULL;
- config->krb5_key_file = NULL;
-}
-
-int load_config(remote_conf_t *config, const char *file)
-{
- int fd, rc, mode, lineno = 1;
- struct stat st;
- FILE *f;
- char buf[128];
-
- clear_config(config);
-
- /* open the file */
- mode = O_RDONLY;
- rc = open(file, mode);
- if (rc < 0) {
- if (errno != ENOENT) {
- syslog(LOG_ERR, "Error opening %s (%s)", file,
- strerror(errno));
- return 1;
- }
- syslog(LOG_WARNING,
- "Config file %s doesn't exist, skipping", file);
- return 0;
- }
- fd = rc;
-
- /* check the file's permissions: owned by root, not world writable,
- * not symlink.
- */
- if (fstat(fd, &st) < 0) {
- syslog(LOG_ERR, "Error fstat'ing config file (%s)",
- strerror(errno));
- close(fd);
- return 1;
- }
- if (st.st_uid != 0) {
- syslog(LOG_ERR, "Error - %s isn't owned by root",
- file);
- close(fd);
- return 1;
- }
- if ((st.st_mode & S_IWOTH) == S_IWOTH) {
- syslog(LOG_ERR, "Error - %s is world writable",
- file);
- close(fd);
- return 1;
- }
- if (!S_ISREG(st.st_mode)) {
- syslog(LOG_ERR, "Error - %s is not a regular file",
- file);
- close(fd);
- return 1;
- }
-
- /* it's ok, read line by line */
- f = fdopen(fd, "rm");
- if (f == NULL) {
- syslog(LOG_ERR, "Error - fdopen failed (%s)",
- strerror(errno));
- close(fd);
- return 1;
- }
-
- while (get_line(f, buf)) {
- // convert line into name-value pair
- const struct kw_pair *kw;
- struct nv_pair nv;
- rc = nv_split(buf, &nv);
- switch (rc) {
- case 0: // fine
- break;
- case 1: // not the right number of tokens.
- syslog(LOG_ERR,
- "Wrong number of arguments for line %d in %s",
- lineno, file);
- break;
- case 2: // no '=' sign
- syslog(LOG_ERR,
- "Missing equal sign for line %d in %s",
- lineno, file);
- break;
- default: // something else went wrong...
- syslog(LOG_ERR,
- "Unknown error for line %d in %s",
- lineno, file);
- break;
- }
- if (nv.name == NULL) {
- lineno++;
- continue;
- }
- if (nv.value == NULL) {
- fclose(f);
- return 1;
- }
-
- /* identify keyword or error */
- kw = kw_lookup(nv.name);
- if (kw->name == NULL) {
- syslog(LOG_ERR,
- "Unknown keyword \"%s\" in line %d of %s",
- nv.name, lineno, file);
- fclose(f);
- return 1;
- }
-
- /* Check number of options */
- if (kw->max_options == 0 && nv.option != NULL) {
- syslog(LOG_ERR,
- "Keyword \"%s\" has invalid option "
- "\"%s\" in line %d of %s",
- nv.name, nv.option, lineno, file);
- fclose(f);
- return 1;
- }
-
- /* dispatch to keyword's local parser */
- rc = kw->parser(&nv, lineno, config);
- if (rc != 0) {
- fclose(f);
- return 1; // local parser puts message out
- }
-
- lineno++;
- }
-
- fclose(f);
- if (lineno > 1)
- return sanity_check(config, file);
- return 0;
-}
-
-static char *get_line(FILE *f, char *buf)
-{
- if (fgets_unlocked(buf, 128, f)) {
- /* remove newline */
- char *ptr = strchr(buf, 0x0a);
- if (ptr)
- *ptr = 0;
- return buf;
- }
- return NULL;
-}
-
-static int nv_split(char *buf, struct nv_pair *nv)
-{
- /* Get the name part */
- char *ptr, *saved;
-
- nv->name = NULL;
- nv->value = NULL;
- nv->option = NULL;
- ptr = strtok_r(buf, " ", &saved);
- if (ptr == NULL)
- return 0; /* If there's nothing, go to next line */
- if (ptr[0] == '#')
- return 0; /* If there's a comment, go to next line */
- nv->name = ptr;
-
- /* Check for a '=' */
- ptr = strtok_r(NULL, " ", &saved);
- if (ptr == NULL)
- return 1;
- if (strcmp(ptr, "=") != 0)
- return 2;
-
- /* get the value */
- ptr = strtok_r(NULL, " ", &saved);
- if (ptr == NULL)
- return 1;
- nv->value = ptr;
-
- /* See if there's an option */
- ptr = strtok_r(NULL, " ", &saved);
- if (ptr) {
- nv->option = ptr;
-
- /* Make sure there's nothing else */
- ptr = strtok_r(NULL, " ", &saved);
- if (ptr)
- return 1;
- }
-
- /* Everything is OK */
- return 0;
-}
-
-static const struct kw_pair *kw_lookup(const char *val)
-{
- int i = 0;
- while (keywords[i].name != NULL) {
- if (strcasecmp(keywords[i].name, val) == 0)
- break;
- i++;
- }
- return &keywords[i];
-}
-
-static int check_exe_name(const char *val, int line)
-{
- struct stat buf;
-
- if (val == NULL) {
- syslog(LOG_ERR, "Executable path needed for line %d", line);
- return -1;
- }
-
- if (*val != '/') {
- syslog(LOG_ERR, "Absolute path needed for %s - line %d",
- val, line);
- return -1;
- }
-
- if (stat(val, &buf) < 0) {
- syslog(LOG_ERR, "Unable to stat %s (%s) - line %d", val,
- strerror(errno), line);
- return -1;
- }
- if (!S_ISREG(buf.st_mode)) {
- syslog(LOG_ERR, "%s is not a regular file - line %d", val,
- line);
- return -1;
- }
- if (buf.st_uid != 0) {
- syslog(LOG_ERR, "%s is not owned by root - line %d", val,
- line);
- return -1;
- }
- if ((buf.st_mode & (S_IRWXU|S_IRWXG|S_IWOTH)) !=
- (S_IRWXU|S_IRGRP|S_IXGRP)) {
- syslog(LOG_ERR, "%s permissions should be 0750 - line %d", val,
- line);
- return -1;
- }
- return 0;
-}
-
-static int server_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- if (nv->value)
- config->remote_server = strdup(nv->value);
- else
- config->remote_server = NULL;
- return 0;
-}
-
-static int parse_uint (const struct nv_pair *nv, int line, unsigned int *valp,
- unsigned int min, unsigned int max)
-{
- const char *ptr = nv->value;
- unsigned int i;
-
- /* check that all chars are numbers */
- for (i=0; ptr[i]; i++) {
- if (!isdigit(ptr[i])) {
- syslog(LOG_ERR,
- "Value %s should only be numbers - line %d",
- nv->value, line);
- return 1;
- }
- }
-
- /* convert to unsigned int */
- errno = 0;
- i = strtoul(nv->value, NULL, 10);
- if (errno) {
- syslog(LOG_ERR,
- "Error converting string to a number (%s) - line %d",
- strerror(errno), line);
- return 1;
- }
- /* Check its range */
- if (min != 0 && i < (int)min) {
- syslog(LOG_ERR,
- "Error - converted number (%s) is too small - line %d",
- nv->value, line);
- return 1;
- }
- if (max != 0 && i > max) {
- syslog(LOG_ERR,
- "Error - converted number (%s) is too large - line %d",
- nv->value, line);
- return 1;
- }
- *valp = (unsigned int)i;
- return 0;
-}
-
-static int port_parser(struct nv_pair *nv, int line, remote_conf_t *config)
-{
- return parse_uint (nv, line, &(config->port), 0, 65535);
-}
-
-static int local_port_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- if ((strcasecmp(nv->value, "any") == 0))
- return 0; // The default is 0, which means any port
- return parse_uint (nv, line, &(config->local_port), 0, 65535);
-}
-
-static int transport_parser(struct nv_pair *nv, int line, remote_conf_t *config)
-{
- int i;
- for (i=0; transport_words[i].name != NULL; i++) {
- if (strcasecmp(nv->value, transport_words[i].name) == 0) {
- config->transport = transport_words[i].option;
- return 0;
- }
- }
- syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
- return 1;
-}
-
-static int mode_parser(struct nv_pair *nv, int line, remote_conf_t *config)
-{
- int i;
- for (i=0; mode_words[i].name != NULL; i++) {
- if (strcasecmp(nv->value, mode_words[i].name) == 0) {
- config->mode = mode_words[i].option;
- return 0;
- }
- }
- syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
- return 1;
-}
-
-static int queue_file_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- if (nv->value) {
- if (*nv->value != '/') {
- syslog(LOG_ERR, "Absolute path needed for %s - line %d",
- nv->value, line);
- return 1;
- }
- config->queue_file = strdup(nv->value);
- } else
- config->queue_file = NULL;
- return 0;
-}
-
-static int depth_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- return parse_uint (nv, line, &(config->queue_depth), 1, INT_MAX);
-}
-
-static int action_parser(struct nv_pair *nv, int line,
- failure_action_t *actp, const char **exep)
-{
- int i;
- for (i=0; fail_action_words[i].name != NULL; i++) {
- if (strcasecmp(nv->value, fail_action_words[i].name) == 0) {
- if (fail_action_words[i].option == FA_EXEC) {
- if (check_exe_name(nv->option, line))
- return 1;
- *exep = strdup(nv->option);
- }
- *actp = fail_action_words[i].option;
- return 0;
- }
- }
- syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
- return 1;
-}
-
-#define AP(x) \
-static int x##_action_parser(struct nv_pair *nv, int line, \
- remote_conf_t *config) \
-{ \
- return action_parser(nv,line,&(config->x##_action),&(config->x##_exe));\
-} \
-
-AP(network_failure)
-AP(disk_low)
-AP(disk_full)
-AP(disk_error)
-AP(generic_error)
-AP(generic_warning)
-AP(queue_error)
-#undef AP
-
-static int overflow_action_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- int i;
-
- for (i=0; overflow_action_words[i].name != NULL; i++) {
- if (strcasecmp(nv->value, overflow_action_words[i].name) == 0) {
- config->overflow_action = overflow_action_words[i].option;
- return 0;
- }
- }
- syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
- return 1;
-}
-
-static int remote_ending_action_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- if (strcasecmp(nv->value, "reconnect") == 0) {
- config->remote_ending_action = FA_RECONNECT;
- return 0;
- }
- return action_parser(nv, line, &config->remote_ending_action,
- &config->remote_ending_exe);
-}
-
-static int format_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- int i;
- for (i=0; format_words[i].name != NULL; i++) {
- if (strcasecmp(nv->value, format_words[i].name) == 0) {
- config->format = format_words[i].option;
- return 0;
- }
- }
- syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
- return 1;
-}
-
-static int network_retry_time_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- return parse_uint(nv, line, &config->network_retry_time, 1, INT_MAX);
-}
-
-static int max_tries_per_record_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- return parse_uint(nv, line, &config->max_tries_per_record, 1, INT_MAX);
-}
-
-static int max_time_per_record_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- return parse_uint(nv, line, &(config->max_time_per_record), 1, INT_MAX);
-}
-
-static int heartbeat_timeout_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
- return parse_uint (nv, line, &(config->heartbeat_timeout), 0, INT_MAX);
-}
-
-static int enable_krb5_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
-#ifndef USE_GSSAPI
- syslog(LOG_INFO,
- "GSSAPI support is not enabled, ignoring value at line %d",
- line);
- return 0;
-#else
- unsigned long i;
-
- for (i=0; enable_krb5_values[i].name != NULL; i++) {
- if (strcasecmp(nv->value, enable_krb5_values[i].name) == 0) {
- config->enable_krb5 = enable_krb5_values[i].option;
- return 0;
- }
- }
- syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line);
- return 1;
-#endif
-}
-
-static int krb5_principal_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
-#ifndef USE_GSSAPI
- syslog(LOG_INFO,
- "GSSAPI support is not enabled, ignoring value at line %d",
- line);
-#else
- if (config->krb5_principal)
- free ((char *)config->krb5_principal);
-
- config->krb5_principal = strdup(nv->value);
-#endif
- return 0;
-}
-
-static int krb5_client_name_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
-#ifndef USE_GSSAPI
- syslog(LOG_INFO,
- "GSSAPI support is not enabled, ignoring value at line %d",
- line);
-#else
- if (config->krb5_client_name)
- free ((char *)config->krb5_client_name);
-
- config->krb5_client_name = strdup(nv->value);
-#endif
- return 0;
-}
-
-static int krb5_key_file_parser(struct nv_pair *nv, int line,
- remote_conf_t *config)
-{
-#ifndef USE_GSSAPI
- syslog(LOG_INFO,
- "GSSAPI support is not enabled, ignoring value at line %d",
- line);
-#else
- if (config->krb5_key_file)
- free ((char *)config->krb5_key_file);
-
- config->krb5_key_file = strdup(nv->value);
-#endif
- return 0;
-}
-
-/*
- * This function is where we do the integrated check of the audispd config
- * options. At this point, all fields have been read. Returns 0 if no
- * problems and 1 if problems detected.
- */
-static int sanity_check(remote_conf_t *config, const char *file)
-{
- /* Error checking */
-// server should have string
-// port should be less that 32k
-// queue_depth should be less than 100k
-// If fail_action is F_EXEC, fail_exec must exist
- if (config->mode == M_STORE_AND_FORWARD
- && config->format != F_MANAGED) {
- syslog(LOG_ERR, "\"mode=forward\" is valid only with "
- "\"format=managed\"");
- return 1;
- }
- return 0;
-}
-
-void free_config(remote_conf_t *config)
-{
- free((void *)config->remote_server);
- free((void *)config->queue_file);
- free((void *)config->network_failure_exe);
- free((void *)config->disk_low_exe);
- free((void *)config->disk_full_exe);
- free((void *)config->disk_error_exe);
- free((void *)config->remote_ending_exe);
- free((void *)config->generic_error_exe);
- free((void *)config->generic_warning_exe);
- free((void *)config->queue_error_exe);
- free((void *)config->krb5_principal);
- free((void *)config->krb5_client_name);
- free((void *)config->krb5_key_file);
-}
-
diff --git a/framework/src/audit/audisp/plugins/remote/remote-config.h b/framework/src/audit/audisp/plugins/remote/remote-config.h
deleted file mode 100644
index 20c1f0b2..00000000
--- a/framework/src/audit/audisp/plugins/remote/remote-config.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* remote-config.h --
- * Copyright 2008, 2009, 2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- *
- */
-
-#ifndef REMOTE_CONFIG_H
-#define REMOTE_CONFIG_H
-
-typedef enum { M_IMMEDIATE, M_STORE_AND_FORWARD } rmode_t;
-typedef enum { T_TCP, T_SSL, T_GSSAPI, T_LABELED } transport_t;
-typedef enum { F_ASCII, F_MANAGED } format_t;
-typedef enum { FA_IGNORE, FA_SYSLOG, FA_EXEC, FA_RECONNECT, FA_SUSPEND,
- FA_SINGLE, FA_HALT, FA_STOP } failure_action_t;
-typedef enum { OA_IGNORE, OA_SYSLOG, OA_SUSPEND, OA_SINGLE,
- OA_HALT } overflow_action_t;
-
-typedef struct remote_conf
-{
- const char *remote_server;
- unsigned int port;
- unsigned int local_port;
- transport_t transport;
- rmode_t mode;
- const char *queue_file;
- unsigned int queue_depth;
- format_t format;
- unsigned int network_retry_time;
- unsigned int max_tries_per_record;
- unsigned int max_time_per_record;
- unsigned int heartbeat_timeout;
- int enable_krb5;
- const char *krb5_principal;
- const char *krb5_client_name;
- const char *krb5_key_file;
-
- failure_action_t network_failure_action;
- const char *network_failure_exe;
- failure_action_t disk_low_action;
- const char *disk_low_exe;
- failure_action_t disk_full_action;
- const char *disk_full_exe;
- failure_action_t disk_error_action;
- const char *disk_error_exe;
- failure_action_t remote_ending_action;
- const char *remote_ending_exe;
- failure_action_t generic_error_action;
- const char *generic_error_exe;
- failure_action_t generic_warning_action;
- const char *generic_warning_exe;
- failure_action_t queue_error_action;
- const char *queue_error_exe;
- overflow_action_t overflow_action;
-} remote_conf_t;
-
-void clear_config(remote_conf_t *config);
-int load_config(remote_conf_t *config, const char *file);
-void free_config(remote_conf_t *config);
-
-#endif
-
diff --git a/framework/src/audit/audisp/plugins/remote/remote-fgets.c b/framework/src/audit/audisp/plugins/remote/remote-fgets.c
deleted file mode 100644
index 41e9c0c2..00000000
--- a/framework/src/audit/audisp/plugins/remote/remote-fgets.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* remote-fgets.c --
- * Copyright 2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- */
-
-#include "config.h"
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include "remote-fgets.h"
-
-#define BUF_SIZE 8192
-static char buffer[2*BUF_SIZE+1] = { 0 };
-static char *current = buffer;
-static char *const eptr = buffer+(2*BUF_SIZE);
-static int eof = 0;
-
-int remote_fgets_eof(void)
-{
- return eof;
-}
-
-/* Function to check if we have more data stored
- * and ready to process. If we have a newline or enough
- * bytes we return 1 for success. Otherwise 0 meaning that
- * there is not enough to process without blocking. */
-int remote_fgets_more(size_t blen)
-{
- char *ptr = strchr(buffer, '\n');
- assert(blen != 0);
- if (ptr || (size_t)(current-buffer) >= blen-1)
- return 1;
- return 0;
-}
-
-int remote_fgets(char *buf, size_t blen, int fd)
-{
- int complete = 0;
- size_t line_len;
- char *line_end = NULL;
-
- assert(blen != 0);
- /* See if we have more in the buffer first */
- if (current != buffer) {
- line_end = strchr(buffer, '\n');
- if (line_end == NULL && (size_t)(current - buffer) >= blen-1)
- line_end = current-1; // have enough to fill blen, so point to end
- }
-
- /* Otherwise get some new bytes */
- if (line_end == NULL && current != eptr && !eof) {
- ssize_t len;
-
- /* Use current since we may be adding more */
- do {
- len = read(fd, current, eptr - current);
- } while (len < 0 && errno == EINTR);
- if (len < 0)
- return -1;
- if (len == 0)
- eof = 1;
- else
- current[len] = 0;
- current += len;
-
- /* Start from beginning to see if we have one */
- line_end = strchr(buffer, '\n');
- }
-
- /* See what we have */
- if (line_end) {
- /* Include the last character (usually newline) */
- line_len = (line_end+1) - buffer;
- /* Make sure we are within the right size */
- if (line_len > blen-1)
- line_len = blen-1;
- complete = 1;
- } else if (current == eptr) {
- /* We are full but no newline */
- line_len = blen-1;
- complete = 1;
- } else if (current >= buffer+blen-1) {
- /* Not completely full, no newline, but enough to fill buf */
- line_len = blen-1;
- complete = 1;
- }
- if (complete) {
- size_t remainder_len;
-
- /* Move to external buf and terminate it */
- memcpy(buf, buffer, line_len);
- buf[line_len] = 0;
- remainder_len = current - (buffer + line_len);
- if (remainder_len > 0) {
- /* We have a few leftover bytes to move */
- memmove(buffer, buffer+line_len, remainder_len);
- current = buffer+remainder_len;
- } else {
- /* Got the whole thing, just reset */
- current = buffer;
- }
- *current = 0;
- }
- return complete;
-}
diff --git a/framework/src/audit/audisp/plugins/remote/remote-fgets.h b/framework/src/audit/audisp/plugins/remote/remote-fgets.h
deleted file mode 100644
index cb6b2d51..00000000
--- a/framework/src/audit/audisp/plugins/remote/remote-fgets.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* remote-fgtes.h -- a replacement for glibc's fgets
- * Copyright 2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- */
-
-#ifndef REMOTE_FGETS_HEADER
-#define REMOTE_FGETS_HEADER
-
-#include <sys/types.h>
-
-int remote_fgets_eof(void);
-int remote_fgets_more(size_t blen);
-int remote_fgets(char *buf, size_t blen, int fd);
-
-#endif
-
diff --git a/framework/src/audit/audisp/plugins/remote/test-queue.c b/framework/src/audit/audisp/plugins/remote/test-queue.c
deleted file mode 100644
index cbf815e8..00000000
--- a/framework/src/audit/audisp/plugins/remote/test-queue.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/* test-queue.c -- test suite for persistent-queue.c
- * Copyright 2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Authors:
- * Miloslav Trmač <mitr@redhat.com>
- */
-
-#include "config.h"
-#include <errno.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include "queue.h"
-
-#define NUM_ENTRIES 7
-/* 3*4096, larger than MAX_AUDIT_MESSAGE_LENGTH. The same value is used in the
- main audisp-remote code. */
-#define ENTRY_SIZE 12288
-
-static char filename[] = "/tmp/tqXXXXXX";
-static struct queue *q;
-
-static char *sample_entries[NUM_ENTRIES - 1];
-#define NUM_SAMPLE_ENTRIES (sizeof(sample_entries) / sizeof(*sample_entries))
-
-#define die(...) die__(__LINE__, __VA_ARGS__)
-static void __attribute__((format (printf, 2, 3)))
-die__(int line, const char *message, ...)
-{
- va_list ap;
-
- fprintf(stderr, "test-queue: %d: ", line);
- va_start(ap, message);
- vfprintf(stderr, message, ap);
- va_end(ap);
- putc('\n', stderr);
- abort();
-}
-
-#define err(...) err__(__LINE__, __VA_ARGS__)
-static void __attribute__((format (printf, 2, 3)))
-err__(int line, const char *message, ...)
-{
- char *errno_str;
- va_list ap;
-
- errno_str = strerror(errno);
- fprintf(stderr, "test-queue: %d: ", line);
- va_start(ap, message);
- vfprintf(stderr, message, ap);
- va_end(ap);
- fprintf(stderr, ": %s\n", errno_str);
- abort();
-}
-
-static void
-init_sample_entries(void)
-{
- size_t i;
-
- for (i = 0; i < NUM_SAMPLE_ENTRIES; i++) {
- char *e;
- size_t j, len;
-
- len = rand() % ENTRY_SIZE;
- e = malloc(len + 1);
- if (e == NULL)
- err("malloc");
- for (j = 0; j < len; j++)
- e[j] = rand() % CHAR_MAX + 1;
- e[j] = '\0';
- sample_entries[i] = e;
- }
-}
-
-static void
-free_sample_entries(void)
-{
- size_t i;
-
- for (i = 0; i < NUM_SAMPLE_ENTRIES; i++)
- free(sample_entries[i]);
-}
-
-static void
-test_q_open(void)
-{
- struct queue *q2;
-
- /* Test that flags are honored */
- q2 = q_open(Q_IN_FILE | Q_CREAT | Q_EXCL, filename, NUM_ENTRIES,
- ENTRY_SIZE);
- if (q2 != NULL)
- die("q_open didn't fail");
- if (errno != EEXIST)
- err("q_open");
-
- /* Test that locking is enforced. Use a separate process because
- fcntl()/lockf() locking is attached to processes, not file
- descriptors. */
- fflush(NULL);
- switch (fork()) {
- case -1:
- err("fork");
- case 0:
- q2 = q_open(Q_IN_FILE, filename, NUM_ENTRIES, ENTRY_SIZE);
- if (q2 != NULL)
- die("q_open didn't fail");
- if (errno != EBUSY)
- err("q_open");
- _exit(0);
- default: {
- int status;
-
- if (wait(&status) == (pid_t)-1)
- err("wait");
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- die("wait status %d", status);
- }
- }
-}
-
-static void
-test_empty_q (void)
-{
- char buf[ENTRY_SIZE];
-
- if (q_peek(q, buf, sizeof(buf)) != 0)
- die("q_peek reports non-empty");
-
- if (q_drop_head(q) != -1)
- die("q_drop_head didn't fail");
- if (errno != EINVAL)
- err("q_drop_head");
-
- if (q_queue_length(q) != 0)
- die("Unexpected q_queue_length");
-}
-
-static void
-test_basic_data (void)
-{
- char buf[ENTRY_SIZE + 1];
- int i;
-
- if (q_append(q, " ") != 0)
- die("q_append");
-
- memset (buf, 'A', ENTRY_SIZE);
- buf[ENTRY_SIZE] = '\0';
- if (q_append(q, buf) != -1)
- die("q_append didn't fail");
- if (errno != EINVAL)
- err("q_append");
-
- buf[ENTRY_SIZE - 1] = '\0';
- if (q_append(q, buf) != 0)
- die("q_append");
-
- if (q_queue_length(q) != 2)
- die("Unexpected q_queue_length");
-
- if (q_peek(q, buf, sizeof(buf)) < 1)
- err("q_peek");
- if (strcmp(buf, " ") != 0)
- die("invalid data returned");
- if (q_drop_head(q) != 0)
- err("q_drop_head");
-
- if (q_peek(q, buf, ENTRY_SIZE - 1) != -1)
- err("q_peek didn't fail");
- if (errno != ERANGE)
- err("q_peek");
- for (i = 0; i < 2; i++) {
- size_t j;
-
- if (q_peek(q, buf, sizeof(buf)) < 1)
- err("q_peek");
- for (j = 0; j < ENTRY_SIZE - 1; j++) {
- if (buf[j] != 'A')
- die("invalid data at %zu", j);
- }
- if (buf[j] != '\0')
- die("invalid data at %zu", j);
- }
- if (q_drop_head(q) != 0)
- err("q_drop_head");
-
- if (q_queue_length(q) != 0)
- die("Unexpected q_queue_length");
-}
-
-static void
-append_sample_entries(size_t count)
-{
- size_t i;
-
- for (i = 0; i < count; i++) {
- if (q_append(q, sample_entries[i % NUM_SAMPLE_ENTRIES]) != 0)
- die("q_append %zu", i);
- }
-}
-
-static void
-verify_sample_entries(size_t count)
-{
- char buf[ENTRY_SIZE + 1];
- size_t i;
-
- if (q_queue_length(q) != count)
- die("Unexpected q_queue_length");
- for (i = 0; i < count; i++) {
- if (q_peek(q, buf, sizeof(buf)) < 1)
- err("q_peek %zu", i);
- if (strcmp(buf, sample_entries[i % NUM_SAMPLE_ENTRIES]) != 0)
- die("invalid data %zu", i);
- if (q_drop_head(q) != 0)
- err("q_drop_head");
- }
- if (q_peek(q, buf, sizeof(buf)) != 0)
- die("q_peek reports non-empty");
-}
-
-static void
-test_run(int flags)
-{
- size_t j;
-
- q = q_open(flags | Q_CREAT | Q_EXCL, filename, NUM_ENTRIES, ENTRY_SIZE);
- if (q == NULL)
- err("q_open");
-
- if ((flags & Q_IN_FILE) != 0)
- test_q_open();
-
- /* Do this enough times to get a wraparound */
- for (j = 0; j < NUM_ENTRIES; j++) {
- test_empty_q();
- test_basic_data();
- }
-
- append_sample_entries(NUM_ENTRIES - 1);
- if (q_queue_length(q) != NUM_ENTRIES - 1)
- die("Unexpected q_queue_length");
-
- q_close(q);
-
- q = q_open(flags, filename, NUM_ENTRIES, ENTRY_SIZE);
- if (q == NULL)
- err("q_open");
- if ((flags & Q_IN_FILE) != 0)
- /* Test that the queue can be reopened and data has been
- preserved. */
- verify_sample_entries(NUM_ENTRIES - 1);
- else
- /* Test that a new in-memory queue is empty. */
- verify_sample_entries(0);
- q_close(q);
-
- if ((flags & Q_IN_FILE) != 0 && unlink(filename) != 0)
- err("unlink");
-}
-
-static void
-test_resizing(void)
-{
- q = q_open(Q_IN_FILE | Q_CREAT | Q_EXCL, filename, NUM_ENTRIES,
- ENTRY_SIZE);
- if (q == NULL)
- err("q_open");
-
- append_sample_entries(NUM_ENTRIES);
- if (q_queue_length(q) != NUM_ENTRIES)
- die("Unexpected q_queue_length");
-
- q_close(q);
-
- /* Verify num_entries is validated */
- q = q_open(Q_IN_FILE, filename, NUM_ENTRIES + 1, ENTRY_SIZE);
- if (q != NULL)
- die("q_open didn't fail");
- if (errno != EINVAL)
- err("q_open");
- q = q_open(Q_IN_FILE, filename, NUM_ENTRIES - 1, ENTRY_SIZE);
- if (q != NULL)
- die("q_open didn't fail");
- if (errno != EINVAL)
- err("q_open");
-
- /* Test increasing size */
- q = q_open(Q_IN_FILE | Q_RESIZE, filename, 2 * NUM_ENTRIES, ENTRY_SIZE);
- if (q == NULL)
- err("q_open");
- verify_sample_entries(NUM_ENTRIES);
-
- append_sample_entries(NUM_ENTRIES);
- q_close(q);
-
- /* Test decreasing size */
- q = q_open(Q_IN_FILE | Q_RESIZE, filename, NUM_ENTRIES / 2, ENTRY_SIZE);
- if (q != NULL)
- die("q_open didn't fail");
- if (errno != ENOSPC)
- err("q_open");
- q = q_open(Q_IN_FILE | Q_RESIZE, filename, NUM_ENTRIES, ENTRY_SIZE);
- if (q == NULL)
- err("q_open");
- verify_sample_entries(NUM_ENTRIES);
- q_close(q);
-
- if (unlink(filename) != 0)
- err("unlink");
-}
-
-int
-main(void)
-{
- static const int flags[] = {
- Q_IN_MEMORY,
- Q_IN_FILE,
- Q_IN_FILE | Q_SYNC,
- Q_IN_MEMORY | Q_IN_FILE
- };
-
- int fd;
- size_t i;
-
- init_sample_entries();
-
- /* We really want tmpnam() here (safe due to the Q_EXCL below), but
- gcc warns on any use of tmpnam(). */
- fd = mkstemp(filename);
- if (fd == -1)
- err("tmpnam");
- if (close(fd) != 0)
- err("close");
- if (unlink(filename) != 0)
- err("unlink");
-
- for (i = 0; i < sizeof(flags) / sizeof(*flags); i++)
- test_run(flags[i]);
-
- test_resizing();
-
- free_sample_entries();
-
- return EXIT_SUCCESS;
-}