Jonathan Turner 9 лет назад
Родитель
Сommit
dd60e8a047
3 измененных файлов с 52 добавлено и 20 удалено
  1. 5 1
      messages/Ticket_test.go
  2. 10 4
      pac/pac_signature_data.go
  3. 37 15
      pac/pac_type.go

+ 5 - 1
messages/Ticket_test.go

@@ -4,6 +4,7 @@ import (
 	"encoding/hex"
 	"fmt"
 	"github.com/jcmturner/gokrb5/iana/adtype"
+	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/testdata"
 	"github.com/jcmturner/gokrb5/types"
 	"github.com/stretchr/testify/assert"
@@ -128,7 +129,10 @@ func TestAuthorizationData_GetPACType(t *testing.T) {
 		},
 	}
 	tkt := Ticket{DecryptedEncPart: EncTicketPart{AuthorizationData: a}}
-	pactype, err := tkt.GetPACType()
+	b, _ = hex.DecodeString(testdata.HTTP_KEYTAB)
+	kt, _ := keytab.Parse(b)
+	key, _ := kt.GetEncryptionKey([]string{"HTTP", "host.test.gokrb5"}, "TEST.GOKRB5", 1, 18)
+	pactype, err := tkt.GetPACType(key)
 	if err != nil {
 		t.Fatalf("Error getting PAC Type: %v\n", err)
 	}

+ 10 - 4
pac/pac_signature_data.go

@@ -36,10 +36,10 @@ 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 (k *PAC_SignatureData) Unmarshal(b []byte) error {
+func (k *PAC_SignatureData) Unmarshal(b []byte) ([]byte, error) {
 	ch, _, p, err := ndr.ReadHeaders(&b)
 	if err != nil {
-		return fmt.Errorf("Error parsing byte stream headers: %v", err)
+		return []byte{}, fmt.Errorf("Error parsing byte stream headers: %v", err)
 	}
 	e := &ch.Endianness
 
@@ -62,9 +62,15 @@ func (k *PAC_SignatureData) Unmarshal(b []byte) error {
 	//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 []byte{}, ndr.NDRMalformed{EText: "Non-zero padding left over at end of data stream"}
 		}
 	}
 
-	return nil
+	// Create bytes with zeroed signature needed for checksum verification
+	rb := make([]byte, len(b), len(b))
+	copy(rb, b)
+	z := make([]byte, c, c)
+	copy(rb[p:p+c], z)
+
+	return rb, nil
 }

+ 37 - 15
pac/pac_type.go

@@ -3,6 +3,10 @@ package pac
 import (
 	"encoding/binary"
 	"errors"
+	"fmt"
+	"github.com/jcmturner/gokrb5/crypto"
+	"github.com/jcmturner/gokrb5/crypto/engine"
+	"github.com/jcmturner/gokrb5/iana/keyusage"
 	"github.com/jcmturner/gokrb5/ndr"
 	"github.com/jcmturner/gokrb5/types"
 )
@@ -11,7 +15,7 @@ import (
 type PACType struct {
 	CBuffers           uint32
 	Version            uint32
-	Buffers            []PACInfoBuffer // Size 1
+	Buffers            []PACInfoBuffer
 	Data               []byte
 	KerbValidationInfo *KerbValidationInfo
 	CredentialsInfo    *PAC_CredentialsInfo
@@ -23,11 +27,16 @@ type PACType struct {
 	ClientClaimsInfo   *PAC_ClientClaimsInfo
 	DeviceInfo         *PAC_DeviceInfo
 	DeviceClaimsInfo   *PAC_DeviceClaimsInfo
+	ZeroSigData        []byte
 }
 
 func (pac *PACType) Unmarshal(b []byte) error {
 	var p int
 	var e binary.ByteOrder = binary.LittleEndian
+	pac.Data = b
+	zb := make([]byte, len(b), len(b))
+	copy(zb, b)
+	pac.ZeroSigData = zb
 	pac.CBuffers = ndr.Read_uint32(&b, &p, &e)
 	pac.Version = ndr.Read_uint32(&b, &p, &e)
 	buf := make([]PACInfoBuffer, pac.CBuffers, pac.CBuffers)
@@ -52,7 +61,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k KerbValidationInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing KerbValidationInfo: %v", err)
 			}
 			pac.KerbValidationInfo = &k
 		case ULTYPE_CREDENTIALS:
@@ -63,7 +72,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k PAC_CredentialsInfo
 			err := k.Unmarshal(p, key)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing CredentialsInfo: %v", err)
 			}
 			pac.CredentialsInfo = &k
 		case ULTYPE_PAC_SERVER_SIGNATURE_DATA:
@@ -72,9 +81,10 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 				continue
 			}
 			var k PAC_SignatureData
-			err := k.Unmarshal(p)
+			zb, err := k.Unmarshal(p)
+			copy(pac.ZeroSigData[int(buf.Offset):int(buf.Offset)+int(buf.CBBufferSize)], zb)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing ServerChecksum: %v", err)
 			}
 			pac.ServerChecksum = &k
 		case ULTYPE_PAC_KDC_SIGNATURE_DATA:
@@ -83,9 +93,10 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 				continue
 			}
 			var k PAC_SignatureData
-			err := k.Unmarshal(p)
+			zb, err := k.Unmarshal(p)
+			copy(pac.ZeroSigData[int(buf.Offset):int(buf.Offset)+int(buf.CBBufferSize)], zb)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing KDCChecksum: %v", err)
 			}
 			pac.KDCChecksum = &k
 		case ULTYPE_PAC_CLIENT_INFO:
@@ -96,7 +107,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k PAC_ClientInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing ClientInfo: %v", err)
 			}
 			pac.ClientInfo = &k
 		case ULTYPE_S4U_DELEGATION_INFO:
@@ -107,7 +118,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k S4U_DelegationInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing S4U_DelegationInfo: %v", err)
 			}
 			pac.S4U_DelegationInfo = &k
 		case ULTYPE_UPN_DNS_INFO:
@@ -118,7 +129,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k UPN_DNSInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing UPN_DNSInfo: %v", err)
 			}
 			pac.UPN_DNSInfo = &k
 		case ULTYPE_PAC_CLIENT_CLAIMS_INFO:
@@ -129,7 +140,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k PAC_ClientClaimsInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing ClientClaimsInfo: %v", err)
 			}
 			pac.ClientClaimsInfo = &k
 		case ULTYPE_PAC_DEVICE_INFO:
@@ -140,7 +151,7 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k PAC_DeviceInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing DeviceInfo: %v", err)
 			}
 			pac.DeviceInfo = &k
 		case ULTYPE_PAC_DEVICE_CLAIMS_INFO:
@@ -151,20 +162,20 @@ func (pac *PACType) ProcessPACInfoBuffers(key types.EncryptionKey) error {
 			var k PAC_DeviceClaimsInfo
 			err := k.Unmarshal(p)
 			if err != nil {
-				return err
+				return fmt.Errorf("Error processing DeviceClaimsInfo: %v", err)
 			}
 			pac.DeviceClaimsInfo = &k
 		}
 	}
 
-	if ok, err := pac.validate(); !ok {
+	if ok, err := pac.validate(key); !ok {
 		return err
 	}
 
 	return nil
 }
 
-func (pac *PACType) validate() (bool, error) {
+func (pac *PACType) validate(key types.EncryptionKey) (bool, error) {
 	if pac.KerbValidationInfo == nil {
 		return false, errors.New("PAC Info Buffers does not contain a KerbValidationInfo")
 	}
@@ -177,6 +188,17 @@ func (pac *PACType) validate() (bool, error) {
 	if pac.ClientInfo == nil {
 		return false, errors.New("PAC Info Buffers does not contain a ClientInfo")
 	}
+	etype, err := crypto.GetChksumEtype(int(pac.ServerChecksum.SignatureType))
+	if err != nil {
+		return false, err
+	}
+	if ok := engine.VerifyChecksum(key.KeyValue,
+		pac.ServerChecksum.Signature,
+		pac.ZeroSigData,
+		keyusage.KERB_NON_KERB_CKSUM_SALT,
+		etype); !ok {
+		return false, errors.New("PAC service checksum verification failed")
+	}
 
 	return true, nil
 }