# FreeBSD + FreeIPA (via SSSD)



## sethlyons (May 20, 2014)

The following is what we did in order to utilize all of the benefits of a FreeIPA server (on Linux) with a FreeBSD client.  The software packages needed are:

security/sssd
security/sudo (with SSSD backend)
net/openldap24-client-sasl
security/cyrus-sasl2
security/cyrus-sasl2-gssapi

In order to ensure that net/openldap24-client-sasl is used, we added a line to /etc/make.conf:

```
WANT_OPENLDAP_SASL=yes
```

Once all software is installed, ensure the following directories exist:

/var/db/sss
/var/log/sssd

The base configuration needed for authentication, authorization, HBAC, and sudo (more on sudo to follow) is:

```
[domain/<domain_name>]
cache_credentials = True
krb5_store_password_if_offline = True
ipa_domain = <domain_name>
id_provider = ipa
auth_provider = ipa
access_provider = ipa
ipa_hostname = <fqdn>
chpass_provider = ipa
ipa_server = _srv_ #our FreeIPA server has DNS SRV entries
ldap_tls_cacert = <ldap tls CA cert location>
enumerate = True #to enumerate users and groups

[sssd]
enumerate = True
services = nss, pam, sudo
config_file_version = 2
domains = <domain_name>

[nss]

[pam]

[sudo]
```

The tricky part was getting sudo to work with host groups. FreeIPA keeps host groups in netgroups, and FreeBSD's support for netgroups is limited. One solution would have been to enable NIS services on the FreeIPA server so that we could use proper netgroups on FreeBSD clients. We didn't like that solution, so instead we wrote a script that pulls all netgroup data from FreeIPA and stores it in /etc/netgroup. We run the script every hour via cron.

```
#!/bin/sh
#
# Construct a netgroup file from LDAP hostgroup definitions.
# This is a hack for FreeBSD IPA clients because they can't get netgroup
# data through LDAP or sssd backends (lacking nsswitch/nsdb support).
#

PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
export PATH

progname=$(basename $0)
tmpf=$(mktemp)

trap "rm -f $tmpf" EXIT

ldapsearch -LLLx -H ldap://<ldap_server> \
           -b 'cn=hostgroups,cn=accounts,dc=<domain_name>' \
           '(objectClass=ipahostgroup)' cn member \
| while read line; do
  # new line between records; this means a record ended.
  if [ "$line" = "" ]; then
    # output netgroup line if we have members.
    if [ "$members" != "" ]; then
      echo "$groupname \\" >>$tmpf
      for host in $members; do
        echo " ($host, -, fxcorp) \\" >>$tmpf
      done
      echo "" >>$tmpf
    fi

    # reset data
    groupname=""
    members=""
    continue
  fi

  # parse "key: value" from LDAP
  key=${line%%: *}
  value=${line##*: }

  if [ "$key" = "dn" ]; then
    continue
  elif [ "$key" = "cn" ]; then
    groupname=$value
  elif [ "$key" = "member" ]; then
    host=${value%%,cn*}
    host=${host##fqdn=}
    members="$members $host"
  fi
done

if [ ! -s "$tmpf" ]; then
  echo "$progname: refusing to install an empty file, bailing" >&2
  exit 1
fi

install -m 0644 -o root -g wheel $tmpf /etc/netgroup
rc=$?

if [ $rc -ne 0 ]; then
  echo "$progname: error installing /etc/netgroup (rc = $rc)" >&2
  exit 2
fi

exit 0
```

We wrote a patch for pam_sss to support ignore_unknown_user. Without that support local users could authenticate when using SSSD for authentication. We submitted the patch upstream. It was accepted by the FreeIPA team and will hopefully be ported to FreeBSD soon. Our PAM  configuration to support SSSD is:

```
#
# $FreeBSD: release/10.0.0/etc/pam.d/system 197769 2009-10-05 09:28:54Z des $
#
# System-wide defaults
#

# auth
auth sufficient pam_opie.so no_warn no_fake_prompts
auth requisite pam_opieaccess.so no_warn allow_local
auth sufficient pam_krb5.so no_warn try_first_pass
auth sufficient /usr/local/lib/pam_sss.so debug use_first_pass
auth required pam_unix.so no_warn try_first_pass

# account
account required pam_login_access.so
account required pam_unix.so
account required /usr/local/lib/pam_sss.so ignore_unknown_user

# session
#session optional pam_ssh.so want_agent
#session optional /usr/local/lib/pam_sss.so
session required pam_lastlog.so no_fail

# password
#password sufficient pam_krb5.so no_warn try_first_pass
password sufficient /usr/local/lib/pam_sss.so use_authtok
password required pam_unix.so no_warn try_first_pass
```


```
#
# $FreeBSD: release/10.0.0/etc/pam.d/sshd 197769 2009-10-05 09:28:54Z des $
#
# PAM configuration for the "sshd" service
#

# auth
auth sufficient pam_opie.so no_warn no_fake_prompts
auth requisite pam_opieaccess.so no_warn allow_local
auth sufficient pam_krb5.so no_warn try_first_pass
#auth sufficient pam_ssh.so no_warn try_first_pass
auth sufficient /usr/local/lib/pam_sss.so debug use_first_pass
auth required pam_unix.so no_warn try_first_pass

# account
account required pam_nologin.so
#account required pam_krb5.so
account required pam_login_access.so
account required pam_unix.so
account required /usr/local/lib/pam_sss.so ignore_unknown_user

# session
#session optional pam_ssh.so
#session required /usr/local/lib/pam_mkhomedir.so
session required pam_permit.so

# password
#password sufficient pam_krb5.so no_warn try_first_pass
password sufficient /usr/local/lib/pam_sss.so debug use_authtok
password required pam_unix.so no_warn try_first_pass
```

To let the system know what method to use for passwd, group, sudo, etc. we updated our /etc/nsswitch.conf:

```
#
# nsswitch.conf(5) - name service switch configuration file
# $FreeBSD: release/10.0.0/etc/nsswitch.conf 224765 2011-08-10 20:52:02Z dougb $
#
#group: compat
group: files sss
group_compat: nis
hosts: files dns
networks: files
#passwd: compat
passwd: files sss
passwd_compat: nis
shells: files
services: compat
services_compat: nis
protocols: files
rpc: files
sudoers: sss files
netgroup: files
```

The final step was to create a kerberos keytab on the FreeIPA server and copy it over to our FreeBSD host.  On the FreeIPA server we excecuted:

```
freeipa-server# ipa-host-add <fqdn>
freeipa-server# ipa-getkeytab -s <freeipa server hostname> -p host/<freebsd host fqdn> -k <location to export the keytab>
```

We then simply copied the keytab to /etc/krb5.keytab on our FreeBSD host.


----------



## orkhan (Oct 17, 2014)

Thanks for the post, it seems to be the only post about FreeBSD - FreeIPA integration.

I set up everything as you advise, but get a problem: I can't locally log into my FreeBSD client (either as a local user or as an IPA user).

The problem is in this string in the /etc/pam.d/system file:

```
account required /usr/local/lib/pam_sss.so ignore_unknown_user
```
That string gives login errors, with or without the ignore_unknown_user part. The only solution I found for now is to comment that string out and add it explicitly into /etc/pam.d/login file. Then the local login process proceeds without errors.

You said: "We wrote a patch for pam_sss to support ignore_unknown_user." But the problem seems to be not in the ignore_unknown_user part, it is in the account required /usr/local/lib/pam_sss.so part.

Is it a bug in PAM/SSSD? Please advise, what to do now?


----------



## orkhan (Oct 21, 2014)

orkhan said:


> Thanks for the post, it seems to be the only post about FreeBSD - FreeIPA integration.
> 
> I set up everything as you advise, but get a problem: I can't locally log into my FreeBSD client (either as a local user or as an IPA user).
> 
> ...



I shared this problem at FreeIPA mailing lists, and Lukas Slebodnik helped to troubleshoot it:



> You have a typo in pam.d/system
> Here is a word-diff:
> [-account-]{+acconut+} required /usr/local/lib/pam_sss.so ignore_unknown_user ignore_authinfo_unavail



It was my mistake (acconut instead of account), and a very simple one, but sometimes the simplest mistakes are hardest to find.

Another valuable advice Lukas gave was regarding comments in the /usr/local/etc/sssd/sssd.conf file, specifically this line:

```
enumerate = True #to enumerate users and groups
```



> Just FYI, comments on the same line are treated as part of value i.e. not interpreted as comments.
> ...As for enumeration - it is not needed in 90% of cases so we recommend not to configure it.



With comments on the same line, sssd won't start. Another simple thing that causes headache.


----------



## Jim Trigg (Jul 7, 2017)

It seems to me that a cleaner way than "--ignore-unknown-user" would be to port pam_localuser and put that as "sufficient" before pam_sss. (In my day job I'm a RHEL administrator, and my current employer uses the RH paid version of FreeIPA.)


----------



## asghar_h (Jul 17, 2020)

I was able to successfully get this working based on some input from this page itself, so thanks to the contributors.

Here are my instructions.

Assumptions:

   Successfully working FreeIPA servers named below:

        ipa1.zone.example.com
        ipa2.zone.example.com

    Realm:

        zone.example.com

Install the following packages:

        pkg install -y cyrus-sasl cyrus-sasl-gssapi ding-libs libinotify nss \
                        openldap-sasl-client popt talloc tdb tevent cmocka \
                        lmdb gamin jansson libarchive libsunacl py37-iso8601 \
                        krb5 pam_mkhomedir c-ares

Compile and install the following in sequence:

    For the builds below choose LMDB and GSSAPI-MIT options when the curses 
    menu appears after initiating the make command.

    LDB14

        cd /usr/ports/databases/ldb14
        make
        make install

    Samba410

        cd /usr/ports/net/samba410
        make 
        make install

    SSSD

        cd /usr/ports/security/sssd
        make
        make install

Configure LDAP (on client host):

    Add the following to /usr/local/etc/openldap/ldap.conf

        BASE               dc=zone,dc=example,dc=com
        URI                ldaps://ipa1.zone.example.com
        SSL                start_tls
        SASL_NOCANON       on
        TLS_CACERT         /usr/local/etc/sssd/cacert.crt
        TLS_CACERTDIR      /usr/local/etc/sssd

Get IPA cacert.crt file from IPA server (on client host):

        mkdir -p /usr/local/etc/sssd
        fetch http://ipa1.zone.example.com/ipa/config/ca.crt -o /usr/local/etc/sssd/cacert.crt

Configure the SSSD service:

    Add the following content to /usr/local/etc/sssd/sssd.conf and change the "ipa_hostname" variable to the DNS resolvalble FQDN of the client host:

        [domain/zone.example.com]
        cache_credential = True
        krb5_store_password_if_offline = True
        ipa_domain = zone.example.com
        id_provider = ipa
        auth_provider = ipa
        access_provider = ipa
        ipa_hostname = <DNS resolvable hostname of this client host>
        chpass_provider = ipa
        ipa_server = _srv_, ipa1.zone.example.com
        ldap_tls_cacert = /usr/local/etc/sssd/cacert.crt
        entry_cache_timeout = 5
        enumerate = True
        ldap_sudo_search_base = ou=sudoers,dc=zone,dc=example,dc=com
        krb5_keytab = /etc/krb5.keytab
        debug_level = 3 # Granular logging 1-10
        [sssd]
        config_file_version = 2
        services = nss, pam, sudo, ssh
        domains = zone.example.com

        [nss]
        override_homedir = /usr/home/%u
        override_shell = /bin/csh

        [pam]

        [sudo]

Add SSSD service start on powercycle:

    Add the following entry to /etc/rc.conf

        sssd_enable="YES"

Configure Kerberos Client

    Add the following content to /etc/krb5.conf

        [libdefaults]
        default_realm = ZONE.EXAMPLE.COM
        default_keytab_name = /etc/krb5.keytab
        dns_lookup_realm = true
        dns_lookup_kdc = true
        forwardable = yes
        rdns = false

        [realms]
        ZONE.EXAMPLE.COm = {
            kdc = ipa1.zone.example.com
            kdc = ipa2.zone.example.com
            master_kdc = ipa1.zone.example.com
            admin_server = ipa2.zone.example.com
            default_domain = zone.example.com
            pkinit_anchors = FILE:/usr/local/etc/sssd/cacert.crt
        }

        [domain_realm]
        .zone.example.com = ZONE.EXAMPLE.COM
        zone.example.com = ZONE.EXAMPLE.COM

        [logging]
        kdc = FILE:/var/log/krb5/krb5kdc.log
        admin_server = FILE:/var/log/krb5/kadmin.log
        kadmin_local = FILE:/var/log/krb5/kadmin_local.log
        default = FILE:/var/log/krb5/krb5lib.log

    Create /var/log/krb5 directory

        mkdir /var/log/krb5

Add client host to the FreeIPA server

    On the FreeIPA server add the client host

        sudo su - 
        kinit <admin user>
        ipa host-add <client fqdn>

        Example:

        sudo su - 
        kinit joecool
        ipa host-add client1.zone.example.com

Store client keytab in a file 

    On the FreeIPA server get the clients keytab and store it in a file

        ipa-getkeytab -p host/client1.zone.example.com -k clien1.zone.example.com.keytab

    From the FreeIPA server copy the keytab file to client host

        scp client1.zone.example.com.keytab user@client1.zone.example.com:~

    On the client host move the keytab into its appropriate location and change the permissions (assuming user is user)

        mv client1.zone.example.com.keytab /etc/krb5.keytab
        chown root:wheel /etc/krb5.keytab
        chmod 400 /etc/krb5.keytab

Verify if LDAP client is working

    Run the following command(s) on the client host to verify if user can kinit

        $ kinit <user>

        Example:

        root@freebsdtest:/usr/ports # kinit joecool
joecool@ZONE.EXAMPLE.COM's Password: 

        $ klist

        Example:

        $ klist
        Credentials cache: FILE:/tmp/krb5cc_0
        Principal: joecool@ZONE.EXAMPLE.COM

        Issued                Expires               Principal
        Jul 14 21:14:44 2020  Jul 15 07:14:44 2020  krbtgt/ZONE.EXAMPLE.COM@ZONE.EXAMPLE.COM

        $ ldapsearch -Y GSSAPI

        root@freebsdtest:/usr/ports # ldapsearch -Y GSSAPI
        SASL/GSSAPI authentication started
        SASL username: joecool@ZONE.EXAMPLE.COM
        SASL SSF: 56
        SASL data security layer installed.
        # extended LDIF
        ...(ouput continues)

Change SSSD config permissions

    chmod 0600 /usr/local/etc/sssd/sssd.conf

Starting SSSD

    On the client host machine start SSSD using the following command

        # service sssd start

Configuring PAM

    WARNING: Make sure you create a backup of these files in case you might 
    need them later. You have been warned. The author assumes no responsibility
    if you are locked out of your system.

    On the client host machine change the /etc/pam.d/sshd to the following

        auth            sufficient      pam_opie.so                 no_warn no_fake_prompts
        auth            requisite       pam_opieaccess.so           no_warn allow_local
        auth            sufficient      pam_krb5.so                 debug no_warn try_first_pass
        auth            sufficient      /usr/local/lib/pam_sss.so   use_first_pass
        auth            required        pam_unix.so                 no_warn try_first_pass
        account         required        pam_nologin.so
        account         required        pam_login_access.so
        account         required        pam_unix.so
        account         required        /usr/local/lib/pam_sss.so   ignore_unknown_user ignore_authinfo_unavail
        session         required        /usr/local/lib/pam_mkhomedir.so
        session         required        pam_permit.so
        password        sufficient      /usr/local/lib/pam_sss.so   use_authtok
        password        required        pam_unix.so                 no_warn try_first_pass

    On the client host machine change the /etc/pam.d/system to the following

        auth            sufficient      pam_opie.so                 no_warn no_fake_prompts
        auth            requisite       pam_opieaccess.so           no_warn allow_local
        auth            sufficient      /usr/local/lib/pam_sss.so   use_first_pass
        auth            required        pam_unix.so                 no_warn try_first_pass nullok
        account         required        pam_login_access.so
        account         required        pam_unix.so
        account         required        /usr/local/lib/pam_sss.so   ignore_unknown_user ignore_authinfo_unavail
        session         required        pam_lastlog.so              no_fail
        session         required        /usr/local/lib/pam_mkhomedir.so
        password        sufficient      /usr/local/lib/pam_sss.so   use_authtok
        password        required        pam_unix.so                 no_warn try_first_pass

Configuring nsswitch

    WARNING: Make sure you create a backup of these files in case you might 
    need them later. You have been warned. The author assumes no responsiblity
    if you are locked out of your system

    On the client host machine change the /etc/nsswitch.conf to the following

        group: files sss
        group_compat: nis
        hosts: files dns
        netgroup: compat
        networks: files
        passwd: files sss
        passwd_compat: nis
        shells: files
        services: compat
        services_compat: nis
        protocols: files
        rpc: files
        sudoers: sss files

Use verification

    On the client host, use the following command to check if IPA integration is working

        $ id -a <your-FreeIPA-user>
        $ getent passwd
        $ getent group

Troubleshooting SSSD

    To troubleshoot SSSD, issue the following command and watch its output

        $ sudo sssd -i -c /usr/local/etc/sssd/sssd.conf -d6


----------

