Linux-AD Integration with Windows Server 2008

In the event that your organization is considering a migration later this year (or next?) to Windows Server 2008 (formerly “Longhorn”), here are some instructions for integrating Linux login requests against Active Directory on Windows Server 2008.  These instructions are based on Linux-AD Integration, Version 4 and utilize Kerberos, LDAP, and Samba.

When this process is complete, AD users can be enabled for use on Linux systems on the network and login to those Linux systems using the same username and password as throughout the rest of Active Directory.

If you are looking for information on using Linux with a previous version of Windows before Windows Server 2008, please refer back to my AD integration index and select the appropriate article.  The only significant changes in the process involve the mapping of the LDAP attributes; otherwise, the procedure is very similar between the two versions of Windows.

Preparing Active Directory (One-Time)

The process of installing and configuring Windows Server 2008 is beyond the scope of this article (although I may touch on that in the near future in a separate article).  Therefore, I won’t provide detailed instructions on how to perform some of these tasks, but instead provide a high-level overview.

Enable Editing/Display of UNIX Attributes

In order to store UNIX attributes in Active Directory, the schema must be extended.  To extend the schema, first install Active Directory (add the Active Directory Domain Services role to an installed server, then use the Active Directory Installation Wizard to setup Active Directory) and then add the “Identity Management for UNIX” role service (this can be done in Server Manager).

Once that role service has been installed, then the AD schema now includes a partially RFC 2307-compliant set of UNIX attributes, such as UID, UID number, GID number, login shell, etc.  (Note that it may be that these attributes are already included in the schema for Windows Server 2008; I did not check the schema before installing the Identity Management for UNIX role service.  With Windows Server 2003 R2, the schema was present at the time of installation, but the attributes were not visible until installing the UNIX identity services.)

At this point a new tab, labeled “UNIX Attributes,” will appear in the properties dialog box for users and groups in Active Directory.  You’ll use this tab to edit the UNIX-specific attributes that are required for logins to Linux-based systems.

Create an LDAP Bind Account

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.  This helps minimize any potential security risks as a result of this account.  Just be sure that you know the account’s user principal name (UPN) and password.

Prepare 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.

After all the user accounts have been configured, then we are ready to configure Active Directory objects for each of the Linux server(s) that we’ll be integrating with AD.

Prepare Active Directory (Each Server)

Prior to using Samba to join Linux computers to Active Directory and generate a keytab automatically, we had to use the ktpass.exe utility on Windows to generate a keytab.  Due to some current Samba-Windows Server 2008 interoperability issues, we can’t use Samba.  That means we’ll be back to using ktpass.exe to map service principals onto accounts in Active Directory.  Unfortunately, you’ll need to first disable User Account Control (UAC) on your server, since UAC interferes with ktpass.exe.  (Nice, huh?)

Once you’ve disabled UAC (and rebooted your server), then you can map the service principal names (SPNs) using the following steps:

  1. Create a computer account (or a user account; either will work) with the name of the Linux server.
  2. Use the following command to map the needed SPN onto this account (backslashes indicate line continuation):
    ktpass.exe -princ HOST/server.fqdn@REALM.COM \
    -mapuser DOMAIN\AccountName$ -crypto all \
    -pass Password123 -ptype KRB5_NT_PRINCIPAL \
    -out filename.keytab
  3. Copy this file to the Linux server (using SCP or SFTP is a good option) and merge it with the existing keytab (if it exists) using ktutil.  If there is no existing keytab, simply copy the file to /etc/krb5.keytab and you should be good to go.

Now that Active Directory has computer objects (and, more importantly, SPNs) for the Linux servers and the AD users have been enabled for UNIX (by populating the UNIX attributes), we’re ready to start configuring the Linux server(s) directly.

Prepare Each Linux Server

Follow the steps below to configure the Linux server for authentication against Active Directory.  (Note that this configuration was tested on a system running CentOS—a variation of Red Hat Enterprise Linux—version 4.3.)

  1. Edit the /etc/hosts file and ensure that the server’s fully-qualified domain name is listed first after its IP address.
  2. Make sure that the appropriate Kerberos libraries, OpenLDAP, pam_krb5, and nss_ldap are installed.  If they are not installed, install them.
  3. Be sure that time is being properly synchronized between Active Directory and the Linux server in question.  Kerberos requires time synchronization.  Configure the NTP daemon if necessary.
  4. Edit the /etc/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
    }
  5. 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.  (Please note that the nss_base_group line should not be broken across two lines when you edit it; it has been wrapped here for readability.)
    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
    nss_base_passwd dc=example,dc=com?sub
    nss_base_shadow dc=example,dc=com?sub
    nss_base_group dc=mydomain,dc=com?sub?
    &(objectCategory=group)(gidnumber=*)
    nss_map_objectclass posixAccount user
    nss_map_objectclass shadowAccount user
    nss_map_objectclass posixGroup group
    nss_map_attribute gecos cn
    nss_map_attribute homeDirectory unixHomeDirectory
    nss_map_attribute uniqueMember member
  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.  Here’s a properly edited /etc/pam.d/system-auth file taken from CentOS 4.4 (some lines have been wrapped for readability; do not wrap them when editing the file):
    #%PAM-1.0
    # This file is auto-generated.
    # User changes will be destroyed the next time
    # authconfig is run.
    auth required /lib/security/pam_env.so
    auth sufficient /lib/security/pam_unix.so
       likeauth nullok
    auth sufficient /lib/security/pam_krb5.so
    auth required /lib/security/pam_deny.so
     
    account sufficient /lib/security/pam_unix.so
    account sufficient /lib/security/pam_krb5.so
    account sufficient /lib/security/pam_succeed_if.so
       uid < 100 quiet
    account required /lib/security/pam_deny.so
     
    password requisite /lib/security/pam_cracklib.so
       retry=3
    password sufficient /lib/security/pam_unix.so
       nullok use_authtok md5 shadow
    password required /lib/security/pam_deny.so
     
    session required /lib/security/pam_limits.so
    session required /lib/security/pam_unix.so
  7. Edit the /etc/nsswitch.conf file to include “ldap” as a lookup source for passwd, shadow, and groups.

At this point we are now ready to test our configuration and, if successful, to perform the final step:  to join the Linux server to Active Directory for authentication.

Test the Configuration

To test the Kerberos authentication, use the “kinit” command, as in “kinit <AD username>@<AD domain DNS name>”; this should return no errors.  A “klist” at that point should then show that you have retrieved a TGT (ticket granting ticket) from the AD domain controller.  If this fails, go back and troubleshoot the Kerberos configuration.  In particular, if you are seeing references to failed TGT validation, check to make sure that both your Linux servers and AD domain controllers have reverse lookup (PTR) records in DNS and that the Linux server’s /etc/hosts file listed the FQDN of the server first instead of just the nodename.

<aside>Some readers and some other articles have suggested the use of the AD domain DNS name in the /etc/krb5.conf file instead of an AD domain controller specifically; I recommend against this.  First, I believe it may contribute to TGT validation errors; second, it is possible to list multiple KDCs (AD DCs) in the configuration.  Since the only major reason to use the AD domain DNS name instead of the DNS name of one or more DCs would be fault tolerance, then it doesn’t really gain anything.</aside>

To test the LDAP lookups, use the “getent” command, as in “getent passwd <AD username>”; this should return a listing of the account information from Active Directory.  If this does not work, users will not be able to login, even if Kerberos is working fine.  If you run into errors or failures here, go back and double-check the LDAP configuration.  One common source of errors is the name of the LDAP bind account, so be sure that is correct.

At this point, SSH logins to the Linux system using an account present in Active Directory (one which has had its UNIX attributes specified properly) should be successful.  This will be true as long as you used the ktpass.exe command earlier to map the SPN onto the computer object in Active Directory.  Even if you didn’t copy the keytab over to the Linux server, logins will work.  Why?  Because the PAM Kerberos configuration, by default, does not require a client keytab, and does not attempt to validate the tickets granted by the TGT.  This means that as long as the SPN(s) are mapped to the accounts in AD, the keytab is not necessarily required.

(Note, however, that not using a keytab and/or not requiring a keytab does leave the Linux server open to potentially spoofed Kerberos tickets from a fake KDC.  In addition, “native” Kerberos authentication—i.e., using a Kerberos ticket to authenticate instead of typing in a password—won’t work without a keytab.)

Deal with Home Directories

Unlike Windows systems, home directories are required on Linux-based systems.  As a result, we must provide home directories for each AD user that will log in to a Linux-based system.  We basically have three options here:

  • Manually create home directories and set ownership/permissions properly before users will be able to log in.
  • Use the pam_mkhomedir.so PAM module to automatically create local home directories “on the fly” as users log in.  To do this, you would add an entry for pam_mkhomedir.so in the session portion of the PAM configuration file.
  • Use the automounter to automatically mount home directories from a network server.  This process is fairly complicated (too involved to include the information here), so I’ll refer you to this article on using NFS and automounts for home directories.  This has the added benefit of providing a foundation for unified home directories across both Windows and Linux systems.

Once you’ve settled on and implemented a system for dealing with home directories, you are finished!  UNIX-enabled users in Active Directory can now login to Linux-based systems with their Active Directory username and password.

What’s not addressed in this article?  Password management.  In this configuration, users will most likely not be able to change their password from the Linux servers and have that change properly reflected in Active Directory.  In addition, “native” Kerberos authentication using Kerberos tickets won’t work unless the keytab is present.  In my testing, I ran into a number of issues with the keytab and TGT validation, but I’m not sure if those are errors in my process or the result of the beta status of Windows Server 2008.

I welcome your corrections, additions, or suggestions in the comments below.

Tags: , , , , , , ,

Hi Slowe,

It seems not work with Red Hat Enterprise Linux—version 5.1.

Kinit and ldapsearch works fine, but “getent passwd user@domain.com” returns nothing.

The “binddn” seems ok in the ldap.conf as the account was logged in successful when run the “getent … ”

The AD is a Windows Server 2008 RC1.
Is it win 2008 or RHEL 5.1 issue?

Regards,

JR

Scott,

Do you know of anybody that has been able to use openldap with a kerberos sasl bind to AD? Using simple bind/tls has some security issues like the password being in clear text in ldap.conf and not being able to change the ldap proxy password without visiting the unix servers and editing ldap.conf.

Steve,

MS had some documentation about achieving an end-state where LDAP binds were handled via Kerberos, but I’ve never been able to make it work.

Scott,

Wondering if you may be able to help me here because racking my brain doesn’t seem to be working.

My config works even though I skipped the step of creating an AD account and creating a keytab file, associating it w/ the account, and placing it at /etc/krb5.keytab. Any idea why this might be happening? Is it possible there’s a security hole in this config?

Thanks for the help and the blog.

Scott,

Disregard my last post, I just realized it’s because I had TGT validation turned off. Thanks.

I was able to use the your v4 guide w/o using ktpass on my windows 2008 domain…

my 2008 domain controller is upgraded form a 2003 domain controller. so maybe i’m not running into the same issues. (or maybe i’m not aware of the issues I will run into)

hey, thank you very much for your HOWTO.

im on testing it atm (well, im on setup both systems in vmware) and wanna try to authenticate AD groups on SAMBA shares.

AD domain.test (The Master with all users) /
Office (LINUX Server Samba) office.domain.test where users should be able to Login with a home dir. And another Linux Server (samba.domain.test) where no users should login local. there are only samba shares on it; and those shares should be authenticate against the AD groups @domain.test.

any suggestions for me? :)
thanks in advance
greets
Angelo

Scott,

I installed a new server 2008 domain controler in a new forest for testing.
I installed Service for NFS…
but I cannot find a unix tab in the MMC for user account properties.
I want to do the unix identity management with AD…but I cannot find the tab, perhaps I am missing a snapin.
I do find a UID property in the ‘attribute editor’ tab.
Could you tell me how to add the unix attributes tab ?

Ralph,

There’s a role feature called UNIX Identity Management (I think). Add that role feature and it should take care of the tab for you. You’ll want to add that role feature to the DC, and then the UNIX Attributes tab will be visible on the DC.

Hope this helps!

Scott,

At least on my enterprize 2008 server, there is not a role feature called this. There is a property on the ’services for NFS’ mmc that allows you to either use a ‘unix identity server’ or active directory. The docs lead me to beleive this server (identity) is not part of server 2008.
I configured the NFS to use AD lookup… but the tabs are not there. Although the schema seems to have the data elements, as you can see the names with the attribute editor tab.
All instance that I looked at, where the tab apeared…were on older AD servers that had been upgraded.

Ralph,

In Server Manager, if you expand Roles, then select Active Directory Domain Services, then look under the Role Services section, you’ll see an area where you can add Role Services. In the Add Role Services wizard, you should see “Identity Management for UNIX”. You’ll need to at least install Server for Network Information Services and the Administration Tools. That should take care of adding the UNIX Attributes tab for you. This will need to be repeated on every DC where you’d like the tab to appear. I’ve not yet attempted to make this tab appear on a remote system managing Win2K8, so I’m not sure about the procedure for that.

Good luck!

Scott,

Thanks, that worked. I had kept looking at the File Services and not Directory services.

Ralph

Hi,

I am trying to follow the HOWTO on a Fedora . I get to a point that kerberos works, kinit returns no error while klist shows the key. I also tried getent passwd and group. Both worked and showed my AD users and groups. However, when I try to logon with SSH using my AD user, it asked for the password and then never gets to the prompt. I wonder what may be wrong in my set up.

Peng

Peng,

Check the logs on your Linux system. There are bound to be messages letting you know what’s going on.

Scott,

I found the problem was in LDAP. Kerberos was able to authenticate a AD user with the AD password when there is a user in NIS with the same name. It seems like when I use getent passwd to test the LDAP, sometimes it takes a long time for the command to return to prompt. Do you have any idea on this?

Peng

Peng,

Depending upon the LDAP schema mapping used, you may want/need to create an index on the UID attribute, which is not indexed by default. That usually makes quite a difference in performance.

Hey Guys, I was wondering If I can get a little advice.

Situation is as follows. We have had for quite a while, a one way trust with two domains. I have integrated two Ubuntu servers into AD using Samba/Winbind and they have been running for the best part of 2 years without any troubles. Because we have two domains and it’s only a one way trust I actually configured two servers. (One homed to each domain). They only run printing services and accounting services (Pykota) and as such do not require users to log in locally. It only needs to authenticate users against AD for Samba.

Winbind has worked fine for some time. However, we are ditching this trust. We are moving to child domains. We will end up with one root domain and three child domains. To make it even more difficult the new child domain controllers will be Server 2008 rather than 2003.

I have been playing for a few days attempting to build one server in a vm that communicates using either Samba/Winbind or LDAP/Kerberos, supports child domains and authenticates against a windows 2003 server with a 2008 schema update applied, or simply just the 2008 server.

Winbind struggles, while it recognises both domains, and indicates a trust exists. It cannot detect AD installed on the windows 2008 server, and therefore completely ignores it. It happily authenticates against the root domain. I must have tried about 20 different configurations of Samba, setting every Winbind option differently each time. I just can’t get it to recognise the child domain.

Hence I moved onto LDAP. Kerberos works perfectly, I can search the AD directory using ldapsearch(), however, I can never get any results using getent passwd even though I have tried various configurations for LDAP. I was going to post my config files but realised this post was long enough all ready.

I would just like to ask if anyone knows which solution is best for supporting multiple domains and possible a combination of Windows Server 2008 servers and 2003. (Although as they both run the same schema they shouldn’t cause to many problems) Can I specify multiple servers in LDAP? Or would I have to get Winbind to work correctly?

Cheers!

Just wanted to add that there is no need for doing schema updates - RfC2307 is implemented by server 2008 by default.

hi Scott!

When testing kerberos authentication with ADDS (server 2008) from RHEL5 I found that the keytab file is only relevant for ssh-logins when you configure your pam.d/sshd with “pam_krb5.so validate”! If you do not enter the validate-option PAM completely ignores the keytab file, no matter if you entered the verify_ap_req_nofail in the libdefaults-section of krb5.conf. It not only lets you in without a keytab file, it even lets you in with a wrong keytab file! I used RHEL5 with pam_krb5-2.2.14-1and krb5-libs-1.6.1-25.el5

FYI GoGrid is offering virtual Servers. They have a free $100 trial when you use the promo code ‘GGED’. They are one of the first to offer 2008. EC2 doesn’t even offer windows. http://www.gogrid.com

Scott,

I can confirm that with Samba 3.2.3 (and this should be true for the entire 3.2.x release tree) joining a pure 2008 AD domain works again using ‘net ads join’

This was tested under CentOS 5.2 on an x86_64 box. It’s not easy to find prebuilt RPMs, but I’m using the ones at ftp://ftp.sernet.de/pub/samba/experimental/rhel/5/x86_64/ and they work great. Unfortunately, I first spent a ton of time trying to build my own RPMs from the specfile provided with the Samba 3.2 tarbll, and this fails in various ways, so thar be dragons…

Alex,

Thanks for the information! I’m sure that will prove quite useful to many readers.

Scott,

Thank you for your very informative howto. I have configured my AD DC as specified on this page, and also the linux server I am trying to join to the domain. However, when I run getent passwd I only see the local users.

After I run getent I see the following sort of entries in /var/log/auth.log aswell:

Nov 7 04:35:57 s-09-chaos getent: nss_ldap: failed to bind to LDAP server ldap://s-02-zeus.internal.vesuviustechnologies.com/: Invalid credentials
Nov 7 04:35:57 s-09-chaos getent: nss_ldap: reconnecting to LDAP server…
Nov 7 04:35:57 s-09-chaos getent: nss_ldap: failed to bind to LDAP server ldap://s-02-zeus.internal.vesuviustechnologies.com/: Invalid credentials
Nov 7 04:35:57 s-09-chaos getent: nss_ldap: reconnecting to LDAP server (sleeping 1 seconds)…
Nov 7 04:35:58 s-09-chaos getent: nss_ldap: failed to bind to LDAP server ldap://s-02-zeus.internal.vesuviustechnologies.com/: Invalid credentials
Nov 7 04:35:58 s-09-chaos getent: nss_ldap: could not search LDAP server - Server is unavailable

Furthermore, here’s what I get when I run ldapsearch using the bind account (password removed):

s-09-chaos:~# ldapsearch -D UnixLdapBind@INTERNAL.VESUVIUSTECHNOLOGIES.COM -w
SASL/EXTERNAL authentication started
ldap_sasl_interactive_bind_s: Unknown authentication method (-6)
additional info: SASL(-4): no mechanism available:

And finally heres the really interesting bit — when I add the -x (use simple authentication) to the same ldapsearch command, it works fine and I get results back.

Any help here would be very much appreciated.

Thanks!
Joe Crivello

Hi Scott,

a possible helpfull addition for others. Got me tearing my hair out for some time…

We have recently upgraded from W2K3 to W2K8 and are running nss_ldap 264.
Kinit works fine, and ldapsearch too.
However, a ‘getent passwd’ or ‘getent group’ only shows the groups and users defined before the upgrade.
If I remove a user from the Active Directory, then it disappears from the output of ‘getent passwd’. But when I add a new user (with UID filled in etc), it does not appear in the list.

Logging shows nothing special.

Using a dump of ldapsearch and debugging of LDAP packages from ldap.conf, I’ve found that:

* The new accounts are included in the dump from nss_ldap, as well as the old accounts.
* Additionally, the old accounts have different fields (those used for W2K3).

I’ve changed the mapping to

nss_map_attribute uid sAMAccountName
nss_map_attribute uidNumber uidNumber
nss_map_attribute gidNumber gidNumber
nss_map_attribute cn sAMAccountName
nss_map_attribute uniqueMember member
nss_map_attribute userPassword msSFUPassword
nss_map_attribute homeDirectory unixHomeDirectory
nss_map_attribute loginShell loginShell
nss_map_attribute gecos cn
nss_map_objectclass posixGroup Group
nss_map_attribute shadowLastChange pwdLastSet

And now it is working again. The old mappings were based upon msSFU30* names.

Hi Scott,
I have just checked my AD before starting to play with linux AD integration. And it seems that I don’t need to install any of the subroles of the “Identity Management for UNIX” role because the “Server for NIS Tools” from the RSAT (Remote Server Administration Tools) feature makes the “UNIX Attributes” tab visible.

Thanks for the post, I was able to use this to get my RHEL5.1 working with my test domain. I do have one question, is it possible to set login restrictions with this setup? Example: users of GroupA can login to Server1, and users of GroupB can login to server2 etc?

Right now it seems as though anyone with an account in AD can login to any Linux host configured for AD Authentication.