aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Crypto/Macaroon/Verifier.hs
blob: 713a9714359ea947630fe2d8ebe5c95a15894d87 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}
{-|
Module      : Crypto.Macaroon.Verifier
Copyright   : (c) 2015 Julien Tanguy
License     : BSD3

Maintainer  : julien.tanguy@jhome.fr
Stability   : experimental
Portability : portable



-}
module Crypto.Macaroon.Verifier (
    Verifier
  , verifyMacaroon
  , verifySig
  -- , verifyExact
  -- , verifyFun
  , module Data.Attoparsec.ByteString.Char8
  , verifyCavs
) where


import           Crypto.Hash
import           Data.Attoparsec.ByteString
import           Data.Attoparsec.ByteString.Char8
import           Data.Bool
import           Data.Byteable
import qualified Data.ByteString                  as BS
import           Data.Either
import           Data.Either.Validation
import           Data.Foldable
import           Data.Function
import           Data.Maybe
import           Data.Traversable

import           Crypto.Macaroon.Internal

type Verifier = Caveat -> Maybe (Either String Caveat)

verifySig :: Key -> Macaroon -> Either String Macaroon
verifySig k m = bool (Left "Signatures do not match") (Right m) $
      signature m == foldl' hash (toBytes (hmac derivedKey (identifier m) :: HMAC SHA256)) (caveats m)
  where
    hash s c = toBytes (hmac s (vid c `BS.append` cid c) :: HMAC SHA256)
    derivedKey = toBytes (hmac "macaroons-key-generator" k :: HMAC SHA256)

verifyMacaroon :: Key -> [Verifier] -> Macaroon -> Either String Macaroon
verifyMacaroon secret verifiers m = verifySig secret m >>= verifyCavs verifiers

verifyCavs :: [Verifier] -> Macaroon -> Either String Macaroon
verifyCavs verifiers m = case partitionEithers verifiedCaveats of
    ([],_) -> Right m
    (errs,_) -> Left (mconcat errs)
  where
    verifiedCaveats = map (\c -> defaultFail c $ foldMap (fmap eitherToValidation . ($c)) verifiers) $ caveats m
    defaultFail c = maybe (Left ("No validation for this caveat: " ++ show c)) validationToEither


-- TODO: define API