[SAMSRV]
[reactos.git] / reactos / dll / win32 / samsrv / user.c
index 0805e44..a442780 100644 (file)
@@ -6,13 +6,8 @@
  * COPYRIGHT:   Copyright 2013 Eric Kohl
  */
 
-/* INCLUDES ****************************************************************/
-
 #include "samsrv.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(samsrv);
-
-
 /* FUNCTIONS ***************************************************************/
 
 NTSTATUS
@@ -117,23 +112,20 @@ SampRemoveGroupMembershipFromUser(IN PSAM_DB_OBJECT UserObject,
     ULONG GroupsCount = 0;
     ULONG Length = 0;
     ULONG i;
-    NTSTATUS Status;
+    NTSTATUS Status = STATUS_SUCCESS;
 
     TRACE("(%p %lu)\n",
           UserObject, GroupId);
 
-    Status = SampGetObjectAttribute(UserObject,
-                                    L"Groups",
-                                    NULL,
-                                    NULL,
-                                    &Length);
+    SampGetObjectAttribute(UserObject,
+                           L"Groups",
+                           NULL,
+                           NULL,
+                           &Length);
 
-    if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+    if (Length == 0)
         return STATUS_MEMBER_NOT_IN_GROUP;
 
-    if (!NT_SUCCESS(Status))
-        return Status;
-
     GroupsBuffer = midl_user_allocate(Length);
     if (GroupsBuffer == NULL)
     {
@@ -158,14 +150,15 @@ SampRemoveGroupMembershipFromUser(IN PSAM_DB_OBJECT UserObject,
         {
             Length -= sizeof(GROUP_MEMBERSHIP);
             Status = STATUS_SUCCESS;
-            break;
-        }
 
-        if (Status == STATUS_SUCCESS && i < GroupsCount - 1)
-        {
-            CopyMemory(&GroupsBuffer[i],
-                       &GroupsBuffer[i + 1],
-                       sizeof(GROUP_MEMBERSHIP));
+            if (GroupsCount - i - 1 > 0)
+            {
+                CopyMemory(&GroupsBuffer[i],
+                           &GroupsBuffer[i + 1],
+                           (GroupsCount - i - 1) * sizeof(GROUP_MEMBERSHIP));
+            }
+
+            break;
         }
     }
 
@@ -321,4 +314,417 @@ done:
     return Status;
 }
 
+
+NTSTATUS
+SampRemoveUserFromAllGroups(IN PSAM_DB_OBJECT UserObject)
+{
+    PGROUP_MEMBERSHIP GroupsBuffer = NULL;
+    PSAM_DB_OBJECT GroupObject;
+    ULONG Length = 0;
+    ULONG i;
+    NTSTATUS Status;
+
+    SampGetObjectAttribute(UserObject,
+                           L"Groups",
+                           NULL,
+                           NULL,
+                           &Length);
+
+    if (Length == 0)
+        return STATUS_SUCCESS;
+
+    GroupsBuffer = midl_user_allocate(Length);
+    if (GroupsBuffer == NULL)
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto done;
+    }
+
+    Status = SampGetObjectAttribute(UserObject,
+                                    L"Groups",
+                                    NULL,
+                                    GroupsBuffer,
+                                    &Length);
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    for (i = 0; i < (Length / sizeof(GROUP_MEMBERSHIP)); i++)
+    {
+        Status = SampOpenGroupObject(UserObject->ParentObject,
+                                     GroupsBuffer[i].RelativeId,
+                                     0,
+                                     &GroupObject);
+        if (!NT_SUCCESS(Status))
+        {
+            goto done;
+        }
+
+        Status = SampRemoveMemberFromGroup(GroupObject,
+                                           UserObject->RelativeId);
+        if (Status == STATUS_MEMBER_NOT_IN_GROUP)
+            Status = STATUS_SUCCESS;
+
+        SampCloseDbObject(GroupObject);
+
+        if (!NT_SUCCESS(Status))
+        {
+            goto done;
+        }
+    }
+
+    /* Remove all groups from the Groups attribute */
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"Groups",
+                                    REG_BINARY,
+                                    NULL,
+                                    0);
+
+done:
+    if (GroupsBuffer != NULL)
+        midl_user_free(GroupsBuffer);
+
+    return Status;
+}
+
+
+NTSTATUS
+SampRemoveUserFromAllAliases(IN PSAM_DB_OBJECT UserObject)
+{
+    FIXME("(%p)\n", UserObject);
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+SampSetUserPassword(IN PSAM_DB_OBJECT UserObject,
+                    IN PENCRYPTED_NT_OWF_PASSWORD NtPassword,
+                    IN BOOLEAN NtPasswordPresent,
+                    IN PENCRYPTED_LM_OWF_PASSWORD LmPassword,
+                    IN BOOLEAN LmPasswordPresent)
+{
+    PENCRYPTED_NT_OWF_PASSWORD NtHistory = NULL;
+    PENCRYPTED_LM_OWF_PASSWORD LmHistory = NULL;
+    ULONG NtHistoryLength = 0;
+    ULONG LmHistoryLength = 0;
+    ULONG CurrentHistoryLength;
+    ULONG MaxHistoryLength = 3;
+    ULONG Length = 0;
+    BOOLEAN UseNtPassword;
+    BOOLEAN UseLmPassword;
+    NTSTATUS Status;
+
+    UseNtPassword =
+       ((NtPasswordPresent != FALSE) &&
+        (NtPassword != NULL) &&
+        (memcmp(NtPassword, &EmptyNtHash, sizeof(ENCRYPTED_NT_OWF_PASSWORD)) != 0));
+
+    UseLmPassword =
+       ((LmPasswordPresent != FALSE) &&
+        (LmPassword != NULL) &&
+        (memcmp(LmPassword, &EmptyLmHash, sizeof(ENCRYPTED_LM_OWF_PASSWORD)) != 0));
+
+    /* Update the NT password history only if we have a new non-empty NT password */
+    if (UseNtPassword)
+    {
+        /* Get the size of the NT history */
+        SampGetObjectAttribute(UserObject,
+                               L"NTPwdHistory",
+                               NULL,
+                               NULL,
+                               &Length);
+
+        CurrentHistoryLength = Length / sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+        if (CurrentHistoryLength < MaxHistoryLength)
+        {
+            NtHistoryLength = (CurrentHistoryLength + 1) * sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+        }
+        else
+        {
+            NtHistoryLength = MaxHistoryLength * sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+        }
+
+        /* Allocate the history buffer */
+        NtHistory = midl_user_allocate(NtHistoryLength);
+        if (NtHistory == NULL)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        if (Length > 0)
+        {
+            /* Get the history */
+            Status = SampGetObjectAttribute(UserObject,
+                                            L"NTPwdHistory",
+                                            NULL,
+                                            NtHistory,
+                                            &Length);
+            if (!NT_SUCCESS(Status))
+                goto done;
+        }
+
+        /* Move the old passwords down by one entry */
+        if (NtHistoryLength > sizeof(ENCRYPTED_NT_OWF_PASSWORD))
+        {
+            MoveMemory(&(NtHistory[1]),
+                       &(NtHistory[0]),
+                       NtHistoryLength - sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+        }
+
+        /* Add the new password to the top of the history */
+        if (NtPasswordPresent)
+        {
+            CopyMemory(&(NtHistory[0]),
+                       NtPassword,
+                       sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+        }
+        else
+        {
+            ZeroMemory(&(NtHistory[0]),
+                       sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+        }
+
+        /* Set the history */
+        Status = SampSetObjectAttribute(UserObject,
+                                        L"NTPwdHistory",
+                                        REG_BINARY,
+                                        (PVOID)NtHistory,
+                                        NtHistoryLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+    /* Update the LM password history only if we have a new non-empty LM password */
+    if (UseLmPassword)
+    {
+        /* Get the size of the LM history */
+        Length = 0;
+        SampGetObjectAttribute(UserObject,
+                               L"LMPwdHistory",
+                               NULL,
+                               NULL,
+                               &Length);
+
+        CurrentHistoryLength = Length / sizeof(ENCRYPTED_LM_OWF_PASSWORD);
+        if (CurrentHistoryLength < MaxHistoryLength)
+        {
+            LmHistoryLength = (CurrentHistoryLength + 1) * sizeof(ENCRYPTED_LM_OWF_PASSWORD);
+        }
+        else
+        {
+            LmHistoryLength = MaxHistoryLength * sizeof(ENCRYPTED_LM_OWF_PASSWORD);
+        }
+
+        /* Allocate the history buffer */
+        LmHistory = midl_user_allocate(LmHistoryLength);
+        if (LmHistory == NULL)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        if (Length > 0)
+        {
+            /* Get the history */
+            Status = SampGetObjectAttribute(UserObject,
+                                            L"LMPwdHistory",
+                                            NULL,
+                                            LmHistory,
+                                            &Length);
+            if (!NT_SUCCESS(Status))
+                goto done;
+        }
+
+        /* Move the old passwords down by one entry */
+        if (LmHistoryLength > sizeof(ENCRYPTED_LM_OWF_PASSWORD))
+        {
+            MoveMemory(&(LmHistory[1]),
+                       &(LmHistory[0]),
+                       LmHistoryLength - sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+        }
+
+        /* Add the new password to the top of the history */
+        if (LmPasswordPresent)
+        {
+            CopyMemory(&(LmHistory[0]),
+                       LmPassword,
+                       sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+        }
+        else
+        {
+            ZeroMemory(&(LmHistory[0]),
+                       sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+        }
+
+        /* Set the LM password history */
+        Status = SampSetObjectAttribute(UserObject,
+                                        L"LMPwdHistory",
+                                        REG_BINARY,
+                                        (PVOID)LmHistory,
+                                        LmHistoryLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+    /* Set the new NT password */
+    if (UseNtPassword)
+    {
+        Status = SampSetObjectAttribute(UserObject,
+                                        L"NTPwd",
+                                        REG_BINARY,
+                                        (PVOID)NtPassword,
+                                        sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+    else
+    {
+        Status = SampSetObjectAttribute(UserObject,
+                                        L"NTPwd",
+                                        REG_BINARY,
+                                        &EmptyNtHash,
+                                        sizeof(ENCRYPTED_NT_OWF_PASSWORD));
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+    /* Set the new LM password */
+    if (UseLmPassword)
+    {
+        Status = SampSetObjectAttribute(UserObject,
+                                        L"LMPwd",
+                                        REG_BINARY,
+                                        (PVOID)LmPassword,
+                                        sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+    else
+    {
+        Status = SampSetObjectAttribute(UserObject,
+                                        L"LMPwd",
+                                        REG_BINARY,
+                                        &EmptyLmHash,
+                                        sizeof(ENCRYPTED_LM_OWF_PASSWORD));
+        if (!NT_SUCCESS(Status))
+            goto done;
+    }
+
+done:
+    if (NtHistory != NULL)
+        midl_user_free(NtHistory);
+
+    if (LmHistory != NULL)
+        midl_user_free(LmHistory);
+
+    return Status;
+}
+
+
+NTSTATUS
+SampGetLogonHoursAttrbute(IN PSAM_DB_OBJECT UserObject,
+                          IN OUT PSAMPR_LOGON_HOURS LogonHours)
+{
+    PUCHAR RawBuffer = NULL;
+    ULONG Length = 0;
+    ULONG BufferLength = 0;
+    NTSTATUS Status;
+
+    Status = SampGetObjectAttribute(UserObject,
+                                    L"LogonHours",
+                                    NULL,
+                                    NULL,
+                                    &Length);
+    if (Status != STATUS_BUFFER_OVERFLOW)
+    {
+        TRACE("SampGetObjectAttribute failed (Status 0x%08lx)\n", Status);
+        return Status;
+    }
+
+    Status = STATUS_SUCCESS;
+
+    if (Length == 0)
+    {
+        LogonHours->UnitsPerWeek = 0;
+        LogonHours->LogonHours = NULL;
+    }
+    else
+    {
+        RawBuffer = midl_user_allocate(Length);
+        if (RawBuffer == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        Status = SampGetObjectAttribute(UserObject,
+                                        L"LogonHours",
+                                        NULL,
+                                        (PVOID)RawBuffer,
+                                        &Length);
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        LogonHours->UnitsPerWeek = *((PUSHORT)RawBuffer);
+
+        BufferLength = (((ULONG)LogonHours->UnitsPerWeek) + 7) / 8;
+
+        LogonHours->LogonHours = midl_user_allocate(BufferLength);
+        if (LogonHours->LogonHours == NULL)
+        {
+            TRACE("Failed to allocate LogonHours buffer!\n");
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        memcpy(LogonHours->LogonHours,
+               &(RawBuffer[2]),
+               BufferLength);
+    }
+
+done:
+
+    if (RawBuffer != NULL)
+        midl_user_free(RawBuffer);
+
+    return Status;
+}
+
+
+NTSTATUS
+SampSetLogonHoursAttrbute(IN PSAM_DB_OBJECT UserObject,
+                          IN PSAMPR_LOGON_HOURS LogonHours)
+{
+    PUCHAR RawBuffer = NULL;
+    ULONG BufferLength;
+    ULONG Length = 0;
+    NTSTATUS Status;
+
+    if (LogonHours->UnitsPerWeek > 0)
+    {
+        BufferLength = (((ULONG)LogonHours->UnitsPerWeek) + 7) / 8;
+
+        Length = BufferLength + sizeof(USHORT);
+
+        RawBuffer = midl_user_allocate(Length);
+        if (RawBuffer == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto done;
+        }
+
+        *((PUSHORT)RawBuffer) = LogonHours->UnitsPerWeek;
+
+        memcpy(&(RawBuffer[2]),
+               LogonHours->LogonHours,
+               BufferLength);
+    }
+
+    Status = SampSetObjectAttribute(UserObject,
+                                    L"LogonHours",
+                                    REG_BINARY,
+                                    RawBuffer,
+                                    Length);
+
+done:
+    if (RawBuffer != NULL)
+        midl_user_free(RawBuffer);
+
+    return Status;
+}
+
 /* EOF */