masscan-mark-ii/src/proto-ftp.c

152 lines
4.8 KiB
C

#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 <ctype.h>
#include <string.h>
/***************************************************************************
***************************************************************************/
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; i<length; i++) {
switch (state) {
case 0:
case 100:
ftp->code = 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,
};