diff options
Diffstat (limited to 'nix')
| -rw-r--r-- | nix/libstore/store-api.cc | 111 | ||||
| -rw-r--r-- | nix/libstore/store-api.hh | 18 | ||||
| -rw-r--r-- | nix/libstore/worker-protocol.hh | 3 |
3 files changed, 116 insertions, 16 deletions
diff --git a/nix/libstore/store-api.cc b/nix/libstore/store-api.cc index 26d44f78b19..6445209652e 100644 --- a/nix/libstore/store-api.cc +++ b/nix/libstore/store-api.cc | |||
| @@ -29,6 +29,71 @@ bool isStorePath(const Path & path) | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | bool isStoreName(const string & name, string & problemDescription) | ||
| 33 | { | ||
| 34 | const string validChars = "+-._?="; | ||
| 35 | if (name.empty()) { | ||
| 36 | problemDescription = "empty string is not a valid name"; | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | /* Disallow names starting with a dot for possible security | ||
| 40 | reasons (e.g., "." and ".."). */ | ||
| 41 | if (name.starts_with(".")) { | ||
| 42 | problemDescription = std::format("invalid name: `{}' (can't begin with dot)", | ||
| 43 | name); | ||
| 44 | return false; | ||
| 45 | } | ||
| 46 | for (const auto& i : name) | ||
| 47 | if (!((i >= 'A' && i <= 'Z') || | ||
| 48 | (i >= 'a' && i <= 'z') || | ||
| 49 | (i >= '0' && i <= '9') || | ||
| 50 | validChars.find(i) != string::npos)) | ||
| 51 | { | ||
| 52 | problemDescription = std::format("invalid character `{}' in name `{}'", | ||
| 53 | i, | ||
| 54 | name); | ||
| 55 | return false; | ||
| 56 | } | ||
| 57 | return true; | ||
| 58 | } | ||
| 59 | |||
| 60 | |||
| 61 | bool isStoreName(const string & name) | ||
| 62 | { | ||
| 63 | string problemDescription; /* Placeholder */ | ||
| 64 | return isStoreName(name, problemDescription); | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | void checkStoreName(const string & name) | ||
| 69 | { | ||
| 70 | string problemDescription; | ||
| 71 | if (!isStoreName(name, problemDescription)) | ||
| 72 | throw Error(problemDescription); | ||
| 73 | } | ||
| 74 | |||
| 75 | |||
| 76 | bool isStoreBasenameStrict(const string & name) | ||
| 77 | { | ||
| 78 | /* 1. At least 34 characters long | ||
| 79 | 2. First 32 characters are all nix-base32 characters | ||
| 80 | 3. 33rd character (index 32) is a dash | ||
| 81 | 4. 34th character (index 33) and those following it form a valid store | ||
| 82 | name. */ | ||
| 83 | return name.size() >= 34 | ||
| 84 | && isHash32(string(name, 0, 32)) | ||
| 85 | && name[32] == '-' | ||
| 86 | && isStoreName(string(name, 33)); | ||
| 87 | } | ||
| 88 | |||
| 89 | |||
| 90 | bool isStorePathStrict(const Path & path) | ||
| 91 | { | ||
| 92 | return isStorePath(path) | ||
| 93 | && isStoreBasenameStrict(string(path, settings.nixStore.size() + 1)); | ||
| 94 | } | ||
| 95 | |||
| 96 | |||
| 32 | void assertStorePath(const Path & path) | 97 | void assertStorePath(const Path & path) |
| 33 | { | 98 | { |
| 34 | if (!isStorePath(path)) | 99 | if (!isStorePath(path)) |
| @@ -36,6 +101,13 @@ void assertStorePath(const Path & path) | |||
| 36 | } | 101 | } |
| 37 | 102 | ||
| 38 | 103 | ||
| 104 | void assertStorePathStrict(const Path & path) | ||
| 105 | { | ||
| 106 | if (!isStorePathStrict(path)) | ||
| 107 | throw Error(std::format("path `{}' is not a valid store path", path)); | ||
| 108 | } | ||
| 109 | |||
| 110 | |||
| 39 | Path toStorePath(const Path & path) | 111 | Path toStorePath(const Path & path) |
| 40 | { | 112 | { |
| 41 | if (!isInStore(path)) | 113 | if (!isInStore(path)) |
| @@ -55,22 +127,7 @@ string storePathToName(const Path & path) | |||
| 55 | } | 127 | } |
| 56 | 128 | ||
| 57 | 129 | ||
| 58 | void checkStoreName(const string & name) | 130 | |
| 59 | { | ||
| 60 | string validChars = "+-._?="; | ||
| 61 | /* Disallow names starting with a dot for possible security | ||
| 62 | reasons (e.g., "." and ".."). */ | ||
| 63 | if (name.starts_with(".")) | ||
| 64 | throw Error(std::format("invalid name: `{}' (can't begin with dot)", name)); | ||
| 65 | for (const auto& i : name) | ||
| 66 | if (!((i >= 'A' && i <= 'Z') || | ||
| 67 | (i >= 'a' && i <= 'z') || | ||
| 68 | (i >= '0' && i <= '9') || | ||
| 69 | validChars.find(i) != string::npos)) | ||
| 70 | { | ||
| 71 | throw Error(std::format("invalid character `{}' in name `{}'", i, name)); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | 131 | ||
| 75 | 132 | ||
| 76 | /* Store paths have the following form: | 133 | /* Store paths have the following form: |
| @@ -250,6 +307,28 @@ template<class T> T readStorePaths(Source & from) | |||
| 250 | return paths; | 307 | return paths; |
| 251 | } | 308 | } |
| 252 | 309 | ||
| 310 | |||
| 253 | template PathSet readStorePaths(Source & from); | 311 | template PathSet readStorePaths(Source & from); |
| 254 | 312 | ||
| 313 | |||
| 314 | Path readStorePathStrict(Source & from) | ||
| 315 | { | ||
| 316 | Path path = readString(from); | ||
| 317 | assertStorePathStrict(path); | ||
| 318 | return path; | ||
| 319 | } | ||
| 320 | |||
| 321 | |||
| 322 | template<class T> T readStorePathsStrict(Source & from) | ||
| 323 | { | ||
| 324 | T paths = readStrings<T>(from); | ||
| 325 | for (auto& i : paths) assertStorePathStrict(i); | ||
| 326 | return paths; | ||
| 327 | } | ||
| 328 | |||
| 329 | |||
| 330 | template PathSet readStorePathsStrict(Source & from); | ||
| 331 | |||
| 255 | } | 332 | } |
| 333 | |||
| 334 | |||
diff --git a/nix/libstore/store-api.hh b/nix/libstore/store-api.hh index b57f1e10842..bc90d145a29 100644 --- a/nix/libstore/store-api.hh +++ b/nix/libstore/store-api.hh | |||
| @@ -301,6 +301,12 @@ public: | |||
| 301 | 301 | ||
| 302 | /* Throw an exception if `path' is not directly in the Nix store. */ | 302 | /* Throw an exception if `path' is not directly in the Nix store. */ |
| 303 | void assertStorePath(const Path & path); | 303 | void assertStorePath(const Path & path); |
| 304 | /* Throw an exception if `path' is not a valid path for a store item. This | ||
| 305 | requires not only that it is directly in the store (like with | ||
| 306 | assertStorePath), but also that it has a valid hash part (32 nix-base32 | ||
| 307 | characters) followed by a dash ('-') followed by a valid store name as per | ||
| 308 | isStoreName and checkStoreName. */ | ||
| 309 | void assertStorePathStrict(const Path & path); | ||
| 304 | 310 | ||
| 305 | bool isInStore(const Path & path); | 311 | bool isInStore(const Path & path); |
| 306 | bool isStorePath(const Path & path); | 312 | bool isStorePath(const Path & path); |
| @@ -308,8 +314,20 @@ bool isStorePath(const Path & path); | |||
| 308 | /* Extract the name part of the given store path. */ | 314 | /* Extract the name part of the given store path. */ |
| 309 | string storePathToName(const Path & path); | 315 | string storePathToName(const Path & path); |
| 310 | 316 | ||
| 317 | /* Return true iff `name' is a valid name for a store item. If false is | ||
| 318 | returned, `problemDescription' is set to a string suitable for use in an | ||
| 319 | Error exception. */ | ||
| 320 | bool isStoreName(const string & name, string & problemDescription); | ||
| 321 | bool isStoreName(const string & name); | ||
| 311 | void checkStoreName(const string & name); | 322 | void checkStoreName(const string & name); |
| 312 | 323 | ||
| 324 | /* Return true iff `name' is a valid basename for a store item's path, e.g. of | ||
| 325 | the form hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh-NAME, where 'h' represents a | ||
| 326 | nix-base32 character and NAME is a valid store name per isStoreName. */ | ||
| 327 | bool isStoreBasenameStrict(const string & name); | ||
| 328 | /* Return true iff `path' is a valid path for a store item. */ | ||
| 329 | bool isStorePathStrict(const Path & path); | ||
| 330 | |||
| 313 | 331 | ||
| 314 | /* Chop off the parts after the top-level store name, e.g., | 332 | /* Chop off the parts after the top-level store name, e.g., |
| 315 | /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */ | 333 | /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */ |
diff --git a/nix/libstore/worker-protocol.hh b/nix/libstore/worker-protocol.hh index ef259db2a01..8e3fb369193 100644 --- a/nix/libstore/worker-protocol.hh +++ b/nix/libstore/worker-protocol.hh | |||
| @@ -59,5 +59,8 @@ typedef enum { | |||
| 59 | Path readStorePath(Source & from); | 59 | Path readStorePath(Source & from); |
| 60 | template<class T> T readStorePaths(Source & from); | 60 | template<class T> T readStorePaths(Source & from); |
| 61 | 61 | ||
| 62 | Path readStorePathStrict(Source & from); | ||
| 63 | template<class T> T readStorePathsStrict(Source & from); | ||
| 64 | |||
| 62 | 65 | ||
| 63 | } | 66 | } |
