Added annex.gnupg-decrypt-options and remote.<name>.annex-gnupg-decrypt-options, which are passed to gpg when it's decrypting data.

The naming is unofrtunately not consistent, but the gnupg-options
were only used for encrypting, and it's too late to change that.

It would be nice to have a third setting that is always passed to gnupg,
but ~/.gnupg/options can be used to specify such global options when really
needed.
This commit is contained in:
Joey Hess 2016-05-10 13:03:56 -04:00
parent 5f1c316b0c
commit 3f1aaa84c5
Failed to extract signature
8 changed files with 61 additions and 20 deletions

View file

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

View file

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

View file

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

View file

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

3
debian/changelog vendored
View file

@ -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.<name>.annex-gnupg-decrypt-options, which are passed to gpg
when it's decrypting data.
-- Joey Hess <id@joeyh.name> Thu, 28 Apr 2016 13:17:04 -0400

View file

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

View file

@ -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.
"""]]

View file

@ -1189,15 +1189,22 @@ Here are all the supported configuration settings.
* `remote.<name>.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.<name>.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.