Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Confd / Utils.hs @ c92b4671

History | View | Annotate | Download (3.2 kB)

1 62377cf5 Iustin Pop
{-| Implementation of the Ganeti confd utilities.
2 62377cf5 Iustin Pop
3 62377cf5 Iustin Pop
This holds a few utility functions that could be useful in both
4 62377cf5 Iustin Pop
clients and servers.
5 62377cf5 Iustin Pop
6 62377cf5 Iustin Pop
-}
7 62377cf5 Iustin Pop
8 62377cf5 Iustin Pop
{-
9 62377cf5 Iustin Pop
10 62377cf5 Iustin Pop
Copyright (C) 2011, 2012 Google Inc.
11 62377cf5 Iustin Pop
12 62377cf5 Iustin Pop
This program is free software; you can redistribute it and/or modify
13 62377cf5 Iustin Pop
it under the terms of the GNU General Public License as published by
14 62377cf5 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
15 62377cf5 Iustin Pop
(at your option) any later version.
16 62377cf5 Iustin Pop
17 62377cf5 Iustin Pop
This program is distributed in the hope that it will be useful, but
18 62377cf5 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
19 62377cf5 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 62377cf5 Iustin Pop
General Public License for more details.
21 62377cf5 Iustin Pop
22 62377cf5 Iustin Pop
You should have received a copy of the GNU General Public License
23 62377cf5 Iustin Pop
along with this program; if not, write to the Free Software
24 62377cf5 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 62377cf5 Iustin Pop
02110-1301, USA.
26 62377cf5 Iustin Pop
27 62377cf5 Iustin Pop
-}
28 62377cf5 Iustin Pop
29 62377cf5 Iustin Pop
module Ganeti.Confd.Utils
30 62377cf5 Iustin Pop
  ( getClusterHmac
31 5bfcd75f Michele Tartara
  , parseSignedMessage
32 497f5cbf Michele Tartara
  , parseRequest
33 1a0defea Michele Tartara
  , parseReply
34 62377cf5 Iustin Pop
  , signMessage
35 46300ac2 Michele Tartara
  , getCurrentTime
36 62377cf5 Iustin Pop
  ) where
37 62377cf5 Iustin Pop
38 62377cf5 Iustin Pop
import qualified Data.ByteString as B
39 62377cf5 Iustin Pop
import qualified Text.JSON as J
40 62377cf5 Iustin Pop
41 62377cf5 Iustin Pop
import Ganeti.BasicTypes
42 cdc2392b Iustin Pop
import Ganeti.Confd.Types
43 62377cf5 Iustin Pop
import Ganeti.Hash
44 62377cf5 Iustin Pop
import qualified Ganeti.Constants as C
45 9eeb0aa5 Michael Hanselmann
import qualified Ganeti.Path as Path
46 f3baf5ef Iustin Pop
import Ganeti.JSON
47 26d62e4c Iustin Pop
import Ganeti.Utils
48 62377cf5 Iustin Pop
49 9d3867b1 Iustin Pop
-- | Type-adjusted max clock skew constant.
50 9d3867b1 Iustin Pop
maxClockSkew :: Integer
51 9d3867b1 Iustin Pop
maxClockSkew = fromIntegral C.confdMaxClockSkew
52 9d3867b1 Iustin Pop
53 62377cf5 Iustin Pop
-- | Returns the HMAC key.
54 62377cf5 Iustin Pop
getClusterHmac :: IO HashKey
55 29a30533 Iustin Pop
getClusterHmac = Path.confdHmacKey >>= fmap B.unpack . B.readFile
56 62377cf5 Iustin Pop
57 5bfcd75f Michele Tartara
-- | Parses a signed message.
58 5bfcd75f Michele Tartara
parseSignedMessage :: (J.JSON a) => HashKey -> String
59 5bfcd75f Michele Tartara
                   -> Result (String, String, a)
60 5bfcd75f Michele Tartara
parseSignedMessage key str = do
61 5bfcd75f Michele Tartara
  (SignedMessage hmac msg salt) <- fromJResult "parsing signed message"
62 5bfcd75f Michele Tartara
    $ J.decode str
63 5bfcd75f Michele Tartara
  parsedMsg <- if verifyMac key (Just salt) msg hmac
64 62377cf5 Iustin Pop
           then fromJResult "parsing message" $ J.decode msg
65 62377cf5 Iustin Pop
           else Bad "HMAC verification failed"
66 5bfcd75f Michele Tartara
  return (salt, msg, parsedMsg)
67 62377cf5 Iustin Pop
68 1a0defea Michele Tartara
-- | Message parsing. This can either result in a good, valid request
69 1a0defea Michele Tartara
-- message, or fail in the Result monad.
70 497f5cbf Michele Tartara
parseRequest :: HashKey -> String -> Integer
71 62377cf5 Iustin Pop
             -> Result (String, ConfdRequest)
72 497f5cbf Michele Tartara
parseRequest hmac msg curtime = do
73 5bfcd75f Michele Tartara
  (salt, origmsg, request) <- parseSignedMessage hmac msg
74 62377cf5 Iustin Pop
  ts <- tryRead "Parsing timestamp" salt::Result Integer
75 9d3867b1 Iustin Pop
  if abs (ts - curtime) > maxClockSkew
76 62377cf5 Iustin Pop
    then fail "Too old/too new timestamp or clock skew"
77 62377cf5 Iustin Pop
    else return (origmsg, request)
78 62377cf5 Iustin Pop
79 1a0defea Michele Tartara
-- | Message parsing. This can either result in a good, valid reply
80 1a0defea Michele Tartara
-- message, or fail in the Result monad.
81 1a0defea Michele Tartara
-- It also checks that the salt in the message corresponds to the one
82 1a0defea Michele Tartara
-- that is expected
83 1a0defea Michele Tartara
parseReply :: HashKey -> String -> String -> Result (String, ConfdReply)
84 1a0defea Michele Tartara
parseReply hmac msg expSalt = do
85 1a0defea Michele Tartara
  (salt, origmsg, reply) <- parseSignedMessage hmac msg
86 1a0defea Michele Tartara
  if salt /= expSalt
87 1a0defea Michele Tartara
    then fail "The received salt differs from the expected salt"
88 1a0defea Michele Tartara
    else return (origmsg, reply)
89 1a0defea Michele Tartara
90 62377cf5 Iustin Pop
-- | Signs a message with a given key and salt.
91 62377cf5 Iustin Pop
signMessage :: HashKey -> String -> String -> SignedMessage
92 62377cf5 Iustin Pop
signMessage key salt msg =
93 62377cf5 Iustin Pop
  SignedMessage { signedMsgMsg  = msg
94 62377cf5 Iustin Pop
                , signedMsgSalt = salt
95 62377cf5 Iustin Pop
                , signedMsgHmac = hmac
96 62377cf5 Iustin Pop
                }
97 62377cf5 Iustin Pop
    where hmac = computeMac key (Just salt) msg