Fix handling of forwarded activities from local repos

This commit is contained in:
fr33domlover 2019-10-18 23:20:48 +00:00
parent e96749a19e
commit 1e8dd71f23
3 changed files with 98 additions and 42 deletions

View file

@ -24,6 +24,7 @@ module Vervis.ActivityPub.Recipient
, LocalSharerRelatedSet (..)
, LocalRecipientSet
, concatRecipients
, parseLocalActor
, parseAudience
, actorRecips
)

View file

@ -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

View file

@ -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