ygu
ygu

Reputation: 345

How to debug a HANDSHAKE_FAILURE when requesting an HTTPS server with ocaml-cohttp Client.post method ? (And why am I getting this error ?)

I wrote the following OCaml code in order to make POST requests to an https server.

open Lwt
open Cohttp
open Cohttp_lwt_unix

try
    let headers = Header.init ()
    |> fun h -> Header.add h "content-type" "application/json" in
    let body = Client.post
      ~headers
      ~body:(body_of_credentials nickname secret)
      (uri_of_project project)
    >>= fun (response, body) ->
      let code = response |> Response.status |> Code.code_of_status in
      Printf.printf "Response code: %d\n" code;
      Printf.printf "Headers: %s\n" (response |> Response.headers |> Header.to_string);
      body |> Cohttp_lwt.Body.to_string >|= fun body ->
      Printf.printf "Body of length: %d\n" (String.length body);
      body
    in

    let body = Lwt_main.run body in
      print_endline ("Received body\n" ^ body)

  with
  | Tls_lwt.Tls_alert e ->
    print_endline (Tls.Packet.alert_type_to_string e);
    exit 1

But when executing it with CONDUIT_TLS=native CONDUIT_DEBUG=true COHTTP_DEBUG=true I get the following response :

Selected TLS library: Native
Resolver system: https://my_server/auth/tokens/ ((name https) (port 443) (tls true)) -> (TCP ((V4 xx.xxx.xx.xxx) 443))
HANDSHAKE_FAILURE

I've read all the google results (documentation, ocaml/cohttp/ocaml-tls lists and stack overflow questions) I could find about it, but nothing helps, so I would like to start from scratch here.

How can I get more details about this failure ?

In case it helps, I'm using the following opam configuration:

"lwt" {>= "4.1.0"}
"cohttp" {>= "1.1.1"}
"cohttp-lwt"
"cohttp-lwt-unix" {>= "1.1.1"}
"tls" {>= "0.9.2"}

EDIT: As suggested by @ivg, I tried with CONDUIT_TLS=openssl but then I get the following error:

Selected TLS library: OpenSSL
Resolver system: https://my_server/auth/tokens/ ((name https) (port 443) (tls true)) -> (TCP ((V4 xx.xxx.xx.xxx) 443))
...: internal error, uncaught exception:
    SSL: Method error

EDIT²: As suggested in the following discussion: github.com/savonet/ocaml-ssl/issues/40 I added an opam pin to ssl-0.5.5: opam pin add ssl 0.5.5 in order to fix this error. Now I am able to post requests to my https server, but not with the pure ocaml implementation of tls.

Upvotes: 1

Views: 182

Answers (1)

ivg
ivg

Reputation: 35280

You're getting this alert because the handshaking process (authentication) had failed. This alert means, that the peer is not authenticated (either the server or the client) and thus a secure connection could not be established.

To debug the issue, I would suggest first to ensure that everything works fine with conventional tools, e.g., openssl, wget, or curl.

If you're sure that your configuration is fine and this is a problem on the ocaml-tls part I would suggest to use the low-level interface of the ocaml-tls library. Apparently, conduit doesn't expose or use any of the tracing capabilities of ocaml-tls, so there is no other choice.

The alert type is projected from two more rich fatal and error types that bear much more information about the nature of the problem, cf. the following code that creates an alert and consider possible input values that lead to the HANDSHAKE_FAILURE alert.

To access the particular error or alert I would suggest you to use the Tracing capabilities of ocaml-tls. There are examples in the source repository that already enable tracing and should provide sufficient information. I hope those examples will fit into your use case.

Upvotes: 2

Related Questions