Jonathan Turner 9 лет назад
Родитель
Сommit
bf41383bad

+ 9 - 80
messages/Ticket.go

@@ -2,7 +2,6 @@ package messages
 
 import (
 	"crypto/rand"
-	"encoding/binary"
 	"errors"
 	"fmt"
 	"github.com/jcmturner/asn1"
@@ -14,7 +13,6 @@ import (
 	"github.com/jcmturner/gokrb5/iana/errorcode"
 	"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"
@@ -187,7 +185,7 @@ func (t *Ticket) DecryptEncPart(keytab keytab.Keytab) error {
 	return nil
 }
 
-func (t *Ticket) GetPACType(key types.EncryptionKey) (mstypes.PACType, error) {
+func (t *Ticket) GetPACType(key types.EncryptionKey) (pac.PACType, error) {
 	for _, ad := range t.DecryptedEncPart.AuthorizationData {
 		if ad.ADType == adtype.AD_IF_RELEVANT {
 			var ad2 types.AuthorizationData
@@ -197,84 +195,15 @@ func (t *Ticket) GetPACType(key types.EncryptionKey) (mstypes.PACType, error) {
 			}
 			// 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 = binary.LittleEndian
-				pt := mstypes.Read_PACType(&ad2[0].ADData, &p, &endian)
-				err = processAD_PAC(pt, ad2[0].ADData, key)
-				return pt, err
+				var pac pac.PACType
+				err = pac.Unmarshal(ad2[0].ADData)
+				if err != nil {
+					return pac, err
+				}
+				err = pac.ProcessPACInfoBuffers(key)
+				return pac, 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
+	return pac.PACType{}, errors.New("AuthorizationData within the ticket does not contain PAC data.")
 }

+ 36 - 0
mstypes/claims_set_metadata.go

@@ -0,0 +1,36 @@
+package mstypes
+
+import (
+	"encoding/binary"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+// 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
+}
+
+const (
+	COMPRESSION_FORMAT_NONE        = 0
+	COMPRESSION_FORMAT_LZNT1       = 2
+	COMPRESSION_FORMAT_XPRESS      = 3
+	COMPRESSION_FORMAT_XPRESS_HUFF = 4
+)
+
+func Read_ClaimsSetMetadata(b *[]byte, p *int, e *binary.ByteOrder) ClaimsSetMetadata {
+	var c ClaimsSetMetadata
+	c.ULClaimsSetSize = ndr.Read_uint32(b, p, e)
+	c.ClaimsSet = ndr.Read_bytes(b, p, int(c.ULClaimsSetSize), e)
+	c.USCompressionFormat = ndr.Read_uint32(b, p, e)
+	c.ULUncompressedClaimsSetSize = ndr.Read_uint32(b, p, e)
+	c.USReservedType = ndr.Read_uint16(b, p, e)
+	c.ULReservedFieldSize = ndr.Read_uint32(b, p, e)
+	c.ReservedField = ndr.Read_bytes(b, p, int(c.ULReservedFieldSize), e)
+	return c
+}

+ 0 - 27
mstypes/pac_type.go

@@ -1,27 +0,0 @@
-package mstypes
-
-import (
-	"encoding/binary"
-	"github.com/jcmturner/gokrb5/ndr"
-)
-
-// https://msdn.microsoft.com/en-us/library/cc237950.aspx
-type PACType struct {
-	CBuffers uint32
-	Version  uint32
-	Buffers  []PACInfoBuffer // Size 1
-}
-
-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)
-	for i := range buf {
-		buf[i] = Read_PACInfoBuffer(b, p, e)
-	}
-	return PACType{
-		CBuffers: c,
-		Version:  v,
-		Buffers:  buf,
-	}
-}

+ 0 - 0
mstypes/crypto.go → mstypes/user_session_key.go


+ 34 - 0
pac/pac_client_claims.go

@@ -0,0 +1,34 @@
+package pac
+
+import (
+	"fmt"
+	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+// https://msdn.microsoft.com/en-us/library/hh536365.aspx
+type PAC_ClientClaimsInfo struct {
+	Claims mstypes.ClaimsSetMetadata
+}
+
+func (k *PAC_ClientClaimsInfo) 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.Claims = mstypes.Read_ClaimsSetMetadata(&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 - 6
pac/pac_client.go → pac/pac_client_info.go

@@ -40,9 +40,3 @@ func (k *PAC_ClientInfo) Unmarshal(b []byte) error {
 
 	return nil
 }
-
-// TODO come back to this struct
-// https://msdn.microsoft.com/en-us/library/hh536365.aspx
-//type PAC_ClientClaimsInfo struct {
-//	Claims ClaimsSetMetadata
-//}

+ 0 - 0
pac/pac_credentials.go → pac/pac_credentials_info.go


+ 34 - 0
pac/pac_device_claims.go

@@ -0,0 +1,34 @@
+package pac
+
+import (
+	"fmt"
+	"github.com/jcmturner/gokrb5/mstypes"
+	"github.com/jcmturner/gokrb5/ndr"
+)
+
+// https://msdn.microsoft.com/en-us/library/hh554226.aspx
+type PAC_DeviceClaimsInfo struct {
+	Claims mstypes.ClaimsSetMetadata
+}
+
+func (k *PAC_DeviceClaimsInfo) 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.Claims = mstypes.Read_ClaimsSetMetadata(&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 - 6
pac/pac_device_info.go

@@ -87,9 +87,3 @@ func (k *PAC_DeviceInfo) Unmarshal(b []byte) error {
 
 	return nil
 }
-
-// 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 → pac/pac_info_buffer.go

@@ -1,4 +1,4 @@
-package mstypes
+package pac
 
 import (
 	"encoding/binary"

+ 182 - 0
pac/pac_type.go

@@ -0,0 +1,182 @@
+package pac
+
+import (
+	"encoding/binary"
+	"errors"
+	"github.com/jcmturner/gokrb5/ndr"
+	"github.com/jcmturner/gokrb5/types"
+)
+
+// https://msdn.microsoft.com/en-us/library/cc237950.aspx
+type PACType struct {
+	CBuffers           uint32
+	Version            uint32
+	Buffers            []PACInfoBuffer // Size 1
+	Data               []byte
+	KerbValidationInfo *KerbValidationInfo
+	CredentialsInfo    *PAC_CredentialsInfo
+	ServerChecksum     *PAC_SignatureData
+	KDCChecksum        *PAC_SignatureData
+	ClientInfo         *PAC_ClientInfo
+	S4U_DelegationInfo *S4U_DelegationInfo
+	UPN_DNSInfo        *UPN_DNSInfo
+	ClientClaimsInfo   *PAC_ClientClaimsInfo
+	DeviceInfo         *PAC_DeviceInfo
+	DeviceClaimsInfo   *PAC_DeviceInfo
+}
+
+func (pac *PACType) Unmarshal(b []byte) error {
+	var p int
+	var e binary.ByteOrder = binary.LittleEndian
+	pac.CBuffers = ndr.Read_uint32(&b, &p, &e)
+	pac.Version = ndr.Read_uint32(&b, &p, &e)
+	buf := make([]PACInfoBuffer, pac.CBuffers, pac.CBuffers)
+	for i := range buf {
+		buf[i] = Read_PACInfoBuffer(&b, &p, &e)
+	}
+	pac.Buffers = buf
+	return nil
+}
+
+// https://msdn.microsoft.com/en-us/library/cc237954.aspx
+func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
+	for _, buf := range pac.Buffers {
+		p := make([]byte, buf.CBBufferSize, buf.CBBufferSize)
+		copy(p, pac.Data[int(buf.Offset):int(buf.Offset)+int(buf.CBBufferSize)])
+		switch int(buf.ULType) {
+		case ULTYPE_KERB_VALIDATION_INFO:
+			if pac.KerbValidationInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k KerbValidationInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.KerbValidationInfo = &k
+		case ULTYPE_CREDENTIALS:
+			if pac.ClientInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_CredentialsInfo
+			err := k.Unmarshal(p, key)
+			if err != nil {
+				return err
+			}
+			pac.ClientInfo = &k
+		case ULTYPE_PAC_SERVER_SIGNATURE_DATA:
+			if pac.ServerChecksum != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_SignatureData
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.ServerChecksum = &k
+		case ULTYPE_PAC_KDC_SIGNATURE_DATA:
+			if pac.KDCChecksum != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_SignatureData
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.KDCChecksum = &k
+		case ULTYPE_PAC_CLIENT_INFO:
+			if pac.ClientInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_ClientInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.ClientInfo = &k
+		case ULTYPE_S4U_DELEGATION_INFO:
+			if pac.S4U_DelegationInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k S4U_DelegationInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.S4U_DelegationInfo = &k
+		case ULTYPE_UPN_DNS_INFO:
+			if pac.UPN_DNSInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k UPN_DNSInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.UPN_DNSInfo = &k
+		case ULTYPE_PAC_CLIENT_CLAIMS_INFO:
+			if pac.ClientClaimsInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_ClientClaimsInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.ClientClaimsInfo = &k
+		case ULTYPE_PAC_DEVICE_INFO:
+			if pac.DeviceInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_DeviceInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.DeviceInfo = &k
+		case ULTYPE_PAC_DEVICE_CLAIMS_INFO:
+			if pac.DeviceClaimsInfo != nil {
+				//Must ignore subsequent buffers of this type
+				continue
+			}
+			var k PAC_DeviceClaimsInfo
+			err := k.Unmarshal(p)
+			if err != nil {
+				return err
+			}
+			pac.DeviceClaimsInfo = &k
+		}
+	}
+
+	if ok, err := pac.validate(); !ok {
+		return err
+	}
+
+	return nil
+}
+
+func (pac *PACType) validate() (bool, error) {
+	if pac.KerbValidationInfo == nil {
+		return false, errors.New("PAC Info Buffers does not contain a KerbValidationInfo")
+	}
+	if pac.ServerChecksum == nil {
+		return false, errors.New("PAC Info Buffers does not contain a ServerChecksum")
+	}
+	if pac.KDCChecksum == nil {
+		return false, errors.New("PAC Info Buffers does not contain a KDCChecksum")
+	}
+	if pac.ClientInfo == nil {
+		return false, errors.New("PAC Info Buffers does not contain a ClientInfo")
+	}
+
+	return true, nil
+}