суббота, 6 апреля 2013 г.

Installing Samba4 on FreeBSD 8.0 as Domain Member

Hi everybody! Today's post about Installing latest Samba (on time of writing this) on FreeBSD 8.0 (I've installed it in 2010, and didn't want to update yet). I've just added a new 2tb disk to the box and I want Windows users to write there. Domain controllers are Windows Server 2008 machines.
All commands i run from superuser (root), but you can sudo them if you installed sudo port and configured it properly.
My Windows users are Russian, so charsets in config files are tuned to display Cyrillic letters.
First of all I read this HowTo and began with
# portsnap fetch update
It took a while, cause I haven't updated it since Nov 2010...
Now I have samba4 port, let's go there:
# cd /usr/ports/net/samba4
It's version 4.0.4 for the date. Ok, let's make it happen:
# make install clean
On options dialog I selected some and my /var/db/ports/samba4/options is:
# This file is auto-generated by 'make config'.
# Options for samba4-4.0.4
_OPTIONS_READ=samba4-4.0.4
_FILE_COMPLETE_OPTIONS_LIST=ACL_SUPPORT ADS AIO_SUPPORT AVAHI CUPS DEBUG DEVELOPER \
DNSUPDATE EXP_MODULES FAM_SUPPORT LDAP MANPAGES PAM_SMBPASS PTHREADPOOL QUOTAS SWAT \
SYSLOG UTMP WINBIND NSUPDATE BIND98 BIND99
OPTIONS_FILE_SET+=ACL_SUPPORT
OPTIONS_FILE_SET+=ADS
OPTIONS_FILE_SET+=AIO_SUPPORT
OPTIONS_FILE_UNSET+=AVAHI
OPTIONS_FILE_UNSET+=CUPS
OPTIONS_FILE_SET+=DEBUG
OPTIONS_FILE_UNSET+=DEVELOPER
OPTIONS_FILE_SET+=DNSUPDATE
OPTIONS_FILE_UNSET+=EXP_MODULES
OPTIONS_FILE_SET+=FAM_SUPPORT
OPTIONS_FILE_SET+=LDAP
OPTIONS_FILE_SET+=MANPAGES
OPTIONS_FILE_SET+=PAM_SMBPASS
OPTIONS_FILE_SET+=PTHREADPOOL
OPTIONS_FILE_SET+=QUOTAS
OPTIONS_FILE_SET+=SWAT
OPTIONS_FILE_SET+=SYSLOG
OPTIONS_FILE_SET+=UTMP
OPTIONS_FILE_SET+=WINBIND
OPTIONS_FILE_SET+=NSUPDATE
OPTIONS_FILE_UNSET+=BIND98
OPTIONS_FILE_UNSET+=BIND99
Several packages were in conflict with already installed, so I had to remove them with make uninstall or pkg_delete -f
And there was a problem in some dependent package about ZONEINFO so i added to /etc/scr.conf
WITHOUT_ZONEINFO=yes
Okay Samba is there.
Now time to write some configs and start scripts.
smb.conf in Samba4 is in /usr/local/etc/smb4.conf After all experiments I ended up with:
[global]
workgroup = DOMAIN_NAME
interfaces = 192.168.1.0/24
security = ADS
realm = DOMAIN_NAME.LOCAL
server string = gate
encrypt passwords = yes
dos charset = cp866
unix charset = CP1251

idmap config *:backend = tdb
idmap config *:range = 70001-80000
idmap config DSK:backend = ad
idmap config DSK:schema_mode = rfc2307
idmap config DSK:range = 500-40000

winbind nss info = rfc2307
winbind trusted domains only = no
winbind use default domain = yes
winbind enum users  = yes
winbind enum groups = yes

[ff]
path = /mnt/2tb/ff
comment = Share_Comment
guest ok = yes
read only = no
Some comments: as I use the box as a gateway to Internet, I set interfaces= to allow access to samba shares only from LAN.
There is 1 share that located in /mnt/2tb/ff folder that can be accessed as \\gate\ff from Windows explorer. (gate is FreeBSD box's name)
Copied this onto /usr/local/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 = DOMAIN_NAME.LOCAL
    dns_lookup_realm = true
    dns_lookup_kdc = true
    ticket_lifetime = 24h
    forwardable = yes
                                        
[appdefaults]
    pam = {
 debug = false
 ticket_lifetime = 36000
 renew_lifetime = 36000
 forwardable = true
 krb4_convert = false
    }
Now we can test our config:
$ testparm
Load smb config files from /usr/local/etc/smb4.conf
Processing section "[ff]"
Loaded services file OK.
Server role: ROLE_DOMAIN_MEMBER
Press enter to see a dump of your service definitions
[global]
 dos charset = cp866
 unix charset = CP1251
 workgroup = DOMAIN_NAME
 realm = domain_name.local
 server string = gate
 interfaces = 192.168.1.0/24
 security = ADS
 winbind enum users = Yes
 winbind enum groups = Yes
 winbind use default domain = Yes
 winbind nss info = rfc2307
 idmap config DSK:range = 500-40000
 idmap config DSK:schema_mode = rfc2307
 idmap config DSK:backend = ad
 idmap config *:range = 70001-80000
 idmap config * : backend = tdb

[ff]
 comment = Share_Comment
 path = /mnt/2tb/ff
 read only = No
 guest ok = Yes

If you want to see all active parameters use testparm -v

OK, we are ready to join domain:
# net ads join -U administrator
Where administrator is your domain admin name, of course. If it says that domain controllers not found, check /etc/resolv.conf - it must have domain controller IP:
search DOMAIN_NAME.LOCAL
domain domain_name.local
nameserver 192.168.1.100
And check that DC resolves DNS names:
# nslookup ds
Server:         192.168.1.100
Address:        192.168.1.100#53

Name:   ds.domain_name.local
Address: 192.168.1.100
Change "ds" to the hostname of your DC.

Now libnss_winbind.so. I spent a lot of time to get it work, but you're lucky to read this. I searched if that library already in system:
# locate nss_winbind
/usr/local/lib/nss_winbind.so.1
Ok, we got one. I copied that file to /lib/libnss_winbind.so (note filename change) and made link to /lib/libnss_winbind.so.2

My /etc/nsswitch.conf now looks like:
#
# nsswitch.conf(5) - name service switch configuration file
# $FreeBSD: src/etc/nsswitch.conf,v 1.1.10.1.2.1 2009/10/25 01:10:29 kensmith Exp $
#
group: files nis winbind
#group: compat
#group_compat: nis
hosts: files dns
networks: files
passwd: files nis winbind
#passwd: compat winbind
#passwd_compat: nis
shells: files
services: compat
services_compat: nis
protocols: files
rpc: files
Note commented (#) lines - that was there before.

If you feel okay with your configs start the daemons:
# smbd
# nmbd
# winbindd
I had no errors in output, so we can test further:
# wbinfo -u
# wbinfo -g
Should list domain's users and groups.

Now try
# id DomainUser
If it outputs errors check DC availability and nsswitch.conf again.

If you are here without errors - you almost done. Check your share from windows, create folders, files, etc.
And last but not least - start daemons at boot time. If you try to use /usr/local/etc/rc.d/samba4 by adding samba4_enable="yes" to your rc.conf you'll get warning mesage saying that this script is for Domain Controller role, and you must start daemons by hand. 'This is very sad', I thought, and started to search ready scripts to start daemons from rc.conf. After few hours of search I decided to create it myself, but I never did that kind of things... Eventually I combined script from samba 3.6 and samba4. So now I have this in /usr/local/etc/rc.d/samba (I left file name 'samba' without '4' to keep samba4 too):
#!/bin/sh
#
# $FreeBSD: net/samba36/files/samba.in 311317 2013-01-31 15:59:44Z timur $
#

# PROVIDE: nmbd smbd
# PROVIDE: winbindd
# REQUIRE: NETWORKING SERVERS DAEMON ldconfig resolv
# BEFORE: LOGIN
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
#samba_enable="YES"
# You can disable/enable any of the Samba daemons by specifying:
#nmbd_enable="NO"
#smbd_enable="NO"
# You need to enable winbindd separately, by adding:
#winbindd_enable="YES"
#
# Configuration file can be set with:
#samba_config="/usr/local/etc/smb4.conf"
#

. /etc/rc.subr

name="samba"
rcvar=samba_enable
# Custom commands
extra_commands="reload status"
start_precmd="samba_start_precmd"
start_cmd="samba_cmd"
stop_cmd="samba_cmd"
status_cmd="samba_cmd"
restart_precmd="samba_checkconfig"
reload_precmd="samba_checkconfig"
reload_cmd="samba_reload_cmd"
rcvar_cmd="samba_rcvar_cmd"

# Defaults
samba_flags=${samba_flags=--daemon}
samba_config_default="/usr/local/etc/smb4.conf"
samba_config=${samba_config=${samba_config_default}}
samba_configfile_arg=${samba_config:+--configfile="${samba_config}"}                 #"
testparm_command="/usr/local/bin/samba-tool testparm --suppress-prompt --verbose ${samba_configfile_arg}"
# Fetch parameters from configuration file
samba_role=$(${testparm_command} --parameter-name='server role' 2>/dev/null)
samba_lockdir=$(${testparm_command} --parameter-name='lock directory' 2>/dev/null)
samba_piddir=$(${testparm_command} --parameter-name='pid directory' 2>/dev/null)


smbcontrol_command="/usr/local/bin/smbcontrol"
samba_parm="${testparm_command} -s -v --parameter-name"
pid_extra=
#
samba_daemons="nmbd smbd"
samba_daemons="${samba_daemons} winbindd"

samba_checkconfig() {
    echo -n "Performing sanity check on Samba configuration: "
    if ${testparm_command} -s ${samba_config:+"${samba_config}"} >/dev/null 2>&1; then #"
 echo "OK"
    else
 echo "FAILED"
 return 1
    fi
    return 0
}

samba_start_precmd() {
    # Make sure rundir exists
    if [ ! -d "/var/run/samba4" -a ! -e "/var/run/samba4" ]; then
 install -m 0755 -d "/var/run/samba4"
    fi
    # XXX: Never delete winbindd_idmap, winbindd_cache and group_mapping
    if [ -n "${samba_lockdir}" -a -d "${samba_lockdir}" ]; then
 echo -n "Removing stale Samba tdb files: "
 for file in brlock.tdb browse.dat connections.tdb gencache.tdb \
      locking.tdb messages.tdb namelist.debug sessionid.tdb \
      unexpected.tdb
 do
     rm "${samba_lockdir}/${file}" < /dev/null 2>/dev/null && echo -n '.'
 done
 echo " done"
    fi
}

samba_rcvar_cmd() {
    local name rcvar
    rcvar=${name}_enable
    # Prevent recursive calling
    unset "${rc_arg}_cmd" "${rc_arg}_precmd" "${rc_arg}_postcmd"
    # Check master variable
    run_rc_command "${_rc_prefix}${rc_arg}" ${rc_extra_args}
    # Check dependent variables
    for name in ${samba_daemons}; do
 # XXX
 rcvars=''; v=''
 rcvar=${name}_enable
 run_rc_command "${_rc_prefix}${rc_arg}" ${rc_extra_args}
    done
}

samba_reload_cmd() {
    local name rcvar command pidfile force_run
    # Prevent recursive calling
    unset "${rc_arg}_cmd" "${rc_arg}_precmd" "${rc_arg}_postcmd"
    # Ignore rcvar and run command
    if [ -n "${_rc_prefix}" -a "${_rc_prefix}" = "one" ] || [ -n "${rc_force}" ] || [ -n "${rc_fast}" ]; then
 force_run=yes
    fi
    # Apply to all daemons
    for name in ${samba_daemons}; do
 rcvar=${name}_enable
 command="/usr/local/sbin/${name}"
 pidfile="/var/run/samba4/${name}${pid_extra}.pid"
 # Daemon should be enabled and running
 if ( [ -n "${rcvar}" ] && checkyesno "${rcvar}" ) || [ -n "$force_run" ]; then
     if [ -n "$(check_pidfile "${pidfile}" "${command}")" ]; then
  debug "reloading ${name} configuration"
  echo "Reloading ${name}."
  # XXX: Hack with pid_extra
  ${smbcontrol_command} "${name}${pid_extra}" 'reload-config' ${command_args} >/dev/null 2>&1
     fi
 fi
    done
}

samba_cmd() {
    local name rcvar rcvars v command pidfile samba_daemons result force_run
    # Prevent recursive calling
    unset "${rc_arg}_cmd" "${rc_arg}_precmd" "${rc_arg}_postcmd"
    # Stop processes in the reverse order
    if [ "${rc_arg}" = "stop" ] ; then
 samba_daemons=$(reverse_list ${samba_daemons})
    fi
    # Ignore rcvar and run command
    if [ -n "${_rc_prefix}" -a "${_rc_prefix}" = "one" ] || [ -n "${rc_force}" ] || [ -n "${rc_fast}" ]; then
 force_run=yes
    fi
    # Assume success
    result=0
    # Apply to all daemons
    for name in ${samba_daemons}; do
 # XXX
 rcvars=''; v=''
 rcvar=${name}_enable
 command="/usr/local/sbin/${name}"
 pidfile="/var/run/samba4/${name}${pid_extra}.pid"
 # Daemon should be enabled and running
 if ( [ -n "${rcvar}" ] && checkyesno "${rcvar}" ) || [ -n "$force_run" ]; then
     run_rc_command "${_rc_prefix}${rc_arg}" ${rc_extra_args}
     # If any of the commands failed, take it as a global result
     result=$((${result} || $?))
 fi
    done
    return ${result}
}

samba_config_init() {
    local name
    # Load configuration
    load_rc_config "${name}"
    for name in ${samba_daemons}; do
 load_rc_config "${name}"
    done
    # Location of the config
    samba_config=${samba_config="${samba_config_default}"} #"
    # XXX: Hack to work around name change of pid file with non-default config
    if [ -n "${samba_config}" -a "${samba_config}" != "${samba_config_default}" ]; then
 pid_extra="-$(basename "${samba_config}")"
    fi
    # Setup dependent variables
    if [ -n "${rcvar}" ] && checkyesno "${rcvar}"; then
 nmbd_enable=${nmbd_enable=YES}
 smbd_enable=${smbd_enable=YES}
    fi
    # Defaults
    samba_enable=${samba_enable:=NO}
    nmbd_enable=${nmbd_enable:=NO}
    smbd_enable=${smbd_enable:=NO}
    # Winbindd
    if [ -z "${winbind_enable}" ]; then
 samba_idmap=$(${samba_parm} 'idmap uid' "${samba_config}" 2>/dev/null)
 # Check that winbindd is actually configured
 if [ -n "${samba_idmap}" ]; then
  winbindd_enable="YES"
 fi
 winbindd_enable=${winbindd_enable:=NO}
    fi
}

# Load configuration variables
samba_config_init
# Common flags
command_args=${samba_config:+-s "${samba_config}"} #"
nmbd_flags=${nmbd_flags="-D"}
smbd_flags=${smbd_flags="-D"}
winbindd_flags=${winbindd_flags=''}
# Requirements
required_files="${samba_config}"
required_dirs="${samba_lockdir}"

run_rc_command "$1"
And here is /etc/rc.conf:
ifconfig_vr1="inet 192.168.1.14  netmask 255.255.255.0"
ifconfig_vr0="inet XXX.XXX.XXX.XXX  netmask 255.255.255.0"
defaultrouter="XXX.XXX.XXX.XXX"
named_enable="YES"
ntpd_enable="YES"
ntpd_flags="-p /var/run/ntpd.pid"
gateway_enable="YES"
firewall_enable="YES"
natd_enable="YES"
natd_interface="vr0"
natd_flags=""
squid_enable="YES"
hostname="gate.domain_name.local"
keymap="ru.cp1251"
scrnmap="win2cpp866" 
font8x16=cp866b-8x16 
font8x14=cp866-8x14 
font8x8=cp866-8x8
moused_enable="YES"
sshd_enable="YES"
inetd_enable="YES"
samba_enable="YES"
winbindd_enable="YES"
Now reboot and test everything again.

Thanks for reading my first article here, feel free to comment. Вопросы можно задать и на русском языке.

2 комментария:

  1. Ошибка в файле /usr/local/etc/rc.d/samba на 83 строке - отсутствует символ ">". В результате при запуске зачем-то сносится устройство /dev/null

    ОтветитьУдалить
    Ответы
    1. Ваша правда, видимо при вставке текста редактор принял "</" за закрывающий тэг. Добавил пробел, теперь должно быть ОК. Спасибо за замечание!

      Удалить