User enters username / pwd into the form. Next, before I do anything else,
I implement impersonation as per the HOW TO article:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q306158
System.Environment.Username will return the user entered into the form, or
the impersonation process fails if invalid AD credentials are entered, so I
believe this part is working as intended.
I then attempt to implement access to AD as per this HOW TO article:
http://support.microsoft.com/default.aspx?scid=KB;EN-US;326340
Note I don't have the VS IDE (yet), so I've been using notepad and the
command-line compiler to include the System.DirectoryServices.dll and
successfully compile FormsAuthad.dll and placed in my web application's bin
folder, all classes and namespaces that I believe I need are properly
configured.
My web.config is set to forms authorization and impersonation = true. IIS
website access is set to anonymous using the default IUSR_machine account.
I am unclear as to what my LDAP connection string should be. I get the
following error every time this whole shabang is executed - In other words I
attempt to access resource on the website, am redirected to login form as
per .net forms auth directive, I enter creds into the form, click the login
button, I impersonate successfully and then when I attempt to check my group
membership on AD, exception is thrown as follows:
I have determined that this line of code, in FormsAuthad.dll,
Dim obj As Object = entry.NativeObject
...is producing the following [beautifully ambiguous] .net exception,
Unknown error (0x80005000)
...which has this COM error code & description:
-2147463168, Unknown error (0x80005000)
I'm stuck right here... I think it's my LDAP path string? Given my AD box
is seperate from my IIS box and resolves to "ads2003.domain.net" I'm unclear
on when, where and why to use CN, DC, UO, et al in the LDAP path. I've
tried the netbios name, the ip address, DNS name, and lots of
shot-in-the-dark attempts at CN/DC/UO values. I get the above error every
attempt, which is the same error I get if I enter pure nonsense as the LDAP
path, so I'm guessing it's the path. I don't know if I should try to "bind
to the user object" or, bind to the root or what (I'm still fuzzy on that
bit, I'm totally new to ADSI/LDAP).
So to recap, I want to look up the user they entered into the form (who I'm
also currently impersonating) and see what groups they belong too, but I
can't seem to connect to AD correctly and I receive "unknown error
0x80005000" when I try. What is my mistake?
Eric
LDAP://ads2003.domain.net/dc=ad2003,dc=domain,dc=net
You can discover a lot of this stuff by using a tool like ldp.exe which
comes with the Windows 2000 support tools on the Win2K AS CD. It is very
helpful for testing searches and binds and the like.
You might also consider writing some simple console applications that you
can test easily to see if you can get some of these AD operations to work in
that environment.
I also don't quite understand what you are trying to do with impersonation
in conjunction with forms auth? If you want to impersonate the user logging
on to the web server, you usually don't do forms auth. Can you elaborate on
what you are trying to accomplish?
Joe K.
"eruess" <eruess_at_reddingpath_dot_com> wrote in message
news:yQidnd72I4j...@speakeasy.net...
etc... I checked out LDAP ADsPath string examples and explanations @ msdn,
all of which produce the error in question. I tried your suggestion as well
with the same results. Perhaps it's not the string? I'm not sure, it's
almost as if it's ignoring it, because I'm pretty sure some of them have
been valid connection/bind strings. Out of sheer frustration, I put a bunch
of nonsense in the LDAP path string and got the same error.
Here's an elaboration of what I'm trying to accomplish (I'm open to
suggestions if there's a better way)
I'll be running a web site that is for the most part anonymous, but there
will be a protected area that will require login. Clients and employees
will use this area to access the company database(s). SQL server uses
windows authentication from Active Directory, so user and permissions
management is convienently centralized for both web content and database
access.
I don't want to use Basic Auth primarily for asthetic reasons (the pop-up is
very unprofessional) but also becuase a lot of our data is very sensitive
and tied into gov't regulations, so I absolutely need some sort of
logout/session timeout system other than closing the browser window, which
is tricky to impossible with Basic auth.
Windows integration is out, as I want to support non-IE browsers.
I don't want to give aspnet, iusr_machine, et al, high-level access to the
database so anonymous access is out.
Each client can have different rights in SQL, which is by in large dependant
upon their AD group membership, so I need to "be" the user when I make SQL
queries.
All these requirements led me to .net forms authentication with
impersonation... this would give me total control over a professional
looking form login interface, cookie based (can crush the cookie to logout),
and then I can impersonate the user (which essentially validates them) but I
also want to see what groups they belong to, in order to deliver custom web
content.
This would all run with SSL to secure it, even tho I think .net forms auth
is secure anyway, the data itself will more than likely need to be
encrypted.
A bit on the topology as well: sql2003.domain.net and ads2003.domain.net
reside on subnetA and iis2003.domain.net resides on subnetB, I'm not sure if
LDAP is routable or if it uses TCP/IP or what. These are .NET 2003 RC2
servers, IIS6, .NET 1.1.
I'm going to check out ldp.exe later this afternoon when I get a chance,
hopefully it will educate me to something I'm (obviously) missing.
eric
"Joe Kaplan" <ilearnedthi...@noway.com> wrote in message
news:OeJLgnUC...@TK2MSFTNGP12.phx.gbl...
I guess there are two points I want to make regarding your impersonation
scheme:
- If you use windows auth. with your database, you will not be able to take
advantage of connection pooling, so you may have scalability issues. That
is something to look out for.
- If you want to do impersonation, you need to get a logon token for the
user somehow. For example, with Basic auth, IIS calls LogonUser for you.
I'm not sure if this is built in to forms auth, so you may need to look at
that.
Check out what kind of progress you can make with ldp and some simple test
programs and let us know how you do.
Joe K.
"eruess" <eruess_at_reddingpath_dot_com> wrote in message
news:tzadnZKH1-7...@speakeasy.net...
I can use ldp.exe and connect to AD just fine from the IIS box. Up in ldp's
title bar, it shows the string as such:
LDAP://ads2003.domain.net/CN=domain,CN=net
I can view objects and the like just fine from the ldp tool. And I can do
this while logged into the iis box as one of the users I'm entering into the
form (and thusly impersonating) so I'm not sure if it's a permissions issue.
I'm starting to suspect that the code from microsoft's HOW TO that I'm using
to interact with AD is malformed given my environment... I don't know why it
does a few of the things it does, it seems like System.DirectoryServices
would have sufficient tools to do what I need to do... for some reason the
HOW TO article uses unmanaged COM code and it just so happens that's what's
producing the error. I feel like there's some variables here I don't
understand, because this isn't making much sense to me at this point :p
"Joe Kaplan" <ilearnedthi...@noway.com> wrote in message
news:u0fN5RcC...@TK2MSFTNGP10.phx.gbl...
The reason the same code accesses the NativeObject property is just to force
the entry to bind to the directory. The object doesn't bind until forced
to. You could just as easily access the Guid or NativeGuid property or call
RefreshCache to get the same effect.
The next thing I would suggest is writing a simple console app with a known
good path and see if you can make progress with that.
It sounds like your impersonation approach will work, although MS has posted
a new, much improved Pinvoke impersonation sample in the 1.1 documentation
here:
Keep us posted. I wish I had a magic solution for you, but the problem
isn't obvious to me yet.
Joe K.
"eruess" <eruess_at_reddingpath_dot_com> wrote in message
news:ADednfixg9e...@speakeasy.net...
http://support.microsoft.com/default.aspx?scid=KB;EN-US;326340
and modified it to interact directly at the console, allowing me to enter an
ldap path, username & password (I went ahead and hard-coded the domain since
there's only one). I compiled it as an .exe & ran it from the command
prompt. The results were encouraging, yet confusing - The line that
typically throws an exception, where it casts the NativeObject to force a
bind, executes without error - it goes on to perform a search on the user I
enter and it returns a pipe delineated list of memberOf for that user. It
worked - perfectly! At the very least, my moral shot way up at that point.
It's in a console, and useless, but it's *working!* That's using an LDAP
path of simply LDAP://ads2003, which makes logical sense to me since I've
got WINS going and that's the NETBIOS name of the PDC I'm trying to talk to.
Other successful LDAP strings include
LDAP://ads2003.domain.net/DC=domain,DC=net, LDAP://DC=domain,DC=net and
LDAP://x.x.2.4 (server's ip). They all work fine. None of these work in my
asp.net version of things, leading me to believe error code 0x80005000 is
an erroneously reported error code (or the LDAP provider's error codes are
different from the WinNT providers, that code is actually "bad path"
returned from the WinNT provider, I think).
So anyway, my next obvious question is: why does this work as a console
.exe, but not as an Asp.net process? I think I can guess the answer... my
vague understanding of all of this is telling me it simply must be a
permissions issue. Asp.net and the console app must be running under
different security contexts, right? The logic in the code, with the
exception of where it gets input from and where it outputs feedback to, is
basically identical from the console.exe and the formsauth.dll. Despite my
impersonation in the asp.net process, there must still be a
permissions/security issue denying me access or otherwise flubbing things
up.
I admit I'm wandering into pretty murky waters here; I have no idea how I
could impersonate as the Domain Administrator and still have a security
issue, but it certainly seems that way.
"Joe Kaplan" <ilearnedthi...@noway.com> wrote in message
news:#T2MEfgC...@TK2MSFTNGP10.phx.gbl...
Just as one other check, you can verify the identity of the current thread
by calling System.Security.Principal.WindowsIdentity.GetCurrent().Name.
This will give you the windows username for the current thread.
It sounds like you are getting it worked out. One other thing I should
point out is that memberOf doesn't give you nested group membership, only
direct group membership. If you want a flat list of all groups (including
nested membership), then the user's tokenGroups attribute can use used to
get a list of SIDs (as byte arrays) for the user.
However, given that you have called LogonUser and have an appropriate token
for the current user, you shouldn't need to actually do any group lookups.
You can use this token handle to create a WindowIdentity and a
WindowsPrincipal that you can associate with the current HTTP context. The
WindowsPrincipal will then be used for all of your role-based security
checks (by calling its IsInRole method). The roles will correspond to the
domain groups the user belongs. They are specified in Win NT account name
format (domain\samAccountName).
So it seems to me that you might not even need to lookup the user in AD at
all. Just let the platform security services take care of that stuff for
you.
Joe K.
"eruess" <eruess_at_reddingpath_dot_com> wrote in message
news:oRycnTyNsJt...@speakeasy.net...
Impersonating as "DOMAIN\AdministrativeUser" in the Asp.net application,
using the code referenced in the link above, produces the following
anomolies:
System.Environment.UserName will return "AdministrativeUser"
however,
System.Environment.DomainUserName will throw a "DomainUserName native call
failed" exception
System.Security.Principal.WindowsIdentity.GetCurrent().Name will throw an
"access denied" exception
However, logging into the IIS box directly as DOMAIN\AdministrativeUser and
running the same queries in a console app produces the following:
System.Security.Principal.WindowsIdentity.GetCurrent().Name returns
"DOMAIN\AdministrativeUser"
System.Environment.UserName returns "AdministrativeUser"
System.Environment.DomainUserName returns "DOMAIN"
Somehow I'm not really taking on the full rights and permissions of
DOMAIN\AdministrativeUser (or whomever) in the asp.net impersonation.
I thought that was interesting... and for some reason, more or less just to
tinker, I went into my web.config file for this application and changed the
<identity impersonate> value from true, which is what it's been all this
time, to false.
Now, in the asp.net application, I can call GetCurrent().Name and it returns
it properly, I can call Environment.UserDomainName and it returns it
properly, and as far as I can tell, I'm now doing what I set out to do in
the first place - the entire asp.net application, such as it currently is,
is running without error.
I assume this is because NETWORK SERVICE has rights the IUSR_IIS2003 does
not? I'm not sure what explains it exactly, though.
e
"Joe Kaplan" <ilearnedthi...@noway.com> wrote in message
news:uiB$D1oCD...@TK2MSFTNGP11.phx.gbl...