I think that the new authentication configuration packages that come with RHEL6 will make this a little bit easier, but I haven’t played around with it yet, so here’s what I got for making this stuff work.

Assumptions: I’m a domain administrator w/ the administrative tools pack installed (to get ADUC)

The technology: RHEL 5.x (I’ve done this on 5.1 – 5.5), Samba server and client packages installed, Windows Server 2003/Active Directory

The goal: Users of a certain AD group will be able to login to the server using their network credentials, and we will capture users and groups from Active Directory. This means that we don’t have to add the users locally (like we would using krb5), and that the only requirement is that they are in the group of our choosing. For the purposes of this example, I will use the ominous “Domain Users”.

Step 1) Configure Samba & Winbind:

 [global]
workgroup = <DOMAIN NETBIOS NAME; for example: MY-DOMAIN>
password server = *
; this is the IP Address of your Domain Controller
realm = 10.1.1.2
encrypt passwords = yes
lanman auth = no
ntlm auth = no
client ntlm auth = no
client lanman auth = no
client plaintext auth = no
; local mapping of AD UID/GID
idmap uid = 10000-20000
idmap gid = 10000-20000
winbind separator = +
; here's the default shell that your AD users will get when they login
template shell = /bin/bash
; let's use the default domain so that user's don't have to login with DOMAIN+Username
winbind use default domain = true
netbios name = SERVERNAME
log file = /var/log/samba/log.%m
max log size = 50
socket options = TCP_NODELAY SO_RCVBUF=16384 SO_SNDBUF=16384
preferred master = No
dns proxy = No
; let's make sure that we're not storing credentials too long...
winbind cache time = 5
; we want to enumerate users and groups -- otherwise they don't get an ID on the local system
winbind enum users = Yes
winbind enum groups = Yes

Now, time to edit /etc/nsswitch.conf and tell it that we want to use winbind to get user accounts, password, and group information … On the lines where you see passwd, shadow, and group, append “winbind” to the end of the line … In a simple setup it will look something like this:

passwd: files winbind
shadow: files winbind
group: files winbind

At this point we can do two things — 1) Join the box to the domain and 2) Get the user/group info from active directory.

… Start winbind:

[root@host ~]# service winbind start
Starting Winbind services:                                 [  OK  ]
[root@host ~]#

Step 2) Join the Domain:

[root@host ~]# net -d ads join -U dan -S dc01.example.com
[2010/06/22 08:02:46, 0] lib/debug.c:debug_parse_params(434)
debug_parse_params: unrecognized debug class name or format [ads]
Password:
Joined domain MY-DOMAIN.
[root@host ~]#

Note For whatever reason, w/o the “debug” switch in the command, this command will always fail — ignore the “debug class” errors that you get. I’ve noticed that on Fedora setups you have to use “-d0″ instead of “-d” to get it to work. On RHEL “-d0″ doesn’t work, only “-d”. Also, and maybe this is just the AD setup that my company currently uses, for the server options “-S” I have to specify the hostname of the server and not the IP address. Final note: this is all with the understanding that “dan@example.com” is a domain administrator account — YOU MUST BE A DOMAIN ADMINISTRATOR TO JOIN YOUR SERVER TO THE DOMAIN.

Step 3) Grab the users and groups from Active Directory:

[root@host ~]# getent passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
<... snip ...> 
[root@host ~]# getent group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root
lp:x:7:daemon,lp
<... snip ...> 

Note: Both of these processes should take a while, depending on the size of your organization. If you don’t see domain users in either of those lists, rinse and repeat from the beginning. Inevitably, you will spend hours destroying all of your work and starting over.

Now, it’s time to configure PAM so that the users can login with their domain credentials.

Step 4) Configure PAM:
Basically, we’re going to be using the pam_winbind.so module in PAM to require the membership of specific groups. This is a fun one, for a number of reasons. Let me outline those real quick.

pam_winbind.so Fun Facts:

  1. The “require_membership_of” parameter does not support spaces, so anytime you’re working with a group that has a space in it, you need to specify the SID as it is in Active Directory… I’ll show you how to get this information in a second.
  2. If your organization is like most, the Windows guys never want to install the Domain UNIX extensions that allow Active Directory to pass *nix boxes account information (similar to what we would get from NIS). This is OK to me, because I tend to prefer to be on the “self sufficient” side with server administration anyway. So, we’ll need to configure pam_winbind.so to specifically not get account information from Active Directory; basically, we want the user’s “account” to be our own.

Ok, now on to it… Get the “Domain Users” SID from Active Directory.
[root@host ~]# wbinfo -n Domain\ Users
S-1-5-21-464601995-1902203606-794563710-513 Domain Group (2)
[root@host ~]#

… configure PAM:

[root@host ~]# cat /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      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth	    requisite     pam_winbind.so try_first_pass require_membership_of=S-1-5-21-464601995-1902203606-794563710-513
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        sufficient    pam_winbind.so try_first_pass
auth        required      pam_deny.so

account     required      pam_unix.so broken_shadow
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    sufficient    pam_winbind.so
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     optional      pam_mkhomedir.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
[root@host ~]# 

Note: You can see from the above that basically all we’re using is the “auth” and “password” components of the account from active directory. If you don’t do this, you’ll get some weird stuff when the users login. Also, doing it this way allows us to maintain a time source on the server different from the Domain Controller… We’re really just asking AD to tell us that the user is good to login.

Now your box is configured to allow AD user accounts to login. This line in the system-auth file will allow the home directories to be created the first time that the user logs in. The home directory skeleton will still come from /etc/skel:
session optional pam_mkhomedir.so

There’s one final caveat — if you don’t want to have to manually rejoin the domain every single time the box gets rebooted, then you’ll have to modify one of your startup scripts to automatically join the domain. I use /etc/rc.local:
[root@host ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

net -d ads join -U dan%password -S dc01.example.com &>/dev/null

getent passwd &>/dev/null
getent group &>/dev/null

Done! You now have a Linux box fully integrated for your Active Directory domain users.

Troubleshooting:

  1. Users can’t login: check /var/log/secure
  2. The “getent” commands are only returning local account information: Check with your windows guys to make sure that there isn’t a specific OU that the box needs to be in to pull account information from AD. They may not know the answer to this, so subscribe to my philosophy of “ask for forgiveness” by just moving the box into different OUs until it works. :-)
  3. Tried that, “getent” commands are still not working: While not necessary for making this work in general, try configuring your krb5 realm (/etc/krb5.conf) and performing a kinit against the domain controller. In some domains, exchanging a ticket to the DC will force Active Directory to acknowledge your server.
  4. Generally, I’m going to assume that the person reading this post and who is about to apply the commands has a healthy amount of common sense, and an average amount of technical knowledge… So do your best, and feel free to post questions or email me if you need some help!

-dan

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2013 Dan's Blog Suffusion theme by Sayontan Sinha