╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1447 // signature verifies against the offered pubkey. │ │1448 var auth_attempts: u32 = 0; │ │1449 while (true) { │ │1291 - const req = try readNonIgnoredPacket(cs_cipher, allocator, reader); │ │1450 + const req = try readSessionPacket(io, allocator, reader, writer, cs_cipher, sc_cipher, rekey);│ │1451 defer allocator.free(req); │ │1293 - if (req.len >= 1 and req[0] == SSH_MSG_KEXINIT) { │ │1294 - try sendDisconnect(io, allocator, sc_cipher, writer, "rekey is not supported"); │ │1295 - return error.RekeyUnsupported; │ │1296 - } │ │1452 if (req.len < 1 or req[0] != SSH_MSG_USERAUTH_REQUEST) return error.UnexpectedMessage; │ │1453 │ │1454 var req_reader = std.Io.Reader.fixed(req[1..]); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │1458 defer allocator.free(service_name); │ │1459 const method = try takeStringField(allocator, &req_reader, 64); │ │1460 defer allocator.free(method); │ │1461 + │ │1462 + // RFC 4252 §5: the server must verify the requested service │ │1463 + if (!std.mem.eql(u8, service_name, "ssh-connection")) { │ │1464 + auth_attempts += 1; │ │1465 + if (auth_attempts >= max_auth_attempts) return error.TooManyAuthAttempts;│ │1466 + try sendUserauthFailure(io, allocator, sc_cipher, writer); │ │1467 + continue; │ │1468 + } │ │1469 │ │1470 if (!std.mem.eql(u8, method, "publickey")) { │ │1471 auth_attempts += 1; │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────╮ │1508 │ │1509 const ok = verifyUserauthSignature(│ │1510 allocator, │ │1348 - session_id, │ │1511 + &rekey.session_id, │ │1512 user_name, │ │1513 service_name, │ │1514 algo, │ ╰─────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │1542 try sc_cipher.writePacket(io, allocator, writer, buf.items); │ │1543 } │ │1544 │ │1382 -fn sendDisconnect( │ │1383 - io: std.Io, │ │1384 - allocator: std.mem.Allocator, │ │1385 - sc_cipher: *Cipher, │ │1386 - writer: *std.Io.Writer, │ │1387 - description: []const u8, │ │1388 -) !void { │ │1389 - var buf: std.ArrayList(u8) = .empty; │ │1390 - defer buf.deinit(allocator); │ │1391 - try buf.append(allocator, SSH_MSG_DISCONNECT); │ │1392 - try writeU32(&buf, allocator, SSH_DISCONNECT_PROTOCOL_ERROR); │ │1393 - try writeStringField(&buf, allocator, description); │ │1394 - try writeStringField(&buf, allocator, ""); │ │1395 - try sc_cipher.writePacket(io, allocator, writer, buf.items); │ │1396 -} │ │1397 - │ │1545 /// Append the canonical publickey-signed-data bytes (RFC 4252 §7) to `buf`.│ │1546 /// Used by the server to recompute the signed input for verification │ │1547 pub fn appendPublickeySignedData( │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────╮ │1640 writer: *std.Io.Writer, │ │1641 cs_cipher: *Cipher, │ │1642 sc_cipher: *Cipher, │ │1643 + rekey: *const RekeyState, │ │1644 fingerprint: *const [fingerprint_len]u8,│ │1645 handler: anytype, │ │1646 ) !void { │ ╰──────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1649 defer if (pending_exec) |s| allocator.free(s); │ │1650 │ │1651 while (true) { │ │1504 - const packet = try cs_cipher.readPacket(allocator, reader); │ │1652 + const packet = try readSessionPacket(io, allocator, reader, writer, cs_cipher, sc_cipher, rekey);│ │1653 defer allocator.free(packet); │ │1654 if (packet.len < 1) return error.EmptyPacket; │ │1655 const msg_type = packet[0]; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1656 │ │1657 switch (msg_type) { │ │1658 SSH_MSG_GLOBAL_REQUEST => try handleGlobalRequest(io, allocator, sc_cipher, writer, packet),│ │1511 - │ │1512 - SSH_MSG_KEXINIT => { │ │1513 - try sendDisconnect(io, allocator, sc_cipher, writer, "rekey is not supported"); │ │1514 - return error.RekeyUnsupported; │ │1515 - }, │ │1659 │ │1660 SSH_MSG_CHANNEL_OPEN => { │ │1661 if (channel != null) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │1680 .writer = writer, │ │1681 .cs_cipher = cs_cipher, │ │1682 .sc_cipher = sc_cipher, │ │1683 + .rekey = rekey, │ │1684 .channel = ch, │ │1685 .fingerprint = fingerprint.*,│ │1686 }; │ ╰───────────────────────────────────────────────────────────╯