suricata
detect-tls-certs.c
Go to the documentation of this file.
1/* Copyright (C) 2019-2022 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 Mats Klepsland <mats.klepsland@gmail.com>
22 *
23 * Implements support for tls.certs keyword.
24 */
25
26#include "suricata-common.h"
27#include "threads.h"
28#include "decode.h"
29#include "detect.h"
30
31#include "detect-parse.h"
32#include "detect-engine.h"
34#include "detect-engine-mpm.h"
37#include "detect-content.h"
38#include "detect-pcre.h"
39#include "detect-tls-certs.h"
40#include "detect-engine-uint.h"
41
42#include "flow.h"
43#include "flow-util.h"
44#include "flow-var.h"
45
46#include "util-debug.h"
47#include "util-spm.h"
48#include "util-print.h"
49
50#include "stream-tcp.h"
51
52#include "app-layer.h"
53#include "app-layer-ssl.h"
54
55#include "util-profiling.h"
56#include "util-unittest.h"
58
59static int DetectTlsCertsSetup(DetectEngineCtx *, Signature *, const char *);
60#ifdef UNITTESTS
61static void DetectTlsCertsRegisterTests(void);
62#endif
63
64static int g_tls_certs_buffer_id = 0;
65
66static bool TlsCertsGetData(DetectEngineThreadCtx *det_ctx, const void *txv, const uint8_t flags,
67 uint32_t local_id, const uint8_t **buf, uint32_t *buf_len)
68{
69 const SSLState *ssl_state = (SSLState *)txv;
70 const SSLStateConnp *connp;
71
72 if (flags & STREAM_TOSERVER) {
73 connp = &ssl_state->client_connp;
74 } else {
75 connp = &ssl_state->server_connp;
76 }
77
78 if (TAILQ_EMPTY(&connp->certs)) {
79 return false;
80 }
81
82 SSLCertsChain *cert;
83 if (local_id == 0) {
84 cert = TAILQ_FIRST(&connp->certs);
85 } else {
86 // TODO optimize ?
87 cert = TAILQ_FIRST(&connp->certs);
88 for (uint32_t i = 0; i < local_id; i++) {
89 cert = TAILQ_NEXT(cert, next);
90 }
91 }
92 if (cert == NULL) {
93 return false;
94 }
95
96 *buf = cert->cert_data;
97 *buf_len = cert->cert_len;
98 return true;
99}
100
101/**
102 * \brief Registration function for keyword: tls.certs
103 */
105{
106 sigmatch_table[DETECT_TLS_CERTS].name = "tls.certs";
107 sigmatch_table[DETECT_TLS_CERTS].desc = "sticky buffer to match the TLS certificate buffer";
108 sigmatch_table[DETECT_TLS_CERTS].url = "/rules/tls-keywords.html#tls-certs";
109 sigmatch_table[DETECT_TLS_CERTS].Setup = DetectTlsCertsSetup;
110#ifdef UNITTESTS
111 sigmatch_table[DETECT_TLS_CERTS].RegisterTests = DetectTlsCertsRegisterTests;
112#endif
115
117 TLS_STATE_SERVER_CERT_DONE, TlsCertsGetData, 2);
119 TLS_STATE_CLIENT_CERT_DONE, TlsCertsGetData, 2);
120
121 DetectBufferTypeSetDescriptionByName("tls.certs", "TLS certificate");
122
124
125 g_tls_certs_buffer_id = DetectBufferTypeGetByName("tls.certs");
126}
127
128/**
129 * \brief This function setup the tls.certs modifier keyword
130 *
131 * \param de_ctx Pointer to the Detect Engine Context
132 * \param s Pointer to the Signature to which the keyword belongs
133 * \param str Should hold an empty string always
134 *
135 * \retval 0 On success
136 * \retval -1 On failure
137 */
138static int DetectTlsCertsSetup(DetectEngineCtx *de_ctx, Signature *s,
139 const char *str)
140{
141 if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_certs_buffer_id) < 0)
142 return -1;
143
145 return -1;
146
147 return 0;
148}
149
150static int g_tls_cert_buffer_id = 0;
151#define BUFFER_NAME "tls:server_cert_done:generic"
152#define KEYWORD_ID DETECT_TLS_CHAIN_LEN
153#define KEYWORD_NAME "tls.cert_chain_len"
154#define KEYWORD_DESC "match TLS certificate chain length"
155#define KEYWORD_URL "/rules/tls-keywords.html#tls-cert-chain-len"
156
157/**
158 * \internal
159 * \brief Function to match cert chain length in TLS
160 *
161 * \param t Pointer to thread vars.
162 * \param det_ctx Pointer to the pattern matcher thread.
163 * \param f Pointer to the current flow.
164 * \param flags Flags.
165 * \param state App layer state.
166 * \param s Pointer to the Signature.
167 * \param m Pointer to the sigmatch that we will cast into
168 * DetectU64Data.
169 *
170 * \retval 0 no match.
171 * \retval 1 match.
172 */
173static int DetectTLSCertChainLenMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags,
174 void *state, void *txv, const Signature *s, const SigMatchCtx *ctx)
175{
176 SCEnter();
177
178 SSLState *ssl_state = state;
179 if (flags & STREAM_TOCLIENT) {
180 SSLStateConnp *connp = &ssl_state->server_connp;
181 uint32_t cnt = 0;
182 SSLCertsChain *cert;
183 TAILQ_FOREACH (cert, &connp->certs, next) {
184 cnt++;
185 }
186 SCLogDebug("%u certs in chain", cnt);
187
188 const DetectU32Data *dd = (const DetectU32Data *)ctx;
189 if (DetectU32Match(cnt, dd)) {
190 SCReturnInt(1);
191 }
192 }
193 SCReturnInt(0);
194}
195
196/**
197 * \internal
198 * \brief Function to free memory associated with DetectU64Data.
199 *
200 * \param de_ptr Pointer to DetectU64Data.
201 */
202static void DetectTLSCertChainLenFree(DetectEngineCtx *de_ctx, void *ptr)
203{
204 SCDetectU32Free(ptr);
205}
206
207/**
208 * \brief Function to add the parsed tls cert chain len field into the current signature.
209 *
210 * \param de_ctx Pointer to the Detection Engine Context.
211 * \param s Pointer to the Current Signature.
212 * \param rawstr Pointer to the user provided flags options.
213 * \param type Defines if this is notBefore or notAfter.
214 *
215 * \retval 0 on Success.
216 * \retval -1 on Failure.
217 */
218static int DetectTLSCertChainLenSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
219{
221 return -1;
222
223 DetectU32Data *dd = DetectU32Parse(rawstr);
224 if (dd == NULL) {
225 SCLogError("Parsing \'%s\' failed for %s", rawstr, sigmatch_table[KEYWORD_ID].name);
226 return -1;
227 }
228
229 if (SCSigMatchAppendSMToList(de_ctx, s, KEYWORD_ID, (SigMatchCtx *)dd, g_tls_cert_buffer_id) ==
230 NULL) {
231 SCDetectU32Free(dd);
232 return -1;
233 }
234 return 0;
235}
236
238{
242 sigmatch_table[KEYWORD_ID].AppLayerTxMatch = DetectTLSCertChainLenMatch;
243 sigmatch_table[KEYWORD_ID].Setup = DetectTLSCertChainLenSetup;
244 sigmatch_table[KEYWORD_ID].Free = DetectTLSCertChainLenFree;
245
246 g_tls_cert_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
247}
248
249#ifdef UNITTESTS
251#endif
struct HtpBodyChunk_ * next
@ ALPROTO_TLS
@ TLS_STATE_CLIENT_CERT_DONE
@ TLS_STATE_SERVER_CERT_DONE
uint8_t flags
Definition decode-gre.h:0
int SCDetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
DetectUintData_u32 * DetectU32Parse(const char *u32str)
This function is used to parse u32 options passed via some u32 keyword.
int DetectU32Match(const uint32_t parg, const DetectUintData_u32 *du32)
DetectUintData_u32 DetectU32Data
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
void DetectBufferTypeSupportsMultiInstance(const char *name)
void DetectAppLayerMultiRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectionMultiBufferGetDataPtr GetData, int priority)
int DetectBufferTypeGetByName(const char *name)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigTableElmt * sigmatch_table
void DetectTlsCertChainLenRegister(void)
void DetectTlsCertsRegister(void)
Registration function for keyword: tls.certs.
#define KEYWORD_URL
#define KEYWORD_DESC
#define BUFFER_NAME
#define KEYWORD_NAME
#define KEYWORD_ID
#define SIGMATCH_NOOPT
Definition detect.h:1651
#define SIG_FLAG_TOCLIENT
Definition detect.h:272
#define SIGMATCH_INFO_STICKY_BUFFER
Definition detect.h:1676
#define SIG_FLAG_TOSERVER
Definition detect.h:271
DetectEngineCtx * de_ctx
struct Thresholds ctx
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
#define TAILQ_FIRST(head)
Definition queue.h:250
#define TAILQ_NEXT(elm, field)
Definition queue.h:307
#define TAILQ_EMPTY(head)
Definition queue.h:248
main detection engine ctx
Definition detect.h:932
Flow data structure.
Definition flow.h:356
uint8_t * cert_data
SSLv[2.0|3.[0|1|2|3]] state structure.
SSLStateConnp server_connp
SSLStateConnp client_connp
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
uint16_t flags
Definition detect.h:1450
const char * desc
Definition detect.h:1461
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition detect.h:1424
void(* RegisterTests)(void)
Definition detect.h:1448
const char * name
Definition detect.h:1459
Signature container.
Definition detect.h:668
#define str(s)
const char * name
uint32_t cnt
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267