-
-
Notifications
You must be signed in to change notification settings - Fork 66
/
Copy pathhandlers.go
121 lines (101 loc) · 3.53 KB
/
handlers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package stunner
import (
"errors"
"net"
"github.com/l7mp/stunner/internal/object"
"github.com/l7mp/stunner/internal/util"
stnrv1 "github.com/l7mp/stunner/pkg/apis/v1"
a12n "github.com/l7mp/stunner/pkg/authentication"
)
// NewAuthHandler returns an authentication handler callback to be used with a TURN server for
// authenticating clients.
func (s *Stunner) NewAuthHandler() a12n.AuthHandler {
s.log.Trace("NewAuthHandler")
return func(username string, realm string, srcAddr net.Addr) ([]byte, bool) {
// dynamic: auth mode might have changed behind ur back
auth := s.GetAuth()
switch auth.Type {
case stnrv1.AuthTypeStatic:
auth.Log.Infof("static auth request: username=%q realm=%q srcAddr=%v\n",
username, realm, srcAddr)
key := a12n.GenerateAuthKey(auth.Username, auth.Realm, auth.Password)
if username == auth.Username {
auth.Log.Debug("static auth request: valid username")
return key, true
}
auth.Log.Info("static auth request: failed: invalid username")
return nil, false
case stnrv1.AuthTypeEphemeral:
auth.Log.Infof("ephemeral auth request: username=%q realm=%q srcAddr=%v",
username, realm, srcAddr)
if err := a12n.CheckTimeWindowedUsername(username); err != nil {
auth.Log.Infof("ephemeral auth request: failed: %s", err)
return nil, false
}
password, err := a12n.GetLongTermCredential(username, auth.Secret)
if err != nil {
auth.Log.Infof("ephemeral auth request: error generating password: %s",
err)
return nil, false
}
auth.Log.Info("ephemeral auth request: success")
return a12n.GenerateAuthKey(username, auth.Realm, password), true
default:
auth.Log.Errorf("internal error: unknown authentication mode %q",
auth.Type.String())
return nil, false
}
}
}
// NewPermissionHandler returns a callback to handle client permission requests to access peers.
func (s *Stunner) NewPermissionHandler(l *object.Listener) a12n.PermissionHandler {
s.log.Trace("NewPermissionHandler")
return func(src net.Addr, peer net.IP) bool {
// need auth for logging
// dynamic: authHandler might have changed behind ur back
auth := s.GetAuth()
peerIP := peer.String()
auth.Log.Debugf("permission handler for listener %q: client %q, peer %q", l.Name,
src.String(), peerIP)
clusters := s.clusterManager.Keys()
for _, r := range l.Routes {
auth.Log.Tracef("considering route to cluster %q", r)
if util.Member(clusters, r) {
auth.Log.Tracef("considering cluster %q", r)
c := s.GetCluster(r)
if c.Route(peer) {
auth.Log.Infof("permission granted on listener %q for client "+
"%q to peer %s via cluster %q", l.Name, src.String(),
peerIP, c.Name)
return true
}
}
}
auth.Log.Debugf("permission denied on listener %q for client %q to peer %s: "+
"no route to endpoint", l.Name, src.String(), peerIP)
return false
}
}
// NewReadinessHandler creates a helper function for checking the readiness of STUNner.
func (s *Stunner) NewReadinessHandler() object.ReadinessHandler {
return func() error {
if s.IsReady() {
return nil
} else {
return errors.New("stunnerd not ready")
}
}
}
// NewRealmHandler creates a helper function for listeners to find out the authentication realm.
func (s *Stunner) NewRealmHandler() object.RealmHandler {
return func() string {
if s != nil {
return s.GetRealm()
}
return ""
}
}
// NewStatusHandler creates a helper function for printing the status of STUNner.
func (s *Stunner) NewStatusHandler() object.StatusHandler {
return func() stnrv1.Status { return s.Status() }
}