summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--WHATSNEW.txt24
-rw-r--r--librpc/idl/windows_event_ids.idl21
-rw-r--r--python/samba/tests/group_audit.py51
-rw-r--r--source4/dsdb/samdb/ldb_modules/group_audit.c254
-rw-r--r--source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c199
-rw-r--r--source4/dsdb/samdb/ldb_modules/tests/test_group_audit_errors.c71
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);