From b5529a8c58f1e718fd07a15af25b940db2ee9700 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Thu, 21 Dec 2023 15:39:31 +0900 Subject: [PATCH] allow use of std.crypto.Certificate.Bundle --- src/easy.zig | 10 ++++++++++ src/main.zig | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/easy.zig b/src/easy.zig index 888fc6f..e1de9ef 100644 --- a/src/easy.zig +++ b/src/easy.zig @@ -259,6 +259,16 @@ pub fn do(self: Self, req: anytype) !Response { try checkCode(c.curl_easy_setopt(self.handle, c.CURLOPT_CUSTOMREQUEST, req.args.method.asString().ptr)); try checkCode(c.curl_easy_setopt(self.handle, c.CURLOPT_VERBOSE, req.getVerbose())); + const CaBundle = @import("main.zig").CaBundle; + if (CaBundle) |bundle| { + const blob = c.curl_blob { + .data = @constCast(bundle.ptr), + .len = bundle.len, + .flags = c.CURL_BLOB_NOCOPY, + }; + try checkCode(c.curl_easy_setopt(self.handle, c.CURLOPT_CAINFO_BLOB, blob)); + } + const body = try req.getBody(self.allocator); defer if (body) |b| { self.allocator.free(b); diff --git a/src/main.zig b/src/main.zig index 3fb6ee3..0b10e16 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6,6 +6,38 @@ pub const Easy = @import("easy.zig"); pub usingnamespace Easy; pub usingnamespace @import("c.zig"); +pub var CaBundle: ?[]const u8 = null; + +/// Not thread safe +/// Refreshes CaBundle for future requests +pub fn refresh_ca_bundle() !void { + if (CaBundle) |ptr| std.heap.c_allocator.free(ptr); + var bundle = std.crypto.Certificate.Bundle{}; + defer bundle.deinit(std.heap.c_allocator); + try bundle.rescan(std.heap.c_allocator); + var pem = std.ArrayListUnmanaged(u8){}; + const base64 = std.base64.standard.Encoder; + var iter = bundle.map.iterator(); + while (iter.next()) |entry| { + const der = try std.crypto.Certificate.der.Element.parse(bundle.bytes.items, entry.value_ptr.*); + const cert = bundle.bytes.items[entry.value_ptr.*..der.slice.end]; + const begin_marker = "-----BEGIN CERTIFICATE-----"; + const end_marker = "\n-----END CERTIFICATE-----\n"; + const encoded_sz = base64.calcSize(cert.len); + try pem.ensureTotalCapacity(std.heap.c_allocator, pem.items.len + encoded_sz); + var encoded = try std.heap.c_allocator.alloc(u8, encoded_sz); + defer std.heap.c_allocator.free(encoded); + _ = base64.encode(encoded[0..], cert); + try pem.appendSlice(std.heap.c_allocator, begin_marker); + for (encoded, 0..) |char, n| { + if (n % 64 == 0) try pem.append(std.heap.c_allocator, '\n'); + try pem.append(std.heap.c_allocator, char); + } + try pem.appendSlice(std.heap.c_allocator, end_marker); + } + CaBundle = pem.items; +} + /// This function sets up the program environment that libcurl needs. /// Since this function is not thread safe before libcurl 7.84.0, this function /// must be called before the program calls any other function in libcurl. @@ -17,6 +49,8 @@ pub fn global_init() !void { /// This function releases resources acquired by curl_global_init. pub fn global_deinit() void { + if (CaBundle) |bundle| std.heap.c_allocator.free(bundle); + CaBundle = null; c.curl_global_cleanup(); }