Skip to content

Commit be4f5b4

Browse files
authored
Safer implementation of no-SNI connection (arduino-libraries#24)
1 parent 6588d07 commit be4f5b4

File tree

3 files changed

+152
-14
lines changed

3 files changed

+152
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
This example creates a client object that connects and transfers
3+
data using always TLS but with Server Name Indication check disabled.
4+
5+
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
6+
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
7+
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
8+
WARNING WARNING
9+
WARNING This can be useful when testing initial server configurations but makes WARNING
10+
WARNING it possible for a malicious third party to impersonate your server WARNING
11+
WARNING through DNS spoofing, for example. WARNING
12+
WARNING WARNING
13+
WARNING USE THIS OPTION IN TESTING ONLY WARNING
14+
WARNING WARNING
15+
WARNING If you need to resort to using this option in a production environment, WARNING
16+
WARNING your setup is at fault and there is no point using encryption. WARNING
17+
WARNING WARNING
18+
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
19+
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
20+
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
21+
22+
It is compatible with the methods normally related to plain
23+
connections, like client.connect(host, port).
24+
25+
Written by Arturo Guadalupi
26+
Modified by Giampaolo Mancini
27+
last revision May 2020
28+
29+
*/
30+
31+
#include <SPI.h>
32+
#include <WiFi101.h>
33+
#include <ArduinoBearSSL.h>
34+
35+
char ssid[] = "yourNetwork"; // your network SSID (name)
36+
char pass[] = "secretPassword"; // your network password (use for WPA, or use as key for WEP)
37+
int keyIndex = 0; // your network key Index number (needed only for WEP)
38+
39+
int status = WL_IDLE_STATUS;
40+
// if you don't want to use DNS (and reduce your sketch size)
41+
// use the numeric IP instead of the name for the server:
42+
//IPAddress server(192,168,1,1); // numeric IP for testing server (no DNS)
43+
char server[] = "192.168.1.1"; // name address for testing server (using DNS)
44+
45+
// Initialize the Ethernet client library
46+
// with the IP address and port of the server
47+
// that you want to connect to (port 80 is default for HTTP):
48+
WiFiClient client;
49+
BearSSLClient sslClient(client);
50+
51+
unsigned long getTime() {
52+
return WiFi.getTime();
53+
}
54+
55+
void setup() {
56+
//Initialize serial and wait for port to open:
57+
Serial.begin(9600);
58+
while (!Serial) {
59+
; // wait for serial port to connect. Needed for native USB port only
60+
}
61+
62+
// check for the presence of the shield:
63+
if (WiFi.status() == WL_NO_SHIELD) {
64+
Serial.println("WiFi shield not present");
65+
// don't continue:
66+
while (true);
67+
}
68+
69+
// attempt to connect to WiFi network:
70+
while (status != WL_CONNECTED) {
71+
Serial.print("Attempting to connect to SSID: ");
72+
Serial.println(ssid);
73+
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
74+
status = WiFi.begin(ssid, pass);
75+
76+
// wait 10 seconds for connection:
77+
delay(10000);
78+
}
79+
Serial.println("Connected to wifi");
80+
printWiFiStatus();
81+
82+
ArduinoBearSSL.onGetTime(getTime);
83+
84+
// Disable Server Name Indication:
85+
// for testing purposes only
86+
// DO NOT USE IN PRODUCTION
87+
sslClient.setInsecure(BearSSLClient::SNI::Insecure);
88+
89+
Serial.println("\nStarting connection to server...");
90+
// if you get a connection, report back via serial:
91+
if (sslClient.connect(server, 443)) {
92+
Serial.println("connected to server");
93+
// Make a HTTP request:
94+
sslClient.println("GET /search?q=arduino HTTP/1.1");
95+
sslClient.println("Host: www.google.com");
96+
sslClient.println("Connection: close");
97+
sslClient.println();
98+
}
99+
}
100+
101+
void loop() {
102+
// if there are incoming bytes available
103+
// from the server, read them and print them:
104+
while (sslClient.available()) {
105+
char c = sslClient.read();
106+
Serial.write(c);
107+
}
108+
109+
// if the server's disconnected, stop the client:
110+
if (!sslClient.connected()) {
111+
Serial.println();
112+
Serial.println("disconnecting from server.");
113+
sslClient.stop();
114+
115+
// do nothing forevermore:
116+
while (true);
117+
}
118+
}
119+
120+
121+
void printWiFiStatus() {
122+
// print the SSID of the network you're attached to:
123+
Serial.print("SSID: ");
124+
Serial.println(WiFi.SSID());
125+
126+
// print your WiFi shield's IP address:
127+
IPAddress ip = WiFi.localIP();
128+
Serial.print("IP Address: ");
129+
Serial.println(ip);
130+
131+
// print the received signal strength:
132+
long rssi = WiFi.RSSI();
133+
Serial.print("signal strength (RSSI):");
134+
Serial.print(rssi);
135+
Serial.println(" dBm");
136+
}

src/BearSSLClient.cpp

+10-12
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,15 @@
3131
#include "BearSSLClient.h"
3232

3333
BearSSLClient::BearSSLClient(Client& client) :
34-
BearSSLClient(client, TAs, TAs_NUM, false)
35-
{
36-
}
37-
38-
BearSSLClient::BearSSLClient(Client& client, bool noSNI) :
39-
BearSSLClient(client, TAs, TAs_NUM, noSNI)
34+
BearSSLClient(client, TAs, TAs_NUM)
4035
{
4136
}
4237

4338
BearSSLClient::BearSSLClient(Client& client, const br_x509_trust_anchor* myTAs, int myNumTAs) :
44-
BearSSLClient(client, myTAs, myNumTAs, false)
45-
{
46-
}
47-
48-
BearSSLClient::BearSSLClient(Client& client, const br_x509_trust_anchor* myTAs, int myNumTAs, bool noSNI) :
4939
_client(&client),
5040
_TAs(myTAs),
5141
_numTAs(myNumTAs),
52-
_noSNI(noSNI)
42+
_noSNI(false)
5343
{
5444
_ecKey.curve = 0;
5545
_ecKey.x = NULL;
@@ -189,6 +179,14 @@ BearSSLClient::operator bool()
189179
return (*_client);
190180
}
191181

182+
void BearSSLClient::setInsecure(SNI insecure)
183+
{
184+
switch (insecure) {
185+
case SNI::Insecure : _noSNI = true; break;
186+
default: _noSNI = false;
187+
}
188+
}
189+
192190
void BearSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLength)
193191
{
194192
// HACK: put the key slot info. in the br_ec_private_key structure

src/BearSSLClient.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ class BearSSLClient : public Client {
4242

4343
public:
4444
BearSSLClient(Client& client);
45-
BearSSLClient(Client& client, bool noSNI);
4645
BearSSLClient(Client& client, const br_x509_trust_anchor* myTAs, int myNumTAs);
47-
BearSSLClient(Client& client, const br_x509_trust_anchor* myTAs, int myNumTAs, bool noSNI);
4846
virtual ~BearSSLClient();
4947

5048
virtual int connect(IPAddress ip, uint16_t port);
@@ -62,6 +60,12 @@ class BearSSLClient : public Client {
6260

6361
using Print::write;
6462

63+
enum class SNI {
64+
Insecure
65+
};
66+
67+
void setInsecure(SNI insecure) __attribute__((deprecated("INSECURE. DO NOT USE IN PRODUCTION")));
68+
6569
void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength);
6670
void setEccSlot(int ecc508KeySlot, const char cert[]);
6771

0 commit comments

Comments
 (0)