123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package kadmin
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "math"
- "github.com/jcmturner/gokrb5/v8/messages"
- "github.com/jcmturner/gokrb5/v8/types"
- )
- const (
- verisonHex = "ff80"
- )
- // Request message for changing password.
- type Request struct {
- APREQ messages.APReq
- KRBPriv messages.KRBPriv
- }
- // Reply message for a password change.
- type Reply struct {
- MessageLength int
- Version int
- APREPLength int
- APREP messages.APRep
- KRBPriv messages.KRBPriv
- KRBError messages.KRBError
- IsKRBError bool
- ResultCode uint16
- Result string
- }
- // Marshal a Request into a byte slice.
- func (m *Request) Marshal() (b []byte, err error) {
- b = []byte{255, 128} // protocol version number: contains the hex constant 0xff80 (big-endian integer).
- ab, e := m.APREQ.Marshal()
- if e != nil {
- err = fmt.Errorf("error marshaling AP_REQ: %v", e)
- return
- }
- if len(ab) > math.MaxUint16 {
- err = errors.New("length of AP_REQ greater then max Uint16 size")
- return
- }
- al := make([]byte, 2)
- binary.BigEndian.PutUint16(al, uint16(len(ab)))
- b = append(b, al...)
- b = append(b, ab...)
- pb, e := m.KRBPriv.Marshal()
- if e != nil {
- err = fmt.Errorf("error marshaling KRB_Priv: %v", e)
- return
- }
- b = append(b, pb...)
- if len(b)+2 > math.MaxUint16 {
- err = errors.New("length of message greater then max Uint16 size")
- return
- }
- ml := make([]byte, 2)
- binary.BigEndian.PutUint16(ml, uint16(len(b)+2))
- b = append(ml, b...)
- return
- }
- // Unmarshal a byte slice into a Reply.
- func (m *Reply) Unmarshal(b []byte) error {
- m.MessageLength = int(binary.BigEndian.Uint16(b[0:2]))
- m.Version = int(binary.BigEndian.Uint16(b[2:4]))
- if m.Version != 1 {
- return fmt.Errorf("kadmin reply has incorrect protocol version number: %d", m.Version)
- }
- m.APREPLength = int(binary.BigEndian.Uint16(b[4:6]))
- if m.APREPLength != 0 {
- err := m.APREP.Unmarshal(b[6 : 6+m.APREPLength])
- if err != nil {
- return err
- }
- err = m.KRBPriv.Unmarshal(b[6+m.APREPLength : m.MessageLength])
- if err != nil {
- return err
- }
- } else {
- m.IsKRBError = true
- m.KRBError.Unmarshal(b[6:m.MessageLength])
- m.ResultCode, m.Result = parseResponse(m.KRBError.EData)
- }
- return nil
- }
- func parseResponse(b []byte) (c uint16, s string) {
- c = binary.BigEndian.Uint16(b[0:2])
- buf := bytes.NewBuffer(b[2:])
- m := make([]byte, len(b)-2)
- binary.Read(buf, binary.BigEndian, &m)
- s = string(m)
- return
- }
- // Decrypt the encrypted part of the KRBError within the change password Reply.
- func (m *Reply) Decrypt(key types.EncryptionKey) error {
- if m.IsKRBError {
- return m.KRBError
- }
- err := m.KRBPriv.DecryptEncPart(key)
- if err != nil {
- return err
- }
- m.ResultCode, m.Result = parseResponse(m.KRBPriv.DecryptedEncPart.UserData)
- return nil
- }
|