소스 검색

handle raw KRB5 token (#366)

* handle raw krb5 tokens in negotiation header

Co-authored-by: jgiannuzzi <jgiannuzzi@users.noreply.github.com>

Co-authored-by: Jonathan Giannuzzi <jgiannuzzi@users.noreply.github.com>
Jonathan Turner 6 년 전
부모
커밋
00ec292fa4
2개의 변경된 파일45개의 추가작업 그리고 3개의 파일을 삭제
  1. 14 3
      v8/spnego/http.go
  2. 31 0
      v8/spnego/http_test.go

+ 14 - 3
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
 }

+ 31 - 0
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)