Retrieving Groups from a DSQUERY


#1

I need a list of all the groups a user is part of. When I do the
DSQuery in returns a bunch of groups. I need to capture the group
names.
All groups start with CN=group name and end with a comma.
How to I capture the group name only, which starts after CN= and ends
at the FIRST comma??


#2

anon1m0us wrote:

I need a list of all the groups a user is part of. When I do the
DSQuery in returns a bunch of groups. I need to capture the group
names.
All groups start with CN=group name and end with a comma.
How to I capture the group name only, which starts after CN= and ends
at the FIRST comma??

Actually it doesn’t end at the first comma - you could have
a backslashed comma inside the group’s CN. I recsll doing it
something like this:

group_dn =‘CN=Users, Group,OU=farnarkle’

group_cn = group_dn.sub(/CN=((:?[^\,]|\.))./, $1)

puts group_cn

Users, Group

This matches the name as a sequence of either a single
backslashed character, or a char that’s not either
a backslash or a comma. Note that the result is still
LDAP-escaped.

Clifford H…


#3

From: anon1m0us [mailto:removed_email_address@domain.invalid] :

I need a list of all the groups a user is part of. When I do the

DSQuery in returns a bunch of groups. I need to capture the group

names.

All groups start with CN=group name and end with a comma.

How to I capture the group name only, which starts after CN= and ends

at the FIRST comma??

small world :wink:

look into “dsquery group” and “dsget group <group_name> -members”

C:\family\ruby\win-ds-groups>cat test.rb
#######################

botp

updated: 2007 03 21

#######################

get all internet groups w names like “internet mail or internetusers”

groups=dsquery group -limit 1000 | egrep -i "internet(users| mail)"

len = groups.max.length + 20 # not important; just want to get length
for
header line separator

display groups and the count

groups.each_with_index do |g,i|
puts “-”*len
puts “Group #{i+1}: #{g}”
puts “-”*len

for each group get the members

members = dsget group #{g} -members

for each member display name and the count

members.each_with_index do |m,i|
name = m.sub “,CN=Users,DC=delmonte-phil,DC=com”", “”
name = name.sub "“CN=”, “”
name = name.sub “\”, “”
puts “#{i+1}: #{name}”
end
end
#------------------

hth.
kind regards -botp


#4

From: Clifford H. [mailto:removed_email_address@domain.invalid] :

It sounds like the OP already did that.

arggh, mea culpa. you’re right, in fact, after reading again th op, my
sample was totally wrong. He was asking what groups the user belong to
and my sample just plain listed all the groups and users (of no use
really)

This only works for users in CN=Users, even assuming that

you adjust the domain name as appropriate. My solution

gets the CN from any user, whether in CN=Users or not,

without knowing the domain name.

Hint: many organizations put their users in OU’s… The

CN=Users container is really only there for migration

from NT4, so the domain root isn’t filled up with users

and computers from the migration.

It’s even legal to put users in a container (CN=) under

an OU, though it’s not advised (it’s allowed because

that’s what CN=Users is). The only correct solution is

to match the RDN component after the user’s CN=, up to

the start of the next RDN part, as I showed.

Great tip/info there, Clifford.

Many thanks
-botp

ps: Clifford, if by any chance you know how to query a msexchange: I’d
like to query all exchange mailboxes and for each mailbox, list all the
users who have rights to access it. (since many of us share mailboxes).
Pardon the nubiness on windows/exchange…


#5

Peña wrote:

look into “dsquery group” and “dsget group <group_name> -members”

It sounds like the OP already did that.

  name = m.sub ",CN=Users,DC=delmonte-phil,DC=com\"", ""
  name = name.sub "\"CN=", ""
  name = name.sub "\\", ""

This only works for users in CN=Users, even assuming that
you adjust the domain name as appropriate. My solution
gets the CN from any user, whether in CN=Users or not,
without knowing the domain name.

Hint: many organizations put their users in OU’s… The
CN=Users container is really only there for migration
from NT4, so the domain root isn’t filled up with users
and computers from the migration.

It’s even legal to put users in a container (CN=) under
an OU, though it’s not advised (it’s allowed because
that’s what CN=Users is). The only correct solution is
to match the RDN component after the user’s CN=, up to
the start of the next RDN part, as I showed.

Clifford H…


#6

Peña wrote:

ps: Clifford, if by any chance you know how to query a msexchange:
I’d like to query all exchange mailboxes and for each mailbox,
list all the users who have rights to access it.
(since many of us share mailboxes).
Pardon the nubiness on windows/exchange…

On the contrary, this is not a nuby question.
I do know how to do it, it is not simple,
and there’s not a supported method AFAIK.

Apologies for the non-Ruby-ness of the following…

You need to enumerate the Access Control Entries for
the mailbox (and potentially the mbox’s ancestors)
and for each relevant ACE that pertains to a group,
establish the transitive closure of the group’s
membership. Do this separately across all ACEs for
both the allowed members and the denied members, then
subtract the denied set from the allowed set. Either
set may be a wild-card (like World, or Authenticated
Users), so you must handle that.

This is thousands of lines of code, and cannot be done
efficiently using ADSI (or ADO/ADSI) because the ADSI
ACE’s hide the SID, exposing only the SAM name of the
ACE, which is obtained by a remote directory lookup.
LDAP is the way to go. Even that’s not easy, since you
can’t get the ACL via LDAP unless you send a special
custom LDAP control with the query, saying you don’t
want the sACL when you fetch the ntSecurityDescriptor.

As you can tell, I’ve actually done this, but it was
for a former employer and I’m not at liberty to share
the code. It was close to being their prize jewel :-).

Clifford H…


#7

From: Clifford H. [mailto:removed_email_address@domain.invalid]

You need to enumerate the Access Control Entries for

the mailbox (and potentially the mbox’s ancestors)

and for each relevant ACE that pertains to a group,

establish the transitive closure of the group’s

membership. Do this separately across all ACEs for

both the allowed members and the denied members, then

subtract the denied set from the allowed set. Either

set may be a wild-card (like World, or Authenticated

Users), so you must handle that.

This is thousands of lines of code, and cannot be done

efficiently using ADSI (or ADO/ADSI) because the ADSI

ACE’s hide the SID, exposing only the SAM name of the

ACE, which is obtained by a remote directory lookup.

LDAP is the way to go. Even that’s not easy, since you

can’t get the ACL via LDAP unless you send a special

custom LDAP control with the query, saying you don’t

want the sACL when you fetch the ntSecurityDescriptor.

Clifford, this great info.
Many thanks again,
-botp