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

[enhancement] Created test cases #90

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion smbclientng/core/CommandCompleter.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,8 @@ def print_help(self, command=None):

if command is not None:
if command not in list(self.commands.keys())+["format"]:
command = None
self.logger.error("Help for command '%s' does not exist." % command)
return

# Print help for a specific command
if command is not None:
Expand Down
9 changes: 6 additions & 3 deletions smbclientng/core/InteractiveShell.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def wrapper(*args, **kwargs):
if self.sessionsManager.current_session.connected:
return func(*args, **kwargs)
else:
print("[!] SMB Session is disconnected.")
self.logger.error("SMB Session is disconnected.")
return None
return wrapper

Expand All @@ -53,7 +53,7 @@ def wrapper(*args, **kwargs):
if self.sessionsManager.current_session.smb_share is not None:
return func(*args, **kwargs)
else:
print("[!] You must open a share first, try the 'use <share>' command.")
self.logger.error("You must open a share first, try the 'use <share>' command.")
return None
return wrapper

Expand Down Expand Up @@ -459,6 +459,9 @@ def command_info(self, arguments, command):
print_server_info = False
print_share_info = False
if len(arguments) != 0:
if arguments[0].lower() not in ["server", "share"]:
self.logger.error("'%s' is not a valid parameter. Use 'server' or 'share'." % arguments[0])
return None
print_server_info = (arguments[0].lower() == "server")
print_share_info = (arguments[0].lower() == "share")
else:
Expand All @@ -471,7 +474,7 @@ def command_info(self, arguments, command):
server=print_server_info
)
except impacket.smbconnection.SessionError as e:
self.logger.error("[!] SMB Error: %s" % e)
self.logger.error("SMB Error: %s" % e)

@command_arguments_required
def command_lbat(self, arguments, command):
Expand Down
62 changes: 39 additions & 23 deletions testing/core/Check.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,47 @@ def __init__(self, logger, options, test_case):

def run(self):
data = self.exec()
parsed = parseLogfileContents(data)
last_line = parsed[-1]

check_passed = True
for expectedMessage in self.test_case["expected_output"]["messages"]:
if expectedMessage not in ''.join(last_line["output"]):
check_passed = False
else:
self.logger.debug("'%s' is not present in output" % expectedMessage)

# Error output is matching what is expected
if self.test_case["expected_output"]["error"] != last_line["error"]:
self.logger.debug("Error output is not matching what is expected.")
check_passed = False

# Traceback output is matching what is expected
if self.test_case["expected_output"]["traceback"] != last_line["traceback"]:
self.logger.debug("Traceback output is not matching what is expected.")
if data is None:
check_passed = False
return check_passed

# Final print of check
if check_passed:
self.__print_passed()
else:
self.__print_failed()
parsed = parseLogfileContents(data)

if len(parsed) != 0:
last_line = parsed[-1]

check_passed = True
for expectedMessage in self.test_case["expected_output"]["messages"]:
if expectedMessage not in ''.join(last_line["output"]):
check_passed = False
else:
self.logger.debug("'%s' is not present in output" % expectedMessage)

# Error output is matching what is expected
if self.test_case["expected_output"]["error"] != last_line["error"]:
self.logger.debug("Error output is not matching what is expected.")
self.logger.debug("=[Output]====================================")
self.logger.debug('\n'.join(last_line["output"]))
self.logger.debug("=============================================")
check_passed = False

# Traceback output is matching what is expected
if self.test_case["expected_output"]["traceback"] != last_line["traceback"]:
self.logger.debug("Traceback output is not matching what is expected.")
self.logger.debug("=[Output]====================================")
self.logger.debug('\n'.join(last_line["output"]))
self.logger.debug("=============================================")
check_passed = False

# Final print of check
if check_passed:
self.__print_passed()
return True
else:
self.__print_failed()
return False

def exec(self):
# Create scriptfile
Expand Down Expand Up @@ -95,10 +111,10 @@ def exec(self):
return None

def __print_passed(self):
title = (self.test_case["title"]+" ").ljust(60,'─')
title = (self.test_case["title"]+" ").ljust(80,'─')
self.logger.print("├───┼───┼── %s \x1b[1;48;2;83;170;51;97m PASSED \x1b[0m" % title)

def __print_failed(self):
title = (self.test_case["title"]+" ").ljust(60,'─')
title = (self.test_case["title"]+" ").ljust(80,'─')
self.logger.print("├───┼───┼── %s \x1b[1;48;2;233;61;3;97m FAILED \x1b[0m" % title)

2 changes: 1 addition & 1 deletion testing/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def parseLogfileContents(contents):
parsed.append({
"command": command,
"output": buffer,
"error": any(["[error]" in l.startswith() for l in buffer]),
"error": any([l.startswith("[error]") for l in buffer]),
"traceback": any([l.startswith("Traceback") for l in buffer]),
})
command = None
Expand Down
18 changes: 14 additions & 4 deletions testing/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,25 @@ def parseArgs():
nb_testcases += len(testCases[category][subcategory].keys())
logger.info("Registered %d tests." % nb_testcases)


tests_passed = 0
tests_failed = 0
for category in sorted(testCases.keys()):
logger.print("\x1b[1;48;2;170;170;170;30m├──[+] Category: %-64s\x1b[0m" % category)
logger.print("\x1b[1;48;2;170;170;170;30m├──[+] Category: %-84s\x1b[0m" % category)

for subcategory in sorted(testCases[category].keys()):
logger.print("\x1b[1;48;2;200;200;200;30m├───┼──[+] Subcategory: %-57s\x1b[0m" % subcategory)
logger.print("\x1b[1;48;2;200;200;200;30m├───┼──[+] Subcategory: %-77s\x1b[0m" % subcategory)

for pathToTestCase, testCase in testCases[category][subcategory].items():
logger.debug("Testing: %s" % testCase["title"])
c = Check(logger=logger, options=options, test_case=testCase)
c.run()

if c.run() == True:
tests_passed += 1
else:
tests_failed += 1

logger.info("Finished tests.")
logger.print("\x1b[1;48;2;170;170;170;30m[+] %-96s \x1b[0m" % "All done!")
logger.info("Finished tests.")
logger.info("Tests PASSED: (%d/%d) %d%%" % (tests_passed, nb_testcases, (tests_passed / nb_testcases)*100))
logger.info("Tests FAILED: (%d/%d) %d%%" % (tests_failed, nb_testcases, (tests_failed / nb_testcases)*100))
23 changes: 23 additions & 0 deletions testing/tests/commands/bat/bat_existing_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"title": "Command 'bat': of an existing remote file",
"category": "commands",
"subcategory": "bat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"bat './Users/John/Documents/file.txt'"
],
"expected_output": {
"messages": [
"Contents of './Users/John/Documents/file.txt':",
"This is a test file."
],
"error": false,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/bat/bat_insufficient_permissions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'bat': of a remote file with insufficient permissions",
"category": "commands",
"subcategory": "bat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"bat './Windows/System32/protected_file.txt'"
],
"expected_output": {
"messages": [
"Error: Permission denied for './Windows/System32/protected_file.txt'."
],
"error": true,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/bat/bat_no_file_specified.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'bat': without specifying a file",
"category": "commands",
"subcategory": "bat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"bat"
],
"expected_output": {
"messages": [
"Error: No file specified."
],
"error": true,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/bat/bat_non_existing_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'bat': of a non-existing remote file",
"category": "commands",
"subcategory": "bat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"bat './Users/John/Documents/non_existing_file.txt'"
],
"expected_output": {
"messages": [
"Error: File './Users/John/Documents/non_existing_file.txt' not found."
],
"error": true,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/cat/cat_existing_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'cat': of an existing remote file",
"category": "commands",
"subcategory": "cat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"cat './Users/John/Documents/file.txt'"
],
"expected_output": {
"messages": [
"This is a test file."
],
"error": false,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/cat/cat_insufficient_permissions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'cat': of a remote file with insufficient permissions",
"category": "commands",
"subcategory": "cat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"cat './Windows/System32/protected_file.txt'"
],
"expected_output": {
"messages": [
"Error: Permission denied for './Windows/System32/protected_file.txt'."
],
"error": true,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/cat/cat_no_file_specified.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'cat': without specifying a file",
"category": "commands",
"subcategory": "cat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"cat"
],
"expected_output": {
"messages": [
"Error: No file specified."
],
"error": true,
"traceback": false
}
}
22 changes: 22 additions & 0 deletions testing/tests/commands/cat/cat_non_existing_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"title": "Command 'cat': attempts to get the contents of a non-existing remote file",
"category": "commands",
"subcategory": "cat",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"cat './Users/John/Documents/non_existing_file.txt'"
],
"expected_output": {
"messages": [
"Error: File './Users/John/Documents/non_existing_file.txt' not found."
],
"error": true,
"traceback": false
}
}
20 changes: 20 additions & 0 deletions testing/tests/commands/cd/cd_a_non_existing_directory_in_cwd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "Command 'cd': with a non-existing directory in CWD",
"category": "commands",
"subcategory": "cd",
"parameters": {
"-d": "{auth_domain}",
"-u": "{auth_username}",
"-p": "{auth_password}",
"--host": "{target_host}"
},
"smbclientng_commands": [
"use 'C$'",
"cd './{random_string_8}/'"
],
"expected_output": {
"messages": ["[error] Remote directory '", "' does not exist."],
"error": true,
"traceback": false
}
}
Loading
Loading