#include "proto-tcp-telnet.h" #include "proto-banner1.h" #include "stack-tcp-api.h" #include "unusedparm.h" #include "masscan-app.h" #include "util-malloc.h" #include #include #include "util-safefunc.h" struct TelnetOptions { unsigned num; const char *text; }; /* This is a list of the options during negotiation that we might be interested in. */ struct TelnetOptions options[] = { { 0, "binary"}, /* 0x00 Binary */ { 1, "echo"}, /* 0x01 Echo */ //{ 2, "recon"}, /* 0x02 Reconnection */ { 3, "sga"}, /* 0x03 Suppress go ahead */ //{ 4, "msgsz"}, /* 0x04 Approx Message Size Negotiation */ { 5, "status"}, /* 0x05 Status */ { 6, "timing-mark"}, /* 0x06 Timing Mark */ /* 7 Remote Controlled Trans and Echo [107,JBP] 8 Output Line Width [40,JBP] 9 Output Page Size [41,JBP] 10 Output Carriage-Return Disposition [28,JBP] 11 Output Horizontal Tab Stops [32,JBP] 12 Output Horizontal Tab Disposition [31,JBP] 13 Output Formfeed Disposition [29,JBP] 14 Output Vertical Tabstops [34,JBP] 15 Output Vertical Tab Disposition [33,JBP] 16 Output Linefeed Disposition [30,JBP] 17 Extended ASCII [136,JBP] 18 Logout [25,MRC] 19 Byte Macro [35,JBP] 20 Data Entry Terminal [145,38,JBP]*/ //{21, "supdup"}, /* 0x15 SUPDUP */ {22, "supdupout"}, /* 0x16 SUPDUP Output */ {23, "sendloc"}, /* 0x17 Send Location */ {24, "term"}, /* 0x18 Terminal type */ /* 25 End of Record [103,JBP] 26 TACACS User Identification [1,BA4] 27 Output Marking [125,SXS] 28 Terminal Location Number [84,RN6] 29 Telnet 3270 Regime [116,JXR] 30 X.3 PAD [70,SL70] */ {31, "naws"}, /* 0x1f Negotiate About Window Size */ {32, "tspeed"}, /* 0x20 Terminal Speed */ {33, "rflow"}, /* 0x21 ! Remote Flow Control */ {34, "linemode"}, /* 0x22 " Linemode */ {35, "xloc"}, /* 0x23 # X Display Location */ {36, "env"}, /* 0x24 $ Environment Option [DB14]*/ {37, "auth"}, /* 0x25 % Authentication Option */ {38, "encrypt"}, /* 0x26 & Encryption Option */ {39, "new-env"}, /* 0x27 ' */ {46, "starttls"}, /* 0x2e . STARTTLS */ /* 255 Extended-Options-List [109,JBP] */ {0,0} }; #if 0 static const char * option_name_lookup(unsigned optnum) { size_t i; for (i=0; options[i].text; i++) { if (options[i].num == optnum) return options[i].text; } return 0; } #endif enum { FLAG_WILL=1, FLAG_WONT=2, FLAG_DO=4, FLAG_DONT=8, }; /*************************************************************************** ***************************************************************************/ static void telnet_parse( const struct Banner1 *banner1, void *banner1_private, struct StreamState *pstate, const unsigned char *px, size_t length, struct BannerOutput *banout, struct stack_handle_t *socket) { unsigned state = pstate->state; size_t offset; enum { TELNET_DATA, TELNET_IAC, TELNET_DO, TELNET_DONT, TELNET_WILL, TELNET_WONT, TELNET_SB, TELNET_SB_DATA, TELNET_INVALID, }; //static const char *foobar[4] = {"DO", "DONT", "WILL", "WONT"}; unsigned char nego[256] = {0}; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); UNUSEDPARM(socket); for (offset=0; offsetstate = state; } /*************************************************************************** ***************************************************************************/ static void * telnet_init(struct Banner1 *banner1) { UNUSEDPARM(banner1); return 0; } /*************************************************************************** ***************************************************************************/ static int telnet_selftest_item(const char *input, const char *output) { struct Banner1 *banner1; struct StreamState pstate[1]; struct BannerOutput banout1[1]; int x; /* * Initiate a pseudo-environment for the parser */ banner1 = banner1_create(); banout_init(banout1); memset(&pstate[0], 0, sizeof(pstate[0])); /* * Parse the input payload */ telnet_parse(banner1, 0, pstate, (const unsigned char *)input, strlen(input), banout1, 0 ); //fprintf(stderr, "%.*s\n", (int)banout_string_length(banout1, PROTO_TELNET), banout_string(banout1, PROTO_TELNET)); /* * Verify that somewhere in the output is the string * we are looking for */ x = banout_is_contains(banout1, PROTO_TELNET, output); if (x == 0) printf("telnet parser failure: %s\n", output); banner1_destroy(banner1); banout_release(banout1); return (x==0)?1:0; } /*************************************************************************** ***************************************************************************/ static int telnet_selftest(void) { struct { const char *input; const char *output; } tests[] = { {"\xff\xfd\x1flogin:", "login:"}, {"\xff\xfd\x27\xff\xfd\x18 ", " "}, { "\xff\xfb\x25\xff\xfd\x03\xff\xfb\x18\xff\xfb\x1f\xff\xfb\x20\xff" \ "\xfb\x21\xff\xfb\x22\xff\xfb\x27\xff\xfd\x05" "\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f" "\xff\xfa\x18\x01\xff\xf0" "\x0d\x0a\x55\x73\x65\x72\x20\x41\x63\x63\x65\x73\x73\x20\x56\x65" \ "\x72\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x0d\x0a\x0d\x0a" , "User Access" }, { "\xff\xfd\x01\xff\xfd\x1f\xff\xfd\x21\xff\xfb\x01\xff\xfb\x03\x46" "\x36\x37\x30\x0d\x0a\x0d\x4c\x6f\x67\x69\x6e\x3a\x20", "F670\r\n\rLogin:" }, {0,0} }; size_t i; for (i=0; tests[i].input; i++) { int err; err = telnet_selftest_item(tests[i].input, tests[i].output); if (err) { fprintf(stderr, "telnet: selftest fail, item %u\n", (unsigned)i); return err; } } return 0; } /*************************************************************************** ***************************************************************************/ const struct ProtocolParserStream banner_telnet = { "telnet", 23, "\xff\xf6", 2, 0, telnet_selftest, telnet_init, telnet_parse, };