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 Nothing -> return Nothing
fromenccreds enccreds cipher storablecipher = do fromenccreds enccreds cipher storablecipher = do
cmd <- gpgCmd <$> Annex.getGitConfig cmd <- gpgCmd <$> Annex.getGitConfig
mcreds <- liftIO $ catchMaybeIO $ decrypt cmd cipher mcreds <- liftIO $ catchMaybeIO $ decrypt cmd (getGpgDecParams c) cipher
(feedBytes $ L.pack $ fromB64 enccreds) (feedBytes $ L.pack $ fromB64 enccreds)
(readBytes $ return . L.unpack) (readBytes $ return . L.unpack)
case mcreds of case mcreds of

View file

@ -29,6 +29,7 @@ module Crypto (
encrypt, encrypt,
decrypt, decrypt,
getGpgEncParams, getGpgEncParams,
getGpgDecParams,
prop_HmacSha1WithCipher_sane prop_HmacSha1WithCipher_sane
) where ) where
@ -184,10 +185,12 @@ encrypt cmd params cipher = case cipher of
{- Runs a Feeder action, that generates content that is decrypted with the {- 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 - Cipher (or using a private key if the Cipher is empty), and read by the
- Reader action. -} - Reader action. -}
decrypt :: (MonadIO m, MonadMask m) => Gpg.GpgCmd -> Cipher -> Feeder -> Reader m a -> m a decrypt :: (MonadIO m, MonadMask m) => Gpg.GpgCmd -> [CommandParam] -> Cipher -> Feeder -> Reader m a -> m a
decrypt cmd cipher = case cipher of decrypt cmd params cipher = case cipher of
Cipher{} -> Gpg.feedRead cmd [Param "--decrypt"] $ cipherPassphrase cipher Cipher{} -> Gpg.feedRead cmd params' $ cipherPassphrase cipher
MacOnlyCipher{} -> Gpg.pipeLazy cmd [Param "--decrypt"] MacOnlyCipher{} -> Gpg.pipeLazy cmd params'
where
params' = Param "--decrypt" : params
macWithCipher :: Mac -> Cipher -> String -> String macWithCipher :: Mac -> Cipher -> String -> String
macWithCipher mac c = macWithCipher' mac (cipherMac c) macWithCipher mac c = macWithCipher' mac (cipherMac c)
@ -200,26 +203,30 @@ prop_HmacSha1WithCipher_sane = known_good == macWithCipher' HmacSha1 "foo" "bar"
where where
known_good = "46b4ec586117154dacd49d664e5d63fdc88efb51" known_good = "46b4ec586117154dacd49d664e5d63fdc88efb51"
{- Return some options suitable for GnuPG encryption, symmetric or not. -} class LensGpgEncParams a where
class LensGpgEncParams a where getGpgEncParams :: a -> [CommandParam] {- 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 {- Extract the GnuPG options from a pair of a Remote Config and a Remote
- Git Config. -} - Git Config. -}
instance LensGpgEncParams (RemoteConfig, RemoteGitConfig) where instance LensGpgEncParams (RemoteConfig, RemoteGitConfig) where
getGpgEncParams (c,gc) = map Param (remoteAnnexGnupgOptions gc) ++ getGpgEncParams c 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 {- Extract the GnuPG options from a Remote Config, ignoring any
- git config settings. (Which is ok if the remote is just being set up - git config settings. (Which is ok if the remote is just being set up
- and so doesn't have any.) - 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.-}
instance LensGpgEncParams RemoteConfig where 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 getGpgEncParams c = case M.lookup "encryption" c of
Just "pubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $ M.lookup "cipherkeys" c Just "pubkey" -> Gpg.pkEncTo $ maybe [] (split ",") $ M.lookup "cipherkeys" c
_ -> [] _ -> []
getGpgDecParams _ = []
{- Extract the GnuPG options from a Remote. -} {- Extract the GnuPG options from a Remote. -}
instance LensGpgEncParams (RemoteA a) where instance LensGpgEncParams (RemoteA a) where
getGpgEncParams r = getGpgEncParams (config r, gitconfig r) 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 cip = cipherKey c
isencrypted = isJust (extractCipher c) isencrypted = isJust (extractCipher c)
gpgopts = getGpgEncParams encr gpgencopts = getGpgEncParams encr
gpgdecopts = getGpgDecParams encr
safely a = catchNonAsync a (\e -> warning (show e) >> return False) 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 storechunk (Just (cipher, enck)) storer k content p = do
cmd <- gpgCmd <$> Annex.getGitConfig cmd <- gpgCmd <$> Annex.getGitConfig
withBytes content $ \b -> withBytes content $ \b ->
encrypt cmd gpgopts cipher (feedBytes b) $ encrypt cmd gpgencopts cipher (feedBytes b) $
readBytes $ \encb -> readBytes $ \encb ->
storer (enck k) (ByteContent encb) p storer (enck k) (ByteContent encb) p
@ -210,7 +211,7 @@ specialRemote' cfg c preparestorer prepareretriever prepareremover preparecheckp
where where
go (Just retriever) = displayprogress p k $ \p' -> go (Just retriever) = displayprogress p k $ \p' ->
retrieveChunks retriever (uuid baser) chunkconfig retrieveChunks retriever (uuid baser) chunkconfig
enck k dest p' (sink dest enc) enck k dest p' (sink dest enc gpgdecopts)
go Nothing = return False go Nothing = return False
enck = maybe id snd enc enck = maybe id snd enc
@ -245,23 +246,24 @@ specialRemote' cfg c preparestorer prepareretriever prepareremover preparecheckp
sink sink
:: FilePath :: FilePath
-> Maybe (Cipher, EncKey) -> Maybe (Cipher, EncKey)
-> [CommandParam]
-> Maybe Handle -> Maybe Handle
-> Maybe MeterUpdate -> Maybe MeterUpdate
-> ContentSource -> ContentSource
-> Annex Bool -> Annex Bool
sink dest enc mh mp content = do sink dest enc gpgdecopts mh mp content = do
case (enc, mh, content) of case (enc, mh, content) of
(Nothing, Nothing, FileContent f) (Nothing, Nothing, FileContent f)
| f == dest -> noop | f == dest -> noop
| otherwise -> liftIO $ moveFile f dest | otherwise -> liftIO $ moveFile f dest
(Just (cipher, _), _, ByteContent b) -> do (Just (cipher, _), _, ByteContent b) -> do
cmd <- gpgCmd <$> Annex.getGitConfig cmd <- gpgCmd <$> Annex.getGitConfig
decrypt cmd cipher (feedBytes b) $ decrypt cmd gpgdecopts cipher (feedBytes b) $
readBytes write readBytes write
(Just (cipher, _), _, FileContent f) -> do (Just (cipher, _), _, FileContent f) -> do
cmd <- gpgCmd <$> Annex.getGitConfig cmd <- gpgCmd <$> Annex.getGitConfig
withBytes content $ \b -> withBytes content $ \b ->
decrypt cmd cipher (feedBytes b) $ decrypt cmd gpgdecopts cipher (feedBytes b) $
readBytes write readBytes write
liftIO $ nukeFile f liftIO $ nukeFile f
(Nothing, _, FileContent f) -> do (Nothing, _, FileContent f) -> do

View file

@ -162,6 +162,7 @@ data RemoteGitConfig = RemoteGitConfig
, remoteAnnexRsyncDownloadOptions :: [String] , remoteAnnexRsyncDownloadOptions :: [String]
, remoteAnnexRsyncTransport :: [String] , remoteAnnexRsyncTransport :: [String]
, remoteAnnexGnupgOptions :: [String] , remoteAnnexGnupgOptions :: [String]
, remoteAnnexGnupgDecryptOptions :: [String]
, remoteAnnexRsyncUrl :: Maybe String , remoteAnnexRsyncUrl :: Maybe String
, remoteAnnexBupRepo :: Maybe String , remoteAnnexBupRepo :: Maybe String
, remoteAnnexTahoe :: Maybe FilePath , remoteAnnexTahoe :: Maybe FilePath
@ -196,6 +197,7 @@ extractRemoteGitConfig r remotename = RemoteGitConfig
, remoteAnnexRsyncUploadOptions = getoptions "rsync-upload-options" , remoteAnnexRsyncUploadOptions = getoptions "rsync-upload-options"
, remoteAnnexRsyncTransport = getoptions "rsync-transport" , remoteAnnexRsyncTransport = getoptions "rsync-transport"
, remoteAnnexGnupgOptions = getoptions "gnupg-options" , remoteAnnexGnupgOptions = getoptions "gnupg-options"
, remoteAnnexGnupgDecryptOptions = getoptions "gnupg-decrypt-options"
, remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl" , remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl"
, remoteAnnexBupRepo = getmaybe "buprepo" , remoteAnnexBupRepo = getmaybe "buprepo"
, remoteAnnexTahoe = getmaybe "tahoe" , 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. * version: Display OS version and architecture too.
* Propigate GIT_DIR and GIT_WORK_TREE environment to external special * Propigate GIT_DIR and GIT_WORK_TREE environment to external special
remotes. 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 -- 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) ### 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` * `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 use the AES cipher with a 256 bits key and disable compression, set it
to `--cipher-algo AES256 --compress-algo none`. (These options take to `--cipher-algo AES256 --compress-algo none`. (These options take
precedence over the default GnuPG configuration, which is otherwise precedence over the default GnuPG configuration, which is otherwise
used.) 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.ssh-options`, `annex.rsync-options`,
`annex.rsync-upload-options`, `annex.rsync-download-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 Default options to use if a remote does not have more specific options
as described above. as described above.