Friday, November 18, 2011

Group Creation Script

The final script:
:This script will create the proper domain local group and global groups
:The only input this script needs is the UNC path to the folder. At the end
:of this script the only thing you'll need to do is add the users from the actual
:folder to the global group.
:
:eg create-groups.cmd "\\file01\HR\HR Support Group\HR Team\HR Support Services"

SET /P Permissions=What permissions will this group have ([F]ULL/[M]ODIFIY/[RO]READ ONLY)?

IF /I '%PERMISSIONS%' EQU 'F' SET PERMISSIONS=FULL
IF /I '%PERMISSIONS%' EQU 'M' SET PERMISSIONS=MODIFY
IF /I '%PERMISSIONS%' EQU 'RO' SET PERMISSIONS=RO





:ECHO %1 |sed "s/\\\\//g"|sed "s/\\/\./g" | sed "s/\"//g"

:We parse the command line for the UNC structure, now we need to find the last folder
for /F "tokens=*" %%A IN ('ECHO %1 ^|sed ^"s/\\\\//g^"^|sed ^"s/\\/\./g^" ^| sed ^"s/\^"//g^"') DO set groupname=%%A


set str=%groupname%
set N=0
setLocal EnableDELAYedExpansion

:loop
if !N! equ 55 (
goto :exceedcharacterquota
)

set /A N+=1

ECHO N=!N!
if "!str:~1!" neq "" (
set str=!str:~1!
goto :loop
)
goto :skip-string-modification

:if string length exceeds 55 chars, take the first 25 chars and the last 25 chars with an ellipse (...)
:in between.
:exceedcharacterquota
set string-part-one=!groupname:~0,25!
set string-part-two=!groupname:~-25!
set GROUPNAME=!string-part-one!...!string-part-two!


:skip-string-modification
setLocal disableDELAYedExpansion
:Remove any trailing spaces
for /F "tokens=*" %%A IN ('ECHO %GROUPNAME% ^|sed ^"s/ $//g^"') DO set groupname=%%A
ECHO GROUP=%GROUPNAME%

:Sets OU to domain local resource group...
SET OUL=OU=Resource,OU=Security Groups,OU=AD Project 3,DC=CCS,DC=CORP
dsadd group "CN=F.lg.%GROUPNAME%.%PERMISSIONS%,%OUL%" -desc %1 -secgrp yes -scope l

:Sets OU to Global group...
SET OUG=OU=Global,OU=Security Groups,OU=AD Project 3,DC=CCS,DC=CORP
dsadd group "CN=gg.%GROUPNAME%.%PERMISSIONS%,%OUG%" -desc %1 -secgrp yes -scope g

:adds the global group to the domain local group
dsmod group "CN=F.lg.%GROUPNAME%.%PERMISSIONS%,%OUL%" -addmbr "CN=gg.%GROUPNAME%.%PERMISSIONS%,%OUG%"

Count Characters in a Batch File

I have an issue where I need to ensure I don't exceed a certain number of characters in a script. Specifically, I cannot exceed 64 characters while making a group through script in AD. To do this I came up with the following:

ECHO OFF
:Set some variables, the string variable, a second string variable and our starting count.
set str=\\fileservertestserver\accounting\Budgets\Budgets 2012\2012 Budget GA Loads
set str2=%str%
set N=0
setLocal EnableDELAYedExpansion

:the loop works like so... we check to see if N has been incremented to 55 (our
:target number of characters). If it has, it goes to a new routine which creates
:our path. If it does not, we increment N by one then check to see if the string
:has reached a NULL character. If it has not reached "55" then goto loop and repeat.
:loop
if !N! equ 55 (
goto :exceedcharacterquota
)

set /A N+=1

ECHO N=!N!
if "!str:~1!" neq "" (
set str=!str:~1!
goto :loop
)

:if string length exceeds 55 chars, take the first 25 chars and the last 25 chars with an ellipse (...)
:in between.
:exceedcharacterquota
set string-part-one=!str2:~0,25!
set string-part-two=!str2:~-25!
echo !string-part-one!...!string-part-two!

Monday, November 07, 2011

Working around a VPN administrator issue...

We recently had a workstation that was sent to a user that didn't have the user in the local administrator group. This should be an easy fix, just add the user to that group. We could not though, as the user was a domain user and the computer was not on a network with a domain controller. I did have the local administrator account password and could login with it, but the VPN technology we use (Juniper's Network Connect) requires local administrator rights to install it (which I was able to do) but is setup to verify that the user account is a domain user account. Without the user account being from the domain and a local administrator account, Network Connect will not connect to our network.

Well, this is a bit of a pickle. Since this user was in Victoria BC and I was in Calgary AB, I needed to find a way to connect their computer to our domain network so they could authenticate against our DC and then I could add their account to the local admin group.

To do this I did the following:

1) Using the local administrator account on the remote computer, install TeamViewer and set it to launch on Windows Startup.
2) Setup unattended access through TeamViewer and install the VPN client on the remote computer and my local computer.
3) The network the remote computer was on was a 192.168.X.X and our network is a 10.X.X.X. So I set a persistent route on the remote computer to route all traffic to the 10/8 network to the VPN ip on *my* (the local) end "route add 10.0.0.0 mask 255.0.0.0 7.154.200.11 -p"
4) Add a DNS entry on both the Teamviewer and ethernet adapter of the remote computer to the DNS on one of the computers in the Domain (a 10.X.X.X address).
5) I downloaded and installed NAT32 onto the local computer. I configured it like so:
Teamviewer VPN Adapter - Private
Local Network Adapter - Internet
"Share the Windows IP Address"

Then NAT32 generated a screen like so:


From here, I connected to the user through Teamviewer's VPN and via Remote Control. I confirmed I could ping the DNS server on the domain from the remote computer. I rebooted the computer, phoned the user and found out when it was at the CTRL-ALT-DEL screen. Once it was at that stage, I connected to it, from TeamViewer's VPN, and then I could login to the domain. While under the users account, I started an elevated command-prompt and opened compmgmt.msc and added her domain account to the local admin account. I then had her log off, and via Teamviewer's remote control, logged back on via the local admin account. I then removed the persistent static route and logged back off and had the user log back in. From here, she had all the rights she needed to launch Network Connect and Network Connect saw that this computer is connected to the domain and allowed connection.

http://kb.juniper.net/InfoCenter/index?page=content&id=KB9084

Tuesday, October 25, 2011

Cool tool!

Mariano Sergio Cosentino created a script that will convert registry keys into ADMX template files. This is awesome as the alternative to deploying large number of registry keys and values is typically a startup script with regedit.exe /s %regfile%.

http://mscosentino-en.blogspot.com/2010/02/convert-registry-file-to-admx-policy.html

Tool is available here:
http://www.mscosentino.com/desarrollos/reg2admxl/reg_2_admx.vbs

Usage is: CSCRIPT REG_2_ADMXL.vbs registry-file language [name]

I used this tool to create a ADMX template of the following registry key:
KEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem

We use Microsoft fRX and it utilizes this key to determine your mail prefences if you're using exchange. If you have the old Office 2000/2003 (IIRC) you should have this key. 2007 and greater now use a different method of storing email account information (apparently). This content is generated by using the "Mail" control panel icon. We used this tool to prestage the server name and a "Windows Messaging Profile" so that when you try to email from fRX you don't go through a complicated wizard asking for things like "server name". If you're organization is like ours, your internal email server name is something users won't know and won't be able to guess (eg, 3-digit-company-abbr,3-digit-code-for-prod-or-dev,3-digit-code-for-virtual-or-physical,3-digit-code-for-server-role(eg EXC-exchange),3-digit-code-for-number).

Friday, October 14, 2011

LDAP query for *just* users

We have numerous "mailbox only" user accounts in our AD. I've been asked for a query of all the user accounts on our domain. The query needs to exclude these accounts and disabled accounts as we're only interested in active user accounts. This is what I came up with:

adfind -f "&(objectcategory=person)(samaccountname=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2)(!(msExchRecipientTypeDetails=4)(!(msExchRecipientDisplayType=7)(!(msExchRecipientDisplayType=8)(!(extensionattribute1=Service Account))))))" -csv -csvdelim ;

This query does the following:
Find all user accounts (objectcategory=person)(samaccountname=*)
But NOT
Disabled accounts (userAccountControl:1.2.840.113556.1.4.803:=2)
Exchange Shared Mailboxes: (msExchRecipientTypeDetails=4)
Exchange Rooms: (msExchRecipientDisplayType=7)
Exchange Equipment: (msExchRecipientDisplayType=8)
Service Accounts: (extensionattribute1=Service Account)

MS Software usually adds "SERVICE ACCOUNT" to the extensionattribute1.

Thursday, September 15, 2011

Change file shares via scripting

I've come across a problem where users are filling up their hard disks and we need to move the highest utilization users to a new disk. In order to accomplish this I've setup a robocopy to move their files to a new disk and have it constantly mirrored until after-hours; where we run this script to move the file shares:


:backup original shares:
reg export "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares" C:\shares-backup.reg /y

setlocal enabledelayedexpansion
:what we need to do is grab the user name and the key...
for /f "tokens=1-2*" %%A IN ('reg query "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares" ^| findstr /I /C:"E:\User Files\Corporate" ^| sed.exe "s/Path=E:\\User Files\\Corporate/Path=G:\\User Files\\Corporate/"') DO (
echo reg add HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares /v %%A /t %%B /D "%%C" /f
)

for /f "tokens=1-2*" %%A IN ('reg query "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares" ^| findstr /I /C:"E:\User Files\Finance" ^| sed.exe "s/Path=E:\\User Files\\Finance/Path=G:\\User Files\\Finance/"') DO (
echo reg add HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares /v %%A /t %%B /D "%%C" /f
)

net stop server /y
net start server


What this script does is:
1) Backs up the existing share structure
2) Queries the file shares for the specific path of the share we're going to move
3) Using SED.exe we change the drive letter from E: to G:
4) Using reg.exe we overwrite the registry key with the new value
5) we then stop and restart the server service to get the new shares working.

And we set that up as a scheduled task to run after-hours :)

Tuesday, September 13, 2011

Saving and restoring ACL's on OU's

Saving and moving OU ACLs

I’ve written a batch file that will move ACLs from one OU to another. It works by you outputting the results of a ACL from a OU to a text file, specifying the new OU in a batch file and inputting the text file you just created. I use three utilities to accomplish this: adfind.exe, sed.exe and dsacls.exe.
The command to save the text file is:

adfind -b "OU=Users,OU=LAB,DC=LAB,DC=CORP" -f (distinguishedName=OU=Users,OU=LAB,DC=LAB,DC=corp) -sddl++ -resolvesids -onlydacl ntsecuritydescriptor -sddlnotfilter ;inherited| sed.exe "s/;;/; ;/g" | sed.exe "s/;;/; ;/g" | sed.exe "s/;;/; ;/g" | sed.exe "s/;;/; ;/g" > %PATHTOFILE%.txt


From here, you need to delete the header in the text file and the footer.
Once that is done, run this script, changing the two variables at the top:


:RESTORE-OU-ACL.CMD
:Restore OU Properties
SET TARGETOU=OU=Users Accounts,OU=AD Project 3,DC=LAB,DC=CORP
SET TARGETFILE="New Text Document (5).txt"

@ECHO OFF

SETLOCAL ENABLEDELAYEDEXPANSION
for /F "tokens=1-6 delims=;" %%A IN ('type %TARGETFILE%') DO (
SET PROP=
SET INHERIT=0
IF "%%C" EQU " " SET PROP=GA
ECHO CALL :PROPERTYACL %%C
CALL :PROPERTYACL %%C

ECHO CALL :INHERITANCE %%B
CALL :INHERITANCE %%B

SET PROPERTY=
IF /I "%%D" NEQ " " SET PROPERTY=%%D
ECHO PROPERTY=!PROPERTY!
SET TARGET=
IF /I "%%E" NEQ " " SET TARGET=%%E
ECHO TARGET=!TARGET!
ECHO dsacls "%TARGETOU%" !INHERIT! /G "%%F:!PROP!;!PROPERTY!;!TARGET!"
dsacls "%TARGETOU%" !INHERIT! /G "%%F:!PROP!;!PROPERTY!;!TARGET!"

)
GOTO:EOF

:INHERITANCE
REM We need to figure out what ACLS we're dealing with...
FOR /F "tokens=*" %%Z IN ('ECHO %*') DO (
IF '!INHERIT!' EQU '/I:S' GOTO:EOF
ECHO %%Z | FINDSTR /I /C:"[CONT INHERIT]"
IF '!ERRORLEVEL!' EQU '0' SET INHERIT=/I:T
ECHO %%Z | FINDSTR /I /C:"[CONT INHERIT][INHERIT ONLY]"
IF '!ERRORLEVEL!' EQU '0' SET INHERIT=/I:S
ECHO %%Z | FINDSTR /I /C:"INHERIT"
IF '!ERRORLEVEL!' EQU '1' SET INHERIT=/I:P
ECHO INHERIT=!INHERIT!
)
GOTO:EOF

:PROPERTYACL
REM We need to figure out what ACLS we're dealing with...
FOR /F "tokens=*" %%Z IN ('ECHO %*') DO (
ECHO %%Z | FINDSTR /I /C:"WRT PROP"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!WP
ECHO %%Z | FINDSTR /I /C:"READ PROP"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!RP
ECHO %%Z | FINDSTR /I /C:"CTL"
IF '!ERRORLEVEL!' EQU '0' SET PROP=CA
ECHO %%Z | FINDSTR /I /C:"[CR CHILD]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!CC
ECHO %%Z | FINDSTR /I /C:"[DEL CHILD]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!DC
ECHO %%Z | FINDSTR /I /C:"[LIST CHILDREN]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!LC
ECHO %%Z | FINDSTR /I /C:"[LIST OBJECT]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!LO
ECHO %%Z | FINDSTR /I /C:"[READ]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!GR
ECHO %%Z | FINDSTR /I /C:"[FC]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!GA

ECHO PROP=!PROP!
)
GOTO:EOF

:/I:P = This Object Only *BLANK*
:/I:S = Child Objects Only [CONT INERIT][INHERIT ONLY]
:/I:T = This object and all child objects [CONT INERIT]
:Blank inheritance = /I:P
:When "Properties" are set, it should be /I:S
:When there are no properties listed at all ACL should be GA

Friday, August 26, 2011

Issue with WSH (Scripting.FileSystemObject 800A01AD)



I recently had a Windows 2008 Server that was unable to execute a VBS script that works with other servers and other combinations of desktops. I decided to break out Process Monitor and try and see if I can figure out what's going on...

To simplify this process, I found this vbs script that trys to utilize the Scripting.FileSystemObject in a script:

cscript Version.vbs

The VBScript program follows:
Option Explicit

Dim objFSO, strFolder

Call MsgBox("WSH Version: " & Wscript.Version _
& vbCrLF & "VBScript major version: " & ScriptEngineMajorVersion _
& vbCrLf & "VBScript minor version: " & ScriptEngineMinorVersion)

strFolder = "C:\Windows"

Set objFSO = CreateObject("Scripting.FileSystemObject")
If (objFSO.FolderExists(strFolder) = True) Then
Call MsgBox("Folder " & strFolder & " exists" _
& vbCrLf & "and the FileSystemObject works fine")
Else
Call MsgBox("Folder " & strFolder & " does NOT exists" _
& vbCrLf & "but the FileSystemObject works fine")
End If



I ran that script on the affected server and, after clicking OK on the WSH Version dialog, I got this message:



I broke out Process Monitor and monitored on the File System. It sounds like it should be a file system error so we'll scope that out first. I filtered for everything but wscript.exe (I executed all my command lines as wscript.exe test.vbs) and nothing appeared. So wscript.exe wasn't even getting to the file system. So I enabled registry filtering and filtered for wscript.exe:


And I reran the script and got this result:



From here I went to another Windows 2008 server and added the missing registry keys (NAME NOT FOUND) and repeated the process again, finding more keys until all were added to the non-functioning server.

I ended up adding the following registry keys:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Scripting.FileSystemObject]
@="FileSystem Object"

[HKEY_CLASSES_ROOT\Scripting.FileSystemObject\CLSID]
@="{0D43FE01-F093-11CF-8940-00A0C9054228}"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}]
@="FileSystem Object"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\InprocServer32]
@="C:\\Windows\\SysWOW64\\scrrun.dll"
"ThreadingModel"="Both"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\ProgID]
@="Scripting.FileSystemObject"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\TypeLib]
@="{420B2830-E718-11CF-893D-00A0C9054228}"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\Version]
@="1.0"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}]

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0]
@="Microsoft Scripting Runtime"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\0]

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\0\win32]
@="C:\\Windows\\SysWOW64\\scrrun.dll"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\0\win64]
@="C:\\Windows\\system32\\scrrun.dll"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\FLAGS]
@="0"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\HELPDIR]
@="C:\\Windows\\system32"


For some reason, it is launching the Wscript.exe in a 32bit process (as evidenced by WOW6432Node key). On the working 64bit server I have it is running as a 64bit process.

After entering those registry keys, here is my new result.


Success! Hopefully, if you encounter the same issue, you are not missing any more, or too many more, registry keys. I wonder why they disappeared, but I don't have a way to trace that unfortunately.

Wednesday, August 24, 2011

Awesome AD blog and post

I've only viewed a few AD posts on this blog but this is fantastic.

http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-part-2-protected-accounts-and-groups-in-active-directory.aspx

from Laura Robins that discusses minimizing privledges.

Tuesday, August 23, 2011

Watch the folder redirect log live

If you've enabled the folder redirect log, you can watch it on a remote computer using the tail command and SED.exe.

Currently, the fdeploy.log (for XP anyways) stores the log as a binary file with a NULL character between each character. To clean up this output you can pipe tail.exe into sed and tell sed to delete the NULL characters...



To:



The command to watch it is now:
tail -f \\gkwngq1\c$\WINDOWS\Debug\UserMode\fdeploy.log | sed "s/\x00//g"

Cool.

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


SETLOCAL ENABLEDELAYEDEXPANSION

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,,,
Desktops;OU=SanFrancisco;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyC;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=NewYork;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=GreekTown;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=Houston;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=Alexandria;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=GreekTown;OU=BigCompanyB;OU=fabrikcom;OU=com,x,,x,x,,x,x,x,x,x,x,,,
Desktops;OU=Okotoks;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Victoria;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Winnipeg;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Malahat;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=Toronto;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=Calgary;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=Vancouver;OU=BigCompanyC;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=SanJose;OU=BigCompanyC;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=Houston;OU=BigCompanyC;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=GoMax;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Richmond;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Kelowna;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Edmonton;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=BigCompanyB-Hamilton;OU=BigCompanyB;OU=fabrikcom;OU=com,x,x,x,x,,x,x,x,x,,x,,,
Desktops;OU=ITGroup;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:
C000023A STATUS_CONNECTION_INVALID

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 http://support.microsoft.com.
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/Computername.domain.com. No authentication protocol was available.
For more information, see Help and Support Center at http://support.microsoft.com.
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:
http://support.microsoft.com/kb/244474

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
pause
: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.
Echo Search Complete! Check 'EmptyOUs.txt' file.
Echo.
ENDLOCAL
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
substitution:

-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
\users$\janed\home

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!

Tuesday, June 28, 2011

AD Script to Link GPO's via the command line

I've modified a script I found online to allow standard batch file passthrough for linking a GPO to a OU.

Usage: cscript.exe linkGPO.vbs "Test GPO" "lab.com" "OU=AD Project,DC=lab,DC=com"









If WScript.Arguments.Count = 3 Then
strGPO = WScript.Arguments.Item(0)
strDomain = WScript.Arguments.Item(1)
strOU = WScript.Arguments.Item(2)
Else
Wscript.Echo "Usage: linkGPO.vbs ""GPO Name"" ""Domain name"" OUs"
Wscript.Echo "Usage: linkGPO.vbs ""Test GPO"" ""lab.com"" ""OU=AD Project,DC=lab,DC=com"""
Wscript.Quit
End If


' This code links a GPO to an OU
' ------ SCRIPT CONFIGURATION ------
'strGPO = "zCCS IE 7" ' e.g. "Sales GPO"
'strDomain = "lab.com" ' e.g. "rallencorp.com"
'strOU = "OU=Offices,OU=AD Project,DC=lab,DC=com" ' e.g. "ou=Sales,dc=rallencorp,dc=com"
intLinkPos = -1 ' set this to the position the GPO evaluated at
' a value of -1 signifies appending it to the end of the list
' ------ END CONFIGURATION ---------

set objGPM = CreateObject("GPMgmt.GPM")
set objGPMConstants = objGPM.GetConstants( )

' Initialize the Domain object
set objGPMDomain = objGPM.GetDomain(strDomain, "", objGPMConstants.UseAnyDC)

' Find the specified GPO
set objGPMSearchCriteria = objGPM.CreateSearchCriteria
objGPMSearchCriteria.Add objGPMConstants.SearchPropertyGPODisplayName, _
objGPMConstants.SearchOpEquals, cstr(strGPO)
set objGPOList = objGPMDomain.SearchGPOs(objGPMSearchCriteria)
if objGPOList.Count = 0 then
WScript.Echo "Did not find GPO: " & strGPO
WScript.Echo "Exiting."
WScript.Quit
elseif objGPOList.Count > 1 then
WScript.Echo "Found more than one matching GPO. Count: " & _
objGPOList.Count
WScript.Echo "Exiting."
WScript.Quit
else
WScript.Echo "Found GPO: " & objGPOList.Item(1).DisplayName
end if

' Find the specified OU
set objSOM = objGPMDomain.GetSOM(strOU)
if IsNull(objSOM) then
WScript.Echo "Did not find OU: " & strOU
WScript.Echo "Exiting."
WScript.Quit
else
WScript.Echo "Found OU: " & objSOM.Name
end if

on error resume next

set objGPMLink = objSOM.CreateGPOLink( intLinkPos, objGPOList.Item(1) )

if Err.Number <> 0 then
WScript.Echo "There was an error creating the GPO link."
WScript.Echo "Error: " & Err.Description
else
WScript.Echo "Sucessfully linked GPO to OU"
end if

Excel Find Text Formula

=IF(ISNUMBER(FIND("My Documents Folder Redirect",A1)),"Yes","No")

This excel formula searches that the formula (A1) "contains" the text "My Documents Folder Redirect". If it does, it puts Yes in the field it's run in. If not, No.

Tuesday, May 03, 2011

invalid pxe server list format - Altiris


I restarted our Altiris server and our PXE services wouldn't come up. Trying to start them resulted in:
File not found

I then checked the path listed in the service and found that, indeed, our PXE files where not in the location that the service was trying to start them in:
F:\Program Files\Altiris\eXpress\Deployment Server\PXE

The missing files were:
PXEService.exe
PXEmtftp.exe
PXEMgr.exe
PXECfgService.exe

They were located here:
F:\Program Files\Altiris\eXpress\Deployment Server\PXE\MasterImages\UpSrv\51

I don't know why it wasn't looking for them in the longer path, but I copied those files to the directory it wanted (\PXE)

I then attempted to start the services and they all started correctly.

Then I attempted to PXE boot one of my VM's. This failed with an error stating:
"invalid pxe server list format"

Attempting to troubleshoot this, I used procmon and saw that it was downloading bstrap.0 successfully then generating the error. I enabled logging for the PXE Server in Altiris and set the logging level for "Errors". I then restarted all the Altiris services. When I restarted the PXE Server service, I got this error message:
E [11:32:26 05/03] (3480): Enter: SetupDHCP(...)
E [11:32:26 05/03] (3480): SetupDHCP: Auto Detect, configure option 60.
(3480)Failed to load Dll Library.
(3480)Failed to load Dll Library.
(3480)Failed to load Dll Library.
(3480)Failed to load Dll Library.

I then fired up Process Monitor and did a file trace while restarting PXE Server. It informed me it could not find the following files:

I then copied those missing DLL's from the F:\Program Files\Altiris\eXpress\Deployment Server\PXE\MasterImages\UpSrv\51 directory to the F:\Program Files\Altiris\eXpress\Deployment Server\PXE directory and restarted the PXE Server Service.

I then attempted to PXE boot my VM and lo and behold, it worked again.

Friday, April 29, 2011

Configure Local Group Policy via the command line

Apply a security policy using an .inf file

[Unicode]Unicode=yes
[Version]signature="$CHICAGO$"
Revision=1
[Profile Description]
Description=profile description
[System Access]
MinimumPasswordAge = 10
MaximumPasswordAge = 30
MinimumPasswordLength = 6
RequireLogonToChangePassword = 0
NewAdministratorName = "NewAdminAccountName"
NewGuestName = "NewGuestAccountName"

Simple to apply from a cmd line

secedit /configure /db %windir%\security\database\localdb.sdb /cfg %systemdrive%\install\local\policy\policyname.inf /verbose

Tuesday, April 19, 2011

Maya and rendering priorities

I have a small farm of computers at home that I want to use as a render farm. Some of them are used by my family though and starting Maya renderings on them greatly diminishes their usability during that time. What needs to be done is force the priority lower on the rendering app (mayabatch.exe). 3D Studio Max has a script called "serverpriority.ms" that does this and it's essentially one line that, upon startup, sets the priority to low. I've been unable to find one like that for Maya but have found an acceptable workaround.

If you start the Backburner server.exe app as low priority all threads that the apps server.exe starts (like cmdjob and mayabatch.exe) will start in the same priority. Start the server.exe as low and your rendering threads will be low. To start server.exe in a low priority mode via command-line it looks like this:

START "" /LOW "\path\to\server.exe"

Done!