wip, integrating policy

This commit is contained in:
voidlizard 2024-10-18 06:33:29 +03:00
parent 15be1cc0b4
commit 3fc740099e
3 changed files with 88 additions and 30 deletions

View File

@ -20,6 +20,7 @@ import HBS2.Net.Proto
import HBS2.Base58 import HBS2.Base58
import HBS2.Storage import HBS2.Storage
import HBS2.Storage.Operations.Missed import HBS2.Storage.Operations.Missed
import HBS2.Storage.Operations.ByteString
import HBS2.Merkle import HBS2.Merkle
import HBS2.Hash import HBS2.Hash
import HBS2.Net.Auth.Credentials import HBS2.Net.Auth.Credentials
@ -53,10 +54,12 @@ import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Except import Control.Monad.Trans.Except
import Control.Monad.Except (throwError) import Control.Monad.Except (throwError)
import Data.Coerce import Data.Coerce
import Data.ByteString.Lazy.Char8 qualified as LBS8
import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as HM import Data.HashMap.Strict qualified as HM
import Data.HashSet (HashSet) import Data.HashSet (HashSet)
import Data.HashSet qualified as HS import Data.HashSet qualified as HS
import Data.Either
import Data.List qualified as L import Data.List qualified as L
import Data.Maybe import Data.Maybe
import Data.Word import Data.Word
@ -125,7 +128,7 @@ data MailboxProtoWorker (s :: CryptoScheme) e =
, mpwStorage :: AnyStorage , mpwStorage :: AnyStorage
, mpwCredentials :: PeerCredentials s , mpwCredentials :: PeerCredentials s
, mpwFetchQ :: TVar (HashSet (MailboxRefKey s)) , mpwFetchQ :: TVar (HashSet (MailboxRefKey s))
, inMessageQueue :: TBQueue (Message s, MessageContent s) , inMessageQueue :: TBQueue (Maybe (PubKey 'Sign s), Message s, MessageContent s)
, inMessageMergeQueue :: TVar (HashMap (MailboxRefKey s) (HashSet HashRef)) , inMessageMergeQueue :: TVar (HashMap (MailboxRefKey s) (HashSet HashRef))
, inPolicyDownloadQ :: TVar (HashMap HashRef (PolicyDownload s)) , inPolicyDownloadQ :: TVar (HashMap HashRef (PolicyDownload s))
, inMailboxDownloadQ :: TVar (HashMap HashRef (MailboxDownload s)) , inMailboxDownloadQ :: TVar (HashMap HashRef (MailboxDownload s))
@ -145,7 +148,7 @@ pattern PlainMessageDelete x <- DeleteMessagesPayload (MailboxMessagePredicate1
instance IsAcceptPolicy HBS2Basic () where instance IsAcceptPolicy HBS2Basic () where
policyAcceptPeer _ _ = pure True policyAcceptPeer _ _ = pure True
policyAcceptMessage _ _ _ = pure True policyAcceptMessage _ _ _ = pure True
policyAcceptSender _ _ = pure True
instance (s ~ HBS2Basic, e ~ L4Proto, s ~ Encryption e) => IsMailboxProtoAdapter s (MailboxProtoWorker s e) where instance (s ~ HBS2Basic, e ~ L4Proto, s ~ Encryption e) => IsMailboxProtoAdapter s (MailboxProtoWorker s e) where
@ -153,15 +156,20 @@ instance (s ~ HBS2Basic, e ~ L4Proto, s ~ Encryption e) => IsMailboxProtoAdapter
mailboxGetStorage = pure . mpwStorage mailboxGetStorage = pure . mpwStorage
mailboxGetPolicy w = pure (AnyPolicy @s ()) mailboxGetPolicy MailboxProtoWorker{..} mbox = do
let def = AnyPolicy (defaultBasicPolicy @s)
fromMaybe def <$> runMaybeT do
dbe <- readTVarIO mailboxDB >>= toMPlus
co <- loadPolicyContent dbe mpwStorage mbox
pure (AnyPolicy co)
mailboxAcceptMessage MailboxProtoWorker{..} m c = do mailboxAcceptMessage MailboxProtoWorker{..} peer m c = do
atomically do atomically do
full <- isFullTBQueue inMessageQueue full <- isFullTBQueue inMessageQueue
if full then do if full then do
modifyTVar inMessageQueueDropped succ modifyTVar inMessageQueueDropped succ
else do else do
writeTBQueue inMessageQueue (m,c) writeTBQueue inMessageQueue (peer, m,c)
modifyTVar inMessageQueueInNum succ modifyTVar inMessageQueueInNum succ
mailboxAcceptDelete MailboxProtoWorker{..} mbox dmp box = do mailboxAcceptDelete MailboxProtoWorker{..} mbox dmp box = do
@ -494,6 +502,32 @@ loadPolicyPayloadUnboxed dbe sto mbox = do
<&> join <&> join
<&> fmap snd <&> fmap snd
loadPolicyContent :: forall s m . (s ~ HBS2Basic, ForMailbox s, MonadIO m)
=> DBPipeEnv
-> AnyStorage
-> MailboxRefKey s
-> m (BasicPolicy s)
loadPolicyContent dbe sto mbox = do
let def = defaultBasicPolicy @s
fromMaybe def <$> runMaybeT do
SetPolicyPayload{..} <- loadPolicyPayloadUnboxed dbe sto mbox >>= toMPlus
lbs' <- runExceptT (readFromMerkle sto (SimpleKey (coerce sppPolicyRef)))
when (isLeft lbs') do
warn $ yellow "can't read policy for" <+> pretty mbox
syn' <- toMPlus lbs'
<&> LBS8.unpack
<&> parseTop
when (isLeft syn') do
warn $ yellow "can't parse policy for" <+> pretty mbox
syn <- toMPlus syn'
liftIO (parseBasicPolicy syn) >>= toMPlus
getMailboxType_ :: (ForMailbox s, MonadIO m) => DBPipeEnv -> MailboxRefKey s -> m (Maybe MailboxType) getMailboxType_ :: (ForMailbox s, MonadIO m) => DBPipeEnv -> MailboxRefKey s -> m (Maybe MailboxType)
getMailboxType_ d r = do getMailboxType_ d r = do
let sql = [qc|select type from mailbox where recipient = ? limit 1|] let sql = [qc|select type from mailbox where recipient = ? limit 1|]
@ -586,15 +620,37 @@ mailboxProtoWorker readConf me@MailboxProtoWorker{..} = do
forever do forever do
pause @'Seconds 10 pause @'Seconds 10
mess <- atomically $ STM.flushTBQueue inMessageQueue mess <- atomically $ STM.flushTBQueue inMessageQueue
for_ mess $ \(m,s) -> do for_ mess $ \(peer, m, s) -> do
atomically $ modifyTVar inMessageQueueInNum pred atomically $ modifyTVar inMessageQueueInNum pred
-- TODO: process-with-policy -- TODO: process-with-policy
for_ (messageRecipients s) $ \rcpt -> void $ runMaybeT do for_ (messageRecipients s) $ \rcpt -> void $ runMaybeT do
mbox <- getMailboxType_ @s dbe (MailboxRefKey rcpt)
let theMailbox = MailboxRefKey @s rcpt
mbox <- getMailboxType_ @s dbe theMailbox
>>= toMPlus >>= toMPlus
-- FIXME: excess-sign-check
(sender, _) <- unboxSignedBox0 (messageContent m) & toMPlus
po <- mailboxGetPolicy @s me theMailbox
acceptPeer <- maybe1 peer (pure True) $ \p ->
policyAcceptPeer @s po p
unless acceptPeer do
warn $ red "message dropped by peer policy"
<+> pretty mbox <+> pretty (fmap AsBase58 peer)
mzero
accept <- policyAcceptMessage @s po sender s
unless accept do
warn $ red "message dropped by policy for" <+> pretty theMailbox
mzero
-- TODO: ASAP-block-accounting -- TODO: ASAP-block-accounting
ha' <- putBlock sto (serialise m) <&> fmap HashRef ha' <- putBlock sto (serialise m) <&> fmap HashRef
@ -604,9 +660,7 @@ mailboxProtoWorker readConf me@MailboxProtoWorker{..} = do
err $ red "storage error, can't store message" err $ red "storage error, can't store message"
mzero mzero
let ref = MailboxRefKey @s rcpt debug $ yellow "mailbox: message stored" <+> pretty theMailbox <+> pretty ha
debug $ yellow "mailbox: message stored" <+> pretty ref <+> pretty ha
-- TODO: add-policy-reference -- TODO: add-policy-reference
let proof = ProofOfExist mzero let proof = ProofOfExist mzero
@ -614,7 +668,7 @@ mailboxProtoWorker readConf me@MailboxProtoWorker{..} = do
for_ h' $ \h -> do for_ h' $ \h -> do
atomically do atomically do
modifyTVar inMessageMergeQueue (HM.insertWith (<>) ref (HS.singleton (HashRef h))) modifyTVar inMessageMergeQueue (HM.insertWith (<>) theMailbox (HS.singleton (HashRef h)))
-- TODO: check-attachment-policy-for-mailbox -- TODO: check-attachment-policy-for-mailbox
@ -829,7 +883,7 @@ mailboxProtoWorker readConf me@MailboxProtoWorker{..} = do
Just (_, content) -> do Just (_, content) -> do
-- FIXME: what-if-message-queue-full? -- FIXME: what-if-message-queue-full?
mailboxAcceptMessage me normal content mailboxAcceptMessage me mzero normal content
pure () pure ()
failNum <- readTVarIO fails failNum <- readTVarIO fails
@ -919,10 +973,4 @@ instance ForMailbox s => FromField (MailboxRefKey s) where
instance FromField MailboxType where instance FromField MailboxType where
fromField w = fromField @String w <&> fromString @MailboxType fromField w = fromField @String w <&> fromString @MailboxType
-- TODO: test-multiple-recipients
-- TODO: implement-basic-policy
-- TODO: test-basic-policy

View File

@ -44,10 +44,11 @@ class ForMailbox s => IsMailboxProtoAdapter s a where
mailboxGetStorage :: forall m . MonadIO m => a -> m AnyStorage mailboxGetStorage :: forall m . MonadIO m => a -> m AnyStorage
mailboxGetPolicy :: forall m . MonadIO m => a -> m (AnyPolicy s) mailboxGetPolicy :: forall m . MonadIO m => a -> MailboxRefKey s -> m (AnyPolicy s)
mailboxAcceptMessage :: forall m . (ForMailbox s, MonadIO m) mailboxAcceptMessage :: forall m . (ForMailbox s, MonadIO m)
=> a => a
-> Maybe (PubKey 'Sign s) -- ^ peer
-> Message s -> Message s
-> MessageContent s -> MessageContent s
-> m () -> m ()
@ -154,7 +155,6 @@ mailboxProto inner adapter mess = deferred @p do
-- common stuff -- common stuff
sto <- mailboxGetStorage @s adapter sto <- mailboxGetStorage @s adapter
policy <- mailboxGetPolicy @s adapter
pc <- mailboxGetCredentials @s adapter pc <- mailboxGetCredentials @s adapter
now <- liftIO $ getPOSIXTime <&> round now <- liftIO $ getPOSIXTime <&> round
@ -163,22 +163,17 @@ mailboxProto inner adapter mess = deferred @p do
flip runContT pure $ callCC \exit -> do flip runContT pure $ callCC \exit -> do
se <- ContT $ maybe1 se' none
pip <- if inner then do pip <- if inner then do
pure $ view peerSignPk pc pure $ view peerSignPk pc
else do else do
se <- ContT $ maybe1 se' none
pure $ view peerSignKey se pure $ view peerSignKey se
acceptPeer <- policyAcceptPeer @s policy pip
unless acceptPeer do
debug $ red "Peer rejected by policy" <+> pretty (AsBase58 pip)
exit ()
case mailBoxProtoPayload mess of case mailBoxProtoPayload mess of
SendMessage msg -> do SendMessage msg -> do
debug $ red "AAAAAA!" <+> pretty now
-- проверить подпись быстрее, чем читать диск -- проверить подпись быстрее, чем читать диск
let unboxed' = unboxSignedBox0 @(MessageContent s) (messageContent msg) let unboxed' = unboxSignedBox0 @(MessageContent s) (messageContent msg)
@ -187,6 +182,7 @@ mailboxProto inner adapter mess = deferred @p do
-- $workflow: backlog -- $workflow: backlog
(_, content) <- ContT $ maybe1 unboxed' none (_, content) <- ContT $ maybe1 unboxed' none
let h = hashObject @HbSync (serialise mess) & HashRef let h = hashObject @HbSync (serialise mess) & HashRef
let routed = serialise (RoutedEntry h) let routed = serialise (RoutedEntry h)
@ -196,7 +192,18 @@ mailboxProto inner adapter mess = deferred @p do
unless seen $ lift do unless seen $ lift do
gossip mess gossip mess
mailboxAcceptMessage adapter msg content let whoever = if inner then Nothing else Just pip
-- TODO: maybe-dont-gossip-message-if-dropped-by-policy
-- сейчас policy проверяется для почтового ящика,
-- а тут мы еще не знаем, какой почтовый ящик и есть
-- ли он вообще. надо бы не рассылать, если пира
-- не поддерживаем.
--
-- с другой стороны -- мы не поддерживаем, а другие,
-- может, поддерживают.
mailboxAcceptMessage adapter whoever msg content
-- TODO: expire-block-and-collect-garbage -- TODO: expire-block-and-collect-garbage
-- $class: leak -- $class: leak
void $ putBlock sto routed void $ putBlock sto routed
@ -251,7 +258,7 @@ mailboxProto inner adapter mess = deferred @p do
let r = unboxSignedBox0 @(MailBoxStatusPayload s) box let r = unboxSignedBox0 @(MailBoxStatusPayload s) box
let PeerData{..} = se PeerData{..} <- ContT $ maybe1 se' none
(who, content@MailBoxStatusPayload{..}) <- ContT $ maybe1 r none (who, content@MailBoxStatusPayload{..}) <- ContT $ maybe1 r none

View File

@ -5,6 +5,7 @@ module HBS2.Peer.Proto.Mailbox.Policy.Basic
, BasicPolicyAction(..) , BasicPolicyAction(..)
, getAsSyntax , getAsSyntax
, parseBasicPolicy , parseBasicPolicy
, defaultBasicPolicy
, BasicPolicy(..) , BasicPolicy(..)
) where ) where
@ -73,6 +74,8 @@ getAsSyntax BasicPolicy{..} =
Allow -> mkSym "allow" Allow -> mkSym "allow"
Deny -> mkSym "deny" Deny -> mkSym "deny"
defaultBasicPolicy :: forall s . (ForMailbox s) => BasicPolicy s
defaultBasicPolicy = BasicPolicy Deny Deny mempty mempty
parseBasicPolicy :: forall s c m . (IsContext c, s ~ HBS2Basic, ForMailbox s, MonadUnliftIO m) parseBasicPolicy :: forall s c m . (IsContext c, s ~ HBS2Basic, ForMailbox s, MonadUnliftIO m)
=> [Syntax c] => [Syntax c]