|
3 | 3 | import os |
4 | 4 | import time |
5 | 5 | import hmac |
| 6 | +import hashlib |
6 | 7 | import asyncio |
7 | 8 | import argparse |
8 | 9 | import traceback |
@@ -112,14 +113,16 @@ async def ssh_process_handler(process: SSHServerProcess[str]) -> int: |
112 | 113 | console_cls.add_console_arguments(parser) |
113 | 114 | namespace = parser.parse_args(command.split(), namespace) |
114 | 115 |
|
115 | | - # Manage save directory |
| 116 | + # Manage save directory — hash username to prevent path traversal |
116 | 117 | if "save_directory" in namespace.__dict__: |
117 | | - save_directory = ( |
118 | | - None |
119 | | - if getattr(namespace, "input_file", False) |
120 | | - else Path("ssh_save") / username |
121 | | - ) |
122 | | - setattr(namespace, "save_directory", save_directory) |
| 118 | + if getattr(namespace, "input_file", False): |
| 119 | + setattr(namespace, "save_directory", None) |
| 120 | + else: |
| 121 | + safe_name = hashlib.sha256(username.encode("utf-8")).hexdigest()[:16] |
| 122 | + save_directory = Path("ssh_save") / safe_name |
| 123 | + save_directory.mkdir(parents=True, exist_ok=True) |
| 124 | + (save_directory / "username").write_text(username) |
| 125 | + setattr(namespace, "save_directory", save_directory) |
123 | 126 |
|
124 | 127 | # Pop console arguments and extract configuration |
125 | 128 | console_callback = console_cls.pop_console_arguments(namespace) |
@@ -457,6 +460,11 @@ def main( |
457 | 460 | "Both `--password` and `--no-auth` cannot be provided at the same time" |
458 | 461 | ) |
459 | 462 |
|
| 463 | + # Make sure that the ROM file exists before starting the server |
| 464 | + rom_path: Path = namespace.romfile |
| 465 | + if not rom_path.exists(): |
| 466 | + raise SystemExit(f"ROM file `{rom_path}` does not exist") |
| 467 | + |
460 | 468 | # Run an executor with no limit on the number of threads |
461 | 469 | try: |
462 | 470 | with ThreadPoolExecutor(max_workers=32) as executor: |
|
0 commit comments