* Bump aws build dependency to 0.24.1.
* stack.yaml: Update to lts-24.2.
* Removed support for git versions older than 2.22.
+ * Don't allow the type of encryption of an existing special remote to be
+ changed. Fixes reversion introduced in version 7.20191230.
-- Joey Hess <id@joeyh.name> Wed, 30 Jul 2025 13:45:42 -0400
(remoteAnnexAndroidSerial gc)
adbSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-adbSetup _ mu _ c gc = do
+adbSetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
-- verify configuration
serial <- getserial =<< enumerateAdbConnected
let c' = M.insert androidserialField (Proposed (fromAndroidSerial serial)) c
- (c'', _encsetup) <- encryptionSetup c' gc
+ (c'', _encsetup) <- encryptionSetup ss c' gc
ok <- adbShellBool serial
[Param "mkdir", Param "-p", File (fromAndroidPath adir)]
buprepo = fromMaybe (giveup "missing buprepo") $ remoteAnnexBupRepo gc
bupSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-bupSetup _ mu _ c gc = do
+bupSetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
-- verify configuration is sane
let buprepo = maybe (giveup "Specify buprepo=") fromProposedAccepted $
M.lookup buprepoField c
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
-- bup init will create the repository.
-- (If the repository already exists, bup init again appears safe.)
ddarrepo = maybe (giveup "missing ddarrepo") (DdarRepo gc) (remoteAnnexDdarRepo gc)
ddarSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-ddarSetup _ mu _ c gc = do
+ddarSetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
-- verify configuration is sane
let ddarrepo = maybe (giveup "Specify ddarrepo=") fromProposedAccepted $
M.lookup ddarrepoField c
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
-- The ddarrepo is stored in git config, as well as this repo's
-- persistent state, so it can vary between hosts.
(remoteAnnexDirectory gc)
directorySetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-directorySetup _ mu _ c gc = do
+directorySetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
-- verify configuration is sane
let dir = maybe (giveup "Specify directory=") fromProposedAccepted $
absdir <- liftIO $ absPath (toOsPath dir)
liftIO $ unlessM (doesDirectoryExist absdir) $
giveup $ "Directory does not exist: " ++ fromOsPath absdir
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
-- The directory is stored in git config, not in this remote's
-- persistent state, so it can vary between hosts.
(remoteAnnexExternalType gc)
externalSetup :: Maybe ExternalProgram -> Maybe (String, String) -> SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-externalSetup externalprogram setgitconfig _ mu _ c gc = do
+externalSetup externalprogram setgitconfig ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
pc <- either giveup return $ parseRemoteConfig c (lenientRemoteConfigParser externalprogram)
let readonlyconfig = getRemoteConfigValue readonlyField pc == Just True
then "readonly"
else fromMaybe (giveup "Specify externaltype=") $
getRemoteConfigValue externaltypeField pc
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
c'' <- if readonlyconfig
then do
unsupportedUrl = giveup "unsupported repo url for gcrypt"
gCryptSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-gCryptSetup _ mu _ c gc = go $ fromProposedAccepted <$> M.lookup gitRepoField c
+gCryptSetup ss mu _ c gc = go $ fromProposedAccepted <$> M.lookup gitRepoField c
where
remotename = fromJust (lookupName c)
go Nothing = giveup "Specify gitrepo="
go (Just gitrepo) = do
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
let url = Git.GCrypt.urlPrefix ++ gitrepo
rs <- Annex.getGitRemotes
mySetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
pc <- either giveup return . parseRemoteConfig c' =<< configParser remote c'
let failinitunlessforced msg = case ss of
Init -> unlessM (Annex.getRead Annex.force) (giveup msg)
glacierSetup' ss u mcreds c gc
glacierSetup' :: SetupStage -> UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
glacierSetup' ss u mcreds c gc = do
- (c', encsetup) <- encryptionSetup (c `M.union` defaults) gc
+ (c', encsetup) <- encryptionSetup ss (c `M.union` defaults) gc
pc <- either giveup return . parseRemoteConfig c'
=<< configParser remote c'
c'' <- setRemoteCredPair ss encsetup pc gc (AWS.creds u) mcreds
- an encryption key, or not encrypt. An encrypted cipher is created, or is
- updated to be accessible to an additional encryption key. Or the user
- could opt to use a shared cipher, which is stored unencrypted. -}
-encryptionSetup :: RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, EncryptionIsSetup)
-encryptionSetup c gc = do
+encryptionSetup :: SetupStage -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, EncryptionIsSetup)
+encryptionSetup setupstage c gc = do
+ checkallowedchange
pc <- either giveup return $ parseEncryptionConfig c
gpgcmd <- gpgCmd <$> Annex.getGitConfig
maybe (genCipher pc gpgcmd) (updateCipher pc gpgcmd) (extractCipher pc)
-- public-key encryption, hence we leave it on newer
-- remotes (while being backward-compatible).
(map Accepted ["keyid", "keyid+", "keyid-", "highRandomQuality"])
+ oldpc = either (const Nothing) Just $ parseEncryptionConfig $
+ case setupstage of
+ Init -> mempty
+ Enable oldc -> oldc
+ AutoEnable oldc -> oldc
+ checkallowedchange = case oldpc of
+ Nothing -> return ()
+ Just oldpc' -> case extractCipher oldpc' of
+ Nothing -> req NoneEncryption
+ Just (EncryptedCipher _ Hybrid _) -> req HybridEncryption
+ Just (EncryptedCipher _ PubKey _) -> req PubKeyEncryption
+ Just (SharedCipher _) -> req SharedEncryption
+ Just (SharedPubKeyCipher _ _) -> req SharedPubKeyEncryption
+ where
+ req v
+ | encryption /= Right v = cannotchange
+ | otherwise = return ()
data CipherPurpose t = CipherAllPurpose t | CipherOnlyCreds t
hooktype = fromMaybe (giveup "missing hooktype") $ remoteAnnexHookType gc
hookSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-hookSetup _ mu _ c gc = do
+hookSetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
let hooktype = maybe (giveup "Specify hooktype=") fromProposedAccepted $
M.lookup hooktypeField c
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
gitConfigSpecialRemote u c' [("hooktype", hooktype)]
return (c', u)
httpAlsoSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
httpAlsoSetup _ Nothing _ _ _ =
giveup "Must use --sameas when initializing a httpalso remote."
-httpAlsoSetup _ (Just u) _ c gc = do
+httpAlsoSetup ss (Just u) _ c gc = do
_url <- maybe (giveup "Specify url=")
(return . fromProposedAccepted)
(M.lookup urlField c)
c' <- if isJust (M.lookup encryptionField c)
- then fst <$> encryptionSetup c gc
+ then fst <$> encryptionSetup ss c gc
else pure c
gitConfigSpecialRemote u c' [("httpalso", "true")]
return (c', u)
setupremote r = do
let c' = M.insert remoteUUIDField
(Proposed (fromUUID (uuid r) :: String)) c
- (c'', encsetup) <- encryptionSetup c' gc
+ (c'', encsetup) <- encryptionSetup setupstage c' gc
verifyencryptionok encsetup r
u <- maybe (liftIO genUUID) return mu
-- get autoenabled later, or need to be
-- manually enabled.
_ -> do
- (c', _) <- encryptionSetup c gc
+ (c', _) <- encryptionSetup setupstage c gc
u <- maybe (liftIO genUUID) return mu
gitConfigSpecialRemote u c' [ ("mask", "true") ]
return (c', u)
fromNull as xs = if null xs then as else xs
rsyncSetup :: SetupStage -> Maybe UUID -> Maybe CredPair -> RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, UUID)
-rsyncSetup _ mu _ c gc = do
+rsyncSetup ss mu _ c gc = do
u <- maybe (liftIO genUUID) return mu
-- verify configuration is sane
let url = maybe (giveup "Specify rsyncurl=") fromProposedAccepted $
M.lookup rsyncUrlField c
- (c', _encsetup) <- encryptionSetup c gc
+ (c', _encsetup) <- encryptionSetup ss c gc
-- The rsyncurl is stored in git config, not only in this remote's
-- persistent state, so it can vary between hosts.
return (fullconfig, u)
defaulthost = do
- (c', encsetup) <- encryptionSetup (c `M.union` defaults) gc
+ (c', encsetup) <- encryptionSetup ss (c `M.union` defaults) gc
pc <- either giveup return . parseRemoteConfig c'
=<< configParser remote c'
c'' <- if isAnonymous pc
url <- maybe (giveup "Specify url=")
(return . fromProposedAccepted)
(M.lookup urlField c)
- (c', encsetup) <- encryptionSetup c gc
+ (c', encsetup) <- encryptionSetup ss c gc
pc <- either giveup return . parseRemoteConfig c' =<< configParser remote c'
creds <- maybe (getCreds pc gc u) (return . Just) mcreds
case ss of
| PubKeyEncryption
| SharedPubKeyEncryption
| HybridEncryption
- deriving (Typeable, Eq)
+ deriving (Typeable, Eq, Show)
-- A base-64 encoded random value used for encryption.
-- XXX ideally, this would be a locked memory region
| SharedCipher ByteString
| SharedPubKeyCipher ByteString KeyIds
deriving (Ord, Eq)
+
data EncryptedCipherVariant = Hybrid | PubKey
deriving (Ord, Eq)
enableremote d (encryption setup) (encryption key stored in git repository) ok
(recording state in git...)
-This config change should not be allowed.
+This config change should not be allowed. This is a reversion,
+probably introduced around [[!commit 71f78fe45dc91dbef0bedd79b33d6a9fed85704d]]
Also, the new onlyencryptcreds=yes setting can passed to enableremote,
which changes a previously encrypted remote to not use encryption for the