Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Permissions required to enumerate domain using WinNT provider

1,673 views
Skip to first unread message

Brian Baker [MVP]

unread,
Feb 27, 2003, 4:11:09 PM2/27/03
to
I want to write some code in VB that can enumerate users or lookup
information about a specific user in an NT4 domain. I'm wondering what
specific rights the user will need to have to run this code. I know that
a domain administrator has access to this, but I would prefer to take a
normal user and just add the necessary privileges.

Here is some example code:

set oAds = GetObject("WinNT://domain/username")

This statement will generate an error number -2147024843 (80070035h) if
invoked as a normal user.

Brian Baker
--
Microsoft MVP -- ASP / ASP.NET
Please post responses to the group


Carlos Magalhaes

unread,
Feb 28, 2003, 5:49:21 AM2/28/03
to
You running it through as web page I assume?
The minimum requirements to query a domain is a valid user on that
domain (that is for QUERYING the domain like querying a user) this
applys to the WinNT provider.

ASP is the IUSW_an user if you have annonymous enabled on the Vir Dir

What is your application setup:

web application( i suspect) windows appliation>?

Are you using impersonation? What or how is you Vir Directory setup?

If you using asp.net is impersonation = true in your web.config?


How are you invoking the user to run the code, if you running asp.net
ASPNET is running the process and

On Thu, 27 Feb 2003 16:11:09 -0500, "Brian Baker [MVP]"
<ne...@plproductions.biz> wrote:

>I want to write some code in VB that can enumerate users or lookup


Carlos Magalhaes
Professional ADSI/DirectoryServices Help and answers?
http://groups.yahoo.com/group/ADSIANDDirectoryServices/
Professional WMI Programming Help and answers?
http://groups.yahoo.com/group/WMIPROGRAMMING

Brian Baker [MVP]

unread,
Feb 28, 2003, 9:53:48 AM2/28/03
to
Carlos Magalhaes wrote:
> You running it through as web page I assume?
> The minimum requirements to query a domain is a valid user on that
> domain (that is for QUERYING the domain like querying a user) this
> applys to the WinNT provider.

No, acutally I am trying to do it with a VB6 desktop application. I know
in most cases you only need a valid user, but I think at the location that
I am trying to do this, the network administrators have disabled something
(or enabled some security setting) that is causing it to not work as I
expected.

Carlos Magalhaes

unread,
Feb 28, 2003, 1:31:41 PM2/28/03
to
Well then you need to obtain a valid user for that group or object you
are trying to access and then use those credentials to bind to that
object i.e WinNT://mydomain,username,password

And that should set the perm for you.

On Fri, 28 Feb 2003 09:53:48 -0500, "Brian Baker [MVP]"
<ne...@plproductions.biz> wrote:

>Carlos Magalhaes wrote:
>> You running it through as web page I assume?
>> The minimum requirements to query a domain is a valid user on that
>> domain (that is for QUERYING the domain like querying a user) this
>> applys to the WinNT provider.
>
>No, acutally I am trying to do it with a VB6 desktop application. I know
>in most cases you only need a valid user, but I think at the location that
>I am trying to do this, the network administrators have disabled something
>(or enabled some security setting) that is causing it to not work as I
>expected.
>
>Brian Baker

Carlos Magalhaes

Brian Baker [MVP]

unread,
Mar 4, 2003, 3:51:36 PM3/4/03
to
Carlos Magalhaes wrote:
> Well then you need to obtain a valid user for that group or object you
> are trying to access and then use those credentials to bind to that
> object i.e WinNT://mydomain,username,password

The code is already executing as a valid domain user. (I am logged in to
the domain at my workstation when executing the application.)

I have been able to get this to work correctly in a test environment with
a standard user account. But since it does not work in this scenario, I
am a little stumped. I thought there might be some restrictions on the
domain controllers that would prevent querying this information.

Carlos Magalhaes

unread,
Mar 5, 2003, 7:37:32 AM3/5/03
to
The only restrictions are if that user(S) group that you are using
does not have permissions to the object(s) you are trying to access.

Can you re post the code and the error message. Also are you in the
same domain you trying to query when excuting the application?

I.e. if you trying to retrive info from domain A are you exe'ng the
application in domain A or are you in a diffrent domain?


On Tue, 4 Mar 2003 15:51:36 -0500, "Brian Baker [MVP]"
<ne...@plproductions.biz> wrote:

>Carlos Magalhaes wrote:
>> Well then you need to obtain a valid user for that group or object you
>> are trying to access and then use those credentials to bind to that
>> object i.e WinNT://mydomain,username,password
>
>The code is already executing as a valid domain user. (I am logged in to
>the domain at my workstation when executing the application.)
>
>I have been able to get this to work correctly in a test environment with
>a standard user account. But since it does not work in this scenario, I
>am a little stumped. I thought there might be some restrictions on the
>domain controllers that would prevent querying this information.
>
>Brian Baker

Carlos Magalhaes

Brian Baker [MVP]

unread,
Mar 5, 2003, 10:15:25 AM3/5/03
to
Hi Carlos.

Thanks again for helping. To answer the question, I am in the same domain
that I am trying to query.

I did read somewhere in MSDN that the WinNT provider uses the underlying
Net* API calls. In reading documentation on those, I came across some
statements like needing "List Contents access to the Domain object" and
"Enumerate Entire SAM Domain access on the SAM Server object in the System
container". However, I have no idea what those statements refer to or how
to determine that the user account does or does not have that access.
Does this make sense to you?

Here is the code that I am running. Again, this is in a standard VB6 app
with a reference to the Active DS Type Library.
***************************************
Private Sub Command1_Click()

Dim oAds
Dim oAdsMember
Dim strResult As String

On Error Resume Next

Set oAds = GetObject("WinNT://" & Text1.Text)

If Err.Number = "-2147024843" Then
strResult = "Bad username!!"
ElseIf Err.Number <> 0 Then
strResult = "Error #: " & Err.Number
Else
strResult = strResult & "Full Name: " & oAds.Get("FullName") &
vbNewLine
strResult = strResult & "Bad Password attempts: " &
oAds.Get("BadPasswordAttempts") & vbNewLine
strResult = strResult & "Description: " & oAds.Get("Description")
& vbNewLine
strResult = strResult & "Password expired: " &
CBool(oAds.Get("PasswordExpired")) & vbNewLine & vbNewLine
strResult = strResult & "Group membership:" & vbNewLine

For Each oAdsMember In oAds.Groups
strResult = strResult & " " & oAdsMember.Name & " ("
& oAdsMember.Description & ")" & vbNewLine
Next
End If

Text2.Text = strResult

Set oAds = Nothing
End Sub
***************************************

When I run this and specify "domain/user", I get the -2147024843 error.
(The actual description in the Err object is "Automation error The network
path was not found.")

Thanks,
Brian Baker

Carlos Magalhaes wrote:
> The only restrictions are if that user(S) group that you are using
> does not have permissions to the object(s) you are trying to access.
>
> Can you re post the code and the error message. Also are you in the
> same domain you trying to query when excuting the application?
>
> I.e. if you trying to retrive info from domain A are you exe'ng the
> application in domain A or are you in a diffrent domain?
>
>
>
>
> On Tue, 4 Mar 2003 15:51:36 -0500, "Brian Baker [MVP]"
> <ne...@plproductions.biz> wrote:
>
>> Carlos Magalhaes wrote:
>>> Well then you need to obtain a valid user for that group or object you
>>> are trying to access and then use those credentials to bind to that
>>> object i.e WinNT://mydomain,username,password
>>
>> The code is already executing as a valid domain user. (I am logged in
>> to the domain at my workstation when executing the application.)
>>
>> I have been able to get this to work correctly in a test environment
>> with a standard user account. But since it does not work in this
>> scenario, I am a little stumped. I thought there might be some
>> restrictions on the domain controllers that would prevent querying this
>> information.

--

Carlos Magalhaes

unread,
Mar 6, 2003, 8:53:29 AM3/6/03
to
>I did read somewhere in MSDN that the WinNT provider uses the underlying
>Net* API calls. In reading documentation on those, I came across some
>statements like needing "List Contents access to the Domain object" and
>"Enumerate Entire SAM Domain access on the SAM Server object in the System
>container". However, I have no idea what those statements refer to or how
>to determine that the user account does or does not have that access.

That is correct, through the WinNT provider provided to you by ADSI
you are accessing underlying API's.

Ok

Can you change your bind string to the following:
GetObject("WinNT://" & Text1.Text ,Nothing,
Nothing,AuthenticationType.Secure)

Basically what this does, requests secure authentication. When this
flag is set, the WinNT provider uses NTLM to authenticate the client.
Active Directory uses Kerberos, and possibly NTLM, to authenticate the
client. When the user name and password are a null reference (Nothing
in Visual Basic), ADSI binds to the object using the security context
of the calling thread, which is either the security context of the
user account under which the application is running or of the client
user account that the calling thread is impersonating.


BUT from your error, it does not look like the WinNT provider is
finding the Path being specified by Text1.Text

Can you quickly hardcode a path that you know exsits and test then
report back.


On Wed, 5 Mar 2003 10:15:25 -0500, "Brian Baker [MVP]"
<ne...@plproductions.biz> wrote:

Carlos Magalhaes

Brian Baker [MVP]

unread,
Mar 6, 2003, 11:07:51 AM3/6/03
to
Carlos:

VB did not like your GetObject syntax. I did get the following code to
compile correctly, but with the same run-time error message:

******************************
Dim openDS As IADsOpenDSObject
Dim usr As IADsUser
Dim strResult As String

Set openDS = GetObject("WinNT:")
On Error Resume Next
Set usr = openDS.OpenDSObject("WinNT://domain/username", "", "",
ADS_SECURE_AUTHENTICATION)

If Err.Number = "-2147024843" Then
strResult = "Bad username!!"
ElseIf Err.Number <> 0 Then
strResult = "Error #: " & Err.Number
Else

strResult = strResult & "Full Name: " & usr.Get("FullName") &


vbNewLine
strResult = strResult & "Bad Password attempts: " &

usr.Get("BadPasswordAttempts") & vbNewLine
strResult = strResult & "Description: " & usr.Get("Description") &


vbNewLine
strResult = strResult & "Password expired: " &

CBool(usr.Get("PasswordExpired")) & vbNewLine & vbNewLine


strResult = strResult & "Group membership:" & vbNewLine

End If

Text2.Text = strResult

Set usr = Nothing
Set openDS = Nothing
******************************

So, even with hardcoding the path (which happens to be the same domain I
am logged into and my own username), the code still generates
error -2147024843.

I'd be happy to heard any more tips that you might have!

Brian Baker

--

Carlos Magalhaes

unread,
Mar 6, 2003, 2:39:46 PM3/6/03
to
Sorry about that it was late and i posted System.DirectoryServices
code! didnt see you using vb6.

Ok so let me make sure here Brian,

You have done the following:

hard coded the path into the Getobject i.e. WinNT://Mydomain/Username,
" ", " " ,ADS_SECURE_AUTHENTICATION)

I would check the equivalant in VB6 for the object Nothing because a
empty string is not the same as the Nothing object.

hard coded your user name and password into the path

WinNT://Mydomain/Username, "Brian ", "whydoesthisnotwork "
,ADS_SECURE_AUTHENTICATION)

And you say that on the test domain this worked?

Also have you made ABSOLUTELY SURE that that path is correct , Netbios
domain name and the user exsits on the domain, are you sure you not
trying to access a local computer account the code for this is
diffrent.

reason i am asking is because the error you getting is that it can not
find the path.....

Can you answer these questions for me?

Also please use this path rather, if you know which user you trying to
access:

("WinNT://" & strDomain & "/" & strUser & ",user")

strDomain =netbios Domain name
strUser = Username
User = is expicitly specifiying that you binding to a User class

let me know!

On Thu, 6 Mar 2003 11:07:51 -0500, "Brian Baker [MVP]"
<ne...@plproductions.biz> wrote:

>

Carlos Magalhaes

Brian Baker [MVP]

unread,
Mar 6, 2003, 3:14:43 PM3/6/03
to
Carlos et al:

I found the problem! I did some searching on older posts on Google and
discovered that there was a problem with the Security Rollup Package
(http://support.microsoft.com/?kbid=299444) breaking some functionality of
ADSI 2.5 on NT 4. Installing the Active Directory Client Extension update
(http://support.microsoft.com/?kbid=288358) fixed it. With this
installed, the code works as originally posted.

Thanks for all your help!

Brian Baker

Brian Baker [MVP] wrote:
> I want to write some code in VB that can enumerate users or lookup
> information about a specific user in an NT4 domain. I'm wondering what
> specific rights the user will need to have to run this code. I know
that
> a domain administrator has access to this, but I would prefer to take a
> normal user and just add the necessary privileges.
>
> Here is some example code:
>
> set oAds = GetObject("WinNT://domain/username")
>
> This statement will generate an error number -2147024843 (80070035h) if
> invoked as a normal user.

--

Carlos Magalhaes

unread,
Mar 7, 2003, 1:21:49 AM3/7/03
to
Hey Brian

I was about to pull my hair out!

Thanks for the info will def add to my lib.

Good luck on your application!

Carlos Magalhaes

Zweitze de Vries

unread,
Mar 7, 2003, 4:48:38 AM3/7/03
to
Another workaround, that does not require DSClient, is using a different
connection string:

set oAds = GetObject("WinNT://domain/domaincontroller/username")

Where "domaincontroller" is the name of a known DC in the domain. It's also
faster, since ADSI does not need to find a suitable DC anymore. You can find
a DC on the domain using NetGetDcName and NetGetAnyDcName. If the user
logged on to the same domain, you can use NetWkstaUserGetInfo, which is much
faster (it returns the DC that validated the logon of the user).

It's a bug in SRP; when ADSI tries to find a DC for the domain. It should
use NetGetDcName, but instead it uses DsGetDcName, which was introduced at
Windows 2000. Installing DSClient installs the function on WinNT. The
problem is described in:
http://support.microsoft.com/default.aspx?scid=kb;en-us;311055
Don't be distracted by error code 800a0046: Permission denied. I always get
error code 80070035: The network name could not found.

Hope this helps.
--
Zweitze de Vries
Cyco Software
Rijswijk, Netherlands


"Brian Baker [MVP]" <ne...@plproductions.biz> wrote in message
news:OdQne0B5...@TK2MSFTNGP10.phx.gbl...

Brian Baker [MVP]

unread,
Mar 7, 2003, 9:57:16 AM3/7/03
to
Zweitze de Vries wrote:
> It's a bug in SRP; when ADSI tries to find a DC for the domain. It
should
> use NetGetDcName, but instead it uses DsGetDcName, which was introduced
> at Windows 2000. Installing DSClient installs the function on WinNT. The
> problem is described in:
> http://support.microsoft.com/default.aspx?scid=kb;en-us;311055
> Don't be distracted by error code 800a0046: Permission denied. I always
> get error code 80070035: The network name could not found.

Just curious, but how do you know which API is being called by ADSI? I
had a hard time finding any concrete documentation in the MSDN library
and/or the Knowledge Base that would have led me to the actual resolution.
Even after I read article 311055 the first time I wouldn't have
necessarily thought that it applied to my code -- since I had no way to
know if it was calling DsGetDcName().

Brian Baker

Zweitze de Vries

unread,
Mar 7, 2003, 12:21:02 PM3/7/03
to
Well it's a guess, and it's even wrong (!). But when I deduct everything:
- ADSI needs to forward the request to a server;
- Only a DC can fullfill the request;
- ADSI must determine a DC unless one is specified in the binding string.
If you have a domain name, and want to find a DC:
- On Windows NT 4, you can use NetGetDcName of NetGetAnyDcName
- On Windows 2000 and higher, you should use the new DsGetDcName, which can
also work out Active Directory issues. This function is also available when
the DSClient installed, so clients can resolve the same AD issues.

KB311055 describes a serious bug: SRP updates ADSI, which makes calls to a
DLL that does not exist. The Microsoft solution is mind-boggling: WinNT4
client systems that connect to a WinNT4 domain, should install an extension
issued for connecting Active Directory domains!
For me everything became clear when I read the suggestion to enter the
server name in the binding string: everything is fine from that moment on.
So it's got to be the determination of the DC. BTW: Technically, it's not
ADSI that calls the function, but just the WinNT provider.

But... my suggestion that it's using DsGetDcName is wrong: the second
workaround is updating Dnsapi32.dll. Note that DsGetDcName resides in
Netapi32.dll. So something out there is using a function in Dnsapi32.dll
which is broken. When you install DSClient, it works again, and you also get
an updated Netapi32.dll with DsGetDcName.
I assume that ADSI uses the most advanced methods it can think of: Either
use DsGetDcName, or some function in Dnsapi32.dll I don't know of, or use
NetGetDCName. But something broke in the SRP, and ADSI failed to find the
DC.

I had to be sure that everything works in all situations - I develop
software for thousands of users, which use all kinds of combinations of
service packs, and do not always want to install new addons just because I
tell them. Anyway, you are on the safe side if you determine a DC yourself,
and include it in the connection string.


--
Zweitze de Vries
Cyco Software
Rijswijk, Netherlands


"Brian Baker [MVP]" <ne...@plproductions.biz> wrote in message

news:emSxzvL5...@TK2MSFTNGP10.phx.gbl...

0 new messages