/
conn_ssh_su.go
182 lines (147 loc) · 3.39 KB
/
conn_ssh_su.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package srvconn
import (
"errors"
"fmt"
"strings"
)
func LoginToSSHSu(sc *SSHConnection) error {
cfg := sc.options.suConfig
suService, err := NewSuService(cfg, sc)
if err != nil {
return err
}
switch cfg.MethodType {
case SuMethodSu, SuMethodSudo:
startCmd := cfg.SuCommand()
suService.execCommand = func() {
_ = sc.session.Start(startCmd)
}
default:
_ = sc.session.Shell()
}
return suService.RunSwitchUser()
}
type ExecuteResult struct {
Finished bool
Err error
}
func createLinuxSuccessPattern(username string) string {
pattern := fmt.Sprintf("%s@", username)
pattern = fmt.Sprintf("(?i)%s|%s|%s", pattern,
normalUserMark, superUserMark)
return pattern
}
func createCiscoSuccessPattern(username string) string {
return fmt.Sprintf("%s|%s", normalUserMark, superUserMark)
}
func createHuaweiH3CSuccessPattern(username string) string {
return huaweiH3CPs1Mark
}
const (
normalUserMark = "\\s*\\$"
superUserMark = "\\s*#"
)
const (
/*
huawei、h3c 的终端提示符
*/
huaweiH3CPs1Mark = "^<.*>"
)
const (
/*
Linux 相关
*/
LinuxSuCommand = "su - %s; exit"
LinuxSudoCommand = "sudo su - %s; exit"
/*
Cisco 相关
*/
SuCommandEnable = "enable"
/*
huawei 相关
*/
SuCommandSuper = "super 15"
/*
h3c super 相关
*/
SuCommandSuperH3C = "super level-15"
/*
\b: word boundary 即: 匹配某个单词边界
*/
passwordMatchPattern = "(?i)\\bpassword\\b\\s*|密码|password"
usernameMatchPattern = "(?i)username:?\\s*$|name:?\\s*$|用户名:?\\s*$"
)
// 收集完善切换用户失败的提示信息
var switchPasswordFailures = []string{
"password has not been set",
"wrong\\s*passwords",
"bad\\s*secrets",
"access\\s*denied",
"authentication\\s*failure",
"invalid\\s*password",
}
func createFailedPattern() string {
allFailure := strings.Join(switchPasswordFailures, "|")
return fmt.Sprintf("(?i)%s", allFailure)
}
var ErrorTimeout = errors.New("i/o timeout")
type SUMethodType string
const (
SuMethodSudo SUMethodType = "sudo"
SuMethodSu SUMethodType = "su"
SuMethodEnable SUMethodType = "enable"
SuMethodSuper SUMethodType = "super"
SuMethodSuperLevel SUMethodType = "super_level"
)
func NewSuMethodType(suMethod string) SUMethodType {
method := strings.ToLower(suMethod)
switch method {
case "enable":
return SuMethodEnable
case "super":
return SuMethodSuper
case "super_level":
return SuMethodSuperLevel
case "su":
return SuMethodSu
case "sudo":
return SuMethodSudo
default:
}
return SuMethodSu
}
type SuConfig struct {
MethodType SUMethodType
SudoUsername string
SudoPassword string
}
func (s *SuConfig) SuCommand() string {
switch s.MethodType {
case SuMethodEnable:
return SuCommandEnable
case SuMethodSuper:
return SuCommandSuper
case SuMethodSuperLevel:
return SuCommandSuperH3C
case SuMethodSudo:
return fmt.Sprintf(LinuxSudoCommand, s.SudoUsername)
default:
}
return fmt.Sprintf(LinuxSuCommand, s.SudoUsername)
}
func (s *SuConfig) UsernameMatchPattern() string {
return usernameMatchPattern
}
func (s *SuConfig) PasswordMatchPattern() string {
return passwordMatchPattern
}
func (s *SuConfig) SuccessPattern() string {
switch s.MethodType {
case SuMethodEnable:
return createCiscoSuccessPattern(s.SudoUsername)
case SuMethodSuper, SuMethodSuperLevel:
return createHuaweiH3CSuccessPattern(s.SudoUsername)
default:
}
return createLinuxSuccessPattern(s.SudoUsername)
}