{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} module Handler.Hosts where import Startlude hiding ( ask ) import Control.Carrier.Lift ( runM ) import Data.Conduit import qualified Data.Conduit.Binary as CB import Yesod.Core hiding ( expiresAt ) import Foundation import Handler.Register ( checkExistingPasswordRegistration , getRegistration ) import Handler.Types.Hosts import Lib.Crypto import Lib.Error import Lib.Password ( rootAccountName ) import Lib.ProductKey import Lib.SystemPaths ( injectFilesystemBaseFromContext , rootCaCertPath , SystemPath(relativeTo) ) import Settings getHostsR :: Handler HostsRes getHostsR = handleS9ErrT $ do settings <- getsYesod appSettings productKey <- liftIO . getProductKey . appFilesystemBase $ settings hostParams <- extractHostsQueryParams verifyHmac productKey hostParams mClaimedAt <- checkExistingPasswordRegistration rootAccountName case mClaimedAt of Nothing -> pure $ NullReply Just claimedAt -> do fmap HostsRes . mapExceptT (liftIO . runM . injectFilesystemBaseFromContext settings) $ getRegistration productKey claimedAt verifyHmac :: MonadIO m => Text -> HostsParams -> S9ErrT m () verifyHmac productKey params = do let computedHmacDigest = computeHmac productKey hostsParamsExpiration hostsParamsSalt unless (hostsParamsHmac == computedHmacDigest) $ throwE unauthorizedHmac where HostsParams { hostsParamsHmac, hostsParamsExpiration, hostsParamsSalt } = params unauthorizedHmac = ClientCryptographyE "Unauthorized hmac" getCertificateR :: Handler TypedContent getCertificateR = do base <- getsYesod $ appFilesystemBase . appSettings respondSource "application/x-x509-ca-cert" $ CB.sourceFile (toS $ rootCaCertPath `relativeTo` base) .| awaitForever sendChunkBS