summaryrefslogtreecommitdiff
path: root/kiki.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2014-04-21 20:07:23 -0400
committerjoe <joe@jerkface.net>2014-04-21 20:07:23 -0400
commitbb7640591e32e117c68b3ce54114bf562a67beaf (patch)
tree12a58921325b54abcd807484683db7214cde807a /kiki.hs
parent1a8986f93fbdf1b444bbe7ef6e45363cba5c78ba (diff)
removed more unused bindings from kiki.hs
Diffstat (limited to 'kiki.hs')
-rw-r--r--kiki.hs348
1 files changed, 6 insertions, 342 deletions
diff --git a/kiki.hs b/kiki.hs
index 532c2ab..32b86bd 100644
--- a/kiki.hs
+++ b/kiki.hs
@@ -38,9 +38,6 @@ import Control.Applicative
38import System.Environment 38import System.Environment
39import System.Exit 39import System.Exit
40import System.IO (hPutStrLn,stderr) 40import System.IO (hPutStrLn,stderr)
41#if ! MIN_VERSION_base(4,6,0)
42import ControlMaybe ( handleIO_ )
43#endif
44import Data.Char 41import Data.Char
45import Control.Arrow (first,second) 42import Control.Arrow (first,second)
46-- import Data.Traversable hiding (mapM,forM,sequence) 43-- import Data.Traversable hiding (mapM,forM,sequence)
@@ -51,7 +48,7 @@ import Control.Arrow (first,second)
51import qualified Data.Map as Map 48import qualified Data.Map as Map
52import DotLock 49import DotLock
53-- import Codec.Crypto.ECC.Base -- hecc package 50-- import Codec.Crypto.ECC.Base -- hecc package
54import Text.Printf 51-- import Text.Printf
55import qualified CryptoCoins as CryptoCoins 52import qualified CryptoCoins as CryptoCoins
56import LengthPrefixedBE 53import LengthPrefixedBE
57import Data.Binary.Put (putWord32be,runPut,putByteString) 54import Data.Binary.Put (putWord32be,runPut,putByteString)
@@ -62,10 +59,6 @@ import Base58
62 59
63-- instance Default S.ByteString where def = S.empty 60-- instance Default S.ByteString where def = S.empty
64 61
65-- DER-encoded elliptic curve ids
66nistp256_id = 0x2a8648ce3d030107
67secp256k1_id = 0x2b8104000a
68
69warn str = hPutStrLn stderr str 62warn str = hPutStrLn stderr str
70 63
71 64
@@ -113,20 +106,12 @@ getPackets = do
113-} 106-}
114 107
115 108
116isEmbeddedSignature (EmbeddedSignaturePacket {}) = True
117isEmbeddedSignature _ = False
118
119isCertificationSig (CertificationSignature {}) = True 109isCertificationSig (CertificationSignature {}) = True
120isCertificationSig _ = True 110isCertificationSig _ = True
121 111
122issuer (IssuerPacket issuer) = Just issuer
123issuer _ = Nothing
124isSubkeySignature (SubkeySignature {}) = True 112isSubkeySignature (SubkeySignature {}) = True
125isSubkeySignature _ = False 113isSubkeySignature _ = False
126 114
127isPublicMaster k@(PublicKeyPacket {}) = not $ is_subkey k
128isPublicMaster _ = False
129
130verifyBindings keys nonkeys = (top ++ filter isSubkeySignature embedded,othersigs) 115verifyBindings keys nonkeys = (top ++ filter isSubkeySignature embedded,othersigs)
131 where 116 where
132 verified = do 117 verified = do
@@ -149,8 +134,6 @@ verifyBindings keys nonkeys = (top ++ filter isSubkeySignature embedded,othersig
149 guard (not . null $ signatures_over v) 134 guard (not . null $ signatures_over v)
150 return v 135 return v
151 136
152grip k = drop 32 $ fingerprint k
153
154smallpr k = drop 24 $ fingerprint k 137smallpr k = drop 24 $ fingerprint k
155 138
156 139
@@ -167,13 +150,6 @@ disjoint_fp ks = {- concatMap group2 $ -} transpose grouped
167 group2 [] = [] 150 group2 [] = []
168 -} 151 -}
169 152
170verifyBindingsEx :: [Packet] -> ([SignatureOver], [SignatureOver]) -- ^ (binding signatures, other signatures)
171verifyBindingsEx pkts = bicat . unzip $ do
172 let (keys,_) = partition isKey pkts
173 keys <- disjoint_fp keys
174 return $ verifyBindings keys pkts
175 where
176 bicat (xs,ys) = (concat xs,concat ys)
177 153
178getBindings :: 154getBindings ::
179 [Packet] 155 [Packet]
@@ -234,9 +210,11 @@ fpmatch grip key =
234 210
235listKeys pkts = listKeysFiltered [] pkts 211listKeys pkts = listKeysFiltered [] pkts
236 212
213{-
237ecc_curve k = printf "%x" num :: String 214ecc_curve k = printf "%x" num :: String
238 where unmpi (MPI num) = num 215 where unmpi (MPI num) = num
239 num = maybe 0 unmpi $ lookup 'c' (key k) 216 num = maybe 0 unmpi $ lookup 'c' (key k)
217-}
240 218
241listKeysFiltered grips pkts = do 219listKeysFiltered grips pkts = do
242 let (certs,bs) = getBindings pkts 220 let (certs,bs) = getBindings pkts
@@ -326,213 +304,20 @@ listKeysFiltered grips pkts = do
326 304
327 305
328 306
307{-
329modifyUID (UserIDPacket str) = UserIDPacket str' 308modifyUID (UserIDPacket str) = UserIDPacket str'
330 where 309 where
331 (fstname,rst) = break (==' ') str 310 (fstname,rst) = break (==' ') str
332 str' = mod fstname ++ rst 311 str' = mod fstname ++ rst
333 mod "Bob" = "Bob Fucking" 312 mod "Bob" = "Bob Slacking"
334 mod x = x 313 mod x = x
335modifyUID other = other 314modifyUID other = other
315-}
336 316
337todo = error "unimplemented"
338
339#if ! MIN_VERSION_base(4,6,0)
340lookupEnv var =
341 handleIO_ (return Nothing) $ fmap Just (getEnv var)
342#endif
343
344unmaybe def = fmap (maybe def id)
345
346expandPath path (c:cs) | c/='/' = path ++ "/" ++ (c:cs)
347 | otherwise = c:cs
348expandPath path [] = []
349 317
350 318
351-- type TimeStamp = Word32 319-- type TimeStamp = Word32
352 320
353-- | Attempts to lock each file in the list.
354-- Returns a list of locks and a list of filenames
355-- that could not be locked.
356lockFiles :: [FilePath] -> IO ( [(DotLock,FilePath)], [FilePath] )
357lockFiles fs = do
358 ls <- forM fs $ \f -> do
359 lk <- dotlock_create f 0
360 v <- flip (maybe $ return Nothing) lk $ \lk -> do
361 e <- dotlock_take lk (-1)
362 return $ if e==0 then Just lk
363 else Nothing
364 return (v,f)
365 let (lks, fails) = partition (isJust . fst) ls
366 return (map (\(lk,f)->(fromJust lk,f)) lks, map snd fails)
367
368unlockFiles lks = forM_ lks $ \(lk,f) -> do
369 -- warn $ "unlocking "++show f
370 dotlock_release lk
371
372{-
373options_from_file ::
374 (forall a. [String] -> Term a -> IO (Either EvalExit a))
375 -> Term b
376 -> (String,String,Term (Maybe String))
377 -> ([String],Term (Maybe String))
378 -> IO [String]
379options_from_file unwrapCmd term (homevar,appdir,home) (optfile_alts,options_file) = doit
380 where
381 homedir = envhomedir <$> home
382 envhomedir opt = do
383 gnupghome <- lookupEnv homevar >>=
384 \d -> return $ d >>= guard . (/="") >> d
385 home <- flip fmap getHomeDirectory $
386 \d -> fmap (const d) $ guard (d/="")
387 let homegnupg = (++('/':appdir)) <$> home
388 let val = (opt `mplus` gnupghome `mplus` homegnupg)
389 return $ val
390
391 doit = do
392 args <- getArgs
393 {-
394 let wants_help =
395 not . null $ filter cryForHelp args
396 where cryForHelp "--help" = True
397 cryForHelp "--version" = True
398 cryForHelp x =
399 and (zipWith (==) x "--help=")
400 -}
401 (o,h) <- do
402 val <- unwrapCmd args (liftA2 (,) options_file homedir)
403 case val of
404 Left e -> return (Nothing,Nothing)
405 Right (o,h) -> (o,) <$> h
406 ofile <- fmap listToMaybe . flip (maybe (return [])) h $ \h ->
407 let optfiles = map (second ((h++"/")++))
408 (maybe optfile_alts' (:[]) o')
409 optfile_alts' = zip (False:repeat True) optfile_alts
410 o' = fmap (False,) o
411 in filterM (doesFileExist . snd) optfiles
412 args <- flip (maybe $ return args) ofile $ \(forgive,fname) -> do
413 let h' = fromJust h
414 newargs <- (:) <$> pure ("homedir "++h') <*> parseOptionFile fname
415 let toArgs = toHead ("--"++) . words
416 toHead f (x:xs) = f x : xs
417 toHead f [] = []
418 voidTerm = fmap (const ())
419 appendArgs as [] = return as
420 appendArgs as (configline:cs) = do
421 let xs = toArgs configline
422 w <-unwrap (xs++as) (voidTerm term,defTI)
423 case w of
424 Left _ -> appendArgs as cs
425 Right _ -> appendArgs (xs++as) cs
426 -- TODO: check errors if forgive = False
427 appendArgs args newargs
428 return args
429
430runWithOptionsFile :: (Term (IO b), TermInfo) -> IO b
431runWithOptionsFile (term,ti) = do
432 as <- options_from_file unwrapCmd
433 term
434 ("GNUPGHOME",".gnupg",opt_homedir)
435 (["keys.conf","gpg.conf-2","gpg.conf"]
436 ,opt_options)
437 q <- eval as (term , ti)
438 q
439 where
440 unwrapCmd args term = unwrap args (term,defTI)
441
442runChoiceWithOptionsFile ::
443 (Term (IO b), TermInfo) -> [(Term (IO b), TermInfo)] -> IO b
444runChoiceWithOptionsFile (realterm,ti) choices = do
445 as <- options_from_file unwrapCmd
446 realterm
447 ("GNUPGHOME",".gnupg",opt_homedir)
448 (["keys.conf","gpg.conf-2","gpg.conf"]
449 ,opt_options)
450 -- putStrLn $ "as = " ++ show as
451 q <- evalChoice as (realterm , ti) choices
452 q
453 where
454 unwrapCmd args t =
455 unwrapChoice args (realterm <:> t,ti) (map (neuter t) choices)
456 neuter term (t,ti) = (t <:> term, ti)
457
458data Command =
459 List
460 | Autosign
461 deriving (Eq,Show,Read,Enum)
462
463capitolizeFirstLetter (x:xs) = toUpper x : xs
464capitolizeFirstLetter xs = xs
465
466instance ArgVal Command where
467 converter =
468 ( maybe (Left $ text "unknown command") Right
469 . fmap fst . listToMaybe . reads
470 . capitolizeFirstLetter . map toLower
471 , text . map toLower . show
472 )
473class AutoMaybe a
474instance AutoMaybe Command
475instance (ArgVal a, AutoMaybe a) => ArgVal (Maybe a) where
476 converter =
477 ( toRight Just . fst converter
478 , maybe (text "(unspecified)") id . fmap (snd converter)
479 )
480
481toRight f (Right x) = Right (f x)
482toRight f (Left y) = Left y
483
484cmd :: Term Command
485cmd = required . pos 0 Nothing $ posInfo
486 { posName = "command"
487 , posDoc = "What action to perform."
488 }
489
490a <:> b = flip const <$> a <*> b
491infixr 2 <:>
492
493selectAction cmd actions = actions !! fromEnum cmd
494
495cmdInfo :: ArgVal cmd =>
496 cmd -> String -> Term a -> (cmd, (Term a, TermInfo))
497cmdInfo cmd doc action =
498 ( cmd
499 , ( action
500 , defTI { termName = print cmd
501 , termDoc = doc } ) )
502 where
503 print = show . snd converter
504
505cmdlist :: (Command, (Term (IO ()), TermInfo))
506cmdlist = cmdInfo List "list key pairs for which secrets are known" $
507 (>>= putStrLn . listKeys . unMessage) <$> secret_packets
508 where unMessage (Message pkts) = pkts
509
510cmdautosign = cmdInfo Autosign "auto-sign tor-style uids" $
511 pure (putStrLn "autosign")
512
513
514multiCommand ::
515 TermInfo
516 -> [(Command, (Term a, TermInfo))]
517 -> ( (Term a, TermInfo)
518 , [(Term a, TermInfo)] )
519multiCommand ti choices =
520 ( ( selectAction <$> cmd <*> sequenceA (map strip choices)
521 , ti )
522 , map snd choices )
523 where
524 selectAction cmd choices =
525 fromJust $ lookup (cmd::Command) choices
526 strip (cmd,(action,_)) = fmap (cmd,) action
527-}
528
529
530trimCR bs = fst $ S.spanEnd (\x -> x==10 || x==13) bs
531
532guessKeyFormat 'P' "ssh-client" = "SSH"
533guessKeyFormat 'S' "ssh-client" = "PEM"
534guessKeyFormat 'S' "ssh-host" = "PEM"
535guessKeyFormat _ _ = "PEM" -- "PGP"
536 321
537readPublicKey :: Char8.ByteString -> RSAPublicKey 322readPublicKey :: Char8.ByteString -> RSAPublicKey
538readPublicKey bs = maybe er id $ do 323readPublicKey bs = maybe er id $ do
@@ -557,44 +342,6 @@ getPassphrase cmd =
557 342
558#define HOMEOPTION (def &= explicit &= name "homedir" &= typDir ) 343#define HOMEOPTION (def &= explicit &= name "homedir" &= typDir )
559 344
560writeOutKeyrings :: Map.Map FilePath t -> KeyDB -> IO ()
561writeOutKeyrings lkmap db = do
562 let ks = Map.elems db
563 fs = Map.keys (foldr unionfiles Map.empty ks)
564 where unionfiles (KeyData p _ _ _) m =
565 Map.union m (locations p)
566 fromfile f (KeyData p _ _ _) = Map.member f $ locations p
567 let s = do
568 f <- fs
569 let x = do
570 d@(KeyData p _ _ _) <- filter (fromfile f) (sortByHint f keyMappedPacket ks)
571 n <- maybeToList $ Map.lookup f (locations p)
572 flattenTop f (originallyPublic n) d
573 changes = filter isnew x
574 where isnew p = isNothing (Map.lookup f $ locations p)
575 {-
576 trace (unlines $ ( (f ++ ":") : map (showPacket . packet) x) ++
577 ( "CHANGES: " : map ((" "++) . showPacket . packet) changes)) $ do
578 -}
579 return (f,(changes,x))
580 towrites <- fmap catMaybes $ Control.Monad.forM s $ \(f,(changes,x)) -> do
581 let noop = return Nothing
582 write f = return (Just f)
583 case changes of
584 [] -> noop -- warn (f ++": nothing to do.") >> noop
585 cs -> case Map.lookup f lkmap of
586 Just lk -> do
587 forM_ cs $ \c -> warn $ f++": new "++showPacket (packet c)
588 write (f,lk,x)
589 Nothing -> do
590 forM_ cs $ \c -> warn $ f++": missing "++showPacket (packet c)
591 noop
592 forM_ towrites $ \(f,lk,x) -> do
593 let m = Message $ map packet x
594 -- warn $ "writing "++f
595 L.writeFile f (encode m)
596
597
598 345
599toLast f [] = [] 346toLast f [] = []
600toLast f [x] = [f x] 347toLast f [x] = [f x]
@@ -715,39 +462,6 @@ cannonical_eckey x y = 0x4:pad32(numToBytes x) ++ pad32(numToBytes y) :: [Word8]
715 where 462 where
716 zlen = 32 - length xs 463 zlen = 32 - length xs
717 464
718oidToDER ns = S.pack $ b1 : concatMap encode ys
719 where
720 (xs,ys) = splitAt 2 ns
721 b1 = fromIntegral $ foldl' (\a b->a*40+b) 0 xs
722 encode x | x <= 127 = [fromIntegral x]
723 | otherwise = (\(x:xs)-> reverse (x:map (0x80 .|.) xs))
724 (base128r x)
725 base128r n = unfoldr getbyte n
726 where
727 getbyte d = do
728 guard (d/=0)
729 let (q,b) = d `divMod` 128
730 return (fromIntegral b,q)
731
732nistp256=[1,2,840,10045,3,1,7]
733nistp256_der=[0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07]
734-- "\x2a\x86\x48\xce\x3d\x03\x01\x07"
735{- OID Curve description Curve name
736 ----------------------------------------------------------------
737 1.2.840.10045.3.1.7 NIST Curve P-256 [FIPS 186-2] "NIST P-256"
738 1.3.132.0.34 NIST Curve P-384 [FIPS 186-2] "NIST P-384"
739 1.3.132.0.35 NIST Curve P-521 [FIPS 186-2] "NIST P-521"
740
741 Implementations MUST implement "NIST P-256", "NIST P-384" and "NIST
742 P-521". The hexadecimal representation used in the public and
743 private key encodings are:
744
745 Curve Name Len Hexadecimal representation of the OID
746 ----------------------------------------------------------------
747 "NIST P-256" 8 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
748 "NIST P-384" 6 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22
749 "NIST P-521" 6 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23
750-}
751 465
752bitcoinAddress network_id k = address 466bitcoinAddress network_id k = address
753 where 467 where
@@ -815,51 +529,6 @@ whoseKey rsakey db = filter matchkey (Map.elems db)
815 s2 <- signatures . Message $ [k,sub,subsig] 529 s2 <- signatures . Message $ [k,sub,subsig]
816 signatures_over $ verify (Message [sub]) s2 530 signatures_over $ verify (Message [sub]) s2
817 531
818workingKey grip use_db = listToMaybe $ do
819 fp <- maybeToList grip
820 elm <- Map.toList use_db
821 guard $ matchSpec (KeyGrip fp) elm
822 return $ keyPacket (snd elm)
823
824has_good_sig wk (KeyData k sigs uids subs) = any goodsig $ Map.toList uids
825 where
826 goodsig (uidstr,(sigs,_)) = not . null $ do
827 sig0 <- fmap (packet . fst) sigs
828 pre_ov <- signatures (Message [packet k, UserIDPacket uidstr, sig0])
829 signatures_over $ verify (Message [wk]) pre_ov
830
831markForImport
832 :: Ord d =>
833 Map.Map String a
834 -> Maybe String
835 -> FilePath
836 -> Map.Map d KeyData
837 -> IO (Map.Map d KeyData)
838markForImport margs grip pubring db = maybe (return db) import_db $ wantToImport
839 where wantToImport = mplus import_f importifauth_f
840 where
841 import_f = do Map.lookup "--import" margs
842 return dont_have
843 importifauth_f = do Map.lookup "--import-if-authentic" margs
844 return isauth
845 dont_have (KeyData p _ _ _) = not . Map.member pubring
846 $ locations p
847 isauth keydata = dont_have keydata && maybe False (`has_good_sig` keydata) wk
848 where wk = workingKey grip db
849 import_db dont_have = do
850 forM_ to_alters $ \(_,KeyData c _ _ _) ->
851 warn $ pubring ++ ": new "++showPacket (packet c)
852 let db' = Map.union (Map.fromList altered)
853 db
854 return db'
855 where
856 to_alters = filter (dont_have . snd) $ Map.toList db
857 altered = map (second append_loc) to_alters
858 append_loc (KeyData p a b c) = KeyData p' a b c
859 where p' = p { locations = Map.insert pubring
860 (origin (secretToPublic (packet p)) (-1))
861 (locations p)
862 }
863 532
864kiki_usage = do 533kiki_usage = do
865 putStr . unlines $ 534 putStr . unlines $
@@ -1149,11 +818,6 @@ groupBindings pub =
1149 gs = {- filter matchgrip $ -} groupBy sameMaster (sortBy (comparing code) bindings') 818 gs = {- filter matchgrip $ -} groupBy sameMaster (sortBy (comparing code) bindings')
1150 in gs 819 in gs
1151 820
1152isTopKey p@(SecretKeyPacket {}) | not (is_subkey p) = True
1153isTopKey p@(PublicKeyPacket {}) | not (is_subkey p) = True
1154isTopKey _ = False
1155
1156groupTops ps = groupBy (\_ b -> not (isTopKey b)) ps
1157 821
1158 822
1159{- 823{-