|
|
|||||||
I am trying to put together a script that tells me if a users has a particular group/privilege on their account. For example, I want to see which users have access to a specific group. If the user has access, I want the script to dump their name into a file telling me they have access to this group. My sticking point is I am not sure how to read active directory to pull a list of @userid to query against. I would like to be able to query all the accounts in AD. Any help would be greatly appreciate. Thanks Indigo |
||||||||
|
|
|||||||
You could get all usernames from AD like this. Code: $oDomain = GetObject("WinNT://@LDomain") $oDomain.filter = "User","" For Each $oUser In $oDomain $oUser.Name + ': ' + $oUser.FullName ? Next Instead of doing $oUser.Name + ': ' + $oUser.FullName ? you could use the UserGroups() UDF to get all groups that user is in and check if group X is one of them. If it is write the username name to a file. UDF Library » UserGroups() - returns all groups of a given user |
||||||||
|
|
|||||||
Right On, I agree. The first section of my code to pull out the users groups is the UserGroups() UDF.. I just needed a wrapper to fit around the UsersGroup UDF to feed it user names.. Thanks.. bud Indigo, |
||||||||
|
|
|||||||
Is there a way to pull acitive exchange email address from AD? Indigo, |
||||||||
|
|
|||||||
Yes.... Attribute name = "Mail" |
||||||||
|
|
|||||||
I have noticed an issue with the script i am writing... the first result of any query doesn't get processed.. Example: Group1 Group2 Group3 are assigned to XXX User. when i read the groups from AD with UserGroups UDF I don't see the first group it pulled from the list. I Would only see Group2 Group3 Does anyone have any ideas? Indigo, |
||||||||
|
|
|||||||
Are you looking at 1 - 3? If so you need to remember that Arrays are 0 based so your return would really be 0-2 |
||||||||
|
|
|||||||
The groups that are being looked at don't have numbers just values like Group1 = Eng. Group2 = Sales. Group3 = Quality. Except when i try to do a print statement of the first variable assigned a group IE Eng. it overlooks it and doesn't print it, but it will print 2 - 3. Hope I am clear enough.. not sure how to explain it. Indigo, |
||||||||
|
|
|||||||
Code: $groups = UserGroups(@domain,@userid) For Each $x in $groups ? $x Next Sleep 15 Function UserGroups($target,$user,OPTIONAL $datatype) ;UserGroups, returns the groups of a specified user ; ;Returns: ; An array containing all groups of the given user. the array data type ; is controlled by the flag ; ;Syntax: ; $groups = usergroups({Target},{Userid},[OPTIONAL datatype]) ; ; {Target}................the domain or local computer you want to preform the action on. ; for faster workstation access include the domain name "domain/computer" ; ; {Userid}................The userid you want to lookup ; ; [datatype]..............Optional flag for what type of data to return ; 0 = default, the groupname ; 1 = the ADSI group object ; 2 = the ADSI group's ADSPath ; ;Examples: ; ;this will return all groups of a given user in the the local domain ; $groups = UserGroups(@domain,@userid) ; ; ;this will give you all the ADSI groupobjects of the user jsmith in the kixtart domain ; $group = UserGroups("Kixtart","jsmith",2) DIM $group, $temp[2], $i $user = getobject("WinNT://$target/$user,user") if @error <> 0 and vartype($user) <> 9 exit(@error) endif for each $group in $user.groups select case $datatype = 0 ;return the group.name $temp[$i] = $group.name case $datatype = 1 ;return the groupobject $temp[$i] = $group case $datatype = 2 ;return the group.adspath $temp[$i] = $group.adspath case 1 exit(1) endselect if $i = ubound($temp) redim preserve $temp[$i+2] endif $i = $i+1 next if $i <> 0 redim preserve $temp[$i-1] $UserGroups = $temp else redim preserve $temp[$i] $usergroups = "" endif exit(0) endfunction |
||||||||
|
|
|||||||
The above code skips the group that is read first. I have run it, and it fail to print the first group on my access list. The way I am determining this is I look at the results, and then i view my access groups in active directory. Hope that explians it better. Indigo |
||||||||
|
|
|||||||
Change your script to this and see what your get. Code: $groups = UserGroups(@domain,@userid) $count = 0 For Each $x in $groups ? "Element "+$Count+" ="+$x $count = $count + 1 Next Sleep 15 |
||||||||
|
|
|||||||
Ok, I have been digging around, and it looks like the first read group is not the only group being ignored.. Almost like there is a selective pattern of non-read groups? Indigo, |
||||||||
|
|
|||||||
Could that be nested groups? For example does the user belong to group1 and group2 and group1 is a member of group3 so the user is only a memebr of group3 because he is in group1? |
||||||||
|
|
|||||||
Good Idea, I will check Indigo |
||||||||
|
|
|||||||
It doesn't look like the goup i want is a nested one. thanks for the tip though. Indigo, |
||||||||
|
|
|||||||
I just did some tests and it seems to only return the regular groups. Nested groups are not returned. One could use the ListNestedGroups() udf for this. Can you post the code you have so far? Can you also state (some of) the names of groups that are not shown? Do they contain any special characters? |
||||||||
|
|
|||||||
How would i use define someones user name in LDap form? Indigo, |
||||||||
|
|
|||||||
The names of the Groups don't contain any special chars. Its straightforward. Eng Sales There is however spaces Eng Depart Things of that nature. I think your on the right track about the nested. I mean I looked and didn't see any nesting, but I only checked a few. I would like to get the ListNestedGroups UDF working and see if it returns more accurate data. Indigo, |
||||||||
|
|
|||||||
Code: $Groups = ListNestedGroups(@userid) For each $grp in $Groups ? $grp Next Does this look right? |
||||||||
|
|
|||||||
Nope. You need the distinguished name for the ListNestedGroups UDF. The TranslateName UDF can get this for you. This works for me. Code: Break on ;Get the DN name from AD for the current user. $DN = TranslateName (3, "", 3, @LDomain + "\" + @userid, 1) ;Get all groups and add <nested> to nested groups (see options). $groups = ListNestedGroups("LDAP://" + $dn[0],1) ;Show each group. For Each $group in $groups ?$group Next ;sleep 5 seconds. Sleep 5 ; !!! THE CODE BLOW SHOULD NOT BE CHANGED !!! ; !!! THESE ARE UDF'S WORK FINE AS THEY ARE !!! ;FUNCTION TranslateName() ; ;AUTHOR Howard A. Bullock (hbullock@tycoelectronics.com) ; ;VERSION 2.0 ; ;ACTION Translates from one name type to another. Good for converting an NT4 name ; like domain\user into an LDAP distinguished name or the reverse. ; ;SYNTAX TranslateName ($InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType) ; ;PARAMETERS $InitType (Required) ; - Integer value ; 1 = ADS_NAME_INITTYPE_DOMAIN ; Initializes a NameTranslate object by setting the domain that the object will bind to. ; ; 2 = ADS_NAME_INITTYPE_SERVER ; Initializes a NameTranslate object by setting the server that the object will bind to. ; ; 3 = ADS_NAME_INITTYPE_GC ; Initializes a NameTranslate object by locating the global catalog to which the object ; will bind. ; ; $BindName (Required) ; - String value ; If an $InitType = 3 (ADS_NAME_INITTYPE_GC), then the $BindName = "". ; InitTypes 1 and 2 require a name of a domain or server to be input. ; Note: "" may default to the current server or domain. ; ; $LookupNameType (Required) ; - Integer value ; ; $LookupName (Required) ; - String value see below ; ; $ReturnNameType (Required) ; - Integer value see below ; ; Documentation of Name Types. Lookup the more info on http://MSDN.Microsoft.com ; Not all name types work. "1", "2", and "3" have been the most useful. ; ; 1 = ADS_NAME_TYPE_1779 ; Name format as specified in RFC 1779. For example, "CN=Jane Doe,CN=users, DC=Microsoft, DC=com". ; ; 2 = ADS_NAME_TYPE_CANONICAL ; Canonical name format. For example, "Microsoft.com/Users/Jane Doe". ; ; 3 = ADS_NAME_TYPE_NT4 ; Account name format used in Microsoft® Windows© NT® 4.0. For example, "Microsoft\JaneDoe". ; ; 4 = ADS_NAME_TYPE_DISPLAY ; Display name format. For example, "Jane Doe". ; ; 5 = ADS_NAME_TYPE_DOMAIN_SIMPLE ; Simple domain name format. For example, "JaneDoe@Microsoft.com". ; ; 6 = ADS_NAME_TYPE_ENTERPRISE_SIMPLE ; Simple enterprise name format. For example, "JaneDoe@Microsoft.com". ; ; 7 = ADS_NAME_TYPE_GUID ; Global Unique Identifier format. For example, {95ee9fff-3436-11d1-b2b0-d15ae3ac8436}. ; ; 8 = ADS_NAME_TYPE_UNKNOWN ; Unknown name type. The system will try to make the best guess. ; ; 9 = ADS_NAME_TYPE_USER_PRINCIPAL_NAME ; User principal name format. For example, "JaneDoe@Fabrikam.com". ; ; 10 = ADS_NAME_TYPE_CANONICAL_EX ; Extended canonical name format. For example, "Microsoft.com/Users Jane Doe". ; ; 11 = ADS_NAME_TYPE_SERVICE_PRINCIPAL_NAME ; Service principal name format. For example, "www/www.microsoft.com@microsoft.com" ; ; 12 = ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME ; A SID string, as defined in the Security Descriptor Definition Language (SDDL), for either ; the SID of the current object or one from the object's SID history. ; For example, "O:AOG:DAD:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)" For more information see ; Security Descriptor String Format under "Security" in the Microsoft Platform SDK documentation. ; ;REMARKS Not name types seem to work. ; ;RETURNS This function returns an ARRAY of three values: ; Name of the type specified by $ReturnNameType (String) ; Error number (Long Integer) ; Error text (String). ; ;DEPENDENCIES OS: Active Directory aware client ; ;EXAMPLES $DN = TranslateName (3, "", 3, "@Domain\@wksta$", 1) ; ? "DN = " + $DN[0] ; ? "Error = " + $DN[1] ; ? "ErrorText = " + $DN[2] ; ; $DN = TranslateName (3, "", 3, "@LDomain\@userid", 1) ; ? "DN = " + $DN[0] ; ? "Error = " + $DN[1] ; ? "ErrorText = " + $DN[2] ; ; Function TranslateName ($InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType) Dim $InitType, $BindName, $LookupNameType, $LookupName, $ReturnNameType Dim $NameTranslate, $ReturnName, $Error, $ErrorText $Error = 0 $ErrorText = "" $ReturnName = "" $NameTranslate = CreateObject ("NameTranslate") $Error = @error $ErrorText = @serror If $Error = 0 $NameTranslate.Init ($InitType, $BindName) $Error = @error $ErrorText = @serror If $Error = 0 $NameTranslate.Set ($LookupNameType, $LookupName) $Error = @error $ErrorText = @serror If $Error = 0 $ReturnName = $NameTranslate.Get($ReturnNameType) $Error = @error $ErrorText = @serror EndIf EndIf EndIf $TranslateName = $ReturnName, $Error, $ErrorText EndFunction ;Function ListNestedGroups() ; ;Authors NTDOC and Glenn Barnas ; (Glenn came up with new method to Golf down the original code) ; ;Action Retrieves a list of all the groups an account is a member of including ; nested groups which normally are not seen. This can be useful for locating ; security holes where users have rights they shouldn't have due to nested groups. ; ;NOTE: ; Based on The Scripting Guys code from here ; MS Scripting Guys ; ; Grabbing again from the MS Scripting Guys ; Due to the way the Groups method and Active Directory work, normal scripts can’t return ; all of Ken Myer’s group memberships unless it checks to see whether Groups A and B belong ; to any other groups. This script can now do that. ; ; The Scripting Guys code shows the nested groups but also allowed duplicates to be returned. ; This KiX UDF does not because the guys at Korg cared the most to bring you the best ; In the example you'll see Administrators twice, but strictly speaking they're not duplicates ; Running the Scripting Guys code returns 3 entries for Administrators ; ; The Source looks large only because we commented it and showed a good example of running it ; ;Syntax ListNestedGroups($_Account,Optional $_Nested) ; ;Version 1.0 ; ;Date 2006-Mar-23 ; ;Date Revised xxxx-xxx-xx ; ;Revised Reason ; ;Parameters ListNestedGroups($_Account,Optional $_Nested) ; $_Account = The full LDAP path to the account you want to check ; $_Nested = This is a two part flag to determine what nested groups to show ; 0 or blank = Show all groups including nested ; 1 = Show all groups but flag the nested groups with <Nested> tag ; 2 = Show only Nested groups ; ;Returns Array of the groups, or Error level on error ; ;Dependencies None, this is a two part UDF that uses a sub-function to operate ; ;KiXtart Ver Written and tested with KiXtart v4.52 beta 2 on 2000/XP/2003 against 2003-AD and 2000-AD ; ;Source Function ListNestedGroups($_Account,Optional $_Nested) Dim $_objUser, $_colGroups, $_objGroup, $_Grps, $_NFlag Dim $_W, $_Element, $_TempString, $_OD, $_CN, $_ERR ; init the vars $ListNestedGroups = 0 ; default return value if errors occur $_Nested = Val($_Nested) ; force to numeric value $_NFlag = IIf($_Nested = 1, ' <Nested>', '') ; set the output message for nested groups $_objUser = GetObject($_Account) ; instantiate the object $_ERR = Val('&' + Right(DecToHex(@ERROR), 4)) ; get last 4 nybbles (2 bytes) of the error code If $_ERR Exit $_ERR EndIf $_colGroups = $_objUser.Groups ; get the collection For Each $_objGroup in $_colGroups $_OD = GetNested($_objGroup) ; nested group name $_CN = $_objGroup.CN ; parent group name ; Write the nested group name (and optional NESTED tag) to the index file If $_OD <> '' If InStr($_TempString, $_OD) = 0 $_TempString = $_TempString + $_OD + $_NFlag + Chr(10) EndIf EndIf ; write the parent group name to the index file, unless in nested-only mode If $_Nested < 2 If InStr($_TempString, $_CN) = 0 $_TempString = $_TempString + $_CN + Chr(10) EndIf EndIf Next ; enumerate the index and put the value(s) into an array $_Grps = Split(Left($_TempString,Len($_TempString)-1), Chr(10)) ; Return the array of groups, and exit with success $ListNestedGroups = $_Grps Exit 0 EndFunction ; Sub-Function for returning nested groups Function GetNested($objGroup) Dim $_colMembers, $_strMember, $_strPath, $_objNestedGroup, $_ERR ; init the return value to a null string $GetNested = '' ; get the collection $_colMembers = $objGroup.GetEx("memberOf") ; enumerate the collection For Each $_strMember in $_colMembers $_strPath = "LDAP://" + $_strMember $_objNestedGroup = GetObject($_strPath) $GetNested = $_objNestedGroup.CN Next Exit 0 EndFunction |
||||||||
|
|
|||||||
Ok, Silver platter time. This is a complete working script for what you want/need to do. Do not forget to include the TranslateName() UDF an the ListNestedGroups() UDF. Code: Break on $rc = Open(1, "c:\useringroupx.txt", 5) $oDomain = GetObject("WinNT://@LDomain") $oDomain.filter = "User","" For Each $oUser In $oDomain ;Get the DN name from AD for the specific user. $dn = TranslateName (3, "", 3, @LDomain + "\" + $oUser.Name, 1) ;Get all groups and add <nested> to nested groups (see options). $groups = ListNestedGroups("LDAP://" + $dn[0],1) ;See if the user is in a group with GroupX in its name nested and not nested. For Each $group in $groups If InStr($group, "GroupX") $rc = WriteLine(1, $oUser.Name + " is a member of group: " + $group + "." + @CRLF) EndIf Next Next $rc = Close(1) UDF Library » ListNestedGroups() - Query AD for all groups of an account + nested UDF Library » TranslateName() - converts a name from one type to another |
||||||||
|
|
|||||||
I wanted to say thank you for all your help. I appreciate it alot.. Indigo, |
||||||||
|
|
|||||||
Oh, heheh The script is done, and it works great! |
||||||||
|
|
|||||||
I just looked at your script... thas much nicer than mine.. I am going to study it, and see how to create scripts like that. Thx bud, |