internal/ldap: Handle bind
This commit is contained in:
parent
b3783dffb5
commit
83e78da739
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/hashicorp/go-hclog v0.9.2
|
github.com/hashicorp/go-hclog v0.9.2
|
||||||
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
|
||||||
github.com/netauth/netauth v0.3.4
|
github.com/netauth/netauth v0.3.4
|
||||||
github.com/ps78674/goldap v0.0.0-20200721080011-cd2e7ee23841
|
github.com/ps78674/goldap v0.0.0-20200721080011-cd2e7ee23841
|
||||||
github.com/ps78674/ldapserver v0.0.0-20200521101606-2395f680392c
|
github.com/ps78674/ldapserver v0.0.0-20200521101606-2395f680392c
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -52,6 +52,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
|
||||||
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
||||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
|
|
6
internal/buildinfo/info.go
Normal file
6
internal/buildinfo/info.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package buildinfo
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Version is the version this server.
|
||||||
|
Version = "dev"
|
||||||
|
)
|
|
@ -22,7 +22,16 @@ func (s *server) handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||||
|
|
||||||
s.l.Debug("Bind from dn", "dn", r.Name())
|
s.l.Debug("Bind from dn", "dn", r.Name())
|
||||||
|
|
||||||
if err := s.c.AuthEntity(ctx, entityIDFromDN(r.Name()), string(r.AuthenticationSimple())); err != nil {
|
entityID, err := s.entityIDFromDN(r.Name())
|
||||||
|
if err != nil {
|
||||||
|
res := ldap.NewBindResponse(ldap.LDAPResultInvalidDNSyntax)
|
||||||
|
res.SetDiagnosticMessage(err.Error())
|
||||||
|
s.l.Warn("Request with invalid DN", "dn", r.Name())
|
||||||
|
w.Write(res)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.c.AuthEntity(ctx, entityID, string(r.AuthenticationSimple())); err != nil {
|
||||||
res := ldap.NewBindResponse(ldap.LDAPResultInvalidCredentials)
|
res := ldap.NewBindResponse(ldap.LDAPResultInvalidCredentials)
|
||||||
res.SetDiagnosticMessage("invalid credentials")
|
res.SetDiagnosticMessage("invalid credentials")
|
||||||
w.Write(res)
|
w.Write(res)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ldap
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
|
@ -79,3 +80,17 @@ func (s *server) handleAbandon(w ldap.ResponseWriter, m *ldap.Message) {
|
||||||
requestToAbandon.Abandon()
|
requestToAbandon.Abandon()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *server) SetDomain(domain string) {
|
||||||
|
nc := "dc=netauth,"
|
||||||
|
parts := strings.Split(domain, ".")
|
||||||
|
for i := range parts {
|
||||||
|
nc += "dc=" + parts[i] + ","
|
||||||
|
}
|
||||||
|
nc = strings.TrimSuffix(nc, ",")
|
||||||
|
|
||||||
|
s.nc = strings.Split(nc, ",")
|
||||||
|
for i := range s.nc {
|
||||||
|
s.nc[i] = strings.TrimSpace(s.nc[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,17 +2,23 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ps78674/goldap/message"
|
||||||
ldap "github.com/ps78674/ldapserver"
|
ldap "github.com/ps78674/ldapserver"
|
||||||
|
|
||||||
|
"github.com/netauth/ldap/internal/buildinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleSearchDSE(w ldap.ResponseWriter, m *ldap.Message) {
|
func (s *server) handleSearchDSE(w ldap.ResponseWriter, m *ldap.Message) {
|
||||||
|
nc := strings.Join(s.nc, ", ")
|
||||||
|
|
||||||
e := ldap.NewSearchResultEntry("")
|
e := ldap.NewSearchResultEntry("")
|
||||||
e.AddAttribute("vendorName", "NetAuth")
|
e.AddAttribute("vendorName", "NetAuth")
|
||||||
e.AddAttribute("vendorVersion", "1.0")
|
e.AddAttribute("vendorVersion", message.AttributeValue(buildinfo.Version))
|
||||||
e.AddAttribute("objectClass", "top", "extensibleObject")
|
e.AddAttribute("objectClass", "top", "extensibleObject")
|
||||||
e.AddAttribute("supportedLDAPVersion", "3")
|
e.AddAttribute("supportedLDAPVersion", "3")
|
||||||
e.AddAttribute("namingContexts", "o=My Company, c=US")
|
e.AddAttribute("namingContexts", message.AttributeValue(nc))
|
||||||
w.Write(e)
|
w.Write(e)
|
||||||
|
|
||||||
res := ldap.NewSearchResultDoneResponse(ldap.LDAPResultSuccess)
|
res := ldap.NewSearchResultDoneResponse(ldap.LDAPResultSuccess)
|
||||||
|
|
|
@ -16,4 +16,6 @@ type server struct {
|
||||||
|
|
||||||
c naClient
|
c naClient
|
||||||
l hclog.Logger
|
l hclog.Logger
|
||||||
|
|
||||||
|
nc []string
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,34 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ps78674/goldap/message"
|
"github.com/ps78674/goldap/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func entityIDFromDN(message.LDAPDN) string {
|
// entityIDFromDN parses out an ID from a given DN. This only works
|
||||||
return ""
|
// for ID's that don't contain an escaped comma, but these aren't
|
||||||
|
// valid in NetAuth anyway, so this is taken as a known defect.
|
||||||
|
func (s *server) entityIDFromDN(dn message.LDAPDN) (string, error) {
|
||||||
|
parts := strings.Split(string(dn), ",")
|
||||||
|
for i := range parts {
|
||||||
|
parts[i] = strings.TrimSpace(parts[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(parts[0], "uid=") {
|
||||||
|
return "", errors.New("entity DN must start with uid=")
|
||||||
|
}
|
||||||
|
|
||||||
|
if parts[1] != "cn=entities" {
|
||||||
|
return "", errors.New("entity DN is underneath cn=entities")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, p := range parts[2:] {
|
||||||
|
if p != s.nc[i] {
|
||||||
|
return "", errors.New("queries must be rooted at " + strings.Join(s.nc, ","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimPrefix(parts[0], "uid="), nil
|
||||||
}
|
}
|
||||||
|
|
3
main.go
3
main.go
|
@ -42,6 +42,9 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ls := ldap.New(appLogger, nacl)
|
ls := ldap.New(appLogger, nacl)
|
||||||
|
|
||||||
|
ls.SetDomain("netauth.org")
|
||||||
|
|
||||||
if err := ls.Serve("localhost:10389"); err != nil {
|
if err := ls.Serve("localhost:10389"); err != nil {
|
||||||
appLogger.Error("Error serving", "error", err)
|
appLogger.Error("Error serving", "error", err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue