@@ -492,18 +492,34 @@ def _fetch_specific_groups(self, specific_groups: str) -> dict:
492
492
}
493
493
494
494
@staticmethod
495
- def _get_ad_username (username : str ) -> str :
495
+ def _get_ad_username (logon_name : str ) -> str :
496
496
"""
497
- Gets a user logon name (the username that is used for log in to XSOAR)
497
+ Gets a User logon name (the username that is used for log in to XSOAR)
498
498
and returns the Active Directory username.
499
499
"""
500
- x_username = username
501
- if '\\ ' in username :
502
- x_username = username .split ('\\ ' )[1 ]
503
- elif '@' in username :
504
- x_username = username .split ('@' )[0 ]
500
+ ad_username = logon_name
501
+ if '\\ ' in logon_name :
502
+ ad_username = logon_name .split ('\\ ' )[1 ]
503
+ elif '@' in logon_name :
504
+ ad_username = logon_name .split ('@' )[0 ]
505
505
506
- return x_username
506
+ return ad_username
507
+
508
+ @staticmethod
509
+ def _has_wildcards_in_ad_logon (logon_name : str ):
510
+ """
511
+ Gets a User logon name (the username that is used for log in to XSOAR) and checks if it includes wildcards.
512
+ raises exception if wildcards are found in the logon name.
513
+ (Wildcards are illegal characters for active directory logon names).
514
+ """
515
+ err_msg = f"Wildcards were detected in the user logon name - Input Username: { logon_name } ." \
516
+ f" Wildcards are not permitted for user authentication purposes."
517
+
518
+ wildcards = ['*' , '?' ]
519
+ for wildcard in wildcards :
520
+ if wildcard in logon_name :
521
+ demisto .debug (f"LDAP Authentication - User login attempt failed - { err_msg } " )
522
+ raise Exception (f"LDAP Authentication - Authentication failed - { err_msg } " )
507
523
508
524
def _get_auto_bind_value (self ) -> str :
509
525
"""
@@ -637,6 +653,34 @@ def get_user_groups(self, user_identifier: str):
637
653
paged_size = self ._page_size )
638
654
return LdapClient ._parse_ldap_users_groups_entries (ldap_group_entries )
639
655
656
+ def validate_exact_username_match (self , username : str , user_dn : str ):
657
+ """
658
+ Validates that the given username is an exact match of the username appeared in the DN returned from the ldap search.
659
+ Raises exception if the username does not exactly match the username in the DN.
660
+ Used in authentication commands ('ad-authenticate', 'ad-authenticate-and-roles').
661
+
662
+ Background:
663
+ LDAP servers support the use of wildcards primarily through the '*' and the '?' symbols for searching entries in the
664
+ directory. In addition, '*' and '?' are valid characters for OpenLdap usernames.
665
+
666
+ When the username provided by the user differs from the one retrieved from the DN in the LDAP server,
667
+ it typically indicates that wildcards were used in the input username.
668
+ Example: for input username: 'test*', the Base DN returned from the ldap search could be user_dn:
669
+ 'uid=test,cn=Users,dc=openldaptest'.
670
+ Since the authentication process relies on exact username matches for login, the login attempt will be denied if there's
671
+ a discrepancy.
672
+ Login will only be successful if the input username exactly matches the username in the DN from the LDAP search.
673
+
674
+ Args:
675
+ username (str): the username given as an input by the user.
676
+ user_dn (str): the DN returned from an ldap search of the username.
677
+ """
678
+ err_msg = f"Mismatch likely due to wildcard use. Input Username: { username } , LDAP Search Base DN: { user_dn } ." \
679
+ f"Authentication requires exact match."
680
+ if f'{ self .USER_IDENTIFIER_ATTRIBUTE } ={ username } ' not in user_dn :
681
+ demisto .debug (f"LDAP Authentication - User login attempt failed - { err_msg } " )
682
+ raise Exception (f"LDAP Authentication - Authentication failed - { err_msg } " )
683
+
640
684
def authenticate_and_roles_openldap (self , username : str , password : str , pull_name : bool = True ,
641
685
pull_mail : bool = True , pull_phone : bool = False , mail_attribute : str = 'mail' ,
642
686
name_attribute : str = 'name' , phone_attribute : str = 'mobile' ) -> dict :
@@ -647,7 +691,10 @@ def authenticate_and_roles_openldap(self, username: str, password: str, pull_nam
647
691
user_data = self .get_user_data (username = username , search_user_by_dn = search_user_by_dn , pull_name = pull_name ,
648
692
pull_mail = pull_mail , pull_phone = pull_phone , mail_attribute = mail_attribute ,
649
693
name_attribute = name_attribute , phone_attribute = phone_attribute )
650
- self .authenticate_ldap_user (user_data ['dn' ], password )
694
+ user_dn = user_data ['dn' ]
695
+ self .validate_exact_username_match (username , user_dn ) # fail login attempt when a wildcard is used
696
+
697
+ self .authenticate_ldap_user (user_dn , password )
651
698
user_groups = self .get_user_groups (user_identifier )
652
699
653
700
return {
@@ -665,7 +712,8 @@ def authenticate_and_roles_active_directory(self, username: str, password: str,
665
712
"""
666
713
Implements authenticate and roles command for Active Directory.
667
714
"""
668
- xsoar_username = self ._get_ad_username (username )
715
+ self ._has_wildcards_in_ad_logon (username ) # fail login attempt when a wildcard is used
716
+ ad_username = self ._get_ad_username (username )
669
717
auto_bind = self ._get_auto_bind_value ()
670
718
671
719
with Connection (self ._ldap_server , self ._username , self ._password , auto_bind = auto_bind ) as ldap_conn :
@@ -679,7 +727,7 @@ def authenticate_and_roles_active_directory(self, username: str, password: str,
679
727
if pull_phone :
680
728
attributes .append (phone_attribute )
681
729
682
- search_filter = f'(|(sAMAccountName={ xsoar_username } )(userPrincipalName={ username } ))'
730
+ search_filter = f'(|(sAMAccountName={ ad_username } )(userPrincipalName={ username } ))'
683
731
ldap_conn_entries = ldap_conn .extend .standard .paged_search (search_base = self ._base_dn ,
684
732
search_filter = search_filter ,
685
733
attributes = attributes ,
@@ -764,7 +812,12 @@ def ad_authenticate(self, username: str, password: str) -> str:
764
812
# If the given username is not a full DN, search for it in the ldap server and find it's full DN
765
813
search_user_by_dn , _ = LdapClient ._is_valid_dn (username , self .USER_IDENTIFIER_ATTRIBUTE )
766
814
user_data_entry , _ = self .search_user_data (username , [self .GROUPS_IDENTIFIER_ATTRIBUTE ], search_user_by_dn )
767
- username = user_data_entry .entry_dn
815
+ user_dn = user_data_entry .entry_dn
816
+ self .validate_exact_username_match (username , user_dn ) # fail authentication when a wildcard is used
817
+ username = user_dn
818
+
819
+ elif self ._ldap_server_vendor == self .ACTIVE_DIRECTORY :
820
+ self ._has_wildcards_in_ad_logon (username ) # fail authentication when a wildcard is used
768
821
769
822
return self .authenticate_ldap_user (username , password )
770
823
0 commit comments