diff options
author | James Crayne <jim.crayne@gmail.com> | 2014-04-26 19:37:59 -0400 |
---|---|---|
committer | James Crayne <jim.crayne@gmail.com> | 2014-04-26 19:37:59 -0400 |
commit | 278e30eb03b821c9ce9502eb3879ef728367dde8 (patch) | |
tree | ab1b4e557b1caa8479a9ab2b41e925bf80b8f2bb | |
parent | bd6992f90dea2425190efa048eafdda27ac84456 (diff) |
show command
-rw-r--r-- | kiki.hs | 340 |
1 files changed, 208 insertions, 132 deletions
@@ -461,7 +461,48 @@ whoseKey rsakey db = filter matchkey (Map.elems db) | |||
461 | 461 | ||
462 | kiki_usage bSecret cmd = putStr $ | 462 | kiki_usage bSecret cmd = putStr $ |
463 | case cmd of | 463 | case cmd of |
464 | "sync-secret" -> unlines | 464 | "show" -> unlines $ |
465 | ["kiki show [options...]" | ||
466 | ,"" | ||
467 | ," show displays infomration about keys stored in the data files which resides in" | ||
468 | ," the home directory (see --homedir)." | ||
469 | ,"" | ||
470 | ," The files pubring.gpg and subring.gpg in the directory specified by the " | ||
471 | ," --homedir option are implicitly included in the keyring set." | ||
472 | ,"" | ||
473 | ," Subkeys that are imported with kiki are given an annotation \"usage@\" which" | ||
474 | ," indicates what the key is for. This tag can be used as a SPEC to select a" | ||
475 | ," particular key. Master keys may be specified by using fingerprints or by" | ||
476 | ," specifying a substring of an associated UID." | ||
477 | ,"Options: " | ||
478 | ] ++ commonOptions ++ | ||
479 | [" --working" | ||
480 | ," Show fingerprints for the working key (which will be used to" | ||
481 | ," make signatures) and all its subkeys and UID." | ||
482 | ,"" | ||
483 | ," --key SPEC" | ||
484 | ," Show fingerprints for the specified key and all its subkeys" | ||
485 | ," and UID." | ||
486 | ,"" | ||
487 | ," --all Show fingerprints and UIDs and usage tags for all known keys." | ||
488 | ,"" | ||
489 | ," --whose-key" | ||
490 | ," Shows the fingerprint and UIDs of the key that owns the one that" | ||
491 | ," is input on stdin in ssh-rsa format." | ||
492 | ,"" | ||
493 | ," --pem SPEC" | ||
494 | ," Outputs the PKCS #8 public key corresponding to SPEC." | ||
495 | ,"" | ||
496 | ," --ssh SPEC" | ||
497 | ," Outputs the ssh-rsa blob for the specified public key." | ||
498 | ,"" | ||
499 | ," --wip SPEC" | ||
500 | ," Outputs the secret crypto-coin key in Wallet Input Format." | ||
501 | ,"" | ||
502 | ," --help Shows this help screen." | ||
503 | ,"" | ||
504 | ] ++ keyspec | ||
505 | "sync-secret" -> unlines $ | ||
465 | ["kiki sync-secret [options...]" | 506 | ["kiki sync-secret [options...]" |
466 | ,"" | 507 | ,"" |
467 | ," sync-secret merges a set of key files into a combined database and then" | 508 | ," sync-secret merges a set of key files into a combined database and then" |
@@ -475,8 +516,8 @@ kiki_usage bSecret cmd = putStr $ | |||
475 | ," indicates what the key is for. This tag can be used as a SPEC to select a" | 516 | ," indicates what the key is for. This tag can be used as a SPEC to select a" |
476 | ," particular key. Master keys may be specified by using fingerprints or by" | 517 | ," particular key. Master keys may be specified by using fingerprints or by" |
477 | ," specifying a substring of an associated UID." | 518 | ," specifying a substring of an associated UID." |
478 | ] | 519 | ] ++ syncflags ++ keyspec |
479 | "import-secret" -> unlines | 520 | "import-secret" -> unlines $ |
480 | ["kiki import-secret [options...]" | 521 | ["kiki import-secret [options...]" |
481 | ,"" | 522 | ,"" |
482 | ," import-secret uses a set of key files to update your keyring. It does not" | 523 | ," import-secret uses a set of key files to update your keyring. It does not" |
@@ -489,130 +530,108 @@ kiki_usage bSecret cmd = putStr $ | |||
489 | ," indicates what the key is for. This tag can be used as a SPEC to select a" | 530 | ," indicates what the key is for. This tag can be used as a SPEC to select a" |
490 | ," particular key. Master keys may be specified by using fingerprints or by" | 531 | ," particular key. Master keys may be specified by using fingerprints or by" |
491 | ," specifying a substring of an associated UID." | 532 | ," specifying a substring of an associated UID." |
492 | ] | 533 | ] ++ syncflags ++ keyspec |
493 | ++ unlines | 534 | where |
494 | ["" | 535 | commonOptions :: [String] |
495 | ,"Flags:" | 536 | commonOptions = |
496 | ," --homedir DIR" | 537 | [" --homedir DIR" |
497 | ," Where to find the the files secring.gpg and pubring.gpg. The " | 538 | ," Where to find the the files secring.gpg and pubring.gpg. The " |
498 | ," default location is taken from the environment variable " | 539 | ," default location is taken from the environment variable " |
499 | ," GNUPGHOME." | 540 | ," GNUPGHOME." |
500 | ,"" | 541 | ,"" |
501 | ," --passphrase-fd N" | 542 | ," --passphrase-fd N" |
502 | ," Read passphrase from the given file descriptor." | 543 | ," Read passphrase from the given file descriptor." |
503 | ,"" | 544 | ,"" |
504 | ," --import Add master keys to pubring.gpg. Without this option, only UID" | 545 | ] |
505 | ," and subkey data is updated. " | 546 | syncflags :: [String] |
506 | ,"" | 547 | syncflags = |
507 | ," --import-if-authentic" | 548 | ["" |
508 | ," Add signed master keys to pubring.gpg. Like --import except that" | 549 | ,"Flags:"] ++ commonOptions ++ |
509 | ," only keys with signatures from the working key (--show-wk) are" | 550 | [" --import Add master keys to pubring.gpg. Without this option, only UID" |
510 | ," imported." | 551 | ," and subkey data is updated. " |
511 | ,"" | 552 | ,"" |
512 | ," --autosign Sign all cross-certified tor-style UIDs." | 553 | ," --import-if-authentic" |
513 | ," A tor-style UID is of the form:" | 554 | ," Add signed master keys to pubring.gpg. Like --import except that" |
514 | ," Anonymous <root@HOSTNAME.onion>" | 555 | ," only keys with signatures from the working key (--show-wk) are" |
515 | ," It is considered cross certified if there exists a cross-certified" | 556 | ," imported." |
516 | ," 'tor' subkey corresponding to the address HOSTNAME.onion." | 557 | ,"" |
517 | ,"" | 558 | ," --autosign Sign all cross-certified tor-style UIDs." |
518 | ,"Merging:" | 559 | ," A tor-style UID is of the form:" |
519 | ," --keyrings FILE FILE..." | 560 | ," Anonymous <root@HOSTNAME.onion>" |
520 | ," Provide keyring files other than the implicit secring.gpg and" | 561 | ," It is considered cross certified if there exists a cross-certified" |
521 | ," pubring.gpg in the --homedir. This option is implicit unless" | 562 | ," 'tor' subkey corresponding to the address HOSTNAME.onion." |
522 | ," --keypairs or --wallets is used." | 563 | ,"" |
523 | ,""] | 564 | ,"Merging:" |
524 | ++ do | 565 | ," --keyrings FILE FILE..." |
525 | guard bSecret | 566 | ," Provide keyring files other than the implicit secring.gpg and" |
526 | unlines | 567 | ," pubring.gpg in the --homedir. This option is implicit unless" |
527 | [" --wallets FILE FILE..." | 568 | ," --keypairs or --wallets is used." |
528 | ," Provide wallet files with secret crypto-coin keys in Wallet" | 569 | ,""] |
529 | ," Import Format. The keys will be treated as subkeys of your" | 570 | ++ do |
530 | ," current working key (the one shown by --show-wk)." | 571 | guard bSecret |
531 | ,"" | 572 | return $ unlines |
532 | ," --keypairs KEYSPEC KEYSPEC..." | 573 | [" --wallets FILE FILE..." |
533 | ," A keypair is a secret key coupled with it's corresponding public" | 574 | ," Provide wallet files with secret crypto-coin keys in Wallet" |
534 | ," key, both of which are ordinarily stored in a single file in pem" | 575 | ," Import Format. The keys will be treated as subkeys of your" |
535 | ," format. Users incognisant of the fact that the public key (which" | 576 | ," current working key (the one shown by --show-wk)." |
536 | ," is also stored separately) is in this file, often think of it as" | 577 | ,"" |
537 | ," their secret key file." | 578 | ," --keypairs KEYSPEC KEYSPEC..." |
538 | ,"" | 579 | ," A keypair is a secret key coupled with it's corresponding public" |
539 | ," Each KEYSPEC specifies that a key should match the content and" | 580 | ," key, both of which are ordinarily stored in a single file in pem" |
540 | ," timestamp of an external PKCS #1 private RSA key file." | 581 | ," format. Users incognisant of the fact that the public key (which" |
541 | ," " | 582 | ," is also stored separately) is in this file, often think of it as" |
542 | ," KEYSPEC ::= SPEC=FILE{CMD} " | 583 | ," their secret key file." |
543 | ,"" | 584 | ,"" |
544 | ," The form of SPEC is documented below. If there is only one master" | 585 | ," Each KEYSPEC specifies that a key should match the content and" |
545 | ," key in your keyring and only one key is used for each purpose, then" | 586 | ," timestamp of an external PKCS #1 private RSA key file." |
546 | ," it is possible for SPEC in this case to merely be a tag which offers" | 587 | ," " |
547 | ," information about what this key is used for, for example, any of" | 588 | ," KEYSPEC ::= SPEC=FILE{CMD} " |
548 | ," `tor', `ssh-client', `ssh-host', or `strongswan' will do." | 589 | ,"" |
549 | ,"" | 590 | ," The form of SPEC is documented below. If there is only one master" |
550 | ," If neither SPEC or FILE match any keys, then the CMD will be " | 591 | ," key in your keyring and only one key is used for each purpose, then" |
551 | ," executed in order to create the FILE." | 592 | ," it is possible for SPEC in this case to merely be a tag which offers" |
552 | ,""] | 593 | ," information about what this key is used for, for example, any of" |
553 | {- ,"Output:" | 594 | ," `tor', `ssh-client', `ssh-host', or `strongswan' will do." |
554 | ," --show-wk Show fingerprints for the working key (which will be used to" | 595 | ,"" |
555 | ," make signatures) and all its subkeys and UID." | 596 | ," If neither SPEC or FILE match any keys, then the CMD will be " |
556 | ,"" | 597 | ," executed in order to create the FILE." |
557 | ," --show-key SPEC" | 598 | ,""] |
558 | ," Show fingerprints for the specified key and all its subkeys" | 599 | keyspec = -- unlines $ |
559 | ," and UID." | 600 | ["Specifying keys on the kiki command line:" |
560 | ,"" | 601 | ,"" |
561 | ," --show-all Show fingerprints and UIDs and usage tags for all known keys." | 602 | ," SPEC ::= MASTER/SUBKEY" |
562 | ,"" | 603 | ,"" |
563 | ," --show-whose-key" | 604 | ," SPEC indicates a specific key in the keyring, in it's longest incarnation," |
564 | ," Shows the fingerprint and UIDs of the key that owns the one that" | 605 | ," it is of the form MASTER/SUBKEY where MASTER and SUBKEY are documented below." |
565 | ," is input on stdin in ssh-rsa format." | 606 | ," If kiki can infer the key unambiguously, either via the command in question or" |
566 | ,"" | 607 | ," the contents of the keyring, then it is permissable to ommit either MASTER or" |
567 | ," --show-pem SPEC" | 608 | ," SUBKEY, in which case the slash may also be ommitted unless it is used via its" |
568 | ," Outputs the PKCS #8 public key corresponding to SPEC." | 609 | ," position to indicate whether a SUBKEY or MASTER is intended." |
569 | ,"" | 610 | ,"" |
570 | ," --show-ssh SPEC" | 611 | ," MASTER may be any of" |
571 | ," Outputs the ssh-rsa blob for the specified public key." | 612 | ," * The tail end of a fingerprint prefixed by 'fp:'" |
572 | ,"" | 613 | ," * A sub-string of a user id (without slashes) prefixed by 'u:'" |
573 | ," --show-wip SPEC" | 614 | ," * 40 characters of hexidecimal (kiki will assume this to be a fingerprint)" |
574 | ," Outputs the secret crypto-coin key in Wallet Input Format." | 615 | ," * A sub-string of a user id (without slashes, the prefix 'u:' is optional)" |
575 | ,"" | 616 | ,"" |
576 | ," --help Shows this help screen." | 617 | ," SUBKEY may be any of" |
577 | ,"" | 618 | ," * The tail end of a fingerprint prefixed by 'fp:'" |
578 | -} | 619 | ," * An exact match of a usage tag prefixed by 't:'" |
579 | ++ | 620 | ," * 40 characters of hexidecimal (kiki will assume this to be a fingerprint)" |
580 | unlines | 621 | ," * An exact match of a usage tag (The prefix 't:' is optional)" |
581 | ["Specifying keys on the kiki command line:" | 622 | ,"" |
582 | ,"" | 623 | ," In parsing the spec, kiki will attempt to match the string to one of the" |
583 | ," SPEC ::= MASTER/SUBKEY" | 624 | ," above formats, in the order presented." |
584 | ,"" | 625 | ,"" |
585 | ," SPEC indicates a specific key in the keyring, in it's longest incarnation," | 626 | ," Examples of valid SPEC strings:" |
586 | ," it is of the form MASTER/SUBKEY where MASTER and SUBKEY are documented below." | 627 | ,"" |
587 | ," If kiki can infer the key unambiguously, either via the command in question or" | 628 | ," fp:4A39F/tor" |
588 | ," the contents of the keyring, then it is permissable to ommit either MASTER or" | 629 | ," u:joe/tor" |
589 | ," SUBKEY, in which case the slash may also be ommitted unless it is used via its" | 630 | ," u:joe/t:tor" |
590 | ," position to indicate whether a SUBKEY or MASTER is intended." | 631 | ," u:joe/fp:4abf30" |
591 | ,"" | 632 | ," joe/tor" |
592 | ," MASTER may be any of" | 633 | ," 5E24CD442AA6965D2012E62A905C24185D5379C2" |
593 | ," * The tail end of a fingerprint prefixed by 'fp:'" | 634 | ] |
594 | ," * A sub-string of a user id (without slashes) prefixed by 'u:'" | ||
595 | ," * 40 characters of hexidecimal (kiki will assume this to be a fingerprint)" | ||
596 | ," * A sub-string of a user id (without slashes, the prefix 'u:' is optional)" | ||
597 | ,"" | ||
598 | ," SUBKEY may be any of" | ||
599 | ," * The tail end of a fingerprint prefixed by 'fp:'" | ||
600 | ," * An exact match of a usage tag prefixed by 't:'" | ||
601 | ," * 40 characters of hexidecimal (kiki will assume this to be a fingerprint)" | ||
602 | ," * An exact match of a usage tag (The prefix 't:' is optional)" | ||
603 | ,"" | ||
604 | ," In parsing the spec, kiki will attempt to match the string to one of the" | ||
605 | ," above formats, in the order presented." | ||
606 | ,"" | ||
607 | ," Examples of valid SPEC strings:" | ||
608 | ,"" | ||
609 | ," fp:4A39F/tor" | ||
610 | ," u:joe/tor" | ||
611 | ," u:joe/t:tor" | ||
612 | ," u:joe/fp:4abf30" | ||
613 | ," joe/tor" | ||
614 | ," 5E24CD442AA6965D2012E62A905C24185D5379C2" | ||
615 | ] | ||
616 | 635 | ||
617 | doAutosign rt kd@(KeyData k ksigs umap submap) = ops | 636 | doAutosign rt kd@(KeyData k ksigs umap submap) = ops |
618 | where | 637 | where |
@@ -651,13 +670,15 @@ processArgs sargspec polyVariadicArgs defaultPoly args_raw = (sargs,margs) | |||
651 | trail = drop 1 trail1 | 670 | trail = drop 1 trail1 |
652 | commonArgSpec = [ ("--homedir",1) | 671 | commonArgSpec = [ ("--homedir",1) |
653 | , ("--passphrase-fd",1) | 672 | , ("--passphrase-fd",1) |
673 | , ("--help",0) | ||
654 | ] | 674 | ] |
675 | sargspec' = commonArgSpec ++ sargspec | ||
655 | (sargs,margs) = | 676 | (sargs,margs) = |
656 | (sargs, foldl' (\m (k:xs)->Map.alter (appendArgs k xs) k m) | 677 | (sargs, foldl' (\m (k:xs)->Map.alter (appendArgs k xs) k m) |
657 | Map.empty | 678 | Map.empty |
658 | gargs) | 679 | gargs) |
659 | where (sargs,vargs) = partitionStaticArguments (commonArgSpec ++ sargspec) args | 680 | where (sargs,vargs) = partitionStaticArguments sargspec' args |
660 | argspec = map fst sargspec ++ polyVariadicArgs | 681 | argspec = map fst sargspec' ++ polyVariadicArgs |
661 | args' = if map (take 1) (take 1 vargs) == ["-"] | 682 | args' = if map (take 1) (take 1 vargs) == ["-"] |
662 | then vargs | 683 | then vargs |
663 | else defaultPoly:vargs | 684 | else defaultPoly:vargs |
@@ -705,7 +726,6 @@ sync bExport bImport bSecret cmdarg args_raw = do | |||
705 | , ("--show-pem",1) | 726 | , ("--show-pem",1) |
706 | , ("--show-ssh",1) | 727 | , ("--show-ssh",1) |
707 | , ("--show-wip",1) -} | 728 | , ("--show-wip",1) -} |
708 | , ("--help",0) | ||
709 | ] | 729 | ] |
710 | polyVariadicArgs = ["--keyrings" | 730 | polyVariadicArgs = ["--keyrings" |
711 | ,"--hosts" ] | 731 | ,"--hosts" ] |
@@ -833,7 +853,63 @@ kiki "help" args = forM_ args $ \arg -> case lookup arg commands of | |||
833 | Nothing -> putStrLn $ "No help available for commmand '" ++ arg ++ "'." | 853 | Nothing -> putStrLn $ "No help available for commmand '" ++ arg ++ "'." |
834 | _ -> kiki arg ["--help"] | 854 | _ -> kiki arg ["--help"] |
835 | 855 | ||
836 | kiki "show" args = return () | 856 | kiki "show" args = do |
857 | let (sargs,margs) = processArgs sargspec polyVariadicArgs "--show" args | ||
858 | sargspec = [ ("--working",0) --("--show-wk",0) | ||
859 | , ("--all",0) --("--show-all",0) | ||
860 | , ("--whose-key",0) | ||
861 | , ("--key",1) | ||
862 | , ("--pem",1) | ||
863 | , ("--ssh",1) | ||
864 | , ("--wip",1) | ||
865 | ] | ||
866 | polyVariadicArgs = ["--show"] | ||
867 | let cap = parseCommonArgs margs | ||
868 | homespec = cap_homespec cap | ||
869 | passfd = cap_passfd cap | ||
870 | pems = [] | ||
871 | rings = [] | ||
872 | hosts = [] | ||
873 | walts = [] | ||
874 | kikiOp = KeyRingOperation | ||
875 | { kFiles = Map.fromList $ | ||
876 | [ ( HomeSec, (ConstRef, KeyRingFile passfd) ) | ||
877 | , ( HomePub, (ConstRef, KeyRingFile Nothing) ) | ||
878 | ] | ||
879 | ++ rings | ||
880 | ++ pems | ||
881 | ++ walts | ||
882 | ++ hosts | ||
883 | , kImports = Map.empty | ||
884 | , kManip = noManip | ||
885 | , homeSpec = homespec | ||
886 | } | ||
887 | |||
888 | (\f -> maybe f (const $ kiki_usage False "show") $ Map.lookup "--help" margs) $ do | ||
889 | KikiResult rt report <- runKeyRing kikiOp | ||
890 | |||
891 | input_key <- maybe (return Nothing) | ||
892 | (const $ fmap (Just . readPublicKey) Char8.getContents) | ||
893 | $ Map.lookup "--whose-key" margs | ||
894 | |||
895 | case rt of | ||
896 | KikiSuccess rt -> do -- interpret --show-* commands. | ||
897 | let grip = rtGrip rt | ||
898 | let shspec = Map.fromList [("--working", const $ show_wk (rtSecring rt) grip) | ||
899 | ,("--all",const show_all) | ||
900 | ,("--whose-key", const $ show_whose_key input_key) | ||
901 | ,("--key",\[x] -> show_key x $ fromMaybe "" grip) | ||
902 | ,("--pem",\[x] -> show_pem x $ fromMaybe "" grip) | ||
903 | ,("--ssh",\[x] -> show_ssh x $ fromMaybe "" grip) | ||
904 | ,("--wip",\[x] -> show_wip x $ fromMaybe "" grip) | ||
905 | ] | ||
906 | shargs = mapMaybe (\(x:xs) -> (,xs) <$> Map.lookup x shspec) sargs | ||
907 | |||
908 | forM_ shargs $ \(cmd,args) -> cmd args (rtKeyDB rt) | ||
909 | err -> putStrLn $ errorString err | ||
910 | |||
911 | forM_ report $ \(fname,act) -> do | ||
912 | putStrLn $ fname ++ ": " ++ reportString act | ||
837 | 913 | ||
838 | commands :: [(String,String)] | 914 | commands :: [(String,String)] |
839 | commands = | 915 | commands = |
@@ -859,4 +935,4 @@ main = do | |||
859 | cmd : args | cmd `elem` map fst commands | 935 | cmd : args | cmd `elem` map fst commands |
860 | -> kiki cmd args | 936 | -> kiki cmd args |
861 | 937 | ||
862 | _ -> kiki "help" args_raw | 938 | _ -> kiki "help" [] --args_raw |