- Currently using gpg; could later be modified to support different
- crypto backends if necessary.
-
- - Copyright 2011-2023 Joey Hess <id@joeyh.name>
+ - Copyright 2011-2024 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
import Annex.Common
import qualified Utility.Gpg as Gpg
+import qualified Utility.StatelessOpenPGP as SOP
import Types.Crypto
import Types.Remote
import Types.Key
readBytesStrictly :: (MonadIO m) => (S.ByteString -> m a) -> Reader m a
readBytesStrictly a h = liftIO (S.hGetContents h) >>= a
-
{- Runs a Feeder action, that generates content that is symmetrically
- encrypted with the Cipher (unless it is empty, in which case
- public-key encryption is used) using the given gpg options, and then
encryptionSetup :: RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, EncryptionIsSetup)
encryptionSetup c gc = do
pc <- either giveup return $ parseEncryptionConfig c
- cmd <- gpgCmd <$> Annex.getGitConfig
- maybe (genCipher pc cmd) (updateCipher pc cmd) (extractCipher pc)
+ gpgcmd <- gpgCmd <$> Annex.getGitConfig
+ maybe (genCipher pc gpgcmd) (updateCipher pc gpgcmd) (extractCipher pc)
where
-- The type of encryption
encryption = parseEncryptionMethod (fromProposedAccepted <$> M.lookup encryptionField c) c
-- Generate a new cipher, depending on the chosen encryption scheme
- genCipher pc cmd = case encryption of
+ genCipher pc gpgcmd = case encryption of
Right NoneEncryption -> return (c, NoEncryption)
- Right SharedEncryption -> encsetup $ genSharedCipher cmd
- Right HybridEncryption -> encsetup $ genEncryptedCipher cmd (pc, gc) key Hybrid
- Right PubKeyEncryption -> encsetup $ genEncryptedCipher cmd (pc, gc) key PubKey
- Right SharedPubKeyEncryption -> encsetup $ genSharedPubKeyCipher cmd key
+ Right SharedEncryption -> encsetup $ genSharedCipher gpgcmd
+ Right HybridEncryption -> encsetup $ genEncryptedCipher gpgcmd (pc, gc) key Hybrid
+ Right PubKeyEncryption -> encsetup $ genEncryptedCipher gpgcmd (pc, gc) key PubKey
+ Right SharedPubKeyEncryption -> encsetup $ genSharedPubKeyCipher gpgcmd key
Left err -> giveup err
key = maybe (giveup "Specify keyid=...") fromProposedAccepted $
M.lookup (Accepted "keyid") c
maybe [] (\k -> [(False,fromProposedAccepted k)]) (M.lookup (Accepted "keyid-") c)
cannotchange = giveup "Cannot set encryption type of existing remotes."
-- Update an existing cipher if possible.
- updateCipher pc cmd v = case v of
+ updateCipher pc gpgcmd v = case v of
SharedCipher _ | encryption == Right SharedEncryption ->
return (c', EncryptionIsSetup)
EncryptedCipher _ variant _ | sameasencryption variant ->
- use "encryption update" $ updateCipherKeyIds cmd (pc, gc) newkeys v
+ use "encryption update" $ updateCipherKeyIds gpgcmd (pc, gc) newkeys v
SharedPubKeyCipher _ _ ->
- use "encryption update" $ updateCipherKeyIds cmd (pc, gc) newkeys v
+ use "encryption update" $ updateCipherKeyIds gpgcmd (pc, gc) newkeys v
_ -> cannotchange
sameasencryption variant = case encryption of
Right HybridEncryption -> variant == Hybrid
(go cachev encipher)
where
go cachev encipher cache = do
- cmd <- gpgCmd <$> Annex.getGitConfig
- cipher <- liftIO $ decryptCipher cmd (c, gc) encipher
+ gpgcmd <- gpgCmd <$> Annex.getGitConfig
+ cipher <- liftIO $ decryptCipher gpgcmd (c, gc) encipher
liftIO $ atomically $ putTMVar cachev $
M.insert encipher cipher cache
return $ Just (cipher, encipher)
case filter (\(k, _) -> k == ck) gc of
[] -> noop
((_, sopcmd):_) -> go $
- Utility.StatelessOpenPGP.SopCmd $
+ Utility.StatelessOpenPGP.SOPCmd $
Git.Types.fromConfigValue sopcmd
where
ck = fromString "annex.shared-sop-command"
import Config.DynamicConfig
import Utility.HumanTime
import Utility.Gpg (GpgCmd, mkGpgCmd)
+import Utility.StatelessOpenPGP (SOPCmd(..))
import Utility.ThreadScheduler (Seconds(..))
import Utility.Url (Scheme, mkScheme)
, remoteAnnexRsyncTransport :: [String]
, remoteAnnexGnupgOptions :: [String]
, remoteAnnexGnupgDecryptOptions :: [String]
- , remoteAnnexSharedSOPCommand :: Maybe String
+ , remoteAnnexSharedSOPCommand :: Maybe SOPCmd
, remoteAnnexSharedSOPProfile :: Maybe String
, remoteAnnexRsyncUrl :: Maybe String
, remoteAnnexBupRepo :: Maybe String
, remoteAnnexRsyncTransport = getoptions "rsync-transport"
, remoteAnnexGnupgOptions = getoptions "gnupg-options"
, remoteAnnexGnupgDecryptOptions = getoptions "gnupg-decrypt-options"
- , remoteAnnexSharedSOPCommand = notempty $ getmaybe "shared-sop-command"
+ , remoteAnnexSharedSOPCommand = SOPCmd <$>
+ notempty (getmaybe "shared-sop-command")
, remoteAnnexSharedSOPProfile = notempty $ getmaybe "shared-sop-profile"
, remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl"
, remoteAnnexBupRepo = getmaybe "buprepo"
{-# LANGUAGE CPP, OverloadedStrings #-}
module Utility.StatelessOpenPGP (
- SopCmd(..),
+ SOPCmd(..),
SopSubCmd,
Password,
Profile,
import qualified Data.ByteString as B
{- The command to run, eq sqop. -}
-newtype SopCmd = SopCmd { unSopCmd :: String }
+newtype SOPCmd = SOPCmd { unSOPCmd :: String }
{- The subcommand to run eg encrypt. -}
type SopSubCmd = String
{- Encrypt using symmetric encryption with the specified password. -}
encryptSymmetric
:: (MonadIO m, MonadMask m)
- => SopCmd
+ => SOPCmd
-> Password
-> EmptyDirectory
-> Maybe Profile
{- Deccrypt using symmetric encryption with the specified password. -}
decryptSymmetric
:: (MonadIO m, MonadMask m)
- => SopCmd
+ => SOPCmd
-> Password
-> EmptyDirectory
-> (Handle -> IO ())
feedRead sopcmd "decrypt" [] password emptydirectory feeder reader
{- Test a value round-trips through symmetric encryption and decryption. -}
-test_encrypt_decrypt_Symmetric :: SopCmd -> SopCmd -> Password -> Armoring -> B.ByteString -> IO Bool
+test_encrypt_decrypt_Symmetric :: SOPCmd -> SOPCmd -> Password -> Armoring -> B.ByteString -> IO Bool
test_encrypt_decrypt_Symmetric a b password armoring v = catchBoolIO $
withTmpDir "test" $ \d -> do
let ed = EmptyDirectory d
- Note that the reader must fully consume its input before returning. -}
feedRead
:: (MonadIO m, MonadMask m)
- => SopCmd
+ => SOPCmd
-> SopSubCmd
-> [CommandParam]
-> Password
{- Like feedRead, but without password. -}
feedRead'
:: (MonadIO m, MonadMask m)
- => SopCmd
+ => SOPCmd
-> SopSubCmd
-> [CommandParam]
-> Maybe EmptyDirectory
-> (Handle -> IO ())
-> (Handle -> m a)
-> m a
-feedRead' (SopCmd cmd) subcmd params med feeder reader = do
+feedRead' (SOPCmd cmd) subcmd params med feeder reader = do
let p = (proc cmd (subcmd:toCommand params))
{ std_in = CreatePipe
, std_out = CreatePipe