gssapi.go 2.7 KB

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