gssapi.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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. )
  9. var SPNEGO_OID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 2}
  10. type SPNEGO struct {
  11. Init bool
  12. Resp bool
  13. NegTokenInit NegTokenInit
  14. NegTokenResp NegTokenResp
  15. }
  16. // Unmarshal SPNEGO negotiation token
  17. func (s *SPNEGO) Unmarshal(b []byte) error {
  18. var r []byte
  19. var err error
  20. if b[0] != byte(161) {
  21. // Not a NegTokenResp/Targ could be a NegTokenInit
  22. var oid asn1.ObjectIdentifier
  23. r, err = asn1.UnmarshalWithParams(b, &oid, fmt.Sprintf("application,explicit,tag:%v", 0))
  24. if err != nil {
  25. return fmt.Errorf("Not a valid SPNEGO token: %v", err)
  26. }
  27. // Check the OID is the SPNEGO OID value
  28. if !oid.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 2}) {
  29. return errors.New("OID does not match SPNEGO OID 1.3.6.1.5.5.2")
  30. }
  31. } else {
  32. // Could be a NegTokenResp/Targ
  33. r = b
  34. }
  35. var a asn1.RawValue
  36. _, err = asn1.Unmarshal(r, &a)
  37. if err != nil {
  38. return fmt.Errorf("Error unmarshalling SPNEGO: %v", err)
  39. }
  40. switch a.Tag {
  41. case 0:
  42. _, err = asn1.Unmarshal(a.Bytes, &s.NegTokenInit)
  43. if err != nil {
  44. return fmt.Errorf("Error unmarshalling NegotiationToken type %d (Init): %v", a.Tag, err)
  45. }
  46. s.Init = true
  47. case 1:
  48. _, err = asn1.Unmarshal(a.Bytes, &s.NegTokenResp)
  49. if err != nil {
  50. return fmt.Errorf("Error unmarshalling NegotiationToken type %d (Resp/Targ): %v", a.Tag, err)
  51. }
  52. s.Resp = true
  53. default:
  54. return errors.New("Unknown choice type for NegotiationToken")
  55. }
  56. return nil
  57. }
  58. // Marshal SPNEGO negotiation token
  59. func (s *SPNEGO) Marshal() ([]byte, error) {
  60. var b []byte
  61. if !s.Init && !s.Resp {
  62. return b, errors.New("SPNEGO cannot be marshalled. It contains neither a NegTokenInit or NegTokenResp")
  63. }
  64. hb, _ := asn1.Marshal(SPNEGO_OID)
  65. if s.Init {
  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. }
  72. if s.Resp {
  73. tb, err := s.NegTokenResp.Marshal()
  74. if err != nil {
  75. return b, fmt.Errorf("Could not marshal NegTokenResp: %v", err)
  76. }
  77. b = append(hb, tb...)
  78. }
  79. return asn1tools.AddASNAppTag(b, 0), nil
  80. }