/*++ Copyright (c) 2001 Microsoft Corporation Module Name: msvlogon.cxx Abstract: logon Author: Larry Zhu (LZhu) December 1, 2001 Created Environment: User Mode Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "msvlogon.hxx" VOID Usage( IN PCSTR pszApp ) { DebugPrintf(SSPI_ERROR, "\n\nUsage: %s [-p] -s -S " "-c -C -k -h -l " "-H -L -w -a\n\n", pszApp); exit(-1); } NTSTATUS GetMsvLogonInfo( IN HANDLE hLogonHandle, IN ULONG PackageId, IN LUID* pLogonId, IN ULONG ParameterControl, IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH], IN UNICODE_STRING* pUserName, IN UNICODE_STRING* pUserDomain, IN UNICODE_STRING* pPassword, IN UNICODE_STRING* pServerName, IN UNICODE_STRING* pServerDomain, IN UNICODE_STRING* pWorkstation, OUT ULONG* pcbLogonInfo, OUT MSV1_0_LM20_LOGON** ppLogonInfo ) { TNtStatus Status; NTSTATUS AuthPackageStatus = STATUS_UNSUCCESSFUL; MSV1_0_GETCHALLENRESP_REQUEST* pRequest = NULL; MSV1_0_GETCHALLENRESP_RESPONSE* pResponse = NULL; ULONG cbResponse = 0; ULONG cbRequest = 0; WCHAR* pWhere = NULL; UNICODE_STRING NtlmServerName = {0}; ULONG cbLogonInfo = 0; MSV1_0_LM20_LOGON* pLogonInfo = NULL; NtlmServerName.Length = (pServerDomain->Length ? pServerDomain->Length + sizeof(WCHAR) : 0) + pServerName->Length; NtlmServerName.MaximumLength = NtlmServerName.Length + sizeof(WCHAR); NtlmServerName.Buffer = (PWSTR) new CHAR[NtlmServerName.MaximumLength]; Status DBGCHK = NtlmServerName.Buffer ? STATUS_SUCCESS : STATUS_NO_MEMORY; if (NT_SUCCESS(Status)) { RtlZeroMemory(NtlmServerName.Buffer, NtlmServerName.MaximumLength); if (pServerDomain->Length) { RtlCopyMemory(NtlmServerName.Buffer, pServerDomain->Buffer, pServerDomain->Length); RtlCopyMemory(NtlmServerName.Buffer + (pServerDomain->Length / sizeof(WCHAR)) + 1, pServerName->Buffer, pServerName->Length); } else { RtlCopyMemory(NtlmServerName.Buffer, pServerName->Buffer, pServerName->Length); } cbRequest = ROUND_UP_COUNT(sizeof(MSV1_0_GETCHALLENRESP_REQUEST), sizeof(ULONG_PTR)) + pUserName->Length + sizeof(WCHAR) + pUserDomain->Length + sizeof(WCHAR) + NtlmServerName.Length + sizeof(WCHAR) + pPassword->Length + sizeof(WCHAR); pRequest = (MSV1_0_GETCHALLENRESP_REQUEST*) new CHAR[cbRequest]; Status DBGCHK = pRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY; } if (NT_SUCCESS(Status)) { RtlZeroMemory(pRequest, cbRequest); pWhere = (WCHAR*) (pRequest + 1); pRequest->MessageType = MsV1_0Lm20GetChallengeResponse; pRequest->ParameterControl = ParameterControl; pRequest->LogonId = *pLogonId; RtlCopyMemory(pRequest->ChallengeToClient, ChallengeToClient, MSV1_0_CHALLENGE_LENGTH); PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, &pRequest->UserName); PackUnicodeStringAsUnicodeStringZ(pUserDomain, &pWhere, &pRequest->LogonDomainName); PackUnicodeStringAsUnicodeStringZ(&NtlmServerName, &pWhere, &pRequest->ServerName); PackUnicodeStringAsUnicodeStringZ(pPassword, &pWhere, &pRequest->Password); DebugPrintf(SSPI_LOG, "MsvLsaLogonUser PackageId %#x, " "UserName %wZ, DomainName %wZ, Password %wZ, " "ParameterControl %#x, LogonId %#x:%#x\n", PackageId, &pRequest->UserName, &pRequest->LogonDomainName, &pRequest->Password, pRequest->ParameterControl, pRequest->LogonId.HighPart, pRequest->LogonId.LowPart); DebugPrintHex(SSPI_LOG, "pRequest->ServerName:", pRequest->ServerName.MaximumLength, pRequest->ServerName.Buffer); DebugPrintHex(SSPI_LOG, "ChallengeToClient:", MSV1_0_CHALLENGE_LENGTH, pRequest->ChallengeToClient); Status DBGCHK = LsaCallAuthenticationPackage( hLogonHandle, PackageId, pRequest, cbRequest, (VOID**) &pResponse, &cbResponse, &AuthPackageStatus ); } if (NT_SUCCESS(Status)) { Status DBGCHK = AuthPackageStatus; } if (NT_SUCCESS(Status)) { DebugPrintf(SSPI_LOG, "GetMsvLogonInfo response LogonDomain %wZ, UserName %wZ\n", pResponse->LogonDomainName, pResponse->UserName); DebugPrintHex(SSPI_LOG, "CaseSensitiveChallengeResponse:", pResponse->CaseSensitiveChallengeResponse.Length, pResponse->CaseSensitiveChallengeResponse.Buffer); DebugPrintHex(SSPI_LOG, "CaseInsensitiveChallengeResponse:", pResponse->CaseInsensitiveChallengeResponse.Length, pResponse->CaseInsensitiveChallengeResponse.Buffer); DebugPrintHex(SSPI_LOG, "UserSessionKey:", MSV1_0_USER_SESSION_KEY_LENGTH, pResponse->UserSessionKey); DebugPrintHex(SSPI_LOG, "LanmanSessionKey:", MSV1_0_USER_SESSION_KEY_LENGTH, pResponse->LanmanSessionKey); cbLogonInfo = ROUND_UP_COUNT(sizeof(MSV1_0_LM20_LOGON), sizeof(ULONG_PTR)) + pUserDomain->Length + sizeof(WCHAR) + pWorkstation->Length + sizeof(WCHAR) + pUserName->Length + sizeof(WCHAR) + pResponse->CaseSensitiveChallengeResponse.Length + sizeof(WCHAR) + pResponse->CaseInsensitiveChallengeResponse.Length + sizeof(WCHAR); pLogonInfo = (MSV1_0_LM20_LOGON*) new CHAR[cbLogonInfo]; Status DBGCHK = pLogonInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY; } if (NT_SUCCESS(Status)) { RtlZeroMemory(pLogonInfo, cbLogonInfo); pLogonInfo->MessageType = MsV1_0NetworkLogon; pLogonInfo->ParameterControl = ParameterControl; RtlCopyMemory(pLogonInfo->ChallengeToClient, ChallengeToClient, MSV1_0_CHALLENGE_LENGTH); pWhere = (PWSTR) (pLogonInfo + 1); PackUnicodeStringAsUnicodeStringZ(pUserDomain, &pWhere, &pLogonInfo->LogonDomainName); PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, &pLogonInfo->UserName); PackUnicodeStringAsUnicodeStringZ(pWorkstation, &pWhere, &pLogonInfo->Workstation); PackString( &pResponse->CaseSensitiveChallengeResponse, (CHAR**) &pWhere, &pLogonInfo->CaseSensitiveChallengeResponse ); PackString( &pResponse->CaseSensitiveChallengeResponse, (CHAR**) &pWhere, &pLogonInfo->CaseSensitiveChallengeResponse ); DebugPrintf(SSPI_LOG, "pLogonInfo ParameterControl %#x, LogonDomain %wZ, UserName %wZ, Workstation %wZ\n", pLogonInfo->ParameterControl, &pLogonInfo->LogonDomainName, &pLogonInfo->UserName, &pLogonInfo->Workstation); DebugPrintHex(SSPI_LOG, "ChallengeToClient:", MSV1_0_CHALLENGE_LENGTH, pLogonInfo->ChallengeToClient); DebugPrintHex(SSPI_LOG, "CaseSensitiveChallengeResponse:", pLogonInfo->CaseSensitiveChallengeResponse.Length, pLogonInfo->CaseSensitiveChallengeResponse.Buffer); DebugPrintHex(SSPI_LOG, "CaseInsensitiveChallengeResponse:", pLogonInfo->CaseInsensitiveChallengeResponse.Length, pLogonInfo->CaseInsensitiveChallengeResponse.Buffer); *ppLogonInfo = pLogonInfo; pLogonInfo = NULL; *pcbLogonInfo = cbLogonInfo; } if (pRequest) { delete [] pRequest; } if (pLogonInfo) { delete [] pLogonInfo; } if (pResponse) { LsaFreeReturnBuffer(pResponse); } return Status; } NTSTATUS MsvLsaLogon( IN HANDLE hLogonHandle, IN ULONG PackageId, IN LUID* pLogonId, IN ULONG ParameterControl, IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH], IN UNICODE_STRING* pUserName, IN UNICODE_STRING* pUserDomain, IN UNICODE_STRING* pPassword, IN UNICODE_STRING* pServerName, IN UNICODE_STRING* pServerDomain, IN UNICODE_STRING* pWorkstation, OUT HANDLE* pTokenHandle ) { TNtStatus Status; NTSTATUS SubStatus = STATUS_UNSUCCESSFUL; MSV1_0_LM20_LOGON* pLogonInfo = NULL; ULONG cbLogonInfoSize = 0; LSA_STRING Name = {0}; TOKEN_SOURCE SourceContext = {0}; VOID* pProfile = NULL; ULONG cbProfileSize = 0; LUID LogonId = {0}; QUOTA_LIMITS Quotas = {0}; Status DBGCHK = GetMsvLogonInfo( hLogonHandle, PackageId, pLogonId, ParameterControl, ChallengeToClient, pUserName, pUserDomain, pPassword, pServerName, pServerDomain, pWorkstation, &cbLogonInfoSize, &pLogonInfo ); if (NT_SUCCESS(Status)) { strncpy( SourceContext.SourceName, "ssptest", sizeof(SourceContext.SourceName) ); NtAllocateLocallyUniqueId(&SourceContext.SourceIdentifier); // // Now call LsaLogonUser // RtlInitString( &Name, "ssptest" ); Status DBGCHK = LsaLogonUser( hLogonHandle, &Name, Network, PackageId, pLogonInfo, cbLogonInfoSize, NULL, // no token groups &SourceContext, (VOID**) &pProfile, &cbProfileSize, &LogonId, pTokenHandle, &Quotas, &SubStatus ); } if (NT_SUCCESS(Status)) { Status DBGCHK = SubStatus; } if (NT_SUCCESS(Status)) { DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", LogonId.HighPart, LogonId.LowPart); DebugPrintf(SSPI_LOG, "TokenHandle %p\n", *pTokenHandle); DebugPrintProfileAndQuotas(SSPI_LOG, pProfile, &Quotas); } if (pProfile) { LsaFreeReturnBuffer(pProfile); } if (pLogonInfo) { delete [] pLogonInfo; } return Status; } VOID __cdecl main( IN INT argc, IN PSTR argv[] ) { TNtStatus Status = STATUS_SUCCESS; UNICODE_STRING UserName = {0}; UNICODE_STRING UserDomain = {0}; UNICODE_STRING Password = {0}; UNICODE_STRING Application = {0}; UNICODE_STRING ServerName = {0}; UNICODE_STRING ServerDomain = {0}; UNICODE_STRING Workstation = {0}; ULONG ParameterControl = 0; LUID LogonId = {0}; LUID ChallengeToClient = {0}; C_ASSERT(MSV1_0_CHALLENGE_LENGTH == sizeof(LUID)); HANDLE hToken = NULL; HANDLE hLogonHandle = NULL; ULONG PackageId = 0; RtlGenRandom(&ChallengeToClient, sizeof(ChallengeToClient)); for (INT i = 1; NT_SUCCESS(Status) && (i < argc); i++) { if ((*argv[i] == '-') || (*argv[i] == '/')) { switch (argv[i][1]) { case 'c': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &UserName); break; case 'C': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &UserDomain); break; case 'a': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &Application); break; case 'k': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &Password); break; case 'p': ParameterControl = strtol(argv[i] + 2, NULL, 0); break; case 'h': LogonId.HighPart = strtol(argv[i] + 2, NULL, 0); break; case 'l': LogonId.LowPart = strtol(argv[i] + 2, NULL, 0); break; case 'H': ChallengeToClient.HighPart = strtol(argv[i] + 2, NULL, 0); break; case 'L': ChallengeToClient.LowPart = strtol(argv[i] + 2, NULL, 0); break; case 's': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ServerName); break; case 'S': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ServerDomain); break; case 'w': Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &Workstation); break; case '?': default: Usage(argv[0]); break; } } else { Usage(argv[0]); } } DebugLogOpen(NULL, SSPI_LOG | SSPI_WARN | SSPI_ERROR); if (NT_SUCCESS(Status)) { Status DBGCHK = GetLsaHandleAndPackageId( NTLMSP_NAME_A, &hLogonHandle, &PackageId ); } if (NT_SUCCESS(Status)) { Status DBGCHK = MsvLsaLogon( hLogonHandle, PackageId, &LogonId, ParameterControl, (UCHAR*) &ChallengeToClient, &UserName, &UserDomain, &Password, &ServerName, &ServerDomain, &Workstation, &hToken ); } if (NT_SUCCESS(Status)) { Status DBGCHK = CheckUserToken(hToken); } if (NT_SUCCESS(Status) && Application.Length && Application.Buffer) { Status DBGCHK = StartInteractiveClientProcessAsUser(hToken, Application.Buffer); } if (NT_SUCCESS(Status)) { DebugPrintf(SSPI_LOG, "Operation succeeded\n"); } else { DebugPrintf(SSPI_ERROR, "Operation failed\n"); } if (hLogonHandle) { LsaDeregisterLogonProcess(hLogonHandle); } if (hToken) { CloseHandle(hToken); } RtlFreeUnicodeString(&UserName); RtlFreeUnicodeString(&UserDomain); RtlFreeUnicodeString(&Password); RtlFreeUnicodeString(&ServerName); RtlFreeUnicodeString(&ServerDomain); RtlFreeUnicodeString(&Application); RtlFreeUnicodeString(&Workstation); }