Richard York

Web Developer, Author, and Artist

Linux Active Directory Integration

Linux Active Directory Integration

September 6, 2007 by Richard

Recently I undertook the very daunting task of integrating a Red Hat Enterprise Linux 5 server in a Windows Server 2003 RC2 Active Directory environment.

As enterprise networks go, single sign-on between operating systems from all walks of life is sort-of a holy grail of achievement, and with good reason, it was by no means obvious or easy to make it happen! But with some determination, lots of Google searching, trial and error, and a desk to bang your head against, it is ultimately possible.

In Linux-land, those nifty GUI tools for doing this sort of thing are completely worthless. On the Windows side Microsoft isn't exactly the biggest help either. The web and various man pages are your only friends. I spent the better part of two weeks searching the web, reading documentation, ant attempting to follow in the footsteps of those that came before me.

You see, I wanted to make AD login happen on a Linux server, but I did not want to become an expert in Kerberos, LDAP, Windows Active Directory, or networking in general. Unfortunately, you're much better off if you are an expert. Linux does not forgive the weak or the naive. And AD login on Linux doesn't look like it will ever be as easy as integrating a Windows client on a Windows domain. That is to say, set your domain, enter the Administrator password, and you're good to go. No, no, no, that's far too easy. OK, enough whining, let's get on with it.

Here are the goals I set out with:

  • I want to have file shares that Windows clients can log into without having to login. Their credentials should be passed automatically via Active Directory, as is the case when a Windows client accesses a share on a Windows server.
  • Network users should be able to log into a Linux client using their Windows Active Directory login.
  • Windows Active Directory users and security groups should be exposed in Linux automatically. Linux chown and chgrp operations should work on domain users and groups the same way that they work with native Linux users and groups.
  • Linux attributes like GID, UID, etc, as assigned to domain users should be the same from server to server.

That's the synopsis, currently my integration of Linux in a Windows AD environment fulfills all of those requirements but the last, and with some further research and experimentation, I believe I can fulfill all of those requirements. Now a word of warning.

DISCLAIMER: I am not an Active Directory expert. Neither am I an expert on the various technologies that Linux uses to perform authentication. There may be flaws in my configurations. I MAY NOT BE ABLE TO ASSIST YOU WITH YOUR PARTICULAR CONFIGURATION. I CANNOT GUARANTEE SECURITY. PROCEED AT YOUR OWN RISK.

The following configuration is specific to my company's particular implementation of a Windows Server 2003 (RC2) domain running Active Directory. Your results may vary, God help you in your quest.

So, without further delay, here are the configuration instructions.

In order to configure Linux for AD authentication, you must configure PAM (Pluggable Authentication Modules), nsswitch (Name Service Switch), LDAP, Kerberos, Samba, and Winbind. I present two different methods of AD authentication simultaneously, that is to say authentication via LDAP, and authentication via Winbind. These instructions are based on personal experience with the help of the following online resources/blogs.

Again, my configuration is specific to Red Hat Enterprise Linux 5, certain bits may need to be tweaked for your particular distribution of Linux.

Configure LDAP, /etc/ldap.conf

First up is LDAP. Make the following configuration changes to /etc/ldap.conf

bind_policy soft host 192.168.1.10 base dc=example,dc=com uri ldap://dc.example.com/ binddn adquery@EXAMPLE.COM bindpw adquerypassword scope sub ssl no referrals no nss_base_passwd dc=example,dc=com?sub nss_base_shadow dc=example,dc=com?sub nss_base_group dc=example,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

In the LDAP configuration, the configuration is set for a domain called example.com. The domain controller has the host name dc.example.com. The domain controller is located at the IP address 192.168.1.10.

If your domain is called something.example.com, and your domain controller is called dc.something.example.com you'd change the configuration like so where only the domain is referenced: dc=something,dc=example,dc=com

Active Directory also does not allow anonymous queries. Each query made must be associated with a valid domain user. Therefore, you must create a new user in Active Directory for this purpose. In the example configuration, this user is adquery@EXAMPLE.COM, and the user's password is adquerypassword. This user should have no privileges, in fact you should make this user a member of Domain Guests.

The remainder of the file has to do with mapping Microsoft's Services for Unix (SFU) snapin to Linux user attributes. My configuration ultimately does not utilize SFU at all, though it could with some experimentation.

The configurations I present allow two different ways of authenticating a domain user, via LDAP and Kerberos, or via Winbind. The former configuration does not allow Linux SMB shares to mount on Windows clients, while the latter does, at least in this particular Windows AD domain.

Configure NSSwitch, /etc/nsswitch.conf

# An example Name Service Switch config file. This file should be # sorted with the most-used services at the beginning. # # The entry '[NOTFOUND=return]' means that the search for an # entry should stop if the search in the previous entry turned # up nothing. Note that if the search failed due to some other reason # (like no NIS server responding) then the search continues with the # next entry. # # Legal entries are: # # nisplus or nis+ Use NIS+ (NIS version 3) # nis or yp Use NIS (NIS version 2), also called YP # dns Use DNS (Domain Name Service) # files Use the local files # db Use the local database (.db) files # compat Use NIS on compat mode # hesiod Use Hesiod for user lookups # [NOTFOUND=return] Stop searching if not found so far # # To use db, put the "db" in front of "files" for entries you want to be # looked up first in the databases # # Example: #passwd: db files nisplus nis #shadow: db files nisplus nis #group: db files nisplus nis passwd: files winbind shadow: files group: files winbind #hosts: db files nisplus nis dns hosts: files dns wins # Example - obey only what nisplus tells us... #services: nisplus [NOTFOUND=return] files #networks: nisplus [NOTFOUND=return] files #protocols: nisplus [NOTFOUND=return] files #rpc: nisplus [NOTFOUND=return] files #ethers: nisplus [NOTFOUND=return] files #netmasks: nisplus [NOTFOUND=return] files bootparams: files ethers: files netmasks: files networks: files protocols: files rpc: files services: files netgroup: files publickey: nisplus automount: files aliases: files nisplus

In the preceding block you see the standard nsswitch.conf file that's shipping with Red Hat (and presumably Fedora and CentOS). This is the only important modification to make:

passwd: files winbind shadow: files group: files winbind

You're telling Linux to look at winbind as a source of authentication information, in addition to the Linux files /etc/passwd and /etc/group.

I could use the following configuration for LDAP, instead of Winbind. If only AD authentication is required (but no file shares), that would be the way to go. If going that method, you'll need that Microsoft Services for Unix snapin to be installed, and you'll have to configure the UID, GID, Home Directory, and Login Shell attributes for each domain user logging into Linux.

passwd: files ldap shadow: files group: files ldap

Configure PAM, /etc/pam.d/system-auth-ac

#%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 auth sufficient /lib/security/$ISA/pam_winbind.so auth sufficient /lib/security/$ISA/pam_unix.so nullok_secure use_first_pass auth required /lib/security/$ISA/pam_deny.so #account sufficient /lib/security/$ISA/pam_unix.so #account sufficient /lib/security/$ISA/pam_krb5.so #account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet #account required /lib/security/$ISA/pam_deny.so account sufficient /lib/security/$ISA/pam_winbind.so account required /lib/security/$ISA/pam_unix.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_mkhomedir.so skel=/etc/skel umask=0077 session required /lib/security/$ISA/pam_limits.so session required /lib/security/$ISA/pam_unix.so

PAM is configured to use winbind for authentication in this example, if going the LDAP route, remove the "auth" and "account" blocks, and uncomment the corresponding "auth" and "account" lines containing references to krb5.

Configure Hosts, /etc/hosts

# Do not remove the following line, or various programs # that require network functionality will fail. 127.0.0.1 NETBIOS.EXAMPLE.COM NETBIOS localhost 192.168.1.10 DC.EXAMPLE.COM DC

In the hosts configuration, you're doing two things. One, you're setting the Fully-Qualified Domain Name (FQDN) of the server or workstation, and two, you're hard-coding a DNS entry for the location of the domain controller. For good measure.

Configure Kerberos, /etc/krb5.conf

[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 = dc.example.com admin_server = dc.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 }

WARNING: The case of the domain names in krb5.conf is important. You will fail if this is not configured correctly.

At this point, you should be able to do a kerberos authentication. At the command line, cross your fingers and type the following:

# kinit user@EXAMPLE.COM

The above command obtains a new kerberos ticket. You do not have to be joined to the domain to obtain a kerberos ticket. Joining to the domain is necessary for mutual authentication, and is required for Linux SMB shares. Again, the case is important. The domain must be typed in all uppercase, or this command will fail. See if you have obtained a kerberos ticket by running the following command:

# klist

You should see a valid kerberos ticket.

Don't forget that the clock of the Linux client must be within the range allowed by the Windows server. Typically this is a skew of plus or minus five minutes. The best way to handle this is to set your clock to automatically synchronize to an NTP server, such as time.redhat.com.

Configure Samba and Winbind, /etc/samba/smb.conf

If they are running, stop the smb and winbind services.

# /sbin/service smb stop # /sbin/service winbind stop

Now, configure /etc/samba/smb.conf.

[global] workgroup = EXAMPLE realm = EXAMPLE.COM netbios name = NETBIOS server string = security = ads use kerberos keytab = true hosts allow = 192.168. 127. 10. load printers = no log file = /var/log/samba/%m.log client use spnego = yes max log size = 50 log level = 1 password server = DC.EXAMPLE.COM idmap uid = 10000 - 20000 idmap gid = 10000 - 20000 winbind enum users = yes winbind enum groups = yes winbind cache time = 10 winbind nested groups = yes ;winbind nss info = template sfu winbind use default domain = no wins server = 192.168.1.15 192.168.1.16 template homedir = /home/%U template shell = /bin/bash ;idmap backend = idmap_ad dns proxy = no domain master = no preferred master = no [www] comment = www on NETBIOS path = /home/www valid users = @EXAMPLEweb force user = www force group = EXAMPLEweb public = no writable = yes printable = no

Although I haven't tested it yet, I believe it is possible to use both winbind and Windows Services for Unix to generate Unix account attributes, UID, GID, login shell, and home directory. man smb.conf leads me to believe this is possible, but more tinkering is required. Additionally, smb.conf can be configured to store the winbind-generated attributes in an LDAP container, which is useful for synchronizing these attributes among multiple Linux clients.

Test the samba configuration.

# testparm /etc/samba/smb.conf

With regards to share definitions, group membership can be tested as criteria

valid users = @EXAMPLEweb

The above says that anyone in the group EXAMPLEweb is allowed access to the share.

Spaces in group names must be accounted for specially, just enclose the name in quotes.

valid users = @"EXAMPLEgroup name"

Now make sure that winbind and samba are set to start at boot, and that samba starts before winbind. Do this from the webmin console or the services console.

Now, start Winbind and Samba services, samba sbould be started first.

# /sbin/service smb start # /sbin/service winbind start

Join the Windows Domain

Obtain a kerberos ticket for the domain Administrator

# kinit Administrator@EXAMPLE.COM

Verify that you have a ticket.

# klist

Join the workstation to the domain.

# net ads join

Alternatively, you can also join using the following command, which supersedes the need to pull a kerberos ticket for the domain Administrator.

# net ads join -U Administrator

As I explained previously in the configuration for LDAP, Windows Server 2003 does not allow anonymous queries, so you'll have to assign winbind a domain user, again this domain user does not need any privileges, in fact it's better if it is a member of domain guests.

# wbinfo --set-auth-user adquery%adquerypassword

The modulus separates the username and password, for a more complex password that may have characters that have special meaning in the BASH terminal, enclose the password in single (or double) quotes.

# wbinfo --set-auth-user adquery%'adquerypassword'

In Active Directory, the user lookup should be a member of Domain Guests. Verify that you have set the user with the following

# wbinfo --get-auth-user

The above should print the username and password.

Verify that you are joined by testing the join

# wbinfo -t # net ads testjoin

Now, test that you have domain users and groups available.

# wbinfo -u

The above should print every domain user as EXAMPLEuser.

# wbinfo -g

The above should print every domain group as EXAMPLEgroup.

Test that you have merged domain users and local users with the following.

# getent passwd

The same for groups

# getent group

Domain users should be appended to the results of each of those commands.

Test a login with a domain user account.

# ssh -l EXAMPLEuser localhost

If the above is successful, you should see "Directory created for user", and have a login by SSH.

Operations like chown and chgrp should now work with domain users. At the command line, and in most other operations, any user or group name containing spaces must be enclosed in quotations. Additionally, the backslash character must be escaped like you see above in the SSH login.

Troubleshooting

If you are not able to login via a domain user, or if getent passwd / getent group does not return domain users, it may be necessary to clear the winbind cache.

# /sbin/service smb stop # /sbin/service winbind stop

Delete the winbind cache.

# rm -f /var/cache/samba/winbindd_idmap.tdb # /sbin/service smb start # /sbin/service winbind start

For debugging, change the log level in smb.conf to 10, and look for the log for the client you are attempting to connect with in /var/log/samba. Logs are kept by netbios name and IP address.

Before attempting to connect to a Linux SMB share from a Window client, it may be necessary to logout and login on the client. It may also be necessary to wait a little time for propagation.

You may also find that the testparm /etc/samba/smb.conf command complains about the winbind separator. It's supposed to be a backslash by default. If this is a problem for you, you may want to change the separator to a plus sign instead. That change might look like this:

winbind enum users = yes winbind enum groups = yes winbind cache time = 10 winbind nested groups = yes winbind separator = +

Other Useful Commands

# net ads changetrustpw

The above changes the machine's kerberos password, and updates the samba-maintained Kerberos keytab. This hangs when I do it, so CTRL + C to cancel out of it.

Once done, you have logout and login to any machines you're using to test.

Test the join.

# net ads testjoin

Leave the domain.

# net ads leave

Print out the workgroup of the kerberos realm.

# net ads workgroup

Print out the workgroup of the kerberos realm.

Cleanup, before logging off the server run the following command:

# kdestroy

This will remove any active kerberos tickets, including any obtained for the domain Administrator.

The domain Administrator can be given root access to the Linux server by editing the /etc/sudoers file.

# visudo -f /etc/sudoers

Make the following modification around the "root" line.

root ALL=(ALL) ALL %Domain_Admins All=(ALL)ALL

I have not yet tested granting the domain administrator root privileges via sudo, so I'm not certain if that works.

Comments

  • March 27, 2009 poker on tv says:

    In Linux-land, those nifty GUI tools for doing this sort of thing are completely worthless. On the Windows side Microsoft isn't exactly the biggest help either. The web and various man pages are your only friends. AD loin on Linux doesn't look like it will ever be as easy as integrating a Windows client on a Windows domain.i found this informative and interesting blog so i think so its very useful and knowledge able.it is Very good info.i would like to thank you for the efforts you have made in writing this article.
  • June 3, 2009 Nancy Mathew says:

    Great information put together. Well done. I have a question. Have you gone to the extent of file security for AD users and groups? Not samba share but group level security to restrict users on the linux server itself.
  • September 27, 2009 oes tsetnoc says:

    Hi, Just like to tell you that this piece of info is one quick to the point, no nonsense, workable and effective way to have directories shared in Linux as fast as possible. It worked for me and thank you for the effort. Keep up the good work.
  • December 22, 2009 athomm says:

    this was a great article, and did the trick. we are not sure how to handle security though with the ad accounts. any user at this point can login, and we do not want that. any suggestions?
  • December 23, 2009 Walter Kalata says:

    athomm, if you stick to winbind auth in pam, you can use the "require_membership_of" option of pam_winbind.so in /etc/pam.d/system-auth to restrict authentication to specific domain users or groups. (check out man pam_winbind) If you don't want any winbind users to log on to a local shell, then it might be simpler to change your 'template shell' in the global section to /bin/false or similar. (check out man smb.conf)
  • January 6, 2010 Pete J says:

    It's a very good article and I have recently done this setup and have winbind authentication working. I have a question: In terms of granting access to files on the Linux side, Is it possible to to have an AD user be assigned to more than one group and have it be effective in Linux? In AD a user can only belong to a single primary group. It would be useful if a user could belong to multiple groups on the Linux side for settings ACLs. - Pete
  • July 14, 2010 Jorge Fernandez says:

    Save your self some time and use Likewise-open it has a GUI and it works like a charm
  • March 23, 2011 Peter Wright says:

    To give Domain Admins sudo rights the line you need to add to /etc/sudoers is: %Domain Admins ALL=(ALL) ALL
  • November 14, 2011 Pablo Salaberri says:

    Work in part...now my root user is unable to enter the server :( Ideas?
  • November 14, 2011 Richard York says:

    Not "works in part". Pretty bold thing to say without any proof that you haven't screwed up somewhere. If you aren't able to login I would try any one of the following:
    1. Boot from another Linux partition.
    2. Boot into recovery mode.
    3. Hook the HD up to another Linux/Unix computer.
    4. Boot from a DVD or CD containing an OS disk image.
    Any of those would allow to directly access the file system, negating the need for your own root account to function. Good luck.

There are no comments posted at this time.

Leave a Comment

Simple HTML is allowed: <code>, <b>, <i>, <u>, <var>, <strong>, <em>, <blockquote>, <ul>, <ol>, <li>, <p> (no attributes). All spacing and line breaks in your comment will be preserved.

* All comments are moderated and are subject to approval.
Your comment will appear once it has been approved.
Posting multiple times will not expedite the approval process.

Archive

© Copyright 2014 Hot Toddy, All Rights Reserved.