2020-10-09 20:36:02 +00:00
|
|
|
// Package ldap provides a LDAP authentification backend
|
2020-09-22 09:42:57 +00:00
|
|
|
package ldap
|
|
|
|
|
2020-09-22 10:54:12 +00:00
|
|
|
import (
|
|
|
|
"github.com/go-ldap/ldap/v3"
|
2020-12-06 12:36:24 +00:00
|
|
|
"log"
|
2021-01-03 04:07:25 +00:00
|
|
|
"strings"
|
2020-09-22 10:54:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Options holds package configuration
|
2020-09-22 09:42:57 +00:00
|
|
|
type Options struct {
|
2021-01-03 04:07:25 +00:00
|
|
|
Aliases map[string]map[string]string
|
2020-12-06 12:36:24 +00:00
|
|
|
URI string
|
|
|
|
UserDn string
|
2020-09-22 09:42:57 +00:00
|
|
|
}
|
2020-09-22 10:54:12 +00:00
|
|
|
|
|
|
|
// LDAP authentification backend
|
|
|
|
type LDAP struct {
|
2020-09-22 12:16:52 +00:00
|
|
|
Cfg *Options
|
|
|
|
Conn *ldap.Conn
|
2020-09-22 10:54:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Login tries to bind to LDAP
|
|
|
|
// Returns (true, nil) if success
|
2021-01-08 21:23:33 +00:00
|
|
|
func (a LDAP) Login(username string, password string) (bool, string, error) {
|
2021-01-03 04:07:25 +00:00
|
|
|
aliasSplit := strings.SplitN(username, "__", 2)
|
|
|
|
potentialUsernames := []string{username}
|
|
|
|
|
2021-01-08 21:23:33 +00:00
|
|
|
if len(aliasSplit) == 2 {
|
2021-01-03 04:07:25 +00:00
|
|
|
alias := aliasSplit[0]
|
|
|
|
trueUsername := aliasSplit[1]
|
|
|
|
// Resolve stream alias if necessary
|
|
|
|
if aliases, ok := a.Cfg.Aliases[alias]; ok {
|
|
|
|
if _, ok := aliases[trueUsername]; ok {
|
|
|
|
log.Printf("[LDAP] Use stream alias %s for username %s", alias, trueUsername)
|
|
|
|
potentialUsernames = append(potentialUsernames, trueUsername)
|
|
|
|
}
|
|
|
|
}
|
2020-12-06 12:36:24 +00:00
|
|
|
}
|
|
|
|
|
2021-01-03 04:07:25 +00:00
|
|
|
var err error = nil
|
|
|
|
for _, username := range potentialUsernames {
|
|
|
|
// Try to bind as user
|
|
|
|
bindDn := "cn=" + username + "," + a.Cfg.UserDn
|
2021-01-08 21:56:19 +00:00
|
|
|
log.Printf("[LDAP] Logging to %s...", bindDn)
|
2021-01-03 04:07:25 +00:00
|
|
|
err = a.Conn.Bind(bindDn, password)
|
|
|
|
if err == nil {
|
|
|
|
// Login succeeded if no error
|
2021-01-08 21:23:33 +00:00
|
|
|
return true, aliasSplit[0], nil
|
2021-01-03 04:07:25 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-22 10:54:12 +00:00
|
|
|
|
2021-01-08 22:05:01 +00:00
|
|
|
log.Printf("[LDAP] Logging failed: %s", err)
|
2021-01-03 04:07:25 +00:00
|
|
|
// Unable to log in
|
2021-01-08 21:23:33 +00:00
|
|
|
return err == nil, "", err
|
2020-09-22 10:54:12 +00:00
|
|
|
}
|
2020-09-22 12:16:52 +00:00
|
|
|
|
|
|
|
// Close LDAP connection
|
|
|
|
func (a LDAP) Close() {
|
|
|
|
a.Conn.Close()
|
|
|
|
}
|
|
|
|
|
2020-09-22 14:39:06 +00:00
|
|
|
// New instanciates a new LDAP connection
|
|
|
|
func New(cfg *Options) (LDAP, error) {
|
2020-09-22 12:16:52 +00:00
|
|
|
backend := LDAP{Cfg: cfg}
|
|
|
|
|
|
|
|
// Connect to LDAP server
|
|
|
|
c, err := ldap.DialURL(backend.Cfg.URI)
|
|
|
|
backend.Conn = c
|
|
|
|
return backend, err
|
|
|
|
}
|