diff options
Diffstat (limited to 'KeyRing.hs')
-rw-r--r-- | KeyRing.hs | 113 |
1 files changed, 84 insertions, 29 deletions
@@ -15,6 +15,7 @@ import Data.List | |||
15 | import Data.OpenPGP | 15 | import Data.OpenPGP |
16 | import Data.Functor | 16 | import Data.Functor |
17 | import Data.Monoid | 17 | import Data.Monoid |
18 | import Data.Tuple ( swap ) | ||
18 | import Data.Bits ( (.|.) ) | 19 | import Data.Bits ( (.|.) ) |
19 | import Control.Applicative ( liftA2, (<$>) ) | 20 | import Control.Applicative ( liftA2, (<$>) ) |
20 | import System.Directory ( getHomeDirectory, doesFileExist ) | 21 | import System.Directory ( getHomeDirectory, doesFileExist ) |
@@ -77,6 +78,9 @@ data FileType = KeyRingFile PassWordFile | PEMFile UsageTag | WalletFile | |||
77 | 78 | ||
78 | data RefType = ConstRef | MutableRef (Maybe Initializer) | 79 | data RefType = ConstRef | MutableRef (Maybe Initializer) |
79 | 80 | ||
81 | initializer (MutableRef x) = x | ||
82 | initializer _ = Nothing | ||
83 | |||
80 | 84 | ||
81 | data KeyRingRuntime = KeyRingRuntime | 85 | data KeyRingRuntime = KeyRingRuntime |
82 | { rtPubring :: FilePath | 86 | { rtPubring :: FilePath |
@@ -96,6 +100,7 @@ data KeyRingData = KeyRingData | |||
96 | , homeSpec :: Maybe String | 100 | , homeSpec :: Maybe String |
97 | } | 101 | } |
98 | 102 | ||
103 | resolveInputFile :: FilePath -> FilePath -> InputFile -> [FilePath] | ||
99 | resolveInputFile secring pubring = resolve | 104 | resolveInputFile secring pubring = resolve |
100 | where | 105 | where |
101 | resolve HomeSec = return secring | 106 | resolve HomeSec = return secring |
@@ -472,6 +477,44 @@ data KeySpec = | |||
472 | | KeyUidMatch String | 477 | | KeyUidMatch String |
473 | deriving Show | 478 | deriving Show |
474 | 479 | ||
480 | parseSpec :: String -> String -> (KeySpec,Maybe String) | ||
481 | parseSpec grip spec = (topspec,subspec) | ||
482 | where | ||
483 | (topspec0,subspec0) = unprefix '/' spec | ||
484 | (toptyp,top) = unprefix ':' topspec0 | ||
485 | (subtyp,sub) = unprefix ':' subspec0 | ||
486 | topspec = case () of | ||
487 | _ | null top && or [ subtyp=="fp" | ||
488 | , null subtyp && is40digitHex sub | ||
489 | ] | ||
490 | -> KeyGrip sub | ||
491 | _ | null top && null grip -> KeyUidMatch sub | ||
492 | _ | null top -> KeyGrip grip | ||
493 | _ | toptyp=="fp" || (null toptyp && is40digitHex top) | ||
494 | -> {- trace "using top" $ -} KeyGrip top | ||
495 | _ | toptyp=="u" -> KeyUidMatch top | ||
496 | _ | otherwise -> KeyUidMatch top | ||
497 | subspec = case subtyp of | ||
498 | "t" -> Just sub | ||
499 | "fp" | top=="" -> Nothing | ||
500 | "" | top=="" && is40digitHex sub -> Nothing | ||
501 | "" -> listToMaybe sub >> Just sub | ||
502 | |||
503 | is40digitHex xs = ys == xs && length ys==40 | ||
504 | where | ||
505 | ys = filter ishex xs | ||
506 | ishex c | '0' <= c && c <= '9' = True | ||
507 | | 'A' <= c && c <= 'F' = True | ||
508 | | 'a' <= c && c <= 'f' = True | ||
509 | ishex c = False | ||
510 | |||
511 | unprefix c spec = if null (snd p) then swap p else (fst p, tail (snd p)) | ||
512 | where p = break (==c) spec | ||
513 | |||
514 | |||
515 | filterMatches :: KeySpec -> [(KeyKey,KeyData)] -> [(KeyKey,KeyData)] | ||
516 | filterMatches spec ks = filter (matchSpec spec) ks | ||
517 | |||
475 | 518 | ||
476 | buildKeyDB :: FilePath -> FilePath -> Maybe String -> KeyRingData | 519 | buildKeyDB :: FilePath -> FilePath -> Maybe String -> KeyRingData |
477 | -> IO (KikiCondition ((KeyDB,Maybe String,Maybe Packet),[(FilePath,KikiReportAction)])) | 520 | -> IO (KikiCondition ((KeyDB,Maybe String,Maybe Packet),[(FilePath,KikiReportAction)])) |
@@ -494,31 +537,7 @@ buildKeyDB secring pubring grip0 keyring = do | |||
494 | 537 | ||
495 | readw wk n = fmap (n,) (readPacketsFromWallet wk n) | 538 | readw wk n = fmap (n,) (readPacketsFromWallet wk n) |
496 | 539 | ||
497 | ms <- mapM readp (files isring) | 540 | importWalletKey wk db' (top,fname,sub,tag) = do |
498 | let grip = grip0 `mplus` (fingerprint <$> fstkey) | ||
499 | where | ||
500 | fstkey = listToMaybe $ mapMaybe isSecringKey ms | ||
501 | where isSecringKey (fn,Message ps) | ||
502 | | fn==secring = listToMaybe ps | ||
503 | isSecringKey _ = Nothing | ||
504 | db_rings = foldl' (uncurry . merge) Map.empty ms | ||
505 | wk = listToMaybe $ do | ||
506 | fp <- maybeToList grip | ||
507 | elm <- Map.toList db_rings | ||
508 | guard $ matchSpec (KeyGrip fp) elm | ||
509 | return $ keyPacket (snd elm) | ||
510 | |||
511 | wms <- mapM (readw wk) (files iswallet) | ||
512 | let wallet_keys = do | ||
513 | maybeToList wk | ||
514 | (fname,xs) <- wms | ||
515 | (_,sub,(_,m)) <- xs | ||
516 | (tag,top) <- Map.toList m | ||
517 | return (top,fname,sub,tag) | ||
518 | |||
519 | doDecrypt = todo | ||
520 | |||
521 | importWalletKey db' (top,fname,sub,tag) = do | ||
522 | try db' $ \(db',report0) -> do | 541 | try db' $ \(db',report0) -> do |
523 | r <- doImportG doDecrypt | 542 | r <- doImportG doDecrypt |
524 | db' | 543 | db' |
@@ -537,12 +556,48 @@ buildKeyDB secring pubring grip0 keyring = do | |||
537 | try r $ \(db'',report) -> do | 556 | try r $ \(db'',report) -> do |
538 | return $ KikiSuccess (db'', report0 ++ report) | 557 | return $ KikiSuccess (db'', report0 ++ report) |
539 | 558 | ||
540 | db <- foldM importWalletKey (KikiSuccess (db_rings,[])) wallet_keys | 559 | doDecrypt = todo |
560 | |||
561 | -- KeyRings (todo: KikiCondition reporting?) | ||
562 | (db_rings,wk,grip) <- do | ||
563 | ms <- mapM readp (files isring) | ||
564 | let grip = grip0 `mplus` (fingerprint <$> fstkey) | ||
565 | where | ||
566 | fstkey = listToMaybe $ mapMaybe isSecringKey ms | ||
567 | where isSecringKey (fn,Message ps) | ||
568 | | fn==secring = listToMaybe ps | ||
569 | isSecringKey _ = Nothing | ||
570 | db_rings = foldl' (uncurry . merge) Map.empty ms | ||
571 | |||
572 | wk = listToMaybe $ do | ||
573 | fp <- maybeToList grip | ||
574 | elm <- Map.toList db_rings | ||
575 | guard $ matchSpec (KeyGrip fp) elm | ||
576 | return $ keyPacket (snd elm) | ||
577 | return (db_rings,wk,grip) | ||
578 | |||
579 | -- Wallets | ||
580 | wms <- mapM (readw wk) (files iswallet) | ||
581 | let wallet_keys = do | ||
582 | maybeToList wk | ||
583 | (fname,xs) <- wms | ||
584 | (_,sub,(_,m)) <- xs | ||
585 | (tag,top) <- Map.toList m | ||
586 | return (top,fname,sub,tag) | ||
587 | db <- foldM (importWalletKey wk) (KikiSuccess (db_rings,[])) wallet_keys | ||
541 | try db $ \(db,reportWallets) -> do | 588 | try db $ \(db,reportWallets) -> do |
542 | 589 | ||
543 | -- todo: import PEMFiles | 590 | -- PEM files |
544 | let imports = todo | 591 | let pems = do |
545 | db <- foldM importPEMKey (KikiSuccess (db,[])) (map snd imports) | 592 | (n,(rtyp,ftyp)) <- Map.toList $ kFiles keyring |
593 | grip <- maybeToList grip | ||
594 | (topspec,subspec) <- fmap (parseSpec grip) $ getUsage ftyp | ||
595 | n <- resolveInputFile secring pubring n | ||
596 | let ms = map fst $ filterMatches topspec (Map.toList db) | ||
597 | cmd = initializer rtyp | ||
598 | return (n,subspec,ms,cmd) | ||
599 | imports <- filterM (\(n,_,_,_) -> doesFileExist n) pems | ||
600 | db <- foldM importPEMKey (KikiSuccess (db,[])) imports | ||
546 | try db $ \(db,reportPEMs) -> do | 601 | try db $ \(db,reportPEMs) -> do |
547 | 602 | ||
548 | return $ KikiSuccess ( (db, grip, wk), reportWallets ++ reportPEMs ) | 603 | return $ KikiSuccess ( (db, grip, wk), reportWallets ++ reportPEMs ) |