Coverage Report

Created: 2026-06-07 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/output-json-pgsql.c
Line
Count
Source
1
/* Copyright (C) 2022-2024 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Juliana Fajardini <jufajardini@oisf.net>
22
 *
23
 * Implement JSON/eve logging for app-layer Pgsql.
24
 */
25
26
#include "suricata-common.h"
27
#include "detect.h"
28
#include "pkt-var.h"
29
#include "conf.h"
30
31
#include "threads.h"
32
#include "threadvars.h"
33
#include "tm-threads.h"
34
35
#include "util-unittest.h"
36
#include "util-buffer.h"
37
#include "util-debug.h"
38
#include "util-byte.h"
39
40
#include "output.h"
41
#include "output-json.h"
42
43
#include "app-layer.h"
44
#include "app-layer-parser.h"
45
46
#include "output-json-pgsql.h"
47
#include "rust.h"
48
49
4
#define PGSQL_LOG_PASSWORDS BIT_U32(0)
50
0
#define PGSQL_DEFAULTS      (PGSQL_LOG_PASSWORDS)
51
52
typedef struct OutputPgsqlCtx_ {
53
    uint32_t flags;
54
    OutputJsonCtx *eve_ctx;
55
} OutputPgsqlCtx;
56
57
typedef struct LogPgsqlLogThread_ {
58
    OutputPgsqlCtx *pgsqllog_ctx;
59
    OutputJsonThreadCtx *ctx;
60
} LogPgsqlLogThread;
61
62
bool JsonPgsqlAddMetadata(const Flow *f, uint64_t tx_id, JsonBuilder *jb)
63
0
{
64
0
    void *state = FlowGetAppState(f);
65
0
    if (state) {
66
0
        void *tx = AppLayerParserGetTx(f->proto, ALPROTO_PGSQL, state, tx_id);
67
0
        if (tx) {
68
0
            return SCPgsqlLogger(tx, PGSQL_DEFAULTS, jb);
69
0
        }
70
0
    }
71
0
    return false;
72
0
}
73
74
static int JsonPgsqlLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state,
75
        void *txptr, uint64_t tx_id)
76
353
{
77
353
    LogPgsqlLogThread *thread = thread_data;
78
353
    SCLogDebug("Logging pgsql transaction %" PRIu64 ".", tx_id);
79
80
353
    JsonBuilder *jb =
81
353
            CreateEveHeader(p, LOG_DIR_FLOW, "pgsql", NULL, thread->pgsqllog_ctx->eve_ctx);
82
353
    if (unlikely(jb == NULL)) {
83
0
        return TM_ECODE_FAILED;
84
0
    }
85
86
353
    if (!SCPgsqlLogger(txptr, thread->pgsqllog_ctx->flags, jb)) {
87
0
        goto error;
88
0
    }
89
90
353
    OutputJsonBuilderBuffer(jb, thread->ctx);
91
353
    jb_free(jb);
92
93
353
    return TM_ECODE_OK;
94
95
0
error:
96
0
    jb_free(jb);
97
0
    return TM_ECODE_FAILED;
98
353
}
99
100
static void OutputPgsqlLogDeInitCtxSub(OutputCtx *output_ctx)
101
0
{
102
0
    OutputPgsqlCtx *pgsqllog_ctx = (OutputPgsqlCtx *)output_ctx->data;
103
0
    SCFree(pgsqllog_ctx);
104
0
    SCFree(output_ctx);
105
0
}
106
107
static void JsonPgsqlLogParseConfig(ConfNode *conf, OutputPgsqlCtx *pgsqllog_ctx)
108
4
{
109
4
    pgsqllog_ctx->flags = ~0U;
110
111
4
    const char *query = ConfNodeLookupChildValue(conf, "passwords");
112
4
    if (query != NULL) {
113
0
        if (ConfValIsTrue(query)) {
114
0
            pgsqllog_ctx->flags |= PGSQL_LOG_PASSWORDS;
115
0
        } else {
116
0
            pgsqllog_ctx->flags &= ~PGSQL_LOG_PASSWORDS;
117
0
        }
118
4
    } else {
119
4
        pgsqllog_ctx->flags &= ~PGSQL_LOG_PASSWORDS;
120
4
    }
121
4
}
122
123
static OutputInitResult OutputPgsqlLogInitSub(ConfNode *conf, OutputCtx *parent_ctx)
124
4
{
125
4
    OutputInitResult result = { NULL, false };
126
4
    OutputJsonCtx *ojc = parent_ctx->data;
127
128
4
    OutputPgsqlCtx *pgsql_ctx = SCMalloc(sizeof(OutputPgsqlCtx));
129
4
    if (unlikely(pgsql_ctx == NULL))
130
0
        return result;
131
132
4
    OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
133
4
    if (unlikely(output_ctx == NULL)) {
134
0
        SCFree(pgsql_ctx);
135
0
        return result;
136
0
    }
137
138
4
    pgsql_ctx->eve_ctx = ojc;
139
140
4
    output_ctx->data = pgsql_ctx;
141
4
    output_ctx->DeInit = OutputPgsqlLogDeInitCtxSub;
142
143
4
    JsonPgsqlLogParseConfig(conf, pgsql_ctx);
144
145
4
    AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_PGSQL);
146
147
4
    SCLogDebug("PostgreSQL log sub-module initialized.");
148
149
4
    result.ctx = output_ctx;
150
4
    result.ok = true;
151
4
    return result;
152
4
}
153
154
static TmEcode JsonPgsqlLogThreadInit(ThreadVars *t, const void *initdata, void **data)
155
4
{
156
4
    LogPgsqlLogThread *thread = SCCalloc(1, sizeof(LogPgsqlLogThread));
157
4
    if (unlikely(thread == NULL)) {
158
0
        return TM_ECODE_FAILED;
159
0
    }
160
161
4
    if (initdata == NULL) {
162
0
        SCLogDebug("Error getting context for EveLogPgsql.  \"initdata\" is NULL.");
163
0
        goto error_exit;
164
0
    }
165
166
4
    thread->pgsqllog_ctx = ((OutputCtx *)initdata)->data;
167
4
    thread->ctx = CreateEveThreadCtx(t, thread->pgsqllog_ctx->eve_ctx);
168
4
    if (!thread->ctx) {
169
0
        goto error_exit;
170
0
    }
171
4
    *data = (void *)thread;
172
173
4
    return TM_ECODE_OK;
174
175
0
error_exit:
176
0
    SCFree(thread);
177
0
    return TM_ECODE_FAILED;
178
4
}
179
180
static TmEcode JsonPgsqlLogThreadDeinit(ThreadVars *t, void *data)
181
0
{
182
0
    LogPgsqlLogThread *thread = (LogPgsqlLogThread *)data;
183
0
    if (thread == NULL) {
184
0
        return TM_ECODE_OK;
185
0
    }
186
0
    FreeEveThreadCtx(thread->ctx);
187
0
    SCFree(thread);
188
0
    return TM_ECODE_OK;
189
0
}
190
191
void JsonPgsqlLogRegister(void)
192
74
{
193
    /* PGSQL_START_REMOVE */
194
74
    if (ConfGetNode("app-layer.protocols.pgsql") == NULL) {
195
3
        SCLogDebug("Disabling Pgsql eve-logger");
196
3
        return;
197
3
    }
198
    /* PGSQL_END_REMOVE */
199
    /* Register as an eve sub-module. */
200
71
    OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonPgsqlLog", "eve-log.pgsql",
201
71
            OutputPgsqlLogInitSub, ALPROTO_PGSQL, JsonPgsqlLogger, JsonPgsqlLogThreadInit,
202
71
            JsonPgsqlLogThreadDeinit, NULL);
203
204
71
    SCLogDebug("PostgreSQL JSON logger registered.");
205
71
}