[PATCH, v3 2/8] audispd-zos-remote plugin - configuration interface

Klaus Heinrich Kiwi klausk at linux.vnet.ibm.com
Thu Dec 13 15:49:24 UTC 2007


This patch brings the configuration interface for the zos-remote plugin
This is taken directly from Steve's audit dispatcher code, only adapted
for this specific plugin.

Signed-off-by: Klaus Heinrich Kiwi <klausk at br.ibm.com> 

diff -purN audit-1.6.2/audisp/plugins/zos-remote/zos-remote-config.c audit-1.6.2_zos-remote/audisp/plugins/zos-remote/zos-remote-config.c
--- audit-1.6.2/audisp/plugins/zos-remote/zos-remote-config.c	1969-12-31 21:00:00.000000000 -0300
+++ audit-1.6.2_zos-remote/audisp/plugins/zos-remote/zos-remote-config.c	2007-12-04 15:33:06.000000000 -0200
@@ -0,0 +1,442 @@
+/***************************************************************************
+ *   Copyright (C) 2007 International Business Machines  Corp.             *
+ *   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:                                                                *
+ *   Klaus Heinrich Kiwi <klausk at br.ibm.com>                               *
+ *   based on code by Steve Grubb <sgrubb at redhat.com>                      *
+ ***************************************************************************/
+
+#include "zos-remote-config.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "zos-remote-log.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, plugin_conf_t *);
+        int max_options;
+};
+
+struct nv_list
+{
+        const char *name;
+        int option;
+};
+
+static char *get_line(FILE *, char *);
+static int nv_split(char *, struct nv_pair *);
+static const struct kw_pair *kw_lookup(const char *);
+static int server_parser(struct nv_pair *, int, plugin_conf_t *);
+static int port_parser(struct nv_pair *, int, plugin_conf_t *);
+static int timeout_parser(struct nv_pair *, int, plugin_conf_t *);
+static int user_parser(struct nv_pair *, int, plugin_conf_t *);
+static int password_parser(struct nv_pair *, int, plugin_conf_t *);
+static int q_depth_parser(struct nv_pair *, int, plugin_conf_t *);
+static int sanity_check(plugin_conf_t *, const char *);
+
+static const struct kw_pair keywords[] = {
+        {"server", server_parser, 0},
+        {"port", port_parser, 0},
+        {"timeout", timeout_parser, 0},
+        {"user", user_parser, 0},
+        {"password", password_parser, 0},
+        {"q_depth", q_depth_parser, 0},
+        {NULL, NULL, 0}
+};
+
+
+
+/*
+ * Set everything to its default value
+*/
+void plugin_clear_config(plugin_conf_t * c)
+{
+        c->server = NULL;
+        c->port = 0;
+        c->user = NULL;
+        c->password = NULL;
+        c->timeout = 15;
+        c->q_depth = 64;
+        /* not re-setting counter */
+}
+
+int plugin_load_config(plugin_conf_t * c, char *file)
+{
+        int fd, rc, mode, lineno = 1;
+        struct stat st;
+        FILE *f;
+        char buf[128];
+
+        plugin_clear_config(c);
+
+        /* open the file */
+        mode = O_RDONLY;
+        rc = open(file, mode);
+        if (rc < 0) {
+                if (errno != ENOENT) {
+                        log_err("Error opening %s (%s)", file,
+                                strerror(errno));
+                        return 1;
+                }
+                log_warn("Config file %s doesn't exist, skipping", file);
+                return 1;
+        }
+        fd = rc;
+
+        /* check the file's permissions: owned by root, not world anything,
+         * not symlink.
+         */
+        if (fstat(fd, &st) < 0) {
+                log_err("Error fstat'ing config file (%s)",
+                        strerror(errno));
+                close(fd);
+                return 1;
+        }
+        if (st.st_uid != 0) {
+                log_err("Error - %s isn't owned by root", file);
+                close(fd);
+                return 1;
+        }
+        if ((st.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP)) !=
+            (S_IRUSR | S_IWUSR | S_IRGRP)) {
+                log_err("%s permissions should be 0640", file);
+                return 1;
+        }
+        if (!S_ISREG(st.st_mode)) {
+                log_err("Error - %s is not a regular file", file);
+                close(fd);
+                return 1;
+        }
+
+        /* it's ok, read line by line */
+        f = fdopen(fd, "r");
+        if (f == NULL) {
+                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. */
+                        log_err("Wrong number of arguments for line %d in %s", lineno, file);
+                        break;
+                case 2:        /* no '=' sign */
+                        log_err("Missing equal sign for line %d in %s",
+                                lineno, file);
+                        break;
+                default:       /* something else went wrong... */
+                        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) {
+                        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) {
+                        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, c);
+                if (rc != 0) {
+                        fclose(f);
+                        return 1;       /* local parser puts message out */
+                }
+
+                lineno++;
+        }
+
+        fclose(f);
+        c->name = strdup(basename(file));
+        if (lineno > 1)
+                return sanity_check(c, 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;
+
+        nv->name = NULL;
+        nv->value = NULL;
+        nv->option = NULL;
+        ptr = strtok(buf, " ");
+        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(NULL, " ");
+        if (ptr == NULL)
+                return 1;
+        if (strcmp(ptr, "=") != 0)
+                return 2;
+
+        /* get the value */
+        ptr = strtok(NULL, " ");
+        if (ptr == NULL)
+                return 1;
+        nv->value = ptr;
+
+        /* See if there's an option */
+        ptr = strtok(NULL, " ");
+        if (ptr) {
+                nv->option = ptr;
+
+                /* Make sure there's nothing else */
+                ptr = strtok(NULL, " ");
+                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 server_parser(struct nv_pair *nv, int line, plugin_conf_t * c)
+{
+
+        if (nv->value == NULL)
+                c->server = NULL;
+        else
+                c->server = strdup(nv->value);
+
+        return 0;
+}
+
+static int port_parser(struct nv_pair *nv, int line, plugin_conf_t * c)
+{
+        const char *ptr = nv->value;
+        unsigned long i;
+
+        /* check that all chars are numbers */
+        for (i = 0; ptr[i]; i++) {
+                if (!isdigit(ptr[i])) {
+                        log_err("Value %s should only be numbers - line %d", nv->value, line);
+                        return 1;
+                }
+        }
+
+        /* convert to unsigned long */
+        errno = 0;
+        i = strtoul(nv->value, NULL, 10);
+        if (errno) {
+                log_err("Error converting string to a number (%s) - line %d", strerror(errno), line);
+                return 1;
+        }
+
+        c->port = i;
+        return 0;
+
+}
+
+static int timeout_parser(struct nv_pair *nv, int line, plugin_conf_t * c)
+{
+        const char *ptr = nv->value;
+        unsigned long i;
+
+        /* check that all chars are numbers */
+        for (i = 0; ptr[i]; i++) {
+                if (!isdigit(ptr[i])) {
+                        log_err("Value %s should only be numbers - line %d", nv->value, line);
+                        return 1;
+                }
+        }
+
+        /* convert to unsigned long */
+        errno = 0;
+        i = strtoul(nv->value, NULL, 10);
+        if (errno) {
+                log_err("Error converting string to a number (%s) - line %d", strerror(errno), line);
+                return 1;
+        }
+
+        c->timeout = i;
+        return 0;
+
+}
+
+
+static int user_parser(struct nv_pair *nv, int line, plugin_conf_t * c)
+{
+
+        if (nv->value == NULL)
+                c->user = NULL;
+        else
+                c->user = strdup(nv->value);
+
+        return 0;
+}
+
+static int password_parser(struct nv_pair *nv, int line, plugin_conf_t * c)
+{
+
+        if (nv->value == NULL)
+                c->password = NULL;
+        else
+                c->password = strdup(nv->value);
+
+        return 0;
+}
+
+static int q_depth_parser(struct nv_pair *nv, int line, plugin_conf_t * c)
+{
+        const char *ptr = nv->value;
+        unsigned long i;
+
+        /* check that all chars are numbers */
+        for (i = 0; ptr[i]; i++) {
+                if (!isdigit(ptr[i])) {
+                        log_err("Value %s should only be numbers - line %d", nv->value, line);
+                        return 1;
+                }
+        }
+
+        /* convert to unsigned long */
+        errno = 0;
+        i = strtoul(nv->value, NULL, 10);
+        if (errno) {
+                log_err("Error converting string to a number (%s) - line %d", strerror(errno), line);
+                return 1;
+        }
+        
+        if (i < 16 || i > 99999) {
+                log_err("q_depth must be between 16 and 99999");
+                return 1;
+        }
+
+        c->q_depth = i;
+        return 0;
+
+}
+
+
+/*
+ * Check configuration.At this point, all fields have been read. 
+ * Returns 0 if no problems and 1 if problems detected.
+ */
+static int sanity_check(plugin_conf_t * c, const char *file)
+{
+        /* Error checking */
+        if (!c->server) {
+                log_err("Error - no server hostname given");
+                return 1;
+        }
+
+        if (!c->user) {
+                log_err("Error - no bind user given");
+                return 1;
+        }
+
+        if (!c->password) {
+                log_err("Error - no password given");
+                return 1;
+        }
+        
+        if (!c->timeout) {
+                log_err("Error - timeout can't be zero");
+                return 1;
+        }
+        return 0;
+}
+
+void plugin_free_config(plugin_conf_t * c)
+{
+
+        if (c == NULL)
+                return;
+
+        free((void *) c->server);
+        free((void *) c->user);
+        free((void *) c->password);
+        free((void *) c->name);
+}
diff -purN audit-1.6.2/audisp/plugins/zos-remote/zos-remote-config.h audit-1.6.2_zos-remote/audisp/plugins/zos-remote/zos-remote-config.h
--- audit-1.6.2/audisp/plugins/zos-remote/zos-remote-config.h	1969-12-31 21:00:00.000000000 -0300
+++ audit-1.6.2_zos-remote/audisp/plugins/zos-remote/zos-remote-config.h	2007-12-04 10:40:56.000000000 -0200
@@ -0,0 +1,48 @@
+/***************************************************************************
+ *   Copyright (C) 2007 International Business Machines  Corp.             *
+ *   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:                                                                *
+ *   Klaus Heinrich Kiwi <klausk at br.ibm.com>                               *
+ *   based on code by Steve Grubb <sgrubb at redhat.com>                      *
+ ***************************************************************************/
+
+#ifndef _ZOS_REMOTE_CONFIG_H
+#define _ZOS_REMOTE_CONFIG_H
+
+
+/***************************************************************************
+ *   z/OS Remote-services Plugin configuration                             *
+ ***************************************************************************/
+typedef struct plugin_conf
+{
+        char *name;
+        char *server;
+        unsigned int port;
+        char *user;
+        char *password;
+        long timeout;
+        unsigned int q_depth;
+        unsigned int counter;
+} plugin_conf_t;
+
+void plugin_clear_config(plugin_conf_t *);
+int plugin_load_config(plugin_conf_t *, char *);
+void plugin_free_config(plugin_conf_t *);
+
+#endif                          /* _ZOS_REMOTE_CONFIG_H */

-- 
Klaus Heinrich Kiwi <klausk at linux.vnet.ibm.com>
IBM STG, Linux Technology Center




More information about the Linux-audit mailing list