-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow to use ktls for send and receive
- Loading branch information
Showing
6 changed files
with
241 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
open Alcotest | ||
|
||
module Util = Util_ktls | ||
|
||
let test_verify () = | ||
let addr = Unix.ADDR_INET (Unix.inet_addr_of_string "127.0.0.1", 11342) in | ||
Util.server_thread addr None |> ignore; | ||
|
||
let context = Ssl.create_context ~ktls:true TLSv1_2 Client_context in | ||
let ssl = Ssl.open_connection_with_context context addr in | ||
assert(Ssl.ktls_send_available ssl); | ||
assert(Ssl.ktls_recv_available ssl); | ||
let verify_result = | ||
try | ||
Ssl.verify ssl; | ||
"" | ||
with | ||
| e -> Printexc.to_string e | ||
in | ||
Ssl.shutdown_connection ssl; | ||
check | ||
bool | ||
"no verify errors" | ||
true | ||
(Str.search_forward | ||
(Str.regexp_string "error:00:000000:lib(0)") | ||
verify_result | ||
0 | ||
> 0) | ||
|
||
let test_set_host () = | ||
let addr = Unix.ADDR_INET (Unix.inet_addr_of_string "127.0.0.1", 11343) in | ||
Util.server_thread addr None |> ignore; | ||
|
||
let context = Ssl.create_context ~ktls:true TLSv1_2 Client_context in | ||
let domain = Unix.domain_of_sockaddr addr in | ||
let sock = Unix.socket domain Unix.SOCK_STREAM 0 in | ||
let ssl = Ssl.embed_socket sock context in | ||
Ssl.set_host ssl "localhost"; | ||
Unix.connect sock addr; | ||
Ssl.connect ssl; | ||
let verify_result = | ||
try | ||
Ssl.verify ssl; | ||
assert(Ssl.ktls_send_available ssl); | ||
assert(Ssl.ktls_recv_available ssl); | ||
"" | ||
with | ||
| e -> Printexc.to_string e | ||
in | ||
Ssl.shutdown_connection ssl; | ||
check | ||
bool | ||
"no verify errors" | ||
true | ||
(Str.search_forward | ||
(Str.regexp_string "error:00:000000:lib(0)") | ||
verify_result | ||
0 | ||
> 0) | ||
|
||
let test_read_write () = | ||
let addr = Unix.ADDR_INET (Unix.inet_addr_of_string "127.0.0.1", 11344) in | ||
Util.server_thread addr (Some (fun _ -> "received")) |> ignore; | ||
|
||
let context = Ssl.create_context ~ktls:true TLSv1_2 Client_context in | ||
let ssl = Ssl.open_connection_with_context context addr in | ||
assert(Ssl.ktls_send_available ssl); | ||
assert(Ssl.ktls_recv_available ssl); | ||
let send_msg = "send" in | ||
let write_buf = Bytes.create (String.length send_msg) in | ||
Unix.single_write (Ssl.file_descr_of_socket ssl) write_buf 0 4 |> ignore; | ||
let read_buf = Bytes.create 8 in | ||
Unix.read (Ssl.file_descr_of_socket ssl) read_buf 0 8 |> ignore; | ||
Ssl.shutdown_connection ssl; | ||
check string "received message" "received" (Bytes.to_string read_buf) | ||
|
||
let () = | ||
run | ||
"Ssl io functions" | ||
[ ( "IO" | ||
, [ test_case "Verify" `Quick test_verify | ||
; test_case "Set host" `Quick test_set_host | ||
; test_case "Read write" `Quick test_read_write | ||
] ) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
module Ssl = struct | ||
include Ssl | ||
|
||
let[@ocaml.alert "-deprecated"] get_error_string = get_error_string | ||
end | ||
|
||
open Ssl | ||
|
||
type server_args = | ||
{ address : Unix.sockaddr | ||
; condition : Condition.t | ||
; mutex : Mutex.t | ||
; parser : (string -> string) option | ||
} | ||
|
||
let server_rw_loop ssl parser_func = | ||
let fd = Ssl.file_descr_of_socket ssl in | ||
let rw_loop = ref true in | ||
while !rw_loop do | ||
try | ||
let read_buf = Bytes.create 256 in | ||
let read_bytes = Unix.read fd read_buf 0 256 in | ||
if read_bytes > 0 | ||
then ( | ||
let input = Bytes.to_string read_buf in | ||
let response = parser_func input in | ||
Unix.write_substring fd response 0 (String.length response) |> ignore; | ||
Ssl.close_notify ssl |> ignore; | ||
rw_loop := false) | ||
with | ||
| Read_error read_error -> | ||
(match read_error with Error_ssl -> rw_loop := false | _ -> ()) | ||
done | ||
|
||
let server_init args = | ||
try | ||
(* Server initialization *) | ||
Mutex.lock args.mutex; | ||
let socket = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in | ||
Unix.setsockopt socket Unix.SO_REUSEADDR true; | ||
Unix.bind socket args.address; | ||
let context = create_context ~ktls:true TLSv1_2 Server_context in | ||
use_certificate context "server.pem" "server.key"; | ||
Ssl.set_context_alpn_select_callback context (fun client_protos -> | ||
List.find_opt (fun opt -> opt = "http/1.1") client_protos); | ||
(* Signal ready and listen for connection *) | ||
Unix.listen socket 1; | ||
Some (socket, context) | ||
with | ||
| exn -> | ||
Printexc.to_string exn |> print_endline; | ||
None | ||
|
||
let server_listen args = | ||
match server_init args with | ||
| None -> | ||
Mutex.unlock args.mutex; | ||
Condition.signal args.condition; | ||
Thread.exit () [@warning "-3"] | ||
| Some (socket, context) -> | ||
Mutex.unlock args.mutex; | ||
Condition.signal args.condition; | ||
let listen = Unix.accept socket in | ||
let ssl = embed_socket (fst listen) context in | ||
accept ssl; | ||
assert(ktls_send_available ssl); | ||
assert(ktls_recv_available ssl); | ||
(* Exit right away unless we need to rw *) | ||
(match args.parser with | ||
| Some parser_func -> server_rw_loop ssl parser_func | ||
| None -> | ||
(); | ||
shutdown ssl; | ||
Thread.exit () [@warning "-3"]) | ||
|
||
let server_thread addr parser = | ||
let mutex = Mutex.create () in | ||
Mutex.lock mutex; | ||
let condition = Condition.create () in | ||
let args = { address = addr; condition; mutex; parser } in | ||
let thread = Thread.create server_listen args in | ||
Condition.wait condition mutex; | ||
thread | ||
|
||
let check_ssl_no_error err = | ||
Str.string_partial_match (Str.regexp_string "error:00000000:lib(0)") err 0 | ||
|
||
let[@ocaml.alert "-deprecated"] pp_protocol ppf = function | ||
| SSLv23 -> Format.fprintf ppf "SSLv23" | ||
| SSLv3 -> Format.fprintf ppf "SSLv3" | ||
| TLSv1 -> Format.fprintf ppf "TLSv1" | ||
| TLSv1_1 -> Format.fprintf ppf "TLSv1_1" | ||
| TLSv1_2 -> Format.fprintf ppf "TLSv1_2" | ||
| TLSv1_3 -> Format.fprintf ppf "TLSv1_3" | ||
|
||
let protocol_testable = Alcotest.testable pp_protocol (fun r1 r2 -> r1 == r2) |