Skip to content

feat: expose the PLC protection level on the S7CommPlus clients - #826

Open
bvanelli wants to merge 1 commit into
gijzelaerr:masterfrom
bvanelli:expose-protection-level
Open

feat: expose the PLC protection level on the S7CommPlus clients#826
bvanelli wants to merge 1 commit into
gijzelaerr:masterfrom
bvanelli:expose-protection-level

Conversation

@bvanelli

@bvanelli bvanelli commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Read the session's effective protection level once the S7CommPlus session is established, and expose it as a protection_level property on the connection, the sync client and the async client, so callers can tell an unprotected PLC from one that needs legitimation. AccessLevel names the values the PLC reports.

This is required to display better exceptions whenever the PLC is not browsable/partially browsable. A high-protection level (4) indicates that the PLC is password protected.

See reference code during legitimation:

https://github.com/thomas-v2/S7CommPlusDriver/blob/dbd61e447c7aaf4486cf1f1fe0201212a6bd93c8/src/S7CommPlusDriver/Legitimation/Legitimation.cs#L118-L123

Here are the logs from the connection test to three different PLCs
INFO snap7.connection: Connected to 192.168.101.34:102, PDU size: 1024
INFO s7commplus.connection: TLS activated (tunneled inside COTP frames)
INFO s7commplus.connection: ServerSessionVersion captured (87 bytes)
INFO s7commplus.connection: Public key fingerprint captured: 00:181B7B0847D11694
INFO s7commplus.connection: Session challenge captured (20 bytes): f8bcd90fb18fbe6d93bf513d6475f7ee23a5be79
INFO s7commplus.connection: Session setup completed successfully
INFO s7commplus.connection: V2 IntegrityId tracking enabled
INFO s7commplus.connection: PLC reports protection level: 4
INFO s7commplus.connection: S7CommPlus connected to 192.168.101.34:102, version=V2, session=1879051447, tls=True
...
INFO snap7.connection: Connected to 192.168.101.36:102, PDU size: 1024
INFO s7commplus.connection: TLS activated (tunneled inside COTP frames)
INFO s7commplus.connection: ServerSessionVersion captured (87 bytes)
INFO s7commplus.connection: Public key fingerprint captured: 00:181B7B0847D11694
INFO s7commplus.connection: Session challenge captured (20 bytes): 783cc57d8fba0878cf2bfe49237464dd6c3aeaa3
INFO s7commplus.connection: Session setup completed successfully
INFO s7commplus.connection: V2 IntegrityId tracking enabled
INFO s7commplus.connection: PLC reports protection level: 3
INFO s7commplus.connection: S7CommPlus connected to 192.168.101.36:102, version=V2, session=1879051858, tls=True
...
INFO snap7.connection: Connected to 192.168.101.51:102, PDU size: 1024
INFO s7commplus.connection: TLS activated (tunneled inside COTP frames)
INFO s7commplus.connection: ServerSessionVersion captured (88 bytes)
INFO s7commplus.connection: Public key fingerprint captured: 00:181B7B0847D11694
INFO s7commplus.connection: Session challenge captured (20 bytes): 573806da4aa6f548da4f06ca687b7fe703ec9543
INFO s7commplus.connection: Session setup completed successfully
INFO s7commplus.connection: V2 IntegrityId tracking enabled
INFO s7commplus.connection: PLC reports protection level: 0
INFO s7commplus.connection: S7CommPlus connected to 192.168.101.51:102, version=V2, session=1879052254, tls=True
INFO __main__: Connected to 192.168.101.51: protocol=V2 session=0x70000FDE session_setup_ok=True tls_active=True
...

Easier to review and merge to master after #775

@gijzelaerr
gijzelaerr changed the base branch from fix-tls-layering-v2 to master August 19, 2026 05:23

@gijzelaerr gijzelaerr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hardware captures and focused implementation. I merged current master into the branch so the PR now targets master cleanly and shows only the intended five files.

I found three issues to address:

  1. The protection-level GET_VAR_SUBSTREAMED request currently runs before _session_activate(). V1-initial SessionKey PLCs require activation before any data read, so this can reject or reset connect(). The query is also unconditional when session setup is incomplete, which can break the existing fallback path. Please activate first for SessionKey sessions and only query a session where this operation is supported.

  2. protection_level is cached during connect but is never refreshed after sync or async authenticate(). Successful legitimation changes the effective access level, so the exposed value becomes stale. Please refresh it after authentication, or rename/document it as the initial protection level if that is the intended contract.

  3. _parse_protection_level_response() skips the PValue flags/type bytes without validating them and leaks ValueError for short VLQ data. Please require a scalar UDINT, validate bounds, and wrap malformed framing in S7ConnectionError like _parse_get_var_substreamed_response(). Add malformed/type regression coverage as well.

Local validation of the master merge: 1,766 tests passed, 82 skipped; mypy, Ruff, formatting, and the other pre-commit hooks passed; wheel build passed.

Read the session's effective protection level (id 1842) once the S7CommPlus session is established, and expose it as a protection_level property on the connection, the sync client and the async client, so callers can tell an unprotected PLC from one that needs legitimation. AccessLevel names the values the PLC reports.

The request reuses the existing GetVarSubStreamed payload builder, whose framing matches the reference driver: the 0x0001 field following the ObjectQualifier is a protocol constant, and the IntegrityId is the separate VLQ that send_request splices in after it.
@gijzelaerr
gijzelaerr force-pushed the expose-protection-level branch from a26f492 to ce4c1c6 Compare August 19, 2026 05:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants