gssapi.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Package gssapi implements Generic Security Services Application Program Interface required for SPNEGO kerberos authentication.
  2. package gssapi
  3. import (
  4. "errors"
  5. "fmt"
  6. "github.com/jcmturner/gofork/encoding/asn1"
  7. "gopkg.in/jcmturner/gokrb5.v6/asn1tools"
  8. "gopkg.in/jcmturner/gokrb5.v6/credentials"
  9. "gopkg.in/jcmturner/gokrb5.v6/messages"
  10. "gopkg.in/jcmturner/gokrb5.v6/types"
  11. )
  12. // SPNEGO_OID is the OID for SPNEGO header type.
  13. var SPNEGO_OID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 2}
  14. // SPNEGO header struct
  15. type SPNEGO struct {
  16. Init bool
  17. Resp bool
  18. NegTokenInit NegTokenInit
  19. NegTokenResp NegTokenResp
  20. }
  21. // Unmarshal SPNEGO negotiation token
  22. func (s *SPNEGO) Unmarshal(b []byte) error {
  23. var r []byte
  24. var err error
  25. if b[0] != byte(161) {
  26. // Not a NegTokenResp/Targ could be a NegTokenInit
  27. var oid asn1.ObjectIdentifier
  28. r, err = asn1.UnmarshalWithParams(b, &oid, fmt.Sprintf("application,explicit,tag:%v", 0))
  29. if err != nil {
  30. return fmt.Errorf("not a valid SPNEGO token: %v", err)
  31. }
  32. // Check the OID is the SPNEGO OID value
  33. if !oid.Equal(SPNEGO_OID) {
  34. return fmt.Errorf("OID %s does not match SPNEGO OID %s", oid.String(), SPNEGO_OID.String())
  35. }
  36. } else {
  37. // Could be a NegTokenResp/Targ
  38. r = b
  39. }
  40. var a asn1.RawValue
  41. _, err = asn1.Unmarshal(r, &a)
  42. if err != nil {
  43. return fmt.Errorf("error unmarshalling SPNEGO: %v", err)
  44. }
  45. switch a.Tag {
  46. case 0:
  47. _, err = asn1.Unmarshal(a.Bytes, &s.NegTokenInit)
  48. if err != nil {
  49. return fmt.Errorf("error unmarshalling NegotiationToken type %d (Init): %v", a.Tag, err)
  50. }
  51. s.Init = true
  52. case 1:
  53. _, err = asn1.Unmarshal(a.Bytes, &s.NegTokenResp)
  54. if err != nil {
  55. return fmt.Errorf("error unmarshalling NegotiationToken type %d (Resp/Targ): %v", a.Tag, err)
  56. }
  57. s.Resp = true
  58. default:
  59. return errors.New("unknown choice type for NegotiationToken")
  60. }
  61. return nil
  62. }
  63. // Marshal SPNEGO negotiation token
  64. func (s *SPNEGO) Marshal() ([]byte, error) {
  65. var b []byte
  66. if s.Init {
  67. hb, _ := asn1.Marshal(SPNEGO_OID)
  68. tb, err := s.NegTokenInit.Marshal()
  69. if err != nil {
  70. return b, fmt.Errorf("could not marshal NegTokenInit: %v", err)
  71. }
  72. b = append(hb, tb...)
  73. return asn1tools.AddASNAppTag(b, 0), nil
  74. }
  75. if s.Resp {
  76. b, err := s.NegTokenResp.Marshal()
  77. if err != nil {
  78. return b, fmt.Errorf("could not marshal NegTokenResp: %v", err)
  79. }
  80. return b, nil
  81. }
  82. return b, errors.New("SPNEGO cannot be marshalled. It contains neither a NegTokenInit or NegTokenResp")
  83. }
  84. // GetSPNEGOKrbNegTokenInit returns an SPNEGO struct containing a NegTokenInit.
  85. func GetSPNEGOKrbNegTokenInit(creds credentials.Credentials, tkt messages.Ticket, sessionKey types.EncryptionKey) (SPNEGO, error) {
  86. negTokenInit, err := NewNegTokenInitKrb5(creds, tkt, sessionKey)
  87. if err != nil {
  88. return SPNEGO{}, fmt.Errorf("could not create NegTokenInit: %v", err)
  89. }
  90. return SPNEGO{
  91. Init: true,
  92. NegTokenInit: negTokenInit,
  93. }, nil
  94. }