From 46218add4570b418491cf2d6ca2c9d67978130f5 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Tue, 21 Jan 2020 04:24:58 +0530 Subject: [PATCH 01/11] Add Cookie Header for Websocket CONNECT Event Websocket Protocol has 2 main authentication schemes. Basic Authentication and Cookie Based Authentication. Therefore `Cookie` Header should be sent along the Connect Event. --- src/AsyncWebSocket.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index 52dcd75f0..524664802 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -1159,6 +1159,7 @@ void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){ const char * WS_STR_CONNECTION = "Connection"; const char * WS_STR_UPGRADE = "Upgrade"; const char * WS_STR_ORIGIN = "Origin"; +const char * WS_STR_COOKIE = "Cookie"; const char * WS_STR_VERSION = "Sec-WebSocket-Version"; const char * WS_STR_KEY = "Sec-WebSocket-Key"; const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol"; @@ -1175,6 +1176,7 @@ bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){ request->addInterestingHeader(WS_STR_CONNECTION); request->addInterestingHeader(WS_STR_UPGRADE); request->addInterestingHeader(WS_STR_ORIGIN); + request->addInterestingHeader(WS_STR_COOKIE); request->addInterestingHeader(WS_STR_VERSION); request->addInterestingHeader(WS_STR_KEY); request->addInterestingHeader(WS_STR_PROTOCOL); From b81e315662f8243b0d8133ac819bcd68dfb74735 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 15:45:43 +0530 Subject: [PATCH 02/11] Added Handshake handler for Event Source This lets users to accept or reject event source request after checking the request headers. ( like a cookie ) --- src/AsyncEventSource.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AsyncEventSource.h b/src/AsyncEventSource.h index b097fa623..f394e3035 100644 --- a/src/AsyncEventSource.h +++ b/src/AsyncEventSource.h @@ -49,6 +49,7 @@ class AsyncEventSource; class AsyncEventSourceResponse; class AsyncEventSourceClient; typedef std::function ArEventHandlerFunction; +typedef std::function ArHandshakeHandlerFunction; class AsyncEventSourceMessage { private: @@ -100,6 +101,7 @@ class AsyncEventSource: public AsyncWebHandler { String _url; LinkedList _clients; ArEventHandlerFunction _connectcb; + ArAuthHandlerFunction _authcb; public: AsyncEventSource(const String& url); ~AsyncEventSource(); @@ -107,6 +109,8 @@ class AsyncEventSource: public AsyncWebHandler { const char * url() const { return _url.c_str(); } void close(); void onConnect(ArEventHandlerFunction cb); + void onHandshake(ArHandshakeHandlerFunction cb); + void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0); size_t count() const; //number clinets connected size_t avgPacketsWaiting() const; From 358213f4eab70bbc4c454375a46c5ff10035ca6e Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 15:50:57 +0530 Subject: [PATCH 03/11] Typo Fix --- src/AsyncEventSource.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncEventSource.h b/src/AsyncEventSource.h index f394e3035..8d547aec5 100644 --- a/src/AsyncEventSource.h +++ b/src/AsyncEventSource.h @@ -101,7 +101,7 @@ class AsyncEventSource: public AsyncWebHandler { String _url; LinkedList _clients; ArEventHandlerFunction _connectcb; - ArAuthHandlerFunction _authcb; + ArHandshakeHandlerFunction _handshakecb; public: AsyncEventSource(const String& url); ~AsyncEventSource(); From dccb54c5dd7940787a34dba50c1c7932e2a2515b Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 15:51:40 +0530 Subject: [PATCH 04/11] Added relevant logic --- src/AsyncEventSource.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index f2914df54..98eee78d6 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -263,6 +263,10 @@ void AsyncEventSource::onConnect(ArEventHandlerFunction cb){ _connectcb = cb; } +void AsyncEventSource::onHandshake(ArHandshakeHandlerFunction cb){ + _handshakecb = cb; +} + void AsyncEventSource::_addClient(AsyncEventSourceClient * client){ /*char * temp = (char *)malloc(2054); if(temp != NULL){ @@ -339,7 +343,20 @@ bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){ void AsyncEventSource::handleRequest(AsyncWebServerRequest *request){ if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())) return request->requestAuthentication(); - request->send(new AsyncEventSourceResponse(this)); + + // If Custom Handshake Handler is supplied + if(_handshakecb != nullptr){ + if(_handshakecb()){ + // Request Accepted + request->send(new AsyncEventSourceResponse(this)); + }else{ + // Request Rejected. Supply unauthorised http response. + request->send(401); + } + }else{ + // No Custom Handshake Handler Supplied. Accept as default action. + request->send(new AsyncEventSourceResponse(this)); + } } // Response From 315572bf445e0733b46721b4a9c2653b4e6bedd3 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 15:54:01 +0530 Subject: [PATCH 05/11] Added Cookie Header for AsyncEventSource Plugin Allows Cookie-based authentication strategies. --- src/AsyncEventSource.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index 98eee78d6..f1db86a1b 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -337,6 +337,7 @@ bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){ return false; } request->addInterestingHeader("Last-Event-ID"); + request->addInterestingHeader("Cookie"); return true; } From d14a2d246e9c28bea6dde64d657824d1d8b9c100 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 15:56:16 +0530 Subject: [PATCH 06/11] Update AsyncEventSource.cpp --- src/AsyncEventSource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index f1db86a1b..51a84f031 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -347,7 +347,7 @@ void AsyncEventSource::handleRequest(AsyncWebServerRequest *request){ // If Custom Handshake Handler is supplied if(_handshakecb != nullptr){ - if(_handshakecb()){ + if(_handshakecb(request)){ // Request Accepted request->send(new AsyncEventSourceResponse(this)); }else{ From eca9f1597e20782617b662512791b1be2d3368c3 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 16:02:30 +0530 Subject: [PATCH 07/11] Declared custom handshake handlers for AsyncWebsocket Plugin --- src/AsyncWebSocket.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 5b03aceb9..5eb0afa7b 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -237,6 +237,7 @@ class AsyncWebSocketClient { void _onData(void *pbuf, size_t plen); }; +typedef std::function AwsHandshakeHandlerFunction; typedef std::function AwsEventHandler; //WebServer Handler implementation that plays the role of a socket server @@ -248,6 +249,7 @@ class AsyncWebSocket: public AsyncWebHandler { AsyncWebSocketClientLinkedList _clients; uint32_t _cNextId; AwsEventHandler _eventHandler; + AwsHandshakeHandlerFunction _handshakecb; bool _enabled; AsyncWebLock _lock; From fe84caae55137761d75de1dbe4f781532e8318db Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 16:05:01 +0530 Subject: [PATCH 08/11] Update AsyncWebSocket.h --- src/AsyncWebSocket.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 5eb0afa7b..2f97830bc 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -237,7 +237,7 @@ class AsyncWebSocketClient { void _onData(void *pbuf, size_t plen); }; -typedef std::function AwsHandshakeHandlerFunction; +typedef std::function AwsHandshakeHandler; typedef std::function AwsEventHandler; //WebServer Handler implementation that plays the role of a socket server @@ -249,7 +249,7 @@ class AsyncWebSocket: public AsyncWebHandler { AsyncWebSocketClientLinkedList _clients; uint32_t _cNextId; AwsEventHandler _eventHandler; - AwsHandshakeHandlerFunction _handshakecb; + AwsHandshakeHandler _handshakeHandler; bool _enabled; AsyncWebLock _lock; @@ -317,6 +317,11 @@ class AsyncWebSocket: public AsyncWebHandler { void onEvent(AwsEventHandler handler){ _eventHandler = handler; } + + // Handshake Handler + void handleHandshake(AwsHandshakeHandler handler){ + _handshakeHandler = handler; + } //system callbacks (do not call) uint32_t _getNextId(){ return _cNextId++; } From 506bcdd43e0773a61372531cfeebbcc82f848a89 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 16:11:58 +0530 Subject: [PATCH 09/11] Added relevant logic --- src/AsyncWebSocket.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index 524664802..2197cf515 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -1166,6 +1166,10 @@ const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol"; const char * WS_STR_ACCEPT = "Sec-WebSocket-Accept"; const char * WS_STR_UUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +void AsyncWebSocket::handleHandshake(AwsHandshakeHandler handler){ + _handshakeHandler = handler; +} + bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){ if(!_enabled) return false; @@ -1191,6 +1195,14 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){ if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())){ return request->requestAuthentication(); } + + if(_handshakeHandler != nullptr){ + if(!_handshakeHandler(&request){ + request->send(401); + return; + } + } + AsyncWebHeader* version = request->getHeader(WS_STR_VERSION); if(version->value().toInt() != 13){ AsyncWebServerResponse *response = request->beginResponse(400); From bd3369e968d2a62a6230dcec522afb8070bcd7a0 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 16:17:42 +0530 Subject: [PATCH 10/11] Update AsyncWebSocket.cpp --- src/AsyncWebSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index 2197cf515..caec5944c 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -1197,7 +1197,7 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){ } if(_handshakeHandler != nullptr){ - if(!_handshakeHandler(&request){ + if(!_handshakeHandler(request){ request->send(401); return; } From 01cf475bd539bb50d685713091183031072204b8 Mon Sep 17 00:00:00 2001 From: Ayush Sharma Date: Sun, 26 Jan 2020 16:35:53 +0530 Subject: [PATCH 11/11] Update AsyncWebSocket.cpp --- src/AsyncWebSocket.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index caec5944c..ff30df1d4 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -1166,9 +1166,6 @@ const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol"; const char * WS_STR_ACCEPT = "Sec-WebSocket-Accept"; const char * WS_STR_UUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; -void AsyncWebSocket::handleHandshake(AwsHandshakeHandler handler){ - _handshakeHandler = handler; -} bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){ if(!_enabled) @@ -1197,7 +1194,7 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){ } if(_handshakeHandler != nullptr){ - if(!_handshakeHandler(request){ + if(!_handshakeHandler(request)){ request->send(401); return; }