|
|
@ -22,19 +22,21 @@ import ( |
|
|
|
"code.gitea.io/gitea/services/auth/source/sspi" |
|
|
|
"code.gitea.io/gitea/services/auth/source/sspi" |
|
|
|
|
|
|
|
|
|
|
|
gouuid "github.com/google/uuid" |
|
|
|
gouuid "github.com/google/uuid" |
|
|
|
"github.com/quasoft/websspi" |
|
|
|
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
|
tplSignIn base.TplName = "user/auth/signin" |
|
|
|
tplSignIn base.TplName = "user/auth/signin" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type SSPIAuth interface { |
|
|
|
|
|
|
|
AppendAuthenticateHeader(w http.ResponseWriter, data string) |
|
|
|
|
|
|
|
Authenticate(r *http.Request, w http.ResponseWriter) (userInfo *SSPIUserInfo, outToken string, err error) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
var ( |
|
|
|
// sspiAuth is a global instance of the websspi authentication package,
|
|
|
|
sspiAuth SSPIAuth // a global instance of the websspi authenticator to avoid acquiring the server credential handle on every request
|
|
|
|
// which is used to avoid acquiring the server credential handle on
|
|
|
|
sspiAuthOnce sync.Once |
|
|
|
// every request
|
|
|
|
sspiAuthErrInit error |
|
|
|
sspiAuth *websspi.Authenticator |
|
|
|
|
|
|
|
sspiAuthOnce sync.Once |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure the struct implements the interface.
|
|
|
|
// Ensure the struct implements the interface.
|
|
|
|
_ Method = &SSPI{} |
|
|
|
_ Method = &SSPI{} |
|
|
@ -42,8 +44,9 @@ var ( |
|
|
|
|
|
|
|
|
|
|
|
// SSPI implements the SingleSignOn interface and authenticates requests
|
|
|
|
// SSPI implements the SingleSignOn interface and authenticates requests
|
|
|
|
// via the built-in SSPI module in Windows for SPNEGO authentication.
|
|
|
|
// via the built-in SSPI module in Windows for SPNEGO authentication.
|
|
|
|
// On successful authentication returns a valid user object.
|
|
|
|
// The SSPI plugin is expected to be executed last, as it returns 401 status code if negotiation
|
|
|
|
// Returns nil if authentication fails.
|
|
|
|
// fails (or if negotiation should continue), which would prevent other authentication methods
|
|
|
|
|
|
|
|
// to execute at all.
|
|
|
|
type SSPI struct{} |
|
|
|
type SSPI struct{} |
|
|
|
|
|
|
|
|
|
|
|
// Name represents the name of auth method
|
|
|
|
// Name represents the name of auth method
|
|
|
@ -56,15 +59,10 @@ func (s *SSPI) Name() string { |
|
|
|
// If negotiation should continue or authentication fails, immediately returns a 401 HTTP
|
|
|
|
// If negotiation should continue or authentication fails, immediately returns a 401 HTTP
|
|
|
|
// response code, as required by the SPNEGO protocol.
|
|
|
|
// response code, as required by the SPNEGO protocol.
|
|
|
|
func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { |
|
|
|
func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { |
|
|
|
var errInit error |
|
|
|
sspiAuthOnce.Do(func() { sspiAuthErrInit = sspiAuthInit() }) |
|
|
|
sspiAuthOnce.Do(func() { |
|
|
|
if sspiAuthErrInit != nil { |
|
|
|
config := websspi.NewConfig() |
|
|
|
return nil, sspiAuthErrInit |
|
|
|
sspiAuth, errInit = websspi.New(config) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
if errInit != nil { |
|
|
|
|
|
|
|
return nil, errInit |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if !s.shouldAuthenticate(req) { |
|
|
|
if !s.shouldAuthenticate(req) { |
|
|
|
return nil, nil |
|
|
|
return nil, nil |
|
|
|
} |
|
|
|
} |