Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file vmm_tls.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104(* (c) 2018 Hannes Mehnert, all rights reserved *)openRresultopenRresult.R.InfixopenX509(* we skip all non-albatross certificates *)letcert_namecert=matchExtension.(find(UnsupportedVmm_asn.oid)(Certificate.extensionscert))with|None->OkNone|Some(_,data)->matchX509.(Distinguished_name.common_name(Certificate.subjectcert))with|Somename->Ok(Somename)|None->matchVmm_asn.of_cert_extensiondatawith|Error(`Msg_)->Error(`Msg"couldn't parse albatross extension")|Ok(_,`Policy_cmdpc)->beginmatchpcwith|`Policy_add_->Error(`Msg"policy add may not have an empty name")|`Policy_remove->Error(`Msg"policy remove may not have an empty name")|`Policy_info->OkNoneend|Ok(_,`Block_cmdbc)->beginmatchbcwith|`Block_add_->Error(`Msg"block add may not have an empty name")|`Block_remove->Error(`Msg"block remove may not have an empty name")|`Block_info->OkNoneend|_->OkNoneletnamechain=List.fold_left(funacccert->matchacc,cert_namecertwith|Errore,_->Errore|_,Errore->Errore|Okacc,OkNone->Okacc|Okacc,Ok(Somedata)->Vmm_core.Name.appenddataacc)(OkVmm_core.Name.root)chain(* this separates the leaf and top-level certificate from the chain,
and also reverses the intermediates (to be (leaf, CA -> subCA -> subCA')
in which subCA' signed leaf *)letseparate_chain=function|[]->Error(`Msg"empty chain")|[leaf]->Ok(leaf,[])|leaf::xs->Ok(leaf,List.revxs)letwire_command_of_certcert=matchExtension.(find(UnsupportedVmm_asn.oid)(Certificate.extensionscert))with|None->Error`Not_present|Some(_,data)->Vmm_asn.of_cert_extensiondata>>=fun(v,wire)->ifnotVmm_commands.(is_currentv)thenLogs.warn(funm->m"version mismatch, received %a current %a"Vmm_commands.pp_versionvVmm_commands.pp_versionVmm_commands.current);Ok(v,wire)letextract_policieschain=List.fold_left(funacccert->matchacc,wire_command_of_certcertwith|Errore,_->Errore|Okacc,Error`Not_present->Okacc|Ok_,Error(`Msgmsg)->Error(`Msgmsg)|Ok(prefix,acc),Ok(_,`Policy_cmd`Policy_addp)->(cert_namecert>>=function|None->Okprefix|Somex->Vmm_core.Name.prependxprefix)>>|funname->(name,(name,p)::acc)|_,Okwire->R.error_msgf"unexpected wire %a"Vmm_commands.pp(sndwire))(Ok(Vmm_core.Name.root,[]))chainlethandlechain=(ifList.lengthchain<10thenOk()elseError(`Msg"certificate chain too long"))>>=fun()->separate_chainchain>>=fun(leaf,rest)->(* use subject common names of intermediate certs as prefix *)namerest>>=funname'->(* and subject common name of leaf certificate -- allowing dots in CN -- as postfix *)(cert_nameleaf>>=function|None|Some"."->Okname'|Somex->Vmm_core.Name.of_stringx>>|funpost->Vmm_core.Name.concatname'post)>>=funname->Logs.debug(funm->m"name is %a leaf is %a, chain %a"Vmm_core.Name.ppnameCertificate.ppleafFmt.(list~sep:(unit" -> ")Certificate.pp)rest);extract_policiesrest>>=fun(_,policies)->(* TODO: logging let login_hdr, login_ev = Log.hdr name, `Login addr in *)matchwire_command_of_certleafwith|Error`Msgp->Error(`Msgp)|Error`Not_present->Error(`Msg"leaf certificate does not contain an albatross extension")|Ok(v,wire)->(* we only allow some commands via certificate *)matchwirewith|`Console_cmd(`Console_subscribe_)|`Stats_cmd`Stats_subscribe|`Unikernel_cmd_|`Policy_cmd`Policy_info|`Block_cmd_->Ok(name,policies,v,wire)|_->Error(`Msg"unexpected command")