static uint64_t generateLuid() {
  LUID luid;
  if (AllocateLocallyUniqueId(&luid)) {
    uint64_t id = luid.HighPart;
    return id << 32 | luid.LowPart;
  }
  throw std::system_error(
      GetLastError(), Win32ErrorCategory::get(), "Failed to generate the luid");
}
Exemple #2
0
/**
 * Creates MidpSession for the specified XRPC client id. Invoked on the XRPC
 * thread under synchronization.
 */
STATIC MidpSession* GWENG_MidpCreateSession(EcmtGateway* gw, int xrpcSid)
{
    MidpSession* ses = MEM_New(MidpSession);
    if (ses) {
        LUID luid;
        /* Just in case if AllocateLocallyUniqueId fails... */
        luid.LowPart = (DWORD)ses;
        AllocateLocallyUniqueId(&luid);
        memset(ses, 0, sizeof(*ses));
        ses->key.xrpcSid = xrpcSid;
        ses->key.xrpcSession = XRPC_GetCurrentSession(gw->xrpc);
        ses->sid = luid.LowPart;
        ASSERT(!HASH_Contains(&gw->ecmtSessionMap,(HashKey)ses->sid));
        ASSERT(!HASH_Contains(&gw->midpSessionMap,&ses->key));
        if (HASH_Init(&ses->connMap, 1, NULL, NULL, hashFreeValueProc)) {
            /* Create context for the control connection (number zero) */
            MidpConnection* conn = MEM_New(MidpConnection);
            if (conn) {
                memset(conn, 0, sizeof(*conn));
                if (HASH_Put(&ses->connMap, (HashKey)0, conn)) {
                    if (HASH_Put(&gw->ecmtSessionMap,(HashKey)ses->sid,ses)) {
                        if (HASH_Put(&gw->midpSessionMap, &ses->key, ses)) {
                            if (MUTEX_Init(&ses->xrpcMutex)) {
                                ses->xrpcWorkThread = WKQ_Create();
                                if (ses->xrpcWorkThread) {
                                    ses->xrpcWorkItem = WKI_Create(
                                        ses->xrpcWorkThread, GWENG_AsyncXRpc,
                                        ses);
                                    if (ses->xrpcWorkItem) {
                                        QUEUE_Init(&ses->xrpcQueue);
                                        TRACE3("GW: new session %08x for "
                                            "%08x.%08x\n", ses->sid,
                                            ses->key.xrpcSession,
                                            ses->key.xrpcSid);
                                        return ses;
                                    }
                                    WKQ_Delete(ses->xrpcWorkThread);
                                }
                                MUTEX_Destroy(&ses->xrpcMutex);
                            }
                            HASH_Remove(&gw->midpSessionMap, &ses->key);
                        }
                        HASH_Remove(&gw->ecmtSessionMap, (HashKey)ses->sid);
                    }
                } else {
                    MEM_Free(conn);
                }
            }
            HASH_Destroy(&ses->connMap);
        }
        MEM_Free(ses);
    }
    return NULL;
}
HANDLE CreateUserToken(const char *userName, 
                           const char *domainName, const char *sourceName)
{
  debug2("-> CreateUserToken()...");
  
  HMODULE hNtDll = NULL;
  
  NtCreateTokenPtr NtCreateToken = NULL;
  
  HANDLE token = INVALID_HANDLE_VALUE;
  
  /*
   * These are compounds of user's access token structure.
   * The goal is setup these strutures and combine them
   * into one access token using NtCreateToken() WINAPI function.
   */
  
  LUID authId = SYSTEM_LUID;
  
  TOKEN_USER userToken;

  PTOKEN_GROUPS groupsToken = NULL;
  
  PTOKEN_PRIVILEGES pPrivToken = NULL;
  
  TOKEN_OWNER ownerToken;
  
  TOKEN_PRIMARY_GROUP primaryGroupToken;

  TOKEN_SOURCE sourceToken;  
  
  PTOKEN_DEFAULT_DACL pDaclToken = NULL;
  
  LARGE_INTEGER expirationTime = {0xFFFFFFFF, 0x7FFFFFFF};
  
  OBJECT_ATTRIBUTES oa;
  
  /*
   * Temporary variables
   */
  
  SECURITY_QUALITY_OF_SERVICE sqos = 
  {
    sizeof(sqos), 
    SecurityAnonymous, 
    SECURITY_STATIC_TRACKING,
    FALSE
  };
    
  int i;
  
  size_t size = 0;
  
  wchar_t *userNameW = NULL;
  
  DWORD cbSize;
  
  HANDLE hProcToken = NULL;
  
  /*
   * Variables to handle error codes.
   */
  
  int exitCode = 1;
  int ntStat   = 0;
  
  /*
   * Make wide char version of user's name.
   */
  
  size = (strlen(userName) + 1) * sizeof(wchar_t);
  
  userNameW = (wchar_t *) LocalAlloc(LPTR, size);;

  swprintf(userNameW, L"%hs", userName);
  
  /*
   * Give needed privilege to current running process
   */
  
  debug("Enabling privilege to current running process...");

  EnablePrivilege("SeTcbPrivilege", 1);
  EnablePrivilege("SeChangeNotifyPrivilege", 1);
  EnablePrivilege("SeIncreaseQuotaPrivilege", 1);
  EnablePrivilege("SeAssignPrimaryTokenPrivilege", 1);
  EnablePrivilege("SeCreateTokenPrivilege", 1);
  
  /*
   * Create TOKEN_USER part
   */
      
  debug("Setting up TOKEN_USER...");
  
  FAIL(GetSidW(&userToken.User.Sid, userNameW));

  userToken.User.Attributes = 0;
  
  /*
   * Create TOKEN_OWNER part. We assume Owner = User.
   */
  
  debug("Setting up TOKEN_OWNER...");
  
  FAIL(GetSidW(&ownerToken.Owner, userNameW));
  
  /*
   * Create TOKEN_SOURCE part
   */
  
  debug("Setting up TOKEN_SOURCE...");
  
  FAIL(AllocateLocallyUniqueId(&sourceToken.SourceIdentifier) == FALSE);
  
  size = min(strlen(sourceName), 8);
      
  memcpy(sourceToken.SourceName, "********", 8);
  memcpy(sourceToken.SourceName, sourceName, size);

  /*
   * Create TOKEN_GROUPS part
   */
  
  debug("Setting up TOKEN_GROUPS...");
  
  FAIL(SetupTokenGroups(&groupsToken, userNameW));
  
  /*
   * Create TOKEN_PRIVILEGES part
   */
  
  debug("Setting up TOKEN_PRIVILEGES...");
  
  FAIL(SetupTokenPrivileges(&pPrivToken, userToken.User.Sid));
  
  /*
   * Create TOKEN_PRIMARY_GROUP part
   */
  
  debug("Setting up TOKEN_PRIMARY GROUP...");
  
  primaryGroupToken.PrimaryGroup = EveryoneSID();
  
  /*
   * Setup object attributes
   */
  
  memset(&oa, 0, sizeof(oa));

  oa.Length = sizeof(oa);
  
  oa.SecurityQualityOfService = &sqos;

  /*
   * Setup TOKEN_DEFAULT_DACL part.
   */
  
  debug("Setting up TOKEN_DEFAULT_DACL...");
  
  debug("Opening current process's token...");

  FAIL(OpenProcessToken(GetCurrentProcess(),
                            TOKEN_QUERY | TOKEN_QUERY_SOURCE, 
                                &hProcToken) == FALSE);

  debug("Retrieving TOKEN_DEFAULT_DACL...");

  GetTokenInformation(hProcToken, TokenDefaultDacl, NULL, 0, &cbSize);
  
  pDaclToken = LocalAlloc(LPTR, cbSize);

  FAIL(GetTokenInformation(hProcToken, TokenDefaultDacl,
                               pDaclToken, cbSize, &cbSize) == FALSE);

  /*
   * Print debug info about parts
   */
  
  //PrintPartsInfo(&token, TOKEN_ALL_ACCESS, &oa, 
  //                            TokenPrimary, &authId, &expirationTime,
  //                                &userToken, groupsToken, pPrivToken,
  //                                    &ownerToken, &primaryGroupToken, 
  //                                        pDaclToken, &sourceToken);

  /*
   * Retrieve address of NtCreateToken() function.
   */

  debug("Retrieving NtCreateToken() address...");
  
  hNtDll = GetModuleHandle("ntdll.dll");
  
  FAIL(hNtDll == NULL);

  NtCreateToken = (NtCreateTokenPtr) GetProcAddress(hNtDll, "NtCreateToken");

  FAIL(NtCreateToken == NULL);

  /*
   * Create new user acces token from parts setted up above.
   */

  debug("Creating token from parts...");
  
  ntStat = NtCreateToken(&token, TOKEN_ALL_ACCESS, &oa,
                              TokenPrimary, &authId, &expirationTime,
                                  &userToken, groupsToken, pPrivToken,
                                      &ownerToken, &primaryGroupToken,
                                          pDaclToken, &sourceToken);                         
  FAIL(ntStat);

  /*
   * Add rights to use 'default' desktop and WinStation0.
   */

  if (AddRightsToDesktopBySid(userToken.User.Sid))
  {
    debug("WARNING. Cannot add rights to 'winsta0\\default'!");
  }

  exitCode = 0;
  
fail:

  /*
   * Free allocated memory
   */
  
  debug2("Freeing groupsToken...");
  
  if (groupsToken)
  {
    /*
     * We don't need to test were SIDs allocated correctly,
     * becouse FreeSid() do it.
     */
    
    for (i = 0; i < groupsToken -> GroupCount; i++)
    {
      FreeSid(groupsToken -> Groups[i].Sid);
    }

    LocalFree(groupsToken);
  }
  
  debug2("Freeing local buffers...");
  
  LocalFree(userNameW);
  LocalFree(pDaclToken);
  LocalFree(pPrivToken);
  
  debug2("Freeing SIDs...");
  
  FreeSid(userToken.User.Sid);
  FreeSid(ownerToken.Owner);
  FreeSid(primaryGroupToken.PrimaryGroup);
  
  debug2("Closing hProcToken...");
  
  CloseHandle(hProcToken);

  debug2("Closing hNtDll...");
  
  CloseHandle(hNtDll);
  
  /*
   * Something was wrong.
   */
  
  if (exitCode)
  {
    debug("ERROR. Cannot create user's acces token. (err = %u, ntStat = %x)",
              GetLastError(), ntStat);
  }

  debug2("<- CreateUserToken()...");
  
  return token;
}
Exemple #4
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;
}
//
//	Create a primary access token for specified user account
//
HANDLE CreateToken(LPCTSTR szUserName)
{
	SID_IDENTIFIER_AUTHORITY	nt   = SECURITY_NT_AUTHORITY;
	SECURITY_QUALITY_OF_SERVICE	sqos = { sizeof(sqos), SecurityAnonymous, SECURITY_STATIC_TRACKING, FALSE };

	HANDLE				hToken;
	PSID				sid;
	TOKEN_USER			user;

	LUID				authid	= SYSTEM_LUID;
	OBJECT_ATTRIBUTES	oa		= { sizeof(oa), 0, 0, 0, 0, &sqos };
	TOKEN_SOURCE		source	= {{'*', '*', 'A', 'N', 'O', 'N', '*', '*'}, {0, 0}};
	HANDLE				hToken2 = 0;
	PTOKEN_STATISTICS	stats;

	PVOID				tokarr[5];
	int					i;
	DWORD				status;

	// Get address of Nt/ZwCreateToken from NTDLL.DLL
	ZwCreateToken         = (PVOID)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwCreateToken");
	RtlNtStatusToDosError = (PVOID)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlNtStatusToDosError");

	if(ZwCreateToken == 0 || RtlNtStatusToDosError == 0)
		return 0;

	// Must have SeCreateToken privilege
	if(!EnablePrivilege(SE_CREATE_TOKEN_NAME, TRUE)){
		DBG("EnablePrivilege failed\n");
	}
	

	// Use an existing process token as our basic for a new token
	if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &hToken))
		return 0;
	
	// Convert username to a SID
	if((sid = GetUserSid(szUserName)) == 0)
	{
		CloseHandle(hToken);
		return 0;
	}

	user.User.Attributes	= 0;
	user.User.Sid			= sid;

	if(!AllocateLocallyUniqueId(&source.SourceIdentifier))
	{
		free(sid);
		CloseHandle(hToken);
		return 0;
	}

	if(!GetTokenInfo(hToken, TokenStatistics, &stats))
	{
		free(sid);
		CloseHandle(hToken);
		return 0;
	}
	

	//
	//	Undocumented ZwCreateToken service: will not work for us
	//  under WIN2003, will need to do this from WINLOGON process in future?
	//
	status = ZwCreateToken(&hToken2, TOKEN_ALL_ACCESS, &oa, TokenPrimary,
		(PLUID)&authid, 
		(PLARGE_INTEGER)&stats->ExpirationTime,
		&user,
		(PTOKEN_GROUPS)			GetTokenInfo(hToken, TokenGroups,		&tokarr[0]),
		(PTOKEN_PRIVILEGES)		GetTokenInfo(hToken, TokenPrivileges,	&tokarr[1]),
		(PTOKEN_OWNER)			GetTokenInfo(hToken, TokenOwner,		&tokarr[2]),
		(PTOKEN_PRIMARY_GROUP)	GetTokenInfo(hToken, TokenPrimaryGroup, &tokarr[3]),
		(PTOKEN_DEFAULT_DACL)	GetTokenInfo(hToken, TokenDefaultDacl,	&tokarr[4]),
		&source);

	for(i = 0; i < 5; i++)
		free(tokarr[i]);

	free(stats);
	free(sid);

	CloseHandle(hToken);

	SetLastError(RtlNtStatusToDosError(status));

	return hToken2;
}
Exemple #6
0
NTSTATUS NTAPI
LsaApLogonUserEx (PLSA_CLIENT_REQUEST request, SECURITY_LOGON_TYPE logon_type,
		  PVOID auth, PVOID client_auth_base, ULONG auth_len,
		  PVOID *pbuf, PULONG pbuf_len, PLUID logon_id,
		  PNTSTATUS sub_stat, PLSA_TOKEN_INFORMATION_TYPE tok_type,
		  PVOID *tok, PUNICODE_STRING *account,
		  PUNICODE_STRING *authority, PUNICODE_STRING *machine)
{
  DWORD checksum, i;
  PDWORD csp, csp_end;
  NTSTATUS stat;
  SECPKG_CLIENT_INFO clinf;
  PLSA_TOKEN_INFORMATION_V2 tokinf;

  cyglsa_t *authinf = (cyglsa_t *) auth;

  /* Check if the caller has the SeTcbPrivilege, otherwise refuse service. */
  stat = funcs->GetClientInfo (&clinf);
  if (stat != STATUS_SUCCESS)
    {
      cyglsa_printf ("GetClientInfo failed: 0x%08lx\n", stat);
      return stat;
    }
  if (!clinf.HasTcbPrivilege)
    {
      cyglsa_printf ("Client has no TCB privilege.  Access denied.\n");
      return STATUS_ACCESS_DENIED;
    }

  /* Make a couple of validity checks. */
  if (auth_len < sizeof *authinf
      || authinf->magic != CYG_LSA_MAGIC
      || !authinf->username[0]
      || !authinf->domain[0])
    {
      cyglsa_printf ("Invalid authentication parameter.\n");
      return STATUS_INVALID_PARAMETER;
    }
  checksum = CYG_LSA_MAGIC;
  csp = (PDWORD) &authinf->username;
  csp_end = (PDWORD) ((PBYTE) authinf + auth_len);
  while (csp < csp_end)
    checksum += *csp++;
  if (authinf->checksum != checksum)
    {
      cyglsa_printf ("Invalid checksum.\n");
      return STATUS_INVALID_PARAMETER_3;
    }

  /* Set account to username and authority to domain resp. machine name.
     The name of the logon account name as returned by LookupAccountSid
     is created from here as "authority\account". */
  authinf->username[UNLEN] = '\0';
  authinf->domain[MAX_DOMAIN_NAME_LEN] = '\0';
  if (account && !(*account = uni_alloc (authinf->username,
  					 wcslen (authinf->username))))
    {
      cyglsa_printf ("No memory trying to create account.\n");
      return STATUS_NO_MEMORY;
    }
  if (authority && !(*authority = uni_alloc (authinf->domain,
					     wcslen (authinf->domain))))
    {
      cyglsa_printf ("No memory trying to create authority.\n");
      return STATUS_NO_MEMORY;
    }
  if (machine)
    {
      WCHAR mach[MAX_COMPUTERNAME_LENGTH + 1];
      DWORD msize = MAX_COMPUTERNAME_LENGTH + 1;
      if (!GetComputerNameW (mach, &msize))
        wcscpy (mach, L"UNKNOWN");
      if (!(*machine = uni_alloc (mach, wcslen (mach))))
	{
	  cyglsa_printf ("No memory trying to create machine.\n");
	  return STATUS_NO_MEMORY;
	}
    }
  /* Create a fake buffer in pbuf which is free'd again in the client.
     Windows 2000 tends to crash when setting this pointer to NULL. */
  if (pbuf)
    {
#ifdef JUST_ANOTHER_NONWORKING_SOLUTION
      cygprf_t prf;
      WCHAR sam_username[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
      SECURITY_STRING sam_user, prefix;
      PUCHAR user_auth;
      ULONG user_auth_size;
      WCHAR flatname[UNLEN + 1];
      UNICODE_STRING flatnm;
      TOKEN_SOURCE ts;
      HANDLE token;
#endif /* JUST_ANOTHER_NONWORKING_SOLUTION */

      stat = funcs->AllocateClientBuffer (request, 64UL, pbuf);
      if (!LSA_SUCCESS (stat))
	{
	  cyglsa_printf ("AllocateClientBuffer failed: 0x%08lx\n", stat);
	  return stat;
	}
#ifdef JUST_ANOTHER_NONWORKING_SOLUTION
      prf.magic_pre = MAGIC_PRE;
      prf.token = NULL;
      prf.magic_post = MAGIC_POST;

#if 0
      /* That's how it was supposed to work according to MSDN... */
      wcscpy (sam_username, authinf->domain);
      wcscat (sam_username, L"\\");
      wcscat (sam_username, authinf->username);
#else
      /* That's the only solution which worked, and then it only worked
         for machine local accounts.  No domain authentication possible.
	 STATUS_NO_SUCH_USER galore! */
      wcscpy (sam_username, authinf->username);
#endif
      RtlInitUnicodeString (&sam_user, sam_username);
      RtlInitUnicodeString (&prefix, L"");
      RtlInitEmptyUnicodeString (&flatnm, flatname,
				 (UNLEN + 1) * sizeof (WCHAR));

      stat = funcs->GetAuthDataForUser (&sam_user, SecNameSamCompatible,
					NULL, &user_auth,
					&user_auth_size, &flatnm);
      if (!NT_SUCCESS (stat))
	{
	  char sam_u[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
	  wcstombs (sam_u, sam_user.Buffer, sizeof (sam_u));
	  cyglsa_printf ("GetAuthDataForUser (%u,%u,%s) failed: 0x%08lx\n",
		  sam_user.Length, sam_user.MaximumLength, sam_u, stat);
	  return stat;
	}

      memcpy (ts.SourceName, "MSYS.2", 6);
      ts.SourceIdentifier.HighPart = 0;
      ts.SourceIdentifier.LowPart = 0x0104;
      RtlInitEmptyUnicodeString (&flatnm, flatname,
				 (UNLEN + 1) * sizeof (WCHAR));
      stat = funcs->ConvertAuthDataToToken (user_auth, user_auth_size,
					    SecurityDelegation, &ts,
					    Interactive, *authority,
					    &token, logon_id, &flatnm,
					    sub_stat);
      if (!NT_SUCCESS (stat))
	{
	  cyglsa_printf ("ConvertAuthDataToToken failed: 0x%08lx\n", stat);
	  return stat;
	}

      stat = funcs->DuplicateHandle (token, &prf.token);
      if (!NT_SUCCESS (stat))
	{
	  cyglsa_printf ("DuplicateHandle failed: 0x%08lx\n", stat);
	  return stat;
	}
      
      stat = funcs->CopyToClientBuffer (request, sizeof prf, *pbuf, &prf);
      if (!NT_SUCCESS (stat))
	{
	  cyglsa_printf ("CopyToClientBuffer failed: 0x%08lx\n", stat);
	  return stat;
	}
      funcs->FreeLsaHeap (user_auth);
#endif /* JUST_ANOTHER_NONWORKING_SOLUTION */
    }
  if (pbuf_len)
    *pbuf_len = 64UL;

  /* A PLSA_TOKEN_INFORMATION_V2 is allocated in one piece, so... */
#if defined (__x86_64__) || defined (_M_AMD64)
    {
      /* ...on 64 bit systems we have to convert the incoming 32 bit offsets
	 into 64 bit pointers.  That requires to re-evaluate the size of the
	 outgoing tokinf structure and a somewhat awkward procedure to copy
	 the information over. */
      LONG_PTR base;
      PBYTE tptr;
      DWORD size, newsize;
      PSID src_sid;
      PCYG_TOKEN_GROUPS src_grps;
      PTOKEN_GROUPS grps;
      PTOKEN_PRIVILEGES src_privs;
      PACL src_acl;

      base = (LONG_PTR) &authinf->inf;

      newsize = authinf->inf_size;
      newsize += sizeof (TOKEN_USER) - sizeof (CYG_TOKEN_USER); /* User SID */
      newsize += sizeof (PTOKEN_GROUPS) - sizeof (OFFSET); /* Groups */
      src_grps = (PCYG_TOKEN_GROUPS) (base + authinf->inf.Groups);
      newsize += src_grps->GroupCount		  /* Group SIDs */
      		 * (sizeof (SID_AND_ATTRIBUTES)
		    - sizeof (CYG_SID_AND_ATTRIBUTES));
      newsize += sizeof (PSID) - sizeof (OFFSET); /* Primary Group SID */
      newsize += sizeof (PTOKEN_PRIVILEGES) - sizeof (OFFSET); /* Privileges */
      newsize += 0; /* Owner SID */
      newsize += sizeof (PACL) - sizeof (OFFSET); /* Default DACL */

      if (!(tokinf = funcs->AllocateLsaHeap (newsize)))
	return STATUS_NO_MEMORY;
      tptr = (PBYTE)(tokinf + 1);

      tokinf->ExpirationTime = authinf->inf.ExpirationTime;
      /* User SID */
      src_sid = (PSID) (base + authinf->inf.User.User.Sid);
      size = GetLengthSid (src_sid);
      CopySid (size, (PSID) tptr, src_sid);
      tokinf->User.User.Sid = (PSID) tptr;
      tptr += size;
      tokinf->User.User.Attributes = authinf->inf.User.User.Attributes;
      /* Groups */
      grps = (PTOKEN_GROUPS) tptr;
      tokinf->Groups = grps;
      grps->GroupCount = src_grps->GroupCount;
      tptr += sizeof grps->GroupCount
	      + grps->GroupCount * sizeof (SID_AND_ATTRIBUTES);
      /* Group SIDs */
      for (i = 0; i < src_grps->GroupCount; ++i)
	{
	  src_sid = (PSID) (base + src_grps->Groups[i].Sid);
	  size = GetLengthSid (src_sid);
	  CopySid (size, (PSID) tptr, src_sid);
	  tokinf->Groups->Groups[i].Sid = (PSID) tptr;
	  tptr += size;
	  tokinf->Groups->Groups[i].Attributes = src_grps->Groups[i].Attributes;
	}
      /* Primary Group SID */
      src_sid = (PSID) (base + authinf->inf.PrimaryGroup.PrimaryGroup);
      size = GetLengthSid (src_sid);
      CopySid (size, (PSID) tptr, src_sid);
      tokinf->PrimaryGroup.PrimaryGroup = (PSID) tptr;
      tptr += size;
      /* Privileges */
      src_privs = (PTOKEN_PRIVILEGES) (base + authinf->inf.Privileges);
      size = sizeof src_privs->PrivilegeCount
	     + src_privs->PrivilegeCount * sizeof (LUID_AND_ATTRIBUTES);
      memcpy (tptr, src_privs, size);
      tokinf->Privileges = (PTOKEN_PRIVILEGES) tptr;
      tptr += size;
      /* Owner */
      tokinf->Owner.Owner = NULL;
      /* Default DACL */
      src_acl = (PACL) (base + authinf->inf.DefaultDacl.DefaultDacl);
      size = src_acl->AclSize;
      memcpy (tptr, src_acl, size);
      tokinf->DefaultDacl.DefaultDacl = (PACL) tptr;
    }
#else
    {
      /* ...on 32 bit systems we just allocate tokinf with the same size as
         we get, copy the whole structure and convert offsets into pointers. */

      /* Allocate LUID for usage in the logon SID on Windows 2000.  This is
	 not done in the 64 bit code above for hopefully obvious reasons... */
      LUID logon_sid_id;

      if (must_create_logon_sid && !AllocateLocallyUniqueId (&logon_sid_id))
	return STATUS_INSUFFICIENT_RESOURCES;

      if (!(tokinf = funcs->AllocateLsaHeap (authinf->inf_size)))
	return STATUS_NO_MEMORY;
      memcpy (tokinf, &authinf->inf, authinf->inf_size);

      /* User SID */
      tokinf->User.User.Sid = (PSID)
	      ((PBYTE) tokinf + (LONG_PTR) tokinf->User.User.Sid);
      /* Groups */
      tokinf->Groups = (PTOKEN_GROUPS)
	      ((PBYTE) tokinf + (LONG_PTR) tokinf->Groups);
      /* Group SIDs */
      for (i = 0; i < tokinf->Groups->GroupCount; ++i)
	{
	  tokinf->Groups->Groups[i].Sid = (PSID)
		((PBYTE) tokinf + (LONG_PTR) tokinf->Groups->Groups[i].Sid);
	  if (must_create_logon_sid
	      && tokinf->Groups->Groups[i].Attributes & SE_GROUP_LOGON_ID
	      && *GetSidSubAuthorityCount (tokinf->Groups->Groups[i].Sid) == 3
	      && *GetSidSubAuthority (tokinf->Groups->Groups[i].Sid, 0)
		 == SECURITY_LOGON_IDS_RID)
	    {
	      *GetSidSubAuthority (tokinf->Groups->Groups[i].Sid, 1)
	      = logon_sid_id.HighPart;
	      *GetSidSubAuthority (tokinf->Groups->Groups[i].Sid, 2)
	      = logon_sid_id.LowPart;
	    }
	}

      /* Primary Group SID */
      tokinf->PrimaryGroup.PrimaryGroup = (PSID)
	      ((PBYTE) tokinf + (LONG_PTR) tokinf->PrimaryGroup.PrimaryGroup);
      /* Privileges */
      tokinf->Privileges = (PTOKEN_PRIVILEGES)
	      ((PBYTE) tokinf + (LONG_PTR) tokinf->Privileges);
      /* Owner SID */
      tokinf->Owner.Owner = NULL;
      /* Default DACL */
      tokinf->DefaultDacl.DefaultDacl = (PACL)
	      ((PBYTE) tokinf + (LONG_PTR) tokinf->DefaultDacl.DefaultDacl);

    }
#endif

  *tok = (PVOID) tokinf;
  *tok_type = LsaTokenInformationV2;

  print_tokinf (tokinf, authinf->inf_size, authinf, &authinf->inf,
		(PVOID)((LONG_PTR) &authinf->inf + authinf->inf_size));

  /* Create logon session. */
  if (!AllocateLocallyUniqueId (logon_id))
    {
      funcs->FreeLsaHeap (*tok);
      *tok = NULL;
      cyglsa_printf ("AllocateLocallyUniqueId failed: Win32 error %lu\n",
		     GetLastError ());
      return STATUS_INSUFFICIENT_RESOURCES;
    }
  stat = funcs->CreateLogonSession (logon_id);
  if (stat != STATUS_SUCCESS)
    {
      funcs->FreeLsaHeap (*tok);
      *tok = NULL;
      cyglsa_printf ("CreateLogonSession failed: 0x%08lx\n", stat);
      return stat;
    }

  cyglsa_printf ("BINGO!!!\n", stat);
  return STATUS_SUCCESS;
}
Exemple #7
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;
}
Exemple #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;
}