From 2f4b7ee55503c5d7df5dc8e0df688c3823273c65 Mon Sep 17 00:00:00 2001 From: James Crayne Date: Sun, 21 Jun 2015 04:07:08 -0400 Subject: init-key command as non-root user. Support for ssh client key only at this time. --- kiki.hs | 85 +++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 29 deletions(-) (limited to 'kiki.hs') diff --git a/kiki.hs b/kiki.hs index d05424f..c80f2cc 100644 --- a/kiki.hs +++ b/kiki.hs @@ -22,7 +22,7 @@ import Data.Maybe import Data.OpenPGP import Data.Ord import Data.Text.Encoding --- import System.Posix.User +import System.Posix.User import System.FilePath.Posix import System.Directory import System.Environment @@ -1137,8 +1137,8 @@ kiki "init-key" args | "--help" `elem` args = do , " | --chroot=ROOTDIR ] ..."] return () kiki "init-key" args = do - {- me <- getEffectiveUserID + {- if me/=0 then error "This command requires root." else do -} let as = lefts $ map splitArg args @@ -1146,6 +1146,8 @@ kiki "init-key" args = do bads = map fst as \\ ["passphrase-fd","home","chroot"] if not (null bads) then error ("Bad option: " ++ unwords bads) else do let rootdir = fmap (fromMaybe "") $ lookup "chroot" as + let noChrootArg = rootdir == Nothing + bUnprivileged = (me/=0) && noChrootArg if rootdir==Just "" then error "--chroot requires an argument" else do -- maybe id fchroot rootdir $ do args <- return $ map (second $ fromMaybe "") as @@ -1161,6 +1163,7 @@ kiki "init-key" args = do createDirectoryIfMissing True dir -- ssl = Just "mkdir -p \"$(dirname $file)\" && openssl genrsa -out $file 1024" (home,secring,pubring,mbwk) <- unconditionally $ getHomeDir homespec + osHomeDir <- if bUnprivileged then getHomeDirectory else return "/root" -- putStrLn $ "home = " ++ show (home,secring,pubring,mbwk) gotsec <- doesFileExist secring when (not gotsec) $ do @@ -1183,10 +1186,10 @@ kiki "init-key" args = do -- TODO: These should be read from a configuration file. -- (use SimpleConfig) let torpath = fromMaybe "" rootdir ++ "/var/lib/tor/samizdat/private_key" - sshcpath0 = fromMaybe "" rootdir ++ "/root/.ssh/id_rsa" + sshcpath0 = fromMaybe "" rootdir ++ osHomeDir ".ssh" "id_rsa" sshspath0 = fromMaybe "" rootdir ++ "/etc/ssh/ssh_host_rsa_key" ipsecpath0 = fromMaybe "" rootdir ++ "/etc/ipsec.d/private/%(onion).pem" - sshcpathpub0 = fromMaybe "" rootdir ++ "/root/.ssh/id_rsa.pub" + sshcpathpub0 = fromMaybe "" rootdir ++ osHomeDir ".ssh" "id_rsa.pub" sshspathpub0 = fromMaybe "" rootdir ++ "/etc/ssh/ssh_host_rsa_key.pub" ipsecpathpub0 = fromMaybe "" rootdir ++ "/etc/ipsec.d/certs/%(onion).pem" contactipsec0 = fromMaybe "" rootdir ++ "/etc/ipsec.d/certs/%(onion).pem" @@ -1219,22 +1222,33 @@ kiki "init-key" args = do , opHome = homespec , opTransforms = [] } - mkdirFor torpath - KikiResult rt report <- runKeyRing op + doNothing = return () + nop = KeyRingOperation + { opFiles = Map.empty + , opPassphrases = do pfd <- maybeToList passfd + return $ PassphraseSpec Nothing Nothing pfd + , opHome=homespec, opTransforms = [] + } + if bUnprivileged then doNothing else mkdirFor torpath + KikiResult rt report <- runKeyRing (if bUnprivileged then nop else op) forM_ report $ \(fname,act) -> do putStrLn $ fname ++ ": " ++ reportString act - rt <- unconditionally $ return rt + rt <- case rt of + BadPassphrase -> + error "Operation requires correct passphrase. (Hint: Use --passphrase-fd=0 to input it on stdin.)" + _ -> unconditionally $ return rt -- Now import, export, or generate the remaining secret keys. - let oname = do wk <- rtWorkingKey rt - onionNameForContact (keykey wk) (rtKeyDB rt) - flip (maybe $ error "Missing tor key") oname $ \oname -> do - let [ sshcpath , sshspath , ipsecpath, - sshcpathpub, sshspathpub, ipsecpathpub ] - = map (interp (Map.fromList [("onion",oname)])) - [ sshcpath0, sshspath0, ipsecpath0 - , sshcpathpub0, sshspathpub0, ipsecpathpub0 ] - let op2 = op + let oname' = do wk <- rtWorkingKey rt + onionNameForContact (keykey wk) (rtKeyDB rt) + if (oname' == Nothing) && (not bUnprivileged) then error "Missing tor key" else do + let oname = fromMaybe "" oname' + let [ sshcpath, sshcpathpub ] = {- map (interp (Map.fromList [("onion",oname)]))-} [ sshcpath0, sshcpathpub0 ] + [ sshspath , ipsecpath ] = map (interp (Map.fromList [("onion",oname)])) [ sshspath0, ipsecpath0 ] + [ sshspathpub, ipsecpathpub ] + = map (interp (Map.fromList [("onion",oname)])) + [ sshspathpub0, ipsecpathpub0 ] + let opPriv = op { opFiles = Map.fromList $ [ ( HomeSec, buildStreamInfo KF_All KeyRingFile ) , ( HomePub, (buildStreamInfo KF_All KeyRingFile) { access = Pub } ) @@ -1243,12 +1257,22 @@ kiki "init-key" args = do , ( ArgFile sshspath, peminfo 2048 "ssh-server" ) ] , opPassphrases = [ PassphraseMemoizer (rtPassphrases rt) ] } - forM_ [sshcpath,sshspath,ipsecpath - ,sshcpathpub,sshspathpub,ipsecpathpub] mkdirFor - KikiResult rt report <- runKeyRing op2 + opUnPriv = op + { opFiles = Map.fromList $ + [ ( HomeSec, buildStreamInfo KF_All KeyRingFile ) + , ( HomePub, (buildStreamInfo KF_All KeyRingFile) { access = Pub } ) + , ( ArgFile sshcpath, peminfo 2048 "ssh-client" ) + ] + , opPassphrases = [ PassphraseMemoizer (rtPassphrases rt) ] + } + mapM_ mkdirFor $ [sshcpath,sshcpathpub] ++ if not bUnprivileged then [sshspath,ipsecpath,sshspathpub,ipsecpathpub] else [] + KikiResult rt report <- runKeyRing (if bUnprivileged then opUnPriv else opPriv) forM_ report $ \(fname,act) -> do putStrLn $ fname ++ ": " ++ reportString act - rt <- unconditionally $ return rt + rt <- case rt of + BadPassphrase -> + error "Operation requires correct passphrase. (Hint: Use --passphrase-fd=0 to input it on stdin.)" + _ -> unconditionally $ return rt -- Finally, export public keys if they do not exist. flip (maybe $ warn "missing working key?") (rtGrip rt) $ \grip -> do @@ -1256,15 +1280,18 @@ kiki "init-key" args = do when (not gotc) $ do either warn (writeFile sshcpathpub) $ show_ssh' "ssh-client" grip (rtKeyDB rt) - goth <- doesFileExist (sshspathpub) - when (not goth) $ do - either warn (writeFile $ sshspathpub) - $ show_ssh' "ssh-host" grip (rtKeyDB rt) - - goti <- doesFileExist (ipsecpathpub) - when (not goti) $ do - either warn (writeFile $ ipsecpathpub) - $ show_pem' "strongswan" grip (rtKeyDB rt) + if (not bUnprivileged) + then do + goth <- doesFileExist (sshspathpub) + when (not goth) $ do + either warn (writeFile $ sshspathpub) + $ show_ssh' "ssh-host" grip (rtKeyDB rt) + goti <- doesFileExist (ipsecpathpub) + when (not goti) $ do + either warn (writeFile $ ipsecpathpub) + $ show_pem' "strongswan" grip (rtKeyDB rt) + else return () + let cs = filter notme (Map.elems $ rtKeyDB rt) kk = keykey (fromJust $ rtWorkingKey rt) -- cgit v1.2.3