From 4c2247da547db65d3e7a9fa18c719a0f25e10d86 Mon Sep 17 00:00:00 2001 From: Konstantin Olkhovskiy Date: Thu, 19 Sep 2019 21:39:34 +0000 Subject: [PATCH] Support reading of cert/private key from memory --- src/ssl.ml | 2 ++ src/ssl.mli | 2 ++ src/ssl_stubs.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/ssl.ml b/src/ssl.ml index 4ecd57d..9219b7a 100644 --- a/src/ssl.ml +++ b/src/ssl.ml @@ -157,6 +157,8 @@ external create_context : protocol -> context_type -> context = "ocaml_ssl_creat external use_certificate : context -> string -> string -> unit = "ocaml_ssl_ctx_use_certificate" +external use_certificate_from_string : context -> string -> string -> unit = "ocaml_ssl_ctx_use_certificate_from_string" + external set_password_callback : context -> (bool -> string) -> unit = "ocaml_ssl_ctx_set_default_passwd_cb" external embed_socket : Unix.file_descr -> context -> socket = "ocaml_ssl_embed_socket" diff --git a/src/ssl.mli b/src/ssl.mli index eb62baa..64e2f31 100644 --- a/src/ssl.mli +++ b/src/ssl.mli @@ -245,6 +245,8 @@ val create_context : protocol -> context_type -> context * name. *) val use_certificate : context -> string -> string -> unit +val use_certificate_from_string : context -> string -> string -> unit + (** Set the callback function called to get passwords for encrypted PEM files. * The callback function takes a boolean argument which indicates if it's used * for reading/decryption ([false]) or writing/encryption ([true]). diff --git a/src/ssl_stubs.c b/src/ssl_stubs.c index 3d431b8..5868286 100644 --- a/src/ssl_stubs.c +++ b/src/ssl_stubs.c @@ -470,6 +470,42 @@ CAMLprim value ocaml_ssl_ctx_use_certificate(value context, value cert, value pr CAMLreturn(Val_unit); } +CAMLprim value ocaml_ssl_ctx_use_certificate_from_string(value context, value cert, value privkey) +{ + CAMLparam3(context, cert, privkey); + SSL_CTX *ctx = Ctx_val(context); + char *cert_data = String_val(cert); + int cert_data_length = caml_string_length(cert); + char *privkey_data = String_val(privkey); + int privkey_data_length = caml_string_length(privkey); + char buf[256]; + X509 *x509_cert = NULL; + RSA *rsa = NULL; + BIO *cbio, *kbio; + + cbio = BIO_new_mem_buf((void*)cert_data, cert_data_length); + x509_cert = PEM_read_bio_X509(cbio, NULL, 0, NULL); + if (NULL == x509_cert || SSL_CTX_use_certificate(ctx, x509_cert) <= 0) + { + ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); + caml_raise_with_arg(*caml_named_value("ssl_exn_certificate_error"), caml_copy_string(buf)); + } + + kbio = BIO_new_mem_buf((void*)privkey_data, privkey_data_length); + rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL); + if (NULL == rsa || SSL_CTX_use_RSAPrivateKey(ctx, rsa) <= 0) + { + ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); + caml_raise_with_arg(*caml_named_value("ssl_exn_private_key_error"), caml_copy_string(buf)); + } + if (!SSL_CTX_check_private_key(ctx)) + { + caml_raise_constant(*caml_named_value("ssl_exn_unmatching_keys")); + } + + CAMLreturn(Val_unit); +} + CAMLprim value ocaml_ssl_get_verify_result(value socket) { CAMLparam1(socket);