Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "LDAP Authentication - Fail login attempts when wildcards are used" #38371

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 12 additions & 65 deletions Packs/OpenLDAP/Integrations/OpenLDAP/OpenLDAP.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,34 +492,18 @@ def _fetch_specific_groups(self, specific_groups: str) -> dict:
}

@staticmethod
def _get_ad_username(logon_name: str) -> str:
def _get_ad_username(username: str) -> str:
"""
Gets a User logon name (the username that is used for log in to XSOAR)
Gets a user logon name (the username that is used for log in to XSOAR)
and returns the Active Directory username.
"""
ad_username = logon_name
if '\\' in logon_name:
ad_username = logon_name.split('\\')[1]
elif '@' in logon_name:
ad_username = logon_name.split('@')[0]
x_username = username
if '\\' in username:
x_username = username.split('\\')[1]
elif '@' in username:
x_username = username.split('@')[0]

return ad_username

@staticmethod
def _has_wildcards_in_ad_logon(logon_name: str):
"""
Gets a User logon name (the username that is used for log in to XSOAR) and checks if it includes wildcards.
raises exception if wildcards are found in the logon name.
(Wildcards are illegal characters for active directory logon names).
"""
err_msg = f"Wildcards were detected in the user logon name - Input Username: {logon_name}."\
f" Wildcards are not permitted for user authentication purposes."

wildcards = ['*', '?']
for wildcard in wildcards:
if wildcard in logon_name:
demisto.debug(f"LDAP Authentication - User login attempt failed - {err_msg}")
raise Exception(f"LDAP Authentication - Authentication failed - {err_msg}")
return x_username

def _get_auto_bind_value(self) -> str:
"""
Expand Down Expand Up @@ -653,34 +637,6 @@ def get_user_groups(self, user_identifier: str):
paged_size=self._page_size)
return LdapClient._parse_ldap_users_groups_entries(ldap_group_entries)

def validate_exact_username_match(self, username: str, user_dn: str):
"""
Validates that the given username is an exact match of the username appeared in the DN returned from the ldap search.
Raises exception if the username does not exactly match the username in the DN.
Used in authentication commands ('ad-authenticate', 'ad-authenticate-and-roles').

Background:
LDAP servers support the use of wildcards primarily through the '*' and the '?' symbols for searching entries in the
directory. In addition, '*' and '?' are valid characters for OpenLdap usernames.

When the username provided by the user differs from the one retrieved from the DN in the LDAP server,
it typically indicates that wildcards were used in the input username.
Example: for input username: 'test*', the Base DN returned from the ldap search could be user_dn:
'uid=test,cn=Users,dc=openldaptest'.
Since the authentication process relies on exact username matches for login, the login attempt will be denied if there's
a discrepancy.
Login will only be successful if the input username exactly matches the username in the DN from the LDAP search.

Args:
username (str): the username given as an input by the user.
user_dn (str): the DN returned from an ldap search of the username.
"""
err_msg = f"Mismatch likely due to wildcard use. Input Username: {username}, LDAP Search Base DN: {user_dn}."\
f"Authentication requires exact match."
if f'{self.USER_IDENTIFIER_ATTRIBUTE}={username}' not in user_dn:
demisto.debug(f"LDAP Authentication - User login attempt failed - {err_msg}")
raise Exception(f"LDAP Authentication - Authentication failed - {err_msg}")

def authenticate_and_roles_openldap(self, username: str, password: str, pull_name: bool = True,
pull_mail: bool = True, pull_phone: bool = False, mail_attribute: str = 'mail',
name_attribute: str = 'name', phone_attribute: str = 'mobile') -> dict:
Expand All @@ -691,10 +647,7 @@ def authenticate_and_roles_openldap(self, username: str, password: str, pull_nam
user_data = self.get_user_data(username=username, search_user_by_dn=search_user_by_dn, pull_name=pull_name,
pull_mail=pull_mail, pull_phone=pull_phone, mail_attribute=mail_attribute,
name_attribute=name_attribute, phone_attribute=phone_attribute)
user_dn = user_data['dn']
self.validate_exact_username_match(username, user_dn) # fail login attempt when a wildcard is used

self.authenticate_ldap_user(user_dn, password)
self.authenticate_ldap_user(user_data['dn'], password)
user_groups = self.get_user_groups(user_identifier)

return {
Expand All @@ -712,8 +665,7 @@ def authenticate_and_roles_active_directory(self, username: str, password: str,
"""
Implements authenticate and roles command for Active Directory.
"""
self._has_wildcards_in_ad_logon(username) # fail login attempt when a wildcard is used
ad_username = self._get_ad_username(username)
xsoar_username = self._get_ad_username(username)
auto_bind = self._get_auto_bind_value()

with Connection(self._ldap_server, self._username, self._password, auto_bind=auto_bind) as ldap_conn:
Expand All @@ -727,7 +679,7 @@ def authenticate_and_roles_active_directory(self, username: str, password: str,
if pull_phone:
attributes.append(phone_attribute)

search_filter = f'(|(sAMAccountName={ad_username})(userPrincipalName={username}))'
search_filter = f'(|(sAMAccountName={xsoar_username})(userPrincipalName={username}))'
ldap_conn_entries = ldap_conn.extend.standard.paged_search(search_base=self._base_dn,
search_filter=search_filter,
attributes=attributes,
Expand Down Expand Up @@ -812,12 +764,7 @@ def ad_authenticate(self, username: str, password: str) -> str:
# If the given username is not a full DN, search for it in the ldap server and find it's full DN
search_user_by_dn, _ = LdapClient._is_valid_dn(username, self.USER_IDENTIFIER_ATTRIBUTE)
user_data_entry, _ = self.search_user_data(username, [self.GROUPS_IDENTIFIER_ATTRIBUTE], search_user_by_dn)
user_dn = user_data_entry.entry_dn
self.validate_exact_username_match(username, user_dn) # fail authentication when a wildcard is used
username = user_dn

elif self._ldap_server_vendor == self.ACTIVE_DIRECTORY:
self._has_wildcards_in_ad_logon(username) # fail authentication when a wildcard is used
username = user_data_entry.entry_dn

return self.authenticate_ldap_user(username, password)

Expand Down
52 changes: 10 additions & 42 deletions Packs/OpenLDAP/Integrations/OpenLDAP/OpenLDAP_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,27 +146,6 @@ def test_get_ad_username(self, user_logon_name, expected_ad_username):
ad_username = client._get_ad_username(user_logon_name)
assert ad_username == expected_ad_username

@pytest.mark.parametrize('user_logon_name', [
('test*'),
('test?test'),
])
def test_has_wildcards_in_ad_logon(self, user_logon_name):
"""
Given:
1. A user logon name contains the "*" symbol.
2. A user logon name contains the "?" symbol.
When:
- Running the 'has_wildcards_in_ad_logon()' function.
Then:
- Verify that an exception is raised due to the use of wildcards in the logon name.
"""
client = LdapClient({'ldap_server_vendor': 'Active Directory', 'host': 'server_ip'})

with pytest.raises(Exception) as e:
client._has_wildcards_in_ad_logon(user_logon_name)
assert 'Wildcards were detected in the user logon name' in e.value.args[0]
assert user_logon_name in e.value.args[0]

@pytest.mark.parametrize('connection_type, expected_auto_bind_value', [
('Start TLS', 'TLS_BEFORE_BIND'),
('SSL', 'NO_TLS'),
Expand Down Expand Up @@ -244,27 +223,11 @@ def test_is_valid_dn_user_id_not_in_dn(self, dn, user_identifier_attribute):
client._is_valid_dn(dn, client.USER_IDENTIFIER_ATTRIBUTE)
assert e.value.args[0] == f'OpenLDAP {user_identifier_attribute} attribute was not found in user DN : {dn}'

@pytest.mark.parametrize('user_logon_name, user_dn', [
('test*', 'uid=test,cn=Users,dc=openldaptest'),
('tes?t', 'uid=test,cn=Users,dc=openldaptest')
])
def test_validate_exact_username_match(self, user_logon_name, user_dn):
"""
Given:
1. A user logon name contains the "*" symbol, and the user dn.
2. A user logon name contains the "?" symbol, and the user dn
When:
- Running the 'validate_exact_username_match()' function.
Then:
- Verify that an exception is raised due to the use of wildcards in the logon name.
"""
client = LdapClient({'ldap_server_vendor': 'OpenLDAP', 'host': 'server_ip'})

with pytest.raises(Exception) as e:
client.validate_exact_username_match(user_logon_name, user_dn)
assert 'Mismatch likely due to wildcard use' in e.value.args[0]
assert user_logon_name in e.value.args[0]
assert user_dn in e.value.args[0]
# def test_get_user_data(self):
# client = LdapClient({'ldap_server_vendor': 'OpenLDAP', 'host': 'server_ip',
# 'connection_type': 'SSL', 'user_identifier_attribute': 'uid'})
#
# mocker.patch('OpenLDAP.LdapClient.search_user_data', return_value=)


class TestLDAPAuthentication:
Expand Down Expand Up @@ -343,6 +306,11 @@ def test_get_formatted_custom_attributes_invalid_attributes_input(self):
f'{client.CUSTOM_ATTRIBUTE}')


'''
please add doc string to the tests in our format given: when: then
'''


class TestEntriesPagedSearch(unittest.TestCase):

def setUp(self):
Expand Down
5 changes: 5 additions & 0 deletions Packs/OpenLDAP/ReleaseNotes/2_0_17.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#### Integrations

##### LDAP Authentication

- Fixed an issue where *OpenLDAP* users couldn't login.
ShacharKidor marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion Packs/OpenLDAP/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "LDAP Authentication",
"description": "Authenticate using Open LDAP or Active Directory",
"support": "xsoar",
"currentVersion": "2.0.16",
"currentVersion": "2.0.17",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down
Loading