-
Notifications
You must be signed in to change notification settings - Fork 7.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support for STARTLS/STARTSSL in-band transport upgrades/renegotation (#…
…9100) * Split start_ssl_client into two phases; to allow the implementation of protocols that use some sort of in-band STARTTLS or STARTSSL signal to upgrade a plaint text connection to SSL/TLS. Examples of these protocols are XMPP, SMTP and various database TCP connections. * Remove removed setTimeout that was accidentally included (was removed for IDF >=5), bring timeout inline with the other timeouts (ints), fix cert/key checks to look if there is actually something there (all issues caught by the CI/CD on windows-latest * Quell compiler warning; use the right timeout * Newer versions of MBEDTLS make the client key struct private (and most of the x509 struct too), so absent of a non-null pointer we cannot check wether it is populated. Solve this by looking at the version (as 0 is not a valid x509 version). * Fix another \(rightfull\) compiler warning iwth the version pointer * Quell CI/CD runs on non-WiFi supporting hardare * Quell CI/CD runs on non-WiFi supporting hardare * Fix typo in directory name * Apply suggestions from code review Co-authored-by: Jan Procházka <[email protected]> * Rename Files * Remove leftover file --------- Co-authored-by: Me No Dev <[email protected]> Co-authored-by: Jan Procházka <[email protected]> Co-authored-by: Lucas Saavedra Vaz <[email protected]>
- Loading branch information
1 parent
13fac08
commit 48072ee
Showing
6 changed files
with
314 additions
and
34 deletions.
There are no files selected for viewing
Empty file.
176 changes: 176 additions & 0 deletions
176
...ClientSecure/examples/WiFiClientSecureProtocolUpgrade/WiFiClientSecureProtocolUpgrade.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
/* STARTSSL example | ||
Inline upgrading from a clear-text connection to an SSL/TLS connection. | ||
Some protocols such as SMTP, XMPP, Mysql, Postgress and others allow, or require, | ||
that you start the connection without encryption; and then send a command to switch | ||
over to encryption. | ||
E.g. a typical SMTP submission would entail a dialogue such as this: | ||
1. client connects to server in the clear | ||
2. server says hello | ||
3. client sents a EHLO | ||
4. server tells the client that it supports SSL/TLS | ||
5. client sends a 'STARTTLS' to make use of this faciltiy | ||
6. client/server negiotiate a SSL or TLS connection. | ||
7. client sends another EHLO | ||
8. server now tells the client what (else) is supported; such as additional authentication options. | ||
... conversation continues encrypted. | ||
This can be enabled in WiFiClientSecure by telling it to start in plaintext: | ||
client.setPlainStart(); | ||
and client is than a plain, TCP, connection (just as WiFiClient would be); until the client calls | ||
the method: | ||
client.startTLS(); // returns zero on error; non zero on success. | ||
After which things switch to TLS/SSL. | ||
*/ | ||
|
||
#include <WiFiClientSecure.h> | ||
|
||
#ifndef WIFI_NETWORK | ||
#define WIFI_NETWORK "YOUR Wifi SSID" | ||
#endif | ||
|
||
#ifndef WIFI_PASSWD | ||
#define WIFI_PASSWD "your-secret-password" | ||
#endif | ||
|
||
#ifndef SMTP_HOST | ||
#define SMTP_HOST "smtp.gmail.com" | ||
#endif | ||
|
||
#ifndef SMTP_PORT | ||
#define SMTP_PORT (587) // Standard (plaintext) submission port | ||
#endif | ||
|
||
const char* ssid = WIFI_NETWORK; // your network SSID (name of wifi network) | ||
const char* password = WIFI_PASSWD; // your network password | ||
const char* server = SMTP_HOST; // Server URL | ||
const int submission_port = SMTP_PORT; // submission port. | ||
|
||
WiFiClientSecure client; | ||
|
||
static bool readAllSMTPLines(); | ||
|
||
void setup() { | ||
int ret; | ||
//Initialize serial and wait for port to open: | ||
Serial.begin(115200); | ||
delay(100); | ||
|
||
Serial.print("Attempting to connect to SSID: "); | ||
Serial.print(ssid); | ||
WiFi.begin(ssid, password); | ||
|
||
// attempt to connect to Wifi network: | ||
while (WiFi.status() != WL_CONNECTED) { | ||
Serial.print("."); | ||
// wait 1 second for re-trying | ||
delay(1000); | ||
} | ||
|
||
Serial.print("Connected to "); | ||
Serial.println(ssid); | ||
|
||
Serial.printf("\nStarting connection to server: %s:%d\n", server, submission_port); | ||
|
||
|
||
// skip verification for this demo. In production one should at the very least | ||
// enable TOFU; or ideally hardcode a (CA) certificate that is trusted. | ||
client.setInsecure(); | ||
|
||
// Enable a plain-test start. | ||
client.setPlainStart(); | ||
|
||
if (!client.connect(server, SMTP_PORT)) { | ||
Serial.println("Connection failed!"); | ||
return; | ||
}; | ||
|
||
Serial.println("Connected to server (in the clear, in plaintest)"); | ||
|
||
if (!readAllSMTPLines()) goto err; | ||
|
||
Serial.println("Sending : EHLO\t\tin the clear"); | ||
client.print("EHLO there\r\n"); | ||
|
||
if (!readAllSMTPLines()) goto err; | ||
|
||
Serial.println("Sending : STARTTLS\t\tin the clear"); | ||
client.print("STARTTLS\r\n"); | ||
|
||
if (!readAllSMTPLines()) goto err; | ||
|
||
Serial.println("Upgrading connection to TLS"); | ||
if ((ret=client.startTLS()) <= 0) { | ||
Serial.printf("Upgrade connection failed: err %d\n", ret); | ||
goto err; | ||
} | ||
|
||
Serial.println("Sending : EHLO again\t\tover the now encrypted connection"); | ||
client.print("EHLO again\r\n"); | ||
|
||
if (!readAllSMTPLines()) goto err; | ||
|
||
// normally, as this point - we'd be authenticating and then be submitting | ||
// an email. This has been left out of this example. | ||
|
||
Serial.println("Sending : QUIT\t\t\tover the now encrypted connection"); | ||
client.print("QUIT\r\n"); | ||
|
||
if (!readAllSMTPLines()) goto err; | ||
|
||
Serial.println("Completed OK\n"); | ||
err: | ||
Serial.println("Closing connection"); | ||
client.stop(); | ||
} | ||
|
||
// SMTP command repsponse start with three digits and a space; | ||
// or, for continuation, with three digits and a '-'. | ||
static bool readAllSMTPLines() { | ||
String s = ""; | ||
int i; | ||
|
||
// blocking read; we cannot rely on a timeout | ||
// of a WiFiClientSecure read; as it is non | ||
// blocking. | ||
const unsigned long timeout = 15 * 1000; | ||
unsigned long start = millis(); // the timeout is for the entire CMD block response; not per character/line. | ||
while (1) { | ||
while ((i = client.available()) == 0 && millis() - start < timeout) { | ||
/* .. wait */ | ||
}; | ||
if (i == 0) { | ||
Serial.println("Timeout reading SMTP response"); | ||
return false; | ||
}; | ||
if (i < 0) | ||
break; | ||
|
||
i = client.read(); | ||
if (i < 0) | ||
break; | ||
|
||
if (i > 31 && i < 128) s += (char)i; | ||
if (i == 0x0A) { | ||
Serial.print("Receiving: "); | ||
Serial.println(s); | ||
if (s.charAt(3) == ' ') | ||
return true; | ||
s = ""; | ||
} | ||
} | ||
Serial.printf("Error reading SMTP command response line: %d\n", i); | ||
return false; | ||
} | ||
|
||
void loop() { | ||
// do nothing | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.