@@ -16,15 +16,6 @@ import (
16
16
"golang.org/x/crypto/ssh"
17
17
)
18
18
19
- /*
20
- This global variable is only used in two methods: publicKeyCallback, handleChannels.
21
- Such a workaround is needed because there is no way to find out what public key
22
- the user has when processing channels (the token is passed there). Although SSH
23
- provides the User value, it cannot be changed and is passed from the user side.
24
- And we need the ability to assign any username for the key
25
- */
26
- var sshAddrToUsername sync.Map
27
-
28
19
// Tokens that the browser generates and the user passes to us
29
20
var (
30
21
ssh_tokens = map [string ]SSH_Token_Info {}
@@ -92,7 +83,8 @@ func startSshServer() {
92
83
// Checks if the public key is in `authorized_keys` list
93
84
func publicKeyCallback (sshConn ssh.ConnMetadata , remoteKey ssh.PublicKey ) (* ssh.Permissions , error ) {
94
85
log .Printf ("Trying to auth: %s (%s::%s) - %s " , sshConn .User (), sshConn .ClientVersion (), remoteKey .Type (), sshConn .RemoteAddr ())
95
- for username , localKey := range authorized_keys {
86
+ // TODO Do not show knowledge of public keys, somehow require the client to confirm the private key
87
+ for _ , localKey := range authorized_keys {
96
88
// Make sure the key types match
97
89
if remoteKey .Type () != localKey .keyType {
98
90
continue
@@ -115,11 +107,13 @@ func publicKeyCallback(sshConn ssh.ConnMetadata, remoteKey ssh.PublicKey) (*ssh.
115
107
continue
116
108
}
117
109
// Now we know user
118
- sshAddrToUsername .Store (sshConn .RemoteAddr ().String (), username )
119
- log .Printf ("Public key match: %s" , username )
120
- return nil , nil
110
+ log .Printf ("Public key match: %s" , localKey .username )
111
+ // TODO can client send Extensions?
112
+ perm := ssh.Permissions {Extensions : make (map [string ]string )}
113
+ perm .Extensions ["username" ] = localKey .username
114
+ return & perm , nil
121
115
}
122
- return nil , errors .New ("not authorized key" )
116
+ return nil , errors .New (yellow ( "not authorized key" ) )
123
117
}
124
118
125
119
// This is called for already authenticated(via publicKeyCallback) users
@@ -138,20 +132,8 @@ func handleChannels(sshConn ssh.ServerConn, channels <-chan ssh.NewChannel) {
138
132
log .Printf ("could not accept channel (%s)" , err )
139
133
continue
140
134
}
141
-
142
135
// Get the previously(in publicKeyCallback) saved username
143
- addr := sshConn .RemoteAddr ().String ()
144
- tmp , ok := sshAddrToUsername .Load (addr )
145
- // It shouldn't be possible. But we'll be safe
146
- if ! ok {
147
- channel .Close ()
148
- }
149
- // Deletion is not necessary for security, because even if user logs in
150
- // under a different name from same address, value in `map` will change.
151
- // And the call to this method always occurs after checking public key.
152
- // Just saves some memory
153
- sshAddrToUsername .Delete (addr )
154
- username := tmp .(string )
136
+ username := sshConn .Permissions .Extensions ["username" ]
155
137
fmt .Fprintf (channel , "Authenticated username: %s \n " , username )
156
138
157
139
// Typically SSH sessions have out-of-band requests such as "shell", "pty-req" and "env"
@@ -182,7 +164,7 @@ func handleChannels(sshConn ssh.ServerConn, channels <-chan ssh.NewChannel) {
182
164
// Show the user some animation and check the connection at the same time
183
165
_ , err := fmt .Fprint (channel , "." )
184
166
if err != nil {
185
- log .Printf ("The SSH connection to user `%s` has been terminated" , username )
167
+ log .Printf (yellow ( "The SSH connection to user `%s` has been terminated" ) , username )
186
168
break
187
169
}
188
170
// Lock and read from global var
@@ -237,7 +219,10 @@ func loadAuthorizedKeys(filename string) {
237
219
if err != nil {
238
220
log .Fatal (err )
239
221
}
240
- authorized_keys [name ] = SSH_Info {key .Type (), key .Marshal (), nil }
222
+ authorized_keys = append (authorized_keys , SSH_Info {
223
+ keyType : key .Type (),
224
+ keyData : key .Marshal (),
225
+ username : name })
241
226
}
242
227
} else {
243
228
log .Fatalf ("SSH: Can't open %s" , filename )
0 commit comments