-
Notifications
You must be signed in to change notification settings - Fork 95
/
auth.go
113 lines (105 loc) · 3.6 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
package main
import (
"errors"
"fmt"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"golang.org/x/crypto/ssh"
)
var authAttemptsMetric = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "sshesame_auth_attempts_total",
Help: "Total number of authentication attempts",
}, []string{"method", "accepted"})
func (cfg *config) getAuthLogCallback() func(conn ssh.ConnMetadata, method string, err error) {
return func(conn ssh.ConnMetadata, method string, err error) {
var acceptedLabel string
if err == nil {
acceptedLabel = "true"
} else {
acceptedLabel = "false"
}
authAttemptsMetric.WithLabelValues(method, acceptedLabel).Inc()
if method == "none" {
connContext{ConnMetadata: conn, cfg: cfg}.logEvent(noAuthLog{authLog: authLog{
User: conn.User(),
Accepted: err == nil,
}})
}
}
}
func (cfg *config) getPasswordCallback() func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
if !cfg.Auth.PasswordAuth.Enabled {
return nil
}
return func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
connContext{ConnMetadata: conn, cfg: cfg}.logEvent(passwordAuthLog{
authLog: authLog{
User: conn.User(),
Accepted: authAccepted(cfg.Auth.PasswordAuth.Accepted),
},
Password: string(password),
})
if !cfg.Auth.PasswordAuth.Accepted {
return nil, errors.New("")
}
return nil, nil
}
}
func (cfg *config) getPublicKeyCallback() func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
if !cfg.Auth.PublicKeyAuth.Enabled {
return nil
}
return func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
connContext{ConnMetadata: conn, cfg: cfg}.logEvent(publicKeyAuthLog{
authLog: authLog{
User: conn.User(),
Accepted: authAccepted(cfg.Auth.PublicKeyAuth.Accepted),
},
PublicKeyFingerprint: ssh.FingerprintSHA256(key),
})
if !cfg.Auth.PublicKeyAuth.Accepted {
return nil, errors.New("")
}
return nil, nil
}
}
func (cfg *config) getKeyboardInteractiveCallback() func(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
if !cfg.Auth.KeyboardInteractiveAuth.Enabled {
return nil
}
var keyboardInteractiveQuestions []string
var keyboardInteractiveEchos []bool
for _, question := range cfg.Auth.KeyboardInteractiveAuth.Questions {
keyboardInteractiveQuestions = append(keyboardInteractiveQuestions, question.Text)
keyboardInteractiveEchos = append(keyboardInteractiveEchos, question.Echo)
}
return func(conn ssh.ConnMetadata, client ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
answers, err := client(conn.User(), cfg.Auth.KeyboardInteractiveAuth.Instruction, keyboardInteractiveQuestions, keyboardInteractiveEchos)
if err != nil {
warningLogger.Printf("Failed to process keyboard interactive authentication: %v", err)
return nil, errors.New("")
}
connContext{ConnMetadata: conn, cfg: cfg}.logEvent(keyboardInteractiveAuthLog{
authLog: authLog{
User: conn.User(),
Accepted: authAccepted(cfg.Auth.KeyboardInteractiveAuth.Accepted),
},
Answers: answers,
})
if !cfg.Auth.KeyboardInteractiveAuth.Accepted {
return nil, errors.New("")
}
return nil, nil
}
}
func (cfg *config) getBannerCallback() func(conn ssh.ConnMetadata) string {
if cfg.SSHProto.Banner == "" {
return nil
}
banner := strings.ReplaceAll(strings.ReplaceAll(cfg.SSHProto.Banner, "\r\n", "\n"), "\n", "\r\n")
if !strings.HasSuffix(banner, "\r\n") {
banner = fmt.Sprintf("%v\r\n", banner)
}
return func(conn ssh.ConnMetadata) string { return banner }
}