Zoho Banner September 2011

Archive for the ‘Windows Server 2008 R2’ Category

 

Recently, I have been working in an Windows Server 2008 R2 AD environment that has a number of RODCs in branch offices.   The environment uses DFSR (i.e. not FRS) for SYSVOL replication an I wondered whether I could simply remove the connection objects named “RODC Connection (FRS)”.  To me, the use of “FRS” in the name indicated that it was a probably a legacy object.  Rather than going ahead with the removal, I thought I would first check on-line and with some fellow MVPs as well as Microsoft employees.  Here’s what I found….

The FRS connection objects are not required by DFS Replication” in the RODC Frequently Asked Questions article on Technet (note: this has since been reworded).

http://technet.microsoft.com/en-us/library/cc754956(v=WS.10).aspx

I also found this statement in the Directory Services Team Blog…

Despite the mention only of FRS in this article, the 0×40 value is required for both DFSR and FRS

http://blogs.technet.com/b/askds/archive/2010/10/08/friday-mail-sack-cluedo-edition.aspx#rodc

The two statements are contradictory and it was only after helpful clarification from Microsoft’s Kurt Hudson that it transpires the connection object is required for SYSVOL replication using either method (i.e. FRS or DFSR).  In other words if you are using DRSR for SYSVOL don’t delete these connection objects or you will need to manually recreate them (being sure to set the 0×40 bit in the options attribute as described in the DS team blog article).

I fired up an RODC on Windows Server 2010 Release Candidate yesterday and was pleased to see the connection object has been renamed to avoid confusion.

Windows Server 2008 R2

RODC_Connections_2008R2

Windows Server 2012 Release Candidate

RODC_Connection_Objects

Well done Kurt!  It’s great to see this sort of thing getting resolved.

 

I’ve been working with the Windows Server 2008 R2 Active Directory cmdlets quite a bit recently.  If you’ve come from a background of using ADFIND, the cmdlets take a bit of getting used, but for me it’s definitely been worth the time spent.  One thing that frustrates me a little is that the names used by the cmdlets for AD attributes tend to vary greatly.  Not only is there inconsistency between cmdlets that stem from different modules and snap-ins, but also between the cmdlets and the traditional UI tools.  The table below shows some examples:

 

AD Users and Computers

ldapDisplayName

AD cmdlet property name

Exchange 2010 cmdlet property name

Telephone Number

telephoneNumber

OfficePhone

Phone

E-mail

mail

EmailAddress

WindowsEmailAddress

P.O. Box

postofficeBox

POBox

PostOfficeBox

 

I guess the Microsoft Product Groups try to protect the long-suffering customer from the obscurity of some of the attribute LDAP display names by giving them friendly names.  This approach would work well if there were universal consistency, but it not it just becomes confusing.  My preference is always to use the ldapDisplayName values whenever possible – and certainly always with the AD cmdlets, e.g.

Get-ADUser –LDAPFilter “(samaccountname=bobm)”

If in doubt however, refer to the object model:

get-help about_ActiveDirectory_ObjectModel

Tony

The objectGUID attribute is a little tricky to work with, especially if you want to use it as part of an LDAP filter.  This is because the value in stored within the directory as an octet string – essentially an array of one-byte characters.  This syntax is not especially user-friendly, which is why it is typically displayed (by tools such as LDP.EXE and the AD Powershell cmdlets) in a registry string format, e.g. “af97d4c7-5f17-4ce2-9245-687d410b4b20″Another way of displaying the value is using a hex string format, e.g. “C7D497AF175FE24C9245687D410B4B20″.  If you’re into migrations using Quest Migration Manager for AD, the hex string representation is used for the matching attribute value (using either extenstionAttribute15 or adminDisplayName).  As you can see, the two representations are similar, but have a slightly different ordering of the bytes.

You’d think that you would be able to use one of these two string representations of the objectGUID as part of an LDAP search filter, wouldn’t you?  Well, no, that would be too helpful.  Instead, you need a slightly modified version of the hex string, i.e. “\C7\D4\97\AF\17\5F\E2\4C\92\45\68\7D\41\0B\4B\20″.   The search filter syntax would look like this “(objectGUID=\C7\D4\97\AF\17\5F\E2\4C\92\45\68\7D\41\0B\4B\20)”

The script below accepts either of the two string formats as input and prompts you for the naming context in which to search for the object represented by the objectGUID attribute.

#########################################################
#
# Name: Get-ADObjectFromGUID.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 24/08/2010
# Comment: PowerShell script to search for an AD object
# using 'objectGUID' as the LDAP search filter
#
#########################################################

# Import the AD module
ipmo ActiveDirectory

# Get the objectGUID value
$Input1 = @'
    Please enter the objectGUID value in one
    of the two following formats:

    Registry string format, e.g.
        bb67681f-0ac1-471a-bf3d-f7f4c4cb1290
    or
    Hex string format, e.g.
        455E54E9D58B0F4B8F389E4982791D40

'@

$strGUID = Read-Host $Input1

# Present Menu
[string] $menu = @'
    Choose the AD partition to search within
    1. Current Domain
    2. Configuration
    3. Schema
    4. Other

'@

$a = Read-Host $menu
switch ($a)
{
    1 { $SearchBase = (Get-ADRootDSE).defaultNamingContext }
    2 { $SearchBase = (Get-ADRootDSE).configurationNamingContext }
    3 { $SearchBase = (Get-ADRootDSE).schemaNamingContext }
    4 { $SearchBase = Read-Host "Enter the search base: " }

}

if ($strGUID.length -eq 36)
{
    # We have a string in registry format and need to convert it to Hex string
    $strHex = -join (([guid]$strGUID).tobytearray() | %{$_.tostring("X").padleft(2,"0")})
}
elseif ($strGUID.length -eq 32)
{
    # We have a string in Hex format - no need to modify
    $strHex = $strGUID
}
else
{
    # Unrecognised string format
    Write-host "Unrecognised string format - remove any leading or trailing spaces and try again"
    Break
}

# We need to modify the Hex string to allow it to be used as a filter
$strSearch = $strHex -replace '(..)','\$1'

# Go ahead and search for the object
Get-ADObject -LDAPFilter "(objectGUID=$strSearch)" -SearchBase $SearchBase -Properties * | fl

# End

You can download the script here: get-adobjectfromguid.zip

As promised, here are the Powershell data files from my Teched NZ 2011 demos.  I’ve also included the FSMO role mover script.

te_2011.zip

Let me know if you have any questions. Enjoy!

When preparing for a migration of AD objects from one forest to another it is useful to know if any of the names are going to conflict.  There are, as you probably know, a number of different naming attributes in AD, but the one most likely to cause problems in the event of a conflict is sAMAccountName.  This is because sAMAccountName is used for domain logon (assuming UPN is not used).  If you know which names conflict between source and target you can plan changes before you get into the migration itself.

I’ve written a couple of small scripts to detect sAMAccountName conflicts.  I’ve used two scripts instead of one as there is not always trust connectivity between the two forests.  The first script (SourceUsersToCSV) is run in the source domain and basically just dumps all the user sAMaccountName attribute values to a file.  The second script (DupeCheckFromCSV) is run in the target domains and reads the exported file information line-by-line and checks to see if there are any conflicts in the target domain.  If a conflict is found the sAMAccountName is written to a file.

Enjoy!

#########################################################
#
# Name: SourceUsersToCSV.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 14/07/2011
# Comment: PowerShell script to export AD user info
# to CSV to support search for duplicate users
#
#
#########################################################

### --- Varible Definitions ---

$DOMAIN = "source.com"
$EXPFILE = "C:\util\CSV\domain_export.csv"
$sourceOU = "OU=MyUsers,DC=source,DC=com"
$filter = "(&(objectClass=user)(!iscriticalsystemobject=TRUE))"

### --- Main ---

# Export Source AD User info to file

if(@(get-module `
| where-object {$_.Name -eq "ActiveDirectory"} ).count -eq 0) {import-module ActiveDirectory}

$objSourceDC = Get-ADDomainController -Discover -DomainName $DOMAIN
$sourceDC = [string]$objSourceDC.HostName
$UserInfo = '' | Select 'UsrsAMAccountName'
$AllUsers = @()
$MyUsers = Get-ADUser -LDAPFilter $filter -Server $sourceDC -SearchBase $sourceOU
foreach($User in $MyUsers) {
    $UserInfo.'UsrsAMAccountName' = $User.sAMAccountname
    $AllUsers += $UserInfo | Select 'UsrsAMAccountName'
}
$AllUsers | Export-Csv $EXPFILE -NoTypeInformation
#########################################################
#
# Name: DupeCheckfromCSV.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 14/07/2011
# Comment: PowerShell script to import AD User info
# from CSV to check for duplicates
#
#########################################################

### Set Global variables

$domain = "target.com"
$impfile = "C:\util\CSV\Domain_Export.csv"
$EXPFILE = "C:\util\CSV\Duplicate_Users.csv"
$dc = Get-ADDomainController -Discover -DomainName $domain
$targetdc = [string]$dc.HostName
$arrSrcSAMs=@()
$arrTarSAMs = @()
$arrDupeUsers = @()

### Load the CSV file and extract the source domain unique User names

$colsrcUsers = import-csv $impfile #| select UsrSAMAccountName

foreach ($srcUser in $colsrcUsers)
	{
		$srcSAM = $srcUser.UsrSAMAccountName
		$arrsrcSAMs += $srcSAM
	}    

# Check for empty file
if ($colsrcUsers.Count -eq 0)
    {
        write-host "No Users found in CSV import file!"
        break
    }

### Enumerate Users in the local (target) domain 

$coltarUsers = Get-ADUser -Filter '*' -Server $targetDC -Properties samaccountname

foreach ($tarUser in $coltarUsers)
	{
		$tarSAM = [string]$tarUser.samaccountname
		$arrTarSAMs += $tarSAM
	}    

### Find Users to Add or Modify

foreach ($tarUser in $arrTarSAMs)
	{
		if ($arrSrcSAMs -contains $tarUser)
		{
			write-host "Duplicate User found for " $tarUser
			$arrDupeUsers += $tarUser
		}
		else
		{
			write-host "No Duplicate found for " $tarUser
		}
	}

### Add new Users to target and apply the membership

$arrDupeUsers | out-file $EXPFILE

Something I often recommend to my customers is keep the membership of the Enterprise Admins and Schema Admins groups empty and only populate them (temporarily) when required.  The privileges assigned to these groups are obviously high and removing the members reduces the potential for costly mistakes and/or compromise. 

Here’s a quick Powershell snippet that will perform the removal:

$grps = "Enterprise Admins", "Schema Admins" 
foreach ($grp in $grps) { 
Get-ADGroupMember -Identity $grp ` 
| %{Remove-ADGroupMember -Identity $grp -Members $_ -Confirm:$false} 
}

This is something that you could consider running as a scheduled task to ensure the memberships are kept clear.

Many organisations choose to rename the Built-in Administrator account for the domain for security reasons.  Whether or not renaming the account provides any real protection is the matter of some debate.  What is clear is that any hacker worth his or her salt is not going to be fooled by the rename, because the account has a well known security identifer:

SID: S-1-5-21domain-500

I was working on something the other day and needed to find the Built-in Administrator account using Powershell.  It wasn’t quite as straightforward as I thought it would be.  Anyway, here’s what I came up with:

$BA = (Get-ADDomain).domainsid 
$BA = $BA.ToString() + "-500" 
Get-ADUser -Identity $BA

As you can see it basically involves grabbing the domain SID, adding on the well-known identifier “-500″ and then searching for the account based on the concatenanted string. 

I can’t help thinking there must be an easier method, so if you have one please post a comment here.

Here’s a little WMI script I threw together the other day to help someone out.  The requirement was to set the display name (label) of a network adapter based on its hardware location.

Let’s say we have a NIC with the display name “Local Area Connection” and you want to change it to “MyNIC”, but only if it has a specific hardware location (e.g. PCI bus 3, device 0, function 0).  Of course, you can do this manually by nipping into the network connection properties (ncpa.cpl), but what if you have tens or hundreds of servers that you want to do this for?

nic_details_before.jpg

nic_configure.jpg

######################################################### 
# 
# Name: SetNetConnectionID.ps1 
# Author: Tony Murray 
# Version: 1.0 
# Date: 20/04/2011 
# Comment: PowerShell script to 
# change device display name for network adapter based 
# on hardware location 
# 
######################################################### 
$newname = "MyNIC" 
$location = "PCI bus 3, device 0, function 0" 
$drvinfo = (Get-WMIObject Win32_PnPSignedDriver `
| ?{$_.Location -eq $location}).DeviceID 
$nic = Get-WMIObject Win32_NetworkAdapter `
| ?{$_.PNPDeviceID -eq $drvinfo} 
$oldname = $nic.NetConnectionID 
write-host "Network Adapter name before change: " $oldname 
$nic.NetConnectionID = $newname 
$nic.Put()

After running the script, you should see that the display name has changed.

nic_details_after.jpg

My script only changes the NIC display name for the computer on which it is running, but you could easily change this to run against multiple machines.

I’ve been running dual boot Windows 7 and Windows Server 2008 R2 on my laptop for a little while now.  I use Windows 2008 R2 for running Hyper-V guests for testing and demo purposes.  For some time I’d been running Microsoft Security Essentials on the Windows 7 partition, but without any Anti-Malware software on the 2008 R2 partition – something that made me a little uncomfortable.  Recently, I found Comodo Antivirus.  It’s free and seems to run quite happily on my Windows Server 2008 R2 partition. 

Be aware that it does throw up the occasional advertisement bubble from its location in the notification area of the Windows task bar. This doesn’t really bother me – it seems a small price to pay for peace of mind.

Tony

 

I came across a problem the other day when using version 6.5.8211.0 of Microsoft Exchange MAPI and CDO 1.2.1 on a server running Good Mobile Messaging.  The Good software accesses user mailboxes via the MAPI CDO client.  At first the mailbox access was failing horribly with the following errors:

2011-03-11 13:24:33 12:00  ERROR:-2147219707
2011-03-11 13:24:33 12:00  MSG:Code:IDispatch error #1285 Source:Collaboration Data Objects Description:The attempt to log on to the Microsoft Exchange Server computer has failed. [Microsoft Exchange Server Information Store - [MAPI_E_FAILONEPROVIDER(8004011D)]]

The MAPI_E_FAILONEPROVIDER error appears to be fairly generic and I couldn’t find anything on the Microsoft Knowledge Base that matched my scenario.

In the end the problem turned out to be a by-product of my Exchange 2010 SP1 environment not having any Public Folders.  Apparently the MAPI CDO client will by default look for Public Folders when accessing the mailbox and will throw the error if it can’t find any. 

The fix is to add a registry key to the server running MAPI CDO that sets a flag (CONNECT_IGNORE_NO_PF) that instructs the client to ignore the absence of Public Folders.

  1. On the computer running Microsoft Exchange MAPI and CDO 1.2.1, click Start > Run.
  2. In the Open field, type regedit.
  3. Click OK.
  4. Perform one of the following actions:
    • If you are running a 32-bit version of Windows, navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Messaging Subsystem\CDO.
    • If you are running a 64-bit version of Windows, navigate to HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Messaging Subsystem.

  5. If the CDO registry key does not exist, create a registry key that you name CDO.
  6. In the CDO registry key, if the DWORD value does not exist, create a DWORD value that you name Ignore No PF.
  7. Change the DWORD value to 1.
  8. Click OK.

Source: Technet

Interestingly, the only references I could find to the “Ignore No PF” key were some MSDN and Technet blogs and the support documentation for Blackberry Enterprise Server.  There is currently nothing available in the Microsoft on-line documentation, including the Knowledge Base (at least nothing I could find). Given that Public Folders are being “de-emphasised” within Exchange I would have thought this workaround would be given much more prominence.

Tony