mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
add explicit error union for Bundle.rescan and associated functions
This commit is contained in:
parent
40e1fca34b
commit
038ed32cff
@ -371,7 +371,9 @@ test "Parsed.checkHostName" {
|
||||
try expectEqual(false, Parsed.checkHostName("lang.org", "zig*.org"));
|
||||
}
|
||||
|
||||
pub fn parse(cert: Certificate) !Parsed {
|
||||
pub const ParseError = der.Element.ParseElementError || ParseVersionError || ParseTimeError || ParseEnumError || ParseBitStringError;
|
||||
|
||||
pub fn parse(cert: Certificate) ParseError!Parsed {
|
||||
const cert_bytes = cert.buffer;
|
||||
const certificate = try der.Element.parse(cert_bytes, cert.index);
|
||||
const tbs_certificate = try der.Element.parse(cert_bytes, certificate.slice.start);
|
||||
@ -514,14 +516,18 @@ pub fn contents(cert: Certificate, elem: der.Element) []const u8 {
|
||||
return cert.buffer[elem.slice.start..elem.slice.end];
|
||||
}
|
||||
|
||||
pub const ParseBitStringError = error{ CertificateFieldHasWrongDataType, CertificateHasInvalidBitString };
|
||||
|
||||
pub fn parseBitString(cert: Certificate, elem: der.Element) !der.Element.Slice {
|
||||
if (elem.identifier.tag != .bitstring) return error.CertificateFieldHasWrongDataType;
|
||||
if (cert.buffer[elem.slice.start] != 0) return error.CertificateHasInvalidBitString;
|
||||
return .{ .start = elem.slice.start + 1, .end = elem.slice.end };
|
||||
}
|
||||
|
||||
pub const ParseTimeError = error{ CertificateTimeInvalid, CertificateFieldHasWrongDataType };
|
||||
|
||||
/// Returns number of seconds since epoch.
|
||||
pub fn parseTime(cert: Certificate, elem: der.Element) !u64 {
|
||||
pub fn parseTime(cert: Certificate, elem: der.Element) ParseTimeError!u64 {
|
||||
const bytes = cert.contents(elem);
|
||||
switch (elem.identifier.tag) {
|
||||
.utc_time => {
|
||||
@ -647,34 +653,38 @@ test parseYear4 {
|
||||
try expectError(error.CertificateTimeInvalid, parseYear4("crap"));
|
||||
}
|
||||
|
||||
pub fn parseAlgorithm(bytes: []const u8, element: der.Element) !Algorithm {
|
||||
pub fn parseAlgorithm(bytes: []const u8, element: der.Element) ParseEnumError!Algorithm {
|
||||
return parseEnum(Algorithm, bytes, element);
|
||||
}
|
||||
|
||||
pub fn parseAlgorithmCategory(bytes: []const u8, element: der.Element) !AlgorithmCategory {
|
||||
pub fn parseAlgorithmCategory(bytes: []const u8, element: der.Element) ParseEnumError!AlgorithmCategory {
|
||||
return parseEnum(AlgorithmCategory, bytes, element);
|
||||
}
|
||||
|
||||
pub fn parseAttribute(bytes: []const u8, element: der.Element) !Attribute {
|
||||
pub fn parseAttribute(bytes: []const u8, element: der.Element) ParseEnumError!Attribute {
|
||||
return parseEnum(Attribute, bytes, element);
|
||||
}
|
||||
|
||||
pub fn parseNamedCurve(bytes: []const u8, element: der.Element) !NamedCurve {
|
||||
pub fn parseNamedCurve(bytes: []const u8, element: der.Element) ParseEnumError!NamedCurve {
|
||||
return parseEnum(NamedCurve, bytes, element);
|
||||
}
|
||||
|
||||
pub fn parseExtensionId(bytes: []const u8, element: der.Element) !ExtensionId {
|
||||
pub fn parseExtensionId(bytes: []const u8, element: der.Element) ParseEnumError!ExtensionId {
|
||||
return parseEnum(ExtensionId, bytes, element);
|
||||
}
|
||||
|
||||
fn parseEnum(comptime E: type, bytes: []const u8, element: der.Element) !E {
|
||||
pub const ParseEnumError = error{ CertificateFieldHasWrongDataType, CertificateHasUnrecognizedObjectId };
|
||||
|
||||
fn parseEnum(comptime E: type, bytes: []const u8, element: der.Element) ParseEnumError!E {
|
||||
if (element.identifier.tag != .object_identifier)
|
||||
return error.CertificateFieldHasWrongDataType;
|
||||
const oid_bytes = bytes[element.slice.start..element.slice.end];
|
||||
return E.map.get(oid_bytes) orelse return error.CertificateHasUnrecognizedObjectId;
|
||||
}
|
||||
|
||||
pub fn parseVersion(bytes: []const u8, version_elem: der.Element) !Version {
|
||||
pub const ParseVersionError = error{ UnsupportedCertificateVersion, CertificateFieldHasInvalidLength };
|
||||
|
||||
pub fn parseVersion(bytes: []const u8, version_elem: der.Element) ParseVersionError!Version {
|
||||
if (@bitCast(u8, version_elem.identifier) != 0xa0)
|
||||
return .v1;
|
||||
|
||||
@ -861,9 +871,9 @@ pub const der = struct {
|
||||
pub const empty: Slice = .{ .start = 0, .end = 0 };
|
||||
};
|
||||
|
||||
pub const ParseError = error{CertificateFieldHasInvalidLength};
|
||||
pub const ParseElementError = error{CertificateFieldHasInvalidLength};
|
||||
|
||||
pub fn parse(bytes: []const u8, index: u32) ParseError!Element {
|
||||
pub fn parse(bytes: []const u8, index: u32) ParseElementError!Element {
|
||||
var i = index;
|
||||
const identifier = @bitCast(Identifier, bytes[i]);
|
||||
i += 1;
|
||||
|
||||
@ -50,11 +50,13 @@ pub fn deinit(cb: *Bundle, gpa: Allocator) void {
|
||||
cb.* = undefined;
|
||||
}
|
||||
|
||||
pub const RescanError = RescanLinuxError || RescanMacError || RescanWindowsError;
|
||||
|
||||
/// Clears the set of certificates and then scans the host operating system
|
||||
/// file system standard locations for certificates.
|
||||
/// For operating systems that do not have standard CA installations to be
|
||||
/// found, this function clears the set of certificates.
|
||||
pub fn rescan(cb: *Bundle, gpa: Allocator) !void {
|
||||
pub fn rescan(cb: *Bundle, gpa: Allocator) RescanError!void {
|
||||
switch (builtin.os.tag) {
|
||||
.linux => return rescanLinux(cb, gpa),
|
||||
.macos => return rescanMac(cb, gpa),
|
||||
@ -64,8 +66,11 @@ pub fn rescan(cb: *Bundle, gpa: Allocator) !void {
|
||||
}
|
||||
|
||||
pub const rescanMac = @import("Bundle/macos.zig").rescanMac;
|
||||
pub const RescanMacError = @import("Bundle/macos.zig").RescanMacError;
|
||||
|
||||
pub fn rescanLinux(cb: *Bundle, gpa: Allocator) !void {
|
||||
pub const RescanLinuxError = AddCertsFromFilePathError || AddCertsFromDirPathError;
|
||||
|
||||
pub fn rescanLinux(cb: *Bundle, gpa: Allocator) RescanLinuxError!void {
|
||||
// Possible certificate files; stop after finding one.
|
||||
const cert_file_paths = [_][]const u8{
|
||||
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
|
||||
@ -107,7 +112,9 @@ pub fn rescanLinux(cb: *Bundle, gpa: Allocator) !void {
|
||||
cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len);
|
||||
}
|
||||
|
||||
pub fn rescanWindows(cb: *Bundle, gpa: Allocator) !void {
|
||||
pub const RescanWindowsError = Allocator.Error || ParseCertError || std.os.UnexpectedError || error{FileNotFound};
|
||||
|
||||
pub fn rescanWindows(cb: *Bundle, gpa: Allocator) RescanWindowsError!void {
|
||||
cb.bytes.clearRetainingCapacity();
|
||||
cb.map.clearRetainingCapacity();
|
||||
|
||||
@ -132,12 +139,14 @@ pub fn rescanWindows(cb: *Bundle, gpa: Allocator) !void {
|
||||
cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len);
|
||||
}
|
||||
|
||||
pub const AddCertsFromDirPathError = fs.File.OpenError || AddCertsFromDirError;
|
||||
|
||||
pub fn addCertsFromDirPath(
|
||||
cb: *Bundle,
|
||||
gpa: Allocator,
|
||||
dir: fs.Dir,
|
||||
sub_dir_path: []const u8,
|
||||
) !void {
|
||||
) AddCertsFromDirPathError!void {
|
||||
var iterable_dir = try dir.openIterableDir(sub_dir_path, .{});
|
||||
defer iterable_dir.close();
|
||||
return addCertsFromDir(cb, gpa, iterable_dir);
|
||||
@ -147,14 +156,16 @@ pub fn addCertsFromDirPathAbsolute(
|
||||
cb: *Bundle,
|
||||
gpa: Allocator,
|
||||
abs_dir_path: []const u8,
|
||||
) !void {
|
||||
) AddCertsFromDirPathError!void {
|
||||
assert(fs.path.isAbsolute(abs_dir_path));
|
||||
var iterable_dir = try fs.openIterableDirAbsolute(abs_dir_path, .{});
|
||||
defer iterable_dir.close();
|
||||
return addCertsFromDir(cb, gpa, iterable_dir);
|
||||
}
|
||||
|
||||
pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, iterable_dir: fs.IterableDir) !void {
|
||||
pub const AddCertsFromDirError = AddCertsFromFilePathError;
|
||||
|
||||
pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, iterable_dir: fs.IterableDir) AddCertsFromDirError!void {
|
||||
var it = iterable_dir.iterate();
|
||||
while (try it.next()) |entry| {
|
||||
switch (entry.kind) {
|
||||
@ -166,11 +177,13 @@ pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, iterable_dir: fs.IterableDir
|
||||
}
|
||||
}
|
||||
|
||||
pub const AddCertsFromFilePathError = fs.File.OpenError || AddCertsFromFileError;
|
||||
|
||||
pub fn addCertsFromFilePathAbsolute(
|
||||
cb: *Bundle,
|
||||
gpa: Allocator,
|
||||
abs_file_path: []const u8,
|
||||
) !void {
|
||||
) AddCertsFromFilePathError!void {
|
||||
assert(fs.path.isAbsolute(abs_file_path));
|
||||
var file = try fs.openFileAbsolute(abs_file_path, .{});
|
||||
defer file.close();
|
||||
@ -182,13 +195,15 @@ pub fn addCertsFromFilePath(
|
||||
gpa: Allocator,
|
||||
dir: fs.Dir,
|
||||
sub_file_path: []const u8,
|
||||
) !void {
|
||||
) AddCertsFromFilePathError!void {
|
||||
var file = try dir.openFile(sub_file_path, .{});
|
||||
defer file.close();
|
||||
return addCertsFromFile(cb, gpa, file);
|
||||
}
|
||||
|
||||
pub fn addCertsFromFile(cb: *Bundle, gpa: Allocator, file: fs.File) !void {
|
||||
pub const AddCertsFromFileError = Allocator.Error || fs.File.GetSeekPosError || fs.File.ReadError || ParseCertError || std.base64.Error || error{ CertificateAuthorityBundleTooBig, MissingEndCertificateMarker };
|
||||
|
||||
pub fn addCertsFromFile(cb: *Bundle, gpa: Allocator, file: fs.File) AddCertsFromFileError!void {
|
||||
const size = try file.getEndPos();
|
||||
|
||||
// We borrow `bytes` as a temporary buffer for the base64-encoded data.
|
||||
@ -222,7 +237,9 @@ pub fn addCertsFromFile(cb: *Bundle, gpa: Allocator, file: fs.File) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parseCert(cb: *Bundle, gpa: Allocator, decoded_start: u32, now_sec: i64) !void {
|
||||
pub const ParseCertError = Allocator.Error || Certificate.ParseError;
|
||||
|
||||
pub fn parseCert(cb: *Bundle, gpa: Allocator, decoded_start: u32, now_sec: i64) ParseCertError!void {
|
||||
// Even though we could only partially parse the certificate to find
|
||||
// the subject name, we pre-parse all of them to make sure and only
|
||||
// include in the bundle ones that we know will parse. This way we can
|
||||
|
||||
@ -5,7 +5,9 @@ const mem = std.mem;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Bundle = @import("../Bundle.zig");
|
||||
|
||||
pub fn rescanMac(cb: *Bundle, gpa: Allocator) !void {
|
||||
pub const RescanMacError = Allocator.Error || fs.File.OpenError || fs.File.ReadError || fs.File.SeekError || Bundle.ParseCertError || error{EndOfStream};
|
||||
|
||||
pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void {
|
||||
cb.bytes.clearRetainingCapacity();
|
||||
cb.map.clearRetainingCapacity();
|
||||
|
||||
|
||||
@ -29,34 +29,16 @@ connection_pool: ConnectionPool = .{},
|
||||
last_error: ?ExtraError = null,
|
||||
|
||||
pub const ExtraError = union(enum) {
|
||||
fn impliedErrorSet(comptime f: anytype) type {
|
||||
const set = @typeInfo(@typeInfo(@TypeOf(f)).Fn.return_type.?).ErrorUnion.error_set;
|
||||
if (@typeName(set)[0] != '@') @compileError(@typeName(f) ++ " doesn't have an implied error set any more.");
|
||||
return set;
|
||||
}
|
||||
|
||||
// There's apparently a dependency loop with using Client.DeflateDecompressor.
|
||||
const FakeTransferError = proto.HeadersParser.ReadError || error{ReadFailed};
|
||||
const FakeTransferReader = std.io.Reader(void, FakeTransferError, fakeRead);
|
||||
fn fakeRead(ctx: void, buf: []u8) FakeTransferError!usize {
|
||||
_ = .{ buf, ctx };
|
||||
return 0;
|
||||
}
|
||||
|
||||
const FakeDeflateDecompressor = std.compress.zlib.ZlibStream(FakeTransferReader);
|
||||
const FakeGzipDecompressor = std.compress.gzip.Decompress(FakeTransferReader);
|
||||
const FakeZstdDecompressor = std.compress.zstd.DecompressStream(FakeTransferReader, .{});
|
||||
|
||||
pub const TcpConnectError = std.net.TcpConnectToHostError;
|
||||
pub const TlsError = std.crypto.tls.Client.InitError(net.Stream);
|
||||
pub const WriteError = BufferedConnection.WriteError;
|
||||
pub const ReadError = BufferedConnection.ReadError || error{HttpChunkInvalid};
|
||||
pub const CaBundleError = impliedErrorSet(std.crypto.Certificate.Bundle.rescan);
|
||||
pub const CaBundleError = std.crypto.Certificate.Bundle.RescanError;
|
||||
|
||||
pub const ZlibInitError = error{ BadHeader, InvalidCompression, InvalidWindowSize, Unsupported, EndOfStream, OutOfMemory } || Request.TransferReadError;
|
||||
pub const GzipInitError = error{ BadHeader, InvalidCompression, OutOfMemory, WrongChecksum, EndOfStream, StreamTooLong } || Request.TransferReadError;
|
||||
// pub const DecompressError = Client.DeflateDecompressor.Error || Client.GzipDecompressor.Error || Client.ZstdDecompressor.Error;
|
||||
pub const DecompressError = FakeDeflateDecompressor.Error || FakeGzipDecompressor.Error || FakeZstdDecompressor.Error;
|
||||
// pub const DecompressError = Compression.DeflateDecompressor.Error || Compression.GzipDecompressor.Error || Compression.ZstdDecompressor.Error;
|
||||
pub const DecompressError = anyerror; // FIXME: the above line causes a false positive dependency loop
|
||||
|
||||
zlib_init: ZlibInitError, // error.CompressionInitializationFailed
|
||||
gzip_init: GzipInitError, // error.CompressionInitializationFailed
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user