Commit d541986e73f6c04b7078a52b4bde97ebd78bdc87

Authored by Wiebe Cazemier
1 parent 421a666b

Handle loading various invalid files

https://github.com/halfgaar/FlashMQ/issues/2
configfileparser.cpp
@@ -22,6 +22,7 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. @@ -22,6 +22,7 @@ License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>.
22 #include <sstream> 22 #include <sstream>
23 #include "fstream" 23 #include "fstream"
24 #include <regex> 24 #include <regex>
  25 +#include "sys/stat.h"
25 26
26 #include "openssl/ssl.h" 27 #include "openssl/ssl.h"
27 #include "openssl/err.h" 28 #include "openssl/err.h"
@@ -42,7 +43,7 @@ void ConfigFileParser::testKeyValidity(const std::string &amp;key, const std::set&lt;st @@ -42,7 +43,7 @@ void ConfigFileParser::testKeyValidity(const std::string &amp;key, const std::set&lt;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 if (access(pathToCheck.c_str(), R_OK) != 0) 48 if (access(pathToCheck.c_str(), R_OK) != 0)
48 { 49 {
@@ -50,6 +51,21 @@ void ConfigFileParser::checkFileExistsAndReadable(const std::string &amp;key, const @@ -50,6 +51,21 @@ void ConfigFileParser::checkFileExistsAndReadable(const std::string &amp;key, const
50 oss << "Error for '" << key << "': " << pathToCheck << " is not there or not readable"; 51 oss << "Error for '" << key << "': " << pathToCheck << " is not there or not readable";
51 throw ConfigFileException(oss.str()); 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 void ConfigFileParser::checkFileOrItsDirWritable(const std::string &filepath) const 71 void ConfigFileParser::checkFileOrItsDirWritable(const std::string &filepath) const
@@ -105,7 +121,7 @@ void ConfigFileParser::loadFile(bool test) @@ -105,7 +121,7 @@ void ConfigFileParser::loadFile(bool test)
105 if (path.empty()) 121 if (path.empty())
106 return; 122 return;
107 123
108 - checkFileExistsAndReadable("application config file", path); 124 + checkFileExistsAndReadable("application config file", path, 1024*1024*10);
109 125
110 std::ifstream infile(path, std::ios::in); 126 std::ifstream infile(path, std::ios::in);
111 127
@@ -236,10 +252,12 @@ void ConfigFileParser::loadFile(bool test) @@ -236,10 +252,12 @@ void ConfigFileParser::loadFile(bool test)
236 } 252 }
237 else if (key == "fullchain") 253 else if (key == "fullchain")
238 { 254 {
  255 + checkFileExistsAndReadable("SSL fullchain", value, 1024*1024);
239 curListener->sslFullchain = value; 256 curListener->sslFullchain = value;
240 } 257 }
241 if (key == "privkey") 258 if (key == "privkey")
242 { 259 {
  260 + checkFileExistsAndReadable("SSL privkey", value, 1024*1024);
243 curListener->sslPrivkey = value; 261 curListener->sslPrivkey = value;
244 } 262 }
245 if (key == "inet_protocol") 263 if (key == "inet_protocol")
@@ -278,7 +296,7 @@ void ConfigFileParser::loadFile(bool test) @@ -278,7 +296,7 @@ void ConfigFileParser::loadFile(bool test)
278 296
279 if (key == "auth_plugin") 297 if (key == "auth_plugin")
280 { 298 {
281 - checkFileExistsAndReadable(key, value); 299 + checkFileExistsAndReadable(key, value, 1024*1024*100);
282 tmpSettings->authPluginPath = value; 300 tmpSettings->authPluginPath = value;
283 } 301 }
284 302
@@ -346,11 +364,13 @@ void ConfigFileParser::loadFile(bool test) @@ -346,11 +364,13 @@ void ConfigFileParser::loadFile(bool test)
346 364
347 if (key == "mosquitto_password_file") 365 if (key == "mosquitto_password_file")
348 { 366 {
  367 + checkFileExistsAndReadable("mosquitto_password_file", value, 1024*1024*1024);
349 tmpSettings->mosquittoPasswordFile = value; 368 tmpSettings->mosquittoPasswordFile = value;
350 } 369 }
351 370
352 if (key == "mosquitto_acl_file") 371 if (key == "mosquitto_acl_file")
353 { 372 {
  373 + checkFileExistsAndReadable("mosquitto_acl_file", value, 1024*1024*1024);
354 tmpSettings->mosquittoAclFile = value; 374 tmpSettings->mosquittoAclFile = value;
355 } 375 }
356 376
configfileparser.h
@@ -24,6 +24,7 @@ License along with FlashMQ. If not, see &lt;https://www.gnu.org/licenses/&gt;. @@ -24,6 +24,7 @@ License along with FlashMQ. If not, see &lt;https://www.gnu.org/licenses/&gt;.
24 #include <vector> 24 #include <vector>
25 #include <memory> 25 #include <memory>
26 #include <list> 26 #include <list>
  27 +#include <limits>
27 28
28 #include "sslctxmanager.h" 29 #include "sslctxmanager.h"
29 #include "listener.h" 30 #include "listener.h"
@@ -44,7 +45,7 @@ class ConfigFileParser @@ -44,7 +45,7 @@ class ConfigFileParser
44 std::set<std::string> validListenKeys; 45 std::set<std::string> validListenKeys;
45 46
46 void testKeyValidity(const std::string &key, const std::set<std::string> &validKeys) const; 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 void checkFileOrItsDirWritable(const std::string &filepath) const; 49 void checkFileOrItsDirWritable(const std::string &filepath) const;
49 public: 50 public:
50 ConfigFileParser(const std::string &path); 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,6 +15,8 @@ You should have received a copy of the GNU Affero General Public
15 License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>. 15 License along with FlashMQ. If not, see <https://www.gnu.org/licenses/>.
16 */ 16 */
17 17
  18 +#include "sys/stat.h"
  19 +
18 #include "utils.h" 20 #include "utils.h"
19 21
20 #include "sys/time.h" 22 #include "sys/time.h"
@@ -465,6 +467,12 @@ void testSsl(const std::string &amp;fullchain, const std::string &amp;privkey) @@ -465,6 +467,12 @@ void testSsl(const std::string &amp;fullchain, const std::string &amp;privkey)
465 if (privkey.empty()) 467 if (privkey.empty())
466 throw ConfigFileException("No fullchain specified for private key"); 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 SslCtxManager sslCtx; 476 SslCtxManager sslCtx;
469 if (SSL_CTX_use_certificate_file(sslCtx.get(), fullchain.c_str(), SSL_FILETYPE_PEM) != 1) 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 &amp;bindAddress, int port) @@ -541,3 +549,13 @@ BindAddr getBindAddr(int family, const std::string &amp;bindAddress, int port)
541 549
542 return result; 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 +}
@@ -86,5 +86,7 @@ std::string dirnameOf(const std::string&amp; fname); @@ -86,5 +86,7 @@ std::string dirnameOf(const std::string&amp; fname);
86 86
87 BindAddr getBindAddr(int family, const std::string &bindAddress, int port); 87 BindAddr getBindAddr(int family, const std::string &bindAddress, int port);
88 88
  89 +ssize_t getFileSize(const std::string &path);
  90 +
89 91
90 #endif // UTILS_H 92 #endif // UTILS_H