2011-04-17 04:40:23 +00:00
|
|
|
{- common functions for encryptable remotes
|
2011-04-16 17:25:27 +00:00
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2011 Joey Hess <id@joeyh.name>
|
2011-04-16 17:25:27 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2011-04-16 17:25:27 +00:00
|
|
|
-}
|
|
|
|
|
glacier, S3: Fix bug that caused embedded creds to not be encypted using the remote's key.
encryptionSetup must be called before setRemoteCredPair. Otherwise,
the RemoteConfig doesn't have the cipher in it, and so no cipher is used to
encrypt the embedded creds.
This is a security fix for non-shared encryption methods!
For encryption=shared, there's no security problem, just an
inconsistentency in whether the embedded creds are encrypted.
This is very important to get right, so used some types to help ensure that
setRemoteCredPair is only run after encryptionSetup. Note that the external
special remote bypasses the type safety, since creds can be set after the
initial remote config, if the external special remote program requests it.
Also note that IA remotes never use encryption, so encryptionSetup is not
run for them at all, and again the type safety is bypassed.
This leaves two open questions:
1. What to do about S3 and glacier remotes that were set up
using encryption=pubkey/hybrid with embedcreds?
Such a git repo has a security hole embedded in it, and this needs to be
communicated to the user. Is the changelog enough?
2. enableremote won't work in such a repo, because git-annex will
try to decrypt the embedded creds, which are not encrypted, so fails.
This needs to be dealt with, especially for ecryption=shared repos,
which are not really broken, just inconsistently configured.
Noticing that problem for encryption=shared is what led to commit
fbdeeeed5fa276d94be587c8916d725eddcaf546, which tried to
fix the problem by not decrypting the embedded creds.
This commit was sponsored by Josh Taylor.
2014-09-18 21:07:17 +00:00
|
|
|
module Remote.Helper.Encryptable (
|
|
|
|
EncryptionIsSetup,
|
|
|
|
encryptionSetup,
|
|
|
|
noEncryptionUsed,
|
|
|
|
encryptionAlreadySetup,
|
|
|
|
remoteCipher,
|
2014-09-18 21:58:03 +00:00
|
|
|
remoteCipher',
|
glacier, S3: Fix bug that caused embedded creds to not be encypted using the remote's key.
encryptionSetup must be called before setRemoteCredPair. Otherwise,
the RemoteConfig doesn't have the cipher in it, and so no cipher is used to
encrypt the embedded creds.
This is a security fix for non-shared encryption methods!
For encryption=shared, there's no security problem, just an
inconsistentency in whether the embedded creds are encrypted.
This is very important to get right, so used some types to help ensure that
setRemoteCredPair is only run after encryptionSetup. Note that the external
special remote bypasses the type safety, since creds can be set after the
initial remote config, if the external special remote program requests it.
Also note that IA remotes never use encryption, so encryptionSetup is not
run for them at all, and again the type safety is bypassed.
This leaves two open questions:
1. What to do about S3 and glacier remotes that were set up
using encryption=pubkey/hybrid with embedcreds?
Such a git repo has a security hole embedded in it, and this needs to be
communicated to the user. Is the changelog enough?
2. enableremote won't work in such a repo, because git-annex will
try to decrypt the embedded creds, which are not encrypted, so fails.
This needs to be dealt with, especially for ecryption=shared repos,
which are not really broken, just inconsistently configured.
Noticing that problem for encryption=shared is what led to commit
fbdeeeed5fa276d94be587c8916d725eddcaf546, which tried to
fix the problem by not decrypting the embedded creds.
This commit was sponsored by Josh Taylor.
2014-09-18 21:07:17 +00:00
|
|
|
embedCreds,
|
|
|
|
cipherKey,
|
|
|
|
extractCipher,
|
2017-09-04 16:40:33 +00:00
|
|
|
isEncrypted,
|
2014-10-21 18:36:09 +00:00
|
|
|
describeEncryption,
|
glacier, S3: Fix bug that caused embedded creds to not be encypted using the remote's key.
encryptionSetup must be called before setRemoteCredPair. Otherwise,
the RemoteConfig doesn't have the cipher in it, and so no cipher is used to
encrypt the embedded creds.
This is a security fix for non-shared encryption methods!
For encryption=shared, there's no security problem, just an
inconsistentency in whether the embedded creds are encrypted.
This is very important to get right, so used some types to help ensure that
setRemoteCredPair is only run after encryptionSetup. Note that the external
special remote bypasses the type safety, since creds can be set after the
initial remote config, if the external special remote program requests it.
Also note that IA remotes never use encryption, so encryptionSetup is not
run for them at all, and again the type safety is bypassed.
This leaves two open questions:
1. What to do about S3 and glacier remotes that were set up
using encryption=pubkey/hybrid with embedcreds?
Such a git repo has a security hole embedded in it, and this needs to be
communicated to the user. Is the changelog enough?
2. enableremote won't work in such a repo, because git-annex will
try to decrypt the embedded creds, which are not encrypted, so fails.
This needs to be dealt with, especially for ecryption=shared repos,
which are not really broken, just inconsistently configured.
Noticing that problem for encryption=shared is what led to commit
fbdeeeed5fa276d94be587c8916d725eddcaf546, which tried to
fix the problem by not decrypting the embedded creds.
This commit was sponsored by Josh Taylor.
2014-09-18 21:07:17 +00:00
|
|
|
) where
|
2011-04-16 17:25:27 +00:00
|
|
|
|
|
|
|
import qualified Data.Map as M
|
2015-05-07 22:07:13 +00:00
|
|
|
import qualified "sandi" Codec.Binary.Base64 as B64
|
|
|
|
import qualified Data.ByteString as B
|
2011-04-16 17:25:27 +00:00
|
|
|
|
2016-01-20 20:36:33 +00:00
|
|
|
import Annex.Common
|
2011-06-02 01:56:04 +00:00
|
|
|
import Types.Remote
|
2018-10-10 15:07:49 +00:00
|
|
|
import Config
|
2011-04-16 17:25:27 +00:00
|
|
|
import Crypto
|
2013-03-29 16:06:02 +00:00
|
|
|
import Types.Crypto
|
2011-04-16 22:22:52 +00:00
|
|
|
import qualified Annex
|
2011-04-16 17:25:27 +00:00
|
|
|
|
glacier, S3: Fix bug that caused embedded creds to not be encypted using the remote's key.
encryptionSetup must be called before setRemoteCredPair. Otherwise,
the RemoteConfig doesn't have the cipher in it, and so no cipher is used to
encrypt the embedded creds.
This is a security fix for non-shared encryption methods!
For encryption=shared, there's no security problem, just an
inconsistentency in whether the embedded creds are encrypted.
This is very important to get right, so used some types to help ensure that
setRemoteCredPair is only run after encryptionSetup. Note that the external
special remote bypasses the type safety, since creds can be set after the
initial remote config, if the external special remote program requests it.
Also note that IA remotes never use encryption, so encryptionSetup is not
run for them at all, and again the type safety is bypassed.
This leaves two open questions:
1. What to do about S3 and glacier remotes that were set up
using encryption=pubkey/hybrid with embedcreds?
Such a git repo has a security hole embedded in it, and this needs to be
communicated to the user. Is the changelog enough?
2. enableremote won't work in such a repo, because git-annex will
try to decrypt the embedded creds, which are not encrypted, so fails.
This needs to be dealt with, especially for ecryption=shared repos,
which are not really broken, just inconsistently configured.
Noticing that problem for encryption=shared is what led to commit
fbdeeeed5fa276d94be587c8916d725eddcaf546, which tried to
fix the problem by not decrypting the embedded creds.
This commit was sponsored by Josh Taylor.
2014-09-18 21:07:17 +00:00
|
|
|
-- Used to ensure that encryption has been set up before trying to
|
|
|
|
-- eg, store creds in the remote config that would need to use the
|
|
|
|
-- encryption setup.
|
|
|
|
data EncryptionIsSetup = EncryptionIsSetup | NoEncryption
|
|
|
|
|
|
|
|
-- Remotes that don't use encryption can use this instead of
|
|
|
|
-- encryptionSetup.
|
|
|
|
noEncryptionUsed :: EncryptionIsSetup
|
|
|
|
noEncryptionUsed = NoEncryption
|
|
|
|
|
|
|
|
-- Using this avoids the type-safe check, so you'd better be sure
|
|
|
|
-- of what you're doing.
|
|
|
|
encryptionAlreadySetup :: EncryptionIsSetup
|
|
|
|
encryptionAlreadySetup = EncryptionIsSetup
|
|
|
|
|
2011-04-16 17:25:27 +00:00
|
|
|
{- Encryption setup for a remote. The user must specify whether to use
|
|
|
|
- an encryption key, or not encrypt. An encrypted cipher is created, or is
|
2012-04-29 18:02:18 +00:00
|
|
|
- updated to be accessible to an additional encryption key. Or the user
|
|
|
|
- could opt to use a shared cipher, which is stored unencrypted. -}
|
2016-05-23 21:27:15 +00:00
|
|
|
encryptionSetup :: RemoteConfig -> RemoteGitConfig -> Annex (RemoteConfig, EncryptionIsSetup)
|
|
|
|
encryptionSetup c gc = do
|
2015-09-09 22:06:49 +00:00
|
|
|
cmd <- gpgCmd <$> Annex.getGitConfig
|
|
|
|
maybe (genCipher cmd) (updateCipher cmd) (extractCipher c)
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
2013-08-28 02:24:14 +00:00
|
|
|
-- The type of encryption
|
|
|
|
encryption = M.lookup "encryption" c
|
|
|
|
-- Generate a new cipher, depending on the chosen encryption scheme
|
2015-09-09 22:06:49 +00:00
|
|
|
genCipher cmd = case encryption of
|
2017-09-04 16:40:33 +00:00
|
|
|
_ | hasEncryptionConfig c -> cannotchange
|
glacier, S3: Fix bug that caused embedded creds to not be encypted using the remote's key.
encryptionSetup must be called before setRemoteCredPair. Otherwise,
the RemoteConfig doesn't have the cipher in it, and so no cipher is used to
encrypt the embedded creds.
This is a security fix for non-shared encryption methods!
For encryption=shared, there's no security problem, just an
inconsistentency in whether the embedded creds are encrypted.
This is very important to get right, so used some types to help ensure that
setRemoteCredPair is only run after encryptionSetup. Note that the external
special remote bypasses the type safety, since creds can be set after the
initial remote config, if the external special remote program requests it.
Also note that IA remotes never use encryption, so encryptionSetup is not
run for them at all, and again the type safety is bypassed.
This leaves two open questions:
1. What to do about S3 and glacier remotes that were set up
using encryption=pubkey/hybrid with embedcreds?
Such a git repo has a security hole embedded in it, and this needs to be
communicated to the user. Is the changelog enough?
2. enableremote won't work in such a repo, because git-annex will
try to decrypt the embedded creds, which are not encrypted, so fails.
This needs to be dealt with, especially for ecryption=shared repos,
which are not really broken, just inconsistently configured.
Noticing that problem for encryption=shared is what led to commit
fbdeeeed5fa276d94be587c8916d725eddcaf546, which tried to
fix the problem by not decrypting the embedded creds.
This commit was sponsored by Josh Taylor.
2014-09-18 21:07:17 +00:00
|
|
|
Just "none" -> return (c, NoEncryption)
|
2016-05-10 20:50:31 +00:00
|
|
|
Just "shared" -> encsetup $ genSharedCipher cmd
|
2013-09-04 23:09:56 +00:00
|
|
|
-- hybrid encryption is the default when a keyid is
|
2014-10-09 19:09:26 +00:00
|
|
|
-- specified but no encryption
|
2013-09-04 23:09:56 +00:00
|
|
|
_ | maybe (M.member "keyid" c) (== "hybrid") encryption ->
|
2016-05-23 21:48:15 +00:00
|
|
|
encsetup $ genEncryptedCipher cmd (c, gc) key Hybrid
|
|
|
|
Just "pubkey" -> encsetup $ genEncryptedCipher cmd (c, gc) key PubKey
|
2016-05-10 20:50:31 +00:00
|
|
|
Just "sharedpubkey" -> encsetup $ genSharedPubKeyCipher cmd key
|
2016-11-16 01:29:54 +00:00
|
|
|
_ -> giveup $ "Specify " ++ intercalate " or "
|
2013-09-01 18:12:00 +00:00
|
|
|
(map ("encryption=" ++)
|
2016-05-10 20:50:31 +00:00
|
|
|
["none","shared","hybrid","pubkey", "sharedpubkey"])
|
2013-09-01 18:12:00 +00:00
|
|
|
++ "."
|
2017-02-11 09:38:49 +00:00
|
|
|
key = fromMaybe (giveup "Specify keyid=...") $ M.lookup "keyid" c
|
2013-08-28 02:24:14 +00:00
|
|
|
newkeys = maybe [] (\k -> [(True,k)]) (M.lookup "keyid+" c) ++
|
|
|
|
maybe [] (\k -> [(False,k)]) (M.lookup "keyid-" c)
|
2016-11-16 01:29:54 +00:00
|
|
|
cannotchange = giveup "Cannot set encryption type of existing remotes."
|
2013-08-28 02:24:14 +00:00
|
|
|
-- Update an existing cipher if possible.
|
2015-09-09 22:06:49 +00:00
|
|
|
updateCipher cmd v = case v of
|
glacier, S3: Fix bug that caused embedded creds to not be encypted using the remote's key.
encryptionSetup must be called before setRemoteCredPair. Otherwise,
the RemoteConfig doesn't have the cipher in it, and so no cipher is used to
encrypt the embedded creds.
This is a security fix for non-shared encryption methods!
For encryption=shared, there's no security problem, just an
inconsistentency in whether the embedded creds are encrypted.
This is very important to get right, so used some types to help ensure that
setRemoteCredPair is only run after encryptionSetup. Note that the external
special remote bypasses the type safety, since creds can be set after the
initial remote config, if the external special remote program requests it.
Also note that IA remotes never use encryption, so encryptionSetup is not
run for them at all, and again the type safety is bypassed.
This leaves two open questions:
1. What to do about S3 and glacier remotes that were set up
using encryption=pubkey/hybrid with embedcreds?
Such a git repo has a security hole embedded in it, and this needs to be
communicated to the user. Is the changelog enough?
2. enableremote won't work in such a repo, because git-annex will
try to decrypt the embedded creds, which are not encrypted, so fails.
This needs to be dealt with, especially for ecryption=shared repos,
which are not really broken, just inconsistently configured.
Noticing that problem for encryption=shared is what led to commit
fbdeeeed5fa276d94be587c8916d725eddcaf546, which tried to
fix the problem by not decrypting the embedded creds.
This commit was sponsored by Josh Taylor.
2014-09-18 21:07:17 +00:00
|
|
|
SharedCipher _ | maybe True (== "shared") encryption -> return (c', EncryptionIsSetup)
|
2013-09-05 02:18:33 +00:00
|
|
|
EncryptedCipher _ variant _
|
2016-05-23 21:27:15 +00:00
|
|
|
| maybe True (== if variant == Hybrid then "hybrid" else "pubkey") encryption -> do
|
|
|
|
use "encryption update" $ updateCipherKeyIds cmd (c, gc) newkeys v
|
2016-05-10 20:50:31 +00:00
|
|
|
SharedPubKeyCipher _ _ ->
|
2016-05-23 21:27:15 +00:00
|
|
|
use "encryption update" $ updateCipherKeyIds cmd (c, gc) newkeys v
|
2013-09-01 18:12:00 +00:00
|
|
|
_ -> cannotchange
|
2016-05-10 20:50:31 +00:00
|
|
|
encsetup a = use "encryption setup" . a =<< highRandomQuality
|
2012-11-11 04:51:07 +00:00
|
|
|
use m a = do
|
2013-05-18 23:30:52 +00:00
|
|
|
showNote m
|
2012-11-11 04:51:07 +00:00
|
|
|
cipher <- liftIO a
|
2016-05-11 20:09:39 +00:00
|
|
|
showNote (describeCipher cipher)
|
2016-05-10 20:50:31 +00:00
|
|
|
return (storeCipher cipher c', EncryptionIsSetup)
|
2013-04-06 20:14:57 +00:00
|
|
|
highRandomQuality =
|
|
|
|
(&&) (maybe True ( /= "false") $ M.lookup "highRandomQuality" c)
|
|
|
|
<$> fmap not (Annex.getState Annex.fast)
|
2013-09-01 18:12:00 +00:00
|
|
|
c' = foldr M.delete c
|
2014-10-09 19:09:26 +00:00
|
|
|
-- git-annex used to remove 'encryption' as well, since
|
|
|
|
-- it was redundant; we now need to keep it for
|
|
|
|
-- public-key encryption, hence we leave it on newer
|
|
|
|
-- remotes (while being backward-compatible).
|
2013-09-01 18:12:00 +00:00
|
|
|
[ "keyid", "keyid+", "keyid-", "highRandomQuality" ]
|
2011-04-16 22:22:52 +00:00
|
|
|
|
2016-05-23 21:27:15 +00:00
|
|
|
remoteCipher :: RemoteConfig -> RemoteGitConfig -> Annex (Maybe Cipher)
|
|
|
|
remoteCipher c gc = fmap fst <$> remoteCipher' c gc
|
2014-09-18 21:58:03 +00:00
|
|
|
|
2011-12-08 20:01:46 +00:00
|
|
|
{- Gets encryption Cipher. The decrypted Ciphers are cached in the Annex
|
2011-05-01 18:05:10 +00:00
|
|
|
- state. -}
|
2016-05-23 21:27:15 +00:00
|
|
|
remoteCipher' :: RemoteConfig -> RemoteGitConfig -> Annex (Maybe (Cipher, StorableCipher))
|
|
|
|
remoteCipher' c gc = go $ extractCipher c
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
|
|
|
go Nothing = return Nothing
|
|
|
|
go (Just encipher) = do
|
|
|
|
cache <- Annex.getState Annex.ciphers
|
|
|
|
case M.lookup encipher cache of
|
2014-09-18 21:58:03 +00:00
|
|
|
Just cipher -> return $ Just (cipher, encipher)
|
2012-11-18 19:27:44 +00:00
|
|
|
Nothing -> do
|
2015-09-09 22:06:49 +00:00
|
|
|
cmd <- gpgCmd <$> Annex.getGitConfig
|
2016-05-23 21:27:15 +00:00
|
|
|
cipher <- liftIO $ decryptCipher cmd (c, gc) encipher
|
2012-11-18 19:27:44 +00:00
|
|
|
Annex.changeState (\s -> s { Annex.ciphers = M.insert encipher cipher cache })
|
2014-09-18 21:58:03 +00:00
|
|
|
return $ Just (cipher, encipher)
|
2011-05-01 18:05:10 +00:00
|
|
|
|
2012-11-19 21:32:58 +00:00
|
|
|
{- Checks if the remote's config allows storing creds in the remote's config.
|
|
|
|
-
|
|
|
|
- embedcreds=yes allows this, and embedcreds=no prevents it.
|
|
|
|
-
|
|
|
|
- If not set, the default is to only store creds when it's surely safe:
|
2016-05-10 20:50:31 +00:00
|
|
|
- When gpg encryption is used and the creds are encrypted using it.
|
|
|
|
- Not when a shared cipher is used.
|
2012-11-19 21:32:58 +00:00
|
|
|
-}
|
|
|
|
embedCreds :: RemoteConfig -> Bool
|
2018-10-10 15:07:49 +00:00
|
|
|
embedCreds c = case yesNo =<< M.lookup "embedcreds" c of
|
|
|
|
Just v -> v
|
|
|
|
Nothing -> isJust (M.lookup "cipherkeys" c) && isJust (M.lookup "cipher" c)
|
2012-09-26 16:06:44 +00:00
|
|
|
|
2014-07-27 00:14:09 +00:00
|
|
|
{- Gets encryption Cipher, and key encryptor. -}
|
2016-05-23 21:27:15 +00:00
|
|
|
cipherKey :: RemoteConfig -> RemoteGitConfig -> Annex (Maybe (Cipher, EncKey))
|
|
|
|
cipherKey c gc = fmap make <$> remoteCipher c gc
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
2014-07-27 00:14:09 +00:00
|
|
|
make ciphertext = (ciphertext, encryptKey mac ciphertext)
|
2013-03-29 16:06:02 +00:00
|
|
|
mac = fromMaybe defaultMac $ M.lookup "mac" c >>= readMac
|
2012-04-29 18:31:34 +00:00
|
|
|
|
|
|
|
{- Stores an StorableCipher in a remote's configuration. -}
|
2016-05-10 20:50:31 +00:00
|
|
|
storeCipher :: StorableCipher -> RemoteConfig -> RemoteConfig
|
|
|
|
storeCipher cip = case cip of
|
|
|
|
(SharedCipher t) -> addcipher t
|
|
|
|
(EncryptedCipher t _ ks) -> addcipher t . storekeys ks "cipherkeys"
|
|
|
|
(SharedPubKeyCipher t ks) -> addcipher t . storekeys ks "pubkeys"
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
2016-05-10 20:50:31 +00:00
|
|
|
addcipher t = M.insert "cipher" (toB64bs t)
|
|
|
|
storekeys (KeyIds l) n = M.insert n (intercalate "," l)
|
2012-04-29 18:31:34 +00:00
|
|
|
|
|
|
|
{- Extracts an StorableCipher from a remote's configuration. -}
|
|
|
|
extractCipher :: RemoteConfig -> Maybe StorableCipher
|
2013-09-01 18:12:00 +00:00
|
|
|
extractCipher c = case (M.lookup "cipher" c,
|
2016-05-10 20:50:31 +00:00
|
|
|
M.lookup "cipherkeys" c <|> M.lookup "pubkeys" c,
|
2013-09-01 18:12:00 +00:00
|
|
|
M.lookup "encryption" c) of
|
|
|
|
(Just t, Just ks, encryption) | maybe True (== "hybrid") encryption ->
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
Just $ EncryptedCipher (fromB64bs t) Hybrid (readkeys ks)
|
2013-09-01 18:12:00 +00:00
|
|
|
(Just t, Just ks, Just "pubkey") ->
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
Just $ EncryptedCipher (fromB64bs t) PubKey (readkeys ks)
|
2016-05-10 20:50:31 +00:00
|
|
|
(Just t, Just ks, Just "sharedpubkey") ->
|
|
|
|
Just $ SharedPubKeyCipher (fromB64bs t) (readkeys ks)
|
2013-09-01 18:12:00 +00:00
|
|
|
(Just t, Nothing, encryption) | maybe True (== "shared") encryption ->
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
Just $ SharedCipher (fromB64bs t)
|
2013-09-01 18:12:00 +00:00
|
|
|
_ -> Nothing
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
2017-01-31 22:40:42 +00:00
|
|
|
readkeys = KeyIds . splitc ','
|
2014-10-21 18:36:09 +00:00
|
|
|
|
2017-09-04 16:40:33 +00:00
|
|
|
isEncrypted :: RemoteConfig -> Bool
|
|
|
|
isEncrypted c = case M.lookup "encryption" c of
|
|
|
|
Just "none" -> False
|
|
|
|
Just _ -> True
|
|
|
|
Nothing -> hasEncryptionConfig c
|
|
|
|
|
|
|
|
hasEncryptionConfig :: RemoteConfig -> Bool
|
|
|
|
hasEncryptionConfig c = M.member "cipher" c || M.member "cipherkeys" c || M.member "pubkeys" c
|
|
|
|
|
2014-10-21 18:36:09 +00:00
|
|
|
describeEncryption :: RemoteConfig -> String
|
|
|
|
describeEncryption c = case extractCipher c of
|
2016-05-11 20:09:39 +00:00
|
|
|
Nothing -> "none"
|
|
|
|
Just cip -> nameCipher cip ++ " (" ++ describeCipher cip ++ ")"
|
|
|
|
|
|
|
|
nameCipher :: StorableCipher -> String
|
|
|
|
nameCipher (SharedCipher _) = "shared"
|
|
|
|
nameCipher (EncryptedCipher _ PubKey _) = "pubkey"
|
|
|
|
nameCipher (EncryptedCipher _ Hybrid _) = "hybrid"
|
|
|
|
nameCipher (SharedPubKeyCipher _ _) = "sharedpubkey"
|
2016-05-10 20:50:31 +00:00
|
|
|
|
2016-05-11 20:09:39 +00:00
|
|
|
describeCipher :: StorableCipher -> String
|
2016-05-10 20:50:31 +00:00
|
|
|
describeCipher c = case c of
|
2016-05-11 20:09:39 +00:00
|
|
|
(SharedCipher _) -> "encryption key stored in git repository"
|
|
|
|
(EncryptedCipher _ _ ks) -> showkeys ks
|
|
|
|
(SharedPubKeyCipher _ ks) -> showkeys ks
|
2016-05-10 20:50:31 +00:00
|
|
|
where
|
|
|
|
showkeys (KeyIds { keyIds = ks }) = "to gpg keys: " ++ unwords ks
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
|
|
|
|
{- Not using Utility.Base64 because these "Strings" are really
|
2015-05-07 22:07:13 +00:00
|
|
|
- bags of bytes and that would convert to unicode and not round-trip
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
- cleanly. -}
|
|
|
|
toB64bs :: String -> String
|
2015-05-07 22:07:13 +00:00
|
|
|
toB64bs = w82s . B.unpack . B64.encode . B.pack . s2w8
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
|
|
|
|
fromB64bs :: String -> String
|
2015-05-07 22:07:13 +00:00
|
|
|
fromB64bs s = either (const bad) (w82s . B.unpack) (B64.decode $ B.pack $ s2w8 s)
|
metadata: Fix encoding problem that led to mojibake when storing metadata strings that contained both unicode characters and a space (or '!') character.
The fix is to stop using w82s, which does not properly reconstitute unicode
strings. Instrad, use utf8 bytestring to get the [Word8] to base64. This
passes unicode through perfectly, including any invalid filesystem encoded
characters.
Note that toB64 / fromB64 are also used for creds and cipher
embedding. It would be unfortunate if this change broke those uses.
For cipher embedding, note that ciphers can contain arbitrary bytes (should
really be using ByteString.Char8 there). Testing indicated it's not safe to
use the new fromB64 there; I think that characters were incorrectly
combined.
For credpair embedding, the username or password could contain unicode.
Before, that unicode would fail to round-trip through the b64.
So, I guess this is not going to break any embedded creds that worked
before.
This bug may have affected some creds before, and if so,
this change will not fix old ones, but should fix new ones at least.
2015-03-04 15:16:03 +00:00
|
|
|
where
|
|
|
|
bad = error "bad base64 encoded data"
|