August 2006

You are currently browsing the monthly archive for August 2006.

A Couple Cool Mac Discoveries

The first of these discoveries I found while working on the Kerberos SSO article, and while verifying information for my updated Linux-AD integration instructions for Windows Server 2003 R2.

As you may already know, Mac OS X has built-in Kerberos support.  Not only can you use the standard “kinit” command from the Terminal, but Apple also provided a graphical interface to obtain and manage Kerberos tickets.  Buried in /System/Library/CoreServices is Kerberos.app, a graphical application for obtaining and managing Kerberos tickets.  Now, if you use your Mac in a Windows network running Active Directory (which is a lot of you), using this application to obtain a Kerberos ticket from your AD domain controller then means that you can mount any Windows share in your domain without any password prompts whatsoever.  Furthermore, using Safari or Shiira to access sites using Integrated Windows Authentication means you’ll be transparently logged on to those web sites without any password prompts whatsoever.

Even better, there are hooks that allow you to configure the Mac login window to automatically go get you a Kerberos ticket from Active Directory, further automating this process and further making your life easier.

The second handy discovery came today while working with a Solaris 10 virtual machine (I’m working on some testing of Solaris-AD integration using Kerberos and LDAP…look for an article soon).  I needed a way to grab a remote X Window session—not just a single X11 window, but the whole desktop.  So, based on this information, I launched X11 on my PowerBook, opened an SSH session to the Solaris server and ran this command:

/usr/openwin/bin/Xnest :1 -query localhost

Lo and behold, a XDMCP session popped up on my Mac’s desktop, all neatly contained within its own window.  Very handy!  I found that you must first set the DISPLAY variable in Terminal in order for this to work (or you just use the xterm that opens when you launch X11).  Using this trick, I was able to do what I needed to do on the Solaris server.

<aside>I suspect that, given the fact that Solaris’ SSH daemon is Kerberized, that once I get Kerberos support on the Solaris server configured I will be able to use Kerberos.app to obtain a Kerberos ticket from Active Directory, then seamlessly authenticate to the Solaris server to tunnel an X Window desktop over SSH.  Now that’s cool.</aside>

I’m looking forward to using Xnest to do the same thing on Linux servers as well, but haven’t yet had the time to test it.  I’ll post more information here as soon as I do.

Tags: , , , , ,

del.icio.us API Change

Fortunately, the fix for Cocoalicious is really straightforward; simply go into the preferences, change the API URI to “https://api.del.icio.us/v1/”, click OK, then exit and restart the application.  All should be well after that.  (At least, it worked for me.)

However, this also means that if you have any scripts or WordPress plug-ins, you may have to modify those as well.  I have a plug-in that lists recent del.icio.us posts in the sidebar, and I’ll need to see if that plug-in (or the plug-in’s configuration) needs to be updated.

(Funny how a “little” thing like a URI can have a ripple effect like this.)

Tags: , ,

The key to the magic here is the mod_auth_kerb module, which adds Kerberos authentication to Apache.  This module not only allows Apache to use Kerberos on the “back-end,” so to speak, but also supports the SPNEGO and GSS-API stuff on the “front-end” that allow it to transparently authenticate users connecting with supported browsers, without ever prompting for a password.

Preparing Active Directory (Each Apache Server)

These steps need to be repeated for each Apache server that will authenticating via Kerberos to Active Directory.

  1. First, create a user account (not a computer account) for each Apache server.  I highly suggest using a naming convention that supports a) the service principal(s) involved; and b) the name of the server.  Since Apache will use the HTTP service principal, a name like “HTTP-lnxservername” would be good.  The password doesn’t matter, but do be sure to check the “Password never expires” check box, and after the account is created specify a good description so that you’ll remember what this account is for in 6 months.
  2. For each account that was created, run the ktpass.exe command to generate a unique keytab for each account.  The command will look something like this (substitute the appropriate values where necessary):
    ktpass -princ HTTP/fqdn@REALM -mapuser DOMAIN\account
    -crypto DES-CBC-MD5 +DesOnly -pass password -ptype KRB5_NT_PRINCIPAL
    -out filename

    Be sure to specify a unique output filename (so that you don’t overwrite files; each server/account will needs its own unique file).  I suggest using the server’s name as the filename, i.e., something like “lnxservername.keytab”.

It would be ideal if we could leverage the existing computer account that may exist for that Linux server for host authentication (I’m assuming you followed my instructions for integrating host authentication into Active Directory, yes?), but for some reason it doesn’t work.  We can use the SetSPN utility to add the appropriate SPN to the computer account, but authentication still doesn’t work.  If any Kerberos/Active Directory gurus out there have some insight on this, please let me know.  (By the way, this may be one reason for using user accounts for all the various SPNs—HOST/fqdn@REALM, HTTP/fqdn@REALM, etc.—as some of the online guides for integrating Linux and Active Directory have suggested.)

Now we’re ready to move on to configuring the Apache servers.

Configuring Apache (Each Server)

Repeat these steps for each Apache server.  In case I haven’t already mentioned this, I’m assuming you’re running Apache 2.0 on Linux, and not on some flavor of Windows.

  1. Download and install the mod_auth_kerb Apache module.
  2. Add the following directives to the Apache configuration, either in httpd.conf or in the conf.d directory in its own file (my installation of mod_auth_kerb created an auth_kerb.conf in conf.d):
    LoadModule auth_kerb_module modules/mod_auth_kerb.so
    
    <Location /secured>
      AuthType Kerberos
      AuthName “Kerberos Login”
      KrbMethodNegotiate On
      KrbMethodK5Passwd On
      KrbAuthRealms EXAMPLE.COM
      Krb5KeyTab /etc/httpd/conf/httpd.keytab
      require valid-user
    </Location>

    Substitute the correct values for the KrbAuthRealms directive (your Kerberos realm name will be your Active Directory domain name in UPPERCASE) and the location and name of the keytab.  (We’ll copy the keytab over shortly.)

  3. Securely copy over the keytab for this server from the Windows server where it was generated using ktpass.exe earlier.  SFTP or SCP are good candidates.  Once the file has been copied over, rename it and place it in the right location, as specified in the configuration entered above.
  4. Change the owner of the keytab to the Apache user (typically “apache” or “web”), and set the permissions to 400 (readable only by the Apache user).
  5. Restart the Apache HTTP daemon for the configuration changes to be read and applied.

Assuming that your Apache server is accessible as web.example.com, you should now be able to fire up a recent version of Internet Explorer (one that supports Integrated Windows Authentication) and navigate to the “http://web.example.com/secured” URL and gain access, without getting prompted for authentication.  A quick review of the access logs (typically /var/log/httpd/access_log) shows that you are being authenticated as the user that is currently logged on to Windows.  (If the browser you are using doesn’t support the transparent authentication, you’ll get prompted for a username and password, in which case you can enter your Active Directory username and password and gain access to the site.)

If this doesn’t work, go back and double-check your ktpass.exe command (noting that the case of the Kerberos principal specified by the “-princ” option is important, as it is case-sensitive).  Also check the permissions on the keytab after it has been copied over to the Linux server; it must be readable by the Apache user (and should not be readable by any other users or groups).  Finally, try unchecking the “Enable Integrated Windows Authentication” option in Internet Explorer, restarting IE, re-checking that box, and then restarting IE again.  (Don’t ask why, but it does seem to help in some instances.)

Finally, note that a few other browsers also support the transparent authentication.  I personally tested Safari and Shiira on Mac OS X, and both worked fine (after I had obtained a Kerberos ticket, either using the Kerberos application or kinit from a shell prompt).  Camino didn’t work, which is a bummer.  I haven’t tested Firefox yet, but I’m told that Firefox also works, although an extension may be required.

Extensive credit goes to Achim Grolms for his walk-through of using mod_auth_kerb with a Windows KDC.

Tags: , , , , , ,

UPDATE: A revised version of these instructions is available here.

The integration of (what was formerly called) Services for UNIX into Windows Server 2003 R2 also brought some other changes; most notably, a change in the schema.  To accommodate those changes, I’ve updated my Linux-AD integration instructions (the previous instructions are here for pre-R2 versions of Windows).  If you need to integrate Linux systems for authentication into Active Directory with Windows Server 2003 R2, these instructions should get you there.  (Note that a previous version of these instructions is also available.)

For the most part, these instructions are reasonably similar to the instructions for pre-R2 versions of Windows.

Preparing Active Directory (One-Time)

Based on what I’ve seen so far, it appears as if a partial RFC 2307-compliant schema is included by default with Windows Server 2003 R2.  This means that it is no longer necessary to extend the schema to include attributes such as uid, gid, login shell, etc.  However, while the schema does appear to be present by default (based on explorations using ADSI Edit), you must install the “Server for NIS” component on at least one domain controller in order to be able to actually set those attributes (and it will be necessary to set those attributes using the Active Directory Users and Computers console before logins from Linux will work).

However, to optimize Active Directory logins from Linux systems, it’s also necessary to index the uid attribute in Active Directory.  By default, most PAM-enabled systems use the uid attribute as the default login attribute (refer to the “pam_login_attribute” parameter in the /etc/ldap.conf file).  Logins will work without having this attribute indexed, but as was discovered in a recent VAS installation, this can introduce delays and drive CPU utilization through the roof.  Use the Schema Management MMC snap-in to check the box labeled “Index this attribute in the Active Directory” for the uid attribute.  (If you don’t want to index the uid attribute, change the value of the pam_login_attribute to something like sAMAccountName, which is already indexed.)

Next, create a new global security group that will act as the default group for Linux-enabled users.  Be sure to set the values on the “UNIX Attributes” tab for this group.  Add the users that will authenticate to this group using both the “Members” tab and the members list on the “UNIX Attributes” tab.

Finally, you’ll also need to create an account in Active Directory that will be used to bind to Active Directory for LDAP queries.  This account does not need any special privileges; in fact, making the account a member of Domain Guests and not a member of Domain Users is perfectly fine.

Each of these tasks are one-time tasks that must be accomplished before logins from Linux will work.  Once they have been completed, you are ready to configure the individual users.

Preparing Active Directory (Each User)

Each Active Directory account that will authenticate via Linux must be configured with a uid and other UNIX attributes.  This is accomplished via the new “UNIX Attributes” tab on the properties dialog box of a user account.  Installing the “Server for NIS” component enables this new tab, as mentioned previously.

Each user must be given an NIS domain, but this parameter is ignored in our authentication scheme.  Each user must also have a unique uid; I believe that the Server for NIS defaults at a starting uid of 10000, which is pretty safe for most systems.  In addition, each member must have a gid (group ID); simply specify the group that was created earlier.  Be sure to also specify a login shell (such as “/bin/bash”) and a home directory (such as “/home/slowe”).

After all the user accounts have been configured, then we are ready to perform the additional tasks within Active Directory and on the Linux server that will enable the authentication.

Preparing Active Directory (Each Linux Server)

Here is where it starts getting tricky.  So far, nothing we’ve done has been unusual or terribly difficult.  Things will start getting a bit more complex now.

First off, you’ll need to decide if you want to use TGT validation.  I don’t have the space here to fully describe this, but basically it’s a check that the Kerberos Key Distribution Center (KDC—in this case, an Active Directory domain controller) is not being spoofed.  It’s an added level of security that ensures that all hosts involved are indeed who they say they are, which is one of the core principles of the Kerberos authentication system.

Without TGT Validation

If you don’t care about TGT validation, then ignore this whole section and proceed to “Preparing Each Linux Server”, below.  Once Linux is properly configured for Kerberos authentication and LDAP lookups, it can authenticate against Active Directory with no further action required.  You’ll note that this is in contrast to many of the instructions out there (including my original instructions), which state that you must perform additional steps.  In my experience, the additional steps are only necessary if you want TGT validation, i.e., if you want the Linux server to verify the identity of the Active Directory domain controller handing out the Kerberos tickets.  If you don’t care about that, then you’re ready to proceed with the next step.

With TGT Validation

For each Linux-based server that will be authenticating against Active Directory, follow the steps below.

  1. Create a computer account in Active Directory.  When creating the computer account, be sure to specify that this account may be used by a pre-Windows 2000–based computer.
  2. Use the following command at a command prompt to configure the new computer account:
    ktpass -princ HOST/fqdn@REALM -mapuser DOMAIN\name$
    -crypto DES-CBC-MD5 +DesOnly -pass password -ptype KRB5_NT_SRV_HST
    -out filename

    Of course, you’ll need to substitute the appropriate values for “fqdn” (the fully-qualified domain name of the computer), “REALM” (the DNS name of your Active Directory domain in UPPERCASE), “DOMAIN” (the NetBIOS name of your Active Directory domain), “name$” (the name of the computer account created, with a dollar sign appended at the end), “password” (the password that will be set for the new computer account), and “filename” (the keytab that will be generated and must be copied over to the Linux computer).  Please note (and this is important) that the “HOST/fqdn@REALM” portion is case-sensitive and should be typed as shown above.#160; Of course, if you are repeating this process for multiple servers, please be sure to use a unique filename for each keytab generated using ktpass.exe.  (I use each Linux server’s hostname as the filename.)

If this computer account ever gets deleted from Active Directory, then Active Directory users will be unable to authenticate to Linux systems.  You’ll need to repeat the process—create a new computer account, run ktpass.exe, and copy the keytab over to the Linux server (as described below).

Preparing Each Linux Server

Follow the steps below to configure each Linux server for authentication against Active Directory.

  1. Make sure that the appropriate Kerberos libraries, OpenLDAP, pam_krb5, and nss_ldap are installed.  If they are not installed, install them.
  2. Be sure that time is being properly synchronized between Active Directory and the Linux server in question.  Kerberos requires time synchronization.  Set up NTP if necessary.
  3. Edit the krb5.conf file to look something like this, substituting your actual host names and domain names where appropriate:
    [logging]
     default = FILE:/var/log/krb5libs.log
     kdc = FILE:/var/log/krb5kdc.log
     admin_server = FILE:/var/log/kadmind.log
    
    [libdefaults]
     default_realm = EXAMPLE.COM
     dns_lookup_realm = true
     dns_lookup_kdc = true
    
    #[realms]
    # EXAMPLE.COM = {
    #  kdc = host.example.com:88
    #  admin_server = host.example.com:749
    #  default_domain = example.com
    # }
    
    [domain_realm]
     .example.com = EXAMPLE.COM
     example.com = EXAMPLE.COM
    
    [kdc]
     profile = /var/kerberos/krb5kdc/kdc.conf
    
    [appdefaults]
     pam = {
       debug = false
       ticket_lifetime = 36000
       renew_lifetime = 36000
       forwardable = true
       krb4_convert = false
       validate = true
     }

    Note that the line “validate =” should be set to true if you want TGT validation; otherwise, set it to false.  Note also that we’ve commented out the [realms] section because we are using DNS to locate the KDCs (“dns_lookup_kdc = true”); this requires the presence of the appropriate SRV records in DNS.  In a correctly-functioning Active Directory environment, these records will be present.

  4. Edit the /etc/ldap.conf file to look something like this, substituting the appropriate host names, domain names, account names, and distinguished names (DNs) where appropriate.
    host 10.10.10.10
    base dc=example,dc=com
    uri ldap://server.example.com/
    binddn ldap@example.com
    bindpw adldapbindpw
    scope sub
    ssl no
    pam_filter objectClass=User
    nss_base_passwd dc=example,dc=com?sub
    nss_base_shadow dc=example,dc=com?sub
    nss_base_group dc=example,dc=com?sub
    nss_map_objectclass posixAccount user
    nss_map_objectclass shadowAccount user
    nss_map_objectclass posixGroup group
    nss_map_attribute gecos name
    nss_map_attribute homeDirectory unixHomeDirectory
    nss_map_attribute uniqueMember member
  5. Securely copy the file generated by the ktpass.exe command above to the Linux server.  You can replace the existing /etc/krb5.keytab file if and only if you do not need any of the existing keys stored there.  If you haven’t put any keys in there, then you probably don’t have any and don’t need to worry about using ktutil to merge the new keys (from the file generated by ktpass.exe) with the existing keys.  If, however, you do have existing keys you need to maintain, be sure to use ktutil to merge/append the new keys to the existing keytab.
  6. Configure PAM (this varies according to Linux distributions) to use pam_krb5 for authentication.  Many modern distributions use a stacking mechanism whereby one file can be modified and those changes will applied to all the various PAM-aware services.  For example, in Red Hat-based distributions, the system-auth file is referenced by most other PAM-aware services.  A sample system-auth file that would be found in /etc/pam.d might look something like this:
    #%PAM-1.0
    # This file is auto-generated.
    # User changes will be destroyed the next time authconfig is run.
    auth      required    /lib/security/$ISA/pam_env.so
    auth      sufficient  /lib/security/$ISA/pam_unix.so likeauth nullok
    auth      sufficient  /lib/security/$ISA/pam_krb5.so
    auth      required    /lib/security/$ISA/pam_deny.so
    
    account   sufficient  /lib/security/$ISA/pam_krb5.so
    account   required    /lib/security/$ISA/pam_unix.so
    account   sufficient  /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet
    account   required    /lib/security/$ISA/pam_deny.so
    
    password  requisite   /lib/security/$ISA/pam_cracklib.so retry=3
    password  sufficient  /lib/security/$ISA/pam_unix.so nullok \use_authtok md5 shadow
    password  required    /lib/security/$ISA/pam_deny.so
    
    session   required    /lib/security/$ISA/pam_limits.so
    session   required    /lib/security/$ISA/pam_unix.so

    (Lines have been wrapped above for readability, but should be typed all on a single line.)  Of course, each distribution’s PAM configuration may be different, so be sure to consult the documentation for your particular distribution.  The sample above was taken from CentOS 4.3, with a few modifications.  Remember that in Red Hat-based distributions, such as CentOS, running the authconfig program will overwrite all the changes to /etc/pam.d/system-auth, so be careful.

  7. Edit the /etc/nsswitch.conf file to include “ldap” as a lookup source for passwd, shadow, and groups.

That should be it.  Once you do that, you should be able to use kinit from a Linux shell prompt (for example, “kinit aduser”) and generate a valid Kerberos ticket for the specified Active Directory account.

At this point, any PAM-aware service that is configured to use the stacked system file (such as the system-auth configuration on Red Hat-based distributions) will use Active Directory for authentication.  The SSH daemon is a good one to test.  Note, however, that unless you also add the pam_mkhomedir.so module in the PAM configuration, home directories will have to be created manually (with the correct permissions and ownership set manually as well) for any Active Directory account that may log on to that server.  (I generally recommend the use of pam_mkhomedir.so in this situation.)

Caveats/Limitations/Disclaimers

I haven’t tested this configuration on every possible distribution of Linux.  This configuration was tested on CentOS 4.3 running as a virtual machine under ESX Server 3.0, authenticating against a pair of domain controllers running Windows Server 2003 R2 (which were also VMs).  It should work without major modifications on most other Linux distributions, and with modifications on various other Unix operating systems.  (I plan to test OpenBSD 3.9 and possibly Solaris 10 x86 soon.)

Also, even though the “validate = true” setting in /etc/krb5.conf implies that the Kerberos TGT must be validated, pam_krb5 appears to bypass the TGT validation if the keytab is not present or not readable.  This means that logins will succeed, even if the keytab is not present or not readable.  If the computer account in Active Directory is missing, however, logins will fail.  I know it’s odd; the only possible explanation I can offer is described in a follow-up posting regarding ESX-AD integration.

If anyone finds any errors, discrepancies, or inaccuracies in this article, please let me know and I’ll correct them as soon as possible.

Tags: , , , , , , ,

VMware on Mac OS X

Various sources (this notice on virtualization.info and this notice on MacNN) alerted me this morning to the announcement by VMware of a Mac OS X-based version of VMware Workstation, intended to run on any Intel-based Mac system.

I can’t tell you how long I’ve been waiting for this (like so many others).  I first pined for virtualization on Apple back in February of this year, and I’m thrilled that VMware is now stepping up to the plate to provide a Mac OS X-based version of VMware Workstation.  Here’s hoping they also release Mac OS X-based versions of their remote consoles as well, so that I can manage virtual machines hosted on VMware Server or ESX Server from my Mac as well.

Tags: , , , ,

Assorted Links

I have a variety of links and articles, mostly security related, that aren’t really substantial enough for a full-blown entry, but I wanted to mention them anyway.

UPDATE:  Apparently, the Wi-Fi hijacking of an Apple MacBook was indeed demonstrated yesterday; see this updated article.

Tags: , , , , ,

Disabling AD Replication

Replication is bidirectional, occurring both inbound and outbound.  Each of these directions can be disabled/enabled indepedently of the other using the Repadmin command.  Repadmin is part of the support tools, included on the Windows 2000 and Windows Server 2003 CDs but not installed by default.  (Installing them is highly recommended in all situations.)

To disable outbound replication from a particular DC, use this command:

repadmin /options <DC NAME> +DISABLE_OUTBOUND_REPL

Likewise, to disable inbound replication for a particular DC, use this command:

repadmin /options <DC NAME> +DISABLE_INBOUND_REPL

In these commands, we are adding the “DISABLE_OUTBOUND_REPL” or “DISABLE_INBOUND_REPL” flag to the DC, so that running “repadmin /options” will show that flag as an option on the selected DC.  To re-enable replication, then, we need to remove the flag using one of the two commands:

repadmin /options <DC NAME> -DISABLE_OUTBOUND_REPL
repadmin /options <DC NAME> -DISABLE_INBOUND_REPL

When replication is disabled, warning events 1115 (for disabled outbound replication) or 1113 (for disabled inbound replication) from source NTDS General will be logged in the Directory Service event log during system startup.  As far as I am aware, no events are regularly logged during normal operation to indicate that replication is disabled.  When replication is re-enabled, informational events 1116 (for outbound replication) and 1114 (for inbound replication) are logged.

When replication is disabled, NTDS KCC warning events (typically with event ID 1265) will be logged; the text of the message will provide information on the specific DCs and naming contexts involved, but the useful information is near the end of the event, where the message states that “The destination/source server is currently rejecting replication requests.”  If you see this, make sure that replication is enabled by searching the Directory Service event log for messages indicating that replication has been disabled.

Tags: ,

For example, consider a situation where you may need to compare two different attributes in Active Directory and list those accounts where the two attributes aren’t the same.  One excellent example is the situation where an organization has standardized on UPN (User Principal Name; looks like an RFC 822-compliant e-mail address) logons, and each user’s UPN is supposed to match that user’s e-mail address.  How do you go about finding those accounts where the UPN and primary e-mail address don’t match?

It may be possible to do this with DSQuery, but I couldn’t find any way to make it happen.  After trying for a while, I turned again to Log Parser (download here), Microsoft’s Swiss Army Knife of log parsing and data manipulation utilities.  Log Parser is particularly helpful in this case because it offers a input format specifically for Active Directory, capable of making native Active Directory queries with all the flexibility of Log Parser’s SQL-like functionality.

Here’s a query that does exactly what we just mentioned—finds all accounts where the UPN prefix (the part before the @ symbol) doesn’t match the user name portion of the e-mail address (the part before the @ symbol):

logparser -i:ads -o:csv -stats:off “SELECT cn,
TO_LOWERCASE(SUBSTR(mail,0,LAST_INDEX_OF(mail,'@'))) as mailPrefix,
TO_LOWERCASE(SUBSTR(userPrincipalName,0,LAST_INDEX_OF
(userPrincipalName,'@'))) as uPNPrefix
FROM 'ldap://server.domain.com/cn=Users,dc=domain,dc=com'
WHERE NOT (mailPrefix = uPNPrefix)” -objClass:user >> output.csv

Of course, this is just one example; I’m sure that you can think up many other examples where this kind of complex query functionality would be useful in managing Active Directory.  Why don’t you list some ideas for useful queries in the comments below, and then I’ll post another article with all the appropriate Log Parser commands.

UPDATE:  Another fairly complicated query came to me today:  trying to locate user accounts that aren’t named “Lastname, Firstname.”  The only way I could think to do this was using this Log Parser query:

logparser -i:ads -o:csv -stats:off “SELECT cn FROM 
'ldap://server.domain.com/cn=Users,dc=domain,dc=com' WHERE 
cn NOT LIKE '%,%'” -objClass:user

This will return all users that do not contain a comma in their name, thus finding any accounts not named “Lastname, Firstname.”

Tags: ,

Newer entries »