Commit d541986e73f6c04b7078a52b4bde97ebd78bdc87
1 parent
421a666b
Handle loading various invalid files
https://github.com/halfgaar/FlashMQ/issues/2
Showing
4 changed files
with
45 additions
and
4 deletions
configfileparser.cpp
| ... | ... | @@ -22,6 +22,7 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. |
| 22 | 22 | #include <sstream> |
| 23 | 23 | #include "fstream" |
| 24 | 24 | #include <regex> |
| 25 | +#include "sys/stat.h" | |
| 25 | 26 | |
| 26 | 27 | #include "openssl/ssl.h" |
| 27 | 28 | #include "openssl/err.h" |
| ... | ... | @@ -42,7 +43,7 @@ void ConfigFileParser::testKeyValidity(const std::string &key, const std::set<st |
| 42 | 43 | } |
| 43 | 44 | } |
| 44 | 45 | |
| 45 | -void ConfigFileParser::checkFileExistsAndReadable(const std::string &key, const std::string &pathToCheck) const | |
| 46 | +void ConfigFileParser::checkFileExistsAndReadable(const std::string &key, const std::string &pathToCheck, ssize_t max_size) const | |
| 46 | 47 | { |
| 47 | 48 | if (access(pathToCheck.c_str(), R_OK) != 0) |
| 48 | 49 | { |
| ... | ... | @@ -50,6 +51,21 @@ void ConfigFileParser::checkFileExistsAndReadable(const std::string &key, const |
| 50 | 51 | oss << "Error for '" << key << "': " << pathToCheck << " is not there or not readable"; |
| 51 | 52 | throw ConfigFileException(oss.str()); |
| 52 | 53 | } |
| 54 | + | |
| 55 | + struct stat statbuf; | |
| 56 | + memset(&statbuf, 0, sizeof(struct stat)); | |
| 57 | + if (stat(path.c_str(), &statbuf) < 0) | |
| 58 | + throw ConfigFileException(formatString("Reading stat of '%s' failed.", pathToCheck.c_str())); | |
| 59 | + | |
| 60 | + if (!S_ISREG(statbuf.st_mode)) | |
| 61 | + { | |
| 62 | + throw ConfigFileException(formatString("Error for '%s': '%s' is not a regular file.", key.c_str(), pathToCheck.c_str())); | |
| 63 | + } | |
| 64 | + | |
| 65 | + if (statbuf.st_size > max_size) | |
| 66 | + { | |
| 67 | + throw ConfigFileException(formatString("Error for '%s': '%s' is bigger than %ld bytes.", key.c_str(), pathToCheck.c_str(), max_size)); | |
| 68 | + } | |
| 53 | 69 | } |
| 54 | 70 | |
| 55 | 71 | void ConfigFileParser::checkFileOrItsDirWritable(const std::string &filepath) const |
| ... | ... | @@ -105,7 +121,7 @@ void ConfigFileParser::loadFile(bool test) |
| 105 | 121 | if (path.empty()) |
| 106 | 122 | return; |
| 107 | 123 | |
| 108 | - checkFileExistsAndReadable("application config file", path); | |
| 124 | + checkFileExistsAndReadable("application config file", path, 1024*1024*10); | |
| 109 | 125 | |
| 110 | 126 | std::ifstream infile(path, std::ios::in); |
| 111 | 127 | |
| ... | ... | @@ -236,10 +252,12 @@ void ConfigFileParser::loadFile(bool test) |
| 236 | 252 | } |
| 237 | 253 | else if (key == "fullchain") |
| 238 | 254 | { |
| 255 | + checkFileExistsAndReadable("SSL fullchain", value, 1024*1024); | |
| 239 | 256 | curListener->sslFullchain = value; |
| 240 | 257 | } |
| 241 | 258 | if (key == "privkey") |
| 242 | 259 | { |
| 260 | + checkFileExistsAndReadable("SSL privkey", value, 1024*1024); | |
| 243 | 261 | curListener->sslPrivkey = value; |
| 244 | 262 | } |
| 245 | 263 | if (key == "inet_protocol") |
| ... | ... | @@ -278,7 +296,7 @@ void ConfigFileParser::loadFile(bool test) |
| 278 | 296 | |
| 279 | 297 | if (key == "auth_plugin") |
| 280 | 298 | { |
| 281 | - checkFileExistsAndReadable(key, value); | |
| 299 | + checkFileExistsAndReadable(key, value, 1024*1024*100); | |
| 282 | 300 | tmpSettings->authPluginPath = value; |
| 283 | 301 | } |
| 284 | 302 | |
| ... | ... | @@ -346,11 +364,13 @@ void ConfigFileParser::loadFile(bool test) |
| 346 | 364 | |
| 347 | 365 | if (key == "mosquitto_password_file") |
| 348 | 366 | { |
| 367 | + checkFileExistsAndReadable("mosquitto_password_file", value, 1024*1024*1024); | |
| 349 | 368 | tmpSettings->mosquittoPasswordFile = value; |
| 350 | 369 | } |
| 351 | 370 | |
| 352 | 371 | if (key == "mosquitto_acl_file") |
| 353 | 372 | { |
| 373 | + checkFileExistsAndReadable("mosquitto_acl_file", value, 1024*1024*1024); | |
| 354 | 374 | tmpSettings->mosquittoAclFile = value; |
| 355 | 375 | } |
| 356 | 376 | ... | ... |
configfileparser.h
| ... | ... | @@ -24,6 +24,7 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. |
| 24 | 24 | #include <vector> |
| 25 | 25 | #include <memory> |
| 26 | 26 | #include <list> |
| 27 | +#include <limits> | |
| 27 | 28 | |
| 28 | 29 | #include "sslctxmanager.h" |
| 29 | 30 | #include "listener.h" |
| ... | ... | @@ -44,7 +45,7 @@ class ConfigFileParser |
| 44 | 45 | std::set<std::string> validListenKeys; |
| 45 | 46 | |
| 46 | 47 | void testKeyValidity(const std::string &key, const std::set<std::string> &validKeys) const; |
| 47 | - void checkFileExistsAndReadable(const std::string &key, const std::string &pathToCheck) const; | |
| 48 | + void checkFileExistsAndReadable(const std::string &key, const std::string &pathToCheck, ssize_t max_size = std::numeric_limits<ssize_t>::max()) const; | |
| 48 | 49 | void checkFileOrItsDirWritable(const std::string &filepath) const; |
| 49 | 50 | public: |
| 50 | 51 | ConfigFileParser(const std::string &path); | ... | ... |
utils.cpp
| ... | ... | @@ -15,6 +15,8 @@ You should have received a copy of the GNU Affero General Public |
| 15 | 15 | License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. |
| 16 | 16 | */ |
| 17 | 17 | |
| 18 | +#include "sys/stat.h" | |
| 19 | + | |
| 18 | 20 | #include "utils.h" |
| 19 | 21 | |
| 20 | 22 | #include "sys/time.h" |
| ... | ... | @@ -465,6 +467,12 @@ void testSsl(const std::string &fullchain, const std::string &privkey) |
| 465 | 467 | if (privkey.empty()) |
| 466 | 468 | throw ConfigFileException("No fullchain specified for private key"); |
| 467 | 469 | |
| 470 | + if (getFileSize(fullchain) == 0) | |
| 471 | + throw ConfigFileException(formatString("SSL 'fullchain' file '%s' is empty or invalid", fullchain.c_str())); | |
| 472 | + | |
| 473 | + if (getFileSize(privkey) == 0) | |
| 474 | + throw ConfigFileException(formatString("SSL 'privkey' file '%s' is empty or invalid", privkey.c_str())); | |
| 475 | + | |
| 468 | 476 | SslCtxManager sslCtx; |
| 469 | 477 | if (SSL_CTX_use_certificate_file(sslCtx.get(), fullchain.c_str(), SSL_FILETYPE_PEM) != 1) |
| 470 | 478 | { |
| ... | ... | @@ -541,3 +549,13 @@ BindAddr getBindAddr(int family, const std::string &bindAddress, int port) |
| 541 | 549 | |
| 542 | 550 | return result; |
| 543 | 551 | } |
| 552 | + | |
| 553 | +ssize_t getFileSize(const std::string &path) | |
| 554 | +{ | |
| 555 | + struct stat statbuf; | |
| 556 | + memset(&statbuf, 0, sizeof(struct stat)); | |
| 557 | + if (stat(path.c_str(), &statbuf) < 0) | |
| 558 | + return -1; | |
| 559 | + | |
| 560 | + return statbuf.st_size; | |
| 561 | +} | ... | ... |