mirror of
https://git.checksum.fail/alec/erythros
synced 2025-12-10 13:09:55 +02:00
142 lines
3.3 KiB
HolyC
142 lines
3.3 KiB
HolyC
// A very dumb, not-quite-Telnet program for testing purposes
|
|
// If running from a VM, on the host you can do something like:
|
|
|
|
// socat TCP-LISTEN:2323,bind=10.20.0.254,reuseaddr,fork EXEC:"/bin/bash",pty,stderr,setsid,sigint,sane
|
|
|
|
// and connect to the host from Erythros with "telnet 10.20.0.254 2323"
|
|
|
|
#define TELNET_WILL 251
|
|
#define TELNET_WONT 252
|
|
#define TELNET_DO 253
|
|
#define TELNET_DONT 254
|
|
#define TELNET_IAC 255
|
|
|
|
#define TELNET_CONNECTION_TIMED_OUT cnts.jiffies > ts_begin + ts_timeout
|
|
|
|
class TelnetSession {
|
|
@shell* sh;
|
|
TlsSocket* s;
|
|
};
|
|
|
|
I64 @telnet_ignore_commands(U8* buf)
|
|
{
|
|
I64 i = 0;
|
|
while (buf[i] == TELNET_IAC) {
|
|
switch (buf[i + 1]) {
|
|
case TELNET_WILL:
|
|
case TELNET_WONT:
|
|
buf[i + 1] = TELNET_DONT;
|
|
break;
|
|
case TELNET_DO:
|
|
case TELNET_DONT:
|
|
buf[i + 1] = TELNET_WONT;
|
|
break;
|
|
}
|
|
i += 3;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
U0 @telnet_session(TelnetSession* session)
|
|
{
|
|
U8 chars[1040];
|
|
U8* buf = &chars;
|
|
I64 cnt = 1;
|
|
I64 i;
|
|
|
|
while (cnt && session->s->state != TCP_SOCKET_STATE_CLOSED) {
|
|
cnt = session->s->receive(buf, 1024);
|
|
if (cnt) {
|
|
buf[cnt] = NULL;
|
|
i = 0;
|
|
while (i < cnt) {
|
|
switch (buf[i]) {
|
|
case TELNET_IAC:
|
|
i += @telnet_ignore_commands(buf);
|
|
session->s->send(buf, i);
|
|
buf += i;
|
|
break;
|
|
default:
|
|
Stdio.WriteLine(session->sh, buf);
|
|
i = cnt;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Sleep(1);
|
|
}
|
|
}
|
|
|
|
U0 @telnet_handle_input(@shell* sh, TlsSocket* s)
|
|
{
|
|
U8 buf[128];
|
|
I64 len = 0;
|
|
while (FifoU8Cnt(sh->input))
|
|
FifoU8Rem(sh->input, buf + len++);
|
|
if (len)
|
|
s->send(buf, len);
|
|
}
|
|
|
|
I64 @shell_cmd_telnet(@shell* sh, I64 argc, U8** argv)
|
|
{
|
|
if (argc < 2) {
|
|
Stdio.WriteLine(sh, "Usage: telnet host [port]\n");
|
|
return 1;
|
|
}
|
|
|
|
U8 buf[128];
|
|
U8* host = argv[1];
|
|
I64 port = 23;
|
|
if (argc > 2) {
|
|
port = Str2I64(argv[2]);
|
|
}
|
|
|
|
I64 ts_begin = 0;
|
|
I64 ts_timeout = 10000;
|
|
|
|
if (!host || !StrLen(host)) {
|
|
Stdio.WriteLine(sh, "telnet: Invalid host specified\n");
|
|
return 1;
|
|
}
|
|
|
|
if (@dns_query(host) == U32_MAX) {
|
|
Stdio.WriteLine(sh, "telnet: Host not found: %s\n", host);
|
|
return 1;
|
|
}
|
|
|
|
StrPrint(buf, "Trying %s port %d...\n", host, port);
|
|
Stdio.WriteLine(sh, buf);
|
|
|
|
TelnetSession session;
|
|
session.sh = sh;
|
|
session.s = @tcp_socket_create(host, port);
|
|
ts_begin = cnts.jiffies;
|
|
|
|
while (!sh->break && session.s->state != TCP_SOCKET_STATE_ESTABLISHED && !(TELNET_CONNECTION_TIMED_OUT)) {
|
|
Sleep(1);
|
|
}
|
|
|
|
if (sh->break) {
|
|
session.s->close();
|
|
return 1;
|
|
}
|
|
|
|
if (TELNET_CONNECTION_TIMED_OUT) {
|
|
Stdio.WriteLine(sh, "Connection timed out.\n");
|
|
session.s->close();
|
|
return 1;
|
|
}
|
|
|
|
StrPrint(buf, "Connected to %s.\n", host);
|
|
Stdio.WriteLine(sh, buf);
|
|
|
|
Spawn(&@telnet_session, &session);
|
|
|
|
while (session.s->state != TCP_SOCKET_STATE_CLOSED) {
|
|
@telnet_handle_input(sh, session.s);
|
|
Sleep(1);
|
|
}
|
|
|
|
Stdio.WriteLine(sh, "Connection closed by foreign host.\n");
|
|
return 1;
|
|
} |