diff --git a/src/templates/__init__.py b/src/templates/__init__.py new file mode 100644 index 0000000..3eb9f72 --- /dev/null +++ b/src/templates/__init__.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +""" +Templates package for the deception server. +""" + +from .template_loader import load_template, clear_cache, TemplateNotFoundError +from . import html_templates + +__all__ = [ + 'load_template', + 'clear_cache', + 'TemplateNotFoundError', + 'html_templates', +] diff --git a/src/templates/html/directory_listing.html b/src/templates/html/directory_listing.html new file mode 100644 index 0000000..75b7f03 --- /dev/null +++ b/src/templates/html/directory_listing.html @@ -0,0 +1,20 @@ + + +Index of {path} + + + +

Index of {path}

+ + + +{rows} +
NameLast ModifiedSize
Parent Directory--
\ No newline at end of file diff --git a/src/templates/html/directory_row.html b/src/templates/html/directory_row.html new file mode 100644 index 0000000..faf407f --- /dev/null +++ b/src/templates/html/directory_row.html @@ -0,0 +1 @@ +{name}{date}{size} diff --git a/src/templates/html/login_error.html b/src/templates/html/login_error.html new file mode 100644 index 0000000..8e4974d --- /dev/null +++ b/src/templates/html/login_error.html @@ -0,0 +1,29 @@ + + + + + Login Failed + + + +
+

Admin Login

+
ERROR: Invalid username or password.
+
+ + + +
+

Forgot your password?

+
+ + \ No newline at end of file diff --git a/src/templates/html/login_form.html b/src/templates/html/login_form.html new file mode 100644 index 0000000..d39ede6 --- /dev/null +++ b/src/templates/html/login_form.html @@ -0,0 +1,25 @@ + + + + + Admin Login + + + +
+

Admin Login

+
+ + + +
+
+ + \ No newline at end of file diff --git a/src/templates/html/phpmyadmin.html b/src/templates/html/phpmyadmin.html new file mode 100644 index 0000000..870281a --- /dev/null +++ b/src/templates/html/phpmyadmin.html @@ -0,0 +1,24 @@ + + + + phpMyAdmin + + + +

phpMyAdmin

+
+

MySQL Server Login

+
+ + + +
+
+ + \ No newline at end of file diff --git a/src/templates/html/robots.txt b/src/templates/html/robots.txt new file mode 100644 index 0000000..3e82414 --- /dev/null +++ b/src/templates/html/robots.txt @@ -0,0 +1,19 @@ +User-agent: * +Disallow: /admin/ +Disallow: /api/ +Disallow: /backup/ +Disallow: /config/ +Disallow: /database/ +Disallow: /private/ +Disallow: /uploads/ +Disallow: /wp-admin/ +Disallow: /phpMyAdmin/ +Disallow: /admin/login.php +Disallow: /api/v1/users +Disallow: /api/v2/secrets +Disallow: /.env +Disallow: /credentials.txt +Disallow: /passwords.txt +Disallow: /.git/ +Disallow: /backup.sql +Disallow: /db_backup.sql diff --git a/src/templates/html/wordpress.html b/src/templates/html/wordpress.html new file mode 100644 index 0000000..034d973 --- /dev/null +++ b/src/templates/html/wordpress.html @@ -0,0 +1,73 @@ + + + + + + My Blog – Just another WordPress site + + + + + + + + +
+ + +
+
+
+

Hello world!

+ +
+
+

Welcome to WordPress. This is your first post. Edit or delete it, then start writing!

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+
+
+ +
+
+

About This Site

+ +
+
+

This is a sample page. You can use it to write about your site, yourself, or anything else you'd like.

+
+
+
+ + +
+ + + \ No newline at end of file diff --git a/src/templates/html_templates.py b/src/templates/html_templates.py index e17df75..69f562b 100644 --- a/src/templates/html_templates.py +++ b/src/templates/html_templates.py @@ -2,228 +2,46 @@ """ HTML templates for the deception server. -Edit these templates to customize the appearance of fake pages. +Templates are loaded from the html/ subdirectory. """ +from .template_loader import load_template + def login_form() -> str: """Generate fake login page""" - return """ - - - - Admin Login - - - -
-

Admin Login

-
- - - -
-
- -""" + return load_template("login_form") def login_error() -> str: """Generate fake login error page""" - return """ - - - - Login Failed - - - -
-

Admin Login

-
ERROR: Invalid username or password.
-
- - - -
-

Forgot your password?

-
- -""" + return load_template("login_error") def wordpress() -> str: """Generate fake WordPress page""" - return """ - - - - - My Blog – Just another WordPress site - - - - - - - - -
- - -
-
-
-

Hello world!

- -
-
-

Welcome to WordPress. This is your first post. Edit or delete it, then start writing!

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

-
-
- -
-
-

About This Site

- -
-
-

This is a sample page. You can use it to write about your site, yourself, or anything else you'd like.

-
-
-
- - -
- - -""" + return load_template("wordpress") def phpmyadmin() -> str: """Generate fake phpMyAdmin page""" - return """ - - - phpMyAdmin - - - -

phpMyAdmin

-
-

MySQL Server Login

-
- - - -
-
- -""" + return load_template("phpmyadmin") def robots_txt() -> str: """Generate juicy robots.txt""" - return """User-agent: * -Disallow: /admin/ -Disallow: /api/ -Disallow: /backup/ -Disallow: /config/ -Disallow: /database/ -Disallow: /private/ -Disallow: /uploads/ -Disallow: /wp-admin/ -Disallow: /phpMyAdmin/ -Disallow: /admin/login.php -Disallow: /api/v1/users -Disallow: /api/v2/secrets -Disallow: /.env -Disallow: /credentials.txt -Disallow: /passwords.txt -Disallow: /.git/ -Disallow: /backup.sql -Disallow: /db_backup.sql -""" + return load_template("robots.txt") def directory_listing(path: str, dirs: list, files: list) -> str: """Generate fake directory listing""" - html = f""" - -Index of {path} - - - -

Index of {path}

- - - -""" - + row_template = load_template("directory_row") + + rows = "" for d in dirs: - html += f'\n' - + rows += row_template.format(href=d, name=d, date="2024-12-01 10:30", size="-") + for f, size in files: - html += f'\n' - - html += '
NameLast ModifiedSize
Parent Directory--
{d}2024-12-01 10:30-
{f}2024-12-01 14:22{size}
' - return html + rows += row_template.format(href=f, name=f, date="2024-12-01 14:22", size=size) + + return load_template("directory_listing", path=path, rows=rows) diff --git a/src/templates/template_loader.py b/src/templates/template_loader.py new file mode 100644 index 0000000..3faf61b --- /dev/null +++ b/src/templates/template_loader.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +""" +Template loader for HTML templates. +Loads templates from the html/ subdirectory and supports string formatting for dynamic content. +""" + +from pathlib import Path +from typing import Dict + + +class TemplateNotFoundError(Exception): + """Raised when a template file cannot be found.""" + pass + + +# Module-level cache for loaded templates +_template_cache: Dict[str, str] = {} + +# Base directory for template files +_TEMPLATE_DIR = Path(__file__).parent / "html" + + +def load_template(name: str, **kwargs) -> str: + """ + Load a template by name and optionally substitute placeholders. + + Args: + name: Template name (without extension for HTML, with extension for others like .txt) + **kwargs: Key-value pairs for placeholder substitution using str.format() + + Returns: + Rendered template string + + Raises: + TemplateNotFoundError: If template file doesn't exist + + Example: + >>> load_template("login_form") # Loads html/login_form.html + >>> load_template("robots.txt") # Loads html/robots.txt + >>> load_template("directory_listing", path="/var/www", rows="...") + """ + # Check cache first + if name not in _template_cache: + # Determine file path based on whether name has an extension + if '.' in name: + file_path = _TEMPLATE_DIR / name + else: + file_path = _TEMPLATE_DIR / f"{name}.html" + + if not file_path.exists(): + raise TemplateNotFoundError(f"Template '{name}' not found at {file_path}") + + _template_cache[name] = file_path.read_text(encoding='utf-8') + + template = _template_cache[name] + + # Apply substitutions if kwargs provided + if kwargs: + template = template.format(**kwargs) + + return template + + +def clear_cache() -> None: + """Clear the template cache. Useful for testing or development.""" + _template_cache.clear()