1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

dsdb audit_log: Add windows event codes to password changes

Add a new "eventId" element to the PasswordChange JSON log messages.
This contains a Windows Event Code Id either:
	4723	Password changed
	4724	Password reset

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Gary Lockyer 2018-12-14 11:09:20 +13:00 committed by Andrew Bartlett
parent 105cdd6c1c
commit e97acc714d
4 changed files with 74 additions and 4 deletions

View File

@ -10,7 +10,9 @@ interface windows_events
typedef [v1_enum,public] enum {
EVT_ID_SUCCESSFUL_LOGON = 4624,
EVT_ID_UNSUCCESSFUL_LOGON = 4625
EVT_ID_UNSUCCESSFUL_LOGON = 4625,
EVT_ID_PASSWORD_CHANGE = 4723,
EVT_ID_PASSWORD_RESET = 4724
} event_id_type;
typedef [v1_enum,public] enum {

View File

@ -28,6 +28,11 @@ from samba.tests.audit_log_base import AuditLogTestBase
from samba.tests import delete_force
from samba.net import Net
from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS
from samba.dcerpc.windows_event_ids import (
EVT_ID_PASSWORD_CHANGE,
EVT_ID_PASSWORD_RESET
)
USER_NAME = "auditlogtestuser"
USER_PASS = samba.generate_random_password(32, 32)
@ -119,6 +124,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
len(messages),
"Did not receive the expected number of messages")
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_CHANGE, audit["eventId"])
self.assertEquals("Change", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],
@ -147,6 +153,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
"Did not receive the expected number of messages")
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"])
self.assertEquals("Reset", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],
@ -187,6 +194,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
"Did not receive the expected number of messages")
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"])
self.assertEquals("Reset", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],
@ -223,6 +231,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
"Did not receive the expected number of messages")
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"])
self.assertEquals("Reset", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],
@ -256,6 +265,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
"Did not receive the expected number of messages")
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_CHANGE, audit["eventId"])
self.assertEquals("Change", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],
@ -286,6 +296,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
"Did not receive the expected number of messages")
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"])
self.assertEquals("Reset", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],
@ -312,6 +323,7 @@ class AuditLogPassChangeTests(AuditLogTestBase):
# The first message should be the reset from the Setup code.
#
audit = messages[0]["passwordChange"]
self.assertEquals(EVT_ID_PASSWORD_RESET, audit["eventId"])
self.assertEquals("Reset", audit["action"])
self.assertEquals(dn, audit["dn"])
self.assertRegexpMatches(audit["remoteAddress"],

View File

@ -33,6 +33,7 @@
#include "libcli/security/dom_sid.h"
#include "auth/common_auth.h"
#include "param/param.h"
#include "librpc/gen_ndr/windows_event_ids.h"
#define OPERATION_JSON_TYPE "dsdbChange"
#define OPERATION_HR_TAG "DSDB Change"
@ -43,7 +44,7 @@
#define PASSWORD_JSON_TYPE "passwordChange"
#define PASSWORD_HR_TAG "Password Change"
#define PASSWORD_MAJOR 1
#define PASSWORD_MINOR 0
#define PASSWORD_MINOR 1
#define PASSWORD_LOG_LVL 5
#define TRANSACTION_JSON_TYPE "dsdbTransaction"
@ -121,6 +122,47 @@ static bool has_password_changed(const struct ldb_message *message)
return false;
}
/*
* @brief get the password change windows event id
*
* Get the Windows Event Id for the action being performed on the user password.
*
* This routine assumes that the request contains password attributes and that the
* password ACL checks have been performed by acl.c
*
* @param request the ldb_request to inspect
* @param reply the ldb_reply, will contain the password controls
*
* @return The windows event code.
*/
static enum event_id_type get_password_windows_event_id(
const struct ldb_request *request,
const struct ldb_reply *reply)
{
if(request->operation == LDB_ADD) {
return EVT_ID_PASSWORD_RESET;
} else {
struct ldb_control *pav_ctrl = NULL;
struct dsdb_control_password_acl_validation *pav = NULL;
pav_ctrl = ldb_reply_get_control(
discard_const(reply),
DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID);
if (pav_ctrl == NULL) {
return EVT_ID_PASSWORD_RESET;
}
pav = talloc_get_type_abort(
pav_ctrl->data,
struct dsdb_control_password_acl_validation);
if (pav->pwd_reset) {
return EVT_ID_PASSWORD_RESET;
} else {
return EVT_ID_PASSWORD_CHANGE;
}
}
}
/*
* @brief Is the request a password "Change" or a "Reset"
*
@ -455,6 +497,7 @@ static struct json_object password_change_json(
= talloc_get_type_abort(ldb_module_get_private(module),
struct audit_private);
int rc = 0;
enum event_id_type event_id;
ldb = ldb_module_get_ctx(module);
@ -463,6 +506,7 @@ static struct json_object password_change_json(
dn = dsdb_audit_get_primary_dn(request);
action = get_password_action(request, reply);
unique_session_token = dsdb_audit_get_unique_session_token(module);
event_id = get_password_windows_event_id(request, reply);
audit = json_new_object();
if (json_is_invalid(&audit)) {
@ -472,6 +516,10 @@ static struct json_object password_change_json(
if (rc != 0) {
goto failure;
}
rc = json_add_int(&audit, "eventId", event_id);
if (rc != 0) {
goto failure;
}
rc = json_add_int(&audit, "statusCode", reply->error);
if (rc != 0) {
goto failure;

View File

@ -828,11 +828,14 @@ static void test_password_change_json_empty(void **state)
audit = json_object_get(json.root, "passwordChange");
assert_non_null(audit);
assert_true(json_is_object(audit));
assert_int_equal(9, json_object_size(audit));
assert_int_equal(10, json_object_size(audit));
o = json_object_get(audit, "version");
assert_non_null(o);
v = json_object_get(audit, "eventId");
assert_non_null(v);
v = json_object_get(audit, "statusCode");
assert_non_null(v);
@ -950,12 +953,17 @@ static void test_password_change_json(void **state)
audit = json_object_get(json.root, "passwordChange");
assert_non_null(audit);
assert_true(json_is_object(audit));
assert_int_equal(9, json_object_size(audit));
assert_int_equal(10, json_object_size(audit));
o = json_object_get(audit, "version");
assert_non_null(o);
check_version(o, PASSWORD_MAJOR,PASSWORD_MINOR);
v = json_object_get(audit, "eventId");
assert_non_null(v);
assert_true(json_is_integer(v));
assert_int_equal(EVT_ID_PASSWORD_RESET, json_integer_value(v));
v = json_object_get(audit, "statusCode");
assert_non_null(v);
assert_true(json_is_integer(v));