Использовать DsBindWithCred .Обратите внимание, что эта функция завершается ошибкой с отказом в доступе, даже если учетные данные технически действительны, например, учетная запись заблокирована.Вам придется использовать функцию LogonUser, если вы хотите, чтобы этот уровень детализации, но каждый вызов будет засчитываться как попытка входа в систему.
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Text;
public class PInvoke
{
public static bool TestCreds(string usernamePossiblyWithDomain,
SecureString password,
string dnsDomainName)
{
string username, usernameDomain;
ParseUserName(usernamePossiblyWithDomain, out username, out usernameDomain);
IntPtr pPass = Marshal.SecureStringToGlobalAllocUnicode(password);
try
{
IntPtr hDS = IntPtr.Zero;
IntPtr authID = MakePassCreds(username, usernameDomain, pPass);
//if you're really paranoid, you can uncomment the next two lines
//to zero out the memory as soon as possible
//Marshal.ZeroFreeGlobalAllocUnicode(pPass);
//pPass = IntPtr.Zero;
try
{
int lastErr = DsBindWithCred(null, dnsDomainName, authID, ref hDS);
switch(lastErr)
{
case 0: return true; //ERROR_SUCCESS
case 5: return false; //ERROR_ACCESS_DENIED
default: throw new Win32Exception(lastErr);
}
}
finally
{
if(hDS != IntPtr.Zero) DsUnBind(ref hDS);
if(authID != IntPtr.Zero) DsFreePasswordCredentials(authID);
}
}
finally
{
if(pPass != IntPtr.Zero) Marshal.ZeroFreeGlobalAllocUnicode(pPass);
}
}
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
protected static extern int CredUIParseUserName(string pszUserName,
StringBuilder pszUser, int ulUserMaxChars,
StringBuilder pszDomain, int ulDomainMaxChars);
public static void ParseUserName(string usernamePossiblyWithDomain,
out string username, out string domain)
{
int MaxUserChars = 256, maxDomainChars = 256;
StringBuilder sbUser = new StringBuilder(maxUserChars);
StringBuilder sbDomain = new StringBuilder(maxDomainChars);
int lastErr = CredUIParseUserName(usernamePossiblyWithDomain, sbUser,
maxUserChars - 1, sbDomain, maxDomainChars - 1);
if(lastErr != 0) throw new Win32Exception(lastErr);
username = sbUser.ToString();
domain = sbDomain.ToString();
}
[DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)]
protected static extern int DsMakePasswordCredentials(
string User, string Domain, IntPtr Password, ref IntPtr pAuthIdentity);
[DllImport("ntdsapi.dll")]
public static extern int DsFreePasswordCredentials(IntPtr AuthIdentity);
//caller is responsible for calling DsFreePasswordCredentials on the return val
public static IntPtr MakePassCreds(string username, string domain, IntPtr pPass)
{
IntPtr auth = IntPtr.Zero;
int lastErr = DsMakePasswordCredentials(username, domain, pPass, ref auth);
if(lastErr != 0) throw new Win32Exception(lastErr);
return auth;
}
[DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)]
protected static extern int DsBindWithCred(string DomainControllerName,
string DnsDomainName, IntPtr AuthIdentity, ref IntPtr phDS);
[DllImport("ntdsapi.dll")]
public static extern int DsUnBind(ref IntPtr phDS);
}