Browse Source

wip on btstring marshal

Jonathan Turner 9 years ago
parent
commit
3105b99d39
4 changed files with 117 additions and 34 deletions
  1. 2 1
      README.md
  2. 61 26
      messages/KDCReq.go
  3. 51 0
      messages/KDCReq_test.go
  4. 3 7
      types/Ticket.go

+ 2 - 1
README.md

@@ -26,4 +26,5 @@ This is work in progress and does not yet work...
 | 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) |
-| Cannot marshal with application tags | Yes | |
+| Cannot marshal with application tags | Yes | |
+| Marshalling of bit string does not just marshal the bitstring bytes but also the BitLength attribute | | |

+ 61 - 26
messages/KDCReq.go

@@ -6,6 +6,8 @@ package messages
 import (
 	"encoding/asn1"
 	"fmt"
+	jtasn1 "github.com/jcmturner/asn1"
+	"github.com/jcmturner/gokrb5/asn1tools"
 	"github.com/jcmturner/gokrb5/types"
 	"github.com/jcmturner/gokrb5/types/asnAppTag"
 	"time"
@@ -110,6 +112,11 @@ func (k *KDCReqBody) Unmarshal(b []byte) error {
 		return fmt.Errorf("Error unmarshalling KDC_REQ_BODY: %v", err)
 	}
 	k.KDCOptions = m.KDCOptions
+	if len(k.KDCOptions.Bytes) < 4 {
+		tb := make([]byte, 4-len(k.KDCOptions.Bytes))
+		k.KDCOptions.Bytes = append(tb, k.KDCOptions.Bytes...)
+		k.KDCOptions.BitLength = len(k.KDCOptions.Bytes) * 8
+	}
 	k.CName = m.CName
 	k.Realm = m.Realm
 	k.SName = m.SName
@@ -129,32 +136,60 @@ func (k *KDCReqBody) Unmarshal(b []byte) error {
 	return nil
 }
 
-func NewASReq() ASReq {
-	return ASReq{
-		PVNO:    5,
-		MsgType: types.KrbDictionary.MsgTypesByName["KRB_AS_REQ"],
-		ReqBody: KDCReqBody{
-			KDCOptions: asn1.BitString{},
-		},
+//func NewASReq() ASReq {
+//	return ASReq{
+//		PVNO:    5,
+//		MsgType: types.KrbDictionary.MsgTypesByName["KRB_AS_REQ"],
+//		ReqBody: KDCReqBody{
+//			KDCOptions: asn1.BitString{},
+//		},
+//	}
+//}
+
+func (k *ASReq) Marshal() ([]byte, error) {
+	m := marshalKDCReq{
+		PVNO:    k.PVNO,
+		MsgType: k.MsgType,
+		PAData:  k.PAData,
+	}
+	b, err := k.ReqBody.Marshal()
+	if err != nil {
+		var mk []byte
+		return mk, err
+	}
+	m.ReqBody = asn1.RawValue{
+		Class:      2,
+		IsCompound: true,
+		Tag:        4,
+		Bytes:      b,
+	}
+	mk, err := jtasn1.Marshal(m)
+	if err != nil {
+		return mk, fmt.Errorf("Error marshalling AS_REQ: %v", err)
 	}
+	mk = asn1tools.AddASNAppTag(mk, asnAppTag.ASREQ)
+	return mk, nil
 }
 
-//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 *KDCReqBody) Marshal() ([]byte, error) {
+	var b []byte
+	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,
+	}
+	rawtkts, err := types.MarshalTicketSequence(k.AdditionalTickets)
+	if err != nil {
+		return b, fmt.Errorf("Error in marshalling KDC request body additional tickets: %v", err)
+	}
+	m.AdditionalTickets = rawtkts
+	return jtasn1.Marshal(m)
+}

+ 51 - 0
messages/KDCReq_test.go

@@ -3,6 +3,7 @@ package messages
 import (
 	"encoding/hex"
 	"fmt"
+	"github.com/jcmturner/asn1"
 	"github.com/jcmturner/gokrb5/testdata"
 	"github.com/jcmturner/gokrb5/types"
 	"github.com/stretchr/testify/assert"
@@ -390,3 +391,53 @@ func TestUnmarshalASReq_raw(t *testing.T) {
 	assert.Equal(t, 2069991465, asReq.ReqBody.Nonce, "Nonce field in request body not as expected")
 	assert.Equal(t, []int{18, 17, 16, 23, 25, 26}, asReq.ReqBody.EType, "Accepted EType field in request body not as expected")
 }
+
+//// Marshal Tests ////
+
+func TestMarshalKDCReqBody(t *testing.T) {
+	var a KDCReqBody
+	v := "encode_krb5_kdc_req_body"
+	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)
+	}
+	a.KDCOptions.BitLength += 8
+	a.KDCOptions.Bytes = append([]byte{byte(0)}, a.KDCOptions.Bytes...)
+	mb, err := a.Marshal()
+	if err != nil {
+		t.Fatalf("Marshal of ticket errored: %v", err)
+	}
+	//a.KDCOptions.Bytes.BitLength += 8
+	//a.KDCOptions.Bytes.Bytes = append([]byte{byte(0)}, a.KDCOptions.Bytes.Bytes...)
+	//assert.Equal(t, b, mb, "Marshalled bytes not as expected")
+	a.KDCOptions.BitLength = 40
+	fmt.Fprintf(os.Stderr, " in: %v\nout: %v\n", b, mb)
+	j, _ := asn1.Marshal(a.KDCOptions.Bytes)
+	fmt.Fprintf(os.Stderr, "ib: %v\n j: %v\n", b[5:13], j)
+	fmt.Fprintf(os.Stderr, "ib: %v\n j: %v\n", hex.EncodeToString(b[5:13]), hex.EncodeToString(j))
+	fmt.Fprintf(os.Stderr, "bs: %+v", a.KDCOptions.Bytes)
+
+}
+
+func TestMarshalASReq(t *testing.T) {
+	var a ASReq
+	v := "encode_krb5_as_req"
+	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")
+	fmt.Fprintf(os.Stderr, " in: %v\nout: %v", b, mb)
+}

+ 3 - 7
types/Ticket.go

@@ -2,12 +2,10 @@ package types
 
 import (
 	"encoding/asn1"
-	"encoding/hex"
 	"fmt"
 	jtasn1 "github.com/jcmturner/asn1"
 	"github.com/jcmturner/gokrb5/asn1tools"
 	"github.com/jcmturner/gokrb5/types/asnAppTag"
-	"os"
 	"time"
 )
 
@@ -65,10 +63,6 @@ func UnmarshalTicket(b []byte) (t Ticket, err error) {
 }
 
 func UnmarshalTicketsSequence(in asn1.RawValue) ([]Ticket, error) {
-	fmt.Fprintf(os.Stderr, "Raw c: %v is: %v t: %v\n", in.Class, in.IsCompound, in.Tag)
-	fmt.Fprintf(os.Stderr, "Raw  b: %v\n", in.Bytes)
-	fmt.Fprintf(os.Stderr, "Raw  b: %v\n", hex.EncodeToString(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
@@ -114,7 +108,9 @@ func MarshalTicketSequence(tkts []Ticket) (asn1.RawValue, error) {
 	//| 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 |
 	btkts = append(asn1tools.MarshalLengthBytes(len(btkts)), btkts...)
-	fmt.Fprintf(os.Stderr, "mar: %+v", btkts)
+	btkts = append([]byte{byte(32 + asn1.TagSequence)}, btkts...)
 	raw.Bytes = btkts
+	// If we need to create teh full bytes then identifier octect is "context-specific" = 128 + "constructed" + 32 + the wrapping explicit tag (11)
+	//fmt.Fprintf(os.Stderr, "mRaw fb: %v\n", raw.FullBytes)
 	return raw, nil
 }