summaryrefslogtreecommitdiff
path: root/KeyRing.hs
diff options
context:
space:
mode:
Diffstat (limited to 'KeyRing.hs')
-rw-r--r--KeyRing.hs113
1 files changed, 84 insertions, 29 deletions
diff --git a/KeyRing.hs b/KeyRing.hs
index ced1994..52e8f67 100644
--- a/KeyRing.hs
+++ b/KeyRing.hs
@@ -15,6 +15,7 @@ import Data.List
15import Data.OpenPGP 15import Data.OpenPGP
16import Data.Functor 16import Data.Functor
17import Data.Monoid 17import Data.Monoid
18import Data.Tuple ( swap )
18import Data.Bits ( (.|.) ) 19import Data.Bits ( (.|.) )
19import Control.Applicative ( liftA2, (<$>) ) 20import Control.Applicative ( liftA2, (<$>) )
20import System.Directory ( getHomeDirectory, doesFileExist ) 21import System.Directory ( getHomeDirectory, doesFileExist )
@@ -77,6 +78,9 @@ data FileType = KeyRingFile PassWordFile | PEMFile UsageTag | WalletFile
77 78
78data RefType = ConstRef | MutableRef (Maybe Initializer) 79data RefType = ConstRef | MutableRef (Maybe Initializer)
79 80
81initializer (MutableRef x) = x
82initializer _ = Nothing
83
80 84
81data KeyRingRuntime = KeyRingRuntime 85data 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
103resolveInputFile :: FilePath -> FilePath -> InputFile -> [FilePath]
99resolveInputFile secring pubring = resolve 104resolveInputFile 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
480parseSpec :: String -> String -> (KeySpec,Maybe String)
481parseSpec 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
515filterMatches :: KeySpec -> [(KeyKey,KeyData)] -> [(KeyKey,KeyData)]
516filterMatches spec ks = filter (matchSpec spec) ks
517
475 518
476buildKeyDB :: FilePath -> FilePath -> Maybe String -> KeyRingData 519buildKeyDB :: 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 )