···11-(lang dune 1.11)
11+(lang dune 2.0)
22(name ca-certs)
3344(generate_opam_files true)
···10101111(package
1212 (name ca-certs)
1313- (depends)
1313+ (depends
1414+ bos fpath rresult ptime mirage-crypto
1515+ (x509 (>= 0.11.0))
1616+ (ocaml (>= 4.07.0))
1717+ (lwt :with-test)
1818+ (tls :with-test))
1419 (synopsis "Detect root CA certificates from the operating system")
1520 (description
1621 "\> TLS requires a set of root anchors (Certificate Authorities) to
+74-9
lib/ca_certs.ml
···11-let rec detect_list =
22- let open Lwt in
33- function
44- | [] -> return_none
55- | path :: paths ->
66- Lwt_unix.file_exists path >>= fun exists ->
77- if exists then return_some (`Ca_file path) else detect_list paths
11+let issue =
22+ {|Please report an issue at https://github.com/mirage/ca-certs, including:
33+- the output of uname -s
44+- the distribution you use
55+- the location of default trust anchors (if known)
66+|}
8799-let locations =
88+let detect_one path =
99+ let path' = Fpath.v path in
1010+ match Bos.OS.Path.exists path' with
1111+ | Ok true -> Ok path'
1212+ | _ ->
1313+ Error
1414+ (`Msg
1515+ ( "ca-certs: no trust anchor file found, looked into " ^ path ^ ".\n"
1616+ ^ issue ))
1717+1818+let detect_list paths =
1919+ let rec one = function
2020+ | [] ->
2121+ Error
2222+ (`Msg
2323+ ( "ca-certs: no trust anchor file found, looked into "
2424+ ^ String.concat ", " paths ^ ".\n" ^ issue ))
2525+ | path :: paths -> (
2626+ match detect_one path with Ok path -> Ok path | Error _ -> one paths )
2727+ in
2828+ one paths
2929+3030+(* from https://golang.org/src/crypto/x509/root_linux.go *)
3131+let linux_locations =
1032 [
3333+ (* Debian/Ubuntu/Gentoo etc. *)
1134 "/etc/ssl/certs/ca-certificates.crt";
3535+ (* CentOS/RHEL 7 *)
1236 "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
3737+ (* OpenSUSE *)
3838+ "/etc/ssl/ca-bundle.pem";
1339 ]
14401515-let detect () = detect_list locations
4141+(* from https://golang.org/src/crypto/x509/root_bsd.go *)
4242+let openbsd_location = "/etc/ssl/cert.pem"
4343+4444+let freebsd_location = "/usr/local/share/certs/ca-root-nss.crt"
4545+4646+let macos_keychain_location =
4747+ "/System/Library/Keychains/SystemRootCertificates.keychain"
4848+4949+let ta_file_raw () =
5050+ let open Rresult.R.Infix in
5151+ if Sys.win32 then
5252+ Error (`Msg "ca-certs: windows is not supported at the moment")
5353+ else
5454+ let cmd = Bos.Cmd.(v "uname" % "-s") in
5555+ Bos.OS.Cmd.(run_out cmd |> out_string |> success) >>= function
5656+ | "FreeBSD" -> detect_one freebsd_location
5757+ | "OpenBSD" -> detect_one openbsd_location
5858+ | "Linux" -> detect_list linux_locations
5959+ | "Darwin" ->
6060+ let cmd =
6161+ Bos.Cmd.(
6262+ v "security" % "find-certificate" % "-a" % "-p"
6363+ % macos_keychain_location)
6464+ in
6565+ let tmpfile = Fpath.v (Filename.temp_file "cacert" "pem") in
6666+ Bos.OS.Cmd.(run_out cmd |> out_file tmpfile |> success) >>| fun () ->
6767+ tmpfile
6868+ | s -> Error (`Msg ("ca-certs: unknown system " ^ s ^ ".\n" ^ issue))
6969+7070+let trust_anchor_filename () =
7171+ let open Rresult.R.Infix in
7272+ ta_file_raw () >>| Fpath.to_string
7373+7474+let trust_anchor ?crls ?hash_whitelist () =
7575+ let open Rresult.R.Infix in
7676+ ta_file_raw () >>= fun file ->
7777+ Bos.OS.File.read file >>= fun data ->
7878+ X509.Certificate.decode_pem_multiple (Cstruct.of_string data) >>| fun cas ->
7979+ let time () = Some (Ptime_clock.now ()) in
8080+ X509.Authenticator.chain_of_trust ?crls ?hash_whitelist ~time cas
+10-4
lib/ca_certs.mli
···11-val detect : unit -> [> `Ca_file of Lwt_io.file_name ] option Lwt.t
22-(** Detect root CAs in the operating system's trust store.
33- Returns [None] if detection did not succeed. The variants correspond to the
44- ones used in [X509_lwt] in [ocaml-tls]. *)
11+val trust_anchor_filename : unit -> (string, [> `Msg of string ]) result
22+(** Attempts to discover the trust anchor file on this host system. *)
33+44+val trust_anchor :
55+ ?crls:X509.CRL.t list ->
66+ ?hash_whitelist:Mirage_crypto.Hash.hash list ->
77+ unit ->
88+ (X509.Authenticator.t, [> `Msg of string ]) result
99+(** Detects root CAs in the operating system's trust store.
1010+ Returns [Error `Msg msg] if detection did not succeed. *)