221 lines
6.6 KiB
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,
|
|
};
|