Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(): add header support for proxy auth #535

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions spnego/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ func respUnauthorizedNegotiate(resp *http.Response) bool {
return false
}

// SetSPNEGOHeader gets the service ticket and sets it as the SPNEGO authorization header on HTTP request object.
// To auto generate the SPN from the request object pass a null string "".
func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
func setSPNEGOHeaderCommon(cl *client.Client, r *http.Request, spn string, headerName string) error {
// Common SPNEGO logic...
// Generate the SPNEGO token, etc.

if spn == "" {
h := strings.TrimSuffix(strings.SplitN(r.URL.Host, ":", 2)[0], ".")
name, err := net.LookupCNAME(h)
Expand All @@ -185,10 +186,21 @@ func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
return krberror.Errorf(err, krberror.EncodingError, "could not marshal SPNEGO")
}
hs := "Negotiate " + base64.StdEncoding.EncodeToString(nb)
r.Header.Set(HTTPHeaderAuthRequest, hs)
r.Header.Set(headerName, hs)

return nil
}

// SetSPNEGOHeader gets the service ticket and sets it as the SPNEGO authorization header on HTTP request object.
// To auto generate the SPN from the request object pass a null string "".
func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
return setSPNEGOHeaderCommon(cl, r, spn, HTTPHeaderAuthRequest)
}

func SetSPNEGOProxyAuthorizationHeader(cl *client.Client, r *http.Request, spn string) error {
return setSPNEGOHeaderCommon(cl, r, spn, HTTPHeaderProxyAuthRequest)
}

// Service side functionality //

type ctxKey string
Expand All @@ -206,6 +218,8 @@ const (
CTXKeyCredentials ctxKey = "github.com/jcmturner/gokrb5/CTXKeyCredentials"
// HTTPHeaderAuthRequest is the header that will hold authn/z information.
HTTPHeaderAuthRequest = "Authorization"
// HTTPHeaderProxyAuthRequest is the header that will hold proxy authn/z information.
HTTPHeaderProxyAuthRequest = "Proxy-Authorization"
// HTTPHeaderAuthResponse is the header that will hold SPNEGO data from the server.
HTTPHeaderAuthResponse = "WWW-Authenticate"
// HTTPHeaderAuthResponseValueKey is the key in the auth header for SPNEGO.
Expand Down Expand Up @@ -290,4 +304,4 @@ func spnegoResponseReject(s *SPNEGO, w http.ResponseWriter, format string, v ...
func spnegoResponseAcceptCompleted(s *SPNEGO, w http.ResponseWriter, format string, v ...interface{}) {
s.Log(format, v...)
w.Header().Set(HTTPHeaderAuthResponse, spnegoNegTokenRespKRBAcceptCompleted)
}
}
51 changes: 47 additions & 4 deletions v8/spnego/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,40 @@ func setRequestSPN(r *http.Request) (types.PrincipalName, error) {
r.Host = h
return types.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, "HTTP/"+h), nil
}
func GetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) (string, error) {
// Common SPNEGO logic...
// Generate the SPNEGO token, etc.

if spn == "" {
pn, err := setRequestSPN(r)
if err != nil {
return "", err
}
spn = pn.PrincipalNameString()
}
cl.Log("using SPN %s", spn)
s := SPNEGOClient(cl, spn)
err := s.AcquireCred()
if err != nil {
return "", fmt.Errorf("could not acquire client credential: %v", err)
}
st, err := s.InitSecContext()
if err != nil {
return "", fmt.Errorf("could not initialize context: %v", err)
}
nb, err := st.Marshal()
if err != nil {
return "", krberror.Errorf(err, krberror.EncodingError, "could not marshal SPNEGO")
}
hs := base64.StdEncoding.EncodeToString(nb)

return hs, nil
}

func setSPNEGOHeaderCommon(cl *client.Client, r *http.Request, spn string, headerName string) error {
// Common SPNEGO logic...
// Generate the SPNEGO token, etc.

// SetSPNEGOHeader gets the service ticket and sets it as the SPNEGO authorization header on HTTP request object.
// To auto generate the SPN from the request object pass a null string "".
func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
if spn == "" {
pn, err := setRequestSPN(r)
if err != nil {
Expand All @@ -217,10 +247,21 @@ func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
return krberror.Errorf(err, krberror.EncodingError, "could not marshal SPNEGO")
}
hs := "Negotiate " + base64.StdEncoding.EncodeToString(nb)
r.Header.Set(HTTPHeaderAuthRequest, hs)
r.Header.Set(headerName, hs)

return nil
}

// SetSPNEGOHeader gets the service ticket and sets it as the SPNEGO authorization header on HTTP request object.
// To auto generate the SPN from the request object pass a null string "".
func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
return setSPNEGOHeaderCommon(cl, r, spn, HTTPHeaderAuthRequest)
}

func SetSPNEGOProxyAuthorizationHeader(cl *client.Client, r *http.Request, spn string) error {
return setSPNEGOHeaderCommon(cl, r, spn, HTTPHeaderProxyAuthRequest)
}

// Service side functionality //

const (
Expand All @@ -236,6 +277,8 @@ const (
ctxCredentials = "github.com/jcmturner/gokrb5/v8/ctxCredentials"
// HTTPHeaderAuthRequest is the header that will hold authn/z information.
HTTPHeaderAuthRequest = "Authorization"
// HTTPHeaderProxyAuthRequest is the header that will hold proxy authn/z information.
HTTPHeaderProxyAuthRequest = "Proxy-Authorization"
// HTTPHeaderAuthResponse is the header that will hold SPNEGO data from the server.
HTTPHeaderAuthResponse = "WWW-Authenticate"
// HTTPHeaderAuthResponseValueKey is the key in the auth header for SPNEGO.
Expand Down