Jonathan Turner 9 éve
szülő
commit
d4a9fae5de

+ 24 - 0
crypto/crypto.go

@@ -166,3 +166,27 @@ func DecryptEncPart(ed types.EncryptedData, key types.EncryptionKey, usage uint3
 	}
 	return b, nil
 }
+
+func DecryptBytes(ed []byte, key types.EncryptionKey, usage uint32) ([]byte, error) {
+	//Derive the key
+	et, err := GetEtype(key.KeyType)
+	k, err := et.DeriveKey(key.KeyValue, engine.GetUsageKe(usage))
+	if err != nil {
+		return nil, fmt.Errorf("Error deriving key: %v", err)
+	}
+	// Strip off the checksum from the end
+	b, err := et.Decrypt(k, ed[:len(ed)-et.GetHMACBitLength()/8])
+	if err != nil {
+		return nil, fmt.Errorf("Error decrypting: %v", err)
+	}
+	//Verify checksum
+	if !et.VerifyIntegrity(key.KeyValue, ed, b, usage) {
+		return nil, errors.New("Error decrypting encrypted part: integrity verification failed")
+	}
+	//Remove the confounder bytes
+	b = b[et.GetConfounderByteSize():]
+	if err != nil {
+		return nil, fmt.Errorf("Error decrypting encrypted part: %v", err)
+	}
+	return b, nil
+}

+ 82 - 3
messages/Ticket.go

@@ -15,6 +15,7 @@ import (
 	"github.com/jcmturner/gokrb5/iana/keyusage"
 	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/pac"
 	"github.com/jcmturner/gokrb5/types"
 	"time"
 )
@@ -186,16 +187,94 @@ func (t *Ticket) DecryptEncPart(keytab keytab.Keytab) error {
 	return nil
 }
 
-func (t *Ticket) GetPACType() (mstypes.PACType, error) {
+func (t *Ticket) GetPACType(key types.EncryptionKey) (mstypes.PACType, error) {
 	for _, ad := range t.DecryptedEncPart.AuthorizationData {
 		if ad.ADType == adtype.AD_IF_RELEVANT {
 			var ad2 types.AuthorizationData
+			err := ad2.Unmarshal(ad.ADData)
+			if err != nil {
+				continue
+			}
 			// TODO note does tthe entry contain and AuthorizationData or AuthorizationDataEntry. Assuming the former atm.
-			if err := ad2.Unmarshal(ad.ADData); err != nil && ad2[0].ADType == adtype.AD_WIN2K_PAC {
+			if ad2[0].ADType == adtype.AD_WIN2K_PAC {
 				var p int
-				return mstypes.Read_PACType(ad2[0].ADData, &p, binary.LittleEndian), nil
+				var endian binary.ByteOrder = binary.LittleEndian
+				pt := mstypes.Read_PACType(&ad2[0].ADData, &p, &endian)
+				err = processAD_PAC(pt, ad2[0].ADData, key)
+				return pt, err
 			}
 		}
 	}
 	return mstypes.PACType{}, errors.New("AuthorizationData within the ticket does not contain PAC data.")
 }
+
+// https://msdn.microsoft.com/en-us/library/cc237954.aspx
+func processAD_PAC(pt mstypes.PACType, b []byte, key types.EncryptionKey) error {
+	for _, buf := range pt.Buffers {
+		p := make([]byte, buf.CBBufferSize, buf.CBBufferSize)
+		copy(p, b[int(buf.Offset):int(buf.Offset)+int(buf.CBBufferSize)])
+		switch int(buf.ULType) {
+		case mstypes.ULTYPE_KERB_VALIDATION_INFO:
+			var k pac.KerbValidationInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_CREDENTIALS:
+			var c pac.PAC_CredentialsInfo
+			err := c.Unmarshal(p, key)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_PAC_SERVER_SIGNATURE_DATA:
+			var k pac.PAC_SignatureData
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_PAC_KDC_SIGNATURE_DATA:
+			var k pac.PAC_SignatureData
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_PAC_CLIENT_INFO:
+			var k pac.PAC_ClientInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_S4U_DELEGATION_INFO:
+			var k pac.S4U_DelegationInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_UPN_DNS_INFO:
+			var k pac.UPN_DNSInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_PAC_CLIENT_CLAIMS_INFO:
+			var k pac.PAC_ClientClaimsInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_PAC_DEVICE_INFO:
+			var k pac.PAC_DeviceInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		case mstypes.ULTYPE_PAC_DEVICE_CLAIMS_INFO:
+			var k pac.PAC_DeviceClaimsInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}

+ 23 - 0
messages/Ticket_test.go

@@ -3,7 +3,9 @@ package messages
 import (
 	"encoding/hex"
 	"fmt"
+	"github.com/jcmturner/gokrb5/iana/adtype"
 	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/jcmturner/gokrb5/types"
 	"github.com/stretchr/testify/assert"
 	"testing"
 	"time"
@@ -111,3 +113,24 @@ func TestMarshalTicket(t *testing.T) {
 	}
 	assert.Equal(t, b, mb, "Marshalled bytes not as expected")
 }
+
+func TestAuthorizationData_GetPACType(t *testing.T) {
+	v := "PAC_AuthorizationData"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	//TODO should the test data need to be wrapped up again?
+	a := types.AuthorizationData{
+		types.AuthorizationDataEntry{
+			ADType: adtype.AD_IF_RELEVANT,
+			ADData: b,
+		},
+	}
+	tkt := Ticket{DecryptedEncPart: EncTicketPart{AuthorizationData: a}}
+	pactype, err := tkt.GetPACType()
+	if err != nil {
+		t.Fatalf("Error getting PAC Type: %v\n", err)
+	}
+	t.Logf("PACType: %+v", pactype)
+}

+ 0 - 24
mstypes/common.go

@@ -1,24 +0,0 @@
-// Microsoft types for Privilege Attribute Certificate (PAC): https://msdn.microsoft.com/en-us/library/cc237928.aspx
-package mstypes
-
-// A BYTE is an 8-bit unsigned value that corresponds to a single octet in a network protocol.
-type Byte uint8
-
-// A ULONG is a 32-bit unsigned integer (range: 0 through 4294967295 decimal).
-// Because a ULONG is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
-type ULong uint32
-
-// A ULONG64 is a 64-bit unsigned integer (range: 0 through 18446744073709551615 decimal).
-// Because a ULONG64 is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
-type ULong64 uint64
-
-// A USHORT is a 16-bit unsigned integer (range: 0 through 65535 decimal).
-// Because a USHORT is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
-type UShort uint16
-
-// A UCHAR is an 8-bit integer with the range: 0 through 255 decimal.
-// Because a UCHAR is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
-type UChar uint8
-
-// A WCHAR is a 16-bit Unicode character.
-type WChar uint16

+ 1 - 1
mstypes/crypto.go

@@ -13,7 +13,7 @@ type UserSessionKey struct {
 	Data []CypherBlock // size = 2
 }
 
-func Read_UserSessionKey(b []byte, p *int, e *binary.ByteOrder) UserSessionKey {
+func Read_UserSessionKey(b *[]byte, p *int, e *binary.ByteOrder) UserSessionKey {
 	cb1 := CypherBlock{
 		Data: ndr.Read_bytes(b, p, 8, e),
 	}

+ 1 - 1
mstypes/filetime.go

@@ -51,7 +51,7 @@ func GetFileTime(t time.Time) FileTime {
 	}
 }
 
-func Read_FileTime(b []byte, p *int, e *binary.ByteOrder) FileTime {
+func Read_FileTime(b *[]byte, p *int, e *binary.ByteOrder) FileTime {
 	l := ndr.Read_uint32(b, p, e)
 	h := ndr.Read_uint32(b, p, e)
 	return FileTime{

+ 2 - 2
mstypes/group_membership.go

@@ -13,7 +13,7 @@ type GroupMembership struct {
 	Attributes uint32
 }
 
-func Read_GroupMembership(b []byte, p *int, e *binary.ByteOrder) GroupMembership {
+func Read_GroupMembership(b *[]byte, p *int, e *binary.ByteOrder) GroupMembership {
 	r := ndr.Read_uint32(b, p, e)
 	a := ndr.Read_uint32(b, p, e)
 	return GroupMembership{
@@ -32,7 +32,7 @@ type DomainGroupMembership struct {
 	GroupIDs   []GroupMembership // Size is value of GroupCount
 }
 
-func Read_DomainGroupMembership(b []byte, p *int, e *binary.ByteOrder) (DomainGroupMembership, error) {
+func Read_DomainGroupMembership(b *[]byte, p *int, e *binary.ByteOrder) (DomainGroupMembership, error) {
 	d, err := Read_RPC_SID(b, p, e)
 	if err != nil {
 		return DomainGroupMembership{}, err

+ 1 - 1
mstypes/kerb_sid_and_attributes.go

@@ -20,7 +20,7 @@ type KerbSidAndAttributes struct {
 	Attributes uint32
 }
 
-func Read_KerbSidAndAttributes(b []byte, p *int, e *binary.ByteOrder) (KerbSidAndAttributes, error) {
+func Read_KerbSidAndAttributes(b *[]byte, p *int, e *binary.ByteOrder) (KerbSidAndAttributes, error) {
 	s, err := Read_RPC_SID(b, p, e)
 	if err != nil {
 		return KerbSidAndAttributes{}, err

+ 0 - 221
mstypes/kerb_validation_info.go

@@ -1,221 +0,0 @@
-package mstypes
-
-import (
-	"errors"
-	"fmt"
-	"github.com/jcmturner/gokrb5/ndr"
-)
-
-const (
-	USERFLAG_GUEST                                    = 31 // Authentication was done via the GUEST account; no password was used.
-	USERFLAG_NO_ENCRYPTION_AVAILABLE                  = 30 // No encryption is available.
-	USERFLAG_LAN_MANAGER_KEY                          = 28 // LAN Manager key was used for authentication.
-	USERFLAG_SUB_AUTH                                 = 25 // Sub-authentication used; session key came from the sub-authentication package.
-	USERFLAG_EXTRA_SIDS                               = 26 // Indicates that the ExtraSids field is populated and contains additional SIDs.
-	USERFLAG_MACHINE_ACCOUNT                          = 24 // Indicates that the account is a machine account.
-	USERFLAG_DC_NTLM2                                 = 23 // Indicates that the domain controller understands NTLMv2.
-	USERFLAG_RESOURCE_GROUPIDS                        = 22 // Indicates that the ResourceGroupIds field is populated.
-	USERFLAG_PROFILEPATH                              = 21 // Indicates that ProfilePath is populated.
-	USERFLAG_NTLM2_NTCHALLENGERESP                    = 20 // The NTLMv2 response from the NtChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and session key generation.
-	USERFLAG_LM2_LMCHALLENGERESP                      = 19 // The LMv2 response from the LmChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and session key generation.
-	USERFLAG_AUTH_LMCHALLENGERESP_KEY_NTCHALLENGERESP = 18 // The LMv2 response from the LmChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and the NTLMv2 response from the NtChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used session key generation.
-)
-
-// https://msdn.microsoft.com/en-us/library/cc237948.aspx
-// The KERB_VALIDATION_INFO structure defines the user's logon and authorization information
-// provided by the DC. The KERB_VALIDATION_INFO structure is a subset of the
-// NETLOGON_VALIDATION_SAM_INFO4 structure ([MS-NRPC] section 2.2.1.4.13).
-// It is a subset due to historical reasons and to the use of the common Active Directory to generate this information.
-// The KERB_VALIDATION_INFO structure is marshaled by RPC [MS-RPCE].
-type KerbValidationInfo struct {
-	LogOnTime               FileTime
-	LogOffTime              FileTime
-	KickOffTime             FileTime
-	PasswordLastSet         FileTime
-	PasswordCanChange       FileTime
-	PasswordMustChange      FileTime
-	EffectiveName           RPC_UnicodeString
-	FullName                RPC_UnicodeString
-	LogonScript             RPC_UnicodeString
-	ProfilePath             RPC_UnicodeString
-	HomeDirectory           RPC_UnicodeString
-	HomeDirectoryDrive      RPC_UnicodeString
-	LogonCount              uint16
-	BadPasswordCount        uint16
-	UserID                  uint32
-	PrimaryGroupID          uint32
-	GroupCount              uint32
-	pGroupIDs               uint32
-	GroupIDs                []GroupMembership
-	UserFlags               uint32
-	UserSessionKey          UserSessionKey
-	LogonServer             RPC_UnicodeString
-	LogonDomainName         RPC_UnicodeString
-	pLogonDomainID          uint32
-	LogonDomainID           RPC_SID
-	Reserved1               []uint32 // Has 2 elements
-	UserAccountControl      uint32
-	SubAuthStatus           uint32
-	LastSuccessfulILogon    FileTime
-	LastFailedILogon        FileTime
-	FailedILogonCount       uint32
-	Reserved3               uint32
-	SIDCount                uint32
-	pExtraSIDs              uint32
-	ExtraSIDs               []KerbSidAndAttributes
-	pResourceGroupDomainSID uint32
-	ResourceGroupDomainSID  RPC_SID
-	ResourceGroupCount      uint32
-	pResourceGroupIDs       uint32
-	ResourceGroupIDs        []GroupMembership
-}
-
-func (k *KerbValidationInfo) ReadFromStream(b []byte) (err error) {
-	ch, p, err := ndr.GetCommonHeader(b)
-	if err != nil {
-		return fmt.Errorf("Error parsing common header: %v", err)
-	}
-	e := &ch.Endianness
-	_, err = ndr.GetPrivateHeader(b, &p, e)
-	if err != nil {
-		return fmt.Errorf("Error parsing private header: %v", err)
-	}
-
-	//The next 4 bytes are an RPC unique pointer referent. We just skip these
-	p += 4
-
-	k.LogOnTime = Read_FileTime(b, &p, e)
-	k.LogOffTime = Read_FileTime(b, &p, e)
-	k.KickOffTime = Read_FileTime(b, &p, e)
-	k.PasswordLastSet = Read_FileTime(b, &p, e)
-	k.PasswordCanChange = Read_FileTime(b, &p, e)
-	k.PasswordMustChange = Read_FileTime(b, &p, e)
-
-	k.EffectiveName, err = Read_RPC_UnicodeString(b, &p, e)
-	k.FullName, err = Read_RPC_UnicodeString(b, &p, e)
-	k.LogonScript, err = Read_RPC_UnicodeString(b, &p, e)
-	k.ProfilePath, err = Read_RPC_UnicodeString(b, &p, e)
-	k.HomeDirectory, err = Read_RPC_UnicodeString(b, &p, e)
-	k.HomeDirectoryDrive, err = Read_RPC_UnicodeString(b, &p, e)
-	if err != nil {
-		return
-	}
-
-	k.LogonCount = ndr.Read_uint16(b, &p, e)
-	k.BadPasswordCount = ndr.Read_uint16(b, &p, e)
-	k.UserID = ndr.Read_uint32(b, &p, e)
-	k.PrimaryGroupID = ndr.Read_uint32(b, &p, e)
-	k.GroupCount = ndr.Read_uint32(b, &p, e)
-	k.pGroupIDs = ndr.Read_uint32(b, &p, e)
-
-	k.UserFlags = ndr.Read_uint32(b, &p, e)
-	k.UserSessionKey = Read_UserSessionKey(b, &p, e)
-
-	k.LogonServer, err = Read_RPC_UnicodeString(b, &p, e)
-	k.LogonDomainName, err = Read_RPC_UnicodeString(b, &p, e)
-	if err != nil {
-		return
-	}
-
-	k.pLogonDomainID = ndr.Read_uint32(b, &p, e)
-
-	k.Reserved1 = []uint32{
-		ndr.Read_uint32(b, &p, e),
-		ndr.Read_uint32(b, &p, e),
-	}
-
-	k.UserAccountControl = ndr.Read_uint32(b, &p, e)
-	k.SubAuthStatus = ndr.Read_uint32(b, &p, e)
-	k.LastSuccessfulILogon = Read_FileTime(b, &p, e)
-	k.LastFailedILogon = Read_FileTime(b, &p, e)
-	k.FailedILogonCount = ndr.Read_uint32(b, &p, e)
-	k.Reserved3 = ndr.Read_uint32(b, &p, e)
-
-	k.SIDCount = ndr.Read_uint32(b, &p, e)
-	k.pExtraSIDs = ndr.Read_uint32(b, &p, e)
-
-	k.pResourceGroupDomainSID = ndr.Read_uint32(b, &p, e)
-	k.ResourceGroupCount = ndr.Read_uint32(b, &p, e)
-	k.pResourceGroupIDs = ndr.Read_uint32(b, &p, e)
-
-	// Populate pointers
-	err = k.EffectiveName.UnmarshalString(b, &p, e)
-	err = k.FullName.UnmarshalString(b, &p, e)
-	err = k.LogonScript.UnmarshalString(b, &p, e)
-	err = k.ProfilePath.UnmarshalString(b, &p, e)
-	err = k.HomeDirectory.UnmarshalString(b, &p, e)
-	err = k.HomeDirectoryDrive.UnmarshalString(b, &p, e)
-
-	if k.GroupCount > 0 {
-		ac := ndr.Read_UniDimensionalConformantArrayHeader(b, &p, e)
-		if ac != int(k.GroupCount) {
-			return errors.New("Error with size of group list")
-		}
-		g := make([]GroupMembership, k.GroupCount, k.GroupCount)
-		for i := range g {
-			g[i] = Read_GroupMembership(b, &p, e)
-		}
-		k.GroupIDs = g
-	}
-
-	err = k.LogonServer.UnmarshalString(b, &p, e)
-	err = k.LogonDomainName.UnmarshalString(b, &p, e)
-
-	//p += 4 //TODO what is this??? SID size
-	k.LogonDomainID, err = Read_RPC_SID(b, &p, e)
-	if err != nil {
-		return err
-	}
-
-	if k.SIDCount > 0 {
-		ac := ndr.Read_UniDimensionalConformantArrayHeader(b, &p, e)
-		if ac != int(k.SIDCount) {
-			return fmt.Errorf("Error with size of ExtraSIDs list. Expected: %d, Actual: %d", k.SIDCount, ac)
-		}
-		es := make([]KerbSidAndAttributes, k.SIDCount, k.SIDCount)
-		attr := make([]uint32, k.SIDCount, k.SIDCount)
-		ptr := make([]uint32, k.SIDCount, k.SIDCount)
-		for i := range attr {
-			ptr[i] = ndr.Read_uint32(b, &p, e)
-			attr[i] = ndr.Read_uint32(b, &p, e)
-		}
-		for i := range es {
-			if ptr[i] != 0 {
-				s, err := Read_RPC_SID(b, &p, e)
-				es[i] = KerbSidAndAttributes{SID: s, Attributes: attr[i]}
-				if err != nil {
-					return ndr.NDRMalformed{EText: fmt.Sprintf("Could not read ExtraSIDs: %v", err)}
-				}
-			}
-		}
-		k.ExtraSIDs = es
-	}
-
-	if k.pResourceGroupDomainSID != 0 {
-		k.ResourceGroupDomainSID, err = Read_RPC_SID(b, &p, e)
-		if err != nil {
-			return err
-		}
-	}
-
-	if k.ResourceGroupCount > 0 {
-		ac := ndr.Read_UniDimensionalConformantArrayHeader(b, &p, e)
-		if ac != int(k.ResourceGroupCount) {
-			return fmt.Errorf("Error with size of ResourceGroup list. Expected: %d, Actual: %d", k.ResourceGroupCount, ac)
-		}
-		g := make([]GroupMembership, ac, ac)
-		for i := range g {
-			g[i] = Read_GroupMembership(b, &p, e)
-		}
-		k.ResourceGroupIDs = g
-	}
-
-	//Check that there is only zero padding left
-	for _, v := range b[p:] {
-		if v != 0 {
-			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
-		}
-	}
-
-	return nil
-}

+ 0 - 33
mstypes/pac_client.go

@@ -1,33 +0,0 @@
-package mstypes
-
-import (
-	"encoding/binary"
-	"github.com/jcmturner/gokrb5/ndr"
-)
-
-// https://msdn.microsoft.com/en-us/library/cc237951.aspx
-type PAC_ClientInfo struct {
-	ClientID   FileTime // A FILETIME structure in little-endian format that contains the Kerberos initial ticket-granting ticket TGT authentication time
-	NameLength uint16   // An unsigned 16-bit integer in little-endian format that specifies the length, in bytes, of the Name field.
-	Name       string   // An array of 16-bit Unicode characters in little-endian format that contains the client's account name.
-}
-
-func Read_PAC_ClientInfo(b []byte, p *int, e *binary.ByteOrder) PAC_ClientInfo {
-	c := Read_FileTime(b, p, e)
-	l := ndr.Read_uint16(b, p, e)
-	s := make([]rune, l, l)
-	for i := 0; i < int(l); i++ {
-		s[i] = rune(ndr.Read_uint16(b, p, e))
-	}
-	return PAC_ClientInfo{
-		ClientID:   c,
-		NameLength: l,
-		Name:       string(s),
-	}
-}
-
-// TODO come back to this struct
-// https://msdn.microsoft.com/en-us/library/hh536365.aspx
-//type PAC_ClientClaimsInfo struct {
-//	Claims ClaimsSetMetadata
-//}

+ 0 - 57
mstypes/pac_device_info.go

@@ -1,57 +0,0 @@
-package mstypes
-
-import (
-	"encoding/binary"
-	"github.com/jcmturner/gokrb5/ndr"
-)
-
-// https://msdn.microsoft.com/en-us/library/hh536402.aspx
-type PAC_DeviceInfo struct {
-	UserID            uint32                  // A 32-bit unsigned integer that contains the RID of the account. If the UserId member equals 0x00000000, the first group SID in this member is the SID for this account.
-	PrimaryGroupID    uint32                  // A 32-bit unsigned integer that contains the RID for the primary group to which this account belongs.
-	AccountDomainID   RPC_SID                 // A SID structure that contains the SID for the domain of the account.This member is used in conjunction with the UserId, and GroupIds members to create the user and group SIDs for the client.
-	AccountGroupCount uint32                  // A 32-bit unsigned integer that contains the number of groups within the account domain to which the account belongs
-	AccountGroupIDs   []GroupMembership       // A pointer to a list of GROUP_MEMBERSHIP (section 2.2.2) structures that contains the groups to which the account belongs in the account domain. The number of groups in this list MUST be equal to GroupCount.
-	SIDCount          uint32                  // A 32-bit unsigned integer that contains the total number of SIDs present in the ExtraSids member.
-	ExtraSIDs         []KerbSidAndAttributes  // A pointer to a list of KERB_SID_AND_ATTRIBUTES structures that contain a list of SIDs corresponding to groups not in domains. If the UserId member equals 0x00000000, the first group SID in this member is the SID for this account.
-	DomainGroupCount  uint32                  // A 32-bit unsigned integer that contains the number of domains with groups to which the account belongs.
-	DomainGroup       []DomainGroupMembership // A pointer to a list of DOMAIN_GROUP_MEMBERSHIP structures (section 2.2.3) that contains the domains to which the account belongs to a group. The number of sets in this list MUST be equal to DomainCount.
-}
-
-func Read_PAC_DeviceInfo(b []byte, p *int, e *binary.ByteOrder) PAC_DeviceInfo {
-	u := ndr.Read_uint32(b, p, e)
-	pg := ndr.Read_uint32(b, p, e)
-	aSid, _ := Read_RPC_SID(b, p, e)
-	c := ndr.Read_uint32(b, p, e)
-	ag := make([]GroupMembership, c, c)
-	for i := range ag {
-		ag[i] = Read_GroupMembership(b, p, e)
-	}
-	sc := ndr.Read_uint32(b, p, e)
-	eSid := make([]KerbSidAndAttributes, sc, sc)
-	for i := range eSid {
-		eSid[i], _ = Read_KerbSidAndAttributes(b, p, e)
-	}
-	dc := ndr.Read_uint32(b, p, e)
-	dg := make([]DomainGroupMembership, dc, dc)
-	for i := range dg {
-		dg[i], _ = Read_DomainGroupMembership(b, p, e)
-	}
-	return PAC_DeviceInfo{
-		UserID:            u,
-		PrimaryGroupID:    pg,
-		AccountDomainID:   aSid,
-		AccountGroupCount: c,
-		AccountGroupIDs:   ag,
-		SIDCount:          sc,
-		ExtraSIDs:         eSid,
-		DomainGroupCount:  dc,
-		DomainGroup:       dg,
-	}
-}
-
-// TODO come back to this struct
-// https://msdn.microsoft.com/en-us/library/hh554226.aspx
-//type PAC_DeviceClaimsInfo struct {
-//	Claims ClaimsSetMetadata
-//}

+ 1 - 1
mstypes/pac_info_buffer.go

@@ -25,7 +25,7 @@ type PACInfoBuffer struct {
 	Offset       uint64 // A 64-bit unsigned integer in little-endian format that contains the offset to the beginning of the buffer, in bytes, from the beginning of the PACTYPE structure. The data offset MUST be a multiple of eight. The following sections specify the format of each type of element.
 }
 
-func Read_PACInfoBuffer(b []byte, p *int, e *binary.ByteOrder) PACInfoBuffer {
+func Read_PACInfoBuffer(b *[]byte, p *int, e *binary.ByteOrder) PACInfoBuffer {
 	u := ndr.Read_uint32(b, p, e)
 	s := ndr.Read_uint32(b, p, e)
 	o := ndr.Read_uint64(b, p, e)

+ 1 - 1
mstypes/pac_type.go

@@ -12,7 +12,7 @@ type PACType struct {
 	Buffers  []PACInfoBuffer // Size 1
 }
 
-func Read_PACType(b []byte, p *int, e *binary.ByteOrder) PACType {
+func Read_PACType(b *[]byte, p *int, e *binary.ByteOrder) PACType {
 	c := ndr.Read_uint32(b, p, e)
 	v := ndr.Read_uint32(b, p, e)
 	buf := make([]PACInfoBuffer, c, c)

+ 2 - 2
mstypes/rpc_unicode_string.go

@@ -13,7 +13,7 @@ type RPC_UnicodeString struct {
 	Value         string
 }
 
-func Read_RPC_UnicodeString(b []byte, p *int, e *binary.ByteOrder) (RPC_UnicodeString, error) {
+func Read_RPC_UnicodeString(b *[]byte, p *int, e *binary.ByteOrder) (RPC_UnicodeString, error) {
 	l := ndr.Read_uint16(b, p, e)
 	ml := ndr.Read_uint16(b, p, e)
 	if ml < l || l%2 != 0 || ml%2 != 0 {
@@ -27,7 +27,7 @@ func Read_RPC_UnicodeString(b []byte, p *int, e *binary.ByteOrder) (RPC_UnicodeS
 	}, nil
 }
 
-func (s *RPC_UnicodeString) UnmarshalString(b []byte, p *int, e *binary.ByteOrder) (err error) {
+func (s *RPC_UnicodeString) UnmarshalString(b *[]byte, p *int, e *binary.ByteOrder) (err error) {
 	s.Value, err = ndr.Read_ConformantVaryingString(b, p, e)
 	return
 }

+ 0 - 27
mstypes/s4u_delegation_info.go

@@ -1,27 +0,0 @@
-package mstypes
-
-import (
-	"encoding/binary"
-	"github.com/jcmturner/gokrb5/ndr"
-)
-
-// https://msdn.microsoft.com/en-us/library/cc237944.aspx
-type S4U_DelegationInfo struct {
-	S4U2proxyTarget      RPC_UnicodeString // The name of the principal to whom the application can forward the ticket.
-	TransitedListSize    uint32
-	S4UTransitedServices []RPC_UnicodeString // List of all services that have been delegated through by this client and subsequent services or servers.. Size is value of TransitedListSize
-}
-
-func Read_S4U_DelegationInfo(b []byte, p *int, e *binary.ByteOrder) S4U_DelegationInfo {
-	pt, _ := Read_RPC_UnicodeString(b, p, e)
-	s := ndr.Read_uint32(b, p, e)
-	ts := make([]RPC_UnicodeString, s, s)
-	for i := range ts {
-		ts[i], _ = Read_RPC_UnicodeString(b, p, e)
-	}
-	return S4U_DelegationInfo{
-		S4U2proxyTarget:      pt,
-		TransitedListSize:    s,
-		S4UTransitedServices: ts,
-	}
-}

+ 3 - 3
mstypes/sid.go

@@ -20,8 +20,8 @@ type RPC_SIDIdentifierAuthority struct {
 	Value []byte // 6 bytes
 }
 
-func Read_RPC_SID(b []byte, p *int, e *binary.ByteOrder) (RPC_SID, error) {
-	size := int(ndr.Read_uint32(b, p, e))
+func Read_RPC_SID(b *[]byte, p *int, e *binary.ByteOrder) (RPC_SID, error) {
+	size := int(ndr.Read_uint32(b, p, e)) // This is part of the NDR encoding rather than the data type.
 	r := ndr.Read_uint8(b, p)
 	if r != uint8(1) {
 		return RPC_SID{}, ndr.NDRMalformed{EText: fmt.Sprintf("SID revision value read as %d when it must be 1", r)}
@@ -43,7 +43,7 @@ func Read_RPC_SID(b []byte, p *int, e *binary.ByteOrder) (RPC_SID, error) {
 	}, nil
 }
 
-func Read_RPC_SIDIdentifierAuthority(b []byte, p *int, e *binary.ByteOrder) RPC_SIDIdentifierAuthority {
+func Read_RPC_SIDIdentifierAuthority(b *[]byte, p *int, e *binary.ByteOrder) RPC_SIDIdentifierAuthority {
 	return RPC_SIDIdentifierAuthority{
 		Value: ndr.Read_bytes(b, p, 6, e),
 	}

+ 59 - 29
ndr/ndr.go

@@ -54,19 +54,31 @@ type PrivateHeader struct {
 	Filler             []byte
 }
 
-func GetCommonHeader(b []byte) (CommonHeader, int, error) {
+func ReadHeaders(b *[]byte) (CommonHeader, PrivateHeader, int, error) {
+	ch, p, err := GetCommonHeader(b)
+	if err != nil {
+		return CommonHeader{}, PrivateHeader{}, 0, err
+	}
+	ph, err := GetPrivateHeader(b, &p, &ch.Endianness)
+	if err != nil {
+		return CommonHeader{}, PrivateHeader{}, 0, err
+	}
+	return ch, ph, p, err
+}
+
+func GetCommonHeader(b *[]byte) (CommonHeader, int, error) {
 	//The first 8 bytes comprise the Common RPC Header for type marshalling.
-	if len(b) < COMMON_HEADER_BYTES {
+	if len(*b) < COMMON_HEADER_BYTES {
 		return CommonHeader{}, 0, NDRMalformed{EText: "Not enough bytes."}
 	}
-	if b[0] != PROTOCOL_VERSION {
+	if (*b)[0] != PROTOCOL_VERSION {
 		return CommonHeader{}, 0, NDRMalformed{EText: fmt.Sprintf("Stream does not indicate a RPC Type serialization of version %v", PROTOCOL_VERSION)}
 	}
-	endian := int(b[1] >> 4 & 0xF)
+	endian := int((*b)[1] >> 4 & 0xF)
 	if endian != 0 && endian != 1 {
 		return CommonHeader{}, 1, NDRMalformed{EText: "Common header does not indicate a valid endianness"}
 	}
-	charEncoding := uint8(b[1] & 0xF)
+	charEncoding := uint8((*b)[1] & 0xF)
 	if charEncoding != 0 && charEncoding != 1 {
 		return CommonHeader{}, 1, NDRMalformed{EText: "Common header does not indicate a valid charater encoding"}
 	}
@@ -77,28 +89,28 @@ func GetCommonHeader(b []byte) (CommonHeader, int, error) {
 	case BIG_ENDIAN:
 		bo = binary.BigEndian
 	}
-	l := bo.Uint16(b[2:4])
+	l := bo.Uint16((*b)[2:4])
 	if l != COMMON_HEADER_BYTES {
-		return CommonHeader{}, 4, NDRMalformed{EText: fmt.Sprintf("Common header does not indicate a valid length: %v instead of %v", uint8(b[3]), COMMON_HEADER_BYTES)}
+		return CommonHeader{}, 4, NDRMalformed{EText: fmt.Sprintf("Common header does not indicate a valid length: %v instead of %v", uint8((*b)[3]), COMMON_HEADER_BYTES)}
 	}
 
 	return CommonHeader{
-		Version:           uint8(b[0]),
+		Version:           uint8((*b)[0]),
 		Endianness:        bo,
 		CharacterEncoding: charEncoding,
 		//FloatRepresentation: uint8(b[2]),
 		HeaderLength: l,
-		Filler:       b[4:8],
+		Filler:       (*b)[4:8],
 	}, 8, nil
 }
 
-func GetPrivateHeader(b []byte, p *int, bo *binary.ByteOrder) (PrivateHeader, error) {
+func GetPrivateHeader(b *[]byte, p *int, bo *binary.ByteOrder) (PrivateHeader, error) {
 	//The next 8 bytes comprise the RPC type marshalling private header for constructed types.
-	if len(b) < (PRIVATE_HEADER_BYTES) {
+	if len(*b) < (PRIVATE_HEADER_BYTES) {
 		return PrivateHeader{}, NDRMalformed{EText: "Not enough bytes."}
 	}
 	var l uint32
-	buf := bytes.NewBuffer(b[*p : *p+4])
+	buf := bytes.NewBuffer((*b)[*p : *p+4])
 	binary.Read(buf, *bo, &l)
 	if l%8 != 0 {
 		return PrivateHeader{}, NDRMalformed{EText: "Object buffer length not a multiple of 8"}
@@ -106,63 +118,81 @@ func GetPrivateHeader(b []byte, p *int, bo *binary.ByteOrder) (PrivateHeader, er
 	*p += 8
 	return PrivateHeader{
 		ObjectBufferLength: l,
-		Filler:             b[4:8],
+		Filler:             (*b)[4:8],
 	}, nil
 }
 
 // Read bytes representing a thirty two bit integer.
-func Read_uint8(b []byte, p *int) (i uint8) {
+func Read_uint8(b *[]byte, p *int) (i uint8) {
+	if len((*b)[*p:]) < 1 {
+		return
+	}
 	ensureAlignment(p, 1)
-	i = uint8(b[*p])
+	i = uint8((*b)[*p])
 	*p += 1
 	return
 }
 
 // Read bytes representing a thirty two bit integer.
-func Read_uint16(b []byte, p *int, e *binary.ByteOrder) (i uint16) {
+func Read_uint16(b *[]byte, p *int, e *binary.ByteOrder) (i uint16) {
+	if len((*b)[*p:]) < 2 {
+		return
+	}
 	ensureAlignment(p, 2)
-	i = (*e).Uint16(b[*p : *p+2])
+	i = (*e).Uint16((*b)[*p : *p+2])
 	*p += 2
 	return
 }
 
 // Read bytes representing a thirty two bit integer.
-func Read_uint32(b []byte, p *int, e *binary.ByteOrder) (i uint32) {
+func Read_uint32(b *[]byte, p *int, e *binary.ByteOrder) (i uint32) {
+	if len((*b)[*p:]) < 4 {
+		return
+	}
 	ensureAlignment(p, 4)
-	i = (*e).Uint32(b[*p : *p+4])
+	i = (*e).Uint32((*b)[*p : *p+4])
 	*p += 4
 	return
 }
 
 // Read bytes representing a thirty two bit integer.
-func Read_uint64(b []byte, p *int, e *binary.ByteOrder) (i uint64) {
+func Read_uint64(b *[]byte, p *int, e *binary.ByteOrder) (i uint64) {
+	if len((*b)[*p:]) < 8 {
+		return
+	}
 	ensureAlignment(p, 8)
-	i = (*e).Uint64(b[*p : *p+8])
+	i = (*e).Uint64((*b)[*p : *p+8])
 	*p += 8
 	return
 }
 
-func Read_bytes(b []byte, p *int, s int, e *binary.ByteOrder) []byte {
-	buf := bytes.NewBuffer(b[*p : *p+s])
-	r := make([]byte, s)
+func Read_bytes(b *[]byte, p *int, s int, e *binary.ByteOrder) (r []byte) {
+	if len((*b)[*p:]) < s {
+		return
+	}
+	buf := bytes.NewBuffer((*b)[*p : *p+s])
+	r = make([]byte, s)
 	binary.Read(buf, *e, &r)
 	*p += s
 	return r
 }
 
-func Read_bool(b []byte, p *int) bool {
+func Read_bool(b *[]byte, p *int) bool {
+	if len((*b)[*p:]) < 1 {
+		return false
+	}
 	if Read_uint8(b, p) != 0 {
 		return true
 	}
 	return false
 }
 
-func Read_IEEEfloat32(b []byte, p *int, e *binary.ByteOrder) float32 {
+func Read_IEEEfloat32(b *[]byte, p *int, e *binary.ByteOrder) float32 {
 	ensureAlignment(p, 4)
 	return math.Float32frombits(Read_uint32(b, p, e))
 }
 
-func Read_IEEEfloat64(b []byte, p *int, e *binary.ByteOrder) float64 {
+func Read_IEEEfloat64(b *[]byte, p *int, e *binary.ByteOrder) float64 {
 	ensureAlignment(p, 8)
 	return math.Float64frombits(Read_uint64(b, p, e))
 }
@@ -173,7 +203,7 @@ func Read_IEEEfloat64(b []byte, p *int, e *binary.ByteOrder) float64 {
 // The first integer gives the maximum number of elements in the string, including the terminator.
 // The second integer gives the offset from the first index of the string to the first index of the actual subset being passed.
 // The third integer gives the actual number of elements being passed, including the terminator.
-func Read_ConformantVaryingString(b []byte, p *int, e *binary.ByteOrder) (string, error) {
+func Read_ConformantVaryingString(b *[]byte, p *int, e *binary.ByteOrder) (string, error) {
 	m := Read_uint32(b, p, e) // Max element count
 	o := Read_uint32(b, p, e) // Offset
 	a := Read_uint32(b, p, e) // Actual count
@@ -193,7 +223,7 @@ func Read_ConformantVaryingString(b []byte, p *int, e *binary.ByteOrder) (string
 	return string(s), nil
 }
 
-func Read_UniDimensionalConformantArrayHeader(b []byte, p *int, e *binary.ByteOrder) int {
+func Read_UniDimensionalConformantArrayHeader(b *[]byte, p *int, e *binary.ByteOrder) int {
 	return int(Read_uint32(b, p, e))
 }
 

+ 219 - 0
pac/kerb_validation_info.go

@@ -0,0 +1,219 @@
+package pac
+
+import (
+	"errors"
+	"fmt"
+	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+const (
+	USERFLAG_GUEST                                    = 31 // Authentication was done via the GUEST account; no password was used.
+	USERFLAG_NO_ENCRYPTION_AVAILABLE                  = 30 // No encryption is available.
+	USERFLAG_LAN_MANAGER_KEY                          = 28 // LAN Manager key was used for authentication.
+	USERFLAG_SUB_AUTH                                 = 25 // Sub-authentication used; session key came from the sub-authentication package.
+	USERFLAG_EXTRA_SIDS                               = 26 // Indicates that the ExtraSids field is populated and contains additional SIDs.
+	USERFLAG_MACHINE_ACCOUNT                          = 24 // Indicates that the account is a machine account.
+	USERFLAG_DC_NTLM2                                 = 23 // Indicates that the domain controller understands NTLMv2.
+	USERFLAG_RESOURCE_GROUPIDS                        = 22 // Indicates that the ResourceGroupIds field is populated.
+	USERFLAG_PROFILEPATH                              = 21 // Indicates that ProfilePath is populated.
+	USERFLAG_NTLM2_NTCHALLENGERESP                    = 20 // The NTLMv2 response from the NtChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and session key generation.
+	USERFLAG_LM2_LMCHALLENGERESP                      = 19 // The LMv2 response from the LmChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and session key generation.
+	USERFLAG_AUTH_LMCHALLENGERESP_KEY_NTCHALLENGERESP = 18 // The LMv2 response from the LmChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used for authentication and the NTLMv2 response from the NtChallengeResponseFields ([MS-NLMP] section 2.2.1.3) was used session key generation.
+)
+
+// https://msdn.microsoft.com/en-us/library/cc237948.aspx
+// The KERB_VALIDATION_INFO structure defines the user's logon and authorization information
+// provided by the DC. The KERB_VALIDATION_INFO structure is a subset of the
+// NETLOGON_VALIDATION_SAM_INFO4 structure ([MS-NRPC] section 2.2.1.4.13).
+// It is a subset due to historical reasons and to the use of the common Active Directory to generate this information.
+// The KERB_VALIDATION_INFO structure is marshaled by RPC [MS-RPCE].
+type KerbValidationInfo struct {
+	LogOnTime               mstypes.FileTime
+	LogOffTime              mstypes.FileTime
+	KickOffTime             mstypes.FileTime
+	PasswordLastSet         mstypes.FileTime
+	PasswordCanChange       mstypes.FileTime
+	PasswordMustChange      mstypes.FileTime
+	EffectiveName           mstypes.RPC_UnicodeString
+	FullName                mstypes.RPC_UnicodeString
+	LogonScript             mstypes.RPC_UnicodeString
+	ProfilePath             mstypes.RPC_UnicodeString
+	HomeDirectory           mstypes.RPC_UnicodeString
+	HomeDirectoryDrive      mstypes.RPC_UnicodeString
+	LogonCount              uint16
+	BadPasswordCount        uint16
+	UserID                  uint32
+	PrimaryGroupID          uint32
+	GroupCount              uint32
+	pGroupIDs               uint32
+	GroupIDs                []mstypes.GroupMembership
+	UserFlags               uint32
+	UserSessionKey          mstypes.UserSessionKey
+	LogonServer             mstypes.RPC_UnicodeString
+	LogonDomainName         mstypes.RPC_UnicodeString
+	pLogonDomainID          uint32
+	LogonDomainID           mstypes.RPC_SID
+	Reserved1               []uint32 // Has 2 elements
+	UserAccountControl      uint32
+	SubAuthStatus           uint32
+	LastSuccessfulILogon    mstypes.FileTime
+	LastFailedILogon        mstypes.FileTime
+	FailedILogonCount       uint32
+	Reserved3               uint32
+	SIDCount                uint32
+	pExtraSIDs              uint32
+	ExtraSIDs               []mstypes.KerbSidAndAttributes
+	pResourceGroupDomainSID uint32
+	ResourceGroupDomainSID  mstypes.RPC_SID
+	ResourceGroupCount      uint32
+	pResourceGroupIDs       uint32
+	ResourceGroupIDs        []mstypes.GroupMembership
+}
+
+func (k *KerbValidationInfo) Unmarshal(b []byte) (err 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
+
+	k.LogOnTime = mstypes.Read_FileTime(&b, &p, e)
+	k.LogOffTime = mstypes.Read_FileTime(&b, &p, e)
+	k.KickOffTime = mstypes.Read_FileTime(&b, &p, e)
+	k.PasswordLastSet = mstypes.Read_FileTime(&b, &p, e)
+	k.PasswordCanChange = mstypes.Read_FileTime(&b, &p, e)
+	k.PasswordMustChange = mstypes.Read_FileTime(&b, &p, e)
+
+	k.EffectiveName, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	k.FullName, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	k.LogonScript, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	k.ProfilePath, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	k.HomeDirectory, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	k.HomeDirectoryDrive, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	if err != nil {
+		return
+	}
+
+	k.LogonCount = ndr.Read_uint16(&b, &p, e)
+	k.BadPasswordCount = ndr.Read_uint16(&b, &p, e)
+	k.UserID = ndr.Read_uint32(&b, &p, e)
+	k.PrimaryGroupID = ndr.Read_uint32(&b, &p, e)
+	k.GroupCount = ndr.Read_uint32(&b, &p, e)
+	k.pGroupIDs = ndr.Read_uint32(&b, &p, e)
+
+	k.UserFlags = ndr.Read_uint32(&b, &p, e)
+	k.UserSessionKey = mstypes.Read_UserSessionKey(&b, &p, e)
+
+	k.LogonServer, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	k.LogonDomainName, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	if err != nil {
+		return
+	}
+
+	k.pLogonDomainID = ndr.Read_uint32(&b, &p, e)
+
+	k.Reserved1 = []uint32{
+		ndr.Read_uint32(&b, &p, e),
+		ndr.Read_uint32(&b, &p, e),
+	}
+
+	k.UserAccountControl = ndr.Read_uint32(&b, &p, e)
+	k.SubAuthStatus = ndr.Read_uint32(&b, &p, e)
+	k.LastSuccessfulILogon = mstypes.Read_FileTime(&b, &p, e)
+	k.LastFailedILogon = mstypes.Read_FileTime(&b, &p, e)
+	k.FailedILogonCount = ndr.Read_uint32(&b, &p, e)
+	k.Reserved3 = ndr.Read_uint32(&b, &p, e)
+
+	k.SIDCount = ndr.Read_uint32(&b, &p, e)
+	k.pExtraSIDs = ndr.Read_uint32(&b, &p, e)
+
+	k.pResourceGroupDomainSID = ndr.Read_uint32(&b, &p, e)
+	k.ResourceGroupCount = ndr.Read_uint32(&b, &p, e)
+	k.pResourceGroupIDs = ndr.Read_uint32(&b, &p, e)
+
+	// Populate pointers
+	err = k.EffectiveName.UnmarshalString(&b, &p, e)
+	err = k.FullName.UnmarshalString(&b, &p, e)
+	err = k.LogonScript.UnmarshalString(&b, &p, e)
+	err = k.ProfilePath.UnmarshalString(&b, &p, e)
+	err = k.HomeDirectory.UnmarshalString(&b, &p, e)
+	err = k.HomeDirectoryDrive.UnmarshalString(&b, &p, e)
+
+	if k.GroupCount > 0 {
+		ac := ndr.Read_UniDimensionalConformantArrayHeader(&b, &p, e)
+		if ac != int(k.GroupCount) {
+			return errors.New("Error with size of group list")
+		}
+		g := make([]mstypes.GroupMembership, k.GroupCount, k.GroupCount)
+		for i := range g {
+			g[i] = mstypes.Read_GroupMembership(&b, &p, e)
+		}
+		k.GroupIDs = g
+	}
+
+	err = k.LogonServer.UnmarshalString(&b, &p, e)
+	err = k.LogonDomainName.UnmarshalString(&b, &p, e)
+
+	if k.pLogonDomainID != 0 {
+		k.LogonDomainID, err = mstypes.Read_RPC_SID(&b, &p, e)
+		if err != nil {
+			return fmt.Errorf("Error reading LogonDomainID: %v", err)
+		}
+	}
+
+	if k.SIDCount > 0 {
+		ac := ndr.Read_UniDimensionalConformantArrayHeader(&b, &p, e)
+		if ac != int(k.SIDCount) {
+			return fmt.Errorf("Error with size of ExtraSIDs list. Expected: %d, Actual: %d", k.SIDCount, ac)
+		}
+		es := make([]mstypes.KerbSidAndAttributes, k.SIDCount, k.SIDCount)
+		attr := make([]uint32, k.SIDCount, k.SIDCount)
+		ptr := make([]uint32, k.SIDCount, k.SIDCount)
+		for i := range attr {
+			ptr[i] = ndr.Read_uint32(&b, &p, e)
+			attr[i] = ndr.Read_uint32(&b, &p, e)
+		}
+		for i := range es {
+			if ptr[i] != 0 {
+				s, err := mstypes.Read_RPC_SID(&b, &p, e)
+				es[i] = mstypes.KerbSidAndAttributes{SID: s, Attributes: attr[i]}
+				if err != nil {
+					return ndr.NDRMalformed{EText: fmt.Sprintf("Could not read ExtraSIDs: %v", err)}
+				}
+			}
+		}
+		k.ExtraSIDs = es
+	}
+
+	if k.pResourceGroupDomainSID != 0 {
+		k.ResourceGroupDomainSID, err = mstypes.Read_RPC_SID(&b, &p, e)
+		if err != nil {
+			return err
+		}
+	}
+
+	if k.ResourceGroupCount > 0 {
+		ac := ndr.Read_UniDimensionalConformantArrayHeader(&b, &p, e)
+		if ac != int(k.ResourceGroupCount) {
+			return fmt.Errorf("Error with size of ResourceGroup list. Expected: %d, Actual: %d", k.ResourceGroupCount, ac)
+		}
+		g := make([]mstypes.GroupMembership, ac, ac)
+		for i := range g {
+			g[i] = mstypes.Read_GroupMembership(&b, &p, e)
+		}
+		k.ResourceGroupIDs = g
+	}
+
+	//Check that there is only zero padding left
+	for _, v := range b[p:] {
+		if v != 0 {
+			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
+		}
+	}
+
+	return nil
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 11 - 0
pac/kerb_validation_info_test.go


+ 48 - 0
pac/pac_client.go

@@ -0,0 +1,48 @@
+package pac
+
+import (
+	"fmt"
+	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+// https://msdn.microsoft.com/en-us/library/cc237951.aspx
+type PAC_ClientInfo struct {
+	ClientID   mstypes.FileTime // A FILETIME structure in little-endian format that contains the Kerberos initial ticket-granting ticket TGT authentication time
+	NameLength uint16           // An unsigned 16-bit integer in little-endian format that specifies the length, in bytes, of the Name field.
+	Name       string           // An array of 16-bit Unicode characters in little-endian format that contains the client's account name.
+}
+
+func (k *PAC_ClientInfo) Unmarshal(b []byte) 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
+
+	k.ClientID = mstypes.Read_FileTime(&b, &p, e)
+	k.NameLength = ndr.Read_uint16(&b, &p, e)
+	s := make([]rune, k.NameLength, k.NameLength)
+	for i := 0; i < len(s); i++ {
+		s[i] = rune(ndr.Read_uint16(&b, &p, e))
+	}
+	k.Name = string(s)
+
+	//Check that there is only zero padding left
+	for _, v := range b[p:] {
+		if v != 0 {
+			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
+		}
+	}
+
+	return nil
+}
+
+// TODO come back to this struct
+// https://msdn.microsoft.com/en-us/library/hh536365.aspx
+//type PAC_ClientClaimsInfo struct {
+//	Claims ClaimsSetMetadata
+//}

+ 44 - 15
mstypes/pac_credentials.go → pac/pac_credentials.go

@@ -1,29 +1,58 @@
-package mstypes
+package pac
 
 import (
 	"encoding/binary"
+	"fmt"
+	"github.com/jcmturner/gokrb5/crypto"
+	"github.com/jcmturner/gokrb5/iana/keyusage"
+	"github.com/jcmturner/gokrb5/mstypes"
 	"github.com/jcmturner/gokrb5/ndr"
+	"github.com/jcmturner/gokrb5/types"
 )
 
 // https://msdn.microsoft.com/en-us/library/cc237931.aspx
 
-//https://msdn.microsoft.com/en-us/library/cc237953.aspx
+// https://msdn.microsoft.com/en-us/library/cc237953.aspx
 type PAC_CredentialsInfo struct {
 	Version                      uint32 // A 32-bit unsigned integer in little-endian format that defines the version. MUST be 0x00000000.
 	EType                        uint32
 	PAC_CredentialData_Encrypted []byte // Key usage number for encryption: KERB_NON_KERB_SALT (16)
+	PAC_CredentialData           PAC_CredentialData
 }
 
-func Read_PAC_CredentialsInfo(b []byte, p *int, e *binary.ByteOrder) PAC_CredentialsInfo {
-	v := ndr.Read_uint32(b, p, e)
-	et := ndr.Read_uint32(b, p, e)
+func (c *PAC_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
+
+	c.Version = ndr.Read_uint32(&b, &p, e)
+	c.EType = ndr.Read_uint32(&b, &p, e)
 	// TODO review bytes provided to this method as we have to read to the end
-	d := ndr.Read_bytes(b, p, len(b)-*p, e)
-	return PAC_CredentialsInfo{
-		Version: v,
-		EType:   et,
-		PAC_CredentialData_Encrypted: d,
+	c.PAC_CredentialData_Encrypted = ndr.Read_bytes(&b, &p, len(b)-p, e)
+
+	err = c.DecryptEncPart(k, e)
+	if err != nil {
+		return fmt.Errorf("Error decrypting PAC Credentials Data: %v", err)
+	}
+	return nil
+}
+
+func (c *PAC_CredentialsInfo) DecryptEncPart(k types.EncryptionKey, e *binary.ByteOrder) error {
+	if k.KeyType != int(c.EType) {
+		return fmt.Errorf("Key provided is not the correct type. Type needed: %d, type provided: %d", c.EType, k.KeyType)
+	}
+	pt, err := crypto.DecryptBytes(c.PAC_CredentialData_Encrypted, k, keyusage.KERB_NON_KERB_SALT)
+	if err != nil {
+		return err
 	}
+	var p int
+	c.PAC_CredentialData = Read_PAC_CredentialData(&pt, &p, e)
+	return nil
 }
 
 // https://msdn.microsoft.com/en-us/library/cc237952.aspx
@@ -36,7 +65,7 @@ type PAC_CredentialData struct {
 	Credentials     []SECPKG_SupplementalCred // Size is the value of CredentialCount
 }
 
-func Read_PAC_CredentialData(b []byte, p *int, e *binary.ByteOrder) PAC_CredentialData {
+func Read_PAC_CredentialData(b *[]byte, p *int, e *binary.ByteOrder) PAC_CredentialData {
 	c := ndr.Read_uint32(b, p, e)
 	cr := make([]SECPKG_SupplementalCred, c, c)
 	for i := range cr {
@@ -50,13 +79,13 @@ func Read_PAC_CredentialData(b []byte, p *int, e *binary.ByteOrder) PAC_Credenti
 
 // https://msdn.microsoft.com/en-us/library/cc237956.aspx
 type SECPKG_SupplementalCred struct {
-	PackageName    RPC_UnicodeString
+	PackageName    mstypes.RPC_UnicodeString
 	CredentialSize uint32
 	Credentials    []uint8 // Is a ptr. Size is the value of CredentialSize
 }
 
-func Read_SECPKG_SupplementalCred(b []byte, p *int, e *binary.ByteOrder) SECPKG_SupplementalCred {
-	n, _ := Read_RPC_UnicodeString(b, p, e)
+func Read_SECPKG_SupplementalCred(b *[]byte, p *int, e *binary.ByteOrder) SECPKG_SupplementalCred {
+	n, _ := mstypes.Read_RPC_UnicodeString(b, p, e)
 	cs := ndr.Read_uint32(b, p, e)
 	c := make([]uint8, cs, cs)
 	for i := range c {
@@ -77,7 +106,7 @@ type NTLM_SupplementalCred struct {
 	NTPassword []byte // A 16-element array of unsigned 8-bit integers that define the NT OWF. The LtPassword member MUST be ignored if the N flag is not set in the Flags member.
 }
 
-func Read_NTLM_SupplementalCred(b []byte, p *int, e *binary.ByteOrder) NTLM_SupplementalCred {
+func Read_NTLM_SupplementalCred(b *[]byte, p *int, e *binary.ByteOrder) NTLM_SupplementalCred {
 	v := ndr.Read_uint32(b, p, e)
 	f := ndr.Read_uint32(b, p, e)
 	l := ndr.Read_bytes(b, p, 16, e)

+ 95 - 0
pac/pac_device_info.go

@@ -0,0 +1,95 @@
+package pac
+
+import (
+	"fmt"
+	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+// https://msdn.microsoft.com/en-us/library/hh536402.aspx
+type PAC_DeviceInfo struct {
+	UserID            uint32                          // A 32-bit unsigned integer that contains the RID of the account. If the UserId member equals 0x00000000, the first group SID in this member is the SID for this account.
+	PrimaryGroupID    uint32                          // A 32-bit unsigned integer that contains the RID for the primary group to which this account belongs.
+	AccountDomainID   mstypes.RPC_SID                 // A SID structure that contains the SID for the domain of the account.This member is used in conjunction with the UserId, and GroupIds members to create the user and group SIDs for the client.
+	AccountGroupCount uint32                          // A 32-bit unsigned integer that contains the number of groups within the account domain to which the account belongs
+	AccountGroupIDs   []mstypes.GroupMembership       // A pointer to a list of GROUP_MEMBERSHIP (section 2.2.2) structures that contains the groups to which the account belongs in the account domain. The number of groups in this list MUST be equal to GroupCount.
+	SIDCount          uint32                          // A 32-bit unsigned integer that contains the total number of SIDs present in the ExtraSids member.
+	ExtraSIDs         []mstypes.KerbSidAndAttributes  // A pointer to a list of KERB_SID_AND_ATTRIBUTES structures that contain a list of SIDs corresponding to groups not in domains. If the UserId member equals 0x00000000, the first group SID in this member is the SID for this account.
+	DomainGroupCount  uint32                          // A 32-bit unsigned integer that contains the number of domains with groups to which the account belongs.
+	DomainGroup       []mstypes.DomainGroupMembership // A pointer to a list of DOMAIN_GROUP_MEMBERSHIP structures (section 2.2.3) that contains the domains to which the account belongs to a group. The number of sets in this list MUST be equal to DomainCount.
+}
+
+func (k *PAC_DeviceInfo) Unmarshal(b []byte) 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
+
+	k.UserID = ndr.Read_uint32(&b, &p, e)
+	k.PrimaryGroupID = ndr.Read_uint32(&b, &p, e)
+	k.AccountDomainID, err = mstypes.Read_RPC_SID(&b, &p, e)
+	if err != nil {
+		return err
+	}
+	k.AccountGroupCount = ndr.Read_uint32(&b, &p, e)
+	if k.AccountGroupCount > 0 {
+		ag := make([]mstypes.GroupMembership, k.AccountGroupCount, k.AccountGroupCount)
+		for i := range ag {
+			ag[i] = mstypes.Read_GroupMembership(&b, &p, e)
+		}
+		k.AccountGroupIDs = ag
+	}
+
+	k.SIDCount = ndr.Read_uint32(&b, &p, e)
+	if k.SIDCount > 0 {
+		ac := ndr.Read_UniDimensionalConformantArrayHeader(&b, &p, e)
+		if ac != int(k.SIDCount) {
+			return fmt.Errorf("Error with size of ExtraSIDs list. Expected: %d, Actual: %d", k.SIDCount, ac)
+		}
+		es := make([]mstypes.KerbSidAndAttributes, k.SIDCount, k.SIDCount)
+		attr := make([]uint32, k.SIDCount, k.SIDCount)
+		ptr := make([]uint32, k.SIDCount, k.SIDCount)
+		for i := range attr {
+			ptr[i] = ndr.Read_uint32(&b, &p, e)
+			attr[i] = ndr.Read_uint32(&b, &p, e)
+		}
+		for i := range es {
+			if ptr[i] != 0 {
+				s, err := mstypes.Read_RPC_SID(&b, &p, e)
+				es[i] = mstypes.KerbSidAndAttributes{SID: s, Attributes: attr[i]}
+				if err != nil {
+					return ndr.NDRMalformed{EText: fmt.Sprintf("Could not read ExtraSIDs: %v", err)}
+				}
+			}
+		}
+		k.ExtraSIDs = es
+	}
+
+	k.DomainGroupCount = ndr.Read_uint32(&b, &p, e)
+	if k.DomainGroupCount > 0 {
+		dg := make([]mstypes.DomainGroupMembership, k.DomainGroupCount, k.DomainGroupCount)
+		for i := range dg {
+			dg[i], _ = mstypes.Read_DomainGroupMembership(&b, &p, e)
+		}
+		k.DomainGroup = dg
+	}
+
+	//Check that there is only zero padding left
+	for _, v := range b[p:] {
+		if v != 0 {
+			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
+		}
+	}
+
+	return nil
+}
+
+// TODO come back to this struct
+// https://msdn.microsoft.com/en-us/library/hh554226.aspx
+//type PAC_DeviceClaimsInfo struct {
+//	Claims ClaimsSetMetadata
+//}

+ 24 - 11
mstypes/pac_signature_data.go → pac/pac_signature_data.go

@@ -1,7 +1,7 @@
-package mstypes
+package pac
 
 import (
-	"encoding/binary"
+	"fmt"
 	"github.com/jcmturner/gokrb5/iana/chksumtype"
 	"github.com/jcmturner/gokrb5/ndr"
 )
@@ -36,10 +36,19 @@ type PAC_SignatureData struct {
 	RODCIdentifier uint16 // A 16-bit unsigned integer value in little-endian format that contains the first 16 bits of the key version number ([MS-KILE] section 3.1.5.8) when the KDC is an RODC. When the KDC is not an RODC, this field does not exist.
 }
 
-func Read_PAC_SignatureData(b []byte, p *int, e *binary.ByteOrder) PAC_SignatureData {
-	t := ndr.Read_uint32(b, p, e)
+func (k *PAC_SignatureData) Unmarshal(b []byte) 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
+
+	k.SignatureType = ndr.Read_uint32(&b, &p, e)
 	var c int
-	switch t {
+	switch k.SignatureType {
 	case chksumtype.KERB_CHECKSUM_HMAC_MD5:
 		c = 16
 	case chksumtype.HMAC_SHA1_96_AES128:
@@ -47,11 +56,15 @@ func Read_PAC_SignatureData(b []byte, p *int, e *binary.ByteOrder) PAC_Signature
 	case chksumtype.HMAC_SHA1_96_AES256:
 		c = 12
 	}
-	s := ndr.Read_bytes(b, p, c, e)
-	r := ndr.Read_uint16(b, p, e)
-	return PAC_SignatureData{
-		SignatureType:  t,
-		Signature:      s,
-		RODCIdentifier: r,
+	k.Signature = ndr.Read_bytes(&b, &p, c, e)
+	k.RODCIdentifier = ndr.Read_uint16(&b, &p, e)
+
+	//Check that there is only zero padding left
+	for _, v := range b[p:] {
+		if v != 0 {
+			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
+		}
 	}
+
+	return nil
 }

+ 50 - 0
pac/s4u_delegation_info.go

@@ -0,0 +1,50 @@
+package pac
+
+import (
+	"fmt"
+	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+// https://msdn.microsoft.com/en-us/library/cc237944.aspx
+type S4U_DelegationInfo struct {
+	S4U2proxyTarget      mstypes.RPC_UnicodeString // The name of the principal to whom the application can forward the ticket.
+	TransitedListSize    uint32
+	S4UTransitedServices []mstypes.RPC_UnicodeString // List of all services that have been delegated through by this client and subsequent services or servers.. Size is value of TransitedListSize
+}
+
+func (k *S4U_DelegationInfo) Unmarshal(b []byte) 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
+
+	k.S4U2proxyTarget, err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+	if err != nil {
+		return err
+	}
+	k.TransitedListSize = ndr.Read_uint32(&b, &p, e)
+	if k.TransitedListSize > 0 {
+		ts := make([]mstypes.RPC_UnicodeString, k.TransitedListSize, k.TransitedListSize)
+		for i := range ts {
+			ts[i], err = mstypes.Read_RPC_UnicodeString(&b, &p, e)
+		}
+		for i := range ts {
+			ts[i].UnmarshalString(&b, &p, e)
+		}
+		k.S4UTransitedServices = ts
+	}
+
+	//Check that there is only zero padding left
+	for _, v := range b[p:] {
+		if v != 0 {
+			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
+		}
+	}
+
+	return nil
+}

+ 25 - 14
mstypes/upn_dns_info.go → pac/upn_dns_info.go

@@ -1,7 +1,7 @@
-package mstypes
+package pac
 
 import (
-	"encoding/binary"
+	"fmt"
 	"github.com/jcmturner/gokrb5/ndr"
 )
 
@@ -18,17 +18,28 @@ const (
 	UPN_NO_UPN_ATTR = 31 // The user account object does not have the userPrincipalName attribute ([MS-ADA3] section 2.349) set. A UPN constructed by concatenating the user name with the DNS domain name of the account domain is provided.
 )
 
-func Read_UPN_DNSInfo(b []byte, p *int, e *binary.ByteOrder) UPN_DNSInfo {
-	l := ndr.Read_uint16(b, p, e)
-	o := ndr.Read_uint16(b, p, e)
-	dnsl := ndr.Read_uint16(b, p, e)
-	dnso := ndr.Read_uint16(b, p, e)
-	f := ndr.Read_uint32(b, p, e)
-	return UPN_DNSInfo{
-		UPNLength:           l,
-		UPNOffset:           o,
-		DNSDomainNameLength: dnsl,
-		DNSDomainNameOffset: dnso,
-		Flags:               f,
+func (k *UPN_DNSInfo) Unmarshal(b []byte) 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
+
+	k.UPNLength = ndr.Read_uint16(&b, &p, e)
+	k.UPNOffset = ndr.Read_uint16(&b, &p, e)
+	k.DNSDomainNameLength = ndr.Read_uint16(&b, &p, e)
+	k.DNSDomainNameOffset = ndr.Read_uint16(&b, &p, e)
+	k.Flags = ndr.Read_uint32(&b, &p, e)
+
+	//Check that there is only zero padding left
+	for _, v := range b[p:] {
+		if v != 0 {
+			return ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
+		}
+	}
+
+	return nil
 }

+ 0 - 63
types/AuthorizationData.go

@@ -1,13 +1,7 @@
 package types
 
 import (
-	"encoding/binary"
-	"errors"
-	"fmt"
 	"github.com/jcmturner/asn1"
-	"github.com/jcmturner/gokrb5/iana/adtype"
-	"github.com/jcmturner/gokrb5/mstypes"
-	"os"
 )
 
 // Reference: https://www.ietf.org/rfc/rfc4120.txt
@@ -118,60 +112,3 @@ func (a *AuthorizationDataEntry) Unmarshal(b []byte) error {
 	_, err := asn1.Unmarshal(b, a)
 	return err
 }
-
-func (a AuthorizationData) GetPACType() (mstypes.PACType, error) {
-	for _, ad := range a {
-		if ad.ADType == adtype.AD_IF_RELEVANT {
-			var ad2 AuthorizationData
-			err := ad2.Unmarshal(ad.ADData)
-			if err != nil {
-				continue
-			}
-			// TODO note does tthe entry contain and AuthorizationData or AuthorizationDataEntry. Assuming the former atm.
-			if ad2[0].ADType == adtype.AD_WIN2K_PAC {
-				var p int
-				var endian binary.ByteOrder
-				endian = binary.LittleEndian
-				pt := mstypes.Read_PACType(ad2[0].ADData, &p, &endian)
-				err = processPAC(pt, ad2[0].ADData)
-				return pt, err
-			}
-		}
-	}
-	return mstypes.PACType{}, errors.New("AuthorizationData within the ticket does not contain PAC data.")
-}
-
-func processPAC(pt mstypes.PACType, b []byte) error {
-	for _, buf := range pt.Buffers {
-		p := make([]byte, buf.CBBufferSize, buf.CBBufferSize)
-		copy(p, b[int(buf.Offset):int(buf.Offset)+int(buf.CBBufferSize)])
-		switch int(buf.ULType) {
-		case mstypes.ULTYPE_KERB_VALIDATION_INFO:
-			var bi mstypes.KerbValidationInfo
-			err := bi.ReadFromStream(p)
-			fmt.Fprintf(os.Stderr, "\nKInfo: %+v\n", bi)
-			if err != nil {
-				return err
-			}
-		case mstypes.ULTYPE_CREDENTIALS:
-
-		case mstypes.ULTYPE_PAC_SERVER_SIGNATURE_DATA:
-
-		case mstypes.ULTYPE_PAC_KDC_SIGNATURE_DATA:
-
-		case mstypes.ULTYPE_PAC_CLIENT_INFO:
-
-		case mstypes.ULTYPE_S4U_DELEGATION_INFO:
-
-		case mstypes.ULTYPE_UPN_DNS_INFO:
-
-		case mstypes.ULTYPE_PAC_CLIENT_CLAIMS_INFO:
-
-		case mstypes.ULTYPE_PAC_DEVICE_INFO:
-
-		case mstypes.ULTYPE_PAC_DEVICE_CLAIMS_INFO:
-
-		}
-	}
-	return nil
-}

+ 0 - 21
types/AuthorizationData_test.go

@@ -3,7 +3,6 @@ package types
 import (
 	"encoding/hex"
 	"fmt"
-	"github.com/jcmturner/gokrb5/iana/adtype"
 	"github.com/jcmturner/gokrb5/testdata"
 	"github.com/stretchr/testify/assert"
 	"testing"
@@ -49,23 +48,3 @@ func TestUnmarshalAuthorizationData_kdcissued(t *testing.T) {
 		assert.Equal(t, []byte(testdata.TEST_AUTHORIZATION_DATA_VALUE), ele.ADData, fmt.Sprintf("Authorization data of element %d not as expected", i+1))
 	}
 }
-
-func TestAuthorizationData_GetPACType(t *testing.T) {
-	v := "PAC_AuthorizationData"
-	b, err := hex.DecodeString(testdata.TestVectors[v])
-	if err != nil {
-		t.Fatalf("Test vector read error of %s: %v\n", v, err)
-	}
-	//TODO should the test data need to be wrapped up again?
-	a := AuthorizationData{
-		AuthorizationDataEntry{
-			ADType: adtype.AD_IF_RELEVANT,
-			ADData: b,
-		},
-	}
-	pactype, err := a.GetPACType()
-	if err != nil {
-		t.Fatalf("Error getting PAC Type: %v\n", err)
-	}
-	t.Logf("PACType: %+v", pactype)
-}

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott