packages feed

keysafe 0.20161006 → 0.20161007

raw patch · 17 files changed

+240/−52 lines, 17 filesdep −crypto-random

Dependencies removed: crypto-random

Files

ByteStrings.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+ {- Copyright 2016 Joey Hess <id@joeyh.name>  -  - Licensed under the GNU AGPL version 3 or higher.@@ -6,6 +8,9 @@ module ByteStrings where  import qualified Data.ByteString as B+import qualified Raaz+import Control.Monad+import Data.Word  allByteStringsOfLength :: Int -> [B.ByteString] allByteStringsOfLength = go []@@ -28,3 +33,10 @@ 		| otherwise =  			let (h, t) = B.splitAt n b 			in go (h:cs) t++instance Raaz.Random Word8++randomByteStringOfLength :: Int -> Raaz.SystemPRG -> IO B.ByteString+randomByteStringOfLength n prg = B.pack <$> replicateM n randbyte+  where+	randbyte = Raaz.random prg :: IO Word8
CHANGELOG view
@@ -1,3 +1,15 @@+keysafe (0.20161007) unstable; urgency=medium++  * Check if --store-local directory is writable.+  * Removed dependency on crypto-random.+  * Added a LSB init script, for non-systemd systems.+    (It currently uses Debian's start-stop-daemon, so would need porting+    for other distributions.)+  * /etc/default/keysafe is read by both the systemd service file and the+    init script, and contains configuration for the keysafe server.++ -- Joey Hess <id@joeyh.name>  Thu, 20 Oct 2016 14:44:07 -0400+ keysafe (0.20161006) unstable; urgency=medium    * New --add-storage-directory and --add-server options, which can be used
CmdLine.hs view
@@ -27,7 +27,7 @@ 	, customShareParams :: Maybe ShareParams 	, name :: Maybe Name 	, othername :: Maybe Name-	, preferredStorage :: [Maybe LocalStorageDirectory -> Storage]+	, preferredStorage :: [Maybe LocalStorageDirectory -> IO (Maybe Storage)] 	, serverConfig :: ServerConfig 	, chaffMaxDelay :: Maybe Seconds 	}@@ -132,7 +132,7 @@ 	<|> BackupServer <$> strOption 		( long "backup-server" 		<> metavar "BACKUPDIR"-		<> help "Run on a server, populates the directory with a gpg encrypted backup of all objects stored in the --store-directory. This is designed to be rsynced offsite (with --delete) to back up the a keysafe server with minimal information leakage."+		<> help "Run on a server, populates the directory with a gpg encrypted backup of all objects stored in the --store-directory. This is designed to be rsynced offsite (with --delete) to back up a keysafe server with minimal information leakage." 		) 	<|> RestoreServer <$> strOption 		( long "restore-server"
Encryption.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings, MultiParamTypeClasses, DataKinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}  {- Copyright 2016 Joey Hess <id@joeyh.name>  -@@ -15,8 +14,6 @@ import ByteStrings import Data.Monoid import Data.Maybe-import Data.Word-import Control.Monad import qualified Raaz import qualified Raaz.Cipher.AES as Raaz import qualified Raaz.Cipher.Internal as Raaz@@ -152,12 +149,9 @@ type SaltPrefix = B.ByteString  genRandomSaltPrefix :: Raaz.SystemPRG -> Tunables -> IO SaltPrefix-genRandomSaltPrefix prg tunables = B.pack <$> replicateM n randbyte+genRandomSaltPrefix prg tunables = randomByteStringOfLength n prg   where 	n = randomSaltBytes $ keyEncryptionKeyTunable tunables-	randbyte = Raaz.random prg :: IO Word8--instance Raaz.Random Word8  -- | Make an AES key out of a hash value. --
HTTP/ProofOfWork.hs view
@@ -119,8 +119,6 @@ 	rs <- replicateM 16 (Raaz.random prg :: IO Word8) 	return $ RandomSalt $ T.pack $ concatMap show rs -instance Raaz.Random Word8- class POWIdent p where 	getPOWIdent :: p -> B.ByteString 
INSTALL view
@@ -25,7 +25,7 @@ ## System-wide installation  This installs keysafe in /usr/bin, and includes the man page, -desktop file, autostart file, systemd service file, etc.+desktop file, autostart file, systemd service file, init script, etc.  Start by installing the dependencies as shown in Quick installation. @@ -45,6 +45,6 @@ keysafe user at package install time instead, although it is only used by the keysafe server. -While keysafe ships with a systemd service file, distributions should -not enable it to be started by default. (Or can put it in its own-keysafe-server package.)+While keysafe ships with a systemd service file and an init script,+distributions should not enable it to be started by default.+(Or can put it in its own keysafe-server package.)
Makefile view
@@ -30,6 +30,10 @@ 	install -m 0644 keysafe.1 $(PREFIX)/usr/share/man/man1/keysafe.1 	install -d $(PREFIX)/lib/systemd/system 	install -m 0644 keysafe.service $(PREFIX)/lib/systemd/system/keysafe.service+	install -d $(PREFIX)/etc/init.d+	install -m 0755 keysafe.init $(PREFIX)/etc/init.d/keysafe+	install -d $(PREFIX)/etc/default+	install -m 0644 keysafe.default $(PREFIX)/etc/default/keysafe 	install -d $(PREFIX)/usr/share/applications/ 	install -m 0644 keysafe.desktop $(PREFIX)/usr/share/applications/keysafe.desktop 	install -d $(PREFIX)/etc/xdg/autostart/
Storage.hs view
@@ -16,16 +16,17 @@ import Storage.Network import Servers import Tunables+import ByteStrings import Data.Maybe import Data.List import Data.Monoid import Control.Monad-import Crypto.Random-import System.Random import Control.Concurrent.Thread.Delay import Control.Concurrent.Async import qualified Data.Set as S+import System.Random import System.Random.Shuffle+import qualified Raaz  networkStorageLocations :: Maybe LocalStorageDirectory -> StorageLocations networkStorageLocations = StorageLocations . serverList@@ -170,25 +171,25 @@ storeChaff hn port delayseconds = forever $ do 	say $ "Sending chaff to " ++ hn ++ " (press ctrl-c to stop)" 	say "Legend: + = successful upload, ! = upload failure"-	rng <- (cprgCreate <$> createEntropyPool) :: IO SystemRNG-	let (randomname, rng') = cprgGenerate 128 rng+	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG+	randomname <- randomByteStringOfLength 128 prg 	-- It's ok the use the testModeTunables here because 	-- the randomname is not something that can be feasibly guessed. 	-- Prefix "random chaff" to the name to avoid ever using a name 	-- that a real user might want to use. 	let sis = shareIdents testModeTunables (Name $ "random chaff:" <> randomname) AnyGpgKey-	mapConcurrently (go sis rng')+	mapConcurrently (go sis prg) 		[1..totalObjects (shareParams testModeTunables)]   where 	server = networkStorage Untrusted Nothing $  		Server (ServerName hn) [ServerAddress hn port] "chaff server" 	objsize = objectSize defaultTunables * shareOverhead defaultTunables 	maxmsdelay = ceiling $ 1000000 * fromMaybe 0 delayseconds-	go sis rng n = do+	go sis prg n = do 		msdelay <- getStdRandom (randomR (0, maxmsdelay)) 		delay msdelay -		let (b, rng') = cprgGenerate objsize rng+		b <- randomByteStringOfLength objsize prg 		let share = Share 0 (StorableObject b) 		let (is, sis') = nextShareIdents sis 		let i = S.toList is !! (n - 1)@@ -196,7 +197,7 @@ 		case r of 			StoreSuccess -> progress "+" 			_ -> progress "!"-		go sis' rng' n+		go sis' prg n  -- | Shuffles the list, keeping Recommended first, then -- Alternate, and finally Untrusted.
Storage/Local.hs view
@@ -14,6 +14,7 @@  import Types import Types.Storage+import Output import Serialization () import Utility.UserInfo import Utility.Exception@@ -50,8 +51,20 @@   where 	section = Section n -localStorageOverride :: FilePath -> Storage-localStorageOverride d = localStorage LocallyPreferred (\_ -> pure  d) ""+localStorageOverride :: FilePath -> IO (Maybe Storage)+localStorageOverride d = onError' accesserror $ do+	-- Check that the directory can be written to.+	createDirectoryIfMissing True d+	-- Use a filename as long as used for keysafe share files.+	let f = d </> "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.keysafe"+	writeFile f "test"+	_ <- readFile f+	removeFile f+	return $ Just $ localStorage LocallyPreferred (\_ -> pure d) ""+  where+	accesserror e = do+		warn $ "Unable to access local storage directory " ++ d ++ " (" ++ show e ++ ")"+		return Nothing  store :: Section -> GetShareDir -> StorableObjectIdent -> Share -> IO StoreResult store section getsharedir i s = onError (StoreFailure . show) $ do@@ -141,11 +154,14 @@ 			_ -> return StoreAlreadyExists  onError :: (IOException -> a) -> IO a -> IO a-onError f a = do+onError f = onError' (pure . f)++onError' :: (IOException -> IO a) -> IO a -> IO a+onError' f a = do 	v <- try a-	return $ case v of+	case v of 		Left e -> f e-		Right r -> r+		Right r -> return r  storageDir :: Maybe LocalStorageDirectory -> GetShareDir storageDir Nothing (Section section) = do
Storage/Network.hs view
@@ -33,12 +33,13 @@   where 	ServerName name = serverName server -networkStorageOverride :: Maybe LocalStorageDirectory -> HostName -> Port -> Storage-networkStorageOverride lsd h p = networkStorage LocallyPreferred lsd $ Server-	{ serverName = ServerName h-	, serverAddress = [ServerAddress h p]-	, serverDesc = h-	}+networkStorageOverride :: Maybe LocalStorageDirectory -> HostName -> Port -> IO (Maybe Storage)+networkStorageOverride lsd h p = return $ Just $+	networkStorage LocallyPreferred lsd $ Server+		{ serverName = ServerName h+		, serverAddress = [ServerAddress h p]+		, serverDesc = h+		}  store :: Server -> StorableObjectIdent -> Share -> IO StoreResult store srv i (Share _n o) = 
TODO view
@@ -23,6 +23,9 @@ * Add some random padding to http requests and responses, to make it   harder for traffic analysis to tell that given TOR traffic is   keysafe traffic.+* Argon2d is more resistent to GPU/ASIC attack optimisation.+  Switching from Argon2i would require new tunables, so deferred for now+  until there's some other reason to change the tunables.  Wishlist: @@ -32,11 +35,20 @@   are passphrase protected anyway.. * Don't require --totalshares and --neededshares on restore when unusual   values were used for backup. +   The difficulty is that the number of needed shares cannot be determined by   looking at shares, and guessing it wrong will result in combining   too few shares yielding garbage, which it will take up to an hour to   try to decrypt, before it can tell that more shares are needed.+   This could be dealt with by including the number of needed shares in the   serialization of Share, but then an attacker could use it to partition   shares from servers. If only one person uses --neededshares=5,   the attacker can guess that all their shares go together.++  What about including the number of needed shares in the name? Since that's+  hashed, it's not visible to an attacker. Keysafe would need to try names+  with 2 shares, then 3, etc, and once it found shares, it would know the+  number needed. It should also be possible to avoid breaking backwards+  compatability, by only including the number of shares in the name when+  it's not the standard number.
keysafe.1 view
@@ -50,6 +50,50 @@ Upload any data to servers that was queued by a previous keysafe run. This is designed to be put in a cron job. .PP+.IP --autostart+This is run automatically on desktop login by the desktop autostart+file included with keysafe. It checks for any new gpg keys that have+not been backed up, and prompts to see if the user wants to back them up+with keysafe. Also uploads any queued data, and in the future may perform+other checks for problems.+.PP+.IP --server+Runs keysafe in server mode, accepting objects and storing them.+Use --store-directory to configure where the server stores objects,+and --port and --address to configure how the server listens to+connections. It's recommended to only expose keysafe servers over a tor+hidden service.+.PP+.IP --backup-server BACKUPDIR+Run on a server, populates the BACKUPDIR with a gpg encrypted backup+of all the objects stored in the --store-directory. This is designed+to be rsynced offsite (with --delete) to back up a keysafe server with+minimal information leakage.+.PP+.IP --restore-server BACKUPDIR+Restore all objects present in the gpg-encrypted+backups in the specified directory.+.PP+.IP --chaff HOSTNAME+Upload random data to a keysafe server. --port can be used to specify+the server's port. Continues uploading data until interrupted with ctrl-c.+.PP+.IP --chaff-max-delay SECONDS+Specify a delay between chaff uploads. Will delay a+random amount between 0 and this many seconds.+.PP+.IP --check-servers+Tries to connect to each server in the server list.+Displays the server's MOTD, and the amount of data+stored on it. Prints message to stderr and exits+nonzero if any of the servers are not accessible.+.PP+.IP --benchmark+Benchmark speed of keysafe's cryptographic primitives.+.PP+.IP --test+Run test suite.+.PP .IP --gpgkeyid KEYID Specify keyid of gpg key to back up or restore. This is useful if you have multiple gpg keys. But, when this option is used to back up a key,@@ -60,6 +104,17 @@ To restore from the backup, you must use this same option, and pass the exact same filename. .PP+.IP --store-directory dir+Where to store data locally. For the client, data is+stored here before it is uploaded to the server. For+the server, this is where it stores its data.+(default: ~/.keysafe/objects/)+.PP+.IP --gui+Use GUI interface for interaction. Default is to use+readline interface when run in a terminal, and GUI otherwise.+The GUI currently is implemented using zenity(1).+.PP .IP --totalshares M --neededshares N These options have to be specified together. The default values are --totalshares 3 --neededshares 2.@@ -69,20 +124,38 @@ these options when backing up a secret key, you also must specify them with the same values to restore that secret key. .PP-.IP --store-local-Store data locally, in ~/.keysafe/objects/local/. -(The default is to store data in the cloud.)-The local data storage consists of 3 (--totalshares) subdirectories,-which hold the shares of the encrypted secret key. So, you can each-subdirectory to a separate storage location, and then to restore the key,-copy 2 (--neededshares) of them back into place.+.IP --name N+Specify name used for key backup/restore, avoiding the usual prompt. .PP-.IP --gui-Enable graphical user interface. This is the default unless keysafe-was run from a terminal. The GUI currently is implemented using zenity(1).+.IP --othername N+Specify other name used for key backup/restore, avoiding the usual prompt. .PP-.IP --benchmark-Benchmark speed of keysafe's cryptographic primitives.+.IP --add-storage-directory DIR+Add the directory to the list of locations keysafe+will use for backup/restore of keys. Keysafe will use+the directory first, before any of its built-in servers.+.PP+.IP --add-server HOST[:PORT]+Add the server to the server list which keysafe will+use for backup/restore of keys. Keysafe will use the+server first before any of its built-in servers.+.PP+.IP --port P+Port for server to listen on. (default: 80)+.PP+.IP --address A+Address for server to bind to. (Use "*" to bind to+all addresses.) (default: "127.0.0.1")+.PP+.IP --months-to-fill-half-disk N+Server rate-limits requests and requires proof of+work, to avoid too many objects being stored. This is+an lower bound on how long it could possibly take for+half of the current disk space to be+filled. (default: 12)+.PP+.IP --motd MESSAGE+The server's Message Of The Day. .PP .IP --testmode Avoid using expensive cryptographic operations to secure data.
keysafe.cabal view
@@ -1,5 +1,5 @@ Name: keysafe-Version: 0.20161006+Version: 0.20161007 Cabal-Version: >= 1.8 Maintainer: Joey Hess <joey@kitenet.net> Author: Joey Hess@@ -23,6 +23,8 @@   INSTALL   keysafe.1   keysafe.service+  keysafe.init+  keysafe.default   keysafe.desktop   keysafe.autostart   Makefile@@ -68,7 +70,6 @@     , unbounded-delays == 0.1.*     , fast-logger == 2.4.*     , SafeSemaphore == 0.10.*-    , crypto-random == 0.0.*     , async == 2.1.*     , unix-compat == 0.4.*     , exceptions == 0.8.*
+ keysafe.default view
@@ -0,0 +1,2 @@+# Parameters to pass to keysafe when it's started as a daemon.+DAEMON_PARAMS="--port 4242 --store-directory=/var/lib/keysafe/"
keysafe.hs view
@@ -368,12 +368,12 @@ 	return $ Name $ BU8.fromString $ takeWhile (/= ',') (userGecos u)  cmdLineStorageLocations :: CmdLine.CmdLine -> IO StorageLocations-cmdLineStorageLocations cmdline = +cmdLineStorageLocations cmdline = do+	preflocs <- StorageLocations . catMaybes <$>+		mapM (\mk -> mk lsd) (CmdLine.preferredStorage cmdline) 	shuffleStorageLocations (preflocs <> netlocs)   where 	netlocs = networkStorageLocations lsd-	preflocs = StorageLocations $-		map (\mk -> mk lsd) (CmdLine.preferredStorage cmdline) 	lsd = CmdLine.localstoragedirectory cmdline  getPasswordEntropy :: Password -> Name -> IO (Entropy UnknownPassword)
+ keysafe.init view
@@ -0,0 +1,60 @@+#!/bin/sh++### BEGIN INIT INFO+# Provides:          keysafe+# Required-Start:    $network $remote_fs+# Required-Stop:     $network $remote_fs+# Default-Start:     2 3 4 5+# Default-Stop:      0 1 6+# Short-Description: Keysafe server+# Description: Starts keysafe in server mode+### END INIT INFO++PATH=/bin:/usr/bin:/sbin:/usr/sbin+NAME=keysafe+DESC="Keysafe server"+DAEMON="/usr/bin/keysafe"+PIDFILE=/var/run/"$NAME".pid++test -x /usr/bin/keysafe || exit 0++. /lib/lsb/init-functions++# Parameters to pass to keysafe. This can be overridden in /etc/default/keysafe+DAEMON_PARAMS="--port 4242 --store-directory=/var/lib/keysafe/"+if [ -e /etc/default/keysafe ]; then+	. /etc/default/keysafe+fi++case "$1" in+	start)+		log_daemon_msg "Starting $DESC" "$NAME"+		start-stop-daemon --start --quiet --oknodo \+			--background --no-close \+			--pidfile "$PIDFILE" --make-pidfile \+			--chuid keysafe:keysafe \+			--exec "$DAEMON" -- --server $DAEMON_PARAMS \+			> /var/log/keysafe.log+		log_end_msg $?+	;;+	stop)+		log_daemon_msg "Stopping $DESC" "$NAME"+		killproc -p "$PIDFILE" "$DAEMON"+		RETVAL=$?+		[ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE+		log_end_msg $RETVAL+		;;+	restart|reload|force-reload)+		log_daemon_msg "Restarting $DESC" "$NAME"+		$0 stop+		$0 start+		;;+	status)+		status_of_proc -p $PIDFILE "$DAEMON" "$NAME" && exit 0 || exit $?+		;;+	*)+		log_action_msg "Usage: /etc/init.d/keysafe {start|stop|status|restart|reload|force-reload}"+		exit 2+		;;+esac+exit 0
keysafe.service view
@@ -2,7 +2,9 @@ Description=keysafe server  [Service]-ExecStart=/usr/bin/keysafe --server --port 4242 --store-directory=/var/lib/keysafe/+Environment='DAEMON_PARAMS=--port 4242 --store-directory=/var/lib/keysafe/'+EnvironmentFile=-/etc/default/keysafe+ExecStart=/usr/bin/keysafe --server $DAEMON_PARAMS InaccessiblePaths=/home /etc ReadWritePaths=/var/lib/keysafe User=keysafe