Thursday, July 28, 2011

Generate a CSV from your GPO's per OU

If you come into an environment like I have, you'll find that some companies prefer to break out their AD structure by location and then generate a OU structure that matches it. Physically, this is understandable and you can understand what's where. Logically, this causes issues because AD utilizes an inheritance model and this gets complicated and very messy very quickly if you do not follow a strict model. This model falls on its face when you have a centralized IT force. As an example, the company I worked for acquired numerous other companies and a each company/location had it's own IT workforce. Eventually, the company consolidated all of these external IT departments into one. The IT staff then standardized each site for GPO's. Which made having each one redundant.

This is a mockup of the OU structure:

And the GPO's applied:

If you look closely, you can see that some sites are missing some GPO's, some have an extra GPO, and some have the same. The goal I was given is that I need to consolidate the OU's with the same GPO's applied and then I can examine the disparate ones individually. In order to make a nice spreadsheet to do this I created this script (run on Windows, I added awk, sed, and grep to the \windows\system32 folder and installed group policy management).

Since the structure has a nice, predictable "end" OU (eg, Laptops, Desktops, Users) I could script for that keyword:

:Lets grab all the OU's
cscript "%programfiles%\gpmc\scripts\dumpsominfo.wsf" "Desktops" /showinheritedlinks > desktop-gpo-links.txt

:now we're going to parse out all the GPO's
:what this next line does is print the file to stdout, piping stdout to awk
:awk then grabs and prints out the text in the range "OU=Desktop" to "-- Who"
:this stdout is then piped to grep which retrieves the path from that selection of text
:grep then removes all other lines that contain path or two "--". From here,
:awk then removes the first column and prints out the rest of the GPO's. The last
:awk command then removes all duplicates.

type desktop-gpo-links.txt | awk "/OU=Desktop/,/-- Who/" | grep -v -E "Path" | grep -v -E "\-\-" | awk "{ for (i=2; i<=NF; i++) printf \"%%s \", $i; printf \"\n\"; }" | awk "! a[$0]++" | sed.exe "s/ $//g" > GPOs.txt

:Next we need to pull out all the OU's that this is applying against
type desktop-gpo-links.txt | grep -E "Path" > ou.txt

:now we prepare the header's...
ECHO Site > header.txt
type GPOs.txt | sed ":a;N;$!ba;s/\n/,/g" >> header.txt
sed -i ":a;N;$!ba;s/\n//g" header.txt
type header.txt > desktop-gpos.csv

:print the ou's into the desktop-gpos.csv
type ou.txt >> desktop-gpos.csv


for /f "tokens=*" %%A IN ('type "desktop-GPO-links.txt" ^| Grep.exe -E "Path"') DO (
for /f "tokens=*" %%a in ('type gpos.txt') DO (
awk "/%%A/,/-- Who/" "desktop-GPO-links.txt" | grep.exe -E "%%a$"
IF '!ERRORLEVEL!' EQU '0' sed.exe -i "/%%A/s|$|,x|g" desktop-gpos.csv
IF '!ERRORLEVEL!' EQU '1' sed.exe -i "/%%A/s|$|,|g" desktop-gpos.csv

:last we know need to exchange the ,OU and ,DC commas to something else because
:excel will automatically change them to new columns.
sed.exe -i "s/,OU/;OU/g" desktop-gpos.csv
sed.exe -i "s/,DC/;OU/g" desktop-gpos.csv

:and we remove the "Path " string just for nice-ness:
sed -i -r "s/Path.+Desktops/Desktops/g" desktop-gpos.csv

del sed* /q

This generates the following file:

Site ,Windows Update Policy - Workstations,Fabrikcom Workstation Policy,Local Administrator Account - Workstations,Fabrikcom Workstation Policy V2,Fabrikcom IE 7,Windows - Configure Kerberos to use TCP instead of UDP,Default Domain Policy,DisableAutoArchiveOutlook,Fabrikcom Internal Wireless,General Desktop Policy,[Unknown],PowerSchemeOptions,Fabrikcom IT User Policy,GPO_ORG_Outlook Cache Mode Settings
Desktops;OU=New Town;OU=BigCompanyA;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,

Which looks like this when you put it in Excel:

Nice and pretty and if you add conditional formatting on "x" you can easily identify which OU's are the same and can be consolidated, or just a nice report on which GPO's are affecting which OU's.

Monday, July 25, 2011

Offline files and the redirector failed

I have a client that's getting an error message occasionally that is causing her offline files to not appear on her laptop. The Event Viewer captures the data of the packet in event ID 3019 and it appears as such (change to WORD):

The error recorded in Event Viewer actually corresponds to:

I'm unsure why it's getting a status_connection_invalid error for a few minutes as the laptop is local to the network and there is a DC right there (and the file server is right there too).

Unfortunately, I have not been able to solve this yet. More investigation is needed, but it doesn't help that it's intermittent.

Wednesday, July 13, 2011

XP - Slow user login, constant prompts for accessing file shares

At work we were having an issue that seemed to happen a lot at remote sites. Either login times were glacially slow, users could not access file shares without being prompted over and over again for their credentials and numerous logs of:
Event Type: Warning
Event Source: LSASRV
Event Category: SPNEGO (Negotiator)
Event ID: 40960
Date: date
Time: time
User: N/A
Computer: Computername
Description: The Security System detected an authentication error for the server ldap/dca.acc.local. The failure code from authentication protocol Kerberos was "There are currently no logon servers available to service the logon request. (0xc000005e)".
For more information, see Help and Support Center at
Data: 0000: c000005e

Event Type: Warning
Event Source: LSASRV
Event Category: SPNEGO (Negotiator)
Event ID: 40961
Date: date
Time: time
User: N/A
Computer: Computername
Description: The Security System could not establish a secured connection with the server ldap/ No authentication protocol was available.
For more information, see Help and Support Center at
Data: 0000: c0000388

The fix to these issues is to switch Kerberos to UDP. After doing so the warnings disappeared and accessing file shares worked without constant reprompting. As well, logins for these remote users became much, much faster.

The change to set Kerberos to UDP is here:

Start Registry Editor.
Locate and then click the following registry subkey:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\ Kerberos\Parameters
Note If the Parameters key does not exist, create it now.
On the Edit menu, point to New, and then click DWORD Value.
Type MaxPacketSize, and then press ENTER.
Double-click MaxPacketSize, type 1 in the Value data box, click to select the Decimal option, and then click OK.
Quit Registry Editor.
Restart your computer.

Monday, July 11, 2011

Find all OU's and what GPO's are linked to them

I made a script using SED and ADFIND to find all OU's and what GPO's were linked to them:

adfind -b DC=ccs,DC=corp -f "(&(objectCategory=organizationalUnit)(gPLink=*))" cn gplink -csv -csvdelim : > gplinks.txt
adfind -b DC=ccs,DC=corp -f "(&(objectCategory=groupPolicyContainer)(cn=*))" cn displayName -nodn -csv > gpnames.txt
sed -i "s/\"//g" gpnames.txt
sed -i "s/\[LDAP:\/\/..=//g" gplinks.txt
sed -r -i "s/..=.olicies,..=.ystem,DC=ccs,DC=corp\\;.\]//g" gplinks.txt

for /f "tokens=1-2 delims=," %A IN ('type "gpnames.txt"') DO sed -i "s/%A/%B/g" "gplinks.txt"
del sed* /q

Love it :)

To expand on the above, here is a batch file that will find all empty OU's and what GPO's are linked to them:

:This script requires SED.txt and ADFIND.exe

:Goes through every OU and finds every GPO linked to it
adfind -b DC=ccs,DC=corp -f "(&(objectCategory=organizationalUnit)(gPLink=*))" cn gplink -csv -csvdelim : > gplinks.txt
:Goes through every GPO and finds it's common name
adfind -b DC=ccs,DC=corp -f "(&(objectCategory=groupPolicyContainer)(cn=*))" cn displayName -nodn -csv > gpnames.txt

:run some text clean up commands. Deletes double-quotes
sed -i "s/\"//g" gpnames.txt
:run some text clean up commands. Deletes [LDAP://
sed -i "s/\[LDAP:\/\/..=//g" gplinks.txt
:run some text clean up commands.
sed -r -i "s/..=.olicies,..=.ystem,DC=ccs,DC=corp\\;.\]//g" gplinks.txt
:repalces the LDAP GUID name in gplinks.txt with the actual name
for /f "tokens=1-2 delims=," %%A IN ('type "gpnames.txt"') DO sed -i "s/%%A/%%B/g" "gplinks.txt"
sed -i "s/\"//g" gplinks.txt

:Finds all empty OU's
@Echo Off
SETLOCAL EnableDelayedExpansion

IF EXIST EmptyOUs.txt DEL /F /Q EmptyOUs.txt
SET OUQry=DSQuery OU -Name * -Limit 0
FOR /F "delims=#" %%o IN ('%OUQry%') Do (
Echo Processing: %%o
DSQuery * %%o -Limit 0 | Find "CN=" >NUL
IF ERRORLEVEL 1 Echo %%o>>EmptyOUs.txt
Echo Search Complete! Check 'EmptyOUs.txt' file.
sed -i "s/\"//g" EmptyOUs.txt

:if gplinks OU is equal to an OU in EmptyOU then replace the OU with EMPTY:OU
for /f "tokens=1-10 delims=:" %%A IN ('type gplinks.txt') DO (
for /f "tokens=*" %%a IN ('type EmptyOUs.txt') DO (
if /I %%A equ %%a sed -i "s/%%A/EMPTY:%%A/g" gplinks.txt
del sed* /q

Friday, July 08, 2011

ADFind one-liner -> Find operating system of computer in AD

Nice :)

adfind -b "OU=Domain Controllers,DC=lab,DC=com" -f "&(objectcategory=computer)" operatingSystem -csv

Wednesday, July 06, 2011

Set home directories even if it's a hidden share

There exists an issue with DSMOD that prevents you from modifying the -hmdir with a share that has a dollar sign in it. According to the dsmod.exe example:

The special token $username$ (case insensitive) may be used to place the
SAM account name in the value of -webpg, -profile, -hmdir, and
-email parameter.
For example, if the target user DN is
CN=Jane Doe,CN=users,CN=microsoft,CN=com and the SAM account name
attribute is "janed," the -hmdir parameter can have the following

-hmdir \users\$username$\home

The value of the -hmdir parameter is modified to the following value:

- hmdir \users\janed\home

This does not work if your home directory is structured like so:

-hmdir \users$\$username$\home

The value returned by DSMOD is actually:

- hmdir \users$\$username$\home as opposed to the proper

To fix this you can use the awesome ADFIND and ADMOD from Joeware.

The command to fix set it correctly would be:
adfind -b "OU=TEST - Trentent,DC=lab,DC=com" -adcsv -f "(&objectClass=user)" samAccountName | admod homeDirectory::\\test\test$\{{samAccountName}} homeDrive::Z:

Go Joe!