Update telnet server login #296

This commit is contained in:
fvanroie 2022-02-12 11:23:08 +01:00
parent 8b17046ea4
commit ae2f0a1a6f

View File

@ -15,6 +15,9 @@
#include "../../hasp/hasp_dispatch.h" #include "../../hasp/hasp_dispatch.h"
#define IAC_SHOW_CHARACTERS "\xff\xfc\x01"
#define IAC_HIDE_CHARACTERS "\xff\xfb\x01"
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h> #include <WiFi.h>
WiFiClient telnetClient; WiFiClient telnetClient;
@ -44,14 +47,42 @@ ConsoleInput* telnetConsole;
void telnet_update_prompt() void telnet_update_prompt()
{ {
if(telnetConsole) telnetConsole->update(); if(telnetConsole) telnetConsole->update(__LINE__);
bufferedTelnetClient.flush(); bufferedTelnetClient.flush();
} }
static inline void telnet_new_prompt(const char* prompt)
{
if(!telnetConsole) return;
telnetClient.println(IAC_SHOW_CHARACTERS);
telnetConsole->setPrompt(prompt);
telnetConsole->clearLine(); // avoid leaking information, updates the prompt
telnet_update_prompt();
}
static inline void telnet_echo_on()
{
telnetClient.print(IAC_SHOW_CHARACTERS);
}
static inline void telnet_password_prompt()
{
telnetClient.print(IAC_SHOW_CHARACTERS D_PASSWORD " " IAC_HIDE_CHARACTERS);
}
static inline void telnet_username_prompt()
{
telnetClient.print(IAC_SHOW_CHARACTERS D_USERNAME " ");
}
static void telnetClientDisconnect() static void telnetClientDisconnect()
{ {
if(telnetClient.connected()) if(telnetClient.connected())
LOG_TRACE(TAG_TELN, F(D_TELNET_CLOSING_CONNECTION), telnetClient.remoteIP().toString().c_str()); LOG_TRACE(TAG_TELN, F(D_TELNET_CLOSING_CONNECTION), telnetClient.remoteIP().toString().c_str());
bufferedTelnetClient.flush(); // empty buffer
telnetClient.flush(); // empty buffer
Log.unregisterOutput(1); // telnetClient Log.unregisterOutput(1); // telnetClient
telnetClient.stop(); telnetClient.stop();
@ -70,21 +101,25 @@ void telnetStop(void)
void telnetClientLogon() void telnetClientLogon()
{ {
telnetClient.println();
debugPrintHaspHeader(&bufferedTelnetClient); debugPrintHaspHeader(&bufferedTelnetClient);
telnetLoginState = TELNET_AUTHENTICATED; // User and Pass are correct telnetLoginState = TELNET_AUTHENTICATED; // User and Pass are correct
telnetLoginAttempt = 0; // Reset attempt counter telnetLoginAttempt = 0; // Reset attempt counter
// telnetClient.setTimeout(10);
/* Now register logger for telnet */ // empty buffers
Log.registerOutput(1, &bufferedTelnetClient, LOG_LEVEL_VERBOSE, true);
bufferedTelnetClient.flush(); bufferedTelnetClient.flush();
// telnetClient.setTimeout(10); telnet_new_prompt("Prompt > ");
telnetClient.flush();
/* Now register logger for telnet and switch to buffered stream */
Log.registerOutput(1, &bufferedTelnetClient, LOG_LEVEL_VERBOSE, true);
LOG_TRACE(TAG_TELN, F(D_TELNET_CLIENT_LOGIN_FROM), telnetClient.remoteIP().toString().c_str()); LOG_TRACE(TAG_TELN, F(D_TELNET_CLIENT_LOGIN_FROM), telnetClient.remoteIP().toString().c_str());
} }
void telnetAcceptClient() void telnetAcceptClient()
{ {
bufferedTelnetClient.flush(); // empty buffer
if(telnetClient) { if(telnetClient) {
telnetClient.stop(); // previous client has disconnected telnetClient.stop(); // previous client has disconnected
Log.unregisterOutput(1); // telnetClient Log.unregisterOutput(1); // telnetClient
@ -96,6 +131,8 @@ void telnetAcceptClient()
} }
LOG_INFO(TAG_TELN, F(D_TELNET_CLIENT_CONNECT_FROM), telnetClient.remoteIP().toString().c_str()); LOG_INFO(TAG_TELN, F(D_TELNET_CLIENT_CONNECT_FROM), telnetClient.remoteIP().toString().c_str());
telnetClient.setNoDelay(true); telnetClient.setNoDelay(true);
telnetClient.printf("\x1b]2;%s\x07" TERM_CLEAR_LINE, haspDevice.get_hostname());
telnetClient.println("\r\nWelcome\r\n");
/* Avoid a buffer here */ /* Avoid a buffer here */
// telnetClient.print((char)0xFF); // DO TERMINAL-TYPE // telnetClient.print((char)0xFF); // DO TERMINAL-TYPE
@ -104,13 +141,16 @@ void telnetAcceptClient()
#if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0 #if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0
if(strlen(http_config.username) != 0 || strlen(http_config.password) != 0) { if(strlen(http_config.username) != 0 || strlen(http_config.password) != 0) {
telnetClient.println(F("\r\n" D_USERNAME " "));
telnetLoginState = TELNET_UNAUTHENTICATED; telnetLoginState = TELNET_UNAUTHENTICATED;
telnetClient.println();
telnet_username_prompt();
} else } else
#endif #endif
{ {
telnetClientLogon(); telnetClientLogon();
} }
telnetClient.flush();
telnetLoginAttempt = 0; // Initial attempt telnetLoginAttempt = 0; // Initial attempt
} }
@ -202,30 +242,36 @@ static inline void telnetProcessCharacter(char ch)
static void telnetProcessLine(const char* input) static void telnetProcessLine(const char* input)
{ {
bufferedTelnetClient.flush();
switch(telnetLoginState) { switch(telnetLoginState) {
case TELNET_UNAUTHENTICATED: { case TELNET_UNAUTHENTICATED: {
char buffer[20];
snprintf_P(buffer, sizeof(buffer), PSTR(D_PASSWORD " %c%c%c\n"), 0xFF, 0xFB,
0x01); // Hide characters
telnetClient.print(buffer);
#if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0 #if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0
telnetLoginState = strcmp(input, http_config.username) == 0 ? TELNET_USERNAME_OK : TELNET_USERNAME_NOK; bool username_is_valid = strcmp(input, http_config.username) == 0;
telnetLoginState = username_is_valid ? TELNET_USERNAME_OK : TELNET_USERNAME_NOK;
telnet_password_prompt();
break; break;
} }
case TELNET_USERNAME_OK: case TELNET_USERNAME_OK:
case TELNET_USERNAME_NOK: { case TELNET_USERNAME_NOK: {
telnetClient.printf(PSTR("%c%c%c\n"), 0xFF, 0xFC, 0x01); // Show characters bool password_is_valid = strcmp(input, http_config.password) == 0;
if(telnetLoginState == TELNET_USERNAME_OK && strcmp(input, http_config.password) == 0) { if(telnetConsole) telnetConsole->clearLine();
telnet_echo_on(); // Show characters
if(telnetLoginState == TELNET_USERNAME_OK && password_is_valid) {
telnetClientLogon(); telnetClientLogon();
} else { } else {
telnetLoginState = TELNET_UNAUTHENTICATED; telnetLoginState = TELNET_UNAUTHENTICATED;
telnetLoginAttempt++; // Subsequent attempt telnetLoginAttempt++; // Subsequent attempt
telnetClient.println(F(D_NETWORK_CONNECTION_UNAUTHORIZED "\r\n"));
LOG_WARNING(TAG_TELN, F(D_TELNET_INCORRECT_LOGIN_ATTEMPT), telnetClient.remoteIP().toString().c_str()); LOG_WARNING(TAG_TELN, F(D_TELNET_INCORRECT_LOGIN_ATTEMPT), telnetClient.remoteIP().toString().c_str());
telnetClient.println(F(D_NETWORK_CONNECTION_UNAUTHORIZED));
if(telnetLoginAttempt >= 3) { if(telnetLoginAttempt >= 3) {
telnetClientDisconnect(); telnetClientDisconnect();
} else { } else {
telnetClient.print(F(D_USERNAME " ")); telnetClient.println(F("\r\n\r\n" D_USERNAME " "));
} }
} }
#else #else
@ -240,7 +286,7 @@ static void telnetProcessLine(const char* input)
} else if(strcasecmp_P(input, PSTR("logoff")) == 0) { } else if(strcasecmp_P(input, PSTR("logoff")) == 0) {
#if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0 #if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0
if(strcmp(input, http_config.password) == 0) { if(strcmp(input, http_config.password) == 0) {
telnetClient.println(F("\r\n" D_USERNAME " ")); telnet_username_prompt();
telnetLoginState = TELNET_UNAUTHENTICATED; telnetLoginState = TELNET_UNAUTHENTICATED;
} else } else
#endif #endif
@ -251,6 +297,8 @@ static void telnetProcessLine(const char* input)
dispatch_text_line(input, TAG_TELN); dispatch_text_line(input, TAG_TELN);
} }
} }
telnetClient.flush();
} }
void telnetStart() void telnetStart()