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"
#define IAC_SHOW_CHARACTERS "\xff\xfc\x01"
#define IAC_HIDE_CHARACTERS "\xff\xfb\x01"
#if defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
WiFiClient telnetClient;
@ -44,14 +47,42 @@ ConsoleInput* telnetConsole;
void telnet_update_prompt()
{
if(telnetConsole) telnetConsole->update();
if(telnetConsole) telnetConsole->update(__LINE__);
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()
{
if(telnetClient.connected())
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
telnetClient.stop();
@ -70,21 +101,25 @@ void telnetStop(void)
void telnetClientLogon()
{
telnetClient.println();
debugPrintHaspHeader(&bufferedTelnetClient);
telnetLoginState = TELNET_AUTHENTICATED; // User and Pass are correct
telnetLoginAttempt = 0; // Reset attempt counter
// telnetClient.setTimeout(10);
/* Now register logger for telnet */
Log.registerOutput(1, &bufferedTelnetClient, LOG_LEVEL_VERBOSE, true);
// empty buffers
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());
}
void telnetAcceptClient()
{
bufferedTelnetClient.flush(); // empty buffer
if(telnetClient) {
telnetClient.stop(); // previous client has disconnected
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());
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 */
// telnetClient.print((char)0xFF); // DO TERMINAL-TYPE
@ -104,13 +141,16 @@ void telnetAcceptClient()
#if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0
if(strlen(http_config.username) != 0 || strlen(http_config.password) != 0) {
telnetClient.println(F("\r\n" D_USERNAME " "));
telnetLoginState = TELNET_UNAUTHENTICATED;
telnetClient.println();
telnet_username_prompt();
} else
#endif
{
telnetClientLogon();
}
telnetClient.flush();
telnetLoginAttempt = 0; // Initial attempt
}
@ -202,30 +242,36 @@ static inline void telnetProcessCharacter(char ch)
static void telnetProcessLine(const char* input)
{
bufferedTelnetClient.flush();
switch(telnetLoginState) {
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
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;
}
case TELNET_USERNAME_OK:
case TELNET_USERNAME_NOK: {
telnetClient.printf(PSTR("%c%c%c\n"), 0xFF, 0xFC, 0x01); // Show characters
if(telnetLoginState == TELNET_USERNAME_OK && strcmp(input, http_config.password) == 0) {
bool password_is_valid = strcmp(input, http_config.password) == 0;
if(telnetConsole) telnetConsole->clearLine();
telnet_echo_on(); // Show characters
if(telnetLoginState == TELNET_USERNAME_OK && password_is_valid) {
telnetClientLogon();
} else {
telnetLoginState = TELNET_UNAUTHENTICATED;
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());
telnetClient.println(F(D_NETWORK_CONNECTION_UNAUTHORIZED));
if(telnetLoginAttempt >= 3) {
telnetClientDisconnect();
} else {
telnetClient.print(F(D_USERNAME " "));
telnetClient.println(F("\r\n\r\n" D_USERNAME " "));
}
}
#else
@ -240,7 +286,7 @@ static void telnetProcessLine(const char* input)
} else if(strcasecmp_P(input, PSTR("logoff")) == 0) {
#if HASP_USE_HTTP > 0 || HASP_USE_HTTP_ASYNC > 0
if(strcmp(input, http_config.password) == 0) {
telnetClient.println(F("\r\n" D_USERNAME " "));
telnet_username_prompt();
telnetLoginState = TELNET_UNAUTHENTICATED;
} else
#endif
@ -251,6 +297,8 @@ static void telnetProcessLine(const char* input)
dispatch_text_line(input, TAG_TELN);
}
}
telnetClient.flush();
}
void telnetStart()