Windows Access Control List (ACL) Example 33

 

 

 

 

Validate User Credentials on Microsoft Operating Systems Program Example

 

The sample code provided below shows how to call the SSPI services to perform credential validation. To use this method on Windows 95, Windows 98, and Windows Millennium Edition, you also have to enable the NTLM security services by opening Control Panel, Network, Access Control, and then selecting User-level access control. On Windows XP, the ForceGuest registry value is set to 1 by default in the following registry key:

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa

 

On a Windows XP computer that is a member of a workgroup:

 

  1. If ForceGuest is enabled (set to 1), SSPI will always try to log on using the Guest account.
  2. If the Guest account is enabled, an SSPI logon will succeed as Guest for any user credentials.
  3. If the Guest account is disabled, an SSPI logon will fail even for valid credentials.
  4. If ForceGuest is disabled (set to 0), SSPI will log on as the specified user.

 

Additionally, if the Guest account is enabled, SSPI logon may succeed as Guest for user credentials that are not valid. The C sample code in this article demonstrates how you can check the access token of the established security context. The IsGuest() helper function in the sample code shows how you can verify that the logon occurred as the specified user or as Guest.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

Validate User Credentials on Microsoft Operating Systems Program Example: Creating new C++ Win32 empty console project

 

Then, add the source file and give it a suitable name.

 

Validate User Credentials on Microsoft Operating Systems Program Example: Adding the C++ source file

 

Next, add the following source code.

 

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

//  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 <stdio.h>

#include <conio.h>

#include <sspi.h>

#include <lm.h>

#include <lmcons.h>

 

// Link to netapi32.lib

#pragma comment(lib, netapi32.lib)

// 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; \

            }

 

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)

      {

         wprintf(LGetTokenInformation() failed, error %d\n, GetLastError());

         __leave;

      }

 

      // Allocate a buffer for getting token information

      pInfo = LocalAlloc(LPTR, *lpdwSize);

      if (pInfo == NULL)

      {

         wprintf(LLocalAlloc() failed, error %d\n, GetLastError());

         __leave;

      }

 

      if (!GetTokenInformation(hToken,InfoClass,pInfo,*lpdwSize, lpdwSize))

      {

         wprintf(LGetTokenInformation() failed, error %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)

    {

        wprintf(LNetUserModalsGet() failed, error %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, Lsecurity.dll);

   }

   else

   {

      lstrcpy (lpszDLL, Lsecur32.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;

}

 

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

/*++

 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.

--*/

BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,

      PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone)

{

      SECURITY_STATUS ss;

   TimeStamp       tsExpiry;

   SecBufferDesc   sbdOut;

   SecBuffer       sbOut;

   SecBufferDesc   sbdIn;

   SecBuffer       sbIn;

   ULONG           fContextAttr;

 

   if (!pAS->fInitialized)

   {

      ss = _AcquireCredentialsHandle(NULL, LNTLM,

            SECPKG_CRED_OUTBOUND, NULL, pAuthIdentity, NULL, NULL,

            &pAS->hcred, &tsExpiry);

      if (ss < 0)

{

         // fwprintf...

         fwprintf(stderr, LAcquireCredentialsHandle 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>

      fwprintf(stderr, LInitializeSecurityContext 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)

             {

            fwprintf(stderr, LCompleteAuthToken failed with %08X\n, ss);

            return FALSE;

         }

      }

      else

        {

         fwprintf (stderr, LCompleteAuthToken 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;

}

 

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

/*++

 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.

--*/

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

{

   SECURITY_STATUS ss;

   TimeStamp       tsExpiry;

   SecBufferDesc   sbdOut;

   SecBuffer       sbOut;

   SecBufferDesc   sbdIn;

   SecBuffer       sbIn;

   ULONG           fContextAttr;

 

   if (!pAS->fInitialized)

   {

      ss = _AcquireCredentialsHandle(NULL, LNTLM,

            SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred, &tsExpiry);

      if (ss < 0)

        {

         fwprintf(stderr, LAcquireCredentialsHandle 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)

   {

      fwprintf(stderr, LAcceptSecurityContext 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)

             {

            fwprintf(stderr, LCompleteAuthToken failed with %08X\n, ss);

            return FALSE;

         }

      }

      else

        {

         fwprintf (stderr, LCompleteAuthToken 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;

 

   // Enables passing a particular username and password to the run-time library for

   // the purpose of authentication. The structure is valid for Windows and Macintosh.

   SEC_WINNT_AUTH_IDENTITY ai;

 

   __try

   {

      hModule = LoadSecurityDll();

      if (!hModule)

         __leave;

 

      // Get max token size

      _QuerySecurityPackageInfo(LNTLM, &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

      SecureZeroMemory(&ai, sizeof(ai));

        // The following are crapped!!!

        // We need to cast those back to ANSI!!!

        // https://msdn.microsoft.com/en-us/library/aa378664%28VS.85%29.aspx

#if defined(UNICODE) || defined(_UNICODE)

      ai.Domain = (unsigned short *)szDomain;

      ai.DomainLength = lstrlen(szDomain);

      ai.User = (unsigned short *)szUser;

      ai.UserLength = lstrlen(szUser);

      ai.Password = (unsigned short *)szPassword;

      ai.PasswordLength = lstrlen(szPassword);

      ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

#else

      ai.Domain = (unsigned short *)szDomain;

      ai.DomainLength = lstrlen(szDomain);

      ai.User = (unsigned short *)szUser;

      ai.UserLength = lstrlen(szUser);

      ai.Password = (unsigned short *)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))

            {

               wprintf(LLogged in as Guest!\n);

               fResult = FALSE;

            }

            else

               wprintf(LLogged 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.

//  WCHAR* strInput...

void GetConsoleInput(TCHAR* strInput, int intMaxChars)

{

      char ch;

      char minChar = ' ';

      minChar++;

 

      ch = _getch();

      while (ch != '\r')

      {

            if (ch == '\b' && wcslen(strInput) > 0)

            {

                  strInput[wcslen(strInput)-1]   = '\0';

                  printf(\b \b);

            }

            else if (ch >= minChar && (int)wcslen(strInput) < intMaxChars)

            {

                  strInput[wcslen(strInput)+1] = '\0';

                  strInput[wcslen(strInput)]   = ch;

                  _putch('*');

            }

            ch = _getch();

      }

      _putch('\n');

}

int wmain(int argc, WCHAR **argv)

{

      WCHAR password[PWLEN+1];

 

   if (argc != 3)

      {

            wprintf(LUsage: %s DomainName UserName\n, argv[0]);

            return 1;

      }

 

      wprintf(LEnter password for the specified user: );

      password[0] = 0;

      GetConsoleInput(password, PWLEN);

      wprintf(L\n);

   // argv[1] - Domain Name

   // argv[2] - User Name

   if (SSPLogonUser(argv[1], argv[2], password))

   {

      wprintf(LUser Credentials are valid!\n);

   }

   else

      wprintf(LUser Credentials are NOT valid!\n);

}

 

Build and run the project. The following screenshot is a sample output.

 

Validate User Credentials on Microsoft Operating Systems Program Example: A sample output showing the user account validations

 

 

 

< Windows ACL Example 32 | Windows Access Control List (ACL) Main | Win32 Programming | Windows ACL Example 34 >