#include "proto-ftp.h" #include "proto-banner1.h" #include "unusedparm.h" #include "masscan-app.h" #include "stack-tcp-api.h" #include "proto-ssl.h" #include #include /*************************************************************************** ***************************************************************************/ static void ftp_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; unsigned i; struct FTPSTUFF *ftp = &pstate->sub.ftp; UNUSEDPARM(banner1_private); UNUSEDPARM(banner1); for (i=0; icode = 0; state++; /* fall through */ case 1: case 2: case 3: case 101: case 102: case 103: if (!isdigit(px[i]&0xFF)) { state = 0xffffffff; tcpapi_close(socket); } else { ftp->code *= 10; ftp->code += (px[i] - '0'); state++; banout_append_char(banout, PROTO_FTP, px[i]); } break; case 4: case 104: if (px[i] == ' ') { ftp->is_last = 1; state++; banout_append_char(banout, PROTO_FTP, px[i]); } else if (px[i] == '-') { ftp->is_last = 0; state++; banout_append_char(banout, PROTO_FTP, px[i]); } else { state = 0xffffffff; tcpapi_close(socket); } break; case 5: if (px[i] == '\r') continue; else if (px[i] == '\n') { if (ftp->is_last) { tcpapi_send(socket, "AUTH TLS\r\n", 10, 0); state = 100; banout_append_char(banout, PROTO_FTP, px[i]); } else { banout_append_char(banout, PROTO_FTP, px[i]); state = 0; } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_FTP, px[i]); } break; case 105: if (px[i] == '\r') continue; else if (px[i] == '\n') { if (ftp->code == 234) { /* change the state here to SSL */ unsigned port = pstate->port; memset(pstate, 0, sizeof(*pstate)); pstate->app_proto = PROTO_SSL3; pstate->is_sent_sslhello = 1; pstate->port = (unsigned short)port; state = 0; tcpapi_send(socket, banner_ssl.hello, banner_ssl.hello_length, 0); } else { state = 0xffffffff; tcpapi_close(socket); } } else if (px[i] == '\0' || !isprint(px[i])) { state = 0xffffffff; tcpapi_close(socket); continue; } else { banout_append_char(banout, PROTO_FTP, px[i]); } break; default: i = (unsigned)length; break; } } pstate->state = state; } /*************************************************************************** ***************************************************************************/ static void * ftp_init(struct Banner1 *banner1) { UNUSEDPARM(banner1); //banner1->payloads.tcp[21] = &banner_ftp; return 0; } /*************************************************************************** ***************************************************************************/ static int ftp_selftest(void) { return 0; } /*************************************************************************** ***************************************************************************/ const struct ProtocolParserStream banner_ftp = { "ftp", 21, 0, 0, 0, ftp_selftest, ftp_init, ftp_parse, };