From 00ec292fa4ce5f99a283f4ca46a82b0dc70c181e Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 8 Feb 2020 09:52:48 +0000 Subject: [PATCH] handle raw KRB5 token (#366) * handle raw krb5 tokens in negotiation header Co-authored-by: jgiannuzzi Co-authored-by: Jonathan Giannuzzi --- v8/spnego/http.go | 17 ++++++++++++++--- v8/spnego/http_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/v8/spnego/http.go b/v8/spnego/http.go index 5611f050..1c4f42fb 100644 --- a/v8/spnego/http.go +++ b/v8/spnego/http.go @@ -13,6 +13,7 @@ import ( "net/url" "strings" + "github.com/jcmturner/gofork/encoding/asn1" "github.com/jcmturner/goidentity/v6" "github.com/jcmturner/gokrb5/v8/client" "github.com/jcmturner/gokrb5/v8/credentials" @@ -291,9 +292,19 @@ func getAuthorizationNegotiationHeaderAsSPNEGOToken(spnego *SPNEGO, r *http.Requ var st SPNEGOToken err = st.Unmarshal(b) if err != nil { - err = fmt.Errorf("error in unmarshaling SPNEGO token: %v", err) - spnegoNegotiateKRB5MechType(spnego, w, "%s - SPNEGO %v", r.RemoteAddr, err) - return nil, err + // Check if this is a raw KRB5 context token - issue #347. + var k5t KRB5Token + if k5t.Unmarshal(b) != nil { + err = fmt.Errorf("error in unmarshaling SPNEGO token: %v", err) + spnegoNegotiateKRB5MechType(spnego, w, "%s - SPNEGO %v", r.RemoteAddr, err) + return nil, err + } + // Wrap it into an SPNEGO context token + st.Init = true + st.NegTokenInit = NegTokenInit{ + MechTypes: []asn1.ObjectIdentifier{k5t.OID}, + MechTokenBytes: b, + } } return &st, nil } diff --git a/v8/spnego/http_test.go b/v8/spnego/http_test.go index be5477b8..2ee80231 100644 --- a/v8/spnego/http_test.go +++ b/v8/spnego/http_test.go @@ -3,6 +3,7 @@ package spnego import ( "bytes" "crypto/rand" + "encoding/base64" "encoding/hex" "errors" "fmt" @@ -155,6 +156,36 @@ func TestService_SPNEGOKRB_ValidUser(t *testing.T) { assert.Equal(t, http.StatusOK, httpResp.StatusCode, "Status code in response to client SPNEGO request not as expected") } +func TestService_SPNEGOKRB_ValidUser_RawKRB5Token(t *testing.T) { + test.Integration(t) + + s := httpServer() + defer s.Close() + r, _ := http.NewRequest("GET", s.URL, nil) + + cl := getClient() + sc := SPNEGOClient(cl, "HTTP/host.test.gokrb5") + err := sc.AcquireCred() + if err != nil { + t.Fatalf("could not acquire client credential: %v", err) + } + st, err := sc.InitSecContext() + if err != nil { + t.Fatalf("could not initialize context: %v", err) + } + + // Use the raw KRB5 context token + nb := st.(*SPNEGOToken).NegTokenInit.MechTokenBytes + hs := "Negotiate " + base64.StdEncoding.EncodeToString(nb) + r.Header.Set(HTTPHeaderAuthRequest, hs) + + httpResp, err := http.DefaultClient.Do(r) + if err != nil { + t.Fatalf("Request error: %v\n", err) + } + assert.Equal(t, http.StatusOK, httpResp.StatusCode, "Status code in response to client SPNEGO request not as expected") +} + func TestService_SPNEGOKRB_Replay(t *testing.T) { test.Integration(t)