Browse Source

pac tests

Jonathan Turner 9 years ago
parent
commit
23f7fb3052

+ 21 - 5
README.md

@@ -4,12 +4,13 @@
 Currently the following is working/tested:
 * Client side libraries that supports authentication to HTTP servers that implement SPNEGO using Kerberos 5.
 * Service side libraries for implementing HTTP web servers using Kerberos SPNEGO authentication.
-* Tested against MIT KDC only (please let me know if you find it works against Microsoft Active Directory). MIT KDC 1.6.3 is the oldest version tested against.
+* Microsoft PAC Authorization Data is processed and exposed in the HTTP request context. Available if Microsoft Active Directory is used as the KDC.
+* Tested against MIT KDC (1.6.3 is the oldest version tested against) and Microsoft Active Directory (Windows 2008 R2)
 * Tested against a KDC that supports PA-FX-FAST.
 * Tested against users that have pre-authentication required using PA-ENC-TIMESTAMP.
 
 #### Implemented Encryption & Checksum Types
-The currently implemented encryption types are:
+The currently implemented encryption types limited to:
 
 | Implementation | Encryption ID | Checksum ID |
 |-------|-------------|------------|
@@ -123,13 +124,28 @@ h := http.HandlerFunc(apphandler)
 ```
 Configure the HTTP handler:
 ```go
-http.Handler("/", service.SPNEGOKRB5Authenticate(h, kt, l))
+serivceAccountName = ""
+http.Handler("/", service.SPNEGOKRB5Authenticate(h, kt, serivceAccountName, l))
 ```
+The serviceAccountName needs to be defined when using Active Directory where the SPN is mapped to a user account.
+If this is not required it should be set to an empty string "".
 If authentication succeeds then the request's context will have the following values added so they can be accessed within the application's handler:
 * "authenticated" - Boolean indicating if the user is authenticated. Use of this value should also handle that this value may not be set and should assume "false" in that case.
-* "cname" - The authenticated user name.
-* "crealm" - The authenticated user's realm.
+* "credentials" - The authenticated user's credentials.
+If Microsoft Active Directory is used as the KDC then additional ADCredentials are available. For example the SIDs of the users group membership are available and can be used by your application for authorization.
+Access the credentials within your application:
+```go
+ctx := r.Context()
+if validuser, ok := ctx.Value("authenticated").(bool); ok && validuser {
+        if creds, ok := ctx.Value("credentials").(credentials.Credentials); ok {
+                if ADCreds, ok := creds.Attributes["ADCredentials"].(credentials.ADCredentials); ok {
+                        // Now access the fields of the ADCredentials struct. For example:
+                        groupSids := ADCreds.GroupMembershipSIDs
+                }
+        } 
 
+}
+```
 
 ## References
 ### RFCs

+ 15 - 0
credentials/credentials.go

@@ -5,6 +5,7 @@ import (
 	"github.com/jcmturner/gokrb5/iana/nametype"
 	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/types"
+	"time"
 )
 
 // Credentials struct for a user.
@@ -19,6 +20,20 @@ type Credentials struct {
 	Attributes map[string]interface{}
 }
 
+type ADCredentials struct {
+	EffectiveName       string
+	FullName            string
+	UserID              int
+	PrimaryGroupID      int
+	LogOnTime           time.Time
+	LogOffTime          time.Time
+	PasswordLastSet     time.Time
+	GroupMembershipSIDs []string
+	LogonDomainName     string
+	LogonDomainID       string
+	LogonServer         string
+}
+
 // Create a new Credentials struct.
 func NewCredentials(username string, realm string) Credentials {
 	return Credentials{

+ 27 - 17
examples/example-AD.go

@@ -16,7 +16,6 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"os"
-	"time"
 )
 
 func main() {
@@ -72,23 +71,34 @@ func httpServer() *httptest.Server {
 }
 
 func testAppHandler(w http.ResponseWriter, r *http.Request) {
-	w.WriteHeader(http.StatusOK)
 	ctx := r.Context()
-	if ctx.Value("credentials") != nil {
-		// Note that you should really check each attribute is not nil before doing the type assertion.
-		fmt.Fprintf(w, "<html>\nTEST.GOKRB5 Handler\n<ul><li>Authenticed user: %s</li>\n<li>User's realm: %s</li>\n", ctx.Value("credentials").(credentials.Credentials).Username, ctx.Value("credentials").(credentials.Credentials).Realm)
-		fmt.Fprintf(w, "<li>EffectiveName: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["effectiveName"].(string))
-		fmt.Fprintf(w, "<li>FullName: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["fullName"].(string))
-		fmt.Fprintf(w, "<li>UserID: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["userID"].(int))
-		fmt.Fprintf(w, "<li>PrimaryGroupID: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["primaryGroupID"].(int))
-		fmt.Fprintf(w, "<li>Group SIDs: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["groupMembershipSIDs"].([]string))
-		fmt.Fprintf(w, "<li>LogOnTime: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["logOnTime"].(time.Time))
-		fmt.Fprintf(w, "<li>LogOffTime: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["logOffTime"].(time.Time))
-		fmt.Fprintf(w, "<li>PasswordLastSet: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["passwordLastSet"].(time.Time))
-		fmt.Fprintf(w, "<li>LogonServer: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["logonServer"].(string))
-		fmt.Fprintf(w, "<li>LogonDomainName: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["logonDomainName"].(string))
-		fmt.Fprintf(w, "<li>LogonDomainID: %v</li>\n", ctx.Value("credentials").(credentials.Credentials).Attributes["logonDomainID"].(string))
-		fmt.Fprintf(w, "</ul></html>")
+	fmt.Fprint(w, "<html>\n<p><h1>TEST.GOKRB5 Handler</h1></p>\n")
+	if validuser, ok := ctx.Value("authenticated").(bool); ok && validuser {
+		w.WriteHeader(http.StatusOK)
+		if creds, ok := ctx.Value("credentials").(credentials.Credentials); ok {
+			fmt.Fprintf(w, "<ul><li>Authenticed user: %s</li>\n", creds.Username)
+			fmt.Fprintf(w, "<li>User's realm: %s</li>\n", creds.Realm)
+			if ADCreds, ok := creds.Attributes["ADCredentials"].(credentials.ADCredentials); ok {
+				// Now access the fields of the ADCredentials struct. For example:
+				fmt.Fprintf(w, "<li>EffectiveName: %v</li>\n", ADCreds.EffectiveName)
+				fmt.Fprintf(w, "<li>FullName: %v</li>\n", ADCreds.FullName)
+				fmt.Fprintf(w, "<li>UserID: %v</li>\n", ADCreds.UserID)
+				fmt.Fprintf(w, "<li>PrimaryGroupID: %v</li>\n", ADCreds.PrimaryGroupID)
+				fmt.Fprintf(w, "<li>Group SIDs: %v</li>\n", ADCreds.GroupMembershipSIDs)
+				fmt.Fprintf(w, "<li>LogOnTime: %v</li>\n", ADCreds.LogOnTime)
+				fmt.Fprintf(w, "<li>LogOffTime: %v</li>\n", ADCreds.LogOffTime)
+				fmt.Fprintf(w, "<li>PasswordLastSet: %v</li>\n", ADCreds.PasswordLastSet)
+				fmt.Fprintf(w, "<li>LogonServer: %v</li>\n", ADCreds.LogonServer)
+				fmt.Fprintf(w, "<li>LogonDomainName: %v</li>\n", ADCreds.LogonDomainName)
+				fmt.Fprintf(w, "<li>LogonDomainID: %v</li>\n", ADCreds.LogonDomainID)
+			}
+			fmt.Fprint(w, "</ul>")
+		}
+
+	} else {
+		w.WriteHeader(http.StatusUnauthorized)
+		fmt.Fprint(w, "Authentication failed")
 	}
+	fmt.Fprint(w, "</html>")
 	return
 }

+ 13 - 2
examples/example.go

@@ -84,8 +84,19 @@ func httpServer() *httptest.Server {
 }
 
 func testAppHandler(w http.ResponseWriter, r *http.Request) {
-	w.WriteHeader(http.StatusOK)
 	ctx := r.Context()
-	fmt.Fprintf(w, "<html>\nTEST.GOKRB5 Handler\nAuthenticed user: %s\nUser's realm: %s\n</html>", ctx.Value("credentials").(credentials.Credentials).Username, ctx.Value("credentials").(credentials.Credentials).Realm)
+	fmt.Fprint(w, "<html>\n<p><h1>TEST.GOKRB5 Handler</h1></p>\n")
+	if validuser, ok := ctx.Value("authenticated").(bool); ok && validuser {
+		w.WriteHeader(http.StatusOK)
+		if creds, ok := ctx.Value("credentials").(credentials.Credentials); ok {
+			fmt.Fprintf(w, "<ul><li>Authenticed user: %s</li>\n", creds.Username)
+			fmt.Fprintf(w, "<li>User's realm: %s</li></ul>\n", creds.Realm)
+		}
+
+	} else {
+		w.WriteHeader(http.StatusUnauthorized)
+		fmt.Fprint(w, "Authentication failed")
+	}
+	fmt.Fprint(w, "</html>")
 	return
 }

+ 39 - 23
messages/Ticket_test.go

@@ -3,7 +3,9 @@ package messages
 import (
 	"encoding/hex"
 	"fmt"
+	"github.com/jcmturner/gokrb5/keytab"
 	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/jcmturner/gokrb5/types"
 	"github.com/stretchr/testify/assert"
 	"testing"
 	"time"
@@ -112,26 +114,40 @@ 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}}
-//	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)
-//	}
-//	t.Logf("PACType: %+v", pactype)
-//}
+func TestAuthorizationData_GetPACType_GOKRB5TestData(t *testing.T) {
+	v := "PAC_AuthorizationData_GOKRB5"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	var a types.AuthorizationData
+	err = a.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	tkt := Ticket{
+		Realm: "TEST.GOKRB5",
+		EncPart: types.EncryptedData{
+			EType: 18,
+			KVNO:  2,
+		},
+		DecryptedEncPart: EncTicketPart{
+			AuthorizationData: a,
+		},
+	}
+	b, _ = hex.DecodeString(testdata.SYSHTTP_KEYTAB)
+	kt, _ := keytab.Parse(b)
+	isPAC, pac, err := tkt.GetPACType(kt, "sysHTTP")
+	if err != nil {
+		t.Fatalf("Error getting PAC Type: %v\n", err)
+	}
+	assert.True(t, isPAC, "PAC should be present")
+	assert.Equal(t, 5, len(pac.Buffers), "Number of buffers not as expected")
+	assert.Equal(t, uint32(5), pac.CBuffers, "Count of buffers not as expected")
+	assert.Equal(t, uint32(0), pac.Version, "PAC version not as expected")
+	assert.NotNil(t, pac.KerbValidationInfo, "PAC Kerb Validation info is nil")
+	assert.NotNil(t, pac.ClientInfo, "PAC Client Info info is nil")
+	assert.NotNil(t, pac.UPN_DNSInfo, "PAC UPN DNS Info info is nil")
+	assert.NotNil(t, pac.KDCChecksum, "PAC KDC Checksum info is nil")
+	assert.NotNil(t, pac.ServerChecksum, "PAC Server checksum info is nil")
+}

+ 2 - 1
pac/client_info.go

@@ -20,7 +20,8 @@ func (k *PAC_ClientInfo) Unmarshal(b []byte) error {
 
 	k.ClientID = mstypes.Read_FileTime(&b, &p, &e)
 	k.NameLength = ndr.Read_uint16(&b, &p, &e)
-	s := make([]rune, k.NameLength, k.NameLength)
+	//Length devided 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.Read_uint16(&b, &p, &e))
 	}

+ 24 - 0
pac/client_info_test.go

@@ -0,0 +1,24 @@
+package pac
+
+import (
+	"encoding/hex"
+	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/stretchr/testify/assert"
+	"testing"
+	"time"
+)
+
+func TestPAC_ClientInfo_Unmarshal(t *testing.T) {
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_Client_Info"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k PAC_ClientInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	assert.Equal(t, time.Date(2017, 5, 6, 15, 53, 11, 000000000, time.UTC), k.ClientID.Time(), "Client ID time not as expected.")
+	assert.Equal(t, uint16(18), k.NameLength, "Client name length not as expected")
+	assert.Equal(t, "testuser1", k.Name, "Client name not as expected")
+}

File diff suppressed because it is too large
+ 1 - 1
pac/kerb_validation_info_test.go


+ 61 - 0
pac/pac_type_test.go

@@ -0,0 +1,61 @@
+package pac
+
+import (
+	"encoding/hex"
+	"fmt"
+	"github.com/jcmturner/gokrb5/keytab"
+	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestPAC_Type_Validate(t *testing.T) {
+	v := "PAC_AD_WIN2K_PAC"
+	b, err := hex.DecodeString(testdata.TestVectors[v])
+	if err != nil {
+		t.Fatalf("Test vector read error of %s: %v\n", v, err)
+	}
+	var pac PACType
+	err = pac.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+
+	b, _ = hex.DecodeString(testdata.SYSHTTP_KEYTAB)
+	kt, _ := keytab.Parse(b)
+	key, err := kt.GetEncryptionKey([]string{"sysHTTP"}, "TEST.GOKRB5", 2, 18)
+	if err != nil {
+		t.Fatalf("Error getting key: %v", err)
+	}
+	err = pac.ProcessPACInfoBuffers(key)
+	if err != nil {
+		t.Fatalf("Processing reference pac error: %v", err)
+	}
+
+	pac_invalid_server_sig := pac
+	// Check the signature to force failure
+	pac_invalid_server_sig.ServerChecksum.Signature[0] ^= 0xFF
+	pac_invalid_nil_kerb_validation_info := pac
+	pac_invalid_nil_kerb_validation_info.KerbValidationInfo = nil
+	pac_invalid_nil_server_sig := pac
+	pac_invalid_nil_server_sig.ServerChecksum = nil
+	pac_invalid_nil_kdc_sig := pac
+	pac_invalid_nil_kdc_sig.KDCChecksum = nil
+	pac_invalid_client_info := pac
+	pac_invalid_client_info.ClientInfo = nil
+
+	var pacs = []struct {
+		pac PACType
+	}{
+		{pac_invalid_server_sig},
+		{pac_invalid_nil_kerb_validation_info},
+		{pac_invalid_nil_server_sig},
+		{pac_invalid_nil_kdc_sig},
+		{pac_invalid_client_info},
+	}
+	for i, s := range pacs {
+		v, _ := s.pac.validate(key)
+		assert.False(t, v, fmt.Sprintf("Validation should have failed for test %v", i))
+	}
+
+}

+ 45 - 0
pac/signature_data_test.go

@@ -0,0 +1,45 @@
+package pac
+
+import (
+	"encoding/hex"
+	"github.com/jcmturner/gokrb5/iana/chksumtype"
+	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestPAC_SignatureData_Unmarshal_Server_Signature(t *testing.T) {
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_Server_Signature"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k PAC_SignatureData
+	bz, err := k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	sig, _ := hex.DecodeString("1e251d98d552be7df384f550")
+	zeroed, _ := hex.DecodeString("10000000000000000000000000000000")
+	assert.Equal(t, uint32(chksumtype.HMAC_SHA1_96_AES256), k.SignatureType, "Server signature type not as expected")
+	assert.Equal(t, sig, k.Signature, "Server signature not as expected")
+	assert.Equal(t, uint16(0), k.RODCIdentifier, "RODC Identifier not as expected")
+	assert.Equal(t, zeroed, bz, "Returned bytes with zeroed signature not as expected")
+}
+
+func TestPAC_SignatureData_Unmarshal_KDC_Signature(t *testing.T) {
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_KDC_Signature"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k PAC_SignatureData
+	bz, err := k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	sig, _ := hex.DecodeString("340be28b48765d0519ee9346cf53d822")
+	zeroed, _ := hex.DecodeString("76ffffff00000000000000000000000000000000")
+	assert.Equal(t, uint32(chksumtype.KERB_CHECKSUM_HMAC_MD5_UNSIGNED), k.SignatureType, "Server signature type not as expected")
+	assert.Equal(t, sig, k.Signature, "Server signature not as expected")
+	assert.Equal(t, uint16(0), k.RODCIdentifier, "RODC Identifier not as expected")
+	assert.Equal(t, zeroed, bz, "Returned bytes with zeroed signature not as expected")
+}

+ 1 - 1
pac/upn_dns_info.go

@@ -45,7 +45,7 @@ func (k *UPN_DNSInfo) Unmarshal(b []byte) error {
 		q := i * 2
 		d[i] = rune(ndr.Read_uint16(&db, &q, &e))
 	}
-	k.UPN = string(d)
+	k.DNSDomain = string(d)
 
 	l := []int{
 		p,

+ 27 - 0
pac/upn_dns_info_test.go

@@ -0,0 +1,27 @@
+package pac
+
+import (
+	"encoding/hex"
+	"github.com/jcmturner/gokrb5/testdata"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestUPN_DNSInfo_Unmarshal(t *testing.T) {
+	b, err := hex.DecodeString(testdata.TestVectors["PAC_UPN_DNS_Info"])
+	if err != nil {
+		t.Fatal("Could not decode test data hex string")
+	}
+	var k UPN_DNSInfo
+	err = k.Unmarshal(b)
+	if err != nil {
+		t.Fatalf("Error unmarshaling test data: %v", err)
+	}
+	assert.Equal(t, uint16(42), k.UPNLength, "UPN Length not as expected")
+	assert.Equal(t, uint16(16), k.UPNOffset, "UPN Offset not as expected")
+	assert.Equal(t, uint16(22), k.DNSDomainNameLength, "DNS Domain Length not as expected")
+	assert.Equal(t, uint16(64), k.DNSDomainNameOffset, "DNS Domain Offset not as expected")
+	assert.Equal(t, "testuser1@test.gokrb5", k.UPN, "UPN not as expected")
+	assert.Equal(t, "TEST.GOKRB5", k.DNSDomain, "DNS Domain not as expected")
+	assert.Equal(t, uint32(0), k.Flags, "DNS Domain not as expected")
+}

+ 13 - 11
service/APExchange.go

@@ -87,17 +87,19 @@ func ValidateAPREQ(APReq messages.APReq, kt keytab.Keytab, sa string, cAddr stri
 	}
 	if isPAC {
 		// There is a valid PAC. Adding attributes to creds
-		creds.Attributes["groupMembershipSIDs"] = pac.KerbValidationInfo.GetGroupMembershipSIDs()
-		creds.Attributes["logOnTime"] = pac.KerbValidationInfo.LogOnTime.Time()
-		creds.Attributes["logOffTime"] = pac.KerbValidationInfo.LogOffTime.Time()
-		creds.Attributes["passwordLastSet"] = pac.KerbValidationInfo.PasswordLastSet.Time()
-		creds.Attributes["effectiveName"] = pac.KerbValidationInfo.EffectiveName.Value
-		creds.Attributes["fullName"] = pac.KerbValidationInfo.FullName.Value
-		creds.Attributes["userID"] = int(pac.KerbValidationInfo.UserID)
-		creds.Attributes["primaryGroupID"] = int(pac.KerbValidationInfo.PrimaryGroupID)
-		creds.Attributes["logonServer"] = pac.KerbValidationInfo.LogonServer.Value
-		creds.Attributes["logonDomainName"] = pac.KerbValidationInfo.LogonDomainName.Value
-		creds.Attributes["logonDomainID"] = pac.KerbValidationInfo.LogonDomainID.ToString()
+		creds.Attributes["ADCredentials"] = credentials.ADCredentials{
+			GroupMembershipSIDs: pac.KerbValidationInfo.GetGroupMembershipSIDs(),
+			LogOnTime:           pac.KerbValidationInfo.LogOnTime.Time(),
+			LogOffTime:          pac.KerbValidationInfo.LogOffTime.Time(),
+			PasswordLastSet:     pac.KerbValidationInfo.PasswordLastSet.Time(),
+			EffectiveName:       pac.KerbValidationInfo.EffectiveName.Value,
+			FullName:            pac.KerbValidationInfo.FullName.Value,
+			UserID:              int(pac.KerbValidationInfo.UserID),
+			PrimaryGroupID:      int(pac.KerbValidationInfo.PrimaryGroupID),
+			LogonServer:         pac.KerbValidationInfo.LogonServer.Value,
+			LogonDomainName:     pac.KerbValidationInfo.LogonDomainName.Value,
+			LogonDomainID:       pac.KerbValidationInfo.LogonDomainID.ToString(),
+		}
 	}
 	return true, creds, nil
 }

+ 8 - 8
service/APExchange_test.go

@@ -49,7 +49,7 @@ func TestValidateAPREQ(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if !ok || err != nil {
 		t.Fatalf("Validation of AP_REQ failed when it should not have: %v", err)
 	}
@@ -92,7 +92,7 @@ func TestValidateAPREQ_KRB_AP_ERR_BADMATCH(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if ok || err == nil {
 		t.Fatal("Validation of AP_REQ passed when it should not have")
 	}
@@ -134,7 +134,7 @@ func TestValidateAPREQ_LargeClockSkew(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if ok || err == nil {
 		t.Fatal("Validation of AP_REQ passed when it should not have")
 	}
@@ -174,12 +174,12 @@ func TestValidateAPREQ_Replay(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if !ok || err != nil {
 		t.Fatalf("Validation of AP_REQ failed when it should not have: %v", err)
 	}
 	// Replay
-	ok, _, err = ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err = ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if ok || err == nil {
 		t.Fatal("Validation of AP_REQ passed when it should not have")
 	}
@@ -220,7 +220,7 @@ func TestValidateAPREQ_FutureTicket(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if ok || err == nil {
 		t.Fatal("Validation of AP_REQ passed when it should not have")
 	}
@@ -262,7 +262,7 @@ func TestValidateAPREQ_InvalidTicket(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if ok || err == nil {
 		t.Fatal("Validation of AP_REQ passed when it should not have")
 	}
@@ -303,7 +303,7 @@ func TestValidateAPREQ_ExpiredTicket(t *testing.T) {
 		t.Fatalf("Error getting test AP_REQ: %v", err)
 	}
 
-	ok, _, err := ValidateAPREQ(APReq, kt, "127.0.0.1")
+	ok, _, err := ValidateAPREQ(APReq, kt, "", "127.0.0.1")
 	if ok || err == nil {
 		t.Fatal("Validation of AP_REQ passed when it should not have")
 	}

+ 1 - 1
service/http_test.go

@@ -122,7 +122,7 @@ func httpServer() *httptest.Server {
 	b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
 	kt, _ := keytab.Parse(b)
 	th := http.HandlerFunc(testAppHandler)
-	s := httptest.NewServer(SPNEGOKRB5Authenticate(th, kt, l))
+	s := httptest.NewServer(SPNEGOKRB5Authenticate(th, kt, "", l))
 	return s
 }
 

File diff suppressed because it is too large
+ 0 - 0
testdata/test_vectors.go


Some files were not shown because too many files changed in this diff