OATH-LDAP

Download

oathldap-tool
Command-line tool implementing various use-cases via sub-commands

Installation

Prerequisites

Command-line tool

For first tests simply create a separate Python virtualenv (herein it is directory /opt/oathldap):

$ virtualenv-2.7 /opt/oathldap
New python executable in /opt/oathldap/bin/python2
Also creating executable in /opt/oathldap/bin/python
Installing setuptools, pip, wheel...done.

Now install oathldap package:

$ /opt/oathldap/bin/pip2 install oathldap-tool
[..lots of output..]

The CLI tool shows available sub-commands:

$ /opt/oathldap/bin/oathldap-tool
usage: oathldap [-h] {genkey,ykinfo,ykadd,ykinit} ...
oathldap: error: too few arguments

You should encrypt the shared secrets (seeds) in attribute oathSecret. For this you generate a key pair used for seed encryption during enrollment on a secured system and transfer the private key to the OATH-LDAP providers over a secure channel.

$ mkdir -p /etc/oath-ldap/master-secrets
$ chmod 0600 /etc/oath-ldap/master-secrets
$ /opt/oathldap/bin/oathldap-tool genkey --key-path /etc/oath-ldap/master-secrets
Generate RSA-2048 key pair...
wrote /etc/oath-ldap/master-secrets/oathldap_master_key_201712281902.priv
wrote /etc/oath-ldap/master-secrets/oathldap_master_key_201712281902.pub

The filenames (here oathldap_master_key_201712281902) are generated based on timestamps and are also used as JWK key identifier (see RFC 7517 and RFC 7516).

slapd listeners

For OpenLDAP configuration instructions see slapd-sock(5).

bind_proxy.py

Used as overlay it intercepts BIND requests and passes the simple bind request to a remote LDAP server if a configurable LDAP filter is matched.

Start listener demon:

DEBUG=no /path/to/bind_proxy.py \
  /path/to/socket \
  ldapi:///????x-saslmech=EXTERNAL \
  ldaps://remote-ldap.example.com/????x-saslmech=EXTERNAL

hotp_validator.py

Used as overlay it intercepts BIND requests and checks a combined password against password hash in attribute userPassword and the HOTP value against counters and shared secret stored in user entry.

Start listener demon:

DEBUG=no /path/to/hotp_validator.py \
  /path/to/socket \
  ldapi:///????x-saslmech=EXTERNAL