-
Notifications
You must be signed in to change notification settings - Fork 173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide an example of a tls client #479
Comments
while I won't have time for this, here are some pointers (first, conduit would need support for certificates):
(or am I misguided and is there a cohttp API not involving conduit to do HTTP client connections? if so, you could use tls_lwt). A simple example using OCaml-TLS and client certificates is available at https://github.com/mirleft/ocaml-tls/blob/master/lwt/examples/echo_client.ml -- just read private key and certificate chain (line 14-16) and pass them to the client config (line 19). |
Thanks for your answer. Maybe a simple way would be to add a |
That definitely sounds like the way forward. I'd like to make cohttp usable without conduit anyway. |
I'll try to set up an example with such a change. |
@hannesm I'm starting from the https://github.com/mirleft/ocaml-tls/blob/master/lwt/examples/echo_client.ml example but I'm getting tls errors:
Since I don't known which files to use as server certificates, I commented out some code: ...
| Some f -> `Ca_file f) >>= fun authenticator ->
(*X509_lwt.private_of_pems
~cert:server_cert
~priv_key:server_key >>= fun certificate ->*)
Tls_lwt.connect_ext
~trace:eprint_sexp
Tls.Config.(client ~authenticator (*~certificates:(`Single certificate)*) ~ciphers:Ciphers.supported ())
(host, port) >>= fun (ic, oc) ->
... but this does not solve the problem. Are these server certificates required ? |
not sure what your other endpoint is. the client uses you can generate your own certificate and private key and either overwrite server.pem and server.key or change the |
But are these server certificates required ? By now I just use Tls_lwt.connect ~trace:eprint_sexp authenticator (host, port) >>= fun (ic, oc) -> so no server certificate is involved. My problem seems to be that the PEM file I use as authentication certificate is not valid/recognized. This PEM file is exported from firefox, but as you may have guessed already I'm not a TLS specialist and I wonder if this is a correct certificate to use. |
I've no clue about your scenario, and your paste doesn't include the actual error. Depending on your scenario, you need on the client:
if you provide only an |
From what you say, the Now when I use the
|
In fact
Don't know why but it's no luck as it is the one I'm interested in. |
could you provide a bit more output please? the lines you pasted do not include the actual problem... otoh I can try to connect myself to databox and debug... maybe tomorrow.. |
These lines are the only output I have :-/ Is there a way to get more ? |
@rgrinberg The solution to add a But exploring the Cohttp code, I came with another solution which does not require modifying Cohttp. I define a new module IO =
struct
type 'a t = 'a Lwt.t
let (>>=) = Lwt.bind
let return = Lwt.return
type ic = Lwt_io.input_channel
type oc = Lwt_io.output_channel
type conn = ic * oc
let read_line ic = Lwt_io.read_line_opt ic
let read ic count = Lwt_io.read ~count ic
let write oc buf = Lwt_io.write oc buf
let flush oc = Lwt_io.flush oc
end
module Tls_net =
struct
module IO = IO
type ctx = Tls.Config.client Lwt.t
let sexp_of_ctx _ = Sexplib.Sexp.Atom "tls ctx"
let default_ctx =
X509_lwt.authenticator `No_authentication_I'M_STUPID >>=
fun authenticator ->
Lwt.return
(Tls.Config.(client
~authenticator ~ciphers:Ciphers.supported ()))
let connect_uri ~ctx uri =
let host = match Uri.host uri with None -> "" | Some s -> s in
let port = match Uri.port uri with None -> 443 | Some n -> n in
ctx >>= fun client ->
Tls_lwt.connect_ext
~trace:eprint_sexp
client (host, port)
>>= fun (ic, oc) -> Lwt.return ((ic, oc), ic, oc)
let close c = Lwt.catch (fun () -> Lwt_io.close c) (fun _ -> return_unit)
let close_in ic = ignore_result (close ic)
let close_out oc = ignore_result (close oc)
let close ic oc = ignore_result (close ic >>= fun () -> close oc)
end Type Then I get a module Client = Cohttp_lwt.Make_client (IO) (Tls_net) I can then define my own function let call meth ?ca ?body ?chunked ?headers iri =
let%lwt authenticator = X509_lwt.authenticator
(match ca with
| None -> `Ca_dir server_cert_dir
| Some "NONE" -> `No_authentication_I'M_STUPID
| Some f -> `Ca_file f)
in
let%lwt certificate =
X509_lwt.private_of_pems ~cert:server_cert ~priv_key:server_key
in
let ctx = Lwt.return
(Tls.Config.client
~authenticator ~certificates:(`Single certificate)
~ciphers:Tls.Config.Ciphers.supported ()
)
in
Client.call ~ctx ?body ?chunked ?headers meth
(Uri.of_string (Iri.to_uri iri))
let get = call `GET
let delete = call `DELETE
let post = call `POST
let put = call `PUT
let patch = call `PATCH This function can be defined differently according to your application context: here each connection creates a new context (i.e. a Finally, I could tls-authenticate successfully to my account on |
Regarding the default authenticator, now I use type ctx = Tls.Config.client [@@deriving sexp_of]
let default_ctx =
let authenticator = X509.Authenticator.null in
Tls.Config.(client ~authenticator ~ciphers:Ciphers.supported ()) |
@zoggy both are not good ideas: you shouldn't pass EDIT: and there is no such thing as a |
Ok, thanks. So I could use a default authenticator built with Ok for the ciphers, I had just copy-pasted from your example. |
oh, thanks... I just removed the providing a default context with an empty set of trust anchors in |
Did you try your echo example on https://databox.me ? |
@zoggy I just tried echo_client, and https://www.ssllabs.com/ssltest/analyze.html?d=databox.me tells me that they only support 3 ciphersuites, all using ECDHE for the key exchange (and unfortunately neither nocrypto nor OCaml-TLS has EC support at the moment, it is planned) |
I spent a bit of time last week investigating how to use cohttp with https in 0install. Here are my notes on how to get it working using First, you must not use ocaml-tls in the default configuration, because conduit disables certificate validation in this mode and you cannot override it. See https://github.com/mirage/ocaml-conduit/blob/2aa5d06fc81cd74dc56553cd490a9c23cb538680/lwt-unix/conduit_lwt_tls_real.ml#L33 To avoid this, call By default, openssl uses CA certificate paths hard-coded at compile time. As these are different on every Linux system, if you want portable binaries then you will need to search for the right paths yourself. Here's the code I use for that: To use your custom context with the correct CAs you'll need to avoid Luckily, cohttp doesn't actually use the flow for anything, so you can override the |
@samoht did your change to use ca-cert somewhat solve this issue? |
Hello,
It would be great to have an example of a client (not a server) connecting to a server and authenticating with certificates.
This is partly related to #471 .
cc @hannesm
The text was updated successfully, but these errors were encountered: