diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-01 19:26:59 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-01 19:26:59 +0000 |
commit | 9af4cb9545ce481b8d9d4a13acfe26512032e21b (patch) | |
tree | 7e7e6083ebe59999943a211a17f8ef6f07f17c2f /libgo/go/exp/ssh/client_auth.go | |
parent | 6b6cd722f329a168f98d1f421834cf40bb33a77d (diff) | |
download | gcc-9af4cb9545ce481b8d9d4a13acfe26512032e21b.zip gcc-9af4cb9545ce481b8d9d4a13acfe26512032e21b.tar.gz gcc-9af4cb9545ce481b8d9d4a13acfe26512032e21b.tar.bz2 |
libgo: Update to weekly.2012-01-27.
From-SVN: r183810
Diffstat (limited to 'libgo/go/exp/ssh/client_auth.go')
-rw-r--r-- | libgo/go/exp/ssh/client_auth.go | 316 |
1 files changed, 0 insertions, 316 deletions
diff --git a/libgo/go/exp/ssh/client_auth.go b/libgo/go/exp/ssh/client_auth.go deleted file mode 100644 index 3a7e9fb..0000000 --- a/libgo/go/exp/ssh/client_auth.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssh - -import ( - "errors" - "io" -) - -// authenticate authenticates with the remote server. See RFC 4252. -func (c *ClientConn) authenticate(session []byte) error { - // initiate user auth session - if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil { - return err - } - packet, err := c.readPacket() - if err != nil { - return err - } - var serviceAccept serviceAcceptMsg - if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil { - return err - } - // during the authentication phase the client first attempts the "none" method - // then any untried methods suggested by the server. - tried, remain := make(map[string]bool), make(map[string]bool) - for auth := ClientAuth(new(noneAuth)); auth != nil; { - ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand()) - if err != nil { - return err - } - if ok { - // success - return nil - } - tried[auth.method()] = true - delete(remain, auth.method()) - for _, meth := range methods { - if tried[meth] { - // if we've tried meth already, skip it. - continue - } - remain[meth] = true - } - auth = nil - for _, a := range c.config.Auth { - if remain[a.method()] { - auth = a - break - } - } - } - return errors.New("ssh: unable to authenticate, no supported methods remain") -} - -// A ClientAuth represents an instance of an RFC 4252 authentication method. -type ClientAuth interface { - // auth authenticates user over transport t. - // Returns true if authentication is successful. - // If authentication is not successful, a []string of alternative - // method names is returned. - auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) - - // method returns the RFC 4252 method name. - method() string -} - -// "none" authentication, RFC 4252 section 5.2. -type noneAuth int - -func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) { - if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{ - User: user, - Service: serviceSSH, - Method: "none", - })); err != nil { - return false, nil, err - } - - return handleAuthResponse(t) -} - -func (n *noneAuth) method() string { - return "none" -} - -// "password" authentication, RFC 4252 Section 8. -type passwordAuth struct { - ClientPassword -} - -func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) { - type passwordAuthMsg struct { - User string - Service string - Method string - Reply bool - Password string - } - - pw, err := p.Password(user) - if err != nil { - return false, nil, err - } - - if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{ - User: user, - Service: serviceSSH, - Method: "password", - Reply: false, - Password: pw, - })); err != nil { - return false, nil, err - } - - return handleAuthResponse(t) -} - -func (p *passwordAuth) method() string { - return "password" -} - -// A ClientPassword implements access to a client's passwords. -type ClientPassword interface { - // Password returns the password to use for user. - Password(user string) (password string, err error) -} - -// ClientAuthPassword returns a ClientAuth using password authentication. -func ClientAuthPassword(impl ClientPassword) ClientAuth { - return &passwordAuth{impl} -} - -// ClientKeyring implements access to a client key ring. -type ClientKeyring interface { - // Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if - // no key exists at i. - Key(i int) (key interface{}, err error) - - // Sign returns a signature of the given data using the i'th key - // and the supplied random source. - Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) -} - -// "publickey" authentication, RFC 4252 Section 7. -type publickeyAuth struct { - ClientKeyring -} - -type publickeyAuthMsg struct { - User string - Service string - Method string - // HasSig indicates to the reciver packet that the auth request is signed and - // should be used for authentication of the request. - HasSig bool - Algoname string - Pubkey string - // Sig is defined as []byte so marshal will exclude it during validateKey - Sig []byte `ssh:"rest"` -} - -func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) { - - // Authentication is performed in two stages. The first stage sends an - // enquiry to test if each key is acceptable to the remote. The second - // stage attempts to authenticate with the valid keys obtained in the - // first stage. - - var index int - // a map of public keys to their index in the keyring - validKeys := make(map[int]interface{}) - for { - key, err := p.Key(index) - if err != nil { - return false, nil, err - } - if key == nil { - // no more keys in the keyring - break - } - - if ok, err := p.validateKey(key, user, t); ok { - validKeys[index] = key - } else { - if err != nil { - return false, nil, err - } - } - index++ - } - - // methods that may continue if this auth is not successful. - var methods []string - for i, key := range validKeys { - pubkey := serializePublickey(key) - algoname := algoName(key) - sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{ - User: user, - Service: serviceSSH, - Method: p.method(), - }, []byte(algoname), pubkey)) - if err != nil { - return false, nil, err - } - // manually wrap the serialized signature in a string - s := serializeSignature(algoname, sign) - sig := make([]byte, stringLength(s)) - marshalString(sig, s) - msg := publickeyAuthMsg{ - User: user, - Service: serviceSSH, - Method: p.method(), - HasSig: true, - Algoname: algoname, - Pubkey: string(pubkey), - Sig: sig, - } - p := marshal(msgUserAuthRequest, msg) - if err := t.writePacket(p); err != nil { - return false, nil, err - } - success, methods, err := handleAuthResponse(t) - if err != nil { - return false, nil, err - } - if success { - return success, methods, err - } - } - return false, methods, nil -} - -// validateKey validates the key provided it is acceptable to the server. -func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) { - pubkey := serializePublickey(key) - algoname := algoName(key) - msg := publickeyAuthMsg{ - User: user, - Service: serviceSSH, - Method: p.method(), - HasSig: false, - Algoname: algoname, - Pubkey: string(pubkey), - } - if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil { - return false, err - } - - return p.confirmKeyAck(key, t) -} - -func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) { - pubkey := serializePublickey(key) - algoname := algoName(key) - - for { - packet, err := t.readPacket() - if err != nil { - return false, err - } - switch packet[0] { - case msgUserAuthBanner: - // TODO(gpaul): add callback to present the banner to the user - case msgUserAuthPubKeyOk: - msg := decode(packet).(*userAuthPubKeyOkMsg) - if msg.Algo != algoname || msg.PubKey != string(pubkey) { - return false, nil - } - return true, nil - case msgUserAuthFailure: - return false, nil - default: - return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]} - } - } - panic("unreachable") -} - -func (p *publickeyAuth) method() string { - return "publickey" -} - -// ClientAuthKeyring returns a ClientAuth using public key authentication. -func ClientAuthKeyring(impl ClientKeyring) ClientAuth { - return &publickeyAuth{impl} -} - -// handleAuthResponse returns whether the preceding authentication request succeeded -// along with a list of remaining authentication methods to try next and -// an error if an unexpected response was received. -func handleAuthResponse(t *transport) (bool, []string, error) { - for { - packet, err := t.readPacket() - if err != nil { - return false, nil, err - } - - switch packet[0] { - case msgUserAuthBanner: - // TODO: add callback to present the banner to the user - case msgUserAuthFailure: - msg := decode(packet).(*userAuthFailureMsg) - return false, msg.Methods, nil - case msgUserAuthSuccess: - return true, nil, nil - case msgDisconnect: - return false, nil, io.EOF - default: - return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]} - } - } - panic("unreachable") -} |