D
deltalimagolf
I've got an asp.net site where it's setup to use forms authentication. I
take the username and password provided and authenticate them by calling the
LogonUser method (from advapi32). If that is successful I call the
DuplicateToken method and then using WindowsIdentity impersonate the user and
attempt to get the groups the user is a member of. Everything works up to
the attempt to get the groups, I get a 'The specified domain either does not
exist or could not be contacted.' error. The following code works on my
local box (even when running IE as a local - non AD - user), but when it is
deployed to a web server in the DMZ the error mentioned is seen.
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
string principal, string authority, string password,
LogonSessionType logonType, LogonProvider logonProvider, out IntPtr token);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int
impersonationLevel, ref IntPtr hNewToken);
public static ArrayList UserMemberOf(string path, string username)
{
DirectorySearcher search = new DirectorySearcher(path);
search.Filter = "(sAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("memberOf");
ArrayList groups = new ArrayList();
try
{
SearchResult result = search.FindOne();
if (result != null)
{
int propertyCount = result.Properties["memberOf"].Count;
String dn;
int equalsIndex, commaIndex;
for (int propertyCounter = 0; propertyCounter < propertyCount;
propertyCounter++)
{
dn = (String)result.Properties["memberOf"][propertyCounter];
equalsIndex = dn.IndexOf("=", 1);
commaIndex = dn.IndexOf(",", 1);
if (-1 == equalsIndex)
{
return null;
}
groups.Add(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex)
- 1));
}
}
}
catch (Exception ex)
{
throw new Exception("Error obtaining group names ('" + path + "','" +
username + "'). " + ex.Message);
}
return groups;
}
protected void clkLogin(object sender, EventArgs e)
{
IntPtr iptrUserToken = IntPtr.Zero;
IntPtr iptrDuplicateToken = IntPtr.Zero;
try
{
bool bAuthenticated =
LDAP.LogonUser(txtUserName.Text,
GatewayAdministrationWebConfig.AuthenticationDomain, txtPassword.Text,
LDAP.LogonSessionType.NewCredentials, LDAP.LogonProvider.Default, out
iptrUserToken);
if (!bAuthenticated)
{
return;
}
if (LDAP.DuplicateToken(iptrUserToken,
(int)TokenImpersonationLevel.Impersonation, ref iptrDuplicateToken) != 0)
{
using (WindowsImpersonationContext winImpersonation =
WindowsIdentity.Impersonate(iptrDuplicateToken))
{
if (winImpersonation == null)
{
throw new Exception("impersonation context is null");
}
string sUserDn = "LDAP://[authentication server ip
address]/OU=[],dc=[],dc=net";
ArrayList alGroups = LDAP.UserMemberOf(sUserDn, txtUserName.Text);
winImpersonation.Undo();
if ((alGroups == null) || (alGroups.IndexOf("[AD Group]") == -1))
{
return;
}
FormsAuthenticationTicket authTicket =
new FormsAuthenticationTicket(1,
txtUserName.Text,
DateTime.Now,
DateTime.Now.AddMinutes(60),
false,
string.Empty);
string sTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie cookieTicket = new
HttpCookie(FormsAuthentication.FormsCookieName, sTicket);
Response.Cookies.Add(cookieTicket);
Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUserName.Text,
false));
}
}
else
{
return;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{ // Free the tokens
if (iptrUserToken != IntPtr.Zero)
LDAP.CloseHandle(iptrUserToken);
if (iptrDuplicateToken != IntPtr.Zero)
LDAP.CloseHandle(iptrDuplicateToken);
}
}
take the username and password provided and authenticate them by calling the
LogonUser method (from advapi32). If that is successful I call the
DuplicateToken method and then using WindowsIdentity impersonate the user and
attempt to get the groups the user is a member of. Everything works up to
the attempt to get the groups, I get a 'The specified domain either does not
exist or could not be contacted.' error. The following code works on my
local box (even when running IE as a local - non AD - user), but when it is
deployed to a web server in the DMZ the error mentioned is seen.
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
string principal, string authority, string password,
LogonSessionType logonType, LogonProvider logonProvider, out IntPtr token);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int
impersonationLevel, ref IntPtr hNewToken);
public static ArrayList UserMemberOf(string path, string username)
{
DirectorySearcher search = new DirectorySearcher(path);
search.Filter = "(sAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("memberOf");
ArrayList groups = new ArrayList();
try
{
SearchResult result = search.FindOne();
if (result != null)
{
int propertyCount = result.Properties["memberOf"].Count;
String dn;
int equalsIndex, commaIndex;
for (int propertyCounter = 0; propertyCounter < propertyCount;
propertyCounter++)
{
dn = (String)result.Properties["memberOf"][propertyCounter];
equalsIndex = dn.IndexOf("=", 1);
commaIndex = dn.IndexOf(",", 1);
if (-1 == equalsIndex)
{
return null;
}
groups.Add(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex)
- 1));
}
}
}
catch (Exception ex)
{
throw new Exception("Error obtaining group names ('" + path + "','" +
username + "'). " + ex.Message);
}
return groups;
}
protected void clkLogin(object sender, EventArgs e)
{
IntPtr iptrUserToken = IntPtr.Zero;
IntPtr iptrDuplicateToken = IntPtr.Zero;
try
{
bool bAuthenticated =
LDAP.LogonUser(txtUserName.Text,
GatewayAdministrationWebConfig.AuthenticationDomain, txtPassword.Text,
LDAP.LogonSessionType.NewCredentials, LDAP.LogonProvider.Default, out
iptrUserToken);
if (!bAuthenticated)
{
return;
}
if (LDAP.DuplicateToken(iptrUserToken,
(int)TokenImpersonationLevel.Impersonation, ref iptrDuplicateToken) != 0)
{
using (WindowsImpersonationContext winImpersonation =
WindowsIdentity.Impersonate(iptrDuplicateToken))
{
if (winImpersonation == null)
{
throw new Exception("impersonation context is null");
}
string sUserDn = "LDAP://[authentication server ip
address]/OU=[],dc=[],dc=net";
ArrayList alGroups = LDAP.UserMemberOf(sUserDn, txtUserName.Text);
winImpersonation.Undo();
if ((alGroups == null) || (alGroups.IndexOf("[AD Group]") == -1))
{
return;
}
FormsAuthenticationTicket authTicket =
new FormsAuthenticationTicket(1,
txtUserName.Text,
DateTime.Now,
DateTime.Now.AddMinutes(60),
false,
string.Empty);
string sTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie cookieTicket = new
HttpCookie(FormsAuthentication.FormsCookieName, sTicket);
Response.Cookies.Add(cookieTicket);
Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUserName.Text,
false));
}
}
else
{
return;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{ // Free the tokens
if (iptrUserToken != IntPtr.Zero)
LDAP.CloseHandle(iptrUserToken);
if (iptrDuplicateToken != IntPtr.Zero)
LDAP.CloseHandle(iptrDuplicateToken);
}
}