forked from shazow/ssh-chat
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathauth.go
153 lines (133 loc) · 3.62 KB
/
auth.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package sshchat
import (
"errors"
"net"
"time"
"github.com/shazow/ssh-chat/set"
"github.com/shazow/ssh-chat/sshd"
"golang.org/x/crypto/ssh"
)
// The error returned a key is checked that is not whitelisted, with whitelisting required.
var ErrNotWhitelisted = errors.New("not whitelisted")
// The error returned a key is checked that is banned.
var ErrBanned = errors.New("banned")
// newAuthKey returns string from an ssh.PublicKey used to index the key in our lookup.
func newAuthKey(key ssh.PublicKey) string {
if key == nil {
return ""
}
// FIXME: Is there a better way to index pubkeys without marshal'ing them into strings?
return sshd.Fingerprint(key)
}
func newAuthItem(key ssh.PublicKey) set.Item {
return set.StringItem(newAuthKey(key))
}
// newAuthAddr returns a string from a net.Addr used to index the address the key in our lookup.
func newAuthAddr(addr net.Addr) string {
if addr == nil {
return ""
}
host, _, _ := net.SplitHostPort(addr.String())
return host
}
// Auth stores lookups for bans, whitelists, and ops. It implements the sshd.Auth interface.
type Auth struct {
bannedAddr *set.Set
banned *set.Set
whitelist *set.Set
ops *set.Set
}
// NewAuth creates a new empty Auth.
func NewAuth() *Auth {
return &Auth{
bannedAddr: set.New(),
banned: set.New(),
whitelist: set.New(),
ops: set.New(),
}
}
// AllowAnonymous determines if anonymous users are permitted.
func (a *Auth) AllowAnonymous() bool {
return a.whitelist.Len() == 0
}
// Check determines if a pubkey fingerprint is permitted.
func (a *Auth) Check(addr net.Addr, key ssh.PublicKey) (bool, error) {
authkey := newAuthKey(key)
if a.whitelist.Len() != 0 {
// Only check whitelist if there is something in it, otherwise it's disabled.
whitelisted := a.whitelist.In(authkey)
if !whitelisted {
return false, ErrNotWhitelisted
}
return true, nil
}
banned := a.banned.In(authkey)
if !banned {
banned = a.bannedAddr.In(newAuthAddr(addr))
}
if banned {
return false, ErrBanned
}
return true, nil
}
// Op sets a public key as a known operator.
func (a *Auth) Op(key ssh.PublicKey, d time.Duration) {
if key == nil {
return
}
authItem := newAuthItem(key)
if d != 0 {
a.ops.Add(set.Expire(authItem, d))
} else {
a.ops.Add(authItem)
}
logger.Debugf("Added to ops: %s (for %s)", authItem.Key(), d)
}
// IsOp checks if a public key is an op.
func (a *Auth) IsOp(key ssh.PublicKey) bool {
if key == nil {
return false
}
authkey := newAuthKey(key)
return a.ops.In(authkey)
}
// Whitelist will set a public key as a whitelisted user.
func (a *Auth) Whitelist(key ssh.PublicKey, d time.Duration) {
if key == nil {
return
}
authItem := newAuthItem(key)
if d != 0 {
a.whitelist.Add(set.Expire(authItem, d))
} else {
a.whitelist.Add(authItem)
}
logger.Debugf("Added to whitelist: %s (for %s)", authItem.Key(), d)
}
// Ban will set a public key as banned.
func (a *Auth) Ban(key ssh.PublicKey, d time.Duration) {
if key == nil {
return
}
a.BanFingerprint(newAuthKey(key), d)
}
// BanFingerprint will set a public key fingerprint as banned.
func (a *Auth) BanFingerprint(authkey string, d time.Duration) {
authItem := set.StringItem(authkey)
if d != 0 {
a.banned.Add(set.Expire(authItem, d))
} else {
a.banned.Add(authItem)
}
logger.Debugf("Added to banned: %s (for %s)", authItem.Key(), d)
}
// Ban will set an IP address as banned.
func (a *Auth) BanAddr(addr net.Addr, d time.Duration) {
authItem := set.StringItem(addr.String())
if d != 0 {
a.bannedAddr.Add(set.Expire(authItem, d))
} else {
a.bannedAddr.Add(authItem)
}
logger.Debugf("Added to bannedAddr: %s (for %s)", authItem.Key(), d)
}