gssapi.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Package gssapi implements Generic Security Services Application Program Interface required for SPNEGO kerberos authentication.
  2. package gssapi
  3. import (
  4. "context"
  5. "fmt"
  6. "github.com/jcmturner/gofork/encoding/asn1"
  7. )
  8. // GSS-API OID names
  9. const (
  10. // GSS-API OID names
  11. OIDKRB5 OIDName = "KRB5" // MechType OID for Kerberos 5
  12. OIDMSLegacyKRB5 OIDName = "MSLegacyKRB5" // MechType OID for Kerberos 5
  13. OIDSPNEGO OIDName = "SPNEGO"
  14. OIDGSSIAKerb OIDName = "GSSIAKerb" // Indicates the client cannot get a service ticket and asks the server to serve as an intermediate to the target KDC. http://k5wiki.kerberos.org/wiki/Projects/IAKERB#IAKERB_mech
  15. )
  16. // GSS-API status values
  17. const (
  18. StatusBadBindings = 1 << iota
  19. StatusBadMech
  20. StatusBadName
  21. StatusBadNameType
  22. StatusBadStatus
  23. StatusBadSig
  24. StatusBadMIC
  25. StatusContextExpired
  26. StatusCredentialsExpired
  27. StatusDefectiveCredential
  28. StatusDefectiveToken
  29. StatusFailure
  30. StatusNoContext
  31. StatusNoCred
  32. StatusBadQOP
  33. StatusUnauthorized
  34. StatusUnavailable
  35. StatusDuplicateElement
  36. StatusNameNotMN
  37. StatusComplete
  38. StatusContinueNeeded
  39. StatusDuplicateToken
  40. StatusOldToken
  41. StatusUnseqToken
  42. StatusGapToken
  43. )
  44. // ContextToken is an interface for a GSS-API context token.
  45. type ContextToken interface {
  46. Marshal() ([]byte, error)
  47. Unmarshal(b []byte) error
  48. Verify() (bool, Status)
  49. Context() context.Context
  50. }
  51. /*
  52. CREDENTIAL MANAGEMENT
  53. GSS_Acquire_cred acquire credentials for use
  54. GSS_Release_cred release credentials after use
  55. GSS_Inquire_cred display information about credentials
  56. GSS_Add_cred construct credentials incrementally
  57. GSS_Inquire_cred_by_mech display per-mechanism credential information
  58. CONTEXT-LEVEL CALLS
  59. GSS_Init_sec_context initiate outbound security context
  60. GSS_Accept_sec_context accept inbound security context
  61. GSS_Delete_sec_context flush context when no longer needed
  62. GSS_Process_context_token process received control token on context
  63. GSS_Context_time indicate validity time remaining on context
  64. GSS_Inquire_context display information about context
  65. GSS_Wrap_size_limit determine GSS_Wrap token size limit
  66. GSS_Export_sec_context transfer context to other process
  67. GSS_Import_sec_context import transferred context
  68. PER-MESSAGE CALLS
  69. GSS_GetMIC apply integrity check, receive as token separate from message
  70. GSS_VerifyMIC validate integrity check token along with message
  71. GSS_Wrap sign, optionally encrypt, encapsulate
  72. GSS_Unwrap decapsulate, decrypt if needed, validate integrity check
  73. SUPPORT CALLS
  74. GSS_Display_status translate status codes to printable form
  75. GSS_Indicate_mechs indicate mech_types supported on local system
  76. GSS_Compare_name compare two names for equality
  77. GSS_Display_name translate name to printable form
  78. GSS_Import_name convert printable name to normalized form
  79. GSS_Release_name free storage of normalized-form name
  80. GSS_Release_buffer free storage of general GSS-allocated object
  81. GSS_Release_OID_set free storage of OID set object
  82. GSS_Create_empty_OID_set create empty OID set
  83. GSS_Add_OID_set_member add member to OID set
  84. GSS_Test_OID_set_member test if OID is member of OID set
  85. GSS_Inquire_names_for_mech indicate name types supported by mechanism
  86. GSS_Inquire_mechs_for_name indicates mechanisms supporting name type
  87. GSS_Canonicalize_name translate name to per-mechanism form
  88. GSS_Export_name externalize per-mechanism name
  89. GSS_Duplicate_name duplicate name object
  90. */
  91. // Mechanism is the GSS-API interface for authentication mechanisms.
  92. type Mechanism interface {
  93. OID() asn1.ObjectIdentifier
  94. AcquireCred() error // acquire credentials for use (eg. AS exchange for KRB5)
  95. InitSecContext() (ContextToken, error) // initiate outbound security context (eg TGS exchange builds AP_REQ to go into ContextToken to send to service)
  96. AcceptSecContext(ct ContextToken) (bool, context.Context, Status) // service verifies the token server side to establish a context
  97. MIC() MICToken // apply integrity check, receive as token separate from message
  98. VerifyMIC(mt MICToken) (bool, error) // validate integrity check token along with message
  99. Wrap(msg []byte) WrapToken // sign, optionally encrypt, encapsulate
  100. Unwrap(wt WrapToken) []byte // decapsulate, decrypt if needed, validate integrity check
  101. }
  102. // OIDName is the type for defined GSS-API OIDs.
  103. type OIDName string
  104. // OID returns the OID for the provided OID name.
  105. func (o OIDName) OID() asn1.ObjectIdentifier {
  106. switch o {
  107. case OIDSPNEGO:
  108. return asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 2}
  109. case OIDKRB5:
  110. return asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2}
  111. case OIDMSLegacyKRB5:
  112. return asn1.ObjectIdentifier{1, 2, 840, 48018, 1, 2, 2}
  113. case OIDGSSIAKerb:
  114. return asn1.ObjectIdentifier{1, 3, 6, 1, 5, 2, 5}
  115. }
  116. return asn1.ObjectIdentifier{}
  117. }
  118. // Status is the GSS-API status and implements the error interface.
  119. type Status struct {
  120. Code int
  121. Message string
  122. }
  123. // Error returns the Status description.
  124. func (s Status) Error() string {
  125. var str string
  126. switch s.Code {
  127. case StatusBadBindings:
  128. str = "channel binding mismatch"
  129. case StatusBadMech:
  130. str = "unsupported mechanism requested"
  131. case StatusBadName:
  132. str = "invalid name provided"
  133. case StatusBadNameType:
  134. str = "name of unsupported type provided"
  135. case StatusBadStatus:
  136. str = "invalid input status selector"
  137. case StatusBadSig:
  138. str = "token had invalid integrity check"
  139. case StatusBadMIC:
  140. str = "preferred alias for GSS_S_BAD_SIG"
  141. case StatusContextExpired:
  142. str = "specified security context expired"
  143. case StatusCredentialsExpired:
  144. str = "expired credentials detected"
  145. case StatusDefectiveCredential:
  146. str = "defective credential detected"
  147. case StatusDefectiveToken:
  148. str = "defective token detected"
  149. case StatusFailure:
  150. str = "failure, unspecified at GSS-API level"
  151. case StatusNoContext:
  152. str = "no valid security context specified"
  153. case StatusNoCred:
  154. str = "no valid credentials provided"
  155. case StatusBadQOP:
  156. str = "unsupported QOP valu"
  157. case StatusUnauthorized:
  158. str = "operation unauthorized"
  159. case StatusUnavailable:
  160. str = "operation unavailable"
  161. case StatusDuplicateElement:
  162. str = "duplicate credential element requested"
  163. case StatusNameNotMN:
  164. str = "name contains multi-mechanism elements"
  165. case StatusComplete:
  166. str = "normal completion"
  167. case StatusContinueNeeded:
  168. str = "continuation call to routine required"
  169. case StatusDuplicateToken:
  170. str = "duplicate per-message token detected"
  171. case StatusOldToken:
  172. str = "timed-out per-message token detected"
  173. case StatusUnseqToken:
  174. str = "reordered (early) per-message token detected"
  175. case StatusGapToken:
  176. str = "skipped predecessor token(s) detected"
  177. default:
  178. str = "unknown GSS-API error status"
  179. }
  180. if s.Message != "" {
  181. return fmt.Sprintf("%s: %s", str, s.Message)
  182. }
  183. return str
  184. }