Cómo validar las credenciales de usuario en los sistemas operativos de Microsoft

Seleccione idioma Seleccione idioma
Id. de artículo: 180548 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

En ocasiones, puede que desee una aplicación para comprobar nombre de usuario y la contraseña (en lo sucesivo, se denomina credenciales). Esto puede hacerse un par de diferentes maneras, dependiendo del sistema operativo en el que se ejecuta la aplicación.

Este artículo describe todas las formas comunes para comprobar las credenciales de un usuario y los requisitos especiales para cada método.

Nota Recopilar credenciales de usuario desde una aplicación de modo de usuario pueden ser molestas a los usuarios y pueden proporcionar un agujero de seguridad en el entorno informático empresarial. El requisito de inicio de sesión unificado (requisito que el usuario sólo deben escribir sus credenciales una vez en la pantalla CTRL CTRL+ALT+SUPR), se agregó a los requisitos del logotipo de Microsoft BackOffice por estas razones muy. Es importante para asegurarse de que realmente necesita recopilar las credenciales y que algún otro método de validación de cliente/servidor no es más apropiada. Consulte la documentación de seguridad en Platform SDK para obtener más información acerca de suplantación y programación de servidores seguros.

Más información

La API LogonUser ha documentados y disponibles desde Windows NT 3.51 y suele utilizarse para comprobar las credenciales de usuario. Esta API está disponible en Windows NT, Windows 2000 y Windows XP. Desafortunadamente, hay algunas restricciones sobre el uso de LogonUser que no siempre adecuadas satisfacer.

El primer y el mayor de estas restricciones es que en Windows NT y Windows 2000, el proceso que llama a LogonUser debe tener el privilegio SE_TCB_NAME (en el Administrador de usuarios, éste es el derecho "Actuar como parte del sistema operativo"). El privilegio SE_TCB_NAME es muy eficaz y debe no concederse a cualquier usuario arbitrario sólo para que pueda ejecutar una aplicación que necesita para validar las credenciales. El método recomendado es llamar a LogonUser de un servicio que se está ejecutando en la cuenta sistema local, porque la cuenta del sistema local ya tiene el privilegio SE_TCB_NAME.

Nota API Win32 LogonUser no requiere el privilegio TCB en Microsoft Windows Server 2003, sin embargo, para compatibilidad de nivel inferior, éste es todavía el mejor enfoque.

En Windows XP, ya no es necesario que un proceso tener el privilegio SE_TCB_NAME para llamar a LogonUser. Por lo tanto, el método más sencillo para validar credenciales del usuario en Windows XP, es llamar a la API LogonUser.

Un otro problema con LogonUser es que la API no está implementada en Windows 95, Windows 98 o Windows Millennium Edition.

Como otra opción, puede utilizar el proveedor de soporte de seguridad (SSPI) para realizar un inicio de sesión de estilo de red con credenciales de usuario. Este método de validación tiene la ventaja de no requiere ningún privilegio especial, así como trabajar en todas las versiones de Windows. El resultado final del uso de los servicios SSPI para validar las credenciales es un inicio de sesión equivale a llamar a la API LogonUser con el tipo de inicio de sesión LOGON32_LOGON_NETWORK. La mayor desventaja de este tipo de inicio de sesión es que no puede tener acceso remoto recursos de red después de suplantación de un inicio de sesión de tipo de red. Si la aplicación está llamando a LogonUser con el tipo de inicio de sesión LOGON32_LOGON_INTERACTIVE incapacidad de solución Windows NT para realizar la delegación, a continuación, la SSPI inicio de sesión y validación probablemente no será una alternativa viable.

El código de ejemplo proporcionado a continuación muestra cómo llamar a los servicios SSPI para realizar validación de credenciales.

Para utilizar este método en Windows 95, Windows 98 y Windows Millennium Edition, también debe habilitar los servicios de seguridad NTLM abrir Panel de control, red, control de acceso y, a continuación, seleccione control de acceso de nivel de usuario.

En Windows XP, el valor del registro ForceGuest se establece en 1 de forma predeterminada en la siguiente clave del registro:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
En un equipo con Windows XP es un miembro de un grupo de trabajo:
  • Si está habilitada ForceGuest (establecido a 1), SSPI siempre intenta iniciar sesión utilizando la cuenta Invitado.
  • Si la cuenta Invitado está habilitada, se realizará correctamente como invitado un inicio de sesión SSPI las credenciales de usuario.
  • Si la cuenta de invitado está deshabilitada, un inicio de sesión SSPI fallará incluso para credenciales válidas.
  • Si está deshabilitada ForceGuest (establecido a 0), SSPI iniciará una sesión como el usuario especificado.
Además, si la cuenta de invitado está habilitada, el inicio de sesión SSPI puede tener éxito como invitado las credenciales de usuario que no son válidas. El código de ejemplo C en este artículo muestra cómo puede comprobar el token de acceso del contexto de seguridad establecido. La función auxiliar IsGuest en el código de ejemplo muestra cómo puede comprobar que ha producido el inicio de sesión como el usuario especificado o como invitado.

Código de ejemplo

///////////////////////////////////////////////////////////////////////////////
//
//  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"));
}

Propiedades

Id. de artículo: 180548 - Última revisión: lunes, 1 de octubre de 2007 - Versión: 4.0
La información de este artículo se refiere a:
  • Microsoft Win32 Application Programming Interface sobre las siguientes plataformas
    • Microsoft Windows 95
    • Microsoft Windows 98 Standard Edition
    • Microsoft Windows Millennium Edition
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
Palabras clave: 
kbmt kbapi kbfaq kbhowto kbkernbase kbsecurity KB180548 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 180548

Enviar comentarios

 

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