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

221 lines
6.6 KiB
C

/*
imap4 banner checker
*/
#include "proto-imap4.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
imap4_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;
UNUSEDPARM(banner1_private);
UNUSEDPARM(banner1);
for (i=0; i<length; i++) {
if (px[i] == '\r')
continue;
switch (state) {
case 0:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '*')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 1:
if (px[i] == ' ') {
banout_append_char(banout, PROTO_IMAP4, px[i]);
continue;
} else {
state = 0xffffffff;
tcpapi_close(socket);
}
/* fall through */
case 2:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == 'O')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 3:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == 'K')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 4:
if (px[i] == ' ') {
banout_append_char(banout, PROTO_IMAP4, px[i]);
state++;
break;
} else if (px[i] != '\n') {
banout_append_char(banout, PROTO_IMAP4, px[i]);
/* no transition */
break;
} else {
state++;
/* fall through */
}
case 5:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '\n') {
tcpapi_send(socket, "a001 CAPABILITY\r\n", 17, 0);
state = 100;
}
break;
case 100:
case 300:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '*')
state += 100;
else if (px[i] == 'a')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 101:
case 301:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '0')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 102:
case 302:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '0')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 103:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '1')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 303:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '2')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 104:
case 304:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == ' ')
state++;
else {
state = 0xffffffff;
tcpapi_close(socket);
}
break;
case 105:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '\n') {
tcpapi_send(socket, "a002 STARTTLS\r\n", 15, 0);
state = 300;
}
break;
case 200:
case 400:
banout_append_char(banout, PROTO_IMAP4, px[i]);
if (px[i] == '\n')
state -= 100;
break;
case 305:
if (px[i] == '\n') {
/* 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);
break;
}
break;
case 0xffffffff:
default:
i = (unsigned)length;
break;
}
}
pstate->state = state;
}
/***************************************************************************
***************************************************************************/
static void *
imap4_init(struct Banner1 *banner1)
{
UNUSEDPARM(banner1);
return 0;
}
/***************************************************************************
***************************************************************************/
static int
imap4_selftest(void)
{
return 0;
}
/***************************************************************************
***************************************************************************/
const struct ProtocolParserStream banner_imap4 = {
"imap4", 21, 0, 0, 0,
imap4_selftest,
imap4_init,
imap4_parse,
};