more groundwork for StatelessOpenPGP
no behavior changes
This commit is contained in:
parent
2fb200a110
commit
dd3e779020
5 changed files with 27 additions and 25 deletions
|
@ -3,7 +3,7 @@
|
||||||
- Currently using gpg; could later be modified to support different
|
- Currently using gpg; could later be modified to support different
|
||||||
- crypto backends if necessary.
|
- 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.
|
- Licensed under the GNU AGPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
@ -43,6 +43,7 @@ import Control.Monad.IO.Class
|
||||||
|
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
import qualified Utility.Gpg as Gpg
|
import qualified Utility.Gpg as Gpg
|
||||||
|
import qualified Utility.StatelessOpenPGP as SOP
|
||||||
import Types.Crypto
|
import Types.Crypto
|
||||||
import Types.Remote
|
import Types.Remote
|
||||||
import Types.Key
|
import Types.Key
|
||||||
|
@ -195,7 +196,6 @@ readBytes a h = liftIO (L.hGetContents h) >>= a
|
||||||
readBytesStrictly :: (MonadIO m) => (S.ByteString -> m a) -> Reader m a
|
readBytesStrictly :: (MonadIO m) => (S.ByteString -> m a) -> Reader m a
|
||||||
readBytesStrictly a h = liftIO (S.hGetContents h) >>= a
|
readBytesStrictly a h = liftIO (S.hGetContents h) >>= a
|
||||||
|
|
||||||
|
|
||||||
{- Runs a Feeder action, that generates content that is symmetrically
|
{- Runs a Feeder action, that generates content that is symmetrically
|
||||||
- encrypted with the Cipher (unless it is empty, in which case
|
- encrypted with the Cipher (unless it is empty, in which case
|
||||||
- public-key encryption is used) using the given gpg options, and then
|
- public-key encryption is used) using the given gpg options, and then
|
||||||
|
|
|
@ -158,18 +158,18 @@ parseMac (Just (Proposed s)) = case readMac s of
|
||||||
encryptionSetup :: RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, EncryptionIsSetup)
|
encryptionSetup :: RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, EncryptionIsSetup)
|
||||||
encryptionSetup c gc = do
|
encryptionSetup c gc = do
|
||||||
pc <- either giveup return $ parseEncryptionConfig c
|
pc <- either giveup return $ parseEncryptionConfig c
|
||||||
cmd <- gpgCmd <$> Annex.getGitConfig
|
gpgcmd <- gpgCmd <$> Annex.getGitConfig
|
||||||
maybe (genCipher pc cmd) (updateCipher pc cmd) (extractCipher pc)
|
maybe (genCipher pc gpgcmd) (updateCipher pc gpgcmd) (extractCipher pc)
|
||||||
where
|
where
|
||||||
-- The type of encryption
|
-- The type of encryption
|
||||||
encryption = parseEncryptionMethod (fromProposedAccepted <$> M.lookup encryptionField c) c
|
encryption = parseEncryptionMethod (fromProposedAccepted <$> M.lookup encryptionField c) c
|
||||||
-- Generate a new cipher, depending on the chosen encryption scheme
|
-- 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 NoneEncryption -> return (c, NoEncryption)
|
||||||
Right SharedEncryption -> encsetup $ genSharedCipher cmd
|
Right SharedEncryption -> encsetup $ genSharedCipher gpgcmd
|
||||||
Right HybridEncryption -> encsetup $ genEncryptedCipher cmd (pc, gc) key Hybrid
|
Right HybridEncryption -> encsetup $ genEncryptedCipher gpgcmd (pc, gc) key Hybrid
|
||||||
Right PubKeyEncryption -> encsetup $ genEncryptedCipher cmd (pc, gc) key PubKey
|
Right PubKeyEncryption -> encsetup $ genEncryptedCipher gpgcmd (pc, gc) key PubKey
|
||||||
Right SharedPubKeyEncryption -> encsetup $ genSharedPubKeyCipher cmd key
|
Right SharedPubKeyEncryption -> encsetup $ genSharedPubKeyCipher gpgcmd key
|
||||||
Left err -> giveup err
|
Left err -> giveup err
|
||||||
key = maybe (giveup "Specify keyid=...") fromProposedAccepted $
|
key = maybe (giveup "Specify keyid=...") fromProposedAccepted $
|
||||||
M.lookup (Accepted "keyid") c
|
M.lookup (Accepted "keyid") c
|
||||||
|
@ -177,13 +177,13 @@ encryptionSetup c gc = do
|
||||||
maybe [] (\k -> [(False,fromProposedAccepted k)]) (M.lookup (Accepted "keyid-") c)
|
maybe [] (\k -> [(False,fromProposedAccepted k)]) (M.lookup (Accepted "keyid-") c)
|
||||||
cannotchange = giveup "Cannot set encryption type of existing remotes."
|
cannotchange = giveup "Cannot set encryption type of existing remotes."
|
||||||
-- Update an existing cipher if possible.
|
-- Update an existing cipher if possible.
|
||||||
updateCipher pc cmd v = case v of
|
updateCipher pc gpgcmd v = case v of
|
||||||
SharedCipher _ | encryption == Right SharedEncryption ->
|
SharedCipher _ | encryption == Right SharedEncryption ->
|
||||||
return (c', EncryptionIsSetup)
|
return (c', EncryptionIsSetup)
|
||||||
EncryptedCipher _ variant _ | sameasencryption variant ->
|
EncryptedCipher _ variant _ | sameasencryption variant ->
|
||||||
use "encryption update" $ updateCipherKeyIds cmd (pc, gc) newkeys v
|
use "encryption update" $ updateCipherKeyIds gpgcmd (pc, gc) newkeys v
|
||||||
SharedPubKeyCipher _ _ ->
|
SharedPubKeyCipher _ _ ->
|
||||||
use "encryption update" $ updateCipherKeyIds cmd (pc, gc) newkeys v
|
use "encryption update" $ updateCipherKeyIds gpgcmd (pc, gc) newkeys v
|
||||||
_ -> cannotchange
|
_ -> cannotchange
|
||||||
sameasencryption variant = case encryption of
|
sameasencryption variant = case encryption of
|
||||||
Right HybridEncryption -> variant == Hybrid
|
Right HybridEncryption -> variant == Hybrid
|
||||||
|
@ -236,8 +236,8 @@ remoteCipher' c gc = case extractCipher c of
|
||||||
(go cachev encipher)
|
(go cachev encipher)
|
||||||
where
|
where
|
||||||
go cachev encipher cache = do
|
go cachev encipher cache = do
|
||||||
cmd <- gpgCmd <$> Annex.getGitConfig
|
gpgcmd <- gpgCmd <$> Annex.getGitConfig
|
||||||
cipher <- liftIO $ decryptCipher cmd (c, gc) encipher
|
cipher <- liftIO $ decryptCipher gpgcmd (c, gc) encipher
|
||||||
liftIO $ atomically $ putTMVar cachev $
|
liftIO $ atomically $ putTMVar cachev $
|
||||||
M.insert encipher cipher cache
|
M.insert encipher cipher cache
|
||||||
return $ Just (cipher, encipher)
|
return $ Just (cipher, encipher)
|
||||||
|
|
2
Test.hs
2
Test.hs
|
@ -1835,7 +1835,7 @@ test_sop_crypto = do
|
||||||
case filter (\(k, _) -> k == ck) gc of
|
case filter (\(k, _) -> k == ck) gc of
|
||||||
[] -> noop
|
[] -> noop
|
||||||
((_, sopcmd):_) -> go $
|
((_, sopcmd):_) -> go $
|
||||||
Utility.StatelessOpenPGP.SopCmd $
|
Utility.StatelessOpenPGP.SOPCmd $
|
||||||
Git.Types.fromConfigValue sopcmd
|
Git.Types.fromConfigValue sopcmd
|
||||||
where
|
where
|
||||||
ck = fromString "annex.shared-sop-command"
|
ck = fromString "annex.shared-sop-command"
|
||||||
|
|
|
@ -47,6 +47,7 @@ import Types.View
|
||||||
import Config.DynamicConfig
|
import Config.DynamicConfig
|
||||||
import Utility.HumanTime
|
import Utility.HumanTime
|
||||||
import Utility.Gpg (GpgCmd, mkGpgCmd)
|
import Utility.Gpg (GpgCmd, mkGpgCmd)
|
||||||
|
import Utility.StatelessOpenPGP (SOPCmd(..))
|
||||||
import Utility.ThreadScheduler (Seconds(..))
|
import Utility.ThreadScheduler (Seconds(..))
|
||||||
import Utility.Url (Scheme, mkScheme)
|
import Utility.Url (Scheme, mkScheme)
|
||||||
|
|
||||||
|
@ -372,7 +373,7 @@ data RemoteGitConfig = RemoteGitConfig
|
||||||
, remoteAnnexRsyncTransport :: [String]
|
, remoteAnnexRsyncTransport :: [String]
|
||||||
, remoteAnnexGnupgOptions :: [String]
|
, remoteAnnexGnupgOptions :: [String]
|
||||||
, remoteAnnexGnupgDecryptOptions :: [String]
|
, remoteAnnexGnupgDecryptOptions :: [String]
|
||||||
, remoteAnnexSharedSOPCommand :: Maybe String
|
, remoteAnnexSharedSOPCommand :: Maybe SOPCmd
|
||||||
, remoteAnnexSharedSOPProfile :: Maybe String
|
, remoteAnnexSharedSOPProfile :: Maybe String
|
||||||
, remoteAnnexRsyncUrl :: Maybe String
|
, remoteAnnexRsyncUrl :: Maybe String
|
||||||
, remoteAnnexBupRepo :: Maybe String
|
, remoteAnnexBupRepo :: Maybe String
|
||||||
|
@ -441,7 +442,8 @@ extractRemoteGitConfig r remotename = do
|
||||||
, remoteAnnexRsyncTransport = getoptions "rsync-transport"
|
, remoteAnnexRsyncTransport = getoptions "rsync-transport"
|
||||||
, remoteAnnexGnupgOptions = getoptions "gnupg-options"
|
, remoteAnnexGnupgOptions = getoptions "gnupg-options"
|
||||||
, remoteAnnexGnupgDecryptOptions = getoptions "gnupg-decrypt-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"
|
, remoteAnnexSharedSOPProfile = notempty $ getmaybe "shared-sop-profile"
|
||||||
, remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl"
|
, remoteAnnexRsyncUrl = notempty $ getmaybe "rsyncurl"
|
||||||
, remoteAnnexBupRepo = getmaybe "buprepo"
|
, remoteAnnexBupRepo = getmaybe "buprepo"
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{-# LANGUAGE CPP, OverloadedStrings #-}
|
{-# LANGUAGE CPP, OverloadedStrings #-}
|
||||||
|
|
||||||
module Utility.StatelessOpenPGP (
|
module Utility.StatelessOpenPGP (
|
||||||
SopCmd(..),
|
SOPCmd(..),
|
||||||
SopSubCmd,
|
SopSubCmd,
|
||||||
Password,
|
Password,
|
||||||
Profile,
|
Profile,
|
||||||
|
@ -34,7 +34,7 @@ import Control.Monad.IO.Class
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
|
|
||||||
{- The command to run, eq sqop. -}
|
{- The command to run, eq sqop. -}
|
||||||
newtype SopCmd = SopCmd { unSopCmd :: String }
|
newtype SOPCmd = SOPCmd { unSOPCmd :: String }
|
||||||
|
|
||||||
{- The subcommand to run eg encrypt. -}
|
{- The subcommand to run eg encrypt. -}
|
||||||
type SopSubCmd = String
|
type SopSubCmd = String
|
||||||
|
@ -67,7 +67,7 @@ newtype EmptyDirectory = EmptyDirectory FilePath
|
||||||
{- Encrypt using symmetric encryption with the specified password. -}
|
{- Encrypt using symmetric encryption with the specified password. -}
|
||||||
encryptSymmetric
|
encryptSymmetric
|
||||||
:: (MonadIO m, MonadMask m)
|
:: (MonadIO m, MonadMask m)
|
||||||
=> SopCmd
|
=> SOPCmd
|
||||||
-> Password
|
-> Password
|
||||||
-> EmptyDirectory
|
-> EmptyDirectory
|
||||||
-> Maybe Profile
|
-> Maybe Profile
|
||||||
|
@ -91,7 +91,7 @@ encryptSymmetric sopcmd password emptydirectory mprofile armoring feeder reader
|
||||||
{- Deccrypt using symmetric encryption with the specified password. -}
|
{- Deccrypt using symmetric encryption with the specified password. -}
|
||||||
decryptSymmetric
|
decryptSymmetric
|
||||||
:: (MonadIO m, MonadMask m)
|
:: (MonadIO m, MonadMask m)
|
||||||
=> SopCmd
|
=> SOPCmd
|
||||||
-> Password
|
-> Password
|
||||||
-> EmptyDirectory
|
-> EmptyDirectory
|
||||||
-> (Handle -> IO ())
|
-> (Handle -> IO ())
|
||||||
|
@ -101,7 +101,7 @@ decryptSymmetric sopcmd password emptydirectory feeder reader =
|
||||||
feedRead sopcmd "decrypt" [] password emptydirectory feeder reader
|
feedRead sopcmd "decrypt" [] password emptydirectory feeder reader
|
||||||
|
|
||||||
{- Test a value round-trips through symmetric encryption and decryption. -}
|
{- 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 $
|
test_encrypt_decrypt_Symmetric a b password armoring v = catchBoolIO $
|
||||||
withTmpDir "test" $ \d -> do
|
withTmpDir "test" $ \d -> do
|
||||||
let ed = EmptyDirectory d
|
let ed = EmptyDirectory d
|
||||||
|
@ -120,7 +120,7 @@ test_encrypt_decrypt_Symmetric a b password armoring v = catchBoolIO $
|
||||||
- Note that the reader must fully consume its input before returning. -}
|
- Note that the reader must fully consume its input before returning. -}
|
||||||
feedRead
|
feedRead
|
||||||
:: (MonadIO m, MonadMask m)
|
:: (MonadIO m, MonadMask m)
|
||||||
=> SopCmd
|
=> SOPCmd
|
||||||
-> SopSubCmd
|
-> SopSubCmd
|
||||||
-> [CommandParam]
|
-> [CommandParam]
|
||||||
-> Password
|
-> Password
|
||||||
|
@ -165,14 +165,14 @@ feedRead cmd subcmd params password emptydirectory feeder reader = do
|
||||||
{- Like feedRead, but without password. -}
|
{- Like feedRead, but without password. -}
|
||||||
feedRead'
|
feedRead'
|
||||||
:: (MonadIO m, MonadMask m)
|
:: (MonadIO m, MonadMask m)
|
||||||
=> SopCmd
|
=> SOPCmd
|
||||||
-> SopSubCmd
|
-> SopSubCmd
|
||||||
-> [CommandParam]
|
-> [CommandParam]
|
||||||
-> Maybe EmptyDirectory
|
-> Maybe EmptyDirectory
|
||||||
-> (Handle -> IO ())
|
-> (Handle -> IO ())
|
||||||
-> (Handle -> m a)
|
-> (Handle -> m a)
|
||||||
-> 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))
|
let p = (proc cmd (subcmd:toCommand params))
|
||||||
{ std_in = CreatePipe
|
{ std_in = CreatePipe
|
||||||
, std_out = CreatePipe
|
, std_out = CreatePipe
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue