ssh_gss.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. "encoding/asn1"
  7. "errors"
  8. )
  9. var krb5OID []byte
  10. func init() {
  11. krb5OID, _ = asn1.Marshal(krb5Mesh)
  12. }
  13. // GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins.
  14. type GSSAPIClient interface {
  15. // InitSecContext initiates the establishment of a security context for GSS-API between the
  16. // ssh client and ssh server. Initially the token parameter should be specified as nil.
  17. // The routine may return a outputToken which should be transferred to
  18. // the ssh server, where the ssh server will present it to
  19. // AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting
  20. // needContinue to false. To complete the context
  21. // establishment, one or more reply tokens may be required from the ssh
  22. // server;if so, InitSecContext will return a needContinue which is true.
  23. // In this case, InitSecContext should be called again when the
  24. // reply token is received from the ssh server, passing the reply
  25. // token to InitSecContext via the token parameters.
  26. // See RFC 2743 section 2.2.1 and RFC 4462 section 3.4.
  27. InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error)
  28. // GetMIC generates a cryptographic MIC for the SSH2 message, and places
  29. // the MIC in a token for transfer to the ssh server.
  30. // The contents of the MIC field are obtained by calling GSS_GetMIC()
  31. // over the following, using the GSS-API context that was just
  32. // established:
  33. // string session identifier
  34. // byte SSH_MSG_USERAUTH_REQUEST
  35. // string user name
  36. // string service
  37. // string "gssapi-with-mic"
  38. // See RFC 2743 section 2.3.1 and RFC 4462 3.5.
  39. GetMIC(micFiled []byte) ([]byte, error)
  40. // Whenever possible, it should be possible for
  41. // DeleteSecContext() calls to be successfully processed even
  42. // if other calls cannot succeed, thereby enabling context-related
  43. // resources to be released.
  44. // In addition to deleting established security contexts,
  45. // gss_delete_sec_context must also be able to delete "half-built"
  46. // security contexts resulting from an incomplete sequence of
  47. // InitSecContext()/AcceptSecContext() calls.
  48. // See RFC 2743 section 2.2.3.
  49. DeleteSecContext() error
  50. }
  51. // GSSAPIServer provides the API to plug in GSSAPI authentication for server logins.
  52. type GSSAPIServer interface {
  53. // AcceptSecContext allows a remotely initiated security context between the application
  54. // and a remote peer to be established by the ssh client. The routine may return a
  55. // outputToken which should be transferred to the ssh client,
  56. // where the ssh client will present it to InitSecContext.
  57. // If no token need be sent, AcceptSecContext will indicate this
  58. // by setting the needContinue to false. To
  59. // complete the context establishment, one or more reply tokens may be
  60. // required from the ssh client. if so, AcceptSecContext
  61. // will return a needContinue which is true, in which case it
  62. // should be called again when the reply token is received from the ssh
  63. // client, passing the token to AcceptSecContext via the
  64. // token parameters.
  65. // The srcName return value is the authenticated username.
  66. // See RFC 2743 section 2.2.2 and RFC 4462 section 3.4.
  67. AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error)
  68. // VerifyMIC verifies that a cryptographic MIC, contained in the token parameter,
  69. // fits the supplied message is received from the ssh client.
  70. // See RFC 2743 section 2.3.2.
  71. VerifyMIC(micField []byte, micToken []byte) error
  72. // Whenever possible, it should be possible for
  73. // DeleteSecContext() calls to be successfully processed even
  74. // if other calls cannot succeed, thereby enabling context-related
  75. // resources to be released.
  76. // In addition to deleting established security contexts,
  77. // gss_delete_sec_context must also be able to delete "half-built"
  78. // security contexts resulting from an incomplete sequence of
  79. // InitSecContext()/AcceptSecContext() calls.
  80. // See RFC 2743 section 2.2.3.
  81. DeleteSecContext() error
  82. }
  83. var (
  84. // OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,
  85. // so we also support the krb5 mechanism only.
  86. // See RFC 1964 section 1.
  87. krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2}
  88. )
  89. // The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST
  90. // See RFC 4462 section 3.2.
  91. type userAuthRequestGSSAPI struct {
  92. N uint32
  93. OIDS []asn1.ObjectIdentifier
  94. }
  95. func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
  96. n, rest, ok := parseUint32(payload)
  97. if !ok {
  98. return nil, errors.New("parse uint32 failed")
  99. }
  100. s := &userAuthRequestGSSAPI{
  101. N: n,
  102. OIDS: make([]asn1.ObjectIdentifier, n),
  103. }
  104. for i := 0; i < int(n); i++ {
  105. var (
  106. desiredMech []byte
  107. err error
  108. )
  109. desiredMech, rest, ok = parseString(rest)
  110. if !ok {
  111. return nil, errors.New("parse string failed")
  112. }
  113. if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil {
  114. return nil, err
  115. }
  116. }
  117. return s, nil
  118. }
  119. // See RFC 4462 section 3.6.
  120. func buildMIC(sessionID string, username string, service string, authMethod string) []byte {
  121. out := make([]byte, 0, 0)
  122. out = appendString(out, sessionID)
  123. out = append(out, msgUserAuthRequest)
  124. out = appendString(out, username)
  125. out = appendString(out, service)
  126. out = appendString(out, authMethod)
  127. return out
  128. }