GaabMM88

Untitled

Feb 18th, 2025
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.87 KB | None | 0 0
  1. /*
  2.   Asynchronous WebServer library for Espressif MCUs
  3.  
  4.   Copyright (c) 2016 Hristo Gochkov. All rights reserved.
  5.   This file is part of the esp8266 core for Arduino environment.
  6.  
  7.   This library is free software; you can redistribute it and/or
  8.   modify it under the terms of the GNU Lesser General Public
  9.   License as published by the Free Software Foundation; either
  10.   version 2.1 of the License, or (at your option) any later version.
  11.  
  12.   This library is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.   Lesser General Public License for more details.
  16.  
  17.   You should have received a copy of the GNU Lesser General Public
  18.   License along with this library; if not, write to the Free Software
  19.   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20. */
  21. #include "WebAuthentication.h"
  22. #include <libb64/cencode.h>
  23. #ifdef ESP32
  24. #include "mbedtls/md5.h"
  25. #else
  26. #include "md5.h"
  27. #endif
  28.  
  29.  
  30. // Basic Auth hash = base64("username:password")
  31.  
  32. bool checkBasicAuthentication(const char * hash, const char * username, const char * password){
  33.   if(username == NULL || password == NULL || hash == NULL)
  34.     return false;
  35.  
  36.   size_t toencodeLen = strlen(username)+strlen(password)+1;
  37.   size_t encodedLen = base64_encode_expected_len(toencodeLen);
  38.   if(strlen(hash) != encodedLen)
  39.     return false;
  40.  
  41.   char *toencode = new char[toencodeLen+1];
  42.   if(toencode == NULL){
  43.     return false;
  44.   }
  45.   char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
  46.   if(encoded == NULL){
  47.     delete[] toencode;
  48.     return false;
  49.   }
  50.   sprintf(toencode, "%s:%s", username, password);
  51.   if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0){
  52.     delete[] toencode;
  53.     delete[] encoded;
  54.     return true;
  55.   }
  56.   delete[] toencode;
  57.   delete[] encoded;
  58.   return false;
  59. }
  60.  
  61. static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or more
  62. #ifdef ESP32
  63.     mbedtls_md5_context _ctx;
  64. #else
  65.     md5_context_t _ctx;
  66. #endif
  67.   uint8_t i;
  68.   uint8_t * _buf = (uint8_t*)malloc(16);
  69.   if(_buf == NULL)
  70.     return false;
  71.   memset(_buf, 0x00, 16);
  72. #ifdef ESP32
  73.   mbedtls_md5_init(&_ctx);
  74.   mbedtls_md5_starts_ret(&_ctx);
  75.   mbedtls_md5_update_ret(&_ctx, data, len);
  76.   mbedtls_md5_finish_ret(&_ctx, _buf);
  77. #else
  78.   MD5Init(&_ctx);
  79.   MD5Update(&_ctx, data, len);
  80.   MD5Final(_buf, &_ctx);
  81. #endif
  82.   for(i = 0; i < 16; i++) {
  83.     sprintf(output + (i * 2), "%02x", _buf[i]);
  84.   }
  85.   free(_buf);
  86.   return true;
  87. }
  88.  
  89. static String genRandomMD5(){
  90. #ifdef ESP8266
  91.   uint32_t r = RANDOM_REG32;
  92. #else
  93.   uint32_t r = rand();
  94. #endif
  95.   char * out = (char*)malloc(33);
  96.   if(out == NULL || !getMD5((uint8_t*)(&r), 4, out))
  97.     return "";
  98.   String res = String(out);
  99.   free(out);
  100.   return res;
  101. }
  102.  
  103. static String stringMD5(const String& in){
  104.   char * out = (char*)malloc(33);
  105.   if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
  106.     return "";
  107.   String res = String(out);
  108.   free(out);
  109.   return res;
  110. }
  111.  
  112. String generateDigestHash(const char * username, const char * password, const char * realm){
  113.   if(username == NULL || password == NULL || realm == NULL){
  114.     return "";
  115.   }
  116.   char * out = (char*)malloc(33);
  117.   String res = String(username);
  118.   res.concat(":");
  119.   res.concat(realm);
  120.   res.concat(":");
  121.   String in = res;
  122.   in.concat(password);
  123.   if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
  124.     return "";
  125.   res.concat(out);
  126.   free(out);
  127.   return res;
  128. }
  129.  
  130. String requestDigestAuthentication(const char * realm){
  131.   String header = "realm=\"";
  132.   if(realm == NULL)
  133.     header.concat("asyncesp");
  134.   else
  135.     header.concat(realm);
  136.   header.concat( "\", qop=\"auth\", nonce=\"");
  137.   header.concat(genRandomMD5());
  138.   header.concat("\", opaque=\"");
  139.   header.concat(genRandomMD5());
  140.   header.concat("\"");
  141.   return header;
  142. }
  143.  
  144. bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri){
  145.   if(username == NULL || password == NULL || header == NULL || method == NULL){
  146.     //os_printf("AUTH FAIL: missing requred fields\n");
  147.     return false;
  148.   }
  149.  
  150.   String myHeader = String(header);
  151.   int nextBreak = myHeader.indexOf(",");
  152.   if(nextBreak < 0){
  153.     //os_printf("AUTH FAIL: no variables\n");
  154.     return false;
  155.   }
  156.  
  157.   String myUsername = String();
  158.   String myRealm = String();
  159.   String myNonce = String();
  160.   String myUri = String();
  161.   String myResponse = String();
  162.   String myQop = String();
  163.   String myNc = String();
  164.   String myCnonce = String();
  165.  
  166.   myHeader += ", ";
  167.   do {
  168.     String avLine = myHeader.substring(0, nextBreak);
  169.     avLine.trim();
  170.     myHeader = myHeader.substring(nextBreak+1);
  171.     nextBreak = myHeader.indexOf(",");
  172.  
  173.     int eqSign = avLine.indexOf("=");
  174.     if(eqSign < 0){
  175.       //os_printf("AUTH FAIL: no = sign\n");
  176.       return false;
  177.     }
  178.     String varName = avLine.substring(0, eqSign);
  179.     avLine = avLine.substring(eqSign + 1);
  180.     if(avLine.startsWith("\"")){
  181.       avLine = avLine.substring(1, avLine.length() - 1);
  182.     }
  183.  
  184.     if(varName.equals("username")){
  185.       if(!avLine.equals(username)){
  186.         //os_printf("AUTH FAIL: username\n");
  187.         return false;
  188.       }
  189.       myUsername = avLine;
  190.     } else if(varName.equals("realm")){
  191.       if(realm != NULL && !avLine.equals(realm)){
  192.         //os_printf("AUTH FAIL: realm\n");
  193.         return false;
  194.       }
  195.       myRealm = avLine;
  196.     } else if(varName.equals("nonce")){
  197.       if(nonce != NULL && !avLine.equals(nonce)){
  198.         //os_printf("AUTH FAIL: nonce\n");
  199.         return false;
  200.       }
  201.       myNonce = avLine;
  202.     } else if(varName.equals("opaque")){
  203.       if(opaque != NULL && !avLine.equals(opaque)){
  204.         //os_printf("AUTH FAIL: opaque\n");
  205.         return false;
  206.       }
  207.     } else if(varName.equals("uri")){
  208.       if(uri != NULL && !avLine.equals(uri)){
  209.         //os_printf("AUTH FAIL: uri\n");
  210.         return false;
  211.       }
  212.       myUri = avLine;
  213.     } else if(varName.equals("response")){
  214.       myResponse = avLine;
  215.     } else if(varName.equals("qop")){
  216.       myQop = avLine;
  217.     } else if(varName.equals("nc")){
  218.       myNc = avLine;
  219.     } else if(varName.equals("cnonce")){
  220.       myCnonce = avLine;
  221.     }
  222.   } while(nextBreak > 0);
  223.  
  224.   String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ":" + myRealm + ":" + String(password));
  225.   String ha2 = String(method) + ":" + myUri;
  226.   String response = ha1 + ":" + myNonce + ":" + myNc + ":" + myCnonce + ":" + myQop + ":" + stringMD5(ha2);
  227.  
  228.   if(myResponse.equals(stringMD5(response))){
  229.     //os_printf("AUTH SUCCESS\n");
  230.     return true;
  231.   }
  232.  
  233.   //os_printf("AUTH FAIL: password\n");
  234.   return false;
  235. }
  236.  
Add Comment
Please, Sign In to add comment