Adding a Samba 4.0.3 Domain Member to a Windows Server 2012 Domain, the hard way.

I recently had the joy of upgrading a Win2k functional level domain to Win2k12. After upgrading the functional level of the domain to Win2k3, installing the new Win2k12 domain controller and upgrading the functional level (again) to Win2k12, and ensuring all existing Windows XP/7 workstations are applying GPOs correctly (a pain in the ass, in and of itself), it was time to reconfigure our Samba file servers to use the new domain controller. This is where the trouble began. These servers were running Samba version 3.old-as-hell, as such, they can’t communicate with a Win2k12 domain controller. Sure, you could disable SMB signing on the server and put in place a few other hacks floating around on the Internet but you’d still have to deal with the fact that (if I’m not mistaken) < Samba 3.5.x doesn't speak SMB 2.0. So they needed to be upgraded. After running apt-get upgrade and realizing that in order to get the version of Samba I needed, I'd have to upgrade the distro as well -- this particular machine was still running Ubuntu 9.04 (Jaunty)... Yeah. I also had another option: compile/install from source. After downloading Samba 4.0.3, compiling, installing, etc. There were a few problems:

  • The source installation installs in /usr/local/samba. This is different from where the distribution package installs.
  • … because of this, all the necessary libraries and other items required to run are not in the “correct” locations. Two words: symbolic links.

There’s probably an innumerable amount of ways to resolve this issue and get the new Samba installation up and running; here’s what I did:

Get to symlinkin’

mv /lib/libnss_winbind.so /lib/libnss_winbind.so.old
mv /lib/libnss_winbind.so.2 /lib/libnss_winbind.so.2.old
ln -s /usr/local/samba/lib/libnss_winbind.so /lib/libnss_winbind.so
ln -s /usr/local/samba/lib/libnss_winbind.so.2 /lib/libnss_winbind.so.2
mv /usr/sbin/smbd /usr/sbin/smbd.old
mv /usr/sbin/nmbd /usr/sbin/nmbd.old
mv /usr/sbin/winbindd /usr/sbin/winbindd.old
ln -s /usr/local/samba/sbin/smbd /usr/sbin/smbd
ln -s /usr/local/samba/sbin/nmbd /usr/sbin/nmbd
ln -s /usr/local/samba/sbin/winbindd /usr/sbin/winbindd
mv /etc/samba /etc/samba.old
ln -s /usr/local/samba/etc /etc/samba
mv /usr/local/samba/private/secrets.tdb /usr/local/samba/private/secrets.tdb.old
ln -s /var/lib/samba/secrets.tdb /usr/local/samba/private/secrets.tdb
mv /usr/bin/net /usr/bin/net.old
ln -s /usr/local/samba/bin/net /usr/bin/net

Symlink Bonus: I was even able to use the init scripts left over from the distro package for starting/stopping smbd, nmbd, and winbindd (/etc/init.d/{samba,winbind}).

So now what? Samba is all setup, albeit in a duct-tape-and-zip-tie fashion, so now we move on to configuration. Here is an excellent blog post detailing how to do this — I only deviated from these instructions slightly, regardless, I’ll post my configuration (with sensitive parts obfuscated) for posterity.

/etc/krb5.conf

[libdefaults]
  default_realm = MYDOMAIN.INTERNAL
  default_tgs_enctypes = arcfour-hmac-md5 des-cbc-crc des-cbc-md5 des3-hmac-sha1
  default_tkt_enctypes = arcfour-hmac-md5 des-cbc-crc des-cbc-md5 des3-hmac-sha1
  clockskew = 300 
 
[realms]
  DYERASSOC.INTERNAL = { 
    kdc = myserver.mydomain.internal
    kdc = 192.168.0.250
    default_domain = mydomain.internal
}

[domain_realm]
 domain.com = MYDOMAIN.INTERNAL
  .domain.com = MYDOMAIN.INTERNAL
 
[appdefaults]
  pam = { 
    debug = false
    ticket_lifetime = 1d
    renew_lifetime = 1d
    forwardable = true
    proxiable = false
    retain_after_close = false
    minimum_uid = 500 
    try_first_pass = true
}

You’ll notice that I have two KDCs specified; you don’t need two, one will suffice.

/etc/samba/smb.conf

#Global Settings
[global]
    workgroup = MYDOMAIN
    server string = File Server
    netbios name = fileserver01
    log level = 3
    # logs split per machine
    log file = /var/log/samba/%m.log
    # max 50KB per log file, then rotate
    max log size = 50
    security = ADS 
    realm = MYDOMAIN.INTERNAL
    encrypt passwords = yes 
    winbind enum users = Yes 
    winbind enum groups = Yes 
    winbind use default domain = Yes 
    winbind nested groups = Yes 
    winbind separator = / 
    idmap backend = tdb 
    idmap uid = 10000-20000
    idmap gid = 10000-20000
    idmap config * : range = 10000 - 20000 
#    idmap config MYDOMAIN : backend = rid
#    idmap config MYDOMAIN : range = 10000 - 20000
    map untrusted to domain = yes 
#    template primary group = "Domain Users"
    template shell = /sbin/nologin
    allow trusted domains = Yes 
#    server signing = mandatory
    server signing = auto
#    client signing = mandatory
    client use spnego = Yes 
    ntlm auth = Yes 
    lanman auth = No
    follow symlinks = yes 
    wide links = yes 
    unix extensions = no
    passdb backend = tdbsam
    preferred master = no
    local master = no
    load printers = no
    printcap name = /etc/printcap
#Share Definitions
[Shared Data]
   available = yes
   comment = Shared Data
   path = /path/to/data
   read only = no
#   writeable = yes
   browseable = yes
   invalid users = root
   create mask = 0660
   directory mask = 0770
   valid users = MYDOMAIN/username1, MYDOMAIN/username2, MYDOMAIN/username3

/etc/nsswitch.conf

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

hosts:      files dns wins 

bootparams: nisplus [NOTFOUND=return] files

ethers:     files
netmasks:   files
networks:   files
protocols:  files
rpc:        files
services:   files

netgroup:   nisplus

publickey:  nisplus

automount:  files nisplus
aliases:    files nisplus

/etc/pam.d/samba

#auth        sufficient    pam_winbind.so use_first_pass
#account     sufficient    pam_winbind.so use_first_pass
#password    sufficient    pam_winbind.so use_first_pass
#session     optional      pam_winbind.so use_first_pass


#@include common-auth
#@include common-account
#@include common-session


auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        sufficient    pam_krb5.so use_first_pass
auth        sufficient    pam_winbind.so use_first_pass
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     [default=bad success=ok user_unknown=ignore] pam_krb5.so
account     sufficient    pam_winbind.so use_first_pass
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_krb5.so use_authtok
password    sufficient    pam_winbind.so use_first_pass
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so
session     optional      pam_krb5.so
session     optional      pam_winbind.so use_first_pass

Now join Samba to Active Directory:

net ads join -U Administrator

Map a local group to a domain group:

groupadd fileserverusers
net sam createlocalgroup fileserverusers
net sam addmem fileserverusers "MYDOMAIN\Fileserver Users"
getent group

Note: Normally it is not necessary to use “groupadd” to add the local group but I had to do it this way as a result of the manner in which my Samba setup is all hacked together. The second command ‘net sam createlocalgroup [groupname]‘ is actually supposed to create the local group for you, so you will probably never have to use groupadd.

The group ‘MYDOMAIN\Fileserver Users’ is the name of the AD group you’ll be using to control access to your Samba shares. The local UNIX group (fileserverusers) needs to have the same GID as this group, so after running ‘getent group’, note the GID of the “Fileserver Users” group and then run the following command:

groupmod -g [gid-of-fileserver-users-group]

Make sure you restart winbindd and samba:

/etc/init.d/samba restart
/etc/init.d/winbind restart

That should be all you need to do.

Handy commands

List users:

getent passwd

List group mappings:

net groupmap list

Delete group mappings:

net groupmap delete sid="S-1-5-21-2672132483-2700087972-3760138129-1010"

*Where “sid” is the sid of the group map you want to delete; you can find this by using ‘net groupmap list’

Notable problems/error messages

  • Problem: getent only showing local groups
  • Answer: Make sure that libnss_winbind.so and libnss_winbind.so.2 are linked properly (see the first portion of this post)