A while back, I described a method for authenticating CentOS and RHEL servers to Active Directory using LDAP. While this approach is easy to set up and works right out of the gate, there are a few drawbacks to it that I’ve run across:
- Changing passwords from the Linux server does not work unless you set up LDAP over TLS/SSL, which I’ve found very difficult (though not impossible!) to accomplish
- While changing the passwords does work, it can be very user unfriendly. In particular error messages given are very cryptic to the lay user. Unless you are in IT, you’re not going to know or care about the LDAP error codes that are reported back, nor are you going to want to research what the appropriate character classes are for the AD passwords so that you can choose from at least three of them appropriately.
In this article, I’ll describe how to use winbind to join your Linux server to a Microsoft Active Directory and become a domain member.
First, you need to set up your users in AD with the required POSIX attributes. At a minimum, you need to set only two attributes, uidNumber and gidNumber. For the uidNumber, I recommend using the RID of the user you are setting these attributes for. You can also set unixHomeDirectory, gecos and loginShell if you want to maintain this information in AD. These are optional in the set up I am proposing, so it could be considered more of a best practice than a requirement. So my user object looks something like this (many many attributes omitted for brevity):
|
1 2 3 4 5 6 7 8 |
dn: CN=Tester X,OU=Users,dc=techrockdo,dc=com sAMAccountName: testerx objectSid: S-1-5-21-543932-553907294-9392035-34444 uidNumber: 34444 gidNumber: 513 gecos: Tester X loginShell: /bin/bash unixHomeDirectory: /home/testerx |
Then you need a group to go with it. Note that I’ve set this user’s gidNumber to 513. In order for winbind to operate, the gidNumber in AD needs to be set to a group that exists in AD – that is, a user’s primary group can’t be a local group. The user simply will be ignored by winbind and therefore Unix. Keeping that in mind, this is the object dump of my AD group:
|
1 2 3 |
distinguishedName: CN=Domain Users, DC=techrockdo,dc=com gidNumber: 513 objectSid: S-1-5-21-543932-553907294-939203-513 |
Note how the uidNumber for the user object and the gidNumber for the group are based off of the RID of the object (the last number of the object’s SID). This isn’t required. You can set the gidNumber and uidNumber to any arbitrary (but unique) value you choose. I did it simply because the SID is going to be unique in a directory.
Now that we have our user and group objects set up, using winbind relatively simple to do. The first thing I do is to make sure you have the appropriate packages installed. A simple yum command will set that up.
|
1 |
[root@winbind-teste ~]# yum -y install samba-winbind |
Next, I run authconfig-tui and select ‘Cache Information’ and ‘Use Winbind’ under ‘User Information’ and ‘Use MD5 Passwords,’ ‘Use Shadow Passwords,’ ‘Use Winbind Authentication,’ and ‘Local authorization is sufficient’ under ‘Authentication.’ This will configure PAM and NSS for you so you don’t have to worry about editing those files by hand. Unfortunately, (at least the way I want to do things), authconfig-tui does not handle setting up smb.conf quite the way I want it to AND it tries to start winbind without joining it to the domain first. We’ll clean up that cache files that the aborted attempt at starting winbind makes and there are only a couple files to edit by hand and they are consistent across all servers in the domain.
So first:
|
1 |
[root@winind-teste ~]# rm -f /var/lib/samba/*.tdb /var/lib/samba/private/secrets.tdb |
Then make sure your /etc/hosts looks similar to the following:
|
1 2 3 |
127.0.0.1 localhost.localdomain localhost4.localdomain4 localhost4 localhost ::1 localhost.localdomain localhost6.localdomain6 localhost6 localhost 10.1.1.130 winbind-teste.techrockdo.com winbind-teste |
Pretty simple, right? It was just one of the things I found that made my life easier since anaconda (or maybe Network Manager?) has a tendency to put the hostname in with the localhost line, which I’ve found confuses certain applications.
Next, /etc/krb5.conf needs to be tweaked a bit:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = TECHROCKDO.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [realms] TEST.ROCKFIN.COM = { kdc = dc.techrockdo.com } [domain_realm] .techrockdo.com = TECHROCKDO.COM techrockdo.com = TECHROCKDO.COM |
And finally, the all-important /etc/samba/smb.conf. I’ll show you what I do with it and then explain it afterwards.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[global] workgroup = TRD password server = dc.techrockdo.com realm = TECHROCKDO.COM security = ads idmap backend = nss idmap uid = 500-33554431 idmap gid = 500-33554431 template shell = /bin/bash template homedir = /home/%U winbind nss info = rfc2307 winbind use default domain = true winbind offline login = false idmap config TRD:backend = ad idmap config TRD:default = yes idmap config TRD:range = 500-33554431 idmap config TRD:schema_mode = rfc2307 server string = Samba Server Version %y |
There are a lot more options you can put in your smb.conf if you want your server to serve up cifs or smb shares or printers, etc. I’m just focusing on authentication, and this is a configuration file that works to perform this function. Things to note here are that I am setting the id range for uid’s and gid’s to be from 500 – 33554431. This may not work for you if you already have local users that have id’s in this range. CentOS and RHEL work on trying to keep all service accounts (apache, mail, sshd, nscd, etc) uid numbers under 500 so this seemed like a good place to start for me since all of my users will be in AD (no local or LDAP accounts). If you’ll recall, I mentioned above that the loginShell and unixHomeDirectory attributes are not required. That is true, but only if you have the template shell and template homedir set (as above). If either of these attributes are missing, the values from smb.conf will be used.
Now that we’ve got samba configured, we’re ready to join the domain. Using an account with privileges to join servers to the domain, run
|
1 |
[root@winbind-teste ~]# net ads join -U <username> createcomputer='/Server/OU' |
The createcomputer argument is not required. It is used if you want your computer object to be place into the directory in a different OU from /Computers. If that doesn’t matter, just leave off the argument altogether. Another thing to note is that you’ll most like receive what looks like an error – usually it’s that the account doesn’t exist in Kerberos or a DNS update failed. This is fine; just look for the text “<computername> joined to domain.”
Finally start up the winbind service:
|
1 |
[root@teste ~]# service winbind start |
Now, you should be able to authenticate with your AD users and get user information. A word of warning – although authentication and commands like finger and id work against the AD users, one of the shortcomings of winbind is that getent passwd and getent group will not return any entries for AD accounts or groups. Just something to keep in mind.
One of the side benefits of having your computer joined to the domain is that you can now easily run queries or create and delete users and groups. For example, if you wanted to find information about Tester X, you could run
[root@winbind-teste ~]# net ads search -P ‘(cn=Tester X)’
This would return an ldif-like stanza of the Tester X object. The -P tells net ads search to use the computer’s machine account to authenticate while performing the search.
Conclusion
In the end, I’ve presented two methods of integrating your Linux system authentication into an existing AD infrastructure – one using straight LDAP into AD and the other using winbind to join the machine to the domain and use native calls. There advantages to each method.
Advantages to LDAP:
- Easy to configure
- Is a more “standard” configuration for Unix and Linux
- Returns user information properly with commands like getent passwd
Advantages to Winbind:
- Uses native calls into AD
- Presents a slightly more user-friendly interface into functions (eg, passwd displaying more readable errors)
- Allows for changing passwords without having to worry about setting up certificates
- Certain AD functions can be achieved using the ‘net’ command
During the course of my testing and speaking with other Unix engineers, I’ve gotten the impression that authenticating to AD is looked down upon. I don’t see it that way. If you’ve got an established directory service set up, there’s no reason why it shouldn’t be leveraged. In fact, AD authentication just goes to show the strength of *nix systems; after all, how many Windows systems do you know of that can authenticate exclusively against LDAP or NIS?

Hello,
I am trying to integrate AD authentication to Cent OS 6 servers. I am running to this error when I tried to join with AD server. I installed both Samba as well as windbind. can you please suggest where I am missing.
error message :
Code:
# net ads join -U 504783
Host is not configured as a member server.
Invalid configuration. Exiting….
Failed to join domain: This operation is only allowed for the PDC of the doma in.
#
configuration file of samba smb.conf under [global] is updated with this info.
Code:
workgroup = ctab
realm = CTAB.ALPHA.COM
security = ads
idmap uid = 7000-500000
idmap gid = 7000-500000
template shell = /bin/bash
template homedir = /home/%U
winbind use default domain = true
winbind offline logon = false
winbind nss info = rfc2307
idmap config TRD:backend = ad
idmap config TRD:defauly = yes
idmap config TRD:range = 70000-500000
idmap config TRD:schema_mode = rfc2307
server string = Samba Server Version %y
I have updated krb5.conf as this
Code:
#more /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 = CTAB.ALPHA.COM
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
[realms]
CTLAB.ALPHA.COM = {
kdc = ctab.alpha.com
admin_server = ctab.alpha.com
}
[domain_realm]
.ctab.alpha.com = CTLAB.ALPHA.COM
ctab.alpha.com = CTLAB.ALPHA.COM
#
I wasnt able to fix it can someone please suggest.
Thanks,
A couple things:
First, you need to fix the lines that still contain TRD. Change that to your domain (CTAB). Next, you’ve misspelled ‘default’ in the idmap config TRD:defauly = yes line. You’ve also set the range for your idmap to 70000 where you had 7000 as the previous minimum; was this intentional?
Ultimately, I believe your error message stems from a missing
password server =line. I think that’s why when you try the join, net is thinking it is a PDC rather than contacting an outside one.Hope it helps!
Hi Greg,
Thanks for your reply, I still have same issues, I was able to join the domain, but when execute wbinfo for user and group I am getting into error messages any idea??
[global]
workgroup = CTAB
realm = CTAB.ALPHA.COM
server string = Samba Server Version %v
security = ADS
password server = CTAB.ALPHA.COM
log file = /var/log/samba/log.%m
max log size = 50
idmap backend = nss
idmap uid = 10000-20000
idmap gid = 10000-20000
template homedir = /home/%U
template shell = /bin/bash
winbind separator = +
winbind cache time = 10
winbind enum users = Yes
winbind enum groups = Yes
winbind use default domain = Yes
winbind nss info = rfc2307
idmap config CTAB:schema_mode = rfc2307
idmap config CTAB:range = 10000-20000
idmap config CTAB:default = yes
idmap config CTAB:backend = ad
cups options = raw
# net ads join -U z504783
Enter z504783′s password:
Using short domain name — CTAB
Joined ‘HOSTNAME1′ to realm ‘ctab.alpha.com’
[2012/01/16 16:17:58.005964, 0] libads/kerberos.c:333(ads_kinit_password)
kerberos_kinit_password HOSTNAME1$@CTAB.ALPHA.COM failed: Preauthentication failed
[root@HOSTNAME1 /]# wbinfo -u
Error looking up domain users
[root@HOSTNAME1 /]# wbinfo -g
Error looking up domain groups
[root@HOSTNAME1 /]#
Hi
Thanks for the wonderful article. I followed the steps and it worked fine. I could get a list of users by using wbinfo -u and groups by wbinfo -g. However, I had to restart the system for some reason. After reboot, I could rejoin the domain, but can’t authenticate anymore. wbinfo -u and -g come back with errors saying Error Looking up domain users. Please help. What happened between reboots? How do I fix this once and for all.
Does it matter that CentOS is running in a VM (Hyper-V)?
To answer your final question, it does not matter if the CentOS server is virtual or physical. As far as the OS cares, it’s just another hardware platform.
The first thing you need to do is verify winbind is running. You can check that with
If it is running, you might want to try stopping it and then removing the *.tdb files in /var/cache/winbind if you’re running CentOS 5 or /var/lib/samba/*.tdb if you’re running CentOS 6. Then restart winbind and check your results again.
Hi there,
Thanks for this, I have successfully joined a centos client to the domain, and wbinfo returns the correct values.
What I would like to do next is acctually log onto the Centos box with the AD user credentials.
Is this possible?
+1
//great article
I was able to get this going without any walkthrough however how do you manuall set the UID?
Im in an environment where we have users already setup on our linux boxen and UID’s are already setup and need to stay consistent.
ex:
[chicken@strips ~]$ id chicken
uid=544(chicken) gid=544(chicken) groups=544(chicken)
[chicken@strips ~]$
I know of win2k8′s SFU role that can be added to AD, i set the UID and GID but when the user logins in, it doesnt retain the proper ip.