Skip to content

Commit 9822c92

Browse files
authored
add marshal methods KDC replies
1 parent e4c9668 commit 9822c92

7 files changed

Lines changed: 153 additions & 17 deletions

File tree

v8/client/network.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package client
22

33
import (
4-
"bytes"
54
"encoding/binary"
65
"errors"
76
"fmt"
@@ -173,14 +172,11 @@ func (cl *Client) sendTCP(conn *net.TCPConn, b []byte) ([]byte, error) {
173172
defer conn.Close()
174173
var r []byte
175174
// RFC 4120 7.2.2 specifies the first 4 bytes indicate the length of the message in big endian order.
176-
var buf bytes.Buffer
177-
err := binary.Write(&buf, binary.BigEndian, uint32(len(b)))
178-
if err != nil {
179-
return r, err
180-
}
181-
b = append(buf.Bytes(), b...)
175+
hb := make([]byte, 4, 4)
176+
binary.BigEndian.PutUint32(hb, uint32(len(b)))
177+
b = append(hb, b...)
182178

183-
_, err = conn.Write(b)
179+
_, err := conn.Write(b)
184180
if err != nil {
185181
return r, fmt.Errorf("error sending to KDC (%s): %v", conn.RemoteAddr().String(), err)
186182
}

v8/messages/KDCRep.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99

1010
"github.com/jcmturner/gofork/encoding/asn1"
11+
"github.com/jcmturner/gokrb5/v8/asn1tools"
1112
"github.com/jcmturner/gokrb5/v8/config"
1213
"github.com/jcmturner/gokrb5/v8/credentials"
1314
"github.com/jcmturner/gokrb5/v8/crypto"
@@ -103,6 +104,34 @@ func (k *ASRep) Unmarshal(b []byte) error {
103104
return nil
104105
}
105106

107+
// Marshal ASRep struct.
108+
func (k *ASRep) Marshal() ([]byte, error) {
109+
m := marshalKDCRep{
110+
PVNO: k.PVNO,
111+
MsgType: k.MsgType,
112+
PAData: k.PAData,
113+
CRealm: k.CRealm,
114+
CName: k.CName,
115+
EncPart: k.EncPart,
116+
}
117+
b, err := k.Ticket.Marshal()
118+
if err != nil {
119+
return []byte{}, err
120+
}
121+
m.Ticket = asn1.RawValue{
122+
Class: asn1.ClassContextSpecific,
123+
IsCompound: true,
124+
Tag: 5,
125+
Bytes: b,
126+
}
127+
mk, err := asn1.Marshal(m)
128+
if err != nil {
129+
return mk, krberror.Errorf(err, krberror.EncodingError, "error marshaling AS_REP")
130+
}
131+
mk = asn1tools.AddASNAppTag(mk, asnAppTag.ASREP)
132+
return mk, nil
133+
}
134+
106135
// Unmarshal bytes b into the TGSRep struct.
107136
func (k *TGSRep) Unmarshal(b []byte) error {
108137
var m marshalKDCRep
@@ -130,6 +159,34 @@ func (k *TGSRep) Unmarshal(b []byte) error {
130159
return nil
131160
}
132161

162+
// Marshal TGSRep struct.
163+
func (k *TGSRep) Marshal() ([]byte, error) {
164+
m := marshalKDCRep{
165+
PVNO: k.PVNO,
166+
MsgType: k.MsgType,
167+
PAData: k.PAData,
168+
CRealm: k.CRealm,
169+
CName: k.CName,
170+
EncPart: k.EncPart,
171+
}
172+
b, err := k.Ticket.Marshal()
173+
if err != nil {
174+
return []byte{}, err
175+
}
176+
m.Ticket = asn1.RawValue{
177+
Class: asn1.ClassContextSpecific,
178+
IsCompound: true,
179+
Tag: 5,
180+
Bytes: b,
181+
}
182+
mk, err := asn1.Marshal(m)
183+
if err != nil {
184+
return mk, krberror.Errorf(err, krberror.EncodingError, "error marshaling TGS_REP")
185+
}
186+
mk = asn1tools.AddASNAppTag(mk, asnAppTag.TGSREP)
187+
return mk, nil
188+
}
189+
133190
// Unmarshal bytes b into encrypted part of KRB_KDC_REP.
134191
func (e *EncKDCRepPart) Unmarshal(b []byte) error {
135192
_, err := asn1.UnmarshalWithParams(b, e, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncASRepPart))
@@ -145,6 +202,16 @@ func (e *EncKDCRepPart) Unmarshal(b []byte) error {
145202
return nil
146203
}
147204

205+
// Marshal encrypted part of KRB_KDC_REP.
206+
func (e *EncKDCRepPart) Marshal() ([]byte, error) {
207+
b, err := asn1.Marshal(*e)
208+
if err != nil {
209+
return b, krberror.Errorf(err, krberror.EncodingError, "marshaling error of AS_REP encpart")
210+
}
211+
b = asn1tools.AddASNAppTag(b, asnAppTag.EncASRepPart)
212+
return b, nil
213+
}
214+
148215
// DecryptEncPart decrypts the encrypted part of an AS_REP.
149216
func (k *ASRep) DecryptEncPart(c *credentials.Credentials) (types.EncryptionKey, error) {
150217
var key types.EncryptionKey
@@ -201,6 +268,7 @@ func (k *ASRep) Verify(cfg *config.Config, creds *credentials.Credentials, asReq
201268
if k.DecryptedEncPart.SName.NameType != asReq.ReqBody.SName.NameType || k.DecryptedEncPart.SName.NameString == nil {
202269
return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response does not match what was requested. Requested: %v; Reply: %v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
203270
}
271+
//TODO is there something wrong here...>
204272
for i := range k.CName.NameString {
205273
if k.DecryptedEncPart.SName.NameString[i] != asReq.ReqBody.SName.NameString[i] {
206274
return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)

v8/messages/KDCRep_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,24 @@ func TestUnmarshalASRep_optionalsNULL(t *testing.T) {
9191
assert.Equal(t, testdata.TEST_CIPHERTEXT, string(a.EncPart.Cipher), "Ticket encrypted part cipher not as expected")
9292
}
9393

94+
func TestMarshalASRep(t *testing.T) {
95+
t.Parallel()
96+
var a ASRep
97+
b, err := hex.DecodeString(testdata.MarshaledKRB5as_rep)
98+
if err != nil {
99+
t.Fatalf("Test vector read error: %v", err)
100+
}
101+
err = a.Unmarshal(b)
102+
if err != nil {
103+
t.Fatalf("Unmarshal error: %v", err)
104+
}
105+
mb, err := a.Marshal()
106+
if err != nil {
107+
t.Fatalf("Marshal errored: %v", err)
108+
}
109+
assert.Equal(t, b, mb, "Marshal bytes of ASRep not as expected")
110+
}
111+
94112
func TestUnmarshalTGSRep(t *testing.T) {
95113
t.Parallel()
96114
var a TGSRep
@@ -157,6 +175,24 @@ func TestUnmarshalTGSRep_optionalsNULL(t *testing.T) {
157175
assert.Equal(t, testdata.TEST_CIPHERTEXT, string(a.EncPart.Cipher), "Ticket encrypted part cipher not as expected")
158176
}
159177

178+
func TestMarshalTGSRep(t *testing.T) {
179+
t.Parallel()
180+
var a TGSRep
181+
b, err := hex.DecodeString(testdata.MarshaledKRB5tgs_rep)
182+
if err != nil {
183+
t.Fatalf("Test vector read error: %v", err)
184+
}
185+
err = a.Unmarshal(b)
186+
if err != nil {
187+
t.Fatalf("Unmarshal error: %v", err)
188+
}
189+
mb, err := a.Marshal()
190+
if err != nil {
191+
t.Fatalf("Marshal errored: %v", err)
192+
}
193+
assert.Equal(t, b, mb, "Marshal bytes of TGSRep not as expected")
194+
}
195+
160196
func TestUnmarshalEncKDCRepPart(t *testing.T) {
161197
t.Parallel()
162198
var a EncKDCRepPart

v8/messages/KRBError.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
"github.com/jcmturner/gofork/encoding/asn1"
9+
"github.com/jcmturner/gokrb5/v8/asn1tools"
910
"github.com/jcmturner/gokrb5/v8/iana"
1011
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
1112
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
@@ -59,6 +60,16 @@ func (k *KRBError) Unmarshal(b []byte) error {
5960
return nil
6061
}
6162

63+
// Marshal a KRBError into bytes.
64+
func (k *KRBError) Marshal() ([]byte, error) {
65+
b, err := asn1.Marshal(*k)
66+
if err != nil {
67+
return b, krberror.Errorf(err, krberror.EncodingError, "error marshaling KRBError")
68+
}
69+
b = asn1tools.AddASNAppTag(b, asnAppTag.KRBError)
70+
return b, nil
71+
}
72+
6273
// Error method implementing error interface on KRBError struct.
6374
func (k KRBError) Error() string {
6475
etxt := fmt.Sprintf("KRB Error: %s", errorcode.Lookup(k.ErrorCode))

v8/messages/KRBError_test.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/stretchr/testify/assert"
1414
)
1515

16-
func TestUnmarshalKRBError(t *testing.T) {
16+
func TestUnmarshalMarshalKRBError(t *testing.T) {
1717
t.Parallel()
1818
var a KRBError
1919
b, err := hex.DecodeString(testdata.MarshaledKRB5error)
@@ -44,9 +44,15 @@ func TestUnmarshalKRBError(t *testing.T) {
4444
assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, a.SName.NameString, "Ticket SName name string entries not as expected")
4545
assert.Equal(t, "krb5data", a.EText, "EText not as expected")
4646
assert.Equal(t, []byte("krb5data"), a.EData, "EData not as expected")
47+
48+
b2, err := a.Marshal()
49+
if err != nil {
50+
t.Errorf("error marshalling KRBError: %v", err)
51+
}
52+
assert.Equal(t, b, b2, "marshalled bytes not as expected")
4753
}
4854

49-
func TestUnmarshalKRBError_optionalsNULL(t *testing.T) {
55+
func TestUnmarshalMarshalKRBError_optionalsNULL(t *testing.T) {
5056
t.Parallel()
5157
var a KRBError
5258
b, err := hex.DecodeString(testdata.MarshaledKRB5errorOptionalsNULL)
@@ -70,4 +76,10 @@ func TestUnmarshalKRBError_optionalsNULL(t *testing.T) {
7076
assert.Equal(t, nametype.KRB_NT_PRINCIPAL, a.SName.NameType, "Ticket SName NameType not as expected")
7177
assert.Equal(t, len(testdata.TEST_PRINCIPALNAME_NAMESTRING), len(a.SName.NameString), "Ticket SName does not have the expected number of NameStrings")
7278
assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, a.SName.NameString, "Ticket SName name string entries not as expected")
79+
80+
b2, err := a.Marshal()
81+
if err != nil {
82+
t.Errorf("error marshalling KRBError: %v", err)
83+
}
84+
assert.Equal(t, b, b2, "marshalled bytes not as expected")
7385
}

v8/messages/Ticket.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package messages
22

33
import (
4-
"crypto/rand"
54
"fmt"
65
"log"
76
"time"
@@ -60,13 +59,11 @@ func NewTicket(cname types.PrincipalName, crealm string, sname types.PrincipalNa
6059
if err != nil {
6160
return Ticket{}, types.EncryptionKey{}, krberror.Errorf(err, krberror.EncryptingError, "error getting etype for new ticket")
6261
}
63-
ks := etype.GetKeyByteSize()
64-
kv := make([]byte, ks, ks)
65-
rand.Read(kv)
66-
sessionKey := types.EncryptionKey{
67-
KeyType: eTypeID,
68-
KeyValue: kv,
62+
sessionKey, err := types.GenerateEncryptionKey(etype)
63+
if err != nil {
64+
return Ticket{}, types.EncryptionKey{}, krberror.Errorf(err, krberror.EncryptingError, "error generating session key")
6965
}
66+
7067
etp := EncTicketPart{
7168
Flags: flags,
7269
Key: sessionKey,

v8/types/Cryptosystem.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package types
22

33
import (
4+
"crypto/rand"
5+
46
"github.com/jcmturner/gofork/encoding/asn1"
7+
"github.com/jcmturner/gokrb5/v8/crypto/etype"
58
)
69

710
// Reference: https://www.ietf.org/rfc/rfc4120.txt
@@ -53,3 +56,16 @@ func (a *Checksum) Unmarshal(b []byte) error {
5356
_, err := asn1.Unmarshal(b, a)
5457
return err
5558
}
59+
60+
func GenerateEncryptionKey(etype etype.EType) (EncryptionKey, error) {
61+
k := EncryptionKey{
62+
KeyType: etype.GetETypeID(),
63+
}
64+
b := make([]byte, etype.GetKeyByteSize(), etype.GetKeyByteSize())
65+
_, err := rand.Read(b)
66+
if err != nil {
67+
return k, err
68+
}
69+
k.KeyValue = b
70+
return k, nil
71+
}

0 commit comments

Comments
 (0)