From 98b0232d1255054962fabf5e560a34dd3d14489f Mon Sep 17 00:00:00 2001 From: Ali Norouzi Date: Wed, 10 Jun 2026 15:36:29 +0200 Subject: [PATCH] SSH: fix _ComaStrField length calculation AI-Assisted: yes (Claude Sonnet 4.6) --- scapy/layers/ssh.py | 3 +++ test/scapy/layers/ssh.uts | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/scapy/layers/ssh.py b/scapy/layers/ssh.py index a7fbbd52714..9b72a7cd5d2 100644 --- a/scapy/layers/ssh.py +++ b/scapy/layers/ssh.py @@ -62,6 +62,9 @@ def m2i(self, pkt, x): def i2m(self, pkt, x): return super(_ComaStrField, self).i2m(pkt, b",".join(x)) + def i2len(self, pkt, x): + return len(self.i2m(pkt, x)) + class SSHString(Packet): fields_desc = [ diff --git a/test/scapy/layers/ssh.uts b/test/scapy/layers/ssh.uts index b6c82830c9e..bc375772aea 100644 --- a/test/scapy/layers/ssh.uts +++ b/test/scapy/layers/ssh.uts @@ -35,3 +35,45 @@ assert pkts[10].pay.H_hash.value.data.key.value == b"\xef\xecj=~\xe4Y'\xe9\xad\x assert isinstance(pkts[10][SSH:2].pay, SSHNewKeys) assert isinstance(pkts[12].pay, SSHNewKeys) + += ComaStrField encode/decode + +import struct +from scapy.layers.ssh import _ComaStrField + +csf = _ComaStrField("names", []) + +# m2i splits on commas +assert csf.m2i(None, b"curve25519-sha256,diffie-hellman-group14-sha256") == \ + [b"curve25519-sha256", b"diffie-hellman-group14-sha256"] + +# i2m joins with commas +assert csf.i2m(None, [b"curve25519-sha256", b"diffie-hellman-group14-sha256"]) == \ + b"curve25519-sha256,diffie-hellman-group14-sha256" + +# single element, no comma +assert csf.m2i(None, b"ssh-ed25519") == [b"ssh-ed25519"] +assert csf.i2m(None, [b"ssh-ed25519"]) == b"ssh-ed25519" + +# empty string <-> single empty-name list +assert csf.m2i(None, b"") == [b""] +assert csf.i2m(None, [b""]) == b"" + +# round trips +names = [b"a", b"b", b"c"] +assert csf.m2i(None, csf.i2m(None, names)) == names +raw = b"x,y,z" +assert csf.i2m(None, csf.m2i(None, raw)) == raw + +# through NameList length +nl = NameList(names=[b"curve25519-sha256"]) +raw = bytes(nl) +assert struct.unpack("!I", raw[:4])[0] == len(b"curve25519-sha256"), \ + "NameList length field encodes item count instead of byte length" + +# Multi-name list +nl2 = NameList(names=[b"curve25519-sha256", b"diffie-hellman-group14-sha256"]) +raw2 = bytes(nl2) +expected = b"curve25519-sha256,diffie-hellman-group14-sha256" +assert raw2[4:] == expected +assert struct.unpack("!I", raw2[:4])[0] == len(expected)