[LSASRV][MSV1_0]
[reactos.git] / reactos / dll / win32 / msv1_0 / msv1_0.c
index e1fe77c..921aa6f 100644 (file)
@@ -227,22 +227,20 @@ AppendRidToSid(PSID SrcSid,
 {
     PSID DstSid = NULL;
     UCHAR RidCount;
-    ULONG Size;
-    ULONG i;
 
     RidCount = *RtlSubAuthorityCountSid(SrcSid);
     if (RidCount >= 8)
         return NULL;
 
-    Size = RtlLengthRequiredSid(RidCount + 1);
-
-    DstSid = DispatchTable.AllocateLsaHeap(Size);
+    DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
     if (DstSid == NULL)
         return NULL;
 
-    for (i = 0; i < RidCount; i++)
-        *RtlSubAuthoritySid(DstSid, i) = *RtlSubAuthoritySid(SrcSid, i);
+    RtlCopyMemory(DstSid,
+                  SrcSid,
+                  RtlLengthRequiredSid(RidCount));
 
+    *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
     *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
 
     return DstSid;
@@ -256,6 +254,12 @@ BuildTokenUser(OUT PTOKEN_USER User,
 {
     User->User.Sid = AppendRidToSid(AccountDomainSid,
                                     RelativeId);
+    if (User->User.Sid == NULL)
+    {
+        ERR("Could not create the user SID\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
     User->User.Attributes = 0;
 
     return STATUS_SUCCESS;
@@ -536,7 +540,7 @@ BuildTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges)
 
 done:
     if (PolicyHandle != NULL)
-        LsarClose(PolicyHandle);
+        LsarClose(&PolicyHandle);
 
     return Status;
 }
@@ -567,66 +571,6 @@ BuildTokenOwner(PTOKEN_OWNER Owner,
 }
 
 
-static
-NTSTATUS
-BuildTokenDefaultDacl(PTOKEN_DEFAULT_DACL DefaultDacl,
-                      PSID OwnerSid)
-{
-    SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
-    PSID LocalSystemSid = NULL;
-    PACL Dacl = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    RtlAllocateAndInitializeSid(&SystemAuthority,
-                                1,
-                                SECURITY_LOCAL_SYSTEM_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                SECURITY_NULL_RID,
-                                &LocalSystemSid);
-
-    Dacl = DispatchTable.AllocateLsaHeap(1024);
-    if (Dacl == NULL)
-    {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto done;
-    }
-
-    Status = RtlCreateAcl(Dacl, 1024, ACL_REVISION);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
-    RtlAddAccessAllowedAce(Dacl,
-                           ACL_REVISION,
-                           GENERIC_ALL,
-                           OwnerSid);
-
-    /* SID: S-1-5-18 */
-    RtlAddAccessAllowedAce(Dacl,
-                           ACL_REVISION,
-                           GENERIC_ALL,
-                           LocalSystemSid);
-
-    DefaultDacl->DefaultDacl = Dacl;
-
-done:
-    if (!NT_SUCCESS(Status))
-    {
-        if (Dacl != NULL)
-            DispatchTable.FreeLsaHeap(Dacl);
-    }
-
-    if (LocalSystemSid != NULL)
-        RtlFreeSid(LocalSystemSid);
-
-    return Status;
-}
-
-
 static
 NTSTATUS
 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
@@ -679,11 +623,6 @@ BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
     if (!NT_SUCCESS(Status))
         goto done;
 
-    Status = BuildTokenDefaultDacl(&Buffer->DefaultDacl,
-                                   OwnerSid);
-    if (!NT_SUCCESS(Status))
-        goto done;
-
     *TokenInformation = Buffer;
 
 done:
@@ -725,6 +664,131 @@ done:
 }
 
 
+static
+NTSTATUS
+MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
+                   IN PVOID ProtocolSubmitBuffer,
+                   IN PVOID ClientBufferBase,
+                   IN ULONG SubmitBufferLength,
+                   OUT PVOID *ProtocolReturnBuffer,
+                   OUT PULONG ReturnBufferLength,
+                   OUT PNTSTATUS ProtocolStatus)
+{
+    PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
+    ULONG_PTR PtrOffset;
+
+    TRACE("()\n");
+
+    RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
+
+    /* Fix-up pointers in the request buffer info */
+    PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
+
+    RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
+    RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
+    RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
+    RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
+
+    TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
+    TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
+    TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
+    TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
+
+
+    return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+MsvpCheckPassword(PUNICODE_STRING UserPassword,
+                  PSAMPR_USER_INFO_BUFFER UserInfo)
+{
+    ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
+    ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
+    BOOLEAN UserLmPasswordPresent = FALSE;
+    BOOLEAN UserNtPasswordPresent = FALSE;
+    OEM_STRING LmPwdString;
+    CHAR LmPwdBuffer[15];
+    NTSTATUS Status;
+
+    TRACE("(%p %p)\n", UserPassword, UserInfo);
+
+    /* Calculate the LM password and hash for the users password */
+    LmPwdString.Length = 15;
+    LmPwdString.MaximumLength = 15;
+    LmPwdString.Buffer = LmPwdBuffer;
+    ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
+
+    Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
+                                               UserPassword,
+                                               FALSE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Calculate the LM hash value of the users password */
+        Status = SystemFunction006(LmPwdString.Buffer,
+                                   (LPSTR)&UserLmPassword);
+        if (NT_SUCCESS(Status))
+        {
+            UserLmPasswordPresent = TRUE;
+        }
+    }
+
+    /* Calculate the NT hash of the users password */
+    Status = SystemFunction007(UserPassword,
+                               (LPBYTE)&UserNtPassword);
+    if (NT_SUCCESS(Status))
+    {
+        UserNtPasswordPresent = TRUE;
+    }
+
+    Status = STATUS_WRONG_PASSWORD;
+
+    /* Succeed, if no password has been set */
+    if (UserInfo->All.NtPasswordPresent == FALSE &&
+        UserInfo->All.LmPasswordPresent == FALSE)
+    {
+        TRACE("No password check!\n");
+        Status = STATUS_SUCCESS;
+        goto done;
+    }
+
+    /* Succeed, if NT password matches */
+    if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
+    {
+        TRACE("Check NT password hashes:\n");
+        if (RtlEqualMemory(&UserNtPassword,
+                           UserInfo->All.NtOwfPassword.Buffer,
+                           sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+        {
+            TRACE("  success!\n");
+            Status = STATUS_SUCCESS;
+            goto done;
+        }
+
+        TRACE("  failed!\n");
+    }
+
+    /* Succeed, if LM password matches */
+    if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
+    {
+        TRACE("Check LM password hashes:\n");
+        if (RtlEqualMemory(&UserLmPassword,
+                           UserInfo->All.LmOwfPassword.Buffer,
+                           sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+        {
+            TRACE("  success!\n");
+            Status = STATUS_SUCCESS;
+            goto done;
+        }
+        TRACE("  failed!\n");
+    }
+
+done:
+    return Status;
+}
+
+
 /*
  * @unimplemented
  */
@@ -738,8 +802,53 @@ LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
                  OUT PULONG ReturnBufferLength,
                  OUT PNTSTATUS ProtocolStatus)
 {
+    ULONG MessageType;
+    NTSTATUS Status;
+
     TRACE("()\n");
-    return STATUS_NOT_IMPLEMENTED;
+
+    if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
+        return STATUS_INVALID_PARAMETER;
+
+    MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
+
+    *ProtocolReturnBuffer = NULL;
+    *ReturnBufferLength = 0;
+
+    switch (MessageType)
+    {
+        case MsV1_0Lm20ChallengeRequest:
+        case MsV1_0Lm20GetChallengeResponse:
+        case MsV1_0EnumerateUsers:
+        case MsV1_0GetUserInfo:
+        case MsV1_0ReLogonUsers:
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+
+        case MsV1_0ChangePassword:
+            Status = MsvpChangePassword(ClientRequest,
+                                        ProtocolSubmitBuffer,
+                                        ClientBufferBase,
+                                        SubmitBufferLength,
+                                        ProtocolReturnBuffer,
+                                        ReturnBufferLength,
+                                        ProtocolStatus);
+            break;
+
+        case MsV1_0ChangeCachedPassword:
+        case MsV1_0GenericPassthrough:
+        case MsV1_0CacheLogon:
+        case MsV1_0SubAuth:
+        case MsV1_0DeriveCredential:
+        case MsV1_0CacheLookup:
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+
+        default:
+            return STATUS_INVALID_PARAMETER;
+    }
+
+    return Status;
 }
 
 
@@ -798,6 +907,11 @@ LsaApInitializePackage(IN ULONG AuthenticationPackageId,
           Confidentiality, AuthenticationPackageName);
 
     /* Get the dispatch table entries */
+    DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
+    DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
+    DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
+    DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
+    DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
     DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
     DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
     DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
@@ -805,7 +919,6 @@ LsaApInitializePackage(IN ULONG AuthenticationPackageId,
     DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
     DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
 
-
     /* Return the package name */
     NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
     if (NameString == NULL)
@@ -869,6 +982,7 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
     SAMPR_ULONG_ARRAY Use = {0, NULL};
     PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
     UNICODE_STRING LogonServer;
+    BOOLEAN SessionCreated = FALSE;
     NTSTATUS Status;
 
     TRACE("()\n");
@@ -877,7 +991,6 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
     TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
     TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
 
-
     *ProfileBuffer = NULL;
     *ProfileBufferLength = 0;
     *SubStatus = STATUS_SUCCESS;
@@ -893,9 +1006,9 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
         /* Fix-up pointers in the authentication info */
         PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;
 
-        LogonInfo->LogonDomainName.Buffer = (PWSTR)((ULONG_PTR)LogonInfo->LogonDomainName.Buffer + PtrOffset);
-        LogonInfo->UserName.Buffer = (PWSTR)((ULONG_PTR)LogonInfo->UserName.Buffer + PtrOffset);
-        LogonInfo->Password.Buffer = (PWSTR)((ULONG_PTR)LogonInfo->Password.Buffer + PtrOffset);
+        LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
+        LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
+        LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
 
         TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
         TRACE("User: %S\n", LogonInfo->UserName.Buffer);
@@ -989,11 +1102,16 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
 
     /* FIXME: Check restrictions */
 
-    /* FIXME: Check the password */
+    /* Check the password */
     if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
     {
-        FIXME("Must check the password!\n");
-
+        Status = MsvpCheckPassword(&(LogonInfo->Password),
+                                   UserInfo);
+        if (!NT_SUCCESS(Status))
+        {
+            TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
+            goto done;
+        }
     }
 
     /* Return logon information */
@@ -1006,6 +1124,16 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
         goto done;
     }
 
+    /* Create the logon session */
+    Status = DispatchTable.CreateLogonSession(LogonId);
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
+        goto done;
+    }
+
+    SessionCreated = TRUE;
+
     /* Build and fill the interactve profile buffer */
     Status = BuildInteractiveProfileBuffer(ClientRequest,
                                            UserInfo,
@@ -1032,8 +1160,6 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
         goto done;
     }
 
-    *SubStatus = STATUS_SUCCESS;
-
 done:
     /* Return the account name */
     *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
@@ -1051,6 +1177,9 @@ done:
 
     if (!NT_SUCCESS(Status))
     {
+        if (SessionCreated == TRUE)
+            DispatchTable.DeleteLogonSession(LogonId);
+
         if (*ProfileBuffer != NULL)
         {
             DispatchTable.FreeClientBuffer(ClientRequest,
@@ -1076,6 +1205,13 @@ done:
     if (AccountDomainSid != NULL)
         RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
 
+    if (Status == STATUS_NO_SUCH_USER ||
+        Status == STATUS_WRONG_PASSWORD)
+    {
+        *SubStatus = Status;
+        Status = STATUS_LOGON_FAILURE;
+    }
+
     TRACE("LsaApLogonUser done (Status %08lx)\n", Status);
 
     return Status;
@@ -1085,6 +1221,7 @@ done:
 /*
  * @unimplemented
  */
+#if 0
 NTSTATUS
 NTAPI
 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
@@ -1143,5 +1280,6 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
 
     return STATUS_NOT_IMPLEMENTED;
 }
+#endif
 
 /* EOF */