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}