#include "mesh/http/WebServer.h" #include "NodeDB.h" #include "mesh/http/WiFiAPClient.h" #include #include #include #include #include #ifndef NO_ESP32 #include "esp_task_wdt.h" #endif // Persistant Data Storage #include Preferences prefs; /* Including the esp32_https_server library will trigger a compile time error. I've tracked it down to a reoccurrance of this bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824 The work around is described here: https://forums.xilinx.com/t5/Embedded-Development-Tools/Error-with-Standard-Libaries-in-Zynq/td-p/450032 Long story short is we need "#undef str" before including the esp32_https_server. - Jm Casler (jm@casler.org) Oct 2020 */ #undef str // Includes for the https server // https://github.com/fhessel/esp32_https_server #include #include #include #include #include // The HTTPS Server comes in a separate namespace. For easier use, include it here. using namespace httpsserver; #include "mesh/http/ContentHandler.h" SSLCert *cert; HTTPSServer *secureServer; HTTPServer *insecureServer; bool isWebServerReady = 0; bool isCertReady = 0; void handleWebResponse() { if (isWifiAvailable() == 0) { return; } if (isWebServerReady) { // We're going to handle the DNS responder here so it // will be ignored by the NRF boards. handleDNSResponse(); secureServer->loop(); insecureServer->loop(); } /* Slow down the CPU if we have not received a request within the last few seconds. */ if (millis() - getTimeSpeedUp() >= (25 * 1000)) { setCpuFrequencyMhz(80); setTimeSpeedUp(); } } void taskCreateCert(void *parameter) { prefs.begin("MeshtasticHTTPS", false); // Delete the saved certs if (0) { DEBUG_MSG("Deleting any saved SSL keys ...\n"); // prefs.clear(); prefs.remove("PK"); prefs.remove("cert"); } size_t pkLen = prefs.getBytesLength("PK"); size_t certLen = prefs.getBytesLength("cert"); DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n"); if (pkLen && certLen) { DEBUG_MSG("Existing SSL Certificate found!\n"); } else { DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); yield(); cert = new SSLCert(); yield(); int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", "20190101000000", "20300101000000"); yield(); if (createCertResult != 0) { DEBUG_MSG("Creating the certificate failed\n"); // Serial.printf("Creating the certificate failed. Error Code = 0x%02X, check SSLCert.hpp for details", // createCertResult); // while (true) // delay(500); } else { DEBUG_MSG("Creating the certificate was successful\n"); DEBUG_MSG("Created Private Key: %d Bytes\n", cert->getPKLength()); // for (int i = 0; i < cert->getPKLength(); i++) // Serial.print(cert->getPKData()[i], HEX); // Serial.println(); DEBUG_MSG("Created Certificate: %d Bytes\n", cert->getCertLength()); // for (int i = 0; i < cert->getCertLength(); i++) // Serial.print(cert->getCertData()[i], HEX); // Serial.println(); prefs.putBytes("PK", (uint8_t *)cert->getPKData(), cert->getPKLength()); prefs.putBytes("cert", (uint8_t *)cert->getCertData(), cert->getCertLength()); } } isCertReady = 1; vTaskDelete(NULL); } void createSSLCert() { if (isWifiAvailable() == 0) { return; } // Create a new process just to handle creating the cert. // This is a workaround for Bug: https://github.com/fhessel/esp32_https_server/issues/48 // jm@casler.org (Oct 2020) xTaskCreate(taskCreateCert, /* Task function. */ "createCert", /* String with name of task. */ 16384, /* Stack size in bytes. */ NULL, /* Parameter passed as input of the task */ 16, /* Priority of the task. */ NULL); /* Task handle. */ DEBUG_MSG("Waiting for SSL Cert to be generated.\n"); while (!isCertReady) { DEBUG_MSG("."); delay(1000); yield(); esp_task_wdt_reset(); } DEBUG_MSG("SSL Cert Ready!\n"); } WebServerThread *webServerThread; WebServerThread::WebServerThread() : concurrency::OSThread("WebServerThread") {} int32_t WebServerThread::runOnce() { // DEBUG_MSG("WebServerThread::runOnce()\n"); handleWebResponse(); // Loop every 5ms. return (5); } void initWebServer() { DEBUG_MSG("Initializing Web Server ...\n"); prefs.begin("MeshtasticHTTPS", false); size_t pkLen = prefs.getBytesLength("PK"); size_t certLen = prefs.getBytesLength("cert"); DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n"); if (pkLen && certLen) { uint8_t *pkBuffer = new uint8_t[pkLen]; prefs.getBytes("PK", pkBuffer, pkLen); uint8_t *certBuffer = new uint8_t[certLen]; prefs.getBytes("cert", certBuffer, certLen); cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen); DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength()); // DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes"); // for (int i = 0; i < cert->getPKLength(); i++) // Serial.print(cert->getPKData()[i], HEX); // Serial.println(); DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength()); // for (int i = 0; i < cert->getCertLength(); i++) // Serial.print(cert->getCertData()[i], HEX); // Serial.println(); } else { DEBUG_MSG("Web Server started without SSL keys! How did this happen?\n"); } // We can now use the new certificate to setup our server as usual. secureServer = new HTTPSServer(cert); insecureServer = new HTTPServer(); registerHandlers(insecureServer, secureServer); DEBUG_MSG("Starting Web Servers...\n"); secureServer->start(); insecureServer->start(); if (secureServer->isRunning() && insecureServer->isRunning()) { DEBUG_MSG("HTTP and HTTPS Web Servers Ready! :-) \n"); isWebServerReady = 1; } else { DEBUG_MSG("HTTP and HTTPS Web Servers Failed! ;-( \n"); } }