mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 05:54:19 +01:00
Add email whitelist wildcard (#2375)
* add wildcard for email whitelisting --------- Co-authored-by: Kevin Chung <kchung@ctfd.io>
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user