All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lisa Smith <lisa.m.smith@hp.com>
To: LSPP <redhat-lspp@redhat.com>,
	Audit Mailing List <linux-audit@redhat.com>
Subject: [PATCH] Updated audit failure query functionality
Date: Mon, 26 Jun 2006 15:23:08 -0400	[thread overview]
Message-ID: <44A0341C.2040105@hp.com> (raw)

This is an updated patch for the audit failure query 
functionality.  The patch has been completely rewritten
to match the programming style and algorithms used in
auditd-config.c.

This patch introduces a new query function,
get_auditfail_action(enum auditfail_t *failmode), which 
can be called to determine what action should be taken by 
a service after audit_open() fails. The function will 
read the tunable "failure_action" from the new 
/etc/libaudit.conf file to determine what action should be
taken.

This patch provides easy expansion of the /etc/libaudit.conf
file to introduce new libaudit tunables if the need arises 
in the future.

The audit_open() man page will be updated to reference this
query function, and a new man page will also be created for
get_auditfail_action().

Lisa

-------------------

 libaudit.c |  246 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 libaudit.h |   11 ++
 2 files changed, 257 insertions(+)

diff -burN orig/libaudit.c src/libaudit.c
--- orig/libaudit.c     2006-05-25 17:39:52.000000000 -0400
+++ src/libaudit.c      2006-06-26 15:00:56.000000000 -0400
@@ -42,13 +42,56 @@
 #include "libaudit.h"
 #include "private.h"

+/* Local prototypes */
+struct nv_pair
+{
+        const char *name;
+        const char *value;
+};
+
+struct kw_pair
+{
+        const char *name;
+        int (*parser)(const char *, int);
+};
+
+struct nv_list
+{
+        const char *name;
+        int option;
+};
+
+struct libaudit_conf
+{
+        auditfail_t failure_action;
+};

 int audit_archadded = 0;
 int audit_syscalladded = 0;
 unsigned int audit_elf = 0U;
+static struct libaudit_conf config;
+static int load_libaudit_config();
+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 audit_failure_parser(const char *val, int line);
 static int name_to_uid(const char *name, uid_t *uid);
 static int name_to_gid(const char *name, gid_t *gid);

+static const struct kw_pair keywords[] =
+{
+  {"failure_action",           audit_failure_parser },
+  { NULL,                      NULL }
+};
+
+static const struct nv_list failure_actions[] =
+{
+  {"ignore",                   FA_IGNORE },
+  {"log",                      FA_LOG },
+  {"terminate",                FA_TERMINATE },
+  { NULL,                      0 }
+};
+

 int audit_request_status(int fd)
 {
@@ -68,6 +111,209 @@
        return rc;
 }

+/*
+ * Set everything to its default value
+*/
+static void clear_config()
+{
+        config.failure_action = FA_IGNORE;
+}
+
+static int load_libaudit_config()
+{
+        int fd, rc, lineno = 1;
+        struct stat st;
+        FILE *f;
+        char buf[128];
+
+        clear_config();
+
+        /* open the file */
+        rc = open(CONFIG_FILE, O_NOFOLLOW|O_RDONLY);
+        if (rc < 0) {
+                if (errno != ENOENT) {
+                        audit_msg(LOG_ERR, "Error opening config file (%s)",
+                                strerror(errno));
+                        return 1;
+                }
+                audit_msg(LOG_WARNING,
+                        "Config file %s doesn't exist, skipping", CONFIG_FILE);
+                return 0;
+        }
+        fd = rc;
+
+        /* check the file's permissions: owned by root, not world writable,
+         * not symlink.
+         */
+        audit_msg(LOG_DEBUG, "Config file %s opened for parsing",
+                        CONFIG_FILE);
+        if (fstat(fd, &st) < 0) {
+                audit_msg(LOG_ERR, "Error fstat'ing config file (%s)",
+                        strerror(errno));
+                return 1;
+        }
+        if (st.st_uid != 0) {
+                audit_msg(LOG_ERR, "Error - %s isn't owned by root",
+                        CONFIG_FILE);
+                return 1;
+        }
+        if ((st.st_mode & S_IWOTH) == S_IWOTH) {
+                audit_msg(LOG_ERR, "Error - %s is world writable",
+                        CONFIG_FILE);
+                return 1;
+        }
+        if (!S_ISREG(st.st_mode)) {
+                audit_msg(LOG_ERR, "Error - %s is not a regular file",
+                        CONFIG_FILE);
+                return 1;
+        }
+
+        /* it's ok, read line by line */
+        f = fdopen(fd, "r");
+        if (f == NULL) {
+                audit_msg(LOG_ERR, "Error - fdopen failed (%s)",
+                        strerror(errno));
+                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.
+                                audit_msg(LOG_ERR,
+                                "Wrong number of arguments for line %d in %s",
+                                        lineno, CONFIG_FILE);
+                                break;
+                        case 2: // no '=' sign
+                                audit_msg(LOG_ERR,
+                                        "Missing equal sign for line %d in %s",
+                                        lineno, CONFIG_FILE);
+                                break;
+                        default: // something else went wrong...
+                                audit_msg(LOG_ERR,
+                                        "Unknown error for line %d in %s",
+                                        lineno, CONFIG_FILE);
+                                break;
+                }
+                if (nv.name == NULL) {
+                        lineno++;
+                        continue;
+                }
+
+                /* identify keyword or error */
+                kw = kw_lookup(nv.name);
+                if (kw->name == NULL) {
+                        audit_msg(LOG_ERR,
+                                "Unknown keyword \"%s\" in line %d of %s",
+                                nv.name, lineno, CONFIG_FILE);
+                        fclose(f);
+                        return 1;
+                }
+
+                /* dispatch to keyword's local parser */
+                rc = kw->parser(nv.value, lineno);
+                if (rc != 0) {
+                        fclose(f);
+                        return 1; // local parser puts message out
+                }
+
+                lineno++;
+        }
+
+        fclose(f);
+        return 0;
+}
+
+int get_auditfail_action(auditfail_t *failmode)
+{
+       if (load_libaudit_config())
+               *failmode = config.failure_action;
+               return 1;
+
+       *failmode = config.failure_action;
+       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;
+        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;
+
+        /* 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 audit_failure_parser(const char *val, int line)
+{
+        int i;
+
+        audit_msg(LOG_DEBUG, "audit_failure_parser called with: %s", val);
+        for (i=0; failure_actions[i].name != NULL; i++) {
+                if (strcasecmp(val, failure_actions[i].name) == 0) {
+                        config.failure_action = failure_actions[i].option;
+                        return 0;
+                }
+        }
+        audit_msg(LOG_ERR, "Option %s not found - line %d", val, line);
+        return 1;
+}
+
 int audit_set_enabled(int fd, uint32_t enabled)
 {
        int rc;
diff -burN orig/libaudit.h src/libaudit.h
--- orig/libaudit.h     2006-05-25 17:38:21.000000000 -0400
+++ src/libaudit.h      2006-06-26 14:58:53.000000000 -0400
@@ -248,6 +248,16 @@
         MACH_ALPHA
 } machine_t;

+/* These are the valid audit failure tunable enum values */
+typedef enum {
+       FA_IGNORE=0,
+       FA_LOG,
+       FA_TERMINATE
+} auditfail_t;
+
+/* #defines for the audit failure query  */
+#define CONFIG_FILE "/etc/libaudit.conf"
+
 /*
  * audit_rule_data supports filter rules with both integer and string
  * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
@@ -362,6 +372,7 @@
 /* AUDIT_GET */
 extern int audit_request_status(int fd);
 extern int audit_is_enabled(int fd);
+extern int get_auditfail_action(auditfail_t *failmode);

 /* AUDIT_SET */
 typedef enum { WAIT_NO, WAIT_YES } rep_wait_t;

             reply	other threads:[~2006-06-26 19:23 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-06-26 19:23 Lisa Smith [this message]
2006-06-26 22:55 ` [PATCH] Updated audit failure query functionality Timothy R. Chavez
2006-06-27 13:32   ` Lisa Smith
2006-06-27 13:55     ` Steve Grubb

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44A0341C.2040105@hp.com \
    --to=lisa.m.smith@hp.com \
    --cc=linux-audit@redhat.com \
    --cc=redhat-lspp@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.