Here's the updated version, now supporting all of the interfield
comparisons from
https://www.redhat.com/archives/linux-audit/2011-December/msg00018.html

auditctl -l doesn't report the comparison filters correctly. I'll look
more into this.


Signed-off-by: Peter Moody <[email protected]>
---
 trunk/auparse/typetab.h     |    2 +
 trunk/lib/errormsg.h        |    7 +-
 trunk/lib/fieldtab.h        |    3 +
 trunk/lib/libaudit.c        |  302 +++++++++++++++++++++++++++++++++++++++++++
 trunk/lib/libaudit.h        |    2 +
 trunk/src/auditctl.c        |   19 +++-
 trunk/src/ausearch-report.c |    1 +
 7 files changed, 333 insertions(+), 3 deletions(-)

diff --git a/trunk/auparse/typetab.h b/trunk/auparse/typetab.h
index 746573c..cf13f4d 100644
--- a/trunk/auparse/typetab.h
+++ b/trunk/auparse/typetab.h
@@ -32,6 +32,8 @@ _S(AUPARSE_TYPE_UID,          "iuid"          )
 _S(AUPARSE_TYPE_UID,           "id"            )
 _S(AUPARSE_TYPE_UID,           "inode_uid"     )
 _S(AUPARSE_TYPE_UID,           "sauid"         )
+_S(AUPARSE_TYPE_UID,           "obj_uid"       )
+_S(AUPARSE_TYPE_UID,           "obj_gid"       )
 _S(AUPARSE_TYPE_GID,           "gid"           )
 _S(AUPARSE_TYPE_GID,           "egid"          )
 _S(AUPARSE_TYPE_GID,           "sgid"          )
diff --git a/trunk/lib/errormsg.h b/trunk/lib/errormsg.h
index fd6b1c0..a7bc61d 100644
--- a/trunk/lib/errormsg.h
+++ b/trunk/lib/errormsg.h
@@ -54,5 +54,10 @@ static const struct msg_tab err_msgtab[] = {
     { -19,    0,    "Key field needs a watch or syscall given prior to it" },
     { -20,    2,    "-F missing value after operation for" },
     { -21,    2,    "-F value should be number for" },
-    { -22,    2,    "-F missing field name before operator for" }
+    { -22,    2,    "-F missing field name before operator for" },
+    { -23,    2,    "-C missng operation for "},
+    { -24,    2,    "-C missing field name before operator for" },
+    { -25,    2,    "-C missing value after operation for "},
+    { -26,    2,    "-C unknown field:" },
+    { -27,    2,    "-C unknown right hand value for comparison with:" },
 };
diff --git a/trunk/lib/fieldtab.h b/trunk/lib/fieldtab.h
index ad95814..c0432cc 100644
--- a/trunk/lib/fieldtab.h
+++ b/trunk/lib/fieldtab.h
@@ -55,6 +55,8 @@ _S(AUDIT_WATCH,        "path"         )
 _S(AUDIT_PERM,         "perm"         )
 _S(AUDIT_DIR,          "dir"          )
 _S(AUDIT_FILETYPE,     "filetype"     )
+_S(AUDIT_OBJ_UID,      "obj_uid"      )
+_S(AUDIT_OBJ_GID,      "obj_gid"      )

 _S(AUDIT_ARG0,         "a0"           )
 _S(AUDIT_ARG1,         "a1"           )
@@ -63,3 +65,4 @@ _S(AUDIT_ARG3,         "a3"           )

 _S(AUDIT_FILTERKEY,    "key"          )

+_S(AUDIT_FIELD_COMPARE, "field_compare" )
diff --git a/trunk/lib/libaudit.c b/trunk/lib/libaudit.c
index 9a5070c..0fce075 100644
--- a/trunk/lib/libaudit.c
+++ b/trunk/lib/libaudit.c
@@ -783,6 +783,306 @@ int audit_rule_syscallbyname_data(struct
audit_rule_data *rule,
 }
 hidden_def(audit_rule_syscallbyname_data)

+int audit_rule_interfield_fieldpair_data(struct audit_rule_data **rulep,
+                                        const char *pair,
+                                        int flags) {
+       const char *f = pair;
+       char       *v;
+       int        op;
+       int        field1, field2;
+       int        vlen;
+       int        offset;
+       struct audit_rule_data *rule = *rulep;
+
+       if (f == NULL)
+               return -1;
+
+       /* look for 2-char operators first
+          then look for 1-char operators afterwards
+          when found, null out the bytes under the operators to split
+          and set value pointer just past operator bytes
+       */
+       if ( (v = strstr(pair, "!=")) ) {
+               *v++ = '\0';
+               *v++ = '\0';
+               op = AUDIT_NOT_EQUAL;
+       } else if ( (v = strstr(pair, "=")) ) {
+               *v++ = '\0';
+               op = AUDIT_EQUAL;
+       } else {
+               return -13;
+       }
+
+       if (v == NULL)
+               return -23;
+       
+       if (*f == 0)
+               return -24;
+
+       if (*v == 0)
+               return -25;
+
+       if ((field1 = audit_name_to_field(f)) < 0)
+               return -26;
+
+       if ((field2 = audit_name_to_field(v)) < 0)
+               return -27;
+
+       /* Exclude filter can be used only with MSGTYPE field */
+       if (flags == AUDIT_FILTER_EXCLUDE && field1 != AUDIT_MSGTYPE)
+               return -12;
+
+       // It should always be AUDIT_FIELD_COMPARE
+       rule->fields[rule->field_count] = AUDIT_FIELD_COMPARE;
+       rule->fieldflags[rule->field_count] = op;
+       /* oh god, so many permutations */
+       switch (field1)
+       {
+               /* UID comparison */
+               case AUDIT_EUID:
+                       switch(field2) {
+                       case AUDIT_LOGINUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_EUID;
+                               break;
+                       case AUDIT_FSUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_FSUID;
+                               break;
+                       case AUDIT_OBJ_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_SUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_SUID;
+                               break;
+                       case AUDIT_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_EUID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_FSUID:
+                       switch(field2) {
+                       case AUDIT_LOGINUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_EUID;
+                               break;
+                       case AUDIT_EUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_SUID;
+                               break;
+                       case AUDIT_OBJ_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_SUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_SUID;
+                               break;
+                       case AUDIT_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_EUID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_LOGINUID:
+                       switch(field2) {
+                       case AUDIT_EUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_EUID;
+                               break;
+                       case AUDIT_FSUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_FSUID;
+                               break;
+                       case AUDIT_OBJ_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_SUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_SUID;
+                               break;
+                       case AUDIT_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_AUID;
+                               break;
+                       default:
+                               return -1;
+                       }
+               case AUDIT_SUID:
+                       switch(field2) {
+                       case AUDIT_LOGINUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_EUID;
+                               break;
+                       case AUDIT_EUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_SUID;
+                               break;
+                       case AUDIT_FSUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_FSUID;
+                               break;
+                       case AUDIT_OBJ_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_EUID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_OBJ_UID:
+                       switch(field2) {
+                       case AUDIT_LOGINUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_AUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_EUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_FSUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_FSUID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_SUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_SUID_TO_OBJ_UID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_UID:
+                       switch(field2) {
+                       case AUDIT_LOGINUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_AUID;
+                               break;
+                       case AUDIT_EUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_EUID;
+                               break;
+                       case AUDIT_FSUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_FSUID;
+                               break;
+                       case AUDIT_OBJ_UID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_OBJ_UID;
+                               break;
+                       case AUDIT_SUID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_UID_TO_SUID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+
+               /* GID comparisons */
+               case AUDIT_EGID:
+                       switch(field2) {
+                       case AUDIT_FSGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EGID_TO_FSGID;
+                               break;
+                       case AUDIT_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_EGID;
+                               break;
+                       case AUDIT_OBJ_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EGID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_SGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EGID_TO_SGID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_FSGID:
+                       switch(field2) {
+                       case AUDIT_SGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_SGID_TO_FSGID;
+                               break;
+                       case AUDIT_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_FSGID;
+                               break;
+                       case AUDIT_OBJ_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_FSGID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_EGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EGID_TO_FSGID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_GID:
+                       switch(field2) {
+                       case AUDIT_EGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_EGID;
+                               break;
+                       case AUDIT_FSGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_FSGID;
+                               break;
+                       case AUDIT_OBJ_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_SGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_SGID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_OBJ_GID:
+                       switch(field2) {
+                       case AUDIT_EGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EGID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_FSGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_FSGID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_SGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_SGID_TO_OBJ_GID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+               case AUDIT_SGID:
+                       switch(field2) {
+                       case AUDIT_FSGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_SGID_TO_FSGID;
+                               break;
+                       case AUDIT_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_GID_TO_EGID;
+                               break;
+                       case AUDIT_OBJ_GID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_SGID_TO_OBJ_GID;
+                               break;
+                       case AUDIT_EGID:
+                               rule->values[rule->field_count] = 
AUDIT_COMPARE_EGID_TO_SGID;
+                               break;
+                       default:
+                               return -1;
+                       }
+                       break;
+                       /* fallthrough */
+               default:
+                       if (field1 == AUDIT_INODE) {
+                               if (!(op == AUDIT_NOT_EQUAL ||
+                                                       op == AUDIT_EQUAL))
+                                       return -13;
+                       }
+
+                       if (field1 == AUDIT_PPID && !(flags == AUDIT_FILTER_EXIT
+                               || flags == AUDIT_FILTER_ENTRY))
+                               return -17;
+                       
+                       if (!isdigit((char)*(v)))
+                               return -21;
+
+                       if (field1 == AUDIT_INODE)
+                               rule->values[rule->field_count] =
+                                       strtoul(v, NULL, 0);
+                       else
+                               rule->values[rule->field_count] =
+                                       strtol(v, NULL, 0);
+                       break;
+       }
+       rule->field_count++;
+       return 0;       
+}
+
 int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
                               int flags)
 {
@@ -857,6 +1157,8 @@ int audit_rule_fieldpair_data(struct
audit_rule_data **rulep, const char *pair,
                case AUDIT_SUID:
                case AUDIT_FSUID:
                case AUDIT_LOGINUID:
+               case AUDIT_OBJ_UID:
+               case AUDIT_OBJ_GID:
                        // Do positive & negative separate for 32 bit systems
                        vlen = strlen(v);
                        if (isdigit((char)*(v)))
diff --git a/trunk/lib/libaudit.h b/trunk/lib/libaudit.h
index 8feaa39..911bce4 100644
--- a/trunk/lib/libaudit.h
+++ b/trunk/lib/libaudit.h
@@ -428,6 +428,8 @@ extern int  audit_rule_syscallbyname_data(struct
audit_rule_data *rule,
  * adding new fields */
 extern int  audit_rule_fieldpair_data(struct audit_rule_data **rulep,
                                       const char *pair, int flags);
+extern int audit_rule_interfield_fieldpair_data(struct audit_rule_data **rulep,
+                                        const char *pair, int flags);
 extern void audit_rule_free_data(struct audit_rule_data *rule);

 #ifdef __cplusplus
diff --git a/trunk/src/auditctl.c b/trunk/src/auditctl.c
index 34b7935..d7ec998 100644
--- a/trunk/src/auditctl.c
+++ b/trunk/src/auditctl.c
@@ -482,7 +482,7 @@ static int setopt(int count, int lineno, char *vars[])
     keylen = AUDIT_MAX_KEY_LEN;

     while ((retval >= 0) && (c = getopt(count, vars,
-                       "hislDvte:f:r:b:a:A:d:S:F:m:R:w:W:k:p:q:")) != EOF) {
+                       "hislDvtC:e:f:r:b:a:A:d:S:F:m:R:w:W:k:p:q:")) != EOF) {
        int flags = AUDIT_FILTER_UNSET;
        rc = 10;        // Init to something impossible to see if unused.
         switch (c) {
@@ -731,7 +731,6 @@ static int setopt(int count, int lineno, char *vars[])
                        retval = -1;
                        break;
                }
-
                rc = audit_rule_fieldpair_data(&rule_new,optarg,flags);
                if (rc != 0) {
                        audit_number_to_errmsg(rc, optarg);
@@ -743,6 +742,22 @@ static int setopt(int count, int lineno, char *vars[])
                }

                break;
+       case 'C':
+               if (add != AUDIT_FILTER_UNSET)
+                       flags = add & AUDIT_FILTER_MASK;
+               else if (del != AUDIT_FILTER_UNSET)
+                       flags = del & AUDIT_FILTER_MASK;
+
+               rc = audit_rule_interfield_fieldpair_data(&rule_new, optarg, 
flags);
+               if (rc != 0) {
+                       audit_number_to_errmsg(rc, optarg);
+                       retval = -1;
+               } else {
+                       if (rule_new->fields[rule_new->field_count - 1] ==
+                           AUDIT_PERM)
+                               audit_permadded = 1;
+               }
+               break;
         case 'm':
                if (count > 3) {
                        fprintf(stderr,
diff --git a/trunk/src/ausearch-report.c b/trunk/src/ausearch-report.c
index d50c732..62e1ae0 100644
--- a/trunk/src/ausearch-report.c
+++ b/trunk/src/ausearch-report.c
@@ -333,6 +333,7 @@ static struct nv_pair typetab[] = {
        {T_UID, "id"},
        {T_UID, "inode_uid"},
        {T_UID, "sauid"},
+       {T_UID, "obj_uid"},
        {T_GID, "gid"},
        {T_GID, "egid"},
        {T_GID, "sgid"},
-- 
1.7.3.1

-- 
Peter Moody      Google    1.650.253.7306
Security Engineer  pgp:0xC3410038

--
Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to