Skip to content

Commit

Permalink
Merge branch 'master' into lunny/fix_webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
6543 authored Jan 6, 2021
2 parents 726b7e8 + d2ee122 commit b2de9dd
Show file tree
Hide file tree
Showing 19 changed files with 104 additions and 50 deletions.
24 changes: 24 additions & 0 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ steps:
GOSUMDB: sum.golang.org
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
pull: always
image: golang:1.15
Expand Down Expand Up @@ -85,6 +97,18 @@ steps:
- rm ./gitea # clean
depends_on: [checks-backend]

- name: build-backend-windows
image: golang:1.15
environment:
GO111MODULE: on
GOPROXY: off
GOOS: windows
GOARCH: amd64
TAGS: bindata gogit
commands:
- go build -mod=vendor -o gitea_windows
depends_on: [checks-backend]

- name: build-backend-386
image: golang:1.15
environment:
Expand Down
2 changes: 1 addition & 1 deletion docs/content/page/index.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ Windows, on architectures like amd64, i386, ARM, PowerPC, and others.
## Components

* Web framework: [Macaron](http://go-macaron.com/)
* ORM: [XORM](https://github.com/go-xorm/xorm)
* ORM: [XORM](https://xorm.io)
* UI components:
* [Semantic UI](http://semantic-ui.com/)
* [GitHub Octicons](https://octicons.github.com/)
Expand Down
2 changes: 1 addition & 1 deletion docs/content/page/index.fr-fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ Le but de ce projet est de fournir de la manière la plus simple, la plus rapide
## Composants

* Framework web : [Macaron](http://go-macaron.com/)
* ORM : [XORM](https://github.com/go-xorm/xorm)
* ORM: [XORM](https://xorm.io)
* Interface graphique :
* [Semantic UI](http://semantic-ui.com/)
* [GitHub Octicons](https://octicons.github.com/)
Expand Down
2 changes: 1 addition & 1 deletion docs/content/page/index.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Gitea的首要目标是创建一个极易安装,运行非常快速,安装和
## 组件

* Web框架: [Macaron](http://go-macaron.com/)
* ORM [XORM](https://github.com/go-xorm/xorm)
* ORM: [XORM](https://xorm.io)
* UI组件:
* [Semantic UI](http://semantic-ui.com/)
* [GitHub Octicons](https://octicons.github.com/)
Expand Down
2 changes: 1 addition & 1 deletion docs/content/page/index.zh-tw.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Gitea 的首要目標是建立一個容易安裝,運行快速,安装和使
## 元件

* Web 框架: [Macaron](http://go-macaron.com/)
* ORM: [XORM](https://github.com/go-xorm/xorm)
* ORM: [XORM](https://xorm.io)
* UI 元件:
* [Semantic UI](http://semantic-ui.com/)
* [GitHub Octicons](https://octicons.github.com/)
Expand Down
2 changes: 1 addition & 1 deletion modules/auth/sso/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (b *Basic) IsEnabled() bool {
// "Authorization" header of the request and returns the corresponding user object for that
// name/token on successful validation.
// 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")
if len(baHead) == 0 {
return nil
Expand Down
2 changes: 1 addition & 1 deletion modules/auth/sso/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ type SingleSignOn interface {
// or a new user object (with id = 0) populated with the information that was found
// in the authentication data (username or email).
// 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
}
2 changes: 1 addition & 1 deletion modules/auth/sso/oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (o *OAuth2) IsEnabled() bool {
// or the "Authorization" header and returns the corresponding user object for that ID.
// If verification is successful returns an existing user object.
// 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 {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion modules/auth/sso/reverseproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (r *ReverseProxy) IsEnabled() bool {
// If a username is available in the "setting.ReverseProxyAuthUser" header an existing
// user object is returned (populated with username or email found in header).
// 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)
if len(username) == 0 {
return nil
Expand Down
2 changes: 1 addition & 1 deletion modules/auth/sso/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
// object for that uid.
// 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)
if user != nil {
return user
Expand Down
67 changes: 35 additions & 32 deletions modules/auth/sso/sspi_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@ package sso
import (
"errors"
"net/http"
"reflect"
"strings"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"

"gitea.com/macaron/macaron"
"gitea.com/macaron/session"
"code.gitea.io/gitea/modules/templates"

gouuid "github.com/google/uuid"
"github.com/quasoft/websspi"
"github.com/unrolled/render"
)

const (
Expand All @@ -41,14 +39,26 @@ var (
// On successful authentication returns a valid user object.
// Returns nil if authentication fails.
type SSPI struct {
rnd *render.Render
}

// Init creates a new global websspi.Authenticator object
func (s *SSPI) Init() error {
config := websspi.NewConfig()
var err error
sspiAuth, err = websspi.New(config)
return err
if err != nil {
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
Expand All @@ -65,8 +75,8 @@ func (s *SSPI) IsEnabled() bool {
// If authentication is successful, returs the corresponding user object.
// If negotiation should continue or authentication fails, immediately returns a 401 HTTP
// response code, as required by the SPNEGO protocol.
func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionStore) *models.User {
if !s.shouldAuthenticate(ctx) {
func (s *SSPI) VerifyAuthData(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *models.User {
if !s.shouldAuthenticate(req) {
return nil
}

Expand All @@ -76,22 +86,29 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt
return nil
}

userInfo, outToken, err := sspiAuth.Authenticate(req, ctx.Resp)
userInfo, outToken, err := sspiAuth.Authenticate(req, w)
if err != nil {
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
// to login with another authentication method if SSPI authentication
// fails
addFlashErr(ctx, ctx.Tr("auth.sspi_auth_failed"))
ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn
ctx.Data["EnableSSPI"] = true
ctx.HTML(401, string(tplSignIn))
store.GetData()["Flash"] = map[string]string{
"ErrMsg": err.Error(),
}
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
}
if outToken != "" {
sspiAuth.AppendAuthenticateHeader(ctx.Resp, outToken)
sspiAuth.AppendAuthenticateHeader(w, outToken)
}

username := sanitizeUsername(userInfo.Username, cfg)
Expand All @@ -110,16 +127,16 @@ func (s *SSPI) VerifyAuthData(req *http.Request, store DataStore, sess SessionSt
log.Error("User '%s' not found", username)
return nil
}
user, err = s.newUser(ctx, username, cfg)
user, err = s.newUser(username, cfg)
if err != nil {
log.Error("CreateUser: %v", err)
return nil
}
}

// Make sure requests to API paths and PWA resources do not create a new session
if !isAPIPath(ctx) && !isAttachmentDownload(ctx) {
handleSignIn(ctx, sess, user)
if !isAPIPath(req) && !isAttachmentDownload(req) {
handleSignIn(w, req, sess, user)
}

return user
Expand All @@ -146,7 +163,7 @@ func (s *SSPI) shouldAuthenticate(req *http.Request) (shouldAuth bool) {
if path == "/user/login" {
if req.FormValue("user_name") != "" && req.FormValue("password") != "" {
shouldAuth = false
} else if ctx.Req.FormValue("auth_with_sspi") == "1" {
} else if req.FormValue("auth_with_sspi") == "1" {
shouldAuth = true
}
} else if isInternalPath(req) {
Expand Down Expand Up @@ -217,20 +234,6 @@ func sanitizeUsername(username string, cfg *models.SSPIConfig) string {
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.
// 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
Expand Down
4 changes: 2 additions & 2 deletions modules/auth/sso/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// SignedInUser returns the user object of signed user.
// 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 {
return nil, false
}
Expand All @@ -22,7 +22,7 @@ func SignedInUser(req *http.Request, ds DataStore, sess SessionStore) (*models.U
if !ssoMethod.IsEnabled() {
continue
}
user := ssoMethod.VerifyAuthData(req, ds, sess)
user := ssoMethod.VerifyAuthData(req, w, ds, sess)
if user != nil {
_, isBasic := ssoMethod.(*Basic)
return user, isBasic
Expand Down
2 changes: 1 addition & 1 deletion modules/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ func Contexter() macaron.Handler {
}

// 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 {
ctx.IsSigned = true
Expand Down
6 changes: 4 additions & 2 deletions modules/graceful/manager_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,17 @@ func (g *Manager) start() {

// Make SVC process
run := svc.Run
isInteractive, err := svc.IsAnInteractiveSession()
isInteractive, err := svc.IsWindowsService()
if err != nil {
log.Error("Unable to ascertain if running as an Interactive Session: %v", err)
return
}
if isInteractive {
run = debug.Run
}
go run(WindowsServiceName, g)
go func() {
_ = run(WindowsServiceName, g)
}()
}

// Execute makes Manager implement svc.Handler
Expand Down
2 changes: 1 addition & 1 deletion modules/log/console_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func enableVTMode(console windows.Handle) bool {
// 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
// handle to say don't color
mode = mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
err = windows.SetConsoleMode(console, mode)
return err == nil
}
Expand Down
Loading

0 comments on commit b2de9dd

Please sign in to comment.