Skip to content

Commit b62706d

Browse files
author
QuickSander
committed
fix: basic authoriation string length off-by-one
1 parent 2207ee6 commit b62706d

File tree

5 files changed

+63
-36
lines changed

5 files changed

+63
-36
lines changed
Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
#include <ArduinoHttpServer.h>
22

3+
#include <Arduino.h>
4+
5+
36
#ifdef ESP8266 // This example is compatible with both, ATMega and ESP8266
47
#include <ESP8266WiFi.h>
58
#else
69
#include <SPI.h> //! \todo Temporary see fix: https://github.com/platformio/platformio/issues/48
710
#include <WiFi.h>
811
#endif
912

10-
const char* ssid = "";
11-
const char* password = "";
13+
const char* ssid = "***REMOVED***";
14+
const char* password = "***REMOVED***";
1215

1316
WiFiServer wifiServer(80);
1417

@@ -44,22 +47,31 @@ void loop()
4447

4548
// Retrieve 2nd part of HTTP resource.
4649
// E.g.: "on" from "/api/sensors/on"
47-
Serial.println( httpRequest.getResource()[2] );
50+
Serial.println(httpRequest.getResource()[2]);
4851

4952
// Retrieve HTTP method.
5053
// E.g.: GET / PUT / HEAD / DELETE / POST
5154
ArduinoHttpServer::Method method( ArduinoHttpServer::Method::Invalid );
5255
method = httpRequest.getMethod();
5356

54-
if( method == ArduinoHttpServer::Method::Get )
57+
// Optionally athenticate incoming request
58+
if(!httpRequest.authenticate("user", "secret"))
5559
{
56-
Serial.println("Nothing to get here.");
60+
ArduinoHttpServer::StreamHttpAuthenticateReply httpReply(client, httpRequest.getContentType());
61+
httpReply.send();
5762
}
58-
else if( method == ArduinoHttpServer::Method::Put )
63+
else
5964
{
60-
digitalWrite(13, HIGH);
65+
if( method == ArduinoHttpServer::Method::Get )
66+
{
67+
Serial.println("Nothing to get here.");
68+
}
69+
else if( method == ArduinoHttpServer::Method::Put )
70+
{
71+
Serial.println("Writing HIGH to digital pin 13.");
72+
digitalWrite(13, HIGH);
73+
}
6174
}
62-
6375
}
6476
else
6577
{

platformio.ini

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,27 @@
1212
src_dir = examples/HelloHttp
1313
lib_dir = ../
1414

15-
[env:esp01]
15+
[env:huzzah]
1616
platform = espressif8266
1717
framework = arduino
18-
board = esp01
19-
extra_scripts = ../../Tools/platformio_esptool.py
20-
lib_deps = agdl/Base64@^1.0.0
21-
22-
[env:uno]
23-
platform = atmelavr
24-
framework = arduino
25-
board = uno
18+
board = huzzah
19+
upload_port = /dev/cu.SLAB_USBtoUART
20+
monitor_port = /dev/cu.SLAB_USBtoUART
21+
monitor_speed = 115200
2622
lib_deps =
27-
WiFi
2823
agdl/Base64@^1.0.0
24+
25+
; [env:esp01]
26+
; platform = espressif8266
27+
; framework = arduino
28+
; board = esp01
29+
; extra_scripts = ../../Tools/platformio_esptool.py
30+
; lib_deps = agdl/Base64@^1.0.0
31+
32+
; [env:uno]
33+
; platform = atmelavr
34+
; framework = arduino
35+
; board = uno
36+
; lib_deps =
37+
; WiFi
38+
; agdl/Base64@^1.0.0

src/internals/HttpField.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,21 @@ const ArduinoHttpServer::HttpField::Type ArduinoHttpServer::HttpField::getType()
8282

8383
//! \brief Retrieve part of a value indicated by a zero based index.
8484
//! \details Retrieve "username:password" from "Basic username:password": call with subValueIndex 1.
85-
const ArduinoHttpServer::HttpField::SubValueString ArduinoHttpServer::HttpField::getSubValueString(size_t subValueIndex) const
85+
const ArduinoHttpServer::HttpField::SubValueStringT ArduinoHttpServer::HttpField::getSubValueString(size_t subValueIndex) const
8686
{
87-
SubValueString subValue;
87+
SubValueStringT subValue;
8888
auto startIndex(0);
8989
auto endIndex(0);
9090

91-
for(auto currentSubValueIndex=0U; currentSubValueIndex < subValueIndex; currentSubValueIndex++)
91+
for(auto currentSubValueIndex=0U; currentSubValueIndex <= subValueIndex; currentSubValueIndex++)
9292
{
9393
endIndex = m_value.indexOf(SUB_VALUE_SEPERATOR, startIndex);
9494

9595
// If separator has been found.
9696
if(endIndex >=0)
9797
{
98-
subValue = m_value.substring(startIndex + strlen(SUB_VALUE_SEPERATOR), endIndex);
99-
startIndex = endIndex;
98+
subValue = m_value.substring(startIndex + strlen(SUB_VALUE_SEPERATOR) - 1, endIndex);
99+
startIndex = endIndex+1; // One past the found string.
100100
}
101101
else
102102
{

src/internals/HttpField.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class HttpField
2323

2424
public:
2525

26-
using SubValueString = FixString<128>;
26+
using SubValueStringT = FixString<128>;
2727

2828
enum class Type: char
2929
{
@@ -34,6 +34,8 @@ class HttpField
3434
AUTHORIZATION
3535
};
3636

37+
constexpr static const char* BASIC_AUTH_TYPE_STR = "Basic";
38+
3739
HttpField(const char* fieldLine);
3840
HttpField();
3941
virtual ~HttpField();
@@ -45,13 +47,13 @@ class HttpField
4547
const Type getType() const;
4648

4749
inline const String& getValueAsString() const {return m_value; };
48-
const SubValueString getSubValueString(size_t subValueIndex) const;
50+
const SubValueStringT getSubValueString(size_t subValueIndex) const;
4951
inline const int getValueAsInt() const {return m_value.toInt(); };
5052

5153
private:
5254
void determineType(const String& typeStr);
5355

54-
static const char *SEPERATOR;
56+
static const char* SEPERATOR;
5557
static const char* SUB_VALUE_SEPERATOR;
5658
static const char* CONTENT_TYPE_STR;
5759
static const char* CONTENT_LENGTH_TYPE_STR;

src/internals/StreamHttpRequest.hpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class StreamHttpRequest
6565
const ErrorString getError() const;
6666
Stream& getStream() { return m_stream; };
6767

68-
// Check if authenticated request
68+
// Validate if client provided credentials match _username_ and _password_.
6969
bool authenticate(const char * username, const char * password) const;
7070

7171
private:
@@ -85,8 +85,6 @@ class StreamHttpRequest
8585
static const long LINE_READ_TIMEOUT_MS = 10000L; //!< [ms] Wait 10s for reception of a complete line.
8686
static const int MAX_RETRIES_WAIT_DATA_AVAILABLE = 255;
8787

88-
constexpr static const char* BASIC_AUTH_TYPE_STR = "Basic";
89-
9088
void parseRequest(char lineBuffer[MAX_LINE_SIZE]);
9189
void parseMethod(char lineBuffer[MAX_LINE_SIZE]);
9290
void parseResource();
@@ -391,20 +389,25 @@ bool ArduinoHttpServer::StreamHttpRequest<MAX_BODY_SIZE>::authenticate(const cha
391389

392390
// HTTP value: "<Type> <Base 64 encoded credentials>"
393391
// Retrieve type and verify wether it is basic authorization.
394-
if(!(m_authorizationField.getSubValueString(0) == BASIC_AUTH_TYPE_STR))
392+
if(!(m_authorizationField.getSubValueString(0) == HttpField::BASIC_AUTH_TYPE_STR))
395393
{
396-
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Unsupported authentication header: ");
397-
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN(m_authorizationField);
394+
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Unsupported authentication type: ");
395+
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN(m_authorizationField.getSubValueString(0).cStr());
398396
return false;
399397
}
400398

401-
FixString<128U> combinedInput;
402-
combinedInput += username; combinedInput += AHS_F(":"); combinedInput += password;
399+
FixString<128U> combinedInput(username);
400+
combinedInput += AHS_F(":");
401+
combinedInput += password;
403402

404403
const int encodedLength = Base64.encodedLength(combinedInput.length());
405-
char encodedString[encodedLength] = {0};
406-
Base64.encode(encodedString, combinedInput.cStr(), combinedInput.length());
404+
405+
char encodedString[encodedLength+1]; // Base64 makes sure _encodedString_ is zero terminated.
406+
Base64.encode(encodedString, const_cast<char*>(combinedInput.cStr()), combinedInput.length());
407407

408+
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Credentials string in client supplied auth: ");
409+
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN(m_authorizationField.getSubValueString(1).cStr() );
410+
408411
if ( m_authorizationField.getSubValueString(1) == encodedString )
409412
{
410413
return true;

0 commit comments

Comments
 (0)