Like with SSL, there is only a single 'tx'.
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,
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);
* 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 */
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;
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);
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
+ f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
+ f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
+ f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
+ f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
+ f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
f.alproto = ALPROTO_SSH;
+ f.proto = IPPROTO_TCP;
StreamTcpInitConfig(TRUE);
}
-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 */
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;
}
output_ctx->data = ssh_ctx;
output_ctx->DeInit = OutputSshLogDeinit;
+ AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_SSH);
return output_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);
}