Skip to content
Draft
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
27 changes: 20 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Publish to PyPI
on:
push:
branches:
- 'release/pypi-2.14.213.78.21.8'
- 'release/pypi-2.14.213.78.21.9'
release:
types: [published]
workflow_dispatch:
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
run: python -m build

- name: Check distribution
run: twine check dist/*
run: twine check --strict dist/*

- name: Check source distribution contents
run: |
Expand All @@ -75,7 +75,8 @@ jobs:
with tarfile.open(next(pathlib.Path("dist").glob("*.tar.gz")), "r:gz") as source:
names = {name.split("/", 1)[1] for name in source.getnames() if "/" in name}
assert {"requirements.txt", "d2.aspx", "tools/add_diagnostic_tools.py",
"tests/conftest.py", "tests/test_domain_orm.py"}.issubset(names)
"tests/conftest.py", "tests/test_domain_orm.py", "tests/test_diagnostic_pptp.py",
"adpentest/pptp_check.py"}.issubset(names)
PY

- name: Check installed wheel
Expand All @@ -93,7 +94,14 @@ jobs:
import importlib.metadata
requirements = importlib.metadata.metadata("adpentest").get_all("Requires-Dist")
assert any(item.startswith("impacket") and ";" not in item for item in requirements)
assert adpentest.__version__ == "2.14.213.78.21.8"
assert adpentest.__version__ == "2.14.213.78.21.9"
from adpentest.pptp_check import parse_start_reply, start_request
import struct
reply = struct.pack("!HHIHHHBBIIHH64s64s", 156, 1, 0x1A2B3C4D, 2, 0,
0x0100, 1, 0, 3, 3, 0, 42, b"fixture-vpn", b"Fixture Vendor")
assert len(start_request()) == 156
assert parse_start_reply(reply)["control_status"] == "accepted"
assert parse_start_reply(reply)["gre"]["status"] == "not-tested"
from adpentest.smbv1_data import SMBv1ExportParser, analyze_smbv1_data
inventory = analyze_smbv1_data(
[{"host": "fileserver.lab.example", "smbv1": True,
Expand All @@ -117,6 +125,9 @@ jobs:
assert session.scalar(select(SMBv1Host)).users[0].username == "alice"
from adpentest.diagnostics import build_diagnostic_command
args = build_diagnostic_command("nmap_smbv1", "192.0.2.10")
pptp_command = build_diagnostic_command("pptp_control", "vpn.example", resolved_address="192.0.2.10")
assert pathlib.Path(pptp_command[2]).is_file()
assert pptp_command[pptp_command.index("--target") + 1] == "192.0.2.10"
assert "smb-protocols" in args and "445" in args and "-vv" in args
ports = build_diagnostic_command("nmap_tcp_ports", "192.0.2.10", ports="1-65535", timeout=600)
assert "1-65535" in ports and "--script" not in ports and "-vv" in ports
Expand Down Expand Up @@ -150,15 +161,17 @@ jobs:
[sys.executable, "-I", "-c",
"import sys; sys.path.insert(0, " + repr(str(pathlib.Path("wheel-check").resolve())) + "); import adpentest; raise SystemExit(adpentest.main())",
"--port-map", "--ports", "1-65535", "--port-map-timeout", "600", "--smbv1-check", "--smbv1-access",
"--smb-share", "SHARE", "--smb-user", "alice", "--target", "192.0.2.10", "--mode", "dry-run",
"--smb-share", "SHARE", "--smb-user", "alice", "--pptp-check", "--target", "192.0.2.10", "--mode", "dry-run",
"--dns-server=192.0.2.53,2001:db8::53",
"--db-path", str(pathlib.Path("wheel-check-history.sqlite").resolve())],
check=True, capture_output=True, text=True, timeout=30,
)
report = json.loads(result.stdout)
assert len(report["tools"]) == 3
assert len(report["tools"]) == 4
assert all(result["status"] == "dry-run" for result in report["tools"])
assert all(result["persistence"]["status"] == "saved" for result in report["tools"])
pptp_result = next(result for result in report["tools"] if result["tool"] == "pptp_control")
assert pptp_result["pptp"]["details"]["gre"]["status"] == "not-tested"
PY

- name: Publish to TestPyPI
Expand All @@ -171,7 +184,7 @@ jobs:
- name: Publish to PyPI
# Manual dispatch must obey the release-branch boundary too.
if: >-
github.ref == 'refs/heads/release/pypi-2.14.213.78.21.8' &&
github.ref == 'refs/heads/release/pypi-2.14.213.78.21.9' &&
(github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.pypi_environment == 'pypi'))
uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to AdPentestAI-Python are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.14.213.78.21.9] - 2026-10-08

### Added
- Opt-in `--pptp-check` / `pptp_control` for a bounded standard control exchange on TCP/1723 with one pinned endpoint.
- Protocol reply validation, server metadata, accepted/rejected status and explicit untested authentication/GRE/tunnel coverage.
- Domain-linked ORM and configuration-report evidence for completed, failed, blocked and dry-run PPTP checks.
- Offline packet, socket, deadline, scope, address-binding and persistence tests; no new runtime dependency.

## [2.14.213.78.21.8] - 2026-10-08

### Changed
Expand Down
24 changes: 18 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# AdPentestAI-Python

Version `2.14.213.78.21.8` is prepared with the domain ORM, DNS, XML persistence,
required SMB dependency and information-report features released in `.7`.
See [release notes](docs/RELEASE_2.14.213.78.21.8.md) and [domain ORM](docs/DOMAIN_ORM.md).
Version `2.14.213.78.21.9` adds an opt-in PPTP control check on TCP/1723 and carries
forward domain ORM, DNS/XML history, required SMB dependency and information reports.
See [release notes](docs/RELEASE_2.14.213.78.21.9.md) and [domain ORM](docs/DOMAIN_ORM.md).

The PyPI `2.14.213.78.21.6` files published on 2026-10-06 are the
`cb4ce2426765704ddb53d14276e5aacb2cf238fa` snapshot. The features introduced in
`.7` and retained in `.8` are absent from those published `.6` files. See the
`.7` and retained in `.9` are absent from those published `.6` files. See the
[verified artifact provenance](docs/PYPI_2.14.213.78.21.6_PROVENANCE.md).

SMBv1 host, user and UNC inventory from existing exports (2.14.213.78.21.8):
SMBv1 host, user and UNC inventory from existing exports (2.14.213.78.21.9):

```console
python -m adpentest --smbv1-data existing-report.json
Expand Down Expand Up @@ -50,6 +50,18 @@ PPTP control port 1723 is included; its GRE prerequisite is reported as untested
Results are port states and candidate labels, without service or vulnerability
verification. See [VPN port prerequisites and output](docs/DIAGNOSTIC_TOOLS.md#all-tcp-ports-and-vpn-port-states).

For a PPTP control check on one endpoint:

```console
python -m adpentest --pptp-check --target vpn.example --mode dry-run --domain lab.example --info-report ./pptp-review.json --db-path ./pptp-history.sqlite
```

Choose `--mode active --scope-confirmed` for an authorized control exchange. It
uses Python's standard library on TCP/1723, validates the bounded reply, records
the server's result code and metadata, and closes its connection. Domain-linked
ORM history includes failures and dry runs. Authentication, GRE and VPN tunnel
connectivity are reported as untested. See [PPTP checks](docs/DIAGNOSTIC_TOOLS.md#pptp-control-check).

For fixed TLS certificate, SMB and SSH metadata checks with a configuration
review report:

Expand Down Expand Up @@ -89,7 +101,7 @@ per stream and flag truncated output. See [diagnostic profiles](docs/DIAGNOSTIC_
The Python SMB client (`impacket>=0.13,<0.14`) is a required package dependency:

```console
python -m pip install --upgrade --no-cache-dir --index-url https://pypi.org/simple "adpentest==2.14.213.78.21.8"
python -m pip install --upgrade --no-cache-dir --index-url https://pypi.org/simple "adpentest==2.14.213.78.21.9"
```

With Nmap on PATH, run the combined built-in diagnostics on one host you administer:
Expand Down
2 changes: 1 addition & 1 deletion adpentest/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.14.213.78.21.8"
__version__ = "2.14.213.78.21.9"

from .report_generator import generate_html_report, export_html_report

Expand Down
2 changes: 1 addition & 1 deletion adpentest/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ def _ldap_spn_cli_requested(argv):
# Source: adpentest/__init__.py
# ============================================================================

__version__ = "2.14.213.78.21.8"
__version__ = "2.14.213.78.21.9"



Expand Down
Loading
Loading