Skip to content

Commit

Permalink
Merge pull request #17 from teamookla/task/POW-524/add-headers-size-l…
Browse files Browse the repository at this point in the history
…imit

POW-524: Add a maximum size limit to all headers combined
  • Loading branch information
neotron authored Jul 5, 2023
2 parents 339b4f2 + 79b45d5 commit 0b2a667
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ message("--+ Toolchain information:")
message(" +--> C Compiler: ${CMAKE_C_COMPILER}")
message(" +--> CXX Compiler: ${CMAKE_CXX_COMPILER}")
message(" +--> Environment CFLAGS: $ENV{CFLAGS}")

enable_hardening_flags()
## END OOKLA CHANGES ##

# Put the libaries and binaries that get built into directories at the
Expand Down
7 changes: 6 additions & 1 deletion Foundation/src/Thread_POSIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#if POCO_OS == POCO_OS_FREE_BSD
# include <pthread_np.h>
# include <osreldate.h>
# include <sys/thr.h>
#endif

#if defined(__sun) && defined(__SVR4)
Expand Down Expand Up @@ -285,7 +286,11 @@ long ThreadImpl::currentOsTidImpl()
#elif POCO_OS == POCO_OS_MAC_OS_X
return ::pthread_mach_thread_np(::pthread_self());
#elif POCO_OS == POCO_OS_FREE_BSD
return ::pthread_getthreadid_np();
long id;
if(thr_self(&id) < 0) {
return 0;
}
return id;
#else
pthread_t type;
return ::pthread_self();
Expand Down
9 changes: 7 additions & 2 deletions Net/include/Poco/Net/MessageHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,25 @@ class Net_API MessageHeader: public NameValueCollection
static std::string decodeWord(const std::string& text, const std::string& charset = "UTF-8");
/// Decode RFC2047 string.

// Set maximum number of bytes allows for all headers (first line excluded). Defaults to 65KiB.
static void setTotalHeaderLimit(int max);

private:
enum Limits
/// Limits for basic sanity checks when reading a header
{
DFL_NAME_LENGTH_LIMIT = 256,
DFL_VALUE_LENGTH_LIMIT = 8192,
DFL_FIELD_LIMIT = 100
};
DFL_FIELD_LIMIT = 100,
DFL_HEADER_LIMIT = 65536 // OOKLA MODIFICATION
};

int _fieldLimit;
int _nameLengthLimit;
int _valueLengthLimit;

static int _totalHeaderLimit; // OOKLA MODIFICATION

};


Expand Down
33 changes: 20 additions & 13 deletions Net/src/MessageHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
namespace Poco {
namespace Net {

// OOKLA MODIFICATION
int MessageHeader::_totalHeaderLimit = MessageHeader::DFL_HEADER_LIMIT;
// END MODIFICATION

MessageHeader::MessageHeader():
_fieldLimit(DFL_FIELD_LIMIT),
Expand Down Expand Up @@ -78,32 +81,34 @@ void MessageHeader::read(std::istream& istr)
value.reserve(64);
int ch = buf.sbumpc();
int fields = 0;
int totalBytes = 1;
while (ch != eof && ch != '\r' && ch != '\n')
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw MessageException("Too many header fields");
name.clear();
value.clear();
while (ch != eof && ch != ':' && ch != '\n' && name.length() < _nameLengthLimit) { name += ch; ch = buf.sbumpc(); }
if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines
while (ch != eof && ch != ':' && ch != '\n' && name.length() < _nameLengthLimit) { ++totalBytes; name += ch; ch = buf.sbumpc(); }
if (ch == '\n') { ++totalBytes; ch = buf.sbumpc(); continue; } // ignore invalid header lines
if (ch != ':') throw MessageException("Field name too long/no colon found");
if (ch != eof) ch = buf.sbumpc(); // ':'
while (ch != eof && Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n') ch = buf.sbumpc();
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < _valueLengthLimit) { value += ch; ch = buf.sbumpc(); }
if (ch == '\r') ch = buf.sbumpc();
if (ch == '\n')
ch = buf.sbumpc();
if (ch != eof) { ++totalBytes; ch = buf.sbumpc(); } // ':'
while (ch != eof && Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n') { ++totalBytes; ch = buf.sbumpc(); }
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < _valueLengthLimit) { ++totalBytes; value += ch; ch = buf.sbumpc(); }
if (ch == '\r') { ++totalBytes; ch = buf.sbumpc(); }
if (ch == '\n') { ++totalBytes; ch = buf.sbumpc(); }
else if (ch != eof)
throw MessageException("Field value too long/no CRLF found");
while (ch == ' ' || ch == '\t') // folding
{
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < _valueLengthLimit) { value += ch; ch = buf.sbumpc(); }
if (ch == '\r') ch = buf.sbumpc();
if (ch == '\n')
ch = buf.sbumpc();
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < _valueLengthLimit) { ++totalBytes; value += ch; ch = buf.sbumpc(); }
if (ch == '\r') { ++totalBytes; ch = buf.sbumpc(); }
if (ch == '\n') { ++totalBytes; ch = buf.sbumpc(); }
else if (ch != eof)
throw MessageException("Folded field value too long/no CRLF found");
}
if(totalBytes > _totalHeaderLimit) {
throw MessageException("Too many total bytes in headers.");
}
Poco::trimRightInPlace(value);
add(name, decodeWord(value));
++fields;
Expand All @@ -112,7 +117,9 @@ void MessageHeader::read(std::istream& istr)
istr.putback(ch);
}


void MessageHeader::setTotalHeaderLimit(int max) {
_totalHeaderLimit = max;
}
int MessageHeader::getFieldLimit() const
{
return _fieldLimit;
Expand Down

0 comments on commit 0b2a667

Please sign in to comment.