Browse Source

gssapi unit tests

Jonathan Turner 9 years ago
parent
commit
78313f1530
5 changed files with 118 additions and 41 deletions
  1. 3 3
      GSSAPI/NegotiationToken.go
  2. 5 7
      GSSAPI/gssapi.go
  3. 34 0
      GSSAPI/gssapi_test.go
  4. 5 5
      GSSAPI/krb5Token.go
  5. 71 26
      GSSAPI/krb5Token_test.go

+ 3 - 3
GSSAPI/NegotiationToken.go

@@ -4,7 +4,7 @@ import (
 	"errors"
 	"fmt"
 	"github.com/jcmturner/asn1"
-	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/credentials"
 	"github.com/jcmturner/gokrb5/messages"
 	"github.com/jcmturner/gokrb5/types"
 )
@@ -131,8 +131,8 @@ func (n *NegTokenResp) Marshal() ([]byte, error) {
 }
 
 // Create new Init negotiation token for Kerberos 5
-func NewNegTokenInitKrb5(c config.Config, cname types.PrincipalName, tkt messages.Ticket, sessionKey types.EncryptionKey) (NegTokenInit, error) {
-	mt, err := NewKRB5APREQMechToken(c, cname, tkt, sessionKey)
+func NewNegTokenInitKrb5(creds credentials.Credentials, tkt messages.Ticket, sessionKey types.EncryptionKey) (NegTokenInit, error) {
+	mt, err := NewKRB5APREQMechToken(creds, tkt, sessionKey)
 	if err != nil {
 		return NegTokenInit{}, fmt.Errorf("Error getting MechToken; %v", err)
 	}

+ 5 - 7
GSSAPI/gssapi.go

@@ -64,23 +64,21 @@ func (s *SPNEGO) Unmarshal(b []byte) error {
 // Marshal SPNEGO negotiation token
 func (s *SPNEGO) Marshal() ([]byte, error) {
 	var b []byte
-	if !s.Init && !s.Resp {
-		return b, errors.New("SPNEGO cannot be marshalled. It contains neither a NegTokenInit or NegTokenResp")
-	}
-	hb, _ := asn1.Marshal(SPNEGO_OID)
 	if s.Init {
+		hb, _ := asn1.Marshal(SPNEGO_OID)
 		tb, err := s.NegTokenInit.Marshal()
 		if err != nil {
 			return b, fmt.Errorf("Could not marshal NegTokenInit: %v", err)
 		}
 		b = append(hb, tb...)
+		return asn1tools.AddASNAppTag(b, 0), nil
 	}
 	if s.Resp {
-		tb, err := s.NegTokenResp.Marshal()
+		b, err := s.NegTokenResp.Marshal()
 		if err != nil {
 			return b, fmt.Errorf("Could not marshal NegTokenResp: %v", err)
 		}
-		b = append(hb, tb...)
+		return b, nil
 	}
-	return asn1tools.AddASNAppTag(b, 0), nil
+	return b, errors.New("SPNEGO cannot be marshalled. It contains neither a NegTokenInit or NegTokenResp")
 }

+ 34 - 0
GSSAPI/gssapi_test.go

@@ -50,3 +50,37 @@ func TestUnmarshal_SPNEGO_RespTarg(t *testing.T) {
 	assert.Equal(t, asn1.Enumerated(0), s.NegTokenResp.NegState, "Negtiation state not as expected.")
 	assert.Equal(t, MechTypeOID_Krb5, s.NegTokenResp.SupportedMech, "SupportedMech type not as expected.")
 }
+
+func TestMarshal_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)
+	}
+	mb, err := s.Marshal()
+	if err != nil {
+		t.Fatalf("Error marshalling SPNEGO containing NegTokenInit: %v", err)
+	}
+	assert.Equal(t, b, mb, "Marshaled bytes not as expected")
+}
+
+func TestMarshal_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: %v", err)
+	}
+	mb, err := s.Marshal()
+	if err != nil {
+		t.Fatalf("Error marshalling SPNEGO containing NegTokenResp: %v", err)
+	}
+	assert.Equal(t, b, mb, "Marshaled bytes not as expected")
+}

+ 5 - 5
GSSAPI/krb5Token.go

@@ -6,7 +6,7 @@ import (
 	"fmt"
 	"github.com/jcmturner/asn1"
 	"github.com/jcmturner/gokrb5/asn1tools"
-	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/credentials"
 	"github.com/jcmturner/gokrb5/crypto"
 	"github.com/jcmturner/gokrb5/iana/chksumtype"
 	"github.com/jcmturner/gokrb5/messages"
@@ -91,7 +91,7 @@ func (m *MechToken) IsKRBError() bool {
 }
 
 // Create new kerberos AP_REQ MechToken
-func NewKRB5APREQMechToken(c config.Config, cname types.PrincipalName, tkt messages.Ticket, sessionKey types.EncryptionKey) ([]byte, error) {
+func NewKRB5APREQMechToken(creds credentials.Credentials, tkt messages.Ticket, sessionKey types.EncryptionKey) ([]byte, error) {
 	// Create the header
 	b, _ := asn1.Marshal(MechTypeOID_Krb5)
 	tb, _ := hex.DecodeString(TOK_ID_KRB_AP_REQ)
@@ -100,7 +100,7 @@ func NewKRB5APREQMechToken(c config.Config, cname types.PrincipalName, tkt messa
 	APReq, err := messages.NewAPReq(
 		tkt,
 		sessionKey,
-		newAuthenticator(c, cname, sessionKey.KeyType),
+		newAuthenticator(creds, sessionKey.KeyType),
 	)
 	tb, err = APReq.Marshal()
 	if err != nil {
@@ -111,9 +111,9 @@ func NewKRB5APREQMechToken(c config.Config, cname types.PrincipalName, tkt messa
 }
 
 // Create new kerberos authenticator for kerberos MechToken
-func newAuthenticator(c config.Config, cname types.PrincipalName, keyType int) types.Authenticator {
+func newAuthenticator(creds credentials.Credentials, keyType int) types.Authenticator {
 	//RFC 4121 Section 4.1.1
-	auth := types.NewAuthenticator(c.LibDefaults.Default_realm, cname)
+	auth := types.NewAuthenticator(creds.Realm, creds.CName)
 	auth.Cksum = types.Checksum{
 		CksumType: chksumtype.GSSAPI,
 		Checksum:  newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG}),

+ 71 - 26
GSSAPI/krb5Token_test.go

@@ -2,53 +2,98 @@ package GSSAPI
 
 import (
 	"encoding/hex"
+	"github.com/jcmturner/gokrb5/credentials"
+	"github.com/jcmturner/gokrb5/iana/msgtype"
 	"github.com/jcmturner/gokrb5/messages"
 	"github.com/jcmturner/gokrb5/testdata"
 	"github.com/jcmturner/gokrb5/types"
+	"github.com/stretchr/testify/assert"
+	"math"
 	"testing"
 )
 
-const MechToken_Hex = "6082026306092a864886f71201020201006e8202523082024ea003020105a10302010ea20703050000000000a382015d6182015930820155a003020105a10d1b0b544553542e474f4b524235a2233021a003020101a11a30181b04485454501b10686f73742e746573742e676f6b726235a382011830820114a003020112a103020103a28201060482010230621d868c97f30bf401e03bbffcd724bd9d067dce2afc31f71a356449b070cdafcc1ff372d0eb1e7a708b50c0152f3996c45b1ea312a803907fb97192d39f20cdcaea29876190f51de6e2b4a4df0460122ed97f363434e1e120b0e76c172b4424a536987152ac0b73013ab88af4b13a3fcdc63f739039dd46d839709cf5b51bb0ce6cb3af05fab3844caac280929955495235e9d0424f8a1fb9b4bd4f6bba971f40b97e9da60b9dabfcf0b1feebfca02c9a19b327a0004aa8e19192726cf347561fa8ac74afad5d6a264e50cf495b93aac86c77b2bc2d184234f6c2767dbea431485a25687b9044a20b601e968efaefffa1fc5283ff32aa6a53cb6c5cdd2eddcb26a481d73081d4a003020112a103020103a281c70481c4a1b29e420324f7edf9efae39df7bcaaf196a3160cf07e72f52a4ef8a965721b2f3343719c50699046e4fcc18ca26c2bfc7e4a9eddfc9d9cfc57ff2f6bdbbd1fc40ac442195bc669b9a0dbba12563b3e4cac9f4022fc01b8aa2d1ab84815bb078399ff7f4d5f9815eef896a0c7e3c049e6fd9932b97096cdb5861425b9d81753d0743212ded1a0fb55a00bf71a46be5ce5e1c8a5cc327b914347d9efcb6cb31ca363b1850d95c7b6c4c3cc6301615ad907318a0c5379d343610fab17eca9c7dc0a5a60658"
+const (
+	MechToken_Hex = "6082026306092a864886f71201020201006e8202523082024ea003020105a10302010ea20703050000000000a382015d6182015930820155a003020105a10d1b0b544553542e474f4b524235a2233021a003020101a11a30181b04485454501b10686f73742e746573742e676f6b726235a382011830820114a003020112a103020103a28201060482010230621d868c97f30bf401e03bbffcd724bd9d067dce2afc31f71a356449b070cdafcc1ff372d0eb1e7a708b50c0152f3996c45b1ea312a803907fb97192d39f20cdcaea29876190f51de6e2b4a4df0460122ed97f363434e1e120b0e76c172b4424a536987152ac0b73013ab88af4b13a3fcdc63f739039dd46d839709cf5b51bb0ce6cb3af05fab3844caac280929955495235e9d0424f8a1fb9b4bd4f6bba971f40b97e9da60b9dabfcf0b1feebfca02c9a19b327a0004aa8e19192726cf347561fa8ac74afad5d6a264e50cf495b93aac86c77b2bc2d184234f6c2767dbea431485a25687b9044a20b601e968efaefffa1fc5283ff32aa6a53cb6c5cdd2eddcb26a481d73081d4a003020112a103020103a281c70481c4a1b29e420324f7edf9efae39df7bcaaf196a3160cf07e72f52a4ef8a965721b2f3343719c50699046e4fcc18ca26c2bfc7e4a9eddfc9d9cfc57ff2f6bdbbd1fc40ac442195bc669b9a0dbba12563b3e4cac9f4022fc01b8aa2d1ab84815bb078399ff7f4d5f9815eef896a0c7e3c049e6fd9932b97096cdb5861425b9d81753d0743212ded1a0fb55a00bf71a46be5ce5e1c8a5cc327b914347d9efcb6cb31ca363b1850d95c7b6c4c3cc6301615ad907318a0c5379d343610fab17eca9c7dc0a5a60658"
+	Auth_Chksum   = "100000000000000000000000000000000000000030000000"
+)
 
-func TestKrb5Token_NewAPREQ(t *testing.T) {
-	var tkt messages.Ticket
-	b, err := hex.DecodeString(testdata.TestVectors["encode_krb5_ticket"])
-	if err != nil {
-		t.Fatalf("Test vector read error of %s: %v\n", "encode_krb5_ticket", err)
-	}
-	err = tkt.Unmarshal(b)
+func TestMechToken_Unmarshal(t *testing.T) {
+	b, err := hex.DecodeString(MechToken_Hex)
 	if err != nil {
-		t.Fatalf("Unmarshal error of %s: %v\n", "encode_krb5_ticket", err)
+		t.Fatalf("Error decoding MechToken hex: %v", err)
 	}
-	var a types.Authenticator
-	//t.Logf("Starting unmarshal tests of %s", v)
-	b, err = hex.DecodeString(testdata.TestVectors["encode_krb5_authenticator"])
+	var mt MechToken
+	err = mt.Unmarshal(b)
 	if err != nil {
-		t.Fatalf("Test vector read error of %s: %v\n", "encode_krb5_authenticator", err)
+		t.Fatalf("Error unmarshalling MechToken: %v", err)
 	}
-	err = a.Unmarshal(b)
+	assert.Equal(t, MechTypeOID_Krb5, mt.OID, "MechToken OID not as expected.")
+	assert.Equal(t, []byte{1, 0}, mt.TokID, "TokID not as expected")
+	assert.Equal(t, msgtype.KRB_AP_REQ, mt.APReq.MsgType, "MechToken AP_REQ does not have the right message type.")
+	assert.Equal(t, 0, mt.KRBError.ErrorCode, "KRBError in MechToken does not indicate no error.")
+	assert.Equal(t, 18, mt.APReq.Authenticator.EType, "Authenticator within AP_REQ does not have the etype expected.")
+}
+
+func TestMechToken_newAuthenticatorChksum(t *testing.T) {
+	b, err := hex.DecodeString(Auth_Chksum)
 	if err != nil {
-		t.Fatalf("Unmarshal error of %s: %v\n", "encode_krb5_authenticator", err)
+		t.Fatalf("Error decoding MechToken hex: %v", err)
 	}
-	var k types.EncryptionKey
-	b, err = hex.DecodeString(testdata.TestVectors["encode_krb5_keyblock"])
+	cb := newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG})
+	assert.Equal(t, b, cb, "SPNEGO Authenticator checksum not as expected")
+}
+
+func TestMechToken_newAuthenticator(t *testing.T) {
+	creds := credentials.NewCredentials("hftsai", testdata.TEST_REALM)
+	creds.CName.NameString = testdata.TEST_PRINCIPALNAME_NAMESTRING
+	etypeId := 18
+	a := newAuthenticator(creds, etypeId)
+	assert.Equal(t, 32771, a.Cksum.CksumType, "Checksum type in authenticator for SPNEGO mechtoken not as expected.")
+	assert.Equal(t, 18, a.SubKey.KeyType, "Subkey not of the expected type.")
+	assert.Equal(t, 32, len(a.SubKey.KeyValue), "Subkey value not of the right length")
+	// Test the subkey is initialised to random non-zero values. Not a perfect test but better than nothing.
+	assert.Condition(t, assert.Comparison(func() bool {
+		return a.SubKey.KeyValue[0] != 0 && a.SubKey.KeyValue[1] != 0 && a.SubKey.KeyValue[0] != a.SubKey.KeyValue[1]
+	}))
+	assert.Condition(t, assert.Comparison(func() bool {
+		return a.SeqNumber > 0
+	}), "Sequence number is not greater than zero")
+	assert.Condition(t, assert.Comparison(func() bool {
+		return a.SeqNumber <= math.MaxUint32
+	}))
+}
+
+func TestNewKRB5APREQMechToken(t *testing.T) {
+	creds := credentials.NewCredentials("hftsai", testdata.TEST_REALM)
+	creds.CName.NameString = testdata.TEST_PRINCIPALNAME_NAMESTRING
+
+	var tkt messages.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", "encode_krb5_keyblock", err)
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
 	}
-	err = k.Unmarshal(b)
+	err = tkt.Unmarshal(b)
 	if err != nil {
-		t.Fatalf("Unmarshal error of %s: %v\n", "encode_krb5_keyblock", err)
+		t.Fatalf("Unmarshal error of %s: %v\n", v, err)
 	}
-}
 
-func TestMechToken_Unmarshal(t *testing.T) {
-	b, err := hex.DecodeString(MechToken_Hex)
-	if err != nil {
-		t.Fatalf("Error decoding MechToken hex: %v", err)
+	key := types.EncryptionKey{
+		KeyType:  18,
+		KeyValue: make([]byte, 32),
 	}
+
+	mb, err := NewKRB5APREQMechToken(creds, tkt, key)
 	var mt MechToken
-	err = mt.Unmarshal(b)
+	err = mt.Unmarshal(mb)
 	if err != nil {
 		t.Fatalf("Error unmarshalling MechToken: %v", err)
 	}
+	assert.Equal(t, MechTypeOID_Krb5, mt.OID, "MechToken OID not as expected.")
+	assert.Equal(t, []byte{1, 0}, mt.TokID, "TokID not as expected")
+	assert.Equal(t, msgtype.KRB_AP_REQ, mt.APReq.MsgType, "MechToken AP_REQ does not have the right message type.")
+	assert.Equal(t, 0, mt.KRBError.ErrorCode, "KRBError in MechToken does not indicate no error.")
+	assert.Equal(t, testdata.TEST_REALM, mt.APReq.Ticket.Realm, "Realm in ticket within the AP_REQ of the MechToken not as expected.")
+	assert.Equal(t, testdata.TEST_PRINCIPALNAME_NAMESTRING, mt.APReq.Ticket.SName.NameString, "SName in ticket within the AP_REQ of the MechToken not as expected.")
+	assert.Equal(t, 18, mt.APReq.Authenticator.EType, "Authenticator within AP_REQ does not have the etype expected.")
 }