diff --git a/modules/setting/service.go b/modules/setting/service.go index 10e389995032..f1721a6d92b9 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -11,6 +11,8 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" + + "github.com/gobwas/glob" ) // Service settings @@ -25,8 +27,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 +105,23 @@ 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) + } else { + log.Warn("Invalid glob expression %q (skipped): %v", s, err) + } + } + + return emaillist +} + func newService() { sec := Cfg.Section("service") Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180) @@ -119,8 +138,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 036c2ca3ec2c..a8a890bb5dd5 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -16,6 +16,8 @@ import ( "code.gitea.io/gitea/modules/web/middleware" "gitea.com/go-chi/binding" + + "github.com/gobwas/glob" ) // InstallForm form for installation page @@ -107,7 +109,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 } @@ -119,8 +121,8 @@ func IsEmailDomainListed(list []string, email string) bool { domain := strings.ToLower(email[n+1:]) - for _, v := range list { - if strings.ToLower(v) == domain { + for _, l := range list { + if l.Match(domain) { return true } } diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 9f67143d12c8..b6a760fa443f 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -15,7 +15,7 @@ import ( func TestRegisterForm_IsDomainAllowed_Empty(t *testing.T) { _ = setting.Service - setting.Service.EmailDomainWhitelist = []string{} + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{}) form := RegisterForm{} @@ -25,7 +25,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 = setting.BuildEmailGlobs([]string{"gitea.io"}) tt := []struct { email string @@ -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 = setting.BuildEmailGlobs([]string{"gitea.io", "*.gc.ca"}) 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.gc.ca", true}, } for _, v := range tt { @@ -66,8 +67,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"} + setting.Service.EmailDomainWhitelist = setting.BuildEmailGlobs([]string{}) + setting.Service.EmailDomainBlocklist = setting.BuildEmailGlobs([]string{"gitea.io", "*.gov"}) tt := []struct { email string @@ -76,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 {