Exemplo n.º 1
0
/**
 * \brief Check if we need to drop-log this packet
 *
 * \param tv    Pointer the current thread variables
 * \param p     Pointer the packet which is tested
 *
 * \retval bool TRUE or FALSE
 */
static int JsonDropLogCondition(ThreadVars *tv, const Packet *p)
{
    if (!EngineModeIsIPS()) {
        SCLogDebug("engine is not running in inline mode, so returning");
        return FALSE;
    }
    if (PKT_IS_PSEUDOPKT(p)) {
        SCLogDebug("drop log doesn't log pseudo packets");
        return FALSE;
    }

    if (p->flow != NULL) {
        int ret = FALSE;

        /* for a flow that will be dropped fully, log just once per direction */
        FLOWLOCK_RDLOCK(p->flow);
        if (p->flow->flags & FLOW_ACTION_DROP) {
            if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED))
                ret = TRUE;
            else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED))
                ret = TRUE;
        }
        FLOWLOCK_UNLOCK(p->flow);

        /* if drop is caused by signature, log anyway */
        if (p->alerts.drop.action != 0)
            ret = TRUE;

        return ret;
    } else if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
        return TRUE;
    }

    return FALSE;
}
Exemplo n.º 2
0
/**
 * \brief match the specified version on a tls session
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectTlsVersionData
 *
 * \retval 0 no match
 * \retval 1 match
 */
int DetectTlsVersionMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m)
{
    SCEnter();

    DetectTlsVersionData *tls_data = (DetectTlsVersionData *)m->ctx;
    SSLState *ssl_state = (SSLState *)state;
    if (ssl_state == NULL) {
        SCLogDebug("no tls state, no match");
        SCReturnInt(0);
    }

    int ret = 0;
    FLOWLOCK_RDLOCK(f);
    SCLogDebug("looking for tls_data->ver 0x%02X (flags 0x%02X)", tls_data->ver, flags);

    if (flags & STREAM_TOCLIENT) {
        SCLogDebug("server (toclient) version is 0x%02X", ssl_state->server_connp.version);
        if (tls_data->ver == ssl_state->server_connp.version)
            ret = 1;
    } else if (flags & STREAM_TOSERVER) {
        SCLogDebug("client (toserver) version is 0x%02X", ssl_state->client_connp.version);
        if (tls_data->ver == ssl_state->client_connp.version)
            ret = 1;
    }
    FLOWLOCK_UNLOCK(f);

    SCReturnInt(ret);
}
Exemplo n.º 3
0
/**
 * \brief Check if we need to drop-log this packet
 *
 * \param tv    Pointer the current thread variables
 * \param p     Pointer the packet which is tested
 *
 * \retval bool TRUE or FALSE
 */
static int LogDropCondition(ThreadVars *tv, const Packet *p)
{
    if (!EngineModeIsIPS()) {
        SCLogDebug("engine is not running in inline mode, so returning");
        return FALSE;
    }
    if (PKT_IS_PSEUDOPKT(p)) {
        SCLogDebug("drop log doesn't log pseudo packets");
        return FALSE;
    }

    if (p->flow != NULL) {
        int ret = FALSE;
        FLOWLOCK_RDLOCK(p->flow);
        if (p->flow->flags & FLOW_ACTION_DROP) {
            if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED))
                ret = TRUE;
            else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED))
                ret = TRUE;
        }
        FLOWLOCK_UNLOCK(p->flow);
        return ret;
    } else if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
        return TRUE;
    }

    return FALSE;
}
Exemplo n.º 4
0
/**
 * \brief Do the http_method content inspection for a signature.
 *
 * \param de_ctx  Detection engine context.
 * \param det_ctx Detection engine thread context.
 * \param s       Signature to inspect.
 * \param f       Flow.
 * \param flags   App layer flags.
 * \param state   App layer state.
 *
 * \retval 0 No match.
 * \retval 1 Match.
 */
int DetectEngineInspectHttpMethod(DetectEngineCtx *de_ctx,
                                  DetectEngineThreadCtx *det_ctx,
                                  Signature *s, Flow *f, uint8_t flags,
                                  void *alstate)
{
    SCEnter();
    int r = 0;
    HtpState *htp_state = NULL;
    htp_tx_t *tx = NULL;
    int idx;

    FLOWLOCK_RDLOCK(f);

    htp_state = (HtpState *)alstate;
    if (htp_state == NULL) {
        SCLogDebug("no HTTP state");
        goto end;
    }

    if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
        SCLogDebug("HTP state has no conn(p)");
        goto end;
    }

    idx = AppLayerTransactionGetInspectId(f);
    if (idx == -1) {
        goto end;
    }

    int size = (int)list_size(htp_state->connp->conn->transactions);
    for (; idx < size; idx++) {

        tx = list_get(htp_state->connp->conn->transactions, idx);
        if (tx == NULL || tx->request_method == NULL)
            continue;

        det_ctx->buffer_offset = 0;
        det_ctx->discontinue_matching = 0;
        det_ctx->inspection_recursion_counter = 0;

        r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH],
                                          f,
                                          (uint8_t *)bstr_ptr(tx->request_method),
                                          bstr_len(tx->request_method),
                                          DETECT_ENGINE_CONTENT_INSPECTION_MODE_HMD, NULL);
        //r = DoInspectHttpMethod(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HMDMATCH],
        //(uint8_t *)bstr_ptr(tx->request_method),
        //bstr_len(tx->request_method));
        if (r == 1) {
            break;
        }
    }

end:
    FLOWLOCK_UNLOCK(f);
    SCReturnInt(r);
}
Exemplo n.º 5
0
int FlowBitIsnotset(Flow *f, uint16_t idx) {
    int r = 0;
    FLOWLOCK_RDLOCK(f);

    FlowBit *fb = FlowBitGet(f, idx);
    if (fb == NULL) {
        r = 1;
    }

    FLOWLOCK_UNLOCK(f);
    return r;
}
Exemplo n.º 6
0
/**
 * \brief   This function is used to match urilen rule option with the HTTP
 *          uricontent.
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectUrilenData
 *
 * \retval 0 no match
 * \retval 1 match
 */
int DetectUrilenMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f,
                       uint8_t flags, void *state, Signature *s, SigMatch *m)
{
    SCEnter();
    int ret = 0;
    int idx = 0;
    DetectUrilenData *urilend = (DetectUrilenData *) m->ctx;

    HtpState *htp_state = (HtpState *)state;
    if (htp_state == NULL) {
        SCLogDebug("no HTP state, no need to match further");
        SCReturnInt(ret);
    }

    FLOWLOCK_RDLOCK(f);
    htp_tx_t *tx = NULL;

    idx = AppLayerTransactionGetInspectId(f);
    if (idx == -1) {
        goto end;
    }

    int size = (int)list_size(htp_state->connp->conn->transactions);
    for (; idx < size; idx++)
    {
        tx = list_get(htp_state->connp->conn->transactions, idx);
        if (tx == NULL || tx->request_uri_normalized == NULL)
            goto end;

        switch (urilend->mode) {
            case DETECT_URILEN_EQ:
                if (bstr_len(tx->request_uri_normalized) == urilend->urilen1)
                    ret = 1;
                break;
            case DETECT_URILEN_LT:
                if (bstr_len(tx->request_uri_normalized) < urilend->urilen1)
                    ret = 1;
                break;
            case DETECT_URILEN_GT:
                if (bstr_len(tx->request_uri_normalized) > urilend->urilen1)
                    ret = 1;
                break;
            case DETECT_URILEN_RA:
                if (bstr_len(tx->request_uri_normalized) > urilend->urilen1 &&
                        bstr_len(tx->request_uri_normalized) < urilend->urilen2)
                    ret = 1;
                break;
        }
    }
end:
    FLOWLOCK_UNLOCK(f);
    SCReturnInt(ret);
}
Exemplo n.º 7
0
int FlowAlertSidIsnotset(Flow *f, uint32_t sid) {
    int r = 0;
    FLOWLOCK_RDLOCK(f);

    FlowAlertSid *fb = FlowAlertSidGet(f, sid);
    if (fb == NULL) {
        r = 1;
    }

    FLOWLOCK_UNLOCK(f);
    return r;
}
Exemplo n.º 8
0
int DetectAppLayerProtocolMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                                Flow *f, uint8_t flags, void *state,
                                Signature *s, SigMatch *m)
{
    int r = 0;
    DetectAppLayerProtocolData *data = (DetectAppLayerProtocolData *)m->ctx;

    FLOWLOCK_RDLOCK(f);
    r = (data->negated) ? (f->alproto != data->alproto) :
        (f->alproto == data->alproto);
    FLOWLOCK_UNLOCK(f);

    return r;
}
Exemplo n.º 9
0
int DetectEngineRunHttpUAMpm(DetectEngineThreadCtx *det_ctx, Flow *f,
                             HtpState *htp_state, uint8_t flags)
{
    htp_tx_t *tx = NULL;
    uint32_t cnt = 0;
    int idx;

    /* we need to lock because the buffers are not actually true buffers
     * but are ones that point to a buffer given by libhtp */
    FLOWLOCK_RDLOCK(f);

    if (htp_state == NULL) {
        SCLogDebug("no HTTP state");
        goto end;
    }

    if (htp_state->connp == NULL || htp_state->connp->conn == NULL) {
        SCLogDebug("HTP state has no conn(p)");
        goto end;
    }

    idx = AppLayerTransactionGetInspectId(f);
    if (idx == -1) {
        goto end;
    }

    int size = (int)list_size(htp_state->connp->conn->transactions);
    for (; idx < size; idx++) {

        tx = list_get(htp_state->connp->conn->transactions, idx);
        if (tx == NULL)
            continue;

        htp_header_t *h = (htp_header_t *)table_getc(tx->request_headers,
                                                     "User-Agent");
        if (h == NULL) {
            SCLogDebug("HTTP user agent header not present in this request");
            continue;
        }

        cnt += HttpUAPatternSearch(det_ctx,
                                   (uint8_t *)bstr_ptr(h->value),
                                   bstr_len(h->value), flags);
    }

 end:
    FLOWLOCK_UNLOCK(f);
    return cnt;
}
Exemplo n.º 10
0
/**
 * \brief match the specified IssuerDN on a tls session
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectTlsData
 *
 * \retval 0 no match
 * \retval 1 match
 */
static int DetectTlsIssuerDNMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m)
{
    SCEnter();

    DetectTlsData *tls_data = (DetectTlsData *)m->ctx;
    SSLState *ssl_state = (SSLState *)state;
    if (ssl_state == NULL) {
        SCLogDebug("no tls state, no match");
        SCReturnInt(0);
    }

    int ret = 0;
    FLOWLOCK_RDLOCK(f);

    if (tls_data->flags & DETECT_CONTENT_NEGATED) {
        ret = 1;
    } else {
        ret = 0;
    }

    SSLStateConnp *connp = NULL;
    if (flags & STREAM_TOSERVER) {
        connp = &ssl_state->client_connp;
    } else {
        connp = &ssl_state->server_connp;
    }

    if (connp->cert0_issuerdn != NULL) {
        SCLogDebug("TLS: IssuerDN is [%s], looking for [%s]\n",
                   connp->cert0_issuerdn, tls_data->issuerdn);

        if (strstr(connp->cert0_issuerdn, tls_data->issuerdn) != NULL) {
            if (tls_data->flags & DETECT_CONTENT_NEGATED) {
                ret = 0;
            } else {
                ret = 1;
            }
        }
    }

    FLOWLOCK_UNLOCK(f);

    SCReturnInt(ret);
}
Exemplo n.º 11
0
/**
 * \brief   Log the dropped packets when engine is running in inline mode
 *
 * \param tv    Pointer the current thread variables
 * \param data  Pointer to the droplog struct
 * \param p     Pointer the packet which is being logged
 *
 * \retval 0 on succes
 */
static int JsonDropLogger(ThreadVars *tv, void *thread_data, const Packet *p)
{
    JsonDropLogThread *td = thread_data;
    int r = DropLogJSON(td, p);
    if (r < 0)
        return -1;

    if (p->flow) {
        FLOWLOCK_RDLOCK(p->flow);
        if (p->flow->flags & FLOW_ACTION_DROP) {
            if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED))
                p->flow->flags |= FLOW_TOSERVER_DROP_LOGGED;
            else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED))
                p->flow->flags |= FLOW_TOCLIENT_DROP_LOGGED;
        }
        FLOWLOCK_UNLOCK(p->flow);
    }
    return 0;
}
Exemplo n.º 12
0
/**
 * \brief   Log the dropped packets when engine is running in inline mode
 *
 * \param tv    Pointer the current thread variables
 * \param data  Pointer to the droplog struct
 * \param p     Pointer the packet which is being logged
 *
 * \retval 0 on succes
 */
static int LogDropLogger(ThreadVars *tv, void *thread_data, const Packet *p)
{

    int r = LogDropLogNetFilter(tv, p, thread_data);
    if (r < 0)
        return -1;

    if (p->flow) {
        FLOWLOCK_RDLOCK(p->flow);
        if (p->flow->flags & FLOW_ACTION_DROP) {
            if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED))
                p->flow->flags |= FLOW_TOSERVER_DROP_LOGGED;
            else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED))
                p->flow->flags |= FLOW_TOCLIENT_DROP_LOGGED;
        }
        FLOWLOCK_UNLOCK(p->flow);
    }
    return 0;
}
Exemplo n.º 13
0
int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                             Flow *f, uint8_t flags, void *state, Signature *s,
                             SigMatch *m)
{
    SCEnter();
    int r = 0;

    DetectAppLayerEventData *aled = (DetectAppLayerEventData *)m->ctx;

    FLOWLOCK_RDLOCK(f);

    AppLayerDecoderEvents *decoder_events = AppLayerGetDecoderEventsForFlow(f);
    if (decoder_events != NULL &&
            AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) {
        r = 1;
    }

    FLOWLOCK_UNLOCK(f);
    SCReturnInt(r);
}
Exemplo n.º 14
0
int DetectFlowvarMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx)
{
    int ret = 0;
    DetectFlowvarData *fd = (DetectFlowvarData *)ctx;

    /* we need a lock */
    FLOWLOCK_RDLOCK(p->flow);

    FlowVar *fv = FlowVarGet(p->flow, fd->idx);
    if (fv != NULL) {
        uint8_t *ptr = SpmSearch(fv->data.fv_str.value,
                                 fv->data.fv_str.value_len,
                                 fd->content, fd->content_len);
        if (ptr != NULL)
            ret = 1;
    }
    FLOWLOCK_UNLOCK(p->flow);

    return ret;
}
Exemplo n.º 15
0
static int TlsGetSNI(lua_State *luastate)
{
    int r;

    if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
        return LuaCallbackError(luastate, "error: protocol not tls");

    int lock_hint = 0;
    Flow *f = LuaStateGetFlow(luastate, &lock_hint);
    if (f == NULL)
        return LuaCallbackError(luastate, "internal error: no flow");

    if (lock_hint == LUA_FLOW_NOT_LOCKED_BY_PARENT) {
        FLOWLOCK_RDLOCK(f);
        r = GetSNI(luastate, f);
        FLOWLOCK_UNLOCK(f);
    } else {
        r = GetSNI(luastate, f);
    }
    return r;
}
Exemplo n.º 16
0
/**
 * \brief App layer match function ssl_state keyword.
 *
 * \param tv      Pointer to threadvars.
 * \param det_ctx Pointer to the thread's detection context.
 * \param f       Pointer to the flow.
 * \param flags   Flags.
 * \param state   App layer state.
 * \param s       Sig we are currently inspecting.
 * \param m       SigMatch we are currently inspecting.
 *
 * \retval 1 Match.
 * \retval 0 No match.
 */
int DetectSslStateMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                        Flow *f, uint8_t flags, void *alstate, Signature *s,
                        SigMatch *m)
{
    int result = 1;
    DetectSslStateData *ssd = (DetectSslStateData *)m->ctx;
    SSLState *ssl_state = (SSLState *)alstate;
    if (ssl_state == NULL) {
        SCLogDebug("no app state, no match");
        return 0;
    }

    FLOWLOCK_RDLOCK(f);

    if ((ssd->flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) &&
        !(ssl_state->flags & SSL_AL_FLAG_STATE_CLIENT_HELLO)) {
        result = 0;
        goto end;
    }
    if ((ssd->flags & SSL_AL_FLAG_STATE_SERVER_HELLO) &&
        !(ssl_state->flags & SSL_AL_FLAG_STATE_SERVER_HELLO)) {
        result = 0;
        goto end;
    }
    if ((ssd->flags & SSL_AL_FLAG_STATE_CLIENT_KEYX) &&
        !(ssl_state->flags & SSL_AL_FLAG_STATE_CLIENT_KEYX)) {
        result = 0;
        goto end;
    }
    if ((ssd->flags & SSL_AL_FLAG_STATE_SERVER_KEYX) &&
        !(ssl_state->flags & SSL_AL_FLAG_STATE_SERVER_KEYX)) {
        result = 0;
        goto end;
    }

 end:
    FLOWLOCK_UNLOCK(f);
    return result;
}
Exemplo n.º 17
0
/** \internal
 *  \brief Condition function for TLS logger
 *  \retval bool true or false -- log now?
 */
static int LogTlsCondition(ThreadVars *tv, const Packet *p)
{
    if (p->flow == NULL) {
        return FALSE;
    }

    if (!(PKT_IS_TCP(p))) {
        return FALSE;
    }

    FLOWLOCK_RDLOCK(p->flow);
    uint16_t proto = FlowGetAppProtocol(p->flow);
    if (proto != ALPROTO_TLS)
        goto dontlog;

    SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
    if (ssl_state == NULL) {
        SCLogDebug("no tls state, so no request logging");
        goto dontlog;
    }

    /* we only log the state once if we don't have to write
     * the cert due to tls.store keyword. */
    if (!(ssl_state->server_connp.cert_log_flag & SSL_TLS_LOG_PEM) &&
        (ssl_state->flags & SSL_AL_FLAG_STATE_LOGGED))
        goto dontlog;

    if (ssl_state->server_connp.cert0_issuerdn == NULL ||
            ssl_state->server_connp.cert0_subject == NULL)
        goto dontlog;

    /* todo: logic to log once */

    FLOWLOCK_UNLOCK(p->flow);
    return TRUE;
dontlog:
    FLOWLOCK_UNLOCK(p->flow);
    return FALSE;
}
Exemplo n.º 18
0
/**
 * \brief match the specified fingerprint on a tls session
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectTlsData
 *
 * \retval 0 no match
 * \retval 1 match
 */
static int DetectTlsFingerprintMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m)
{
    SCEnter();
    DetectTlsData *tls_data = (DetectTlsData *)m->ctx;
    SSLState *ssl_state = (SSLState *)state;
    if (ssl_state == NULL) {
        SCLogDebug("no tls state, no match");
        SCReturnInt(0);
    }

    int ret = 0;
    FLOWLOCK_RDLOCK(f);

    if (tls_data->flags & DETECT_CONTENT_NEGATED) {
        ret = 1;
    } else {
        ret = 0;
    }
    if (ssl_state->server_connp.cert0_fingerprint != NULL) {
        SCLogDebug("TLS: Fingerprint is [%s], looking for [%s]\n",
                   ssl_state->server_connp.cert0_fingerprint,
                   tls_data->fingerprint);

        if (tls_data->fingerprint &&
            (strstr(ssl_state->server_connp.cert0_fingerprint,
                    tls_data->fingerprint) != NULL)) {
            if (tls_data->flags & DETECT_CONTENT_NEGATED) {
                ret = 0;
            } else {
                ret = 1;

            }
        }
    }

    FLOWLOCK_UNLOCK(f);

    SCReturnInt(ret);
}
Exemplo n.º 19
0
/**
 * \brief match the specified version on a ssh session
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectSshVersionData
 *
 * \retval 0 no match
 * \retval 1 match
 */
int DetectSshVersionMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m)
{
    SCEnter();

    DetectSshVersionData *ssh = (DetectSshVersionData *)m->ctx;
    SshState *ssh_state = (SshState *)state;
    if (ssh_state == NULL) {
        SCLogDebug("no ssh state, no match");
        SCReturnInt(0);
    }

    int ret = 0;
    FLOWLOCK_RDLOCK(f);
    if (flags & STREAM_TOCLIENT && ssh_state->flags & SSH_FLAG_SERVER_VERSION_PARSED) {
        if (ssh->flags & SSH_FLAG_PROTOVERSION_2_COMPAT) {
            SCLogDebug("looking for ssh server protoversion 2 compat");
            if (strncmp((char *) ssh_state->server_proto_version, "2", 1) == 0 ||
                strncmp((char *) ssh_state->server_proto_version, "2.", 2) == 0 ||
                strncmp((char *) ssh_state->server_proto_version, "1.99", 4) == 0)
                ret = 1;
        } else {
            SCLogDebug("looking for ssh server protoversion %s length %"PRIu16"", ssh->ver, ssh->len);
            ret = (strncmp((char *) ssh_state->server_proto_version, (char *) ssh->ver, ssh->len) == 0)? 1 : 0;
        }
    } else if (flags & STREAM_TOSERVER && ssh_state->flags & SSH_FLAG_CLIENT_VERSION_PARSED) {
        if (ssh->flags & SSH_FLAG_PROTOVERSION_2_COMPAT) {
            SCLogDebug("looking for client ssh client protoversion 2 compat");
            if (strncmp((char *) ssh_state->client_proto_version, "2", 1) == 0 ||
                strncmp((char *) ssh_state->client_proto_version, "2.", 2) == 0 ||
                strncmp((char *) ssh_state->client_proto_version, "1.99", 4) == 0)
                ret = 1;
        } else {
            SCLogDebug("looking for ssh client protoversion %s length %"PRIu16"", ssh->ver, ssh->len);
            ret = (strncmp((char *) ssh_state->client_proto_version, (char *) ssh->ver, ssh->len) == 0)? 1 : 0;
        }
    }
    FLOWLOCK_UNLOCK(f);
    SCReturnInt(ret);
}
Exemplo n.º 20
0
/**
 * \brief This function is used to check matches from the FTP App Layer Parser
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch but we don't use it since ftpbounce
 *          has no options
 * \retval 0 no match
 * \retval 1 match
 */
int DetectFtpbounceALMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
                           Flow *f, uint8_t flags, void *state, Signature *s,
                           SigMatch *m)
{
    SCEnter();
    FtpState *ftp_state =(FtpState *)state;
    if (ftp_state == NULL) {
        SCLogDebug("no ftp state, no match");
        SCReturnInt(0);
    }

    int ret = 0;
    FLOWLOCK_RDLOCK(f);

    if (ftp_state->command == FTP_COMMAND_PORT) {
        ret = DetectFtpbounceMatchArgs(ftp_state->port_line,
                  ftp_state->port_line_len, f->src.address.address_un_data32[0],
                  ftp_state->arg_offset);
    }
    FLOWLOCK_UNLOCK(f);

    SCReturnInt(ret);
}
Exemplo n.º 21
0
/** \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;
    }

    FLOWLOCK_RDLOCK(p->flow);
    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 */

    FLOWLOCK_UNLOCK(p->flow);
    return TRUE;
dontlog:
    FLOWLOCK_UNLOCK(p->flow);
    return FALSE;
}
Exemplo n.º 22
0
TmEcode AlertDebugLogger(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
{
    AlertDebugLogThread *aft = (AlertDebugLogThread *)data;
    int i;
    char timebuf[64];

    if (p->alerts.cnt == 0)
        return TM_ECODE_OK;

    MemBufferReset(aft->buffer);

    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));

    MemBufferWriteString(aft->buffer, "+================\n"
                         "TIME:              %s\n", timebuf);
    if (p->pcap_cnt > 0) {
        MemBufferWriteString(aft->buffer, "PCAP PKT NUM:      %"PRIu64"\n", p->pcap_cnt);
    }

    char srcip[46], dstip[46];
    if (PKT_IS_IPV4(p)) {
        PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
        PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
    } else if (PKT_IS_IPV6(p)) {
        PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
        PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
    }

    MemBufferWriteString(aft->buffer, "SRC IP:            %s\n"
                         "DST IP:            %s\n"
                         "PROTO:             %" PRIu32 "\n",
                         srcip, dstip, p->proto);
    if (PKT_IS_TCP(p) || PKT_IS_UDP(p)) {
        MemBufferWriteString(aft->buffer, "SRC PORT:          %" PRIu32 "\n"
                             "DST PORT:          %" PRIu32 "\n",
                             p->sp, p->dp);
        if (PKT_IS_TCP(p)) {
            MemBufferWriteString(aft->buffer, "TCP SEQ:           %"PRIu32"\n"
                                 "TCP ACK:           %"PRIu32"\n",
                                 TCP_GET_SEQ(p), TCP_GET_ACK(p));
        }
    }

    /* flow stuff */
    MemBufferWriteString(aft->buffer, "FLOW:              to_server: %s, "
                         "to_client: %s\n",
                         p->flowflags & FLOW_PKT_TOSERVER ? "TRUE" : "FALSE",
                         p->flowflags & FLOW_PKT_TOCLIENT ? "TRUE" : "FALSE");

    if (p->flow != NULL) {
        FLOWLOCK_RDLOCK(p->flow);
        CreateTimeString(&p->flow->startts, timebuf, sizeof(timebuf));
        MemBufferWriteString(aft->buffer, "FLOW Start TS:     %s\n", timebuf);
#ifdef DEBUG
        MemBufferWriteString(aft->buffer, "FLOW PKTS TODST:   %"PRIu32"\n"
                             "FLOW PKTS TOSRC:   %"PRIu32"\n"
                             "FLOW Total Bytes:  %"PRIu64"\n",
                             p->flow->todstpktcnt, p->flow->tosrcpktcnt,
                             p->flow->bytecnt);
#endif
        MemBufferWriteString(aft->buffer,
                             "FLOW IPONLY SET:   TOSERVER: %s, TOCLIENT: %s\n"
                             "FLOW ACTION:       DROP: %s, PASS %s\n"
                             "FLOW NOINSPECTION: PACKET: %s, PAYLOAD: %s, APP_LAYER: %s\n"
                             "FLOW APP_LAYER:    DETECTED: %s, PROTO %"PRIu16"\n",
                             p->flow->flags & FLOW_TOSERVER_IPONLY_SET ? "TRUE" : "FALSE",
                             p->flow->flags & FLOW_TOCLIENT_IPONLY_SET ? "TRUE" : "FALSE",
                             p->flow->flags & FLOW_ACTION_DROP ? "TRUE" : "FALSE",
                             p->flow->flags & FLOW_ACTION_PASS ? "TRUE" : "FALSE",
                             p->flow->flags & FLOW_NOPACKET_INSPECTION ? "TRUE" : "FALSE",
                             p->flow->flags & FLOW_NOPAYLOAD_INSPECTION ? "TRUE" : "FALSE",
                             p->flow->flags & FLOW_NO_APPLAYER_INSPECTION ? "TRUE" : "FALSE",
                             (p->flow->alproto != ALPROTO_UNKNOWN) ? "TRUE" : "FALSE", p->flow->alproto);
        AlertDebugLogFlowVars(aft, p);
        AlertDebugLogFlowBits(aft, p);
        FLOWLOCK_UNLOCK(p->flow);
    }

    AlertDebugLogPktVars(aft, p);

/* any stuff */
/* Sig details? */

    MemBufferWriteString(aft->buffer,
                         "PACKET LEN:        %" PRIu32 "\n"
                         "PACKET:\n",
                         GET_PKT_LEN(p));
    PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                         GET_PKT_DATA(p), GET_PKT_LEN(p));

    MemBufferWriteString(aft->buffer, "ALERT CNT:           %" PRIu32 "\n",
                         p->alerts.cnt);

    for (i = 0; i < p->alerts.cnt; i++) {
        PacketAlert *pa = &p->alerts.alerts[i];
        if (unlikely(pa->s == NULL)) {
            continue;
        }

        MemBufferWriteString(aft->buffer,
                             "ALERT MSG [%02d]:      %s\n"
                             "ALERT GID [%02d]:      %" PRIu32 "\n"
                             "ALERT SID [%02d]:      %" PRIu32 "\n"
                             "ALERT REV [%02d]:      %" PRIu32 "\n"
                             "ALERT CLASS [%02d]:    %s\n"
                             "ALERT PRIO [%02d]:     %" PRIu32 "\n"
                             "ALERT FOUND IN [%02d]: %s\n",
                             i, pa->s->msg,
                             i, pa->s->gid,
                             i, pa->s->id,
                             i, pa->s->rev,
                             i, pa->s->class_msg ? pa->s->class_msg : "<none>",
                             i, pa->s->prio,
                             i,
                             pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH  ? "STREAM" :
                             (pa->flags & PACKET_ALERT_FLAG_STATE_MATCH ? "STATE" : "PACKET"));
        if (p->payload_len > 0) {
            MemBufferWriteString(aft->buffer,
                                 "PAYLOAD LEN:         %" PRIu32 "\n"
                                 "PAYLOAD:\n",
                                 p->payload_len);
            PrintRawDataToBuffer(aft->buffer->buffer, &aft->buffer->offset, aft->buffer->size,
                                 p->payload, p->payload_len);
        }
        if (pa->flags & PACKET_ALERT_FLAG_STATE_MATCH ||
            pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH) {
            /* This is an app layer or stream alert */
            int ret;
            uint8_t flag;
            if ((! PKT_IS_TCP(p)) || p->flow == NULL ||
                    p->flow->protoctx == NULL) {
                return TM_ECODE_OK;
            }
            /* IDS mode reverse the data */
            /** \todo improve the order selection policy */
            if (p->flowflags & FLOW_PKT_TOSERVER) {
                flag = FLOW_PKT_TOCLIENT;
            } else {
                flag = FLOW_PKT_TOSERVER;
            }
            ret = StreamSegmentForEach(p, flag,
                                 AlertDebugPrintStreamSegmentCallback,
                                 (void *)aft);
            if (ret < 0) {
                return TM_ECODE_FAILED;
            }
        }
    }

    SCMutexLock(&aft->file_ctx->fp_mutex);
    (void)MemBufferPrintToFPAsString(aft->buffer, aft->file_ctx->fp);
    fflush(aft->file_ctx->fp);
    aft->file_ctx->alerts += p->alerts.cnt;
    SCMutexUnlock(&aft->file_ctx->fp_mutex);

    return TM_ECODE_OK;
}
Exemplo n.º 23
0
/**
 * \brief match the specified luajit
 *
 * \param t thread local vars
 * \param det_ctx pattern matcher thread local data
 * \param p packet
 * \param s signature being inspected
 * \param m sigmatch that we will cast into DetectLuajitData
 *
 * \retval 0 no match
 * \retval 1 match
 */
static int DetectLuajitMatch (ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
        Packet *p, Signature *s, SigMatch *m)
{
    SCEnter();
    int ret = 0;
    DetectLuajitData *luajit = (DetectLuajitData *)m->ctx;
    if (luajit == NULL)
        SCReturnInt(0);

    DetectLuajitThreadData *tluajit = (DetectLuajitThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, luajit->thread_ctx_id);
    if (tluajit == NULL)
        SCReturnInt(0);

    if ((tluajit->flags & DATATYPE_PAYLOAD) && p->payload_len == 0)
        SCReturnInt(0);
    if ((tluajit->flags & DATATYPE_PACKET) && GET_PKT_LEN(p) == 0)
        SCReturnInt(0);
    if (tluajit->alproto != ALPROTO_UNKNOWN) {
        if (p->flow == NULL)
            SCReturnInt(0);

        FLOWLOCK_RDLOCK(p->flow);
        int alproto = p->flow->alproto;
        FLOWLOCK_UNLOCK(p->flow);

        if (tluajit->alproto != alproto)
            SCReturnInt(0);
    }

    lua_getglobal(tluajit->luastate, "match");
    lua_newtable(tluajit->luastate); /* stack at -1 */

    if ((tluajit->flags & DATATYPE_PAYLOAD) && p->payload_len) {
        lua_pushliteral(tluajit->luastate, "payload"); /* stack at -2 */
        lua_pushlstring (tluajit->luastate, (const char *)p->payload, (size_t)p->payload_len); /* stack at -3 */
        lua_settable(tluajit->luastate, -3);
    }
    if ((tluajit->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) {
        lua_pushliteral(tluajit->luastate, "packet"); /* stack at -2 */
        lua_pushlstring (tluajit->luastate, (const char *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p)); /* stack at -3 */
        lua_settable(tluajit->luastate, -3);
    }
    if (tluajit->alproto == ALPROTO_HTTP) {
        FLOWLOCK_RDLOCK(p->flow);
        HtpState *htp_state = p->flow->alstate;
        if (htp_state != NULL && htp_state->connp != NULL && htp_state->connp->conn != NULL) {
            int idx = AppLayerTransactionGetInspectId(p->flow);
            if (idx != -1) {
                htp_tx_t *tx = NULL;

                int size = (int)list_size(htp_state->connp->conn->transactions);
                for ( ; idx < size; idx++)
                {
                    tx = list_get(htp_state->connp->conn->transactions, idx);
                    if (tx == NULL)
                        continue;

                    if ((tluajit->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
                            bstr_len(tx->request_line) > 0) {
                        lua_pushliteral(tluajit->luastate, "http.request_line"); /* stack at -2 */
                        lua_pushlstring (tluajit->luastate,
                                (const char *)bstr_ptr(tx->request_line),
                                bstr_len(tx->request_line));
                        lua_settable(tluajit->luastate, -3);
                    }
                }
            }
        }
        FLOWLOCK_UNLOCK(p->flow);
    }

    int retval = lua_pcall(tluajit->luastate, 1, 1, 0);
    if (retval != 0) {
        SCLogInfo("failed to run script: %s", lua_tostring(tluajit->luastate, -1));
    }

    /* process returns from script */
    if (lua_gettop(tluajit->luastate) > 0) {

        /* script returns a number (return 1 or return 0) */
        if (lua_type(tluajit->luastate, 1) == LUA_TNUMBER) {
            double script_ret = lua_tonumber(tluajit->luastate, 1);
            SCLogDebug("script_ret %f", script_ret);
            lua_pop(tluajit->luastate, 1);

            if (script_ret == 1.0)
                ret = 1;

        /* script returns a table */
        } else if (lua_type(tluajit->luastate, 1) == LUA_TTABLE) {
            lua_pushnil(tluajit->luastate);
            const char *k, *v;
            while (lua_next(tluajit->luastate, -2)) {
                v = lua_tostring(tluajit->luastate, -1);
                lua_pop(tluajit->luastate, 1);
                k = lua_tostring(tluajit->luastate, -1);

                if (!k || !v)
                    continue;

                SCLogDebug("k='%s', v='%s'", k, v);

                if (strcmp(k, "retval") == 0) {
                    if (atoi(v) == 1)
                        ret = 1;
                } else {
                    /* set flow var? */
                }
            }

            /* pop the table */
            lua_pop(tluajit->luastate, 1);
        }
    }

    if (luajit->negated) {
        if (ret == 1)
            ret = 0;
        else
            ret = 1;
    }

    SCReturnInt(ret);
}
static int LuaGetFlowvar(lua_State *luastate)
{
    uint16_t idx;
    int id;
    Flow *f;
    FlowVar *fv;
    DetectLuaData *ld;
    int flow_lock = 0;

    /* need luajit data for id -> idx conversion */
    lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
    lua_gettable(luastate, LUA_REGISTRYINDEX);
    ld = lua_touserdata(luastate, -1);
    SCLogDebug("ld %p", ld);
    if (ld == NULL) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "internal error: no ld");
        return 2;
    }

    /* need flow and lock hint */
    f = LuaStateGetFlow(luastate, &flow_lock);
    if (f == NULL) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "no flow");
        return 2;
    }

    /* need flowvar idx */
    if (!lua_isnumber(luastate, 1)) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "1st arg not a number");
        return 2;
    }
    id = lua_tonumber(luastate, 1);
    if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "flowvar id out of range");
        return 2;
    }
    idx = ld->flowvar[id];
    if (idx == 0) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "flowvar id uninitialized");
        return 2;
    }

    /* lookup var */
    if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT)
        FLOWLOCK_RDLOCK(f);

    fv = FlowVarGet(f, idx);
    if (fv == NULL) {
        if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT)
            FLOWLOCK_UNLOCK(f);

        lua_pushnil(luastate);
        lua_pushstring(luastate, "no flow var");
        return 2;
    }

    LuaPushStringBuffer(luastate, (const uint8_t *)fv->data.fv_str.value,
            (size_t)fv->data.fv_str.value_len);

    if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT)
        FLOWLOCK_UNLOCK(f);

    return 1;

}
static int LuaDecrFlowint(lua_State *luastate)
{
    uint16_t idx;
    int id;
    Flow *f;
    FlowVar *fv;
    DetectLuaData *ld;
    int flow_lock = 0;
    uint32_t number;

    /* need luajit data for id -> idx conversion */
    lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
    lua_gettable(luastate, LUA_REGISTRYINDEX);
    ld = lua_touserdata(luastate, -1);
    SCLogDebug("ld %p", ld);
    if (ld == NULL) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "internal error: no ld");
        return 2;
    }

    /* need flow and lock hint */
    f = LuaStateGetFlow(luastate, &flow_lock);
    if (f == NULL) {
        lua_pushnil(luastate);
        lua_pushstring(luastate, "no flow");
        return 2;
    }

    /* need flowint idx */
    if (!lua_isnumber(luastate, 1)) {
        SCLogDebug("1st arg not a number");
        lua_pushnil(luastate);
        lua_pushstring(luastate, "1st arg not a number");
        return 2;
    }
    id = lua_tonumber(luastate, 1);
    if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWINTS) {
        SCLogDebug("id %d", id);
        lua_pushnil(luastate);
        lua_pushstring(luastate, "flowint id out of range");
        return 2;
    }
    idx = ld->flowint[id];
    if (idx == 0) {
        SCLogDebug("idx %u", idx);
        lua_pushnil(luastate);
        lua_pushstring(luastate, "flowint id uninitialized");
        return 2;
    }

    /* lookup var */
    if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT)
        FLOWLOCK_RDLOCK(f);

    fv = FlowVarGet(f, idx);
    if (fv == NULL) {
        number = 0;
    } else {
        number = fv->data.fv_int.value;
        if (number > 0)
            number--;
    }
    FlowVarAddIntNoLock(f, idx, number);

    if (flow_lock == LUA_FLOW_NOT_LOCKED_BY_PARENT)
        FLOWLOCK_UNLOCK(f);

    /* return value through luastate, as a luanumber */
    lua_pushnumber(luastate, (lua_Number)number);
    SCLogDebug("decremented flow:%p idx:%u value:%u", f, idx, number);

    return 1;

}
Exemplo n.º 26
0
static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
{
    MemBuffer *payload = aft->payload_buffer;
    AlertJsonOutputCtx *json_output_ctx = aft->json_output_ctx;

    int i;

    if (p->alerts.cnt == 0)
        return TM_ECODE_OK;

    json_t *js = CreateJSONHeader((Packet *)p, 0, "alert");
    if (unlikely(js == NULL))
        return TM_ECODE_OK;

    for (i = 0; i < p->alerts.cnt; i++) {
        const PacketAlert *pa = &p->alerts.alerts[i];
        if (unlikely(pa->s == NULL)) {
            continue;
        }

        MemBufferReset(aft->json_buffer);

        /* alert */
        AlertJsonHeader(pa, js);

        if (json_output_ctx->flags & LOG_JSON_HTTP) {
            if (p->flow != NULL) {
                FLOWLOCK_RDLOCK(p->flow);
                uint16_t proto = FlowGetAppProtocol(p->flow);

                /* http alert */
                if (proto == ALPROTO_HTTP)
                    AlertJsonHttp(p->flow, js);

                FLOWLOCK_UNLOCK(p->flow);
            }
        }

        if (json_output_ctx->flags & LOG_JSON_TLS) {
            if (p->flow != NULL) {
                FLOWLOCK_RDLOCK(p->flow);
                uint16_t proto = FlowGetAppProtocol(p->flow);

                /* http alert */
                if (proto == ALPROTO_TLS)
                    AlertJsonTls(p->flow, js);

                FLOWLOCK_UNLOCK(p->flow);
            }
        }

        if (json_output_ctx->flags & LOG_JSON_SSH) {
            if (p->flow != NULL) {
                FLOWLOCK_RDLOCK(p->flow);
                uint16_t proto = FlowGetAppProtocol(p->flow);

                /* http alert */
                if (proto == ALPROTO_SSH)
                    AlertJsonSsh(p->flow, js);

                FLOWLOCK_UNLOCK(p->flow);
            }
        }

        /* payload */
        if (json_output_ctx->flags & (LOG_JSON_PAYLOAD | LOG_JSON_PAYLOAD_BASE64)) {
            int stream = (p->proto == IPPROTO_TCP) ?
                         (pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH) ?
                         1 : 0) : 0;

            /* Is this a stream?  If so, pack part of it into the payload field */
            if (stream) {
                uint8_t flag;

                MemBufferReset(payload);

                if (!EngineModeIsIPS()) {
                    if (p->flowflags & FLOW_PKT_TOSERVER) {
                        flag = FLOW_PKT_TOCLIENT;
                    } else {
                        flag = FLOW_PKT_TOSERVER;
                    }
                } else {
                    if (p->flowflags & FLOW_PKT_TOSERVER) {
                        flag = FLOW_PKT_TOSERVER;
                    } else {
                        flag = FLOW_PKT_TOCLIENT;
                    }
                }

                StreamSegmentForEach((const Packet *)p, flag,
                                    AlertJsonDumpStreamSegmentCallback,
                                    (void *)payload);

                if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) {
                    unsigned long len = JSON_STREAM_BUFFER_SIZE * 2;
                    uint8_t encoded[len];
                    Base64Encode((unsigned char *)payload, payload->offset, encoded, &len);
                    json_object_set_new(js, "payload", json_string((char *)encoded));
                }

                if (json_output_ctx->flags & LOG_JSON_PAYLOAD) {
                    uint8_t printable_buf[payload->offset + 1];
                    uint32_t offset = 0;
                    PrintStringsToBuffer(printable_buf, &offset,
                                     sizeof(printable_buf),
                                     (unsigned char *)payload, payload->offset);
                    json_object_set_new(js, "payload_printable",
                                        json_string((char *)printable_buf));
                }
            } else {
                /* This is a single packet and not a stream */
                if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) {
                    unsigned long len = p->payload_len * 2 + 1;
                    uint8_t encoded[len];
                    Base64Encode(p->payload, p->payload_len, encoded, &len);
                    json_object_set_new(js, "payload", json_string((char *)encoded));
                }

                if (json_output_ctx->flags & LOG_JSON_PAYLOAD) {
                    uint8_t printable_buf[p->payload_len + 1];
                    uint32_t offset = 0;
                    PrintStringsToBuffer(printable_buf, &offset,
                                     p->payload_len + 1,
                                     p->payload, p->payload_len);
                    json_object_set_new(js, "payload_printable", json_string((char *)printable_buf));
                }
            }

            json_object_set_new(js, "stream", json_integer(stream));
        }

        /* base64-encoded full packet */
        if (json_output_ctx->flags & LOG_JSON_PACKET) {
            unsigned long len = GET_PKT_LEN(p) * 2;
            uint8_t encoded_packet[len];
            Base64Encode((unsigned char*) GET_PKT_DATA(p), GET_PKT_LEN(p), encoded_packet, &len);
            json_object_set_new(js, "packet", json_string((char *)encoded_packet));
        }

        HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg;

        /* xff header */
        if (!(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) {
            int have_xff_ip = 0;
            char buffer[XFF_MAXLEN];

            FLOWLOCK_RDLOCK(p->flow);
            if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
                if (pa->flags & PACKET_ALERT_FLAG_TX) {
                    have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
                } else {
                    have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN);
                }
            }
            FLOWLOCK_UNLOCK(p->flow);

            if (have_xff_ip) {
                if (xff_cfg->flags & XFF_EXTRADATA) {
                    json_object_set_new(js, "xff", json_string(buffer));
                }
                else if (xff_cfg->flags & XFF_OVERWRITE) {
                    if (p->flowflags & FLOW_PKT_TOCLIENT) {
                        json_object_set(js, "dest_ip", json_string(buffer));
                    } else {
                        json_object_set(js, "src_ip", json_string(buffer));
                    }
                }
            }
        }

        OutputJSONBuffer(js, aft->file_ctx, aft->json_buffer);
        json_object_del(js, "alert");
    }
    json_object_clear(js);
    json_decref(js);

    return TM_ECODE_OK;
}