authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-27 23:30:43-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-02 16:57:16-07:00
log477864dca560b03bb3c3e8e7e1e50362e7ed681f
tree8c2baf47e3c9b478fd38fb5cc2b41edfc797ae8b
parentceb211e65fe6bfe864b1150d08cd5e0383f6c2c2

std.crypto.tls.Client: fix truncation attack vulnerability


2 files changed, 10 insertions(+), 9 deletions(-)

lib/std/crypto/tls/Client.zig+6-3
...@@ -725,8 +725,11 @@ pub fn writeAll(c: *Client, stream: net.Stream, bytes: []const u8) !void {...@@ -725,8 +725,11 @@ pub fn writeAll(c: *Client, stream: net.Stream, bytes: []const u8) !void {
725725
726/// Returns number of bytes that have been read, which are now populated inside726/// Returns number of bytes that have been read, which are now populated inside
727/// `buffer`. A return value of zero bytes does not necessarily mean end of727/// `buffer`. A return value of zero bytes does not necessarily mean end of
728/// stream.728/// stream. Instead, the `eof` flag is set upon end of stream. The `eof` flag
729/// may be set after any call to `read`, including when greater than zero bytes
730/// are returned, and this function asserts that `eof` is `false`.
729pub fn read(c: *Client, stream: net.Stream, buffer: []u8) !usize {731pub fn read(c: *Client, stream: net.Stream, buffer: []u8) !usize {
732 assert(!c.eof);
730 const prev_len = c.partially_read_len;733 const prev_len = c.partially_read_len;
731 var in_buf: [max_ciphertext_len * 4]u8 = undefined;734 var in_buf: [max_ciphertext_len * 4]u8 = undefined;
732 mem.copy(u8, &in_buf, c.partially_read_buffer[0..prev_len]);735 mem.copy(u8, &in_buf, c.partially_read_buffer[0..prev_len]);
...@@ -738,8 +741,8 @@ pub fn read(c: *Client, stream: net.Stream, buffer: []u8) !usize {...@@ -738,8 +741,8 @@ pub fn read(c: *Client, stream: net.Stream, buffer: []u8) !usize {
738 const actual_read_len = try stream.read(ask_slice);741 const actual_read_len = try stream.read(ask_slice);
739 const frag = in_buf[0 .. prev_len + actual_read_len];742 const frag = in_buf[0 .. prev_len + actual_read_len];
740 if (frag.len == 0) {743 if (frag.len == 0) {
741 c.eof = true;744 // This is either a truncation attack, or a bug in the server.
742 return 0;745 return error.TlsConnectionTruncated;
743 }746 }
744 var in: usize = 0;747 var in: usize = 0;
745 var out: usize = 0;748 var out: usize = 0;
lib/std/http/Client.zig+4-6
...@@ -66,13 +66,11 @@ pub const Request = struct {...@@ -66,13 +66,11 @@ pub const Request = struct {
66 var index: usize = 0;66 var index: usize = 0;
67 while (index < len) {67 while (index < len) {
68 const amt = try req.read(buffer[index..]);68 const amt = try req.read(buffer[index..]);
69 if (amt == 0) {
70 switch (req.protocol) {
71 .http => break,
72 .https => if (req.tls_client.eof) break,
73 }
74 }
75 index += amt;69 index += amt;
70 switch (req.protocol) {
71 .http => if (amt == 0) break,
72 .https => if (req.tls_client.eof) break,
73 }
76 }74 }
77 return index;75 return index;
78 }76 }