[MSV1_0]
[reactos.git] / reactos / dll / win32 / msv1_0 / msv1_0.c
index 175014e..def4006 100644 (file)
@@ -729,6 +729,118 @@ done:
 }
 
 
+static
+NTSTATUS
+ChangePassword(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 = (PWSTR)((ULONG_PTR)RequestBuffer->DomainName.Buffer + PtrOffset);
+    RequestBuffer->AccountName.Buffer = (PWSTR)((ULONG_PTR)RequestBuffer->AccountName.Buffer + PtrOffset);
+    RequestBuffer->OldPassword.Buffer = (PWSTR)((ULONG_PTR)RequestBuffer->OldPassword.Buffer + PtrOffset);
+    RequestBuffer->NewPassword.Buffer = (PWSTR)((ULONG_PTR)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_SUCCESS;
+
+    if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
+    {
+        TRACE("Check NT password hashes:\n");
+        if (!RtlEqualMemory(&UserNtPassword,
+                            UserInfo->All.NtOwfPassword.Buffer,
+                            sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+        {
+            TRACE("  failed!\n");
+            Status = STATUS_WRONG_PASSWORD;
+        }
+    }
+    else if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
+    {
+        TRACE("Check LM password hashes:\n");
+        if (!RtlEqualMemory(&UserLmPassword,
+                            UserInfo->All.LmOwfPassword.Buffer,
+                            sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+        {
+            TRACE("  failed!\n");
+            Status = STATUS_WRONG_PASSWORD;
+        }
+    }
+    else
+    {
+        TRACE("No matching hashes available!\n");
+        Status = STATUS_WRONG_PASSWORD;
+    }
+
+    return Status;
+}
+
+
 /*
  * @unimplemented
  */
@@ -742,8 +854,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 = ChangePassword(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;
 }
 
 
@@ -802,6 +959,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;
@@ -809,7 +971,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)
@@ -873,6 +1034,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");
@@ -881,7 +1043,6 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
     TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
     TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
 
-
     *ProfileBuffer = NULL;
     *ProfileBufferLength = 0;
     *SubStatus = STATUS_SUCCESS;
@@ -897,9 +1058,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);
@@ -993,11 +1154,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 */
@@ -1010,6 +1176,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,
@@ -1036,8 +1212,6 @@ LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
         goto done;
     }
 
-    *SubStatus = STATUS_SUCCESS;
-
 done:
     /* Return the account name */
     *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
@@ -1055,6 +1229,9 @@ done:
 
     if (!NT_SUCCESS(Status))
     {
+        if (SessionCreated == TRUE)
+            DispatchTable.DeleteLogonSession(LogonId);
+
         if (*ProfileBuffer != NULL)
         {
             DispatchTable.FreeClientBuffer(ClientRequest,
@@ -1080,6 +1257,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;
@@ -1089,6 +1273,7 @@ done:
 /*
  * @unimplemented
  */
+#if 0
 NTSTATUS
 NTAPI
 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
@@ -1147,5 +1332,6 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
 
     return STATUS_NOT_IMPLEMENTED;
 }
+#endif
 
 /* EOF */