You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

492 lines
14 KiB

  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. "bytes"
  7. "errors"
  8. "fmt"
  9. "io"
  10. "net"
  11. "strings"
  12. )
  13. // The Permissions type holds fine-grained permissions that are
  14. // specific to a user or a specific authentication method for a
  15. // user. Permissions, except for "source-address", must be enforced in
  16. // the server application layer, after successful authentication. The
  17. // Permissions are passed on in ServerConn so a server implementation
  18. // can honor them.
  19. type Permissions struct {
  20. // Critical options restrict default permissions. Common
  21. // restrictions are "source-address" and "force-command". If
  22. // the server cannot enforce the restriction, or does not
  23. // recognize it, the user should not authenticate.
  24. CriticalOptions map[string]string
  25. // Extensions are extra functionality that the server may
  26. // offer on authenticated connections. Common extensions are
  27. // "permit-agent-forwarding", "permit-X11-forwarding". Lack of
  28. // support for an extension does not preclude authenticating a
  29. // user.
  30. Extensions map[string]string
  31. }
  32. // ServerConfig holds server specific configuration data.
  33. type ServerConfig struct {
  34. // Config contains configuration shared between client and server.
  35. Config
  36. hostKeys []Signer
  37. // NoClientAuth is true if clients are allowed to connect without
  38. // authenticating.
  39. NoClientAuth bool
  40. // PasswordCallback, if non-nil, is called when a user
  41. // attempts to authenticate using a password.
  42. PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
  43. // PublicKeyCallback, if non-nil, is called when a client attempts public
  44. // key authentication. It must return true if the given public key is
  45. // valid for the given user. For example, see CertChecker.Authenticate.
  46. PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
  47. // KeyboardInteractiveCallback, if non-nil, is called when
  48. // keyboard-interactive authentication is selected (RFC
  49. // 4256). The client object's Challenge function should be
  50. // used to query the user. The callback may offer multiple
  51. // Challenge rounds. To avoid information leaks, the client
  52. // should be presented a challenge even if the user is
  53. // unknown.
  54. KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
  55. // AuthLogCallback, if non-nil, is called to log all authentication
  56. // attempts.
  57. AuthLogCallback func(conn ConnMetadata, method string, err error)
  58. // ServerVersion is the version identification string to announce in
  59. // the public handshake.
  60. // If empty, a reasonable default is used.
  61. // Note that RFC 4253 section 4.2 requires that this string start with
  62. // "SSH-2.0-".
  63. ServerVersion string
  64. }
  65. // AddHostKey adds a private key as a host key. If an existing host
  66. // key exists with the same algorithm, it is overwritten. Each server
  67. // config must have at least one host key.
  68. func (s *ServerConfig) AddHostKey(key Signer) {
  69. for i, k := range s.hostKeys {
  70. if k.PublicKey().Type() == key.PublicKey().Type() {
  71. s.hostKeys[i] = key
  72. return
  73. }
  74. }
  75. s.hostKeys = append(s.hostKeys, key)
  76. }
  77. // cachedPubKey contains the results of querying whether a public key is
  78. // acceptable for a user.
  79. type cachedPubKey struct {
  80. user string
  81. pubKeyData []byte
  82. result error
  83. perms *Permissions
  84. }
  85. const maxCachedPubKeys = 16
  86. // pubKeyCache caches tests for public keys. Since SSH clients
  87. // will query whether a public key is acceptable before attempting to
  88. // authenticate with it, we end up with duplicate queries for public
  89. // key validity. The cache only applies to a single ServerConn.
  90. type pubKeyCache struct {
  91. keys []cachedPubKey
  92. }
  93. // get returns the result for a given user/algo/key tuple.
  94. func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
  95. for _, k := range c.keys {
  96. if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
  97. return k, true
  98. }
  99. }
  100. return cachedPubKey{}, false
  101. }
  102. // add adds the given tuple to the cache.
  103. func (c *pubKeyCache) add(candidate cachedPubKey) {
  104. if len(c.keys) < maxCachedPubKeys {
  105. c.keys = append(c.keys, candidate)
  106. }
  107. }
  108. // ServerConn is an authenticated SSH connection, as seen from the
  109. // server
  110. type ServerConn struct {
  111. Conn
  112. // If the succeeding authentication callback returned a
  113. // non-nil Permissions pointer, it is stored here.
  114. Permissions *Permissions
  115. }
  116. // NewServerConn starts a new SSH server with c as the underlying
  117. // transport. It starts with a handshake and, if the handshake is
  118. // unsuccessful, it closes the connection and returns an error. The
  119. // Request and NewChannel channels must be serviced, or the connection
  120. // will hang.
  121. func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
  122. fullConf := *config
  123. fullConf.SetDefaults()
  124. s := &connection{
  125. sshConn: sshConn{conn: c},
  126. }
  127. perms, err := s.serverHandshake(&fullConf)
  128. if err != nil {
  129. c.Close()
  130. return nil, nil, nil, err
  131. }
  132. return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
  133. }
  134. // signAndMarshal signs the data with the appropriate algorithm,
  135. // and serializes the result in SSH wire format.
  136. func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
  137. sig, err := k.Sign(rand, data)
  138. if err != nil {
  139. return nil, err
  140. }
  141. return Marshal(sig), nil
  142. }
  143. // handshake performs key exchange and user authentication.
  144. func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
  145. if len(config.hostKeys) == 0 {
  146. return nil, errors.New("ssh: server has no host keys")
  147. }
  148. if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil {
  149. return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
  150. }
  151. if config.ServerVersion != "" {
  152. s.serverVersion = []byte(config.ServerVersion)
  153. } else {
  154. s.serverVersion = []byte(packageVersion)
  155. }
  156. var err error
  157. s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
  158. if err != nil {
  159. return nil, err
  160. }
  161. tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
  162. s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
  163. if err := s.transport.waitSession(); err != nil {
  164. return nil, err
  165. }
  166. // We just did the key change, so the session ID is established.
  167. s.sessionID = s.transport.getSessionID()
  168. var packet []byte
  169. if packet, err = s.transport.readPacket(); err != nil {
  170. return nil, err
  171. }
  172. var serviceRequest serviceRequestMsg
  173. if err = Unmarshal(packet, &serviceRequest); err != nil {
  174. return nil, err
  175. }
  176. if serviceRequest.Service != serviceUserAuth {
  177. return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
  178. }
  179. serviceAccept := serviceAcceptMsg{
  180. Service: serviceUserAuth,
  181. }
  182. if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
  183. return nil, err
  184. }
  185. perms, err := s.serverAuthenticate(config)
  186. if err != nil {
  187. return nil, err
  188. }
  189. s.mux = newMux(s.transport)
  190. return perms, err
  191. }
  192. func isAcceptableAlgo(algo string) bool {
  193. switch algo {
  194. case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
  195. CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
  196. return true
  197. }
  198. return false
  199. }
  200. func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
  201. if addr == nil {
  202. return errors.New("ssh: no address known for client, but source-address match required")
  203. }
  204. tcpAddr, ok := addr.(*net.TCPAddr)
  205. if !ok {
  206. return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
  207. }
  208. for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
  209. if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
  210. if allowedIP.Equal(tcpAddr.IP) {
  211. return nil
  212. }
  213. } else {
  214. _, ipNet, err := net.ParseCIDR(sourceAddr)
  215. if err != nil {
  216. return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
  217. }
  218. if ipNet.Contains(tcpAddr.IP) {
  219. return nil
  220. }
  221. }
  222. }
  223. return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
  224. }
  225. func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
  226. sessionID := s.transport.getSessionID()
  227. var cache pubKeyCache
  228. var perms *Permissions
  229. userAuthLoop:
  230. for {
  231. var userAuthReq userAuthRequestMsg
  232. if packet, err := s.transport.readPacket(); err != nil {
  233. return nil, err
  234. } else if err = Unmarshal(packet, &userAuthReq); err != nil {
  235. return nil, err
  236. }
  237. if userAuthReq.Service != serviceSSH {
  238. return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
  239. }
  240. s.user = userAuthReq.User
  241. perms = nil
  242. authErr := errors.New("no auth passed yet")
  243. switch userAuthReq.Method {
  244. case "none":
  245. if config.NoClientAuth {
  246. authErr = nil
  247. }
  248. case "password":
  249. if config.PasswordCallback == nil {
  250. authErr = errors.New("ssh: password auth not configured")
  251. break
  252. }
  253. payload := userAuthReq.Payload
  254. if len(payload) < 1 || payload[0] != 0 {
  255. return nil, parseError(msgUserAuthRequest)
  256. }
  257. payload = payload[1:]
  258. password, payload, ok := parseString(payload)
  259. if !ok || len(payload) > 0 {
  260. return nil, parseError(msgUserAuthRequest)
  261. }
  262. perms, authErr = config.PasswordCallback(s, password)
  263. case "keyboard-interactive":
  264. if config.KeyboardInteractiveCallback == nil {
  265. authErr = errors.New("ssh: keyboard-interactive auth not configubred")
  266. break
  267. }
  268. prompter := &sshClientKeyboardInteractive{s}
  269. perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge)
  270. case "publickey":
  271. if config.PublicKeyCallback == nil {
  272. authErr = errors.New("ssh: publickey auth not configured")
  273. break
  274. }
  275. payload := userAuthReq.Payload
  276. if len(payload) < 1 {
  277. return nil, parseError(msgUserAuthRequest)
  278. }
  279. isQuery := payload[0] == 0
  280. payload = payload[1:]
  281. algoBytes, payload, ok := parseString(payload)
  282. if !ok {
  283. return nil, parseError(msgUserAuthRequest)
  284. }
  285. algo := string(algoBytes)
  286. if !isAcceptableAlgo(algo) {
  287. authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
  288. break
  289. }
  290. pubKeyData, payload, ok := parseString(payload)
  291. if !ok {
  292. return nil, parseError(msgUserAuthRequest)
  293. }
  294. pubKey, err := ParsePublicKey(pubKeyData)
  295. if err != nil {
  296. return nil, err
  297. }
  298. candidate, ok := cache.get(s.user, pubKeyData)
  299. if !ok {
  300. candidate.user = s.user
  301. candidate.pubKeyData = pubKeyData
  302. candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
  303. if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
  304. candidate.result = checkSourceAddress(
  305. s.RemoteAddr(),
  306. candidate.perms.CriticalOptions[sourceAddressCriticalOption])
  307. }
  308. cache.add(candidate)
  309. }
  310. if isQuery {
  311. // The client can query if the given public key
  312. // would be okay.
  313. if len(payload) > 0 {
  314. return nil, parseError(msgUserAuthRequest)
  315. }
  316. if candidate.result == nil {
  317. okMsg := userAuthPubKeyOkMsg{
  318. Algo: algo,
  319. PubKey: pubKeyData,
  320. }
  321. if err = s.transport.writePacket(Marshal(&okMsg)); err != nil {
  322. return nil, err
  323. }
  324. continue userAuthLoop
  325. }
  326. authErr = candidate.result
  327. } else {
  328. sig, payload, ok := parseSignature(payload)
  329. if !ok || len(payload) > 0 {
  330. return nil, parseError(msgUserAuthRequest)
  331. }
  332. // Ensure the public key algo and signature algo
  333. // are supported. Compare the private key
  334. // algorithm name that corresponds to algo with
  335. // sig.Format. This is usually the same, but
  336. // for certs, the names differ.
  337. if !isAcceptableAlgo(sig.Format) {
  338. break
  339. }
  340. signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
  341. if err := pubKey.Verify(signedData, sig); err != nil {
  342. return nil, err
  343. }
  344. authErr = candidate.result
  345. perms = candidate.perms
  346. }
  347. default:
  348. authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
  349. }
  350. if config.AuthLogCallback != nil {
  351. config.AuthLogCallback(s, userAuthReq.Method, authErr)
  352. }
  353. if authErr == nil {
  354. break userAuthLoop
  355. }
  356. var failureMsg userAuthFailureMsg
  357. if config.PasswordCallback != nil {
  358. failureMsg.Methods = append(failureMsg.Methods, "password")
  359. }
  360. if config.PublicKeyCallback != nil {
  361. failureMsg.Methods = append(failureMsg.Methods, "publickey")
  362. }
  363. if config.KeyboardInteractiveCallback != nil {
  364. failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
  365. }
  366. if len(failureMsg.Methods) == 0 {
  367. return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
  368. }
  369. if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
  370. return nil, err
  371. }
  372. }
  373. if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
  374. return nil, err
  375. }
  376. return perms, nil
  377. }
  378. // sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
  379. // asking the client on the other side of a ServerConn.
  380. type sshClientKeyboardInteractive struct {
  381. *connection
  382. }
  383. func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
  384. if len(questions) != len(echos) {
  385. return nil, errors.New("ssh: echos and questions must have equal length")
  386. }
  387. var prompts []byte
  388. for i := range questions {
  389. prompts = appendString(prompts, questions[i])
  390. prompts = appendBool(prompts, echos[i])
  391. }
  392. if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
  393. Instruction: instruction,
  394. NumPrompts: uint32(len(questions)),
  395. Prompts: prompts,
  396. })); err != nil {
  397. return nil, err
  398. }
  399. packet, err := c.transport.readPacket()
  400. if err != nil {
  401. return nil, err
  402. }
  403. if packet[0] != msgUserAuthInfoResponse {
  404. return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0])
  405. }
  406. packet = packet[1:]
  407. n, packet, ok := parseUint32(packet)
  408. if !ok || int(n) != len(questions) {
  409. return nil, parseError(msgUserAuthInfoResponse)
  410. }
  411. for i := uint32(0); i < n; i++ {
  412. ans, rest, ok := parseString(packet)
  413. if !ok {
  414. return nil, parseError(msgUserAuthInfoResponse)
  415. }
  416. answers = append(answers, string(ans))
  417. packet = rest
  418. }
  419. if len(packet) != 0 {
  420. return nil, errors.New("ssh: junk at end of message")
  421. }
  422. return answers, nil
  423. }