November 19, 2020

login_ldap on OpenBSD 6.8

In September 2020, login_ldap was imported in OpenBSD. It was a few days before the 6.8 release. login_ldap.conf example was also added with its manpage, helping us to understand this new syntax. At work, OpenBSD can cover some of my needs, so I decided to try the native LDAP authentication. Unfortunately, some of the other manpages (like login.conf) are not updated accordingly, so far. Consequently, it was a bit more tricky.

As I was unable to find a recent documentation online, I decided to write this article which will explain what I did, to make it work. Even if I usually never share my personal documentation (for many reasons), today I will make an exception. Here we go.

login_ldap

First, make sure the LDAP server can be reached and verify the data can be listed :

$ ldap search -H ldap://ldap.foo.tld -b "dc=foo,dc=tld" | less

It is just like the usual ldapsearch from OpenLDAP. Using a PAGER allows us to check if everything was found. In that example, we stick to plain LDAP on port 389. Now, it's time to write login_ldap configuration file. By default, it is /etc/login_ldap.conf :

$ vi /etc/login_ldap.conf
host=ldap://192.168.2.5
basedn=dc=foo,dc=tld
scope=sub
filter=(&(objectclass=posixAccount)(uid=%u))

If you used LDAP before, the options will be self-explanatory. Anyway, it won't work without filter line, especially (uid=%u) string. This file requires some special ownership :

$ chown root:auth /etc/login_ldap.conf && chmod 640 /etc/login_ldap.conf

Are we ready to verify the authentication ? Yes, we are :

$ /usr/libexec/auth/login_ldap -d -s login calvin

Replace calvin by the UID you want. -d argument gives us some interesting output :

...
connect success!
bind success!
...
user bind success!
authorize

So far, so good. This upcoming part was a bit more complicated for me, without the updated login.conf manpage. We absolutely need to add the ldap class in /etc/login.conf. This way, we can "allow" LDAP authentication on the system. On the top of the file before auth-defaults line, add this authentication style :

$ vi /etc/login.conf
# LDAP authentication
ldap:auth=ldap:

Then, auth-defaults can finally contain ldap. I put it first, before local passwd. default class now has LDAP auth.

auth-defaults:auth=ldap,passwd,skey:

ypldap

ypldap will populate maps with LDAP backend. Let's do this :

$ cp -a /etc/examples/ypldap.conf /etc/ypldap.conf
$ vi /etc/ypldap.conf
domain          "foo.tld"
interval        60
provide map     "passwd.byname"
provide map     "passwd.byuid"
provide map     "group.byname"
provide map     "group.bygid"
provide map     "netid.byname"

directory "ldap.foo.tld" {
    # directory options
    #binddn "cn=admin,dc=example,dc=com"
    #bindcred "secret"
    basedn "dc=foo,dc=tld"
    # starting point for groups directory search, default to basedn
    #groupdn "ou=Groups,dc=example,dc=com"

    # passwd maps configuration (RFC 2307 posixAccount object class)
    passwd filter "(objectClass=posixAccount)"

    attribute name maps to "uid"
    fixed attribute passwd "*"
    attribute uid maps to "uidNumber"
    attribute gid maps to "gidNumber"
    attribute gecos maps to "cn"
    attribute home maps to "homeDirectory"
    attribute shell maps to "loginShell"
    fixed attribute change "0"
    fixed attribute expire "0"
    fixed attribute class "ldap"

    # group maps configuration (RFC 2307 posixGroup object class)
    group filter "(objectClass=posixGroup)"

    attribute groupname maps to "cn"
    fixed attribute grouppasswd "*"
    attribute groupgid maps to "gidNumber"
    # memberUid returns multiple group members
    list groupmembers maps to "memberUid"
}

Only four lines were modified : domain, directory, basedn and the most important, ldap in fixed attribute class. It is mandatory because it calls the ldap class from /etc/login.conf. As I use an anonymous bind DN, binddn and bindcred were commented.

YP domain name is set with domainname and /etc/defaultdomain at boot. Please, define it :

$ echo 'foo.tld' >/etc/defaultdomain
$ domainname $(</etc/defaultdomain)

The next steps are nicely described in the official OpenBSD FAQ. Therefore, I will just show you the necessary commands :

$ echo '+:*::::::::' >>/etc/master.passwd
$ pwd_mkdb -p /etc/master.passwd
$ echo '+:*::' >>/etc/group

The last piece of work is to enable and launch the daemons :

$ rcctl enable ypldap ypbind portmap
$ rcctl start ypldap ypbind portmap

I also rebooted to make sure all bricks were perfectly sealed together.

Authentication

Users should be correctly mapped to the system :

$ id calvin
uid=123456789(calvin) gid=123456789(calvin) groups=123456789(calvin), 9876543(mvp)
$ getent passwd | grep -i calvin
calvin:*:123456789:123456789:CALVIN Tom:/srv/home/calvin:/bin/ksh
$ su - calvin
$ whoami
calvin

From now on, it is possible to connect on the system with LDAP users in tty or OpenSSH. Have fun.