|
|
@ -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
|
|
|
|
}
|
|
|
|
}
|