basic_auth.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "basic_auth.h"
  2. #include "read_wlanini.h"
  3. #include <esp_tls_crypto.h>
  4. #include <esp_log.h>
  5. #define HTTPD_401 "401 UNAUTHORIZED"
  6. static const char *TAG = "HTTPAUTH";
  7. typedef struct {
  8. const char *username;
  9. const char *password;
  10. } basic_auth_info_t;
  11. basic_auth_info_t basic_auth_info = { NULL, NULL };
  12. void init_basic_auth() {
  13. if (!wlan_config.http_username.empty() && !wlan_config.http_password.empty()) {
  14. basic_auth_info.username = wlan_config.http_username.c_str();
  15. basic_auth_info.password = wlan_config.http_password.c_str();
  16. }
  17. }
  18. static char *http_auth_basic(const char *username, const char *password)
  19. {
  20. int out;
  21. char *user_info = NULL;
  22. char *digest = NULL;
  23. size_t n = 0;
  24. asprintf(&user_info, "%s:%s", username, password);
  25. if (!user_info) {
  26. ESP_LOGE(TAG, "No enough memory for user information");
  27. return NULL;
  28. }
  29. esp_crypto_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info));
  30. /* 6: The length of the "Basic " string
  31. * n: Number of bytes for a base64 encode format
  32. * 1: Number of bytes for a reserved which be used to fill zero
  33. */
  34. digest = static_cast<char*>(calloc(1, 6 + n + 1));
  35. if (digest) {
  36. strcpy(digest, "Basic ");
  37. esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info));
  38. }
  39. free(user_info);
  40. return digest;
  41. }
  42. esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler(httpd_req_t *))
  43. {
  44. char *buf = NULL;
  45. size_t buf_len = 0;
  46. esp_err_t ret = ESP_OK;
  47. char unauthorized[] = "You are not authorized to use this website!";
  48. if (basic_auth_info.username == NULL || basic_auth_info.password == NULL) {
  49. ret = original_handler(req);
  50. } else {
  51. buf_len = httpd_req_get_hdr_value_len(req, "Authorization") + 1;
  52. if (buf_len > 1) {
  53. buf = static_cast<char*>(calloc(1, buf_len));
  54. if (!buf) {
  55. ESP_LOGE(TAG, "No enough memory for basic authorization");
  56. return ESP_ERR_NO_MEM;
  57. }
  58. if (httpd_req_get_hdr_value_str(req, "Authorization", buf, buf_len) == ESP_OK) {
  59. ESP_LOGI(TAG, "Found header => Authorization: %s", buf);
  60. } else {
  61. ESP_LOGE(TAG, "No auth value received");
  62. }
  63. char *auth_credentials = http_auth_basic(basic_auth_info.username, basic_auth_info.password);
  64. if (!auth_credentials) {
  65. ESP_LOGE(TAG, "No enough memory for basic authorization credentials");
  66. free(buf);
  67. return ESP_ERR_NO_MEM;
  68. }
  69. if (strncmp(auth_credentials, buf, buf_len)) {
  70. ESP_LOGE(TAG, "Not authenticated");
  71. httpd_resp_set_status(req, HTTPD_401);
  72. httpd_resp_set_type(req, HTTPD_TYPE_TEXT);
  73. httpd_resp_set_hdr(req, "Connection", "keep-alive");
  74. httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"AIOTED\"");
  75. httpd_resp_send(req, unauthorized, strlen(unauthorized));
  76. } else {
  77. ESP_LOGI(TAG, "Authenticated calling http handler now!");
  78. ret=original_handler(req);
  79. }
  80. free(auth_credentials);
  81. free(buf);
  82. } else {
  83. ESP_LOGE(TAG, "No auth header received");
  84. httpd_resp_set_status(req, HTTPD_401);
  85. httpd_resp_set_type(req, HTTPD_TYPE_TEXT);
  86. httpd_resp_set_hdr(req, "Connection", "keep-alive");
  87. httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"AIOTED\"");
  88. httpd_resp_send(req, unauthorized, strlen(unauthorized));
  89. }
  90. }
  91. return ret;
  92. }