# crypto.Certificate: case insensitive host name check · gitcafe/zig

[View on GitCafe](https://git.cafe/gitcafe/zig/commit/c1e7eb738934399737b3a8452ad9b68bb26805d3)

Repository: [gitcafe/zig](https://git.cafe/gitcafe/zig)

Visibility: public

Requested revision: c1e7eb738934399737b3a8452ad9b68bb26805d3

Requested commit: c1e7eb738934399737b3a8452ad9b68bb26805d3

Commit: c1e7eb738934399737b3a8452ad9b68bb26805d3

Tree: 8f1249e0acf98492730adbfe4e5594b84930e9af

Author: Igor Anić

Committer: Andrew Kelley

## Message

````
crypto.Certificate: case insensitive host name check

This makes comparing host name with dns name from certificate case
insensitive.

I found a few domains (from the
[cloudflare](https://radar.cloudflare.com/domains) list of top domains)
for which tls.Client fails to connect. Error is:

```zig
error: TlsInitializationFailed
Code/zig/lib/std/crypto/Certificate.zig:336:9: 0x1177b1f in verifyHostName (http_get_std)
        return error.CertificateHostMismatch;
Code/zig/lib/std/crypto/tls23/handshake_client.zig:461:25: 0x11752bd in parseServerCertificate (http_get_std)
                        try subject.verifyHostName(opt.host);
```
In its certificate this domains have host names which are not strictly
lower case. This is what checkHostName is comparing:

 |host_name            |  dns_name                |
 |------------------------------------------------|
 |ey.com               | EY.COM                   |
 |truist.com           | Truist.com               |
 |wscampanhas.bradesco | WSCAMPANHAS.BRADESCO     |
 |dell.com             | Dell.com                 |

From
[RFC2818](https://datatracker.ietf.org/doc/html/rfc2818#section-2.4):
>  Matching is performed using the matching rules specified by
   [RFC2459].
From [RFC2459](https://datatracker.ietf.org/doc/html/rfc2459#section-4.2.1.7):
> When comparing URIs, conforming implementations
> MUST compare the scheme and host without regard to case, but assume
> the remainder of the scheme-specific-part is case sensitive.

Testing with:

```
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);

    if (args.len > 1) {
        const domain = args[1];

        var client: std.http.Client = .{ .allocator = allocator };
        defer client.deinit();

        // Add https:// prefix if needed
        const url = brk: {
            const scheme = "https://";
            if (domain.len >= scheme.len and std.mem.eql(u8, domain[0..scheme.len], scheme))
                break :brk domain;

            var url_buf: [128]u8 = undefined;
            break :brk try std.fmt.bufPrint(&url_buf, "https://{s}", .{domain});
        };

        const uri = try std.Uri.parse(url);
        var server_header_buffer: [16 * 1024]u8 = undefined;
        var req = try client.open(.GET, uri, .{ .server_header_buffer = &server_header_buffer });
        defer req.deinit();

        try req.send();
        try req.wait();
    }
}
```
`$ zig run example/main.zig -- truist.com `

````

## Parents

- [2511830442fd96d04f578f2c4251b1994f08c994](https://git.cafe/gitcafe/zig/commit/2511830442fd96d04f578f2c4251b1994f08c994?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zig/tree/c1e7eb738934399737b3a8452ad9b68bb26805d3?format=markdown)
