diff options
author | joe <joe@jerkface.net> | 2014-05-12 20:51:50 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-05-12 20:51:50 -0400 |
commit | 83c9390271cfcb9cd64d0ffab0a2713f204c2ccc (patch) | |
tree | 0b5c4a8aa69a109050d6aaedc12c452b469c6049 | |
parent | 91dd66f6478ec87aaf184daab7c44b17f9796fce (diff) |
parse email-style Date: headers when importing PEM files.
-rw-r--r-- | KeyRing.hs | 17 | ||||
-rw-r--r-- | TimeUtil.hs | 23 |
2 files changed, 35 insertions, 5 deletions
@@ -113,7 +113,7 @@ import Data.ASN1.Types ( toASN1, ASN1Object, fromASN1 | |||
113 | import Data.ASN1.BitArray ( BitArray(..), toBitArray ) | 113 | import Data.ASN1.BitArray ( BitArray(..), toBitArray ) |
114 | import Data.ASN1.Encoding ( encodeASN1, encodeASN1', decodeASN1, decodeASN1' ) | 114 | import Data.ASN1.Encoding ( encodeASN1, encodeASN1', decodeASN1, decodeASN1' ) |
115 | import Data.ASN1.BinaryEncoding ( DER(..) ) | 115 | import Data.ASN1.BinaryEncoding ( DER(..) ) |
116 | import Data.Time.Clock.POSIX ( POSIXTime, utcTimeToPOSIXSeconds ) | 116 | import Data.Time.Clock.POSIX ( POSIXTime, utcTimeToPOSIXSeconds, posixSecondsToUTCTime ) |
117 | import Data.Time.Clock ( UTCTime ) | 117 | import Data.Time.Clock ( UTCTime ) |
118 | import Data.Bits ( Bits ) | 118 | import Data.Bits ( Bits ) |
119 | import Data.Text.Encoding ( encodeUtf8 ) | 119 | import Data.Text.Encoding ( encodeUtf8 ) |
@@ -1500,9 +1500,9 @@ readSecretPEMFile fname = do | |||
1500 | let ctx = InputFileContext "" "" | 1500 | let ctx = InputFileContext "" "" |
1501 | -- Note: The key's timestamp is included in it's fingerprint. | 1501 | -- Note: The key's timestamp is included in it's fingerprint. |
1502 | -- Therefore, we should attempt to preserve it. | 1502 | -- Therefore, we should attempt to preserve it. |
1503 | timestamp <- getInputFileTime ctx fname | 1503 | stamp <- getInputFileTime ctx fname |
1504 | input <- readInputFileL ctx fname | 1504 | input <- readInputFileL ctx fname |
1505 | let dta = catMaybes $ scanAndParse (pkcs1 <> cert) $ Char8.lines input | 1505 | let edta = scanAndParse (fmap Left dateParser <> fmap Right (pkcs1 <> cert)) $ Char8.lines input |
1506 | pkcs1 = fmap (parseRSAPrivateKey . pemBlob) | 1506 | pkcs1 = fmap (parseRSAPrivateKey . pemBlob) |
1507 | $ pemParser $ Just "RSA PRIVATE KEY" | 1507 | $ pemParser $ Just "RSA PRIVATE KEY" |
1508 | cert = fmap (fmap PEMCertificate . parseCertBlob False . pemBlob) | 1508 | cert = fmap (fmap PEMCertificate . parseCertBlob False . pemBlob) |
@@ -1514,7 +1514,7 @@ readSecretPEMFile fname = do | |||
1514 | let _ = rsa :: RSAPrivateKey | 1514 | let _ = rsa :: RSAPrivateKey |
1515 | return $ PEMPacket $ SecretKeyPacket | 1515 | return $ PEMPacket $ SecretKeyPacket |
1516 | { version = 4 | 1516 | { version = 4 |
1517 | , timestamp = toEnum (fromEnum timestamp) | 1517 | , timestamp = fromTime stamp -- toEnum (fromEnum stamp) |
1518 | , key_algorithm = RSA | 1518 | , key_algorithm = RSA |
1519 | , key = [ -- public fields... | 1519 | , key = [ -- public fields... |
1520 | ('n',rsaN rsa) | 1520 | ('n',rsaN rsa) |
@@ -1532,7 +1532,14 @@ readSecretPEMFile fname = do | |||
1532 | , encrypted_data = "" | 1532 | , encrypted_data = "" |
1533 | , is_subkey = True | 1533 | , is_subkey = True |
1534 | } | 1534 | } |
1535 | return dta | 1535 | dta = catMaybes $ map snd $ scanl mergeDate (stamp,Nothing) edta |
1536 | mergeDate (_,obj) (Left tm) = (fromTime tm,obj) | ||
1537 | mergeDate (tm,_) (Right (Just (PEMPacket key))) = (tm,Just $ PEMPacket key') | ||
1538 | where key' = if tm < fromTime (timestamp key) | ||
1539 | then key { timestamp = fromTime tm } | ||
1540 | else key | ||
1541 | mergeDate (tm,_) (Right mb) = (tm,mb) | ||
1542 | return $ dta | ||
1536 | 1543 | ||
1537 | doImport | 1544 | doImport |
1538 | :: Ord k => | 1545 | :: Ord k => |
diff --git a/TimeUtil.hs b/TimeUtil.hs index 1c241a4..9c0a2b5 100644 --- a/TimeUtil.hs +++ b/TimeUtil.hs | |||
@@ -3,8 +3,10 @@ | |||
3 | module TimeUtil | 3 | module TimeUtil |
4 | ( now | 4 | ( now |
5 | , IsTime(..) | 5 | , IsTime(..) |
6 | , fromTime | ||
6 | , parseRFC2822 | 7 | , parseRFC2822 |
7 | , printRFC2822 | 8 | , printRFC2822 |
9 | , dateParser | ||
8 | ) where | 10 | ) where |
9 | 11 | ||
10 | import Data.Time.LocalTime | 12 | import Data.Time.LocalTime |
@@ -18,6 +20,8 @@ import Data.Maybe | |||
18 | import Data.Char | 20 | import Data.Char |
19 | import qualified Data.ByteString.Char8 as S | 21 | import qualified Data.ByteString.Char8 as S |
20 | import qualified Data.ByteString.Lazy.Char8 as L | 22 | import qualified Data.ByteString.Lazy.Char8 as L |
23 | import Foreign.C.Types ( CTime(..) ) | ||
24 | import Data.Word ( Word32 ) | ||
21 | 25 | ||
22 | import ScanningParser | 26 | import ScanningParser |
23 | 27 | ||
@@ -89,6 +93,25 @@ dateParser = ScanningParser ffst pbdy | |||
89 | else Nothing | 93 | else Nothing |
90 | pbdy date xs = (date,xs) | 94 | pbdy date xs = (date,xs) |
91 | 95 | ||
96 | class IsUTC a where | ||
97 | fromUTC :: UTCTime -> a | ||
98 | toUTC :: a -> UTCTime | ||
99 | |||
100 | fromTime :: ( IsUTC a, IsUTC b ) => a -> b | ||
101 | fromTime = fromUTC . toUTC | ||
102 | |||
103 | instance IsUTC UTCTime where | ||
104 | fromUTC = id | ||
105 | toUTC = id | ||
106 | |||
107 | instance IsUTC CTime where | ||
108 | fromUTC utc = CTime (round $ utcTimeToPOSIXSeconds utc) | ||
109 | toUTC (CTime t) = posixSecondsToUTCTime (realToFrac t) | ||
110 | |||
111 | instance IsUTC Word32 where | ||
112 | fromUTC utc = round $ utcTimeToPOSIXSeconds utc | ||
113 | toUTC t = posixSecondsToUTCTime (realToFrac t) | ||
114 | |||
92 | {- | 115 | {- |
93 | main = do | 116 | main = do |
94 | nowtime <- now | 117 | nowtime <- now |