Commit 1f9fa82235
Changed files (3)
lib
std
crypto
Certificate
os
windows
lib/std/crypto/Certificate/Bundle.zig
@@ -57,10 +57,8 @@ pub fn deinit(cb: *Bundle, gpa: Allocator) void {
pub fn rescan(cb: *Bundle, gpa: Allocator) !void {
switch (builtin.os.tag) {
.linux => return rescanLinux(cb, gpa),
- .windows => {
- // TODO
- },
.macos => return rescanMac(cb, gpa),
+ .windows => return rescanWindows(cb, gpa),
else => {},
}
}
@@ -109,6 +107,34 @@ pub fn rescanLinux(cb: *Bundle, gpa: Allocator) !void {
cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len);
}
+pub fn rescanWindows(cb: *Bundle, gpa: Allocator) !void {
+ cb.bytes.clearRetainingCapacity();
+ cb.map.clearRetainingCapacity();
+
+ const store = try os.windows.crypt32.certOpenSystemStoreW(null, &[4:0]u16{ 'R', 'O', 'O', 'T' });
+ defer os.windows.crypt32.certCloseStore(store, 0) catch unreachable;
+
+ var ctx = os.windows.crypt32.CertEnumCertificatesInStore(store, null);
+ while (ctx) |context| : (ctx = os.windows.crypt32.CertEnumCertificatesInStore(store, ctx)) {
+ var start = @intCast(u32, cb.bytes.items.len);
+ try cb.bytes.appendSlice(gpa, context.pbCertEncoded[0..context.cbCertEncoded]);
+ var parsed = Certificate.parse(.{
+ .buffer = cb.bytes.items,
+ .index = start,
+ }) catch {
+ cb.bytes.items.len = start;
+ continue;
+ };
+ const gop = try cb.map.getOrPutContext(gpa, parsed.subject_slice, .{ .cb = cb });
+ if (gop.found_existing) {
+ cb.bytes.items.len = start;
+ } else {
+ gop.value_ptr.* = start;
+ }
+ }
+ cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len);
+}
+
pub fn addCertsFromDirPath(
cb: *Bundle,
gpa: Allocator,
@@ -224,6 +250,7 @@ pub fn parseCert(cb: *Bundle, gpa: Allocator, decoded_start: u32, now_sec: i64)
const builtin = @import("builtin");
const std = @import("../../std.zig");
const assert = std.debug.assert;
+const os = std.os;
const fs = std.fs;
const mem = std.mem;
const crypto = std.crypto;
lib/std/os/windows/crypt32.zig
@@ -0,0 +1,54 @@
+const std = @import("../../std.zig");
+const windows = std.os.windows;
+const BOOL = windows.BOOL;
+const DWORD = windows.DWORD;
+const BYTE = windows.BYTE;
+const LPCWSTR = windows.LPCWSTR;
+const WINAPI = windows.WINAPI;
+const GetLastError = windows.kernel32.GetLastError;
+
+pub const CERT_INFO = *opaque {};
+pub const HCERTSTORE = *opaque {};
+pub const CERT_CONTEXT = extern struct {
+ dwCertEncodingType: DWORD,
+ pbCertEncoded: [*]BYTE,
+ cbCertEncoded: DWORD,
+ pCertInfo: CERT_INFO,
+ hCertStore: HCERTSTORE,
+};
+
+pub extern "crypt32" fn CertOpenSystemStoreW(
+ _: ?*const anyopaque,
+ szSubsystemProtocol: LPCWSTR,
+) callconv(WINAPI) ?HCERTSTORE;
+pub fn certOpenSystemStoreW(
+ hProv: ?*const anyopaque,
+ szSubsystemProtocol: LPCWSTR,
+) !HCERTSTORE {
+ const value = CertOpenSystemStoreW(hProv, szSubsystemProtocol);
+ return if (value) |store|
+ store
+ else switch (GetLastError()) {
+ .FILE_NOT_FOUND => error.FileNotFound,
+ else => |err| windows.unexpectedError(err),
+ };
+}
+
+pub extern "crypt32" fn CertCloseStore(
+ hCertStore: HCERTSTORE,
+ dwFlags: DWORD,
+) callconv(WINAPI) BOOL;
+pub fn certCloseStore(
+ hCertStore: HCERTSTORE,
+ dwFlags: DWORD,
+) !void {
+ const value = CertCloseStore(hCertStore, dwFlags);
+ if (value == 0) {
+ return windows.unexpectedError(GetLastError());
+ }
+}
+
+pub extern "crypt32" fn CertEnumCertificatesInStore(
+ hCertStore: HCERTSTORE,
+ pPrevCertContext: ?*CERT_CONTEXT,
+) callconv(WINAPI) ?*CERT_CONTEXT;
lib/std/os/windows.zig
@@ -28,6 +28,7 @@ pub const user32 = @import("windows/user32.zig");
pub const ws2_32 = @import("windows/ws2_32.zig");
pub const gdi32 = @import("windows/gdi32.zig");
pub const winmm = @import("windows/winmm.zig");
+pub const crypt32 = @import("windows/crypt32.zig");
pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize));