瀏覽代碼

Ticket marshal

Jonathan Turner 9 年之前
父節點
當前提交
230852be27

+ 8 - 1
README.md

@@ -18,4 +18,11 @@ This is work in progress and does not yet work...
 * https://en.wikipedia.org/wiki/Ciphertext_stealing#CBC_ciphertext_stealing
 
 ## Thanks
-* Greg Hudson from the MIT Consortium for Kerberos and Internet Trust for providing useful test vectors.
+* Greg Hudson from the MIT Consortium for Kerberos and Internet Trust for providing useful test vectors.
+
+## Known Issues
+| Issue | Worked around? | References |
+|-------|-------------|------------|
+| Cannot unmarshal into slice of asn1.RawValue | Yes | [https://github.com/golang/go/issues/17321](https://github.com/golang/go/issues/17321) |
+| Cannot marshal into a GeneralString | Yes - using https://github.com/jcmturner/asn1 | [encoding/asn1: cannot marshal into a GeneralString](https://github.com/golang/go/issues/18832) |
+| Cannot marshal into slice of strings and pass stringtype parameter tags to members | Yes - using https://github.com/jcmturner/asn1 |[encoding/asn1: cannot marshal into slice of strings and pass stringtype parameter tags to members](https://github.com/golang/go/issues/18834) |

+ 2 - 2
messages/KDCRep.go

@@ -18,7 +18,7 @@ type marshalKDCRep struct {
 	PVNO             int                 `asn1:"explicit,tag:0"`
 	MsgType          int                 `asn1:"explicit,tag:1"`
 	PAData           types.PADataSequence     `asn1:"explicit,optional,tag:2"`
-	CRealm           string              `asn1:"explicit,tag:3"`
+	CRealm           string              `asn1:"generalstring,explicit,tag:3"`
 	CName            types.PrincipalName `asn1:"explicit,tag:4"`
 	// Ticket needs to be a raw value as it is wrapped in an APPLICATION tag
 	Ticket           asn1.RawValue       `asn1:"explicit,tag:5"`
@@ -50,7 +50,7 @@ type EncKDCRepPart struct {
 	StartTime     time.Time           `asn1:"explicit,optional,tag:6"`
 	EndTime       time.Time           `asn1:"explicit,tag:7"`
 	RenewTill     time.Time           `asn1:"explicit,optional,tag:8"`
-	SRealm        string              `asn1:"explicit,tag:9"`
+	SRealm        string              `asn1:"generalstring,explicit,tag:9"`
 	SName         types.PrincipalName `asn1:"explicit,tag:10"`
 	CAddr         []types.HostAddress `asn1:"explicit,optional,tag:11"`
 }

+ 22 - 22
messages/KDCReq.go

@@ -31,7 +31,7 @@ type TGSReq KDCReq
 type marshalKDCReqBody struct {
 	KDCOptions  asn1.BitString      `asn1:"explicit,tag:0"`
 	CName       types.PrincipalName `asn1:"explicit,optional,tag:1"`
-	Realm       string              `asn1:"ia5,explicit,tag:2"`
+	Realm       string              `asn1:"generalstring,explicit,tag:2"`
 	SName       types.PrincipalName `asn1:"explicit,optional,tag:3"`
 	From        time.Time           `asn1:"explicit,optional,tag:4"`
 	Till        time.Time           `asn1:"explicit,tag:5"`
@@ -47,7 +47,7 @@ type marshalKDCReqBody struct {
 type KDCReqBody struct {
 	KDCOptions        asn1.BitString      `asn1:"explicit,tag:0"`
 	CName             types.PrincipalName `asn1:"explicit,optional,tag:1"`
-	Realm             string              `asn1:"ia5,explicit,tag:2"`
+	Realm             string              `asn1:"generalstring,explicit,tag:2"`
 	SName             types.PrincipalName `asn1:"explicit,optional,tag:3"`
 	From              time.Time           `asn1:"explicit,optional,tag:4"`
 	Till              time.Time           `asn1:"explicit,tag:5"`
@@ -121,7 +121,7 @@ func (k *KDCReqBody) Unmarshal(b []byte) error {
 	k.Addresses = m.Addresses
 	k.EncAuthData = m.EncAuthData
 	if len(m.AdditionalTickets.Bytes) > 0 {
-		k.AdditionalTickets, err = types.UnmarshalSequenceTickets(m.AdditionalTickets)
+		k.AdditionalTickets, err = types.UnmarshalTicketsSequence(m.AdditionalTickets)
 		if err != nil {
 			return fmt.Errorf("Error unmarshalling additional tickets: %v", err)
 		}
@@ -139,22 +139,22 @@ func NewASReq() ASReq {
 	}
 }
 
-func (k *ASReq) Marshal() ([]byte, error) {
-
-}
-
-func (k *KDCReqBody) Marshal() ([]byte, error) {
-	m := marshalKDCReqBody{
-		KDCOptions:  k.KDCOptions,
-		CName:       k.CName,
-		Realm:       k.Realm,
-		SName:       k.SName,
-		From:        k.From,
-		Till:        k.Till,
-		RTime:       k.RTime,
-		Nonce:       k.Nonce,
-		EType:       k.EType,
-		Addresses:   k.Addresses,
-		EncAuthData: k.EncAuthData,
-	}
-}
+//func (k *ASReq) Marshal() ([]byte, error) {
+//
+//}
+//
+//func (k *KDCReqBody) Marshal() ([]byte, error) {
+//	m := marshalKDCReqBody{
+//		KDCOptions:  k.KDCOptions,
+//		CName:       k.CName,
+//		Realm:       k.Realm,
+//		SName:       k.SName,
+//		From:        k.From,
+//		Till:        k.Till,
+//		RTime:       k.RTime,
+//		Nonce:       k.Nonce,
+//		EType:       k.EType,
+//		Addresses:   k.Addresses,
+//		EncAuthData: k.EncAuthData,
+//	}
+//}

+ 3 - 3
messages/KRBCred.go

@@ -37,14 +37,14 @@ type EncKrbCredPart struct {
 
 type KrbCredInfo struct {
 	Key       types.EncryptionKey `asn1:"explicit,tag:0"`
-	PRealm    string              `asn1:"optional,explicit,tag:1"`
+	PRealm    string              `asn1:"generalstring,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"`
+	SRealm    string              `asn1:"optional,explicit,ia5,tag:8"`
 	SName     types.PrincipalName `asn1:"optional,explicit,tag:9"`
 	CAddr     types.HostAddresses `asn1:"optional,explicit,tag:10"`
 }
@@ -63,7 +63,7 @@ func (k *KRBCred) Unmarshal(b []byte) error {
 	k.MsgType = m.MsgType
 	k.EncPart = m.EncPart
 	if len(m.Tickets.Bytes) > 0 {
-		k.Tickets, err = types.UnmarshalSequenceTickets(m.Tickets)
+		k.Tickets, err = types.UnmarshalTicketsSequence(m.Tickets)
 		if err != nil {
 			return fmt.Errorf("Error unmarshalling tickets within KRB_CRED: %v", err)
 		}

+ 3 - 3
messages/KRBError.go

@@ -16,11 +16,11 @@ type KRBError struct {
 	STime     time.Time           `asn1:"explicit,tag:4"`
 	Susec     int                 `asn1:"explicit,tag:5"`
 	ErrorCode int                 `asn1:"explicit,tag:6"`
-	CRealm    string              `asn1:"optional,explicit,tag:7"`
+	CRealm    string              `asn1:"generalstring,optional,explicit,tag:7"`
 	CName     types.PrincipalName `asn1:"optional,explicit,tag:8"`
-	Realm     string              `asn1:"explicit,tag:9"`
+	Realm     string              `asn1:"generalstring,explicit,tag:9"`
 	SName     types.PrincipalName `asn1:"explicit,tag:10"`
-	EText     string              `asn1:"optional,explicit,tag:11"`
+	EText     string              `asn1:"generalstring,optional,explicit,tag:11"`
 	EData     []byte              `asn1:"optional,explicit,tag:12"`
 }
 

+ 1 - 1
types/Authenticator.go

@@ -29,7 +29,7 @@ authorization-data      [8] AuthorizationData OPTIONAL
 
 type Authenticator struct {
 	AVNO              int               `asn1:"explicit,tag:0"`
-	CRealm            string            `asn1:"explicit,tag:1"`
+	CRealm            string            `asn1:"generalstring,explicit,tag:1"`
 	CName             PrincipalName     `asn1:"explicit,tag:2"`
 	Cksum             Checksum          `asn1:"explicit,optional,tag:3"`
 	Cusec             int               `asn1:"explicit,tag:4"`

+ 1 - 1
types/AuthorizationData.go

@@ -91,7 +91,7 @@ type ADAndOr struct {
 
 type ADKDCIssued struct {
 	ADChecksum Checksum          `asn1:"explicit,tag:0"`
-	IRealm     string            `asn1:"optional,explicit,tag:1"`
+	IRealm     string            `asn1:"optional,generalstring,explicit,tag:1"`
 	Isname     PrincipalName     `asn1:"optional,explicit,tag:2"`
 	Elements   AuthorizationData `asn1:"explicit,tag:3"`
 }

+ 1 - 1
types/PAData.go

@@ -32,7 +32,7 @@ type ETypeInfo []ETypeInfoEntry
 
 type ETypeInfo2Entry struct {
 	EType     int    `asn1:"explicit,tag:0"`
-	Salt      string `asn1:"explicit,optional,tag:1,ia5"`
+	Salt      string `asn1:"explicit,optional,generalstring,tag:1,ia5"`
 	S2KParams []byte `asn1:"explicit,optional,tag:2"`
 }
 

+ 2 - 1
types/PrincipalName.go

@@ -5,5 +5,6 @@ package types
 
 type PrincipalName struct {
 	NameType   int      `asn1:"explicit,tag:0"`
-	NameString []string `asn1:"explicit,tag:1,ia5"`
+	NameString []string `asn1:"generalstring,explicit,tag:1"`
 }
+

+ 23 - 10
types/Ticket.go

@@ -4,6 +4,7 @@ import (
 	"encoding/asn1"
 	"fmt"
 	"github.com/jcmturner/gokrb5/types/asnAppTag"
+	jtasn1 "github.com/jcmturner/asn1"
 	"time"
 )
 
@@ -12,7 +13,7 @@ import (
 
 type Ticket struct {
 	TktVNO  int           `asn1:"explicit,tag:0"`
-	Realm   string        `asn1:"explicit,tag:1"`
+	Realm   string        `asn1:"generalstring,explicit,tag:1"`
 	SName   PrincipalName `asn1:"explicit,tag:2"`
 	EncPart EncryptedData `asn1:"explicit,tag:3"`
 }
@@ -20,7 +21,7 @@ type Ticket struct {
 type EncTicketPart struct {
 	Flags             asn1.BitString    `asn1:"explicit,tag:0"`
 	Key               EncryptionKey     `asn1:"explicit,tag:1"`
-	CRealm            string            `asn1:"explicit,tag:2"`
+	CRealm            string            `asn1:"generalstring,explicit,tag:2"`
 	CName             PrincipalName     `asn1:"explicit,tag:3"`
 	Transited         TransitedEncoding `asn1:"explicit,tag:4"`
 	AuthTime          time.Time         `asn1:"explicit,tag:5"`
@@ -41,6 +42,15 @@ func (t *Ticket) Unmarshal(b []byte) error {
 	return err
 }
 
+func (t *Ticket) Marshal() ([]byte, error) {
+	b, err := jtasn1.Marshal(*t)
+	if err != nil {
+		return nil, err
+	}
+	b = asnAppTag.AddASNAppTag(b, asnAppTag.Ticket)
+	return b, nil
+}
+
 func (t *EncTicketPart) Unmarshal(b []byte) error {
 	_, err := asn1.UnmarshalWithParams(b, t, fmt.Sprintf("application,explicit,tag:%d", asnAppTag.EncTicketPart))
 	return err
@@ -51,7 +61,10 @@ func UnmarshalTicket(b []byte) (t Ticket, err error) {
 	return
 }
 
-func UnmarshalSequenceTickets(in asn1.RawValue) ([]Ticket, error) {
+func UnmarshalTicketsSequence(in asn1.RawValue) ([]Ticket, error) {
+	//fmt.Fprintf(os.Stderr, "Raw c: %v\n", in.Class)
+	//fmt.Fprintf(os.Stderr, "Raw  b: %v\n", in.Bytes)
+	//fmt.Fprintf(os.Stderr, "Raw fb: %v\n", in.FullBytes)
 	//This is a workaround to a asn1 decoding issue in golang - https://github.com/golang/go/issues/17321. It's not pretty I'm afraid
 	//We pull out raw values from the larger raw value (that is actually the data of the sequence of raw values) and track our position moving along the data.
 	b := in.Bytes
@@ -74,10 +87,10 @@ func UnmarshalSequenceTickets(in asn1.RawValue) ([]Ticket, error) {
 	return tkts, nil
 }
 
-func MarshalTicketSequence([]Ticket) (asn1.RawValue, error) {
-	raw := asn1.RawValue{
-		Class:      16,
-		IsCompound: true,
-	}
-
-}
+//func MarshalTicketSequence([]Ticket) (asn1.RawValue, error) {
+//	raw := asn1.RawValue{
+//		Class:      16,
+//		IsCompound: true,
+//	}
+//
+//}

+ 18 - 0
types/Ticket_test.go

@@ -93,3 +93,21 @@ func TestUnmarshalEncTicketPart_optionalsNULL(t *testing.T) {
 	assert.Equal(t, tt, a.AuthTime, "Auth time not as expected")
 	assert.Equal(t, tt, a.EndTime, "End time not as expected")
 }
+
+func TestMarshalTicket(t *testing.T) {
+	var a Ticket
+	v := "encode_krb5_ticket"
+	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)
+	}
+	mb, err := a.Marshal()
+	if err != nil {
+		t.Fatalf("Marshal of ticket errored: %v", err)
+	}
+	assert.Equal(t, b, mb, "Marshalled bytes not as expected")
+}

+ 14 - 1
types/asnAppTag/constants.go

@@ -20,5 +20,18 @@ const (
 	EncKrbCredPart = 29
 	KRBError       = 30
 )
-
+// The Marshal method of golang's asn1 package does not enable you to configure to wrap the output in an application tag.
+// This method adds that wrapping tag
+func AddASNAppTag(b []byte, tag int) []byte {
+	// The ASN1 wrapping consists of 2 bytes:
+	// 1st byte -> Application Tag
+	// 2nd byte -> The length (this will be the size indicated in the input bytes + 2 for the additional bytes we add here.
+	// Application Tag:
+	//| Byte:       | 8                            | 7                          | 6                                         | 5 | 4 | 3 | 2 | 1             |
+	//| Value:      | 0                            | 1                          | 1                                         | From the RFC spec 4120        |
+	//| Explanation | Defined by the ASN1 encoding rules for an application tag | A value of 1 indicates a constructed type | The ASN Application tag value |
+	// Therefore the value of the byte is an integer = ( Application tag value + 96 )
+	b = append([]byte{byte(96 + tag), byte(b[1] + 2)}, b...)
+	return b
+}
 //TODO review if we want to consolidate with the MsgTypes in the dictionary