ssh: convert app-layer parser to be tx aware

Like with SSL, there is only a single 'tx'.
pull/2559/head
Victor Julien 8 years ago
parent 4ae4fd0802
commit 3ee4989ba7

@ -494,9 +494,96 @@ static void SSHStateFree(void *state)
if (s->srv_hdr.banner_buffer != NULL)
SCFree(s->srv_hdr.banner_buffer);
//AppLayerDecoderEventsFreeEvents(&s->decoder_events);
if (s->de_state != NULL) {
DetectEngineStateFree(s->de_state);
}
SCFree(s);
}
static int SSHStateHasTxDetectState(void *state)
{
SshState *ssh_state = (SshState *)state;
if (ssh_state->de_state)
return 1;
return 0;
}
static int SSHSetTxDetectState(void *state, void *vtx, DetectEngineState *de_state)
{
SshState *ssh_state = (SshState *)state;
ssh_state->de_state = de_state;
return 0;
}
static DetectEngineState *SSHGetTxDetectState(void *vtx)
{
SshState *ssh_state = (SshState *)vtx;
return ssh_state->de_state;
}
static void SSHStateTransactionFree(void *state, uint64_t tx_id)
{
/* do nothing */
}
static void *SSHGetTx(void *state, uint64_t tx_id)
{
SshState *ssh_state = (SshState *)state;
return ssh_state;
}
static uint64_t SSHGetTxCnt(void *state)
{
/* single tx */
return 1;
}
static void SSHSetTxLogged(void *state, void *tx, uint32_t logger)
{
SshState *ssh_state = (SshState *)state;
if (ssh_state)
ssh_state->logged |= logger;
}
static int SSHGetTxLogged(void *state, void *tx, uint32_t logger)
{
SshState *ssh_state = (SshState *)state;
if (ssh_state && (ssh_state->logged & logger)) {
return 1;
}
return 0;
}
static int SSHGetAlstateProgressCompletionStatus(uint8_t direction)
{
return SSH_STATE_FINISHED;
}
static int SSHGetAlstateProgress(void *tx, uint8_t direction)
{
SshState *ssh_state = (SshState *)tx;
if (ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE &&
ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE) {
return SSH_STATE_FINISHED;
}
if (direction == STREAM_TOSERVER) {
if (ssh_state->cli_hdr.flags & SSH_FLAG_PARSER_DONE) {
return SSH_STATE_BANNER_DONE;
}
} else {
if (ssh_state->srv_hdr.flags & SSH_FLAG_PARSER_DONE) {
return SSH_STATE_BANNER_DONE;
}
}
return SSH_STATE_IN_PROGRESS;
}
static int SSHRegisterPatternsForProtocolDetection(void)
{
if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_SSH,
@ -532,6 +619,22 @@ void RegisterSSHParsers(void)
AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SSH, SSHStateAlloc, SSHStateFree);
AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP,
ALPROTO_SSH, STREAM_TOSERVER|STREAM_TOCLIENT);
AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SSH, SSHStateTransactionFree);
AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SSH, SSHStateHasTxDetectState,
SSHGetTxDetectState, SSHSetTxDetectState);
AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SSH, SSHGetTx);
AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SSH, SSHGetTxCnt);
AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SSH, SSHGetAlstateProgress);
AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_SSH, SSHGetTxLogged, SSHSetTxLogged);
AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_SSH,
SSHGetAlstateProgressCompletionStatus);
} else {
// SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
// "still on.", proto_name);

@ -32,8 +32,6 @@
* must be ciphered, so the parsing finish here */
#define SSH_FLAG_PARSER_DONE 0x02
#define SSH_FLAG_STATE_LOGGED 0x04
#define SSH_FLAG_STATE_LOGGED_LUA 0x08
/* MSG_CODE */
@ -56,6 +54,7 @@ typedef struct SshHeader_ {
uint32_t pkt_len;
uint8_t padding_len;
uint8_t msg_code;
uint16_t banner_len;
uint8_t buf[6];
uint8_t buf_offset;
uint8_t flags;
@ -63,13 +62,23 @@ typedef struct SshHeader_ {
uint8_t *proto_version;
uint8_t *software_version;
uint8_t *banner_buffer;
uint16_t banner_len;
} SshHeader;
enum {
SSH_STATE_IN_PROGRESS,
SSH_STATE_BANNER_DONE,
SSH_STATE_FINISHED,
};
/** structure to store the SSH state values */
typedef struct SshState_ {
SshHeader srv_hdr;
SshHeader cli_hdr;
/* specifies which loggers are done logging */
uint32_t logged;
DetectEngineState *de_state;
} SshState;
void RegisterSSHParsers(void);

@ -360,6 +360,7 @@ static int DetectSshVersionTestDetect01(void)
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
@ -477,6 +478,7 @@ static int DetectSshVersionTestDetect02(void)
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
@ -592,6 +594,7 @@ static int DetectSshVersionTestDetect03(void)
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);

@ -332,6 +332,7 @@ static int DetectSshSoftwareVersionTestDetect01(void)
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
@ -449,6 +450,7 @@ static int DetectSshSoftwareVersionTestDetect02(void)
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
@ -565,6 +567,7 @@ static int DetectSshSoftwareVersionTestDetect03(void)
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);

@ -89,36 +89,29 @@ void JsonSshLogJSON(json_t *tjs, SshState *ssh_state)
}
static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p)
static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p,
Flow *f, void *state, void *txptr, uint64_t tx_id)
{
JsonSshLogThread *aft = (JsonSshLogThread *)thread_data;
OutputSshCtx *ssh_ctx = aft->sshlog_ctx;
if (unlikely(p->flow == NULL)) {
return 0;
}
/* check if we have SSH state or not */
uint16_t proto = FlowGetAppProtocol(p->flow);
if (proto != ALPROTO_SSH)
goto end;
SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
SshState *ssh_state = (SshState *)state;
if (unlikely(ssh_state == NULL)) {
goto end;
return 0;
}
if (ssh_state->cli_hdr.software_version == NULL || ssh_state->srv_hdr.software_version == NULL)
goto end;
if (ssh_state->cli_hdr.software_version == NULL ||
ssh_state->srv_hdr.software_version == NULL)
return 0;
json_t *js = CreateJSONHeader((Packet *)p, 1, "ssh");//TODO
if (unlikely(js == NULL))
goto end;
return 0;
json_t *tjs = json_object();
if (tjs == NULL) {
free(js);
goto end;
return 0;
}
/* reset */
@ -132,9 +125,6 @@ static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p)
json_object_clear(js);
json_decref(js);
/* we only log the state once */
ssh_state->cli_hdr.flags |= SSH_FLAG_STATE_LOGGED;
end:
return 0;
}
@ -230,6 +220,7 @@ OutputCtx *OutputSshLogInit(ConfNode *conf)
output_ctx->data = ssh_ctx;
output_ctx->DeInit = OutputSshLogDeinit;
AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_SSH);
return output_ctx;
}
@ -267,58 +258,24 @@ OutputCtx *OutputSshLogInitSub(ConfNode *conf, OutputCtx *parent_ctx)
output_ctx->data = ssh_ctx;
output_ctx->DeInit = OutputSshLogDeinitSub;
AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_SSH);
return output_ctx;
}
/** \internal
* \brief Condition function for SSH logger
* \retval bool true or false -- log now?
*/
static int JsonSshCondition(ThreadVars *tv, const Packet *p)
{
if (p->flow == NULL) {
return FALSE;
}
if (!(PKT_IS_TCP(p))) {
return FALSE;
}
uint16_t proto = FlowGetAppProtocol(p->flow);
if (proto != ALPROTO_SSH)
goto dontlog;
SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
if (ssh_state == NULL) {
SCLogDebug("no ssh state, so no logging");
goto dontlog;
}
/* we only log the state once */
if (ssh_state->cli_hdr.flags & SSH_FLAG_STATE_LOGGED)
goto dontlog;
if (ssh_state->cli_hdr.software_version == NULL ||
ssh_state->srv_hdr.software_version == NULL)
goto dontlog;
/* todo: logic to log once */
return TRUE;
dontlog:
return FALSE;
}
void JsonSshLogRegister (void)
{
/* register as separate module */
OutputRegisterPacketModule(LOGGER_JSON_SSH, "JsonSshLog", "ssh-json-log",
OutputSshLogInit, JsonSshLogger, JsonSshCondition, JsonSshLogThreadInit,
JsonSshLogThreadDeinit, NULL);
OutputRegisterTxModuleWithProgress(LOGGER_JSON_SSH,
"JsonSshLog", "ssh-json-log",
OutputSshLogInit, ALPROTO_SSH, JsonSshLogger,
SSH_STATE_BANNER_DONE, SSH_STATE_BANNER_DONE,
JsonSshLogThreadInit, JsonSshLogThreadDeinit, NULL);
/* also register as child of eve-log */
OutputRegisterPacketSubModule(LOGGER_JSON_SSH, "eve-log", "JsonSshLog",
"eve-log.ssh", OutputSshLogInitSub, JsonSshLogger, JsonSshCondition,
OutputRegisterTxSubModuleWithProgress(LOGGER_JSON_SSH,
"eve-log", "JsonSshLog", "eve-log.ssh",
OutputSshLogInitSub, ALPROTO_SSH, JsonSshLogger,
SSH_STATE_BANNER_DONE, SSH_STATE_BANNER_DONE,
JsonSshLogThreadInit, JsonSshLogThreadDeinit, NULL);
}

Loading…
Cancel
Save