···5050let macos_keychain_location =
5151 "/System/Library/Keychains/SystemRootCertificates.keychain"
52525353+external iter_on_anchors : (string -> unit) -> unit = "ca_certs_iter_on_anchors"
5454+5555+let get_anchors () =
5656+ let der_list = ref [] in
5757+ match
5858+ iter_on_anchors (fun der_cert ->
5959+ der_list := Cstruct.of_string der_cert :: !der_list)
6060+ with
6161+ | () -> Ok !der_list
6262+ | exception Failure msg -> Rresult.R.error_msg msg
6363+6464+let rec map_m f l =
6565+ match l with
6666+ | [] -> Ok []
6767+ | x :: xs ->
6868+ let open Rresult.R in
6969+ f x >>= fun y ->
7070+ map_m f xs >>| fun ys -> y :: ys
7171+7272+(** Load certificates from Windows' ["ROOT"] system certificate store.
7373+ The C API returns a list of DER-encoded certificates. These are decoded and
7474+ reencoded as a single PEM certificate. *)
7575+let windows_trust_anchors () =
7676+ let open Rresult.R in
7777+ get_anchors () >>= map_m X509.Certificate.decode_der >>| fun cert_list ->
7878+ X509.Certificate.encode_pem_multiple cert_list |> Cstruct.to_string
7979+5380let trust_anchors () =
5481 let open Rresult.R.Infix in
5555- if Sys.win32 then
5656- Error (`Msg "ca-certs: windows is not supported at the moment")
8282+ if Sys.win32 then windows_trust_anchors ()
5783 else
5884 let cmd = Bos.Cmd.(v "uname" % "-s") in
5985 Bos.OS.Cmd.(run_out cmd |> out_string |> success) >>= function
+49
lib/ca_certs_stubs.c
···11+#include "caml/alloc.h"
22+#include "caml/callback.h"
33+#include "caml/fail.h"
44+#include "caml/memory.h"
55+66+#ifdef _WIN32
77+88+#include <windows.h>
99+1010+value ca_certs_iter_on_anchors(value v_f)
1111+{
1212+ CAMLparam1(v_f);
1313+ CAMLlocal1(v_encoded_cert);
1414+1515+ HCERTSTORE hCertStore = CertOpenSystemStore(0, "ROOT");
1616+ if (!hCertStore)
1717+ {
1818+ caml_failwith("ca_certs_iter_on_anchors: CertOpenSystemStore returned NULL");
1919+ }
2020+2121+ PCCERT_CONTEXT pCertContext = NULL;
2222+ while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) != NULL)
2323+ {
2424+ if (!(pCertContext->dwCertEncodingType & X509_ASN_ENCODING))
2525+ {
2626+ caml_failwith("ca_certs_iter_on_anchors: certificate does not have expected encoding");
2727+ }
2828+ v_encoded_cert = caml_alloc_initialized_string(
2929+ pCertContext->cbCertEncoded,
3030+ pCertContext->pbCertEncoded);
3131+ caml_callback(v_f, v_encoded_cert);
3232+ }
3333+3434+ if (!CertCloseStore(hCertStore, 0))
3535+ {
3636+ caml_failwith("ca_certs_iter_on_anchors: CertCloseStore returned an error");
3737+ }
3838+3939+ CAMLreturn(Val_unit);
4040+}
4141+4242+#else
4343+4444+value ca_certs_iter_on_anchors(value v_unit)
4545+{
4646+ caml_failwith("ca_certs_iter_on_anchors: only implemented on Windows");
4747+}
4848+4949+#endif