-- | This module implements secure multi-execution.moduleSME.MEwhereimportControl.Concurrent(MVar,forkIO,putMVar,takeMVar,newEmptyMVar)importControl.Concurrent.ChanimportPreludehiding(readFile,writeFile)importqualifiedSystem.IOasIO(readFile,writeFile,putStrLn)importSME.Lattice-- | Type class to specify security policies for programs run under secure multi-execution. classFiniteLatticel=>Policylab|a->lbwhere-- | It defines the security level assigned to an input or output of type @a@.level::a->l-- | It assigns a default value (of type @b@) to an input of type @a@.defvalue::a->b-- | The multi-execution monad.dataMEa=Returna|WriteFilePathString(MEa)|ReadFilePath(String->MEa)instanceMonadMEwherereturnx=Returnx(Returnx)>>=f=fx(Writefilesp)>>=f=Writefiles(p>>=f)(Readfileg)>>=f=Readfile(\i->gi>>=f)-- | Secure operation for writing files.writeFile::FilePath->String->ME()writeFilefiles=Writefiles(return())-- | Secure operation for reading files.readFile::FilePath->MEStringreadFilefile=Readfilereturn-- | Interpreter for the 'ME' monadrun::PolicylFilePathString=>l->ChanMatrixl->MEa->IOarun__(Returna)=returnarunlc(Writefileot)|levelfile==l=doIO.writeFilefileorunlct|otherwise=runlctrunlc(Readfilef)|levelfile==l=dox<-IO.readFilefilebroadcastclfilexrunlc(fx)|sless(levelfile)l=dox<-reuseInputclfilerunlc(fx)|otherwise=runlc(f(defvaluefile))typeChanMatrixl=[(l,[(l,Chan(FilePath,String))])]-- | Data type to set the security lattice to be used by function 'sme'.dataSetLevell=SetLevel-- | Function to perform secure multi-execution. The first argument is only there for type-checking purposes. sme::PolicylFilePathString=>SetLevell->MEa->IO()sme_t=doc<-newChanMatrixsync<-newSyncVarssequence_$do(l,s)<-syncreturn(forkIO(do_<-runlct;putMVars()))sequence_$do(_,s)<-syncreturn(takeMVars)reuseInput::PolicylFilePathString=>ChanMatrixl->l->FilePath->IOStringreuseInputcmlf=caselookup(levelf)cmofNothing->error"Not possible to reuse input!"Justxs->caselookuplxsofNothing->error"Not possible to reuse an input"Justc->reuseContentscfreuseContents::Chan(FilePath,String)->FilePath->IOStringreuseContentscf=dop@(f',s)<-readChanciff==f'thenreturnselsedos'<-reuseContentscfunGetChancpreturns'broadcast::FiniteLatticel=>ChanMatrixl->l->FilePath->String->IO()broadcastcmlfstr=caselookuplcmofNothing->return()Justxs->mapM_(\c->writeChan(sndc)(f,str))xsnewChanMatrix::FiniteLatticel=>IO(ChanMatrixl)newChanMatrix=mapMnewChanLeveluniversenewChanLevel::FiniteLatticel=>l->IO(l,[(l,Chan(FilePath,String))])newChanLevell=dols<-mapM(\e->newChan>>=\c->return(e,c))(filter(/=l)(upsetl))return(l,ls)newSyncVars::FiniteLatticel=>IO[(l,MVar())]newSyncVars=mapM(\x->newEmptyMVar>>=\v->return(x,v))universe