From 58fbd9e4b693802a53e2f4980290f0dd88f74a97 Mon Sep 17 00:00:00 2001 From: someyack <132161763+someyack@users.noreply.github.com> Date: Fri, 10 Jul 2026 01:20:08 -0400 Subject: [PATCH] Add support for domain-qualified usernames (#207) Co-authored-by: Dylab --- smbclientng/console.py | 11 +++++++++-- smbclientng/core/SessionsManager.py | 2 +- smbclientng/types/Credentials.py | 20 ++++++++++++++++++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/smbclientng/console.py b/smbclientng/console.py index 0b54a8c..d666125 100644 --- a/smbclientng/console.py +++ b/smbclientng/console.py @@ -90,7 +90,11 @@ def parseArgs(): "-d", "--domain", default=".", type=str, help="Authentication domain." ) group_auth.add_argument( - "-u", "--user", type=str, default="", help="Username for authentication." + "-u", + "--user", + type=str, + default="", + help=r"Username for authentication. Supports DOMAIN\user.", ) group_auth.add_argument( "-k", "--kerberos", action="store_true", help="Use Kerberos authentication." @@ -132,8 +136,11 @@ def parseArgs(): if options.user and not (options.password or options.no_pass or options.hashes or options.ccache_file or options.kerberos): from getpass import getpass + prompt_domain, prompt_username = Credentials.parse_domain_username( + domain=options.domain, username=options.user + ) options.password = getpass( - f" | Provide a password for '{options.domain}\\{options.user}': " + f" | Provide a password for '{prompt_domain}\\{prompt_username}': " ) if options.aes_key or options.ccache_file: diff --git a/smbclientng/core/SessionsManager.py b/smbclientng/core/SessionsManager.py index 7740611..959ddc4 100644 --- a/smbclientng/core/SessionsManager.py +++ b/smbclientng/core/SessionsManager.py @@ -213,7 +213,7 @@ class SessionsManager(object): dest="auth_username", metavar="USER", action="store", - help="User to authenticate with.", + help=r"User to authenticate with. Supports DOMAIN\user.", ) secret = mode_create.add_argument_group() cred = secret.add_mutually_exclusive_group() diff --git a/smbclientng/types/Credentials.py b/smbclientng/types/Credentials.py index aa7b6ad..e04b66c 100644 --- a/smbclientng/types/Credentials.py +++ b/smbclientng/types/Credentials.py @@ -61,8 +61,9 @@ class Credentials(object): ): super(Credentials, self).__init__() # Identity - self.domain = domain - self.username = username + self.domain, self.username = self.parse_domain_username( + domain=domain, username=username + ) self.password = password # Hashes @@ -74,6 +75,21 @@ class Credentials(object): self.aesKey = aesKey self.ccacheFile = ccacheFile + @staticmethod + def parse_domain_username( + domain: str, username: Optional[str] + ) -> tuple[str, Optional[str]]: + if username is None: + return domain, username + + for separator in ("\\", "/"): + if separator in username: + user_domain, user_name = username.split(separator, 1) + if user_domain and user_name: + return user_domain, user_name + + return domain, username + def set_hashes(self, hashes: Optional[str]): """ Sets the LM and NT hashes for the credentials.