Skip to content

Commit e7a33be

Browse files
committed
authentication is working
add libb64 for base64 support (todo get espressif base64 working)
1 parent d63e8fd commit e7a33be

File tree

7 files changed

+330
-6
lines changed

7 files changed

+330
-6
lines changed

src/WebSocketsServer.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
#include "WebSockets.h"
2626
#include "WebSocketsServer.h"
2727

28+
extern "C" {
29+
#include "libb64/cencode.h"
30+
}
31+
32+
#include <Hash.h>
33+
2834
WebSocketsServer::WebSocketsServer(uint16_t port) {
2935
_port = port;
3036
_server = new WiFiServer(port);
@@ -160,7 +166,7 @@ void WebSocketsServer::handleClientData(void) {
160166
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
161167
client = &_clients[i];
162168
if(clientIsConnected(client)) {
163-
int len = client->tcp.available();
169+
int len = client->tcp.available();
164170
if(len > 0) {
165171

166172
switch(client->status) {
@@ -179,7 +185,6 @@ void WebSocketsServer::handleClientData(void) {
179185
}
180186
}
181187

182-
183188
/*
184189
[WS-Server][0] new client from 192.168.2.23
185190
[WS-Server][0][handleHeader] RX: GET /test HTTP/1.1
@@ -208,7 +213,6 @@ void WebSocketsServer::handleHeader(WSclients_t * client) {
208213
String headerLine = client->tcp.readStringUntil('\n');
209214
headerLine.trim(); // remove \r
210215

211-
212216
if(headerLine.length() > 0) {
213217
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] RX: %s\n", client->num, headerLine.c_str());
214218

@@ -226,6 +230,7 @@ void WebSocketsServer::handleHeader(WSclients_t * client) {
226230
} else if(headerLine.startsWith("Sec-WebSocket-Key: ")) {
227231
// 19 = lenght of "Sec-WebSocket-Key: "
228232
client->cKey = headerLine.substring(19);
233+
client->cKey.trim(); // see rfc6455
229234
} else if(headerLine.startsWith("Sec-WebSocket-Protocol: ")) {
230235
// 24 = lenght of "Sec-WebSocket-Protocol: "
231236
client->cProtocol = headerLine.substring(24);
@@ -263,12 +268,39 @@ void WebSocketsServer::handleHeader(WSclients_t * client) {
263268

264269
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Websocket connection incomming.\n", client->num);
265270

266-
//todo generate server key
267271

268-
//client->sKey.c_str();
272+
// generate Sec-WebSocket-Accept key
273+
uint8_t sha1HashBin[20] = {0};
274+
sha1(client->cKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", &sha1HashBin[0]);
275+
276+
char sha1Base64[64] = { 0 };
277+
int len = 0;
269278

279+
base64_encodestate _state;
280+
base64_init_encodestate(&_state);
281+
len = base64_encode_block((const char *)&sha1HashBin[0], 20, &sha1Base64[0], &_state);
282+
base64_encode_blockend((sha1Base64 + len), &_state);
283+
284+
client->sKey = sha1Base64;
285+
client->sKey.trim();
286+
287+
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - sKey: %s\n", client->num, client->sKey.c_str());
288+
289+
client->status = WSC_CONNECTED;
290+
291+
client->tcp.write("HTTP/1.1 101 Switching Protocols\r\n"
292+
"Server: ESP8266-WebSocketsServer\r\n"
293+
"Upgrade: websocket\r\n"
294+
"Connection: Upgrade\r\n"
295+
"Sec-WebSocket-Version: 13\r\n"
296+
"Sec-WebSocket-Accept: ");
297+
client->tcp.write(client->sKey.c_str(), client->sKey.length());
298+
client->tcp.write("\r\n"
299+
"Sec-WebSocket-Protocol: ");
300+
client->tcp.write(client->cProtocol.c_str(), client->cProtocol.length()); // support any protocol for now
301+
client->tcp.write("\r\n"
302+
"\r\n");
270303

271-
//client->status = WSC_CONNECTED;
272304
} else {
273305
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] no Websocket connection close.\n", client->num);
274306
client->tcp.write("HTTP/1.1 400 Bad Request\r\n"

src/libb64/AUTHORS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
libb64: Base64 Encoding/Decoding Routines
2+
======================================
3+
4+
Authors:
5+
-------
6+
7+
Chris Venter [email protected] http://rocketpod.blogspot.com

src/libb64/LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Copyright-Only Dedication (based on United States law)
2+
or Public Domain Certification
3+
4+
The person or persons who have associated work with this document (the
5+
"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
6+
his knowledge, the work of authorship identified is in the public domain of the
7+
country from which the work is published, or (b) hereby dedicates whatever
8+
copyright the dedicators holds in the work of authorship identified below (the
9+
"Work") to the public domain. A certifier, moreover, dedicates any copyright
10+
interest he may have in the associated work, and for these purposes, is
11+
described as a "dedicator" below.
12+
13+
A certifier has taken reasonable steps to verify the copyright status of this
14+
work. Certifier recognizes that his good faith efforts may not shield him from
15+
liability if in fact the work certified is not in the public domain.
16+
17+
Dedicator makes this dedication for the benefit of the public at large and to
18+
the detriment of the Dedicator's heirs and successors. Dedicator intends this
19+
dedication to be an overt act of relinquishment in perpetuity of all present
20+
and future rights under copyright law, whether vested or contingent, in the
21+
Work. Dedicator understands that such relinquishment of all rights includes
22+
the relinquishment of all rights to enforce (by lawsuit or otherwise) those
23+
copyrights in the Work.
24+
25+
Dedicator recognizes that, once placed in the public domain, the Work may be
26+
freely reproduced, distributed, transmitted, used, modified, built upon, or
27+
otherwise exploited by anyone for any purpose, commercial or non-commercial,
28+
and in any way, including by methods that have not yet been invented or
29+
conceived.

src/libb64/cdecode.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
cdecoder.c - c source to a base64 decoding algorithm implementation
3+
4+
This is part of the libb64 project, and has been placed in the public domain.
5+
For details, see http://sourceforge.net/projects/libb64
6+
*/
7+
8+
#include "cdecode.h"
9+
10+
int base64_decode_value(char value_in)
11+
{
12+
static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
13+
static const char decoding_size = sizeof(decoding);
14+
value_in -= 43;
15+
if (value_in < 0 || value_in > decoding_size) return -1;
16+
return decoding[(int)value_in];
17+
}
18+
19+
void base64_init_decodestate(base64_decodestate* state_in)
20+
{
21+
state_in->step = step_a;
22+
state_in->plainchar = 0;
23+
}
24+
25+
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
26+
{
27+
const char* codechar = code_in;
28+
char* plainchar = plaintext_out;
29+
char fragment;
30+
31+
*plainchar = state_in->plainchar;
32+
33+
switch (state_in->step)
34+
{
35+
while (1)
36+
{
37+
case step_a:
38+
do {
39+
if (codechar == code_in+length_in)
40+
{
41+
state_in->step = step_a;
42+
state_in->plainchar = *plainchar;
43+
return plainchar - plaintext_out;
44+
}
45+
fragment = (char)base64_decode_value(*codechar++);
46+
} while (fragment < 0);
47+
*plainchar = (fragment & 0x03f) << 2;
48+
case step_b:
49+
do {
50+
if (codechar == code_in+length_in)
51+
{
52+
state_in->step = step_b;
53+
state_in->plainchar = *plainchar;
54+
return plainchar - plaintext_out;
55+
}
56+
fragment = (char)base64_decode_value(*codechar++);
57+
} while (fragment < 0);
58+
*plainchar++ |= (fragment & 0x030) >> 4;
59+
*plainchar = (fragment & 0x00f) << 4;
60+
case step_c:
61+
do {
62+
if (codechar == code_in+length_in)
63+
{
64+
state_in->step = step_c;
65+
state_in->plainchar = *plainchar;
66+
return plainchar - plaintext_out;
67+
}
68+
fragment = (char)base64_decode_value(*codechar++);
69+
} while (fragment < 0);
70+
*plainchar++ |= (fragment & 0x03c) >> 2;
71+
*plainchar = (fragment & 0x003) << 6;
72+
case step_d:
73+
do {
74+
if (codechar == code_in+length_in)
75+
{
76+
state_in->step = step_d;
77+
state_in->plainchar = *plainchar;
78+
return plainchar - plaintext_out;
79+
}
80+
fragment = (char)base64_decode_value(*codechar++);
81+
} while (fragment < 0);
82+
*plainchar++ |= (fragment & 0x03f);
83+
}
84+
}
85+
/* control should not reach here */
86+
return plainchar - plaintext_out;
87+
}
88+

src/libb64/cdecode.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
cdecode.h - c header for a base64 decoding algorithm
3+
4+
This is part of the libb64 project, and has been placed in the public domain.
5+
For details, see http://sourceforge.net/projects/libb64
6+
*/
7+
8+
#ifndef BASE64_CDECODE_H
9+
#define BASE64_CDECODE_H
10+
11+
typedef enum
12+
{
13+
step_a, step_b, step_c, step_d
14+
} base64_decodestep;
15+
16+
typedef struct
17+
{
18+
base64_decodestep step;
19+
char plainchar;
20+
} base64_decodestate;
21+
22+
void base64_init_decodestate(base64_decodestate* state_in);
23+
24+
int base64_decode_value(char value_in);
25+
26+
int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
27+
28+
#endif /* BASE64_CDECODE_H */

src/libb64/cencode.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
cencoder.c - c source to a base64 encoding algorithm implementation
3+
4+
This is part of the libb64 project, and has been placed in the public domain.
5+
For details, see http://sourceforge.net/projects/libb64
6+
*/
7+
8+
#include "cencode.h"
9+
10+
const int CHARS_PER_LINE = 72;
11+
12+
void base64_init_encodestate(base64_encodestate* state_in)
13+
{
14+
state_in->step = step_A;
15+
state_in->result = 0;
16+
state_in->stepcount = 0;
17+
}
18+
19+
char base64_encode_value(char value_in)
20+
{
21+
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
22+
if (value_in > 63) return '=';
23+
return encoding[(int)value_in];
24+
}
25+
26+
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
27+
{
28+
const char* plainchar = plaintext_in;
29+
const char* const plaintextend = plaintext_in + length_in;
30+
char* codechar = code_out;
31+
char result;
32+
char fragment;
33+
34+
result = state_in->result;
35+
36+
switch (state_in->step)
37+
{
38+
while (1)
39+
{
40+
case step_A:
41+
if (plainchar == plaintextend)
42+
{
43+
state_in->result = result;
44+
state_in->step = step_A;
45+
return codechar - code_out;
46+
}
47+
fragment = *plainchar++;
48+
result = (fragment & 0x0fc) >> 2;
49+
*codechar++ = base64_encode_value(result);
50+
result = (fragment & 0x003) << 4;
51+
case step_B:
52+
if (plainchar == plaintextend)
53+
{
54+
state_in->result = result;
55+
state_in->step = step_B;
56+
return codechar - code_out;
57+
}
58+
fragment = *plainchar++;
59+
result |= (fragment & 0x0f0) >> 4;
60+
*codechar++ = base64_encode_value(result);
61+
result = (fragment & 0x00f) << 2;
62+
case step_C:
63+
if (plainchar == plaintextend)
64+
{
65+
state_in->result = result;
66+
state_in->step = step_C;
67+
return codechar - code_out;
68+
}
69+
fragment = *plainchar++;
70+
result |= (fragment & 0x0c0) >> 6;
71+
*codechar++ = base64_encode_value(result);
72+
result = (fragment & 0x03f) >> 0;
73+
*codechar++ = base64_encode_value(result);
74+
75+
++(state_in->stepcount);
76+
if (state_in->stepcount == CHARS_PER_LINE/4)
77+
{
78+
*codechar++ = '\n';
79+
state_in->stepcount = 0;
80+
}
81+
}
82+
}
83+
/* control should not reach here */
84+
return codechar - code_out;
85+
}
86+
87+
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
88+
{
89+
char* codechar = code_out;
90+
91+
switch (state_in->step)
92+
{
93+
case step_B:
94+
*codechar++ = base64_encode_value(state_in->result);
95+
*codechar++ = '=';
96+
*codechar++ = '=';
97+
break;
98+
case step_C:
99+
*codechar++ = base64_encode_value(state_in->result);
100+
*codechar++ = '=';
101+
break;
102+
case step_A:
103+
break;
104+
}
105+
*codechar++ = '\n';
106+
107+
return codechar - code_out;
108+
}
109+

src/libb64/cencode.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
cencode.h - c header for a base64 encoding algorithm
3+
4+
This is part of the libb64 project, and has been placed in the public domain.
5+
For details, see http://sourceforge.net/projects/libb64
6+
*/
7+
8+
#ifndef BASE64_CENCODE_H
9+
#define BASE64_CENCODE_H
10+
11+
typedef enum
12+
{
13+
step_A, step_B, step_C
14+
} base64_encodestep;
15+
16+
typedef struct
17+
{
18+
base64_encodestep step;
19+
char result;
20+
int stepcount;
21+
} base64_encodestate;
22+
23+
void base64_init_encodestate(base64_encodestate* state_in);
24+
25+
char base64_encode_value(char value_in);
26+
27+
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
28+
29+
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
30+
31+
#endif /* BASE64_CENCODE_H */

0 commit comments

Comments
 (0)