Skip to content

fix: Fix legacy authentication for all PLCs with legacy firmware. - #849

Draft
bvanelli wants to merge 1 commit into
gijzelaerr:masterfrom
bvanelli:fix/legacy-authentication
Draft

fix: Fix legacy authentication for all PLCs with legacy firmware.#849
bvanelli wants to merge 1 commit into
gijzelaerr:masterfrom
bvanelli:fix/legacy-authentication

Conversation

@bvanelli

@bvanelli bvanelli commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Changes

Important: Marked as draft because the capture bytes requires #848 to be merged, otherwise tests will fail.

Legacy authentication was never really supported, and that caused authentication to fail on old hardware. The previous condition to authenticate with legacy was the cryptography package not being available:

            # Try new-style first, fall back to legacy SHA-1 XOR
            try:
                response_data = build_new_response(password, challenge, self._oms_secret, "")
                self._send_legitimation_new(response_data)
            except NotImplementedError:
                # cryptography package not available, use legacy
                response_data = build_legacy_response(password, challenge)
                self._send_legitimation_legacy(response_data)

The authentication mode is decided by reading the PLC model and firmware version, and using decide_legitimation_mode to decide which auth to use. The LegitimationType also clearly encodes the 1/2 value into an enum.

This uses a capture from the C# driver to implement with a contract test the exact authentication that the legacy PLC expects. The capture was taken with an S7-1512 Series using 2.9.8 firmware.

Testing

Doing a browse and a variable read against a real PLC now works. The legitimation lowers the protection level correct and both the browse and read are successful:

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): 4a828122931ecc402189a828141a20631cd6be7c
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=1879051449, tls=True
INFO s7commplus.client: Performing PLC legitimation (password authentication)
INFO s7commplus.connection: Using legacy legitimation
INFO s7commplus.connection: Received legitimation challenge (20 bytes)
INFO s7commplus.connection: PLC legitimation completed, protection level 4 -> 2
INFO __main__: Connected to 192.168.101.34: protocol=V2 session=0x70000CB9 session_setup_ok=True tls_active=True
Browse found 23728 variables
Example read:
  LGF_SinusCI_DB.amplitude (REAL) @ 8A0E0007.E
LGF_SinusCI_DB.amplitude (REAL) = 3f800000

The same code, when running it from master, uses the _send_legitimation_new which gets rejected by the PLC:

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): f9a3c61dd5730e484ec329fb6141ea708ca86f3c
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=1879051449, tls=True
INFO s7commplus.client: Performing PLC legitimation (password authentication)
INFO s7commplus.connection: Received legitimation challenge (20 bytes)
Traceback (most recent call last):
  File "/Users/brunno.vanelli/Documents/git/python-snap7/example/s7commplus1_browse_sync.py", line 29, in <module>
    client.connect(host, use_tls=True, password="[redacted]")
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/brunno.vanelli/Documents/git/python-snap7/s7commplus/client.py", line 114, in connect
    self._open_connection()
    ~~~~~~~~~~~~~~~~~~~~~^^
  File "/Users/brunno.vanelli/Documents/git/python-snap7/s7commplus/client.py", line 131, in _open_connection
    self._connection.authenticate(p["password"])
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/Users/brunno.vanelli/Documents/git/python-snap7/s7commplus/connection.py", line 530, in authenticate
    self._send_legitimation_new(response_data)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/Users/brunno.vanelli/Documents/git/python-snap7/s7commplus/connection.py", line 579, in _send_legitimation_new
    _check_set_variable_response(resp_payload)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "/Users/brunno.vanelli/Documents/git/python-snap7/s7commplus/connection.py", line 207, in _check_set_variable_response
    raise S7ConnectionError(f"Legitimation rejected by PLC: return_value=0x{return_value:X}")
snap7.error.S7ConnectionError: Legitimation rejected by PLC: return_value=0xC592CC000222FEA1

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.

1 participant