suricata
output-json-pgsql.c
Go to the documentation of this file.
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#define PGSQL_LOG_PASSWORDS BIT_U32(0)
50#define PGSQL_DEFAULTS (PGSQL_LOG_PASSWORDS)
51
56
61
62bool JsonPgsqlAddMetadata(void *vtx, SCJsonBuilder *jb)
63{
64 return SCPgsqlLogger(vtx, PGSQL_DEFAULTS, jb);
65}
66
67static int JsonPgsqlLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *state,
68 void *txptr, uint64_t tx_id)
69{
70 LogPgsqlLogThread *thread = thread_data;
71 SCLogDebug("Logging pgsql transaction %" PRIu64 ".", tx_id);
72
73 SCJsonBuilder *jb =
74 CreateEveHeader(p, LOG_DIR_FLOW, "pgsql", NULL, thread->pgsqllog_ctx->eve_ctx);
75 if (unlikely(jb == NULL)) {
76 return TM_ECODE_FAILED;
77 }
78
79 if (!SCPgsqlLogger(txptr, thread->pgsqllog_ctx->flags, jb)) {
80 goto error;
81 }
82
83 OutputJsonBuilderBuffer(tv, p, p->flow, jb, thread->ctx);
84 SCJbFree(jb);
85
86 return TM_ECODE_OK;
87
88error:
89 SCJbFree(jb);
90 return TM_ECODE_FAILED;
91}
92
93static void OutputPgsqlLogDeInitCtxSub(OutputCtx *output_ctx)
94{
95 OutputPgsqlCtx *pgsqllog_ctx = (OutputPgsqlCtx *)output_ctx->data;
96 SCFree(pgsqllog_ctx);
97 SCFree(output_ctx);
98}
99
100static void JsonPgsqlLogParseConfig(SCConfNode *conf, OutputPgsqlCtx *pgsqllog_ctx)
101{
102 pgsqllog_ctx->flags = ~0U;
103
104 const char *query = SCConfNodeLookupChildValue(conf, "passwords");
105 if (query != NULL) {
106 if (SCConfValIsTrue(query)) {
107 pgsqllog_ctx->flags |= PGSQL_LOG_PASSWORDS;
108 } else {
109 pgsqllog_ctx->flags &= ~PGSQL_LOG_PASSWORDS;
110 }
111 } else {
112 pgsqllog_ctx->flags &= ~PGSQL_LOG_PASSWORDS;
113 }
114}
115
116static OutputInitResult OutputPgsqlLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
117{
118 OutputInitResult result = { NULL, false };
119 OutputJsonCtx *ojc = parent_ctx->data;
120
121 OutputPgsqlCtx *pgsql_ctx = SCCalloc(1, sizeof(OutputPgsqlCtx));
122 if (unlikely(pgsql_ctx == NULL))
123 return result;
124
125 OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
126 if (unlikely(output_ctx == NULL)) {
127 SCFree(pgsql_ctx);
128 return result;
129 }
130
131 pgsql_ctx->eve_ctx = ojc;
132
133 output_ctx->data = pgsql_ctx;
134 output_ctx->DeInit = OutputPgsqlLogDeInitCtxSub;
135
136 JsonPgsqlLogParseConfig(conf, pgsql_ctx);
137
139
140 SCLogDebug("PostgreSQL log sub-module initialized.");
141
142 result.ctx = output_ctx;
143 result.ok = true;
144 return result;
145}
146
147static TmEcode JsonPgsqlLogThreadInit(ThreadVars *t, const void *initdata, void **data)
148{
149 LogPgsqlLogThread *thread = SCCalloc(1, sizeof(LogPgsqlLogThread));
150 if (unlikely(thread == NULL)) {
151 return TM_ECODE_FAILED;
152 }
153
154 if (initdata == NULL) {
155 SCLogDebug("Error getting context for EveLogPgsql. \"initdata\" is NULL.");
156 goto error_exit;
157 }
158
159 thread->pgsqllog_ctx = ((OutputCtx *)initdata)->data;
160 thread->ctx = CreateEveThreadCtx(t, thread->pgsqllog_ctx->eve_ctx);
161 if (!thread->ctx) {
162 goto error_exit;
163 }
164 *data = (void *)thread;
165
166 return TM_ECODE_OK;
167
168error_exit:
169 SCFree(thread);
170 return TM_ECODE_FAILED;
171}
172
173static TmEcode JsonPgsqlLogThreadDeinit(ThreadVars *t, void *data)
174{
175 LogPgsqlLogThread *thread = (LogPgsqlLogThread *)data;
176 if (thread == NULL) {
177 return TM_ECODE_OK;
178 }
179 FreeEveThreadCtx(thread->ctx);
180 SCFree(thread);
181 return TM_ECODE_OK;
182}
183
185{
186 /* PGSQL_START_REMOVE */
187 if (SCConfGetNode("app-layer.protocols.pgsql") == NULL) {
188 SCLogDebug("Disabling Pgsql eve-logger");
189 return;
190 }
191 /* PGSQL_END_REMOVE */
192 /* Register as an eve sub-module. */
193 OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonPgsqlLog", "eve-log.pgsql",
194 OutputPgsqlLogInitSub, ALPROTO_PGSQL, JsonPgsqlLogger, JsonPgsqlLogThreadInit,
195 JsonPgsqlLogThreadDeinit);
196
197 SCLogDebug("PostgreSQL JSON logger registered.");
198}
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
@ ALPROTO_PGSQL
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition conf.c:181
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition conf.c:551
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition conf.c:824
ThreadVars * tv
@ LOG_DIR_FLOW
OutputJsonThreadCtx * CreateEveThreadCtx(ThreadVars *t, OutputJsonCtx *ctx)
void FreeEveThreadCtx(OutputJsonThreadCtx *ctx)
#define PGSQL_LOG_PASSWORDS
#define PGSQL_DEFAULTS
void JsonPgsqlLogRegister(void)
struct LogPgsqlLogThread_ LogPgsqlLogThread
bool JsonPgsqlAddMetadata(void *vtx, SCJsonBuilder *jb)
struct OutputPgsqlCtx_ OutputPgsqlCtx
SCJsonBuilder * CreateEveHeader(const Packet *p, enum SCOutputJsonLogDirection dir, const char *event_type, JsonAddrInfo *addr, OutputJsonCtx *eve_ctx)
void OutputJsonBuilderBuffer(ThreadVars *tv, const Packet *p, Flow *f, SCJsonBuilder *js, OutputJsonThreadCtx *ctx)
void OutputRegisterTxSubModule(LoggerId id, const char *parent_name, const char *name, const char *conf_name, OutputInitSubFunc InitFunc, AppProto alproto, TxLogger TxLogFunc, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Definition output.c:406
Flow data structure.
Definition flow.h:356
OutputPgsqlCtx * pgsqllog_ctx
OutputJsonThreadCtx * ctx
void * data
Definition tm-modules.h:91
void(* DeInit)(struct OutputCtx_ *)
Definition tm-modules.h:94
OutputCtx * ctx
Definition output.h:47
OutputJsonCtx * eve_ctx
struct Flow_ * flow
Definition decode.h:546
Per thread variable structure.
Definition threadvars.h:58
@ LOGGER_JSON_TX
@ TM_ECODE_FAILED
@ TM_ECODE_OK
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)