1
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
14
// authenticate authenticates with the remote server. See RFC 4252.
15
func (c *ClientConn) authenticate() error {
16
// initiate user auth session
17
if err := c.transport.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
20
packet, err := c.transport.readPacket()
24
var serviceAccept serviceAcceptMsg
25
if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
28
// during the authentication phase the client first attempts the "none" method
29
// then any untried methods suggested by the server.
30
tried, remain := make(map[string]bool), make(map[string]bool)
31
for auth := ClientAuth(new(noneAuth)); auth != nil; {
32
ok, methods, err := auth.auth(c.transport.sessionID, c.config.User, c.transport, c.config.rand())
40
tried[auth.method()] = true
41
delete(remain, auth.method())
42
for _, meth := range methods {
44
// if we've tried meth already, skip it.
50
for _, a := range c.config.Auth {
51
if remain[a.method()] {
57
return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
60
func keys(m map[string]bool) (s []string) {
67
// HostKeyChecker represents a database of known server host keys.
68
type HostKeyChecker interface {
69
// Check is called during the handshake to check server's
70
// public key for unexpected changes. The hostKey argument is
71
// in SSH wire format. It can be parsed using
72
// ssh.ParsePublicKey. The address before DNS resolution is
73
// passed in the addr argument, so the key can also be checked
74
// against the hostname.
75
Check(addr string, remote net.Addr, algorithm string, hostKey []byte) error
78
// A ClientAuth represents an instance of an RFC 4252 authentication method.
79
type ClientAuth interface {
80
// auth authenticates user over transport t.
81
// Returns true if authentication is successful.
82
// If authentication is not successful, a []string of alternative
83
// method names is returned.
84
auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
86
// method returns the RFC 4252 method name.
90
// "none" authentication, RFC 4252 section 5.2.
93
func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
94
if err := c.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
99
return false, nil, err
102
return handleAuthResponse(c)
105
func (n *noneAuth) method() string {
109
// "password" authentication, RFC 4252 Section 8.
110
type passwordAuth struct {
114
func (p *passwordAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
115
type passwordAuthMsg struct {
123
pw, err := p.Password(user)
125
return false, nil, err
128
if err := c.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
135
return false, nil, err
138
return handleAuthResponse(c)
141
func (p *passwordAuth) method() string {
145
// A ClientPassword implements access to a client's passwords.
146
type ClientPassword interface {
147
// Password returns the password to use for user.
148
Password(user string) (password string, err error)
151
// ClientAuthPassword returns a ClientAuth using password authentication.
152
func ClientAuthPassword(impl ClientPassword) ClientAuth {
153
return &passwordAuth{impl}
156
// ClientKeyring implements access to a client key ring.
157
type ClientKeyring interface {
158
// Key returns the i'th Publickey, or nil if no key exists at i.
159
Key(i int) (key PublicKey, err error)
161
// Sign returns a signature of the given data using the i'th key
162
// and the supplied random source.
163
Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
166
// "publickey" authentication, RFC 4252 Section 7.
167
type publickeyAuth struct {
171
type publickeyAuthMsg struct {
175
// HasSig indicates to the receiver packet that the auth request is signed and
176
// should be used for authentication of the request.
180
// Sig is defined as []byte so marshal will exclude it during validateKey
181
Sig []byte `ssh:"rest"`
184
func (p *publickeyAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
185
// Authentication is performed in two stages. The first stage sends an
186
// enquiry to test if each key is acceptable to the remote. The second
187
// stage attempts to authenticate with the valid keys obtained in the
191
// a map of public keys to their index in the keyring
192
validKeys := make(map[int]PublicKey)
194
key, err := p.Key(index)
196
return false, nil, err
199
// no more keys in the keyring
203
if ok, err := p.validateKey(key, user, c); ok {
204
validKeys[index] = key
207
return false, nil, err
213
// methods that may continue if this auth is not successful.
215
for i, key := range validKeys {
216
pubkey := MarshalPublicKey(key)
217
algoname := key.PublicKeyAlgo()
218
data := buildDataSignedForAuth(session, userAuthRequestMsg{
222
}, []byte(algoname), pubkey)
223
sigBlob, err := p.Sign(i, rand, data)
225
return false, nil, err
227
// manually wrap the serialized signature in a string
228
s := serializeSignature(key.PublicKeyAlgo(), sigBlob)
229
sig := make([]byte, stringLength(len(s)))
230
marshalString(sig, s)
231
msg := publickeyAuthMsg{
237
Pubkey: string(pubkey),
240
p := marshal(msgUserAuthRequest, msg)
241
if err := c.writePacket(p); err != nil {
242
return false, nil, err
244
success, methods, err := handleAuthResponse(c)
246
return false, nil, err
249
return success, methods, err
252
return false, methods, nil
255
// validateKey validates the key provided it is acceptable to the server.
256
func (p *publickeyAuth) validateKey(key PublicKey, user string, c packetConn) (bool, error) {
257
pubkey := MarshalPublicKey(key)
258
algoname := key.PublicKeyAlgo()
259
msg := publickeyAuthMsg{
265
Pubkey: string(pubkey),
267
if err := c.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
271
return p.confirmKeyAck(key, c)
274
func (p *publickeyAuth) confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
275
pubkey := MarshalPublicKey(key)
276
algoname := key.PublicKeyAlgo()
279
packet, err := c.readPacket()
284
case msgUserAuthBanner:
285
// TODO(gpaul): add callback to present the banner to the user
286
case msgUserAuthPubKeyOk:
287
msg := userAuthPubKeyOkMsg{}
288
if err := unmarshal(&msg, packet, msgUserAuthPubKeyOk); err != nil {
291
if msg.Algo != algoname || msg.PubKey != string(pubkey) {
295
case msgUserAuthFailure:
298
return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
304
func (p *publickeyAuth) method() string {
308
// ClientAuthKeyring returns a ClientAuth using public key authentication.
309
func ClientAuthKeyring(impl ClientKeyring) ClientAuth {
310
return &publickeyAuth{impl}
313
// handleAuthResponse returns whether the preceding authentication request succeeded
314
// along with a list of remaining authentication methods to try next and
315
// an error if an unexpected response was received.
316
func handleAuthResponse(c packetConn) (bool, []string, error) {
318
packet, err := c.readPacket()
320
return false, nil, err
324
case msgUserAuthBanner:
325
// TODO: add callback to present the banner to the user
326
case msgUserAuthFailure:
327
msg := userAuthFailureMsg{}
328
if err := unmarshal(&msg, packet, msgUserAuthFailure); err != nil {
329
return false, nil, err
331
return false, msg.Methods, nil
332
case msgUserAuthSuccess:
333
return true, nil, nil
335
return false, nil, io.EOF
337
return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
343
// ClientAuthAgent returns a ClientAuth using public key authentication via
345
func ClientAuthAgent(agent *AgentClient) ClientAuth {
346
return ClientAuthKeyring(&agentKeyring{agent: agent})
349
// agentKeyring implements ClientKeyring.
350
type agentKeyring struct {
355
func (kr *agentKeyring) Key(i int) (key PublicKey, err error) {
357
if kr.keys, err = kr.agent.RequestIdentities(); err != nil {
361
if i >= len(kr.keys) {
364
return kr.keys[i].Key()
367
func (kr *agentKeyring) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
369
if key, err = kr.Key(i); err != nil {
373
return nil, errors.New("ssh: key index out of range")
375
if sig, err = kr.agent.SignRequest(key, data); err != nil {
379
// Unmarshal the signature.
382
if _, sig, ok = parseString(sig); !ok {
383
return nil, errors.New("ssh: malformed signature response from agent")
385
if sig, _, ok = parseString(sig); !ok {
386
return nil, errors.New("ssh: malformed signature response from agent")
391
// ClientKeyboardInteractive should prompt the user for the given
393
type ClientKeyboardInteractive interface {
394
// Challenge should print the questions, optionally disabling
395
// echoing (eg. for passwords), and return all the answers.
396
// Challenge may be called multiple times in a single
397
// session. After successful authentication, the server may
398
// send a challenge with no questions, for which the user and
399
// instruction messages should be printed. RFC 4256 section
400
// 3.3 details how the UI should behave for both CLI and
402
Challenge(user, instruction string, questions []string, echos []bool) ([]string, error)
405
// ClientAuthKeyboardInteractive returns a ClientAuth using a
406
// prompt/response sequence controlled by the server.
407
func ClientAuthKeyboardInteractive(impl ClientKeyboardInteractive) ClientAuth {
408
return &keyboardInteractiveAuth{impl}
411
type keyboardInteractiveAuth struct {
412
ClientKeyboardInteractive
415
func (k *keyboardInteractiveAuth) method() string {
416
return "keyboard-interactive"
419
func (k *keyboardInteractiveAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
420
type initiateMsg struct {
428
if err := c.writePacket(marshal(msgUserAuthRequest, initiateMsg{
431
Method: "keyboard-interactive",
433
return false, nil, err
437
packet, err := c.readPacket()
439
return false, nil, err
442
// like handleAuthResponse, but with less options.
444
case msgUserAuthBanner:
445
// TODO: Print banners during userauth.
447
case msgUserAuthInfoRequest:
449
case msgUserAuthFailure:
450
var msg userAuthFailureMsg
451
if err := unmarshal(&msg, packet, msgUserAuthFailure); err != nil {
452
return false, nil, err
454
return false, msg.Methods, nil
455
case msgUserAuthSuccess:
456
return true, nil, nil
458
return false, nil, UnexpectedMessageError{msgUserAuthInfoRequest, packet[0]}
461
var msg userAuthInfoRequestMsg
462
if err := unmarshal(&msg, packet, packet[0]); err != nil {
463
return false, nil, err
466
// Manually unpack the prompt/echo pairs.
470
for i := 0; i < int(msg.NumPrompts); i++ {
471
prompt, r, ok := parseString(rest)
472
if !ok || len(r) == 0 {
473
return false, nil, errors.New("ssh: prompt format error")
475
prompts = append(prompts, string(prompt))
476
echos = append(echos, r[0] != 0)
481
return false, nil, fmt.Errorf("ssh: junk following message %q", rest)
484
answers, err := k.Challenge(msg.User, msg.Instruction, prompts, echos)
486
return false, nil, err
489
if len(answers) != len(prompts) {
490
return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
492
responseLength := 1 + 4
493
for _, a := range answers {
494
responseLength += stringLength(len(a))
496
serialized := make([]byte, responseLength)
498
p[0] = msgUserAuthInfoResponse
500
p = marshalUint32(p, uint32(len(answers)))
501
for _, a := range answers {
502
p = marshalString(p, []byte(a))
505
if err := c.writePacket(serialized); err != nil {
506
return false, nil, err