Jonathan Turner 9 éve
szülő
commit
48d3fa4ea5
6 módosított fájl, 125 hozzáadás és 3 törlés
  1. 0 1
      GSSAPI/MechType.go
  2. 2 0
      GSSAPI/NegotiationToken.go
  3. 61 0
      GSSAPI/gssapi.go
  4. 52 0
      GSSAPI/gssapi_test.go
  5. 8 0
      asn1tools/tools.go
  6. 2 2
      types/Ticket.go

+ 0 - 1
GSSAPI/MechType.go

@@ -1,7 +1,6 @@
 package GSSAPI
 
 const (
-	SPNEGO_OIDHex                = "2b0601050502"       //1.3.6.1.5.5.2
 	MechType_Krb5_OIDHex         = "2a864886f712010202" //1.2.840.113554.1.2.2
 	MechType_MSLegacyKrb5_OIDHex = "2a864882f712010202" //1.2.840.48018.1.2.2
 )

+ 2 - 0
GSSAPI/NegotiationToken.go

@@ -61,6 +61,8 @@ type NegTokenResp struct {
 	MechListMIC   []byte                `asn1:"explicit,optional,tag:3"`
 }
 
+type NegTokenTarg NegTokenResp
+
 // Unmarshal and return either a NegTokenInit or a NegTokenResp.
 //
 // The boolean indicates if the response is a NegTokenInit.

+ 61 - 0
GSSAPI/gssapi.go

@@ -0,0 +1,61 @@
+package GSSAPI
+
+import (
+	"errors"
+	"fmt"
+	"github.com/jcmturner/asn1"
+)
+
+const (
+	SPNEGO_OIDHex = "2b0601050502" //1.3.6.1.5.5.2
+)
+
+type SPNEGO struct {
+	Init         bool
+	Resp         bool
+	NegTokenInit NegTokenInit
+	NegTokenResp NegTokenResp
+}
+
+func (s *SPNEGO) Unmarshal(b []byte) error {
+	var r []byte
+	var err error
+	if b[0] != byte(161) {
+		// Not a NegTokenResp/Targ could be a NegTokenInit
+		var oid asn1.ObjectIdentifier
+		r, err = asn1.UnmarshalWithParams(b, &oid, fmt.Sprintf("application,explicit,tag:%v", 0))
+		if err != nil {
+			return fmt.Errorf("Not a valid SPNEGO token: %v", err)
+		}
+		// Check the OID is the SPNEGO OID value
+		if !oid.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 2}) {
+			return errors.New("OID does not match SPNEGO OID 1.3.6.1.5.5.2")
+		}
+	} else {
+		// Could be a NegTokenResp/Targ
+		r = b
+	}
+
+	var a asn1.RawValue
+	_, err = asn1.Unmarshal(r, &a)
+	if err != nil {
+		return fmt.Errorf("Error unmarshalling SPNEGO: %v", err)
+	}
+	switch a.Tag {
+	case 0:
+		_, err = asn1.Unmarshal(a.Bytes, &s.NegTokenInit)
+		if err != nil {
+			return fmt.Errorf("Error unmarshalling NegotiationToken type %d: %v", a.Tag, err)
+		}
+		s.Init = true
+	case 1:
+		_, err = asn1.Unmarshal(a.Bytes, &s.NegTokenResp)
+		if err != nil {
+			return fmt.Errorf("Error unmarshalling NegotiationToken type %d: %v", a.Tag, err)
+		}
+		s.Resp = true
+	default:
+		return errors.New("Unknown choice type for NegotiationToken")
+	}
+	return nil
+}

+ 52 - 0
GSSAPI/gssapi_test.go

@@ -0,0 +1,52 @@
+package GSSAPI
+
+import (
+	"encoding/hex"
+	"github.com/jcmturner/asn1"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+const (
+	test_gssapi_init = "608202b606062b0601050502a08202aa308202a6a027302506092a864886f71201020206052b0501050206092a864882f71201020206062b0601050205a2820279048202756082027106092a864886f71201020201006e8202603082025ca003020105a10302010ea20703050000000000a38201706182016c30820168a003020105a10d1b0b544553542e474f4b524235a2233021a003020103a11a30181b04485454501b10686f73742e746573742e676f6b726235a382012b30820127a003020112a103020102a282011904820115d4bd890abc456f44e2e7a2e8111bd6767abf03266dfcda97c629af2ece450a5ae1f145e4a4d1bc2c848e66a6c6b31d9740b26b03cdbd2570bfcf126e90adf5f5ebce9e283ff5086da47b129b14fc0aabd4d1df9c1f3c72b80cc614dfc28783450b2c7b7749651f432b47aaa2ff158c0066b757f3fb00dd7b4f63d68276c76373ecdd3f19c66ebc43a81e577f3c263b878356f57e8d6c4eccd587b81538e70392cf7e73fc12a6f7c537a894a7bb5566c83ac4d69757aa320a51d8d690017aebf952add1889adfc3307b0e6cd8c9b57cf8589fbe52800acb6461c25473d49faa1bdceb8bce3f61db23f9cd6a09d5adceb411e1c4546b30b33331e570fd6bc50aa403557e75f488e759750ea038aab6454667d9b64f41a481d23081cfa003020112a281c70481c4eb593beb5afcb1a2a669d54cb85a3772231559f2d40c9f8f053f218ba6eb084ed7efc467d94b88bcd189dda920d6e675ec001a6a2bca11f0a1de37f2f7ae9929f94a86d625b2ec1b213a88cbae6099dda7b172cd3bd1802cb177ae4554d59277004bfd3435248f55044fe7af7b2c9c5a3c43763278c585395aebe2856cdff9f2569d8b823564ce6be2d19748b910ec06bd3c0a9bc5de51ddcf7d875f1108ca6ad935f52d90cb62a18197d9b8e796bef0fbe1463f61df61cfbce6008ae9e1a2d2314a986d"
+	test_gssapi_resp = "a1143012a0030a0100a10b06092a864886f712010202"
+)
+
+func TestUnmarshal_SPNEGO_Init(t *testing.T) {
+	b, err := hex.DecodeString(test_gssapi_init)
+	if err != nil {
+		t.Fatalf("Error converting hex string test data to bytes: %v", err)
+	}
+	var s SPNEGO
+	err = s.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshalling SPNEGO with NegTokenInit: %v", err)
+	}
+	assert.True(t, s.Init, "SPNEGO does not indicate it contains NegTokenInit as expected")
+	assert.False(t, s.Resp, "SPNEGO indicates is contains a NegTokenResp but it shouldn't")
+	assert.Equal(t, 4, len(s.NegTokenInit.MechTypes))
+	expectMechTypes := []asn1.ObjectIdentifier{
+		[]int{1, 2, 840, 113554, 1, 2, 2},
+		[]int{1, 3, 5, 1, 5, 2},
+		[]int{1, 2, 840, 48018, 1, 2, 2},
+		[]int{1, 3, 6, 1, 5, 2, 5},
+	}
+	assert.Equal(t, expectMechTypes, s.NegTokenInit.MechTypes, "MechTypes list in NegTokenInit not as expected")
+	assert.NotZero(t, len(s.NegTokenInit.MechToken), "MechToken is zero in length")
+}
+
+func TestUnmarshal_SPNEGO_RespTarg(t *testing.T) {
+	b, err := hex.DecodeString(test_gssapi_resp)
+	if err != nil {
+		t.Fatalf("Error converting hex string test data to bytes: %v", err)
+	}
+	var s SPNEGO
+	err = s.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshalling SPNEGO with NegTokenResp/NegTokenTarg: %v", err)
+	}
+	assert.True(t, s.Resp, "SPNEGO does not indicate it contains NegTokenResp/Targ as expected")
+	assert.False(t, s.Init, "SPNEGO indicates is contains a NegTokenInit but it shouldn't")
+	assert.Equal(t, asn1.Enumerated(0), s.NegTokenResp.NegState, "Negtiation state not as expected.")
+	assert.Equal(t, asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2}, s.NegTokenResp.SupportedMech, "SupportedMech type not as expected.")
+}

+ 8 - 0
asn1tools/tools.go

@@ -41,6 +41,14 @@ func GetLengthFromASN(b []byte) int {
 	return l
 }
 
+func GetNumberBytesInLengthHeader(b []byte) int {
+	if int(b[1]) <= 127 {
+		return 1
+	}
+	// The bytes that indicate the length
+	return 1 + int(b[1]) - 128
+}
+
 // The Marshal method of golang's asn1 package does not enable you to define wrapping the output in an application tag.
 // This method adds that wrapping tag.
 func AddASNAppTag(b []byte, tag int) []byte {

+ 2 - 2
types/Ticket.go

@@ -66,8 +66,8 @@ func UnmarshalTicketsSequence(in asn1.RawValue) ([]Ticket, error) {
 	//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
-	// Ignore the head of the asn1 stream (3bytes) as this is what tells us its a sequence but we're handling it ourselves
-	p := 3
+	// Ignore the head of the asn1 stream (1 byte for tag and those for the length) as this is what tells us its a sequence but we're handling it ourselves
+	p := 1 + asn1tools.GetNumberBytesInLengthHeader(in.Bytes)
 	var tkts []Ticket
 	var raw asn1.RawValue
 	for p < (len(b)) {