Add email whitelist wildcard (#2375)

* add wildcard for email whitelisting

---------

Co-authored-by: Kevin Chung <kchung@ctfd.io>
This commit is contained in:
Miłosz Skaza
2023-07-26 21:36:55 +02:00
committed by GitHub
parent c2a13e55a7
commit 56c5942259
3 changed files with 101 additions and 3 deletions

View File

@@ -31,7 +31,7 @@ class ResetInstanceForm(BaseForm):
class AccountSettingsForm(BaseForm):
domain_whitelist = StringField(
"Account Email Whitelist",
description="Comma-seperated email domains which users can register under (e.g. ctfd.io, gmail.com, yahoo.com)",
description="Comma-seperated email domains which users can register under (e.g. ctfd.io, example.com, *.example.com)",
)
team_creation = SelectField(
"Team Creation",

View File

@@ -137,8 +137,26 @@ def user_created_notification(addr, name, password):
def check_email_is_whitelisted(email_address):
local_id, _, domain = email_address.partition("@")
domain_whitelist = get_config("domain_whitelist")
if domain_whitelist:
domain_whitelist = [d.strip() for d in domain_whitelist.split(",")]
if domain not in domain_whitelist:
return False
for allowed_domain in domain_whitelist:
if allowed_domain.startswith("*."):
# domains should never container the "*" char
if "*" in domain:
return False
# Handle wildcard domain case
suffix = allowed_domain[1:] # Remove the "*" prefix
if domain.endswith(suffix):
return True
elif domain == allowed_domain:
return True
# whitelist is specified but the email doesn't match any domains
return False
# whitelist is not specified - allow all emails
return True

View File

@@ -6,6 +6,7 @@ from freezegun import freeze_time
from CTFd.utils import get_config, set_config
from CTFd.utils.email import (
check_email_is_whitelisted,
sendmail,
successful_registration_notification,
verify_email_address,
@@ -239,3 +240,82 @@ def test_successful_registration_email(mock_smtp):
email_msg
)
destroy_ctfd(app)
def test_email_whitelist():
app = create_ctfd()
with app.app_context():
set_config("domain_whitelist", "example.com")
test_cases_specific_domain = [
("john.doe@example.com", True),
("john.doe@ext.example.com", False),
("john.doe@example.io", False),
("john.doe@example.co", False),
("john.doe@ample.com", False),
("john.doe@exexample.com", False),
]
for case in test_cases_specific_domain:
email, expected = case
assert check_email_is_whitelisted(email) is expected
set_config("domain_whitelist", "*.example.com")
test_cases_wildcard_domain = [
("john.doe@ext.example.com", True),
("john.doe@.example.com", True), # this is expected behaviour
("john.doe@example.com", False),
("john.doe@example.io", False),
("john.doe@example.co", False),
("john.doe@ample.com", False),
("john.doe@exexample.com", False),
("john.doe@*example.com", False),
("john.doe@*.example.com", False),
]
for case in test_cases_wildcard_domain:
email, expected = case
assert check_email_is_whitelisted(email) is expected
set_config("domain_whitelist", "example.com, *.example.com")
test_cases_combined_domain = [
("john.doe@example.com", True),
("john.doe@ext.example.com", True),
("john.doe@.example.com", True), # this is expected behaviour
("john.doe@example.io", False),
("john.doe@example.co", False),
("john.doe@gmail.com", False),
("john.doe@ample.com", False),
("john.doe@exexample.com", False),
("john.doe@*example.com", False),
("john.doe@*.example.com", False),
]
for case in test_cases_combined_domain:
email, expected = case
assert check_email_is_whitelisted(email) is expected
set_config("domain_whitelist", "example.com, uni.acme.com, *.edu, *.edu.de")
test_cases_multiple_combined_domains = [
("john.doe@example.com", True),
("john.doe@uni.acme.com", True),
("john.doe@uni.edu", True),
("john.doe@cs.uni.edu", True),
("john.doe@mail.cs.uni.edu", True),
("john.doe@uni.edu.de", True),
("john.doe@cs.uni.edu.de", True),
("john.doe@mail.cs.uni.edu.de", True),
("john.doe@gmail.com", False),
("john.doe@ample.com", False),
("john.doe@example1.com", False),
("john.doe@1example.com", False),
("john.doe@ext.example.com", False),
("john.doe@cs.acme.com", False),
("john.doe@edu.com", False),
("john.doe@mail.uni.acme.com", False),
("john.doe@edu", False),
]
for case in test_cases_multiple_combined_domains:
email, expected = case
assert check_email_is_whitelisted(email) is expected