-
Notifications
You must be signed in to change notification settings - Fork 572
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: added first negotiate integration in go stack
* not fully working yet!!! * missing: negotiation integration in httpauth.Authenticationhandler Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> wip: replace go-spnego lib chore: add missing “Negotiate” in authorization header Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: implement negotiation for windows * Changed SpnegoProvider interface and implemented updating security context * fixed issue when sending data Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: ensure to free up ressources in authhandler Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: remove comments after going trhough them Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: support -d Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: adapt debug logging Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: Reduce messages send during negotiation * removed initial state for negotiate since it is not necessary in the current implementation * made state private Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: fixed some typos and simplified naming Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: implemented spnego_nonwindows * including some minor additions and cleanup Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: add missing import Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: refactoring and handling edge cases * refactoring for better testability and readability * handling edge cases Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: add src file dependency to makefile to avoid cleaning Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: go mod tidy Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: moved proxy_authenticator to httpauth * improved error Handling during authentication Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: throwing error when cycle max reached Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: fix failing tests Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: remove outdated tests Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: added logging that indicates the token type Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: close connection only if not nil Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: improved error message Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com> chore: incorporate feedback from review Signed-off-by: Peter Schäfer <101886095+PeterSchafer@users.noreply.github.com>
- Loading branch information
1 parent
b003aa3
commit bdd0ffb
Showing
13 changed files
with
768 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,140 @@ | ||
package httpauth | ||
|
||
import ( | ||
"net/http" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/url" | ||
|
||
"github.com/dpotapov/go-spnego" | ||
) | ||
|
||
type AuthenticationMechanism int | ||
type AuthenticationMechanism string | ||
type AuthenticationState int | ||
|
||
const maxCycleCount int = 10 | ||
|
||
const ( | ||
NoAuth AuthenticationMechanism = "NoAuth" | ||
Mock AuthenticationMechanism = "Mock" | ||
Negotiate AuthenticationMechanism = "Negotiate" | ||
UnknownMechanism AuthenticationMechanism = "UnknownMechanism" | ||
) | ||
|
||
const ( | ||
NoAuth AuthenticationMechanism = iota | ||
Mock AuthenticationMechanism = iota | ||
Negotiate AuthenticationMechanism = iota | ||
Initial AuthenticationState = iota | ||
Negotiating AuthenticationState = iota | ||
Done AuthenticationState = iota | ||
Error AuthenticationState = iota | ||
Cancel AuthenticationState = iota | ||
Close AuthenticationState = iota | ||
) | ||
|
||
const ( | ||
AuthorizationKey string = "Authorization" | ||
ProxyAuthorizationKey string = "Proxy-Authorization" | ||
ProxyAuthenticateKey string = "Proxy-Authenticate" | ||
) | ||
|
||
type AuthenticationHandlerInterface interface { | ||
Close() | ||
Cancel() | ||
Succesful() | ||
IsStopped() bool | ||
GetAuthorizationValue(url *url.URL, responseToken string) (string, error) | ||
SetLogger(logger *log.Logger) | ||
} | ||
|
||
type AuthenticationHandler struct { | ||
Mechanism AuthenticationMechanism | ||
spnegoProvider SpnegoProvider | ||
Mechanism AuthenticationMechanism | ||
state AuthenticationState | ||
cycleCount int | ||
logger *log.Logger | ||
} | ||
|
||
func (a *AuthenticationHandler) GetAuthorizationValue(url *url.URL) (string, error) { | ||
func NewHandler(mechanism AuthenticationMechanism) AuthenticationHandlerInterface { | ||
a := &AuthenticationHandler{ | ||
spnegoProvider: SpnegoProviderInstance(), | ||
Mechanism: mechanism, | ||
state: Initial, | ||
logger: log.New(io.Discard, "", 0), | ||
} | ||
return a | ||
} | ||
|
||
var authorizeValue string | ||
func (a *AuthenticationHandler) Close() { | ||
a.spnegoProvider.Close() | ||
a.state = Close | ||
} | ||
|
||
tmpRequest := http.Request{ | ||
URL: url, | ||
Header: map[string][]string{}, | ||
} | ||
func (a *AuthenticationHandler) GetAuthorizationValue(url *url.URL, responseToken string) (string, error) { | ||
authorizeValue := "" | ||
mechanism := string(a.Mechanism) | ||
var err error | ||
|
||
if a.Mechanism == Negotiate { // supporting mechanism: Negotiate (SPNEGO) | ||
var provider spnego.Provider = spnego.New() | ||
cannonicalize := false | ||
var token string | ||
var done bool | ||
|
||
if err := provider.SetSPNEGOHeader(&tmpRequest, cannonicalize); err != nil { | ||
if len(responseToken) == 0 && Negotiating == a.state { | ||
a.state = Error | ||
return "", fmt.Errorf("Authentication failed! Unexpected empty token during negotiation!") | ||
} | ||
|
||
a.state = Negotiating | ||
|
||
token, done, err = a.spnegoProvider.GetToken(url, responseToken) | ||
if err != nil { | ||
a.state = Error | ||
return "", err | ||
} | ||
|
||
if done { | ||
a.logger.Println("Security context done!") | ||
} | ||
|
||
authorizeValue = mechanism + " " + token | ||
} else if a.Mechanism == Mock { // supporting mechanism: Mock for testing | ||
tmpRequest.Header.Set(AuthorizationKey, "Mock") | ||
authorizeValue = mechanism + " " + responseToken | ||
a.Succesful() | ||
} | ||
|
||
// ugly work around the fact that go-spnego only adds an "Authorize" Header and not "Proxy-Authorize" | ||
if a.Mechanism != NoAuth { | ||
authorizeValue = tmpRequest.Header.Get(AuthorizationKey) | ||
a.cycleCount++ | ||
if a.cycleCount >= maxCycleCount { | ||
err = fmt.Errorf("Failed to authenticate with %d cycles, stopping now!", maxCycleCount) | ||
} | ||
|
||
return authorizeValue, nil | ||
return authorizeValue, err | ||
} | ||
|
||
func (a *AuthenticationHandler) IsStopped() bool { | ||
return (a.state == Done || a.state == Error || a.state == Cancel || a.state == Close) | ||
} | ||
|
||
func (a *AuthenticationHandler) Reset() { | ||
a.state = Initial | ||
a.cycleCount = 0 | ||
a.logger.Println("AuthenticationHandler.Reset()") | ||
} | ||
|
||
func (a *AuthenticationHandler) Cancel() { | ||
a.state = Cancel | ||
a.logger.Println("AuthenticationHandler.Cancel()") | ||
} | ||
|
||
func (a *AuthenticationHandler) Succesful() { | ||
a.state = Done | ||
a.logger.Println("AuthenticationHandler.Succesful()") | ||
} | ||
|
||
func (a *AuthenticationHandler) SetLogger(logger *log.Logger) { | ||
a.logger = logger | ||
a.spnegoProvider.SetLogger(logger) | ||
} | ||
|
||
func StringFromAuthenticationMechanism(mechanism AuthenticationMechanism) string { | ||
var result string | ||
switch mechanism { | ||
case NoAuth: | ||
result = "NoAuth" | ||
case Negotiate: | ||
result = "Negotiate" | ||
case Mock: | ||
result = "Mock" | ||
default: | ||
result = "Unknonwn AuthenticationMechanism" | ||
} | ||
return result | ||
return string(mechanism) | ||
} | ||
|
||
func AuthenticationMechanismFromString(mechanism string) AuthenticationMechanism { | ||
return AuthenticationMechanism(mechanism) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.