text: /* Copyright (C) 2007-2016 Open Information Security Foundation
   *
   * You can copy, redistribute or modify this Program under the terms of
   * the GNU General Public License version 2 as published by the Free
   * Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * version 2 along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301, USA.
   */
  
  /**
   * \ingroup httplayer
   *
   * @{
   */
  
  
  /** \file
   *
   * \author Anoop Saldanha <anoopsaldanha@gmail.com>
   * \author Victor Julien <victor@inliniac.net>
   *
   * \brief Handle HTTP host header.
   *        HHHD - Http Host Header Data
   *
   */
  
  #include "suricata-common.h"
  #include "suricata.h"
  #include "decode.h"
  
  #include "detect.h"
  #include "detect-engine.h"
  #include "detect-engine-mpm.h"
  #include "detect-parse.h"
  #include "detect-engine-state.h"
  #include "detect-engine-content-inspection.h"
  #include "detect-engine-prefilter.h"
  
  #include "flow-util.h"
  #include "util-debug.h"
  #include "util-print.h"
  #include "flow.h"
  
  #include "stream-tcp.h"
  
  #include "app-layer-parser.h"
  
  #include "util-unittest.h"
  #include "util-unittest-helper.h"
  #include "app-layer.h"
  #include "app-layer-htp.h"
  #include "app-layer-protos.h"
  
  #include "detect-engine-hhhd.h"
  #include "util-validate.h"
  
  /** \brief HTTP Host Mpm prefilter callback
   *
   *  \param det_ctx detection engine thread ctx
   *  \param p packet to inspect
   *  \param f flow to inspect
   *  \param txv tx to inspect
   *  \param pectx inspection context
   */
  static void PrefilterTxHostname(DetectEngineThreadCtx *det_ctx,
          const void *pectx,
          Packet *p, Flow *f, void *txv,
          const uint64_t idx, const uint8_t flags)
  {
      SCEnter();
  
      const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
      htp_tx_t *tx = (htp_tx_t *)txv;
  
      if (tx->request_hostname == NULL)
          return;
  
      const uint32_t buffer_len = bstr_len(tx->request_hostname);
      const uint8_t *buffer = bstr_ptr(tx->request_hostname);
  
      if (buffer_len >= mpm_ctx->minlen) {
          (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
                  &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
      }
  }
  
  int PrefilterTxHostnameRegister(SigGroupHead *sgh, MpmCtx *mpm_ctx)
  {
      SCEnter();
  
      return PrefilterAppendTxEngine(sgh, PrefilterTxHostname,
          ALPROTO_HTTP, HTP_REQUEST_HEADERS,
          mpm_ctx, NULL, "http_host");
  }
  
  /**
   * \brief Do the http_header content inspection for a signature.
   *
   * \param de_ctx  Detection engine context.
   * \param det_ctx Detection engine thread context.
   * \param s       Signature to inspect.
   * \param f       Flow.
   * \param flags   App layer flags.
   * \param state   App layer state.
   *
   * \retval 0 No match.
   * \retval 1 Match.
   */
  int DetectEngineInspectHttpHH(ThreadVars *tv,
                                DetectEngineCtx *de_ctx,
                                DetectEngineThreadCtx *det_ctx,
                                Signature *s, Flow *f, uint8_t flags,
                                void *alstate,
                                void *txv, uint64_t tx_id)
  {
      htp_tx_t *tx = (htp_tx_t *)txv;
      if (tx->parsed_uri == NULL || tx->request_hostname == NULL)
          goto end;
      uint8_t *hname = (uint8_t *)bstr_ptr(tx->request_hostname);
      if (hname == NULL)
          goto end;
      uint32_t hname_len = bstr_len(tx->request_hostname);
  
      det_ctx->buffer_offset = 0;
      det_ctx->discontinue_matching = 0;
      det_ctx->inspection_recursion_counter = 0;
      int r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HHHDMATCH],
                                            f,
                                            hname, hname_len,
                                            0,
                                            DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE, NULL);
      if (r == 1)
          return DETECT_ENGINE_INSPECT_SIG_MATCH;
  
   end:
      if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
          return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
      else
          return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
  }
  
  /***********************************Unittests**********************************/
  
  #ifdef UNITTESTS
  
  /**
   * \test Test that the http_host content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest01(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:\"connect\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!(PacketAlertCheck(p, 1))) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest02(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:\"co\"; depth:4; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!(PacketAlertCheck(p, 1))) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest03(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:!\"ect\"; depth:4; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!(PacketAlertCheck(p, 1))) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest04(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:\"ect\"; depth:4; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest05(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:!\"con\"; depth:4; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest06(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:\"ect\"; offset:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!(PacketAlertCheck(p, 1))) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest07(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:!\"co\"; offset:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!(PacketAlertCheck(p, 1))) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest08(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:!\"ect\"; offset:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest09(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http host header test\"; "
                                 "content:\"con\"; offset:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest10(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:\"ec\"; within:4; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest11(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:!\"ec\"; within:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest12(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:\"ec\"; within:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest13(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:!\"ec\"; within:4; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest14(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:\"ec\"; distance:2; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest15(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:!\"ec\"; distance:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest16(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:\"ec\"; distance:3; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  /**
   * \test Test that the http_host header content matches against a http request
   *       which holds the content.
   */
  static int DetectEngineHttpHHTest17(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: CONNECT\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"co\"; http_host;  "
                                 "content:!\"ec\"; distance:2; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest18(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: www.kaboom.com\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"kaboom\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest19(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: www.kaboom.com:8080\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"kaboom\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest20(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET /index.html HTTP/1.0\r\n"
          "Host: www.kaboom.com:8080\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"8080\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but it shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest21(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET http://www.kaboom.com/index.html HTTP/1.0\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"kaboom\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest22(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"kaboom\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest23(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"8080\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but it shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest24(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
          "Host: www.rabbit.com\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"kaboom\"; http_host;  "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (!PacketAlertCheck(p, 1)) {
          printf("sid 1 didn't match but it should have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  static int DetectEngineHttpHHTest25(void)
  {
      TcpSession ssn;
      Packet *p = NULL;
      ThreadVars th_v;
      DetectEngineCtx *de_ctx = NULL;
      DetectEngineThreadCtx *det_ctx = NULL;
      HtpState *http_state = NULL;
      Flow f;
      uint8_t http_buf[] =
          "GET http://www.kaboom.com:8080/index.html HTTP/1.0\r\n"
          "Host: www.rabbit.com\r\n"
          "User-Agent: www.onetwothreefourfivesixseven.org\r\n\r\n";
      uint32_t http_len = sizeof(http_buf) - 1;
      int result = 0;
      AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
  
      memset(&th_v, 0, sizeof(th_v));
      memset(&f, 0, sizeof(f));
      memset(&ssn, 0, sizeof(ssn));
  
      p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
  
      FLOW_INITIALIZE(&f);
      f.protoctx = (void *)&ssn;
      f.proto = IPPROTO_TCP;
      f.flags |= FLOW_IPV4;
      p->flow = &f;
      p->flowflags |= FLOW_PKT_TOSERVER;
      p->flowflags |= FLOW_PKT_ESTABLISHED;
      p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
      f.alproto = ALPROTO_HTTP;
  
      StreamTcpInitConfig(TRUE);
  
      de_ctx = DetectEngineCtxInit();
      if (de_ctx == NULL)
          goto end;
  
      de_ctx->flags |= DE_QUIET;
  
      de_ctx->sig_list = SigInit(de_ctx,"alert http any any -> any any "
                                 "(msg:\"http_host header test\"; "
                                 "content:\"rabbit\"; http_host; "
                                 "sid:1;)");
      if (de_ctx->sig_list == NULL)
          goto end;
  
      SigGroupBuild(de_ctx);
      DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
  
      FLOWLOCK_WRLOCK(&f);
      int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
                                  STREAM_TOSERVER, http_buf, http_len);
      if (r != 0) {
          printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
          result = 0;
          FLOWLOCK_UNLOCK(&f);
          goto end;
      }
      FLOWLOCK_UNLOCK(&f);
  
      http_state = f.alstate;
      if (http_state == NULL) {
          printf("no http state: ");
          result = 0;
          goto end;
      }
  
      /* do detect */
      SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
  
      if (PacketAlertCheck(p, 1)) {
          printf("sid 1 matched but it shouldn't have: ");
          goto end;
      }
  
      result = 1;
  
  end:
      if (alp_tctx != NULL)
          AppLayerParserThreadCtxFree(alp_tctx);
      if (de_ctx != NULL)
          SigGroupCleanup(de_ctx);
      if (de_ctx != NULL)
          SigCleanSignatures(de_ctx);
      if (de_ctx != NULL)
          DetectEngineCtxFree(de_ctx);
  
      StreamTcpFreeConfig(TRUE);
      FLOW_DESTROY(&f);
      UTHFreePackets(&p, 1);
      return result;
  }
  
  #endif /* UNITTESTS */
  
  void DetectEngineHttpHHRegisterTests(void)
  {
  
  #ifdef UNITTESTS
      UtRegisterTest("DetectEngineHttpHHTest01", DetectEngineHttpHHTest01);
      UtRegisterTest("DetectEngineHttpHHTest02", DetectEngineHttpHHTest02);
      UtRegisterTest("DetectEngineHttpHHTest03", DetectEngineHttpHHTest03);
      UtRegisterTest("DetectEngineHttpHHTest04", DetectEngineHttpHHTest04);
      UtRegisterTest("DetectEngineHttpHHTest05", DetectEngineHttpHHTest05);
      UtRegisterTest("DetectEngineHttpHHTest06", DetectEngineHttpHHTest06);
      UtRegisterTest("DetectEngineHttpHHTest07", DetectEngineHttpHHTest07);
      UtRegisterTest("DetectEngineHttpHHTest08", DetectEngineHttpHHTest08);
      UtRegisterTest("DetectEngineHttpHHTest09", DetectEngineHttpHHTest09);
      UtRegisterTest("DetectEngineHttpHHTest10", DetectEngineHttpHHTest10);
      UtRegisterTest("DetectEngineHttpHHTest11", DetectEngineHttpHHTest11);
      UtRegisterTest("DetectEngineHttpHHTest12", DetectEngineHttpHHTest12);
      UtRegisterTest("DetectEngineHttpHHTest13", DetectEngineHttpHHTest13);
      UtRegisterTest("DetectEngineHttpHHTest14", DetectEngineHttpHHTest14);
      UtRegisterTest("DetectEngineHttpHHTest15", DetectEngineHttpHHTest15);
      UtRegisterTest("DetectEngineHttpHHTest16", DetectEngineHttpHHTest16);
      UtRegisterTest("DetectEngineHttpHHTest17", DetectEngineHttpHHTest17);
      UtRegisterTest("DetectEngineHttpHHTest18", DetectEngineHttpHHTest18);
      UtRegisterTest("DetectEngineHttpHHTest19", DetectEngineHttpHHTest19);
      UtRegisterTest("DetectEngineHttpHHTest20", DetectEngineHttpHHTest20);
      UtRegisterTest("DetectEngineHttpHHTest21", DetectEngineHttpHHTest21);
      UtRegisterTest("DetectEngineHttpHHTest22", DetectEngineHttpHHTest22);
      UtRegisterTest("DetectEngineHttpHHTest23", DetectEngineHttpHHTest23);
      UtRegisterTest("DetectEngineHttpHHTest24", DetectEngineHttpHHTest24);
      UtRegisterTest("DetectEngineHttpHHTest25", DetectEngineHttpHHTest25);
  #endif /* UNITTESTS */
  
      return;
  }
  /**
   * @}
   */
  