Jak ověřit pověření uživatele v operačních systémech společnosti Microsoft

Překlady článku Překlady článku
ID článku: 180548 - Produkty, které se vztahují k tomuto článku.
Rozbalit všechny záložky | Minimalizovat všechny záložky

Na této stránce

Souhrn

Někdy můžete chtít aplikaci ověřit uživatelské jméno a heslo (dále jen pověření) uživatele. Je možné proveďte několika různými způsoby v závislosti na operačním systému, ve kterém aplikace spustí.

Tento článek popisuje všechny běžné způsoby ověření pověření uživatele a zvláštní požadavky na jednotlivé metody.

Poznámka: Sběr pověření uživatele z aplikace uživatelského režimu může být otravné uživatele a může poskytovat možné bezpečnostní díra v podnikovém výpočetním prostředí. Požadavek jednotného přihlášení (požadavek že uživatel pouze povinen zadejte svá pověření jednou na Obrazovka CTRL + ALT + DEL) byla přidána do sady Microsoft BackOffice logo požadavky tyto velmi důvodů. Je důležité zajistit, že skutečně potřebujete shromažďuje pověření a je jiný způsob ověření klienta a serveru není vhodnější. V dokumentaci zabezpečení v sadě Platform SDK Další informace o zosobnění a programování zabezpečenými servery.

Další informace

Na LogonUser Rozhraní API byl k dispozici a zdokumentované od systému Windows NT 3.51 a běžně se používá k ověření pověření uživatele. Toto rozhraní API je k dispozici v systému Windows NT, Windows 2000 a Windows XP. Bohužel existují určitá omezení na použití LogonUser, které nejsou vždy vhodné vyhovět.

První a největší z těchto omezení je v systému Windows NT a Windows 2000, proces, který volá LogonUser musí mít oprávnění SE_TCB_NAME (v uživatele Správce, to je právo "Jednat jako část operačního systému"). Na Oprávnění SE_TCB_NAME, je velmi výkonný a nesmí být poskytnuta na libovolnou pouze tak, že mohou spouštět aplikace, která potřebuje ověřit libovolného uživatele pověření. Doporučenou metodou je volat uživatele LogonUser ze služby, která je spuštěn v účtu local system, protože místní systémový účet již má oprávnění SE_TCB_NAME.

Poznámka: Rozhraní API systému Win32 LogonUser nevyžaduje oprávnění TCB v aplikaci Microsoft Windows Server 2003, však nižší úrovně kompatibility, jedná se stále Nejlepším řešením.

V systému Windows XP již není vyžadováno, proces Chcete-li volat uživatele LogonUser máte oprávnění SE_TCB_NAME. Proto Nejjednodušší způsob ověření pověření uživatele v systému Windows XP, je zavolat LogonUser rozhraní API.

Jeden problém s LogonUser je rozhraní API není implementováno v systému Windows 95, Windows 98 nebo Windows Millennium Edition.

Jako další možnost můžete použít Security Support Provider Interface (SSPI) provést přihlášení k síti styl zadané přihlašovací údaje. Tato metoda ověřování má tu výhodu, nesmí požadovat jakékoli zvláštní oprávnění, a také pracuje ve všech verzích systému Windows. Konečný výsledek ověření pověření pomocí SSPI služby je přihlášení, která je analogická volání rozhraní API LogonUser přihlášení LOGON32_LOGON_NETWORK typ. Největší nevýhodou pro tento typ přihlášení je, že nelze získat přístup vzdáleným síťovým prostředkům po zosobnění typ přihlášení k síti. Pokud vaše aplikace volá LogonUser přihlášení typu LOGON32_LOGON_INTERACTIVE k řešení systému Windows NT a neschopnost provést delegování, pak rozhraní SSPI přihlášení a ověření pravděpodobně nebudou životaschopné alternativy.

Na Ukázkový kód níže ukazuje, jak volat služby SSPI provádět ověření pověření.

Tuto metodu lze použít v systému Windows 95, Windows 98, a Windows Millennium Edition, je třeba také povolit zabezpečení NTLM Otevřete ovládací Panel síť, řízení přístupu a potom výběrem služeb Řízení přístupu na úrovni uživatele.

V systému Windows XP registru ForceGuest hodnotu 1 v následujícím klíči registru ve výchozím nastavení:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA
V počítači systém Windows XP, který je členem pracovní skupiny:
  • Pokud ForceGuest je povolena (nastavena na hodnotu 1), se vždy pokusí SSPI přihlásit se pomocí účtu Guest.
  • Pokud je povolen účet Guest, budou úspěšné přihlášení rozhraní SSPI jako Host pro žádné uživatelská pověření.
  • Pokud je účet Guest zakázán, přihlášení rozhraní SSPI se nezdaří i pro platná pověření.
  • Pokud je zakázáno ForceGuest (nastavena na hodnotu 0), rozhraní SSPI se přihlaste jako Zadaný uživatel.
Navíc pokud je povolen účet Guest, přihlášení SSPI může úspěšně jako Host uživatelská pověření, které nejsou platné. C ukázkový kód v tomto článku je ukázáno, jak lze zkontrolovat přístupový token kontextu zabezpečení zavedených. Na IsGuest pomocná funkce v ukázkovém kódu ukazuje, jak lze ověřit, že došlo k přihlášení zadaného uživatele nebo jako Host.

Ukázkový kód

///////////////////////////////////////////////////////////////////////////////
//
//  SSPI Authentication Sample
//
//  This program demonstrates how to use SSPI to authenticate user credentials.
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
//  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//
//  Copyright (C) 2007.  Microsoft Corporation.  All rights reserved.
///////////////////////////////////////////////////////////////////////////////

#define SECURITY_WIN32
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <conio.h>
#include <sspi.h>
#include <lm.h>
#include <lmcons.h>

// Older versions of WinError.h do not have SEC_I_COMPLETE_NEEDED #define.
// So, in such an SDK environment setup, we will include issperr.h which has the
// definition for SEC_I_COMPLETE_NEEDED. Include issperr.h only if
// SEC_I_COMPLETE_NEEDED is not defined.
#ifndef SEC_I_COMPLETE_NEEDED
#include <issperr.h>
#endif

typedef struct _AUTH_SEQ {
   BOOL fInitialized;
   BOOL fHaveCredHandle;
   BOOL fHaveCtxtHandle;
   CredHandle hcred;
   struct _SecHandle hctxt;
} AUTH_SEQ, *PAUTH_SEQ;


// Function pointers
ACCEPT_SECURITY_CONTEXT_FN       _AcceptSecurityContext     = NULL;
ACQUIRE_CREDENTIALS_HANDLE_FN    _AcquireCredentialsHandle  = NULL;
COMPLETE_AUTH_TOKEN_FN           _CompleteAuthToken         = NULL;
DELETE_SECURITY_CONTEXT_FN       _DeleteSecurityContext     = NULL;
FREE_CONTEXT_BUFFER_FN           _FreeContextBuffer         = NULL;
FREE_CREDENTIALS_HANDLE_FN       _FreeCredentialsHandle     = NULL;
INITIALIZE_SECURITY_CONTEXT_FN   _InitializeSecurityContext = NULL;
QUERY_SECURITY_PACKAGE_INFO_FN   _QuerySecurityPackageInfo  = NULL;
QUERY_SECURITY_CONTEXT_TOKEN_FN  _QuerySecurityContextToken = NULL;


#define CheckAndLocalFree(ptr) \
            if (ptr != NULL) \
            { \
               LocalFree(ptr); \
               ptr = NULL; \
            }

#pragma comment(lib, "netapi32.lib")

LPVOID RetrieveTokenInformationClass(
      HANDLE hToken,
      TOKEN_INFORMATION_CLASS InfoClass,
      LPDWORD lpdwSize)
{
   LPVOID pInfo = NULL;
   BOOL fSuccess = FALSE;

   __try
   {
      *lpdwSize = 0;

      //
      // Determine the size of the buffer needed
      //

      GetTokenInformation(
            hToken,
            InfoClass,
            NULL,
            *lpdwSize, lpdwSize);
      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
      {
         _tprintf(_T("GetTokenInformation failed with %d\n"), GetLastError());
         __leave;
      }

      //
      // Allocate a buffer for getting token information
      //
      pInfo = LocalAlloc(LPTR, *lpdwSize);
      if (pInfo == NULL)
      {
         _tprintf(_T("LocalAlloc failed with %d\n"), GetLastError());
         __leave;
      }

      if (!GetTokenInformation(
            hToken,
            InfoClass,
            pInfo,
            *lpdwSize, lpdwSize))
      {
         _tprintf(_T("GetTokenInformation failed with %d\n"), GetLastError());
         __leave;
      }

      fSuccess = TRUE;
   }
   __finally
   {
      // Free pDomainAndUserName only if failed
      // Otherwise, the caller has to free after use
      if (fSuccess == FALSE)
      {
         CheckAndLocalFree(pInfo);
      }
   }

   return pInfo;
}

PSID GetUserSidFromWellKnownRid(DWORD Rid)
{
    PUSER_MODALS_INFO_2 umi2;
    NET_API_STATUS nas;

    UCHAR SubAuthorityCount;
    PSID pSid = NULL;

    BOOL bSuccess = FALSE; // assume failure

    nas = NetUserModalsGet(NULL, 2, (LPBYTE *)&umi2);

    if (nas != NERR_Success)
    {
        printf("NetUserModalsGet failed with error code : [%d]\n", nas);
        SetLastError(nas);
        return NULL;
    }

    SubAuthorityCount = *GetSidSubAuthorityCount
                       (umi2->usrmod2_domain_id);

    // 
    // Allocate storage for new Sid. account domain Sid + account Rid
    // 

    pSid = (PSID)LocalAlloc(LPTR,
          GetSidLengthRequired((UCHAR)(SubAuthorityCount + 1)));

    if (pSid != NULL)
    {
        if (InitializeSid(
              pSid,
              GetSidIdentifierAuthority(umi2->usrmod2_domain_id),
              (BYTE)(SubAuthorityCount+1)
              ))
        {
            DWORD SubAuthIndex = 0;

            // 
            // Copy existing subauthorities from account domain Sid into
            // new Sid
            // 

            for (; SubAuthIndex < SubAuthorityCount ; SubAuthIndex++)
            {
                *GetSidSubAuthority(pSid, SubAuthIndex) =
                *GetSidSubAuthority(umi2->usrmod2_domain_id,
                                  SubAuthIndex);
            }

            // 
            // Append Rid to new Sid
            // 

            *GetSidSubAuthority(pSid, SubAuthorityCount) = Rid;
        }
    }

    NetApiBufferFree(umi2);

    return pSid;
}

BOOL IsGuest(HANDLE hToken)
{
    BOOL fGuest = FALSE;
    PSID pGuestSid = NULL;
    PSID pUserSid = NULL;
    TOKEN_USER *pUserInfo = NULL;
    DWORD dwSize = 0;

    pGuestSid = GetUserSidFromWellKnownRid(DOMAIN_USER_RID_GUEST);
    if (pGuestSid == NULL)
        return fGuest;

    //
    // Get user information
    //

    pUserInfo = (TOKEN_USER *)RetrieveTokenInformationClass(hToken, TokenUser, &dwSize);
    if (pUserInfo != NULL)
    {
        if (EqualSid(pGuestSid, pUserInfo->User.Sid))
            fGuest = TRUE;
    }

    CheckAndLocalFree(pUserInfo);
    CheckAndLocalFree(pGuestSid);

    return fGuest;
}

///////////////////////////////////////////////////////////////////////////////


void UnloadSecurityDll(HMODULE hModule) {

   if (hModule)
      FreeLibrary(hModule);

   _AcceptSecurityContext      = NULL;
   _AcquireCredentialsHandle   = NULL;
   _CompleteAuthToken          = NULL;
   _DeleteSecurityContext      = NULL;
   _FreeContextBuffer          = NULL;
   _FreeCredentialsHandle      = NULL;
   _InitializeSecurityContext  = NULL;
   _QuerySecurityPackageInfo   = NULL;
   _QuerySecurityContextToken  = NULL;
}


///////////////////////////////////////////////////////////////////////////////


HMODULE LoadSecurityDll() {

   HMODULE hModule;
   BOOL    fAllFunctionsLoaded = FALSE;
   TCHAR   lpszDLL[MAX_PATH];
   OSVERSIONINFO VerInfo;

   //
   //  Find out which security DLL to use, depending on
   //  whether we are on Windows NT or Windows 95, Windows 2000, Windows XP, or Windows Server 2003
   //  We have to use security.dll on Windows NT 4.0.
   //  All other operating systems, we have to use Secur32.dll
   //
   VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
   if (!GetVersionEx (&VerInfo))   // If this fails, something has gone wrong
   {
      return FALSE;
   }

   if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
      VerInfo.dwMajorVersion == 4 &&
      VerInfo.dwMinorVersion == 0)
   {
      lstrcpy (lpszDLL, _T("security.dll"));
   }
   else
   {
      lstrcpy (lpszDLL, _T("secur32.dll"));
   }


   hModule = LoadLibrary(lpszDLL);
   if (!hModule)
      return NULL;

   __try {

      _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN)
            GetProcAddress(hModule, "AcceptSecurityContext");
      if (!_AcceptSecurityContext)
         __leave;

#ifdef UNICODE
      _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)
            GetProcAddress(hModule, "AcquireCredentialsHandleW");
#else
      _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN)
            GetProcAddress(hModule, "AcquireCredentialsHandleA");
#endif
      if (!_AcquireCredentialsHandle)
         __leave;

      // CompleteAuthToken is not present on Windows 9x Secur32.dll
      // Do not check for the availablity of the function if it is NULL;
      _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN)
            GetProcAddress(hModule, "CompleteAuthToken");

      _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN)
            GetProcAddress(hModule, "DeleteSecurityContext");
      if (!_DeleteSecurityContext)
         __leave;

      _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN)
            GetProcAddress(hModule, "FreeContextBuffer");
      if (!_FreeContextBuffer)
         __leave;

      _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN)
            GetProcAddress(hModule, "FreeCredentialsHandle");
      if (!_FreeCredentialsHandle)
         __leave;

#ifdef UNICODE
      _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)
            GetProcAddress(hModule, "InitializeSecurityContextW");
#else
      _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN)
            GetProcAddress(hModule, "InitializeSecurityContextA");
#endif
      if (!_InitializeSecurityContext)
         __leave;

#ifdef UNICODE
      _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)
            GetProcAddress(hModule, "QuerySecurityPackageInfoW");
#else
      _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN)
            GetProcAddress(hModule, "QuerySecurityPackageInfoA");
#endif
      if (!_QuerySecurityPackageInfo)
         __leave;


      _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN)
            GetProcAddress(hModule, "QuerySecurityContextToken");
      if (!_QuerySecurityContextToken)
         __leave;

      fAllFunctionsLoaded = TRUE;

   } __finally {

      if (!fAllFunctionsLoaded) {
         UnloadSecurityDll(hModule);
         hModule = NULL;
      }

   }

   return hModule;
}


///////////////////////////////////////////////////////////////////////////////


BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
      PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone) {

/*++

 Routine Description:

   Optionally takes an input buffer coming from the server and returns
   a buffer of information to send back to the server.  Also returns
   an indication of whether or not the context is complete.

 Return Value:

   Returns TRUE if successful; otherwise FALSE.

--*/

   SECURITY_STATUS ss;
   TimeStamp       tsExpiry;
   SecBufferDesc   sbdOut;
   SecBuffer       sbOut;
   SecBufferDesc   sbdIn;
   SecBuffer       sbIn;
   ULONG           fContextAttr;

   if (!pAS->fInitialized) {

      ss = _AcquireCredentialsHandle(NULL, _T("NTLM"),
            SECPKG_CRED_OUTBOUND, NULL, pAuthIdentity, NULL, NULL,
            &pAS->hcred, &tsExpiry);
      if (ss < 0) {
         fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss);
         return FALSE;
      }

      pAS->fHaveCredHandle = TRUE;
   }

   // Prepare output buffer
   sbdOut.ulVersion = 0;
   sbdOut.cBuffers = 1;
   sbdOut.pBuffers = &sbOut;

   sbOut.cbBuffer = *pcbOut;
   sbOut.BufferType = SECBUFFER_TOKEN;
   sbOut.pvBuffer = pOut;

   // Prepare input buffer
   if (pAS->fInitialized)  {
      sbdIn.ulVersion = 0;
      sbdIn.cBuffers = 1;
      sbdIn.pBuffers = &sbIn;

      sbIn.cbBuffer = cbIn;
      sbIn.BufferType = SECBUFFER_TOKEN;
      sbIn.pvBuffer = pIn;
   }

   ss = _InitializeSecurityContext(&pAS->hcred,
         pAS->fInitialized ? &pAS->hctxt : NULL, NULL, 0, 0,
         SECURITY_NATIVE_DREP, pAS->fInitialized ? &sbdIn : NULL,
         0, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry);
   if (ss < 0)  {
      // <winerror.h>
      fprintf(stderr, "InitializeSecurityContext failed with %08X\n", ss);
      return FALSE;
   }

   pAS->fHaveCtxtHandle = TRUE;

   // If necessary, complete token
   if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) {

      if (_CompleteAuthToken) {
         ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut);
         if (ss < 0)  {
            fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss);
            return FALSE;
         }
      }
      else {
         fprintf (stderr, "CompleteAuthToken not supported.\n");
         return FALSE;
      }
   }

   *pcbOut = sbOut.cbBuffer;

   if (!pAS->fInitialized)
      pAS->fInitialized = TRUE;

   *pfDone = !(ss == SEC_I_CONTINUE_NEEDED
         || ss == SEC_I_COMPLETE_AND_CONTINUE );

   return TRUE;
}


///////////////////////////////////////////////////////////////////////////////


BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut,
      PDWORD pcbOut, PBOOL pfDone) {

/*++

 Routine Description:

    Takes an input buffer coming from the client and returns a buffer
    to be sent to the client.  Also returns an indication of whether or
    not the context is complete.

 Return Value:

    Returns TRUE if successful; otherwise FALSE.

--*/

   SECURITY_STATUS ss;
   TimeStamp       tsExpiry;
   SecBufferDesc   sbdOut;
   SecBuffer       sbOut;
   SecBufferDesc   sbdIn;
   SecBuffer       sbIn;
   ULONG           fContextAttr;

   if (!pAS->fInitialized)  {

      ss = _AcquireCredentialsHandle(NULL, _T("NTLM"),
            SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred,
            &tsExpiry);
      if (ss < 0) {
         fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss);
         return FALSE;
      }

      pAS->fHaveCredHandle = TRUE;
   }

   // Prepare output buffer
   sbdOut.ulVersion = 0;
   sbdOut.cBuffers = 1;
   sbdOut.pBuffers = &sbOut;

   sbOut.cbBuffer = *pcbOut;
   sbOut.BufferType = SECBUFFER_TOKEN;
   sbOut.pvBuffer = pOut;

   // Prepare input buffer
   sbdIn.ulVersion = 0;
   sbdIn.cBuffers = 1;
   sbdIn.pBuffers = &sbIn;

   sbIn.cbBuffer = cbIn;
   sbIn.BufferType = SECBUFFER_TOKEN;
   sbIn.pvBuffer = pIn;

   ss = _AcceptSecurityContext(&pAS->hcred,
         pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, 0,
         SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr,
         &tsExpiry);
   if (ss < 0)  {
      fprintf(stderr, "AcceptSecurityContext failed with %08X\n", ss);
      return FALSE;
   }

   pAS->fHaveCtxtHandle = TRUE;

   // If necessary, complete token
   if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) {

      if (_CompleteAuthToken) {
         ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut);
         if (ss < 0)  {
            fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss);
            return FALSE;
         }
      }
      else {
         fprintf (stderr, "CompleteAuthToken not supported.\n");
         return FALSE;
      }
   }

   *pcbOut = sbOut.cbBuffer;

   if (!pAS->fInitialized)
      pAS->fInitialized = TRUE;

   *pfDone = !(ss == SEC_I_CONTINUE_NEEDED
         || ss == SEC_I_COMPLETE_AND_CONTINUE);

   return TRUE;
}


///////////////////////////////////////////////////////////////////////////////


BOOL WINAPI SSPLogonUser(LPTSTR szDomain, LPTSTR szUser, LPTSTR szPassword) {

   AUTH_SEQ    asServer   = {0};
   AUTH_SEQ    asClient   = {0};
   BOOL        fDone      = FALSE;
   BOOL        fResult    = FALSE;
   DWORD       cbOut      = 0;
   DWORD       cbIn       = 0;
   DWORD       cbMaxToken = 0;
   PVOID       pClientBuf = NULL;
   PVOID       pServerBuf = NULL;
   PSecPkgInfo pSPI       = NULL;
   HMODULE     hModule    = NULL;

   SEC_WINNT_AUTH_IDENTITY ai;

   __try {

      hModule = LoadSecurityDll();
      if (!hModule)
         __leave;

      // Get max token size
      _QuerySecurityPackageInfo(_T("NTLM"), &pSPI);
      cbMaxToken = pSPI->cbMaxToken;
      _FreeContextBuffer(pSPI);

      // Allocate buffers for client and server messages
      pClientBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken);
      pServerBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken);

      // Initialize auth identity structure
      ZeroMemory(&ai, sizeof(ai));
#if defined(UNICODE) || defined(_UNICODE)
      ai.Domain = szDomain;
      ai.DomainLength = lstrlen(szDomain);
      ai.User = szUser;
      ai.UserLength = lstrlen(szUser);
      ai.Password = szPassword;
      ai.PasswordLength = lstrlen(szPassword);
      ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
#else
      ai.Domain = (unsigned char *)szDomain;
      ai.DomainLength = lstrlen(szDomain);
      ai.User = (unsigned char *)szUser;
      ai.UserLength = lstrlen(szUser);
      ai.Password = (unsigned char *)szPassword;
      ai.PasswordLength = lstrlen(szPassword);
      ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
#endif

      // Prepare client message (negotiate) .
      cbOut = cbMaxToken;
      if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone))
         __leave;

      // Prepare server message (challenge) .
      cbIn = cbOut;
      cbOut = cbMaxToken;
      if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
            &fDone))
         __leave;
         // Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED
         // in the case of bad szUser or szPassword.
         // Unexpected Result: Logon will succeed if you pass in a bad szUser and
         // the guest account is enabled in the specified domain.

      // Prepare client message (authenticate) .
      cbIn = cbOut;
      cbOut = cbMaxToken;
      if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut,
            &fDone))
         __leave;

      // Prepare server message (authentication) .
      cbIn = cbOut;
      cbOut = cbMaxToken;
      if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut,
            &fDone))
         __leave;

      fResult = TRUE;

      {
         HANDLE hToken = NULL;

         if (_QuerySecurityContextToken(&asServer.hctxt, &hToken) == 0)
         {
            if (IsGuest(hToken))
            {
               printf("Logged in as Guest\n");
               fResult = FALSE;
            }
            else
               printf("Logged in as the desired user\n");
            CloseHandle(hToken);
         }
      }


   } __finally {

      // Clean up resources
      if (asClient.fHaveCtxtHandle)
         _DeleteSecurityContext(&asClient.hctxt);

      if (asClient.fHaveCredHandle)
         _FreeCredentialsHandle(&asClient.hcred);

      if (asServer.fHaveCtxtHandle)
         _DeleteSecurityContext(&asServer.hctxt);

      if (asServer.fHaveCredHandle)
         _FreeCredentialsHandle(&asServer.hcred);

      if (hModule)
         UnloadSecurityDll(hModule);

      HeapFree(GetProcessHeap(), 0, pClientBuf);
      HeapFree(GetProcessHeap(), 0, pServerBuf);

   }

   return fResult;
}

//--------------------------------------------------------------------
// The GetConsoleInput function gets an array of characters from the 
// keyboard, while printing only asterisks to the screen.

void GetConsoleInput(TCHAR* strInput, int intMaxChars)
{
	char ch;
	char minChar = ' ';
	minChar++;

	ch = getch();
	while (ch != '\r')
	{
		if (ch == '\b' && strlen(strInput) > 0)
		{
			strInput[strlen(strInput)-1]   = '\0';
			printf("\b \b");
		}
		else if (ch >= minChar && (int)strlen(strInput) < intMaxChars)
		{
			strInput[strlen(strInput)+1] = '\0';
			strInput[strlen(strInput)]   = ch;
			putch('*');
		}
		ch = getch();
	}
	putch('\n');
}

void _tmain(int argc, TCHAR **argv)
{
	TCHAR password[PWLEN+1];

   if (argc != 3) 
	{
		_tprintf(_T("Usage: %s DomainName UserName\n"), argv[0]);
		return;
	}

	_tprintf(_T("Enter password for the specified user : "));
	password[0] = 0;
	GetConsoleInput(password, PWLEN);
	_tprintf(_T("\n"));
   // argv[1] - Domain Name
   // argv[2] - User Name
   if (SSPLogonUser(argv[1], argv[2], password))
   {
      _tprintf(_T("User Credentials are valid\n"));
   }
   else
      _tprintf(_T("User Credentials are NOT valid\n"));
}

Vlastnosti

ID článku: 180548 - Poslední aktualizace: 23. dubna 2011 - Revize: 6.0
Informace v tomto článku jsou určeny pro produkt:
  • Microsoft Win32 Application Programming Interface na těchto platformách
    • Microsoft Windows 98 Standard Edition
    • Microsoft Windows Millennium Edition
Klíčová slova: 
kbapi kbFAQ kbhowto kbkernbase kbsecurity kbmt KB180548 KbMtcs
Strojově přeložený článek
Důležité: Tento článek byl přeložen pomocí software společnosti Microsoft na strojový překlad, ne profesionálním překladatelem. Společnost Microsoft nabízí jak články přeložené překladatelem, tak články přeložené pomocí software na strojový překlad, takže všechny články ve Znalostní databázi (Knowledge Base) jsou dostupné v češtině. Překlad pomocí software na strojový překlad ale není bohužel vždy dokonalý. Obsahuje chyby ve skloňování slov, skladbě vět, nebo gramatice, podobně jako když cizinci dělají chyby při mluvení v češtině. Společnost Microsoft není právně zodpovědná za nepřesnosti, chyby nebo škody vzniklé chybami v překladu, nebo při použití nepřesně přeložených instrukcí v článku zákazníkem. Společnost Microsoft aktualizuje software na strojový překlad, aby byl počet chyb omezen na minimum.
Projděte si také anglickou verzi článku:180548

Dejte nám zpětnou vazbu

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com