forked from gitea/gitea
		
	Fix windows build error (#14263)
* fix build * take flash error message back and fix more windows lint error * performance optimization * own step to check lint for windows Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
		
							parent
							
								
									4ef5f17a7e
								
							
						
					
					
						commit
						a1c9e8f266
					
				
							
								
								
									
										12
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								.drone.yml
									
									
									
									
									
								
							| @ -33,6 +33,18 @@ steps: | |||||||
|       GOSUMDB: sum.golang.org |       GOSUMDB: sum.golang.org | ||||||
|       TAGS: bindata sqlite sqlite_unlock_notify |       TAGS: bindata sqlite sqlite_unlock_notify | ||||||
| 
 | 
 | ||||||
|  |   - name: lint-backend-windows | ||||||
|  |     pull: always | ||||||
|  |     image: golang:1.15 | ||||||
|  |     commands: | ||||||
|  |       - make golangci-lint vet | ||||||
|  |     environment: | ||||||
|  |       GOPROXY: https://goproxy.cn # proxy.golang.org is blocked in China, this proxy is not | ||||||
|  |       GOSUMDB: sum.golang.org | ||||||
|  |       TAGS: bindata sqlite sqlite_unlock_notify | ||||||
|  |       GOOS: windows | ||||||
|  |       GOARCH: amd64 | ||||||
|  | 
 | ||||||
|   - name: lint-backend-gogit |   - name: lint-backend-gogit | ||||||
|     pull: always |     pull: always | ||||||
|     image: golang:1.15 |     image: golang:1.15 | ||||||
|  | |||||||
| @ -47,7 +47,7 @@ func (b *Basic) IsEnabled() bool { | |||||||
| // "Authorization" header of the request and returns the corresponding user object for that | // "Authorization" header of the request and returns the corresponding user object for that | ||||||
| // name/token on successful validation. | // name/token on successful validation. | ||||||
| // Returns nil if header is empty or validation fails. | // Returns nil if header is empty or validation fails. | ||||||
| func (b *Basic) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | func (b *Basic) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||||
| 	baHead := req.Header.Get("Authorization") | 	baHead := req.Header.Get("Authorization") | ||||||
| 	if len(baHead) == 0 { | 	if len(baHead) == 0 { | ||||||
| 		return nil | 		return nil | ||||||
|  | |||||||
| @ -40,5 +40,5 @@ type SingleSignOn interface { | |||||||
| 	// or a new user object (with id = 0) populated with the information that was found | 	// or a new user object (with id = 0) populated with the information that was found | ||||||
| 	// in the authentication data (username or email). | 	// in the authentication data (username or email). | ||||||
| 	// Returns nil if verification fails. | 	// Returns nil if verification fails. | ||||||
| 	VerifyAuthData(http *http.Request, store DataStore, sess SessionStore) *models.User | 	VerifyAuthData(http *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User | ||||||
| } | } | ||||||
|  | |||||||
| @ -114,7 +114,7 @@ func (o *OAuth2) IsEnabled() bool { | |||||||
| // or the "Authorization" header and returns the corresponding user object for that ID. | // or the "Authorization" header and returns the corresponding user object for that ID. | ||||||
| // If verification is successful returns an existing user object. | // If verification is successful returns an existing user object. | ||||||
| // Returns nil if verification fails. | // Returns nil if verification fails. | ||||||
| func (o *OAuth2) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | func (o *OAuth2) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||||
| 	if !models.HasEngine { | 	if !models.HasEngine { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -60,7 +60,7 @@ func (r *ReverseProxy) IsEnabled() bool { | |||||||
| // If a username is available in the "setting.ReverseProxyAuthUser" header an existing | // If a username is available in the "setting.ReverseProxyAuthUser" header an existing | ||||||
| // user object is returned (populated with username or email found in header). | // user object is returned (populated with username or email found in header). | ||||||
| // Returns nil if header is empty. | // Returns nil if header is empty. | ||||||
| func (r *ReverseProxy) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | func (r *ReverseProxy) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||||
| 	username := r.getUserName(req) | 	username := r.getUserName(req) | ||||||
| 	if len(username) == 0 { | 	if len(username) == 0 { | ||||||
| 		return nil | 		return nil | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ func (s *Session) IsEnabled() bool { | |||||||
| // VerifyAuthData checks if there is a user uid stored in the session and returns the user | // VerifyAuthData checks if there is a user uid stored in the session and returns the user | ||||||
| // object for that uid. | // object for that uid. | ||||||
| // Returns nil if there is no user uid stored in the session. | // Returns nil if there is no user uid stored in the session. | ||||||
| func (s *Session) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | func (s *Session) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||||
| 	user := SessionUser(sess) | 	user := SessionUser(sess) | ||||||
| 	if user != nil { | 	if user != nil { | ||||||
| 		return user | 		return user | ||||||
|  | |||||||
| @ -7,19 +7,17 @@ package sso | |||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"reflect" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"code.gitea.io/gitea/models" | 	"code.gitea.io/gitea/models" | ||||||
| 	"code.gitea.io/gitea/modules/base" | 	"code.gitea.io/gitea/modules/base" | ||||||
| 	"code.gitea.io/gitea/modules/log" | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 
 | 	"code.gitea.io/gitea/modules/templates" | ||||||
| 	"gitea.com/macaron/macaron" |  | ||||||
| 	"gitea.com/macaron/session" |  | ||||||
| 
 | 
 | ||||||
| 	gouuid "github.com/google/uuid" | 	gouuid "github.com/google/uuid" | ||||||
| 	"github.com/quasoft/websspi" | 	"github.com/quasoft/websspi" | ||||||
|  | 	"github.com/unrolled/render" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| @ -41,6 +39,7 @@ var ( | |||||||
| // On successful authentication returns a valid user object. | // On successful authentication returns a valid user object. | ||||||
| // Returns nil if authentication fails. | // Returns nil if authentication fails. | ||||||
| type SSPI struct { | type SSPI struct { | ||||||
|  | 	rnd *render.Render | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Init creates a new global websspi.Authenticator object | // Init creates a new global websspi.Authenticator object | ||||||
| @ -48,8 +47,19 @@ func (s *SSPI) Init() error { | |||||||
| 	config := websspi.NewConfig() | 	config := websspi.NewConfig() | ||||||
| 	var err error | 	var err error | ||||||
| 	sspiAuth, err = websspi.New(config) | 	sspiAuth, err = websspi.New(config) | ||||||
|  | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	s.rnd = render.New(render.Options{ | ||||||
|  | 		Extensions:    []string{".tmpl"}, | ||||||
|  | 		Directory:     "templates", | ||||||
|  | 		Funcs:         templates.NewFuncMap(), | ||||||
|  | 		Asset:         templates.GetAsset, | ||||||
|  | 		AssetNames:    templates.GetAssetNames, | ||||||
|  | 		IsDevelopment: setting.RunMode != "prod", | ||||||
|  | 	}) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // Free releases resources used by the global websspi.Authenticator object | // Free releases resources used by the global websspi.Authenticator object | ||||||
| func (s *SSPI) Free() error { | func (s *SSPI) Free() error { | ||||||
| @ -65,8 +75,8 @@ func (s *SSPI) IsEnabled() bool { | |||||||
| // If authentication is successful, returs the corresponding user object. | // If authentication is successful, returs the corresponding user object. | ||||||
| // 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) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User { | func (s *SSPI) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User { | ||||||
| 	if !s.shouldAuthenticate(ctx) { | 	if !s.shouldAuthenticate(req) { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -76,22 +86,29 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	userInfo, outToken, err := sspiAuth.Authenticate(req, ctx.Resp) | 	userInfo, outToken, err := sspiAuth.Authenticate(req, w) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Warn("Authentication failed with error: %v\n", err) | 		log.Warn("Authentication failed with error: %v\n", err) | ||||||
| 		sspiAuth.AppendAuthenticateHeader(ctx.Resp, outToken) | 		sspiAuth.AppendAuthenticateHeader(w, outToken) | ||||||
| 
 | 
 | ||||||
| 		// Include the user login page in the 401 response to allow the user | 		// Include the user login page in the 401 response to allow the user | ||||||
| 		// to login with another authentication method if SSPI authentication | 		// to login with another authentication method if SSPI authentication | ||||||
| 		// fails | 		// fails | ||||||
| 		addFlashErr(ctx, ctx.Tr("auth.sspi_auth_failed")) | 		store.GetData()["Flash"] = map[string]string{ | ||||||
| 		ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn | 			"ErrMsg": err.Error(), | ||||||
| 		ctx.Data["EnableSSPI"] = true | 		} | ||||||
| 		ctx.HTML(401, string(tplSignIn)) | 		store.GetData()["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn | ||||||
|  | 		store.GetData()["EnableSSPI"] = true | ||||||
|  | 
 | ||||||
|  | 		err := s.rnd.HTML(w, 401, string(tplSignIn), templates.BaseVars().Merge(store.GetData())) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("%v", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	if outToken != "" { | 	if outToken != "" { | ||||||
| 		sspiAuth.AppendAuthenticateHeader(ctx.Resp, outToken) | 		sspiAuth.AppendAuthenticateHeader(w, outToken) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	username := sanitizeUsername(userInfo.Username, cfg) | 	username := sanitizeUsername(userInfo.Username, cfg) | ||||||
| @ -110,7 +127,7 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt | |||||||
| 			log.Error("User '%s' not found", username) | 			log.Error("User '%s' not found", username) | ||||||
| 			return nil | 			return nil | ||||||
| 		} | 		} | ||||||
| 		user, err = s.newUser(ctx, username, cfg) | 		user, err = s.newUser(username, cfg) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Error("CreateUser: %v", err) | 			log.Error("CreateUser: %v", err) | ||||||
| 			return nil | 			return nil | ||||||
| @ -118,8 +135,8 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Make sure requests to API paths and PWA resources do not create a new session | 	// Make sure requests to API paths and PWA resources do not create a new session | ||||||
| 	if !isAPIPath(ctx) && !isAttachmentDownload(ctx) { | 	if !isAPIPath(req) && !isAttachmentDownload(req) { | ||||||
| 		handleSignIn(ctx, sess, user) | 		handleSignIn(w, req, sess, user) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return user | 	return user | ||||||
| @ -146,7 +163,7 @@ func (s *SSPI) shouldAuthenticate(req *http.Request) (shouldAuth bool) { | |||||||
| 	if path == "/user/login" { | 	if path == "/user/login" { | ||||||
| 		if req.FormValue("user_name") != "" && req.FormValue("password") != "" { | 		if req.FormValue("user_name") != "" && req.FormValue("password") != "" { | ||||||
| 			shouldAuth = false | 			shouldAuth = false | ||||||
| 		} else if ctx.Req.FormValue("auth_with_sspi") == "1" { | 		} else if req.FormValue("auth_with_sspi") == "1" { | ||||||
| 			shouldAuth = true | 			shouldAuth = true | ||||||
| 		} | 		} | ||||||
| 	} else if isInternalPath(req) { | 	} else if isInternalPath(req) { | ||||||
| @ -217,20 +234,6 @@ func sanitizeUsername(username string, cfg *models.SSPIConfig) string { | |||||||
| 	return username | 	return username | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // addFlashErr adds an error message to the Flash object mapped to a macaron.Context |  | ||||||
| func addFlashErr(ctx *macaron.Context, err string) { |  | ||||||
| 	fv := ctx.GetVal(reflect.TypeOf(&session.Flash{})) |  | ||||||
| 	if !fv.IsValid() { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	flash, ok := fv.Interface().(*session.Flash) |  | ||||||
| 	if !ok { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	flash.Error(err) |  | ||||||
| 	ctx.Data["Flash"] = flash |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // init registers the SSPI auth method as the last method in the list. | // init registers the SSPI auth method as the last method in the list. | ||||||
| // The SSPI plugin is expected to be executed last, as it returns 401 status code if negotiation | // The SSPI plugin is expected to be executed last, as it returns 401 status code if negotiation | ||||||
| // fails (or if negotiation should continue), which would prevent other authentication methods | // fails (or if negotiation should continue), which would prevent other authentication methods | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ import ( | |||||||
| 
 | 
 | ||||||
| // SignedInUser returns the user object of signed user. | // SignedInUser returns the user object of signed user. | ||||||
| // It returns a bool value to indicate whether user uses basic auth or not. | // It returns a bool value to indicate whether user uses basic auth or not. | ||||||
| func SignedInUser(req *http.Request, ds DataStore, sess SessionStore) (*models.User, bool) { | func SignedInUser(req *http.Request, w http.ResponseWriter, ds DataStore, sess SessionStore) (*models.User, bool) { | ||||||
| 	if !models.HasEngine { | 	if !models.HasEngine { | ||||||
| 		return nil, false | 		return nil, false | ||||||
| 	} | 	} | ||||||
| @ -22,7 +22,7 @@ func SignedInUser(req *http.Request, ds DataStore, sess SessionStore) (*models.U | |||||||
| 		if !ssoMethod.IsEnabled() { | 		if !ssoMethod.IsEnabled() { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		user := ssoMethod.VerifyAuthData(req, ds, sess) | 		user := ssoMethod.VerifyAuthData(req, w, ds, sess) | ||||||
| 		if user != nil { | 		if user != nil { | ||||||
| 			_, isBasic := ssoMethod.(*Basic) | 			_, isBasic := ssoMethod.(*Basic) | ||||||
| 			return user, isBasic | 			return user, isBasic | ||||||
|  | |||||||
| @ -309,7 +309,7 @@ func Contexter() macaron.Handler { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Get user from session if logged in. | 		// Get user from session if logged in. | ||||||
| 		ctx.User, ctx.IsBasicAuth = sso.SignedInUser(ctx.Req.Request, ctx, ctx.Session) | 		ctx.User, ctx.IsBasicAuth = sso.SignedInUser(ctx.Req.Request, c.Resp, ctx, ctx.Session) | ||||||
| 
 | 
 | ||||||
| 		if ctx.User != nil { | 		if ctx.User != nil { | ||||||
| 			ctx.IsSigned = true | 			ctx.IsSigned = true | ||||||
|  | |||||||
| @ -73,7 +73,7 @@ func (g *Manager) start() { | |||||||
| 
 | 
 | ||||||
| 	// Make SVC process | 	// Make SVC process | ||||||
| 	run := svc.Run | 	run := svc.Run | ||||||
| 	isInteractive, err := svc.IsAnInteractiveSession() | 	isInteractive, err := svc.IsWindowsService() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("Unable to ascertain if running as an Interactive Session: %v", err) | 		log.Error("Unable to ascertain if running as an Interactive Session: %v", err) | ||||||
| 		return | 		return | ||||||
| @ -81,7 +81,9 @@ func (g *Manager) start() { | |||||||
| 	if isInteractive { | 	if isInteractive { | ||||||
| 		run = debug.Run | 		run = debug.Run | ||||||
| 	} | 	} | ||||||
| 	go run(WindowsServiceName, g) | 	go func() { | ||||||
|  | 		_ = run(WindowsServiceName, g) | ||||||
|  | 	}() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Execute makes Manager implement svc.Handler | // Execute makes Manager implement svc.Handler | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ func enableVTMode(console windows.Handle) bool { | |||||||
| 	// https://docs.microsoft.com/en-us/windows/console/setconsolemode | 	// https://docs.microsoft.com/en-us/windows/console/setconsolemode | ||||||
| 	// It only works on windows 10. Earlier terminals will fail with an err which we will | 	// It only works on windows 10. Earlier terminals will fail with an err which we will | ||||||
| 	// handle to say don't color | 	// handle to say don't color | ||||||
| 	mode = mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | 	mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | ||||||
| 	err = windows.SetConsoleMode(console, mode) | 	err = windows.SetConsoleMode(console, mode) | ||||||
| 	return err == nil | 	return err == nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -75,7 +75,7 @@ func Recovery() func(next http.Handler) http.Handler { | |||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					// Get user from session if logged in. | 					// Get user from session if logged in. | ||||||
| 					user, _ := sso.SignedInUser(req, &store, sess) | 					user, _ := sso.SignedInUser(req, w, &store, sess) | ||||||
| 					if user != nil { | 					if user != nil { | ||||||
| 						store.Data["IsSigned"] = true | 						store.Data["IsSigned"] = true | ||||||
| 						store.Data["SignedUser"] = user | 						store.Data["SignedUser"] = user | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 GitHub
							GitHub