gssapi.go 6.8 KB

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