mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Add SSL enabled WiFiServer, Updater, WebServer
Adds SSL server mode for WiFiServerSecure, for plain SSL connections, ESP8266WebServerSecure, for HTTPS web serving, and SecureHTTPSUpdater for encrypted OTA updates. Example code is provided for all new options, as well as a BASH script for generating their own, self-signed certificates. Both ESP8266WebServerSecure and SecureHTTPSUpdater are important for secure password-based authentication. HTTP Basic Authentication, the only supported model presently, sends the username and password in *cleartext* and therefore should *never* be used in any un-SSL encrypted channel unless you don't mind sharing your login and password with anyone else on the internet. Even if the ESP8266 is not safety critical, this cleartext broadcast could expose you should you reuse this password elsewhere on your network or the internet.
This commit is contained in:
parent
8765da258b
commit
bd1c7ce1dc
@ -0,0 +1,188 @@
|
||||
/*
|
||||
SecureHTTPSUpdater - SSL encrypted, password-protected firmware update
|
||||
|
||||
This example starts a HTTPS server on the ESP8266 to allow firmware updates
|
||||
to be performed. All communication, including the username and password,
|
||||
is encrypted via SSL. Be sure to update the SSID and PASSWORD before running
|
||||
to allow connection to your WiFi network.
|
||||
|
||||
IMPORTANT NOTES ABOUT SSL CERTIFICATES
|
||||
|
||||
1. USE/GENERATE YOUR OWN CERTIFICATES
|
||||
While a sample, self-signed certificate is included in this example,
|
||||
it is ABSOLUTELY VITAL that you use your own SSL certificate in any
|
||||
real-world deployment. Anyone with the certificate and key may be
|
||||
able to decrypt your traffic, so your own keys should be kept in a
|
||||
safe manner, not accessible on any public network.
|
||||
|
||||
2. HOW TO GENERATE YOUR OWN CERTIFICATE/KEY PAIR
|
||||
A sample script, "make-self-signed-cert.sh" is provided in the
|
||||
ESP8266WiFi/examples/WiFiHTTPSServer directory. This script can be
|
||||
modified (replace "your-name-here" with your Organization name). Note
|
||||
that this will be a *self-signed certificate* and will *NOT* be accepted
|
||||
by default by most modern browsers. They'll display something like,
|
||||
"This certificate is from an untrusted source," or "Your connection is
|
||||
not secure," or "Your connection is not private," and the user will
|
||||
have to manully allow the browser to continue by using the
|
||||
"Advanced/Add Exception" (FireFox) or "Advanced/Proceed" (Chrome) link.
|
||||
|
||||
You may also, of course, use a commercial, trusted SSL provider to
|
||||
generate your certificate. When requesting the certificate, you'll
|
||||
need to specify that it use SHA256 and 1024 or 512 bits in order to
|
||||
function with the axTLS implementation in the ESP8266.
|
||||
|
||||
Interactive usage:
|
||||
Go to https://esp8266-webupdate.local/firmware, enter the username
|
||||
and password, and the select a new BIN to upload.
|
||||
|
||||
To upload through terminal you can use:
|
||||
curl -u admin:admin -F "image=@firmware.bin" esp8266-webupdate.local/firmware
|
||||
|
||||
Adapted by Earle F. Philhower, III, from the SecureWebUpdater.ino example.
|
||||
This example is released into the public domain.
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServerSecure.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
|
||||
const char* host = "esp8266-webupdate";
|
||||
const char* update_path = "/firmware";
|
||||
const char* update_username = "admin";
|
||||
const char* update_password = "admin";
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
ESP8266WebServerSecure httpServer(443);
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
|
||||
// The certificate is stored in PMEM
|
||||
static const uint8_t x509[] PROGMEM = {
|
||||
0x30, 0x82, 0x01, 0xc9, 0x30, 0x82, 0x01, 0x32, 0x02, 0x09, 0x00, 0xe6,
|
||||
0x60, 0x8d, 0xa3, 0x47, 0x8f, 0x57, 0x7a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x29,
|
||||
0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x70,
|
||||
0x73, 0x79, 0x63, 0x68, 0x6f, 0x70, 0x6c, 0x75, 0x67, 0x31, 0x12, 0x30,
|
||||
0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e,
|
||||
0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30,
|
||||
0x32, 0x32, 0x34, 0x30, 0x38, 0x30, 0x35, 0x33, 0x36, 0x5a, 0x17, 0x0d,
|
||||
0x33, 0x30, 0x31, 0x31, 0x30, 0x33, 0x30, 0x38, 0x30, 0x35, 0x33, 0x36,
|
||||
0x5a, 0x30, 0x29, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
|
||||
0x0c, 0x0a, 0x70, 0x73, 0x79, 0x63, 0x68, 0x6f, 0x70, 0x6c, 0x75, 0x67,
|
||||
0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x31,
|
||||
0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9f, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
|
||||
0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
|
||||
0x00, 0xb6, 0x59, 0xd0, 0x57, 0xbc, 0x3e, 0xb9, 0xa0, 0x6c, 0xf5, 0xd5,
|
||||
0x46, 0x49, 0xaa, 0x9a, 0xb3, 0xbf, 0x09, 0xa9, 0xbb, 0x82, 0x3b, 0xdf,
|
||||
0xb7, 0xe3, 0x5a, 0x8e, 0x31, 0xf7, 0x27, 0xdf, 0xaa, 0xed, 0xa3, 0xd6,
|
||||
0xf6, 0x74, 0x35, 0xfc, 0x8d, 0x0b, 0xbc, 0xa2, 0x96, 0x10, 0x57, 0xe8,
|
||||
0xb2, 0xaa, 0x94, 0xf2, 0x47, 0x12, 0x4e, 0x3f, 0x7c, 0x5e, 0x90, 0xfe,
|
||||
0xad, 0x75, 0x88, 0xca, 0x7b, 0x9a, 0x18, 0x15, 0xbe, 0x3d, 0xe0, 0x31,
|
||||
0xb5, 0x45, 0x7f, 0xe7, 0x9d, 0x22, 0x99, 0x65, 0xba, 0x63, 0x70, 0x81,
|
||||
0x3b, 0x37, 0x22, 0x97, 0x64, 0xc5, 0x57, 0x8c, 0x98, 0x9c, 0x10, 0x36,
|
||||
0x98, 0xf0, 0x0b, 0x19, 0x28, 0x16, 0x9a, 0x40, 0x31, 0x5f, 0xbc, 0xd9,
|
||||
0x8e, 0x73, 0x68, 0xe1, 0x6a, 0x5d, 0x91, 0x0b, 0x4f, 0x73, 0xa4, 0x6b,
|
||||
0x8f, 0xa5, 0xad, 0x12, 0x09, 0x32, 0xa7, 0x66, 0x3b, 0x02, 0x03, 0x01,
|
||||
0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x1b, 0x46, 0x78,
|
||||
0xd1, 0xfa, 0x21, 0xc1, 0xd6, 0x75, 0xc0, 0x83, 0x59, 0x57, 0x05, 0xd5,
|
||||
0xae, 0xf8, 0x8c, 0x78, 0x03, 0x65, 0x3b, 0xbf, 0xef, 0x70, 0x3f, 0x78,
|
||||
0xc6, 0xe1, 0x5a, 0xac, 0xb1, 0x93, 0x5b, 0x41, 0x35, 0x45, 0x47, 0xf8,
|
||||
0x07, 0x86, 0x40, 0x34, 0xa2, 0x9e, 0x2a, 0x16, 0x8d, 0xea, 0xf9, 0x1e,
|
||||
0x1f, 0xd7, 0x70, 0xb4, 0x28, 0x6b, 0xd8, 0xf5, 0x3f, 0x33, 0x3f, 0xc2,
|
||||
0x2c, 0x69, 0xf2, 0xa3, 0x54, 0x4d, 0xbf, 0x7d, 0xf9, 0xde, 0x05, 0x0c,
|
||||
0x9c, 0xe3, 0x1b, 0x72, 0x07, 0x7b, 0x41, 0x76, 0x1a, 0x57, 0x03, 0x5d,
|
||||
0xb2, 0xff, 0x4c, 0x17, 0xbd, 0xd7, 0x73, 0x32, 0x98, 0x26, 0x6b, 0x2c,
|
||||
0xc4, 0xbf, 0x6e, 0x01, 0x36, 0x8b, 0xbf, 0x00, 0x48, 0x9c, 0xfb, 0x3d,
|
||||
0x7d, 0x76, 0x1f, 0x55, 0x96, 0x43, 0xc5, 0x4e, 0xc1, 0xa3, 0xa1, 0x6a,
|
||||
0x94, 0x5f, 0x84, 0x3a, 0xdd
|
||||
};
|
||||
|
||||
// And so is the key. These could also be in DRAM
|
||||
static const uint8_t rsakey[] PROGMEM = {
|
||||
0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xb6,
|
||||
0x59, 0xd0, 0x57, 0xbc, 0x3e, 0xb9, 0xa0, 0x6c, 0xf5, 0xd5, 0x46, 0x49,
|
||||
0xaa, 0x9a, 0xb3, 0xbf, 0x09, 0xa9, 0xbb, 0x82, 0x3b, 0xdf, 0xb7, 0xe3,
|
||||
0x5a, 0x8e, 0x31, 0xf7, 0x27, 0xdf, 0xaa, 0xed, 0xa3, 0xd6, 0xf6, 0x74,
|
||||
0x35, 0xfc, 0x8d, 0x0b, 0xbc, 0xa2, 0x96, 0x10, 0x57, 0xe8, 0xb2, 0xaa,
|
||||
0x94, 0xf2, 0x47, 0x12, 0x4e, 0x3f, 0x7c, 0x5e, 0x90, 0xfe, 0xad, 0x75,
|
||||
0x88, 0xca, 0x7b, 0x9a, 0x18, 0x15, 0xbe, 0x3d, 0xe0, 0x31, 0xb5, 0x45,
|
||||
0x7f, 0xe7, 0x9d, 0x22, 0x99, 0x65, 0xba, 0x63, 0x70, 0x81, 0x3b, 0x37,
|
||||
0x22, 0x97, 0x64, 0xc5, 0x57, 0x8c, 0x98, 0x9c, 0x10, 0x36, 0x98, 0xf0,
|
||||
0x0b, 0x19, 0x28, 0x16, 0x9a, 0x40, 0x31, 0x5f, 0xbc, 0xd9, 0x8e, 0x73,
|
||||
0x68, 0xe1, 0x6a, 0x5d, 0x91, 0x0b, 0x4f, 0x73, 0xa4, 0x6b, 0x8f, 0xa5,
|
||||
0xad, 0x12, 0x09, 0x32, 0xa7, 0x66, 0x3b, 0x02, 0x03, 0x01, 0x00, 0x01,
|
||||
0x02, 0x81, 0x81, 0x00, 0xa8, 0x55, 0xf9, 0x33, 0x45, 0x20, 0x52, 0x94,
|
||||
0x7a, 0x81, 0xe6, 0xc4, 0xe0, 0x34, 0x92, 0x63, 0xe4, 0xb3, 0xb2, 0xf0,
|
||||
0xda, 0xa5, 0x13, 0x3d, 0xda, 0xb0, 0x3a, 0x1c, 0x7e, 0x21, 0x5d, 0x25,
|
||||
0x9a, 0x03, 0x69, 0xea, 0x52, 0x15, 0x94, 0x73, 0x50, 0xa6, 0x6f, 0x21,
|
||||
0x41, 0x2d, 0x26, 0x2f, 0xe9, 0xb1, 0x5e, 0x87, 0xa5, 0xaa, 0x7e, 0x88,
|
||||
0xfd, 0x73, 0xb4, 0xe7, 0xc4, 0x5c, 0xe7, 0x2d, 0xeb, 0x9e, 0x6b, 0xe1,
|
||||
0xf1, 0x38, 0x45, 0xf4, 0x10, 0x12, 0xac, 0x79, 0x40, 0x72, 0xf0, 0x45,
|
||||
0x89, 0x5c, 0x9d, 0x8b, 0x7b, 0x5d, 0x69, 0xd9, 0x11, 0xf9, 0x25, 0xff,
|
||||
0xe1, 0x2a, 0xb3, 0x6d, 0x49, 0x18, 0x8d, 0x38, 0x0a, 0x6f, 0x0f, 0xbd,
|
||||
0x48, 0xd0, 0xdd, 0xcb, 0x41, 0x5c, 0x2a, 0x75, 0xa0, 0x51, 0x43, 0x4a,
|
||||
0x0b, 0xf6, 0xa2, 0xd2, 0xe9, 0xda, 0x37, 0xca, 0x2d, 0xd7, 0x22, 0x01,
|
||||
0x02, 0x41, 0x00, 0xe7, 0x11, 0xea, 0x93, 0xf4, 0x0b, 0xe6, 0xa0, 0x1a,
|
||||
0x57, 0x2d, 0xee, 0x96, 0x05, 0x5c, 0xa1, 0x08, 0x8f, 0x9c, 0xac, 0x9a,
|
||||
0x72, 0x60, 0x5a, 0x41, 0x2a, 0x92, 0x38, 0x36, 0xa5, 0xfe, 0xb9, 0x35,
|
||||
0xb2, 0x06, 0xbb, 0x02, 0x58, 0xc8, 0x93, 0xd6, 0x09, 0x6f, 0x57, 0xd7,
|
||||
0xc1, 0x2e, 0x90, 0xb3, 0x09, 0xdd, 0x0c, 0x63, 0x99, 0x91, 0xb7, 0xe4,
|
||||
0xcc, 0x6f, 0x78, 0x24, 0xbc, 0x3b, 0x7b, 0x02, 0x41, 0x00, 0xca, 0x06,
|
||||
0x4a, 0x09, 0x36, 0x08, 0xaa, 0x27, 0x08, 0x91, 0x86, 0xc5, 0x17, 0x14,
|
||||
0x6e, 0x24, 0x9a, 0x86, 0xd1, 0xbc, 0x41, 0xb1, 0x42, 0x5e, 0xe8, 0x80,
|
||||
0x5a, 0x8f, 0x7c, 0x9b, 0xe8, 0xcc, 0x28, 0xe1, 0xa2, 0x8f, 0xe9, 0xdc,
|
||||
0x60, 0xd5, 0x00, 0x34, 0x76, 0x32, 0x36, 0x00, 0x93, 0x69, 0x6b, 0xab,
|
||||
0xc6, 0x8b, 0x70, 0x95, 0x4e, 0xc2, 0x27, 0x4a, 0x24, 0x73, 0xbf, 0xcd,
|
||||
0x24, 0x41, 0x02, 0x40, 0x40, 0x46, 0x75, 0x90, 0x0e, 0x54, 0xb9, 0x24,
|
||||
0x53, 0xef, 0x68, 0x31, 0x73, 0xbd, 0xae, 0x14, 0x85, 0x43, 0x1d, 0x7b,
|
||||
0xcd, 0xc2, 0x7f, 0x16, 0xdc, 0x05, 0xb1, 0x82, 0xbd, 0x80, 0xd3, 0x28,
|
||||
0x45, 0xcd, 0x6d, 0x9d, 0xdb, 0x7b, 0x42, 0xe0, 0x0c, 0xab, 0xb7, 0x33,
|
||||
0x22, 0x2a, 0xf4, 0x7e, 0xff, 0xae, 0x80, 0xb4, 0x8f, 0x88, 0x0a, 0x46,
|
||||
0xb2, 0xf8, 0x43, 0x11, 0x92, 0x76, 0x61, 0xbd, 0x02, 0x40, 0x5c, 0x86,
|
||||
0x3a, 0xdc, 0x33, 0x1a, 0x0e, 0xcb, 0xa7, 0xb9, 0xf6, 0xae, 0x47, 0x5e,
|
||||
0xbc, 0xff, 0x18, 0xa2, 0x8c, 0x66, 0x1a, 0xf4, 0x13, 0x00, 0xa2, 0x9d,
|
||||
0x3e, 0x5c, 0x9e, 0xe6, 0x4c, 0xdd, 0x4c, 0x0f, 0xe2, 0xc2, 0xe4, 0x89,
|
||||
0x60, 0xf3, 0xcc, 0x8f, 0x3a, 0x5e, 0xce, 0xaa, 0xbe, 0xd8, 0xb6, 0x4e,
|
||||
0x4a, 0xb5, 0x4c, 0x0f, 0xa5, 0xad, 0x78, 0x0f, 0x15, 0xd8, 0xc9, 0x4c,
|
||||
0x2b, 0xc1, 0x02, 0x40, 0x4e, 0xe9, 0x78, 0x48, 0x94, 0x11, 0x75, 0xc1,
|
||||
0xa2, 0xc7, 0xff, 0xf0, 0x73, 0xa2, 0x93, 0xd7, 0x67, 0xc7, 0xf8, 0x96,
|
||||
0xac, 0x15, 0xaa, 0xe5, 0x5d, 0x18, 0x18, 0x29, 0xa9, 0x9a, 0xfc, 0xac,
|
||||
0x48, 0x4d, 0xa0, 0xca, 0xa2, 0x34, 0x09, 0x7c, 0x13, 0x22, 0x4c, 0xfc,
|
||||
0x31, 0x75, 0xa0, 0x21, 0x1e, 0x7a, 0x91, 0xbc, 0xb1, 0x97, 0xde, 0x43,
|
||||
0xe1, 0x40, 0x2b, 0xe3, 0xbd, 0x98, 0x44, 0xad
|
||||
};
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println("Booting Sketch...");
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while(WiFi.waitForConnectResult() != WL_CONNECTED){
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("WiFi failed, retrying.");
|
||||
}
|
||||
|
||||
MDNS.begin(host);
|
||||
|
||||
httpServer.setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
|
||||
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
|
||||
httpServer.begin();
|
||||
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
Serial.printf("HTTPSUpdateServer ready!\nOpen https://%s.local%s in "\
|
||||
"your browser and login with username '%s' and password "\
|
||||
"'%s'\n", host, update_path, update_username, update_password);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
httpServer.handleClient();
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
/*
|
||||
HelloServerSecure - Simple HTTPS server example
|
||||
|
||||
This example demonstrates a basic ESP8266WebServerSecure HTTPS server
|
||||
that can serve "/" and "/inline" and generate detailed 404 (not found)
|
||||
HTTP respoinses. Be sure to update the SSID and PASSWORD before running
|
||||
to allow connection to your WiFi network.
|
||||
|
||||
IMPORTANT NOTES ABOUT SSL CERTIFICATES
|
||||
|
||||
1. USE/GENERATE YOUR OWN CERTIFICATES
|
||||
While a sample, self-signed certificate is included in this example,
|
||||
it is ABSOLUTELY VITAL that you use your own SSL certificate in any
|
||||
real-world deployment. Anyone with the certificate and key may be
|
||||
able to decrypt your traffic, so your own keys should be kept in a
|
||||
safe manner, not accessible on any public network.
|
||||
|
||||
2. HOW TO GENERATE YOUR OWN CERTIFICATE/KEY PAIR
|
||||
A sample script, "make-self-signed-cert.sh" is provided in the
|
||||
ESP8266WiFi/examples/WiFiHTTPSServer directory. This script can be
|
||||
modified (replace "your-name-here" with your Organization name). Note
|
||||
that this will be a *self-signed certificate* and will *NOT* be accepted
|
||||
by default by most modern browsers. They'll display something like,
|
||||
"This certificate is from an untrusted source," or "Your connection is
|
||||
not secure," or "Your connection is not private," and the user will
|
||||
have to manully allow the browser to continue by using the
|
||||
"Advanced/Add Exception" (FireFox) or "Advanced/Proceed" (Chrome) link.
|
||||
|
||||
You may also, of course, use a commercial, trusted SSL provider to
|
||||
generate your certificate. When requesting the certificate, you'll
|
||||
need to specify that it use SHA256 and 1024 or 512 bits in order to
|
||||
function with the axTLS implementation in the ESP8266.
|
||||
|
||||
Interactive usage:
|
||||
Go to https://esp8266-webupdate.local/firmware, enter the username
|
||||
and password, and the select a new BIN to upload.
|
||||
|
||||
To upload through terminal you can use:
|
||||
curl -u admin:admin -F "image=@firmware.bin" esp8266-webupdate.local/firmware
|
||||
|
||||
Adapted by Earle F. Philhower, III, from the HelloServer.ino example.
|
||||
This example is released into the public domain.
|
||||
*/
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServerSecure.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
ESP8266WebServerSecure server(443);
|
||||
|
||||
// The certificate is stored in PMEM
|
||||
static const uint8_t x509[] PROGMEM = {
|
||||
0x30, 0x82, 0x01, 0x3d, 0x30, 0x81, 0xe8, 0x02, 0x09, 0x00, 0xfe, 0x56,
|
||||
0x46, 0xf2, 0x78, 0xc6, 0x51, 0x17, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x26, 0x31,
|
||||
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
|
||||
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
|
||||
0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x38, 0x31,
|
||||
0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x31,
|
||||
0x32, 0x35, 0x31, 0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x30, 0x26, 0x31,
|
||||
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
|
||||
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
|
||||
0x31, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02,
|
||||
0x41, 0x00, 0xc6, 0x72, 0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7,
|
||||
0x3a, 0x2a, 0x5a, 0x49, 0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6,
|
||||
0xbb, 0xa3, 0xd6, 0x6f, 0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33,
|
||||
0x50, 0x80, 0xec, 0x49, 0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d,
|
||||
0x81, 0x85, 0x23, 0x24, 0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3,
|
||||
0x3c, 0x10, 0x40, 0x05, 0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
|
||||
0x05, 0x00, 0x03, 0x41, 0x00, 0x69, 0xdc, 0x6c, 0x9b, 0xa7, 0x62, 0x57,
|
||||
0x7e, 0x03, 0x01, 0x45, 0xad, 0x9a, 0x83, 0x90, 0x3a, 0xe7, 0xdf, 0xe8,
|
||||
0x8f, 0x46, 0x00, 0xd3, 0x5f, 0x2b, 0x0a, 0xde, 0x92, 0x1b, 0xc5, 0x04,
|
||||
0xc5, 0xc0, 0x76, 0xf4, 0xf6, 0x08, 0x36, 0x97, 0x27, 0x82, 0xf1, 0x60,
|
||||
0x76, 0xc2, 0xcd, 0x67, 0x6c, 0x4b, 0x6c, 0xca, 0xfd, 0x97, 0xfd, 0x33,
|
||||
0x9e, 0x12, 0x67, 0x6b, 0x98, 0x7e, 0xd5, 0x80, 0x8f
|
||||
};
|
||||
|
||||
// And so is the key. These could also be in DRAM
|
||||
static const uint8_t rsakey[] PROGMEM = {
|
||||
0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xc6, 0x72,
|
||||
0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7, 0x3a, 0x2a, 0x5a, 0x49,
|
||||
0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6, 0xbb, 0xa3, 0xd6, 0x6f,
|
||||
0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33, 0x50, 0x80, 0xec, 0x49,
|
||||
0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d, 0x81, 0x85, 0x23, 0x24,
|
||||
0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3, 0x3c, 0x10, 0x40, 0x05,
|
||||
0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x35, 0x0b, 0x74,
|
||||
0xd3, 0xff, 0x15, 0x51, 0x44, 0x0f, 0x13, 0x2e, 0x9b, 0x0f, 0x93, 0x5c,
|
||||
0x3f, 0xfc, 0xf1, 0x17, 0xf9, 0x72, 0x94, 0x5e, 0xa7, 0xc6, 0xb3, 0xf0,
|
||||
0xfe, 0xc9, 0x6c, 0xb1, 0x1e, 0x83, 0xb3, 0xc6, 0x45, 0x3a, 0x25, 0x60,
|
||||
0x7c, 0x3d, 0x92, 0x7d, 0x53, 0xec, 0x49, 0x8d, 0xb5, 0x45, 0x10, 0x99,
|
||||
0x9b, 0xc6, 0x22, 0x3a, 0x68, 0xc7, 0x13, 0x4e, 0xb6, 0x04, 0x61, 0x21,
|
||||
0x01, 0x02, 0x21, 0x00, 0xea, 0x8c, 0x21, 0xd4, 0x7f, 0x3f, 0xb6, 0x91,
|
||||
0xfa, 0xf8, 0xb9, 0x2d, 0xcb, 0x36, 0x36, 0x02, 0x5f, 0xf0, 0x0c, 0x6e,
|
||||
0x87, 0xaa, 0x5c, 0x14, 0xf6, 0x56, 0x8e, 0x12, 0x92, 0x25, 0xde, 0xb3,
|
||||
0x02, 0x21, 0x00, 0xd8, 0x99, 0x01, 0xf1, 0x04, 0x0b, 0x98, 0xa3, 0x71,
|
||||
0x56, 0x1d, 0xea, 0x6f, 0x45, 0xd1, 0x36, 0x70, 0x76, 0x8b, 0xab, 0x69,
|
||||
0x30, 0x58, 0x9c, 0xe0, 0x45, 0x97, 0xe7, 0xb6, 0xb5, 0xef, 0xc1, 0x02,
|
||||
0x21, 0x00, 0xa2, 0x01, 0x06, 0xc0, 0xf2, 0xdf, 0xbc, 0x28, 0x1a, 0xb4,
|
||||
0xbf, 0x9b, 0x5c, 0xd8, 0x65, 0xf7, 0xbf, 0xf2, 0x5b, 0x73, 0xe0, 0xeb,
|
||||
0x0f, 0xcd, 0x3e, 0xd5, 0x4c, 0x2e, 0x91, 0x99, 0xec, 0xb7, 0x02, 0x20,
|
||||
0x4b, 0x9d, 0x46, 0xd7, 0x3c, 0x01, 0x4c, 0x5d, 0x2a, 0xb0, 0xd4, 0xaa,
|
||||
0xc6, 0x03, 0xca, 0xa0, 0xc5, 0xac, 0x2c, 0xe0, 0x3f, 0x4d, 0x98, 0x71,
|
||||
0xd3, 0xbd, 0x97, 0xe5, 0x55, 0x9c, 0xb8, 0x41, 0x02, 0x20, 0x02, 0x42,
|
||||
0x9f, 0xd1, 0x06, 0x35, 0x3b, 0x42, 0xf5, 0x64, 0xaf, 0x6d, 0xbf, 0xcd,
|
||||
0x2c, 0x3a, 0xcd, 0x0a, 0x9a, 0x4d, 0x7c, 0xad, 0x29, 0xd6, 0x36, 0x57,
|
||||
0xd5, 0xdf, 0x34, 0xeb, 0x26, 0x03
|
||||
};
|
||||
|
||||
const int led = 13;
|
||||
|
||||
void handleRoot() {
|
||||
digitalWrite(led, 1);
|
||||
server.send(200, "text/plain", "Hello from esp8266 over HTTPS!");
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void handleNotFound(){
|
||||
digitalWrite(led, 1);
|
||||
String message = "File Not Found\n\n";
|
||||
message += "URI: ";
|
||||
message += server.uri();
|
||||
message += "\nMethod: ";
|
||||
message += (server.method() == HTTP_GET)?"GET":"POST";
|
||||
message += "\nArguments: ";
|
||||
message += server.args();
|
||||
message += "\n";
|
||||
for (uint8_t i=0; i<server.args(); i++){
|
||||
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
|
||||
}
|
||||
server.send(404, "text/plain", message);
|
||||
digitalWrite(led, 0);
|
||||
}
|
||||
|
||||
void setup(void){
|
||||
pinMode(led, OUTPUT);
|
||||
digitalWrite(led, 0);
|
||||
Serial.begin(115200);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (MDNS.begin("esp8266")) {
|
||||
Serial.println("MDNS responder started");
|
||||
}
|
||||
|
||||
server.setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
|
||||
|
||||
server.on("/", handleRoot);
|
||||
|
||||
server.on("/inline", [](){
|
||||
server.send(200, "text/plain", "this works as well");
|
||||
});
|
||||
|
||||
server.onNotFound(handleNotFound);
|
||||
|
||||
server.begin();
|
||||
Serial.println("HTTPS server started");
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
server.handleClient();
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#######################################
|
||||
|
||||
ESP8266WebServer KEYWORD1
|
||||
ESP8266WebServerSecure KEYWORD1
|
||||
HTTPMethod KEYWORD1
|
||||
|
||||
#######################################
|
||||
|
@ -282,6 +282,7 @@ void ESP8266WebServer::handleClient() {
|
||||
if (_currentClient.connected()) {
|
||||
switch (_currentStatus) {
|
||||
case HC_NONE:
|
||||
// No-op to avoid C++ compiler warning
|
||||
break;
|
||||
case HC_WAIT_READ:
|
||||
// Wait for data from client to become available
|
||||
@ -384,7 +385,7 @@ void ESP8266WebServer::send(int code, const char* content_type, const String& co
|
||||
//if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET)
|
||||
// _contentLength = CONTENT_LENGTH_UNKNOWN;
|
||||
_prepareHeader(header, code, content_type, content.length());
|
||||
_currentClient.write(header.c_str(), header.length());
|
||||
_currentClientWrite(header.c_str(), header.length());
|
||||
if(content.length())
|
||||
sendContent(content);
|
||||
}
|
||||
@ -400,7 +401,7 @@ void ESP8266WebServer::send_P(int code, PGM_P content_type, PGM_P content) {
|
||||
char type[64];
|
||||
memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type));
|
||||
_prepareHeader(header, code, (const char* )type, contentLength);
|
||||
_currentClient.write(header.c_str(), header.length());
|
||||
_currentClientWrite(header.c_str(), header.length());
|
||||
sendContent_P(content);
|
||||
}
|
||||
|
||||
@ -428,11 +429,11 @@ void ESP8266WebServer::sendContent(const String& content) {
|
||||
char * chunkSize = (char *)malloc(11);
|
||||
if(chunkSize){
|
||||
sprintf(chunkSize, "%x%s", len, footer);
|
||||
_currentClient.write(chunkSize, strlen(chunkSize));
|
||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||
free(chunkSize);
|
||||
}
|
||||
}
|
||||
_currentClient.write(content.c_str(), len);
|
||||
_currentClientWrite(content.c_str(), len);
|
||||
if(_chunked){
|
||||
_currentClient.write(footer, 2);
|
||||
if (len == 0) {
|
||||
@ -451,11 +452,11 @@ void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
|
||||
char * chunkSize = (char *)malloc(11);
|
||||
if(chunkSize){
|
||||
sprintf(chunkSize, "%x%s", size, footer);
|
||||
_currentClient.write(chunkSize, strlen(chunkSize));
|
||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||
free(chunkSize);
|
||||
}
|
||||
}
|
||||
_currentClient.write_P(content, size);
|
||||
_currentClientWrite_P(content, size);
|
||||
if(_chunked){
|
||||
_currentClient.write(footer, 2);
|
||||
if (size == 0) {
|
||||
|
@ -71,12 +71,12 @@ class ESP8266WebServer
|
||||
public:
|
||||
ESP8266WebServer(IPAddress addr, int port = 80);
|
||||
ESP8266WebServer(int port = 80);
|
||||
~ESP8266WebServer();
|
||||
virtual ~ESP8266WebServer();
|
||||
|
||||
void begin();
|
||||
void handleClient();
|
||||
virtual void begin();
|
||||
virtual void handleClient();
|
||||
|
||||
void close();
|
||||
virtual void close();
|
||||
void stop();
|
||||
|
||||
bool authenticate(const char * username, const char * password);
|
||||
@ -93,7 +93,7 @@ public:
|
||||
|
||||
String uri() { return _currentUri; }
|
||||
HTTPMethod method() { return _currentMethod; }
|
||||
WiFiClient client() { return _currentClient; }
|
||||
virtual WiFiClient client() { return _currentClient; }
|
||||
HTTPUpload& upload() { return *_currentUpload; }
|
||||
|
||||
String arg(String name); // get request argument value by name
|
||||
@ -140,6 +140,8 @@ template<typename T> size_t streamFile(T &file, const String& contentType){
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual size_t _currentClientWrite(const char* b, size_t l) { return _currentClient.write( b, l ); }
|
||||
virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
|
||||
void _addRequestHandler(RequestHandler* handler);
|
||||
void _handleRequest();
|
||||
void _finalizeResponse();
|
||||
|
140
libraries/ESP8266WebServer/src/ESP8266WebServerSecure.cpp
Normal file
140
libraries/ESP8266WebServer/src/ESP8266WebServerSecure.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
ESP8266WebServerSecure.cpp - Dead simple HTTPS web-server.
|
||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
||||
|
||||
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <libb64/cencode.h>
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "ESP8266WebServerSecure.h"
|
||||
|
||||
|
||||
ESP8266WebServerSecure::ESP8266WebServerSecure(IPAddress addr, int port)
|
||||
: _serverSecure(addr, port)
|
||||
{
|
||||
}
|
||||
|
||||
ESP8266WebServerSecure::ESP8266WebServerSecure(int port)
|
||||
: _serverSecure(port)
|
||||
{
|
||||
}
|
||||
|
||||
void ESP8266WebServerSecure::setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
|
||||
{
|
||||
_serverSecure.setServerKeyAndCert_P(key, keyLen, cert, certLen);
|
||||
}
|
||||
|
||||
void ESP8266WebServerSecure::setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
|
||||
{
|
||||
_serverSecure.setServerKeyAndCert(key, keyLen, cert, certLen);
|
||||
}
|
||||
|
||||
ESP8266WebServerSecure::~ESP8266WebServerSecure() {
|
||||
// Nothing to do here.
|
||||
// Base class's destructor will be called to clean up itself
|
||||
}
|
||||
|
||||
// We need to basically cut-n-paste these from WebServer because of the problem
|
||||
// of object slicing. The class uses assignment operators like "WiFiClient x=y;"
|
||||
// When this happens, even if "y" is a WiFiClientSecure, the main class is
|
||||
// already compiled down into code which will only copy the WiFiClient superclass
|
||||
// and not the extra bits for our own class (since when it was compiled it needed
|
||||
// to know the size of memory to allocate on the stack for this local variable
|
||||
// there's not realy anything else it could do).
|
||||
|
||||
void ESP8266WebServerSecure::begin() {
|
||||
_currentStatus = HC_NONE;
|
||||
_serverSecure.begin();
|
||||
if(!_headerKeysCount)
|
||||
collectHeaders(0, 0);
|
||||
}
|
||||
|
||||
void ESP8266WebServerSecure::handleClient() {
|
||||
if (_currentStatus == HC_NONE) {
|
||||
WiFiClientSecure client = _serverSecure.available();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ESP_HTTP_SERVER
|
||||
DEBUG_OUTPUT.println("New secure client");
|
||||
#endif
|
||||
|
||||
_currentClientSecure = client;
|
||||
_currentStatus = HC_WAIT_READ;
|
||||
_statusChange = millis();
|
||||
}
|
||||
|
||||
bool keepCurrentClient = false;
|
||||
bool callYield = false;
|
||||
|
||||
if (_currentClientSecure.connected()) {
|
||||
switch (_currentStatus) {
|
||||
case HC_NONE:
|
||||
// No-op to avoid C++ compiler warning
|
||||
break;
|
||||
case HC_WAIT_READ:
|
||||
// Wait for data from client to become available
|
||||
if (_currentClientSecure.available()) {
|
||||
if (_parseRequest(_currentClientSecure)) {
|
||||
_currentClientSecure.setTimeout(HTTP_MAX_SEND_WAIT);
|
||||
_contentLength = CONTENT_LENGTH_NOT_SET;
|
||||
_handleRequest();
|
||||
|
||||
if (_currentClientSecure.connected()) {
|
||||
_currentStatus = HC_WAIT_CLOSE;
|
||||
_statusChange = millis();
|
||||
keepCurrentClient = true;
|
||||
}
|
||||
}
|
||||
} else { // !_currentClient.available()
|
||||
if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) {
|
||||
keepCurrentClient = true;
|
||||
}
|
||||
callYield = true;
|
||||
}
|
||||
break;
|
||||
case HC_WAIT_CLOSE:
|
||||
// Wait for client to close the connection
|
||||
if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) {
|
||||
keepCurrentClient = true;
|
||||
callYield = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!keepCurrentClient) {
|
||||
_currentClientSecure = WiFiClientSecure();
|
||||
_currentStatus = HC_NONE;
|
||||
_currentUpload.reset();
|
||||
}
|
||||
|
||||
if (callYield) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void ESP8266WebServerSecure::close() {
|
||||
_currentClientSecure.stop();
|
||||
_serverSecure.close();
|
||||
}
|
||||
|
55
libraries/ESP8266WebServer/src/ESP8266WebServerSecure.h
Normal file
55
libraries/ESP8266WebServer/src/ESP8266WebServerSecure.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
ESP8266WebServerSecure.h - Dead simple HTTPS web-server.
|
||||
Supports only one simultaneous client, knows how to handle GET and POST.
|
||||
|
||||
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ESP8266WEBSERVERSECURE_H
|
||||
#define ESP8266WEBSERVERSECURE_H
|
||||
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <WiFiServerSecure.h>
|
||||
|
||||
class ESP8266WebServerSecure : public ESP8266WebServer
|
||||
{
|
||||
public:
|
||||
ESP8266WebServerSecure(IPAddress addr, int port = 443);
|
||||
ESP8266WebServerSecure(int port = 443);
|
||||
virtual ~ESP8266WebServerSecure();
|
||||
|
||||
void setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
|
||||
void setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
|
||||
|
||||
WiFiClient client() override { return _currentClientSecure; }
|
||||
|
||||
void begin() override;
|
||||
void handleClient() override;
|
||||
void close() override;
|
||||
|
||||
private:
|
||||
size_t _currentClientWrite (const char *bytes, size_t len) override { return _currentClientSecure.write((const uint8_t *)bytes, len); }
|
||||
size_t _currentClientWrite_P (PGM_P bytes, size_t len) override { return _currentClientSecure.write_P(bytes, len); }
|
||||
|
||||
protected:
|
||||
WiFiServerSecure _serverSecure;
|
||||
WiFiClientSecure _currentClientSecure;
|
||||
};
|
||||
|
||||
|
||||
#endif //ESP8266WEBSERVERSECURE_H
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
WiFiHTTPSServer - Simple SSL server example
|
||||
|
||||
This sketch demonstrates how to set up a simple HTTP-like server usingcl
|
||||
HTTPS encryption. This is NOT the recommended way of writing a web server!
|
||||
Please see the ESP8266WebServer and ESP8266WebServerSecure for a much easier
|
||||
and more robust server for your own applications.
|
||||
|
||||
The server will set a GPIO pin depending on the request
|
||||
https://server_ip/gpio/0 will set the GPIO2 low,
|
||||
https://server_ip/gpio/1 will set the GPIO2 high
|
||||
server_ip is the IP address of the ESP8266 module, will be
|
||||
printed to Serial when the module is connected.
|
||||
|
||||
IMPORTANT NOTES ABOUT SSL CERTIFICATES
|
||||
|
||||
1. USE/GENERATE YOUR OWN CERTIFICATES
|
||||
While a sample, self-signed certificate is included in this example,
|
||||
it is ABSOLUTELY VITAL that you use your own SSL certificate in any
|
||||
real-world deployment. Anyone with the certificate and key may be
|
||||
able to decrypt your traffic, so your own keys should be kept in a
|
||||
safe manner, not accessible on any public network.
|
||||
|
||||
2. HOW TO GENERATE YOUR OWN CERTIFICATE/KEY PAIR
|
||||
A sample script, "make-self-signed-cert.sh" is provided in the
|
||||
ESP8266WiFi/examples/WiFiHTTPSServer directory. This script can be
|
||||
modified (replace "your-name-here" with your Organization name). Note
|
||||
that this will be a *self-signed certificate* and will *NOT* be accepted
|
||||
by default by most modern browsers. They'll display something like,
|
||||
"This certificate is from an untrusted source," or "Your connection is
|
||||
not secure," or "Your connection is not private," and the user will
|
||||
have to manully allow the browser to continue by using the
|
||||
"Advanced/Add Exception" (FireFox) or "Advanced/Proceed" (Chrome) link.
|
||||
|
||||
You may also, of course, use a commercial, trusted SSL provider to
|
||||
generate your certificate. When requesting the certificate, you'll
|
||||
need to specify that it use SHA256 and 1024 or 512 bits in order to
|
||||
function with the axTLS implementation in the ESP8266.
|
||||
|
||||
Adapted by Earle F. Philhower, III, from the WiFiWebServer.ino example.
|
||||
This example is released into the public domain.
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
const char* ssid = "your-ssid";
|
||||
const char* password = "your-password";
|
||||
|
||||
// The certificate is stored in PMEM
|
||||
static const uint8_t x509[] PROGMEM = {
|
||||
0x30, 0x82, 0x01, 0x3d, 0x30, 0x81, 0xe8, 0x02, 0x09, 0x00, 0xfe, 0x56,
|
||||
0x46, 0xf2, 0x78, 0xc6, 0x51, 0x17, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x26, 0x31,
|
||||
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
|
||||
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
|
||||
0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x38, 0x31,
|
||||
0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x31,
|
||||
0x32, 0x35, 0x31, 0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x30, 0x26, 0x31,
|
||||
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
|
||||
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
|
||||
0x31, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02,
|
||||
0x41, 0x00, 0xc6, 0x72, 0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7,
|
||||
0x3a, 0x2a, 0x5a, 0x49, 0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6,
|
||||
0xbb, 0xa3, 0xd6, 0x6f, 0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33,
|
||||
0x50, 0x80, 0xec, 0x49, 0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d,
|
||||
0x81, 0x85, 0x23, 0x24, 0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3,
|
||||
0x3c, 0x10, 0x40, 0x05, 0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
|
||||
0x05, 0x00, 0x03, 0x41, 0x00, 0x69, 0xdc, 0x6c, 0x9b, 0xa7, 0x62, 0x57,
|
||||
0x7e, 0x03, 0x01, 0x45, 0xad, 0x9a, 0x83, 0x90, 0x3a, 0xe7, 0xdf, 0xe8,
|
||||
0x8f, 0x46, 0x00, 0xd3, 0x5f, 0x2b, 0x0a, 0xde, 0x92, 0x1b, 0xc5, 0x04,
|
||||
0xc5, 0xc0, 0x76, 0xf4, 0xf6, 0x08, 0x36, 0x97, 0x27, 0x82, 0xf1, 0x60,
|
||||
0x76, 0xc2, 0xcd, 0x67, 0x6c, 0x4b, 0x6c, 0xca, 0xfd, 0x97, 0xfd, 0x33,
|
||||
0x9e, 0x12, 0x67, 0x6b, 0x98, 0x7e, 0xd5, 0x80, 0x8f
|
||||
};
|
||||
|
||||
// And so is the key. These could also be in DRAM
|
||||
static const uint8_t rsakey[] PROGMEM = {
|
||||
0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xc6, 0x72,
|
||||
0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7, 0x3a, 0x2a, 0x5a, 0x49,
|
||||
0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6, 0xbb, 0xa3, 0xd6, 0x6f,
|
||||
0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33, 0x50, 0x80, 0xec, 0x49,
|
||||
0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d, 0x81, 0x85, 0x23, 0x24,
|
||||
0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3, 0x3c, 0x10, 0x40, 0x05,
|
||||
0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x35, 0x0b, 0x74,
|
||||
0xd3, 0xff, 0x15, 0x51, 0x44, 0x0f, 0x13, 0x2e, 0x9b, 0x0f, 0x93, 0x5c,
|
||||
0x3f, 0xfc, 0xf1, 0x17, 0xf9, 0x72, 0x94, 0x5e, 0xa7, 0xc6, 0xb3, 0xf0,
|
||||
0xfe, 0xc9, 0x6c, 0xb1, 0x1e, 0x83, 0xb3, 0xc6, 0x45, 0x3a, 0x25, 0x60,
|
||||
0x7c, 0x3d, 0x92, 0x7d, 0x53, 0xec, 0x49, 0x8d, 0xb5, 0x45, 0x10, 0x99,
|
||||
0x9b, 0xc6, 0x22, 0x3a, 0x68, 0xc7, 0x13, 0x4e, 0xb6, 0x04, 0x61, 0x21,
|
||||
0x01, 0x02, 0x21, 0x00, 0xea, 0x8c, 0x21, 0xd4, 0x7f, 0x3f, 0xb6, 0x91,
|
||||
0xfa, 0xf8, 0xb9, 0x2d, 0xcb, 0x36, 0x36, 0x02, 0x5f, 0xf0, 0x0c, 0x6e,
|
||||
0x87, 0xaa, 0x5c, 0x14, 0xf6, 0x56, 0x8e, 0x12, 0x92, 0x25, 0xde, 0xb3,
|
||||
0x02, 0x21, 0x00, 0xd8, 0x99, 0x01, 0xf1, 0x04, 0x0b, 0x98, 0xa3, 0x71,
|
||||
0x56, 0x1d, 0xea, 0x6f, 0x45, 0xd1, 0x36, 0x70, 0x76, 0x8b, 0xab, 0x69,
|
||||
0x30, 0x58, 0x9c, 0xe0, 0x45, 0x97, 0xe7, 0xb6, 0xb5, 0xef, 0xc1, 0x02,
|
||||
0x21, 0x00, 0xa2, 0x01, 0x06, 0xc0, 0xf2, 0xdf, 0xbc, 0x28, 0x1a, 0xb4,
|
||||
0xbf, 0x9b, 0x5c, 0xd8, 0x65, 0xf7, 0xbf, 0xf2, 0x5b, 0x73, 0xe0, 0xeb,
|
||||
0x0f, 0xcd, 0x3e, 0xd5, 0x4c, 0x2e, 0x91, 0x99, 0xec, 0xb7, 0x02, 0x20,
|
||||
0x4b, 0x9d, 0x46, 0xd7, 0x3c, 0x01, 0x4c, 0x5d, 0x2a, 0xb0, 0xd4, 0xaa,
|
||||
0xc6, 0x03, 0xca, 0xa0, 0xc5, 0xac, 0x2c, 0xe0, 0x3f, 0x4d, 0x98, 0x71,
|
||||
0xd3, 0xbd, 0x97, 0xe5, 0x55, 0x9c, 0xb8, 0x41, 0x02, 0x20, 0x02, 0x42,
|
||||
0x9f, 0xd1, 0x06, 0x35, 0x3b, 0x42, 0xf5, 0x64, 0xaf, 0x6d, 0xbf, 0xcd,
|
||||
0x2c, 0x3a, 0xcd, 0x0a, 0x9a, 0x4d, 0x7c, 0xad, 0x29, 0xd6, 0x36, 0x57,
|
||||
0xd5, 0xdf, 0x34, 0xeb, 0x26, 0x03
|
||||
};
|
||||
|
||||
// Create an instance of the server
|
||||
// specify the port to listen on as an argument
|
||||
WiFiServerSecure server(443);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// prepare GPIO2
|
||||
pinMode(2, OUTPUT);
|
||||
digitalWrite(2, 0);
|
||||
|
||||
// Connect to WiFi network
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
|
||||
// Set the certificates from PMEM (if using DRAM remove the _P from the call)
|
||||
server.setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
|
||||
|
||||
// Start the server
|
||||
server.begin();
|
||||
Serial.println("Server started");
|
||||
|
||||
// Print the IP address
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Check if a client has connected
|
||||
WiFiClientSecure client = server.available();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait until the client sends some data
|
||||
Serial.println("new client");
|
||||
unsigned long timeout = millis() + 3000;
|
||||
while(!client.available() && millis() < timeout){
|
||||
delay(1);
|
||||
}
|
||||
if (millis() > timeout) {
|
||||
Serial.println("timeout");
|
||||
client.flush();
|
||||
client.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the first line of the request
|
||||
String req = client.readStringUntil('\r');
|
||||
Serial.println(req);
|
||||
client.flush();
|
||||
|
||||
// Match the request
|
||||
int val;
|
||||
if (req.indexOf("/gpio/0") != -1)
|
||||
val = 0;
|
||||
else if (req.indexOf("/gpio/1") != -1)
|
||||
val = 1;
|
||||
else {
|
||||
Serial.println("invalid request");
|
||||
client.print("HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html><body>Not found</body></html>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set GPIO2 according to the request
|
||||
digitalWrite(2, val);
|
||||
|
||||
client.flush();
|
||||
|
||||
// Prepare the response
|
||||
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nGPIO is now ";
|
||||
s += (val)?"high":"low";
|
||||
s += "</html>\n";
|
||||
|
||||
// Send the response to the client
|
||||
client.print(s);
|
||||
delay(1);
|
||||
Serial.println("Client disconnected");
|
||||
|
||||
// The client will actually be disconnected
|
||||
// when the function returns and 'client' object is detroyed
|
||||
}
|
||||
|
49
libraries/ESP8266WiFi/examples/WiFiHTTPSServer/make-self-signed-cert.sh
Executable file
49
libraries/ESP8266WiFi/examples/WiFiHTTPSServer/make-self-signed-cert.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script generates a self-signed certificate for use by the ESP8266
|
||||
# Replace your-name-here with somethine appropriate before running and use
|
||||
# the generated .H files in your code as follows:
|
||||
#
|
||||
# static const uint8_t rsakey[] ICACHE_RODATA_ATTR = {
|
||||
# #include "key.h"
|
||||
# };
|
||||
#
|
||||
# static const uint8_t x509[] ICACHE_RODATA_ATTR = {
|
||||
# #include "x509.h"
|
||||
# };
|
||||
#
|
||||
# ....
|
||||
# WiFiServerSecure server(443);
|
||||
# server.setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
|
||||
# ....
|
||||
|
||||
# 1024 or 512. 512 saves memory...
|
||||
BITS=512
|
||||
C=$PWD
|
||||
pushd /tmp
|
||||
|
||||
openssl genrsa -out tls.ca_key.pem $BITS
|
||||
openssl genrsa -out tls.key_$BITS.pem $BITS
|
||||
openssl rsa -in tls.key_$BITS.pem -out tls.key_$BITS -outform DER
|
||||
cat > certs.conf <<EOF
|
||||
[ req ]
|
||||
distinguished_name = req_distinguished_name
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
O = your-name-here
|
||||
CN = 127.0.0.1
|
||||
EOF
|
||||
openssl req -out tls.ca_x509.req -key tls.ca_key.pem -new -config certs.conf
|
||||
openssl req -out tls.x509_$BITS.req -key tls.key_$BITS.pem -new -config certs.conf
|
||||
openssl x509 -req -in tls.ca_x509.req -out tls.ca_x509.pem -sha256 -days 5000 -signkey tls.ca_key.pem
|
||||
openssl x509 -req -in tls.x509_$BITS.req -out tls.x509_$BITS.pem -sha256 -CAcreateserial -days 5000 -CA tls.ca_x509.pem -CAkey tls.ca_key.pem
|
||||
openssl x509 -in tls.ca_x509.pem -outform DER -out tls.ca_x509.cer
|
||||
openssl x509 -in tls.x509_$BITS.pem -outform DER -out tls.x509_$BITS.cer
|
||||
|
||||
xxd -i tls.key_$BITS | sed 's/.*{//' | sed 's/\};//' | sed 's/unsigned.*//' > "$C/key.h"
|
||||
xxd -i tls.x509_$BITS.cer | sed 's/.*{//' | sed 's/\};//' | sed 's/unsigned.*//' > "$C/x509.h"
|
||||
|
||||
rm -f tls.ca_key.pem tls.key_$BITS.pem tls.key_$BITS certs.conf tls.ca_x509.req tls.x509_$BITS.req tls.ca_x509.pem tls.x509_$BITS.pem tls.srl tls.x509_$BITS.cer tls.ca_x509.cer
|
||||
|
||||
popd
|
@ -15,6 +15,7 @@ ESP8266WiFi KEYWORD3
|
||||
WiFi KEYWORD1
|
||||
WiFiClient KEYWORD1
|
||||
WiFiServer KEYWORD1
|
||||
WiFiServerSecure KEYWORD1
|
||||
WiFiUDP KEYWORD1
|
||||
WiFiClientSecure KEYWORD1
|
||||
ESP8266WiFiMulti KEYWORD1
|
||||
|
@ -38,6 +38,7 @@ extern "C" {
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiServerSecure.h"
|
||||
#include "WiFiClientSecure.h"
|
||||
|
||||
#ifdef DEBUG_ESP_WIFI
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
virtual int connect(const String host, uint16_t port);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *buf, size_t size);
|
||||
size_t write_P(PGM_P buf, size_t size);
|
||||
virtual size_t write_P(PGM_P buf, size_t size);
|
||||
size_t write(Stream& stream);
|
||||
|
||||
// This one is deprecated, use write(Stream& instead)
|
||||
|
@ -93,8 +93,6 @@ public:
|
||||
if (_ssl_ctx_refcnt == 0) {
|
||||
ssl_ctx_free(_ssl_ctx);
|
||||
}
|
||||
|
||||
s_io_ctx = nullptr;
|
||||
}
|
||||
|
||||
void ref()
|
||||
@ -116,14 +114,14 @@ public:
|
||||
if (_ssl) {
|
||||
/* Creating a new TLS session on top of a new TCP connection.
|
||||
ssl_free will want to send a close notify alert, but the old TCP connection
|
||||
is already gone at this point, so reset s_io_ctx. */
|
||||
s_io_ctx = nullptr;
|
||||
is already gone at this point, so reset io_ctx. */
|
||||
io_ctx = nullptr;
|
||||
ssl_free(_ssl);
|
||||
_available = 0;
|
||||
_read_ptr = nullptr;
|
||||
}
|
||||
s_io_ctx = ctx;
|
||||
_ssl = ssl_client_new(_ssl_ctx, 0, nullptr, 0, ext);
|
||||
io_ctx = ctx;
|
||||
_ssl = ssl_client_new(_ssl_ctx, reinterpret_cast<int>(this), nullptr, 0, ext);
|
||||
uint32_t t = millis();
|
||||
|
||||
while (millis() - t < timeout_ms && ssl_handshake_status(_ssl) != SSL_OK) {
|
||||
@ -136,14 +134,32 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void connectServer(ClientContext *ctx) {
|
||||
io_ctx = ctx;
|
||||
_ssl = ssl_server_new(_ssl_ctx, reinterpret_cast<int>(this));
|
||||
_isServer = true;
|
||||
|
||||
uint32_t timeout_ms = 5000;
|
||||
uint32_t t = millis();
|
||||
|
||||
while (millis() - t < timeout_ms && ssl_handshake_status(_ssl) != SSL_OK) {
|
||||
uint8_t* data;
|
||||
int rc = ssl_read(_ssl, &data);
|
||||
if (rc < SSL_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
s_io_ctx = nullptr;
|
||||
io_ctx = nullptr;
|
||||
}
|
||||
|
||||
bool connected()
|
||||
{
|
||||
return _ssl != nullptr && ssl_handshake_status(_ssl) == SSL_OK;
|
||||
if (_isServer) return _ssl != nullptr;
|
||||
else return _ssl != nullptr && ssl_handshake_status(_ssl) == SSL_OK;
|
||||
}
|
||||
|
||||
int read(uint8_t* dst, size_t size)
|
||||
@ -189,7 +205,9 @@ public:
|
||||
|
||||
int write(const uint8_t* src, size_t size)
|
||||
{
|
||||
if (!_available) {
|
||||
if (_isServer) {
|
||||
return _write(src, size);
|
||||
} else if (!_available) {
|
||||
if (_hasWriteBuffers()) {
|
||||
int rc = _writeBuffersSend();
|
||||
if (rc < 0) {
|
||||
@ -241,10 +259,10 @@ public:
|
||||
return cb;
|
||||
}
|
||||
|
||||
// similar to availble, but doesn't return exact size
|
||||
// similar to available, but doesn't return exact size
|
||||
bool hasData()
|
||||
{
|
||||
return _available > 0 || (s_io_ctx && s_io_ctx->getSize() > 0);
|
||||
return _available > 0 || (io_ctx && io_ctx->getSize() > 0);
|
||||
}
|
||||
|
||||
bool loadObject(int type, Stream& stream, size_t size)
|
||||
@ -308,8 +326,15 @@ public:
|
||||
|
||||
static ClientContext* getIOContext(int fd)
|
||||
{
|
||||
(void) fd;
|
||||
return s_io_ctx;
|
||||
return reinterpret_cast<SSLContext*>(fd)->io_ctx;
|
||||
}
|
||||
|
||||
int loadServerX509Cert(const uint8_t *cert, int len) {
|
||||
return ssl_obj_memory_load(SSLContext::_ssl_ctx, SSL_OBJ_X509_CERT, cert, len, NULL);
|
||||
}
|
||||
|
||||
int loadServerRSAKey(const uint8_t *rsakey, int len) {
|
||||
return ssl_obj_memory_load(SSLContext::_ssl_ctx, SSL_OBJ_RSA_KEY, rsakey, len, NULL);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -386,6 +411,7 @@ protected:
|
||||
return !_writeBuffers.empty();
|
||||
}
|
||||
|
||||
bool _isServer = false;
|
||||
static SSL_CTX* _ssl_ctx;
|
||||
static int _ssl_ctx_refcnt;
|
||||
SSL* _ssl = nullptr;
|
||||
@ -394,12 +420,11 @@ protected:
|
||||
size_t _available = 0;
|
||||
BufferList _writeBuffers;
|
||||
bool _allowSelfSignedCerts = false;
|
||||
static ClientContext* s_io_ctx;
|
||||
ClientContext* io_ctx;
|
||||
};
|
||||
|
||||
SSL_CTX* SSLContext::_ssl_ctx = nullptr;
|
||||
int SSLContext::_ssl_ctx_refcnt = 0;
|
||||
ClientContext* SSLContext::s_io_ctx = nullptr;
|
||||
|
||||
WiFiClientSecure::WiFiClientSecure()
|
||||
{
|
||||
@ -433,6 +458,42 @@ WiFiClientSecure& WiFiClientSecure::operator=(const WiFiClientSecure& rhs)
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Only called by the WifiServerSecure, need to get the keys/certs loaded before beginning
|
||||
WiFiClientSecure::WiFiClientSecure(ClientContext* client, bool usePMEM, const uint8_t *rsakey, int rsakeyLen, const uint8_t *cert, int certLen)
|
||||
{
|
||||
_client = client;
|
||||
if (_ssl) {
|
||||
_ssl->unref();
|
||||
_ssl = nullptr;
|
||||
}
|
||||
|
||||
_ssl = new SSLContext;
|
||||
_ssl->ref();
|
||||
|
||||
if (usePMEM) {
|
||||
// When using PMEM based certs, allocate stack and copy from flash to DRAM, call SSL functions to avoid
|
||||
// heap fragmentation that would happen w/malloc()
|
||||
uint8_t *stackData = (uint8_t*)alloca(max(certLen, rsakeyLen));
|
||||
if (rsakey && rsakeyLen) {
|
||||
memcpy_P(stackData, rsakey, rsakeyLen);
|
||||
_ssl->loadServerRSAKey(stackData, rsakeyLen);
|
||||
}
|
||||
if (cert && certLen) {
|
||||
memcpy_P(stackData, cert, certLen);
|
||||
_ssl->loadServerX509Cert(stackData, certLen);
|
||||
}
|
||||
} else {
|
||||
if (rsakey && rsakeyLen) {
|
||||
_ssl->loadServerRSAKey(rsakey, rsakeyLen);
|
||||
}
|
||||
if (cert && certLen) {
|
||||
_ssl->loadServerX509Cert(cert, certLen);
|
||||
}
|
||||
}
|
||||
_client->ref();
|
||||
_ssl->connectServer(client);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (!WiFiClient::connect(ip, port)) {
|
||||
@ -496,6 +557,14 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t WiFiClientSecure::write_P(PGM_P buf, size_t size)
|
||||
{
|
||||
// Copy to RAM and call normal send. alloca() auto-frees on return
|
||||
uint8_t *copy = (uint8_t*)alloca(size);
|
||||
memcpy_P(copy, buf, size);
|
||||
return write(copy, size);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_ssl) {
|
||||
@ -584,6 +653,8 @@ void WiFiClientSecure::stop()
|
||||
{
|
||||
if (_ssl) {
|
||||
_ssl->stop();
|
||||
_ssl->unref();
|
||||
_ssl = nullptr;
|
||||
}
|
||||
WiFiClient::stop();
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
|
||||
uint8_t connected() override;
|
||||
size_t write(const uint8_t *buf, size_t size) override;
|
||||
size_t write_P(PGM_P buf, size_t size) override;
|
||||
int read(uint8_t *buf, size_t size) override;
|
||||
int available() override;
|
||||
int read() override;
|
||||
@ -80,6 +81,10 @@ public:
|
||||
return loadCACert(file, file.size());
|
||||
}
|
||||
|
||||
friend class WiFiServerSecure; // Needs access to custom constructor below
|
||||
protected:
|
||||
// Only called by WiFiServerSecure
|
||||
WiFiClientSecure(ClientContext* client, bool usePMEM, const uint8_t *rsakey, int rsakeyLen, const uint8_t *cert, int certLen);
|
||||
|
||||
protected:
|
||||
void _initSSLContext();
|
||||
|
@ -35,7 +35,8 @@ class ClientContext;
|
||||
class WiFiClient;
|
||||
|
||||
class WiFiServer : public Server {
|
||||
private:
|
||||
// Secure server needs access to all the private entries here
|
||||
protected:
|
||||
uint16_t _port;
|
||||
IPAddress _addr;
|
||||
tcp_pcb* _pcb;
|
||||
|
79
libraries/ESP8266WiFi/src/WiFiServerSecure.cpp
Normal file
79
libraries/ESP8266WiFi/src/WiFiServerSecure.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
WiFiServerSecure.cpp - SSL server for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2017 Earle F. Philhower, III
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define LWIP_INTERNAL
|
||||
|
||||
extern "C" {
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include "WiFiServerSecure.h"
|
||||
|
||||
WiFiServerSecure::WiFiServerSecure(IPAddress addr, uint16_t port) : WiFiServer(addr, port)
|
||||
{
|
||||
}
|
||||
|
||||
WiFiServerSecure::WiFiServerSecure(uint16_t port) : WiFiServer(port)
|
||||
{
|
||||
}
|
||||
|
||||
void WiFiServerSecure::setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
|
||||
{
|
||||
this->usePMEM = false;
|
||||
this->rsakey = key;
|
||||
this->rsakeyLen = keyLen;
|
||||
this->cert = cert;
|
||||
this->certLen = certLen;
|
||||
}
|
||||
|
||||
void WiFiServerSecure::setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen)
|
||||
{
|
||||
this->usePMEM = true;
|
||||
this->rsakey = key;
|
||||
this->rsakeyLen = keyLen;
|
||||
this->cert = cert;
|
||||
this->certLen = certLen;
|
||||
}
|
||||
|
||||
WiFiClientSecure WiFiServerSecure::available(uint8_t* status)
|
||||
{
|
||||
(void) status; // Unused
|
||||
if (_unclaimed) {
|
||||
WiFiClientSecure result(_unclaimed, usePMEM, rsakey, rsakeyLen, cert, certLen);
|
||||
_unclaimed = _unclaimed->next();
|
||||
result.setNoDelay(_noDelay);
|
||||
DEBUGV("WS:av\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
optimistic_yield(1000);
|
||||
return WiFiClientSecure();
|
||||
}
|
||||
|
43
libraries/ESP8266WiFi/src/WiFiServerSecure.h
Normal file
43
libraries/ESP8266WiFi/src/WiFiServerSecure.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
WiFiServerSecure.h - Library for Arduino ESP8266
|
||||
Copyright (c) 2017 Earle F. Philhower, III
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef wifiserversecure_h
|
||||
#define wifiserversecure_h
|
||||
|
||||
#include "WiFiServer.h"
|
||||
class WiFiClientSecure;
|
||||
|
||||
class WiFiServerSecure : public WiFiServer {
|
||||
public:
|
||||
WiFiServerSecure(IPAddress addr, uint16_t port);
|
||||
WiFiServerSecure(uint16_t port);
|
||||
void setServerKeyAndCert(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
|
||||
void setServerKeyAndCert_P(const uint8_t *key, int keyLen, const uint8_t *cert, int certLen);
|
||||
virtual ~WiFiServerSecure() {}
|
||||
WiFiClientSecure available(uint8_t* status = NULL);
|
||||
private:
|
||||
bool usePMEM = false;
|
||||
const uint8_t *rsakey = nullptr;
|
||||
int rsakeyLen = 0;
|
||||
const uint8_t *cert = nullptr;
|
||||
int certLen = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user