Пример #1
0
bool getLogonData(mod_pipe * monPipe, vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders)
{
	bool sendOk = true;
	PLUID sessions;
	ULONG count;

	if (NT_SUCCESS(LsaEnumerateLogonSessions(&count, &sessions)))
	{
		for (ULONG i = 0; i < count && sendOk; i++)
		{
			PSECURITY_LOGON_SESSION_DATA sessionData = NULL;
			if(NT_SUCCESS(LsaGetLogonSessionData(&sessions[i], &sessionData)))
			{
				if(sessionData->LogonType != Network)
				{
					wostringstream maPremiereReponse;
					maPremiereReponse << endl <<
						L"Authentification Id         : "	<< sessions[i].HighPart << L";" << sessions[i].LowPart << endl <<
						L"Package d\'authentification  : "	<< mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << endl <<
						L"Utilisateur principal       : "	<< mod_text::stringOfSTRING(sessionData->UserName) << endl <<
						L"Domaine d\'authentification  : "	<< mod_text::stringOfSTRING(sessionData->LogonDomain) << endl;

					sendOk = sendTo(monPipe, maPremiereReponse.str());

					for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++)
					{
						wostringstream maSecondeReponse;
						maSecondeReponse << L'\t' << monProvider->second << L" : \t";
						sendOk = sendTo(monPipe, maSecondeReponse.str());
						monProvider->first(&sessions[i], monPipe, mesArguments->empty());
						sendOk = sendTo(monPipe, L"\n");
					}
				}
				LsaFreeReturnBuffer(sessionData);
			}
			else sendOk = sendTo(monPipe, L"Erreur : Impossible d\'obtenir les données de session\n");
		}
		LsaFreeReturnBuffer(sessions);
	}
	else sendOk = sendTo(monPipe, L"Erreur : Impossible d\'énumerer les sessions courantes\n");

	return sendOk;
}
Пример #2
0
bool mod_mimikatz_sekurlsa::getLogonData(vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders)
{
	PLUID sessions;
	ULONG count;

	if (NT_SUCCESS(LsaEnumerateLogonSessions(&count, &sessions)))
	{
		for (ULONG i = 0; i < count ; i++)
		{
			PSECURITY_LOGON_SESSION_DATA sessionData = NULL;
			if(NT_SUCCESS(LsaGetLogonSessionData(&sessions[i], &sessionData)))
			{
				if(sessionData->LogonType != Network)
				{
					(*outputStream) << "\"" <<
						sessions[i].HighPart << L";" << sessions[i].LowPart << L"\",\"" <<
						mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << L"\",\"" <<
						mod_text::stringOfSTRING(sessionData->UserName) << L"\",\"" <<
						mod_text::stringOfSTRING(sessionData->LogonDomain) << L"\",\"";

					for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++)
					{
						monProvider->first(&sessions[i], mesArguments->empty());
						(*outputStream) << L"\"" << endl;
					}
				}
				LsaFreeReturnBuffer(sessionData);
			}
			else (*outputStream) << L"Erreur : Impossible d\'obtenir les données de session" << endl;
		}
		LsaFreeReturnBuffer(sessions);
	}
	else (*outputStream) << L"Erreur : Impossible d\'énumerer les sessions courantes" << endl;

	return true;
}
Пример #3
0
NTSTATUS kuhl_m_kerberos_tgt(int argc, wchar_t * argv[])
{
	NTSTATUS status, packageStatus;
	KERB_RETRIEVE_TKT_REQUEST kerbRetrieveRequest = {KerbRetrieveTicketMessage, {0, 0}, {0, 0, NULL}, 0, 0, KERB_ETYPE_NULL, {0, 0}};
	PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse;
	DWORD szData;
	KIWI_KERBEROS_TICKET kiwiTicket = {0};
	DWORD i;
	BOOL isNull = FALSE;

	status = LsaCallKerberosPackage(&kerbRetrieveRequest, sizeof(KERB_RETRIEVE_TKT_REQUEST), (PVOID *) &pKerbRetrieveResponse, &szData, &packageStatus);
	kprintf(L"Kerberos TGT of current session : ");
	if(NT_SUCCESS(status))
	{
		if(NT_SUCCESS(packageStatus))
		{
			kiwiTicket.ServiceName = pKerbRetrieveResponse->Ticket.ServiceName;
			kiwiTicket.TargetName = pKerbRetrieveResponse->Ticket.TargetName;
			kiwiTicket.ClientName = pKerbRetrieveResponse->Ticket.ClientName;
			kiwiTicket.DomainName = pKerbRetrieveResponse->Ticket.DomainName;
			kiwiTicket.TargetDomainName = pKerbRetrieveResponse->Ticket.TargetDomainName;
			kiwiTicket.AltTargetDomainName = pKerbRetrieveResponse->Ticket.AltTargetDomainName;
			kiwiTicket.TicketFlags = pKerbRetrieveResponse->Ticket.TicketFlags;
			kiwiTicket.KeyType = kiwiTicket.TicketEncType = pKerbRetrieveResponse->Ticket.SessionKey.KeyType; // TicketEncType not in response
			kiwiTicket.Key.Length = pKerbRetrieveResponse->Ticket.SessionKey.Length;
			kiwiTicket.Key.Value = pKerbRetrieveResponse->Ticket.SessionKey.Value;
			kiwiTicket.StartTime = *(PFILETIME) &pKerbRetrieveResponse->Ticket.StartTime;
			kiwiTicket.EndTime = *(PFILETIME) &pKerbRetrieveResponse->Ticket.EndTime;
			kiwiTicket.RenewUntil = *(PFILETIME) &pKerbRetrieveResponse->Ticket.RenewUntil;
			kiwiTicket.Ticket.Length = pKerbRetrieveResponse->Ticket.EncodedTicketSize;
			kiwiTicket.Ticket.Value = pKerbRetrieveResponse->Ticket.EncodedTicket;
			kuhl_m_kerberos_ticket_display(&kiwiTicket, FALSE);
			
			for(i = 0; !isNull && (i < kiwiTicket.Ticket.Length); i++);
				isNull |= !kiwiTicket.Ticket.Value[i];
			if(isNull)
				kprintf(L"\n\n\t** Session key is NULL! It means allowtgtsessionkey is not set to 1 **\n");

			LsaFreeReturnBuffer(pKerbRetrieveResponse);
		}
		else if(packageStatus == SEC_E_NO_CREDENTIALS)
			kprintf(L"no ticket !\n");
		else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveTicketMessage / Package : %08x\n", packageStatus);
	}
	else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveTicketMessage : %08x\n", status);

	return STATUS_SUCCESS;
}
Пример #4
0
NTSTATUS kuhl_m_kerberos_list(int argc, wchar_t * argv[])
{
	NTSTATUS status, packageStatus;
	KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = {KerbQueryTicketCacheExMessage, {0, 0}};
	PKERB_QUERY_TKT_CACHE_EX_RESPONSE pKerbCacheResponse;
	PKERB_RETRIEVE_TKT_REQUEST pKerbRetrieveRequest;
	PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse;
	DWORD szData, i;
	wchar_t * filename;
	BOOL export = kull_m_string_args_byName(argc, argv, L"export", NULL, NULL);

	status = LsaCallKerberosPackage(&kerbCacheRequest, sizeof(KERB_QUERY_TKT_CACHE_REQUEST), (PVOID *) &pKerbCacheResponse, &szData, &packageStatus);
	if(NT_SUCCESS(status))
	{
		if(NT_SUCCESS(packageStatus))
		{
			for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++)
			{
				kprintf(L"\n[%08x] - 0x%08x - %s", i, pKerbCacheResponse->Tickets[i].EncryptionType, kuhl_m_kerberos_ticket_etype(pKerbCacheResponse->Tickets[i].EncryptionType));
				kprintf(L"\n   Start/End/MaxRenew: ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].StartTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].EndTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].RenewTime);
				kprintf(L"\n   Server Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ServerName, &pKerbCacheResponse->Tickets[i].ServerRealm);
				kprintf(L"\n   Client Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ClientName, &pKerbCacheResponse->Tickets[i].ClientRealm);
				kprintf(L"\n   Flags %08x    : ", pKerbCacheResponse->Tickets[i].TicketFlags);
				kuhl_m_kerberos_ticket_displayFlags(pKerbCacheResponse->Tickets[i].TicketFlags);
			
				if(export)
				{
					szData = sizeof(KERB_RETRIEVE_TKT_REQUEST) + pKerbCacheResponse->Tickets[i].ServerName.MaximumLength;
					if(pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LPTR, szData)) // LPTR implicates KERB_ETYPE_NULL
					{
						pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
						pKerbRetrieveRequest->CacheOptions = /*KERB_RETRIEVE_TICKET_USE_CACHE_ONLY | */KERB_RETRIEVE_TICKET_AS_KERB_CRED;
						pKerbRetrieveRequest->TicketFlags = pKerbCacheResponse->Tickets[i].TicketFlags;
						pKerbRetrieveRequest->TargetName = pKerbCacheResponse->Tickets[i].ServerName;
						pKerbRetrieveRequest->TargetName.Buffer = (PWSTR) ((PBYTE) pKerbRetrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST));
						RtlCopyMemory(pKerbRetrieveRequest->TargetName.Buffer, pKerbCacheResponse->Tickets[i].ServerName.Buffer, pKerbRetrieveRequest->TargetName.MaximumLength);

						status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *) &pKerbRetrieveResponse, &szData, &packageStatus);
						if(NT_SUCCESS(status))
						{
							if(NT_SUCCESS(packageStatus))
							{
								if(filename = kuhl_m_kerberos_generateFileName(i, &pKerbCacheResponse->Tickets[i], MIMIKATZ_KERBEROS_EXT))
								{
									if(kull_m_file_writeData(filename, pKerbRetrieveResponse->Ticket.EncodedTicket, pKerbRetrieveResponse->Ticket.EncodedTicketSize))
										kprintf(L"\n   * Saved to file     : %s", filename);
									LocalFree(filename);
								}
								LsaFreeReturnBuffer(pKerbRetrieveResponse);
							}
							else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage / Package : %08x\n", packageStatus);
						}
						else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbRetrieveEncodedTicketMessage : %08x\n", status);

						LocalFree(pKerbRetrieveRequest);
					}
				}
				kprintf(L"\n");
			}
			LsaFreeReturnBuffer(pKerbCacheResponse);
		}
		else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message / Package : %08x\n", packageStatus);
	}
Пример #5
0
int LookupAccountPwd() {

	int nRet = -1;

	if (m_bNoisy) {
		msg_print("Reading by injecting code! (less-safe mode)\n");
	}

	DWORD dwLSASRV_dll = FindLSASRV_dll(), dwWDIGEST_dll = 0;

	OSVERSIONINFOA sysVersion;
	sysVersion.dwOSVersionInfoSize = sizeof(sysVersion);
	GetVersionExA(&sysVersion);

	if ((sysVersion.dwMajorVersion < 6) && (
		(sysVersion.dwMajorVersion != 5) || (sysVersion.dwMinorVersion != 2))) {
			dwWDIGEST_dll = FindWDIGEST_dll();
	}
	else {
		dwWDIGEST_dll = FindWDIGEST_dll_2();
	}

	if (!dwLSASRV_dll || !dwWDIGEST_dll) {
		msg_print("ERROR: Cannot find dependencies\n");
		return nRet;
	}

	DWORD dwProcessId = GetProcessIdByName(L"lsass.exe");
	if (!dwProcessId) {
		msg_print("Cannot get PID of LSASS.EXE!\n");
		exit(0);
	}

	HANDLE hLSASS = OpenProcess(PROCESS_ALL_ACCESS, 0, dwProcessId);
	if (hLSASS == INVALID_HANDLE_VALUE) {
		msg_print("Error: Cannot open LSASS.EXE!.\n");
		exit(0);
	}

	ULONG nLogonSessionCount = 0;
	PLUID pLogonSessionList = NULL; 
	NTSTATUS status = LsaEnumerateLogonSessions(&nLogonSessionCount, &pLogonSessionList);
	if (!NT_SUCCESS(status)) {
		msg_print("Can't enumerate logon sessions!\n");
		exit(0);
	}

	if (m_bNoisy) {
		msg_print("Logon Sessions Found: %d\n", nLogonSessionCount);
	}

	REMOTE_PARAM_T *remp = (REMOTE_PARAM_T *)malloc(sizeof(REMOTE_PARAM_T));
	if (!remp) {
		msg_print("Cannot alloc wcewdparams!.");
		exit(0);
	}

	INPUT_PARAM_T inpt;
	strcpy(inpt.FuncName, "_0212DBDHJKSAHD0183923kljmLKL");
	inpt.pParam = remp;
	inpt.paramSize = sizeof(REMOTE_PARAM_T);

	char szInjectDll[1024] = {0};	
	::GetCurrentDirectoryA(1022, szInjectDll);
	::PathAppendA(szInjectDll, "getpwd_dll.dll");

	for (ULONG i = 0; i < nLogonSessionCount; ++i) {

		memset(remp, 0, sizeof(REMOTE_PARAM_T));

		remp->dwDecryptAddr = dwLSASRV_dll;
		remp->dwLogonSessionEntry = dwWDIGEST_dll;

		remp->Retn = 0;
		remp->LogonId.LowPart = pLogonSessionList[i].LowPart;
		remp->LogonId.HighPart = pLogonSessionList[i].HighPart;

		if (GetUserPassword(dwProcessId, szInjectDll, &inpt)) {

			if (remp->Retn == 1) {

				msg_print("ID: %d\nAccout: %s\nDomain: %s\nPassword: "******"%s\n", remp->szPassword);
				}
				else {
					msg_print("<contains-non-printable-chars>");
				}			
			}
		}
		else {
			msg_print("Error in InjectDllAndCallFunction\n");
		}
	}

	free(remp);

	LsaFreeReturnBuffer(pLogonSessionList);
	return 0;
}
Пример #6
0
DWORD 
GetEncodedTicket(
    HANDLE LogonHandle,
    ULONG PackageId,
    wchar_t *Server
    )
{
    NTSTATUS Status;
    PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL;
    PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL;
    PKERB_EXTERNAL_TICKET Ticket;
    ULONG ResponseSize;
    NTSTATUS SubStatus;
    BOOLEAN Trusted = TRUE;
    BOOLEAN Success = FALSE;
    UNICODE_STRING Target = {0}; 
    UNICODE_STRING Target2 = {0};

    InitUnicodeString( &Target2, Server);

    CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST)
            LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));

    CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage ;
    CacheRequest->LogonId.LowPart = 0;
    CacheRequest->LogonId.HighPart = 0;

 
    Target.Buffer = (LPWSTR) (CacheRequest + 1);
    Target.Length = Target2.Length;
    Target.MaximumLength = Target2.MaximumLength;

    CopyMemory(
        Target.Buffer,
        Target2.Buffer,
        Target2.Length
        );

    CacheRequest->TargetName = Target;

    Status = LsaCallAuthenticationPackage(
                LogonHandle,
                PackageId,
                CacheRequest,
                Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST),
                (PVOID *) &CacheResponse,
                &ResponseSize,
                &SubStatus
                );

    if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
    {
        ShowNTError("LsaCallAuthenticationPackage", Status);
        printf("Substatus: 0x%x\n",SubStatus);
        ShowNTError("Substatus:", SubStatus);

    }
    else
    {
        Ticket = &(CacheResponse->Ticket);

        printf("\nEncoded Ticket:\n\n");

        printf("ServiceName: "); PrintKerbName(Ticket->ServiceName);

        printf("TargetName: "); PrintKerbName(Ticket->TargetName);

        printf("ClientName: "); PrintKerbName(Ticket->ClientName);
        
        printf("DomainName: %.*S\n",
            Ticket->DomainName.Length/sizeof(WCHAR),Ticket->DomainName.Buffer);

        printf("TargetDomainName: %.*S\n",
            Ticket->TargetDomainName.Length/sizeof(WCHAR),Ticket->TargetDomainName.Buffer);

        printf("AltTargetDomainName: %.*S\n",
            Ticket->AltTargetDomainName.Length/sizeof(WCHAR),Ticket->AltTargetDomainName.Buffer);

        printf("TicketFlags: (0x%x) ",Ticket->TicketFlags);
        PrintTktFlags(Ticket->TicketFlags);
        PrintTime("KeyExpirationTime: ",Ticket->KeyExpirationTime);
        PrintTime("StartTime: ",Ticket->StartTime);
        PrintTime("EndTime: ",Ticket->EndTime);
        PrintTime("RenewUntil: ",Ticket->RenewUntil);
        PrintTime("TimeSkew: ",Ticket->TimeSkew);
        PrintEType(Ticket->SessionKey.KeyType);

        Success = TRUE;
        
    }

    if (CacheResponse)
    {
        LsaFreeReturnBuffer(CacheResponse);
    }
    if (CacheRequest)
    {
        LocalFree(CacheRequest);
    }

    return Success;
}
Пример #7
0
VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
{
#ifdef USE_WINLOGON_EVENT
    WCHAR szUserW[128] = L"";
    char  szUserA[128] = "";
    char szPath[MAX_PATH] = "";
    char szLogonId[128] = "";
    DWORD count;
    char filename[MAX_PATH] = "";
    char newfilename[MAX_PATH] = "";
    char commandline[MAX_PATH+256] = "";
    STARTUPINFO startupinfo;
    PROCESS_INFORMATION procinfo;
    HANDLE hf = NULL;

    LUID LogonId = {0, 0};
    PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;

    HKEY hKey1 = NULL, hKey2 = NULL;

    DebugEvent0("KFW_Logon_Event - Start");

    GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );

    if ( pLogonSessionData ) {
        LogonId = pLogonSessionData->LogonId;
        DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);

        _snprintf(szLogonId, sizeof(szLogonId), "kfwlogon-%d.%d",LogonId.HighPart, LogonId.LowPart);
        LsaFreeReturnBuffer( pLogonSessionData );
    } else {
        DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
        return;
    }

    count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
    if ( count > sizeof(filename) || count == 0 ) {
        GetWindowsDirectory(filename, sizeof(filename));
    }

    if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
        DebugEvent0("KFW_Logon_Event - filename too long");
	return;
    }

    strcat(filename, "\\");
    strcat(filename, szLogonId);    

    hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 
		    FILE_ATTRIBUTE_NORMAL, NULL);
    if (hf == INVALID_HANDLE_VALUE) {
        DebugEvent0("KFW_Logon_Event - file cannot be opened");
	return;
    }
    CloseHandle(hf);

    if (KFW_set_ccache_dacl(filename, pInfo->hToken)) {
        DebugEvent0("KFW_Logon_Event - unable to set dacl");
	DeleteFile(filename);
	return;
    }

    if (KFW_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
        DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
	return;
    }

    if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
        DebugEvent0("KFW_Logon_Event - new filename too long");
	return;
    }

    strcat(newfilename, "\\");
    strcat(newfilename, szLogonId);    

    if (!MoveFileEx(filename, newfilename, 
		     MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
        DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
	return;
    }

    _snprintf(commandline, sizeof(commandline), "kfwcpcc.exe \"%s\"", newfilename);

    GetStartupInfo(&startupinfo);
    if (CreateProcessAsUser( pInfo->hToken,
                             "kfwcpcc.exe",
                             commandline,
                             NULL,
                             NULL,
                             FALSE,
                             CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
                             NULL,
                             NULL,
                             &startupinfo,
                             &procinfo)) 
    {
	DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);

	WaitForSingleObject(procinfo.hProcess, 30000);

	CloseHandle(procinfo.hThread);
	CloseHandle(procinfo.hProcess);
    } else {
	DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
    }

    DeleteFile(newfilename);

    DebugEvent0("KFW_Logon_Event - End");
#endif /* USE_WINLOGON_EVENT */
}
Пример #8
0
int LsaLogon(HANDLE *hToken, char homeDir[MAX_PATH], char *user, 
                 char *pkBlob, int pkBlobSize, char *sign, int signSize, 
                     char *data, int dataSize, int dataFellow)
{
  int exitCode = 1;
  
  NTSTATUS ntStat = 0;
  
  LSA_STRING logonProcName;
  LSA_STRING originName;
  LSA_STRING authPckgName;
  
  HANDLE hLsa = NULL;
  
  LSA_OPERATIONAL_MODE securityMode;
  
  /*
   * Impersonation, "weak" token returned from network logon.
   * We can't create process as other user via this token.
   */
  
  HANDLE hWeakToken = NULL;
  
  /*
   * Login data.
   */
  
  LsaAuth *lsaAuth = NULL;

  ULONG lsaAuthSize = 0;

  ULONG authPckgId  = 0;
  
  TOKEN_SOURCE srcToken;
  
  PVOID profile = NULL;

  ULONG profileSize;
  
  LUID  logonId;
  
  QUOTA_LIMITS quotas;
  
  NTSTATUS loginStat;
  

  debug("-> LsaLogon()...");

  /*
   * We check only hToken arg, becouse other args are tested in AllocLsaAuth().
   */
  
  debug("Checking args...");
  
  FAIL(hToken == NULL);
  
  /*
   * Setup lsa strings.
   */

  debug("Setting up LSA Strings...");
  
  FAIL(InitLsaString(&logonProcName, "sshd-logon"));
  FAIL(InitLsaString(&originName, "NTLM"));
  FAIL(InitLsaString(&authPckgName, "SSH-LSA"));

  /*
   * Enable needed privilege to current running process.
   */

  EnablePrivilege("SeTcbPrivilege", 1);
  
  /*
   * Register new logon process.
   */
  
  debug("LsaRegisterLogonProcess()...");

  NTFAIL(LsaRegisterLogonProcess(&logonProcName, &hLsa, &securityMode));
  
  /*
   * Retrieve Authenticated Package ID.
   */
  
  debug("Retrieving Authentification Package ID...");
  
  NTFAIL(LsaLookupAuthenticationPackage(hLsa, &authPckgName, &authPckgId));
  
  /*
   * Allocate LsaAuth struct.
   */

  debug("Allocating LsaAuth struct...");
  
  FAIL(AllocLsaAuth(&lsaAuth, user, pkBlob, pkBlobSize,
                       sign, signSize, data, dataSize, dataFellow));
                       
  lsaAuthSize = lsaAuth -> totalSize_;                       

  /*
   * Create TOKEN_SOURCE part
   */
  
  debug("Setting up TOKEN_SOURCE...");
  
  FAIL(AllocateLocallyUniqueId(&srcToken.SourceIdentifier) == FALSE);
  
  memcpy(srcToken.SourceName, "**sshd**", 8);

  /*
   * Try to login using LsaAuth struct.
   */

  debug("Login attemp...");
  
  NTFAIL(LsaLogonUser(hLsa, &originName, Network,
                          authPckgId, lsaAuth, lsaAuthSize, NULL,
                              &srcToken, &profile, &profileSize,
                                  &logonId, &hWeakToken, &quotas, &loginStat));

  debug("login status: %x...", loginStat);
  
  
  //FAIL(WideCharToMultiByte( CP_UTF8, 0, profile, -1, homeDir, MAX_PATH, NULL, NULL)==0);
  //memcpy(homeDir, profile, MAX_PATH*sizeof(wchar_t));

  lstrcpyW(homeDir, profile);
  
  debug("homedir = [%ls]", (char *) homeDir);

  //strcpy(homeDir, profile);
  
  //PrintToken(hToken);
  
  /*
   * Duplicate 'weak' impersonation token into Primary Key token.
   * We can create process using duplicated token.
   */
  
  debug("Duplicating token...");
  
  FAIL(DuplicateTokenEx(hWeakToken, MAXIMUM_ALLOWED,
                            NULL, SecurityImpersonation,
                                TokenPrimary, hToken) == 0);
  
  exitCode = 0;
  
fail:

  if (exitCode)
  {
    switch(ntStat)
    {
      case STATUS_LOGON_FAILURE:
      {
        debug("SSH-LSA authorization failed. " 
                  "(err = %u, ntStat = %x).", GetLastError(), ntStat);

        exitCode = 0;

        break;
      }
      
      case STATUS_NO_SUCH_PACKAGE:
      {
        debug("SSH-LSA package not found. "
                  "(err = %u, ntStat = %x).", GetLastError(), ntStat);
                  
        break;          
      }
      
      default:
      {
        debug("Cannot logon using LSA package (err = %u, ntStat = %x).",
                  GetLastError(), ntStat);
      }
    }        
            
    hToken = NULL;
  }
  else
  {
    debug("LsaLogon : OK.");
  }

  /*
   * Clean up.
   */
  
  CloseHandle(hWeakToken);
  
  LsaFreeReturnBuffer(profile);
   
  EnablePrivilege("SeTcbPrivilege", 0);
  
  LsaDeregisterLogonProcess(hLsa);
  
  ClearLsaString(&logonProcName);
  ClearLsaString(&originName);
  ClearLsaString(&authPckgName);
         
  debug("<- LsaLogon()...");
  
  return exitCode;
}
Пример #9
0
STATIC
NET_API_STATUS
WsGetSystemInfo(
    IN  DWORD Level,
    OUT LPBYTE *BufferPointer
    )

/*++

Routine Description:

    This function calls the Redirector FSD, the LSA subsystem and the
    MSV1_0 authentication package, and the Datagram Receiver DD to get
    the system wide information returned by NetWkstaGetInfo API.

Arguments:

    Level - Supplies the requested level of information.

    BufferPointer - Returns a pointer to a buffer which contains the
        requested workstation information.


Return Value:

    NET_API_STATUS - NERR_Success or reason for failure.

--*/
{
    NET_API_STATUS status;
    DWORD NumberOfLoggedOnUsers = 1;

    //
    // Get number of logged on users from the MSV1_0 authentication package
    // if Level == 102.
    //
    if (Level == 102) {

        PMSV1_0_ENUMUSERS_RESPONSE EnumUsersResponse;

        //
        // Ask authentication package to enumerate users who are physically
        // logged to the local machine.
        //
        if ((status = WsLsaEnumUsers(
                          (LPBYTE *) &EnumUsersResponse
                          )) != NERR_Success) {
            return status;
        }

        NumberOfLoggedOnUsers = EnumUsersResponse->NumberOfLoggedOnUsers;

        (VOID) LsaFreeReturnBuffer(EnumUsersResponse);
    }

    //
    // Put all the data collected into output buffer allocated by this routine.
    //
    return WsFillSystemBufferInfo(
               Level,
               NumberOfLoggedOnUsers,
               BufferPointer
               );
}
Пример #10
0
SECURITY_STATUS SEC_ENTRY
AcceptSecurityContext(
    PCredHandle                 phCredential,       // Cred to base context
    PCtxtHandle                 phContext,          // Existing context (OPT)
    PSecBufferDesc              pInput,             // Input buffer
    unsigned long               fContextReq,        // Context Requirements
    unsigned long               TargetDataRep,      // Target Data Rep
    PCtxtHandle                 phNewContext,       // (out) New context handle
    PSecBufferDesc              pOutput,            // (inout) Output buffers
    unsigned long SEC_FAR *     pfContextAttr,      // (out) Context attributes
    PTimeStamp                  ptsExpiry           // (out) Life span (OPT)
    )
{
    SECURITY_STATUS scRet;
    NTSTATUS SubStatus;
    PAUTHENTICATE_MESSAGE AuthenticateMessage;
    ULONG AuthenticateMessageSize;
    PNTLM_AUTHENTICATE_MESSAGE NtlmAuthenticateMessage;
    ULONG NtlmAuthenticateMessageSize;
    PNTLM_ACCEPT_RESPONSE NtlmAcceptResponse = NULL;
    PMSV1_0_LM20_LOGON LogonBuffer = NULL;
    ULONG LogonBufferSize;
    PMSV1_0_LM20_LOGON_PROFILE LogonProfile = NULL;
    ULONG LogonProfileSize;
    PSecBuffer AcceptResponseToken = NULL;
    PClient Client = NULL;
    ANSI_STRING SourceName;
    LUID LogonId;
    LUID UNALIGNED * TempLogonId;
    LARGE_INTEGER UNALIGNED * TempKickoffTime;
    HANDLE TokenHandle = NULL;
    QUOTA_LIMITS Quotas;
    PUCHAR Where;
    STRING DomainName;
    STRING UserName;
    STRING Workstation;
    STRING NtChallengeResponse;
    STRING LmChallengeResponse;
    ULONG EffectivePackageId;


    RtlInitString(
        &SourceName,
        NULL
        );

    PAGED_CODE();

    //
    // Check for valid sizes, pointers, etc.:
    //


    if (!phCredential)
    {
        return(SEC_E_INVALID_HANDLE);
    }


    //
    // Check that we can indeed call the LSA and get the client
    // handle to it.
    //

    scRet = IsOkayToExec(&Client);
    if (!NT_SUCCESS(scRet))
    {
        return(scRet);
    }

    //
    // Locate the buffers with the input data
    //

    if (!GetTokenBuffer(
            pInput,
            0,          // get the first security token
            (PVOID *) &AuthenticateMessage,
            &AuthenticateMessageSize,
            TRUE        // may be readonly
            ) ||
        (!GetTokenBuffer(
            pInput,
            1,          // get the second security token
            (PVOID *) &NtlmAuthenticateMessage,
            &NtlmAuthenticateMessageSize,
            TRUE        // may be readonly
            )))
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    //
    // Get the output tokens
    //

    if (!GetSecurityToken(
            pOutput,
            0,
            &AcceptResponseToken ) )
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    //
    // Make sure the sizes are o.k.
    //

    if ((AuthenticateMessageSize < sizeof(AUTHENTICATE_MESSAGE)) ||
        (NtlmAuthenticateMessageSize < sizeof(NTLM_AUTHENTICATE_MESSAGE)))
    {
        scRet = SEC_E_INVALID_TOKEN;
    }

    //
    // Make sure the caller does not want us to allocate memory:
    //

    if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
    {
        scRet = SEC_E_UNSUPPORTED_FUNCTION;
        goto Cleanup;
    }

    if (AcceptResponseToken->cbBuffer < sizeof(NTLM_ACCEPT_RESPONSE))
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }


    //
    // Verify the validity of the Authenticate message.
    //

    if (strncmp(
            AuthenticateMessage->Signature,
            NTLMSSP_SIGNATURE,
            sizeof(NTLMSSP_SIGNATURE)))
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    if (AuthenticateMessage->MessageType != NtLmAuthenticate)
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    //
    // Fixup the buffer pointers
    //

    UserName = AuthenticateMessage->UserName;
    UserName.Buffer =  UserName.Buffer + (ULONG) AuthenticateMessage;

    DomainName = AuthenticateMessage->DomainName;
    DomainName.Buffer =  DomainName.Buffer + (ULONG) AuthenticateMessage;

    Workstation = AuthenticateMessage->Workstation;
    Workstation.Buffer =  Workstation.Buffer + (ULONG) AuthenticateMessage;

    NtChallengeResponse = AuthenticateMessage->NtChallengeResponse;
    NtChallengeResponse.Buffer =  NtChallengeResponse.Buffer + (ULONG) AuthenticateMessage;

    LmChallengeResponse = AuthenticateMessage->LmChallengeResponse;
    LmChallengeResponse.Buffer =  LmChallengeResponse.Buffer + (ULONG) AuthenticateMessage;

    //
    // Allocate a buffer to pass into LsaLogonUser
    //

    LogonBufferSize = sizeof(MSV1_0_LM20_LOGON) +
                        UserName.Length +
                        DomainName.Length +
                        Workstation.Length +
                        LmChallengeResponse.Length +
                        NtChallengeResponse.Length;

    scRet = ZwAllocateVirtualMemory(
                NtCurrentProcess(),
                &LogonBuffer,
                0L,
                &LogonBufferSize,
                MEM_COMMIT,
                PAGE_READWRITE
                );

    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }

    //
    // Fill in the fixed-length portions
    //

    LogonBuffer->MessageType = MsV1_0NetworkLogon;

    RtlCopyMemory(
        LogonBuffer->ChallengeToClient,
        NtlmAuthenticateMessage->ChallengeToClient,
        MSV1_0_CHALLENGE_LENGTH
        );

    //
    // Fill in the variable length pieces
    //

    Where = (PUCHAR) (LogonBuffer + 1);

    PutString(
        (PSTRING) &LogonBuffer->LogonDomainName,
        &DomainName,
        0,
        &Where
        );

    PutString(
        (PSTRING) &LogonBuffer->UserName,
        &UserName,
        0,
        &Where
        );

    PutString(
        (PSTRING) &LogonBuffer->Workstation,
        &Workstation,
        0,
        &Where
        );

    PutString(
        (PSTRING) &LogonBuffer->CaseSensitiveChallengeResponse,
        &NtChallengeResponse,
        0,
        &Where
        );

    PutString(
        (PSTRING) &LogonBuffer->CaseInsensitiveChallengeResponse,
        &LmChallengeResponse,
        0,
        &Where
        );

    LogonBuffer->ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED |
                                     NtlmAuthenticateMessage->ParameterControl;

    scRet = RtlUnicodeStringToAnsiString(
                &SourceName,
                (PUNICODE_STRING) &Workstation,
                TRUE
                );

    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }

    if ( fContextReq & ASC_REQ_LICENSING )
    {
        EffectivePackageId = PackageId | LSA_CALL_LICENSE_SERVER ;
    }
    else
    {
        EffectivePackageId = PackageId ;
    }

    scRet = LsaLogonUser(
                Client->hPort,
                &SourceName,
                Network,
                EffectivePackageId,
                LogonBuffer,
                LogonBufferSize,
                NULL,               // token groups
                &KsecTokenSource,
                (PVOID *) &LogonProfile,
                &LogonProfileSize,
                &LogonId,
                &TokenHandle,
                &Quotas,
                &SubStatus
                );

    if (scRet == STATUS_ACCOUNT_RESTRICTION)
    {
        scRet = SubStatus;
    }
    if (!NT_SUCCESS(scRet))
    {
        //
        // LsaLogonUser returns garbage for the token if it fails,
        // so zero it now so we don't try to close it later.
        //

        TokenHandle = NULL;
        goto Cleanup;
    }

    //
    // Create the kernel context
    //

    scRet = NtlmInitKernelContext(
                LogonProfile->UserSessionKey,
                LogonProfile->LanmanSessionKey,
                TokenHandle,
                phNewContext
                );

    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }

    TokenHandle = NULL;

    //
    // Allocate the return buffer.
    //


    NtlmAcceptResponse = (PNTLM_ACCEPT_RESPONSE) AcceptResponseToken->pvBuffer;
    if (NtlmAcceptResponse == NULL)
    {
        scRet = SEC_E_INSUFFICIENT_MEMORY;
        goto Cleanup;
    }

    TempLogonId = (LUID UNALIGNED *) &NtlmAcceptResponse->LogonId;
    *TempLogonId = LogonId;
    NtlmAcceptResponse->UserFlags = LogonProfile->UserFlags;

    RtlCopyMemory(
        NtlmAcceptResponse->UserSessionKey,
        LogonProfile->UserSessionKey,
        MSV1_0_USER_SESSION_KEY_LENGTH
        );

    RtlCopyMemory(
        NtlmAcceptResponse->LanmanSessionKey,
        LogonProfile->LanmanSessionKey,
        MSV1_0_LANMAN_SESSION_KEY_LENGTH
        );

    TempKickoffTime = (LARGE_INTEGER UNALIGNED *) &NtlmAcceptResponse->KickoffTime;
    *TempKickoffTime = LogonProfile->KickOffTime;

    AcceptResponseToken->cbBuffer = sizeof(NTLM_ACCEPT_RESPONSE);

    if ( fContextReq & ASC_REQ_LICENSING )
    {
        *pfContextAttr = ASC_RET_ALLOCATED_MEMORY | ASC_RET_LICENSING ;
    }
    else
    {
        *pfContextAttr = ASC_RET_ALLOCATED_MEMORY;
    }

    *ptsExpiry = LogonProfile->LogoffTime;
    scRet = SEC_E_OK;


Cleanup:
    if (SourceName.Buffer != NULL)
    {
        RtlFreeAnsiString(&SourceName);
    }

    if (LogonBuffer != NULL)
    {
        ZwFreeVirtualMemory(
            NtCurrentProcess(),
            &LogonBuffer,
            &LogonBufferSize,
            MEM_RELEASE
            );
    }

    if (LogonProfile != NULL)
    {
        LsaFreeReturnBuffer(LogonProfile);
    }


    if (TokenHandle != NULL)
    {
        NtClose(TokenHandle);
    }

    return(scRet);

}
Пример #11
0
static
BOOL
DoChangePassword(
    IN PGINA_CONTEXT pgContext,
    IN HWND hwndDlg)
{
    WCHAR UserName[256];
    WCHAR Domain[256];
    WCHAR OldPassword[256];
    WCHAR NewPassword1[256];
    WCHAR NewPassword2[256];
    PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
    PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
    ULONG RequestBufferSize;
    ULONG ResponseBufferSize = 0;
    LPWSTR Ptr;
    BOOL res = FALSE;
    NTSTATUS ProtocolStatus;
    NTSTATUS Status;

    GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, 256);
    GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, Domain, 256);
    GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, 256);
    GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, 256);
    GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, 256);

    /* Compare the two passwords and fail if they do not match */
    if (wcscmp(NewPassword1, NewPassword2) != 0)
    {
        ResourceMessageBox(pgContext,
                           hwndDlg,
                           MB_OK | MB_ICONEXCLAMATION,
                           IDS_CHANGEPWDTITLE,
                           IDS_NONMATCHINGPASSWORDS);
        return FALSE;
    }

    /* Calculate the request buffer size */
    RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
                        ((wcslen(Domain) + 1) * sizeof(WCHAR)) +
                        ((wcslen(UserName) + 1) * sizeof(WCHAR)) +
                        ((wcslen(OldPassword) + 1) * sizeof(WCHAR)) +
                        ((wcslen(NewPassword1) + 1) * sizeof(WCHAR));

    /* Allocate the request buffer */
    RequestBuffer = HeapAlloc(GetProcessHeap(),
                              HEAP_ZERO_MEMORY,
                              RequestBufferSize);
    if (RequestBuffer == NULL)
    {
        ERR("HeapAlloc failed\n");
        return FALSE;
    }

    /* Initialize the request buffer */
    RequestBuffer->MessageType = MsV1_0ChangePassword;
    RequestBuffer->Impersonating = TRUE;

    Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));

    /* Pack the domain name */
    RequestBuffer->DomainName.Length = wcslen(Domain) * sizeof(WCHAR);
    RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
    RequestBuffer->DomainName.Buffer = Ptr;

    RtlCopyMemory(RequestBuffer->DomainName.Buffer,
                  Domain,
                  RequestBuffer->DomainName.MaximumLength);

    Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);

    /* Pack the user name */
    RequestBuffer->AccountName.Length = wcslen(UserName) * sizeof(WCHAR);
    RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
    RequestBuffer->AccountName.Buffer = Ptr;

    RtlCopyMemory(RequestBuffer->AccountName.Buffer,
                  UserName,
                  RequestBuffer->AccountName.MaximumLength);

    Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);

    /* Pack the old password */
    RequestBuffer->OldPassword.Length = wcslen(OldPassword) * sizeof(WCHAR);
    RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
    RequestBuffer->OldPassword.Buffer = Ptr;

    RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
                  OldPassword,
                  RequestBuffer->OldPassword.MaximumLength);

    Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);

    /* Pack the new password */
    RequestBuffer->NewPassword.Length = wcslen(NewPassword1) * sizeof(WCHAR);
    RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
    RequestBuffer->NewPassword.Buffer = Ptr;

    RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
                  NewPassword1,
                  RequestBuffer->NewPassword.MaximumLength);

    /* Connect to the LSA server */
    if (!ConnectToLsa(pgContext))
    {
        ERR("ConnectToLsa() failed\n");
        goto done;
    }

    /* Call the authentication package */
    Status = LsaCallAuthenticationPackage(pgContext->LsaHandle,
                                          pgContext->AuthenticationPackage,
                                          RequestBuffer,
                                          RequestBufferSize,
                                          (PVOID*)&ResponseBuffer,
                                          &ResponseBufferSize,
                                          &ProtocolStatus);
    if (!NT_SUCCESS(Status))
    {
        ERR("LsaCallAuthenticationPackage failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    if (!NT_SUCCESS(ProtocolStatus))
    {
        TRACE("LsaCallAuthenticationPackage failed (ProtocolStatus 0x%08lx)\n", ProtocolStatus);
        goto done;
    }

    res = TRUE;

    ResourceMessageBox(pgContext,
                       hwndDlg,
                       MB_OK | MB_ICONINFORMATION,
                       IDS_CHANGEPWDTITLE,
                       IDS_PASSWORDCHANGED);

    if ((wcscmp(UserName, pgContext->UserName) == 0) &&
        (wcscmp(Domain, pgContext->Domain) == 0) &&
        (wcscmp(OldPassword, pgContext->Password) == 0))
    {
        ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR));
        wcscpy(pgContext->Password, NewPassword1);
    }

done:
    if (RequestBuffer != NULL)
        HeapFree(GetProcessHeap(), 0, RequestBuffer);

    if (ResponseBuffer != NULL)
        LsaFreeReturnBuffer(ResponseBuffer);

    return res;
}
Пример #12
0
NTSTATUS kuhl_m_kerberos_list_tickets(PKERB_CALLBACK_CTX callbackCtx, BOOL bExport)
{
	NTSTATUS status, packageStatus;
	KERB_QUERY_TKT_CACHE_REQUEST kerbCacheRequest = {KerbQueryTicketCacheExMessage, {0, 0}};
	PKERB_QUERY_TKT_CACHE_EX_RESPONSE pKerbCacheResponse;
	PKERB_RETRIEVE_TKT_REQUEST pKerbRetrieveRequest = NULL;
	PKERB_RETRIEVE_TKT_RESPONSE pKerbRetrieveResponse = NULL;
	DWORD szData, i;

	status = LsaCallKerberosPackage(&kerbCacheRequest, sizeof(KERB_QUERY_TKT_CACHE_REQUEST), (PVOID *) &pKerbCacheResponse, &szData, &packageStatus);
	if(NT_SUCCESS(status))
	{
		if(NT_SUCCESS(packageStatus))
		{
			for(i = 0; i < pKerbCacheResponse->CountOfTickets; i++)
			{
				kprintf(L"\n[%08x] - 0x%08x - %s", i, pKerbCacheResponse->Tickets[i].EncryptionType, kuhl_m_kerberos_ticket_etype(pKerbCacheResponse->Tickets[i].EncryptionType));
				kprintf(L"\n   Start/End/MaxRenew: ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].StartTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].EndTime); kprintf(L" ; ");
				kull_m_string_displayLocalFileTime((PFILETIME) &pKerbCacheResponse->Tickets[i].RenewTime);
				kprintf(L"\n   Server Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ServerName, &pKerbCacheResponse->Tickets[i].ServerRealm);
				kprintf(L"\n   Client Name       : %wZ @ %wZ", &pKerbCacheResponse->Tickets[i].ClientName, &pKerbCacheResponse->Tickets[i].ClientRealm);
				kprintf(L"\n   Flags %08x    : ", pKerbCacheResponse->Tickets[i].TicketFlags);
				kuhl_m_kerberos_ticket_displayFlags(pKerbCacheResponse->Tickets[i].TicketFlags);
			
				if (bExport)
				{
					szData = sizeof(KERB_RETRIEVE_TKT_REQUEST)+pKerbCacheResponse->Tickets[i].ServerName.MaximumLength;
					if (pKerbRetrieveRequest = (PKERB_RETRIEVE_TKT_REQUEST)LocalAlloc(LPTR, szData)) // LPTR implicates KERB_ETYPE_NULL
					{
						pKerbRetrieveRequest->MessageType = KerbRetrieveEncodedTicketMessage;
						pKerbRetrieveRequest->CacheOptions = /*KERB_RETRIEVE_TICKET_USE_CACHE_ONLY | */KERB_RETRIEVE_TICKET_AS_KERB_CRED;
						pKerbRetrieveRequest->TicketFlags = pKerbCacheResponse->Tickets[i].TicketFlags;
						pKerbRetrieveRequest->TargetName = pKerbCacheResponse->Tickets[i].ServerName;
						pKerbRetrieveRequest->TargetName.Buffer = (PWSTR)((PBYTE)pKerbRetrieveRequest + sizeof(KERB_RETRIEVE_TKT_REQUEST));
						RtlCopyMemory(pKerbRetrieveRequest->TargetName.Buffer, pKerbCacheResponse->Tickets[i].ServerName.Buffer, pKerbRetrieveRequest->TargetName.MaximumLength);

						status = LsaCallKerberosPackage(pKerbRetrieveRequest, szData, (PVOID *)&pKerbRetrieveResponse, &szData, &packageStatus);
					}
				}

				if (callbackCtx && callbackCtx->pTicketHandler)
					callbackCtx->pTicketHandler(callbackCtx->lpContext, &pKerbCacheResponse->Tickets[i], pKerbRetrieveResponse ? &pKerbRetrieveResponse->Ticket : NULL);

				if (pKerbRetrieveRequest)
				{
					LocalFree(pKerbRetrieveRequest);
					pKerbRetrieveRequest = NULL;
				}

				if (pKerbRetrieveResponse)
				{
					LsaFreeReturnBuffer(pKerbRetrieveResponse);
					pKerbRetrieveResponse = NULL;
				}

				kprintf(L"\n");
			}
			LsaFreeReturnBuffer(pKerbCacheResponse);
		}
		else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message / Package : %08x\n", packageStatus);
	}
	else PRINT_ERROR(L"LsaCallAuthenticationPackage KerbQueryTicketCacheEx2Message : %08x\n", status);

	return STATUS_SUCCESS;
}
Пример #13
0
int _tmain(int argc, TCHAR *argv[])
{
   BOOL bResult;
   NTSTATUS Status;
   NTSTATUS SubStatus;

   HANDLE hLsa = NULL;
   HANDLE hProcess = NULL;
   HANDLE hToken = NULL;
   HANDLE hTokenS4U = NULL;

   LSA_STRING Msv1_0Name = { 0 };
   LSA_STRING OriginName = { 0 };
   PMSV1_0_S4U_LOGON pS4uLogon = NULL;
   TOKEN_SOURCE TokenSource;
   ULONG ulAuthenticationPackage;
   DWORD dwMessageLength;

   PBYTE pbPosition;

   PROCESS_INFORMATION pi = { 0 };
   STARTUPINFO si = { 0 };

   PTOKEN_GROUPS pGroups = NULL;
   PSID pLogonSid = NULL;
   PSID pExtraSid = NULL;

   PVOID pvProfile = NULL;
   DWORD dwProfile = 0;
   LUID logonId = { 0 };
   QUOTA_LIMITS quotaLimits;

   LPTSTR szCommandLine = NULL;
   LPTSTR szSrcCommandLine = TEXT("%systemroot%\\system32\\cmd.exe");
   LPTSTR szDomain = NULL;
   LPTSTR szUsername = NULL;
   TCHAR seps[] = TEXT("\\");
   TCHAR *next_token = NULL;

   g_hHeap = GetProcessHeap();

   if (argc < 2)
   {
      fprintf(stderr, "Usage:\n   s4u.exe Domain\\Username [Extra SID]\n\n");
      goto End;
   }

   //
   // Get DOMAIN and USERNAME from command line.
   //
   szDomain = _tcstok_s(argv[1], seps, &next_token);
   if (szDomain == NULL)
   {
      fprintf(stderr, "Unable to parse command line.\n");
      goto End;
   }

   szUsername = _tcstok_s(NULL, seps, &next_token);
   if (szUsername == NULL)
   {
      fprintf(stderr, "Unable to parse command line.\n");
      goto End;
   }

   //
   // Activate the TCB privilege
   //
   hProcess = GetCurrentProcess();
   OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
   if (!SetPrivilege(hToken, SE_TCB_NAME, TRUE))
   {
      goto End;
   }

   //
   // Get logon SID
   //
   if (!GetLogonSID(hToken, &pLogonSid))
   {
      fprintf(stderr, "Unable to find logon SID.\n");
      goto End;
   }

   //
   // Connect (Untrusted) to LSA
   //
   Status = LsaConnectUntrusted(&hLsa);
   if (Status!=STATUS_SUCCESS)
   {
      fprintf(stderr, "LsaConnectUntrusted failed (error 0x%x).", Status);
      hLsa = NULL;
      goto End;
   }

   //
   // Lookup for the MSV1_0 authentication package (NTLMSSP)
   //
   InitLsaString(&Msv1_0Name, MSV1_0_PACKAGE_NAME);
   Status = LsaLookupAuthenticationPackage(hLsa, &Msv1_0Name, &ulAuthenticationPackage);
   if (Status!=STATUS_SUCCESS)
   {
      fprintf(stderr, "LsaLookupAuthenticationPackage failed (error 0x%x).", Status);
      hLsa = NULL;
      goto End;
   }

   //
   // Create MSV1_0_S4U_LOGON structure
   //
   dwMessageLength = sizeof(MSV1_0_S4U_LOGON) + (2 + wcslen(szDomain) + wcslen(szUsername)) * sizeof(WCHAR);
   pS4uLogon = (PMSV1_0_S4U_LOGON)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, dwMessageLength);
   if (pS4uLogon == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   pS4uLogon->MessageType = MsV1_0S4ULogon;
   pbPosition = (PBYTE)pS4uLogon + sizeof(MSV1_0_S4U_LOGON);
   pbPosition = InitUnicodeString(&pS4uLogon->UserPrincipalName, szUsername, pbPosition);
   pbPosition = InitUnicodeString(&pS4uLogon->DomainName, szDomain, pbPosition);

   //
   // Misc
   //
   strcpy_s(TokenSource.SourceName, TOKEN_SOURCE_LENGTH, "S4UWin");
   InitLsaString(&OriginName, "S4U for Windows");
   AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);

   //
   // Add extra SID to token.
   //
   // If the application needs to connect to a Windows Desktop, Logon SID must be added to the Token.
   //
   pGroups = (PTOKEN_GROUPS)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, sizeof(TOKEN_GROUPS) + 2*sizeof(SID_AND_ATTRIBUTES));
   if (pGroups == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   pGroups->GroupCount = 1;
   pGroups->Groups[0].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
   pGroups->Groups[0].Sid = pLogonSid;

   //
   // If an extra SID is specified to command line, add it to the pGroups structure.
   //
   if (argc==3)
   {
      bResult = ConvertStringSidToSid(argv[2], &pExtraSid);

      if (bResult == TRUE)
      {
         pGroups->GroupCount = 2;
         pGroups->Groups[1].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
         pGroups->Groups[1].Sid = pExtraSid;
      }
      else
      {
         fprintf(stderr, "Unable to convert SID (error %u).", GetLastError());
      }
   }

   //
   // Call LSA
   //
   Status = LsaLogonUser(
      hLsa,
      &OriginName,
      Network,                // Or Batch
      ulAuthenticationPackage,
      pS4uLogon,
      dwMessageLength,
      pGroups,                // LocalGroups
      &TokenSource,           // SourceContext
      &pvProfile,
      &dwProfile,
      &logonId,
      &hTokenS4U,
      &quotaLimits,
      &SubStatus
      );
   if (Status!=STATUS_SUCCESS)
   {
      printf("LsaLogonUser failed (error 0x%x).\n", Status);
      goto End;
   }

   printf("LsaLogonUser: OK, LogonId: 0x%x-0x%x\n", logonId.HighPart, logonId.LowPart);

   //
   // Create process with S4U token.
   //
   si.cb = sizeof(STARTUPINFO);
   si.lpDesktop = TEXT("winsta0\\default");

   //
   // Warning: szCommandLine parameter of CreateProcessAsUser() must be writable
   //
   szCommandLine = (LPTSTR)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, MAX_PATH * sizeof(TCHAR));
   if (szCommandLine == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   if (ExpandEnvironmentStrings(szSrcCommandLine, szCommandLine, MAX_PATH) == 0)
   {
      fprintf(stderr, "ExpandEnvironmentStrings failed (error %u).", GetLastError());
      goto End;
   }

   //
   // CreateProcessAsUser required SeAssignPrimaryTokenPrivilege but no need to be activated.
   //
   bResult = CreateProcessAsUser(
      hTokenS4U,
      NULL,
      szCommandLine,
      NULL,
      NULL,
      FALSE,
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
      NULL,
      TEXT("c:\\"),
      &si,
      &pi
      );
   if (bResult == FALSE)
   {
      printf("CreateProcessAsUser failed (error %u).\n", GetLastError());
      goto End;
   }

End:
   //
   // Free resources
   //
   if (Msv1_0Name.Buffer)
      HeapFree(g_hHeap, 0, Msv1_0Name.Buffer);
   if (OriginName.Buffer)
      HeapFree(g_hHeap, 0, OriginName.Buffer);
   if (pLogonSid)
      HeapFree(g_hHeap, 0, pLogonSid);
   if (pExtraSid)
      LocalFree(pExtraSid);
   if (pS4uLogon)
      HeapFree(g_hHeap, 0, pS4uLogon);
   if (pGroups)
      HeapFree(g_hHeap, 0, pGroups);
   if (pvProfile)
      LsaFreeReturnBuffer(pvProfile);
   if (hLsa)
      LsaClose(hLsa);
   if (hToken)
      CloseHandle(hToken);
   if (hTokenS4U)
      CloseHandle(hTokenS4U);
   if (pi.hProcess)
      CloseHandle(pi.hProcess);
   if (pi.hThread)
      CloseHandle(pi.hThread);

   return EXIT_SUCCESS;
}
Пример #14
0
DWORD
DfspInitDomainListFromLSA()
{
    DWORD dwErr;
    NTSTATUS status;
    OBJECT_ATTRIBUTES oa;
    LSA_HANDLE hlsa;
    LSA_ENUMERATION_HANDLE hEnum = (LSA_ENUMERATION_HANDLE) NULL;
    PLSA_TRUST_INFORMATION rglsaDomainInfo = NULL;

    ZeroMemory( &oa, sizeof(OBJECT_ATTRIBUTES) );

    status = LsaOpenPolicy(
                NULL,                            // SystemName
                &oa,                             // LSA Object Attributes
                POLICY_VIEW_LOCAL_INFORMATION,   // Desired Access
                &hlsa);

    if (NT_SUCCESS(status)) {

        do {

            ULONG cEnum;

            status = LsaEnumerateTrustedDomains(
                        hlsa,
                        &hEnum,
                        (PVOID) &rglsaDomainInfo,
                        LSA_MAXIMUM_ENUMERATION_LENGTH,
                        &cEnum);

            if (NT_SUCCESS(status)) {

                status = DfspInsertLsaDomainList(
                            rglsaDomainInfo,
                            cEnum);

                LsaFreeReturnBuffer( rglsaDomainInfo );

            }

        } while ( status == STATUS_SUCCESS );

    }

    switch (status) {
    case STATUS_SUCCESS:
    case STATUS_NO_MORE_ENTRIES:
        dwErr = ERROR_SUCCESS;
        break;

    case STATUS_INSUFFICIENT_RESOURCES:
        dwErr = ERROR_NOT_ENOUGH_MEMORY;
        break;

    default:
        dwErr = ERROR_UNEXP_NET_ERR;
        break;

    }

    return( dwErr );

}
Пример #15
0
bool SecurityHelper::CallLsaLogonUser(
    HANDLE hLsa,
    const wchar_t* domain,
    const wchar_t* user,
    const wchar_t* pass,
    SECURITY_LOGON_TYPE logonType,
    LUID* pLogonSessionId,
    HANDLE* phToken,
    MSV1_0_INTERACTIVE_PROFILE** ppProfile,
    DWORD* pWin32Error)
{

    bool result      = false;
    DWORD win32Error = 0;
    *phToken         = 0;

    LUID ignoredLogonSessionId;

    // optional arguments
    if (ppProfile)        *ppProfile   = 0;
    if (pWin32Error)      *pWin32Error = 0;
    if (!pLogonSessionId) pLogonSessionId = &ignoredLogonSessionId;

    LSA_STRING logonProcessName            = { 0 };
    TOKEN_SOURCE sourceContext             = { 's', 'a', 'm', 'p', 'l', 'e' };
    MSV1_0_INTERACTIVE_PROFILE* pProfile = 0;
    ULONG cbProfile = 0;
    QUOTA_LIMITS quotaLimits;
    NTSTATUS substatus;
    DWORD cbLogonRequest;

    MSV1_0_INTERACTIVE_LOGON* pLogonRequest =
        _allocLogonRequest(domain, user, pass, &cbLogonRequest);
    if (!pLogonRequest)
	{
        win32Error = ERROR_NOT_ENOUGH_MEMORY;
        goto cleanup;   
    }

    if (!_newLsaString(&logonProcessName, LOGON_PROCESS_NAME))
	{
        win32Error = ERROR_NOT_ENOUGH_MEMORY;
        goto cleanup;
    }

    // LsaLogonUser - the function from hell
    NTSTATUS status = LsaLogonUser(
        hLsa,
        &logonProcessName,  // we use our logon process name for the "origin name"
        logonType,
        LOGON32_PROVIDER_DEFAULT, // we use MSV1_0 or Kerb, whichever is supported
        pLogonRequest,
        cbLogonRequest,
        0,                  // we do not add any group SIDs
        &sourceContext,
        (void**)&pProfile,  // caller must free this via LsaFreeReturnBuffer 
        &cbProfile,
        pLogonSessionId,
        phToken,
        &quotaLimits,       // we ignore this, but must pass in anyway
        &substatus);

    if (status)
	{
        win32Error = LsaNtStatusToWinError(status);

        if ((ERROR_ACCOUNT_RESTRICTION == win32Error && STATUS_PASSWORD_EXPIRED == substatus))
		{
            win32Error = ERROR_PASSWORD_EXPIRED;
        }

        *phToken = 0;
        pProfile = 0;
        LDB2(L"LsaLogonUser failed. Status = %d, substatus = 0x%08X", win32Error, substatus);

        goto cleanup;
    }

    if (ppProfile)
	{
        *ppProfile = (MSV1_0_INTERACTIVE_PROFILE*)pProfile;
        pProfile = 0;
    }
    result = true;

cleanup:
    // if caller cares about the details, pass them on
    if (pWin32Error) *pWin32Error = win32Error;

    if (pLogonRequest)
	{
        SecureZeroMemory(pLogonRequest, cbLogonRequest);
        delete pLogonRequest;
    }
    if (pProfile) LsaFreeReturnBuffer(pProfile);
    _deleteLsaString(&logonProcessName);

    return result;
}
Пример #16
0
SECURITY_STATUS SEC_ENTRY
GetSecurityUserInfo(
    IN PLUID pLogonId,
    IN ULONG fFlags,
    OUT PSecurityUserData * ppUserInfo)
{
    NTSTATUS Status, FinalStatus;
    PVOID GetInfoBuffer = NULL;
    PVOID GetInfoResponseBuffer = NULL;
    PMSV1_0_GETUSERINFO_REQUEST GetInfoRequest;
    PMSV1_0_GETUSERINFO_RESPONSE GetInfoResponse;
    ULONG ResponseSize;
    ULONG RegionSize = sizeof(MSV1_0_GETUSERINFO_REQUEST);
    PSecurityUserData UserInfo = NULL;
    ULONG UserInfoSize;
    PUCHAR Where;
    SECURITY_STATUS scRet;
    PClient Client = NULL;


    scRet = IsOkayToExec(&Client);
    if (!NT_SUCCESS(scRet))
    {
        return(scRet);
    }

    //
    //  Allocate virtual memory for the response buffer.
    //

    Status = ZwAllocateVirtualMemory(
                NtCurrentProcess(),
                &GetInfoBuffer, 0L,
                &RegionSize,
                MEM_COMMIT,
                PAGE_READWRITE
                );

    GetInfoRequest = GetInfoBuffer;

    if (!NT_SUCCESS(Status)) {
        scRet = Status;
        goto Cleanup;
    }

    GetInfoRequest->MessageType = MsV1_0GetUserInfo;

    RtlCopyLuid(&GetInfoRequest->LogonId, pLogonId);

    Status = LsaCallAuthenticationPackage(
                Client->hPort,
                PackageId,
                GetInfoRequest,
                RegionSize,
                &GetInfoResponseBuffer,
                &ResponseSize,
                &FinalStatus);

    GetInfoResponse = GetInfoResponseBuffer;

    if (!NT_SUCCESS(Status)) {
        GetInfoResponseBuffer = NULL;
        scRet = Status;
        goto Cleanup;
    }


    if (!NT_SUCCESS(FinalStatus)) {
        scRet = FinalStatus;
        goto Cleanup;
    }

    ASSERT(GetInfoResponse->MessageType == MsV1_0GetUserInfo);

    //
    // Build a SecurityUserData
    //

    UserInfoSize = sizeof(SecurityUserData) +
                   GetInfoResponse->UserName.MaximumLength +
                   GetInfoResponse->LogonDomainName.MaximumLength +
                   GetInfoResponse->LogonServer.MaximumLength +
                   RtlLengthSid(GetInfoResponse->UserSid);



    scRet = ZwAllocateVirtualMemory(
                NtCurrentProcess(),
                &UserInfo,
                0L,
                &UserInfoSize,
                MEM_COMMIT,
                PAGE_READWRITE
                );
    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }

    //
    // Pack in the SID first, to respectalignment boundaries.
    //

    Where = (PUCHAR) (UserInfo + 1);
    UserInfo->pSid = (PSID) (Where);
    RtlCopySid(
        UserInfoSize,
        Where,
        GetInfoResponse->UserSid
        );
    Where += RtlLengthSid(Where);

    //
    // Pack in the strings
    //

    PutString(
        (PSTRING) &UserInfo->UserName,
        (PSTRING) &GetInfoResponse->UserName,
        0,
        &Where
        );

    PutString(
        (PSTRING) &UserInfo->LogonDomainName,
        (PSTRING) &GetInfoResponse->LogonDomainName,
        0,
        &Where
        );

    PutString(
        (PSTRING) &UserInfo->LogonServer,
        (PSTRING) &GetInfoResponse->LogonServer,
        0,
        &Where
        );

    *ppUserInfo = UserInfo;
    UserInfo = NULL;
    scRet = STATUS_SUCCESS;

Cleanup:
    if (GetInfoRequest != NULL)
    {
        ZwFreeVirtualMemory(
            NtCurrentProcess(),
            &GetInfoRequest,
            &RegionSize,
            MEM_RELEASE
            );

    }

    if (UserInfo != NULL)
    {
        FreeContextBuffer(UserInfo);
    }

    if (GetInfoResponseBuffer != NULL)
    {
        LsaFreeReturnBuffer(GetInfoResponseBuffer);
    }

    return(scRet);
}
Пример #17
0
/*
 * Class:     sun_security_krb5_Credentials
 * Method:    acquireDefaultNativeCreds
 * Signature: ()Lsun/security/krb5/Credentials;
 */
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds(
                JNIEnv *env,
                jclass krbcredsClass) {

        KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
        PKERB_RETRIEVE_TKT_RESPONSE TktCacheResponse = NULL;
        PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
        PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
        NTSTATUS Status, SubStatus;
        ULONG requestSize = 0;
        ULONG responseSize = 0;
        ULONG rspSize = 0;
        HANDLE LogonHandle = NULL;
        ULONG PackageId;
        jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
        jobject ticketFlags, startTime, endTime, krbCreds = NULL;
        jobject authTime, renewTillTime, hostAddresses = NULL;
        KERB_EXTERNAL_TICKET *msticket;
        int ignore_cache = 0;
        FILETIME Now, EndTime, LocalEndTime;

        while (TRUE) {

        if (krbcredsConstructor == 0) {
                krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
        "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
            if (krbcredsConstructor == 0) {
                printf("Couldn't find sun.security.krb5.Credentials constructor\n");
                break;
            }
        }

        #ifdef DEBUG
        printf("Found KrbCreds constructor\n");
        #endif

        //
        // Get the logon handle and package ID from the
        // Kerberos package
        //
        if (!PackageConnectLookup(&LogonHandle, &PackageId))
            break;

        #ifdef DEBUG
        printf("Got handle to Kerberos package\n");
        #endif /* DEBUG */

        // Get the MS TGT from cache
        CacheRequest.MessageType = KerbRetrieveTicketMessage;
        CacheRequest.LogonId.LowPart = 0;
        CacheRequest.LogonId.HighPart = 0;

        Status = LsaCallAuthenticationPackage(
                        LogonHandle,
                        PackageId,
                        &CacheRequest,
                        sizeof(CacheRequest),
                        &TktCacheResponse,
                        &rspSize,
                        &SubStatus
                        );

        #ifdef DEBUG
        printf("Response size is %d\n", rspSize);
        #endif

        if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
            if (!LSA_SUCCESS(Status)) {
                ShowNTError("LsaCallAuthenticationPackage", Status);
            } else {
                ShowNTError("Protocol status", SubStatus);
            }
            break;
        }

        // got the native MS TGT
        msticket = &(TktCacheResponse->Ticket);

        // check TGT validity
        switch (msticket->SessionKey.KeyType) {
            case KERB_ETYPE_DES_CBC_CRC:
            case KERB_ETYPE_DES_CBC_MD5:
            case KERB_ETYPE_NULL:
            case KERB_ETYPE_RC4_HMAC_NT:
                GetSystemTimeAsFileTime(&Now);
                EndTime.dwLowDateTime = msticket->EndTime.LowPart;
                EndTime.dwHighDateTime = msticket->EndTime.HighPart;
                FileTimeToLocalFileTime(&EndTime, &LocalEndTime);
                if (CompareFileTime(&Now, &LocalEndTime) >= 0) {
                    ignore_cache = 1;
                }
                if (msticket->TicketFlags & KERB_TICKET_FLAGS_invalid) {
                    ignore_cache = 1;
                }
                break;
            case KERB_ETYPE_RC4_MD4:
            default:
                // not supported
                ignore_cache = 1;
                break;
        }

        if (ignore_cache) {
            #ifdef DEBUG
            printf("MS TGT in cache is invalid/not supported; request new ticket\n");
            #endif /* DEBUG */

            // use domain to request Ticket
            Status = ConstructTicketRequest(msticket->TargetDomainName,
                                &pTicketRequest, &requestSize);
            if (!LSA_SUCCESS(Status)) {
                ShowNTError("ConstructTicketRequest status", Status);
                break;
            }

            pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
            pTicketRequest->EncryptionType = KERB_ETYPE_DES_CBC_MD5;
            pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_DONT_USE_CACHE;

            Status = LsaCallAuthenticationPackage(
                        LogonHandle,
                        PackageId,
                        pTicketRequest,
                        requestSize,
                        &pTicketResponse,
                        &responseSize,
                        &SubStatus
                        );

            #ifdef DEBUG
            printf("Response size is %d\n", responseSize);
            #endif /* DEBUG */

            if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
                if (!LSA_SUCCESS(Status)) {
                    ShowNTError("LsaCallAuthenticationPackage", Status);
                } else {
                    ShowNTError("Protocol status", SubStatus);
                }
                break;
            }

            // got the native MS Kerberos TGT
            msticket = &(pTicketResponse->Ticket);
        }

/*

typedef struct _KERB_RETRIEVE_TKT_RESPONSE {
    KERB_EXTERNAL_TICKET Ticket;
} KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE;

typedef struct _KERB_EXTERNAL_TICKET {
    PKERB_EXTERNAL_NAME ServiceName;
    PKERB_EXTERNAL_NAME TargetName;
    PKERB_EXTERNAL_NAME ClientName;
    UNICODE_STRING DomainName;
    UNICODE_STRING TargetDomainName;
    UNICODE_STRING AltTargetDomainName;
    KERB_CRYPTO_KEY SessionKey;
    ULONG TicketFlags;
    ULONG Flags;
    LARGE_INTEGER KeyExpirationTime;
    LARGE_INTEGER StartTime;
    LARGE_INTEGER EndTime;
    LARGE_INTEGER RenewUntil;
    LARGE_INTEGER TimeSkew;
    ULONG EncodedTicketSize;
    PUCHAR EncodedTicket; <========== Here's the good stuff
} KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET;

typedef struct _KERB_EXTERNAL_NAME {
    SHORT NameType;
    USHORT NameCount;
    UNICODE_STRING Names[ANYSIZE_ARRAY];
} KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME;

typedef struct _LSA_UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;

typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;

typedef struct KERB_CRYPTO_KEY {
    LONG KeyType;
    ULONG Length;
    PUCHAR Value;
} KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY;

*/
        // Build a com.sun.security.krb5.Ticket
        ticket = BuildTicket(env, msticket->EncodedTicket,
                                msticket->EncodedTicketSize);
        if (ticket == NULL) {
                break;
        }
        // OK, have a Ticket, now need to get the client name
        clientPrincipal = BuildPrincipal(env, msticket->ClientName,
                                msticket->TargetDomainName); // mdu
        if (clientPrincipal == NULL) {
                break;
        }

        // and the "name" of tgt
        targetPrincipal = BuildPrincipal(env, msticket->ServiceName,
                        msticket->DomainName);
        if (targetPrincipal == NULL) {
                break;
        }

        // Get the encryption key
        encryptionKey = BuildEncryptionKey(env, &(msticket->SessionKey));
        if (encryptionKey == NULL) {
                break;
        }

        // and the ticket flags
        ticketFlags = BuildTicketFlags(env, &(msticket->TicketFlags));
        if (ticketFlags == NULL) {
                break;
        }

        // Get the start time
        startTime = BuildKerberosTime(env, &(msticket->StartTime));
        if (startTime == NULL) {
                break;
        }

        /*
         * mdu: No point storing the eky expiration time in the auth
         * time field. Set it to be same as startTime. Looks like
         * windows does not have post-dated tickets.
         */
        authTime = startTime;

        // and the end time
        endTime = BuildKerberosTime(env, &(msticket->EndTime));
        if (endTime == NULL) {
                break;
        }

        // Get the renew till time
        renewTillTime = BuildKerberosTime(env, &(msticket->RenewUntil));
        if (renewTillTime == NULL) {
                break;
        }

        // and now go build a KrbCreds object
        krbCreds = (*env)->NewObject(
                env,
                krbcredsClass,
                krbcredsConstructor,
                ticket,
                clientPrincipal,
                targetPrincipal,
                encryptionKey,
                ticketFlags,
                authTime, // mdu
                startTime,
                endTime,
                renewTillTime, //mdu
                hostAddresses);

        break;
        } // end of WHILE

        // clean up resources
        if (TktCacheResponse != NULL) {
                LsaFreeReturnBuffer(TktCacheResponse);
        }
        if (pTicketRequest) {
                LocalFree(pTicketRequest);
        }
        if (pTicketResponse != NULL) {
                LsaFreeReturnBuffer(pTicketResponse);
        }

        return krbCreds;
}
Пример #18
0
SECURITY_STATUS SEC_ENTRY
InitializeSecurityContextW(
    PCredHandle                 phCredential,       // Cred to base context
    PCtxtHandle                 phContext,          // Existing context (OPT)
    PSECURITY_STRING            pssTargetName,      // Name of target
    unsigned long               fContextReq,        // Context Requirements
    unsigned long               Reserved1,          // Reserved, MBZ
    unsigned long               TargetDataRep,      // Data rep of target
    PSecBufferDesc              pInput,             // Input Buffers
    unsigned long               Reserved2,          // Reserved, MBZ
    PCtxtHandle                 phNewContext,       // (out) New Context handle
    PSecBufferDesc              pOutput,            // (inout) Output Buffers
    unsigned long SEC_FAR *     pfContextAttr,      // (out) Context attrs
    PTimeStamp                  ptsExpiry           // (out) Life span (OPT)
    )
{
    SECURITY_STATUS scRet;
    PMSV1_0_GETCHALLENRESP_REQUEST ChallengeRequest = NULL;
    ULONG ChallengeRequestSize;
    PMSV1_0_GETCHALLENRESP_RESPONSE ChallengeResponse = NULL;
    ULONG ChallengeResponseSize;
    PCHALLENGE_MESSAGE ChallengeMessage = NULL;
    ULONG ChallengeMessageSize;
    PNTLM_CHALLENGE_MESSAGE NtlmChallengeMessage = NULL;
    ULONG NtlmChallengeMessageSize;
    PAUTHENTICATE_MESSAGE AuthenticateMessage = NULL;
    ULONG AuthenticateMessageSize;
    PNTLM_INITIALIZE_RESPONSE NtlmInitializeResponse = NULL;
    PClient Client = NULL;
    UNICODE_STRING PasswordToUse;
    UNICODE_STRING UserNameToUse;
    UNICODE_STRING DomainNameToUse;
    ULONG ParameterControl = USE_PRIMARY_PASSWORD |
                                RETURN_PRIMARY_USERNAME |
                                RETURN_PRIMARY_LOGON_DOMAINNAME;

    NTSTATUS FinalStatus = STATUS_SUCCESS;
    PUCHAR Where;
    PSecBuffer AuthenticationToken = NULL;
    PSecBuffer InitializeResponseToken = NULL;
    BOOLEAN UseSuppliedCreds = FALSE;


    PAGED_CODE();

    RtlInitUnicodeString(
        &PasswordToUse,
        NULL
        );

    RtlInitUnicodeString(
        &UserNameToUse,
        NULL
        );

    RtlInitUnicodeString(
        &DomainNameToUse,
        NULL
        );

    //
    // Check for valid sizes, pointers, etc.:
    //


    if (!phCredential)
    {
        return(SEC_E_INVALID_HANDLE);
    }


    //
    // Check that we can indeed call the LSA and get the client
    // handle to it.
    //

    scRet = IsOkayToExec(&Client);
    if (!NT_SUCCESS(scRet))
    {
        return(scRet);
    }

    //
    // Locate the buffers with the input data
    //

    if (!GetTokenBuffer(
            pInput,
            0,          // get the first security token
            (PVOID *) &ChallengeMessage,
            &ChallengeMessageSize,
            TRUE        // may be readonly
            ))
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    //
    // If we are using supplied creds, get them now too.
    //


    if (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS)
    {
        if (!GetTokenBuffer(
            pInput,
            1,          // get the second security token
            (PVOID *) &NtlmChallengeMessage,
            &NtlmChallengeMessageSize,
            TRUE        // may be readonly
            ))
        {
            scRet = SEC_E_INVALID_TOKEN;
            goto Cleanup;
        }
        else
        {
            UseSuppliedCreds = TRUE;
        }

    }

    //
    // Get the output tokens
    //

    if (!GetSecurityToken(
            pOutput,
            0,
            &AuthenticationToken) ||
        !GetSecurityToken(
            pOutput,
            1,
            &InitializeResponseToken ) )
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    //
    // Make sure the sizes are o.k.
    //

    if ((ChallengeMessageSize < sizeof(CHALLENGE_MESSAGE)) ||
        (UseSuppliedCreds &&
            !(NtlmChallengeMessageSize < sizeof(NTLM_CHALLENGE_MESSAGE))))
    {
        scRet = SEC_E_INVALID_TOKEN;
    }

    //
    // Make sure the caller wants us to allocate memory:
    //

    if (!(fContextReq & ISC_REQ_ALLOCATE_MEMORY))
    {
        scRet = SEC_E_UNSUPPORTED_FUNCTION;
        goto Cleanup;
    }

//
// BUGBUG: allow calls requesting PROMPT_FOR_CREDS to go through.
// We won't prompt, but we will setup a context properly.
//

//    if ((fContextReq & ISC_REQ_PROMPT_FOR_CREDS) != 0)
//    {
//        scRet = SEC_E_UNSUPPORTED_FUNCTION;
//        goto Cleanup;
//    }

    //
    // Verify the validity of the challenge message.
    //

    if (strncmp(
            ChallengeMessage->Signature,
            NTLMSSP_SIGNATURE,
            sizeof(NTLMSSP_SIGNATURE)))
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    if (ChallengeMessage->MessageType != NtLmChallenge)
    {
        scRet = SEC_E_INVALID_TOKEN;
        goto Cleanup;
    }

    if (ChallengeMessage->NegotiateFlags & NTLMSSP_REQUIRED_NEGOTIATE_FLAGS !=
        NTLMSSP_REQUIRED_NEGOTIATE_FLAGS)
    {
        scRet = SEC_E_UNSUPPORTED_FUNCTION;
        goto Cleanup;
    }

    if ((ChallengeMessage->NegotiateFlags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY) != 0)
    {
        ParameterControl |= RETURN_NON_NT_USER_SESSION_KEY;
    }

    if ((fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) != 0)
    {
        if ( NtlmChallengeMessage->Password.Buffer != NULL)
        {
            ParameterControl &= ~USE_PRIMARY_PASSWORD;
            PasswordToUse = NtlmChallengeMessage->Password;
            PasswordToUse.Buffer = (LPWSTR) ((PCHAR) PasswordToUse.Buffer +
                                              (ULONG) NtlmChallengeMessage);
        }

        if (NtlmChallengeMessage->UserName.Length != 0)
        {
            UserNameToUse = NtlmChallengeMessage->UserName;
            UserNameToUse.Buffer = (LPWSTR) ((PCHAR) UserNameToUse.Buffer +
                                              (ULONG) NtlmChallengeMessage);
            ParameterControl &= ~RETURN_PRIMARY_USERNAME;
        }
        if (NtlmChallengeMessage->DomainName.Length != 0)
        {
            DomainNameToUse = NtlmChallengeMessage->DomainName;
            DomainNameToUse.Buffer = (LPWSTR) ((PCHAR) DomainNameToUse.Buffer +
                                              (ULONG) NtlmChallengeMessage);
            ParameterControl &= ~RETURN_PRIMARY_LOGON_DOMAINNAME;
        }

    }

    //
    // Package up the parameter for a call to the LSA.
    //

    ChallengeRequestSize = sizeof(MSV1_0_GETCHALLENRESP_REQUEST) +
                                PasswordToUse.Length;

    scRet = ZwAllocateVirtualMemory(
                NtCurrentProcess(),
                &ChallengeRequest,
                0L,
                &ChallengeRequestSize,
                MEM_COMMIT,
                PAGE_READWRITE
                );
    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }


    //
    // Build the challenge request message.
    //

    ChallengeRequest->MessageType = MsV1_0Lm20GetChallengeResponse;
    ChallengeRequest->ParameterControl = ParameterControl;
    ChallengeRequest->LogonId = * (PLUID) phCredential;
    RtlCopyMemory(
        ChallengeRequest->ChallengeToClient,
        ChallengeMessage->Challenge,
        MSV1_0_CHALLENGE_LENGTH
        );
    if ((ParameterControl & USE_PRIMARY_PASSWORD) == 0)
    {
        ChallengeRequest->Password.Buffer = (LPWSTR) (ChallengeRequest+1);
        RtlCopyMemory(
            ChallengeRequest->Password.Buffer,
            PasswordToUse.Buffer,
            PasswordToUse.Length
            );
        ChallengeRequest->Password.Length = PasswordToUse.Length;
        ChallengeRequest->Password.MaximumLength = PasswordToUse.Length;
    }

    //
    // Call the LSA to get the challenge response.
    //

    scRet = LsaCallAuthenticationPackage(
                Client->hPort,
                PackageId,
                ChallengeRequest,
                ChallengeRequestSize,
                &ChallengeResponse,
                &ChallengeResponseSize,
                &FinalStatus
                );
    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }
    if (!NT_SUCCESS(FinalStatus))
    {
        scRet = FinalStatus;
        goto Cleanup;
    }

    ASSERT(ChallengeResponse->MessageType == MsV1_0Lm20GetChallengeResponse);
    //
    // Now prepare the output message.
    //

    if (UserNameToUse.Buffer == NULL)
    {
        UserNameToUse = ChallengeResponse->UserName;
    }
    if (DomainNameToUse.Buffer == NULL)
    {
        DomainNameToUse = ChallengeResponse->LogonDomainName;
    }

    AuthenticateMessageSize = sizeof(AUTHENTICATE_MESSAGE) +
                                UserNameToUse.Length +
                                DomainNameToUse.Length +
                                ChallengeResponse->CaseSensitiveChallengeResponse.Length +
                                ChallengeResponse->CaseInsensitiveChallengeResponse.Length;

    //
    // BUGBUG: where do I get the workstation name from?
    //

    AuthenticateMessage = (PAUTHENTICATE_MESSAGE) SecAllocate(AuthenticateMessageSize);
    if (AuthenticateMessage == NULL)
    {
        scRet = SEC_E_INSUFFICIENT_MEMORY;
        goto Cleanup;
    }

    Where = (PUCHAR) (AuthenticateMessage + 1);
    RtlCopyMemory(
        AuthenticateMessage->Signature,
        NTLMSSP_SIGNATURE,
        sizeof(NTLMSSP_SIGNATURE)
        );
    AuthenticateMessage->MessageType = NtLmAuthenticate;

    PutString(
        &AuthenticateMessage->LmChallengeResponse,
        &ChallengeResponse->CaseInsensitiveChallengeResponse,
        AuthenticateMessage,
        &Where
        );

    PutString(
        &AuthenticateMessage->NtChallengeResponse,
        &ChallengeResponse->CaseSensitiveChallengeResponse,
        AuthenticateMessage,
        &Where
        );

    PutString(
        &AuthenticateMessage->DomainName,
        (PSTRING) &DomainNameToUse,
        AuthenticateMessage,
        &Where
        );

    PutString(
        &AuthenticateMessage->UserName,
        (PSTRING) &UserNameToUse,
        AuthenticateMessage,
        &Where
        );

    //
    // BUGBUG: no workstation name to fill in.
    //

    AuthenticateMessage->Workstation.Length = 0;
    AuthenticateMessage->Workstation.MaximumLength = 0;
    AuthenticateMessage->Workstation.Buffer = NULL;


    //
    // Build the initialize response.
    //

    NtlmInitializeResponse = (PNTLM_INITIALIZE_RESPONSE) SecAllocate(sizeof(NTLM_INITIALIZE_RESPONSE));
    if (NtlmInitializeResponse == NULL)
    {
        scRet = SEC_E_INSUFFICIENT_MEMORY;
        goto Cleanup;
    }


    RtlCopyMemory(
        NtlmInitializeResponse->UserSessionKey,
        ChallengeResponse->UserSessionKey,
        MSV1_0_USER_SESSION_KEY_LENGTH
        );

    RtlCopyMemory(
        NtlmInitializeResponse->LanmanSessionKey,
        ChallengeResponse->LanmanSessionKey,
        MSV1_0_LANMAN_SESSION_KEY_LENGTH
        );

    //
    // Fill in the output buffers now.
    //

    AuthenticationToken->pvBuffer = AuthenticateMessage;
    AuthenticationToken->cbBuffer = AuthenticateMessageSize;
    InitializeResponseToken->pvBuffer = NtlmInitializeResponse;
    InitializeResponseToken->cbBuffer = sizeof(NTLM_INITIALIZE_RESPONSE);


    //
    // Make a local context for this
    //

    scRet = NtlmInitKernelContext(
                NtlmInitializeResponse->UserSessionKey,
                NtlmInitializeResponse->LanmanSessionKey,
                NULL,           // no token,
                phNewContext
                );

    if (!NT_SUCCESS(scRet))
    {
        goto Cleanup;
    }
    scRet = SEC_E_OK;




Cleanup:

    if (ChallengeRequest != NULL)
    {
        ZwFreeVirtualMemory(
            NtCurrentProcess(),
            &ChallengeRequest,
            &ChallengeRequestSize,
            MEM_RELEASE
            );
    }

    if (ChallengeResponse != NULL)
    {
        LsaFreeReturnBuffer( ChallengeResponse );
    }

    if (!NT_SUCCESS(scRet))
    {
        if (AuthenticateMessage != NULL)
        {
            SecFree(AuthenticateMessage);
        }
        if (NtlmInitializeResponse != NULL)
        {
            SecFree(NtlmInitializeResponse);
        }
    }
    return(scRet);
}
/**
 * Detects whether a user is logged on.
 *
 * @returns true if logged in, false if not (or error).
 * @param   pUserInfo           Where to return the user information.
 * @param   pSession            The session to check.
 */
bool VBoxServiceVMInfoWinIsLoggedIn(PVBOXSERVICEVMINFOUSER pUserInfo, PLUID pSession)
{
    AssertPtrReturn(pUserInfo, false);
    if (!pSession)
        return false;

    PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
    NTSTATUS rcNt = LsaGetLogonSessionData(pSession, &pSessionData);
    if (rcNt != STATUS_SUCCESS)
    {
        ULONG ulError = LsaNtStatusToWinError(rcNt);
        switch (ulError)
        {
            case ERROR_NOT_ENOUGH_MEMORY:
                /* If we don't have enough memory it's hard to judge whether the specified user
                 * is logged in or not, so just assume he/she's not. */
                VBoxServiceVerbose(3, "Not enough memory to retrieve logon session data!\n");
                break;

            case ERROR_NO_SUCH_LOGON_SESSION:
                /* Skip session data which is not valid anymore because it may have been
                 * already terminated. */
                break;

            default:
                VBoxServiceError("LsaGetLogonSessionData failed with error %u\n", ulError);
                break;
        }
        if (pSessionData)
            LsaFreeReturnBuffer(pSessionData);
        return false;
    }
    if (!pSessionData)
    {
        VBoxServiceError("Invalid logon session data!\n");
        return false;
    }

    VBoxServiceVerbose(3, "Session data: Name=%ls, Session=%u, LogonID=%ld,%ld, LogonType=%ld\n",
                       pSessionData->UserName.Buffer,
                       pSessionData->Session,
                       pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart,
                       pSessionData->LogonType);

    /*
     * Only handle users which can login interactively or logged in
     * remotely over native RDP.
     */
    bool fFoundUser = false;
    DWORD dwErr = NO_ERROR;
    if (   IsValidSid(pSessionData->Sid)
        && (   (SECURITY_LOGON_TYPE)pSessionData->LogonType == Interactive
            || (SECURITY_LOGON_TYPE)pSessionData->LogonType == RemoteInteractive
            /* Note: We also need CachedInteractive in case Windows cached the credentials
             *       or just wants to reuse them! */
            || (SECURITY_LOGON_TYPE)pSessionData->LogonType == CachedInteractive))
    {
        VBoxServiceVerbose(3, "Session LogonType=%ld is supported -- looking up SID + type ...\n",
                           pSessionData->LogonType);

        /*
         * Copy out relevant data.
         */
        VBoxServiceVMInfoWinSafeCopy(pUserInfo->wszUser, sizeof(pUserInfo->wszUser),
                                     &pSessionData->UserName, "User name");
        VBoxServiceVMInfoWinSafeCopy(pUserInfo->wszAuthenticationPackage, sizeof(pUserInfo->wszAuthenticationPackage),
                                     &pSessionData->AuthenticationPackage, "Authentication pkg name");
        VBoxServiceVMInfoWinSafeCopy(pUserInfo->wszLogonDomain, sizeof(pUserInfo->wszLogonDomain),
                                     &pSessionData->LogonDomain, "Logon domain name");

        TCHAR           szOwnerName[_MAX_PATH]  = { 0 };
        DWORD           dwOwnerNameSize         = sizeof(szOwnerName);
        TCHAR           szDomainName[_MAX_PATH] = { 0 };
        DWORD           dwDomainNameSize        = sizeof(szDomainName);
        SID_NAME_USE    enmOwnerType            = SidTypeInvalid;
        if (!LookupAccountSid(NULL,
                              pSessionData->Sid,
                              szOwnerName,
                              &dwOwnerNameSize,
                              szDomainName,
                              &dwDomainNameSize,
                              &enmOwnerType))
        {
            DWORD dwErr = GetLastError();
            /*
             * If a network time-out prevents the function from finding the name or
             * if a SID that does not have a corresponding account name (such as a
             * logon SID that identifies a logon session), we get ERROR_NONE_MAPPED
             * here that we just skip.
             */
            if (dwErr != ERROR_NONE_MAPPED)
                VBoxServiceError("Failed looking up account info for user=%ls, error=$ld!\n",
                                 pUserInfo->wszUser, dwErr);
        }
        else
        {
            if (enmOwnerType == SidTypeUser) /* Only recognize users; we don't care about the rest! */
            {
                VBoxServiceVerbose(3, "Account User=%ls, Session=%ld, LogonID=%ld,%ld, AuthPkg=%ls, Domain=%ls\n",
                                   pUserInfo->wszUser, pSessionData->Session, pSessionData->LogonId.HighPart,
                                   pSessionData->LogonId.LowPart, pUserInfo->wszAuthenticationPackage,
                                   pUserInfo->wszLogonDomain);

                /* Detect RDP sessions as well. */
                LPTSTR  pBuffer = NULL;
                DWORD   cbRet   = 0;
                int     iState  = -1;
                if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
                                               pSessionData->Session,
                                               WTSConnectState,
                                               &pBuffer,
                                               &cbRet))
                {
                    if (cbRet)
                        iState = *pBuffer;
                    VBoxServiceVerbose(3, "Account User=%ls, WTSConnectState=%d (%ld)\n",
                                       pUserInfo->wszUser, iState, cbRet);
                    if (    iState == WTSActive           /* User logged on to WinStation. */
                         || iState == WTSShadow           /* Shadowing another WinStation. */
                         || iState == WTSDisconnected)    /* WinStation logged on without client. */
                    {
                        /** @todo On Vista and W2K, always "old" user name are still
                         *        there. Filter out the old one! */
                        VBoxServiceVerbose(3, "Account User=%ls using TCS/RDP, state=%d \n",
                                           pUserInfo->wszUser, iState);
                        fFoundUser = true;
                    }
                    if (pBuffer)
                        WTSFreeMemory(pBuffer);
                }
                else
                {
                    DWORD dwLastErr = GetLastError();
                    switch (dwLastErr)
                    {
                        /*
                         * Terminal services don't run (for example in W2K,
                         * nothing to worry about ...).  ... or is on the Vista
                         * fast user switching page!
                         */
                        case ERROR_CTX_WINSTATION_NOT_FOUND:
                            VBoxServiceVerbose(3, "No WinStation found for user=%ls\n",
                                               pUserInfo->wszUser);
                            break;

                        default:
                            VBoxServiceVerbose(3, "Cannot query WTS connection state for user=%ls, error=%ld\n",
                                               pUserInfo->wszUser, dwLastErr);
                            break;
                    }

                    fFoundUser = true;
                }
            }
            else
                VBoxServiceVerbose(3, "SID owner type=%d not handled, skipping\n",
                                   enmOwnerType);
        }

        VBoxServiceVerbose(3, "Account User=%ls %s logged in\n",
                           pUserInfo->wszUser, fFoundUser ? "is" : "is not");
    }

    LsaFreeReturnBuffer(pSessionData);
    return fFoundUser;
}
Пример #20
0
/*
 * @implemented
 */
BOOL
WINAPI
LogonUserExW(
    _In_ LPWSTR lpszUsername,
    _In_opt_ LPWSTR lpszDomain,
    _In_opt_ LPWSTR lpszPassword,
    _In_ DWORD dwLogonType,
    _In_ DWORD dwLogonProvider,
    _Out_opt_ PHANDLE phToken,
    _Out_opt_ PSID *ppLogonSid,
    _Out_opt_ PVOID *ppProfileBuffer,
    _Out_opt_ LPDWORD pdwProfileLength,
    _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
{
    SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
    SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
    PSID LogonSid = NULL;
    PSID LocalSid = NULL;
    LSA_STRING OriginName;
    UNICODE_STRING DomainName;
    UNICODE_STRING UserName;
    UNICODE_STRING Password;
    PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
    ULONG AuthInfoLength;
    ULONG_PTR Ptr;
    TOKEN_SOURCE TokenSource;
    PTOKEN_GROUPS TokenGroups = NULL;
    PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
    ULONG ProfileBufferLength = 0;
    LUID Luid = {0, 0};
    LUID LogonId = {0, 0};
    HANDLE TokenHandle = NULL;
    QUOTA_LIMITS QuotaLimits;
    SECURITY_LOGON_TYPE LogonType;
    NTSTATUS SubStatus = STATUS_SUCCESS;
    NTSTATUS Status;

    *phToken = NULL;

    switch (dwLogonType)
    {
        case LOGON32_LOGON_INTERACTIVE:
            LogonType = Interactive;
            break;

        case LOGON32_LOGON_NETWORK:
            LogonType = Network;
            break;

        case LOGON32_LOGON_BATCH:
            LogonType = Batch;
            break;

        case LOGON32_LOGON_SERVICE:
            LogonType = Service;
            break;

       default:
            ERR("Invalid logon type: %ul\n", dwLogonType);
            Status = STATUS_INVALID_PARAMETER;
            goto done;
    }

    if (LsaHandle == NULL)
    {
        Status = OpenLogonLsaHandle();
        if (!NT_SUCCESS(Status))
            goto done;
    }

    RtlInitAnsiString((PANSI_STRING)&OriginName,
                      "Advapi32 Logon");

    RtlInitUnicodeString(&DomainName,
                         lpszDomain);

    RtlInitUnicodeString(&UserName,
                         lpszUsername);

    RtlInitUnicodeString(&Password,
                         lpszPassword);

    AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
                     DomainName.MaximumLength +
                     UserName.MaximumLength +
                     Password.MaximumLength;

    AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
                               HEAP_ZERO_MEMORY,
                               AuthInfoLength);
    if (AuthInfo == NULL)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto done;
    }

    AuthInfo->MessageType = MsV1_0InteractiveLogon;

    Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);

    AuthInfo->LogonDomainName.Length = DomainName.Length;
    AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
    AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
    if (DomainName.MaximumLength > 0)
    {
        RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
                      DomainName.Buffer,
                      DomainName.MaximumLength);

        Ptr += DomainName.MaximumLength;
    }

    AuthInfo->UserName.Length = UserName.Length;
    AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
    AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
    if (UserName.MaximumLength > 0)
        RtlCopyMemory(AuthInfo->UserName.Buffer,
                      UserName.Buffer,
                      UserName.MaximumLength);

    Ptr += UserName.MaximumLength;

    AuthInfo->Password.Length = Password.Length;
    AuthInfo->Password.MaximumLength = Password.MaximumLength;
    AuthInfo->Password.Buffer = (PWCHAR)Ptr;
    if (Password.MaximumLength > 0)
        RtlCopyMemory(AuthInfo->Password.Buffer,
                      Password.Buffer,
                      Password.MaximumLength);

    /* Create the Logon SID*/
    AllocateLocallyUniqueId(&LogonId);
    Status = RtlAllocateAndInitializeSid(&SystemAuthority,
                                         SECURITY_LOGON_IDS_RID_COUNT,
                                         SECURITY_LOGON_IDS_RID,
                                         LogonId.HighPart,
                                         LogonId.LowPart,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         &LogonSid);
    if (!NT_SUCCESS(Status))
        goto done;

    /* Create the Local SID*/
    Status = RtlAllocateAndInitializeSid(&LocalAuthority,
                                         1,
                                         SECURITY_LOCAL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         SECURITY_NULL_RID,
                                         &LocalSid);
    if (!NT_SUCCESS(Status))
        goto done;

    /* Allocate and set the token groups */
    TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
                                  HEAP_ZERO_MEMORY,
                                  sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
    if (TokenGroups == NULL)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto done;
    }

    TokenGroups->GroupCount = 2;
    TokenGroups->Groups[0].Sid = LogonSid;
    TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
                                        SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
    TokenGroups->Groups[1].Sid = LocalSid;
    TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
                                        SE_GROUP_ENABLED_BY_DEFAULT;

    /* Set the token source */
    strncpy(TokenSource.SourceName, "Advapi  ", sizeof(TokenSource.SourceName));
    AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);

    Status = LsaLogonUser(LsaHandle,
                          &OriginName,
                          LogonType,
                          AuthenticationPackage,
                          (PVOID)AuthInfo,
                          AuthInfoLength,
                          TokenGroups,
                          &TokenSource,
                          (PVOID*)&ProfileBuffer,
                          &ProfileBufferLength,
                          &Luid,
                          &TokenHandle,
                          &QuotaLimits,
                          &SubStatus);
    if (!NT_SUCCESS(Status))
    {
        ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
        goto done;
    }

    if (ProfileBuffer != NULL)
    {
        TRACE("ProfileBuffer: %p\n", ProfileBuffer);
        TRACE("MessageType: %u\n", ProfileBuffer->MessageType);

        TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
        TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);

        TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
        TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
    }

    TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);

    if (TokenHandle != NULL)
    {
        TRACE("TokenHandle: %p\n", TokenHandle);
    }

    *phToken = TokenHandle;

    /* FIXME: return ppLogonSid, ppProfileBuffer, pdwProfileLength and pQuotaLimits */

done:
    if (ProfileBuffer != NULL)
        LsaFreeReturnBuffer(ProfileBuffer);

    if (!NT_SUCCESS(Status))
    {
        if (TokenHandle != NULL)
            CloseHandle(TokenHandle);
    }

    if (TokenGroups != NULL)
        RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);

    if (LocalSid != NULL)
        RtlFreeSid(LocalSid);

    if (LogonSid != NULL)
        RtlFreeSid(LogonSid);

    if (AuthInfo != NULL)
        RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);

    if (!NT_SUCCESS(Status))
    {
        SetLastError(RtlNtStatusToDosError(Status));
        return FALSE;
    }

    return TRUE;
}
Пример #21
0
static BOOL
GetLSAPrincipalName(char * pszUser, DWORD dwUserSize)
{
    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
    PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
    ULONG ResponseSize;
    PKERB_EXTERNAL_NAME pClientName = NULL;
    PUNICODE_STRING     pDomainName = NULL;
    LSA_STRING Name;
    HANDLE hLogon = INVALID_HANDLE_VALUE;
    ULONG PackageId;
    NTSTATUS ntStatus;
    NTSTATUS ntSubStatus = 0;
    WCHAR * wchUser = NULL;
    DWORD   dwSize;
    SHORT   sCount;
    BOOL bRet = FALSE;

    ntStatus = LsaConnectUntrusted( &hLogon);
    if (FAILED(ntStatus))
        goto cleanup;

    Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
    Name.Length = (USHORT)(sizeof(MICROSOFT_KERBEROS_NAME_A) - sizeof(char));
    Name.MaximumLength = Name.Length;

    ntStatus = LsaLookupAuthenticationPackage( hLogon, &Name, &PackageId);
    if (FAILED(ntStatus))
        goto cleanup;

    memset(&CacheRequest, 0, sizeof(KERB_QUERY_TKT_CACHE_REQUEST));
    CacheRequest.MessageType = KerbRetrieveTicketMessage;
    CacheRequest.LogonId.LowPart = 0;
    CacheRequest.LogonId.HighPart = 0;

    ntStatus = LsaCallAuthenticationPackage( hLogon,
                                             PackageId,
                                             &CacheRequest,
                                             sizeof(CacheRequest),
                                             &pTicketResponse,
                                             &ResponseSize,
                                             &ntSubStatus);
    if (FAILED(ntStatus) || FAILED(ntSubStatus))
        goto cleanup;

    /* We have a ticket in the response */
    pClientName = pTicketResponse->Ticket.ClientName;
    pDomainName = &pTicketResponse->Ticket.DomainName;

    /* We want to return ClientName @ DomainName */

    dwSize = 0;
    for ( sCount = 0; sCount < pClientName->NameCount; sCount++)
    {
        dwSize += pClientName->Names[sCount].Length;
    }
    dwSize += pDomainName->Length + sizeof(WCHAR);

    if ( dwSize / sizeof(WCHAR) > dwUserSize )
        goto cleanup;

    wchUser = malloc(dwSize);
    if (wchUser == NULL)
        goto cleanup;

    for ( sCount = 0, wchUser[0] = L'\0'; sCount < pClientName->NameCount; sCount++)
    {
        StringCbCatNW( wchUser, dwSize,
                       pClientName->Names[sCount].Buffer,
                       pClientName->Names[sCount].Length);
    }
    StringCbCatNW( wchUser, dwSize,
                   pDomainName->Buffer,
                   pDomainName->Length);

    if ( !UnicodeToANSI( wchUser, pszUser, dwUserSize) )
        goto cleanup;

    bRet = TRUE;

  cleanup:

    if (wchUser)
        free(wchUser);

    if ( hLogon != INVALID_HANDLE_VALUE)
        LsaDeregisterLogonProcess(hLogon);

    if ( pTicketResponse ) {
        SecureZeroMemory(pTicketResponse,ResponseSize);
        LsaFreeReturnBuffer(pTicketResponse);
    }

    return bRet;
}
/**
 * Determines whether the specified session has processes on the system.
 *
 * @returns Number of processes found for a specified session.
 * @param   pSession        The session.
 * @param   paProcs         The process snapshot.
 * @param   cProcs          The number of processes in the snaphot.
 * @param   puSession       Looked up session number.  Optional.
 */
uint32_t VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession,
                                                 PVBOXSERVICEVMINFOPROC const paProcs, DWORD cProcs,
                                                 PULONG puSession)
{
    if (!pSession)
    {
        VBoxServiceVerbose(1, "Session became invalid while enumerating!\n");
        return 0;
    }

    PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
    NTSTATUS rcNt = LsaGetLogonSessionData(pSession, &pSessionData);
    if (rcNt != STATUS_SUCCESS)
    {
        VBoxServiceError("Could not get logon session data! rcNt=%#x", rcNt);
        return 0;
    }

    /*
     * Even if a user seems to be logged in, it could be a stale/orphaned logon
     * session. So check if we have some processes bound to it by comparing the
     * session <-> process LUIDs.
     */
    uint32_t cNumProcs = 0;
    for (DWORD i = 0; i < cProcs; i++)
    {
        VBoxServiceVerbose(4, "PID=%ld: (Interactive: %RTbool) %ld:%ld <-> %ld:%ld\n",
                           paProcs[i].id,                  paProcs[i].fInteractive,
                           paProcs[i].luid.HighPart,       paProcs[i].luid.LowPart,
                           pSessionData->LogonId.HighPart, pSessionData->LogonId.LowPart);
        if (g_cVerbosity)
        {
            TCHAR szModule[_1K];
            int rc2 = VBoxServiceVMInfoWinProcessesGetModuleName(&paProcs[i], szModule, sizeof(szModule));
            if (RT_SUCCESS(rc2))
                VBoxServiceVerbose(4, "PID=%ld: %s\n",
                                   paProcs[i].id, szModule);
        }

        if (   paProcs[i].fInteractive
            && (   paProcs[i].luid.HighPart == pSessionData->LogonId.HighPart
                && paProcs[i].luid.LowPart  == pSessionData->LogonId.LowPart))
        {
            cNumProcs++;
            if (!g_cVerbosity) /* We want a bit more info on higher verbosity. */
                break;
        }
    }

    if (g_cVerbosity)
        VBoxServiceVerbose(3, "Session %u has %u processes total\n",
                           pSessionData->Session, cNumProcs);
    else
        VBoxServiceVerbose(3, "Session %u has at least one process\n",
                           pSessionData->Session);

    if (puSession)
        *puSession = pSessionData->Session;

    LsaFreeReturnBuffer(pSessionData);
    return cNumProcs;
}
Пример #23
0
/* Get domain specific configuration info.  We are returning void because if anything goes wrong
   we just return defaults.
 */
void 
GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
    HKEY hkParm = NULL; /* Service parameter */
    HKEY hkNp = NULL;   /* network provider key */
    HKEY hkDoms = NULL; /* domains key */
    HKEY hkDom = NULL;  /* DOMAINS/domain key */
    HKEY hkTemp = NULL;
    LONG rv;
    DWORD dwSize;
    DWORD dwType;
    DWORD dwDummy;
    char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
    char *effDomain = NULL;

    memset(opt, 0, sizeof(LogonOptions_t));

    DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
    /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
    opt->flags = LOGON_FLAG_REMOTE;
    if(domain) {
        dwSize = MAX_COMPUTERNAME_LENGTH + 1;
        if(GetComputerName(computerName, &dwSize)) {
            if(!cm_stricmp_utf8(computerName, domain)) {
                effDomain = "LOCALHOST";
                opt->flags = LOGON_FLAG_LOCAL;
            }
        }
        if (effDomain == NULL)
            effDomain = domain;
    }

    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
    if(rv != ERROR_SUCCESS) {
        hkParm = NULL;
        DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
    }

    rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
    if(rv != ERROR_SUCCESS) {
        hkNp = NULL;
        DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
    }

    if(hkNp) {
        rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
        if( rv != ERROR_SUCCESS ) {
            hkDoms = NULL;
            DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
        }
    }

    if(hkDoms && effDomain) {
        rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
        if( rv != ERROR_SUCCESS ) {
            hkDom = NULL;
            DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
            /* If none of the domains match, we shouldn't use the domain key either */
            RegCloseKey(hkDoms);
            hkDoms = NULL;
        }
    } else
        DebugEvent0("Not opening domain key");

    /* Each individual can either be specified on the domain key, the domains key or in the
       net provider key.  They fail over in that order.  If none is found, we just use the 
       defaults. */

    /* LogonOption */
    LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);

    /* FailLoginsSilently */
    dwSize = sizeof(dwDummy);
    rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
    if (rv != ERROR_SUCCESS)
        LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
    opt->failSilently = dwDummy ? 1 :0;

    /* Retry interval */
    LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);

    /* Sleep interval */
    LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);

    if(!ISLOGONINTEGRATED(opt->LogonOption)) {
        DebugEvent0("Integrated logon disabled");
        goto cleanup; /* no need to lookup the logon script */
    }

    /* come up with SMB username */
    if(ISHIGHSECURITY(opt->LogonOption)) {
        DebugEvent0("High Security Mode active");
        opt->smbName = malloc( MAXRANDOMNAMELEN );
        if (opt->smbName == NULL)
            goto cleanup;
        GenRandomName(opt->smbName);
    } else if (lpLogonId) {
        /* username and domain for logon session is not necessarily the same as
           username and domain passed into network provider. */
        PSECURITY_LOGON_SESSION_DATA plsd=NULL;
        char lsaUsername[MAX_USERNAME_LENGTH]="";
        char lsaDomain[MAX_DOMAIN_LENGTH]="";
        size_t len, tlen;
        NTSTATUS Status;

        Status = LsaGetLogonSessionData(lpLogonId, &plsd);
        if ( FAILED(Status) || plsd == NULL ) {
            DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
            goto bad_strings;
        }
        
        if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
            goto bad_strings;

        if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
            goto bad_strings;

        DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);

        if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
            len = tlen;
        else
            goto bad_strings;

        if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
            len += tlen;
        else
            goto bad_strings;

        len += 2;

        opt->smbName = malloc(len);
        if (opt->smbName == NULL)
            goto cleanup;

        StringCbCopy(opt->smbName, len, lsaDomain);
        StringCbCat(opt->smbName, len, "\\");
        StringCbCat(opt->smbName, len, lsaUsername);

        strlwr(opt->smbName);

      bad_strings:
        if (plsd)
            LsaFreeReturnBuffer(plsd);
    }
    if (opt->smbName == NULL) {
        size_t len;

        DebugEvent("Constructing username using [%s] and [%s]",
                   username, domain);
 
        len = strlen(username) + strlen(domain) + 2;

        opt->smbName = malloc(len);
        if (opt->smbName == NULL)
            goto cleanup;

        StringCbCopy(opt->smbName, len, domain);
        StringCbCat(opt->smbName, len, "\\");
        StringCbCat(opt->smbName, len, username);

        strlwr(opt->smbName);
    }

    DebugEvent0("Looking up logon script");
    /* Logon script */
    /* First find out where the key is */
    hkTemp = NULL;
    rv = ~ERROR_SUCCESS;
    dwType = 0;
    if(hkDom)
        rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
    if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
        hkTemp = hkDom;
        DebugEvent0("Located logon script in hkDom");
    }
    else if(hkDoms) {
        rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
        if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
            hkTemp = hkDoms;
            DebugEvent0("Located logon script in hkDoms");
        }
        /* Note that the LogonScript in the NP key is only used if we are doing high security. */
        else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
            rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
            if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
                hkTemp = hkNp;
                DebugEvent0("Located logon script in hkNp");
            }
        }
    }

    if(hkTemp) {
        WCHAR *regscript	= NULL;
        WCHAR *regexscript	= NULL;
        WCHAR *regexuscript	= NULL;
        WCHAR *wuname		= NULL;
        HRESULT hr;

        size_t len;

        StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
        len ++;

        wuname = malloc(len * sizeof(WCHAR));
        if (!wuname)
            goto doneLogonScript;
        MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));

        DebugEvent("Username is set for [%S]", wuname);

        /* dwSize still has the size of the required buffer in bytes. */
        regscript = malloc(dwSize);
        if (!regscript)
            goto doneLogonScript;
        rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
        if(rv != ERROR_SUCCESS) {/* what the ..? */
            DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
            goto doneLogonScript;
        }

        DebugEvent("Found logon script [%S]", regscript);

        if(dwType == REG_EXPAND_SZ) {
            DWORD dwReq;

            dwSize += MAX_PATH * sizeof(WCHAR);  /* make room for environment expansion. */
            regexscript = malloc(dwSize);
            if (!regexscript)
                goto doneLogonScript;
            dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
            free(regscript);
            regscript = regexscript;
            regexscript = NULL;
            if(dwReq > (dwSize / sizeof(WCHAR))) {
                DebugEvent0("Overflow while expanding environment strings.");
                goto doneLogonScript;
            }
        }

        DebugEvent("After expanding env strings [%S]", regscript);

        if(wcsstr(regscript, L"%s")) {
            dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
            regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
            if (!regexuscript)
                goto doneLogonScript;
            hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
        } else {
            regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
            if (!regexuscript)
                goto doneLogonScript;
            hr = StringCbCopyW(regexuscript, dwSize, regscript);
        }

        DebugEvent("After expanding username [%S]", regexuscript);

        if(hr == S_OK)
            opt->logonScript = regexuscript;
        else
            LocalFree(regexuscript);

      doneLogonScript:
        if(wuname) free(wuname);
        if(regscript) free(regscript);
        if(regexscript) free(regexscript);
    }

    DebugEvent0("Looking up TheseCells");
    /* TheseCells */
    /* First find out where the key is */
    hkTemp = NULL;
    rv = ~ERROR_SUCCESS;
    dwSize = 0;
    if (hkDom)
        rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
    if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
        hkTemp = hkDom;
        DebugEvent("Located TheseCells in hkDom size %d", dwSize);
    } else if (hkDoms) {
        rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
        if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
            hkTemp = hkDoms;
            DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
        } else if (hkNp) {
            rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
            if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
                hkTemp = hkNp;
                DebugEvent("Located TheseCells in hkNp size %d", dwSize);
            }
        }
    }

    if (hkTemp) {
        CHAR * thesecells = NULL;

        /* dwSize still has the size of the required buffer in bytes. */
        thesecells = malloc(dwSize*2);
        if (!thesecells)
            goto doneTheseCells;
        dwSize *= 2;
        SetLastError(0);
        rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
        if(rv != ERROR_SUCCESS) {/* what the ..? */
            DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
            goto doneTheseCells;
        }

        DebugEvent("Found TheseCells [%s]", thesecells);
        opt->theseCells = thesecells;
        thesecells = NULL;

      doneTheseCells:
        if (thesecells) free(thesecells);
    }

    DebugEvent0("Looking up Realm");
    /* Realm */
    /* First find out where the key is */
    hkTemp = NULL;
    rv = ~ERROR_SUCCESS;
    dwSize = 0;
    if (hkDom)
        rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
    if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
        hkTemp = hkDom;
        DebugEvent("Located Realm in hkDom size %d", dwSize);
    } else if (hkDoms) {
        rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
        if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
            hkTemp = hkDoms;
            DebugEvent("Located Realm in hkDoms size %d", dwSize);
        } else if (hkNp) {
            rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
            if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
                hkTemp = hkNp;
                DebugEvent("Located Realm in hkNp size %d", dwSize);
            }
        }
    }

    if (hkTemp) {
        CHAR * realm = NULL;

        /* dwSize still has the size of the required buffer in bytes. */
        realm = malloc(dwSize*2);
        if (!realm)
            goto doneRealm;
        dwSize *=2;
        SetLastError(0);
        rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
        if(rv != ERROR_SUCCESS) {/* what the ..? */
            DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
            goto doneRealm;
        }

        DebugEvent("Found Realm [%s]", realm);
        opt->realm = realm;
        realm = NULL;

      doneRealm:
        if (realm) free(realm);
    }

  cleanup:
    if(hkNp) RegCloseKey(hkNp);
    if(hkDom) RegCloseKey(hkDom);
    if(hkDoms) RegCloseKey(hkDoms);
    if(hkParm) RegCloseKey(hkParm);
}       
/**
 * Retrieves the currently logged in users and stores their names along with the
 * user count.
 *
 * @returns VBox status code.
 * @param   ppszUserList    Where to store the user list (separated by commas).
 *                          Must be freed with RTStrFree().
 * @param   pcUsersInList   Where to store the number of users in the list.
 */
int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList)
{
    PLUID       paSessions = NULL;
    ULONG       cSessions = 0;

    /* This function can report stale or orphaned interactive logon sessions
       of already logged off users (especially in Windows 2000). */
    NTSTATUS rcNt = LsaEnumerateLogonSessions(&cSessions, &paSessions);
    if (rcNt != STATUS_SUCCESS)
    {
        ULONG ulError = LsaNtStatusToWinError(rcNt);
        switch (ulError)
        {
            case ERROR_NOT_ENOUGH_MEMORY:
                VBoxServiceError("Not enough memory to enumerate logon sessions!\n");
                break;

            case ERROR_SHUTDOWN_IN_PROGRESS:
                /* If we're about to shutdown when we were in the middle of enumerating the logon
                 * sessions, skip the error to not confuse the user with an unnecessary log message. */
                VBoxServiceVerbose(3, "Shutdown in progress ...\n");
                ulError = ERROR_SUCCESS;
                break;

            default:
                VBoxServiceError("LsaEnumerate failed with error %u\n", ulError);
                break;
        }

        return RTErrConvertFromWin32(ulError);
    }
    VBoxServiceVerbose(3, "Found %ld sessions\n", cSessions);

    PVBOXSERVICEVMINFOPROC  paProcs;
    DWORD                   cProcs;
    int rc = VBoxServiceVMInfoWinProcessesEnumerate(&paProcs, &cProcs);
    if (RT_FAILURE(rc))
    {
        if (rc == VERR_NO_MEMORY)
            VBoxServiceError("Not enough memory to enumerate processes\n");
        else
            VBoxServiceError("Failed to enumerate processes, rc=%Rrc\n", rc);
    }
    else
    {
        PVBOXSERVICEVMINFOUSER pUserInfo;
        pUserInfo = (PVBOXSERVICEVMINFOUSER)RTMemAllocZ(cSessions * sizeof(VBOXSERVICEVMINFOUSER) + 1);
        if (!pUserInfo)
            VBoxServiceError("Not enough memory to store enumerated users!\n");
        else
        {
            ULONG cUniqueUsers = 0;
            for (ULONG i = 0; i < cSessions; i++)
            {
                VBoxServiceVerbose(3, "Handling session %u\n", i);

                VBOXSERVICEVMINFOUSER UserInfo;
                if (VBoxServiceVMInfoWinIsLoggedIn(&UserInfo, &paSessions[i]))
                {
                    VBoxServiceVerbose(4, "Handling user=%ls, domain=%ls, package=%ls\n",
                                       UserInfo.wszUser, UserInfo.wszLogonDomain, UserInfo.wszAuthenticationPackage);

                    /* Retrieve assigned processes of current session. */
                    ULONG ulSession;
                    uint32_t cSessionProcs = VBoxServiceVMInfoWinSessionHasProcesses(&paSessions[i], paProcs, cProcs, &ulSession);
                    /* Don't return here when current session does not have assigned processes
                     * anymore -- in that case we have to search through the unique users list below
                     * and see if got a stale user/session entry. */

                    bool fFoundUser = false;
                    for (ULONG i = 0; i < cUniqueUsers; i++)
                    {
                        if (   !wcscmp(UserInfo.wszUser, pUserInfo[i].wszUser)
                            && !wcscmp(UserInfo.wszLogonDomain, pUserInfo[i].wszLogonDomain)
                            && !wcscmp(UserInfo.wszAuthenticationPackage, pUserInfo[i].wszAuthenticationPackage)
                            && cSessionProcs)
                        {
                            /*
                             * Only respect the highest session for the current user.
                             */
                            if (ulSession > pUserInfo[i].ulSession)
                            {
                                VBoxServiceVerbose(4, "Updating user=%ls to %u processes (last session: %u)\n",
                                                   UserInfo.wszUser, cSessionProcs, ulSession);

                                pUserInfo[i].ulNumProcs = cSessionProcs;
                                pUserInfo[i].ulSession  = ulSession;

                                if (!cSessionProcs)
                                    VBoxServiceVerbose(3, "Stale session for user=%ls detected! Old processes: %u, new: %u\n",
                                                       pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, cSessionProcs);
                            }
                            /* There can be multiple session objects using the same session ID for the
                             * current user -- so when we got the same session again just add the found
                             * processes to it. */
                            else if (pUserInfo[i].ulSession == ulSession)
                            {
                                VBoxServiceVerbose(4, "Adding %u processes to user=%ls (session %u)\n",
                                                   cSessionProcs, UserInfo.wszUser, ulSession);

                                pUserInfo[i].ulNumProcs += cSessionProcs;
                                pUserInfo[i].ulSession   = ulSession;
                            }

                            fFoundUser = true;
                            break;
                        }
                    }

                    if (!fFoundUser)
                    {
                        VBoxServiceVerbose(4, "Adding new user=%ls (session %u) with %u processes\n",
                                           UserInfo.wszUser, ulSession, cSessionProcs);

                        memcpy(&pUserInfo[cUniqueUsers], &UserInfo, sizeof(VBOXSERVICEVMINFOUSER));
                        pUserInfo[cUniqueUsers].ulNumProcs = cSessionProcs;
                        pUserInfo[cUniqueUsers].ulSession  = ulSession;
                        cUniqueUsers++;
                        Assert(cUniqueUsers <= cSessions);
                    }
                }
            }

            VBoxServiceVerbose(3, "Found %u unique logged-in user(s)\n",
                               cUniqueUsers);

            *pcUsersInList = 0;
            for (ULONG i = 0; i < cUniqueUsers; i++)
            {
                if (pUserInfo[i].ulNumProcs)
                {
                    VBoxServiceVerbose(3, "User %ls has %ld processes (session %u)\n",
                                       pUserInfo[i].wszUser, pUserInfo[i].ulNumProcs, pUserInfo[i].ulSession);

                    if (*pcUsersInList > 0)
                    {
                        rc = RTStrAAppend(ppszUserList, ",");
                        AssertRCBreakStmt(rc, RTStrFree(*ppszUserList));
                    }

                    *pcUsersInList += 1;

                    char *pszTemp;
                    int rc2 = RTUtf16ToUtf8(pUserInfo[i].wszUser, &pszTemp);
                    if (RT_SUCCESS(rc2))
                    {
                        rc = RTStrAAppend(ppszUserList, pszTemp);
                        RTMemFree(pszTemp);
                    }
                    else
                        rc = RTStrAAppend(ppszUserList, "<string-conversion-error>");
                    AssertRCBreakStmt(rc, RTStrFree(*ppszUserList));
                }
            }

            RTMemFree(pUserInfo);
        }
        VBoxServiceVMInfoWinProcessesFree(paProcs);
    }
    LsaFreeReturnBuffer(paSessions);
    return rc;
}
Пример #25
0
BOOL 
ShowTickets(
    HANDLE LogonHandle,
    ULONG PackageId,
    DWORD dwMode
    )
{
    NTSTATUS Status;
    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
    PKERB_QUERY_TKT_CACHE_RESPONSE CacheResponse = NULL;
    ULONG ResponseSize;
    NTSTATUS SubStatus;
    ULONG Index;
    int ch;

    CacheRequest.MessageType = KerbQueryTicketCacheMessage;
    CacheRequest.LogonId.LowPart = 0;
    CacheRequest.LogonId.HighPart = 0;

    Status = LsaCallAuthenticationPackage(
                LogonHandle,
                PackageId,
                &CacheRequest,
                sizeof(CacheRequest),
                (PVOID *) &CacheResponse,
                &ResponseSize,
                &SubStatus
                );
    if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
    {
        ShowNTError("LsaCallAuthenticationPackage", Status);
        printf("Substatus: 0x%x\n",SubStatus);
        return FALSE;
    }

    printf("\nCached Tickets: (%lu)\n", CacheResponse->CountOfTickets);
    for (Index = 0; Index < CacheResponse->CountOfTickets ; Index++ )
    {
        printf("\n   Server: %wZ@%wZ\n",
            &CacheResponse->Tickets[Index].ServerName,
            &CacheResponse->Tickets[Index].RealmName);
        printf("      ");
        PrintEType(CacheResponse->Tickets[Index].EncryptionType);
        PrintTime("      End Time: ",CacheResponse->Tickets[Index].EndTime);
        PrintTime("      Renew Time: ",CacheResponse->Tickets[Index].RenewTime);
        printf("      TicketFlags: (0x%x) ", CacheResponse->Tickets[Index].TicketFlags);
        PrintTktFlags(CacheResponse->Tickets[Index].TicketFlags);
        printf("\n");

        if(dwMode == INTERACTIVE_PURGE)
        {
            printf("Purge? (y/n/q) : ");
            ch = _getche();
            if(ch == 'y' || ch == 'Y')
            {
                printf("\n");
                PurgeTicket( 
                    LogonHandle,
                    PackageId,
                    CacheResponse->Tickets[Index].ServerName.Buffer,
                    CacheResponse->Tickets[Index].ServerName.Length,
                    CacheResponse->Tickets[Index].RealmName.Buffer,
                    CacheResponse->Tickets[Index].RealmName.Length
                    );
            }
            else if(ch == 'q' || ch == 'Q')
                goto cleanup;
            else
                printf("\n\n");

        }
    }

cleanup:

    if (CacheResponse != NULL)
    {
        LsaFreeReturnBuffer(CacheResponse);
    }

    return TRUE;
}
Пример #26
0
BOOL 
ShowTgt(
    HANDLE LogonHandle,
    ULONG PackageId
    )
{
    NTSTATUS Status;
    KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
	PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL;
    PKERB_EXTERNAL_TICKET Ticket;
    ULONG ResponseSize;
    NTSTATUS SubStatus;
    BOOLEAN Trusted = TRUE;

    CacheRequest.MessageType = KerbRetrieveTicketMessage;
    CacheRequest.LogonId.LowPart = 0;
    CacheRequest.LogonId.HighPart = 0;

    Status = LsaCallAuthenticationPackage(
                LogonHandle,
                PackageId,
                &CacheRequest,
                sizeof(CacheRequest),
                (PVOID *) &TicketEntry,
                &ResponseSize,
                &SubStatus
                );

    if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
    {
        ShowNTError("LsaCallAuthenticationPackage", Status);
        printf("Substatus: 0x%x\n",SubStatus);
        return FALSE;
    }

    Ticket = &(TicketEntry->Ticket);

    printf("\nCached TGT:\n\n");

    printf("ServiceName: "); PrintKerbName(Ticket->ServiceName);

    printf("TargetName: "); PrintKerbName(Ticket->TargetName);

    printf("FullServiceName: "); PrintKerbName(Ticket->ClientName);

    printf("DomainName: %.*S\n",
        Ticket->DomainName.Length/sizeof(WCHAR),Ticket->DomainName.Buffer);

    printf("TargetDomainName: %.*S\n",
        Ticket->TargetDomainName.Length/sizeof(WCHAR),Ticket->TargetDomainName.Buffer);

    printf("AltTargetDomainName: %.*S\n",
        Ticket->AltTargetDomainName.Length/sizeof(WCHAR),Ticket->AltTargetDomainName.Buffer);
    
    printf("TicketFlags: (0x%x) ",Ticket->TicketFlags);
    PrintTktFlags(Ticket->TicketFlags);
    PrintTime("KeyExpirationTime: ",Ticket->KeyExpirationTime);
    PrintTime("StartTime: ",Ticket->StartTime);
    PrintTime("EndTime: ",Ticket->EndTime);
    PrintTime("RenewUntil: ",Ticket->RenewUntil);
    PrintTime("TimeSkew: ",Ticket->TimeSkew);
    PrintEType(Ticket->SessionKey.KeyType);


    if (TicketEntry != NULL)
    {
        LsaFreeReturnBuffer(TicketEntry);
    }

    return TRUE;
}
Пример #27
0
/*
 * Class:     sun_security_krb5_Credentials
 * Method:    acquireDefaultNativeCreds
 * Signature: ()Lsun/security/krb5/Credentials;
 */
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds(
		JNIEnv *env,
		jclass krbcredsClass) {

   HANDLE LogonHandle = NULL;
   ULONG PackageId;
	PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL;
	PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL;
	ULONG rspSize = 0;
	DWORD errorCode;
	NTSTATUS Status,SubStatus;
	PUCHAR pEncodedTicket = NULL;
	jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
	jobject ticketFlags, startTime, endTime, krbCreds = NULL;
   jobject authTime, renewTillTime, hostAddresses = NULL;
	UNICODE_STRING Target = {0};
	UNICODE_STRING Target2 = {0};
	PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL;
	WCHAR *tgtName = L"krbtgt";
	WCHAR *fullName;

	while (TRUE) {

	if (krbcredsConstructor == 0) {
		krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>", 
       "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
		if (krbcredsConstructor == 0) {
			printf("Couldn't find com.ibm.security.krb5.Credentials constructor\n");
			break;
		}
	}

	//printf("Found KrbCreds constructor\n");

    //
    // Get the logon handle and package ID from the
    // Kerberos package
    //
    if(!PackageConnectLookup(&LogonHandle, &PackageId))
        break;

	#ifdef DEBUG
	printf("Got handle to Kerberos package\n");
   #endif /* DEBUG */

	//InitUnicodeString(&Target2, L"krbtgt"); // this doesn't work 'cause I need the domain name too
	// OK, I don't give up that easily
	// Go get the current domain name
	errorCode = DsGetDcName(
					(LPCTSTR) NULL, // machine name
					(LPCTSTR) NULL, // DomainName, if NULL, I'm asking what it is
					(GUID *)  NULL, // DomainGuid,
					(LPCTSTR) NULL, // SiteName,
					DS_GC_SERVER_REQUIRED, //Flags
					&DomainControllerInfo);
	if (errorCode != NO_ERROR) {
		printf("DsGetDcName returned %d\n", errorCode);
		break;
	}

	#ifdef DEBUG
	printf("The domain name is %S\n", DomainControllerInfo->DomainName);
   #endif /* DEBUG */
	// Build a fully-qualified name
	fullName = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,((wcslen(tgtName)+wcslen(L"/")+wcslen(DomainControllerInfo->DomainName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL)));
	wcscat(fullName, tgtName);
	wcscat(fullName, L"/");
	wcscat(fullName, DomainControllerInfo->DomainName);
	#ifdef DEBUG
	printf("The fully-qualified name is %S\n", fullName);
   #endif /* DEBUG */
	InitUnicodeString(&Target2, fullName);       

    CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST)
            LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));

    CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage ;
 
    Target.Buffer = (LPWSTR) (CacheRequest + 1);
    Target.Length = Target2.Length;
    Target.MaximumLength = Target2.MaximumLength;

    CopyMemory(
        Target.Buffer,
        Target2.Buffer,
        Target2.Length
        );

    CacheRequest->TargetName = Target;	
    CacheRequest->EncryptionType = KERB_ETYPE_DES_CBC_MD5; // mdu

	Status = LsaCallAuthenticationPackage(
                LogonHandle,
                PackageId,
                CacheRequest,
                Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST),
                (PVOID *) &CacheResponse,
                &rspSize,
                &SubStatus
                );

	#ifdef DEBUG
	printf("Response size is %d\n", rspSize);
   #endif /* DEBUG */
	LocalFree(fullName);

	if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus))
    {
        if (!LSA_SUCCESS(Status)) {
			ShowNTError("LsaCallAuthenticationPackage", Status);
		}
		else {
			ShowNTError("Protocol status", SubStatus);
		}
		break;
    }

	// Now we need to skip over most of the junk in the buffer to get to the ticket
	// Here's what we're looking at...

/*

typedef struct _KERB_RETRIEVE_TKT_RESPONSE {
    KERB_EXTERNAL_TICKET Ticket;
} KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE;

typedef struct _KERB_EXTERNAL_TICKET {
    PKERB_EXTERNAL_NAME ServiceName;
    PKERB_EXTERNAL_NAME TargetName;
    PKERB_EXTERNAL_NAME ClientName;
    UNICODE_STRING DomainName;
    UNICODE_STRING TargetDomainName;
    UNICODE_STRING AltTargetDomainName;
    KERB_CRYPTO_KEY SessionKey;
    ULONG TicketFlags;
    ULONG Flags;
    LARGE_INTEGER KeyExpirationTime;
    LARGE_INTEGER StartTime;
    LARGE_INTEGER EndTime;
    LARGE_INTEGER RenewUntil;
    LARGE_INTEGER TimeSkew;
    ULONG EncodedTicketSize;
    PUCHAR EncodedTicket;					<========== Here's the good stuff
} KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET;

typedef struct _KERB_EXTERNAL_NAME {
    SHORT NameType;
    USHORT NameCount;
    UNICODE_STRING Names[ANYSIZE_ARRAY];
} KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME;

typedef struct _LSA_UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;

typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;

typedef struct KERB_CRYPTO_KEY {
    LONG KeyType;
    ULONG Length;
    PUCHAR Value;
} KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY;

*/

	// Build a com.ibm.security.krb5.Ticket
	ticket = BuildTicket(env, CacheResponse->Ticket.EncodedTicket, CacheResponse->Ticket.EncodedTicketSize);
	if (ticket == NULL) {
		break;
	}
	// OK, have a Ticket, now need to get the client name
	clientPrincipal = BuildClientPrincipal(env, CacheResponse->Ticket.ClientName); // mdu
	if (clientPrincipal == NULL) break;
	// and the "name" of tgt
	targetPrincipal = BuildTGSPrincipal(env, CacheResponse->Ticket.TargetDomainName); // mdu
	if (targetPrincipal == NULL) break;
	// Get the encryption key
	encryptionKey = BuildEncryptionKey(env, &(CacheResponse->Ticket.SessionKey));
	if (encryptionKey == NULL) break;
	// and the ticket flags
	ticketFlags = BuildTicketFlags(env, &(CacheResponse->Ticket.TicketFlags));
	if (ticketFlags == NULL) break;
	// Get the start time
	startTime = BuildKerberosTime(env, &(CacheResponse->Ticket.StartTime));
	if (startTime == NULL) break;
	/*
	 * mdu: No point storing the eky expiration time in the auth
	 * time field. Set it to be same as startTime. Looks like
	 * windows does not have post-dated tickets.
	 */
	authTime = startTime;
	// and the end time
	endTime = BuildKerberosTime(env, &(CacheResponse->Ticket.EndTime));
	if (endTime == NULL) break;
	// Get the renew till time
	renewTillTime = BuildKerberosTime(env, &(CacheResponse->Ticket.RenewUntil));
	if (renewTillTime == NULL) break;
	// and now go build a KrbCreds object
	krbCreds = (*env)->NewObject(
		env,
		krbcredsClass,
		krbcredsConstructor,
		ticket,
		clientPrincipal,
		targetPrincipal,
		encryptionKey,
		ticketFlags,
		authTime, // mdu
		startTime,
		endTime,
		renewTillTime, //mdu
		hostAddresses);
	break;
	} // end of WHILE

	if (DomainControllerInfo != NULL) {
		NetApiBufferFree(DomainControllerInfo);
	}
    if (CacheResponse != NULL) {
        LsaFreeReturnBuffer(CacheResponse);
    }
    if (CacheRequest) {
        LocalFree(CacheRequest);
    }
	return krbCreds;
}