lookup.c
lsarpc.c
lsasrv.c
+ notify.c
policy.c
privileges.c
registry.c
ReplyMsg = &RequestMsg;
break;
+ case LSASS_REQUEST_POLICY_CHANGE_NOTIFY:
+ RequestMsg.Status = LsapRegisterNotification(&RequestMsg);
+ ReplyMsg = &RequestMsg;
+ break;
+
default:
RequestMsg.Status = STATUS_INVALID_SYSTEM_SERVICE;
ReplyMsg = &RequestMsg;
/* Initialize logon sessions */
LsapInitLogonSessions();
+ /* Initialize the notification list */
+ LsapInitNotificationList();
+
/* Initialize registered authentication packages */
Status = LsapInitAuthPackages();
if (!NT_SUCCESS(Status))
NTSTATUS
LsarStartRpcServer(VOID);
+/* notify.c */
+VOID
+LsapInitNotificationList(VOID);
+
+NTSTATUS
+LsapRegisterNotification(
+ PLSA_API_MSG RequestMsg);
+
/* policy.c */
NTSTATUS
LsarQueryAuditLog(PLSA_DB_OBJECT PolicyObject,
--- /dev/null
+/*
+ * PROJECT: Local Security Authority Server DLL
+ * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: LSA policy change notifications
+ * COPYRIGHT: Eric Kohl 2018
+ */
+
+#include "lsasrv.h"
+
+typedef struct _LSA_NOTIFICATION_ENTRY
+{
+ LIST_ENTRY Entry;
+ POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass;
+ HANDLE EventHandle;
+} LSA_NOTIFICATION_ENTRY, *PLSA_NOTIFICATION_ENTRY;
+
+/* GLOBALS *****************************************************************/
+
+static LIST_ENTRY NotificationListHead;
+static RTL_RESOURCE NotificationListLock;
+
+
+/* FUNCTIONS ***************************************************************/
+
+VOID
+LsapInitNotificationList(VOID)
+{
+ InitializeListHead(&NotificationListHead);
+ RtlInitializeResource(&NotificationListLock);
+}
+
+
+static
+PLSA_NOTIFICATION_ENTRY
+LsapGetNotificationEntryByHandle(
+ HANDLE EventHandle)
+{
+ PLIST_ENTRY NotificationEntry;
+ PLSA_NOTIFICATION_ENTRY CurrentNotification;
+
+ NotificationEntry = NotificationListHead.Flink;
+ while (NotificationEntry != &NotificationListHead)
+ {
+ CurrentNotification = CONTAINING_RECORD(NotificationEntry, LSA_NOTIFICATION_ENTRY, Entry);
+
+ if (CurrentNotification->EventHandle == EventHandle)
+ return CurrentNotification;
+
+ NotificationEntry = NotificationEntry->Flink;
+ }
+
+ return NULL;
+}
+
+
+NTSTATUS
+LsapRegisterNotification(
+ PLSA_API_MSG pRequestMsg)
+{
+ PLSA_NOTIFICATION_ENTRY pEntry;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ FIXME("LsapRegisterNotification(%p)\n", pRequestMsg);
+
+ /* Acquire the notification list lock exclusively */
+ RtlAcquireResourceExclusive(&NotificationListLock, TRUE);
+
+ if (pRequestMsg->PolicyChangeNotify.Request.Register)
+ {
+ pEntry = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(LSA_NOTIFICATION_ENTRY));
+ if (pEntry == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ pEntry->InformationClass = pRequestMsg->PolicyChangeNotify.Request.InformationClass;
+ pEntry->EventHandle = pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle;
+
+ InsertHeadList(&NotificationListHead,
+ &pEntry->Entry);
+ }
+ else
+ {
+ pEntry = LsapGetNotificationEntryByHandle(pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle);
+ if (pEntry)
+ {
+ RemoveEntryList(&pEntry->Entry);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
+ }
+ }
+
+done:
+ /* Release the notification list lock */
+ RtlReleaseResource(&NotificationListLock);
+
+ return Status;
+}
+
+/* EOF */
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
-LsaRegisterPolicyChangeNotification(POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass,
- HANDLE NotificationEventHandle)
+LsaRegisterPolicyChangeNotification(
+ POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass,
+ HANDLE NotificationEventHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ LSA_API_MSG ApiMessage;
+ NTSTATUS Status;
+
+ TRACE("LsaRegisterPolicyChangeNotification(%lu %p)\n",
+ InformationClass, NotificationEventHandle);
+
+ Status = LsapOpenLsaPort();
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ ApiMessage.ApiNumber = LSASS_REQUEST_POLICY_CHANGE_NOTIFY;
+ ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.PolicyChangeNotify);
+ ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
+ ApiMessage.h.u2.ZeroInit = 0;
+
+ ApiMessage.PolicyChangeNotify.Request.InformationClass = InformationClass;
+ ApiMessage.PolicyChangeNotify.Request.NotificationEventHandle = NotificationEventHandle;
+ ApiMessage.PolicyChangeNotify.Request.Register = TRUE;
+
+ Status = NtRequestWaitReplyPort(LsaPortHandle,
+ (PPORT_MESSAGE)&ApiMessage,
+ (PPORT_MESSAGE)&ApiMessage);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtRequestWaitReplyPort() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ if (!NT_SUCCESS(ApiMessage.Status))
+ {
+ ERR("NtRequestWaitReplyPort() failed (ApiMessage.Status 0x%08lx)\n", ApiMessage.Status);
+ return ApiMessage.Status;
+ }
+
+ return Status;
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
-LsaUnregisterPolicyChangeNotification(POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass,
- HANDLE NotificationEventHandle)
+LsaUnregisterPolicyChangeNotification(
+ POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass,
+ HANDLE NotificationEventHandle)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ LSA_API_MSG ApiMessage;
+ NTSTATUS Status;
+
+ TRACE("LsaUnregisterPolicyChangeNotification(%lu %p)\n",
+ InformationClass, NotificationEventHandle);
+
+ Status = LsapOpenLsaPort();
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ ApiMessage.ApiNumber = LSASS_REQUEST_POLICY_CHANGE_NOTIFY;
+ ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.PolicyChangeNotify);
+ ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
+ ApiMessage.h.u2.ZeroInit = 0;
+
+ ApiMessage.PolicyChangeNotify.Request.InformationClass = InformationClass;
+ ApiMessage.PolicyChangeNotify.Request.NotificationEventHandle = NotificationEventHandle;
+ ApiMessage.PolicyChangeNotify.Request.Register = FALSE;
+
+ Status = NtRequestWaitReplyPort(LsaPortHandle,
+ (PPORT_MESSAGE)&ApiMessage,
+ (PPORT_MESSAGE)&ApiMessage);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtRequestWaitReplyPort() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ if (!NT_SUCCESS(ApiMessage.Status))
+ {
+ ERR("NtRequestWaitReplyPort() failed (ApiMessage.Status 0x%08lx)\n", ApiMessage.Status);
+ return ApiMessage.Status;
+ }
+
+ return Status;
}
/* EOF */
NTSTATUS NTAPI LsaQueryTrustedDomainInfoByName(LSA_HANDLE,PLSA_UNICODE_STRING,
TRUSTED_INFORMATION_CLASS,PVOID*);
NTSTATUS NTAPI LsaRegisterLogonProcess(PLSA_STRING,PHANDLE,PLSA_OPERATIONAL_MODE);
+NTSTATUS NTAPI LsaRegisterPolicyChangeNotification(POLICY_NOTIFICATION_INFORMATION_CLASS,
+ HANDLE);
NTSTATUS NTAPI LsaRemoveAccountRights(LSA_HANDLE,PSID,BOOLEAN,
PLSA_UNICODE_STRING,ULONG);
NTSTATUS NTAPI LsaRemovePrivilegesFromAccount(LSA_HANDLE,BOOLEAN,PPRIVILEGE_SET);
TRUSTED_INFORMATION_CLASS,PVOID);
NTSTATUS NTAPI LsaStorePrivateData(LSA_HANDLE,PLSA_UNICODE_STRING,
PLSA_UNICODE_STRING);
+NTSTATUS NTAPI LsaUnregisterPolicyChangeNotification(POLICY_NOTIFICATION_INFORMATION_CLASS,
+ HANDLE);
typedef NTSTATUS (NTAPI *PSAM_PASSWORD_NOTIFICATION_ROUTINE)(PUNICODE_STRING,
ULONG,PUNICODE_STRING);
typedef BOOLEAN (NTAPI *PSAM_INIT_NOTIFICATION_ROUTINE)(VOID);
LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE,
LSASS_REQUEST_ENUM_LOGON_SESSIONS,
LSASS_REQUEST_GET_LOGON_SESSION_DATA,
+ LSASS_REQUEST_POLICY_CHANGE_NOTIFY,
LSASS_REQUEST_MAXIMUM
} LSA_API_NUMBER, *PLSA_API_NUMBER;
} LSA_GET_LOGON_SESSION_DATA_MSG, *PLSA_GET_LOGON_SESSION_DATA_MSG;
+typedef struct _LSA_POLICY_CHANGE_NOTIFY_MSG
+{
+ union
+ {
+ struct
+ {
+ POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass;
+ HANDLE NotificationEventHandle;
+ BOOLEAN Register;
+ } Request;
+ struct
+ {
+ ULONG Dummy;
+ } Reply;
+ };
+} LSA_POLICY_CHANGE_NOTIFY_MSG, *PLSA_POLICY_CHANGE_NOTIFY_MSG;
+
+
typedef struct _LSA_API_MSG
{
PORT_MESSAGE h;
LSA_LOOKUP_AUTHENTICATION_PACKAGE_MSG LookupAuthenticationPackage;
LSA_ENUM_LOGON_SESSIONS_MSG EnumLogonSessions;
LSA_GET_LOGON_SESSION_DATA_MSG GetLogonSessionData;
+ LSA_POLICY_CHANGE_NOTIFY_MSG PolicyChangeNotify;
};
};
};