mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-03-08 00:07:42 +01:00
Add HTTP basic authentication (#996)
* add http basic auth * add feature check for basic auth process * fix http basic auth build for unsupported platforms (W800, W600) * fix includes in http_basic_auth * fix basic auth invocations when unavailable * add http basic auth allow checks to http_fns * remove unnecessary checks * add my_strnicmp export * silence warning * update web password config ui * update submodules * add base64 lib to boufallo.mk for BL602 * add safe mode http basic auth bypass flag * fix bl602 build with http auth bypass flag * disable shared led driver --------- Co-authored-by: Tester23 <openshwprojects@gmail.com>
This commit is contained in:
56
src/httpserver/http_basic_auth.c
Normal file
56
src/httpserver/http_basic_auth.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "http_basic_auth.h"
|
||||
#include <stdio.h>
|
||||
#include "../logging/logging.h"
|
||||
#include "../base64/base64.h"
|
||||
#include "../new_pins.h"
|
||||
#include "../new_cfg.h"
|
||||
|
||||
#define LOG_FEATURE LOG_FEATURE_HTTP
|
||||
|
||||
int http_basic_auth_eval(http_request_t *request) {
|
||||
#if ALLOW_WEB_PASSWORD
|
||||
if (strlen(g_cfg.webPassword) == 0 || (bSafeMode && CFG_HasFlag(OBK_FLAG_HTTP_DISABLE_AUTH_IN_SAFE_MODE))) {
|
||||
return HTTP_BASIC_AUTH_OK;
|
||||
}
|
||||
char tmp_auth[256];
|
||||
for (int i = 0; i < request->numheaders; i++) {
|
||||
char *header = request->headers[i];
|
||||
if (!my_strnicmp(header, "Authorization: Basic ", 21)) {
|
||||
char *basic_token = header + 21;
|
||||
size_t decoded_len = b64_decoded_size(basic_token);
|
||||
if (decoded_len > 255) {
|
||||
break;
|
||||
}
|
||||
if (!b64_decode(basic_token, (unsigned char *)tmp_auth, decoded_len + 1)) {
|
||||
ADDLOGF_ERROR("AUTH: Failed to decode B64 token.");
|
||||
break;
|
||||
}
|
||||
tmp_auth[decoded_len] = 0;
|
||||
if (!my_strnicmp(tmp_auth, "admin:", 6)) {
|
||||
char *basic_auth_password = tmp_auth + 6;
|
||||
if (strncmp(basic_auth_password, g_cfg.webPassword, 32) == 0) {
|
||||
return HTTP_BASIC_AUTH_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return HTTP_BASIC_AUTH_FAIL;
|
||||
#else
|
||||
return HTTP_BASIC_AUTH_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int http_basic_auth_run(http_request_t *request) {
|
||||
int result = http_basic_auth_eval(request);
|
||||
if (result == HTTP_BASIC_AUTH_FAIL) {
|
||||
poststr(request, "HTTP/1.1 401 Unauthorized\r\n");
|
||||
poststr(request, "Connection: close");
|
||||
poststr(request, "\r\n");
|
||||
poststr(request, "WWW-Authenticate: Basic realm=\"OpenBeken HTTP Server\"");
|
||||
poststr(request, "\r\n");
|
||||
poststr(request, "\r\n");
|
||||
poststr(request, NULL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
12
src/httpserver/http_basic_auth.h
Normal file
12
src/httpserver/http_basic_auth.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _HTTP_BASIC_AUTH_H
|
||||
#define _HTTP_BASIC_AUTH_H
|
||||
|
||||
#include "new_http.h"
|
||||
|
||||
#define HTTP_BASIC_AUTH_FAIL 0
|
||||
#define HTTP_BASIC_AUTH_OK 1
|
||||
|
||||
int http_basic_auth_eval(http_request_t *request);
|
||||
int http_basic_auth_run(http_request_t *request);
|
||||
|
||||
#endif
|
||||
@@ -1335,6 +1335,14 @@ int http_fn_cfg_wifi(http_request_t* request) {
|
||||
poststr_h2(request, "Alternate WiFi (used when first one is not responding)");
|
||||
add_label_text_field(request, "SSID2", "ssid2", CFG_GetWiFiSSID2(), "");
|
||||
add_label_password_field(request, "Password2", "pass2", CFG_GetWiFiPass2(), "<br>");
|
||||
#if ALLOW_WEB_PASSWORD
|
||||
int web_password_enabled = strcmp(CFG_GetWebPassword(), "") == 0 ? 0 : 1;
|
||||
poststr_h2(request, "Web Authentication");
|
||||
poststr(request, "<p>Enabling web authentication will protect this web interface and API using basic HTTP authentication. Username is always <b>admin</b>.</p>");
|
||||
hprintf255(request, "<div><input type=\"checkbox\" name=\"web_admin_password_enabled\" id=\"web_admin_password_enabled\" value=\"1\"%s>", (web_password_enabled > 0 ? " checked" : ""));
|
||||
poststr(request, "<label for=\"web_admin_password_enabled\">Enable web authentication</label></div>");
|
||||
add_label_password_field(request, "Admin Password", "web_admin_password", CFG_GetWebPassword(), "");
|
||||
#endif
|
||||
poststr(request, "<br><br>\
|
||||
<input type=\"submit\" value=\"Submit\" onclick=\"return confirm('Are you sure? Please check SSID and pass twice?')\">\
|
||||
</form>");
|
||||
@@ -1410,12 +1418,27 @@ int http_fn_cfg_wifi_set(http_request_t* request) {
|
||||
if (http_getArg(request->url, "pass2", tmpA, sizeof(tmpA))) {
|
||||
bChanged |= CFG_SetWiFiPass2(tmpA);
|
||||
}
|
||||
#if ALLOW_WEB_PASSWORD
|
||||
if (http_getArg(request->url, "web_admin_password_enabled", tmpA, sizeof(tmpA))) {
|
||||
int web_password_enabled = atoi(tmpA);
|
||||
if (web_password_enabled > 0 && http_getArg(request->url, "web_admin_password", tmpA, sizeof(tmpA))) {
|
||||
if (strlen(tmpA) < 5) {
|
||||
poststr_h4(request, "Web password needs to be at least 5 characters long!");
|
||||
} else {
|
||||
poststr(request, "<p>Web password has been changed.</p>");
|
||||
CFG_SetWebPassword(tmpA);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CFG_SetWebPassword("");
|
||||
}
|
||||
#endif
|
||||
CFG_Save_SetupTimer();
|
||||
if (bChanged == 0) {
|
||||
poststr(request, "No changes detected.");
|
||||
poststr(request, "<p>WiFi: No changes detected.</p>");
|
||||
}
|
||||
else {
|
||||
poststr(request, "Please wait for module to reset...");
|
||||
poststr(request, "<p>WiFi: Please wait for module to reset...</p>");
|
||||
RESET_ScheduleModuleReset(3);
|
||||
}
|
||||
poststr(request, "<br><a href=\"cfg_wifi\">Return to WiFi settings</a><br>");
|
||||
@@ -2426,7 +2449,7 @@ int http_fn_cfg(http_request_t* request) {
|
||||
postFormAction(request, "cfg_generic", "Configure General/Flags");
|
||||
postFormAction(request, "cfg_startup", "Configure Startup");
|
||||
postFormAction(request, "cfg_dgr", "Configure Device Groups");
|
||||
postFormAction(request, "cfg_wifi", "Configure WiFi");
|
||||
postFormAction(request, "cfg_wifi", "Configure WiFi & Web");
|
||||
postFormAction(request, "cfg_ip", "Configure IP");
|
||||
postFormAction(request, "cfg_mqtt", "Configure MQTT");
|
||||
postFormAction(request, "cfg_name", "Configure Names");
|
||||
@@ -2657,6 +2680,7 @@ const char* g_obk_flagNames[] = {
|
||||
"[BTN] Ignore all button events (aka child lock)",
|
||||
"[DoorSensor] Invert state",
|
||||
"[TuyaMCU] Use queue",
|
||||
"[HTTP] Disable authentication in safe mode (not recommended)",
|
||||
"error",
|
||||
"error",
|
||||
};
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "../new_cfg.h"
|
||||
#include "../ota/ota.h"
|
||||
#include "../hal/hal_wifi.h"
|
||||
#include "../base64/base64.h"
|
||||
#include "http_basic_auth.h"
|
||||
|
||||
|
||||
// define the feature ADDLOGF_XXX will use
|
||||
@@ -77,13 +79,14 @@ typedef struct http_callback_tag {
|
||||
char* url;
|
||||
int method;
|
||||
http_callback_fn callback;
|
||||
int auth_required;
|
||||
} http_callback_t;
|
||||
|
||||
#define MAX_HTTP_CALLBACKS 32
|
||||
static http_callback_t* callbacks[MAX_HTTP_CALLBACKS];
|
||||
static int numCallbacks = 0;
|
||||
|
||||
int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback) {
|
||||
int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback, int auth_required) {
|
||||
int i;
|
||||
|
||||
if (!url || !callback) {
|
||||
@@ -112,6 +115,7 @@ int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback
|
||||
strcpy(callbacks[numCallbacks]->url, url);
|
||||
callbacks[numCallbacks]->callback = callback;
|
||||
callbacks[numCallbacks]->method = method;
|
||||
callbacks[numCallbacks]->auth_required = auth_required > 0 ? 1 : 0;
|
||||
|
||||
numCallbacks++;
|
||||
|
||||
@@ -721,10 +725,18 @@ int HTTP_ProcessPacket(http_request_t* request) {
|
||||
if (http_startsWith(urlStr, &url[1])) {
|
||||
int method = callbacks[i]->method;
|
||||
if (method == HTTP_ANY || method == request->method) {
|
||||
if (callbacks[i]->auth_required > 0 && http_basic_auth_run(request) == HTTP_BASIC_AUTH_FAIL) {
|
||||
return 0;
|
||||
}
|
||||
return callbacks[i]->callback(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (http_basic_auth_run(request) == HTTP_BASIC_AUTH_FAIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (http_checkUrlBase(urlStr, "")) return http_fn_empty_url(request);
|
||||
|
||||
if (http_checkUrlBase(urlStr, "testmsg")) return http_fn_testmsg(request);
|
||||
|
||||
@@ -86,7 +86,9 @@ typedef enum {
|
||||
typedef int (*http_callback_fn)(http_request_t* request);
|
||||
// url MUST start with '/'
|
||||
// urls must be unique (i.e. you can't have /about and /aboutme or /about/me)
|
||||
int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback);
|
||||
int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback, int auth_required);
|
||||
|
||||
int my_strnicmp(const char* a, const char* b, int len);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -105,9 +105,9 @@ static int http_rest_post_cmd(http_request_t* request);
|
||||
|
||||
|
||||
void init_rest() {
|
||||
HTTP_RegisterCallback("/api/", HTTP_GET, http_rest_get);
|
||||
HTTP_RegisterCallback("/api/", HTTP_POST, http_rest_post);
|
||||
HTTP_RegisterCallback("/app", HTTP_GET, http_rest_app);
|
||||
HTTP_RegisterCallback("/api/", HTTP_GET, http_rest_get, 1);
|
||||
HTTP_RegisterCallback("/api/", HTTP_POST, http_rest_post, 1);
|
||||
HTTP_RegisterCallback("/app", HTTP_GET, http_rest_app, 1);
|
||||
}
|
||||
|
||||
/* Extracts string token value into outBuffer (128 char). Returns true if the operation was successful. */
|
||||
|
||||
Reference in New Issue
Block a user