diff --git a/src/cdp/domains/security.zig b/src/cdp/domains/security.zig index dad0cebd..830cd591 100644 --- a/src/cdp/domains/security.zig +++ b/src/cdp/domains/security.zig @@ -21,9 +21,48 @@ const std = @import("std"); pub fn processMessage(cmd: anytype) !void { const action = std.meta.stringToEnum(enum { enable, + setIgnoreCertificateErrors, }, cmd.input.action) orelse return error.UnknownMethod; switch (action) { .enable => return cmd.sendResult(null, .{}), + .setIgnoreCertificateErrors => return setIgnoreCertificateErrors(cmd), } } + +fn setIgnoreCertificateErrors(cmd: anytype) !void { + const params = (try cmd.params(struct { + ignore: bool, + })) orelse return error.InvalidParams; + + if (params.ignore) { + try cmd.cdp.browser.http_client.disableTlsVerify(); + } else { + try cmd.cdp.browser.http_client.enableTlsVerify(); + } + + return cmd.sendResult(null, .{}); +} + +const testing = @import("../testing.zig"); + +test "cdp.Security: setIgnoreCertificateErrors" { + var ctx = testing.context(); + defer ctx.deinit(); + + _ = try ctx.loadBrowserContext(.{ .id = "BID-9" }); + + try ctx.processMessage(.{ + .id = 8, + .method = "Security.setIgnoreCertificateErrors", + .params = .{ .ignore = true }, + }); + try ctx.expectSentResult(null, .{ .id = 8 }); + + try ctx.processMessage(.{ + .id = 9, + .method = "Security.setIgnoreCertificateErrors", + .params = .{ .ignore = false }, + }); + try ctx.expectSentResult(null, .{ .id = 9 }); +} diff --git a/src/http/Client.zig b/src/http/Client.zig index 43ada88c..40647336 100644 --- a/src/http/Client.zig +++ b/src/http/Client.zig @@ -93,6 +93,11 @@ notification: ?*Notification = null, // restoring, this originally-configured value is what it goes to. http_proxy: ?[:0]const u8 = null, +// track if the client use a proxy for connections. +// We can't use http_proxy because we want also to track proxy configured via +// CDP. +use_proxy: bool, + // The complete user-agent header line user_agent: [:0]const u8, @@ -126,6 +131,7 @@ pub fn init(allocator: Allocator, ca_blob: ?c.curl_blob, opts: Http.Opts) !*Clie .handles = handles, .allocator = allocator, .http_proxy = opts.http_proxy, + .use_proxy = opts.http_proxy != null, .user_agent = opts.user_agent, .transfer_pool = transfer_pool, }; @@ -315,6 +321,7 @@ pub fn changeProxy(self: *Client, proxy: [:0]const u8) !void { for (self.handles.handles) |*h| { try errorCheck(c.curl_easy_setopt(h.conn.easy, c.CURLOPT_PROXY, proxy.ptr)); } + self.use_proxy = true; } // Same restriction as changeProxy. Should be ok since this is only called on @@ -326,6 +333,41 @@ pub fn restoreOriginalProxy(self: *Client) !void { for (self.handles.handles) |*h| { try errorCheck(c.curl_easy_setopt(h.conn.easy, c.CURLOPT_PROXY, proxy)); } + self.use_proxy = proxy != null; +} + +// Enable TLS verification on all connections. +pub fn enableTlsVerify(self: *const Client) !void { + try self.ensureNoActiveConnection(); + + for (self.handles.handles) |*h| { + const easy = h.conn.easy; + + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_SSL_VERIFYHOST, @as(c_long, 2))); + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_SSL_VERIFYPEER, @as(c_long, 1))); + + if (self.use_proxy) { + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PROXY_SSL_VERIFYHOST, @as(c_long, 2))); + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PROXY_SSL_VERIFYPEER, @as(c_long, 1))); + } + } +} + +// Disable TLS verification on all connections. +pub fn disableTlsVerify(self: *const Client) !void { + try self.ensureNoActiveConnection(); + + for (self.handles.handles) |*h| { + const easy = h.conn.easy; + + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_SSL_VERIFYHOST, @as(c_long, 0))); + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_SSL_VERIFYPEER, @as(c_long, 0))); + + if (self.use_proxy) { + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PROXY_SSL_VERIFYHOST, @as(c_long, 0))); + try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PROXY_SSL_VERIFYPEER, @as(c_long, 0))); + } + } } fn makeRequest(self: *Client, handle: *Handle, transfer: *Transfer) !void {