suricata
detect-tls.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011-2012 ANSSI
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * \file
30  *
31  * \author Pierre Chifflier <pierre.chifflier@ssi.gouv.fr>
32  *
33  * Implements the tls.* keywords
34  */
35 
36 #include "suricata-common.h"
37 #include "threads.h"
38 #include "debug.h"
39 #include "decode.h"
40 
41 #include "detect.h"
42 #include "detect-parse.h"
43 
44 #include "detect-engine.h"
45 #include "detect-engine-mpm.h"
46 #include "detect-engine-state.h"
47 
48 #include "flow.h"
49 #include "flow-var.h"
50 #include "flow-util.h"
51 
52 #include "util-debug.h"
53 #include "util-unittest.h"
54 #include "util-unittest-helper.h"
55 
56 #include "app-layer.h"
57 
58 #include "app-layer-ssl.h"
59 #include "detect-tls.h"
60 
61 #include "stream-tcp.h"
62 
63 /**
64  * \brief Regex for parsing "id" option, matching number or "number"
65  */
66 
67 #define PARSE_REGEX "^([A-z0-9\\s\\-\\.=,\\*@]+|\"[A-z0-9\\s\\-\\.=,\\*@]+\")\\s*$"
68 #define PARSE_REGEX_FINGERPRINT "^([A-z0-9\\:\\*]+|\"[A-z0-9\\:\\* ]+\")\\s*$"
69 
70 static pcre *subject_parse_regex;
71 static pcre_extra *subject_parse_regex_study;
72 static pcre *issuerdn_parse_regex;
73 static pcre_extra *issuerdn_parse_regex_study;
74 static pcre *fingerprint_parse_regex;
75 static pcre_extra *fingerprint_parse_regex_study;
76 
77 static int DetectTlsSubjectMatch (DetectEngineThreadCtx *,
78  Flow *, uint8_t, void *, void *,
79  const Signature *, const SigMatchCtx *);
80 static int DetectTlsSubjectSetup (DetectEngineCtx *, Signature *, const char *);
81 static void DetectTlsSubjectRegisterTests(void);
82 static void DetectTlsSubjectFree(void *);
83 
84 static int DetectTlsIssuerDNMatch (DetectEngineThreadCtx *,
85  Flow *, uint8_t, void *, void *,
86  const Signature *, const SigMatchCtx *);
87 static int DetectTlsIssuerDNSetup (DetectEngineCtx *, Signature *, const char *);
88 static void DetectTlsIssuerDNRegisterTests(void);
89 static void DetectTlsIssuerDNFree(void *);
90 
91 static int DetectTlsFingerprintMatch (DetectEngineThreadCtx *,
92  Flow *, uint8_t, void *, void *,
93  const Signature *, const SigMatchCtx *);
94 static int DetectTlsFingerprintSetup (DetectEngineCtx *, Signature *, const char *);
95 static void DetectTlsFingerprintFree(void *);
96 
97 static int DetectTlsStoreSetup (DetectEngineCtx *, Signature *, const char *);
98 static int DetectTlsStorePostMatch (DetectEngineThreadCtx *det_ctx,
99  Packet *, const Signature *s, const SigMatchCtx *unused);
100 
101 static int g_tls_cert_list_id = 0;
102 
103 static int InspectTlsCert(ThreadVars *tv,
104  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
105  const Signature *s, const SigMatchData *smd,
106  Flow *f, uint8_t flags, void *alstate,
107  void *txv, uint64_t tx_id)
108 {
109  return DetectEngineInspectGenericList(tv, de_ctx, det_ctx, s, smd,
110  f, flags, alstate, txv, tx_id);
111 }
112 
113 /**
114  * \brief Registration function for keyword: tls.version
115  */
116 void DetectTlsRegister (void)
117 {
118  sigmatch_table[DETECT_AL_TLS_SUBJECT].name = "tls.subject";
119  sigmatch_table[DETECT_AL_TLS_SUBJECT].desc = "match TLS/SSL certificate Subject field";
120  sigmatch_table[DETECT_AL_TLS_SUBJECT].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-subject";
121  sigmatch_table[DETECT_AL_TLS_SUBJECT].AppLayerTxMatch = DetectTlsSubjectMatch;
122  sigmatch_table[DETECT_AL_TLS_SUBJECT].Setup = DetectTlsSubjectSetup;
123  sigmatch_table[DETECT_AL_TLS_SUBJECT].Free = DetectTlsSubjectFree;
124  sigmatch_table[DETECT_AL_TLS_SUBJECT].RegisterTests = DetectTlsSubjectRegisterTests;
127 
128  sigmatch_table[DETECT_AL_TLS_ISSUERDN].name = "tls.issuerdn";
129  sigmatch_table[DETECT_AL_TLS_ISSUERDN].desc = "match TLS/SSL certificate IssuerDN field";
130  sigmatch_table[DETECT_AL_TLS_ISSUERDN].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-issuerdn";
131  sigmatch_table[DETECT_AL_TLS_ISSUERDN].AppLayerTxMatch = DetectTlsIssuerDNMatch;
132  sigmatch_table[DETECT_AL_TLS_ISSUERDN].Setup = DetectTlsIssuerDNSetup;
133  sigmatch_table[DETECT_AL_TLS_ISSUERDN].Free = DetectTlsIssuerDNFree;
134  sigmatch_table[DETECT_AL_TLS_ISSUERDN].RegisterTests = DetectTlsIssuerDNRegisterTests;
137 
138  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].name = "tls.fingerprint";
139  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].desc = "match TLS/SSL certificate SHA1 fingerprint";
140  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-fingerprint";
141  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].AppLayerTxMatch = DetectTlsFingerprintMatch;
142  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].Setup = DetectTlsFingerprintSetup;
143  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].Free = DetectTlsFingerprintFree;
147 
148  sigmatch_table[DETECT_AL_TLS_STORE].name = "tls_store";
150  sigmatch_table[DETECT_AL_TLS_STORE].desc = "store TLS/SSL certificate on disk";
151  sigmatch_table[DETECT_AL_TLS_STORE].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-store";
152  sigmatch_table[DETECT_AL_TLS_STORE].Match = DetectTlsStorePostMatch;
153  sigmatch_table[DETECT_AL_TLS_STORE].Setup = DetectTlsStoreSetup;
157 
159  &subject_parse_regex, &subject_parse_regex_study);
161  &issuerdn_parse_regex, &issuerdn_parse_regex_study);
163  &fingerprint_parse_regex, &fingerprint_parse_regex_study);
164 
165  g_tls_cert_list_id = DetectBufferTypeRegister("tls_cert");
166 
169  InspectTlsCert);
170 }
171 
172 /**
173  * \brief match the specified Subject on a tls session
174  *
175  * \param t pointer to thread vars
176  * \param det_ctx pointer to the pattern matcher thread
177  * \param p pointer to the current packet
178  * \param m pointer to the sigmatch that we will cast into DetectTlsData
179  *
180  * \retval 0 no match
181  * \retval 1 match
182  */
183 static int DetectTlsSubjectMatch (DetectEngineThreadCtx *det_ctx,
184  Flow *f, uint8_t flags, void *state, void *txv,
185  const Signature *s, const SigMatchCtx *m)
186 {
187  SCEnter();
188 
189  const DetectTlsData *tls_data = (const DetectTlsData *)m;
190  SSLState *ssl_state = (SSLState *)state;
191  if (ssl_state == NULL) {
192  SCLogDebug("no tls state, no match");
193  SCReturnInt(0);
194  }
195 
196  int ret = 0;
197 
198  SSLStateConnp *connp = NULL;
199  if (flags & STREAM_TOSERVER) {
200  connp = &ssl_state->client_connp;
201  } else {
202  connp = &ssl_state->server_connp;
203  }
204 
205  if (connp->cert0_subject != NULL) {
206  SCLogDebug("TLS: Subject is [%s], looking for [%s]\n",
207  connp->cert0_subject, tls_data->subject);
208 
209  if (strstr(connp->cert0_subject, tls_data->subject) != NULL) {
210  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
211  ret = 0;
212  } else {
213  ret = 1;
214  }
215  } else {
216  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
217  ret = 1;
218  } else {
219  ret = 0;
220  }
221  }
222  } else {
223  ret = 0;
224  }
225 
226  SCReturnInt(ret);
227 }
228 
229 /**
230  * \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
231  *
232  * \param idstr Pointer to the user provided id option
233  *
234  * \retval id_d pointer to DetectTlsData on success
235  * \retval NULL on failure
236  */
237 static DetectTlsData *DetectTlsSubjectParse (const char *str, bool negate)
238 {
239  DetectTlsData *tls = NULL;
240 #define MAX_SUBSTRINGS 30
241  int ret = 0, res = 0;
242  int ov[MAX_SUBSTRINGS];
243  const char *str_ptr;
244  char *orig = NULL;
245  char *tmp_str;
246  uint32_t flag = 0;
247 
248  ret = pcre_exec(subject_parse_regex, subject_parse_regex_study, str, strlen(str), 0, 0,
249  ov, MAX_SUBSTRINGS);
250 
251  if (ret != 2) {
252  SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.subject option");
253  goto error;
254  }
255 
256  if (negate)
257  flag = DETECT_CONTENT_NEGATED;
258 
259  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
260  if (res < 0) {
261  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
262  goto error;
263  }
264 
265  /* We have a correct id option */
266  tls = SCMalloc(sizeof(DetectTlsData));
267  if (unlikely(tls == NULL))
268  goto error;
269  tls->subject = NULL;
270  tls->flags = flag;
271 
272  orig = SCStrdup((char*)str_ptr);
273  if (unlikely(orig == NULL)) {
274  goto error;
275  }
276  pcre_free_substring(str_ptr);
277 
278  tmp_str=orig;
279 
280  /* Let's see if we need to escape "'s */
281  if (tmp_str[0] == '"') {
282  tmp_str[strlen(tmp_str) - 1] = '\0';
283  tmp_str += 1;
284  }
285 
286  tls->subject = SCStrdup(tmp_str);
287  if (unlikely(tls->subject == NULL)) {
288  goto error;
289  }
290 
291  SCFree(orig);
292 
293  SCLogDebug("will look for TLS subject %s", tls->subject);
294 
295  return tls;
296 
297 error:
298  if (orig != NULL)
299  SCFree(orig);
300  if (tls != NULL)
301  DetectTlsSubjectFree(tls);
302  return NULL;
303 
304 }
305 
306 /**
307  * \brief this function is used to add the parsed "id" option
308  * \brief into the current signature
309  *
310  * \param de_ctx pointer to the Detection Engine Context
311  * \param s pointer to the Current Signature
312  * \param idstr pointer to the user provided "id" option
313  *
314  * \retval 0 on Success
315  * \retval -1 on Failure
316  */
317 static int DetectTlsSubjectSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
318 {
319  DetectTlsData *tls = NULL;
320  SigMatch *sm = NULL;
321 
323  return -1;
324 
325  tls = DetectTlsSubjectParse(str, s->init_data->negated);
326  if (tls == NULL)
327  goto error;
328 
329  /* Okay so far so good, lets get this into a SigMatch
330  * and put it in the Signature. */
331  sm = SigMatchAlloc();
332  if (sm == NULL)
333  goto error;
334 
336  sm->ctx = (void *)tls;
337 
338  SigMatchAppendSMToList(s, sm, g_tls_cert_list_id);
339  return 0;
340 
341 error:
342  if (tls != NULL)
343  DetectTlsSubjectFree(tls);
344  if (sm != NULL)
345  SCFree(sm);
346  return -1;
347 
348 }
349 
350 /**
351  * \brief this function will free memory associated with DetectTlsData
352  *
353  * \param id_d pointer to DetectTlsData
354  */
355 static void DetectTlsSubjectFree(void *ptr)
356 {
357  DetectTlsData *id_d = (DetectTlsData *)ptr;
358  if (ptr == NULL)
359  return;
360  if (id_d->subject != NULL)
361  SCFree(id_d->subject);
362  SCFree(id_d);
363 }
364 
365 /**
366  * \brief this function registers unit tests for DetectTlsSubject
367  */
368 static void DetectTlsSubjectRegisterTests(void)
369 {
370 }
371 
372 /**
373  * \brief match the specified IssuerDN on a tls session
374  *
375  * \param t pointer to thread vars
376  * \param det_ctx pointer to the pattern matcher thread
377  * \param p pointer to the current packet
378  * \param m pointer to the sigmatch that we will cast into DetectTlsData
379  *
380  * \retval 0 no match
381  * \retval 1 match
382  */
383 static int DetectTlsIssuerDNMatch (DetectEngineThreadCtx *det_ctx,
384  Flow *f, uint8_t flags, void *state, void *txv,
385  const Signature *s, const SigMatchCtx *m)
386 {
387  SCEnter();
388 
389  const DetectTlsData *tls_data = (const DetectTlsData *)m;
390  SSLState *ssl_state = (SSLState *)state;
391  if (ssl_state == NULL) {
392  SCLogDebug("no tls state, no match");
393  SCReturnInt(0);
394  }
395 
396  int ret = 0;
397 
398  SSLStateConnp *connp = NULL;
399  if (flags & STREAM_TOSERVER) {
400  connp = &ssl_state->client_connp;
401  } else {
402  connp = &ssl_state->server_connp;
403  }
404 
405  if (connp->cert0_issuerdn != NULL) {
406  SCLogDebug("TLS: IssuerDN is [%s], looking for [%s]\n",
407  connp->cert0_issuerdn, tls_data->issuerdn);
408 
409  if (strstr(connp->cert0_issuerdn, tls_data->issuerdn) != NULL) {
410  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
411  ret = 0;
412  } else {
413  ret = 1;
414  }
415  } else {
416  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
417  ret = 1;
418  } else {
419  ret = 0;
420  }
421  }
422  } else {
423  ret = 0;
424  }
425 
426  SCReturnInt(ret);
427 }
428 
429 /**
430  * \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
431  *
432  * \param idstr Pointer to the user provided id option
433  *
434  * \retval id_d pointer to DetectTlsData on success
435  * \retval NULL on failure
436  */
437 static DetectTlsData *DetectTlsIssuerDNParse(const char *str, bool negate)
438 {
439  DetectTlsData *tls = NULL;
440 #define MAX_SUBSTRINGS 30
441  int ret = 0, res = 0;
442  int ov[MAX_SUBSTRINGS];
443  const char *str_ptr;
444  char *orig = NULL;
445  char *tmp_str;
446  uint32_t flag = 0;
447 
448  ret = pcre_exec(issuerdn_parse_regex, issuerdn_parse_regex_study, str, strlen(str), 0, 0,
449  ov, MAX_SUBSTRINGS);
450  if (ret != 2) {
451  SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.issuerdn option");
452  goto error;
453  }
454 
455  if (negate)
456  flag = DETECT_CONTENT_NEGATED;
457 
458  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
459  if (res < 0) {
460  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
461  goto error;
462  }
463 
464  /* We have a correct id option */
465  tls = SCMalloc(sizeof(DetectTlsData));
466  if (unlikely(tls == NULL))
467  goto error;
468  tls->issuerdn = NULL;
469  tls->flags = flag;
470 
471  orig = SCStrdup((char*)str_ptr);
472  if (unlikely(orig == NULL)) {
473  goto error;
474  }
475  pcre_free_substring(str_ptr);
476 
477  tmp_str=orig;
478 
479  /* Let's see if we need to escape "'s */
480  if (tmp_str[0] == '"')
481  {
482  tmp_str[strlen(tmp_str) - 1] = '\0';
483  tmp_str += 1;
484  }
485 
486  tls->issuerdn = SCStrdup(tmp_str);
487  if (unlikely(tls->issuerdn == NULL)) {
488  goto error;
489  }
490 
491  SCFree(orig);
492 
493  SCLogDebug("Will look for TLS issuerdn %s", tls->issuerdn);
494 
495  return tls;
496 
497 error:
498  if (orig != NULL)
499  SCFree(orig);
500  if (tls != NULL)
501  DetectTlsIssuerDNFree(tls);
502  return NULL;
503 
504 }
505 
506 /**
507  * \brief this function is used to add the parsed "id" option
508  * \brief into the current signature
509  *
510  * \param de_ctx pointer to the Detection Engine Context
511  * \param s pointer to the Current Signature
512  * \param idstr pointer to the user provided "id" option
513  *
514  * \retval 0 on Success
515  * \retval -1 on Failure
516  */
517 static int DetectTlsIssuerDNSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
518 {
519  DetectTlsData *tls = NULL;
520  SigMatch *sm = NULL;
521 
523  return -1;
524 
525  tls = DetectTlsIssuerDNParse(str, s->init_data->negated);
526  if (tls == NULL)
527  goto error;
528 
529  /* Okay so far so good, lets get this into a SigMatch
530  * and put it in the Signature. */
531  sm = SigMatchAlloc();
532  if (sm == NULL)
533  goto error;
534 
536  sm->ctx = (void *)tls;
537 
538  SigMatchAppendSMToList(s, sm, g_tls_cert_list_id);
539  return 0;
540 
541 error:
542  if (tls != NULL)
543  DetectTlsIssuerDNFree(tls);
544  if (sm != NULL)
545  SCFree(sm);
546  return -1;
547 
548 }
549 
550 /**
551  * \brief this function will free memory associated with DetectTlsData
552  *
553  * \param id_d pointer to DetectTlsData
554  */
555 static void DetectTlsIssuerDNFree(void *ptr)
556 {
557  DetectTlsData *id_d = (DetectTlsData *)ptr;
558  SCFree(id_d->issuerdn);
559  SCFree(id_d);
560 }
561 
562 /**
563  * \brief This function is used to parse fingerprint passed via keyword: "fingerprint"
564  *
565  * \param idstr Pointer to the user provided fingerprint option
566  *
567  * \retval pointer to DetectTlsData on success
568  * \retval NULL on failure
569  */
570 static DetectTlsData *DetectTlsFingerprintParse (const char *str, bool negate)
571 {
572  DetectTlsData *tls = NULL;
573 #define MAX_SUBSTRINGS 30
574  int ret = 0, res = 0;
575  int ov[MAX_SUBSTRINGS];
576  const char *str_ptr;
577  char *orig;
578  char *tmp_str;
579  uint32_t flag = 0;
580 
581  ret = pcre_exec(fingerprint_parse_regex, fingerprint_parse_regex_study, str, strlen(str), 0, 0,
582  ov, MAX_SUBSTRINGS);
583  if (ret != 2) {
584  SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.fingerprint option");
585  goto error;
586  }
587 
588  if (negate)
589  flag = DETECT_CONTENT_NEGATED;
590 
591  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
592  if (res < 0) {
593  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
594  goto error;
595  }
596 
597  /* We have a correct id option */
598  tls = SCMalloc(sizeof(DetectTlsData));
599  if (unlikely(tls == NULL))
600  goto error;
601  tls->fingerprint = NULL;
602  tls->flags = flag;
603 
604  orig = SCStrdup((char*)str_ptr);
605  if (unlikely(orig == NULL)) {
606  goto error;
607  }
608  pcre_free_substring(str_ptr);
609 
610  tmp_str=orig;
611 
612  /* Let's see if we need to escape "'s */
613  if (tmp_str[0] == '"')
614  {
615  tmp_str[strlen(tmp_str) - 1] = '\0';
616  tmp_str += 1;
617  }
618 
619  tls->fingerprint = SCStrdup(tmp_str);
620  if (tls->fingerprint == NULL) {
621  SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate fingerprint");
622  }
623 
624  SCFree(orig);
625 
626  SCLogDebug("will look for TLS fingerprint %s", tls->fingerprint);
627 
628  return tls;
629 
630 error:
631  if (tls != NULL)
632  DetectTlsFingerprintFree(tls);
633  return NULL;
634 
635 }
636 /**
637  * \brief match the specified fingerprint on a tls session
638  *
639  * \param t pointer to thread vars
640  * \param det_ctx pointer to the pattern matcher thread
641  * \param p pointer to the current packet
642  * \param m pointer to the sigmatch that we will cast into DetectTlsData
643  *
644  * \retval 0 no match
645  * \retval 1 match
646  */
647 static int DetectTlsFingerprintMatch (DetectEngineThreadCtx *det_ctx,
648  Flow *f, uint8_t flags, void *state, void *txv,
649  const Signature *s, const SigMatchCtx *m)
650 {
651  SCEnter();
652  const DetectTlsData *tls_data = (const DetectTlsData *)m;
653  SSLState *ssl_state = (SSLState *)state;
654  if (ssl_state == NULL) {
655  SCLogDebug("no tls state, no match");
656  SCReturnInt(0);
657  }
658 
659  int ret = 0;
660 
661  SSLStateConnp *connp = NULL;
662  if (flags & STREAM_TOSERVER) {
663  connp = &ssl_state->client_connp;
664  } else {
665  connp = &ssl_state->server_connp;
666  }
667 
668  if (connp->cert0_fingerprint != NULL) {
669  SCLogDebug("TLS: Fingerprint is [%s], looking for [%s]\n",
670  connp->cert0_fingerprint,
671  tls_data->fingerprint);
672 
673  if (tls_data->fingerprint &&
674  (strstr(connp->cert0_fingerprint,
675  tls_data->fingerprint) != NULL)) {
676  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
677  ret = 0;
678  } else {
679  ret = 1;
680 
681  }
682  } else {
683  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
684  ret = 1;
685  } else {
686  ret = 0;
687  }
688  }
689  } else {
690  ret = 0;
691  }
692 
693  SCReturnInt(ret);
694 }
695 
696 /**
697  * \brief this function is used to add the parsed "fingerprint" option
698  * \brief into the current signature
699  *
700  * \param de_ctx pointer to the Detection Engine Context
701  * \param s pointer to the Current Signature
702  * \param id pointer to the user provided "fingerprint" option
703  *
704  * \retval 0 on Success
705  * \retval -1 on Failure
706  */
707 static int DetectTlsFingerprintSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
708 {
709  DetectTlsData *tls = NULL;
710  SigMatch *sm = NULL;
711 
713  return -1;
714 
715  tls = DetectTlsFingerprintParse(str, s->init_data->negated);
716  if (tls == NULL)
717  goto error;
718 
719  /* Okay so far so good, lets get this into a SigMatch
720  * and put it in the Signature. */
721  sm = SigMatchAlloc();
722  if (sm == NULL)
723  goto error;
724 
726  sm->ctx = (void *)tls;
727 
728  SigMatchAppendSMToList(s, sm, g_tls_cert_list_id);
729  return 0;
730 
731 error:
732  if (tls != NULL)
733  DetectTlsFingerprintFree(tls);
734  if (sm != NULL)
735  SCFree(sm);
736  return -1;
737 
738 }
739 
740 /**
741  * \brief this function will free memory associated with DetectTlsData
742  *
743  * \param pointer to DetectTlsData
744  */
745 static void DetectTlsFingerprintFree(void *ptr)
746 {
747  DetectTlsData *id_d = (DetectTlsData *)ptr;
748  if (id_d->fingerprint)
749  SCFree(id_d->fingerprint);
750  SCFree(id_d);
751 }
752 
753 /**
754  * \brief this function is used to add the parsed "store" option
755  * \brief into the current signature
756  *
757  * \param de_ctx pointer to the Detection Engine Context
758  * \param s pointer to the Current Signature
759  * \param idstr pointer to the user provided "store" option
760  *
761  * \retval 0 on Success
762  * \retval -1 on Failure
763  */
764 static int DetectTlsStoreSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
765 {
766  SigMatch *sm = NULL;
767 
769  return -1;
770 
771  sm = SigMatchAlloc();
772  if (sm == NULL)
773  return -1;
774 
776  s->flags |= SIG_FLAG_TLSSTORE;
777 
779  return 0;
780 }
781 
782 /** \warning modifies Flow::alstate */
783 static int DetectTlsStorePostMatch (DetectEngineThreadCtx *det_ctx,
784  Packet *p, const Signature *s, const SigMatchCtx *unused)
785 {
786  SCEnter();
787 
788  if (p->flow == NULL)
789  return 0;
790 
791  SSLState *ssl_state = FlowGetAppState(p->flow);
792  if (ssl_state == NULL) {
793  SCLogDebug("no tls state, no match");
794  SCReturnInt(0);
795  }
796 
798  SCReturnInt(1);
799 }
800 
801 
802 /**
803  * \brief this function registers unit tests for DetectTlsIssuerDN
804  */
805 static void DetectTlsIssuerDNRegisterTests(void)
806 {
807 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1448
SignatureInitData * init_data
Definition: detect.h:591
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
char * cert0_subject
#define SCLogDebug(...)
Definition: util-debug.h:335
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
struct Flow_ * flow
Definition: decode.h:445
uint32_t flags
Definition: detect.h:523
#define MAX_SUBSTRINGS
#define unlikely(expr)
Definition: util-optimize.h:35
char * cert0_fingerprint
SSLStateConnp server_connp
Data needed for Match()
Definition: detect.h:327
#define SIG_FLAG_TLSSTORE
Definition: detect.h:239
const char * name
Definition: detect.h:1200
int DetectEngineInspectGenericList(ThreadVars *tv, const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, const uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
Signature container.
Definition: detect.h:522
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:313
main detection engine ctx
Definition: detect.h:761
SSLv[2.0|3.[0|1|2|3]] state structure.
#define str(s)
#define PARSE_REGEX_FINGERPRINT
Definition: detect-tls.c:68
uint32_t flags
Definition: detect-tls.h:39
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1191
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
char * issuerdn
Definition: detect-tls.h:41
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1385
#define SCEnter(...)
Definition: util-debug.h:337
char * subject
Definition: detect-tls.h:40
uint16_t alternative
Definition: detect.h:1198
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1170
uint8_t type
Definition: detect.h:319
#define SCReturnInt(x)
Definition: util-debug.h:341
#define SSL_TLS_LOG_PEM
const char * desc
Definition: detect.h:1202
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:346
int DetectBufferTypeRegister(const char *name)
SigMatchCtx * ctx
Definition: detect.h:321
const char * alias
Definition: detect.h:1201
#define SCMalloc(a)
Definition: util-mem.h:222
#define DETECT_CONTENT_NEGATED
char * fingerprint
Definition: detect-tls.h:42
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
uint32_t cert_log_flag
uint16_t tx_id
#define SIGMATCH_NOOPT
Definition: detect.h:1369
void DetectTlsRegister(void)
Registration function for keyword: tls.version.
Definition: detect-tls.c:116
const char * url
Definition: detect.h:1203
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1173
#define STREAM_TOSERVER
Definition: stream.h:31
SCMutex m
Definition: flow-hash.h:105
void * FlowGetAppState(const Flow *f)
Definition: flow.c:1068
#define SCStrdup(a)
Definition: util-mem.h:268
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1389
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1194
#define PARSE_REGEX
Regex for parsing "id" option, matching number or "number".
Definition: detect-tls.c:67
Flow data structure.
Definition: flow.h:325
SSLStateConnp client_connp
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
void(* RegisterTests)(void)
Definition: detect.h:1192
a single match condition for a signature
Definition: detect.h:318
char * cert0_issuerdn