mirror of
https://github.com/netauth/ldap.git
synced 2026-11-03 11:43:44 -06:00
An LDAP client only accepts the result that pairs with the request it
sent, and silently ignores anything else. Unrouted operations were
answered with a generic result, which encodes with the wrong tag, so a
search with an unexpected base DN (for example the empty base that
ldapsearch uses when -b is omitted) left the client waiting forever
instead of reporting an error.
Every failure path now terminates the request with the matching result
type, panics included, so a single wrapper covers all operations rather
than one responder per operation. NetAuth calls carry a 30s deadline
because the gRPC client dials lazily and applies none of its own, and
refused operations and failed authentication are logged, which is what
an operator needs when a client appears to hang.
💘 Generated with Crush
Assisted-by: Crush:qwen38_flash_next_mtp
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package ldap
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
ldap "github.com/vjeantet/ldapserver"
|
|
)
|
|
|
|
// rpcTimeout bounds every NetAuth call made on behalf of one client
|
|
// request. The gRPC client dials lazily and never applies its own
|
|
// deadline, so without this a stalled server socket hangs the handler
|
|
// goroutine and the LDAP client behind it forever.
|
|
const rpcTimeout = 30 * time.Second
|
|
|
|
func (s *server) handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
|
|
defer cancel()
|
|
|
|
r := m.GetBindRequest()
|
|
// The server only supports simple auth, no SASL or anything
|
|
// fancy because we are after all just fronting another
|
|
// protocol.
|
|
if r.AuthenticationChoice() != "simple" {
|
|
s.markUnbound(m)
|
|
res := ldap.NewBindResponse(ldap.LDAPResultUnwillingToPerform)
|
|
res.SetDiagnosticMessage("Authentication choice not supported")
|
|
w.Write(res)
|
|
return
|
|
}
|
|
|
|
s.l.Debug("Bind from dn", "dn", r.Name())
|
|
|
|
if s.allowAnon && r.Name() == "" {
|
|
s.markBound(m)
|
|
res := ldap.NewBindResponse(ldap.LDAPResultSuccess)
|
|
w.Write(res)
|
|
return
|
|
}
|
|
|
|
entityID, err := s.entityIDFromDN(r.Name())
|
|
if err != nil {
|
|
s.markUnbound(m)
|
|
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 {
|
|
s.l.Warn("NetAuth authentication failed", "id", entityID, "error", err)
|
|
s.markUnbound(m)
|
|
res := ldap.NewBindResponse(ldap.LDAPResultInvalidCredentials)
|
|
res.SetDiagnosticMessage("invalid credentials")
|
|
w.Write(res)
|
|
return
|
|
}
|
|
|
|
s.markBound(m)
|
|
res := ldap.NewBindResponse(ldap.LDAPResultSuccess)
|
|
w.Write(res)
|
|
}
|