From 35b5dae0e08be72c0858977b408a9dac60d5a4b2 Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Thu, 26 Dec 2019 00:10:44 +0100 Subject: [PATCH] Fix integer overflow in basic password authentication The string lengths were added and then stored in "char" which is limited in values at most up to 255. Using size_t is a much more appropriate type. In addition the code was using base64 with newlines injected (easy to fall into that trap as the default is imho wrong), which means that anything longer than ~ 60 characters never matched and you had no way to authenticate against the server. --- .../src/ESP8266WebServer-impl.h | 56 ++++++++----------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h index bc094b1b6e..dbda34075e 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h @@ -121,41 +121,29 @@ String ESP8266WebServerTemplate::_extractParam(String& authReq,const } template -bool ESP8266WebServerTemplate::authenticate(const char * username, const char * password){ - if(hasHeader(FPSTR(AUTHORIZATION_HEADER))) { - String authReq = header(FPSTR(AUTHORIZATION_HEADER)); - if(authReq.startsWith(F("Basic"))){ - authReq = authReq.substring(6); - authReq.trim(); - char toencodeLen = strlen(username)+strlen(password)+1; - char *toencode = new (std::nothrow) char[toencodeLen + 1]; - if(toencode == NULL){ - authReq = ""; - return false; - } - char *encoded = new (std::nothrow) char[base64_encode_expected_len(toencodeLen)+1]; - if(encoded == NULL){ - authReq = ""; - delete[] toencode; - return false; - } - sprintf(toencode, "%s:%s", username, password); - if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equalsConstantTime(encoded)) { - authReq = ""; - delete[] toencode; - delete[] encoded; - return true; - } - delete[] toencode; - delete[] encoded; - } else if(authReq.startsWith(F("Digest"))) { - String _realm = _extractParam(authReq, F("realm=\"")); - String _H1 = credentialHash((String)username,_realm,(String)password); - return authenticateDigest((String)username,_H1); +bool ESP8266WebServerTemplate::authenticate(const char* name, const char* pass) { + if (hasHeader(FPSTR(AUTHORIZATION_HEADER))) { + String authReq = header(FPSTR(AUTHORIZATION_HEADER)); + String username(name); + String password(pass); + + if (authReq.startsWith(F("Basic"))) { + authReq = authReq.substring(6); + authReq.trim(); + String toencode; + toencode.reserve(username.length() + 1 + password.length()); + + toencode += username; + toencode += ':'; + toencode += password; + return authReq.equalsConstantTime(::base64::encode(toencode, false /* doNewLines */)); + } else if (authReq.startsWith(F("Digest"))) { + return authenticateDigest( + username, credentialHash( + username, _extractParam(authReq, F("realm=\"")), password)); + } } - authReq = ""; - } - return false; + return false; } template