package gapi-ocaml

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file netsys_tls.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
(* $Id$ *)

open Printf


module Debug = struct
  let enable = ref false
end

let dlog = Netlog.Debug.mk_dlog "Netsys_tls" Debug.enable
let dlogr = Netlog.Debug.mk_dlogr "Netsys_tls" Debug.enable

let () =
  Netlog.Debug.register_module "Netsys_tls" Debug.enable



type dh_params =
  [ `PKCS3_PEM_file of string
  | `PKCS3_DER of string
  | `Generate of int
  ]

type crt_list =
  [`PEM_file of string | `DER of string list]

type crl_list =
  [`PEM_file of string | `DER of string list]

type private_key =
  [ `PEM_file of string 
  | `RSA of string 
  | `DSA of string
  | `EC of string
  | `PKCS8 of string
  | `PKCS8_encrypted of string
  ]


let debug_backtrace fn exn bt =
  dlog (sprintf "Exception in function Netsys_tls.%s: %s - backtrace: %s"
                fn (Netexn.to_string exn) bt
       )


let error_message tls code =
  let module P = (val tls : Netsys_crypto_types.TLS_PROVIDER) in
  P.error_message code


let create_x509_config
      ?algorithms ?dh_params
      ?(verify = fun _ cert_ok name_ok -> cert_ok && name_ok) 
      ?system_trust ?trust ?revoke ?keys 
      ~peer_auth tls =
  let module P = (val tls : Netsys_crypto_types.TLS_PROVIDER) in
  let verify ep cert_ok name_ok =
    let module EP = struct
      module TLS = P
      let endpoint = ep
    end in
    verify (module EP : Netsys_crypto_types.TLS_ENDPOINT) cert_ok name_ok in
  try
    let credentials = 
      P.create_x509_credentials ?system_trust ?trust ?revoke ?keys () in
    let config =
      P.create_config
        ?algorithms ?dh_params ~verify
        ~peer_auth ~credentials () in
    let module Config = struct
      module TLS = P
      let config = config
    end in
    (module Config : Netsys_crypto_types.TLS_CONFIG)
  with
    | exn -> 
         if !Debug.enable then 
           debug_backtrace "create_x509_config" exn (Printexc.get_backtrace());
         raise exn


let create_file_endpoint ?resume ~role ~rd ~wr ~peer_name config =
  let module Config = (val config : Netsys_crypto_types.TLS_CONFIG) in
  let module P = Config.TLS in
  try
    let recv buf =
      let n = Netsys_mem.mem_recv rd buf 0 (Bigarray.Array1.dim buf) [] in
      dlogr (fun () -> sprintf "Netsys_tls: Unix.recv n=%d" n);
      n in
    let send buf size =
      let n = Netsys_mem.mem_send wr buf 0 size [] in
      dlogr (fun () -> sprintf "Netsys_tls: Unix.send n=%d" n);
      n in
    let ep = 
      match resume with
        | None ->
             P.create_endpoint ~role ~recv ~send ~peer_name Config.config
        | Some data ->
             if role <> `Client then 
               failwith
                 "Netsys_tls.create_file_endpoint: can only resume clients";
             P.resume_client ~recv ~send ~peer_name Config.config data in
    let module Endpoint = struct
      module TLS = P
      let endpoint = ep
      let rd_file = rd
      let wr_file = wr
    end in
    (module Endpoint : Netsys_crypto_types.FILE_TLS_ENDPOINT)
  with
    | exn -> 
         if !Debug.enable then 
           debug_backtrace "create_file_endpoint" 
                           exn (Printexc.get_backtrace());
         raise exn

let at_transport_eof ep =
  let module Endpoint = 
    (val ep : Netsys_crypto_types.TLS_ENDPOINT) in
  let module P = Endpoint.TLS in
  try
    P.at_transport_eof Endpoint.endpoint
  with
    | exn -> 
         if !Debug.enable then
           debug_backtrace "at_transport_eof" exn (Printexc.get_backtrace());
         raise exn
  


let endpoint ep =
  let module File_endpoint = 
    (val ep : Netsys_crypto_types.FILE_TLS_ENDPOINT) in
  (module File_endpoint : Netsys_crypto_types.TLS_ENDPOINT)


let state_driven_action endpoint =
  let module Endpoint = 
    (val endpoint : Netsys_crypto_types.TLS_ENDPOINT) in
  let module P = Endpoint.TLS in
  try
    match P.get_state Endpoint.endpoint with
      | `Start | `Handshake ->
           dlog "Netsys_tls: hello";
           P.hello Endpoint.endpoint;
           dlog "Netsys_tls: verify";
           P.verify Endpoint.endpoint
      | `Accepting ->
           dlog "Netsys_tls: accept_switch";
           P.accept_switch Endpoint.endpoint (P.get_config Endpoint.endpoint)
      | `Refusing ->
           dlog "Netsys_tls: refuse_switch";
           P.refuse_switch Endpoint.endpoint
      | `Switching ->
           dlog "Netsys_tls: switch";
           P.switch Endpoint.endpoint (P.get_config Endpoint.endpoint);
           dlog "Netsys_tls: hello";
           P.hello Endpoint.endpoint;
           dlog "Netsys_tls: verify";
           P.verify Endpoint.endpoint
      | _ -> 
           ()
   with
     | P.Exc.EAGAIN_RD as exn ->
          dlog "Netsys_tls: EAGAIN_RD"; raise exn
     | P.Exc.EAGAIN_WR as exn ->
          dlog "Netsys_tls: EAGAIN_WR"; raise exn
     | exn -> 
          if !Debug.enable then
            debug_backtrace "state_driven_action" exn (Printexc.get_backtrace());
          raise exn


let handshake endpoint =
  let module Endpoint = 
    (val endpoint : Netsys_crypto_types.TLS_ENDPOINT) in
  let module P = Endpoint.TLS in
  let state = P.get_state Endpoint.endpoint in
  if state = `Start || state = `Handshake then
    state_driven_action endpoint;
  dlog "Netsys_tls: handshake done"


let mem_recv ?(on_rehandshake=fun _ -> true) endpoint buf pos len =
  let module Endpoint = 
    (val endpoint : Netsys_crypto_types.TLS_ENDPOINT) in
  let module P = Endpoint.TLS in
  state_driven_action endpoint;
  let buf' =
    if pos=0 && len=Bigarray.Array1.dim buf then
      buf
    else
      Bigarray.Array1.sub buf pos len in
  try
    dlog "Netsys_tls: recv";
    let n = P.recv Endpoint.endpoint buf' in
    dlogr (fun () -> sprintf "Netsys_tls: recv done (n=%d)" n);
    n
  with
    | P.Exc.TLS_switch_request ->
         if on_rehandshake endpoint then
           P.accept_switch Endpoint.endpoint (P.get_config Endpoint.endpoint)
         else
           P.refuse_switch Endpoint.endpoint;
         raise Netsys_types.EAGAIN_RD
    | P.Exc.EAGAIN_RD as exn ->
         dlog "Netsys_tls: EAGAIN_RD"; raise exn
    | P.Exc.EAGAIN_WR as exn ->
         dlog "Netsys_tls: EAGAIN_WR"; raise exn
    | exn ->
         if !Debug.enable then
           debug_backtrace "mem_recv" exn (Printexc.get_backtrace());
         raise exn


let recv ?on_rehandshake endpoint buf pos len =
  let mem, return = Netsys_mem.pool_alloc_memory2 Netsys_mem.default_pool in
  try
    let mem_len = min len (Bigarray.Array1.dim mem) in
    let n = mem_recv ?on_rehandshake endpoint mem 0 mem_len in
    Netsys_mem.blit_memory_to_bytes mem 0 buf pos n;
    return();
    n
  with
    | exn -> return(); raise exn


let mem_send endpoint buf pos len =
  let module Endpoint = 
    (val endpoint : Netsys_crypto_types.TLS_ENDPOINT) in
  let module P = Endpoint.TLS in
  state_driven_action endpoint;
  let buf' =
    if pos=0 then
      buf
    else
      Bigarray.Array1.sub buf pos len in
  try
    dlog "Netsys_tls: send";
    let n = P.send Endpoint.endpoint buf' len in
    dlogr (fun () -> sprintf "Netsys_tls: send done (n=%d)" n);
    n
  with
    | P.Exc.EAGAIN_RD as exn ->
         dlog "Netsys_tls: EAGAIN_RD"; raise exn
    | P.Exc.EAGAIN_WR as exn ->
         dlog "Netsys_tls: EAGAIN_WR"; raise exn
    | exn ->
         if !Debug.enable then
           debug_backtrace "mem_send" exn (Printexc.get_backtrace());
         raise exn


let send endpoint buf pos len =
  state_driven_action endpoint;
  let mem, return = Netsys_mem.pool_alloc_memory2 Netsys_mem.default_pool in
  try
    let mem_len = min len (Bigarray.Array1.dim mem) in
    Netsys_mem.blit_bytes_to_memory buf pos mem 0 mem_len;
    let n = mem_send endpoint mem 0 mem_len in
    return();
    n
  with
    | exn -> return(); raise exn


let str_send endpoint buf pos len =
  send endpoint (Bytes.unsafe_of_string buf) pos len

let shutdown endpoint how =
  let module Endpoint = 
    (val endpoint : Netsys_crypto_types.TLS_ENDPOINT) in
  let module P = Endpoint.TLS in
  state_driven_action endpoint;
  try
    dlog "Netsys_tls: bye";
    P.bye Endpoint.endpoint how;
    dlog "Netsys_tls: bye done";
  with
    | P.Exc.EAGAIN_RD as exn ->
         dlog "Netsys_tls: EAGAIN_RD"; raise exn
    | P.Exc.EAGAIN_WR as exn ->
         dlog "Netsys_tls: EAGAIN_WR"; raise exn
    | exn ->
         if !Debug.enable then
           debug_backtrace "shutdown" exn (Printexc.get_backtrace());
         raise exn
OCaml

Innovation. Community. Security.