diff options
Diffstat (limited to 'nix/libstore/store-api.cc')
| -rw-r--r-- | nix/libstore/store-api.cc | 111 |
1 files changed, 95 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 | |||
