Ver Fonte

implemented TypedData, KRBCred

Jonathan Turner há 9 anos atrás
pai
commit
c8da226728

+ 0 - 37
messages/Cred_test.go

@@ -1,37 +0,0 @@
-package messages
-
-/*
-KRB-CRED        ::= [APPLICATION 22] SEQUENCE {
-	pvno            [0] INTEGER (5),
-	msg-type        [1] INTEGER (22),
-	tickets         [2] SEQUENCE OF Ticket,
-	enc-part        [3] EncryptedData -- EncKrbCredPart
-}
-
-EncKrbCredPart  ::= [APPLICATION 29] SEQUENCE {
-	ticket-info     [0] SEQUENCE OF KrbCredInfo,
-	nonce           [1] UInt32 OPTIONAL,
-	timestamp       [2] KerberosTime OPTIONAL,
-	usec            [3] Microseconds OPTIONAL,
-	s-address       [4] HostAddress OPTIONAL,
-	r-address       [5] HostAddress OPTIONAL
-}
-
-KrbCredInfo     ::= SEQUENCE {
-	key             [0] EncryptionKey,
-	prealm          [1] Realm OPTIONAL,
-	pname           [2] PrincipalName OPTIONAL,
-	flags           [3] TicketFlags OPTIONAL,
-	authtime        [4] KerberosTime OPTIONAL,
-	starttime       [5] KerberosTime OPTIONAL,
-	endtime         [6] KerberosTime OPTIONAL,
-	renew-till      [7] KerberosTime OPTIONAL,
-	srealm          [8] Realm OPTIONAL,
-	sname           [9] PrincipalName OPTIONAL,
-	caddr           [10] HostAddresses OPTIONAL
-}
-*/
-
-//encode_krb5_cred
-//encode_krb5_enc_cred_part
-//encode_krb5_enc_cred_part(optionalsNULL)

+ 1 - 0
messages/KDCRep.go

@@ -127,6 +127,7 @@ func (e *EncKDCRepPart) Unmarshal(b []byte) error {
 }
 
 func decryptKDCRepEncPart(ct []byte, kt keytab.Keytab) (EncKDCRepPart, error) {
+	//TODO move this to the a method on the Encrypted data object and call that from here. update the KRB_CRED too
 	//TODO create the etype based on the EType value in the EncPart and find the corresponding entry in the keytab
 	//k.EncPart.EType
 	var etype crypto.Aes256CtsHmacSha96

+ 107 - 0
messages/KRBCred.go

@@ -0,0 +1,107 @@
+package messages
+
+import (
+	"encoding/asn1"
+	"github.com/jcmturner/gokrb5/types"
+	"time"
+	"fmt"
+	"github.com/jcmturner/gokrb5/types/asnAppTag"
+	"github.com/jcmturner/gokrb5/keytab"
+	"github.com/jcmturner/gokrb5/crypto"
+	"errors"
+)
+
+type marshalKRBCred struct {
+	PVNO    int                 `asn1:"explicit,tag:0"`
+	MsgType int                 `asn1:"explicit,tag:1"`
+	Tickets asn1.RawValue       `asn1:"explicit,tag:2"`
+	EncPart types.EncryptedData `asn1:"explicit,tag:3"`
+}
+
+type KRBCred struct {
+	PVNO             int
+	MsgType          int
+	Tickets          []types.Ticket
+	EncPart          types.EncryptedData
+	DecryptedEncPart EncKrbCredPart
+}
+
+type EncKrbCredPart struct {
+	TicketInfo []KrbCredInfo     `asn1:"explicit,tag:0"`
+	Nouce      int               `asn1:"optional,explicit,tag:1"`
+	Timestamp  time.Time         `asn1:"optional,explicit,tag:2"`
+	Usec       int               `asn1:"optional,explicit,tag:3"`
+	SAddress   types.HostAddress `asn1:"optional,explicit,tag:4"`
+	RAddress   types.HostAddress `asn1:"optional,explicit,tag:5"`
+}
+
+type KrbCredInfo struct {
+	Key       types.EncryptionKey `asn1:"explicit,tag:0"`
+	PRealm    string              `asn1:"optional,explicit,tag:1"`
+	PName     types.PrincipalName `asn1:"optional,explicit,tag:2"`
+	Flags     asn1.BitString      `asn1:"optional,explicit,tag:3"`
+	AuthTime  time.Time           `asn1:"optional,explicit,tag:4"`
+	StartTime time.Time           `asn1:"optional,explicit,tag:5"`
+	EndTime   time.Time           `asn1:"optional,explicit,tag:6"`
+	RenewTill time.Time           `asn1:"optional,explicit,tag:7"`
+	SRealm    string              `asn1:"optional,explicit,tag:8"`
+	SName     types.PrincipalName `asn1:"optional,explicit,tag:9"`
+	CAddr     types.HostAddresses `asn1:"optional,explicit,tag:10"`
+}
+
+func (k *KRBCred) Unmarshal(b []byte) error {
+	var m marshalKRBCred
+	_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBCred))
+	if err != nil {
+		return fmt.Errorf("Error unmarshalling KDC_CRED: %v", err)
+	}
+	expectedMsgType := types.KrbDictionary.MsgTypesByName["KRB_CRED"]
+	if m.MsgType != expectedMsgType {
+		return fmt.Errorf("Message ID does not indicate a KRB_CRED. Expected: %v; Actual: %v", expectedMsgType, m.MsgType)
+	}
+	k.PVNO = m.PVNO
+	k.MsgType = m.MsgType
+	k.EncPart = m.EncPart
+	if len(m.Tickets.Bytes) > 0 {
+		k.Tickets, err = types.UnmarshalSequenceTickets(m.Tickets)
+		if err != nil {
+			return fmt.Errorf("Error unmarshalling tickets within KRB_CRED: %v", err)
+		}
+	}
+	return nil
+}
+
+func (k *KRBCred) DecryptEncPart(kt keytab.Keytab) error {
+	//TODO move this to the a method on the Encrypted data object and call that from here. update the KDCRep too
+	//TODO create the etype based on the EType value in the EncPart and find the corresponding entry in the keytab
+	//k.EncPart.EType
+	var etype crypto.Aes256CtsHmacSha96
+	//Derive the key
+	//Key Usage Number: 3 - "AS-REP encrypted part (includes TGS session key or application session key), encrypted with the client key"
+	key, err := etype.DeriveKey(kt.Entries[0].Key.KeyMaterial, crypto.GetUsageKe(3))
+	// Strip off the checksum from the end
+	//TODO should this check be moved to the Decrypt method?
+	b, err := etype.Decrypt(key, k.EncPart.Cipher[:len(k.EncPart.Cipher)-etype.GetHMACBitLength()/8])
+	//Verify checksum
+	if !etype.VerifyChecksum(kt.Entries[0].Key.KeyMaterial, k.EncPart.Cipher, b, 3) {
+		return errors.New("Error decrypting encrypted part: checksum verification failed")
+	}
+	//Remove the confounder bytes
+	b = b[etype.GetConfounderByteSize():]
+	if err != nil {
+		return fmt.Errorf("Error decrypting encrypted part: %v", err)
+	}
+	err = k.DecryptedEncPart.Unmarshal(b)
+	if err != nil {
+		return fmt.Errorf("Error unmarshalling encrypted part: %v", err)
+	}
+	return nil
+}
+
+func (k *EncKrbCredPart) Unmarshal(b []byte) error {
+	_, err := asn1.UnmarshalWithParams(b, k, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncKrbCredPart))
+	if err != nil {
+		return fmt.Errorf("Error unmarshalling EncKrbCredPart: %v", err)
+	}
+	return nil
+}

+ 128 - 0
messages/KRBCred_test.go

@@ -0,0 +1,128 @@
+package messages
+
+import (
+	"encoding/hex"
+	"fmt"
+	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/jcmturner/gokrb5/types"
+	"github.com/stretchr/testify/assert"
+	"testing"
+	"time"
+)
+
+func TestUnmarshalKRBCred(t *testing.T) {
+	var a KRBCred
+	v := "encode_krb5_cred"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	err = a.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Unmarshal error of %s: %v\n", v, err)
+	}
+	assert.Equal(t, testdata.TEST_KVNO, a.PVNO, "PVNO not as expected")
+	assert.Equal(t, types.KrbDictionary.MsgTypesByName["KRB_CRED"], a.MsgType, "Message type not as expected")
+	assert.Equal(t, 2, len(a.Tickets), "Number of tickets not as expected")
+	for i, tkt := range a.Tickets {
+		assert.Equal(t, testdata.TEST_KVNO, tkt.TktVNO, fmt.Sprintf("Ticket (%v) ticket-vno not as expected", i+1))
+		assert.Equal(t, testdata.TEST_REALM, tkt.Realm, fmt.Sprintf("Ticket (%v) realm not as expected", i+1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMETYPE, tkt.SName.NameType, fmt.Sprintf("Ticket (%v) SName NameType not as expected", i+1))
+		assert.Equal(t, len(testdata.TEST_PRINCIPALNAME_NAMESTRING), len(tkt.SName.NameString), fmt.Sprintf("Ticket (%v) SName does not have the expected number of NameStrings", i+1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, tkt.SName.NameString, fmt.Sprintf("Ticket (%v) SName name string entries not as expected", i+1))
+		assert.Equal(t, testdata.TEST_ETYPE, tkt.EncPart.EType, fmt.Sprintf("Ticket (%v) encPart etype not as expected", i+1))
+		assert.Equal(t, testdata.TEST_KVNO, tkt.EncPart.KVNO, fmt.Sprintf("Ticket (%v) encPart KVNO not as expected", i+1))
+		assert.Equal(t, []byte(testdata.TEST_CIPHERTEXT), tkt.EncPart.Cipher, fmt.Sprintf("Ticket (%v) encPart cipher not as expected", i+1))
+	}
+	assert.Equal(t, testdata.TEST_ETYPE, a.EncPart.EType, "encPart etype not as expected")
+	assert.Equal(t, testdata.TEST_KVNO, a.EncPart.KVNO, "encPart KVNO not as expected")
+	assert.Equal(t, []byte(testdata.TEST_CIPHERTEXT), a.EncPart.Cipher, "encPart cipher not as expected")
+}
+
+func TestUnmarshalEncCredPart(t *testing.T) {
+	var a EncKrbCredPart
+	v := "encode_krb5_enc_cred_part"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	err = a.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Unmarshal error of %s: %v\n", v, err)
+	}
+	//Parse the test time value into a time.Time type
+	tt, _ := time.Parse(testdata.TEST_TIME_FORMAT, testdata.TEST_TIME)
+
+	assert.Equal(t, 2, len(a.TicketInfo), "Number of ticket info items not as expected")
+	for i, tkt := range a.TicketInfo {
+		assert.Equal(t, 1, tkt.Key.KeyType, fmt.Sprintf("Key type not as expected in ticket info item %d", i + 1))
+		assert.Equal(t, []byte("12345678"), tkt.Key.KeyValue, fmt.Sprintf("Key value not as expected in ticket info item %d", i + 1))
+		assert.Equal(t, testdata.TEST_REALM, tkt.PRealm, fmt.Sprintf("PRealm not as expected on ticket info item %d", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMETYPE, tkt.PName.NameType, fmt.Sprintf("Ticket info (%v) PName NameType not as expected", i + 1))
+		assert.Equal(t, len(testdata.TEST_PRINCIPALNAME_NAMESTRING), len(tkt.PName.NameString), fmt.Sprintf("Ticket info (%v) PName does not have the expected number of NameStrings", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, tkt.PName.NameString, fmt.Sprintf("Ticket info (%v) PName name string entries not as expected", i + 1))
+		assert.Equal(t, "fedcba98", hex.EncodeToString(tkt.Flags.Bytes), fmt.Sprintf("Flags not as expected on ticket info %d", i + 1))
+		assert.Equal(t, tt, tkt.AuthTime, fmt.Sprintf("Auth time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, tt, tkt.StartTime, fmt.Sprintf("Start time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, tt, tkt.EndTime, fmt.Sprintf("End time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, tt, tkt.RenewTill, fmt.Sprintf("Renew Till time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMETYPE, tkt.SName.NameType, fmt.Sprintf("Ticket info (%v) PName NameType not as expected", i + 1))
+		assert.Equal(t, len(testdata.TEST_PRINCIPALNAME_NAMESTRING), len(tkt.SName.NameString), fmt.Sprintf("Ticket info (%v) PName does not have the expected number of NameStrings", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, tkt.SName.NameString, fmt.Sprintf("Ticket info (%v) PName name string entries not as expected", i + 1))
+		assert.Equal(t, 2, len(tkt.CAddr), "Number of client addresses not as expected")
+		for j, addr := range tkt.CAddr {
+			assert.Equal(t, 2, addr.AddrType, fmt.Sprintf("Host address type not as expected for address item %d within ticket info %d", j + 1, i + 1))
+			assert.Equal(t, "12d00023", hex.EncodeToString(addr.Address), fmt.Sprintf("Host address not as expected for address item %d within ticket info %d", j + 1, i + 1))
+		}
+	}
+	assert.Equal(t, testdata.TEST_NONCE, a.Nouce, "Nouce not as expected")
+	assert.Equal(t, tt, a.Timestamp, "Timestamp not as expected")
+	assert.Equal(t, 123456, a.Usec, "Microseconds not as expected")
+	assert.Equal(t, 2, a.SAddress.AddrType, "SAddress type not as expected")
+	assert.Equal(t, "12d00023", hex.EncodeToString(a.SAddress.Address), "Address not as expected for SAddress")
+	assert.Equal(t, 2, a.RAddress.AddrType, "RAddress type not as expected")
+	assert.Equal(t, "12d00023", hex.EncodeToString(a.RAddress.Address), "Address not as expected for RAddress")
+}
+
+func TestUnmarshalEncCredPart_optionalsNULL(t *testing.T) {
+	var a EncKrbCredPart
+	v := "encode_krb5_enc_cred_part(optionalsNULL)"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	err = a.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Unmarshal error of %s: %v\n", v, err)
+	}
+	//Parse the test time value into a time.Time type
+	tt, _ := time.Parse(testdata.TEST_TIME_FORMAT, testdata.TEST_TIME)
+
+	assert.Equal(t, 2, len(a.TicketInfo), "Number of ticket info items not as expected")
+	//1st Ticket
+	i:=0
+	assert.Equal(t, 1, a.TicketInfo[i].Key.KeyType, fmt.Sprintf("Key type not as expected in ticket info item %d", i + 1))
+	assert.Equal(t, []byte("12345678"), a.TicketInfo[i].Key.KeyValue, fmt.Sprintf("Key value not as expected in ticket info item %d", i + 1))
+
+	//2nd Ticket
+	i=1
+	assert.Equal(t, 1, a.TicketInfo[i].Key.KeyType, fmt.Sprintf("Key type not as expected in ticket info item %d", i + 1))
+		assert.Equal(t, []byte("12345678"), a.TicketInfo[i].Key.KeyValue, fmt.Sprintf("Key value not as expected in ticket info item %d", i + 1))
+		assert.Equal(t, testdata.TEST_REALM, a.TicketInfo[i].PRealm, fmt.Sprintf("PRealm not as expected on ticket info item %d", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMETYPE, a.TicketInfo[i].PName.NameType, fmt.Sprintf("Ticket info (%v) PName NameType not as expected", i + 1))
+		assert.Equal(t, len(testdata.TEST_PRINCIPALNAME_NAMESTRING), len(a.TicketInfo[i].PName.NameString), fmt.Sprintf("Ticket info (%v) PName does not have the expected number of NameStrings", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, a.TicketInfo[i].PName.NameString, fmt.Sprintf("Ticket info (%v) PName name string entries not as expected", i + 1))
+		assert.Equal(t, "fedcba98", hex.EncodeToString(a.TicketInfo[i].Flags.Bytes), fmt.Sprintf("Flags not as expected on ticket info %d", i + 1))
+		assert.Equal(t, tt, a.TicketInfo[i].AuthTime, fmt.Sprintf("Auth time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, tt, a.TicketInfo[i].StartTime, fmt.Sprintf("Start time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, tt, a.TicketInfo[i].EndTime, fmt.Sprintf("End time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, tt, a.TicketInfo[i].RenewTill, fmt.Sprintf("Renew Till time value not as expected for ticket info %d", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMETYPE, a.TicketInfo[i].SName.NameType, fmt.Sprintf("Ticket info (%v) PName NameType not as expected", i + 1))
+		assert.Equal(t, len(testdata.TEST_PRINCIPALNAME_NAMESTRING), len(a.TicketInfo[i].SName.NameString), fmt.Sprintf("Ticket info (%v) PName does not have the expected number of NameStrings", i + 1))
+		assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, a.TicketInfo[i].SName.NameString, fmt.Sprintf("Ticket info (%v) PName name string entries not as expected", i + 1))
+		assert.Equal(t, 2, len(a.TicketInfo[i].CAddr), "Number of client addresses not as expected")
+		for j, addr := range a.TicketInfo[i].CAddr {
+			assert.Equal(t, 2, addr.AddrType, fmt.Sprintf("Host address type not as expected for address item %d within ticket info %d", j + 1, i + 1))
+			assert.Equal(t, "12d00023", hex.EncodeToString(addr.Address), fmt.Sprintf("Host address not as expected for address item %d within ticket info %d", j + 1, i + 1))
+		}
+}

+ 0 - 0
messages/Cred.go → messages/KRBError.go


+ 0 - 0
messages/Error_test.go → messages/KRBError_test.go


+ 0 - 0
messages/Error.go → messages/KRBPriv.go


+ 0 - 0
messages/Priv_test.go → messages/KRBPriv_test.go


+ 0 - 1
messages/Priv.go

@@ -1 +0,0 @@
-package messages

+ 4 - 4
testdata/test_vectors.go

@@ -51,14 +51,14 @@ var TestVectors = map[string]string{
 	//"encode_krb5_priv":                                           "75333031A003020105A103020115A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765",
 	//"encode_krb5_enc_priv_part":                                  "7C4F304DA00A04086B72623564617461A111180F31393934303631303036303331375AA205020301E240A303020111A40F300DA003020102A106040412D00023A50F300DA003020102A106040412D00023",
 	//"encode_krb5_enc_priv_part(optionalsNULL)":                   "7C1F301DA00A04086B72623564617461A40F300DA003020102A106040412D00023",
-	//"encode_krb5_cred":                                           "7681F63081F3A003020105A103020116A281BF3081BC615C305AA003020105A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765615C305AA003020105A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765",
-	//"encode_krb5_enc_cred_part":                                  "7D8202233082021FA08201DA308201D63081E8A0133011A003020101A10A04083132333435363738A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A307030500FEDCBA98A411180F31393934303631303036303331375AA511180F31393934303631303036303331375AA611180F31393934303631303036303331375AA711180F31393934303631303036303331375AA8101B0E415448454E412E4D49542E454455A91A3018A003020101A111300F1B066866747361691B056578747261AA20301E300DA003020102A106040412D00023300DA003020102A106040412D000233081E8A0133011A003020101A10A04083132333435363738A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A307030500FEDCBA98A411180F31393934303631303036303331375AA511180F31393934303631303036303331375AA611180F31393934303631303036303331375AA711180F31393934303631303036303331375AA8101B0E415448454E412E4D49542E454455A91A3018A003020101A111300F1B066866747361691B056578747261AA20301E300DA003020102A106040412D00023300DA003020102A106040412D00023A10302012AA211180F31393934303631303036303331375AA305020301E240A40F300DA003020102A106040412D00023A50F300DA003020102A106040412D00023",
-	//"encode_krb5_enc_cred_part(optionalsNULL)":                   "7D82010E3082010AA0820106308201023015A0133011A003020101A10A040831323334353637383081E8A0133011A003020101A10A04083132333435363738A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A307030500FEDCBA98A411180F31393934303631303036303331375AA511180F31393934303631303036303331375AA611180F31393934303631303036303331375AA711180F31393934303631303036303331375AA8101B0E415448454E412E4D49542E454455A91A3018A003020101A111300F1B066866747361691B056578747261AA20301E300DA003020102A106040412D00023300DA003020102A106040412D00023",
+	"encode_krb5_cred":                                           "7681F63081F3A003020105A103020116A281BF3081BC615C305AA003020105A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765615C305AA003020105A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765A3253023A003020100A103020105A21704156B726241534E2E312074657374206D657373616765",
+	"encode_krb5_enc_cred_part":                                  "7D8202233082021FA08201DA308201D63081E8A0133011A003020101A10A04083132333435363738A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A307030500FEDCBA98A411180F31393934303631303036303331375AA511180F31393934303631303036303331375AA611180F31393934303631303036303331375AA711180F31393934303631303036303331375AA8101B0E415448454E412E4D49542E454455A91A3018A003020101A111300F1B066866747361691B056578747261AA20301E300DA003020102A106040412D00023300DA003020102A106040412D000233081E8A0133011A003020101A10A04083132333435363738A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A307030500FEDCBA98A411180F31393934303631303036303331375AA511180F31393934303631303036303331375AA611180F31393934303631303036303331375AA711180F31393934303631303036303331375AA8101B0E415448454E412E4D49542E454455A91A3018A003020101A111300F1B066866747361691B056578747261AA20301E300DA003020102A106040412D00023300DA003020102A106040412D00023A10302012AA211180F31393934303631303036303331375AA305020301E240A40F300DA003020102A106040412D00023A50F300DA003020102A106040412D00023",
+	"encode_krb5_enc_cred_part(optionalsNULL)":                   "7D82010E3082010AA0820106308201023015A0133011A003020101A10A040831323334353637383081E8A0133011A003020101A10A04083132333435363738A1101B0E415448454E412E4D49542E454455A21A3018A003020101A111300F1B066866747361691B056578747261A307030500FEDCBA98A411180F31393934303631303036303331375AA511180F31393934303631303036303331375AA611180F31393934303631303036303331375AA711180F31393934303631303036303331375AA8101B0E415448454E412E4D49542E454455A91A3018A003020101A111300F1B066866747361691B056578747261AA20301E300DA003020102A106040412D00023300DA003020102A106040412D00023",
 	//"encode_krb5_error":                                          "7E81BA3081B7A003020105A10302011EA211180F31393934303631303036303331375AA305020301E240A411180F31393934303631303036303331375AA505020301E240A60302013CA7101B0E415448454E412E4D49542E454455A81A3018A003020101A111300F1B066866747361691B056578747261A9101B0E415448454E412E4D49542E454455AA1A3018A003020101A111300F1B066866747361691B056578747261AB0A1B086B72623564617461AC0A04086B72623564617461",
 	//"encode_krb5_error(optionalsNULL)":                           "7E60305EA003020105A10302011EA305020301E240A411180F31393934303631303036303331375AA505020301E240A60302013CA9101B0E415448454E412E4D49542E454455AA1A3018A003020101A111300F1B066866747361691B056578747261",
 	"encode_krb5_authorization_data": "3022300FA003020101A1080406666F6F626172300FA003020101A1080406666F6F626172",
 	"encode_krb5_padata_sequence":    "30243010A10302010DA209040770612D646174613010A10302010DA209040770612D64617461",
-	//"encode_krb5_typed_data":                                     "30243010A00302010DA109040770612D646174613010A00302010DA109040770612D64617461",
+	"encode_krb5_typed_data":                                     "30243010A00302010DA109040770612D646174613010A00302010DA109040770612D64617461",
 	"encode_krb5_padata_sequence(empty)": "3000",
 	"encode_krb5_etype_info":             "30333014A003020100A10D040B4D6F72746F6E27732023303005A0030201013014A003020102A10D040B4D6F72746F6E2773202332",
 	"encode_krb5_etype_info(only1)":      "30163014A003020100A10D040B4D6F72746F6E2773202330",

+ 0 - 17
types/KerberosString.go

@@ -1,17 +0,0 @@
-package types
-
-// Reference: https://www.ietf.org/rfc/rfc4120.txt
-// Section: 5.2.1
-
-import "encoding/asn1"
-
-type KerberosString []byte
-
-type krbStr struct {
-	Str string `asn1:"ia5"`
-}
-
-func ConvertToKerberosString(s string) (KerberosString, error) {
-	val := krbStr{Str: s}
-	return asn1.Marshal(val)
-}

+ 14 - 0
types/TypedData.go

@@ -1 +1,15 @@
 package types
+
+import "encoding/asn1"
+
+type TypedData struct {
+	DataType  int    `asn1:"explicit,tag:0"`
+	DataValue []byte `asn1:"optional,explicit,tag:1"`
+}
+
+type TypedDataSequence []TypedData
+
+func (a *TypedDataSequence) Unmarshal(b []byte) error {
+	_, err := asn1.Unmarshal(b, a)
+	return err
+}

+ 25 - 1
types/TypedData_test.go

@@ -1,3 +1,27 @@
 package types
 
-//encode_krb5_typed_data
+import (
+	"encoding/hex"
+	"github.com/stretchr/testify/assert"
+	"testing"
+	"github.com/jcmturner/gokrb5/testdata"
+	"fmt"
+)
+
+func TestUnmarshalTypedData(t *testing.T) {
+	var a TypedDataSequence
+	v := "encode_krb5_typed_data"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	err = a.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Unmarshal error of %s: %v\n", v, err)
+	}
+	assert.Equal(t, 2, len(a), "Number of typed data elements not as expected")
+	for i, d := range a {
+		assert.Equal(t, testdata.TEST_PADATA_TYPE, d.DataType, fmt.Sprintf("Data type of element %d not as expected", i+1))
+		assert.Equal(t, []byte(testdata.TEST_PADATA_VALUE), d.DataValue, fmt.Sprintf("Data value of element %d not as expected", i+1))
+	}
+}