Raw
 1package ldap
 2
 3import (
 4	"net"
 5	"net/netip"
 6	"time"
 7
 8	"tug/internal/platform/ratelimit"
 9	fk "tug/internal/transport/ldap/internal/glauthldap"
10)
11
12const (
13	peerBurst   = 20
14	peerEvery   = 6 * time.Second
15	peerEntries = 10000
16)
17
18type peerLimit struct {
19	table *ratelimit.Table[netip.Prefix]
20	rate  ratelimit.Rate
21}
22
23func newPeerLimit(now func() time.Time, rate ratelimit.Rate, max int) *peerLimit {
24	return &peerLimit{table: ratelimit.New[netip.Prefix](max, now), rate: rate}
25}
26
27func peerAddr(conn net.Conn) netip.Addr {
28	ap, err := netip.ParseAddrPort(conn.RemoteAddr().String())
29	if err != nil {
30		return netip.Addr{}
31	}
32	return ap.Addr().WithZone("").Unmap()
33}
34
35func (s *Server) bindFrom(addr netip.Addr, bindDN, bindSimplePw string) (fk.LDAPResultCode, string) {
36	peer := ratelimit.Prefix(addr)
37	if _, ok := s.peers.table.Allowed(peer, s.peers.rate); !ok {
38		return fk.LDAPResultBusy, bindLimited
39	}
40	code, result, userID := s.bind(bindDN, bindSimplePw)
41	s.auditBind(addr, result, userID)
42	if result == bindRejected {
43		s.peers.table.Take(peer, s.peers.rate)
44	}
45	return code, result
46}