#!/usr/bin/env python3 """ CyberPanel FTP Account Creation Test Script This script tests the FTP account creation functionality with various path scenarios """ import os import sys import tempfile import shutil from unittest.mock import patch, MagicMock # Add CyberPanel to path sys.path.append('/usr/local/CyberCP') def test_ftp_path_validation(): """Test the FTP path validation functionality""" print("๐Ÿ” Testing FTP Path Validation...") # Import the FTP utilities try: from plogical.ftpUtilities import FTPUtilities print("โœ… Successfully imported FTPUtilities") except ImportError as e: print(f"โŒ Failed to import FTPUtilities: {e}") return False # Test cases for path validation test_cases = [ # Valid paths ("docs", True, "Valid subdirectory"), ("public_html", True, "Valid public_html directory"), ("uploads/images", True, "Valid nested directory"), ("api/v1", True, "Valid API directory"), ("", True, "Empty path (home directory)"), ("None", True, "None path (home directory)"), # Invalid paths ("../docs", False, "Path traversal with .."), ("~/docs", False, "Home directory reference"), ("/docs", False, "Absolute path"), ("docs;rm -rf /", False, "Command injection"), ("docs|cat /etc/passwd", False, "Pipe command injection"), ("docs&reboot", False, "Background command"), ("docs`whoami`", False, "Command substitution"), ("docs'rm -rf /'", False, "Single quote injection"), ('docs"rm -rf /"', False, "Double quote injection"), ("docsmalicious", False, "Output redirection"), ("docs*", False, "Wildcard character"), ("docs?", False, "Wildcard character"), ] print("\n๐Ÿ“‹ Running Path Validation Tests:") print("-" * 60) passed = 0 failed = 0 for path, should_pass, description in test_cases: try: # Mock the external dependencies with patch('pwd.getpwnam') as mock_pwd, \ patch('grp.getgrnam') as mock_grp, \ patch('os.path.exists') as mock_exists, \ patch('os.path.isdir') as mock_isdir, \ patch('os.path.islink') as mock_islink, \ patch('plogical.processUtilities.ProcessUtilities.executioner') as mock_exec, \ patch('websiteFunctions.models.Websites.objects.get') as mock_website, \ patch('loginSystem.models.Administrator.objects.get') as mock_admin: # Setup mocks mock_pwd.return_value.pw_uid = 1000 mock_grp.return_value.gr_gid = 1000 mock_exists.return_value = True mock_isdir.return_value = True mock_islink.return_value = False mock_exec.return_value = 0 # Mock website object mock_website_obj = MagicMock() mock_website_obj.externalApp = "testuser" mock_website_obj.package.diskSpace = 1000 mock_website_obj.package.ftpAccounts = 10 mock_website_obj.users_set.all.return_value.count.return_value = 0 mock_website.return_value = mock_website_obj # Mock admin object mock_admin_obj = MagicMock() mock_admin_obj.userName = "testadmin" mock_admin.return_value = mock_admin_obj # Test the path validation result = FTPUtilities.submitFTPCreation( "testdomain.com", "testuser", "testpass", path, "testadmin" ) if should_pass: if result[0] == 1: print(f"โœ… PASS: {description} ('{path}')") passed += 1 else: print(f"โŒ FAIL: {description} ('{path}') - Expected success but got: {result[1]}") failed += 1 else: if result[0] == 0: print(f"โœ… PASS: {description} ('{path}') - Correctly rejected") passed += 1 else: print(f"โŒ FAIL: {description} ('{path}') - Expected rejection but got success") failed += 1 except Exception as e: if should_pass: print(f"โŒ ERROR: {description} ('{path}') - Unexpected error: {e}") failed += 1 else: print(f"โœ… PASS: {description} ('{path}') - Correctly rejected with error: {e}") passed += 1 print("\n" + "=" * 60) print(f"๐Ÿ“Š Test Results: {passed} passed, {failed} failed") print("=" * 60) return failed == 0 def test_directory_creation(): """Test directory creation functionality""" print("\n๐Ÿ” Testing Directory Creation...") try: from plogical.ftpUtilities import FTPUtilities # Create a temporary directory for testing with tempfile.TemporaryDirectory() as temp_dir: test_path = os.path.join(temp_dir, "test_ftp_dir") print(f"๐Ÿ“ Testing directory creation at: {test_path}") # Test creating a new directory result = FTPUtilities.ftpFunctions(test_path, "testuser") if result[0] == 1: if os.path.exists(test_path) and os.path.isdir(test_path): print("โœ… Directory creation successful") return True else: print("โŒ Directory creation failed - directory not found") return False else: print(f"โŒ Directory creation failed: {result[1]}") return False except Exception as e: print(f"โŒ Directory creation test failed: {e}") return False def test_security_features(): """Test security features""" print("\n๐Ÿ” Testing Security Features...") security_tests = [ ("Path traversal prevention", ".."), ("Home directory reference prevention", "~"), ("Absolute path prevention", "/etc/passwd"), ("Command injection prevention", ";rm -rf /"), ("Pipe command prevention", "|cat /etc/passwd"), ("Background command prevention", "&reboot"), ("Command substitution prevention", "`whoami`"), ] print("๐Ÿ›ก๏ธ Security Test Results:") print("-" * 40) for test_name, malicious_path in security_tests: try: # This should be caught by our validation if any(char in malicious_path for char in ['..', '~', '/', ';', '|', '&', '`']): print(f"โœ… {test_name}: Correctly detected malicious path") else: print(f"โŒ {test_name}: Failed to detect malicious path") except Exception as e: print(f"โœ… {test_name}: Correctly rejected with error: {e}") return True def main(): """Main test function""" print("๐Ÿš€ CyberPanel FTP Account Creation Test Suite") print("=" * 60) # Run all tests tests = [ ("Path Validation", test_ftp_path_validation), ("Directory Creation", test_directory_creation), ("Security Features", test_security_features), ] results = [] for test_name, test_func in tests: print(f"\n๐Ÿงช Running {test_name} Test...") try: result = test_func() results.append((test_name, result)) if result: print(f"โœ… {test_name} Test: PASSED") else: print(f"โŒ {test_name} Test: FAILED") except Exception as e: print(f"โŒ {test_name} Test: ERROR - {e}") results.append((test_name, False)) # Summary print("\n" + "=" * 60) print("๐Ÿ“‹ TEST SUMMARY") print("=" * 60) passed = sum(1 for _, result in results if result) total = len(results) for test_name, result in results: status = "โœ… PASSED" if result else "โŒ FAILED" print(f"{test_name}: {status}") print(f"\n๐ŸŽฏ Overall Result: {passed}/{total} tests passed") if passed == total: print("๐ŸŽ‰ All tests passed! FTP account creation should work correctly.") return 0 else: print("โš ๏ธ Some tests failed. Please review the issues above.") return 1 if __name__ == "__main__": exit(main())