Add LDAP support

This commit is contained in:
Matt Ouille 2020-02-09 00:17:10 -08:00 committed by Shivaram Lingamneni
parent 634470ba30
commit d4afb027e5
2 changed files with 98 additions and 1 deletions

View File

@ -4,6 +4,7 @@
package irc package irc
import ( import (
"crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/smtp" "net/smtp"
@ -14,6 +15,7 @@ import (
"time" "time"
"unicode" "unicode"
"github.com/go-ldap/ldap"
"github.com/oragono/oragono/irc/caps" "github.com/oragono/oragono/irc/caps"
"github.com/oragono/oragono/irc/passwd" "github.com/oragono/oragono/irc/passwd"
"github.com/oragono/oragono/irc/utils" "github.com/oragono/oragono/irc/utils"
@ -828,8 +830,80 @@ func (am *AccountManager) checkPassphrase(accountName, passphrase string) (accou
return return
} }
func (am *AccountManager) checkLDAPPassphrase(accountName, passphrase string) (account ClientAccount, err error) {
var (
host, url string
port int
)
host = am.server.AccountConfig().LDAP.Servers.Host
port = am.server.AccountConfig().LDAP.Servers.Port
account, err = am.LoadAccount(accountName)
if err != nil {
return
}
if !account.Verified {
err = errAccountUnverified
return
}
if am.server.AccountConfig().LDAP.Servers.UseSSL {
url = fmt.Sprintf("ldaps://%s:%d", host, port)
} else {
url = fmt.Sprintf("ldap://%s:%d", host, port)
}
l, err := ldap.DialURL(url)
if err != nil {
return
}
defer l.Close()
if am.server.AccountConfig().LDAP.Servers.StartTLS {
err = l.StartTLS(&tls.Config{InsecureSkipVerify: am.server.AccountConfig().LDAP.Servers.SkipTLSVerify})
if err != nil {
return
}
}
err = l.Bind(am.server.AccountConfig().LDAP.BindDN, am.server.AccountConfig().LDAP.BindPwd)
if err != nil {
return
}
for _, baseDN := range am.server.AccountConfig().LDAP.SearchBaseDNs {
req := ldap.NewSearchRequest(baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, am.server.AccountConfig().LDAP.Timeout, false, fmt.Sprintf("(&(objectClass=organizationalPerson)(uid=%s))", accountName), []string{"dn"}, nil)
sr, err := l.Search(req)
if err != nil {
return
}
userdn := sr.Entries[0].DN
if len(sr.Entries) > 0 {
// verify the user passphrase
err = l.Bind(userdn, passphrase)
if err != nil {
continue
}
break
}
}
return
}
func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName string, passphrase string) error { func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName string, passphrase string) error {
account, err := am.checkPassphrase(accountName, passphrase) var account ClientAccount
var err error
if am.server.AccountConfig().LDAP.Enabled {
account, err = am.checkLDAPPassphrase(accountName, passphrase)
}
account, err = am.checkPassphrase(accountName, passphrase)
if err != nil { if err != nil {
return err return err
} }

View File

@ -68,6 +68,7 @@ type AccountConfig struct {
Exempted []string Exempted []string
exemptedNets []net.IPNet exemptedNets []net.IPNet
} `yaml:"require-sasl"` } `yaml:"require-sasl"`
LDAP LDAPConfig
LoginThrottling struct { LoginThrottling struct {
Enabled bool Enabled bool
Duration time.Duration Duration time.Duration
@ -82,6 +83,28 @@ type AccountConfig struct {
VHosts VHostConfig VHosts VHostConfig
} }
type LDAPConfig struct {
Timeout int
Enabled bool
AllowSignup bool `yaml:"allow-signup"`
BindDN string `yaml:"bind-dn"`
BindPwd string `yaml:"bind-password"`
SearchFilter string `yaml:"search-filter"`
SearchBaseDNs []string `yaml:"search-base-dns"`
Attributes map[string]string
Servers LDAPServerConfig
}
type LDAPServerConfig struct {
Host string
Port int
UseSSL bool `yaml:"use-ssl"`
StartTLS bool `yaml:"start-tls"`
SkipTLSVerify bool `yaml:"skip-tls-verify"`
ClientCert string `yaml:"client-cert"`
ClientKey string `yaml:"client-key"`
}
// AccountRegistrationConfig controls account registration. // AccountRegistrationConfig controls account registration.
type AccountRegistrationConfig struct { type AccountRegistrationConfig struct {
Enabled bool Enabled bool