From 1e8dd71f23e6732d6ce7ae6be928d39b1c580b12 Mon Sep 17 00:00:00 2001 From: fr33domlover Date: Fri, 18 Oct 2019 23:20:48 +0000 Subject: [PATCH] Fix handling of forwarded activities from local repos --- src/Vervis/ActivityPub/Recipient.hs | 1 + src/Vervis/Federation.hs | 92 ++++++++++++++++++++++------- src/Vervis/Federation/Auth.hs | 47 ++++++++------- 3 files changed, 98 insertions(+), 42 deletions(-) diff --git a/src/Vervis/ActivityPub/Recipient.hs b/src/Vervis/ActivityPub/Recipient.hs index 7455d1c..930aa37 100644 --- a/src/Vervis/ActivityPub/Recipient.hs +++ b/src/Vervis/ActivityPub/Recipient.hs @@ -24,6 +24,7 @@ module Vervis.ActivityPub.Recipient , LocalSharerRelatedSet (..) , LocalRecipientSet , concatRecipients + , parseLocalActor , parseAudience , actorRecips ) diff --git a/src/Vervis/Federation.hs b/src/Vervis/Federation.hs index 932b5bd..95193ed 100644 --- a/src/Vervis/Federation.hs +++ b/src/Vervis/Federation.hs @@ -129,7 +129,7 @@ handleSharerInbox -> ActivityAuthentication -> ActivityBody -> ExceptT Text Handler Text -handleSharerInbox _now shrRecip (ActivityAuthLocalPerson pidAuthor) body = do +handleSharerInbox _now shrRecip (ActivityAuthLocal (ActivityAuthLocalPerson pidAuthor)) body = do (shrActivity, obiid) <- do luAct <- fromMaybeE @@ -173,7 +173,7 @@ handleSharerInbox _now shrRecip (ActivityAuthLocalPerson pidAuthor) body = do "Activity already exists in inbox of /s/" <> recip Just _ -> return $ "Activity inserted to inbox of /s/" <> recip -handleSharerInbox _now shrRecip (ActivityAuthLocalProject jidAuthor) body = do +handleSharerInbox _now shrRecip (ActivityAuthLocal (ActivityAuthLocalProject jidAuthor)) body = do (shrActivity, prjActivity, obiid) <- do luAct <- fromMaybeE @@ -217,6 +217,50 @@ handleSharerInbox _now shrRecip (ActivityAuthLocalProject jidAuthor) body = do "Activity already exists in inbox of /s/" <> recip Just _ -> return $ "Activity inserted to inbox of /s/" <> recip +handleSharerInbox _now shrRecip (ActivityAuthLocal (ActivityAuthLocalRepo ridAuthor)) body = do + (shrActivity, rpActivity, obiid) <- do + luAct <- + fromMaybeE + (activityId $ actbActivity body) + "Local activity: No 'id'" + route <- + fromMaybeE + (decodeRouteLocal luAct) + "Local activity: Not a valid route" + case route of + RepoOutboxItemR shr rp obikhid -> + (shr,rp,) <$> decodeKeyHashidE obikhid "Local activity: ID is invalid hashid" + _ -> throwE "Local activity: Not an activity route" + runDBExcept $ do + Entity pidRecip personRecip <- lift $ do + sid <- getKeyBy404 $ UniqueSharer shrRecip + getBy404 $ UniquePersonIdent sid + mobi <- lift $ get obiid + obi <- fromMaybeE mobi "Local activity: No such ID in DB" + mridOutbox <- + lift $ getKeyBy $ UniqueRepoOutbox $ outboxItemOutbox obi + ridOutbox <- + fromMaybeE mridOutbox "Local activity not in a repo outbox" + r <- lift $ getJust ridOutbox + s <- lift $ getJust $ repoSharer r + unless (sharerIdent s == shrActivity) $ + throwE "Local activity: ID invalid, hashid and author shr mismatch" + unless (repoIdent r == rpActivity) $ + throwE "Local activity: ID invalid, hashid and author rp mismatch" + unless (ridAuthor == ridOutbox) $ + throwE "Activity author in DB and in received JSON don't match" + lift $ do + ibiid <- insert $ InboxItem True + let ibid = personInbox personRecip + miblid <- insertUnique $ InboxItemLocal ibid obiid ibiid + let recip = shr2text shrRecip + case miblid of + Nothing -> do + delete ibiid + return $ + "Activity already exists in inbox of /s/" <> recip + Just _ -> + return $ "Activity inserted to inbox of /s/" <> recip handleSharerInbox now shrRecip (ActivityAuthRemote author) body = case activitySpecific $ actbActivity body of AcceptActivity accept -> @@ -231,7 +275,7 @@ handleSharerInbox now shrRecip (ActivityAuthRemote author) body = sharerRejectF shrRecip now author body reject UndoActivity undo -> sharerUndoF shrRecip now author body undo - _ -> return "Unsupported activity type" + _ -> return "Unsupported activity type for sharers" handleProjectInbox :: UTCTime @@ -243,14 +287,7 @@ handleProjectInbox handleProjectInbox now shrRecip prjRecip auth body = do remoteAuthor <- case auth of - ActivityAuthLocalPerson pid -> - throwE $ - "Project inbox got local forwarded activity by pid#" <> - T.pack (show $ fromSqlKey pid) - ActivityAuthLocalProject jid -> - throwE $ - "Project inbox got local forwarded activity by jid#" <> - T.pack (show $ fromSqlKey jid) + ActivityAuthLocal local -> throwE $ errorLocalForwarded local ActivityAuthRemote ra -> return ra case activitySpecific $ actbActivity body of CreateActivity (Create note) -> @@ -261,7 +298,17 @@ handleProjectInbox now shrRecip prjRecip auth body = do projectOfferTicketF now shrRecip prjRecip remoteAuthor body offer UndoActivity undo -> projectUndoF shrRecip prjRecip now remoteAuthor body undo - _ -> return "Unsupported activity type" + _ -> return "Unsupported activity type for projects" + where + errorLocalForwarded (ActivityAuthLocalPerson pid) = + "Project inbox got local forwarded activity by pid#" <> + T.pack (show $ fromSqlKey pid) + errorLocalForwarded (ActivityAuthLocalProject jid) = + "Project inbox got local forwarded activity by jid#" <> + T.pack (show $ fromSqlKey jid) + errorLocalForwarded (ActivityAuthLocalRepo rid) = + "Project inbox got local forwarded activity by rid#" <> + T.pack (show $ fromSqlKey rid) handleRepoInbox :: UTCTime @@ -273,21 +320,24 @@ handleRepoInbox handleRepoInbox now shrRecip rpRecip auth body = do remoteAuthor <- case auth of - ActivityAuthLocalPerson pid -> - throwE $ - "Repo inbox got local forwarded activity by pid#" <> - T.pack (show $ fromSqlKey pid) - ActivityAuthLocalProject jid -> - throwE $ - "Repo inbox got local forwarded activity by jid#" <> - T.pack (show $ fromSqlKey jid) + ActivityAuthLocal local -> throwE $ errorLocalForwarded local ActivityAuthRemote ra -> return ra case activitySpecific $ actbActivity body of FollowActivity follow -> repoFollowF shrRecip rpRecip now remoteAuthor body follow UndoActivity undo-> repoUndoF shrRecip rpRecip now remoteAuthor body undo - _ -> return "Unsupported activity type" + _ -> return "Unsupported activity type for repos" + where + errorLocalForwarded (ActivityAuthLocalPerson pid) = + "Repo inbox got local forwarded activity by pid#" <> + T.pack (show $ fromSqlKey pid) + errorLocalForwarded (ActivityAuthLocalProject jid) = + "Repo inbox got local forwarded activity by jid#" <> + T.pack (show $ fromSqlKey jid) + errorLocalForwarded (ActivityAuthLocalRepo rid) = + "Repo inbox got local forwarded activity by rid#" <> + T.pack (show $ fromSqlKey rid) fixRunningDeliveries :: (MonadIO m, MonadLogger m, IsSqlBackend backend) => ReaderT backend m () fixRunningDeliveries = do diff --git a/src/Vervis/Federation/Auth.hs b/src/Vervis/Federation/Auth.hs index eed51e5..645f966 100644 --- a/src/Vervis/Federation/Auth.hs +++ b/src/Vervis/Federation/Auth.hs @@ -15,6 +15,7 @@ module Vervis.Federation.Auth ( RemoteAuthor (..) + , ActivityAuthenticationLocal (..) , ActivityAuthentication (..) , ActivityBody (..) , authenticateActivity @@ -93,6 +94,7 @@ import Database.Persist.Local import Yesod.Persist.Local import Vervis.ActivityPub +import Vervis.ActivityPub.Recipient import Vervis.ActorKey import Vervis.FedURI import Vervis.Foundation @@ -107,9 +109,13 @@ data RemoteAuthor = RemoteAuthor , remoteAuthorId :: RemoteActorId } -data ActivityAuthentication +data ActivityAuthenticationLocal = ActivityAuthLocalPerson PersonId | ActivityAuthLocalProject ProjectId + | ActivityAuthLocalRepo RepoId + +data ActivityAuthentication + = ActivityAuthLocal ActivityAuthenticationLocal | ActivityAuthRemote RemoteAuthor data ActivityBody = ActivityBody @@ -260,26 +266,25 @@ verifySelfSig -> LocalRefURI -> ByteString -> Signature - -> ExceptT String Handler (Either PersonId ProjectId) + -> ExceptT String Handler ActivityAuthenticationLocal verifySelfSig luAuthor (LocalRefURI lruKey) input (Signature sig) = do author <- do route <- - case decodeRouteLocal luAuthor of - Nothing -> throwE "Local author ID isn't a valid route" - Just r -> return r - case route of - SharerR shr -> return $ Left shr - ProjectR shr prj -> return $ Right (shr, prj) - _ -> throwE "Local author ID isn't an actor route" + fromMaybeE + (decodeRouteLocal luAuthor) + "Local author ID isn't a valid route" + fromMaybeE + (parseLocalActor route) + "Local author ID isn't an actor route" akey <- do route <- do luKey <- case lruKey of Left l -> return l Right _ -> throwE "Local key ID has a fragment" - case decodeRouteLocal luKey of - Nothing -> throwE "Local key ID isn't a valid route" - Just r -> return r + fromMaybeE + (decodeRouteLocal luKey) + "Local key ID isn't a valid route" (akey1, akey2, _) <- liftIO . readTVarIO =<< getsYesod appActorKeys case route of ActorKey1R -> return akey1 @@ -290,18 +295,21 @@ verifySelfSig luAuthor (LocalRefURI lruKey) input (Signature sig) = do unless valid $ throwE "Self sig verification says not valid" ExceptT $ runDB $ do - mauthorId <- runMaybeT $ bitraverse getPerson getProject author + mauthorId <- runMaybeT $ getLocalActor author return $ case mauthorId of Nothing -> Left "Local author: No such user/project" Just id_ -> Right id_ where - getPerson shr = do + getLocalActor (LocalActorSharer shr) = do sid <- MaybeT $ getKeyBy $ UniqueSharer shr - MaybeT $ getKeyBy $ UniquePersonIdent sid - getProject (shr, prj) = do + ActivityAuthLocalPerson <$> MaybeT (getKeyBy $ UniquePersonIdent sid) + getLocalActor (LocalActorProject shr prj) = do sid <- MaybeT $ getKeyBy $ UniqueSharer shr - MaybeT $ getKeyBy $ UniqueProject prj sid + ActivityAuthLocalProject <$> MaybeT (getKeyBy $ UniqueProject prj sid) + getLocalActor (LocalActorRepo shr rp) = do + sid <- MaybeT $ getKeyBy $ UniqueSharer shr + ActivityAuthLocalRepo <$> MaybeT (getKeyBy $ UniqueRepo rp sid) verifyForwardedSig :: Host @@ -314,11 +322,8 @@ verifyForwardedSig hAuthor luAuthor (Verification malgo keyid input signature) = throwE "Author and forwarded sig key on different hosts" local <- hostIsLocal hKey if local - then mkauth <$> verifySelfSig luAuthor luKey input signature + then ActivityAuthLocal <$> verifySelfSig luAuthor luKey input signature else ActivityAuthRemote <$> verifyActorSig' malgo input signature hKey luKey (Just luAuthor) - where - mkauth (Left pid) = ActivityAuthLocalPerson pid - mkauth (Right jid) = ActivityAuthLocalProject jid verifyContentTypeAP :: MonadHandler m => m () verifyContentTypeAP = do