|
|
|
@ -1433,7 +1433,6 @@ void FTPParserCleanup(void)
|
|
|
|
|
/** \test Send a get request in one chunk. */
|
|
|
|
|
static int FTPParserTest01(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf[] = "PORT 192,168,1,1,0,80\r\n";
|
|
|
|
|
uint32_t ftplen = sizeof(ftpbuf) - 1; /* minus the \0 */
|
|
|
|
@ -1443,49 +1442,28 @@ static int FTPParserTest01(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_EOF, ftpbuf, ftplen);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_PORT) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_PORT, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test Send a split get request. */
|
|
|
|
|
static int FTPParserTest03(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf1[] = "POR";
|
|
|
|
|
uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
|
|
|
|
@ -1499,71 +1477,38 @@ static int FTPParserTest03(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_START, ftpbuf1,
|
|
|
|
|
ftplen1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP, STREAM_TOSERVER,
|
|
|
|
|
ftpbuf2, ftplen2);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_EOF, ftpbuf3, ftplen3);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_PORT) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_PORT, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test See how it deals with an incomplete request. */
|
|
|
|
|
static int FTPParserTest06(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf1[] = "PORT";
|
|
|
|
|
uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
|
|
|
|
@ -1573,51 +1518,31 @@ static int FTPParserTest06(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_START | STREAM_EOF,
|
|
|
|
|
ftpbuf1,
|
|
|
|
|
ftplen1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_UNKNOWN) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_UNKNOWN, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_UNKNOWN);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test See how it deals with an incomplete request in multiple chunks. */
|
|
|
|
|
static int FTPParserTest07(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf1[] = "PO";
|
|
|
|
|
uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
|
|
|
|
@ -1629,63 +1554,35 @@ static int FTPParserTest07(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_START, ftpbuf1,
|
|
|
|
|
ftplen1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_EOF, ftpbuf2, ftplen2);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_PORT) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ",
|
|
|
|
|
FTP_COMMAND_PORT, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test Test case where chunks are smaller than the delim length and the
|
|
|
|
|
* last chunk is supposed to match the delim. */
|
|
|
|
|
static int FTPParserTest10(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf1[] = "PORT 1,2,3,4,5,6\r\n";
|
|
|
|
|
uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
|
|
|
|
@ -1695,7 +1592,6 @@ static int FTPParserTest10(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
@ -1710,43 +1606,24 @@ static int FTPParserTest10(void)
|
|
|
|
|
else if (u == (ftplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
|
|
|
|
|
else flags = STREAM_TOSERVER;
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP, flags,
|
|
|
|
|
&ftpbuf1[u], 1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
SCLogDebug("toserver chunk %" PRIu32 " returned %" PRId32 ", expected 0: ", u, r);
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_PORT) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_PORT, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test Supply RETR without a filename */
|
|
|
|
|
static int FTPParserTest11(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
|
|
|
|
|
uint8_t ftpbuf2[] = "RETR\r\n";
|
|
|
|
@ -1758,75 +1635,42 @@ static int FTPParserTest11(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_START, ftpbuf1,
|
|
|
|
|
sizeof(ftpbuf1) - 1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
/* Response */
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOCLIENT,
|
|
|
|
|
ftpbuf3,
|
|
|
|
|
sizeof(ftpbuf3) - 1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER, ftpbuf2,
|
|
|
|
|
sizeof(ftpbuf2) - 1);
|
|
|
|
|
if (r == 0) {
|
|
|
|
|
SCLogDebug("parse should've failed");
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r == 0);
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_RETR) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ",
|
|
|
|
|
FTP_COMMAND_RETR, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_RETR);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \test Supply STOR without a filename */
|
|
|
|
|
static int FTPParserTest12(void)
|
|
|
|
|
{
|
|
|
|
|
int result = 1;
|
|
|
|
|
Flow f;
|
|
|
|
|
uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
|
|
|
|
|
uint8_t ftpbuf2[] = "STOR\r\n";
|
|
|
|
@ -1838,69 +1682,37 @@ static int FTPParserTest12(void)
|
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
|
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
|
|
|
|
|
|
FLOW_INITIALIZE(&f);
|
|
|
|
|
f.protoctx = (void *)&ssn;
|
|
|
|
|
f.proto = IPPROTO_TCP;
|
|
|
|
|
f.alproto = ALPROTO_FTP;
|
|
|
|
|
|
|
|
|
|
StreamTcpInitConfig(TRUE);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER | STREAM_START, ftpbuf1,
|
|
|
|
|
sizeof(ftpbuf1) - 1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
/* Response */
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOCLIENT,
|
|
|
|
|
ftpbuf3,
|
|
|
|
|
sizeof(ftpbuf3) - 1);
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r != 0);
|
|
|
|
|
|
|
|
|
|
FLOWLOCK_WRLOCK(&f);
|
|
|
|
|
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
|
|
|
|
|
STREAM_TOSERVER, ftpbuf2,
|
|
|
|
|
sizeof(ftpbuf2) - 1);
|
|
|
|
|
if (r == 0) {
|
|
|
|
|
SCLogDebug("parse should've failed");
|
|
|
|
|
result = 0;
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FLOWLOCK_UNLOCK(&f);
|
|
|
|
|
FAIL_IF(r == 0);
|
|
|
|
|
|
|
|
|
|
FtpState *ftp_state = f.alstate;
|
|
|
|
|
if (ftp_state == NULL) {
|
|
|
|
|
SCLogDebug("no ftp state: ");
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF_NULL(ftp_state);
|
|
|
|
|
|
|
|
|
|
if (ftp_state->command != FTP_COMMAND_STOR) {
|
|
|
|
|
SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ",
|
|
|
|
|
FTP_COMMAND_STOR, ftp_state->command);
|
|
|
|
|
result = 0;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
FAIL_IF(ftp_state->command != FTP_COMMAND_STOR);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
if (alp_tctx != NULL)
|
|
|
|
|
AppLayerParserThreadCtxFree(alp_tctx);
|
|
|
|
|
StreamTcpFreeConfig(TRUE);
|
|
|
|
|
FLOW_DESTROY(&f);
|
|
|
|
|
return result;
|
|
|
|
|
PASS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
|
|
|
|
|