p2phttp: Allow unauthenticated users to lock content by default

* p2phttp: Allow unauthenticated users to lock content by default.
* p2phttp: Added --unauth-nolocking option to prevent unauthenticated
  users from locking content.

The rationalle for this is that locking is not really a write operation, so
makes sense to allow in a repository that only allows read-only access. Not
supporting locking in that situation will prevent the user from dropping
content from a special remote they control in cases where the other copy of
the content is on the p2phttp server.

Also, when p2phttp is configured to also allow authenticated access,
lockcontent was resulting in a password prompt for users who had no way to
authenticate. And there is no good way to distinguish between the two types
of users client side.

--unauth-nolocking anticipates that this might be abused, and seems better
than disabling unauthenticated access entirely if a server is being
attacked. It may be that rate limiting locking by IP address or similar
would be an effective measure in such a situation. Or just limiting the
number of locks by anonymous users that can be live at any one time. Since
the impact of such an DOS attempt is limited to preventing dropping content
from the server, it seems not a very appealing target anyway.
This commit is contained in:
Joey Hess 2024-10-21 10:02:12 -04:00
parent 87c88025d1
commit de138c642b
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 60 additions and 10 deletions

View file

@ -3,6 +3,9 @@ git-annex (10.20240928) UNRELEASED; urgency=medium
* p2phttp: Support serving unauthenticated users while requesting
authentication for operations that need it. Eg, --unauth-readonly
can be combined with --authenv.
* p2phttp: Allow unauthenticated users to lock content by default.
* p2phttp: Added --unauth-nolocking option to prevent unauthenticated
users from locking content.
* Allow enabling the servant build flag with older versions of stm,
allowing building with ghc 9.0.2.
* git-remote-annex: Fix bug that prevented using it with external special

View file

@ -40,6 +40,7 @@ data Options = Options
, authEnvHttpOption :: Bool
, unauthReadOnlyOption :: Bool
, unauthAppendOnlyOption :: Bool
, unauthNoLockingOption :: Bool
, wideOpenOption :: Bool
, proxyConnectionsOption :: Maybe Integer
, clusterJobsOption :: Maybe Int
@ -83,6 +84,10 @@ optParser _ = Options
( long "unauth-appendonly"
<> help "allow unauthenticated users to read and append to the repository"
)
<*> switch
( long "unauth-nolocking"
<> help "prevent unauthenticated users from locking content in the repository"
)
<*> switch
( long "wideopen"
<> help "give unauthenticated users full read+write access"
@ -128,15 +133,25 @@ seek o = getAnnexWorkerPool $ \workerpool ->
mkGetServerMode :: M.Map Auth P2P.ServerMode -> Options -> GetServerMode
mkGetServerMode _ o _ Nothing
| wideOpenOption o =
ServerMode P2P.ServeReadWrite False
| unauthAppendOnlyOption o =
ServerMode P2P.ServeAppendOnly canauth
| unauthReadOnlyOption o =
ServerMode P2P.ServeReadOnly canauth
| wideOpenOption o = ServerMode
{ serverMode = P2P.ServeReadWrite
, unauthenticatedLockingAllowed = unauthlock
, authenticationAllowed = False
}
| unauthAppendOnlyOption o = ServerMode
{ serverMode = P2P.ServeAppendOnly
, unauthenticatedLockingAllowed = unauthlock
, authenticationAllowed = canauth
}
| unauthReadOnlyOption o = ServerMode
{ serverMode = P2P.ServeReadOnly
, unauthenticatedLockingAllowed = unauthlock
, authenticationAllowed = canauth
}
| otherwise = CannotServeRequests
where
canauth = authEnvOption o || authEnvHttpOption o
unauthlock = not (unauthNoLockingOption o)
mkGetServerMode authenv o issecure (Just auth) =
case (issecure, authEnvOption o, authEnvHttpOption o) of
(Secure, True, _) -> checkauth
@ -144,7 +159,11 @@ mkGetServerMode authenv o issecure (Just auth) =
_ -> noauth
where
checkauth = case M.lookup auth authenv of
Just servermode -> ServerMode servermode False
Just servermode -> ServerMode
{ serverMode = servermode
, authenticationAllowed = False
, unauthenticatedLockingAllowed = False
}
Nothing -> noauth
noauth = mkGetServerMode authenv noautho issecure Nothing
noautho = o { authEnvOption = False, authEnvHttpOption = False }

View file

@ -425,7 +425,7 @@ serveLockContent
-> Maybe Auth
-> Handler LockResult
serveLockContent st su apiver (B64Key k) cu bypass sec auth = do
conn <- getP2PConnection apiver st cu su bypass sec auth WriteAction id
conn <- getP2PConnection apiver st cu su bypass sec auth LockAction id
let lock = do
lockresv <- newEmptyTMVarIO
unlockv <- newEmptyTMVarIO
@ -465,7 +465,7 @@ serveKeepLocked
-> S.SourceT IO UnlockRequest
-> Handler LockResult
serveKeepLocked st _su _apiver lckid _cu _bypass sec auth _ _ unlockrequeststream = do
checkAuthActionClass st sec auth WriteAction $ \_ -> do
checkAuthActionClass st sec auth LockAction $ \_ -> do
liftIO $ keepingLocked lckid st
_ <- liftIO $ S.unSourceT unlockrequeststream go
return (LockResult False Nothing)

View file

@ -57,6 +57,7 @@ type GetServerMode = IsSecure -> Maybe Auth -> ServerMode
data ServerMode
= ServerMode
{ serverMode :: P2P.ServerMode
, unauthenticatedLockingAllowed :: Bool
, authenticationAllowed :: Bool
}
| CannotServeRequests
@ -68,7 +69,7 @@ mkP2PHttpServerState acquireconn annexworkerpool getservermode = P2PHttpServerSt
<*> pure getservermode
<*> newTMVarIO mempty
data ActionClass = ReadAction | WriteAction | RemoveAction
data ActionClass = ReadAction | WriteAction | RemoveAction | LockAction
deriving (Eq)
withP2PConnection
@ -152,6 +153,8 @@ checkAuthActionClass st sec auth actionclass go =
case (sm, actionclass) of
(ServerMode { serverMode = P2P.ServeReadWrite }, _) ->
go P2P.ServeReadWrite
(ServerMode { unauthenticatedLockingAllowed = True }, LockAction) ->
go P2P.ServeReadOnly
(ServerMode { serverMode = P2P.ServeAppendOnly }, RemoveAction) ->
throwError $ forbiddenWithoutAuth sm
(ServerMode { serverMode = P2P.ServeAppendOnly }, _) ->

View file

@ -41,3 +41,5 @@ local repository version: 10
### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
[[!tag projects/INM7]]
> [[fixed|done]] --[[Joey]]

View file

@ -0,0 +1,10 @@
[[!comment format=mdwn
username="joey"
subject="""comment 10"""
date="2024-10-21T13:46:00Z"
content="""
Ok I decided to allow locking for unauthenticated users by default.
In case that gets abused there is a --unauth-nolocking option which will
result in a 401 when --authenv is used, or a 403 otherwise.
"""]]

View file

@ -127,6 +127,19 @@ convenient way to download the content of any key, by using the path
This can be combined with `--authenv` or `--authenv-http` to allow
anonymous appendonly access, and authenticated remove access.
* `--unauth-nolocking`
By default, when `--unauth-readonly` or `--unauth-appendonly` is used,
unauthenticated users are allowed to lock content in the repository.
This option prevents that.
Locking content prevents it from being dropped from the repository
so it may be that an unauthenticated user abuses that, and this option
can be used in such a situation.
Note that enabling this option will prevent unauthenticated users from
dropping content from their other remotes in some cases.
* `--wideopen`
Gives unauthenticated users full read+write+remove access to the