╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │1649 } │ │1650 │ │1651 // has signature — verify it │ │1675 - const signature_blob = try takeStringField(allocator, &req_reader, 1024);│ │1676 - defer allocator.free(signature_blob); │ │1652 + const signature_blob = try takeString(&req_reader, 1024); │ │1653 │ │1654 const ok = verifyUserauthSignature( │ │1655 allocator, │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │1720 │ │1721 // parse pubkey_blob: string "ssh-ed25519" || string raw_pubkey │ │1722 var pubkey_reader = std.Io.Reader.fixed(pubkey_blob); │ │1747 - const pk_algo = try takeStringField(allocator, &pubkey_reader, 64); │ │1748 - defer allocator.free(pk_algo); │ │1723 + const pk_algo = try takeString(&pubkey_reader, 64); │ │1724 if (!std.mem.eql(u8, pk_algo, "ssh-ed25519")) return false; │ │1750 - const raw_pubkey = try takeStringField(allocator, &pubkey_reader, 64);│ │1751 - defer allocator.free(raw_pubkey); │ │1725 + const raw_pubkey = try takeString(&pubkey_reader, 64); │ │1726 if (raw_pubkey.len != Ed25519.PublicKey.encoded_length) return false; │ │1727 │ │1728 // parse signature_blob: string "ssh-ed25519" || string raw_signature │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1729 var sig_reader = std.Io.Reader.fixed(signature_blob); │ │1756 - const sig_algo = try takeStringField(allocator, &sig_reader, 64); │ │1757 - defer allocator.free(sig_algo); │ │1730 + const sig_algo = try takeString(&sig_reader, 64); │ │1731 if (!std.mem.eql(u8, sig_algo, "ssh-ed25519")) return false; │ │1759 - const raw_sig = try takeStringField(allocator, &sig_reader, Ed25519.Signature.encoded_length);│ │1760 - defer allocator.free(raw_sig); │ │1732 + const raw_sig = try takeString(&sig_reader, Ed25519.Signature.encoded_length); │ │1733 if (raw_sig.len != Ed25519.Signature.encoded_length) return false; │ │1734 │ │1735 var pubkey_bytes: [Ed25519.PublicKey.encoded_length]u8 = undefined; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │1777 ) !void { │ │1778 const allocator = conn.allocator; │ │1779 var channel: ?Channel = null; │ │1808 - var pending_exec: ?[]u8 = null; │ │1809 - defer if (pending_exec) |s| allocator.free(s); │ │1780 │ │1781 while (true) { │ │1782 const packet = try readSessionPacket(conn);│ ╰─────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1797 │ │1798 SSH_MSG_CHANNEL_REQUEST => { │ │1799 const ch = if (channel) |*c| c else continue; │ │1830 - const start_request = try handleChannelRequest(conn, ch, packet, &pending_exec);│ │1800 + const start_request = try handleChannelRequest(conn, ch, packet); │ │1801 + // the request borrows from the packet, which outlives the session │ │1802 if (start_request) |request| { │ │1803 // any key authenticates, so the deadline holds until here │ │1804 if (conn.idle) |idle| idle.session_started.store(true, .release); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────╮ │1856 // boolean want_reply │ │1857 // …request-specific data we ignore │ │1858 var r = std.Io.Reader.fixed(packet[1..]); │ │1888 - const name = try takeStringField(conn.allocator, &r, 256);│ │1889 - defer conn.allocator.free(name); │ │1859 + _ = try takeString(&r, 256); │ │1860 const want_reply = (try r.takeByte()) != 0; │ │1861 if (want_reply) { │ │1862 try conn.writePacket(&[_]u8{SSH_MSG_REQUEST_FAILURE});│ ╰────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────╮ │1875 // uint32 initial_window │ │1876 // uint32 max_packet │ │1877 var r = std.Io.Reader.fixed(packet[1..]); │ │1908 - const ch_type = try takeStringField(allocator, &r, 64);│ │1909 - defer allocator.free(ch_type); │ │1878 + const ch_type = try takeString(&r, 64); │ │1879 const remote_id = try r.takeInt(u32, .big); │ │1880 const initial_window = try r.takeInt(u32, .big); │ │1881 const max_packet = try r.takeInt(u32, .big); │ ╰─────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1931 } │ │1932 │ │1933 /// returns the session request if this one triggered it, else null. an exec │ │1965 -/// command is owned by `pending_exec`, which outlives the packet it arrived in. │ │1966 -fn handleChannelRequest(conn: *Conn, ch: *Channel, packet: []const u8, pending_exec: *?[]u8) !?Request {│ │1967 - const allocator = conn.allocator; │ │1968 - │ │1934 +/// command borrows from `packet`. │ │1935 +fn handleChannelRequest(conn: *Conn, ch: *Channel, packet: []const u8) !?Request { │ │1936 // byte SSH_MSG_CHANNEL_REQUEST │ │1937 // uint32 recipient_channel (== our local_id) │ │1938 // string request_type │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │1941 var r = std.Io.Reader.fixed(packet[1..]); │ │1942 const recipient_channel = try r.takeInt(u32, .big); │ │1943 if (recipient_channel != ch.local_id) return error.UnknownChannel;│ │1977 - const req_type = try takeStringField(allocator, &r, 64); │ │1978 - defer allocator.free(req_type); │ │1944 + const req_type = try takeString(&r, 64); │ │1945 const want_reply = (try r.takeByte()) != 0; │ │1946 │ │1947 if (std.mem.eql(u8, req_type, "pty-req")) { │ ╰────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │1948 // string TERM, uint32 width chars, uint32 height rows, uint32 width px,│ │1949 // uint32 height px, string modes │ │1984 - const term = try takeStringField(allocator, &r, 64); │ │1985 - defer allocator.free(term); │ │1950 + _ = try takeString(&r, 64); │ │1951 ch.pty = try takePtySize(&r); │ │1952 try replyChannelRequest(conn, ch, want_reply, true); │ │1953 return null; │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯