summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-12-08 16:01:46 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-12-08 16:01:46 -0400
commite3f1568e0ff7dc872f3782115c74b9e7d8c291b2 (patch)
treedab3d9797fe1ff96d22baf88c45d9e66b827c905
parent2568beee07928d1bd462d631372881f146b190ee (diff)
Fix caching of decrypted ciphers, which failed when drop had to check multiple different encrypted special remotes.
-rw-r--r--Annex.hs5
-rw-r--r--Remote/Helper/Encryptable.hs23
-rw-r--r--Types/Crypto.hs2
-rw-r--r--debian/changelog2
-rw-r--r--doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn7
5 files changed, 27 insertions, 12 deletions
diff --git a/Annex.hs b/Annex.hs
index 6d245a92d..d8d9c63b4 100644
--- a/Annex.hs
+++ b/Annex.hs
@@ -36,6 +36,7 @@ import Types.BranchState
import Types.TrustLevel
import Types.UUID
import qualified Utility.Matcher
+import qualified Data.Map as M
-- git-annex's monad
newtype Annex a = Annex { runAnnex :: StateT AnnexState IO a }
@@ -70,7 +71,7 @@ data AnnexState = AnnexState
, limit :: Either [Utility.Matcher.Token (FilePath -> Annex Bool)] (Utility.Matcher.Matcher (FilePath -> Annex Bool))
, forcetrust :: [(UUID, TrustLevel)]
, trustmap :: Maybe TrustMap
- , cipher :: Maybe Cipher
+ , ciphers :: M.Map EncryptedCipher Cipher
}
newState :: Git.Repo -> AnnexState
@@ -93,7 +94,7 @@ newState gitrepo = AnnexState
, limit = Left []
, forcetrust = []
, trustmap = Nothing
- , cipher = Nothing
+ , ciphers = M.empty
}
{- Create and returns an Annex state object for the specified git repo. -}
diff --git a/Remote/Helper/Encryptable.hs b/Remote/Helper/Encryptable.hs
index 85d269a21..99f48fe7b 100644
--- a/Remote/Helper/Encryptable.hs
+++ b/Remote/Helper/Encryptable.hs
@@ -61,19 +61,22 @@ encryptableRemote c storeKeyEncrypted retrieveKeyFileEncrypted r =
withkey a k = cip k >>= maybe (a k) (a . snd)
cip = cipherKey c
-{- Gets encryption Cipher. The decrypted Cipher is cached in the Annex
+{- Gets encryption Cipher. The decrypted Ciphers are cached in the Annex
- state. -}
remoteCipher :: RemoteConfig -> Annex (Maybe Cipher)
-remoteCipher c = maybe expensive cached =<< Annex.getState Annex.cipher
+remoteCipher c = go $ extractCipher c
where
- cached cipher = return $ Just cipher
- expensive = case extractCipher c of
- Nothing -> return Nothing
- Just encipher -> do
- showNote "gpg"
- cipher <- liftIO $ decryptCipher c encipher
- Annex.changeState (\s -> s { Annex.cipher = Just cipher })
- return $ Just cipher
+ go Nothing = return Nothing
+ go (Just encipher) = do
+ cache <- Annex.getState Annex.ciphers
+ case M.lookup encipher cache of
+ Just cipher -> return $ Just cipher
+ Nothing -> decrypt encipher cache
+ decrypt encipher cache = do
+ showNote "gpg"
+ cipher <- liftIO $ decryptCipher c encipher
+ Annex.changeState (\s -> s { Annex.ciphers = M.insert encipher cipher cache })
+ return $ Just cipher
{- Gets encryption Cipher, and encrypted version of Key. -}
cipherKey :: Maybe RemoteConfig -> Key -> Annex (Maybe (Cipher, Key))
diff --git a/Types/Crypto.hs b/Types/Crypto.hs
index a9d3dddc5..29a4cd099 100644
--- a/Types/Crypto.hs
+++ b/Types/Crypto.hs
@@ -11,5 +11,7 @@ module Types.Crypto where
newtype Cipher = Cipher String
data EncryptedCipher = EncryptedCipher String KeyIds
+ deriving (Ord, Eq)
newtype KeyIds = KeyIds [String]
+ deriving (Ord, Eq)
diff --git a/debian/changelog b/debian/changelog
index 588ea6d5b..04e911672 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,6 +5,8 @@ git-annex (3.20111204) UNRELEASED; urgency=low
* Prevent key names from containing newlines.
* add: If interrupted, add can leave files converted to symlinks but not
yet added to git. Running the add again will now clean up this situtation.
+ * Fix caching of decrypted ciphers, which failed when drop had to check
+ multiple different encrypted special remotes.
-- Joey Hess <joeyh@debian.org> Sun, 04 Dec 2011 12:22:37 -0400
diff --git a/doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn b/doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn
index af1fed2ee..0dad8856e 100644
--- a/doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn
+++ b/doc/bugs/git-annex_losing_rsync_remotes_with_encryption_enabled.mdwn
@@ -92,3 +92,10 @@ git annex copy --to remoteserver -d tools/md5_sha1_utility.exe
> Running: sh ["-c","rsync --quiet 'REMOVED_HOST:annex/work/1F/PQ/'\"'\"'GPGHMACSHA1--ff075e57f649300c5698e346be74fb6e22d70e35/GPGHMACSHA1--ff075e57f649300c5698e346be74fb6e22d70e35'\"'\"'' 2>/dev/null"]
And yes, only the hash *annex copy* is checking for exists on the remote side. --[[gebi]]
+
+> Ok, this is due to too aggressive caching of the decrypted cipher
+> for a remote. When dopping, it decrypts localserver's cipher,
+> caches it, and then when checking remoteserver it says hey,
+> here's an already decrypted cipher -- it must be the right one!
+>
+> Problem reproduced here, and fixed. [[done]] --[[Joey]]