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 (ThreadVars *, 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 (ThreadVars *, 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 (ThreadVars *, 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 (ThreadVars *t, 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;
126 
127  sigmatch_table[DETECT_AL_TLS_ISSUERDN].name = "tls.issuerdn";
128  sigmatch_table[DETECT_AL_TLS_ISSUERDN].desc = "match TLS/SSL certificate IssuerDN field";
129  sigmatch_table[DETECT_AL_TLS_ISSUERDN].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-issuerdn";
130  sigmatch_table[DETECT_AL_TLS_ISSUERDN].AppLayerTxMatch = DetectTlsIssuerDNMatch;
131  sigmatch_table[DETECT_AL_TLS_ISSUERDN].Setup = DetectTlsIssuerDNSetup;
132  sigmatch_table[DETECT_AL_TLS_ISSUERDN].Free = DetectTlsIssuerDNFree;
133  sigmatch_table[DETECT_AL_TLS_ISSUERDN].RegisterTests = DetectTlsIssuerDNRegisterTests;
135 
136  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].name = "tls.fingerprint";
137  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].desc = "match TLS/SSL certificate SHA1 fingerprint";
138  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-fingerprint";
139  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].AppLayerTxMatch = DetectTlsFingerprintMatch;
140  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].Setup = DetectTlsFingerprintSetup;
141  sigmatch_table[DETECT_AL_TLS_FINGERPRINT].Free = DetectTlsFingerprintFree;
144 
145  sigmatch_table[DETECT_AL_TLS_STORE].name = "tls_store";
147  sigmatch_table[DETECT_AL_TLS_STORE].desc = "store TLS/SSL certificate on disk";
148  sigmatch_table[DETECT_AL_TLS_STORE].url = DOC_URL DOC_VERSION "/rules/tls-keywords.html#tls-store";
149  sigmatch_table[DETECT_AL_TLS_STORE].Match = DetectTlsStorePostMatch;
150  sigmatch_table[DETECT_AL_TLS_STORE].Setup = DetectTlsStoreSetup;
154 
156  &subject_parse_regex, &subject_parse_regex_study);
158  &issuerdn_parse_regex, &issuerdn_parse_regex_study);
160  &fingerprint_parse_regex, &fingerprint_parse_regex_study);
161 
162  g_tls_cert_list_id = DetectBufferTypeRegister("tls_cert");
163 
166  InspectTlsCert);
167 }
168 
169 /**
170  * \brief match the specified Subject on a tls session
171  *
172  * \param t pointer to thread vars
173  * \param det_ctx pointer to the pattern matcher thread
174  * \param p pointer to the current packet
175  * \param m pointer to the sigmatch that we will cast into DetectTlsData
176  *
177  * \retval 0 no match
178  * \retval 1 match
179  */
180 static int DetectTlsSubjectMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
181  Flow *f, uint8_t flags, void *state, void *txv,
182  const Signature *s, const SigMatchCtx *m)
183 {
184  SCEnter();
185 
186  const DetectTlsData *tls_data = (const DetectTlsData *)m;
187  SSLState *ssl_state = (SSLState *)state;
188  if (ssl_state == NULL) {
189  SCLogDebug("no tls state, no match");
190  SCReturnInt(0);
191  }
192 
193  int ret = 0;
194 
195  SSLStateConnp *connp = NULL;
196  if (flags & STREAM_TOSERVER) {
197  connp = &ssl_state->client_connp;
198  } else {
199  connp = &ssl_state->server_connp;
200  }
201 
202  if (connp->cert0_subject != NULL) {
203  SCLogDebug("TLS: Subject is [%s], looking for [%s]\n",
204  connp->cert0_subject, tls_data->subject);
205 
206  if (strstr(connp->cert0_subject, tls_data->subject) != NULL) {
207  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
208  ret = 0;
209  } else {
210  ret = 1;
211  }
212  } else {
213  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
214  ret = 1;
215  } else {
216  ret = 0;
217  }
218  }
219  } else {
220  ret = 0;
221  }
222 
223  SCReturnInt(ret);
224 }
225 
226 /**
227  * \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
228  *
229  * \param idstr Pointer to the user provided id option
230  *
231  * \retval id_d pointer to DetectTlsData on success
232  * \retval NULL on failure
233  */
234 static DetectTlsData *DetectTlsSubjectParse (const char *str, bool negate)
235 {
236  DetectTlsData *tls = NULL;
237 #define MAX_SUBSTRINGS 30
238  int ret = 0, res = 0;
239  int ov[MAX_SUBSTRINGS];
240  const char *str_ptr;
241  char *orig = NULL;
242  char *tmp_str;
243  uint32_t flag = 0;
244 
245  ret = pcre_exec(subject_parse_regex, subject_parse_regex_study, str, strlen(str), 0, 0,
246  ov, MAX_SUBSTRINGS);
247 
248  if (ret != 2) {
249  SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.subject option");
250  goto error;
251  }
252 
253  if (negate)
254  flag = DETECT_CONTENT_NEGATED;
255 
256  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
257  if (res < 0) {
258  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
259  goto error;
260  }
261 
262  /* We have a correct id option */
263  tls = SCMalloc(sizeof(DetectTlsData));
264  if (unlikely(tls == NULL))
265  goto error;
266  tls->subject = NULL;
267  tls->flags = flag;
268 
269  orig = SCStrdup((char*)str_ptr);
270  if (unlikely(orig == NULL)) {
271  goto error;
272  }
273  pcre_free_substring(str_ptr);
274 
275  tmp_str=orig;
276 
277  /* Let's see if we need to escape "'s */
278  if (tmp_str[0] == '"') {
279  tmp_str[strlen(tmp_str) - 1] = '\0';
280  tmp_str += 1;
281  }
282 
283  tls->subject = SCStrdup(tmp_str);
284  if (unlikely(tls->subject == NULL)) {
285  goto error;
286  }
287 
288  SCFree(orig);
289 
290  SCLogDebug("will look for TLS subject %s", tls->subject);
291 
292  return tls;
293 
294 error:
295  if (orig != NULL)
296  SCFree(orig);
297  if (tls != NULL)
298  DetectTlsSubjectFree(tls);
299  return NULL;
300 
301 }
302 
303 /**
304  * \brief this function is used to add the parsed "id" option
305  * \brief into the current signature
306  *
307  * \param de_ctx pointer to the Detection Engine Context
308  * \param s pointer to the Current Signature
309  * \param idstr pointer to the user provided "id" option
310  *
311  * \retval 0 on Success
312  * \retval -1 on Failure
313  */
314 static int DetectTlsSubjectSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
315 {
316  DetectTlsData *tls = NULL;
317  SigMatch *sm = NULL;
318 
320  return -1;
321 
322  tls = DetectTlsSubjectParse(str, s->init_data->negated);
323  if (tls == NULL)
324  goto error;
325 
326  /* Okay so far so good, lets get this into a SigMatch
327  * and put it in the Signature. */
328  sm = SigMatchAlloc();
329  if (sm == NULL)
330  goto error;
331 
333  sm->ctx = (void *)tls;
334 
335  SigMatchAppendSMToList(s, sm, g_tls_cert_list_id);
336  return 0;
337 
338 error:
339  if (tls != NULL)
340  DetectTlsSubjectFree(tls);
341  if (sm != NULL)
342  SCFree(sm);
343  return -1;
344 
345 }
346 
347 /**
348  * \brief this function will free memory associated with DetectTlsData
349  *
350  * \param id_d pointer to DetectTlsData
351  */
352 static void DetectTlsSubjectFree(void *ptr)
353 {
354  DetectTlsData *id_d = (DetectTlsData *)ptr;
355  if (ptr == NULL)
356  return;
357  if (id_d->subject != NULL)
358  SCFree(id_d->subject);
359  SCFree(id_d);
360 }
361 
362 /**
363  * \brief this function registers unit tests for DetectTlsSubject
364  */
365 static void DetectTlsSubjectRegisterTests(void)
366 {
367 }
368 
369 /**
370  * \brief match the specified IssuerDN on a tls session
371  *
372  * \param t pointer to thread vars
373  * \param det_ctx pointer to the pattern matcher thread
374  * \param p pointer to the current packet
375  * \param m pointer to the sigmatch that we will cast into DetectTlsData
376  *
377  * \retval 0 no match
378  * \retval 1 match
379  */
380 static int DetectTlsIssuerDNMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
381  Flow *f, uint8_t flags, void *state, void *txv,
382  const Signature *s, const SigMatchCtx *m)
383 {
384  SCEnter();
385 
386  const DetectTlsData *tls_data = (const DetectTlsData *)m;
387  SSLState *ssl_state = (SSLState *)state;
388  if (ssl_state == NULL) {
389  SCLogDebug("no tls state, no match");
390  SCReturnInt(0);
391  }
392 
393  int ret = 0;
394 
395  SSLStateConnp *connp = NULL;
396  if (flags & STREAM_TOSERVER) {
397  connp = &ssl_state->client_connp;
398  } else {
399  connp = &ssl_state->server_connp;
400  }
401 
402  if (connp->cert0_issuerdn != NULL) {
403  SCLogDebug("TLS: IssuerDN is [%s], looking for [%s]\n",
404  connp->cert0_issuerdn, tls_data->issuerdn);
405 
406  if (strstr(connp->cert0_issuerdn, tls_data->issuerdn) != NULL) {
407  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
408  ret = 0;
409  } else {
410  ret = 1;
411  }
412  } else {
413  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
414  ret = 1;
415  } else {
416  ret = 0;
417  }
418  }
419  } else {
420  ret = 0;
421  }
422 
423  SCReturnInt(ret);
424 }
425 
426 /**
427  * \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
428  *
429  * \param idstr Pointer to the user provided id option
430  *
431  * \retval id_d pointer to DetectTlsData on success
432  * \retval NULL on failure
433  */
434 static DetectTlsData *DetectTlsIssuerDNParse(const char *str, bool negate)
435 {
436  DetectTlsData *tls = NULL;
437 #define MAX_SUBSTRINGS 30
438  int ret = 0, res = 0;
439  int ov[MAX_SUBSTRINGS];
440  const char *str_ptr;
441  char *orig = NULL;
442  char *tmp_str;
443  uint32_t flag = 0;
444 
445  ret = pcre_exec(issuerdn_parse_regex, issuerdn_parse_regex_study, str, strlen(str), 0, 0,
446  ov, MAX_SUBSTRINGS);
447  if (ret != 2) {
448  SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.issuerdn option");
449  goto error;
450  }
451 
452  if (negate)
453  flag = DETECT_CONTENT_NEGATED;
454 
455  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
456  if (res < 0) {
457  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
458  goto error;
459  }
460 
461  /* We have a correct id option */
462  tls = SCMalloc(sizeof(DetectTlsData));
463  if (unlikely(tls == NULL))
464  goto error;
465  tls->issuerdn = NULL;
466  tls->flags = flag;
467 
468  orig = SCStrdup((char*)str_ptr);
469  if (unlikely(orig == NULL)) {
470  goto error;
471  }
472  pcre_free_substring(str_ptr);
473 
474  tmp_str=orig;
475 
476  /* Let's see if we need to escape "'s */
477  if (tmp_str[0] == '"')
478  {
479  tmp_str[strlen(tmp_str) - 1] = '\0';
480  tmp_str += 1;
481  }
482 
483  tls->issuerdn = SCStrdup(tmp_str);
484  if (unlikely(tls->issuerdn == NULL)) {
485  goto error;
486  }
487 
488  SCFree(orig);
489 
490  SCLogDebug("Will look for TLS issuerdn %s", tls->issuerdn);
491 
492  return tls;
493 
494 error:
495  if (orig != NULL)
496  SCFree(orig);
497  if (tls != NULL)
498  DetectTlsIssuerDNFree(tls);
499  return NULL;
500 
501 }
502 
503 /**
504  * \brief this function is used to add the parsed "id" option
505  * \brief into the current signature
506  *
507  * \param de_ctx pointer to the Detection Engine Context
508  * \param s pointer to the Current Signature
509  * \param idstr pointer to the user provided "id" option
510  *
511  * \retval 0 on Success
512  * \retval -1 on Failure
513  */
514 static int DetectTlsIssuerDNSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
515 {
516  DetectTlsData *tls = NULL;
517  SigMatch *sm = NULL;
518 
520  return -1;
521 
522  tls = DetectTlsIssuerDNParse(str, s->init_data->negated);
523  if (tls == NULL)
524  goto error;
525 
526  /* Okay so far so good, lets get this into a SigMatch
527  * and put it in the Signature. */
528  sm = SigMatchAlloc();
529  if (sm == NULL)
530  goto error;
531 
533  sm->ctx = (void *)tls;
534 
535  SigMatchAppendSMToList(s, sm, g_tls_cert_list_id);
536  return 0;
537 
538 error:
539  if (tls != NULL)
540  DetectTlsIssuerDNFree(tls);
541  if (sm != NULL)
542  SCFree(sm);
543  return -1;
544 
545 }
546 
547 /**
548  * \brief this function will free memory associated with DetectTlsData
549  *
550  * \param id_d pointer to DetectTlsData
551  */
552 static void DetectTlsIssuerDNFree(void *ptr)
553 {
554  DetectTlsData *id_d = (DetectTlsData *)ptr;
555  SCFree(id_d->issuerdn);
556  SCFree(id_d);
557 }
558 
559 /**
560  * \brief This function is used to parse fingerprint passed via keyword: "fingerprint"
561  *
562  * \param idstr Pointer to the user provided fingerprint option
563  *
564  * \retval pointer to DetectTlsData on success
565  * \retval NULL on failure
566  */
567 static DetectTlsData *DetectTlsFingerprintParse (const char *str, bool negate)
568 {
569  DetectTlsData *tls = NULL;
570 #define MAX_SUBSTRINGS 30
571  int ret = 0, res = 0;
572  int ov[MAX_SUBSTRINGS];
573  const char *str_ptr;
574  char *orig;
575  char *tmp_str;
576  uint32_t flag = 0;
577 
578  ret = pcre_exec(fingerprint_parse_regex, fingerprint_parse_regex_study, str, strlen(str), 0, 0,
579  ov, MAX_SUBSTRINGS);
580  if (ret != 2) {
581  SCLogError(SC_ERR_PCRE_MATCH, "invalid tls.fingerprint option");
582  goto error;
583  }
584 
585  if (negate)
586  flag = DETECT_CONTENT_NEGATED;
587 
588  res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
589  if (res < 0) {
590  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed");
591  goto error;
592  }
593 
594  /* We have a correct id option */
595  tls = SCMalloc(sizeof(DetectTlsData));
596  if (unlikely(tls == NULL))
597  goto error;
598  tls->fingerprint = NULL;
599  tls->flags = flag;
600 
601  orig = SCStrdup((char*)str_ptr);
602  if (unlikely(orig == NULL)) {
603  goto error;
604  }
605  pcre_free_substring(str_ptr);
606 
607  tmp_str=orig;
608 
609  /* Let's see if we need to escape "'s */
610  if (tmp_str[0] == '"')
611  {
612  tmp_str[strlen(tmp_str) - 1] = '\0';
613  tmp_str += 1;
614  }
615 
616  tls->fingerprint = SCStrdup(tmp_str);
617  if (tls->fingerprint == NULL) {
618  SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate fingerprint");
619  }
620 
621  SCFree(orig);
622 
623  SCLogDebug("will look for TLS fingerprint %s", tls->fingerprint);
624 
625  return tls;
626 
627 error:
628  if (tls != NULL)
629  DetectTlsFingerprintFree(tls);
630  return NULL;
631 
632 }
633 /**
634  * \brief match the specified fingerprint on a tls session
635  *
636  * \param t pointer to thread vars
637  * \param det_ctx pointer to the pattern matcher thread
638  * \param p pointer to the current packet
639  * \param m pointer to the sigmatch that we will cast into DetectTlsData
640  *
641  * \retval 0 no match
642  * \retval 1 match
643  */
644 static int DetectTlsFingerprintMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
645  Flow *f, uint8_t flags, void *state, void *txv,
646  const Signature *s, const SigMatchCtx *m)
647 {
648  SCEnter();
649  const DetectTlsData *tls_data = (const DetectTlsData *)m;
650  SSLState *ssl_state = (SSLState *)state;
651  if (ssl_state == NULL) {
652  SCLogDebug("no tls state, no match");
653  SCReturnInt(0);
654  }
655 
656  int ret = 0;
657 
658  SSLStateConnp *connp = NULL;
659  if (flags & STREAM_TOSERVER) {
660  connp = &ssl_state->client_connp;
661  } else {
662  connp = &ssl_state->server_connp;
663  }
664 
665  if (connp->cert0_fingerprint != NULL) {
666  SCLogDebug("TLS: Fingerprint is [%s], looking for [%s]\n",
667  connp->cert0_fingerprint,
668  tls_data->fingerprint);
669 
670  if (tls_data->fingerprint &&
671  (strstr(connp->cert0_fingerprint,
672  tls_data->fingerprint) != NULL)) {
673  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
674  ret = 0;
675  } else {
676  ret = 1;
677 
678  }
679  } else {
680  if (tls_data->flags & DETECT_CONTENT_NEGATED) {
681  ret = 1;
682  } else {
683  ret = 0;
684  }
685  }
686  } else {
687  ret = 0;
688  }
689 
690  SCReturnInt(ret);
691 }
692 
693 /**
694  * \brief this function is used to add the parsed "fingerprint" option
695  * \brief into the current signature
696  *
697  * \param de_ctx pointer to the Detection Engine Context
698  * \param s pointer to the Current Signature
699  * \param id pointer to the user provided "fingerprint" option
700  *
701  * \retval 0 on Success
702  * \retval -1 on Failure
703  */
704 static int DetectTlsFingerprintSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
705 {
706  DetectTlsData *tls = NULL;
707  SigMatch *sm = NULL;
708 
710  return -1;
711 
712  tls = DetectTlsFingerprintParse(str, s->init_data->negated);
713  if (tls == NULL)
714  goto error;
715 
716  /* Okay so far so good, lets get this into a SigMatch
717  * and put it in the Signature. */
718  sm = SigMatchAlloc();
719  if (sm == NULL)
720  goto error;
721 
723  sm->ctx = (void *)tls;
724 
725  SigMatchAppendSMToList(s, sm, g_tls_cert_list_id);
726  return 0;
727 
728 error:
729  if (tls != NULL)
730  DetectTlsFingerprintFree(tls);
731  if (sm != NULL)
732  SCFree(sm);
733  return -1;
734 
735 }
736 
737 /**
738  * \brief this function will free memory associated with DetectTlsData
739  *
740  * \param pointer to DetectTlsData
741  */
742 static void DetectTlsFingerprintFree(void *ptr)
743 {
744  DetectTlsData *id_d = (DetectTlsData *)ptr;
745  if (id_d->fingerprint)
746  SCFree(id_d->fingerprint);
747  SCFree(id_d);
748 }
749 
750 /**
751  * \brief this function is used to add the parsed "store" option
752  * \brief into the current signature
753  *
754  * \param de_ctx pointer to the Detection Engine Context
755  * \param s pointer to the Current Signature
756  * \param idstr pointer to the user provided "store" option
757  *
758  * \retval 0 on Success
759  * \retval -1 on Failure
760  */
761 static int DetectTlsStoreSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
762 {
763  SigMatch *sm = NULL;
764 
766  return -1;
767 
768  sm = SigMatchAlloc();
769  if (sm == NULL)
770  return -1;
771 
773  s->flags |= SIG_FLAG_TLSSTORE;
774 
776  return 0;
777 }
778 
779 /** \warning modifies Flow::alstate */
780 static int DetectTlsStorePostMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
781  Packet *p, const Signature *s, const SigMatchCtx *unused)
782 {
783  SCEnter();
784 
785  if (p->flow == NULL)
786  return 0;
787 
788  SSLState *ssl_state = FlowGetAppState(p->flow);
789  if (ssl_state == NULL) {
790  SCLogDebug("no tls state, no match");
791  SCReturnInt(0);
792  }
793 
795  SCReturnInt(1);
796 }
797 
798 
799 /**
800  * \brief this function registers unit tests for DetectTlsIssuerDN
801  */
802 static void DetectTlsIssuerDNRegisterTests(void)
803 {
804 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1406
SignatureInitData * init_data
Definition: detect.h:563
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1149
int(* AppLayerTxMatch)(ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1135
char * cert0_subject
#define SCLogDebug(...)
Definition: util-debug.h:335
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
struct Flow_ * flow
Definition: decode.h:443
uint32_t flags
Definition: detect.h:496
#define MAX_SUBSTRINGS
#define unlikely(expr)
Definition: util-optimize.h:35
char * cert0_fingerprint
SSLStateConnp server_connp
Data needed for Match()
Definition: detect.h:331
#define SIG_FLAG_TLSSTORE
Definition: detect.h:244
const char * name
Definition: detect.h:1163
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:495
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:317
main detection engine ctx
Definition: detect.h:723
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:242
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1154
#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:1347
#define SCEnter(...)
Definition: util-debug.h:337
char * subject
Definition: detect-tls.h:40
uint8_t type
Definition: detect.h:323
#define SCReturnInt(x)
Definition: util-debug.h:341
#define SSL_TLS_LOG_PEM
const char * desc
Definition: detect.h:1165
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:288
int DetectBufferTypeRegister(const char *name)
SigMatchCtx * ctx
Definition: detect.h:325
const char * alias
Definition: detect.h:1164
#define SCMalloc(a)
Definition: util-mem.h:166
#define DETECT_CONTENT_NEGATED
char * fingerprint
Definition: detect-tls.h:42
#define SCFree(a)
Definition: util-mem.h:228
PoolThreadReserved res
uint32_t cert_log_flag
uint16_t tx_id
#define SIGMATCH_NOOPT
Definition: detect.h:1331
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1132
void DetectTlsRegister(void)
Registration function for keyword: tls.version.
Definition: detect-tls.c:116
const char * url
Definition: detect.h:1166
#define STREAM_TOSERVER
Definition: stream.h:31
SCMutex m
Definition: flow-hash.h:105
void * FlowGetAppState(const Flow *f)
Definition: flow.c:1065
#define SCStrdup(a)
Definition: util-mem.h:212
#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:1351
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1157
#define PARSE_REGEX
Regex for parsing "id" option, matching number or "number".
Definition: detect-tls.c:67
Flow data structure.
Definition: flow.h:324
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:1155
a single match condition for a signature
Definition: detect.h:322
char * cert0_issuerdn