From b69dda0de915bc8b02946c9cf6063913425bfe68 Mon Sep 17 00:00:00 2001 From: John Bain Date: Tue, 5 Jul 2022 14:35:38 -0400 Subject: [PATCH 01/12] added code to match on asterisk wildcard --- services/forms/user_form.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 405b4a9a490f..a6184993d91e 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -9,6 +9,7 @@ import ( "mime/multipart" "net/http" "strings" + "path/filepath" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -118,7 +119,8 @@ func IsEmailDomainListed(list []string, email string) bool { domain := strings.ToLower(email[n+1:]) for _, v := range list { - if strings.ToLower(v) == domain { + matched, _ := filepath.Match(strings.ToLower(v), domain) + if matched { return true } } From 2d358eea268785fb3eab07beca4c18c21e57a995 Mon Sep 17 00:00:00 2001 From: John Bain Date: Tue, 5 Jul 2022 14:53:55 -0400 Subject: [PATCH 02/12] updated test to validate wildcard --- services/forms/user_form_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 9f67143d12c8..4239b6bf954f 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -44,7 +44,7 @@ func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = []string{"gitea.io"} + setting.Service.EmailDomainWhitelist = []string{"gitea.io", "*.gov"} tt := []struct { email string @@ -54,6 +54,7 @@ func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { {"security@gITea.io", true}, {"hdudhdd", false}, {"seee@example.com", false}, + {"security@fishsauce.gov", true}, } for _, v := range tt { From 4bc90fb76f3c18aca38df6802d16136bbf76c9ea Mon Sep 17 00:00:00 2001 From: John Bain Date: Fri, 8 Jul 2022 10:27:49 -0400 Subject: [PATCH 03/12] updated change to use glob for pattern matching --- services/forms/user_form.go | 7 ++++--- services/forms/user_form_test.go | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/services/forms/user_form.go b/services/forms/user_form.go index a6184993d91e..53fd80daa5bf 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -9,7 +9,8 @@ import ( "mime/multipart" "net/http" "strings" - "path/filepath" + + "github.com/gobwas/glob" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" @@ -119,8 +120,8 @@ func IsEmailDomainListed(list []string, email string) bool { domain := strings.ToLower(email[n+1:]) for _, v := range list { - matched, _ := filepath.Match(strings.ToLower(v), domain) - if matched { + g := glob.MustCompile(strings.ToLower(v)) + if g.Match(domain) { return true } } diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 4239b6bf954f..07ba8e1b21fd 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -68,7 +68,7 @@ func TestRegisterForm_IsDomainAllowed_BlocklistedEmail(t *testing.T) { _ = setting.Service setting.Service.EmailDomainWhitelist = []string{} - setting.Service.EmailDomainBlocklist = []string{"gitea.io"} + setting.Service.EmailDomainBlocklist = []string{"gitea.io", "*.gov"} tt := []struct { email string @@ -77,6 +77,7 @@ func TestRegisterForm_IsDomainAllowed_BlocklistedEmail(t *testing.T) { {"security@gitea.io", false}, {"security@gitea.example", true}, {"hdudhdd", true}, + {"security@fishsauce.gov", false}, } for _, v := range tt { From d85cdd2e5b5889ac12fc69288e02232fbad75593 Mon Sep 17 00:00:00 2001 From: John Bain Date: Fri, 8 Jul 2022 10:50:59 -0400 Subject: [PATCH 04/12] should resolve issue with liniting --- services/forms/user_form.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 53fd80daa5bf..9864d11b9568 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -10,14 +10,14 @@ import ( "net/http" "strings" - "github.com/gobwas/glob" - "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web/middleware" "gitea.com/go-chi/binding" + + "github.com/gobwas/glob" ) // InstallForm form for installation page From 4488d979e4988d7b155b0fc858983d8efbae74c4 Mon Sep 17 00:00:00 2001 From: John Bain Date: Mon, 11 Jul 2022 14:28:44 -0400 Subject: [PATCH 05/12] Update services/forms/user_form.go removed extra line --- services/forms/user_form.go | 1 - 1 file changed, 1 deletion(-) diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 9864d11b9568..9d44e634cb6d 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -16,7 +16,6 @@ import ( "code.gitea.io/gitea/modules/web/middleware" "gitea.com/go-chi/binding" - "github.com/gobwas/glob" ) From 8063c65c1616bdea1fb26c320716b06bdccbfd2c Mon Sep 17 00:00:00 2001 From: John Bain Date: Thu, 21 Jul 2022 23:27:03 -0400 Subject: [PATCH 06/12] made changes to use an array of compiled globs --- services/forms/user_form.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 9d44e634cb6d..a0fa39ab2f83 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -106,7 +106,7 @@ func (f *RegisterForm) Validate(req *http.Request, errs binding.Errors) binding. // IsEmailDomainListed checks whether the domain of an email address // matches a list of domains -func IsEmailDomainListed(list []string, email string) bool { +func IsEmailDomainListed(list []glob.Glob, email string) bool { if len(list) == 0 { return false } @@ -118,9 +118,8 @@ func IsEmailDomainListed(list []string, email string) bool { domain := strings.ToLower(email[n+1:]) - for _, v := range list { - g := glob.MustCompile(strings.ToLower(v)) - if g.Match(domain) { + for _, l := range list { + if l.Match(domain) { return true } } @@ -128,6 +127,21 @@ func IsEmailDomainListed(list []string, email string) bool { return false } +// BuildEmailGlobs takes in an array of strings and +// builds an array of compiled globs used to do +// pattern matching in IsEmailDomainAllowed. A compiled list +func BuildEmailGlobs(list []string) []glob.Glob { + var EmailList []glob.Glob + + for _, s := range list { + if g, err := glob.Compile(s); err == nil { + EmailList = append(EmailList, g) + } + } + + return EmailList +} + // IsEmailDomainAllowed validates that the email address // provided by the user matches what has been configured . // The email is marked as allowed if it matches any of the @@ -135,10 +149,10 @@ func IsEmailDomainListed(list []string, email string) bool { // domains in the blocklist, if any such list is not empty. func (f RegisterForm) IsEmailDomainAllowed() bool { if len(setting.Service.EmailDomainWhitelist) == 0 { - return !IsEmailDomainListed(setting.Service.EmailDomainBlocklist, f.Email) + return !IsEmailDomainListed(BuildEmailGlobs(setting.Service.EmailDomainBlocklist), f.Email) } - return IsEmailDomainListed(setting.Service.EmailDomainWhitelist, f.Email) + return IsEmailDomainListed(BuildEmailGlobs(setting.Service.EmailDomainWhitelist), f.Email) } // MustChangePasswordForm form for updating your password after account creation From 5cba7beb7c6cd135aa803a08f1a30040cf472287 Mon Sep 17 00:00:00 2001 From: John Bain Date: Mon, 12 Sep 2022 12:05:05 -0400 Subject: [PATCH 07/12] Moved BuildEmailGlobs to service.go --- modules/setting/service.go | 24 ++++++++++++++++++++---- services/forms/user_form.go | 19 ++----------------- services/forms/user_form_test.go | 26 +++++++++++++++++++++----- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/modules/setting/service.go b/modules/setting/service.go index 10e389995032..103c2b700ea7 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" + "github.com/gobwas/glob" ) // Service settings @@ -25,8 +26,8 @@ var Service = struct { ResetPwdCodeLives int RegisterEmailConfirm bool RegisterManualConfirm bool - EmailDomainWhitelist []string - EmailDomainBlocklist []string + EmailDomainWhitelist []glob.Glob + EmailDomainBlocklist []glob.Glob DisableRegistration bool AllowOnlyInternalRegistration bool AllowOnlyExternalRegistration bool @@ -103,6 +104,21 @@ func (a AllowedVisibility) ToVisibleTypeSlice() (result []structs.VisibleType) { return result } +// BuildEmailGlobs takes in an array of strings and +// builds an array of compiled globs used to do +// pattern matching in IsEmailDomainAllowed. A compiled list +func BuildEmailGlobs(list []string) []glob.Glob { + var EmailList []glob.Glob + + for _, s := range list { + if g, err := glob.Compile(s); err == nil { + EmailList = append(EmailList, g) + } + } + + return EmailList +} + func newService() { sec := Cfg.Section("service") Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180) @@ -119,8 +135,8 @@ func newService() { } else { Service.RegisterManualConfirm = false } - Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",") - Service.EmailDomainBlocklist = sec.Key("EMAIL_DOMAIN_BLOCKLIST").Strings(",") + Service.EmailDomainWhitelist = BuildEmailGlobs(sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",")) + Service.EmailDomainBlocklist = BuildEmailGlobs(sec.Key("EMAIL_DOMAIN_BLOCKLIST").Strings(",")) Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration)) Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true) Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool() diff --git a/services/forms/user_form.go b/services/forms/user_form.go index b24403d50e8a..5e403c52ed07 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -129,21 +129,6 @@ func IsEmailDomainListed(list []glob.Glob, email string) bool { return false } -// BuildEmailGlobs takes in an array of strings and -// builds an array of compiled globs used to do -// pattern matching in IsEmailDomainAllowed. A compiled list -func BuildEmailGlobs(list []string) []glob.Glob { - var EmailList []glob.Glob - - for _, s := range list { - if g, err := glob.Compile(s); err == nil { - EmailList = append(EmailList, g) - } - } - - return EmailList -} - // IsEmailDomainAllowed validates that the email address // provided by the user matches what has been configured . // The email is marked as allowed if it matches any of the @@ -151,10 +136,10 @@ func BuildEmailGlobs(list []string) []glob.Glob { // domains in the blocklist, if any such list is not empty. func (f RegisterForm) IsEmailDomainAllowed() bool { if len(setting.Service.EmailDomainWhitelist) == 0 { - return !IsEmailDomainListed(BuildEmailGlobs(setting.Service.EmailDomainBlocklist), f.Email) + return !IsEmailDomainListed(setting.Service.EmailDomainBlocklist, f.Email) } - return IsEmailDomainListed(BuildEmailGlobs(setting.Service.EmailDomainWhitelist), f.Email) + return IsEmailDomainListed(setting.Service.EmailDomainWhitelist, f.Email) } // MustChangePasswordForm form for updating your password after account creation diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 07ba8e1b21fd..8e759b36143b 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -9,13 +9,29 @@ import ( "code.gitea.io/gitea/modules/setting" + "github.com/gobwas/glob" "github.com/stretchr/testify/assert" ) +// BuildEmailGlobs takes in an array of strings and +// builds an array of compiled globs used to do +// pattern matching in IsEmailDomainAllowed. A compiled list +func BuildEmailGlobs(list []string) []glob.Glob { + var EmailList []glob.Glob + + for _, s := range list { + if g, err := glob.Compile(s); err == nil { + EmailList = append(EmailList, g) + } + } + + return EmailList +} + func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = []string{} + setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{}) form := RegisterForm{} @@ -25,7 +41,7 @@ func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) { func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = []string{"gitea.io"} + setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{"gitea.io"}) tt := []struct { email string @@ -44,7 +60,7 @@ func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = []string{"gitea.io", "*.gov"} + setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{"gitea.io", "*.gov"}) tt := []struct { email string @@ -67,8 +83,8 @@ func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { func TestRegisterForm_IsDomainAllowed_BlocklistedEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = []string{} - setting.Service.EmailDomainBlocklist = []string{"gitea.io", "*.gov"} + setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{}) + setting.Service.EmailDomainBlocklist = BuildEmailGlobs([]string{"gitea.io", "*.gov"}) tt := []struct { email string From 3778a30e06ddaccfcf1375a0170ce7fa9f01dbd9 Mon Sep 17 00:00:00 2001 From: John Bain Date: Mon, 12 Sep 2022 12:12:51 -0400 Subject: [PATCH 08/12] called BuildEmailGlobs from settings pkg --- services/forms/user_form_test.go | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 8e759b36143b..8c5c140ae55d 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -9,29 +9,13 @@ import ( "code.gitea.io/gitea/modules/setting" - "github.com/gobwas/glob" "github.com/stretchr/testify/assert" ) -// BuildEmailGlobs takes in an array of strings and -// builds an array of compiled globs used to do -// pattern matching in IsEmailDomainAllowed. A compiled list -func BuildEmailGlobs(list []string) []glob.Glob { - var EmailList []glob.Glob - - for _, s := range list { - if g, err := glob.Compile(s); err == nil { - EmailList = append(EmailList, g) - } - } - - return EmailList -} - func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{}) + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{}) form := RegisterForm{} @@ -41,7 +25,7 @@ func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) { func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{"gitea.io"}) + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{"gitea.io"}) tt := []struct { email string @@ -60,7 +44,7 @@ func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{"gitea.io", "*.gov"}) + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{"gitea.io", "*.gov"}) tt := []struct { email string @@ -83,8 +67,8 @@ func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { func TestRegisterForm_IsDomainAllowed_BlocklistedEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = BuildEmailGlobs([]string{}) - setting.Service.EmailDomainBlocklist = BuildEmailGlobs([]string{"gitea.io", "*.gov"}) + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{}) + setting.Service.EmailDomainBlocklist = setting.BuildEmailGlobs([]string{"gitea.io", "*.gov"}) tt := []struct { email string From 55b21a7d007df50e1ddd7e2f1e19a2a653e93fad Mon Sep 17 00:00:00 2001 From: John Bain Date: Thu, 15 Sep 2022 11:06:25 -0400 Subject: [PATCH 09/12] included capturing glob compile erro catching. --- modules/setting/service.go | 2 ++ services/forms/user_form_test.go | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/setting/service.go b/modules/setting/service.go index 103c2b700ea7..296d54222ad7 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -113,6 +113,8 @@ func BuildEmailGlobs(list []string) []glob.Glob { for _, s := range list { if g, err := glob.Compile(s); err == nil { EmailList = append(EmailList, g) + } else { + log.Error("glob.Compile %s failed: %v", s, err) } } diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 8c5c140ae55d..b6a760fa443f 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -44,7 +44,7 @@ func TestRegisterForm_IsDomainAllowed_InvalidEmail(t *testing.T) { func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{"gitea.io", "*.gov"}) + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{"gitea.io", "*.gc.ca"}) tt := []struct { email string @@ -54,7 +54,7 @@ func TestRegisterForm_IsDomainAllowed_WhitelistedEmail(t *testing.T) { {"security@gITea.io", true}, {"hdudhdd", false}, {"seee@example.com", false}, - {"security@fishsauce.gov", true}, + {"security@fishsauce.gc.ca", true}, } for _, v := range tt { From dbafa367ba00cae98387181a86997836fd4ea09c Mon Sep 17 00:00:00 2001 From: John Bain Date: Mon, 24 Oct 2022 08:33:47 -0400 Subject: [PATCH 10/12] space added to import statements, local variable name made lowercase. --- modules/setting/service.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/setting/service.go b/modules/setting/service.go index 296d54222ad7..75c91f35863e 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" + "github.com/gobwas/glob" ) @@ -108,17 +109,17 @@ func (a AllowedVisibility) ToVisibleTypeSlice() (result []structs.VisibleType) { // builds an array of compiled globs used to do // pattern matching in IsEmailDomainAllowed. A compiled list func BuildEmailGlobs(list []string) []glob.Glob { - var EmailList []glob.Glob + var emaillist []glob.Glob for _, s := range list { if g, err := glob.Compile(s); err == nil { - EmailList = append(EmailList, g) + emaillist = append(emaillist, g) } else { log.Error("glob.Compile %s failed: %v", s, err) } } - return EmailList + return emaillist } func newService() { From 7752c87c749a08095bdfa8a7c0d0a834194f4334 Mon Sep 17 00:00:00 2001 From: John Bain Date: Mon, 24 Oct 2022 08:35:38 -0400 Subject: [PATCH 11/12] updaed message to show glob will be skipped --- modules/setting/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting/service.go b/modules/setting/service.go index 75c91f35863e..f1721a6d92b9 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -115,7 +115,7 @@ func BuildEmailGlobs(list []string) []glob.Glob { if g, err := glob.Compile(s); err == nil { emaillist = append(emaillist, g) } else { - log.Error("glob.Compile %s failed: %v", s, err) + log.Warn("Invalid glob expression %q (skipped): %v", s, err) } } From 404685a8ae12a2591a58465778529a2eb7d26f5e Mon Sep 17 00:00:00 2001 From: John Bain Date: Mon, 24 Oct 2022 08:36:58 -0400 Subject: [PATCH 12/12] added space to import statements --- services/forms/user_form.go | 1 + 1 file changed, 1 insertion(+) diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 5e403c52ed07..377c1db6e294 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/web/middleware" "gitea.com/go-chi/binding" + "github.com/gobwas/glob" )