client_auth.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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.
  4. package ssh
  5. import (
  6. "errors"
  7. "fmt"
  8. "io"
  9. )
  10. // authenticate authenticates with the remote server. See RFC 4252.
  11. func (c *ClientConn) authenticate(session []byte) error {
  12. // initiate user auth session
  13. if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
  14. return err
  15. }
  16. packet, err := c.readPacket()
  17. if err != nil {
  18. return err
  19. }
  20. var serviceAccept serviceAcceptMsg
  21. if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
  22. return err
  23. }
  24. // during the authentication phase the client first attempts the "none" method
  25. // then any untried methods suggested by the server.
  26. tried, remain := make(map[string]bool), make(map[string]bool)
  27. for auth := ClientAuth(new(noneAuth)); auth != nil; {
  28. ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
  29. if err != nil {
  30. return err
  31. }
  32. if ok {
  33. // success
  34. return nil
  35. }
  36. tried[auth.method()] = true
  37. delete(remain, auth.method())
  38. for _, meth := range methods {
  39. if tried[meth] {
  40. // if we've tried meth already, skip it.
  41. continue
  42. }
  43. remain[meth] = true
  44. }
  45. auth = nil
  46. for _, a := range c.config.Auth {
  47. if remain[a.method()] {
  48. auth = a
  49. break
  50. }
  51. }
  52. }
  53. return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
  54. }
  55. func keys(m map[string]bool) (s []string) {
  56. for k := range m {
  57. s = append(s, k)
  58. }
  59. return
  60. }
  61. // A ClientAuth represents an instance of an RFC 4252 authentication method.
  62. type ClientAuth interface {
  63. // auth authenticates user over transport t.
  64. // Returns true if authentication is successful.
  65. // If authentication is not successful, a []string of alternative
  66. // method names is returned.
  67. auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)
  68. // method returns the RFC 4252 method name.
  69. method() string
  70. }
  71. // "none" authentication, RFC 4252 section 5.2.
  72. type noneAuth int
  73. func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
  74. if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
  75. User: user,
  76. Service: serviceSSH,
  77. Method: "none",
  78. })); err != nil {
  79. return false, nil, err
  80. }
  81. return handleAuthResponse(t)
  82. }
  83. func (n *noneAuth) method() string {
  84. return "none"
  85. }
  86. // "password" authentication, RFC 4252 Section 8.
  87. type passwordAuth struct {
  88. ClientPassword
  89. }
  90. func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
  91. type passwordAuthMsg struct {
  92. User string
  93. Service string
  94. Method string
  95. Reply bool
  96. Password string
  97. }
  98. pw, err := p.Password(user)
  99. if err != nil {
  100. return false, nil, err
  101. }
  102. if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
  103. User: user,
  104. Service: serviceSSH,
  105. Method: "password",
  106. Reply: false,
  107. Password: pw,
  108. })); err != nil {
  109. return false, nil, err
  110. }
  111. return handleAuthResponse(t)
  112. }
  113. func (p *passwordAuth) method() string {
  114. return "password"
  115. }
  116. // A ClientPassword implements access to a client's passwords.
  117. type ClientPassword interface {
  118. // Password returns the password to use for user.
  119. Password(user string) (password string, err error)
  120. }
  121. // ClientAuthPassword returns a ClientAuth using password authentication.
  122. func ClientAuthPassword(impl ClientPassword) ClientAuth {
  123. return &passwordAuth{impl}
  124. }
  125. // ClientKeyring implements access to a client key ring.
  126. type ClientKeyring interface {
  127. // Key returns the i'th *rsa.Publickey or *dsa.Publickey, or nil if
  128. // no key exists at i.
  129. Key(i int) (key interface{}, err error)
  130. // Sign returns a signature of the given data using the i'th key
  131. // and the supplied random source.
  132. Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
  133. }
  134. // "publickey" authentication, RFC 4252 Section 7.
  135. type publickeyAuth struct {
  136. ClientKeyring
  137. }
  138. type publickeyAuthMsg struct {
  139. User string
  140. Service string
  141. Method string
  142. // HasSig indicates to the reciver packet that the auth request is signed and
  143. // should be used for authentication of the request.
  144. HasSig bool
  145. Algoname string
  146. Pubkey string
  147. // Sig is defined as []byte so marshal will exclude it during validateKey
  148. Sig []byte `ssh:"rest"`
  149. }
  150. func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
  151. // Authentication is performed in two stages. The first stage sends an
  152. // enquiry to test if each key is acceptable to the remote. The second
  153. // stage attempts to authenticate with the valid keys obtained in the
  154. // first stage.
  155. var index int
  156. // a map of public keys to their index in the keyring
  157. validKeys := make(map[int]interface{})
  158. for {
  159. key, err := p.Key(index)
  160. if err != nil {
  161. return false, nil, err
  162. }
  163. if key == nil {
  164. // no more keys in the keyring
  165. break
  166. }
  167. if ok, err := p.validateKey(key, user, t); ok {
  168. validKeys[index] = key
  169. } else {
  170. if err != nil {
  171. return false, nil, err
  172. }
  173. }
  174. index++
  175. }
  176. // methods that may continue if this auth is not successful.
  177. var methods []string
  178. for i, key := range validKeys {
  179. pubkey := serializePublickey(key)
  180. algoname := algoName(key)
  181. sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
  182. User: user,
  183. Service: serviceSSH,
  184. Method: p.method(),
  185. }, []byte(algoname), pubkey))
  186. if err != nil {
  187. return false, nil, err
  188. }
  189. // manually wrap the serialized signature in a string
  190. s := serializeSignature(algoname, sign)
  191. sig := make([]byte, stringLength(len(s)))
  192. marshalString(sig, s)
  193. msg := publickeyAuthMsg{
  194. User: user,
  195. Service: serviceSSH,
  196. Method: p.method(),
  197. HasSig: true,
  198. Algoname: algoname,
  199. Pubkey: string(pubkey),
  200. Sig: sig,
  201. }
  202. p := marshal(msgUserAuthRequest, msg)
  203. if err := t.writePacket(p); err != nil {
  204. return false, nil, err
  205. }
  206. success, methods, err := handleAuthResponse(t)
  207. if err != nil {
  208. return false, nil, err
  209. }
  210. if success {
  211. return success, methods, err
  212. }
  213. }
  214. return false, methods, nil
  215. }
  216. // validateKey validates the key provided it is acceptable to the server.
  217. func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
  218. pubkey := serializePublickey(key)
  219. algoname := algoName(key)
  220. msg := publickeyAuthMsg{
  221. User: user,
  222. Service: serviceSSH,
  223. Method: p.method(),
  224. HasSig: false,
  225. Algoname: algoname,
  226. Pubkey: string(pubkey),
  227. }
  228. if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
  229. return false, err
  230. }
  231. return p.confirmKeyAck(key, t)
  232. }
  233. func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
  234. pubkey := serializePublickey(key)
  235. algoname := algoName(key)
  236. for {
  237. packet, err := t.readPacket()
  238. if err != nil {
  239. return false, err
  240. }
  241. switch packet[0] {
  242. case msgUserAuthBanner:
  243. // TODO(gpaul): add callback to present the banner to the user
  244. case msgUserAuthPubKeyOk:
  245. msg := userAuthPubKeyOkMsg{}
  246. if err := unmarshal(&msg, packet, msgUserAuthPubKeyOk); err != nil {
  247. return false, err
  248. }
  249. if msg.Algo != algoname || msg.PubKey != string(pubkey) {
  250. return false, nil
  251. }
  252. return true, nil
  253. case msgUserAuthFailure:
  254. return false, nil
  255. default:
  256. return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
  257. }
  258. }
  259. panic("unreachable")
  260. }
  261. func (p *publickeyAuth) method() string {
  262. return "publickey"
  263. }
  264. // ClientAuthKeyring returns a ClientAuth using public key authentication.
  265. func ClientAuthKeyring(impl ClientKeyring) ClientAuth {
  266. return &publickeyAuth{impl}
  267. }
  268. // handleAuthResponse returns whether the preceding authentication request succeeded
  269. // along with a list of remaining authentication methods to try next and
  270. // an error if an unexpected response was received.
  271. func handleAuthResponse(t *transport) (bool, []string, error) {
  272. for {
  273. packet, err := t.readPacket()
  274. if err != nil {
  275. return false, nil, err
  276. }
  277. switch packet[0] {
  278. case msgUserAuthBanner:
  279. // TODO: add callback to present the banner to the user
  280. case msgUserAuthFailure:
  281. msg := userAuthFailureMsg{}
  282. if err := unmarshal(&msg, packet, msgUserAuthFailure); err != nil {
  283. return false, nil, err
  284. }
  285. return false, msg.Methods, nil
  286. case msgUserAuthSuccess:
  287. return true, nil, nil
  288. case msgDisconnect:
  289. return false, nil, io.EOF
  290. default:
  291. return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
  292. }
  293. }
  294. panic("unreachable")
  295. }
  296. // ClientAuthKeyring returns a ClientAuth using public key authentication via
  297. // an agent.
  298. func ClientAuthAgent(agent *AgentClient) ClientAuth {
  299. return ClientAuthKeyring(&agentKeyring{agent: agent})
  300. }
  301. // agentKeyring implements ClientKeyring.
  302. type agentKeyring struct {
  303. agent *AgentClient
  304. keys []*AgentKey
  305. }
  306. func (kr *agentKeyring) Key(i int) (key interface{}, err error) {
  307. if kr.keys == nil {
  308. if kr.keys, err = kr.agent.RequestIdentities(); err != nil {
  309. return
  310. }
  311. }
  312. if i >= len(kr.keys) {
  313. return
  314. }
  315. return kr.keys[i].Key()
  316. }
  317. func (kr *agentKeyring) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
  318. var key interface{}
  319. if key, err = kr.Key(i); err != nil {
  320. return
  321. }
  322. if key == nil {
  323. return nil, errors.New("ssh: key index out of range")
  324. }
  325. if sig, err = kr.agent.SignRequest(key, data); err != nil {
  326. return
  327. }
  328. // Unmarshal the signature.
  329. var ok bool
  330. if _, sig, ok = parseString(sig); !ok {
  331. return nil, errors.New("ssh: malformed signature response from agent")
  332. }
  333. if sig, _, ok = parseString(sig); !ok {
  334. return nil, errors.New("ssh: malformed signature response from agent")
  335. }
  336. return sig, nil
  337. }
  338. // ClientKeyboardInteractive should prompt the user for the given
  339. // questions.
  340. type ClientKeyboardInteractive interface {
  341. // Challenge should print the questions, optionally disabling
  342. // echoing (eg. for passwords), and return all the answers.
  343. // Challenge may be called multiple times in a single
  344. // session. After successful authentication, the server may
  345. // send a challenge with no questions, for which the user and
  346. // instruction messages should be printed. RFC 4256 section
  347. // 3.3 details how the UI should behave for both CLI and
  348. // GUI environments.
  349. Challenge(user, instruction string, questions []string, echos []bool) ([]string, error)
  350. }
  351. // ClientAuthKeyboardInteractive returns a ClientAuth using a
  352. // prompt/response sequence controlled by the server.
  353. func ClientAuthKeyboardInteractive(impl ClientKeyboardInteractive) ClientAuth {
  354. return &keyboardInteractiveAuth{impl}
  355. }
  356. type keyboardInteractiveAuth struct {
  357. ClientKeyboardInteractive
  358. }
  359. func (c *keyboardInteractiveAuth) method() string {
  360. return "keyboard-interactive"
  361. }
  362. func (c *keyboardInteractiveAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
  363. type initiateMsg struct {
  364. User string
  365. Service string
  366. Method string
  367. Language string
  368. Submethods string
  369. }
  370. if err := t.writePacket(marshal(msgUserAuthRequest, initiateMsg{
  371. User: user,
  372. Service: serviceSSH,
  373. Method: "keyboard-interactive",
  374. })); err != nil {
  375. return false, nil, err
  376. }
  377. for {
  378. packet, err := t.readPacket()
  379. if err != nil {
  380. return false, nil, err
  381. }
  382. // like handleAuthResponse, but with less options.
  383. switch packet[0] {
  384. case msgUserAuthInfoRequest:
  385. // OK
  386. case msgUserAuthFailure:
  387. var msg userAuthFailureMsg
  388. if err := unmarshal(&msg, packet, msgUserAuthFailure); err != nil {
  389. return false, nil, err
  390. }
  391. return false, msg.Methods, nil
  392. case msgUserAuthSuccess:
  393. return true, nil, nil
  394. default:
  395. return false, nil, UnexpectedMessageError{msgUserAuthInfoRequest, packet[0]}
  396. }
  397. var msg userAuthInfoRequestMsg
  398. if err := unmarshal(&msg, packet, packet[0]); err != nil {
  399. return false, nil, err
  400. }
  401. // Manually unpack the prompt/echo pairs.
  402. rest := msg.Prompts
  403. var prompts []string
  404. var echos []bool
  405. for i := 0; i < int(msg.NumPrompts); i++ {
  406. prompt, r, ok := parseString(rest)
  407. if !ok || len(r) == 0 {
  408. return false, nil, errors.New("ssh: prompt format error")
  409. }
  410. prompts = append(prompts, string(prompt))
  411. echos = append(echos, r[0] != 0)
  412. rest = r[1:]
  413. }
  414. if len(rest) != 0 {
  415. return false, nil, fmt.Errorf("ssh: junk following message %q", rest)
  416. }
  417. answers, err := c.Challenge(msg.User, msg.Instruction, prompts, echos)
  418. if err != nil {
  419. return false, nil, err
  420. }
  421. if len(answers) != len(prompts) {
  422. return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
  423. }
  424. responseLength := 1 + 4
  425. for _, a := range answers {
  426. responseLength += stringLength(len(a))
  427. }
  428. serialized := make([]byte, responseLength)
  429. p := serialized
  430. p[0] = msgUserAuthInfoResponse
  431. p = p[1:]
  432. p = marshalUint32(p, uint32(len(answers)))
  433. for _, a := range answers {
  434. p = marshalString(p, []byte(a))
  435. }
  436. if err := t.writePacket(serialized); err != nil {
  437. return false, nil, err
  438. }
  439. }
  440. }