How to check password complexity using NetValidatePasswordPolicy

The NetValidatePasswordPolicy function allows an application to verify that passwords meet the complexity requirement.
Here is an important remark from Microsoft :
“The NetValidatePasswordPolicy function does not validate passwords in Active Directory accounts and cannot be used for this purpose. The only policy that this function checks a password against in Active Directory accounts is the password complexity (the password strength).”

The following code checks if the password meets complexity requirement using NetValidatePasswordPolicy:

#include <Windows.h>
#include <Lm.h>
#include <Dsgetdc.h>
#include <stdio.h>

WCHAR *DisplayErrorText(DWORD dwLastError)
{
    HMODULE hModule = NULL;
    LPWSTR MessageBuffer = NULL;
    DWORD dwBufferLength;

    DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_IGNORE_INSERTS |
        FORMAT_MESSAGE_FROM_SYSTEM ;

    if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {
        hModule = LoadLibraryEx(
            TEXT("netmsg.dll"),
            NULL,
            LOAD_LIBRARY_AS_DATAFILE
            );

        if(hModule != NULL)
            dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
    }

    FormatMessageW(
        dwFormatFlags,
        hModule,
        dwLastError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPWSTR) &MessageBuffer,
        0,
        NULL
        );

    if(hModule != NULL)
        FreeLibrary(hModule);

	return MessageBuffer;
}


int wmain(int argc, wchar_t * argv[])
{
      NET_API_STATUS status;
      NET_VALIDATE_PASSWORD_CHANGE_INPUT_ARG InputArg = {0};
	  DWORD res = 0;
	  wchar_t* wzServer = NULL;
      NET_VALIDATE_OUTPUT_ARG* pOutputArg = NULL;

	  if(argc < 2)
	  {
		  wprintf(L"Usage: MyNetValidatePasswordPolicy password\r\n");
		  return -1;
	  }

	  PDOMAIN_CONTROLLER_INFO  DcInfo;// Get address of nearest DC as cached by OS at boot time.
      if (!DsGetDcName(NULL, NULL, NULL, NULL,
                    DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_FLAT_NAME,
                    &DcInfo))
      {
		  wzServer = DcInfo->DomainControllerName;
	  }
	  else
		  wzServer = _wgetenv(L"LOGONSERVER");

      InputArg.ClearPassword = argv[1];
      InputArg.PasswordMatch = TRUE;
      status = NetValidatePasswordPolicy(wzServer, NULL, NetValidatePasswordChange, &InputArg, (void**)&pOutputArg);
	  if(status != NERR_Success)
	  {
		  wprintf(L"Error NetValidatePasswordPolicy %s\r\n", DisplayErrorText(status));
	  }
	  else
	  {
		  if(pOutputArg->ValidationStatus == 0)
			  wprintf(L"Password validated for a password change operation\r\n");
		  else
			  wprintf(L"Password validation failed for a password change operation: %s\r\n", DisplayErrorText(pOutputArg->ValidationStatus));
	  }
      NetValidatePasswordPolicyFree((void**)&pOutputArg);
	  return 0;
} 

Speak Your Mind

*