krb5Token.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package GSSAPI
  2. import (
  3. "encoding/binary"
  4. "encoding/hex"
  5. "fmt"
  6. "github.com/jcmturner/asn1"
  7. "github.com/jcmturner/gokrb5/asn1tools"
  8. "github.com/jcmturner/gokrb5/config"
  9. "github.com/jcmturner/gokrb5/iana/chksumtype"
  10. "github.com/jcmturner/gokrb5/messages"
  11. "github.com/jcmturner/gokrb5/types"
  12. "math/rand"
  13. )
  14. const (
  15. TOK_ID_KRB_AP_REQ = "0100"
  16. TOK_ID_KRB_AP_REP = "0200"
  17. TOK_ID_KRB_ERROR = "0300"
  18. GSS_C_DELEG_FLAG = 1
  19. GSS_C_MUTUAL_FLAG = 2
  20. GSS_C_REPLAY_FLAG = 4
  21. GSS_C_SEQUENCE_FLAG = 8
  22. GSS_C_CONF_FLAG = 16
  23. GSS_C_INTEG_FLAG = 32
  24. )
  25. func NewKRB5APREQMechToken(c config.Config, cname types.PrincipalName, tkt types.Ticket, sessionKey types.EncryptionKey) ([]byte, error) {
  26. // Create the header
  27. tb, _ := hex.DecodeString(TOK_ID_KRB_AP_REQ)
  28. b, _ := asn1.Marshal(MechTypeOID_Krb5)
  29. b = append(b, tb...)
  30. // Add the token
  31. APReq, err := messages.NewAPReq(
  32. tkt,
  33. sessionKey,
  34. newAuthenticator(c, cname),
  35. )
  36. tb, err = APReq.Marshal()
  37. if err != nil {
  38. return []byte{}, fmt.Errorf("Could not marshal AP_REQ: %v", err)
  39. }
  40. b = append(b, tb...)
  41. return asn1tools.AddASNAppTag(b, 0), nil
  42. }
  43. func newAuthenticator(c config.Config, username types.PrincipalName) types.Authenticator {
  44. //RFC 4121 Section 4.1.1
  45. auth := types.NewAuthenticator(c.LibDefaults.Default_realm, username)
  46. auth.Cksum = types.Checksum{
  47. CksumType: chksumtype.GSSAPI,
  48. Checksum: newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG}),
  49. }
  50. auth.SeqNumber = int(rand.Int63())
  51. return auth
  52. }
  53. func newAuthenticatorChksum(flags []int) []byte {
  54. a := make([]byte, 24)
  55. for i := range flags {
  56. if i == GSS_C_DELEG_FLAG {
  57. x := make([]byte, 28-len(a))
  58. a = append(a, x...)
  59. }
  60. setAuthenticatorChksumFlag(a, uint32(i))
  61. }
  62. return a
  63. }
  64. func setAuthenticatorChksumFlag(a []byte, i uint32) {
  65. f := binary.LittleEndian.Uint32(a[20:24])
  66. f |= i
  67. binary.LittleEndian.PutUint32(a[20:24], f)
  68. }
  69. /*
  70. The authenticator checksum field SHALL have the following format:
  71. Octet Name Description
  72. -----------------------------------------------------------------
  73. 0..3 Lgth Number of octets in Bnd field; Represented
  74. in little-endian order; Currently contains
  75. hex value 10 00 00 00 (16).
  76. 4..19 Bnd Channel binding information, as described in
  77. section 4.1.1.2.
  78. 20..23 Flags Four-octet context-establishment flags in
  79. little-endian order as described in section
  80. 4.1.1.1.
  81. 24..25 DlgOpt The delegation option identifier (=1) in
  82. little-endian order [optional]. This field
  83. and the next two fields are present if and
  84. only if GSS_C_DELEG_FLAG is set as described
  85. in section 4.1.1.1.
  86. 26..27 Dlgth The length of the Deleg field in little-endian order [optional].
  87. 28..(n-1) Deleg A KRB_CRED message (n = Dlgth + 28) [optional].
  88. n..last Exts Extensions [optional].
  89. */