message.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package kadmin
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "math"
  8. "github.com/jcmturner/gokrb5/v8/messages"
  9. "github.com/jcmturner/gokrb5/v8/types"
  10. )
  11. const (
  12. verisonHex = "ff80"
  13. )
  14. // Request message for changing password.
  15. type Request struct {
  16. APREQ messages.APReq
  17. KRBPriv messages.KRBPriv
  18. }
  19. // Reply message for a password change.
  20. type Reply struct {
  21. MessageLength int
  22. Version int
  23. APREPLength int
  24. APREP messages.APRep
  25. KRBPriv messages.KRBPriv
  26. KRBError messages.KRBError
  27. IsKRBError bool
  28. ResultCode uint16
  29. Result string
  30. }
  31. // Marshal a Request into a byte slice.
  32. func (m *Request) Marshal() (b []byte, err error) {
  33. b = []byte{255, 128} // protocol version number: contains the hex constant 0xff80 (big-endian integer).
  34. ab, e := m.APREQ.Marshal()
  35. if e != nil {
  36. err = fmt.Errorf("error marshaling AP_REQ: %v", e)
  37. return
  38. }
  39. if len(ab) > math.MaxUint16 {
  40. err = errors.New("length of AP_REQ greater then max Uint16 size")
  41. return
  42. }
  43. al := make([]byte, 2)
  44. binary.BigEndian.PutUint16(al, uint16(len(ab)))
  45. b = append(b, al...)
  46. b = append(b, ab...)
  47. pb, e := m.KRBPriv.Marshal()
  48. if e != nil {
  49. err = fmt.Errorf("error marshaling KRB_Priv: %v", e)
  50. return
  51. }
  52. b = append(b, pb...)
  53. if len(b)+2 > math.MaxUint16 {
  54. err = errors.New("length of message greater then max Uint16 size")
  55. return
  56. }
  57. ml := make([]byte, 2)
  58. binary.BigEndian.PutUint16(ml, uint16(len(b)+2))
  59. b = append(ml, b...)
  60. return
  61. }
  62. // Unmarshal a byte slice into a Reply.
  63. func (m *Reply) Unmarshal(b []byte) error {
  64. m.MessageLength = int(binary.BigEndian.Uint16(b[0:2]))
  65. m.Version = int(binary.BigEndian.Uint16(b[2:4]))
  66. if m.Version != 1 {
  67. return fmt.Errorf("kadmin reply has incorrect protocol version number: %d", m.Version)
  68. }
  69. m.APREPLength = int(binary.BigEndian.Uint16(b[4:6]))
  70. if m.APREPLength != 0 {
  71. err := m.APREP.Unmarshal(b[6 : 6+m.APREPLength])
  72. if err != nil {
  73. return err
  74. }
  75. err = m.KRBPriv.Unmarshal(b[6+m.APREPLength : m.MessageLength])
  76. if err != nil {
  77. return err
  78. }
  79. } else {
  80. m.IsKRBError = true
  81. m.KRBError.Unmarshal(b[6:m.MessageLength])
  82. m.ResultCode, m.Result = parseResponse(m.KRBError.EData)
  83. }
  84. return nil
  85. }
  86. func parseResponse(b []byte) (c uint16, s string) {
  87. c = binary.BigEndian.Uint16(b[0:2])
  88. buf := bytes.NewBuffer(b[2:])
  89. m := make([]byte, len(b)-2)
  90. binary.Read(buf, binary.BigEndian, &m)
  91. s = string(m)
  92. return
  93. }
  94. // Decrypt the encrypted part of the KRBError within the change password Reply.
  95. func (m *Reply) Decrypt(key types.EncryptionKey) error {
  96. if m.IsKRBError {
  97. return m.KRBError
  98. }
  99. err := m.KRBPriv.DecryptEncPart(key)
  100. if err != nil {
  101. return err
  102. }
  103. m.ResultCode, m.Result = parseResponse(m.KRBPriv.DecryptedEncPart.UserData)
  104. return nil
  105. }