s4 group_audit: Add Windows Event Id's to Group membership changes
authorGary Lockyer <gary@catalyst.net.nz>
Tue, 18 Dec 2018 20:08:22 +0000 (09:08 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 21 Dec 2018 21:16:09 +0000 (22:16 +0100)
Generate a GroupChange event when a user is created with a PrimaryGroup
membership.  Log the windows event id in the JSON GroupChange message.

Event Id's supported are:
4728 A member was added to a security enabled global group
4729 A member was removed from a security enabled global
group
4732 A member was added to a security enabled local group
4733 A member was removed from a security enabled local group
4746 A member was added to a security disabled local group
4747 A member was removed from a security disabled local group
4751 A member was added to a security disabled global group
4752 A member was removed from a security disabled global
group
4756 A member was added to a security enabled universal
group
4757 A member was removed from a security enabled universal
group
4761 A member was added to a security disabled universal
group
4762 A member was removed from a security disabled universal
group

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
WHATSNEW.txt
librpc/idl/windows_event_ids.idl
python/samba/tests/group_audit.py
source4/dsdb/samdb/ldb_modules/group_audit.c
source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c
source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c

index 6698b09d8bcca0f0e34518e60e836eb72286567a..5f2377130154d58d45da73f04cf62842973c1c96 100644 (file)
@@ -118,17 +118,39 @@ type "logonType". The supported event codes and logon types are:
     2  Interactive
     3  Network
     8  NetworkCleartext
     2  Interactive
     3  Network
     8  NetworkCleartext
+
 The version number for Authentication messages is now 1.1, changed from 1.0
 
 Password change messages now contain the Windows Event Id "eventId", the
 supported event Id's are:
   4723 Password changed
   4724 Password reset
 The version number for Authentication messages is now 1.1, changed from 1.0
 
 Password change messages now contain the Windows Event Id "eventId", the
 supported event Id's are:
   4723 Password changed
   4724 Password reset
+
 The version number for PasswordChange messages is now 1.1, changed from 1.0
 
 The version number for PasswordChange messages is now 1.1, changed from 1.0
 
+Group membership change messages now contain the Windows Event Id "eventId",
+the supported event Id's are:
+  4728 A member was added to a security enabled global group
+  4729 A member was removed from a security enabled global group
+  4732 A member was added to a security enabled local group
+  4733 A member was removed from a security enabled local group
+  4746 A member was added to a security disabled local group
+  4747 A member was removed from a security disabled local group
+  4751 A member was added to a security disabled global group
+  4752 A member was removed from a security disabled global group
+  4756 A member was added to a security enabled universal group
+  4757 A member was removed from a security enabled universal group
+  4761 A member was added to a security disabled universal group
+  4762 A member was removed from a security disabled universal group
+
+
+The version number for GroupChange messages is now 1.1, changed from 1.0. Also
+A GroupChange message is generated when a new user is created to log that the
+user has been added to their primary group.
+
 The leading "JSON <message type>:" and source file  prefix of the JSON formatted
 log entries has been removed to make the parsing of the JSON log messages
 The leading "JSON <message type>:" and source file  prefix of the JSON formatted
 log entries has been removed to make the parsing of the JSON log messages
-easier. JSON log entries now start with 2 spaces folowed by an opening brace
+easier. JSON log entries now start with 2 spaces followed by an opening brace
 i.e. "  {"
 
 
 i.e. "  {"
 
 
index c711db1b30fc4221d5367ef0157006c20aca5d9e..240ad9e56ff7a86ff8d684029211a87cf1a251b6 100644 (file)
@@ -9,10 +9,23 @@ interface windows_events
 {
 
        typedef [v1_enum,public] enum {
 {
 
        typedef [v1_enum,public] enum {
-               EVT_ID_SUCCESSFUL_LOGON         = 4624,
-               EVT_ID_UNSUCCESSFUL_LOGON       = 4625,
-               EVT_ID_PASSWORD_CHANGE          = 4723,
-               EVT_ID_PASSWORD_RESET           = 4724
+               EVT_ID_NONE                                             =    0,
+               EVT_ID_SUCCESSFUL_LOGON                                 = 4624,
+               EVT_ID_UNSUCCESSFUL_LOGON                               = 4625,
+               EVT_ID_PASSWORD_CHANGE                                  = 4723,
+               EVT_ID_PASSWORD_RESET                                   = 4724,
+               EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP                   = 4728,
+               EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP               = 4729,
+               EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP                    = 4732,
+               EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP                = 4733,
+               EVT_ID_USER_ADDED_TO_LOCAL_GROUP                        = 4746,
+               EVT_ID_USER_REMOVED_FROM_LOCAL_GROUP                    = 4747,
+               EVT_ID_USER_ADDED_TO_GLOBAL_GROUP                       = 4751,
+               EVT_ID_USER_REMOVED_FROM_GLOBAL_GROUP                   = 4752,
+               EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP                = 4756,
+               EVT_ID_USER_REMOVED_FROM_UNIVERSAL_SEC_GROUP            = 4757,
+               EVT_ID_USER_ADDED_TO_UNIVERSAL_GROUP                    = 4761,
+               EVT_ID_USER_REMOVED_FROM_UNIVERSAL_GROUP                = 4762
        } event_id_type;
 
        typedef [v1_enum,public] enum {
        } event_id_type;
 
        typedef [v1_enum,public] enum {
index 53a8bf6afaf686bad402c29e3f5dfc53b13d85c0..9fe69bd1fc015b4a20f83336f10c4a302790f2a6 100644 (file)
@@ -21,6 +21,10 @@ from __future__ import print_function
 
 import samba.tests
 from samba.dcerpc.messaging import MSG_GROUP_LOG, DSDB_GROUP_EVENT_NAME
 
 import samba.tests
 from samba.dcerpc.messaging import MSG_GROUP_LOG, DSDB_GROUP_EVENT_NAME
+from samba.dcerpc.windows_event_ids import (
+    EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+    EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP
+)
 from samba.samdb import SamDB
 from samba.auth import system_session
 import os
 from samba.samdb import SamDB
 from samba.auth import system_session
 import os
@@ -100,9 +104,9 @@ class GroupAuditTests(AuditLogTestBase):
         #
         # Wait for the primary group change for the created user.
         #
         #
         # Wait for the primary group change for the created user.
         #
-        messages = self.waitForMessages(1)
+        messages = self.waitForMessages(2)
         print("Received %d messages" % len(messages))
         print("Received %d messages" % len(messages))
-        self.assertEquals(1,
+        self.assertEquals(2,
                           len(messages),
                           "Did not receive the expected number of messages")
         audit = messages[0]["groupChange"]
                           len(messages),
                           "Did not receive the expected number of messages")
         audit = messages[0]["groupChange"]
@@ -120,6 +124,21 @@ class GroupAuditTests(AuditLogTestBase):
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
 
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
 
+        # Check the Add message for the new users primary group
+        audit = messages[1]["groupChange"]
+
+        self.assertEqual("Added", audit["action"])
+        user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn
+        group_dn = "cn=domain users,cn=users," + self.base_dn
+        self.assertTrue(user_dn.lower(), audit["user"].lower())
+        self.assertTrue(group_dn.lower(), audit["group"].lower())
+        self.assertRegexpMatches(audit["remoteAddress"],
+                                 self.remoteAddress)
+        self.assertTrue(self.is_guid(audit["sessionId"]))
+        session_id = self.get_session()
+        self.assertEquals(session_id, audit["sessionId"])
+        self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+                          audit["eventId"])
         #
         # Add the user to a group
         #
         #
         # Add the user to a group
         #
@@ -231,11 +250,13 @@ class GroupAuditTests(AuditLogTestBase):
         #
         # Wait for the primary group change for the created user.
         #
         #
         # Wait for the primary group change for the created user.
         #
-        messages = self.waitForMessages(1)
+        messages = self.waitForMessages(2)
         print("Received %d messages" % len(messages))
         print("Received %d messages" % len(messages))
-        self.assertEquals(1,
+        self.assertEquals(2,
                           len(messages),
                           "Did not receive the expected number of messages")
                           len(messages),
                           "Did not receive the expected number of messages")
+
+        # Check the PrimaryGroup message
         audit = messages[0]["groupChange"]
 
         self.assertEqual("PrimaryGroup", audit["action"])
         audit = messages[0]["groupChange"]
 
         self.assertEqual("PrimaryGroup", audit["action"])
@@ -251,6 +272,22 @@ class GroupAuditTests(AuditLogTestBase):
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
 
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
 
+        # Check the Add message for the new users primary group
+        audit = messages[1]["groupChange"]
+
+        self.assertEqual("Added", audit["action"])
+        user_dn = "cn=" + USER_NAME + ",cn=users," + self.base_dn
+        group_dn = "cn=domain users,cn=users," + self.base_dn
+        self.assertTrue(user_dn.lower(), audit["user"].lower())
+        self.assertTrue(group_dn.lower(), audit["group"].lower())
+        self.assertRegexpMatches(audit["remoteAddress"],
+                                 self.remoteAddress)
+        self.assertTrue(self.is_guid(audit["sessionId"]))
+        session_id = self.get_session()
+        self.assertEquals(session_id, audit["sessionId"])
+        self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+                          audit["eventId"])
+
         #
         # Add the user to a group, the user needs to be a member of a group
         # before there primary group can be set to that group.
         #
         # Add the user to a group, the user needs to be a member of a group
         # before there primary group can be set to that group.
@@ -277,6 +314,8 @@ class GroupAuditTests(AuditLogTestBase):
         self.assertEquals(session_id, audit["sessionId"])
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
         self.assertEquals(session_id, audit["sessionId"])
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
+        self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+                          audit["eventId"])
 
         #
         # Change the primary group of a user
 
         #
         # Change the primary group of a user
@@ -323,6 +362,8 @@ class GroupAuditTests(AuditLogTestBase):
         self.assertEquals(session_id, audit["sessionId"])
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
         self.assertEquals(session_id, audit["sessionId"])
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
+        self.assertEquals(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP,
+                          audit["eventId"])
 
         audit = messages[1]["groupChange"]
 
 
         audit = messages[1]["groupChange"]
 
@@ -338,6 +379,8 @@ class GroupAuditTests(AuditLogTestBase):
         self.assertEquals(session_id, audit["sessionId"])
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
         self.assertEquals(session_id, audit["sessionId"])
         service_description = self.get_service_description()
         self.assertEquals(service_description, "LDAP")
+        self.assertEquals(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+                          audit["eventId"])
 
         audit = messages[2]["groupChange"]
 
 
         audit = messages[2]["groupChange"]
 
index 7e6e16de137b22295fad45616baa3e0aca92fb12..9aba865ccd6ba1ebfe49c9415d563d5ef66de30d 100644 (file)
@@ -25,6 +25,7 @@
 #include "includes.h"
 #include "ldb_module.h"
 #include "lib/audit_logging/audit_logging.h"
 #include "includes.h"
 #include "ldb_module.h"
 #include "lib/audit_logging/audit_logging.h"
+#include "librpc/gen_ndr/windows_event_ids.h"
 
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/samdb/ldb_modules/util.h"
 
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/samdb/ldb_modules/util.h"
 #define AUDIT_JSON_TYPE "groupChange"
 #define AUDIT_HR_TAG "Group Change"
 #define AUDIT_MAJOR 1
 #define AUDIT_JSON_TYPE "groupChange"
 #define AUDIT_HR_TAG "Group Change"
 #define AUDIT_MAJOR 1
-#define AUDIT_MINOR 0
+#define AUDIT_MINOR 1
 #define GROUP_LOG_LVL 5
 
 #define GROUP_LOG_LVL 5
 
-static const char * const member_attr[] = {"member", NULL};
+static const char *const group_attrs[] = {"member", "groupType", NULL};
+static const char *const group_type_attr[] = {"groupType", NULL};
 static const char * const primary_group_attr[] = {
        "primaryGroupID",
        "objectSID",
 static const char * const primary_group_attr[] = {
        "primaryGroupID",
        "objectSID",
@@ -105,13 +107,13 @@ static struct GUID *get_transaction_id(
  * @return A json object containing the details.
  *        NULL if an error was detected
  */
  * @return A json object containing the details.
  *        NULL if an error was detected
  */
-static struct json_object audit_group_json(
-       const struct ldb_module *module,
-       const struct ldb_request *request,
-       const char *action,
-       const char *user,
-       const char *group,
-       const int status)
+static struct json_object audit_group_json(const struct ldb_module *module,
+                                          const struct ldb_request *request,
+                                          const char *action,
+                                          const char *user,
+                                          const char *group,
+                                          const enum event_id_type event_id,
+                                          const int status)
 {
        struct ldb_context *ldb = NULL;
        const struct dom_sid *sid = NULL;
 {
        struct ldb_context *ldb = NULL;
        const struct dom_sid *sid = NULL;
@@ -137,6 +139,12 @@ static struct json_object audit_group_json(
        if (rc != 0) {
                goto failure;
        }
        if (rc != 0) {
                goto failure;
        }
+       if (event_id != EVT_ID_NONE) {
+               rc = json_add_int(&audit, "eventId", event_id);
+               if (rc != 0) {
+                       goto failure;
+               }
+       }
        rc = json_add_int(&audit, "statusCode", status);
        if (rc != 0) {
                goto failure;
        rc = json_add_int(&audit, "statusCode", status);
        if (rc != 0) {
                goto failure;
@@ -449,9 +457,11 @@ static const char *get_primary_group_dn(
  * @brief Log details of a change to a users primary group.
  *
  * Log details of a change to a users primary group.
  * @brief Log details of a change to a users primary group.
  *
  * Log details of a change to a users primary group.
+ * There is no windows event id associated with a Primary Group change.
+ * However for a new user we generate an added to group event.
  *
  * @param module The ldb module.
  *
  * @param module The ldb module.
- * @param request The request deing logged.
+ * @param request The request being logged.
  * @param action Description of the action being performed.
  * @param group The linearized for of the group DN
  * @param status the LDB status code for the processing of the request.
  * @param action Description of the action being performed.
  * @param group The linearized for of the group DN
  * @param status the LDB status code for the processing of the request.
@@ -497,12 +507,7 @@ static void log_primary_group_change(
 
                struct json_object json;
                json = audit_group_json(
 
                struct json_object json;
                json = audit_group_json(
-                       module,
-                       request,
-                       action,
-                       user,
-                       group,
-                       status);
+                   module, request, action, user, group, EVT_ID_NONE, status);
                audit_log_json(
                        &json,
                        DBGC_DSDB_GROUP_AUDIT_JSON,
                audit_log_json(
                        &json,
                        DBGC_DSDB_GROUP_AUDIT_JSON,
@@ -515,6 +520,13 @@ static void log_primary_group_change(
                                &json);
                }
                json_free(&json);
                                &json);
                }
                json_free(&json);
+               if (request->operation == LDB_ADD) {
+                       /*
+                        * Have just added a user, generate a groupChange
+                        * message indicating the user has been added to thier
+                        * new PrimaryGroup.
+                        */
+               }
        }
        TALLOC_FREE(ctx);
 }
        }
        TALLOC_FREE(ctx);
 }
@@ -532,12 +544,12 @@ static void log_primary_group_change(
  * @param status the LDB status code for the processing of the request.
  *
  */
  * @param status the LDB status code for the processing of the request.
  *
  */
-static void log_membership_change(
-       struct ldb_module *module,
-       const struct ldb_request *request,
-       const char *action,
-       const char *user,
-       const int  status)
+static void log_membership_change(struct ldb_module *module,
+                                 const struct ldb_request *request,
+                                 const char *action,
+                                 const char *user,
+                                 const enum event_id_type event_id,
+                                 const int status)
 {
        const char *group = NULL;
        struct audit_context *ac =
 {
        const char *group = NULL;
        struct audit_context *ac =
@@ -569,12 +581,7 @@ static void log_membership_change(
                (ac->msg_ctx && ac->send_events)) {
                struct json_object json;
                json = audit_group_json(
                (ac->msg_ctx && ac->send_events)) {
                struct json_object json;
                json = audit_group_json(
-                       module,
-                       request,
-                       action,
-                       user,
-                       group,
-                       status);
+                   module, request, action, user, group, event_id, status);
                audit_log_json(
                        &json,
                        DBGC_DSDB_GROUP_AUDIT_JSON,
                audit_log_json(
                        &json,
                        DBGC_DSDB_GROUP_AUDIT_JSON,
@@ -591,6 +598,68 @@ static void log_membership_change(
        TALLOC_FREE(ctx);
 }
 
        TALLOC_FREE(ctx);
 }
 
+/*
+ * @brief Get the windows event type id for removing a user from a group type.
+ *
+ * @param group_type the type of the current group, see libds/common/flags.h
+ *
+ * @return the Windows Event Id
+ *
+ */
+static enum event_id_type get_remove_member_event(uint32_t group_type)
+{
+
+       switch (group_type) {
+       case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP;
+       case GTYPE_SECURITY_GLOBAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP;
+       case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP;
+       case GTYPE_SECURITY_UNIVERSAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_UNIVERSAL_SEC_GROUP;
+       case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_GLOBAL_GROUP;
+       case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_LOCAL_GROUP;
+       case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
+               return EVT_ID_USER_REMOVED_FROM_UNIVERSAL_GROUP;
+       default:
+               return EVT_ID_NONE;
+       }
+}
+
+/*
+ * @brief Get the windows event type id for adding a user to a group type.
+ *
+ * @param group_type the type of the current group, see libds/common/flags.h
+ *
+ * @return the Windows Event Id
+ *
+ */
+static enum event_id_type get_add_member_event(uint32_t group_type)
+{
+
+       switch (group_type) {
+       case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP;
+       case GTYPE_SECURITY_GLOBAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP;
+       case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP;
+       case GTYPE_SECURITY_UNIVERSAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP;
+       case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_GLOBAL_GROUP;
+       case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_LOCAL_GROUP;
+       case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
+               return EVT_ID_USER_ADDED_TO_UNIVERSAL_GROUP;
+       default:
+               return EVT_ID_NONE;
+       }
+}
+
 /*
  * @brief Log all the changes to a users group membership.
  *
 /*
  * @brief Log all the changes to a users group membership.
  *
@@ -604,12 +673,12 @@ static void log_membership_change(
  * @param status the LDB status code for the processing of the request.
  *
  */
  * @param status the LDB status code for the processing of the request.
  *
  */
-static void log_membership_changes(
-       struct ldb_module *module,
-       const struct ldb_request *request,
-       struct ldb_message_element *el,
-       struct ldb_message_element *old_el,
-       int status)
+static void log_membership_changes(struct ldb_module *module,
+                                  const struct ldb_request *request,
+                                  struct ldb_message_element *el,
+                                  struct ldb_message_element *old_el,
+                                  uint32_t group_type,
+                                  int status)
 {
        unsigned int i, old_i, new_i;
        unsigned int old_num_values;
 {
        unsigned int i, old_i, new_i;
        unsigned int old_num_values;
@@ -674,6 +743,7 @@ static void log_membership_changes(
                         * the new record. So it's been deleted
                         */
                        const char *user = NULL;
                         * the new record. So it's been deleted
                         */
                        const char *user = NULL;
+                       enum event_id_type event_id;
                        if (old_val->dsdb_dn == NULL) {
                                really_parse_trusted_dn(
                                        ctx,
                        if (old_val->dsdb_dn == NULL) {
                                really_parse_trusted_dn(
                                        ctx,
@@ -682,12 +752,9 @@ static void log_membership_changes(
                                        LDB_SYNTAX_DN);
                        }
                        user = ldb_dn_get_linearized(old_val->dsdb_dn->dn);
                                        LDB_SYNTAX_DN);
                        }
                        user = ldb_dn_get_linearized(old_val->dsdb_dn->dn);
+                       event_id = get_remove_member_event(group_type);
                        log_membership_change(
                        log_membership_change(
-                               module,
-                               request,
-                               "Removed",
-                               user,
-                               status);
+                           module, request, "Removed", user, event_id, status);
                        old_i++;
                } else if (cmp == BINARY_EQUAL) {
                        /*
                        old_i++;
                } else if (cmp == BINARY_EQUAL) {
                        /*
@@ -739,27 +806,31 @@ static void log_membership_changes(
                                 * DN has been deleted.
                                 */
                                const char *user = NULL;
                                 * DN has been deleted.
                                 */
                                const char *user = NULL;
+                               enum event_id_type event_id;
                                user = ldb_dn_get_linearized(
                                        old_val->dsdb_dn->dn);
                                user = ldb_dn_get_linearized(
                                        old_val->dsdb_dn->dn);
-                               log_membership_change(
-                                       module,
-                                       request,
-                                       "Removed",
-                                       user,
-                                       status);
+                               event_id = get_remove_member_event(group_type);
+                               log_membership_change(module,
+                                                     request,
+                                                     "Removed",
+                                                     user,
+                                                     event_id,
+                                                     status);
                        } else {
                                /*
                                 * DN has been re-added
                                 */
                                const char *user = NULL;
                        } else {
                                /*
                                 * DN has been re-added
                                 */
                                const char *user = NULL;
+                               enum event_id_type event_id;
                                user = ldb_dn_get_linearized(
                                        new_val->dsdb_dn->dn);
                                user = ldb_dn_get_linearized(
                                        new_val->dsdb_dn->dn);
-                               log_membership_change(
-                                       module,
-                                       request,
-                                       "Added",
-                                       user,
-                                       status);
+                               event_id = get_add_member_event(group_type);
+                               log_membership_change(module,
+                                                     request,
+                                                     "Added",
+                                                     user,
+                                                     event_id,
+                                                     status);
                        }
                        old_i++;
                        new_i++;
                        }
                        old_i++;
                        new_i++;
@@ -769,6 +840,7 @@ static void log_membership_changes(
                         * original, so it must have been added.
                         */
                        const char *user = NULL;
                         * original, so it must have been added.
                         */
                        const char *user = NULL;
+                       enum event_id_type event_id;
                        if ( new_val->dsdb_dn == NULL) {
                                really_parse_trusted_dn(
                                        ctx,
                        if ( new_val->dsdb_dn == NULL) {
                                really_parse_trusted_dn(
                                        ctx,
@@ -777,12 +849,9 @@ static void log_membership_changes(
                                        LDB_SYNTAX_DN);
                        }
                        user = ldb_dn_get_linearized(new_val->dsdb_dn->dn);
                                        LDB_SYNTAX_DN);
                        }
                        user = ldb_dn_get_linearized(new_val->dsdb_dn->dn);
+                       event_id = get_add_member_event(group_type);
                        log_membership_change(
                        log_membership_change(
-                               module,
-                               request,
-                               "Added",
-                               user,
-                               status);
+                           module, request, "Added", user, event_id, status);
                        new_i++;
                }
        }
                        new_i++;
                }
        }
@@ -790,6 +859,46 @@ static void log_membership_changes(
        TALLOC_FREE(ctx);
 }
 
        TALLOC_FREE(ctx);
 }
 
+/*
+ * @brief log a group change message for a newly added user.
+ *
+ * When a user is added we need to generate a GroupChange Add message to
+ * log that the user has been added to their PrimaryGroup
+ */
+static void log_new_user_added_to_primary_group(
+    TALLOC_CTX *ctx,
+    struct audit_callback_context *acc,
+    const char *group,
+    const int status)
+{
+       uint32_t group_type;
+       enum event_id_type event_id = EVT_ID_NONE;
+       struct ldb_result *res = NULL;
+       struct ldb_dn *group_dn = NULL;
+       struct ldb_context *ldb = NULL;
+       int ret;
+
+       ldb = ldb_module_get_ctx(acc->module);
+       group_dn = ldb_dn_new(ctx, ldb, group);
+       ret = dsdb_module_search_dn(acc->module,
+                                   ctx,
+                                   &res,
+                                   group_dn,
+                                   group_type_attr,
+                                   DSDB_FLAG_NEXT_MODULE |
+                                       DSDB_SEARCH_REVEAL_INTERNALS |
+                                       DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
+                                   NULL);
+       if (ret == LDB_SUCCESS) {
+               const char *user = NULL;
+               group_type =
+                   ldb_msg_find_attr_as_uint(res->msgs[0], "groupType", 0);
+               event_id = get_add_member_event(group_type);
+               user = dsdb_audit_get_primary_dn(acc->request);
+               log_membership_change(
+                   acc->module, acc->request, "Added", user, event_id, status);
+       }
+}
 
 /*
  * @brief Log the details of a primary group change.
 
 /*
  * @brief Log the details of a primary group change.
@@ -811,6 +920,7 @@ static void log_user_primary_group_change(
        struct dom_sid *account_sid = NULL;
        int ret;
        const struct ldb_message *msg = dsdb_audit_get_message(acc->request);
        struct dom_sid *account_sid = NULL;
        int ret;
        const struct ldb_message *msg = dsdb_audit_get_message(acc->request);
+
        if (status == LDB_SUCCESS && msg != NULL) {
                struct ldb_result *res = NULL;
                ret = dsdb_module_search_dn(
        if (status == LDB_SUCCESS && msg != NULL) {
                struct ldb_result *res = NULL;
                ret = dsdb_module_search_dn(
@@ -853,6 +963,16 @@ static void log_user_primary_group_change(
                        "PrimaryGroup",
                        group,
                        status);
                        "PrimaryGroup",
                        group,
                        status);
+               /*
+                * Are we adding a new user with the primaryGroupID
+                * set. If so and we're generating JSON audit logs, will need to
+                * generate an "Add" message with the appropriate windows
+                * event id.
+                */
+               if (acc->request->operation == LDB_ADD) {
+                       log_new_user_added_to_primary_group(
+                           ctx, acc, group, status);
+               }
        }
        TALLOC_FREE(ctx);
 }
        }
        TALLOC_FREE(ctx);
 }
@@ -866,7 +986,6 @@ static void log_user_primary_group_change(
  * @param acc details of the group memberships before the operation.
  * @param status The status code returned by the operation.
  *
  * @param acc details of the group memberships before the operation.
  * @param status The status code returned by the operation.
  *
- * @return an LDB status code.
  */
 static void log_group_membership_changes(
        struct audit_callback_context *acc,
  */
 static void log_group_membership_changes(
        struct audit_callback_context *acc,
@@ -875,6 +994,7 @@ static void log_group_membership_changes(
        TALLOC_CTX *ctx = talloc_new(NULL);
        struct ldb_message_element *new_val = NULL;
        int ret;
        TALLOC_CTX *ctx = talloc_new(NULL);
        struct ldb_message_element *new_val = NULL;
        int ret;
+       uint32_t group_type;
        const struct ldb_message *msg = dsdb_audit_get_message(acc->request);
        if (status == LDB_SUCCESS && msg != NULL) {
                struct ldb_result *res = NULL;
        const struct ldb_message *msg = dsdb_audit_get_message(acc->request);
        if (status == LDB_SUCCESS && msg != NULL) {
                struct ldb_result *res = NULL;
@@ -883,21 +1003,23 @@ static void log_group_membership_changes(
                        ctx,
                        &res,
                        msg->dn,
                        ctx,
                        &res,
                        msg->dn,
-                       member_attr,
+                       group_attrs,
                        DSDB_FLAG_NEXT_MODULE |
                        DSDB_SEARCH_REVEAL_INTERNALS |
                        DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
                        NULL);
                if (ret == LDB_SUCCESS) {
                        new_val = ldb_msg_find_element(res->msgs[0], "member");
                        DSDB_FLAG_NEXT_MODULE |
                        DSDB_SEARCH_REVEAL_INTERNALS |
                        DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
                        NULL);
                if (ret == LDB_SUCCESS) {
                        new_val = ldb_msg_find_element(res->msgs[0], "member");
-               }
+                       group_type = ldb_msg_find_attr_as_uint(
+                           res->msgs[0], "groupType", 0);
+                       log_membership_changes(acc->module,
+                                              acc->request,
+                                              new_val,
+                                              acc->members,
+                                              group_type,
+                                              status);
+                               }
        }
        }
-       log_membership_changes(
-               acc->module,
-               acc->request,
-               new_val,
-               acc->members,
-               status);
        TALLOC_FREE(ctx);
 }
 
        TALLOC_FREE(ctx);
 }
 
@@ -1300,7 +1422,7 @@ static int set_group_modify_callback(
                context,
                &res,
                req->op.add.message->dn,
                context,
                &res,
                req->op.add.message->dn,
-               member_attr,
+               group_attrs,
                DSDB_FLAG_NEXT_MODULE |
                DSDB_SEARCH_REVEAL_INTERNALS |
                DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
                DSDB_FLAG_NEXT_MODULE |
                DSDB_SEARCH_REVEAL_INTERNALS |
                DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
index 241c0534dae0feb8e5f1486d55012a29a9c66c5b..a6b9d6039775907a3c50b7cc5371c7add579f06d 100644 (file)
@@ -82,8 +82,8 @@ void audit_message_send(
        messages_sent++;
 }
 
        messages_sent++;
 }
 
-#define check_group_change_message(m, u, a)\
-       _check_group_change_message(m, u, a, __FILE__, __LINE__);
+#define check_group_change_message(m, u, a, e)                                 \
+       _check_group_change_message(m, u, a, e, __FILE__, __LINE__);
 /*
  * declare the internal cmocka cm_print_error so that we can output messages
  * in sub unit format
 /*
  * declare the internal cmocka cm_print_error so that we can output messages
  * in sub unit format
@@ -102,17 +102,18 @@ void cm_print_error(const char * const format, ...);
  * There should be a user element matching the expected value
  * There should be an action matching the expected value
  */
  * There should be a user element matching the expected value
  * There should be an action matching the expected value
  */
-static void _check_group_change_message(
-       const int message,
-       const char *user,
-       const char *action,
-       const char *file,
-       const int line)
+static void _check_group_change_message(const int message,
+                                       const char *user,
+                                       const char *action,
+                                       enum event_id_type event_id,
+                                       const char *file,
+                                       const int line)
 {
        struct json_object json;
        json_t *audit = NULL;
        json_t *v = NULL;
        const char* value;
 {
        struct json_object json;
        json_t *audit = NULL;
        json_t *v = NULL;
        const char* value;
+       int int_value;
        int cmp;
 
        json = messages[message];
        int cmp;
 
        json = messages[message];
@@ -157,12 +158,11 @@ static void _check_group_change_message(
        /*
         * Validate the groupChange element
         */
        /*
         * Validate the groupChange element
         */
-       if (json_object_size(audit) != 10) {
-               cm_print_error(
-                   "Unexpected number of elements in groupChange "
-                   "%zu != %d\n",
-                   json_object_size(audit),
-                   10);
+       if (json_object_size(audit) != 11) {
+               cm_print_error("Unexpected number of elements in groupChange "
+                              "%zu != %d\n",
+                              json_object_size(audit),
+                              11);
                _fail(file, line);
        }
        /*
                _fail(file, line);
        }
        /*
@@ -183,7 +183,6 @@ static void _check_group_change_message(
                    user);
                _fail(file, line);
        }
                    user);
                _fail(file, line);
        }
-
        /*
         * Validate the action element
         */
        /*
         * Validate the action element
         */
@@ -202,6 +201,23 @@ static void _check_group_change_message(
                    action);
                _fail(file, line);
        }
                    action);
                _fail(file, line);
        }
+
+       /*
+        * Validate the eventId element
+        */
+       v = json_object_get(audit, "eventId");
+       if (v == NULL) {
+               cm_print_error("No eventId element\n");
+               _fail(file, line);
+       }
+
+       int_value = json_integer_value(v);
+       if (int_value != event_id) {
+               cm_print_error("Unexpected eventId \"%d\" != \"%d\"\n",
+                              int_value,
+                              event_id);
+               _fail(file, line);
+       }
 }
 
 #define check_timestamp(b, t)\
 }
 
 #define check_timestamp(b, t)\
@@ -752,6 +768,7 @@ static void test_audit_group_json(void **state)
        struct GUID transaction_id;
        const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
 
        struct GUID transaction_id;
        const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
 
+       enum event_id_type event_id = EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP;
 
        struct json_object json;
        json_t *audit = NULL;
 
        struct json_object json;
        json_t *audit = NULL;
@@ -779,13 +796,13 @@ static void test_audit_group_json(void **state)
        add_transaction_id(req, TRANSACTION);
 
        before = time(NULL);
        add_transaction_id(req, TRANSACTION);
 
        before = time(NULL);
-       json = audit_group_json(
-               module,
-               req,
-               "the-action",
-               "the-user-name",
-               "the-group-name",
-               LDB_ERR_OPERATIONS_ERROR);
+       json = audit_group_json(module,
+                               req,
+                               "the-action",
+                               "the-user-name",
+                               "the-group-name",
+                               event_id,
+                               LDB_ERR_OPERATIONS_ERROR);
        assert_int_equal(3, json_object_size(json.root));
 
        v = json_object_get(json.root, "type");
        assert_int_equal(3, json_object_size(json.root));
 
        v = json_object_get(json.root, "type");
@@ -800,12 +817,18 @@ static void test_audit_group_json(void **state)
        audit = json_object_get(json.root, "groupChange");
        assert_non_null(audit);
        assert_true(json_is_object(audit));
        audit = json_object_get(json.root, "groupChange");
        assert_non_null(audit);
        assert_true(json_is_object(audit));
-       assert_int_equal(10, json_object_size(audit));
+       assert_int_equal(11, json_object_size(audit));
 
        o = json_object_get(audit, "version");
        assert_non_null(o);
        check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
 
 
        o = json_object_get(audit, "version");
        assert_non_null(o);
        check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
 
+       v = json_object_get(audit, "eventId");
+       assert_non_null(v);
+       assert_true(json_is_integer(v));
+       assert_int_equal(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+                        json_integer_value(v));
+
        v = json_object_get(audit, "statusCode");
        assert_non_null(v);
        assert_true(json_is_integer(v));
        v = json_object_get(audit, "statusCode");
        assert_non_null(v);
        assert_true(json_is_integer(v));
@@ -887,6 +910,7 @@ static void test_log_membership_changes_removed(void **state)
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
+       uint32_t group_type = GTYPE_SECURITY_GLOBAL_GROUP;
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
@@ -931,7 +955,7 @@ static void test_log_membership_changes_removed(void **state)
         * call log_membership_changes
         */
        messages_sent = 0;
         * call log_membership_changes
         */
        messages_sent = 0;
-       log_membership_changes(module, req, new_el, old_el, status);
+       log_membership_changes(module, req, new_el, old_el, group_type, status);
 
        /*
         * Check the results
 
        /*
         * Check the results
@@ -941,7 +965,8 @@ static void test_log_membership_changes_removed(void **state)
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
-           "Removed");
+           "Removed",
+           EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP);
 
        /*
         * Clean up
 
        /*
         * Clean up
@@ -969,6 +994,7 @@ static void test_log_membership_changes_remove_all(void **state)
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
        int status = 0;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
        int status = 0;
+       uint32_t group_type = GTYPE_SECURITY_BUILTIN_LOCAL_GROUP;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
        setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
        TALLOC_CTX *ctx = talloc_new(NULL);
 
        setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
@@ -1007,7 +1033,7 @@ static void test_log_membership_changes_remove_all(void **state)
         * call log_membership_changes
         */
        messages_sent = 0;
         * call log_membership_changes
         */
        messages_sent = 0;
-       log_membership_changes( module, req, new_el, old_el, status);
+       log_membership_changes(module, req, new_el, old_el, group_type, status);
 
        /*
         * Check the results
 
        /*
         * Check the results
@@ -1017,12 +1043,14 @@ static void test_log_membership_changes_remove_all(void **state)
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
-           "Removed");
+           "Removed",
+           EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP);
 
        check_group_change_message(
            1,
            "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
 
        check_group_change_message(
            1,
            "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
-           "Removed");
+           "Removed",
+           EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP);
 
        /*
         * Clean up
 
        /*
         * Clean up
@@ -1052,6 +1080,7 @@ static void test_log_membership_changes_added(void **state)
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
+       uint32_t group_type = GTYPE_SECURITY_DOMAIN_LOCAL_GROUP;
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
@@ -1095,7 +1124,7 @@ static void test_log_membership_changes_added(void **state)
         * call log_membership_changes
         */
        messages_sent = 0;
         * call log_membership_changes
         */
        messages_sent = 0;
-       log_membership_changes( module, req, new_el, old_el, status);
+       log_membership_changes(module, req, new_el, old_el, group_type, status);
 
        /*
         * Check the results
 
        /*
         * Check the results
@@ -1105,7 +1134,8 @@ static void test_log_membership_changes_added(void **state)
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
-           "Added");
+           "Added",
+           EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP);
 
        /*
         * Clean up
 
        /*
         * Clean up
@@ -1133,6 +1163,7 @@ static void test_log_membership_changes_add_to_empty(void **state)
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
+       uint32_t group_type = GTYPE_SECURITY_UNIVERSAL_GROUP;
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
@@ -1174,18 +1205,20 @@ static void test_log_membership_changes_add_to_empty(void **state)
         * Run log membership changes
         */
        messages_sent = 0;
         * Run log membership changes
         */
        messages_sent = 0;
-       log_membership_changes( module, req, new_el, old_el, status);
+       log_membership_changes(module, req, new_el, old_el, group_type, status);
        assert_int_equal(2, messages_sent);
 
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
        assert_int_equal(2, messages_sent);
 
        check_group_change_message(
            0,
            "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
-           "Added");
+           "Added",
+           EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP);
 
        check_group_change_message(
            1,
 
        check_group_change_message(
            1,
-            "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
-           "Added");
+           "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
+           "Added",
+           EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP);
 
        json_free(&messages[0]);
        json_free(&messages[1]);
 
        json_free(&messages[0]);
        json_free(&messages[1]);
@@ -1216,6 +1249,7 @@ static void test_log_membership_changes_rmd_flags(void **state)
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
        struct ldb_request *req = NULL;
        struct ldb_message_element *new_el = NULL;
        struct ldb_message_element *old_el = NULL;
+       uint32_t group_type = GTYPE_SECURITY_GLOBAL_GROUP;
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
        int status = 0;
        TALLOC_CTX *ctx = talloc_new(NULL);
 
@@ -1286,7 +1320,7 @@ static void test_log_membership_changes_rmd_flags(void **state)
         * call log_membership_changes
         */
        messages_sent = 0;
         * call log_membership_changes
         */
        messages_sent = 0;
-       log_membership_changes( module, req, new_el, old_el, status);
+       log_membership_changes(module, req, new_el, old_el, group_type, status);
 
        /*
         * Check the results
 
        /*
         * Check the results
@@ -1296,11 +1330,13 @@ static void test_log_membership_changes_rmd_flags(void **state)
        check_group_change_message(
            0,
            "cn=grpadttstuser03,cn=users,DC=addom,DC=samba,DC=example,DC=com",
        check_group_change_message(
            0,
            "cn=grpadttstuser03,cn=users,DC=addom,DC=samba,DC=example,DC=com",
-           "Removed");
+           "Removed",
+           EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP);
        check_group_change_message(
            1,
            "cn=grpadttstuser04,cn=users,DC=addom,DC=samba,DC=example,DC=com",
        check_group_change_message(
            1,
            "cn=grpadttstuser04,cn=users,DC=addom,DC=samba,DC=example,DC=com",
-           "Added");
+           "Added",
+           EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP);
 
        /*
         * Clean up
 
        /*
         * Clean up
@@ -1310,6 +1346,71 @@ static void test_log_membership_changes_rmd_flags(void **state)
        TALLOC_FREE(ctx);
 }
 
        TALLOC_FREE(ctx);
 }
 
+static void test_get_add_member_event(void **state)
+{
+       assert_int_equal(
+           EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP,
+           get_add_member_event(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
+
+       assert_int_equal(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
+                        get_add_member_event(GTYPE_SECURITY_GLOBAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP,
+           get_add_member_event(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
+
+       assert_int_equal(EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP,
+                        get_add_member_event(GTYPE_SECURITY_UNIVERSAL_GROUP));
+
+       assert_int_equal(EVT_ID_USER_ADDED_TO_GLOBAL_GROUP,
+                        get_add_member_event(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_ADDED_TO_LOCAL_GROUP,
+           get_add_member_event(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_ADDED_TO_UNIVERSAL_GROUP,
+           get_add_member_event(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
+
+       assert_int_equal(EVT_ID_NONE, get_add_member_event(0));
+
+       assert_int_equal(EVT_ID_NONE, get_add_member_event(UINT32_MAX));
+}
+
+static void test_get_remove_member_event(void **state)
+{
+       assert_int_equal(
+           EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP,
+           get_remove_member_event(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
+
+       assert_int_equal(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP,
+                        get_remove_member_event(GTYPE_SECURITY_GLOBAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP,
+           get_remove_member_event(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_REMOVED_FROM_UNIVERSAL_SEC_GROUP,
+           get_remove_member_event(GTYPE_SECURITY_UNIVERSAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_REMOVED_FROM_GLOBAL_GROUP,
+           get_remove_member_event(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_REMOVED_FROM_LOCAL_GROUP,
+           get_remove_member_event(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
+
+       assert_int_equal(
+           EVT_ID_USER_REMOVED_FROM_UNIVERSAL_GROUP,
+           get_remove_member_event(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
+
+       assert_int_equal(EVT_ID_NONE, get_remove_member_event(0));
+
+       assert_int_equal(EVT_ID_NONE, get_remove_member_event(UINT32_MAX));
+}
 /*
  * Note: to run under valgrind us:
  *       valgrind --suppressions=test_group_audit.valgrind bin/test_group_audit
 /*
  * Note: to run under valgrind us:
  *       valgrind --suppressions=test_group_audit.valgrind bin/test_group_audit
@@ -1319,17 +1420,19 @@ static void test_log_membership_changes_rmd_flags(void **state)
  */
 int main(void) {
        const struct CMUnitTest tests[] = {
  */
 int main(void) {
        const struct CMUnitTest tests[] = {
-               cmocka_unit_test(test_audit_group_json),
-               cmocka_unit_test(test_get_transaction_id),
-               cmocka_unit_test(test_audit_group_hr),
-               cmocka_unit_test(test_get_parsed_dns),
-               cmocka_unit_test(test_dn_compare),
-               cmocka_unit_test(test_get_primary_group_dn),
-               cmocka_unit_test(test_log_membership_changes_removed),
-               cmocka_unit_test(test_log_membership_changes_remove_all),
-               cmocka_unit_test(test_log_membership_changes_added),
-               cmocka_unit_test(test_log_membership_changes_add_to_empty),
-               cmocka_unit_test(test_log_membership_changes_rmd_flags),
+           cmocka_unit_test(test_audit_group_json),
+           cmocka_unit_test(test_get_transaction_id),
+           cmocka_unit_test(test_audit_group_hr),
+           cmocka_unit_test(test_get_parsed_dns),
+           cmocka_unit_test(test_dn_compare),
+           cmocka_unit_test(test_get_primary_group_dn),
+           cmocka_unit_test(test_log_membership_changes_removed),
+           cmocka_unit_test(test_log_membership_changes_remove_all),
+           cmocka_unit_test(test_log_membership_changes_added),
+           cmocka_unit_test(test_log_membership_changes_add_to_empty),
+           cmocka_unit_test(test_log_membership_changes_rmd_flags),
+           cmocka_unit_test(test_get_add_member_event),
+           cmocka_unit_test(test_get_remove_member_event),
        };
 
        cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
        };
 
        cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
index 3c8829e7087127ddfe29e9a40b7bfca6dd98fca7..ea9f2b7db796855df0452897772b9870d91dc1fb 100644 (file)
@@ -139,6 +139,7 @@ static void test_audit_group_json(void **state)
        struct GUID transaction_id;
        const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
 
        struct GUID transaction_id;
        const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
 
+       enum event_id_type event_id = EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP;
 
        struct json_object json;
 
 
        struct json_object json;
 
@@ -166,13 +167,13 @@ static void test_audit_group_json(void **state)
 
        will_return(__wrap_json_new_object, false);
 
 
        will_return(__wrap_json_new_object, false);
 
-       json = audit_group_json(
-               module,
-               req,
-               "the-action",
-               "the-user-name",
-               "the-group-name",
-               LDB_ERR_OPERATIONS_ERROR);
+       json = audit_group_json(module,
+                               req,
+                               "the-action",
+                               "the-user-name",
+                               "the-group-name",
+                               event_id,
+                               LDB_ERR_OPERATIONS_ERROR);
        assert_true(json_is_invalid(&json));
 
        /*
        assert_true(json_is_invalid(&json));
 
        /*
@@ -182,13 +183,13 @@ static void test_audit_group_json(void **state)
        will_return(__wrap_json_new_object, true);
        will_return(__wrap_json_add_version, JSON_ERROR);
 
        will_return(__wrap_json_new_object, true);
        will_return(__wrap_json_add_version, JSON_ERROR);
 
-       json = audit_group_json(
-               module,
-               req,
-               "the-action",
-               "the-user-name",
-               "the-group-name",
-               LDB_ERR_OPERATIONS_ERROR);
+       json = audit_group_json(module,
+                               req,
+                               "the-action",
+                               "the-user-name",
+                               "the-group-name",
+                               event_id,
+                               LDB_ERR_OPERATIONS_ERROR);
        assert_true(json_is_invalid(&json));
 
        /*
        assert_true(json_is_invalid(&json));
 
        /*
@@ -199,13 +200,13 @@ static void test_audit_group_json(void **state)
        will_return(__wrap_json_add_version, 0);
        will_return(__wrap_json_new_object, false);
 
        will_return(__wrap_json_add_version, 0);
        will_return(__wrap_json_new_object, false);
 
-       json = audit_group_json(
-               module,
-               req,
-               "the-action",
-               "the-user-name",
-               "the-group-name",
-               LDB_ERR_OPERATIONS_ERROR);
+       json = audit_group_json(module,
+                               req,
+                               "the-action",
+                               "the-user-name",
+                               "the-group-name",
+                               event_id,
+                               LDB_ERR_OPERATIONS_ERROR);
        assert_true(json_is_invalid(&json));
 
        /*
        assert_true(json_is_invalid(&json));
 
        /*
@@ -216,13 +217,13 @@ static void test_audit_group_json(void **state)
        will_return(__wrap_json_new_object, true);
        will_return(__wrap_json_add_timestamp, JSON_ERROR);
 
        will_return(__wrap_json_new_object, true);
        will_return(__wrap_json_add_timestamp, JSON_ERROR);
 
-       json = audit_group_json(
-               module,
-               req,
-               "the-action",
-               "the-user-name",
-               "the-group-name",
-               LDB_ERR_OPERATIONS_ERROR);
+       json = audit_group_json(module,
+                               req,
+                               "the-action",
+                               "the-user-name",
+                               "the-group-name",
+                               event_id,
+                               LDB_ERR_OPERATIONS_ERROR);
        assert_true(json_is_invalid(&json));
 
 
        assert_true(json_is_invalid(&json));
 
 
@@ -234,13 +235,13 @@ static void test_audit_group_json(void **state)
        will_return(__wrap_json_new_object, true);
        will_return(__wrap_json_add_timestamp, 0);
 
        will_return(__wrap_json_new_object, true);
        will_return(__wrap_json_add_timestamp, 0);
 
-       json = audit_group_json(
-               module,
-               req,
-               "the-action",
-               "the-user-name",
-               "the-group-name",
-               LDB_ERR_OPERATIONS_ERROR);
+       json = audit_group_json(module,
+                               req,
+                               "the-action",
+                               "the-user-name",
+                               "the-group-name",
+                               event_id,
+                               LDB_ERR_OPERATIONS_ERROR);
        assert_false(json_is_invalid(&json));
 
        json_free(&json);
        assert_false(json_is_invalid(&json));
 
        json_free(&json);