Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file tls_mirage.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255openLwtmoduleMake(F:Mirage_flow_lwt.S)=structmoduleFLOW=Ftypeerror=[`Tls_alertofTls.Packet.alert_type|`Tls_failureofTls.Engine.failure|`ReadofF.error|`WriteofF.write_error]typewrite_error=[Mirage_flow.write_error|error]typebuffer=Cstruct.ttype+'aio='aLwt.tletpp_errorppf=function|`Tls_failuref->Fmt.stringppf@@Tls.Engine.string_of_failuref|`Tls_alerta->Fmt.stringppf@@Tls.Packet.alert_type_to_stringa|`Reade->F.pp_errorppfe|`Writee->F.pp_write_errorppfeletpp_write_errorppf=function|#Mirage_flow.write_errorase->Mirage_flow.pp_write_errorppfe|#errorase->pp_errorppfetypetracer=Sexplib.Sexp.t->unittypeflow={role:[`Server|`Client];flow:FLOW.flow;tracer:traceroption;mutablestate:[`ActiveofTls.Engine.state|`Eof|`Erroroferror];mutablelinger:Cstruct.tlist;}lettls_alerta=`Error(`Tls_alerta)lettls_failf=`Error(`Tls_failuref)letlist_of_option=functionNone->[]|Somex->[x]letlift_read_result=function|Ok(`Data_|`Eofasx)->x|Errore->`Error(`Reade)letlift_write_result=function|Ok()->`Ok()|Errore->`Error(`Writee)letcheck_writeflowf_res=letres=lift_write_resultf_resin(matchflow.state,reswith|`Active_,(`Eof|`Error_ase)->flow.state<-e;FLOW.closeflow.flow|_->return_unit)>|=fun()->matchf_reswith|Ok()->Ok()|Errore->Error(`Writee:>write_error)lettracingflowf=matchflow.tracerwith|None->f()|Somehook->Tls.Tracing.active~hookfletread_reactflow=lethandletlsbuf=matchtracingflow@@fun()->Tls.Engine.handle_tlstlsbufwith|`Ok(res,`Responseresp,`Datadata)->flow.state<-(matchreswith|`Oktls->`Activetls|`Eof->`Eof|`Alertalert->tls_alertalert);(matchrespwith|None->return@@Ok()|Somebuf->FLOW.writeflow.flowbuf>>=check_writeflow)>>=fun_->(matchreswith|`Ok_->return_unit|_->FLOW.closeflow.flow)>>=fun()->return@@`Okdata|`Fail(fail,`Responseresp)->letreason=tls_failfailinflow.state<-reason;FLOW.(writeflow.flowresp>>=fun_->closeflow.flow)>>=fun()->returnreasoninmatchflow.statewith|`Eof|`Error_ase->returne|`Active_->FLOW.readflow.flow>|=lift_read_result>>=function|`Eof|`Error_ase->flow.state<-e;returne|`Databuf->matchflow.statewith|`Activetls->handletlsbuf|`Eof|`Error_ase->returneletrecreadflow=matchflow.lingerwith|[]->(read_reactflow>>=function|`OkNone->readflow|`Ok(Somebuf)->return@@Ok(`Databuf)|`Eof->return@@Ok`Eof|`Errore->return@@Errore)|bufs->flow.linger<-[];return@@Ok(`Data(Tls.Utils.Cs.appends@@List.revbufs))letwritevflowbufs=matchflow.statewith|`Eof->return@@Error`Closed|`Errore->return@@Error(e:>write_error)|`Activetls->matchtracingflow@@fun()->Tls.Engine.send_application_datatlsbufswith|Some(tls,answer)->flow.state<-`Activetls;FLOW.writeflow.flowanswer>>=check_writeflow|None->(* "Impossible" due to handshake draining. *)assertfalseletwriteflowbuf=writevflow[buf](*
* XXX bad XXX
* This is a point that should particularly be protected from concurrent r/w.
* Doing this before a `t` is returned is safe; redoing it during rekeying is
* not, as the API client already sees the `t` and can mistakenly interleave
* writes while this is in progress.
* *)letrecdrain_handshakeflow=matchflow.statewith|`Activetlswhennot(Tls.Engine.handshake_in_progresstls)->return@@Okflow|_->(* read_react re-throws *)read_reactflow>>=function|`Okmbuf->flow.linger<-list_of_optionmbuf@flow.linger;drain_handshakeflow|`Errore->return@@Error(e:>write_error)|`Eof->return@@Error`Closedletreneg?authenticator?acceptable_cas?cert?(drop=true)flow=matchflow.statewith|`Eof->return@@Error`Closed|`Errore->return@@Error(e:>write_error)|`Activetls->matchtracingflow@@fun()->Tls.Engine.reneg?authenticator?acceptable_cas?certtlswith|None->(* XXX make this impossible to reach *)invalid_arg"Renegotiation already in progress"|Some(tls',buf)->ifdropthenflow.linger<-[];flow.state<-`Activetls';FLOW.writeflow.flowbuf>>=fun_->drain_handshakeflow>|=function|Ok_->Ok()|Error_ase->eletcloseflow=matchflow.statewith|`Activetls->flow.state<-`Eof;let(_,buf)=tracingflow@@fun()->Tls.Engine.send_close_notifytlsinFLOW.(writeflow.flowbuf>>=fun_->closeflow.flow)|_->return_unitletclient_of_flow?traceconf?hostflow=letconf'=matchhostwith|None->conf|Somehost->Tls.Config.peerconfhostinlet(tls,init)=Tls.Engine.clientconf'inlettls_flow={role=`Client;flow=flow;state=`Activetls;linger=[];tracer=trace;}inFLOW.writeflowinit>>=fun_->drain_handshaketls_flowletserver_of_flow?traceconfflow=lettls_flow={role=`Server;flow=flow;state=`Active(Tls.Engine.serverconf);linger=[];tracer=trace;}indrain_handshaketls_flowletepochflow=matchflow.statewith|`Eof|`Error_->Error()|`Activetls->matchTls.Engine.epochtlswith|`InitialEpoch->assertfalse(* `drain_handshake` invariant. *)|`Epoche->Oke(* let create_connection t tls_params host (addr, port) =
|+ XXX addr -> (host : string) +|
TCP.create_connection t (addr, port) >>= function
| `Error _ as e -> return e
| `Ok flow -> client_of_tcp_flow tls_params host flow *)(* let listen_ssl t cert ~port callback =
let cb flow =
server_of_tcp_flow cert flow >>= callback in
TCP.input t ~listeners:(fun p -> if p = port then Some cb else None) *)endmoduleX509(KV:Mirage_kv_lwt.RO)(C:Mirage_clock.PCLOCK)=structletca_roots_file=Mirage_kv.Key.v"ca-roots.crt"letdefault_cert="server"leterr_failpp=function|Okx->returnx|Errore->Fmt.kstrffail_with"%a"ppeletpp_msgppf=function`Msgm->Fmt.stringppfmletdecode_or_failfcs=err_failpp_msg(fcs)letreadkvname=KV.getkvname>>=err_failKV.pp_error>|=Cstruct.of_stringletauthenticatorkvclock=function|`Noop->returnX509.Authenticator.null|`CAs->lettime=Ptime.v(C.now_d_psclock)inreadkvca_roots_file>>=decode_or_failX509.Certificate.decode_pem_multiple>|=X509.Authenticator.chain_of_trust?crls:None~timeletcertificatekv=letreadname=readkv(Mirage_kv.Key.v(name^".pem"))>>=decode_or_failX509.Certificate.decode_pem_multiple>>=funcerts->readkv(Mirage_kv.Key.v(name^".key"))>>=decode_or_failX509.Private_key.decode_pem>|=fun(`RSApk)->(certs,pk)infunction|`Default->readdefault_cert|`Namename->readnameend