Skip to content

Commit

Permalink
WiFiClientSecure: don't trash unread decrypted data when writing
Browse files Browse the repository at this point in the history
When application requests to write data, check if there is any unread
decrypted data left. If there is, don't write immediately, but save the
data to be written. When all decrypted data has been consumed by the
application, send out the saved outgoing data.

Fixes #2256.
  • Loading branch information
igrr committed Dec 25, 2017
1 parent 9913e52 commit 87b7d5e
Showing 1 changed file with 112 additions and 1 deletion.
113 changes: 112 additions & 1 deletion libraries/ESP8266WiFi/src/WiFiClientSecure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern "C"
{
#include "osapi.h"
#include "ets_sys.h"
#include "queue.h"
}
#include <errno.h>
#include "debug.h"
Expand All @@ -50,6 +51,28 @@ extern "C"
#define SSL_DEBUG_OPTS 0
#endif


typedef struct BufferItem
{
size_t size;
STAILQ_ENTRY(BufferItem) next;
uint8_t data[0];

static BufferItem* Create(const uint8_t* data, size_t size)
{
BufferItem* newItem = (BufferItem*) calloc(1, sizeof(BufferItem) + size);
if (newItem == nullptr) {
return nullptr;
}
newItem->size = size;
memcpy(newItem->data, data, size);
return newItem;
}

} BufferItem;

typedef STAILQ_HEAD(BufferList, BufferItem) BufferList;

class SSLContext
{
public:
Expand All @@ -59,6 +82,7 @@ class SSLContext
_ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER | SSL_DEBUG_OPTS | SSL_CONNECT_IN_PARTS | SSL_READ_BLOCKING | SSL_NO_DEFAULT_KEY, 0);
}
++_ssl_ctx_refcnt;
STAILQ_INIT(&_writeBuffers);
}

~SSLContext()
Expand Down Expand Up @@ -139,6 +163,10 @@ class SSLContext
_available -= will_copy;
if (_available == 0) {
_read_ptr = nullptr;
/* Send pending outgoing data, if any */
if (_hasWriteBuffers()) {
_writeBuffersSend();
}
}
return will_copy;
}
Expand All @@ -155,10 +183,34 @@ class SSLContext
--_available;
if (_available == 0) {
_read_ptr = nullptr;
/* Send pending outgoing data, if any */
if (_hasWriteBuffers()) {
_writeBuffersSend();
}
}
return result;
}

int write(const uint8_t* src, size_t size)
{
if (!_available) {
if (_hasWriteBuffers()) {
int rc = _writeBuffersSend();
if (rc < 0) {
return rc;
}
}
return _write(src, size);
}
/* Some received data is still present in the axtls fragment buffer.
We can't call ssl_write now, as that will overwrite the contents of
the fragment buffer, corrupting the received data.
Save a copy of the outgoing data, and call ssl_write when all
recevied data has been consumed by the application.
*/
return _writeBufferAdd(src, size);
}

int peek()
{
if (!_available) {
Expand Down Expand Up @@ -282,12 +334,71 @@ class SSLContext
return _available;
}

int _write(const uint8_t* src, size_t size)
{
if (!_ssl) {
return 0;
}

int rc = ssl_write(_ssl, src, size);
if (rc >= 0) {
return rc;
}
return rc;
}

int _writeBufferAdd(const uint8_t* data, size_t size)
{
if (!_ssl) {
return 0;
}

BufferItem* newItem = BufferItem::Create(data, size);
if (newItem == nullptr) {
return SSL_NOT_OK;
}
STAILQ_INSERT_TAIL(&_writeBuffers, newItem, next);
return size;
}

int _writeBuffersSend()
{
BufferItem* it;
BufferItem* tmp;
STAILQ_FOREACH_SAFE(it, &_writeBuffers, next, tmp) {
STAILQ_REMOVE_HEAD(&_writeBuffers, next);
int rc = _write(it->data, it->size);
free(it);
if (rc < 0) {
_writeBuffersDiscard();
return rc;
}
}
return 0;
}

void _writeBuffersDiscard()
{
BufferItem* it;
BufferItem* tmp;
STAILQ_FOREACH_SAFE(it, &_writeBuffers, next, tmp) {
STAILQ_REMOVE_HEAD(&_writeBuffers, next);
free(it);
}
}

bool _hasWriteBuffers()
{
return !STAILQ_EMPTY(&_writeBuffers);
}

static SSL_CTX* _ssl_ctx;
static int _ssl_ctx_refcnt;
SSL* _ssl = nullptr;
int _refcnt = 0;
const uint8_t* _read_ptr = nullptr;
size_t _available = 0;
BufferList _writeBuffers;
bool _allowSelfSignedCerts = false;
static ClientContext* s_io_ctx;
};
Expand Down Expand Up @@ -371,7 +482,7 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
return 0;
}

int rc = ssl_write(*_ssl, buf, size);
int rc = _ssl->write(buf, size);
if (rc >= 0) {
return rc;
}
Expand Down

0 comments on commit 87b7d5e

Please sign in to comment.