diff options
-rw-r--r-- | WHATSNEW.txt | 24 | ||||
-rw-r--r-- | librpc/idl/windows_event_ids.idl | 21 | ||||
-rw-r--r-- | python/samba/tests/group_audit.py | 51 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/group_audit.c | 254 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c | 199 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c | 71 |
6 files changed, 462 insertions, 158 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 6698b09d8bc..5f237713015 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -118,17 +118,39 @@ type "logonType". The supported event codes and logon types are: 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 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 -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. " {" diff --git a/librpc/idl/windows_event_ids.idl b/librpc/idl/windows_event_ids.idl index c711db1b30f..240ad9e56ff 100644 --- a/librpc/idl/windows_event_ids.idl +++ b/librpc/idl/windows_event_ids.idl @@ -9,10 +9,23 @@ interface windows_events { 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 { diff --git a/python/samba/tests/group_audit.py b/python/samba/tests/group_audit.py index 53a8bf6afaf..9fe69bd1fc0 100644 --- a/python/samba/tests/group_audit.py +++ b/python/samba/tests/group_audit.py @@ -21,6 +21,10 @@ from __future__ import print_function 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 @@ -100,9 +104,9 @@ class GroupAuditTests(AuditLogTestBase): # # Wait for the primary group change for the created user. # - messages = self.waitForMessages(1) + messages = self.waitForMessages(2) 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"] @@ -120,6 +124,21 @@ class GroupAuditTests(AuditLogTestBase): 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 # @@ -231,11 +250,13 @@ class GroupAuditTests(AuditLogTestBase): # # Wait for the primary group change for the created user. # - messages = self.waitForMessages(1) + messages = self.waitForMessages(2) print("Received %d messages" % len(messages)) - self.assertEquals(1, + self.assertEquals(2, len(messages), "Did not receive the expected number of messages") + + # Check the PrimaryGroup message 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") + # 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. @@ -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(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, + audit["eventId"]) # # 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(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP, + audit["eventId"]) 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(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP, + audit["eventId"]) audit = messages[2]["groupChange"] diff --git a/source4/dsdb/samdb/ldb_modules/group_audit.c b/source4/dsdb/samdb/ldb_modules/group_audit.c index 7e6e16de137..9aba865ccd6 100644 --- a/source4/dsdb/samdb/ldb_modules/group_audit.c +++ b/source4/dsdb/samdb/ldb_modules/group_audit.c @@ -25,6 +25,7 @@ #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" @@ -36,10 +37,11 @@ #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 -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", @@ -105,13 +107,13 @@ static struct GUID *get_transaction_id( * @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; @@ -137,6 +139,12 @@ static struct json_object audit_group_json( 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; @@ -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. + * 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 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. @@ -497,12 +507,7 @@ static void log_primary_group_change( 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, @@ -515,6 +520,13 @@ static void log_primary_group_change( &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); } @@ -532,12 +544,12 @@ static void log_primary_group_change( * @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 = @@ -569,12 +581,7 @@ static void log_membership_change( (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, @@ -592,6 +599,68 @@ static void log_membership_change( } /* + * @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. * * Log details of a change to a users group memberships, except for changes @@ -604,12 +673,12 @@ static void log_membership_change( * @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; @@ -674,6 +743,7 @@ static void log_membership_changes( * 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, @@ -682,12 +752,9 @@ static void log_membership_changes( LDB_SYNTAX_DN); } user = ldb_dn_get_linearized(old_val->dsdb_dn->dn); + event_id = get_remove_member_event(group_type); log_membership_change( - module, - request, - "Removed", - user, - status); + module, request, "Removed", user, event_id, status); old_i++; } else if (cmp == BINARY_EQUAL) { /* @@ -739,27 +806,31 @@ static void log_membership_changes( * DN has been deleted. */ const char *user = NULL; + enum event_id_type event_id; 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; + enum event_id_type event_id; 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++; @@ -769,6 +840,7 @@ static void log_membership_changes( * 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, @@ -777,12 +849,9 @@ static void log_membership_changes( LDB_SYNTAX_DN); } user = ldb_dn_get_linearized(new_val->dsdb_dn->dn); + event_id = get_add_member_event(group_type); log_membership_change( - module, - request, - "Added", - user, - status); + module, request, "Added", user, event_id, status); new_i++; } } @@ -790,6 +859,46 @@ static void log_membership_changes( 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. @@ -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); + 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); + /* + * 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); } @@ -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. * - * @return an LDB status code. */ 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; + 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; @@ -883,21 +1003,23 @@ static void log_group_membership_changes( 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"); - } + 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); } @@ -1300,7 +1422,7 @@ static int set_group_modify_callback( 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, diff --git a/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c b/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c index 241c0534dae..a6b9d603977 100644 --- a/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c +++ b/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c @@ -82,8 +82,8 @@ void audit_message_send( 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 @@ -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 */ -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; + int int_value; int cmp; json = messages[message]; @@ -157,12 +158,11 @@ static void _check_group_change_message( /* * 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); } /* @@ -183,7 +183,6 @@ static void _check_group_change_message( user); _fail(file, line); } - /* * Validate the action element */ @@ -202,6 +201,23 @@ static void _check_group_change_message( 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)\ @@ -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"; + enum event_id_type event_id = EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP; 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); - 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"); @@ -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)); - 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); + 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)); @@ -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; + uint32_t group_type = GTYPE_SECURITY_GLOBAL_GROUP; 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; - 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 @@ -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", - "Removed"); + "Removed", + EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP); /* * 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; + uint32_t group_type = GTYPE_SECURITY_BUILTIN_LOCAL_GROUP; 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; - 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 @@ -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", - "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", - "Removed"); + "Removed", + EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP); /* * 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; + uint32_t group_type = GTYPE_SECURITY_DOMAIN_LOCAL_GROUP; 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; - 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 @@ -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", - "Added"); + "Added", + EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP); /* * 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; + uint32_t group_type = GTYPE_SECURITY_UNIVERSAL_GROUP; 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; - 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", - "Added"); + "Added", + EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP); 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]); @@ -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; + uint32_t group_type = GTYPE_SECURITY_GLOBAL_GROUP; 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; - 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 @@ -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", - "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", - "Added"); + "Added", + EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP); /* * Clean up @@ -1310,6 +1346,71 @@ static void test_log_membership_changes_rmd_flags(void **state) 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 @@ -1319,17 +1420,19 @@ static void test_log_membership_changes_rmd_flags(void **state) */ 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); diff --git a/source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c b/source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c index 3c8829e7087..ea9f2b7db79 100644 --- a/source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c +++ b/source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c @@ -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"; + enum event_id_type event_id = EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP; struct json_object json; @@ -166,13 +167,13 @@ static void test_audit_group_json(void **state) 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)); /* @@ -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); - 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)); /* @@ -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); - 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)); /* @@ -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); - 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)); @@ -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); - 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); |