Exemple #1
0
static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p) {
    JsonTlsLogThread *aft = (JsonTlsLogThread *)thread_data;
    MemBuffer *buffer = (MemBuffer *)aft->buffer;
    OutputTlsCtx *tls_ctx = aft->tlslog_ctx;

    if (unlikely(p->flow == NULL)) {
        return 0;
    }

    /* check if we have TLS state or not */
    FLOWLOCK_WRLOCK(p->flow);
    uint16_t proto = FlowGetAppProtocol(p->flow);
    if (proto != ALPROTO_TLS)
        goto end;

    SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
    if (unlikely(ssl_state == NULL)) {
        goto end;
    }

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

    json_t *js = CreateJSONHeader((Packet *)p, 0, "tls");//TODO
    if (unlikely(js == NULL))
        goto end;

    json_t *tjs = json_object();
    if (tjs == NULL) {
        free(js);
        goto end;
    }

    /* reset */
    MemBufferReset(buffer);

    /* tls.subject */
    json_object_set_new(tjs, "subject",
                        json_string(ssl_state->server_connp.cert0_subject));

    /* tls.issuerdn */
    json_object_set_new(tjs, "issuerdn",
                        json_string(ssl_state->server_connp.cert0_issuerdn));

    if (tls_ctx->flags & LOG_TLS_EXTENDED) {
        LogTlsLogExtendedJSON(tjs, ssl_state);
    }

    json_object_set_new(js, "tls", tjs);

    OutputJSONBuffer(js, tls_ctx->file_ctx, buffer);
    json_object_clear(js);
    json_decref(js);

    /* we only log the state once */
    ssl_state->flags |= SSL_AL_FLAG_STATE_LOGGED;
end:
    FLOWLOCK_UNLOCK(p->flow);
    return 0;
}
Exemple #2
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;
}
/** \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;
}
Exemple #4
0
/**
 *  \internal
 *  \brief Write meta data on a single line json record
 */
static void LogFileWriteJsonRecord(LogFileLogThread *aft, const Packet *p, const File *ff, int ipver)
{
    SCMutexLock(&aft->file_ctx->fp_mutex);

    /* As writes are done via the LogFileCtx, check for rotation here. */
    if (aft->file_ctx->rotation_flag) {
        aft->file_ctx->rotation_flag = 0;
        if (SCConfLogReopen(aft->file_ctx) != 0) {
            SCLogWarning(SC_ERR_FOPEN, "Failed to re-open log file. "
                "Logging for this module will be disabled.");
        }
    }

    /* Bail early if no file pointer to write to (in the unlikely
     * event file rotation failed. */
    if (aft->file_ctx->fp == NULL) {
        SCMutexUnlock(&aft->file_ctx->fp_mutex);
        return;
    }

    FILE *fp = aft->file_ctx->fp;
    char timebuf[64];
    AppProto alproto = FlowGetAppProtocol(p->flow);

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

    fprintf(fp, "{ ");

    if (ff->file_id > 0)
        fprintf(fp, "\"id\": %u, ", ff->file_id);

    fprintf(fp, "\"timestamp\": \"");
    PrintRawJsonFp(fp, (uint8_t *)timebuf, strlen(timebuf));
    fprintf(fp, "\", ");
    if (p->pcap_cnt > 0) {
        fprintf(fp, "\"pcap_pkt_num\": %"PRIu64", ", p->pcap_cnt);
    }

    fprintf(fp, "\"ipver\": %d, ", ipver == AF_INET ? 4 : 6);

    char srcip[46], dstip[46];
    Port sp, dp;
    switch (ipver) {
        case AF_INET:
            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));
            break;
        case AF_INET6:
            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));
            break;
        default:
            strlcpy(srcip, "<unknown>", sizeof(srcip));
            strlcpy(dstip, "<unknown>", sizeof(dstip));
            break;
    }
    sp = p->sp;
    dp = p->dp;

    fprintf(fp, "\"srcip\": \"%s\", ", srcip);
    fprintf(fp, "\"dstip\": \"%s\", ", dstip);
    fprintf(fp, "\"protocol\": %" PRIu32 ", ", p->proto);
    if (PKT_IS_TCP(p) || PKT_IS_UDP(p)) {
        fprintf(fp, "\"sp\": %" PRIu16 ", ", sp);
        fprintf(fp, "\"dp\": %" PRIu16 ", ", dp);
    }

    if (alproto == ALPROTO_HTTP) {
        fprintf(fp, "\"http_uri\": \"");
        LogFileMetaGetUri(fp, p, ff);
        fprintf(fp, "\", ");

        fprintf(fp, "\"http_host\": \"");
        LogFileMetaGetHost(fp, p, ff);
        fprintf(fp, "\", ");

        fprintf(fp, "\"http_referer\": \"");
        LogFileMetaGetReferer(fp, p, ff);
        fprintf(fp, "\", ");

        fprintf(fp, "\"http_user_agent\": \"");
        LogFileMetaGetUserAgent(fp, p, ff);
        fprintf(fp, "\", ");
    } else if (p->flow->alproto == ALPROTO_SMTP) {
        /* Only applicable to SMTP */
        LogFileMetaGetSmtp(fp, p, ff);
    }

    fprintf(fp, "\"filename\": \"");
    PrintRawJsonFp(fp, ff->name, ff->name_len);
    fprintf(fp, "\", ");
#ifdef HAVE_MAGIC
    fprintf(fp, "\"magic\": \"");
    if (ff->magic) {
        PrintRawJsonFp(fp, (uint8_t *)ff->magic, strlen(ff->magic));
    } else {
        fprintf(fp, "unknown");
    }
    fprintf(fp, "\", ");
#endif
    switch (ff->state) {
        case FILE_STATE_CLOSED:
            fprintf(fp, "\"state\": \"CLOSED\", ");
#ifdef HAVE_NSS
            if (ff->flags & FILE_MD5) {
                fprintf(fp, "\"md5\": \"");
                size_t x;
                for (x = 0; x < sizeof(ff->md5); x++) {
                    fprintf(fp, "%02x", ff->md5[x]);
                }
                fprintf(fp, "\", ");
            }
            if (ff->flags & FILE_SHA1) {
                fprintf(fp, "\"sha1\": \"");
                size_t x;
                for (x = 0; x < sizeof(ff->sha1); x++) {
                    fprintf(fp, "%02x", ff->sha1[x]);
                }
                fprintf(fp, "\", ");
            }
            if (ff->flags & FILE_SHA256) {
                fprintf(fp, "\"sha256\": \"");
                size_t x;
                for (x = 0; x < sizeof(ff->sha256); x++) {
                    fprintf(fp, "%02x", ff->sha256[x]);
                }
                fprintf(fp, "\", ");
            }
#endif
            break;
        case FILE_STATE_TRUNCATED:
            fprintf(fp, "\"state\": \"TRUNCATED\", ");
            break;
        case FILE_STATE_ERROR:
            fprintf(fp, "\"state\": \"ERROR\", ");
            break;
        default:
            fprintf(fp, "\"state\": \"UNKNOWN\", ");
            break;
    }
    fprintf(fp, "\"stored\": %s, ", ff->flags & FILE_STORED ? "true" : "false");
    fprintf(fp, "\"size\": %"PRIu64" ", FileSize(ff));
    fprintf(fp, "}\n");
    fflush(fp);
    SCMutexUnlock(&aft->file_ctx->fp_mutex);
}
Exemple #5
0
static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
{
    MemBuffer *payload = aft->payload_buffer;
    AlertJsonOutputCtx *json_output_ctx = aft->json_output_ctx;
    json_t *hjs = NULL;

    int i;

    if (p->alerts.cnt == 0 && !(p->flags & PKT_HAS_TAG))
        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(p, pa, js);

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

                /* http alert */
                if (proto == ALPROTO_HTTP) {
                    hjs = JsonHttpAddMetadata(p->flow, pa->tx_id);
                    if (hjs)
                        json_object_set_new(js, "http", hjs);
                }
            }
        }

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

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

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

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

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

                /* http alert */
                if (proto == ALPROTO_SMTP) {
                    hjs = JsonSMTPAddMetadata(p->flow, pa->tx_id);
                    if (hjs)
                        json_object_set_new(js, "smtp", hjs);

                    hjs = JsonEmailAddMetadata(p->flow, pa->tx_id);
                    if (hjs)
                        json_object_set_new(js, "email", hjs);
                }
            }
        }

        /* 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 (p->flowflags & FLOW_PKT_TOSERVER) {
                    flag = FLOW_PKT_TOCLIENT;
                } else {
                    flag = FLOW_PKT_TOSERVER;
                }

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

                if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) {
                    unsigned long len = json_output_ctx->payload_buffer_size * 2;
                    uint8_t encoded[len];
                    Base64Encode(payload->buffer, 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),
                                     payload->buffer, 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) {
            AlertJsonPacket(p, js);
        }

        HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg;

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

            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);
                }
            }

            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);

    if ((p->flags & PKT_HAS_TAG) && (json_output_ctx->flags &
            LOG_JSON_TAGGED_PACKETS)) {
        MemBufferReset(aft->json_buffer);
        json_t *packetjs = CreateJSONHeader((Packet *)p, 0, "packet");
        if (unlikely(packetjs != NULL)) {
            AlertJsonPacket(p, packetjs);
            OutputJSONBuffer(packetjs, aft->file_ctx, &aft->json_buffer);
            json_decref(packetjs);
        }
    }

    return TM_ECODE_OK;
}
static int JsonSshLogger(ThreadVars *tv, void *thread_data, const Packet *p)
{
    JsonSshLogThread *aft = (JsonSshLogThread *)thread_data;
    MemBuffer *buffer = (MemBuffer *)aft->buffer;
    OutputSshCtx *ssh_ctx = aft->sshlog_ctx;

    if (unlikely(p->flow == NULL)) {
        return 0;
    }

    /* check if we have SSH state or not */
    FLOWLOCK_WRLOCK(p->flow);
    uint16_t proto = FlowGetAppProtocol(p->flow);
    if (proto != ALPROTO_SSH)
        goto end;

    SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
    if (unlikely(ssh_state == NULL)) {
        goto end;
    }

    if (ssh_state->cli_hdr.software_version == NULL || ssh_state->srv_hdr.software_version == NULL)
        goto end;

    json_t *js = CreateJSONHeader((Packet *)p, 1, "ssh");//TODO
    if (unlikely(js == NULL))
        goto end;

    json_t *tjs = json_object();
    if (tjs == NULL) {
        free(js);
        goto end;
    }

    /* reset */
    MemBufferReset(buffer);

    json_t *cjs = json_object();
    if (cjs != NULL) {
        json_object_set_new(cjs, "proto_version",
                json_string((char *)ssh_state->cli_hdr.proto_version));

        json_object_set_new(cjs, "software_version",
                json_string((char *)ssh_state->cli_hdr.software_version));
    }
    json_object_set_new(tjs, "client", cjs);

    json_t *sjs = json_object();
    if (sjs != NULL) {
        json_object_set_new(sjs, "proto_version",
                json_string((char *)ssh_state->srv_hdr.proto_version));

        json_object_set_new(sjs, "software_version",
                json_string((char *)ssh_state->srv_hdr.software_version));
    }
    json_object_set_new(tjs, "server", sjs);

    json_object_set_new(js, "ssh", tjs);

    OutputJSONBuffer(js, ssh_ctx->file_ctx, buffer);
    json_object_clear(js);
    json_decref(js);

    /* we only log the state once */
    ssh_state->cli_hdr.flags |= SSH_FLAG_STATE_LOGGED;
end:
    FLOWLOCK_UNLOCK(p->flow);
    return 0;
}
Exemple #7
0
static int LogTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p)
{
    LogTlsLogThread *aft = (LogTlsLogThread *)thread_data;
    LogTlsFileCtx *hlog = aft->tlslog_ctx;
    char timebuf[64];
    int ipproto = (PKT_IS_IPV4(p)) ? AF_INET : AF_INET6;

    if (unlikely(p->flow == NULL)) {
        return 0;
    }

    /* check if we have TLS state or not */
    FLOWLOCK_WRLOCK(p->flow);
    uint16_t proto = FlowGetAppProtocol(p->flow);
    if (proto != ALPROTO_TLS)
        goto end;

    SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
    if (unlikely(ssl_state == NULL)) {
        goto end;
    }

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

    /* Don't log again the state. If we are here it was because we had
     * to store the cert. */
    if (ssl_state->flags & SSL_AL_FLAG_STATE_LOGGED)
        goto end;

    CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
#define PRINT_BUF_LEN 46
    char srcip[PRINT_BUF_LEN], dstip[PRINT_BUF_LEN];
    Port sp, dp;
    if (!TLSGetIPInformations(p, srcip, PRINT_BUF_LEN,
                              &sp, dstip, PRINT_BUF_LEN, &dp, ipproto)) {
        goto end;
    }

    MemBufferReset(aft->buffer);
    MemBufferWriteString(aft->buffer,
                         "%s %s:%d -> %s:%d  TLS: Subject='%s' Issuerdn='%s'",
                         timebuf, srcip, sp, dstip, dp,
                         ssl_state->server_connp.cert0_subject,
                         ssl_state->server_connp.cert0_issuerdn);

    if (hlog->flags & LOG_TLS_EXTENDED) {
        LogTlsLogExtended(aft, ssl_state);
    } else {
        MemBufferWriteString(aft->buffer, "\n");
    }

    aft->tls_cnt++;

    SCMutexLock(&hlog->file_ctx->fp_mutex);
    hlog->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
        MEMBUFFER_OFFSET(aft->buffer), hlog->file_ctx);
    SCMutexUnlock(&hlog->file_ctx->fp_mutex);

    /* we only log the state once */
    ssl_state->flags |= SSL_AL_FLAG_STATE_LOGGED;
end:
    FLOWLOCK_UNLOCK(p->flow);
    return 0;
}