Repository: jcmturner/gokrb5
Pull request #173 (2018-07-29 08:49:59)

fixes to PAC decoding


Patch:
diff --git a/messages/Ticket.go b/messages/Ticket.go
index 89faea6..75e7246 100644
--- a/messages/Ticket.go
+++ b/messages/Ticket.go
@@ -216,7 +216,7 @@ func (t *Ticket) DecryptEncPart(keytab keytab.Keytab, ktprinc string) error {
 }
 
 // GetPACType returns a Microsoft PAC that has been extracted from the ticket and processed.
-func (t *Ticket) GetPACType(keytab keytab.Keytab, sa string) (bool, pac.PACType, error) {
+func (t *Ticket) GetPACType(keytab keytab.Keytab, ktprinc string) (bool, pac.PACType, error) {
 	var isPAC bool
 	for _, ad := range t.DecryptedEncPart.AuthorizationData {
 		if ad.ADType == adtype.ADIfRelevant {
@@ -233,8 +233,8 @@ func (t *Ticket) GetPACType(keytab keytab.Keytab, sa string) (bool, pac.PACType,
 					return isPAC, p, fmt.Errorf("error unmarshaling PAC: %v", err)
 				}
 				var upn []string
-				if sa != "" {
-					upn = strings.Split(sa, "/")
+				if ktprinc != "" {
+					upn = strings.Split(ktprinc, "/")
 				} else {
 					upn = t.SName.NameString
 				}
diff --git a/mstypes/claims.go b/mstypes/claims.go
new file mode 100644
index 0000000..54f5cc7
--- /dev/null
+++ b/mstypes/claims.go
@@ -0,0 +1,312 @@
+package mstypes
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+
+	"gopkg.in/jcmturner/rpc.v0/ndr"
+)
+
+// Compression format assigned numbers.
+const (
+	CompressionFormatNone       uint16 = 0
+	CompressionFormatLZNT1      uint16 = 2
+	CompressionFormatXPress     uint16 = 3
+	CompressionFormatXPressHuff uint16 = 4
+)
+
+// ClaimsSourceType
+const ClaimsSourceTypeAD uint16 = 1
+
+// Claim Type assigned numbers
+const (
+	ClaimTypeIDInt64    uint16 = 1
+	ClaimTypeIDUInt64   uint16 = 2
+	ClaimTypeIDString   uint16 = 3
+	ClaimsTypeIDBoolean uint16 = 6
+)
+
+// ClaimsBlob implements https://msdn.microsoft.com/en-us/library/hh554119.aspx
+type ClaimsBlob struct {
+	Size        uint32
+	EncodedBlob []byte
+}
+
+// ReadClaimsBlob reads a ClaimsBlob from the byte slice.
+func ReadClaimsBlob(b *[]byte, p *int, e *binary.ByteOrder) (c ClaimsBlob) {
+	c.Size = ndr.ReadUint32(b, p, e)
+	c.EncodedBlob = ndr.ReadBytes(b, p, int(c.Size), e)
+	return
+}
+
+// ClaimsSetMetadata implements https://msdn.microsoft.com/en-us/library/hh554073.aspx
+type ClaimsSetMetadata struct {
+	claimsSetSize             uint32
+	ClaimsSet                 ClaimsSet
+	CompressionFormat         uint16 // Enum see constants for options
+	uncompressedClaimsSetSize uint32
+	ReservedType              uint16
+	reservedFieldSize         uint32
+	ReservedField             []byte
+}
+
+// ClaimSet implements https://msdn.microsoft.com/en-us/library/hh554122.aspx
+type ClaimsSet struct {
+	ClaimsArrayCount  uint32
+	ClaimsArrays      []ClaimsArray
+	ReservedType      uint16
+	reservedFieldSize uint32
+	ReservedField     []byte
+}
+
+// ClaimsArray implements https://msdn.microsoft.com/en-us/library/hh536458.aspx
+type ClaimsArray struct {
+	ClaimsSourceType uint16
+	ClaimsCount      uint32
+	ClaimsEntries    []ClaimEntry
+}
+
+// ClaimEntry implements https://msdn.microsoft.com/en-us/library/hh536374.aspx
+type ClaimEntry struct {
+	ID         string //utf16string
+	Type       uint16 // enums are 16 bit https://msdn.microsoft.com/en-us/library/windows/desktop/aa366818(v=vs.85).aspx
+	TypeInt64  ClaimTypeInt64
+	TypeUInt64 ClaimTypeUInt64
+	TypeString ClaimTypeString
+	TypeBool   ClaimTypeBoolean
+}
+
+// ClaimTypeInt64 is a claim of type int64
+type ClaimTypeInt64 struct {
+	ValueCount uint32
+	Value      []int64
+}
+
+// ClaimTypeUInt64 is a claim of type uint64
+type ClaimTypeUInt64 struct {
+	ValueCount uint32
+	Value      []uint64
+}
+
+// ClaimTypeString is a claim of type string
+type ClaimTypeString struct {
+	ValueCount uint32
+	Value      []string
+}
+
+// ClaimTypeBoolean is a claim of type bool
+type ClaimTypeBoolean struct {
+	ValueCount uint32
+	Value      []bool
+}
+
+// ReadClaimsSetMetadata reads a ClaimsSetMetadata from the bytes slice.
+func ReadClaimsSetMetadata(b *[]byte, p *int, e *binary.ByteOrder) (c ClaimsSetMetadata, err error) {
+	c.claimsSetSize = ndr.ReadUint32(b, p, e)
+	*p += 4 //Move over pointer to ClaimSet array
+	c.CompressionFormat = ndr.ReadUint16(b, p, e)
+	// TODO Currently compression is not supported so if it is compressed we just have to return.
+	if c.CompressionFormat != CompressionFormatNone {
+		*p = len(*b)
+		return
+	}
+	c.uncompressedClaimsSetSize = ndr.ReadUint32(b, p, e)
+	c.ReservedType = ndr.ReadUint16(b, p, e)
+	c.reservedFieldSize = ndr.ReadUint32(b, p, e)
+	*p += 4 //Move over pointer to ReservedField array
+	var ah ndr.ConformantArrayHeader
+	if c.claimsSetSize > 0 {
+		// ClaimsSet is a conformant array https://msdn.microsoft.com/en-us/library/windows/desktop/aa373603(v=vs.85).aspx
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(b, p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(c.claimsSetSize) {
+			err = errors.New("error with size of CLAIMS_SET array")
+			return
+		}
+		csb := ndr.ReadBytes(b, p, int(c.claimsSetSize), e)
+		//TODO put decompression here
+		c.ClaimsSet, err = ReadClaimsSet(csb)
+		if err != nil {
+			return
+		}
+	}
+	if c.reservedFieldSize > 0 {
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(b, p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(c.reservedFieldSize) {
+			err = errors.New("error with size of CLAIMS_SET_METADATA's reserved field array")
+			return
+		}
+		c.ReservedField = ndr.ReadBytes(b, p, int(c.reservedFieldSize), e)
+	}
+	return
+}
+
+// ReadClaimsSet reads a ClaimsSet from the bytes slice.
+func ReadClaimsSet(b []byte) (c ClaimsSet, err error) {
+	ch, _, p, err := ndr.ReadHeaders(&b)
+	if err != nil {
+		err = fmt.Errorf("error parsing NDR byte stream headers of CLAIMS_SET: %v", err)
+		return
+	}
+	e := &ch.Endianness
+	//The next 4 bytes are an RPC unique pointer referent. We just skip these
+	p += 4
+
+	c.ClaimsArrayCount = ndr.ReadUint32(&b, &p, e)
+	p += 4 //Move over pointer to claims array
+	c.ReservedType = ndr.ReadUint16(&b, &p, e)
+	c.reservedFieldSize = ndr.ReadUint32(&b, &p, e)
+	p += 4 //Move over pointer to ReservedField array
+
+	var ah ndr.ConformantArrayHeader
+	if c.ClaimsArrayCount > 0 {
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(c.ClaimsArrayCount) {
+			err = errors.New("error with size of CLAIMS_SET's claims array")
+			return
+		}
+		c.ClaimsArrays = make([]ClaimsArray, c.ClaimsArrayCount, c.ClaimsArrayCount)
+		for i := range c.ClaimsArrays {
+			c.ClaimsArrays[i], err = ReadClaimsArray(&b, &p, e)
+			if err != nil {
+				return
+			}
+		}
+	}
+	if c.reservedFieldSize > 0 {
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(c.reservedFieldSize) {
+			err = errors.New("error with size of CLAIMS_SET's reserved field array")
+			return
+		}
+		c.ReservedField = ndr.ReadBytes(&b, &p, int(c.reservedFieldSize), e)
+	}
+	return c, nil
+}
+
+// ReadClaimsArray reads a ClaimsArray from the bytes slice.
+func ReadClaimsArray(b *[]byte, p *int, e *binary.ByteOrder) (c ClaimsArray, err error) {
+	c.ClaimsSourceType = ndr.ReadUint16(b, p, e)
+	c.ClaimsCount = ndr.ReadUint32(b, p, e)
+	*p += 4 //Move over pointer to claims array
+	ah, err := ndr.ReadUniDimensionalConformantArrayHeader(b, p, e)
+	if err != nil {
+		return
+	}
+	if ah.MaxCount != int(c.ClaimsCount) {
+		err = errors.New("error with size of CLAIMS_ARRAY's claims entries")
+		return
+	}
+	c.ClaimsEntries = make([]ClaimEntry, c.ClaimsCount, c.ClaimsCount)
+	for i := range c.ClaimsEntries {
+		var vc uint32
+		c.ClaimsEntries[i].Type, vc, err = ReadClaimEntriesUnionHeaders(b, p, e)
+		if err != nil {
+			return
+		}
+		switch c.ClaimsEntries[i].Type {
+		case ClaimTypeIDInt64:
+			c.ClaimsEntries[i].TypeInt64.ValueCount = vc
+		case ClaimTypeIDUInt64:
+			c.ClaimsEntries[i].TypeUInt64.ValueCount = vc
+		case ClaimTypeIDString:
+			c.ClaimsEntries[i].TypeString.ValueCount = vc
+		case ClaimsTypeIDBoolean:
+			c.ClaimsEntries[i].TypeBool.ValueCount = vc
+		}
+	}
+	for i := range c.ClaimsEntries {
+		err = FillClaimEntry(b, p, e, &c.ClaimsEntries[i])
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
+func ReadClaimEntriesUnionHeaders(b *[]byte, p *int, e *binary.ByteOrder) (uint16, uint32, error) {
+	*p += 4
+	// This is an NDR union: http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagfcjh_39
+	// The discriminant [tag] is marshalled into the transmitted data stream twice:
+	// once as the field or parameter in the procedure argument list and
+	// once as the first part of the union representation [value]
+	t1 := ndr.ReadUint16(b, p, e)
+	t2 := ndr.ReadUint16(b, p, e)
+	if t1 != t2 {
+		return 0, 0, ndr.Malformed{EText: "malformed NDR encoding of CLAIM_ENTRY union"}
+	}
+	vc := ndr.ReadUint32(b, p, e)
+	*p += 4 //Move over pointer to array of values
+	return t1, vc, nil
+}
+
+// FillClaimEntry reads a ClaimEntry from the bytes slice.
+func FillClaimEntry(b *[]byte, p *int, e *binary.ByteOrder, c *ClaimEntry) (err error) {
+	c.ID, err = ndr.ReadConformantVaryingString(b, p, e)
+	if err != nil {
+		return
+	}
+	ah, err := ndr.ReadUniDimensionalConformantArrayHeader(b, p, e)
+	if err != nil {
+		return
+	}
+	switch c.Type {
+	case ClaimTypeIDInt64:
+		if ah.MaxCount != int(c.TypeInt64.ValueCount) {
+			return errors.New("error with size of CLAIM_ENTRY's value")
+		}
+		c.TypeInt64.Value = make([]int64, c.TypeInt64.ValueCount, c.TypeInt64.ValueCount)
+		for i := range c.TypeInt64.Value {
+			buf := bytes.NewReader((*b)[*p : *p+8])
+			err = binary.Read(buf, *e, &c.TypeInt64.Value[i])
+			if err != nil {
+				return
+			}
+			*p += 8 // progress position for a uint64
+		}
+	case ClaimTypeIDUInt64:
+		if ah.MaxCount != int(c.TypeUInt64.ValueCount) {
+			return errors.New("error with size of CLAIM_ENTRY's value")
+		}
+		c.TypeUInt64.Value = make([]uint64, c.TypeUInt64.ValueCount, c.TypeUInt64.ValueCount)
+		for i := range c.TypeUInt64.Value {
+			c.TypeUInt64.Value[i] = ndr.ReadUint64(b, p, e)
+		}
+	case ClaimTypeIDString:
+		if ah.MaxCount != int(c.TypeString.ValueCount) {
+			return errors.New("error with size of CLAIM_ENTRY's value")
+		}
+		c.TypeString.Value = make([]string, c.TypeString.ValueCount, c.TypeString.ValueCount)
+		*p += 4 * (int(c.TypeString.ValueCount)) // Move over pointers
+		for i := range c.TypeString.Value {
+			c.TypeString.Value[i], err = ndr.ReadConformantVaryingString(b, p, e)
+			if err != nil {
+				return
+			}
+		}
+	case ClaimsTypeIDBoolean:
+		if ah.MaxCount != int(c.TypeBool.ValueCount) {
+			return errors.New("error with size of CLAIM_ENTRY's value")
+		}
+		c.TypeBool.Value = make([]bool, c.TypeBool.ValueCount, c.TypeBool.ValueCount)
+		for i := range c.TypeBool.Value {
+			if ndr.ReadUint64(b, p, e) != 0 {
+				c.TypeBool.Value[i] = true
+			}
+		}
+	}
+	return
+}
diff --git a/mstypes/claims_set_metadata.go b/mstypes/claims_set_metadata.go
deleted file mode 100644
index d53b63d..0000000
--- a/mstypes/claims_set_metadata.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package mstypes
-
-import (
-	"encoding/binary"
-
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
-)
-
-// ClaimsSetMetadata implements https://msdn.microsoft.com/en-us/library/hh554073.aspx
-type ClaimsSetMetadata struct {
-	ULClaimsSetSize             uint32
-	ClaimsSet                   []byte
-	USCompressionFormat         uint32 // Enum see constants below for options
-	ULUncompressedClaimsSetSize uint32
-	USReservedType              uint16
-	ULReservedFieldSize         uint32
-	ReservedField               []byte
-}
-
-// Compression format assigned numbers.
-const (
-	CompressionFormatNone       = 0
-	CompressionFormatLZNT1      = 2
-	CompressionFormatXPress     = 3
-	CompressionFormatXPressHuff = 4
-)
-
-// ReadClaimsSetMetadata reads a ClaimsSetMetadata from the bytes slice.
-func ReadClaimsSetMetadata(b *[]byte, p *int, e *binary.ByteOrder) ClaimsSetMetadata {
-	var c ClaimsSetMetadata
-	c.ULClaimsSetSize = ndr.ReadUint32(b, p, e)
-	c.ClaimsSet = ndr.ReadBytes(b, p, int(c.ULClaimsSetSize), e)
-	c.USCompressionFormat = ndr.ReadUint32(b, p, e)
-	c.ULUncompressedClaimsSetSize = ndr.ReadUint32(b, p, e)
-	c.USReservedType = ndr.ReadUint16(b, p, e)
-	c.ULReservedFieldSize = ndr.ReadUint32(b, p, e)
-	c.ReservedField = ndr.ReadBytes(b, p, int(c.ULReservedFieldSize), e)
-	return c
-}
diff --git a/mstypes/filetime.go b/mstypes/filetime.go
index f67912a..417e4dc 100644
--- a/mstypes/filetime.go
+++ b/mstypes/filetime.go
@@ -5,7 +5,7 @@ import (
 	"encoding/binary"
 	"time"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 /*
diff --git a/mstypes/group_membership.go b/mstypes/group_membership.go
index 4801c20..984160f 100644
--- a/mstypes/group_membership.go
+++ b/mstypes/group_membership.go
@@ -3,7 +3,7 @@ package mstypes
 import (
 	"encoding/binary"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // GroupMembership implements https://msdn.microsoft.com/en-us/library/cc237945.aspx
diff --git a/mstypes/kerb_sid_and_attributes.go b/mstypes/kerb_sid_and_attributes.go
index f84c578..fee509b 100644
--- a/mstypes/kerb_sid_and_attributes.go
+++ b/mstypes/kerb_sid_and_attributes.go
@@ -3,7 +3,7 @@ package mstypes
 import (
 	"encoding/binary"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // Attributes of a security group membership and can be combined by using the bitwise OR operation.
diff --git a/mstypes/rpc_unicode_string.go b/mstypes/rpc_unicode_string.go
index 3c38afe..0981b97 100644
--- a/mstypes/rpc_unicode_string.go
+++ b/mstypes/rpc_unicode_string.go
@@ -3,7 +3,7 @@ package mstypes
 import (
 	"encoding/binary"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // RPCUnicodeString implements https://msdn.microsoft.com/en-us/library/cc230365.aspx
diff --git a/mstypes/sid.go b/mstypes/sid.go
index 0a62fa1..626d0b1 100644
--- a/mstypes/sid.go
+++ b/mstypes/sid.go
@@ -5,7 +5,7 @@ import (
 	"encoding/hex"
 	"fmt"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // RPCSID implements https://msdn.microsoft.com/en-us/library/cc230364.aspx
diff --git a/mstypes/user_session_key.go b/mstypes/user_session_key.go
index f3324c4..7ae4f7d 100644
--- a/mstypes/user_session_key.go
+++ b/mstypes/user_session_key.go
@@ -3,7 +3,7 @@ package mstypes
 import (
 	"encoding/binary"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // CypherBlock implements https://msdn.microsoft.com/en-us/library/cc237040.aspx
diff --git a/ndr/ndr.go b/ndr/ndr.go
index 97958f5..f5e6c42 100644
--- a/ndr/ndr.go
+++ b/ndr/ndr.go
@@ -1,4 +1,4 @@
-// Package ndr is a partial implementation of NDR encoding: http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm
+// Package ndr is DEPRECATED and will be removed from next major revision of gokrb5. Please use gopkg.in/jcmturner/rpc.vX instead. This package is a partial implementation of NDR encoding: http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm
 package ndr
 
 import (
diff --git a/pac/client_claims.go b/pac/client_claims.go
index 54d7094..a66a91e 100644
--- a/pac/client_claims.go
+++ b/pac/client_claims.go
@@ -4,9 +4,11 @@ import (
 	"fmt"
 
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
+// Claims reference: https://msdn.microsoft.com/en-us/library/hh553895.aspx
+
 // ClientClaimsInfo implements https://msdn.microsoft.com/en-us/library/hh536365.aspx
 type ClientClaimsInfo struct {
 	Claims mstypes.ClaimsSetMetadata
@@ -16,23 +18,24 @@ type ClientClaimsInfo struct {
 func (k *ClientClaimsInfo) Unmarshal(b []byte) error {
 	ch, _, p, err := ndr.ReadHeaders(&b)
 	if err != nil {
-		return fmt.Errorf("error parsing byte stream headers: %v", err)
+		return fmt.Errorf("error parsing byte stream headers of CLIENT_CLAIMS_INFO: %v", err)
 	}
 	e := &ch.Endianness
-
 	//The next 4 bytes are an RPC unique pointer referent. We just skip these
 	p += 4
 
-	k.Claims = mstypes.ReadClaimsSetMetadata(&b, &p, e)
+	k.Claims, err = mstypes.ReadClaimsSetMetadata(&b, &p, e)
+	if err != nil {
+		return err
+	}
 
 	//Check that there is only zero padding left
 	if len(b) >= p {
 		for _, v := range b[p:] {
 			if v != 0 {
-				return ndr.Malformed{EText: "Non-zero padding left over at end of data stream"}
+				return ndr.Malformed{EText: "non-zero padding left over at end of data stream"}
 			}
 		}
 	}
-
 	return nil
 }
diff --git a/pac/client_info.go b/pac/client_info.go
index fd925db..a0c2468 100644
--- a/pac/client_info.go
+++ b/pac/client_info.go
@@ -4,7 +4,7 @@ import (
 	"encoding/binary"
 
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // ClientInfo implements https://msdn.microsoft.com/en-us/library/cc237951.aspx
@@ -25,18 +25,13 @@ func (k *ClientInfo) Unmarshal(b []byte) error {
 	if len(b[p:]) < int(k.NameLength) {
 		return ndr.Malformed{EText: "PAC ClientInfo length truncated"}
 	}
-	//Length divided by 2 as each run is 16bits = 2bytes
-	s := make([]rune, k.NameLength/2, k.NameLength/2)
-	for i := 0; i < len(s); i++ {
-		s[i] = rune(ndr.ReadUint16(&b, &p, &e))
-	}
-	k.Name = string(s)
+	k.Name = ndr.ReadUTF16String(int(k.NameLength), &b, &p, &e)
 
 	//Check that there is only zero padding left
 	if len(b) >= p {
 		for _, v := range b[p:] {
 			if v != 0 {
-				return ndr.Malformed{EText: "Non-zero padding left over at end of data stream"}
+				return ndr.Malformed{EText: "non-zero padding left over at end of data stream"}
 			}
 		}
 	}
diff --git a/pac/credentials_info.go b/pac/credentials_info.go
index ff89d34..4a3c516 100644
--- a/pac/credentials_info.go
+++ b/pac/credentials_info.go
@@ -2,13 +2,14 @@ package pac
 
 import (
 	"encoding/binary"
+	"errors"
 	"fmt"
 
 	"gopkg.in/jcmturner/gokrb5.v5/crypto"
 	"gopkg.in/jcmturner/gokrb5.v5/iana/keyusage"
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
 	"gopkg.in/jcmturner/gokrb5.v5/types"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // https://msdn.microsoft.com/en-us/library/cc237931.aspx
@@ -23,20 +24,18 @@ type CredentialsInfo struct {
 
 // Unmarshal bytes into the CredentialsInfo struct
 func (c *CredentialsInfo) Unmarshal(b []byte, k types.EncryptionKey) error {
-	ch, _, p, err := ndr.ReadHeaders(&b)
-	if err != nil {
-		return fmt.Errorf("error parsing byte stream headers: %v", err)
-	}
-	e := &ch.Endianness
-
-	//The next 4 bytes are an RPC unique pointer referent. We just skip these
-	p += 4
+	//The CredentialsInfo structure is a simple structure that is not NDR-encoded.
+	var p int
+	var e binary.ByteOrder = binary.LittleEndian
 
-	c.Version = ndr.ReadUint32(&b, &p, e)
-	c.EType = ndr.ReadUint32(&b, &p, e)
-	c.PACCredentialDataEncrypted = ndr.ReadBytes(&b, &p, len(b)-p, e)
+	c.Version = ndr.ReadUint32(&b, &p, &e)
+	if c.Version != 0 {
+		return errors.New("credentials info version is not zero")
+	}
+	c.EType = ndr.ReadUint32(&b, &p, &e)
+	c.PACCredentialDataEncrypted = ndr.ReadBytes(&b, &p, len(b)-p, &e)
 
-	err = c.DecryptEncPart(k, e)
+	err := c.DecryptEncPart(k, &e)
 	if err != nil {
 		return fmt.Errorf("error decrypting PAC Credentials Data: %v", err)
 	}
diff --git a/pac/device_claims.go b/pac/device_claims.go
index 3a6699a..977170d 100644
--- a/pac/device_claims.go
+++ b/pac/device_claims.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // DeviceClaimsInfo implements https://msdn.microsoft.com/en-us/library/hh554226.aspx
@@ -16,14 +16,16 @@ type DeviceClaimsInfo struct {
 func (k *DeviceClaimsInfo) Unmarshal(b []byte) error {
 	ch, _, p, err := ndr.ReadHeaders(&b)
 	if err != nil {
-		return fmt.Errorf("error parsing byte stream headers: %v", err)
+		return fmt.Errorf("error parsing byte stream headers of DEVICE_CLAIMS_INFO: %v", err)
 	}
 	e := &ch.Endianness
-
 	//The next 4 bytes are an RPC unique pointer referent. We just skip these
 	p += 4
 
-	k.Claims = mstypes.ReadClaimsSetMetadata(&b, &p, e)
+	k.Claims, err = mstypes.ReadClaimsSetMetadata(&b, &p, e)
+	if err != nil {
+		return err
+	}
 
 	//Check that there is only zero padding left
 	if len(b) >= p {
@@ -33,6 +35,5 @@ func (k *DeviceClaimsInfo) Unmarshal(b []byte) error {
 			}
 		}
 	}
-
 	return nil
 }
diff --git a/pac/device_info.go b/pac/device_info.go
index 9155525..e3fa3fc 100644
--- a/pac/device_info.go
+++ b/pac/device_info.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // DeviceInfo implements https://msdn.microsoft.com/en-us/library/hh536402.aspx
@@ -47,10 +47,11 @@ func (k *DeviceInfo) Unmarshal(b []byte) error {
 	}
 
 	k.SIDCount = ndr.ReadUint32(&b, &p, e)
+	var ah ndr.ConformantArrayHeader
 	if k.SIDCount > 0 {
-		ac := ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
-		if ac != int(k.SIDCount) {
-			return fmt.Errorf("error with size of ExtraSIDs list. expected: %d, Actual: %d", k.SIDCount, ac)
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
+		if ah.MaxCount != int(k.SIDCount) {
+			return fmt.Errorf("error with size of ExtraSIDs list. expected: %d, Actual: %d", k.SIDCount, ah.MaxCount)
 		}
 		es := make([]mstypes.KerbSidAndAttributes, k.SIDCount, k.SIDCount)
 		attr := make([]uint32, k.SIDCount, k.SIDCount)
diff --git a/pac/kerb_validation_info.go b/pac/kerb_validation_info.go
index c7916a8..cc346ad 100644
--- a/pac/kerb_validation_info.go
+++ b/pac/kerb_validation_info.go
@@ -6,7 +6,7 @@ import (
 	"fmt"
 
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // KERB_VALIDATION_INFO flags.
@@ -168,11 +168,15 @@ func (k *KerbValidationInfo) Unmarshal(b []byte) (err error) {
 	if err = k.HomeDirectoryDrive.UnmarshalString(&b, &p, e); err != nil {
 		return
 	}
-
+	var ah ndr.ConformantArrayHeader
 	if k.GroupCount > 0 {
-		ac := ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
-		if ac != int(k.GroupCount) {
-			return errors.New("error with size of group list")
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(k.GroupCount) {
+			err = errors.New("error with size of group list")
+			return
 		}
 		g := make([]mstypes.GroupMembership, k.GroupCount, k.GroupCount)
 		for i := range g {
@@ -196,9 +200,12 @@ func (k *KerbValidationInfo) Unmarshal(b []byte) (err error) {
 	}
 
 	if k.SIDCount > 0 {
-		ac := ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
-		if ac != int(k.SIDCount) {
-			return fmt.Errorf("error with size of ExtraSIDs list. Expected: %d, Actual: %d", k.SIDCount, ac)
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(k.SIDCount) {
+			return fmt.Errorf("error with size of ExtraSIDs list. Expected: %d, Actual: %d", k.SIDCount, ah.MaxCount)
 		}
 		es := make([]mstypes.KerbSidAndAttributes, k.SIDCount, k.SIDCount)
 		attr := make([]uint32, k.SIDCount, k.SIDCount)
@@ -227,11 +234,14 @@ func (k *KerbValidationInfo) Unmarshal(b []byte) (err error) {
 	}
 
 	if k.ResourceGroupCount > 0 {
-		ac := ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
-		if ac != int(k.ResourceGroupCount) {
-			return fmt.Errorf("error with size of ResourceGroup list. Expected: %d, Actual: %d", k.ResourceGroupCount, ac)
+		ah, err = ndr.ReadUniDimensionalConformantArrayHeader(&b, &p, e)
+		if err != nil {
+			return
+		}
+		if ah.MaxCount != int(k.ResourceGroupCount) {
+			return fmt.Errorf("error with size of ResourceGroup list. Expected: %d, Actual: %d", k.ResourceGroupCount, ah.MaxCount)
 		}
-		g := make([]mstypes.GroupMembership, ac, ac)
+		g := make([]mstypes.GroupMembership, k.ResourceGroupCount, k.ResourceGroupCount)
 		for i := range g {
 			g[i] = mstypes.ReadGroupMembership(&b, &p, e)
 		}
diff --git a/pac/pac_info_buffer.go b/pac/pac_info_buffer.go
index 70cd68f..be6f41b 100644
--- a/pac/pac_info_buffer.go
+++ b/pac/pac_info_buffer.go
@@ -3,7 +3,7 @@ package pac
 import (
 	"encoding/binary"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 const (
diff --git a/pac/pac_type.go b/pac/pac_type.go
index ea2a8ad..be12e96 100644
--- a/pac/pac_type.go
+++ b/pac/pac_type.go
@@ -7,8 +7,8 @@ import (
 
 	"gopkg.in/jcmturner/gokrb5.v5/crypto"
 	"gopkg.in/jcmturner/gokrb5.v5/iana/keyusage"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
 	"gopkg.in/jcmturner/gokrb5.v5/types"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // PACType implements: https://msdn.microsoft.com/en-us/library/cc237950.aspx
@@ -67,16 +67,20 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			}
 			pac.KerbValidationInfo = &k
 		case ulTypeCredentials:
-			if pac.CredentialsInfo != nil {
-				//Must ignore subsequent buffers of this type
-				continue
-			}
-			var k CredentialsInfo
-			err := k.Unmarshal(p, key)
-			if err != nil {
-				return fmt.Errorf("error processing CredentialsInfo: %v", err)
-			}
-			pac.CredentialsInfo = &k
+			// Currently PAC parsing is only useful on the service side in gokrb5
+			// The CredentialsInfo are only useful when gokrb5 has implemented RFC4556 and only applied on the client side.
+			// Skipping CredentialsInfo - will be revisited under RFC4556 implementation.
+			continue
+			//if pac.CredentialsInfo != nil {
+			//	//Must ignore subsequent buffers of this type
+			//	continue
+			//}
+			//var k CredentialsInfo
+			//err := k.Unmarshal(p, key) // The encryption key used is the AS reply key only available to the client.
+			//if err != nil {
+			//	return fmt.Errorf("error processing CredentialsInfo: %v", err)
+			//}
+			//pac.CredentialsInfo = &k
 		case ulTypePACServerSignatureData:
 			if pac.ServerChecksum != nil {
 				//Must ignore subsequent buffers of this type
@@ -135,7 +139,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			}
 			pac.UPNDNSInfo = &k
 		case ulTypePACClientClaimsInfo:
-			if pac.ClientClaimsInfo != nil {
+			if pac.ClientClaimsInfo != nil || len(p) < 1 {
 				//Must ignore subsequent buffers of this type
 				continue
 			}
diff --git a/pac/s4u_delegation_info.go b/pac/s4u_delegation_info.go
index e13fea2..82b9687 100644
--- a/pac/s4u_delegation_info.go
+++ b/pac/s4u_delegation_info.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 
 	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // S4UDelegationInfo implements https://msdn.microsoft.com/en-us/library/cc237944.aspx
diff --git a/pac/signature_data.go b/pac/signature_data.go
index 3b588dd..c0bb5cb 100644
--- a/pac/signature_data.go
+++ b/pac/signature_data.go
@@ -4,7 +4,7 @@ import (
 	"encoding/binary"
 
 	"gopkg.in/jcmturner/gokrb5.v5/iana/chksumtype"
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 /*
@@ -60,7 +60,7 @@ func (k *SignatureData) Unmarshal(b []byte) ([]byte, error) {
 	//Check that there is only zero padding left
 	for _, v := range b[p:] {
 		if v != 0 {
-			return []byte{}, ndr.Malformed{EText: "Non-zero padding left over at end of data stream"}
+			return []byte{}, ndr.Malformed{EText: "non-zero padding left over at end of data stream"}
 		}
 	}
 
diff --git a/pac/upn_dns_info.go b/pac/upn_dns_info.go
index 4695ce3..71f10f0 100644
--- a/pac/upn_dns_info.go
+++ b/pac/upn_dns_info.go
@@ -4,7 +4,7 @@ import (
 	"encoding/binary"
 	"sort"
 
-	"gopkg.in/jcmturner/gokrb5.v5/ndr"
+	"gopkg.in/jcmturner/rpc.v0/ndr"
 )
 
 // UPNDNSInfo implements https://msdn.microsoft.com/en-us/library/dd240468.aspx
@@ -58,7 +58,7 @@ func (k *UPNDNSInfo) Unmarshal(b []byte) error {
 	//Check that there is only zero padding left
 	for _, v := range b[l[2]:] {
 		if v != 0 {
-			return ndr.Malformed{EText: "Non-zero padding left over at end of data stream."}
+			return ndr.Malformed{EText: "non-zero padding left over at end of data stream."}
 		}
 	}
 


Test patch:
diff --git a/client/client_ad_integration_test.go b/client/client_ad_integration_test.go
index a76971e..7b37e1f 100644
--- a/client/client_ad_integration_test.go
+++ b/client/client_ad_integration_test.go
@@ -106,3 +106,46 @@ func TestClient_GetServiceTicket_AD_TRUST_USER_DOMAIN(t *testing.T) {
 	assert.Equal(t, "testuser1", pac.KerbValidationInfo.EffectiveName.Value, "PAC value not parsed")
 
 }
+
+func TestClient_GetServiceTicket_AD_USER_DOMAIN(t *testing.T) {
+	b, _ := hex.DecodeString(testdata.TESTUSER1_USERKRB5_AD_KEYTAB)
+	kt, _ := keytab.Parse(b)
+	c, _ := config.NewConfigFromString(testdata.TEST_KRB5CONF)
+	c.Realms[0].KDC = []string{testdata.TEST_KDC_AD_TRUST_USER_DOMAIN}
+	c.LibDefaults.DefaultRealm = "USER.GOKRB5"
+	c.LibDefaults.Canonicalize = true
+	cl := NewClientWithKeytab("testuser1", "USER.GOKRB5", kt)
+	c.LibDefaults.DefaultTktEnctypes = []string{"rc4-hmac"}
+	c.LibDefaults.DefaultTktEnctypeIDs = []int32{etypeID.ETypesByName["rc4-hmac"]}
+	c.LibDefaults.DefaultTGSEnctypes = []string{"rc4-hmac"}
+	c.LibDefaults.DefaultTGSEnctypeIDs = []int32{etypeID.ETypesByName["rc4-hmac"]}
+	cl.WithConfig(c)
+	cl.GoKrb5Conf.DisablePAFXFast = true
+
+	err := cl.Login()
+
+	if err != nil {
+		t.Fatalf("Error on login: %v\n", err)
+	}
+	spn := "HTTP/user2.user.gokrb5"
+	tkt, _, err := cl.GetServiceTicket(spn)
+	if err != nil {
+		t.Fatalf("Error getting service ticket: %v\n", err)
+	}
+	assert.Equal(t, spn, tkt.SName.GetPrincipalNameString())
+	//assert.Equal(t, etypeID.ETypesByName["rc4-hmac"], key.KeyType)
+
+	b, _ = hex.DecodeString(testdata.TESTUSER2_USERKRB5_AD_KEYTAB)
+	skt, _ := keytab.Parse(b)
+	err = tkt.DecryptEncPart(skt, "testuser2")
+	if err != nil {
+		t.Errorf("error decrypting ticket with service keytab: %v", err)
+	}
+	isPAC, pac, err := tkt.GetPACType(skt, "testuser2")
+	if err != nil {
+		t.Errorf("error getting PAC: %v", err)
+	}
+	assert.True(t, isPAC, "Did not find PAC in service ticket")
+	assert.Equal(t, "testuser1", pac.KerbValidationInfo.EffectiveName.Value, "PAC value not parsed")
+
+}
diff --git a/pac/client_claims_test.go b/pac/client_claims_test.go
new file mode 100644
index 0000000..79775dc
--- /dev/null
+++ b/pac/client_claims_test.go
@@ -0,0 +1,144 @@
+package pac
+
+import (
+	"encoding/hex"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"gopkg.in/jcmturner/gokrb5.v5/mstypes"
+	"gopkg.in/jcmturner/gokrb5.v5/testdata"
+)
+
+const (
+	ClaimsEntryIDStr            = "ad://ext/sAMAccountName:88d5d9085ea5c0c0"
+	ClaimsEntryValueStr         = "testuser1"
+	ClaimsEntryIDInt64          = "ad://ext/msDS-SupportedE:88d5dea8f1af5f19"
+	ClaimsEntryValueInt64 int64 = 28
+	ClaimsEntryIDUInt64         = "ad://ext/objectClass:88d5de791e7b27e6"
+)
+
+func TestPAC_ClientClaimsInfoStr_Unmarshal(t *testing.T) {
+	t.Parallel()
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_ClientClaimsInfoStr"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k ClientClaimsInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrayCount, "claims array count not as expected")
+	assert.Equal(t, mstypes.ClaimsSourceTypeAD, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsSourceType, "claims source type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsCount, "claims count not as expected")
+	assert.Equal(t, uint16(3), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].Type, "claims entry type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeString.ValueCount, "claims value count not as expected")
+	assert.Equal(t, ClaimsEntryIDStr, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].ID, "claims entry ID not as expected")
+	assert.Equal(t, []string{ClaimsEntryValueStr}, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeString.Value, "claims value not as expected")
+	assert.Equal(t, mstypes.CompressionFormatNone, k.Claims.CompressionFormat, "compression format not as expected")
+}
+
+func TestPAC_ClientClaimsMultiValueUint_Unmarshal(t *testing.T) {
+	t.Parallel()
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_ClientClaimsInfoMultiUint"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k ClientClaimsInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrayCount, "claims array count not as expected")
+	assert.Equal(t, mstypes.ClaimsSourceTypeAD, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsSourceType, "claims source type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsCount, "claims count not as expected")
+	assert.Equal(t, mstypes.ClaimTypeIDUInt64, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].Type, "claims entry type not as expected")
+	assert.Equal(t, uint32(4), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeUInt64.ValueCount, "claims value count not as expected")
+	assert.Equal(t, ClaimsEntryIDUInt64, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].ID, "claims entry ID not as expected")
+	assert.Equal(t, []uint64{655369, 65543, 65542, 65536}, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeUInt64.Value, "claims value not as expected")
+	assert.Equal(t, mstypes.CompressionFormatNone, k.Claims.CompressionFormat, "compression format not as expected")
+}
+
+func TestPAC_ClientClaimsInt_Unmarshal(t *testing.T) {
+	t.Parallel()
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_ClientClaimsInfoInt"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k ClientClaimsInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrayCount, "claims array count not as expected")
+	assert.Equal(t, mstypes.ClaimsSourceTypeAD, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsSourceType, "claims source type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsCount, "claims count not as expected")
+	assert.Equal(t, mstypes.ClaimTypeIDInt64, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].Type, "claims entry type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeInt64.ValueCount, "claims value count not as expected")
+	assert.Equal(t, ClaimsEntryIDInt64, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].ID, "claims entry ID not as expected")
+	assert.Equal(t, []int64{ClaimsEntryValueInt64}, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeInt64.Value, "claims value not as expected")
+	assert.Equal(t, mstypes.CompressionFormatNone, k.Claims.CompressionFormat, "compression format not as expected")
+}
+
+func TestPAC_ClientClaimsMultiValueStr_Unmarshal(t *testing.T) {
+	t.Parallel()
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_ClientClaimsInfoMultiStr"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k ClientClaimsInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	t.Logf("%+v\n", k)
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrayCount, "claims array count not as expected")
+	assert.Equal(t, mstypes.ClaimsSourceTypeAD, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsSourceType, "claims source type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsCount, "claims count not as expected")
+	assert.Equal(t, mstypes.ClaimTypeIDString, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].Type, "claims entry type not as expected")
+	assert.Equal(t, uint32(4), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeString.ValueCount, "claims value count not as expected")
+	assert.Equal(t, "ad://ext/otherIpPhone:88d5de9f6b4af985", k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].ID, "claims entry ID not as expected")
+	assert.Equal(t, []string{"str1", "str2", "str3", "str4"}, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeString.Value, "claims value not as expected")
+	assert.Equal(t, mstypes.CompressionFormatNone, k.Claims.CompressionFormat, "compression format not as expected")
+}
+
+func TestPAC_ClientClaimsInfoMultiEntry_Unmarshal(t *testing.T) {
+	// Has an int and a str claim type
+	t.Parallel()
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_ClientClaimsInfoMulti"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k ClientClaimsInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	t.Logf("%+v\n", k)
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrayCount, "claims array count not as expected")
+	assert.Equal(t, mstypes.ClaimsSourceTypeAD, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsSourceType, "claims source type not as expected")
+	assert.Equal(t, uint32(2), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsCount, "claims count not as expected")
+	assert.Equal(t, uint16(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].Type, "claims entry type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeInt64.ValueCount, "claims value count not as expected")
+	assert.Equal(t, ClaimsEntryIDInt64, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].ID, "claims entry ID not as expected")
+	assert.Equal(t, []int64{int64(28)}, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[0].TypeInt64.Value, "claims value not as expected")
+	assert.Equal(t, uint16(3), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[1].Type, "claims entry type not as expected")
+	assert.Equal(t, uint32(1), k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[1].TypeString.ValueCount, "claims value count not as expected")
+	assert.Equal(t, ClaimsEntryIDStr, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[1].ID, "claims entry ID not as expected")
+	assert.Equal(t, []string{ClaimsEntryValueStr}, k.Claims.ClaimsSet.ClaimsArrays[0].ClaimsEntries[1].TypeString.Value, "claims value not as expected")
+	assert.Equal(t, mstypes.CompressionFormatNone, k.Claims.CompressionFormat, "compression format not as expected")
+}
+
+func TestPAC_ClientClaimsInfo_Unmarshal_UnsupportedCompression(t *testing.T) {
+	t.Parallel()
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_ClientClaimsInfo_XPRESS_HUFF"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k ClientClaimsInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	assert.Equal(t, mstypes.CompressionFormatXPressHuff, k.Claims.CompressionFormat, "compression format not as expected")
+}
diff --git a/testdata/test_vectors.go b/testdata/test_vectors.go
index a563733..5308839 100644
--- a/testdata/test_vectors.go
+++ b/testdata/test_vectors.go
@@ -93,16 +93,22 @@ var TestVectors = map[string]string{
 	//"encode_krb5_secure_cookie":                                  "302C02042DF8022530243010A10302010DA209040770612D646174613010A10302010DA209040770612D64617461",
 
 	//MS PAC Vectors
-	"PAC_AuthorizationData_MS":       "308205523082054ea00402020080a182054404820540040000000000000001000000b004000048000000000000000a00000012000000f804000000000000060000001400000010050000000000000700000014000000280500000000000001100800cccccccca00400000000000000000200d186660f656ac601ffffffffffffff7fffffffffffffff7f17d439fe784ac6011794a328424bc601175424977a81c60108000800040002002400240008000200120012000c0002000000000010000200000000001400020000000000180002005410000097792c00010200001a0000001c000200200000000000000000000000000000000000000016001800200002000a000c002400020028000200000000000000000010000000000000000000000000000000000000000000000000000000000000000d0000002c0002000000000000000000000000000400000000000000040000006c007a00680075001200000000000000120000004c0069007100690061006e00670028004c006100720072007900290020005a00680075000900000000000000090000006e0074006400730032002e0062006100740000000000000000000000000000000000000000000000000000000000000000000000000000001a00000061c433000700000009c32d00070000005eb4320007000000010200000700000097b92c00070000002bf1320007000000ce30330007000000a72e2e00070000002af132000700000098b92c000700000062c4330007000000940133000700000076c4330007000000aefe2d000700000032d22c00070000001608320007000000425b2e00070000005fb4320007000000ca9c35000700000085442d0007000000c2f0320007000000e9ea310007000000ed8e2e0007000000b6eb310007000000ab2e2e0007000000720e2e00070000000c000000000000000b0000004e0054004400450056002d00440043002d003000350000000600000000000000050000004e0054004400450056000000040000000104000000000005150000005951b81766725d2564633b0b0d0000003000020007000000340002000700002038000200070000203c000200070000204000020007000020440002000700002048000200070000204c000200070000205000020007000020540002000700002058000200070000205c00020007000020600002000700002005000000010500000000000515000000b9301b2eb7414c6c8c3b351501020000050000000105000000000005150000005951b81766725d2564633b0b74542f00050000000105000000000005150000005951b81766725d2564633b0be8383200050000000105000000000005150000005951b81766725d2564633b0bcd383200050000000105000000000005150000005951b81766725d2564633b0b5db43200050000000105000000000005150000005951b81766725d2564633b0b41163500050000000105000000000005150000005951b81766725d2564633b0be8ea3100050000000105000000000005150000005951b81766725d2564633b0bc1193200050000000105000000000005150000005951b81766725d2564633b0b29f13200050000000105000000000005150000005951b81766725d2564633b0b0f5f2e00050000000105000000000005150000005951b81766725d2564633b0b2f5b2e00050000000105000000000005150000005951b81766725d2564633b0bef8f3100050000000105000000000005150000005951b81766725d2564633b0b075f2e00000000000049d90e656ac60108006c007a006800750000000000000076ffffff41edce9a34815d3aef7bc98874805d250000000076fffffff7a534dab2c02986efe0fbe5110a4f3200000000",
-	"PAC_Kerb_Validation_Info_MS":    "01100800cccccccca00400000000000000000200d186660f656ac601ffffffffffffff7fffffffffffffff7f17d439fe784ac6011794a328424bc601175424977a81c60108000800040002002400240008000200120012000c0002000000000010000200000000001400020000000000180002005410000097792c00010200001a0000001c000200200000000000000000000000000000000000000016001800200002000a000c002400020028000200000000000000000010000000000000000000000000000000000000000000000000000000000000000d0000002c0002000000000000000000000000000400000000000000040000006c007a00680075001200000000000000120000004c0069007100690061006e00670028004c006100720072007900290020005a00680075000900000000000000090000006e0074006400730032002e0062006100740000000000000000000000000000000000000000000000000000000000000000000000000000001a00000061c433000700000009c32d00070000005eb4320007000000010200000700000097b92c00070000002bf1320007000000ce30330007000000a72e2e00070000002af132000700000098b92c000700000062c4330007000000940133000700000076c4330007000000aefe2d000700000032d22c00070000001608320007000000425b2e00070000005fb4320007000000ca9c35000700000085442d0007000000c2f0320007000000e9ea310007000000ed8e2e0007000000b6eb310007000000ab2e2e0007000000720e2e00070000000c000000000000000b0000004e0054004400450056002d00440043002d003000350000000600000000000000050000004e0054004400450056000000040000000104000000000005150000005951b81766725d2564633b0b0d0000003000020007000000340002000700002038000200070000203c000200070000204000020007000020440002000700002048000200070000204c000200070000205000020007000020540002000700002058000200070000205c00020007000020600002000700002005000000010500000000000515000000b9301b2eb7414c6c8c3b351501020000050000000105000000000005150000005951b81766725d2564633b0b74542f00050000000105000000000005150000005951b81766725d2564633b0be8383200050000000105000000000005150000005951b81766725d2564633b0bcd383200050000000105000000000005150000005951b81766725d2564633b0b5db43200050000000105000000000005150000005951b81766725d2564633b0b41163500050000000105000000000005150000005951b81766725d2564633b0be8ea3100050000000105000000000005150000005951b81766725d2564633b0bc1193200050000000105000000000005150000005951b81766725d2564633b0b29f13200050000000105000000000005150000005951b81766725d2564633b0b0f5f2e00050000000105000000000005150000005951b81766725d2564633b0b2f5b2e00050000000105000000000005150000005951b81766725d2564633b0bef8f3100050000000105000000000005150000005951b81766725d2564633b0b075f2e0000000000",
-	"PAC_AuthorizationData_GOKRB5":   "3082034730820343a003020101a182033a04820336308203323082032ea00402020080a1820324048203200500000000000000010000002802000058000000000000000a0000001c00000080020000000000000c00000058000000a0020000000000000600000010000000f8020000000000000700000014000000080300000000000001100800cccccccc180200000000000000000200058e4fdd80c6d201ffffffffffffff7fffffffffffffff7fcc27969c39c6d201cce7ffc602c7d201ffffffffffffff7f12001200040002001600160008000200000000000c000200000000001000020000000000140002000000000018000200d80000005104000001020000050000001c000200200000000000000000000000000000000000000008000a002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000020000002c00020000000000000000000000000009000000000000000900000074006500730074007500730065007200310000000b000000000000000b000000540065007300740031002000550073006500720031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000102000007000000540400000700000055040000070000005b040000070000005c0400000700000005000000000000000400000041004400440043000500000000000000040000005400450053005400040000000104000000000005150000004c86cebca07160e63fdce8870200000030000200070000203400020007000020050000000105000000000005150000004c86cebca07160e63fdce8875a040000050000000105000000000005150000004c86cebca07160e63fdce8875704000000000000808dd1dc80c6d2011200740065007300740075007300650072003100000000002a001000160040000000000000000000740065007300740075007300650072003100400074006500730074002e0067006f006b0072006200350000000000000054004500530054002e0047004f004b005200420035000000100000001e251d98d552be7df384f55076ffffff340be28b48765d0519ee9346cf53d82200000000",
-	"PAC_AD_WIN2K_PAC":               "0500000000000000010000002802000058000000000000000a0000001c00000080020000000000000c00000058000000a0020000000000000600000010000000f8020000000000000700000014000000080300000000000001100800cccccccc180200000000000000000200058e4fdd80c6d201ffffffffffffff7fffffffffffffff7fcc27969c39c6d201cce7ffc602c7d201ffffffffffffff7f12001200040002001600160008000200000000000c000200000000001000020000000000140002000000000018000200d80000005104000001020000050000001c000200200000000000000000000000000000000000000008000a002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000020000002c00020000000000000000000000000009000000000000000900000074006500730074007500730065007200310000000b000000000000000b000000540065007300740031002000550073006500720031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000102000007000000540400000700000055040000070000005b040000070000005c0400000700000005000000000000000400000041004400440043000500000000000000040000005400450053005400040000000104000000000005150000004c86cebca07160e63fdce8870200000030000200070000203400020007000020050000000105000000000005150000004c86cebca07160e63fdce8875a040000050000000105000000000005150000004c86cebca07160e63fdce8875704000000000000808dd1dc80c6d2011200740065007300740075007300650072003100000000002a001000160040000000000000000000740065007300740075007300650072003100400074006500730074002e0067006f006b0072006200350000000000000054004500530054002e0047004f004b005200420035000000100000001e251d98d552be7df384f55076ffffff340be28b48765d0519ee9346cf53d82200000000",
-	"PAC_Kerb_Validation_Info":       "01100800cccccccc180200000000000000000200058e4fdd80c6d201ffffffffffffff7fffffffffffffff7fcc27969c39c6d201cce7ffc602c7d201ffffffffffffff7f12001200040002001600160008000200000000000c000200000000001000020000000000140002000000000018000200d80000005104000001020000050000001c000200200000000000000000000000000000000000000008000a002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000020000002c00020000000000000000000000000009000000000000000900000074006500730074007500730065007200310000000b000000000000000b000000540065007300740031002000550073006500720031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000102000007000000540400000700000055040000070000005b040000070000005c0400000700000005000000000000000400000041004400440043000500000000000000040000005400450053005400040000000104000000000005150000004c86cebca07160e63fdce8870200000030000200070000203400020007000020050000000105000000000005150000004c86cebca07160e63fdce8875a040000050000000105000000000005150000004c86cebca07160e63fdce8875704000000000000",
-	"PAC_Client_Info":                "808dd1dc80c6d2011200740065007300740075007300650072003100",
-	"PAC_UPN_DNS_Info":               "2a001000160040000000000000000000740065007300740075007300650072003100400074006500730074002e0067006f006b0072006200350000000000000054004500530054002e0047004f004b005200420035000000",
-	"PAC_Server_Signature":           "100000001e251d98d552be7df384f550",
-	"PAC_KDC_Signature":              "76ffffff340be28b48765d0519ee9346cf53d822",
-	"PAC_Kerb_Validation_Info_Trust": "01100800cccccccc000200000000000000000200c30bcc79e444d301ffffffffffffff7fffffffffffffff7fc764125a0842d301c7247c84d142d301ffffffffffffff7f12001200040002001600160008000200000000000c0002000000000010000200000000001400020000000000180002002e0000005204000001020000030000001c0002002002000000000000000000000000000000000000060008002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000010000002c00020034000200020000003800020009000000000000000900000074006500730074007500730065007200310000000b000000000000000b0000005400650073007400310020005500730065007200310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000056040000070000000102000007000000550400000700000004000000000000000300000055004400430000000500000000000000040000005500530045005200040000000104000000000005150000002057308834e7d1d0a2fb0444010000003000020007000000010000000101000000000012010000000400000001040000000000051500000062dc8db6c8705249b5459e75020000005304000007000020540400000700002000000000",
+	"PAC_AuthorizationData_MS":         "308205523082054ea00402020080a182054404820540040000000000000001000000b004000048000000000000000a00000012000000f804000000000000060000001400000010050000000000000700000014000000280500000000000001100800cccccccca00400000000000000000200d186660f656ac601ffffffffffffff7fffffffffffffff7f17d439fe784ac6011794a328424bc601175424977a81c60108000800040002002400240008000200120012000c0002000000000010000200000000001400020000000000180002005410000097792c00010200001a0000001c000200200000000000000000000000000000000000000016001800200002000a000c002400020028000200000000000000000010000000000000000000000000000000000000000000000000000000000000000d0000002c0002000000000000000000000000000400000000000000040000006c007a00680075001200000000000000120000004c0069007100690061006e00670028004c006100720072007900290020005a00680075000900000000000000090000006e0074006400730032002e0062006100740000000000000000000000000000000000000000000000000000000000000000000000000000001a00000061c433000700000009c32d00070000005eb4320007000000010200000700000097b92c00070000002bf1320007000000ce30330007000000a72e2e00070000002af132000700000098b92c000700000062c4330007000000940133000700000076c4330007000000aefe2d000700000032d22c00070000001608320007000000425b2e00070000005fb4320007000000ca9c35000700000085442d0007000000c2f0320007000000e9ea310007000000ed8e2e0007000000b6eb310007000000ab2e2e0007000000720e2e00070000000c000000000000000b0000004e0054004400450056002d00440043002d003000350000000600000000000000050000004e0054004400450056000000040000000104000000000005150000005951b81766725d2564633b0b0d0000003000020007000000340002000700002038000200070000203c000200070000204000020007000020440002000700002048000200070000204c000200070000205000020007000020540002000700002058000200070000205c00020007000020600002000700002005000000010500000000000515000000b9301b2eb7414c6c8c3b351501020000050000000105000000000005150000005951b81766725d2564633b0b74542f00050000000105000000000005150000005951b81766725d2564633b0be8383200050000000105000000000005150000005951b81766725d2564633b0bcd383200050000000105000000000005150000005951b81766725d2564633b0b5db43200050000000105000000000005150000005951b81766725d2564633b0b41163500050000000105000000000005150000005951b81766725d2564633b0be8ea3100050000000105000000000005150000005951b81766725d2564633b0bc1193200050000000105000000000005150000005951b81766725d2564633b0b29f13200050000000105000000000005150000005951b81766725d2564633b0b0f5f2e00050000000105000000000005150000005951b81766725d2564633b0b2f5b2e00050000000105000000000005150000005951b81766725d2564633b0bef8f3100050000000105000000000005150000005951b81766725d2564633b0b075f2e00000000000049d90e656ac60108006c007a006800750000000000000076ffffff41edce9a34815d3aef7bc98874805d250000000076fffffff7a534dab2c02986efe0fbe5110a4f3200000000",
+	"PAC_Kerb_Validation_Info_MS":      "01100800cccccccca00400000000000000000200d186660f656ac601ffffffffffffff7fffffffffffffff7f17d439fe784ac6011794a328424bc601175424977a81c60108000800040002002400240008000200120012000c0002000000000010000200000000001400020000000000180002005410000097792c00010200001a0000001c000200200000000000000000000000000000000000000016001800200002000a000c002400020028000200000000000000000010000000000000000000000000000000000000000000000000000000000000000d0000002c0002000000000000000000000000000400000000000000040000006c007a00680075001200000000000000120000004c0069007100690061006e00670028004c006100720072007900290020005a00680075000900000000000000090000006e0074006400730032002e0062006100740000000000000000000000000000000000000000000000000000000000000000000000000000001a00000061c433000700000009c32d00070000005eb4320007000000010200000700000097b92c00070000002bf1320007000000ce30330007000000a72e2e00070000002af132000700000098b92c000700000062c4330007000000940133000700000076c4330007000000aefe2d000700000032d22c00070000001608320007000000425b2e00070000005fb4320007000000ca9c35000700000085442d0007000000c2f0320007000000e9ea310007000000ed8e2e0007000000b6eb310007000000ab2e2e0007000000720e2e00070000000c000000000000000b0000004e0054004400450056002d00440043002d003000350000000600000000000000050000004e0054004400450056000000040000000104000000000005150000005951b81766725d2564633b0b0d0000003000020007000000340002000700002038000200070000203c000200070000204000020007000020440002000700002048000200070000204c000200070000205000020007000020540002000700002058000200070000205c00020007000020600002000700002005000000010500000000000515000000b9301b2eb7414c6c8c3b351501020000050000000105000000000005150000005951b81766725d2564633b0b74542f00050000000105000000000005150000005951b81766725d2564633b0be8383200050000000105000000000005150000005951b81766725d2564633b0bcd383200050000000105000000000005150000005951b81766725d2564633b0b5db43200050000000105000000000005150000005951b81766725d2564633b0b41163500050000000105000000000005150000005951b81766725d2564633b0be8ea3100050000000105000000000005150000005951b81766725d2564633b0bc1193200050000000105000000000005150000005951b81766725d2564633b0b29f13200050000000105000000000005150000005951b81766725d2564633b0b0f5f2e00050000000105000000000005150000005951b81766725d2564633b0b2f5b2e00050000000105000000000005150000005951b81766725d2564633b0bef8f3100050000000105000000000005150000005951b81766725d2564633b0b075f2e0000000000",
+	"PAC_AuthorizationData_GOKRB5":     "3082034730820343a003020101a182033a04820336308203323082032ea00402020080a1820324048203200500000000000000010000002802000058000000000000000a0000001c00000080020000000000000c00000058000000a0020000000000000600000010000000f8020000000000000700000014000000080300000000000001100800cccccccc180200000000000000000200058e4fdd80c6d201ffffffffffffff7fffffffffffffff7fcc27969c39c6d201cce7ffc602c7d201ffffffffffffff7f12001200040002001600160008000200000000000c000200000000001000020000000000140002000000000018000200d80000005104000001020000050000001c000200200000000000000000000000000000000000000008000a002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000020000002c00020000000000000000000000000009000000000000000900000074006500730074007500730065007200310000000b000000000000000b000000540065007300740031002000550073006500720031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000102000007000000540400000700000055040000070000005b040000070000005c0400000700000005000000000000000400000041004400440043000500000000000000040000005400450053005400040000000104000000000005150000004c86cebca07160e63fdce8870200000030000200070000203400020007000020050000000105000000000005150000004c86cebca07160e63fdce8875a040000050000000105000000000005150000004c86cebca07160e63fdce8875704000000000000808dd1dc80c6d2011200740065007300740075007300650072003100000000002a001000160040000000000000000000740065007300740075007300650072003100400074006500730074002e0067006f006b0072006200350000000000000054004500530054002e0047004f004b005200420035000000100000001e251d98d552be7df384f55076ffffff340be28b48765d0519ee9346cf53d82200000000",
+	"PAC_AD_WIN2K_PAC":                 "0500000000000000010000002802000058000000000000000a0000001c00000080020000000000000c00000058000000a0020000000000000600000010000000f8020000000000000700000014000000080300000000000001100800cccccccc180200000000000000000200058e4fdd80c6d201ffffffffffffff7fffffffffffffff7fcc27969c39c6d201cce7ffc602c7d201ffffffffffffff7f12001200040002001600160008000200000000000c000200000000001000020000000000140002000000000018000200d80000005104000001020000050000001c000200200000000000000000000000000000000000000008000a002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000020000002c00020000000000000000000000000009000000000000000900000074006500730074007500730065007200310000000b000000000000000b000000540065007300740031002000550073006500720031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000102000007000000540400000700000055040000070000005b040000070000005c0400000700000005000000000000000400000041004400440043000500000000000000040000005400450053005400040000000104000000000005150000004c86cebca07160e63fdce8870200000030000200070000203400020007000020050000000105000000000005150000004c86cebca07160e63fdce8875a040000050000000105000000000005150000004c86cebca07160e63fdce8875704000000000000808dd1dc80c6d2011200740065007300740075007300650072003100000000002a001000160040000000000000000000740065007300740075007300650072003100400074006500730074002e0067006f006b0072006200350000000000000054004500530054002e0047004f004b005200420035000000100000001e251d98d552be7df384f55076ffffff340be28b48765d0519ee9346cf53d82200000000",
+	"PAC_Kerb_Validation_Info":         "01100800cccccccc180200000000000000000200058e4fdd80c6d201ffffffffffffff7fffffffffffffff7fcc27969c39c6d201cce7ffc602c7d201ffffffffffffff7f12001200040002001600160008000200000000000c000200000000001000020000000000140002000000000018000200d80000005104000001020000050000001c000200200000000000000000000000000000000000000008000a002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000020000002c00020000000000000000000000000009000000000000000900000074006500730074007500730065007200310000000b000000000000000b000000540065007300740031002000550073006500720031000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000102000007000000540400000700000055040000070000005b040000070000005c0400000700000005000000000000000400000041004400440043000500000000000000040000005400450053005400040000000104000000000005150000004c86cebca07160e63fdce8870200000030000200070000203400020007000020050000000105000000000005150000004c86cebca07160e63fdce8875a040000050000000105000000000005150000004c86cebca07160e63fdce8875704000000000000",
+	"PAC_Client_Info":                  "808dd1dc80c6d2011200740065007300740075007300650072003100",
+	"PAC_UPN_DNS_Info":                 "2a001000160040000000000000000000740065007300740075007300650072003100400074006500730074002e0067006f006b0072006200350000000000000054004500530054002e0047004f004b005200420035000000",
+	"PAC_Server_Signature":             "100000001e251d98d552be7df384f550",
+	"PAC_KDC_Signature":                "76ffffff340be28b48765d0519ee9346cf53d822",
+	"PAC_Kerb_Validation_Info_Trust":   "01100800cccccccc000200000000000000000200c30bcc79e444d301ffffffffffffff7fffffffffffffff7fc764125a0842d301c7247c84d142d301ffffffffffffff7f12001200040002001600160008000200000000000c0002000000000010000200000000001400020000000000180002002e0000005204000001020000030000001c0002002002000000000000000000000000000000000000060008002000020008000a00240002002800020000000000000000001002000000000000000000000000000000000000000000000000000000000000010000002c00020034000200020000003800020009000000000000000900000074006500730074007500730065007200310000000b000000000000000b0000005400650073007400310020005500730065007200310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000056040000070000000102000007000000550400000700000004000000000000000300000055004400430000000500000000000000040000005500530045005200040000000104000000000005150000002057308834e7d1d0a2fb0444010000003000020007000000010000000101000000000012010000000400000001040000000000051500000062dc8db6c8705249b5459e75020000005304000007000020540400000700002000000000",
+	"PAC_ClientClaimsInfoStr":          "01100800cccccccc000100000000000000000200d80000000400020000000000d8000000000000000000000000000000d800000001100800ccccccccc80000000000000000000200010000000400020000000000000000000000000001000000010000000100000008000200010000000c000200030003000100000010000200290000000000000029000000610064003a002f002f006500780074002f00730041004d004100630063006f0075006e0074004e0061006d0065003a0038003800640035006400390030003800350065006100350063003000630030000000000001000000140002000a000000000000000a00000074006500730074007500730065007200310000000000000000000000",
+	"PAC_ClientClaimsInfoInt":          "01100800cccccccce00000000000000000000200b80000000400020000000000b8000000000000000000000000000000b800000001100800cccccccca80000000000000000000200010000000400020000000000000000000000000001000000010000000100000008000200010000000c0002000100010001000000100002002a000000000000002a000000610064003a002f002f006500780074002f006d007300440053002d0053007500700070006f00720074006500640045003a0038003800640035006400650061003800660031006100660035006600310039000000010000001c0000000000000000000000",
+	"PAC_ClientClaimsInfoMulti":        "01100800cccccccc780100000000000000000200500100000400020000000000500100000000000000000000000000005001000001100800cccccccc400100000000000000000200010000000400020000000000000000000000000001000000010000000200000008000200020000000c000200010001000100000010000200140002000300030001000000180002002a000000000000002a000000610064003a002f002f006500780074002f006d007300440053002d0053007500700070006f00720074006500640045003a0038003800640035006400650061003800660031006100660035006600310039000000010000001c00000000000000290000000000000029000000610064003a002f002f006500780074002f00730041004d004100630063006f0075006e0074004e0061006d0065003a00380038006400350064003900300038003500650061003500630030006300300000000000010000001c0002000a000000000000000a000000740065007300740075007300650072003100000000000000",
+	"PAC_ClientClaimsInfoMultiUint":    "01100800ccccccccf00000000000000000000200c80000000400020000000000c8000000000000000000000000000000c800000001100800ccccccccb80000000000000000000200010000000400020000000000000000000000000001000000010000000100000008000200010000000c000200020002000400000010000200260000000000000026000000610064003a002f002f006500780074002f006f0062006a0065006300740043006c006100730073003a00380038006400350064006500370039003100650037006200320037006500360000000400000009000a000000000007000100000000000600010000000000000001000000000000000000",
+	"PAC_ClientClaimsInfoMultiStr":     "01100800cccccccc480100000000000000000200200100000400020000000000200100000000000000000000000000002001000001100800cccccccc100100000000000000000200010000000400020000000000000000000000000001000000010000000100000008000200010000000c000200030003000400000010000200270000000000000027000000610064003a002f002f006500780074002f006f00740068006500720049007000500068006f006e0065003a003800380064003500640065003900660036006200340061006600390038003500000000000400000014000200180002001c000200200002000500000000000000050000007300740072003100000000000500000000000000050000007300740072003200000000000500000000000000050000007300740072003300000000000500000000000000050000007300740072003400000000000000000000000000",
+	"PAC_ClientClaimsInfo_XPRESS_HUFF": "01100800ccccccccd00100000000000000000200a80100000400020004000000e0010000000000000000000000000000a8010000727807888708080007000800080008000800080880000080870870887807000080800000000080080000080000000000605767070007777707677700770000000000000000000000000000000000000000000000000000000000000000000000000000000000070007000000000000000000000000000000000000000000000076000700700000007600000000000000750700000000000064770700000000007607000000000000060700000000000077060700000000707770700070000770007700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a85652950bb9d8bae030b2212b90df95764d1b182da22f2c848b23b3cc4efc8e3499701e481cf938e490986a384c3d572250aaab2446572fc26be279c263e4a4c9c2c24f9649e2444d8ddb3277373c600363beb73200baaa783da183dd85830af863e1a00d5cf718aac4879519fbf0745bcc59214493a330f940bf99a446f1ade6df2610c5f154b432eaba964d7ad1f1182e522019fc21ce498a204d06b96a476f7386e6003000000000000",
 
 	"ChangePasswdData": "3036a00d040b6e657770617373776f7264a1163014a003020101a10d300b1b09746573747573657231a20d1b0b544553542e474f4b524235",
 	"Kpasswd_Req":      "037aff8002c16e8202bd308202b9a003020105a10302010ea20703050000000000a38201f1618201ed308201e9a003020105a10d1b0b544553542e474f4b524235a21d301ba003020101a11430121b066b61646d696e1b086368616e67657077a38201b2308201aea003020111a103020101a28201a00482019ca3de94df50e8e9fe7a8c9386f594f469bf08874407fc7b95ddcf22110ef63e62ff0ba3c31c3bb725dc1dde1f4c2f69a4973b4b43c9b4b31f71f676d5e8e7b4d7906b1dfacc9897d865b17f934fb96b802344463bb0746fdd39e9e48ff1b2665dc895a74d3d3aac89512b43bd8ead8f455b9b819cc6f6a34fb7c5975d7c2dbd4349524961215b98f33f5747f1e0c89f3b3637462308953940741ab7fc38ae817ba85800dd911bb78b42264f2d285c2a0a33ca21c1a3d281ec14614010db31c3e3f4d4622b799f97b3d31c4445411278fec62dd8e6e349db280aaa4419b53ef6fbc01f0206bcfea2cbe835b46764c03c138722e54dab53a1080e5d6c99f8cd7a948880677176cfc2d3800f9ef64d1ec4f8bdadc1ae409990c4855a82e265682e8ddaa6dea70a1d7855f3e1e766f5efe428dd6da71c585f5d17d8f81e8f2a4f4b2245f5ff2cc444a2a1ae5d16a15d588597219d5659da537f752ca9b572b635088b325b60e8e62fd99487872261f41dcc466516b89992d277bb8b3a1ca770671fca36dd33c3dd6dab643e6710280661029254054273151ccfca9aaddc55a481ae3081aba003020112a103020101a2819e04819be66387f971d751d7d3ebb6acd815a0991e0ed9f07e2643783e7961fb88127b31f767bf00d1d071a81858b101f4d45460412d8013228f942bc51891e95a06aefa8cedd95e5a3e6e65597c0f05c19ee54dc6dc00b1a3f9d7a95516b5e447c40cd5b462ed6b17a007670311efa44dbe939cab11072b9af1443c3203767bb1a3240542db06dffcaebcedd5c335bb295127bc0e6d99f2c1e87f68de1f547581b03081ada003020105a103020115a381a030819da003020112a103020101a2819004818df272b2726c8f31c578f3b4275bc283828716010a20f0c4369bff474fcf202537060a71edcbe8ba720d0d9b2bac26b58353dc5b2945570374928a819eb3526362eda328e704f1a5ebe3272eed0fa6a6aa7d0f32c4fc0bd2e4ea52a8834ea7b5fb018934df87c18ab625f5c07f6c28e202e0cec63bcc37b1d381d64937998c1bdcd1585695eeffb75f8ce9e736b3",
@@ -113,6 +119,7 @@ const (
 	TESTUSER1_PASSWORD            = "passwordvalue"
 	TESTUSER1_KEYTAB              = "05020000003b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d80100110010698c4df8e9f60e7eea5a21bf4526ad25000000010000004b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d80100120020bbdc430aab7e2d4622a0b6951481453b0962e9db8e2f168942ad175cda6d9de9000000010000003b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d80200110010698c4df8e9f60e7eea5a21bf4526ad25000000020000004b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d80200120020bbdc430aab7e2d4622a0b6951481453b0962e9db8e2f168942ad175cda6d9de9000000020000003b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d801001300102eb8501967a7886e1f0c63ac9be8c4a0000000010000003b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d802001300102eb8501967a7886e1f0c63ac9be8c4a0000000020000004b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d801001400208ad66f209bb07daa186f8a229830f5ba06a3a2a33638f4ec66e1d29324e417ee000000010000004b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d802001400208ad66f209bb07daa186f8a229830f5ba06a3a2a33638f4ec66e1d29324e417ee00000002000000430001000b544553542e474f4b52423500097465737475736572310000000159beb1d801001000184580fb91760dabe6f808c22c26494f644cb35d61d32c79e300000001000000430001000b544553542e474f4b52423500097465737475736572310000000159beb1d802001000184580fb91760dabe6f808c22c26494f644cb35d61d32c79e3000000020000003b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d80100170010084768c373663b3bef1f6385883cf7ff000000010000003b0001000b544553542e474f4b52423500097465737475736572310000000159beb1d80200170010084768c373663b3bef1f6385883cf7ff00000002"
 	TESTUSER1_USERKRB5_AD_KEYTAB  = "05020000003b0001000b555345522e474f4b52423500097465737475736572310000000159de7c040100170010084768c373663b3bef1f6385883cf7ff000000010000003b0001000b555345522e474f4b52423500097465737475736572310000000159de7c040100110010528b8ba0ae5131fbf71f6ddc5870cdce000000010000004b0001000b555345522e474f4b52423500097465737475736572310000000159de7c04010012002016475f89eba70e62af20a20e7bf3ca4ccad5ae22485c93ffb133650bc6f12585000000010000003b0001000b555345522e474f4b52423500097465737475736572310000000159de7c040100130010a3ddea306fa06c068bc3e1fcf4b280ca000000010000004b0001000b555345522e474f4b52423500097465737475736572310000000159de7c0401001400205d2a66a8af5142db59bcaabac8310777bf60a85e8881469e2063bba4dff0c00a000000010000003b0001000b555345522e474f4b52423500097465737475736572310000000159de7c040200170010084768c373663b3bef1f6385883cf7ff000000020000003b0001000b555345522e474f4b52423500097465737475736572310000000159de7c040200110010528b8ba0ae5131fbf71f6ddc5870cdce000000020000004b0001000b555345522e474f4b52423500097465737475736572310000000159de7c04020012002016475f89eba70e62af20a20e7bf3ca4ccad5ae22485c93ffb133650bc6f12585000000020000003b0001000b555345522e474f4b52423500097465737475736572310000000159de7c040200130010a3ddea306fa06c068bc3e1fcf4b280ca000000020000004b0001000b555345522e474f4b52423500097465737475736572310000000159de7c0402001400205d2a66a8af5142db59bcaabac8310777bf60a85e8881469e2063bba4dff0c00a00000002"
+	TESTUSER2_USERKRB5_AD_KEYTAB  = "05020000003b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d0100170010084768c373663b3bef1f6385883cf7ff000000010000003b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d0100110010a771a31fae504621fffc644a521e0cee000000010000004b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d01001200203262b201af7ec73c77bbee75a4ff10950cf2bda56529ead30ced4f0f0b9a591d000000010000003b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d01001300104be17a4cf1761f0494475617f671fa6a000000010000004b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d01001400208b1c60589b6c0d78d5e8fe265e92c2babf920a6a2828c37fc343e43497ad9fab000000010000003b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d0200170010084768c373663b3bef1f6385883cf7ff000000020000003b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d0200110010a771a31fae504621fffc644a521e0cee000000020000004b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d02001200203262b201af7ec73c77bbee75a4ff10950cf2bda56529ead30ced4f0f0b9a591d000000020000003b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d02001300104be17a4cf1761f0494475617f671fa6a000000020000004b0001000b555345522e474f4b5242350009746573747573657232000000015b2e4f5d02001400208b1c60589b6c0d78d5e8fe265e92c2babf920a6a2828c37fc343e43497ad9fab00000002"
 	TESTUSER1_WRONGPASSWD         = "0502000000370001000b544553542e474f4b52423500097465737475736572310000000158ef4bc5010011001039a9a382153105f8708e80f93382654e000000470001000b544553542e474f4b52423500097465737475736572310000000158ef4bc60100120020fc5bb940d6075214e0c6fc0456ce68c33306094198a927b4187d7cf3f4aea50d"
 	TESTUSER2_KEYTAB              = "05020000003b0001000b544553542e474f4b52423500097465737475736572320000000159beb240010011001086824c55ff5de30386dd83dc62b44bb7000000010000004b0001000b544553542e474f4b52423500097465737475736572320000000159beb2400100120020d8ed27f96be76fd5b281ee9f8029db93cc5fb06c7eb3be9ee753106d3488fa92000000010000003b0001000b544553542e474f4b52423500097465737475736572320000000159beb240020011001086824c55ff5de30386dd83dc62b44bb7000000020000004b0001000b544553542e474f4b52423500097465737475736572320000000159beb2400200120020d8ed27f96be76fd5b281ee9f8029db93cc5fb06c7eb3be9ee753106d3488fa92000000020000003b0001000b544553542e474f4b52423500097465737475736572320000000159beb24001001300106ccff358aaa8a4a41c444e173b1463c2000000010000003b0001000b544553542e474f4b52423500097465737475736572320000000159beb24002001300106ccff358aaa8a4a41c444e173b1463c2000000020000004b0001000b544553542e474f4b52423500097465737475736572320000000159beb24001001400205cf3773dd920be800229ac1c6f9bf59c6706c583f82c2dea66c9a29152118cd7000000010000004b0001000b544553542e474f4b52423500097465737475736572320000000159beb24002001400205cf3773dd920be800229ac1c6f9bf59c6706c583f82c2dea66c9a29152118cd700000002000000430001000b544553542e474f4b52423500097465737475736572320000000159beb2400100100018bc025746e9e66bd6b62a918f6413d529803192a28aabf79200000001000000430001000b544553542e474f4b52423500097465737475736572320000000159beb2400200100018bc025746e9e66bd6b62a918f6413d529803192a28aabf792000000020000003b0001000b544553542e474f4b52423500097465737475736572320000000159beb2400100170010084768c373663b3bef1f6385883cf7ff000000010000003b0001000b544553542e474f4b52423500097465737475736572320000000159beb2400200170010084768c373663b3bef1f6385883cf7ff00000002"
 	TESTUSER3_KEYTAB              = "05020000003b0001000b544553542e474f4b52423500097465737475736572330000000159beb2740100110010220789f5cf68e44a852c73b1e3729efc000000010000004b0001000b544553542e474f4b52423500097465737475736572330000000159beb27401001200205e1b7287f78f3f88c9eefe92c08ec1613f35d72bc6ee2c2e1c5cb6fb9d8b0580000000010000003b0001000b544553542e474f4b52423500097465737475736572330000000159beb2740200110010220789f5cf68e44a852c73b1e3729efc000000020000004b0001000b544553542e474f4b52423500097465737475736572330000000159beb27402001200205e1b7287f78f3f88c9eefe92c08ec1613f35d72bc6ee2c2e1c5cb6fb9d8b0580000000020000003b0001000b544553542e474f4b52423500097465737475736572330000000159beb2740100130010d2509e2bf9c08f73aafe08745c85e8fd000000010000003b0001000b544553542e474f4b52423500097465737475736572330000000159beb2740200130010d2509e2bf9c08f73aafe08745c85e8fd000000020000004b0001000b544553542e474f4b52423500097465737475736572330000000159beb274010014002060e5e3fb9166db825eb3e4ff4bd1f4307e3f5fe85cdf7faccf8d65330557f74e000000010000004b0001000b544553542e474f4b52423500097465737475736572330000000159beb274020014002060e5e3fb9166db825eb3e4ff4bd1f4307e3f5fe85cdf7faccf8d65330557f74e00000002000000430001000b544553542e474f4b52423500097465737475736572330000000159beb27401001000182cad768989a125fd26f24adf671976456d8097548c4c83f100000001000000430001000b544553542e474f4b52423500097465737475736572330000000159beb27402001000182cad768989a125fd26f24adf671976456d8097548c4c83f1000000020000003b0001000b544553542e474f4b52423500097465737475736572330000000159beb2740100170010084768c373663b3bef1f6385883cf7ff000000010000003b0001000b544553542e474f4b52423500097465737475736572330000000159beb2740200170010084768c373663b3bef1f6385883cf7ff00000002"
diff --git a/testenv/ActiveDirectory.md b/testenv/ActiveDirectory.md
new file mode 100644
index 0000000..318f426
--- /dev/null
+++ b/testenv/ActiveDirectory.md
@@ -0,0 +1,30 @@
+# Active Directory Test Environment Setup Notes
+
+
+## Claims
+* Needs Windows 2012
+### Enable Claims
+* Administrative Tools > Group Policy Management
+  * Forest > Domains > DOMAIN.COM > Default Domain Policy (right click, Edit)
+  * Compute Configuration > Policies > Administrative Templates > System > KDC
+    * Edit "KDC Support for claims"
+    * Set to "Enabled" with the option "Always provide claims"
+    
+### Configure Claims Values
+* Administrative Tools > Active Directory Administrative Center
+  * Dynamic Access Control > Claim Types > New
+
+| Display name | Attribute | Type |
+| -------------|-----------|------|
+| username | sAMAccountName | string |
+| msTSAllowLogon | msTSAllowLogon | boolean |
+| sAMAccountType | sAMAccountType | Integer |
+| objectClass | objectClass | multi-valued unsigned integer |
+| ou | ou | multi-valued string |
+| postalAddress | postalAddress | multi-valued string |
+
+### Inspect Values
+```
+Get-ADUser -Filter 'Name -like "*test*1*" -properties *
+```
+    
\ No newline at end of file