joeware - never stop exploring... :)

Information about joeware mixed with wild and crazy opinions...

11/23/2010

From the mailbag: Unique Values on AD Attributes and Locking down an attribute and why defaultSecurityDescriptor may not help you…

by @ 8:05 pm. Filed under tech

This one isn’t from my personal inbox but from a thread on ActiveDir Org a little while ago. I wanted to post it to the blog as well because I actually think I get a little wider audience here and this blog seems to be popular with the search engines and this is good info to share with folks because they truly are pretty common questions.

The original post:

Hi,

We have the UNIX attibs added in your AD with uidNumber and gidNumber etc. One part of our file storage uses UNIX rights (with gidNumber). The goal is to transfer the group definitions from the file storage into the AD, but I have a concern.

We delegate rights to create groups on various places (every department have their own OU where they can create groups and other objects). If we have a group with a certain gidNumber centrally, what stops a creative admin to create another group (with a different name), but with the same gidNumber and then access the UNIX share?

I can think of two solutions on this problem:

1. Is it possible to modify the attribute to only allow unique values?

2. Is it possible to add ACL:s to the attribute (in the schema) so only a service account have write access?

Thank you

 

Here is my response to the post…

 

1. No. The OS does not have that functionality available to enable/disable for attributes, would be nice though. 😉 The MSFT answer here is that all of your provisioning should be handled through a provisioning tool such as FIM which allows you to configure business rules such as this.

2. No. If you give someone the ability to create groups, it is entirely up to them what the ACL will be on that object when they create it or even after they create it if you allow default creator/owner functionality. The defaultSecurityDescriptor in the Schema is *only* used when a security descriptor is not specified in the object create. Granted this is the default most of the time, but if someone is looking to side step you, it is less than trivial to do so if you have granted CREATE rights.

For an example of #2…

This  first request creates a group using the default security descriptor (because I didn’t specify one)

C:\>admod -default -rb cn=group1,ou=defaultsdtest -add objectclass::group

AdMod V01.12.00cpp Joe Richards (joe@joeware.net) February 2010

DN Count: 1
Using server: TEST-DC1.test.loc:389
Directory: Windows Server 2003
Base DN: cn=group1,ou=defaultsdtest,DC=test,DC=loc

Adding specified objects…
   DN: cn=group1,ou=defaultsdtest,DC=test,DC=loc…

The command completed successfully

 

This second request creates a group using the security descriptor I want

 

C:\>admod -default -rb cn=group2,ou=defaultsdtest -add objectclass::group SD##ntsecuritydescriptor::D:P(A;;GA;;;WD)

AdMod V01.12.00cpp Joe Richards (joe@joeware.net) February 2010

DN Count: 1

Using server: TEST-DC1.test.loc:389

Directory: Windows Server 2003

Base DN: cn=group2,ou=defaultsdtest,DC=test,DC=loc

Adding specified objects…

   DN: cn=group2,ou=defaultsdtest,DC=test,DC=loc…

The command completed successfully

 

And here is what AD has for the ACL for group1

 

C:\>dsacls cn=group1,ou=defaultsdtest,DC=test,DC=loc

Access list:

Effective Permissions on this object are:

Allow TEST\Domain Admins                          FULL CONTROL

Allow BUILTIN\Account Operators                   FULL CONTROL

Allow NT AUTHORITY\SELF                           SPECIAL ACCESS

                                                  READ PERMISSONS

                                                  LIST CONTENTS

                                                  READ PROPERTY

                                                  LIST OBJECT

Allow NT AUTHORITY\Authenticated Users            SPECIAL ACCESS

                                                  READ PERMISSONS

                                                  LIST CONTENTS

                                                  READ PROPERTY

                                                  LIST OBJECT

Allow NT AUTHORITY\SYSTEM                         FULL CONTROL

Allow BUILTIN\Pre-Windows 2000 Compatible Access  SPECIAL ACCESS   <Inherited from parent>

                                                  READ PERMISSONS

                                                  LIST CONTENTS

                                                  READ PROPERTY

                                                  LIST OBJECT

Allow TEST\Enterprise Admins                      FULL CONTROL   <Inherited from parent>

Allow BUILTIN\Pre-Windows 2000 Compatible Access  SPECIAL ACCESS   <Inherited from parent>

                                                  LIST CONTENTS

Allow BUILTIN\Administrators                      SPECIAL ACCESS   <Inherited from parent>

                                                  DELETE

                                                  READ PERMISSONS

                                                  WRITE PERMISSIONS

                                                  CHANGE OWNERSHIP

                                                  CREATE CHILD

                                                  LIST CONTENTS

                                                  WRITE SELF

                                                  WRITE PROPERTY

                                                 READ PROPERTY

                                                  LIST OBJECT

                                                  CONTROL ACCESS

Allow BUILTIN\Windows Authorization Access Group  SPECIAL ACCESS for tokenGroupsGlobalAndUniversal

                                                  READ PROPERTY

Allow NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS  SPECIAL ACCESS for tokenGroups   <Inherited from parent>

                                                  READ PROPERTY

Allow NT AUTHORITY\Authenticated Users            Send To

Permissions inherited to subobjects are:

Inherited to all subobjects

Allow TEST\Enterprise Admins                      FULL CONTROL   <Inherited from parent>

Allow BUILTIN\Pre-Windows 2000 Compatible Access  SPECIAL ACCESS   <Inherited from parent>

                                                  LIST CONTENTS

Allow BUILTIN\Administrators                      SPECIAL ACCESS   <Inherited from parent>

                                                  DELETE

                                                  READ PERMISSONS

                                                  WRITE PERMISSIONS

                                                  CHANGE OWNERSHIP

                                                  CREATE CHILD

                                                  LIST CONTENTS

                                                  WRITE SELF

                                                  WRITE PROPERTY

                                                  READ PROPERTY

                                                  LIST OBJECT

                                                  CONTROL ACCESS

Inherited to user

Allow BUILTIN\Pre-Windows 2000 Compatible Access  SPECIAL ACCESS   <Inherited from parent>

                                                  READ PERMISSONS

                                                  LIST CONTENTS

                                                  READ PROPERTY

                                                  LIST OBJECT

Inherited to inetOrgPerson

Allow BUILTIN\Pre-Windows 2000 Compatible Access  SPECIAL ACCESS   <Inherited from parent>

                                                  READ PERMISSONS

                                                  LIST CONTENTS

                                                  READ PROPERTY

                                                  LIST OBJECT

Inherited to user

Allow NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS  SPECIAL ACCESS for tokenGroups   <Inherited from parent>

                                                  READ PROPERTY

Inherited to computer

Allow NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS  SPECIAL ACCESS for tokenGroups   <Inherited from parent>

                                                  READ PROPERTY

The command completed successfully

 

And here is the ACL that AD has for group2.

 

C:\>dsacls cn=group2,ou=defaultsdtest,DC=test,DC=loc

Access list:

{This object is protected from inheriting permissions from the parent}

Effective Permissions on this object are:

Allow Everyone  FULL CONTROL

The command completed successfully

 

As you can see I effectively killed the inheritance for any permissions flowing down from above and I have taken the defaultSecurityDescriptor out of the picture.

 

A quick comment on Brian’s response too. He mentioned

2: Yes and no. You could restrict the ability to write to gidNumber on objects of group class, however, if you’ve given the ability to create objects of the group class to anyone, or full control of groups, then they can circumvent that ACL. Explicit Allow ACEs trump inherited Deny ACEs in AD. And object owners (by default whoever creates an object) have full control.

Assuming the defaultSecurityDescriptor was used to add the DENY modify of gidNumber, it would be applied as an explicit DENY and therefore override the creator’s explicit FC for the object. However, as mentioned above, the defaultSecurityDescriptor is moot. But also… if the creator has FC applied, even with an explicit DENY, they will just modify the ACL on the object to remove the explicit DENY and voila, they are in the game yet again.

BTW, another fun point here… Some people try to circumvent this security issue by having an agent constantly monitoring ACLs and “correcting” the “bad” ones when found. This can also be beaten, once the person finds out what the security context of the agent is running in (assuming not localsystem on DCs as that is discouraged as a best practice right?), you just set up the DACL that you lay down on the object to deny FC for that object and then the agent has no power over the object if it even sees it at all (it won’t be returned in queries right?). Maybe it will flag an error, maybe it won’t, depending on how well it was written. Maybe the flagged error will be looked at by an administrator, maybe it won’t, depending on how well that process is being managed/supported.

As Brian indicated, the proper way to handle this is to not allow people to create groups natively. Provisioning as a general statement should be done through a gatekeeper system, either a team that is responsible strictly for provisioning or a tool that does it. Giving random folks ability to create objects in AD is in general a bad idea. It should be a team or person that is dedicated to that function and on the hook to know and follow the rules. 

joe

Rating 4.33 out of 5

From the mailbag: Determining domain membership by IP

by @ 8:00 pm. Filed under tech

I received an email the likes of which I have seen a few times over the last few years and figured I would share the issue and my response.

The issue is someone who has a bunch of machines scattered around a very large environment and they really don’t know what domain those machines are in, if any. Now I expect there are folks out there reading this who are absolutely incredulous over the fact that you could have machines in the environment and not even know if they are in a domain or if they are in a domain, what domain that might be. Unfortunately I have to say that that happens rather regularly in the larger environments where you have hundreds if not thousands of machines and you actually, I am not lying, have even tens or hundreds of domains laying about the network.

There will be machines in the environment and actually forgotten for years once the person who was responsible for them moves on or gets fired or whatever. I recall once that I found a very super high powered server (Quad Proc when even a Dual Proc was pretty darn cool) that was probably 5-10 times more powerful than most of the stuff I got to use that was just sitting and spinning idle. Had been in that state for over three years. Someone had a hot project that needed a hot server, they paid for it up front, it got deployed, then something happened and the project died and no one came and reclaimed it. It wasn’t listed in any of the standard support databases, not in AD, nothing. I only found it because it was infected with something and beating the network up trying to infect other machines.

Anyway, the basic problem is, say you have an IP or a resolvable machine name but you don’t know what domain that machine is part of and need to determine that info remotely. Yes, I know the quick answer is, well whatever the domain suffix it has on it, that is the domain it is part of. That is the quick answer, but it could very likely be the wrong answer. There is no rule that states a machine has to be a member of a given domain in order to have that domain as its DNS suffix.

The quickest and easiest solution I am aware of kind of old school and will slowly become less and less useful. The idea is to enumerate the NetBIOS Name table for the machine and work out what the records are. Obviously, machine based firewalls and turning off NetBIOS can impact this, both of which are becoming more common and why I said this idea will slowly become less and less useful.

Here are some examples:

G:\>nbtstat -a joeware-dc1

Local Area Connection:
Node IpAddress: [192.168.0.122] Scope Id: []

           NetBIOS Remote Machine Name Table

       Name               Type         Status
    ———————————————
    JOEWARE-DC1    <00>  UNIQUE      Registered
    JOEWARE        <00>  GROUP       Registered
    JOEWARE        <1C>  GROUP       Registered
    JOEWARE-DC1    <20>  UNIQUE      Registered
    JOEWARE        <1B>  UNIQUE      Registered
    JOEWARE        <1E>  GROUP       Registered
    JOEWARE        <1D>  UNIQUE      Registered
    ..__MSBROWSE__.<01>  GROUP       Registered

    MAC Address = 00-0C-29-F4-7B-5E

Note if you had the IP you would use NBSTAT -A IPADDRESS  (note the cap –A switch)

From that name table you can see that this machine has the <00> and <1E> group records for JOEWARE which means it is a member of the JOEWARE domain. Not only that, but it also has a <1C> group record for JOEWARE which means it is a domain controller for JOEWARE…. And not only that… It has a <1B> record for JOEWARE which means it is the PDC for JOEWARE. The only catch here is… JOEWARE is a NetBIOS name, the DNS name could be anything. Thankfully since it is a DC, you can (assuming not Windows NT) query the RootDSE and get more data like so:

G:\>adfind -h joeware-dc1 -rootdseanon

AdFind V01.41.00cpp Joe Richards (joe@joeware.net) February 2010

Using server: JOEWARE-DC1.joeware.local:389
Directory: Windows Server 2003

dn:
>currentTime: 20101123194337.0Z
>subschemaSubentry: CN=Aggregate,CN=Schema,CN=Configuration,DC=joeware,DC=local
>dsServiceName: CN=NTDS Settings,CN=JOEWARE-DC1,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=joeware,DC=local
>namingContexts: DC=joeware,DC=local
>namingContexts: CN=Configuration,DC=joeware,DC=local
>namingContexts: CN=Schema,CN=Configuration,DC=joeware,DC=local
>namingContexts: DC=DomainDnsZones,DC=joeware,DC=local
>namingContexts: DC=ForestDnsZones,DC=joeware,DC=local
>defaultNamingContext: DC=joeware,DC=local
>schemaNamingContext: CN=Schema,CN=Configuration,DC=joeware,DC=local
>configurationNamingContext: CN=Configuration,DC=joeware,DC=local
>rootDomainNamingContext: DC=joeware,DC=local
>supportedControl: 1.2.840.113556.1.4.319 [LDAP_PAGED_RESULT_OID_STRING]
>supportedControl: 1.2.840.113556.1.4.801 [LDAP_SERVER_SD_FLAGS_OID]
>supportedControl: 1.2.840.113556.1.4.473 [LDAP_SERVER_SORT_OID]
>supportedControl: 1.2.840.113556.1.4.528 [LDAP_SERVER_NOTIFICATION_OID]
>supportedControl: 1.2.840.113556.1.4.417 [LDAP_SERVER_SHOW_DELETED_OID]
>supportedControl: 1.2.840.113556.1.4.619 [LDAP_SERVER_LAZY_COMMIT_OID]
>supportedControl: 1.2.840.113556.1.4.841 [LDAP_SERVER_DIRSYNC_OID]
>supportedControl: 1.2.840.113556.1.4.529 [LDAP_SERVER_EXTENDED_DN_OID]
>supportedControl: 1.2.840.113556.1.4.805 [LDAP_SERVER_TREE_DELETE_OID]
>supportedControl: 1.2.840.113556.1.4.521 [LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID]
>supportedControl: 1.2.840.113556.1.4.970 [LDAP_SERVER_GET_STATS_OID]
>supportedControl: 1.2.840.113556.1.4.1338 [LDAP_SERVER_VERIFY_NAME_OID]
>supportedControl: 1.2.840.113556.1.4.474 [LDAP_SERVER_RESP_SORT_OID]
>supportedControl: 1.2.840.113556.1.4.1339 [LDAP_SERVER_DOMAIN_SCOPE_OID]
>supportedControl: 1.2.840.113556.1.4.1340 [LDAP_SERVER_SEARCH_OPTIONS_OID]
>supportedControl: 1.2.840.113556.1.4.1413 [LDAP_SERVER_PERMISSIVE_MODIFY_OID]
>supportedControl: 2.16.840.1.113730.3.4.9 [LDAP_CONTROL_VLVREQUEST]
>supportedControl: 2.16.840.1.113730.3.4.10 [LDAP_CONTROL_VLVRESPONSE]
>supportedControl: 1.2.840.113556.1.4.1504 [LDAP_SERVER_ASQ_OID]
>supportedControl: 1.2.840.113556.1.4.1852 [LDAP_SERVER_QUOTA_CONTROL_OID]
>supportedControl: 1.2.840.113556.1.4.802 [LDAP_SERVER_RANGE_OPTION_OID]
>supportedControl: 1.2.840.113556.1.4.1907 [LDAP_SERVER_SHUTDOWN_NOTIFY_OID]
>supportedControl: 1.2.840.113556.1.4.1948 [LDAP_SERVER_RANGE_RETRIEVAL_NOERR]
>supportedLDAPVersion: 3
>supportedLDAPVersion: 2
>supportedLDAPPolicies: MaxPoolThreads
>supportedLDAPPolicies: MaxDatagramRecv
>supportedLDAPPolicies: MaxReceiveBuffer
>supportedLDAPPolicies: InitRecvTimeout
>supportedLDAPPolicies: MaxConnections
>supportedLDAPPolicies: MaxConnIdleTime
>supportedLDAPPolicies: MaxPageSize
>supportedLDAPPolicies: MaxQueryDuration
>supportedLDAPPolicies: MaxTempTableSize
>supportedLDAPPolicies: MaxResultSetSize
>supportedLDAPPolicies: MaxNotificationPerConn
>supportedLDAPPolicies: MaxValRange
>highestCommittedUSN: 741310
>supportedSASLMechanisms: GSSAPI
>supportedSASLMechanisms: GSS-SPNEGO
>supportedSASLMechanisms: EXTERNAL
>supportedSASLMechanisms: DIGEST-MD5
>dnsHostName: JOEWARE-DC1.joeware.local
>ldapServiceName: joeware.local:joeware-dc1$@JOEWARE.LOCAL
>serverName: CN=JOEWARE-DC1,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=joeware,DC=local
>supportedCapabilities: 1.2.840.113556.1.4.800 [LDAP_CAP_ACTIVE_DIRECTORY_OID]
>supportedCapabilities: 1.2.840.113556.1.4.1670 [LDAP_CAP_ACTIVE_DIRECTORY_V51_OID]
>supportedCapabilities: 1.2.840.113556.1.4.1791 [LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID]
>dsSchemaAttrCount: 1980
>dsSchemaClassCount: 361
>dsSchemaPrefixCount: 47
>isSynchronized: TRUE
>isGlobalCatalogReady: TRUE
>supportedConfigurableSettings: DynamicObjectDefaultTTL
>supportedConfigurableSettings: DynamicObjectMinTTL
>supportedConfigurableSettings: DisableVLVSupport
>supportedExtension: 1.3.6.1.4.1.1466.20037 [LDAP_SERVER_START_TLS_OID]
>supportedExtension: 1.3.6.1.4.1.1466.101.119.1 [LDAP_TTL_REFRESH_OID]
>supportedExtension: 1.2.840.113556.1.4.1781 [LDAP_SERVER_FAST_BIND_OID]
>domainFunctionality: 2 [Windows Server 2003 Domain Mode]
>forestFunctionality: 2 [Windows Server 2003 Forest Mode]
>domainControllerFunctionality: 2 [Windows Server 2003 Mode]
>validFSMOs: CN=Schema,CN=Configuration,DC=joeware,DC=local
>validFSMOs: CN=Partitions,CN=Configuration,DC=joeware,DC=local
>validFSMOs: DC=joeware,DC=local
>validFSMOs: CN=Infrastructure,DC=joeware,DC=local
>validFSMOs: CN=RID Manager$,CN=System,DC=joeware,DC=local

1 Objects returned

That extra info, available because it is a DC, really lets us know what is going on with that machine. Best of all, it is all anonymous, no need for creds if you even knew what creds to use… In fact, the reason for this exercise could be to try and ascertain what ID you should be using.

 

Unfortunately, a machine that isn’t a DC isn’t quite as helpful but perhaps it does give enough info.

G:\>nbtstat -a mbx01

Local Area Connection:
Node IpAddress: [192.168.0.122] Scope Id: []

           NetBIOS Remote Machine Name Table

       Name               Type         Status
    ———————————————
    MBX01          <00>  UNIQUE      Registered
    JOEWARE        <00>  GROUP       Registered
    MBX01          <20>  UNIQUE      Registered
    JOEWARE        <1E>  GROUP       Registered

    MAC Address = 00-0C-29-64-4D-D7

The <00> and <1E> Group records again tell you the domain, but that is about all you get out of this one. Occasionally you will find that if you portscan the machine, you will find a port for some common service, say SMTP that may give you more info, that can be enough to get you going in the right direction.

Overall, I see this issue getting more and more difficult to handle as we move forward and lock machines down. It has made me recommend to some people that maybe their standard OS loads should have some sort of beacon type functionality in place. If you hit the server on the right port with some simple string, say IDENTIFY, it responds with some basic info about the machine. That port and command would be maintained in a very stringent manner and well tested for string length etc so it doesn’t later become an Achilles heel for the machine but could be very useful for larger orgs that just for the life of them can’t seem to get a handle on stray machines in the environment.

 

   joe

Rating 4.00 out of 5

11/19/2010

Cheaper…

by @ 7:00 pm. Filed under quotes

Do we have any tetanus shots in the first aid kid?

We do not have a first aid kit, if someone gets hurt, it’s cheaper to hire a new worker.

Rating 3.00 out of 5

Great commercial for a Friday

by @ 7:00 am. Filed under humour
Rating 4.00 out of 5

11/18/2010

I’m on a roll…

by @ 6:59 pm. Filed under quotes

I think we can attribute this to shooting first and figuring out which way to point the gun afterwards. Or to put it another way, they are too busy trying to get things done to spend time trying to figure out how it should be done.

  – me

Rating 4.00 out of 5

Duck….

by @ 9:46 am. Filed under quotes

…even if you wear a bullet proof vest, you still want to duck if someone shoots at you.

   – me (when discussing belt and suspenders methods of protecting yourself)

Rating 3.00 out of 5

11/17/2010

Command Prompt Application Hint

by @ 7:00 pm. Filed under tech

Hi
I came across your free tools and think these tools are very much what any administrator needs but it seems that when i downloaded this utility it does nothing. Command box opens and disappears in flash of a second.  I am running Windows 7, any idea? Any help would much appreciated.

Thanks
xxx
IT Desktop Support

To all computer admins, if  you click on an application and a command prompt flashes on the screen, the likely next step is to open a command prompt and type in the command and try that. 

     joe

Rating 4.67 out of 5

11/16/2010

Oops. Root Kit can attack 64 bit Windows systems – not worried about driver signing…

by @ 11:17 pm. Filed under tech

A notorious rootkit that for years has ravaged 32-bit versions of Windows has begun claiming 64-bit versions of the Microsoft operating system as well.

The ability of TDL, aka Alureon, to infect 64-bit versions of Windows 7 is something of a coup for its creators, because Microsoft endowed the OS with enhanced security safeguards that were intended to block such attacks. The rootkit crossed into the 64-bit realm sometime in August, according to security firm Prevx.

Full article…

http://www.theregister.co.uk/2010/11/16/tdl_rootkit_does_64_bit_windows/

Rating 3.33 out of 5

11/15/2010

What is DFL3? or What is FFL2?

by @ 8:00 pm. Filed under tech

On a regular basis I will say some tool or app or something requires DFL2 or DFL3 or FFL2 or something like that, I am amazed still how many people do not know what that means and I get a response of “huh? I don’t think I have that tool.” or “I typed in DFL2 and it says it is a bad command".”  Sad smile 

DFL stands for Domain Functional Level. It tells you quickly the minimum level that your Domain Controllers in a given domain must be. And FFL stands for Forest Functional Level. And you may surmise it tells you what the minimum level that your Domain Controllers must be across the entire forest. Here is a nice KB about it all http://support.microsoft.com/kb/322692.

These functional levels are important because certain types of functionality only become available once you hit certain functionality levels. A few “important” FL’s that I regularly mention:

  • DFL2 – Windows Server 2003 Domain Functional Level. This DFL gets you the lastLogonTimeStamp attribute.
  • FFL2 – Windows Server 2003 Forest Functional Level. This FFL gets you Linked Value Replication (LVR) which is a pretty substantial change in how your replication works. To most people that means that you don’t replicate entire group memberships when a single member changes, you replicate just the changed values. It means that you can avoid a particularly nasty replication error due to version store exhaustion you could hit with very large groups and it also means that you can have the opportunity to experience lingering backlinks.
  • DFL3 – Windows Server 2008 Domain Functional Level. This gets you Fine Grained Password Policy.
  • FFL4 – Windows Server 2008 R2 Forest Functional Level. This gets you to a state that you can enable the AD Recycle Bin.

 

You may ask… but why would they need to do this… Because when you are writing operating systems, you can’t always back port every function to every old version of the OS. This could be due to substantial changes in the new OS that just won’t allow the change to be ported backwards, or it could be more costly than it is worth, or it could be a desire to get people to upgrade to the new versions so you can stop supporting the old versions or say, make money on selling new versions of the OS. Winking smile  So you have to set a minimum bar and the bar is set via the DFL and FFL requirements. You want the whole domain or the whole forest to be at that required level because you want consistency. Say you only have fine grained password policy working on 1/3 of your domain controllers, how much fun would that be for your users? Not much at all if I can hazard a guess. You would need to know what the OS of your DC is before you could know properly what kind of password you might be able to use or whether you will lock out or not for some given bad number of attempts. Or from a replication standpoint, if 1/4 of your DCs know about LVR but the other 3/4’s don’t, that would be a pain in the butt to deal with even if MSFT said, we will waste the time to write the code to make this work for you by sending the whole group membership to those 3/4 that don’t know LVR.

 

Here is a quick pair of tables to tell you the DFL/FFL numbers and their related OS level…

DFL Level OS Version
0 Windows 2000
1 Windows Server 2003 (interim)
2 Windows Server 2003
3 Windows Server 2008
4 Windows Server 2008 R2

 

FFL Level OS Version
0 Windows 2000
1 Windows Server 2003 (interim)
2 Windows Server 2003
3 Windows Server 2008
4 Windows Server 2008 R2

 

If you are looking at the values of “1” and thinking, “WTF is that?” Don’t worry about it. It is rare and unless you are a developer of AD software or actually dealing with a situation that requires you to be involved with a D/FFL1 environment, you don’t need to worry about it. I personally have never seen one in actual production, only in test labs. If you want to learn what it is, knock yourself out, I am not going to spend any more time on it here. Smile

BTW, you can easily ascertain what functionality modes you are at with AdFind and querying the RootDSE of a DC.

Ex 1:

C:\>adfind -rootdse domaincontrollerfunctionality domainfunctionality forestfunctionality

AdFind V01.42.00cpp Joe Richards (joe@joeware.net) April 2010

Using server: TEST-DC1.test.loc:389
Directory: Windows Server 2003

dn:
>domainFunctionality: 2 [Windows Server 2003 Domain Mode]
>forestFunctionality: 2 [Windows Server 2003 Forest Mode]
>domainControllerFunctionality: 2 [Windows Server 2003 Mode]

1 Objects returned

Ex 2:

C:\temp>adfind -rootdse domaincontrollerfunctionality domainfunctionality forestfunctionality

AdFind V01.42.00cpp Joe Richards (joe@joeware.net) April 2010

Using server: K8R2Dom-DC01.K8R2Dom.loc:389
Directory: Windows Server 2008 R2

dn:
>domainFunctionality: 4 [Windows Server 2008 R2 Domain Mode]
>forestFunctionality: 4 [Windows Server 2008 R2 Forest Mode]
>domainControllerFunctionality: 4 [Windows Server 2008 R2 Mode]

1 Objects returned

 

   joe

Rating 4.00 out of 5

11/14/2010

Some quick hitters when integrating apps to use AD and ADAM

by @ 10:44 pm. Filed under tech

It has been almost 11 years since Windows 2000 and Active Directory hit the world and apps are still having issues. At this point I just want to look at vendors and say “Seriously??? Figure it out already.”.

So I am just going to start typing issues that I have encountered that by now shouldn’t really be issues IMO. Maybe by doing this, vendors will stumble upon it and make sure their apps don’t have these issues. This isn’t an all inclusive list, this is just me typing things that pop into my head as I sit here watching TV.

Simple Binds

The first thing that pops into my head is simple bind. If you are using simple bind you absolutely should be using LDAPS. Period. You have this important (at least it should be right?) application that needs to talk to AD so they give you an ID and you set a nice safe secure password to keep the ID and your application and any data it has access to safe and then you throw out there in the clear for the world to see.

Hard-coding DCs

Hard-coding DCs is probably one of the most frustrating things to hit Active Directory Admins around the world. Someone thinks their application is so important that, of course, the AD Admins, who have nothing else to worry about, will be constantly focused on the DC the application people decided to target and make sure it has 110% uptime. Ah yeah, not going to happen. Application vendors, developers, integrators, and support teams… the AD Support people have lots of things to do that have nothing to do with your application, they very likely don’t even remember talking to you about your app if they know you exist at all.

There are multiple ways to solve this issue but the most professional is to set things up like MSFT intended. Microsoft didn’t come up with the idea of publishing SRV records for the services so they could keep the DNS people in work, they did it so applications can locate DC resources as needed. I have seen teams in companies working on UNIX apps as long ago as 2002 writing their own DC Locator services. If these teams who work for companies whose focus in the world is something entirely different than writing software to integrate with AD can pull this off, how come vendors who write LDAP products that they sell can’t accomplish the same thing? Especially when they say their applications are Active Directory aware. I would propose that if an LDAP based application can’t locate the closest DCs via some sort of DC Locator functionality, they are NOT Active Directory aware and we should be pretty quick to tell them that. I haven’t looked in a while, but I expect JNDI still doesn’t work right for this[2]. That is pretty annoying because it is so ubiquitous out there, if they could fix that, lots of apps would be fixed.

Poor Handling of Multiple Domain / Complex Domain Configurations

What is an Active Directory forest supposed to look like? Default answer for most companies, including sometimes, even MSFT, one single domain in the forest. Reality though is much different. As much as many companies, especially now a days, would like to have a single domain forest for their corporate AD, they often have an AD forest that was built up from several geographically based NT4 domains that they had deployed before AD came along. Possibly even having more than one or two domains for a single geographic area. This could be for a variety of reasons but the most common I have encountered are 1) NT4 SAM DB size limitations  2) Corporate HQ gets its own domain and everyone else in the geographic region gets another 3) Business user domain versus manufacturing domains.

These domains are often combined in a variety of configurations. The most common I have experienced is the empty forest root with child domains for each of the geographic domains. This is so common for me that I am in shock if I don’t see it in larger multinational companies. You will have company.com, na.company.com (or am.company.com or americas.company.com or nam.company.com or northam.company.com or amer.company.com, etc), eu.company.com (or emea.company.com or ema.company.com or europe.company.com, etc), ap.company.com (or apj.company.com or apac.company.com) and possibly a few more depending on the company. But in general, you have americas, europe/middle east, and asia pacific rim all as children of the forest root. I have also encountered a case where someone actually used grandchildren domains which is, for me, unusual to see. You will also occasionally run into environments where different domain trees are deployed. Out of all of these, the different domain trees are probably the worst for normal MSFT based apps and scripts. Most scripts do not take this case into account and if you try to run generic scripts that make assumptions instead of properly checking the RootDSE for the namespace and therefore get confused and can’t find things they should be finding.

People writing tools for alternate LDAP directories that get “ported” to work on AD tend to make additional mistakes that hurt you even when you have a nice pretty namespace layout (as defined by having a nice clean domain hierarchy like parent and 3 children). That issue is that they have you point at a single DC (aka LDAP server) and expect to be able to see the whole LDAP hierarchy for the forest. That can work, but only if you point at a Global Catalog and specify the GC port… But wait, now you don’t have access to all of the attributes and if the tool writes to AD, that offers additional issues. Add in multiple domain trees and you can totally freak out those alternate directory tools.

Lack of Paging/Ranging Support

This one is another one of the “If your LDAP app can’t do this, your app really isn’t Active Directory Aware” items in my book. I hate when I see emails or forum posts or any mechanism of asking, hey, how do I change the page size or default range size in Active Directory because I have an app that doesn’t do paging/ranging. My response is usually of two parts, 1) “If you increase it now, what happens later when that isn’t enough? You raise it again? Will your app be smart enough to know it has hit the limit?”  2) Go beat on the vendor to fix their app.

If you have are a vendor and your app doesn’t page or range properly, you can be 100% sure that if one of your customers or your possible customers asks me about it and what I think I will say they need to run as fast as they can from your app because you do not know enough about Active Directory to be messing with it.

LDAP Signing/Sealing

LDAP Signing and Sealing is really cool, for security. It sucks for when you are trying to troubleshoot an application that doesn’t have good logging and you want to use a network sniffer to figure out what is happening. Application developers, yes use LDAP Signing and Sealing, but please give an easy to find and use method to disable it at least for short periods of time so when your application isn’t doing what is expected, we have a method to troubleshoot it that doesn’t entirely depend on what you foresaw you needed to do for logging. Hey if it only disables for 24 hours and then resets itself or maybe it resets itself between every launch of the app, whatever, that is fine.

LDAP Logging

This is one I fall down on myself, logging of LDAP transactions. Active Directory’s logging is traditionally pretty weak. Many LDAP Servers will log darn near everything you could possibly want from the requests the server will handle to a text file, Active Directory doesn’t. Now there is some stuff in the Event Tracing functionality that is more difficult than just saying, log this stuff to a text file, but I haven’t yet had time to dig into. You can learn more from Brandon (http://bsonposh.com/archives/347) and Tony (http://www.activedir.org/Articles/tabid/54/articleType/ArticleView/articleId/49/Default.aspx).

Inefficient and/or Incorrect Queries

This one really irks me when I see it from big time vendors. While paging and ranging and domain controller location and even complex forest structures take some decent knowledge to figure out, an ok filter really shouldn’t be that difficult. A vendor who doesn’t produce a decent query for AD really should invest some time and money into figuring it out. At the very least read the following document – http://msdn.microsoft.com/en-us/library/ms808539.aspx. It’s bad enough to find this in apps when looking at network traces (and yes even MSFT has screwed this up themselves) because you can maybe hope no one will go look and see what you screwed up, but when you actually publish this in a support document you publish on the web… sheesh. As a recent example, I had to go through the Google Apps Directory Sync for Postini Services document this last week, I ran into a couple of bad queries right off:

All users, but exclude disabled users:

(&(&(objectclass=user)(objectcategory=person))(!(userAccountControl=514)))

This isn’t inefficient, it is just incorrect. If you are checking for disabled users, you need to perform a bit-wise check of userAccountControl, not check it for a specific value.

Active Directory LDAP: All users
(objectClass=person)

Unless you have indexed objectClass or you have deployed Windows Server 2008, this will be inefficient. Also it will return more than users… such as contacts, trusts, etc.

Active Directory LDAP: All email users (alternate)
(&(objectclass=user)(objectcategory=person))

This one is incorrect for what they are looking for, it is an efficient query for all users… Regardless of email status. Will still get trusts btw.

If Google is looking for good AD people… contact me… ;o)

Inefficient ADSI Use

This last one may confuse people. Folks may think… “Hey it’s a Microsoft framework, doesn’t it just work efficiently automatically?” No. This impacts people using ADSI directly or the .NET stuff that thunks down to ADSI, i.e. the stuff under System.DirectoryServices (excluding S.DS.Protocols). My recommendation here is if you aren’t completely positive about what ADSI is doing with what you are telling it, get out a network sniffer and look at the traffic for your operations and see if you can clean it up[1]. Heck do it even if you think you know exactly what it is doing. You could very likely find parts of your app that are incredibly inefficient and slow and unnecessarily beating up the DCs. One quick one here is app developers not taking advantage of IADs:GetInfoEx to pull the actual individual attributes needed versus the whole object. When and why is this important? If you have an app running on one machine that is dealing with one off AD Objects occasionally then the importance goes down a little as it won’t be generating a lot of load on the DC or network though personally I think you should still only pull what you need. If it is an app running on hundreds of thousands of machines and you are pulling the whole object instead of just the attributes you need then you are pulling way too much data from the DC. Or if you have the app running on one machine but pulling lots of objects, again, you are pulling way too much data from the DC.

 

    joe

 

[1] I would love for the Microsoft Developers on the Exchange team to pay attention to this point because I was looking at an Exchange 2010 network trace the other day and the best thing that I had to say was that whatever I was looking at was an unnecessary network and AD utilization pig. Every object that it pulled it pulled twice. The first time to see if it existed with just the objectClass, the next time it pulled the whole object, for every object.

[2] UPDATE (2010-12-09): I was looking for something and I found what appears to look like good news for JNDI. It seems that in the JNDI 1.5 docs they discuss automatic discovery of LDAP Service. (http://download.oracle.com/javase/1.5.0/docs/guide/jndi/jndi-ldap.html)  It doesn’t look like they look at site specific records, but at least they are looking at LDAP SRV records which is further along than they were previously that I recall.

Rating 4.40 out of 5

[joeware – never stop exploring… :) is proudly powered by WordPress.]