From 22bd16e936cfd594849815d5c6ca4d38938438d1 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sat, 11 Feb 2023 07:49:16 -0600 Subject: [PATCH] Added ability to set OTA password from within sketch Adds second form of homeSpan.enableOTA(const char *pwd, boolean safeLoad=true) --- src/HAP.cpp | 14 +++++------ src/HomeSpan.cpp | 64 +++++++++++++++++++++++++++++------------------- src/HomeSpan.h | 8 +++--- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/HAP.cpp b/src/HAP.cpp index a922826..3db9f4a 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -40,14 +40,12 @@ void HAPClient::init(){ nvs_open("SRP",NVS_READWRITE,&srpNVS); // open SRP data namespace in NVS nvs_open("HAP",NVS_READWRITE,&hapNVS); // open HAP data namespace in NVS - if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS - nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // retrieve data - } else { - MD5Builder otaPwdHash; - otaPwdHash.begin(); - otaPwdHash.add(DEFAULT_OTA_PASSWORD); - otaPwdHash.calculate(); - otaPwdHash.getChars(homeSpan.spanOTA.otaPwd); + if(strlen(homeSpan.spanOTA.otaPwd)==0){ // OTA password has not been specified in sketch + if(!nvs_get_str(homeSpan.otaNVS,"OTADATA",NULL,&len)){ // if found OTA data in NVS... + nvs_get_str(homeSpan.otaNVS,"OTADATA",homeSpan.spanOTA.otaPwd,&len); // ...retrieve data. + } else { // otherwise... + homeSpan.spanOTA.setPassword(DEFAULT_OTA_PASSWORD); // ...use default password + } } if(strlen(homeSpan.pairingCodeCommand)){ // load verification setup code if provided diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index bb8a013..16915bc 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -519,25 +519,20 @@ void Span::checkConnect(){ mdns_service_txt_item_set("_hap","_tcp","sh",setupHash); // Step 4: broadcast the resulting Setup Hash if(spanOTA.enabled){ - if(esp_ota_get_running_partition()!=esp_ota_get_next_update_partition(NULL)){ - ArduinoOTA.setHostname(hostName); + ArduinoOTA.setHostname(hostName); - if(spanOTA.auth) - ArduinoOTA.setPasswordHash(spanOTA.otaPwd); + if(spanOTA.auth) + ArduinoOTA.setPasswordHash(spanOTA.otaPwd); - ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error); - - ArduinoOTA.begin(); - Serial.print("Starting OTA Server: "); - Serial.print(displayName); - Serial.print(" at "); - Serial.print(WiFi.localIP()); - Serial.print("\nAuthorization Password: "); - Serial.print(spanOTA.auth?"Enabled\n\n":"DISABLED!\n\n"); - } else { - Serial.print("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n"); - spanOTA.enabled=false; - } + ArduinoOTA.onStart(spanOTA.start).onEnd(spanOTA.end).onProgress(spanOTA.progress).onError(spanOTA.error); + + ArduinoOTA.begin(); + Serial.print("Starting OTA Server: "); + Serial.print(displayName); + Serial.print(" at "); + Serial.print(WiFi.localIP()); + Serial.print("\nAuthorization Password: "); + Serial.print(spanOTA.auth?"Enabled\n\n":"DISABLED!\n\n"); } mdns_service_txt_item_set("_hap","_tcp","ota",spanOTA.enabled?"yes":"no"); // OTA status (info only - NOT used by HAP) @@ -682,13 +677,8 @@ void Span::processSerialCommand(const char *c){ } Serial.print(mask(textPwd,2)); - Serial.print("\n"); - - MD5Builder otaPwdHash; - otaPwdHash.begin(); - otaPwdHash.add(textPwd); - otaPwdHash.calculate(); - otaPwdHash.getChars(spanOTA.otaPwd); + Serial.print("\n"); + spanOTA.setPassword(textPwd); nvs_set_str(otaNVS,"OTADATA",spanOTA.otaPwd); // update data nvs_commit(otaNVS); @@ -2147,11 +2137,35 @@ void SpanWebLog::vLog(boolean sysMsg, const char *fmt, va_list ap){ // SpanOTA // /////////////////////////////// -void SpanOTA::init(boolean _auth, boolean _safeLoad){ +int SpanOTA::init(boolean _auth, boolean _safeLoad, const char *pwd){ + if(esp_ota_get_running_partition()==esp_ota_get_next_update_partition(NULL)){ + Serial.print("\n*** WARNING: Can't start OTA Server - Partition table used to compile this sketch is not configured for OTA.\n\n"); + return(-1); + } + enabled=true; safeLoad=_safeLoad; auth=_auth; homeSpan.reserveSocketConnections(1); + if(pwd==NULL) + return(0); + return(setPassword(pwd)); +} + +/////////////////////////////// + +int SpanOTA::setPassword(const char *pwd){ + if(strlen(pwd)<1 || strlen(pwd)>32){ + Serial.printf("\n*** WARNING: Cannot change OTA password to '%s'. Password length must be between 1 and 32 characters.\n\n",pwd); + return(-1); + } + + MD5Builder otaPwdHash; + otaPwdHash.begin(); + otaPwdHash.add(pwd); + otaPwdHash.calculate(); + otaPwdHash.getChars(homeSpan.spanOTA.otaPwd); + return(0); } /////////////////////////////// diff --git a/src/HomeSpan.h b/src/HomeSpan.h index a7db2d4..bae1df2 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -168,14 +168,15 @@ struct SpanWebLog{ // optional web status/log data struct SpanOTA{ // manages OTA process - char otaPwd[33]; // MD5 Hash of OTA password, represented as a string of hexidecimal characters + char otaPwd[33]=""; // MD5 Hash of OTA password, represented as a string of hexidecimal characters static boolean enabled; // enables OTA - default if not enabled static boolean auth; // indicates whether OTA password is required static int otaPercent; static boolean safeLoad; // indicates whether OTA update should reject any application update that is not another HomeSpan sketch - void init(boolean auth, boolean safeLoad); + int init(boolean auth, boolean safeLoad, const char *pwd); + int setPassword(const char *pwd); static void start(); static void end(); static void progress(uint32_t progress, uint32_t total); @@ -326,7 +327,8 @@ class Span{ void setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS - void enableOTA(boolean auth=true, boolean safeLoad=true){spanOTA.init(auth, safeLoad);} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password + int enableOTA(boolean auth=true, boolean safeLoad=true){return(spanOTA.init(auth, safeLoad, NULL));} // enables Over-the-Air updates, with (auth=true) or without (auth=false) authorization password + int enableOTA(const char *pwd, boolean safeLoad=true){return(spanOTA.init(true, safeLoad, pwd));} // enables Over-the-Air updates, with custom authorization password (overrides any password stored with the 'O' command) void enableWebLog(uint16_t maxEntries=0, const char *serv=NULL, const char *tz="UTC", const char *url=DEFAULT_WEBLOG_URL){ // enable Web Logging webLog.init(maxEntries, serv, tz, url);