From edf769d244c383de3267765fe0d53c49fdd84c72 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 28 Jul 2021 17:24:26 +0800 Subject: [PATCH 1/5] Use middleware but not new routers for http cors --- routers/web/repo/http.go | 25 +++++++++++++++++++------ routers/web/web.go | 24 ++++++++++++------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index b2a49e3e3a103..6d166e4386d77 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -33,19 +33,29 @@ import ( repo_service "code.gitea.io/gitea/services/repository" ) -// httpBase implementation git smart HTTP protocol -func httpBase(ctx *context.Context) (h *serviceHandler) { - if setting.Repository.DisableHTTPGit { +// HTTPMustEnabled check if http enabled +func HTTPMustEnabled() func(ctx *context.Context) { + if !setting.Repository.DisableHTTPGit { + return func(ctx *context.Context) {} + } + + return func(ctx *context.Context) { ctx.Resp.WriteHeader(http.StatusForbidden) _, err := ctx.Resp.Write([]byte("Interacting with repositories by HTTP protocol is not allowed")) if err != nil { log.Error(err.Error()) } - return } +} - if len(setting.Repository.AccessControlAllowOrigin) > 0 { - allowedOrigin := setting.Repository.AccessControlAllowOrigin +// HTTPCors check if cors matched +func HTTPCors() func(ctx *context.Context) { + var allowedOrigin = setting.Repository.AccessControlAllowOrigin + if len(allowedOrigin) == 0 { + return func(ctx *context.Context) {} + } + + return func(ctx *context.Context) { // Set CORS headers for browser-based git clients ctx.Resp.Header().Set("Access-Control-Allow-Origin", allowedOrigin) ctx.Resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, User-Agent") @@ -67,7 +77,10 @@ func httpBase(ctx *context.Context) (h *serviceHandler) { return } } +} +// httpBase implementation git smart HTTP protocol +func httpBase(ctx *context.Context) (h *serviceHandler) { username := ctx.Params(":username") reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git") diff --git a/routers/web/web.go b/routers/web/web.go index 889a89f0d4ae4..a91c5f50c3db3 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1346,18 +1346,18 @@ func RegisterRoutes(m *web.Route) { }, ignSignInAndCsrf, lfsServerEnabled) m.Group("", func() { - m.PostOptions("/git-upload-pack", repo.ServiceUploadPack) - m.PostOptions("/git-receive-pack", repo.ServiceReceivePack) - m.GetOptions("/info/refs", repo.GetInfoRefs) - m.GetOptions("/HEAD", repo.GetTextFile("HEAD")) - m.GetOptions("/objects/info/alternates", repo.GetTextFile("objects/info/alternates")) - m.GetOptions("/objects/info/http-alternates", repo.GetTextFile("objects/info/http-alternates")) - m.GetOptions("/objects/info/packs", repo.GetInfoPacks) - m.GetOptions("/objects/info/{file:[^/]*}", repo.GetTextFile("")) - m.GetOptions("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) - m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) - m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) - }, ignSignInAndCsrf, context_service.UserAssignmentWeb()) + m.Post("/git-upload-pack", repo.ServiceUploadPack) + m.Post("/git-receive-pack", repo.ServiceReceivePack) + m.Get("/info/refs", repo.GetInfoRefs) + m.Get("/HEAD", repo.GetTextFile("HEAD")) + m.Get("/objects/info/alternates", repo.GetTextFile("objects/info/alternates")) + m.Get("/objects/info/http-alternates", repo.GetTextFile("objects/info/http-alternates")) + m.Get("/objects/info/packs", repo.GetInfoPacks) + m.Get("/objects/info/{file:[^/]*}", repo.GetTextFile("")) + m.Get("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) + m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) + m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) + }, repo.HTTPMustEnabled, ignSignInAndCsrf, repo.HTTPCors, context_service.UserAssignmentWeb()) }) }) // ***** END: Repository ***** From d1087857483c721b184e1b68544af608b289262b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 29 Jul 2021 09:53:07 +0800 Subject: [PATCH 2/5] Fix bug --- routers/web/web.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/web.go b/routers/web/web.go index a91c5f50c3db3..6ff2834c592a6 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1357,7 +1357,7 @@ func RegisterRoutes(m *web.Route) { m.Get("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) - }, repo.HTTPMustEnabled, ignSignInAndCsrf, repo.HTTPCors, context_service.UserAssignmentWeb()) + }, repo.HTTPMustEnabled(), ignSignInAndCsrf, repo.HTTPCors(), context_service.UserAssignmentWeb()) }) }) // ***** END: Repository ***** From 1d5658d187a3f19e5f10ac7b5c15a60045f2df51 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 29 Jul 2021 21:52:43 +0800 Subject: [PATCH 3/5] Fix group middlewares cannot handler options method --- .../doc/advanced/config-cheat-sheet.en-us.md | 5 +++-- .../doc/advanced/config-cheat-sheet.zh-cn.md | 3 +++ routers/web/repo/http.go | 21 +++++++++++++------ routers/web/web.go | 1 + 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index dcf91c3396fb9..d6a460e4c7048 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -98,8 +98,9 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build - `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when default SSH port is used. - `ACCESS_CONTROL_ALLOW_ORIGIN`: **\**: Value for Access-Control-Allow-Origin header, - default is not to present. **WARNING**: This maybe harmful to you website if you do not - give it a right value. + default is not to present. You can give `*` to allow requests from any website or `null` to not allow any. + This allow multiple websites via comma an no space. i.e. `https://gitea.com,https://api.gitea.com` + **WARNING**: This maybe harmful to you website if you do not give it a right value. - `DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH`: **false**: Close an issue if a commit on a non default branch marks it as closed. - `ENABLE_PUSH_CREATE_USER`: **false**: Allow users to push local repositories to Gitea and have them automatically created for a user. - `ENABLE_PUSH_CREATE_ORG`: **false**: Allow users to push local repositories to Gitea and have them automatically created for an org. diff --git a/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md b/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md index f10b6258c87a2..66f9bd8d36d79 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md +++ b/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md @@ -42,6 +42,9 @@ menu: - `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 通过 ``push-to-create`` 方式创建的仓库是否默认为私有仓库. - `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。 - `PULL_REQUEST_QUEUE_LENGTH`: 小心:合并请求测试队列的长度,尽量放大。 +- `ACCESS_CONTROL_ALLOW_ORIGIN`: **\**: `Access-Control-Allow-Origin`请求头的值,默认为空。 + 设置为 `*` 将允许来自任意网站的请求,为 `null` 则屏蔽所有网站的请求。也可以允许用逗号连接的多个网址,比如: `https://gitea.com,https://api.gitea.com` + **警告**: 如果此项设置不正确,可能会对你的网站产生负面影响。 ### Repository - Release (`repository.release`) diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index 6d166e4386d77..bbc3195282e2d 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -50,25 +50,34 @@ func HTTPMustEnabled() func(ctx *context.Context) { // HTTPCors check if cors matched func HTTPCors() func(ctx *context.Context) { - var allowedOrigin = setting.Repository.AccessControlAllowOrigin - if len(allowedOrigin) == 0 { + var allowedOrigins = setting.Repository.AccessControlAllowOrigin + if len(allowedOrigins) == 0 { return func(ctx *context.Context) {} } return func(ctx *context.Context) { // Set CORS headers for browser-based git clients - ctx.Resp.Header().Set("Access-Control-Allow-Origin", allowedOrigin) + allowedOriginSlices := strings.Split(allowedOrigins, ",") + var matchAll util.OptionalBool // + for _, allowedOrigin := range allowedOriginSlices { + if allowedOrigin == "*" { + matchAll = util.OptionalBoolTrue + } else if allowedOrigin == "null" { + matchAll = util.OptionalBoolFalse + } + ctx.Resp.Header().Set("Access-Control-Allow-Origin", allowedOrigin) + } ctx.Resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, User-Agent") // Handle preflight OPTIONS request if ctx.Req.Method == "OPTIONS" { - if allowedOrigin == "*" { + if matchAll.IsTrue() { ctx.Status(http.StatusOK) - } else if allowedOrigin == "null" { + } else if matchAll.IsFalse() { ctx.Status(http.StatusForbidden) } else { origin := ctx.Req.Header.Get("Origin") - if len(origin) > 0 && origin == allowedOrigin { + if len(origin) > 0 && util.IsStringInSlice(origin, allowedOriginSlices) { ctx.Status(http.StatusOK) } else { ctx.Status(http.StatusForbidden) diff --git a/routers/web/web.go b/routers/web/web.go index 6ff2834c592a6..b7f36dd82cf36 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1357,6 +1357,7 @@ func RegisterRoutes(m *web.Route) { m.Get("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) + m.Options("/*", func(ctx *context.Context) {}) // to ensure middlewares could handle options requests }, repo.HTTPMustEnabled(), ignSignInAndCsrf, repo.HTTPCors(), context_service.UserAssignmentWeb()) }) }) From 5946ec5ff5c9c1af024c5ef4b224e900f738cc64 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 31 Jul 2021 01:06:11 +0800 Subject: [PATCH 4/5] Fix test --- routers/web/web.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/web.go b/routers/web/web.go index b7f36dd82cf36..fc9b1ecd113a0 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1357,7 +1357,7 @@ func RegisterRoutes(m *web.Route) { m.Get("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) - m.Options("/*", func(ctx *context.Context) {}) // to ensure middlewares could handle options requests + m.Options("/", func(ctx *context.Context) {}) // to ensure middlewares could handle options requests }, repo.HTTPMustEnabled(), ignSignInAndCsrf, repo.HTTPCors(), context_service.UserAssignmentWeb()) }) }) From 00a211e27454a37641c5b3f248a19931e0fc89e4 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 1 Aug 2021 10:06:05 +0800 Subject: [PATCH 5/5] Fix test --- routers/web/web.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/routers/web/web.go b/routers/web/web.go index fc9b1ecd113a0..d1fa3300a64c7 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1357,7 +1357,9 @@ func RegisterRoutes(m *web.Route) { m.Get("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile) m.Get("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile) - m.Options("/", func(ctx *context.Context) {}) // to ensure middlewares could handle options requests + m.Options("/*", func(ctx *context.Context) { + ctx.Resp.WriteHeader(http.StatusMethodNotAllowed) + }) // to ensure middlewares could handle options requests }, repo.HTTPMustEnabled(), ignSignInAndCsrf, repo.HTTPCors(), context_service.UserAssignmentWeb()) }) })