Return 400 status for invalid hashes

This commit is contained in:
Gabriella Gonzalez
2022-06-30 13:28:50 -07:00
parent 87daaac881
commit 7f1251cc47
3 changed files with 39 additions and 7 deletions

View File

@@ -51,6 +51,7 @@ executable nix-serve-ng
, base32 , base32
, bsd-sysctl , bsd-sysctl
, bytestring , bytestring
, charset
, http-types , http-types
, managed , managed
, megaparsec , megaparsec

View File

@@ -1,16 +1,16 @@
{ mkDerivation, base, base16, base32, bsd-sysctl, bytestring { mkDerivation, base, base16, base32, bsd-sysctl, bytestring
, http-types, lib, managed, megaparsec, mtl, network, nixstore , charset, http-types, lib, managed, megaparsec, mtl, network
, nixutil, optparse-applicative, vector, wai, wai-extra, warp , nixstore, nixutil, optparse-applicative, vector, wai, wai-extra
, warp-tls , warp, warp-tls
}: }:
mkDerivation { mkDerivation {
pname = "nix-serve-ng"; pname = "nix-serve-ng";
version = "1.0.0"; version = "1.0.0";
src = ./.; src = ./..;
isLibrary = false; isLibrary = false;
isExecutable = true; isExecutable = true;
executableHaskellDepends = [ executableHaskellDepends = [
base base16 base32 bsd-sysctl bytestring http-types managed base base16 base32 bsd-sysctl bytestring charset http-types managed
megaparsec mtl network optparse-applicative vector wai wai-extra megaparsec mtl network optparse-applicative vector wai wai-extra
warp warp-tls warp warp-tls
]; ];

View File

@@ -8,6 +8,7 @@ module Main where
import Control.Monad.IO.Class (liftIO) import Control.Monad.IO.Class (liftIO)
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.CharSet.ByteSet (ByteSet(..))
import Data.Function ((&)) import Data.Function ((&))
import Network.Socket (SockAddr(..)) import Network.Socket (SockAddr(..))
import Network.Wai (Application) import Network.Wai (Application)
@@ -21,6 +22,7 @@ import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as ByteString.Char8 import qualified Data.ByteString.Char8 as ByteString.Char8
import qualified Data.ByteString.Builder as Builder import qualified Data.ByteString.Builder as Builder
import qualified Data.ByteString.Lazy as ByteString.Lazy import qualified Data.ByteString.Lazy as ByteString.Lazy
import qualified Data.CharSet.ByteSet as ByteSet
import qualified Data.Vector as Vector import qualified Data.Vector as Vector
import qualified Data.Void as Void import qualified Data.Void as Void
import qualified Network.HTTP.Types as Types import qualified Network.HTTP.Types as Types
@@ -41,6 +43,22 @@ data ApplicationOptions = ApplicationOptions
, secretKey :: Maybe ByteString , secretKey :: Maybe ByteString
} }
-- https://github.com/NixOS/nix/blob/2.8.1/src/libutil/hash.cc#L83-L84
validHashPartBytes :: ByteSet
validHashPartBytes =
ByteSet.fromList
( [ 0x30 .. 0x39 ] -- 0..9
<> [ 0x61 .. 0x64 ] -- abcd
<> [ 0x66 .. 0x6e ] -- fghijklmn
<> [ 0x70 .. 0x73 ] -- pqrs
<> [ 0x76 .. 0x7a ] -- vwxyz
)
validHashPart :: ByteString -> Bool
validHashPart hash =
ByteString.length hash == 32
&& ByteString.all (`ByteSet.member` validHashPartBytes) hash
makeApplication :: ApplicationOptions -> Application makeApplication :: ApplicationOptions -> Application
makeApplication ApplicationOptions{..} request respond = do makeApplication ApplicationOptions{..} request respond = do
let stripStore = ByteString.stripPrefix (storeDirectory <> "/") let stripStore = ByteString.stripPrefix (storeDirectory <> "/")
@@ -63,8 +81,21 @@ makeApplication ApplicationOptions{..} request respond = do
result <- Except.runExceptT do result <- Except.runExceptT do
let rawPath = Wai.rawPathInfo request let rawPath = Wai.rawPathInfo request
if | Just suffix <- ByteString.stripSuffix ".narinfo" rawPath if | Just prefix <- ByteString.stripSuffix ".narinfo" rawPath
, Just hashPart <- ByteString.stripPrefix "/" suffix -> do , Just hashPart <- ByteString.stripPrefix "/" prefix -> do
Monad.unless (validHashPart hashPart) do
let headers = [ ("Content-Type", "text/plain") ]
let builder = "Invalid hash part.\n"
let response =
Wai.responseBuilder
Types.status400
headers
builder
done response
maybeStorePath <- liftIO (Nix.queryPathFromHashPart hashPart) maybeStorePath <- liftIO (Nix.queryPathFromHashPart hashPart)
storePath <- case maybeStorePath of storePath <- case maybeStorePath of