Jonathan Turner 9 лет назад
Родитель
Сommit
f7465a49d8
7 измененных файлов с 233 добавлено и 261 удалено
  1. 45 14
      client/ASExchange.go
  2. 13 27
      client/client.go
  3. 5 6
      client/network.go
  4. 40 0
      credentials/credentials.go
  5. 32 7
      debug.go
  6. 98 18
      messages/KDCRep.go
  7. 0 189
      types/dictionary.go

+ 45 - 14
client/ASExchange.go

@@ -1,17 +1,22 @@
 package client
 
 import (
-	"github.com/jcmturner/gokrb5/messages"
-	"fmt"
 	"errors"
+	"fmt"
+	"github.com/jcmturner/gokrb5/crypto"
 	"github.com/jcmturner/gokrb5/iana/errorcode"
+	"github.com/jcmturner/gokrb5/iana/patype"
+	"github.com/jcmturner/gokrb5/messages"
+	"github.com/jcmturner/gokrb5/types"
+	"os"
+	"sort"
 )
 
 func (cl *Client) ASExchange() error {
 	if !cl.IsConfigured() {
 		return errors.New("Client is not configured correctly.")
 	}
-	a := messages.NewASReq(cl.Config, cl.Username)
+	a := messages.NewASReq(cl.Config, cl.Credentials.Username)
 	b, err := a.Marshal()
 	if err != nil {
 		return fmt.Errorf("Error marshalling AS_REQ: %v", err)
@@ -30,20 +35,46 @@ func (cl *Client) ASExchange() error {
 			return fmt.Errorf("Could not unmarshal data returned from KDC: %v", err)
 		}
 		if krberr.ErrorCode == errorcode.KDC_ERR_PREAUTH_REQUIRED {
-			//TODO put PA TIMESTAMP here
+			paTSb, err := types.GetPAEncTSEncAsnMarshalled()
+			if err != nil {
+				return fmt.Errorf("Error creating PAEncTSEnc for Pre-Authentication: %v", err)
+			}
+			sort.Sort(sort.Reverse(sort.IntSlice(cl.Config.LibDefaults.Default_tkt_enctype_ids)))
+			etype, err := crypto.GetEtype(cl.Config.LibDefaults.Default_tkt_enctype_ids[0])
+			if err != nil {
+				return fmt.Errorf("Error creating etype: %v", err)
+			}
+			paEncTS, err := crypto.GetEncryptedData(paTSb, etype, cl.Config.LibDefaults.Default_realm, cl.Credentials.Username, cl.Credentials.Keytab, 1)
+			if err != nil {
+				return fmt.Errorf("Error encrypting pre-authentication timestamp: %v", err)
+			}
+			pa := types.PAData{
+				PADataType:  patype.PA_ENC_TIMESTAMP,
+				PADataValue: paEncTS,
+			}
+			a.PAData = append(a.PAData, pa)
+			b, err := a.Marshal()
+			if err != nil {
+				return fmt.Errorf("Error marshalling AS_REQ: %v", err)
+			}
+			rb, err := cl.SendToKDC(b)
+			if err != nil {
+				return fmt.Errorf("Error sending AS_REQ to KDC: %v", err)
+			}
+			err = ar.Unmarshal(rb)
+			if err != nil {
+				return fmt.Errorf("Could not unmarshal data returned from KDC: %v", err)
+			}
 		}
 		return krberr
 	}
-	if len(cl.Keytab.Entries) > 1 {
-		err = ar.DecryptEncPartWithKeytab(cl.Keytab)
-		if err != nil {
-			return fmt.Errorf("Error decrypting AS_REP encPart with keytab: %v", err)
-		}
-	} else {
-		err = ar.DecryptEncPartWithPassword(cl.Password)
-		if err != nil {
-			return fmt.Errorf("Error decrypting AS_REP encPart with password: %v", err)
-		}
+	err = ar.DecryptEncPart(cl.Credentials)
+	if err != nil {
+		return fmt.Errorf("Error decrypting EncPart of AS_REP: %v", err)
+	}
+	if ok, err := ar.IsValid(cl.Config, a); !ok {
+		return fmt.Errorf("AS_REQ is not valid: %v", err)
 	}
+	fmt.Fprintf(os.Stderr, "AS_REP: %+v\n", ar)
 	return nil
 }

+ 13 - 27
client/client.go

@@ -1,43 +1,32 @@
 package client
 
 import (
-	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/credentials"
+	"github.com/jcmturner/gokrb5/keytab"
 )
+
 type Client struct {
-	Username string
-	Password string
-	Keytab   keytab.Keytab
-	Config   *config.Config
+	Credentials *credentials.Credentials
+	Config      *config.Config
 }
 
 func NewClientWithPassword(username, password string) Client {
+	creds := credentials.NewCredentials(username)
 	return Client{
-		Username: username,
-		Password: password,
-		Keytab: keytab.NewKeytab(),
-		Config: config.NewConfig(),
+		Credentials: creds.WithPassword(password),
+		Config:      config.NewConfig(),
 	}
 }
 
 func NewClientWithKeytab(username string, kt keytab.Keytab) Client {
+	creds := credentials.NewCredentials(username)
 	return Client{
-		Username: username,
-		Keytab:   kt,
-		Config: config.NewConfig(),
+		Credentials: creds.WithKeytab(kt),
+		Config:      config.NewConfig(),
 	}
 }
 
-func (cl *Client) WithPassword(p string) *Client {
-	cl.Password = p
-	return cl
-}
-
-func (cl *Client) WithKeytab(kt keytab.Keytab) *Client {
-	cl.Keytab = kt
-	return cl
-}
-
 func (cl *Client) WithConfig(cfg *config.Config) *Client {
 	cl.Config = cfg
 	return cl
@@ -53,10 +42,10 @@ func (cl *Client) LoadConfig(cfgPath string) (*Client, error) {
 }
 
 func (cl *Client) IsConfigured() bool {
-	if cl.Password == "" && len(cl.Keytab.Entries) < 1 {
+	if !cl.Credentials.HasPassword() && !cl.Credentials.HasKeytab() {
 		return false
 	}
-	if cl.Username == "" {
+	if cl.Credentials.Username == "" {
 		return false
 	}
 	if cl.Config.LibDefaults.Default_realm == "" {
@@ -73,6 +62,3 @@ func (cl *Client) IsConfigured() bool {
 	}
 	return false
 }
-
-
-

+ 5 - 6
client/network.go

@@ -1,11 +1,11 @@
 package client
 
 import (
-	"net"
-	"fmt"
-	"time"
 	"bytes"
+	"fmt"
 	"math/rand"
+	"net"
+	"time"
 )
 
 func (cl *Client) SendToKDC(b []byte) ([]byte, error) {
@@ -78,7 +78,7 @@ func sendUDP(kdc string, b []byte) ([]byte, error) {
 		return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
 	}
 	defer conn.Close()
-	conn.SetDeadline(time.Now().Add(time.Duration(5) * time.Second))
+	conn.SetDeadline(time.Now().Add(time.Duration(5 * time.Second)))
 	_, err = conn.Write(b)
 	if err != nil {
 		return r, fmt.Errorf("Error sending to KDC: %v", err)
@@ -103,7 +103,7 @@ func sendTCP(kdc string, b []byte) ([]byte, error) {
 		return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
 	}
 	defer conn.Close()
-	conn.SetDeadline(time.Now().Add(time.Duration(5) * time.Second))
+	conn.SetDeadline(time.Now().Add(time.Duration(5 * time.Second)))
 	_, err = conn.Write(b)
 	if err != nil {
 		return r, fmt.Errorf("Error sending to KDC: %v", err)
@@ -116,4 +116,3 @@ func sendTCP(kdc string, b []byte) ([]byte, error) {
 	}
 	return r, nil
 }
-

+ 40 - 0
credentials/credentials.go

@@ -0,0 +1,40 @@
+package credentials
+
+import "github.com/jcmturner/gokrb5/keytab"
+
+type Credentials struct {
+	Username string
+	Keytab   keytab.Keytab
+	Password string
+}
+
+func NewCredentials(username string) Credentials {
+	return Credentials{
+		Username: username,
+		Keytab:   keytab.NewKeytab(),
+	}
+}
+
+func (c *Credentials) WithKeytab(kt keytab.Keytab) *Credentials {
+	c.Keytab = kt
+	return c
+}
+
+func (c *Credentials) WithPassword(password string) *Credentials {
+	c.Password = password
+	return c
+}
+
+func (c *Credentials) HasKeytab() bool {
+	if len(c.Keytab.Entries) > 0 {
+		return true
+	}
+	return false
+}
+
+func (c *Credentials) HasPassword() bool {
+	if c.Password != "" {
+		return true
+	}
+	return false
+}

+ 32 - 7
debug.go

@@ -6,12 +6,14 @@ import (
 	"github.com/jcmturner/asn1"
 	"github.com/jcmturner/gokrb5/client"
 	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/credentials"
 	"github.com/jcmturner/gokrb5/crypto"
 	"github.com/jcmturner/gokrb5/iana/keyusage"
 	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/messages"
 	"github.com/jcmturner/gokrb5/types"
 	"os"
+	"time"
 )
 
 const ktab = "05020000003b0001000b544553542e474f4b524235000974657374757365723100000001589b9b2b0100110010698c4df8e9f60e7eea5a21bf4526ad25000000010000004b0001000b544553542e474f4b524235000974657374757365723100000001589b9b2b0100120020bbdc430aab7e2d4622a0b6951481453b0962e9db8e2f168942ad175cda6d9de900000001"
@@ -33,13 +35,12 @@ const krb5conf = `[libdefaults]
 [domain_realm]
  .test.gokrb5 = TEST.GOKRB5
  test.gokrb5 = TEST.GOKRB5`
-const noparep="6b8202bc308202b8a003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020100a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a2820106048201021ced05c1ad2bfcd32c14306cd0c2ed3499e0dbdff120f64151b0fc8fe15a5f4dcc185cd14a9d67570dc4a0410d1384172860e844cabfe8cc3172ac0f1c32e7290ca28fe3499a9ac144a1c8918424165a932711e3fccefb3fff4f599d753edc21c2ec005df65da2e66bac24dca69041af231cbaaf6e18c6799731e1bda62a2a774c4adebbb81b1cf87956418b9944a711e3910c26e5e8e60e069eea8c3ed7769c231614a9ca36fb8407b81b5e67c262795fff243869b44358b36510c4e3f46d281d45306fc01eb0975d01e02be17078450085d08007e0f231ee6264896b05a57d0fd5dd167a725de99891c23f05ad9ce891f714e0cdc73d8a1db441195d95e3bbb259a681f63081f3a003020112a281eb0481e8cdc7aeaa51ae78e2adabd140f0c28a21ca527dc6960cbad675564dcd54954ff4bfd96cb95ef7714f21d0c0d5c94f0f0970574488fdd8d519563e0d775607b084170c4959205c4dbc4f16fa0d4099546de7239d64194c92de073a53e2af868e823262926ffc01e488a306fe84e59ad375fea8debf2b864789d275412947508592bd5adac0d2ddf31f7d56be6bd1cf722a3bdae04d7514e8cd9c4460890afb901c75dd6659cced7e84a82446e8779ce5b7e740c61c149982936d37667191b4d0c28daafc66ddb4c71772800217bf1281109da55bda95f32eea02a06d00a87f91e2bdbfbb7906d5a143"
-const pa149rep= "6b8202f3308202efa003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010237e486e32cd18ab1ac9f8d42e93f8babd7b3497084cc5599f18ec61961c6d5242d350354d99d67a7604c451116188d16cb719e84377212eac2743440e8c504ef69c755e489cc6b65f935dd032bfc076f9b2c56d816197845b8fe857d738bc59712787631a50e86833d1b0e4732c8712c856417a6a257758e7d01d3182adb3233f0dde65d228c240ed26aa1af69f8d765dc0bc69096fdb037a75af220fea176839528d44b70f7dabfaa2ea506de1296f847176a60c501fd8cef8e0a51399bb6d5f753962d96292e93ffe344c6630db912931d46d88c0279f00719e22d0efcfd4ee33a702d0b660c1f13970a9beec12c0c8af3dda68bd81ac1fe3f126d2a24ebb445c5a682012c30820128a003020112a282011f0482011bb149cc16018072c4c18788d95a33aba540e52c11b54a93e67e788d05de75d8f3d4aa1afafbbfa6fde3eb40e5aa1890644cea2607efd5213a3fd00345b02eeb9ae1b589f36c74c689cd4ec1239dfe61e42ba6afa33f6240e3cfab291e4abb465d273302dbf7dbd148a299a9369044dd03377c1687e7dd36aa66501284a4ca50c0a7b08f4f87aecfa23b0dd0b11490e3ad330906dab715de81fc52f120d09c39990b8b5330d4601cc396b2ed258834329c4cc02c563a12de3ef9bf11e946258bc2ab5257f4caa4d443a7daf0fc25f6f531c2fcba88af8ca55c85300997cd05abbea52811fe2d038ba8f62fc8e3bc71ce04362d356ea2e1df8ac55c784c53cfb07817d48e39fe99fc8788040d98209c79dcf044d97e80de9f47824646"
-
+const noparep = "6b8202bc308202b8a003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020100a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a2820106048201021ced05c1ad2bfcd32c14306cd0c2ed3499e0dbdff120f64151b0fc8fe15a5f4dcc185cd14a9d67570dc4a0410d1384172860e844cabfe8cc3172ac0f1c32e7290ca28fe3499a9ac144a1c8918424165a932711e3fccefb3fff4f599d753edc21c2ec005df65da2e66bac24dca69041af231cbaaf6e18c6799731e1bda62a2a774c4adebbb81b1cf87956418b9944a711e3910c26e5e8e60e069eea8c3ed7769c231614a9ca36fb8407b81b5e67c262795fff243869b44358b36510c4e3f46d281d45306fc01eb0975d01e02be17078450085d08007e0f231ee6264896b05a57d0fd5dd167a725de99891c23f05ad9ce891f714e0cdc73d8a1db441195d95e3bbb259a681f63081f3a003020112a281eb0481e8cdc7aeaa51ae78e2adabd140f0c28a21ca527dc6960cbad675564dcd54954ff4bfd96cb95ef7714f21d0c0d5c94f0f0970574488fdd8d519563e0d775607b084170c4959205c4dbc4f16fa0d4099546de7239d64194c92de073a53e2af868e823262926ffc01e488a306fe84e59ad375fea8debf2b864789d275412947508592bd5adac0d2ddf31f7d56be6bd1cf722a3bdae04d7514e8cd9c4460890afb901c75dd6659cced7e84a82446e8779ce5b7e740c61c149982936d37667191b4d0c28daafc66ddb4c71772800217bf1281109da55bda95f32eea02a06d00a87f91e2bdbfbb7906d5a143"
+const pa149rep = "6b8202f3308202efa003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010237e486e32cd18ab1ac9f8d42e93f8babd7b3497084cc5599f18ec61961c6d5242d350354d99d67a7604c451116188d16cb719e84377212eac2743440e8c504ef69c755e489cc6b65f935dd032bfc076f9b2c56d816197845b8fe857d738bc59712787631a50e86833d1b0e4732c8712c856417a6a257758e7d01d3182adb3233f0dde65d228c240ed26aa1af69f8d765dc0bc69096fdb037a75af220fea176839528d44b70f7dabfaa2ea506de1296f847176a60c501fd8cef8e0a51399bb6d5f753962d96292e93ffe344c6630db912931d46d88c0279f00719e22d0efcfd4ee33a702d0b660c1f13970a9beec12c0c8af3dda68bd81ac1fe3f126d2a24ebb445c5a682012c30820128a003020112a282011f0482011bb149cc16018072c4c18788d95a33aba540e52c11b54a93e67e788d05de75d8f3d4aa1afafbbfa6fde3eb40e5aa1890644cea2607efd5213a3fd00345b02eeb9ae1b589f36c74c689cd4ec1239dfe61e42ba6afa33f6240e3cfab291e4abb465d273302dbf7dbd148a299a9369044dd03377c1687e7dd36aa66501284a4ca50c0a7b08f4f87aecfa23b0dd0b11490e3ad330906dab715de81fc52f120d09c39990b8b5330d4601cc396b2ed258834329c4cc02c563a12de3ef9bf11e946258bc2ab5257f4caa4d443a7daf0fc25f6f531c2fcba88af8ca55c85300997cd05abbea52811fe2d038ba8f62fc8e3bc71ce04362d356ea2e1df8ac55c784c53cfb07817d48e39fe99fc8788040d98209c79dcf044d97e80de9f47824646"
 
 func main() {
 
-NoPA()
+	AS()
 }
 
 func NoPA() {
@@ -52,7 +53,9 @@ func NoPA() {
 		fmt.Fprintf(os.Stderr, "Unmarshal err: %v\n", err)
 	}
 	//err = ar.DecryptEncPartWithKeytab(kt)
-	err = ar.DecryptEncPartWithPassword("passwordvalue")
+	cred := credentials.NewCredentials("testuser1")
+	cred.WithPassword("passwordvalue")
+	err = ar.DecryptEncPart(cred.WithPassword("passwordvalue"))
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "\nDecrypt err: %v\n%+v\n", err, ar)
 	} else {
@@ -60,7 +63,7 @@ func NoPA() {
 	}
 }
 
-func Fast (){
+func Fast() {
 	c, err := config.NewConfigFromString(krb5conf)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "Error creating config: %v", err)
@@ -84,7 +87,9 @@ func Fast (){
 	}
 	var ar messages.ASRep
 	ar.Unmarshal(rb)
-	err = ar.DecryptEncPartWithKeytab(kt)
+	cred := credentials.NewCredentials("testuser1")
+	cred.WithPassword("passwordvalue")
+	err = ar.DecryptEncPart(cred.WithKeytab(kt))
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "\nDecrypt err: %v\n", err)
 	} else {
@@ -104,3 +109,23 @@ func Fast (){
 		}
 	}
 }
+
+func AS() {
+	kb, _ := hex.DecodeString(ktab)
+	kt, err := keytab.Parse(kb)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "KT load err: %v\n\n", err)
+	}
+	cl := client.NewClientWithKeytab("testuser1", kt)
+	c, err := config.NewConfigFromString(krb5conf)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error creating config: %v", err)
+	}
+	cl.WithConfig(c)
+	fmt.Fprintf(os.Stderr, "Start: %v\n", time.Now())
+	err = cl.ASExchange()
+	fmt.Fprintf(os.Stderr, "End  : %v\n", time.Now())
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "ERROR: %v", err)
+	}
+}

+ 98 - 18
messages/KDCRep.go

@@ -7,12 +7,15 @@ import (
 	"errors"
 	"fmt"
 	"github.com/jcmturner/asn1"
+	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/credentials"
 	"github.com/jcmturner/gokrb5/crypto"
 	"github.com/jcmturner/gokrb5/iana/asnAppTag"
 	"github.com/jcmturner/gokrb5/iana/keyusage"
 	"github.com/jcmturner/gokrb5/iana/msgtype"
 	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/types"
+	"sort"
 	"time"
 )
 
@@ -125,8 +128,66 @@ func (e *EncKDCRepPart) Unmarshal(b []byte) error {
 	return err
 }
 
-func (k *ASRep) DecryptEncPartWithPassword(passwd string) error {
-	key, etype, err := crypto.GetKeyFromPassword(passwd, k.CName, k.CRealm, k.EncPart.EType, k.PAData)
+//func (k *ASRep) DecryptEncPartWithPassword(passwd string) error {
+//	key, etype, err := crypto.GetKeyFromPassword(passwd, k.CName, k.CRealm, k.EncPart.EType, k.PAData)
+//	b, err := crypto.DecryptEncPart(key, k.EncPart, etype, keyusage.AS_REP_ENCPART)
+//	if err != nil {
+//		return fmt.Errorf("Error decrypting KDC_REP EncPart: %v", err)
+//	}
+//	var denc EncKDCRepPart
+//	err = denc.Unmarshal(b)
+//	if err != nil {
+//		return fmt.Errorf("Error unmarshalling encrypted part: %v", err)
+//	}
+//	k.DecryptedEncPart = denc
+//	return nil
+//}
+//
+//func (k *ASRep) DecryptEncPartWithKeytab(kt keytab.Keytab) error {
+//	etype, err := crypto.GetEtype(k.EncPart.EType)
+//	if err != nil {
+//		return fmt.Errorf("Error getting encryption type: %v", err)
+//	}
+//	key, err := kt.GetKey(k.CName.NameString[0], k.CRealm, k.EncPart.KVNO, k.EncPart.EType)
+//	if err != nil {
+//		return fmt.Errorf("Could not get key from keytab: %v", err)
+//	}
+//	b, err := crypto.DecryptEncPart(key, k.EncPart, etype, keyusage.AS_REP_ENCPART)
+//	if err != nil {
+//		return fmt.Errorf("Error decrypting KDC_REP EncPart: %v", err)
+//	}
+//	var denc EncKDCRepPart
+//	err = denc.Unmarshal(b)
+//	if err != nil {
+//		return fmt.Errorf("Error unmarshalling encrypted part: %v", err)
+//	}
+//	k.DecryptedEncPart = denc
+//	return nil
+//}
+
+func (k *ASRep) DecryptEncPart(c *credentials.Credentials) error {
+	var etype crypto.EType
+	var key []byte
+	var err error
+	if c.HasKeytab() {
+		etype, err = crypto.GetEtype(k.EncPart.EType)
+		if err != nil {
+			return fmt.Errorf("Error getting encryption type: %v", err)
+		}
+		key, err = c.Keytab.GetKey(k.CName.NameString[0], k.CRealm, k.EncPart.KVNO, k.EncPart.EType)
+		if err != nil {
+			return fmt.Errorf("Could not get key from keytab: %v", err)
+		}
+	}
+	if c.HasPassword() {
+		key, etype, err = crypto.GetKeyFromPassword(c.Password, k.CName, k.CRealm, k.EncPart.EType, k.PAData)
+		if err != nil {
+			return fmt.Errorf("Could not derive key from password: %v", err)
+		}
+	}
+	if !c.HasKeytab() && !c.HasPassword() {
+		return errors.New("No secret available in credentials to preform decryption")
+	}
 	b, err := crypto.DecryptEncPart(key, k.EncPart, etype, keyusage.AS_REP_ENCPART)
 	if err != nil {
 		return fmt.Errorf("Error decrypting KDC_REP EncPart: %v", err)
@@ -140,26 +201,45 @@ func (k *ASRep) DecryptEncPartWithPassword(passwd string) error {
 	return nil
 }
 
-func (k *ASRep) DecryptEncPartWithKeytab(kt keytab.Keytab) error {
-	etype, err := crypto.GetEtype(k.EncPart.EType)
-	if err != nil {
-		return fmt.Errorf("Error getting encryption type: %v", err)
+func (k *ASRep) IsValid(cfg *config.Config, asReq ASReq) (bool, error) {
+	//Ref RFC 4120 Section 3.1.5
+	//TODO change the following to a contains check or slice compare
+	if k.CName.NameType != asReq.ReqBody.CName.NameType {
+		return false, fmt.Errorf("CName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.CName, k.CName)
 	}
-	key, err := kt.GetKey(k.CName.NameString[0], k.CRealm, k.EncPart.KVNO, k.EncPart.EType)
-	if err != nil {
-		return fmt.Errorf("Could not get key from keytab: %v", err)
+	sort.Strings(k.CName.NameString)
+	sort.Strings(asReq.ReqBody.CName.NameString)
+	for i := range k.CName.NameString {
+		if k.CName.NameString[i] != asReq.ReqBody.CName.NameString[i] {
+			return false, fmt.Errorf("CName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.CName, k.CName)
+		}
 	}
-	b, err := crypto.DecryptEncPart(key, k.EncPart, etype, keyusage.AS_REP_ENCPART)
-	if err != nil {
-		return fmt.Errorf("Error decrypting KDC_REP EncPart: %v", err)
+	if k.CRealm != asReq.ReqBody.Realm {
+		return false, fmt.Errorf("CRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.CRealm)
 	}
-	var denc EncKDCRepPart
-	err = denc.Unmarshal(b)
-	if err != nil {
-		return fmt.Errorf("Error unmarshalling encrypted part: %v", err)
+	if k.DecryptedEncPart.Nonce != asReq.ReqBody.Nonce {
+		return false, errors.New("Possible replay attack, nonce in response does not match that in request")
 	}
-	k.DecryptedEncPart = denc
-	return nil
+	if k.DecryptedEncPart.SName.NameType != asReq.ReqBody.SName.NameType {
+		return false, fmt.Errorf("SName in response does not match what was requested. Requested: %v; Reply: %v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
+	}
+	sort.Strings(k.DecryptedEncPart.SName.NameString)
+	sort.Strings(asReq.ReqBody.SName.NameString)
+	for i := range k.CName.NameString {
+		if k.DecryptedEncPart.SName.NameString[i] != asReq.ReqBody.SName.NameString[i] {
+			return false, fmt.Errorf("SName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
+		}
+	}
+	if k.DecryptedEncPart.SRealm != asReq.ReqBody.Realm {
+		return false, fmt.Errorf("SRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.DecryptedEncPart.SRealm)
+	}
+	if len(asReq.ReqBody.Addresses) > 0 {
+		//TODO compare if address list is the same
+	}
+	if time.Since(k.DecryptedEncPart.AuthTime) > cfg.LibDefaults.Clockskew || time.Until(k.DecryptedEncPart.AuthTime) > cfg.LibDefaults.Clockskew {
+		return false, fmt.Errorf("Clock skew with KDC too large. Greater than %d seconds", cfg.LibDefaults.Clockskew.Seconds())
+	}
+	return true, nil
 }
 
 func (k *TGSRep) DecryptEncPart(kt keytab.Keytab) error {

+ 0 - 189
types/dictionary.go

@@ -1,189 +0,0 @@
-package types
-
-var KrbDictionary1 = struct {
-	MsgTypesByID      map[int]string
-	MsgTypesByName    map[string]int
-	NameTypesByID     map[int]string
-	ErrorCodesByID    map[int]string
-	ADTypesByID       map[int]string
-	PADataTypesByID   map[int]string
-	PADataTypesByName map[string]int
-	ETypesByID        map[int]string
-	ETypesByName      map[string]int
-}{
-	MsgTypesByID: map[int]string{
-		10: "KRB_AS_REQ",
-		11: "KRB_AS_REP",
-		12: "KRB_TGS_REQ",
-		13: "KRB_TGS_REP",
-		14: "KRB_AP_REQ",
-		15: "KRB_AP_REP",
-		16: "KRB_RESERVED16",
-		17: "KRB_RESERVED17",
-		20: "KRB_SAFE",
-		21: "KRB_PRIV",
-		22: "KRB_CRED",
-		30: "KRB_ERROR",
-	},
-	MsgTypesByName: map[string]int{
-		"KRB_AS_REQ":     10,
-		"KRB_AS_REP":     11,
-		"KRB_TGS_REQ":    12,
-		"KRB_TGS_REP":    13,
-		"KRB_AP_REQ":     14,
-		"KRB_AP_REP":     15,
-		"KRB_RESERVED16": 16,
-		"KRB_RESERVED17": 17,
-		"KRB_SAFE":       20,
-		"KRB_PRIV":       21,
-		"KRB_CRED":       22,
-		"KRB_ERROR":      30,
-	},
-	NameTypesByID: map[int]string{
-		0:  "KRB_NT_UNKNOWN",
-		1:  "KRB_NT_PRINCIPAL",
-		2:  "KRB_NT_SRV_INST",
-		3:  "KRB_NT_SRV_HST",
-		4:  "KRB_NT_SRV_XHST",
-		5:  "KRB_NT_UID",
-		6:  "KRB_NT_X500_PRINCIPAL",
-		7:  "KRB_NT_SMTP_NAME",
-		10: "KRB_NT_ENTERPRISE",
-	},
-	ErrorCodesByID: map[int]string{
-		0:  "KDC_ERR_NONE",
-		1:  "KDC_ERR_NAME_EXP",
-		2:  "KDC_ERR_SERVICE_EXP",
-		3:  "KDC_ERR_BAD_PVNO",
-		4:  "KDC_ERR_C_OLD_MAST_KVNO",
-		5:  "KDC_ERR_S_OLD_MAST_KVNO",
-		6:  "KDC_ERR_C_PRINCIPAL_UNKNOWN",
-		7:  "KDC_ERR_S_PRINCIPAL_UNKNOWN",
-		8:  "KDC_ERR_PRINCIPAL_NOT_UNIQUE",
-		9:  "KDC_ERR_NULL_KEY",
-		10: "KDC_ERR_CANNOT_POSTDATE",
-		11: "KDC_ERR_NEVER_VALID",
-		12: "KDC_ERR_POLICY",
-		13: "KDC_ERR_BADOPTION",
-		14: "KDC_ERR_ETYPE_NOSUPP",
-		15: "KDC_ERR_SUMTYPE_NOSUPP",
-		16: "KDC_ERR_PADATA_TYPE_NOSUPP",
-		17: "KDC_ERR_TRTYPE_NOSUPP",
-		18: "KDC_ERR_CLIENT_REVOKED",
-		19: "KDC_ERR_SERVICE_REVOKED",
-		20: "KDC_ERR_TGT_REVOKED",
-		21: "KDC_ERR_CLIENT_NOTYET",
-		22: "KDC_ERR_SERVICE_NOTYET",
-		23: "KDC_ERR_KEY_EXPIRED",
-		24: "KDC_ERR_PREAUTH_FAILED",
-		25: "KDC_ERR_PREAUTH_REQUIRED",
-		26: "KDC_ERR_SERVER_NOMATCH",
-		27: "KDC_ERR_MUST_USE_USER2USER",
-		28: "KDC_ERR_PATH_NOT_ACCEPTED",
-		29: "KDC_ERR_SVC_UNAVAILABLE",
-		31: "KRB_AP_ERR_BAD_INTEGRITY",
-		32: "KRB_AP_ERR_TKT_EXPIRED",
-		33: "KRB_AP_ERR_TKT_NYV",
-		34: "KRB_AP_ERR_REPEAT",
-		35: "KRB_AP_ERR_NOT_US",
-		36: "KRB_AP_ERR_BADMATCH",
-		37: "KRB_AP_ERR_SKEW",
-		38: "KRB_AP_ERR_BADADDR",
-		39: "KRB_AP_ERR_BADVERSION",
-		40: "KRB_AP_ERR_MSG_TYPE",
-		41: "KRB_AP_ERR_MODIFIED",
-		42: "KRB_AP_ERR_BADORDER",
-		44: "KRB_AP_ERR_BADKEYVER",
-		45: "KRB_AP_ERR_NOKEY",
-		46: "KRB_AP_ERR_MUT_FAIL",
-		47: "KRB_AP_ERR_BADDIRECTION",
-		48: "KRB_AP_ERR_METHOD",
-		49: "KRB_AP_ERR_BADSEQ",
-		50: "KRB_AP_ERR_INAPP_CKSUM",
-		51: "KRB_AP_PATH_NOT_ACCEPTED",
-		52: "KRB_ERR_RESPONSE_TOO_BIG",
-		60: "KRB_ERR_GENERIC",
-		61: "KRB_ERR_FIELD_TOOLONG",
-		62: "KDC_ERROR_CLIENT_NOT_TRUSTED",
-		63: "KDC_ERROR_KDC_NOT_TRUSTED",
-		64: "KDC_ERROR_INVALID_SIG",
-		65: "KDC_ERR_KEY_TOO_WEAK",
-		66: "KDC_ERR_CERTIFICATE_MISMATCH",
-		67: "KRB_AP_ERR_NO_TGT",
-		68: "KDC_ERR_WRONG_REALM",
-		69: "KRB_AP_ERR_USER_TO_USER_REQUIRED",
-		70: "KDC_ERR_CANT_VERIFY_CERTIFICATE",
-		71: "KDC_ERR_INVALID_CERTIFICATE",
-		72: "KDC_ERR_REVOKED_CERTIFICATE",
-		73: "KDC_ERR_REVOCATION_STATUS_UNKNOWN",
-		74: "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE",
-		75: "KDC_ERR_CLIENT_NAME_MISMATCH",
-		76: "KDC_ERR_KDC_NAME_MISMATCH",
-	},
-	ADTypesByID: map[int]string{
-		1: "AD-IF-RELEVANT",
-		4: "AD-KDCIssued",
-		5: "AD-AND-OR",
-		8: "AD-MANDATORY-FOR-KDC",
-	},
-	PADataTypesByID: map[int]string{
-		1:  "pa-tgs-req",
-		2:  "pa-enc-timestamp",
-		3:  "pa-pw-salt",
-		11: "pa-etype-info",
-		19: "pa-etype-info2",
-	},
-	PADataTypesByName: map[string]int{
-		"pa-tgs-req":       1,
-		"pa-enc-timestamp": 2,
-		"pa-pw-salt":       3,
-		"pa-etype-info":    11,
-		"pa-etype-info2":   19,
-	},
-	ETypesByID: map[int]string{
-		1:  "des-cbc-crc",
-		2:  "des-cbc-md4",
-		3:  "des-cbc-md5",
-		4:  "reserved4",
-		5:  "des3-cbc-md5",
-		6:  "reserved6",
-		7:  "des3-cbc-sha1",
-		9:  "dsaWithSHA1-CmsOID",
-		10: "md5WithRSAEncryption-CmsOID",
-		11: "sha1WithRSAEncryption-CmsOID",
-		12: "rc2CBC-EnvOID",
-		13: "rsaEncryption-EnvOID",
-		14: "rsaES-OAEP-ENV-OID",
-		15: "des-ede3-cbc-Env-OID",
-		16: "des3-cbc-sha1-kd",
-		17: "aes128-cts-hmac-sha1-96",
-		18: "aes256-cts-hmac-sha1-96",
-		23: "rc4-hmac",
-		24: "rc4-hmac-exp",
-		65: "subkey-keymaterial",
-	},
-	ETypesByName: map[string]int{
-		"des-cbc-crc":                  1,
-		"des-cbc-md4":                  2,
-		"des-cbc-md5":                  3,
-		"reserved4":                    4,
-		"des3-cbc-md5":                 5,
-		"reserved6":                    6,
-		"des3-cbc-sha1":                7,
-		"dsaWithSHA1-CmsOID":           9,
-		"md5WithRSAEncryption-CmsOID":  10,
-		"sha1WithRSAEncryption-CmsOID": 11,
-		"rc2CBC-EnvOID":                12,
-		"rsaEncryption-EnvOID":         13,
-		"rsaES-OAEP-ENV-OID":           14,
-		"des-ede3-cbc-Env-OID":         15,
-		"des3-cbc-sha1-kd":             16,
-		"aes128-cts-hmac-sha1-96":      17,
-		"aes256-cts-hmac-sha1-96":      18,
-		"rc4-hmac":                     23,
-		"rc4-hmac-exp":                 23,
-		"subkey-keymaterial":           65,
-	},
-}
-
-// TODO I think we should have a map of message type map[int]string or message interface???