On Tue, 2006-06-13 at 14:52 -0400, Lisa Smith wrote:
This is this initial patch for the audit failure query functionality.
[...]
libaudit.c | 163
+++++++++++++++++++++++++++++++++++++++++++++++++++++
libaudit.h | 25 ++++++++
2 files changed, 188 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-13 14:46:33.000000000 -0400
@@ -68,6 +68,169 @@
return rc;
}
+/*
+ * This function will retrieve the audit failure tunable value
+ * from the filename passed in. If no file is specified, the default
+ * /etc/libaudit.conf file will be used.
+ */
+auditfail_t audit_failure_action(char *file)
+{
+ int ret;
+ struct nv_pair nv;
+
+ if (file == NULL)
+ file = AUDIT_FAIL_CONFIG;
+
+ /* Find the audit failure action tunable in the config file */
+ ret = search_audituser_conf(file, AUDIT_FAIL_KEYWORD, &nv);
+
+ if (ret == -1) {
+ audit_msg(LOG_WARNING, "Error in %s", file);
+ return ERR;
+ } else if (ret == 1) {
+ /* Keyword not found, so do the default action */
+ return IGNORE;
+ }
+
+ /* Translate tunable string to valid enum */
+ if (strncmp(nv.value, AUDIT_FAIL_IGNORE,
+ strlen(AUDIT_FAIL_IGNORE)) == 0) {
This means that "ignores" will be valid, as will "logout".
+ free (nv.name);
+ free (nv.value);
+ return IGNORE;
+ }
[...]
+/*
+ * This function searches for a keyword pair in the passed in filename.
+ * If the keyword pair is found, it is saved in the nv structure and zero
+ * is returned. If the file can not be opened, -1 is returned.
+ * If the keyword is not found in the file, 1 is returned.
+ *
+ * nv->name and nv->value must be freed if an error will be returned from this
+ * function after nv_split() is called. If this function returns success,
+ * the caller must free nv->name and nv->value when finished using the
+ * values.
+ */
+int search_audituser_conf(char *file, char *keyword, struct nv_pair *nv)
+{
+ int rc, lineno = 1;
+ size_t len = 0;
+ ssize_t bytesread;
+ FILE *fp;
+ char *buf = NULL;
+
+ /* Open the file for line by line reading*/
+ fp = fopen(file, "r");
+ if (fp == NULL) {
+ audit_msg(LOG_ERR, "Error - fdopen failed for %s (%s)",
+ file, strerror(errno));
+ return -1;
+ }
+
+ while ((bytesread = getline(&buf, &len, fp)) != -1) {
+
+ if (buf[0] == '#') {
+ lineno++;
+ continue; // Ignore comments
+ }
+
+ /* Convert line into name-value pair */
+ rc = nv_split(buf, nv);
The values in nv are leaked when there isn't a match or an error.
+ if (rc == 1) {
+ audit_msg(LOG_ERR, "Error on line %d in %s", lineno,
+ file);
+ lineno++;
+ continue;
+ }
+
+ /* Find the name-value pair */
+ if (strcmp(nv->name, keyword) == 0)
+ {
+ fclose(fp);
+ if (buf)
+ free (buf);
+ return 0;
+ }
+
+ lineno++;
+ }
+
+ /* If we get here, the keyword was not found in the file */
+ audit_msg(LOG_ERR, "Keyword %s not found in %s", keyword, file);
+ fclose(fp);
+ if (buf)
+ free (buf);
+ if (nv->name)
+ free (nv->name);
+ if (nv->value)
+ free (nv->value);
+ return 1;
+}
+
+/*
+ * This function parses a line looking for a keyword = value pair
+ * and if found, returns it in the nv structure. If the function
+ * returns success, the calling function is expected to free
+ * nv->name and nv->value.
+ */
+int nv_split(char *buffer, struct nv_pair *nv)
+{
+ /* Get the name part */
+ char *saveptr, *ptr = NULL;
+ char *buf = strdup(buffer);
This is always leaked.
+
+ /* Look for = in buf */
+ nv->name = NULL;
+ nv->value = NULL;
+ ptr = strtok_r(buf, " =", &saveptr);
+ if ((ptr == NULL) || !(strcmp(ptr,"\n"))) {
+ return 0; // If there's nothing, go to next line
+ }
+ nv->name = strdup(ptr);
+
+ /* Get the keyword value */
+ ptr = strtok_r(NULL, " =", &saveptr);
I appreciate this is somewhat easier given C's default string API, but
it would be really nice to do the right thing if the user uses "x=y"
instead of needing "x =y".
This also isn't how auditd parses the it's file.
+ if (ptr == NULL) {
+ free (nv->name);
+ return 1;
+ }
+ nv->value = strdup(ptr);
+
+ /* Make sure there's nothing else on the line */
+ ptr = strtok_r(NULL, " ", &saveptr);
+ if (ptr) {
+ free (nv->name);
+ free (nv->value);
+ return 1;
+ }
+
+ /* Everything is OK */
+ return 0;
+}
+
+
+
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-13 13:01:30.000000000 -0400
@@ -248,6 +248,28 @@
MACH_ALPHA
} machine_t;
+/* These are the valid audit failure tunable enum values */
+typedef enum {
+ ERR=-1,
+ IGNORE=0,
+ LOG,
+ TERM
+} auditfail_t;
These enum values should be namespaced esp. as they are very generic
names.
+
+/* #defines for the audit failure query */
+#define AUDIT_FAIL_CONFIG "/etc/libaudit.conf"
+#define AUDIT_FAIL_KEYWORD "auditfailure"
+#define AUDIT_FAIL_IGNORE "ignore"
+#define AUDIT_FAIL_LOG "log"
+#define AUDIT_FAIL_TERM "terminate"
+
+/* Name-value pair */
+struct nv_pair
+{
+ char *name;
+ char *value;
+};
+
This should be namespaced.
/*
* audit_rule_data supports filter rules with both integer and string
* fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
@@ -362,6 +384,9 @@
/* AUDIT_GET */
extern int audit_request_status(int fd);
extern int audit_is_enabled(int fd);
+extern auditfail_t audit_failure_action(char *file);
+static int search_audituser_conf(char *file, char *keyword, struct nv_pair *nv);
+static int nv_split(char *buf, struct nv_pair *nv);
These shouldn't be in the public .h file.
/* AUDIT_SET */
typedef enum { WAIT_NO, WAIT_YES } rep_wait_t;
Could these be namespaced too?
--
James Antill <jantill(a)redhat.com>