diff --git a/Creds.hs b/Creds.hs index 8cc7eed1a9..6a2eaafd5e 100644 --- a/Creds.hs +++ b/Creds.hs @@ -94,7 +94,7 @@ getRemoteCredPair c storage = maybe fromcache (return . Just) =<< fromenv Nothing -> return Nothing fromenccreds enccreds cipher storablecipher = do cmd <- gpgCmd <$> Annex.getGitConfig - mcreds <- liftIO $ catchMaybeIO $ decrypt cmd cipher + mcreds <- liftIO $ catchMaybeIO $ decrypt cmd (getGpgDecParams c) cipher (feedBytes $ L.pack $ fromB64 enccreds) (readBytes $ return . L.unpack) case mcreds of diff --git a/Crypto.hs b/Crypto.hs index 64b7f69d41..1b08771882 100644 --- a/Crypto.hs +++ b/Crypto.hs @@ -29,6 +29,7 @@ module Crypto ( encrypt, decrypt, getGpgEncParams, + getGpgDecParams, prop_HmacSha1WithCipher_sane ) where @@ -184,10 +185,12 @@ encrypt cmd params cipher = case cipher of {- Runs a Feeder action, that generates content that is decrypted with the - Cipher (or using a private key if the Cipher is empty), and read by the - Reader action. -} -decrypt :: (MonadIO m, MonadMask m) => Gpg.GpgCmd -> Cipher -> Feeder -> Reader m a -> m a -decrypt cmd cipher = case cipher of - Cipher{} -> Gpg.feedRead cmd [Param "--decrypt"] $ cipherPassphrase cipher - MacOnlyCipher{} -> Gpg.pipeLazy cmd [Param "--decrypt"] +decrypt :: (MonadIO m, MonadMask m) => Gpg.GpgCmd -> [CommandParam] -> Cipher -> Feeder -> Reader m a -> m a +decrypt cmd params cipher = case cipher of + Cipher{} -> Gpg.feedRead cmd params' $ cipherPassphrase cipher + MacOnlyCipher{} -> Gpg.pipeLazy cmd params' + where + params' = Param "--decrypt" : params macWithCipher :: Mac -> Cipher -> String -> String macWithCipher mac c = macWithCipher' mac (cipherMac c) @@ -200,26 +203,30 @@ prop_HmacSha1WithCipher_sane = known_good == macWithCipher' HmacSha1 "foo" "bar" where known_good = "46b4ec586117154dacd49d664e5d63fdc88efb51" -{- Return some options suitable for GnuPG encryption, symmetric or not. -} -class LensGpgEncParams a where getGpgEncParams :: a -> [CommandParam] +class LensGpgEncParams a where + {- Parameters for encrypting. -} + getGpgEncParams :: a -> [CommandParam] + {- Parameters for decrypting. -} + getGpgDecParams :: a -> [CommandParam] {- Extract the GnuPG options from a pair of a Remote Config and a Remote - Git Config. -} instance LensGpgEncParams (RemoteConfig, RemoteGitConfig) where getGpgEncParams (c,gc) = map Param (remoteAnnexGnupgOptions gc) ++ getGpgEncParams c - where + getGpgDecParams (c,gc) = map Param (remoteAnnexGnupgDecryptOptions gc) ++ getGpgDecParams c {- Extract the GnuPG options from a Remote Config, ignoring any - git config settings. (Which is ok if the remote is just being set up - - and so doesn't have any.) - - - - If the remote is configured to use public-key encryption, - - look up the recipient keys and add them to the option list.-} + - and so doesn't have any.) -} instance LensGpgEncParams RemoteConfig where + {- If the remote is configured to use public-key encryption, + - look up the recipient keys and add them to the option list. -} getGpgEncParams c = case M.lookup "encryption" c of Just "pubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $ M.lookup "cipherkeys" c _ -> [] + getGpgDecParams _ = [] {- Extract the GnuPG options from a Remote. -} instance LensGpgEncParams (RemoteA a) where getGpgEncParams r = getGpgEncParams (config r, gitconfig r) + getGpgDecParams r = getGpgDecParams (config r, gitconfig r) diff --git a/Remote/Helper/Special.hs b/Remote/Helper/Special.hs index f9b5deae42..cf0524dc45 100644 --- a/Remote/Helper/Special.hs +++ b/Remote/Helper/Special.hs @@ -178,7 +178,8 @@ specialRemote' cfg c preparestorer prepareretriever prepareremover preparecheckp } cip = cipherKey c isencrypted = isJust (extractCipher c) - gpgopts = getGpgEncParams encr + gpgencopts = getGpgEncParams encr + gpgdecopts = getGpgDecParams encr safely a = catchNonAsync a (\e -> warning (show e) >> return False) @@ -200,7 +201,7 @@ specialRemote' cfg c preparestorer prepareretriever prepareremover preparecheckp storechunk (Just (cipher, enck)) storer k content p = do cmd <- gpgCmd <$> Annex.getGitConfig withBytes content $ \b -> - encrypt cmd gpgopts cipher (feedBytes b) $ + encrypt cmd gpgencopts cipher (feedBytes b) $ readBytes $ \encb -> storer (enck k) (ByteContent encb) p @@ -210,7 +211,7 @@ specialRemote' cfg c preparestorer prepareretriever prepareremover preparecheckp where go (Just retriever) = displayprogress p k $ \p' -> retrieveChunks retriever (uuid baser) chunkconfig - enck k dest p' (sink dest enc) + enck k dest p' (sink dest enc gpgdecopts) go Nothing = return False enck = maybe id snd enc @@ -245,23 +246,24 @@ specialRemote' cfg c preparestorer prepareretriever prepareremover preparecheckp sink :: FilePath -> Maybe (Cipher, EncKey) + -> [CommandParam] -> Maybe Handle -> Maybe MeterUpdate -> ContentSource -> Annex Bool -sink dest enc mh mp content = do +sink dest enc gpgdecopts mh mp content = do case (enc, mh, content) of (Nothing, Nothing, FileContent f) | f == dest -> noop | otherwise -> liftIO $ moveFile f dest (Just (cipher, _), _, ByteContent b) -> do cmd <- gpgCmd <$> Annex.getGitConfig - decrypt cmd cipher (feedBytes b) $ + decrypt cmd gpgdecopts cipher (feedBytes b) $ readBytes write (Just (cipher, _), _, FileContent f) -> do cmd <- gpgCmd <$> Annex.getGitConfig withBytes content $ \b -> - decrypt cmd cipher (feedBytes b) $ + decrypt cmd gpgdecopts cipher (feedBytes b) $ readBytes write liftIO $ nukeFile f (Nothing, _, FileContent f) -> do diff --git a/Types/GitConfig.hs b/Types/GitConfig.hs index b5e3d795e4..33f102e1d4 100644 --- a/Types/GitConfig.hs +++ b/Types/GitConfig.hs @@ -162,6 +162,7 @@ data RemoteGitConfig = RemoteGitConfig , remoteAnnexRsyncDownloadOptions :: [String] , remoteAnnexRsyncTransport :: [String] , remoteAnnexGnupgOptions :: [String] + , remoteAnnexGnupgDecryptOptions :: [String] , remoteAnnexRsyncUrl :: Maybe String , remoteAnnexBupRepo :: Maybe String , remoteAnnexTahoe :: Maybe FilePath @@ -196,6 +197,7 @@ extractRemoteGitConfig r remotename = RemoteGitConfig , remoteAnnexRsyncUploadOptions = getoptions "rsync-upload-options" , remoteAnnexRsyncTransport = getoptions "rsync-transport" , remoteAnnexGnupgOptions = getoptions "gnupg-options" + , remoteAnnexGnupgDecryptOptions = getoptions "gnupg-decrypt-options" , remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl" , remoteAnnexBupRepo = getmaybe "buprepo" , remoteAnnexTahoe = getmaybe "tahoe" diff --git a/debian/changelog b/debian/changelog index 55c46079ac..6c5bc0e30c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,6 +20,9 @@ git-annex (6.20160420) UNRELEASED; urgency=medium * version: Display OS version and architecture too. * Propigate GIT_DIR and GIT_WORK_TREE environment to external special remotes. + * Added annex.gnupg-decrypt-options and + remote..annex-gnupg-decrypt-options, which are passed to gpg + when it's decrypting data. -- Joey Hess Thu, 28 Apr 2016 13:17:04 -0400 diff --git a/doc/bugs/annex.gnupg-options_not_used_by_assistant.mdwn b/doc/bugs/annex.gnupg-options_not_used_by_assistant.mdwn index 3141ca06ac..9ad3f533e0 100644 --- a/doc/bugs/annex.gnupg-options_not_used_by_assistant.mdwn +++ b/doc/bugs/annex.gnupg-options_not_used_by_assistant.mdwn @@ -78,3 +78,4 @@ gpg: cannot open `/dev/tty': Device not configured ### 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) +> added annex.gnupg-decrypt-options; [[done]] --[[Joey]] diff --git a/doc/bugs/annex.gnupg-options_not_used_by_assistant/comment_1_724e68d2980fd28fa39707692bf22520._comment b/doc/bugs/annex.gnupg-options_not_used_by_assistant/comment_1_724e68d2980fd28fa39707692bf22520._comment new file mode 100644 index 0000000000..31a1897f65 --- /dev/null +++ b/doc/bugs/annex.gnupg-options_not_used_by_assistant/comment_1_724e68d2980fd28fa39707692bf22520._comment @@ -0,0 +1,19 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 1""" + date="2016-05-10T16:30:04Z" + content=""" +annex.gnupg-options is only used when encrypting content, not when +decrypting. And it has to decrypt the shared encryption key first, +so that's why the error shows it was running gpg with --decrypt. + +Probable, even if you were able to make it always run gpg with +--no-tty, it wouldn't help, because gpg needs to prompt for a passphrase. + +There should be a way to get gnupg to use gpg-agent, which would let it +prompt for your password with a dialog box, rather than trying to prompt on +the terminal. That would work better with the webapp. + +I do think there ought to be a config setting that allows passing options +to gpg when it's decrypting things, and so I'll add something. +"""]] diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn index 236912df6e..955f67629f 100644 --- a/doc/git-annex.mdwn +++ b/doc/git-annex.mdwn @@ -1189,15 +1189,22 @@ Here are all the supported configuration settings. * `remote..annex-gnupg-options` - Options to pass to GnuPG for symmetric encryption. For instance, to + Options to pass to GnuPG when it's encrypting data. For instance, to use the AES cipher with a 256 bits key and disable compression, set it to `--cipher-algo AES256 --compress-algo none`. (These options take precedence over the default GnuPG configuration, which is otherwise used.) +* `remote..annex-gnupg-decrypt-options` + + Options to pass to GnuPG when it's decrypting data. (These options take + precedence over the default GnuPG configuration, which is otherwise + used.) + * `annex.ssh-options`, `annex.rsync-options`, `annex.rsync-upload-options`, `annex.rsync-download-options`, - `annex.bup-split-options`, `annex.gnupg-options` + `annex.bup-split-options`, `annex.gnupg-options`, + `annex.gnupg-decrypt-options` Default options to use if a remote does not have more specific options as described above.