1 //--------------------------------------------------------------------------
2 // Copyright (C) 2015-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 // ips_http.cc author Tom Peters <thopeter@cisco.com>
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "ips_http.h"
25 
26 #include "framework/cursor.h"
27 #include "hash/hash_key_operations.h"
28 #include "log/messages.h"
29 #include "parser/parse_utils.h"
30 #include "protocols/packet.h"
31 #include "service_inspectors/http2_inspect/http2_flow_data.h"
32 
33 #include "http_common.h"
34 #include "http_enum.h"
35 #include "http_flow_data.h"
36 #include "http_inspect.h"
37 #include "http_msg_head_shared.h"
38 #include "http_param.h"
39 
40 using namespace snort;
41 using namespace HttpCommon;
42 using namespace HttpEnums;
43 
44 THREAD_LOCAL std::array<ProfileStats, PSI_MAX> HttpRuleOptModule::http_ps;
45 
46 const std::string hdrs_num_range = "0:" + std::to_string(HttpMsgHeadShared::MAX_HEADERS);
47 
begin(const char *,int,SnortConfig *)48 bool HttpRuleOptModule::begin(const char*, int, SnortConfig*)
49 {
50     para_list.reset();
51     sub_id = 0;
52     form = 0;
53     switch (rule_opt_index)
54     {
55     case HTTP_BUFFER_RAW_STATUS:
56     case HTTP_BUFFER_STAT_CODE:
57     case HTTP_BUFFER_STAT_MSG:
58         inspect_section = IS_HEADER;
59         break;
60     case HTTP_BUFFER_COOKIE:
61     case HTTP_BUFFER_HEADER:
62     case HTTP_BUFFER_METHOD:
63     case HTTP_BUFFER_PARAM:
64     case HTTP_BUFFER_RAW_COOKIE:
65     case HTTP_BUFFER_RAW_HEADER:
66     case HTTP_BUFFER_RAW_REQUEST:
67     case HTTP_BUFFER_RAW_URI:
68     case HTTP_BUFFER_TRUE_IP:
69     case HTTP_BUFFER_URI:
70     case HTTP_BUFFER_VERSION:
71     case HTTP_RANGE_NUM_HDRS:
72         inspect_section = IS_FLEX_HEADER;
73         break;
74     case HTTP_BUFFER_CLIENT_BODY:
75     case HTTP_BUFFER_RAW_BODY:
76     case BUFFER_JS_DATA:
77         inspect_section = IS_BODY;
78         break;
79     case HTTP_BUFFER_RAW_TRAILER:
80     case HTTP_BUFFER_TRAILER:
81     case HTTP_RANGE_NUM_TRAILERS:
82         inspect_section = IS_TRAILER;
83         break;
84     default:
85         assert(false);
86     }
87     return true;
88 }
89 
set(const char *,Value & v,SnortConfig *)90 bool HttpRuleOptModule::set(const char*, Value& v, SnortConfig*)
91 {
92     if (v.is("field"))
93     {
94         if (sub_id != 0)
95             ParseError("Only specify one header field to match");
96         para_list.field = v.get_string();
97         const int32_t name_size = (para_list.field.size() <= MAX_FIELD_NAME_LENGTH) ?
98             para_list.field.size() : MAX_FIELD_NAME_LENGTH;
99         uint8_t lower_name[MAX_FIELD_NAME_LENGTH];
100         for (int32_t k=0; k < name_size; k++)
101         {
102             lower_name[k] = ((para_list.field[k] < 'A') || (para_list.field[k] > 'Z')) ?
103                 para_list.field[k] : para_list.field[k] - ('A' - 'a');
104         }
105         sub_id = str_to_code(lower_name, name_size, HttpMsgHeadShared::header_list);
106         if (sub_id == STAT_OTHER)
107             ParseError("Unrecognized header field name");
108     }
109     else if (v.is("~param"))
110     {
111         std::string bc = v.get_string();
112         bool negated = false;
113         if (!parse_byte_code(bc.c_str(), negated, para_list.param) or negated)
114             ParseError("Invalid http_param");
115     }
116     else if (v.is("nocase"))
117     {
118         para_list.nocase = true;
119     }
120     else if (v.is("request"))
121     {
122         para_list.request = true;
123         form |= FORM_REQUEST;
124     }
125     else if (v.is("with_header"))
126     {
127         para_list.with_header = true;
128         inspect_section = IS_HEADER;
129     }
130     else if (v.is("with_body"))
131     {
132         para_list.with_body = true;
133         inspect_section = IS_BODY;
134     }
135     else if (v.is("with_trailer"))
136     {
137         para_list.with_trailer = true;
138         inspect_section = IS_TRAILER;
139     }
140     else if (v.is("scheme"))
141     {
142         para_list.scheme = true;
143         sub_id = UC_SCHEME;
144     }
145     else if (v.is("host"))
146     {
147         para_list.host = true;
148         sub_id = UC_HOST;
149     }
150     else if (v.is("port"))
151     {
152         para_list.port = true;
153         sub_id = UC_PORT;
154     }
155     else if (v.is("path"))
156     {
157         para_list.path = true;
158         sub_id = UC_PATH;
159     }
160     else if (v.is("query"))
161     {
162         para_list.query = true;
163         sub_id = UC_QUERY;
164     }
165     else if (v.is("fragment"))
166     {
167         para_list.fragment = true;
168         sub_id = UC_FRAGMENT;
169     }
170     else if (v.is("~range"))
171     {
172         return para_list.range.validate(v.get_string(), hdrs_num_range.c_str());
173     }
174     return true;
175 }
176 
end(const char *,int,SnortConfig *)177 bool HttpRuleOptModule::end(const char*, int, SnortConfig*)
178 {
179     // Check for option conflicts
180     if (para_list.with_header + para_list.with_body + para_list.with_trailer > 1)
181         ParseError("Only specify one with_ option. Use the one that happens last.");
182     if (((rule_opt_index == HTTP_BUFFER_TRAILER) || (rule_opt_index == HTTP_BUFFER_RAW_TRAILER) || (rule_opt_index == HTTP_RANGE_NUM_TRAILERS)) &&
183         (para_list.with_header || para_list.with_body) &&
184         !para_list.request)
185         ParseError("Trailers with with_ option must also specify request");
186     if (para_list.scheme + para_list.host + para_list.port + para_list.path + para_list.query +
187           para_list.fragment > 1)
188         ParseError("Only specify one part of the URI");
189     if (rule_opt_index == HTTP_BUFFER_PARAM && para_list.param.length() == 0)
190         ParseError("Specify parameter name");
191     return true;
192 }
193 
reset()194 void HttpRuleOptModule::HttpRuleParaList::reset()
195 {
196     field.clear();
197     param.clear();
198     nocase = false;
199     request = false;
200     with_header = false;
201     with_body = false;
202     with_trailer = false;
203     scheme = false;
204     host = false;
205     port = false;
206     path = false;
207     query = false;
208     fragment = false;
209     range.init();
210 }
211 
hash() const212 uint32_t HttpIpsOption::hash() const
213 {
214     uint32_t a = IpsOption::hash();
215     uint32_t b = (uint32_t)inspect_section;
216     uint32_t c = buffer_info.hash();
217     mix(a,b,c);
218     a += range.hash();
219     finalize(a,b,c);
220     return c;
221 }
222 
operator ==(const IpsOption & ips) const223 bool HttpIpsOption::operator==(const IpsOption& ips) const
224 {
225     const HttpIpsOption& hio = static_cast<const HttpIpsOption&>(ips);
226     return IpsOption::operator==(ips) &&
227            inspect_section == hio.inspect_section &&
228            buffer_info == hio.buffer_info &&
229            range == hio.range;
230 }
231 
retry(Cursor & current_cursor,const Cursor &)232 bool HttpIpsOption::retry(Cursor& current_cursor, const Cursor&)
233 {
234     if (buffer_info.type == HTTP_BUFFER_PARAM)
235     {
236         HttpCursorData* cd = (HttpCursorData*)current_cursor.get_data(HttpCursorData::id);
237 
238         if (cd)
239             return cd->retry();
240     }
241     return false;
242 }
243 
eval(Cursor & c,Packet * p)244 IpsOption::EvalStatus HttpIpsOption::eval(Cursor& c, Packet* p)
245 {
246     RuleProfile profile(HttpRuleOptModule::http_ps[psi]);
247 
248     if (!p->flow || !p->flow->gadget || (HttpInspect::get_latest_is(p) == IS_NONE))
249         return NO_MATCH;
250 
251     const bool section_match =
252         (HttpInspect::get_latest_is(p) == inspect_section) ||
253         ((HttpInspect::get_latest_is(p) == IS_HEADER) && (inspect_section == IS_FLEX_HEADER)) ||
254         ((HttpInspect::get_latest_is(p) == IS_FIRST_BODY) && (inspect_section == IS_BODY)) ||
255         ((HttpInspect::get_latest_src(p) == SRC_CLIENT) && (inspect_section == IS_FLEX_HEADER));
256     if (!section_match)
257         return NO_MATCH;
258 
259     const Http2FlowData* const h2i_flow_data =
260         (Http2FlowData*)p->flow->get_flow_data(Http2FlowData::inspector_id);
261 
262     const HttpInspect* const hi = (h2i_flow_data != nullptr) ?
263         (HttpInspect*)(p->flow->assistant_gadget) : (HttpInspect*)(p->flow->gadget);
264 
265     if (buffer_info.type <= HTTP_BUFFER_MAX)
266     {
267         const Field& http_buffer = hi->http_get_buf(c, p, buffer_info);
268 
269         if (http_buffer.length() <= 0)
270             return NO_MATCH;
271 
272         c.set(key, http_buffer.start(), http_buffer.length());
273 
274         return MATCH;
275     }
276     else
277     {
278         const int32_t num_lines = hi->http_get_num_headers(p, buffer_info);
279         if (num_lines != HttpCommon::STAT_NOT_PRESENT && range.eval(num_lines))
280             return MATCH;
281 
282         return NO_MATCH;
283     }
284 }
285 
286 //-------------------------------------------------------------------------
287 // http_client_body
288 //-------------------------------------------------------------------------
289 
290 #undef IPS_OPT
291 #define IPS_OPT "http_client_body"
292 #undef IPS_HELP
293 #define IPS_HELP "rule option to set the detection cursor to the request body"
294 
client_body_mod_ctor()295 static Module* client_body_mod_ctor()
296 {
297     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_CLIENT_BODY, CAT_SET_BODY,
298         PSI_CLIENT_BODY);
299 }
300 
301 static const IpsApi client_body_api =
302 {
303     {
304         PT_IPS_OPTION,
305         sizeof(IpsApi),
306         IPSAPI_VERSION,
307         1,
308         API_RESERVED,
309         API_OPTIONS,
310         IPS_OPT,
311         IPS_HELP,
312         client_body_mod_ctor,
313         HttpRuleOptModule::mod_dtor
314     },
315     OPT_TYPE_DETECTION,
316     0, PROTO_BIT__TCP,
317     nullptr,
318     nullptr,
319     nullptr,
320     nullptr,
321     HttpIpsOption::opt_ctor,
322     HttpIpsOption::opt_dtor,
323     nullptr
324 };
325 
326 //-------------------------------------------------------------------------
327 // http_cookie
328 //-------------------------------------------------------------------------
329 
330 static const Parameter http_cookie_params[] =
331 {
332     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
333         "match against the cookie from the request message even when examining the response" },
334     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
335         "this rule is limited to examining HTTP message headers" },
336     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
337         "parts of this rule examine HTTP message body" },
338     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
339         "parts of this rule examine HTTP message trailers" },
340     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
341 };
342 
343 #undef IPS_OPT
344 #define IPS_OPT "http_cookie"
345 #undef IPS_HELP
346 #define IPS_HELP "rule option to set the detection cursor to the HTTP cookie"
347 
cookie_mod_ctor()348 static Module* cookie_mod_ctor()
349 {
350     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_COOKIE, CAT_SET_COOKIE, PSI_COOKIE,
351         http_cookie_params);
352 }
353 
354 static const IpsApi cookie_api =
355 {
356     {
357         PT_IPS_OPTION,
358         sizeof(IpsApi),
359         IPSAPI_VERSION,
360         1,
361         API_RESERVED,
362         API_OPTIONS,
363         IPS_OPT,
364         IPS_HELP,
365         cookie_mod_ctor,
366         HttpRuleOptModule::mod_dtor
367     },
368     OPT_TYPE_DETECTION,
369     0, PROTO_BIT__TCP,
370     nullptr,
371     nullptr,
372     nullptr,
373     nullptr,
374     HttpIpsOption::opt_ctor,
375     HttpIpsOption::opt_dtor,
376     nullptr
377 };
378 
379 //-------------------------------------------------------------------------
380 // http_header
381 //-------------------------------------------------------------------------
382 
383 // FIXIT-M add match_unknown option to look at HEAD__UNKNOWN.
384 
385 // FIXIT-M if http_header is the fast pattern buffer and the content to be
386 // matched appears in the normalized field but not in the raw field
387 // detection will fail.
388 
389 static const Parameter http_header_params[] =
390 {
391     { "field", Parameter::PT_STRING, nullptr, nullptr,
392         "restrict to given header. Header name is case insensitive." },
393     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
394         "match against the headers from the request message even when examining the response" },
395     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
396         "this rule is limited to examining HTTP message headers" },
397     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
398         "parts of this rule examine HTTP message body" },
399     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
400         "parts of this rule examine HTTP message trailers" },
401     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
402 };
403 
404 #undef IPS_OPT
405 #define IPS_OPT "http_header"
406 #undef IPS_HELP
407 #define IPS_HELP "rule option to set the detection cursor to the normalized headers"
408 
header_mod_ctor()409 static Module* header_mod_ctor()
410 {
411     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_HEADER, CAT_SET_HEADER,
412         PSI_HEADER, http_header_params);
413 }
414 
415 static const IpsApi header_api =
416 {
417     {
418         PT_IPS_OPTION,
419         sizeof(IpsApi),
420         IPSAPI_VERSION,
421         1,
422         API_RESERVED,
423         API_OPTIONS,
424         IPS_OPT,
425         IPS_HELP,
426         header_mod_ctor,
427         HttpRuleOptModule::mod_dtor
428     },
429     OPT_TYPE_DETECTION,
430     0, PROTO_BIT__TCP,
431     nullptr,
432     nullptr,
433     nullptr,
434     nullptr,
435     HttpIpsOption::opt_ctor,
436     HttpIpsOption::opt_dtor,
437     nullptr
438 };
439 
440 //-------------------------------------------------------------------------
441 // http_method
442 //-------------------------------------------------------------------------
443 
444 static const Parameter http_method_params[] =
445 {
446     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
447         "this rule is limited to examining HTTP message headers" },
448     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
449         "parts of this rule examine HTTP message body" },
450     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
451         "parts of this rule examine HTTP message trailers" },
452     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
453 };
454 
455 #undef IPS_OPT
456 #define IPS_OPT "http_method"
457 #undef IPS_HELP
458 #define IPS_HELP "rule option to set the detection cursor to the HTTP request method"
459 
method_mod_ctor()460 static Module* method_mod_ctor()
461 {
462     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_METHOD, CAT_SET_METHOD, PSI_METHOD,
463         http_method_params);
464 }
465 
466 static const IpsApi method_api =
467 {
468     {
469         PT_IPS_OPTION,
470         sizeof(IpsApi),
471         IPSAPI_VERSION,
472         1,
473         API_RESERVED,
474         API_OPTIONS,
475         IPS_OPT,
476         IPS_HELP,
477         method_mod_ctor,
478         HttpRuleOptModule::mod_dtor
479     },
480     OPT_TYPE_DETECTION,
481     0, PROTO_BIT__TCP,
482     nullptr,
483     nullptr,
484     nullptr,
485     nullptr,
486     HttpIpsOption::opt_ctor,
487     HttpIpsOption::opt_dtor,
488     nullptr
489 };
490 
491 //-------------------------------------------------------------------------
492 // http_param
493 //-------------------------------------------------------------------------
494 
495 static const Parameter http_param_params[] =
496 {
497     { "~param", Parameter::PT_STRING, nullptr, nullptr,
498         "parameter to match" },
499     { "nocase", Parameter::PT_IMPLIED, nullptr, nullptr,
500         "case insensitive match" },
501     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
502 };
503 
504 #undef IPS_OPT
505 #define IPS_OPT "http_param"
506 #undef IPS_HELP
507 #define IPS_HELP "rule option to set the detection cursor to the value of the specified HTTP parameter key which may be in the query or body"
508 
param_mod_ctor()509 static Module* param_mod_ctor()
510 {
511     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_PARAM, CAT_SET_OTHER, PSI_PARAM,
512         http_param_params);
513 }
514 
515 static const IpsApi param_api =
516 {
517     {
518         PT_IPS_OPTION,
519         sizeof(IpsApi),
520         IPSAPI_VERSION,
521         1,
522         API_RESERVED,
523         API_OPTIONS,
524         IPS_OPT,
525         IPS_HELP,
526         param_mod_ctor,
527         HttpRuleOptModule::mod_dtor
528     },
529     OPT_TYPE_DETECTION,
530     0, PROTO_BIT__TCP,
531     nullptr,
532     nullptr,
533     nullptr,
534     nullptr,
535     HttpIpsOption::opt_ctor,
536     HttpIpsOption::opt_dtor,
537     nullptr
538 };
539 
540 //-------------------------------------------------------------------------
541 // http_raw_body
542 //-------------------------------------------------------------------------
543 
544 #undef IPS_OPT
545 #define IPS_OPT "http_raw_body"
546 #undef IPS_HELP
547 #define IPS_HELP "rule option to set the detection cursor to the unnormalized message body"
548 
raw_body_mod_ctor()549 static Module* raw_body_mod_ctor()
550 {
551     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_BODY, CAT_SET_OTHER,
552         PSI_RAW_BODY);
553 }
554 
555 static const IpsApi raw_body_api =
556 {
557     {
558         PT_IPS_OPTION,
559         sizeof(IpsApi),
560         IPSAPI_VERSION,
561         1,
562         API_RESERVED,
563         API_OPTIONS,
564         IPS_OPT,
565         IPS_HELP,
566         raw_body_mod_ctor,
567         HttpRuleOptModule::mod_dtor
568     },
569     OPT_TYPE_DETECTION,
570     0, PROTO_BIT__TCP,
571     nullptr,
572     nullptr,
573     nullptr,
574     nullptr,
575     HttpIpsOption::opt_ctor,
576     HttpIpsOption::opt_dtor,
577     nullptr
578 };
579 
580 //-------------------------------------------------------------------------
581 // http_raw_cookie
582 //-------------------------------------------------------------------------
583 
584 static const Parameter http_raw_cookie_params[] =
585 {
586     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
587         "match against the cookie from the request message even when examining the response" },
588     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
589         "this rule is limited to examining HTTP message headers" },
590     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
591         "parts of this rule examine HTTP message body" },
592     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
593         "parts of this rule examine HTTP message trailers" },
594     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
595 };
596 
597 #undef IPS_OPT
598 #define IPS_OPT "http_raw_cookie"
599 #undef IPS_HELP
600 #define IPS_HELP "rule option to set the detection cursor to the unnormalized cookie"
601 
raw_cookie_mod_ctor()602 static Module* raw_cookie_mod_ctor()
603 {
604     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_COOKIE, CAT_SET_OTHER,
605         PSI_RAW_COOKIE, http_raw_cookie_params);
606 }
607 
608 static const IpsApi raw_cookie_api =
609 {
610     {
611         PT_IPS_OPTION,
612         sizeof(IpsApi),
613         IPSAPI_VERSION,
614         1,
615         API_RESERVED,
616         API_OPTIONS,
617         IPS_OPT,
618         IPS_HELP,
619         raw_cookie_mod_ctor,
620         HttpRuleOptModule::mod_dtor
621     },
622     OPT_TYPE_DETECTION,
623     0, PROTO_BIT__TCP,
624     nullptr,
625     nullptr,
626     nullptr,
627     nullptr,
628     HttpIpsOption::opt_ctor,
629     HttpIpsOption::opt_dtor,
630     nullptr
631 };
632 
633 //-------------------------------------------------------------------------
634 // http_raw_header
635 //-------------------------------------------------------------------------
636 
637 static const Parameter http_raw_header_params[] =
638 {
639     { "field", Parameter::PT_STRING, nullptr, nullptr,
640         "restrict to given header. Header name is case insensitive." },
641     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
642         "match against the headers from the request message even when examining the response" },
643     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
644         "this rule is limited to examining HTTP message headers" },
645     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
646         "parts of this rule examine HTTP message body" },
647     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
648         "parts of this rule examine HTTP message trailers" },
649     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
650 };
651 
652 #undef IPS_OPT
653 #define IPS_OPT "http_raw_header"
654 #undef IPS_HELP
655 #define IPS_HELP "rule option to set the detection cursor to the unnormalized headers"
656 
raw_header_mod_ctor()657 static Module* raw_header_mod_ctor()
658 {
659     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER, CAT_SET_RAW_HEADER,
660         PSI_RAW_HEADER, http_raw_header_params);
661 }
662 
663 static const IpsApi raw_header_api =
664 {
665     {
666         PT_IPS_OPTION,
667         sizeof(IpsApi),
668         IPSAPI_VERSION,
669         1,
670         API_RESERVED,
671         API_OPTIONS,
672         IPS_OPT,
673         IPS_HELP,
674         raw_header_mod_ctor,
675         HttpRuleOptModule::mod_dtor
676     },
677     OPT_TYPE_DETECTION,
678     0, PROTO_BIT__TCP,
679     nullptr,
680     nullptr,
681     nullptr,
682     nullptr,
683     HttpIpsOption::opt_ctor,
684     HttpIpsOption::opt_dtor,
685     nullptr
686 };
687 
688 //-------------------------------------------------------------------------
689 // http_raw_request
690 //-------------------------------------------------------------------------
691 
692 static const Parameter http_raw_request_params[] =
693 {
694     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
695         "this rule is limited to examining HTTP message headers" },
696     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
697         "parts of this rule examine HTTP message body" },
698     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
699         "parts of this rule examine HTTP message trailers" },
700     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
701 };
702 
703 #undef IPS_OPT
704 #define IPS_OPT "http_raw_request"
705 #undef IPS_HELP
706 #define IPS_HELP "rule option to set the detection cursor to the unnormalized request line"
707 
raw_request_mod_ctor()708 static Module* raw_request_mod_ctor()
709 {
710     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_REQUEST, CAT_SET_OTHER,
711         PSI_RAW_REQUEST, http_raw_request_params);
712 }
713 
714 static const IpsApi raw_request_api =
715 {
716     {
717         PT_IPS_OPTION,
718         sizeof(IpsApi),
719         IPSAPI_VERSION,
720         1,
721         API_RESERVED,
722         API_OPTIONS,
723         IPS_OPT,
724         IPS_HELP,
725         raw_request_mod_ctor,
726         HttpRuleOptModule::mod_dtor
727     },
728     OPT_TYPE_DETECTION,
729     0, PROTO_BIT__TCP,
730     nullptr,
731     nullptr,
732     nullptr,
733     nullptr,
734     HttpIpsOption::opt_ctor,
735     HttpIpsOption::opt_dtor,
736     nullptr
737 };
738 
739 //-------------------------------------------------------------------------
740 // http_raw_status
741 //-------------------------------------------------------------------------
742 
743 static const Parameter http_raw_status_params[] =
744 {
745     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
746         "parts of this rule examine HTTP message body" },
747     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
748         "parts of this rule examine HTTP message trailers" },
749     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
750 };
751 
752 #undef IPS_OPT
753 #define IPS_OPT "http_raw_status"
754 #undef IPS_HELP
755 #define IPS_HELP "rule option to set the detection cursor to the unnormalized status line"
756 
raw_status_mod_ctor()757 static Module* raw_status_mod_ctor()
758 {
759     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_STATUS, CAT_SET_OTHER,
760         PSI_RAW_STATUS, http_raw_status_params);
761 }
762 
763 static const IpsApi raw_status_api =
764 {
765     {
766         PT_IPS_OPTION,
767         sizeof(IpsApi),
768         IPSAPI_VERSION,
769         1,
770         API_RESERVED,
771         API_OPTIONS,
772         IPS_OPT,
773         IPS_HELP,
774         raw_status_mod_ctor,
775         HttpRuleOptModule::mod_dtor
776     },
777     OPT_TYPE_DETECTION,
778     0, PROTO_BIT__TCP,
779     nullptr,
780     nullptr,
781     nullptr,
782     nullptr,
783     HttpIpsOption::opt_ctor,
784     HttpIpsOption::opt_dtor,
785     nullptr
786 };
787 
788 //-------------------------------------------------------------------------
789 // http_raw_trailer
790 //-------------------------------------------------------------------------
791 
792 static const Parameter http_raw_trailer_params[] =
793 {
794     { "field", Parameter::PT_STRING, nullptr, nullptr,
795         "restrict to given trailer. Trailer name is case insensitive." },
796     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
797         "match against the trailers from the request message even when examining the response" },
798     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
799         "parts of this rule examine HTTP response message headers (must be combined with request)"
800         },
801     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
802         "parts of this rule examine HTTP response message body (must be combined with request)" },
803     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
804 };
805 
806 #undef IPS_OPT
807 #define IPS_OPT "http_raw_trailer"
808 #undef IPS_HELP
809 #define IPS_HELP "rule option to set the detection cursor to the unnormalized trailers"
810 
raw_trailer_mod_ctor()811 static Module* raw_trailer_mod_ctor()
812 {
813     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_TRAILER, CAT_SET_RAW_HEADER,
814         PSI_RAW_TRAILER, http_raw_trailer_params);
815 }
816 
817 static const IpsApi raw_trailer_api =
818 {
819     {
820         PT_IPS_OPTION,
821         sizeof(IpsApi),
822         IPSAPI_VERSION,
823         1,
824         API_RESERVED,
825         API_OPTIONS,
826         IPS_OPT,
827         IPS_HELP,
828         raw_trailer_mod_ctor,
829         HttpRuleOptModule::mod_dtor
830     },
831     OPT_TYPE_DETECTION,
832     0, PROTO_BIT__TCP,
833     nullptr,
834     nullptr,
835     nullptr,
836     nullptr,
837     HttpIpsOption::opt_ctor,
838     HttpIpsOption::opt_dtor,
839     nullptr
840 };
841 
842 //-------------------------------------------------------------------------
843 // http_raw_uri
844 //-------------------------------------------------------------------------
845 
846 static const Parameter http_raw_uri_params[] =
847 {
848     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
849         "this rule is limited to examining HTTP message headers" },
850     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
851         "parts of this rule examine HTTP message body" },
852     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
853         "parts of this rule examine HTTP message trailers" },
854     { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
855         "match against scheme section of URI only" },
856     { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
857         "match against host section of URI only" },
858     { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
859         "match against port section of URI only" },
860     { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
861         "match against path section of URI only" },
862     { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
863         "match against query section of URI only" },
864     { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
865         "match against fragment section of URI only" },
866     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
867 };
868 
869 #undef IPS_OPT
870 #define IPS_OPT "http_raw_uri"
871 #undef IPS_HELP
872 #define IPS_HELP "rule option to set the detection cursor to the unnormalized URI"
873 
raw_uri_mod_ctor()874 static Module* raw_uri_mod_ctor()
875 {
876     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_URI, CAT_SET_RAW_KEY,
877         PSI_RAW_URI, http_raw_uri_params);
878 }
879 
880 static const IpsApi raw_uri_api =
881 {
882     {
883         PT_IPS_OPTION,
884         sizeof(IpsApi),
885         IPSAPI_VERSION,
886         1,
887         API_RESERVED,
888         API_OPTIONS,
889         IPS_OPT,
890         IPS_HELP,
891         raw_uri_mod_ctor,
892         HttpRuleOptModule::mod_dtor
893     },
894     OPT_TYPE_DETECTION,
895     0, PROTO_BIT__TCP,
896     nullptr,
897     nullptr,
898     nullptr,
899     nullptr,
900     HttpIpsOption::opt_ctor,
901     HttpIpsOption::opt_dtor,
902     nullptr
903 };
904 
905 //-------------------------------------------------------------------------
906 // http_stat_code
907 //-------------------------------------------------------------------------
908 
909 static const Parameter http_stat_code_params[] =
910 {
911     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
912         "parts of this rule examine HTTP message body" },
913     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
914         "parts of this rule examine HTTP message trailers" },
915     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
916 };
917 
918 #undef IPS_OPT
919 #define IPS_OPT "http_stat_code"
920 #undef IPS_HELP
921 #define IPS_HELP "rule option to set the detection cursor to the HTTP status code"
922 
stat_code_mod_ctor()923 static Module* stat_code_mod_ctor()
924 {
925     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_CODE, CAT_SET_STAT_CODE,
926         PSI_STAT_CODE, http_stat_code_params);
927 }
928 
929 static const IpsApi stat_code_api =
930 {
931     {
932         PT_IPS_OPTION,
933         sizeof(IpsApi),
934         IPSAPI_VERSION,
935         1,
936         API_RESERVED,
937         API_OPTIONS,
938         IPS_OPT,
939         IPS_HELP,
940         stat_code_mod_ctor,
941         HttpRuleOptModule::mod_dtor
942     },
943     OPT_TYPE_DETECTION,
944     0, PROTO_BIT__TCP,
945     nullptr,
946     nullptr,
947     nullptr,
948     nullptr,
949     HttpIpsOption::opt_ctor,
950     HttpIpsOption::opt_dtor,
951     nullptr
952 };
953 
954 //-------------------------------------------------------------------------
955 // http_stat_msg
956 //-------------------------------------------------------------------------
957 
958 static const Parameter http_stat_msg_params[] =
959 {
960     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
961         "parts of this rule examine HTTP message body" },
962     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
963         "parts of this rule examine HTTP message trailers" },
964     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
965 };
966 
967 #undef IPS_OPT
968 #define IPS_OPT "http_stat_msg"
969 #undef IPS_HELP
970 #define IPS_HELP "rule option to set the detection cursor to the HTTP status message"
971 
stat_msg_mod_ctor()972 static Module* stat_msg_mod_ctor()
973 {
974     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_STAT_MSG, CAT_SET_STAT_MSG,
975         PSI_STAT_MSG, http_stat_msg_params);
976 }
977 
978 static const IpsApi stat_msg_api =
979 {
980     {
981         PT_IPS_OPTION,
982         sizeof(IpsApi),
983         IPSAPI_VERSION,
984         1,
985         API_RESERVED,
986         API_OPTIONS,
987         IPS_OPT,
988         IPS_HELP,
989         stat_msg_mod_ctor,
990         HttpRuleOptModule::mod_dtor
991     },
992     OPT_TYPE_DETECTION,
993     0, PROTO_BIT__TCP,
994     nullptr,
995     nullptr,
996     nullptr,
997     nullptr,
998     HttpIpsOption::opt_ctor,
999     HttpIpsOption::opt_dtor,
1000     nullptr
1001 };
1002 
1003 //-------------------------------------------------------------------------
1004 // http_trailer
1005 //-------------------------------------------------------------------------
1006 
1007 static const Parameter http_trailer_params[] =
1008 {
1009     { "field", Parameter::PT_STRING, nullptr, nullptr, "restrict to given trailer" },
1010     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
1011         "match against the trailers from the request message even when examining the response" },
1012     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
1013         "parts of this rule examine HTTP response message headers (must be combined with request)"
1014         },
1015     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
1016         "parts of this rule examine HTTP message body (must be combined with request)" },
1017     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
1018 };
1019 
1020 #undef IPS_OPT
1021 #define IPS_OPT "http_trailer"
1022 #undef IPS_HELP
1023 #define IPS_HELP "rule option to set the detection cursor to the normalized trailers"
1024 
trailer_mod_ctor()1025 static Module* trailer_mod_ctor()
1026 {
1027     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRAILER, CAT_SET_HEADER,
1028         PSI_TRAILER, http_trailer_params);
1029 }
1030 
1031 static const IpsApi trailer_api =
1032 {
1033     {
1034         PT_IPS_OPTION,
1035         sizeof(IpsApi),
1036         IPSAPI_VERSION,
1037         1,
1038         API_RESERVED,
1039         API_OPTIONS,
1040         IPS_OPT,
1041         IPS_HELP,
1042         trailer_mod_ctor,
1043         HttpRuleOptModule::mod_dtor
1044     },
1045     OPT_TYPE_DETECTION,
1046     0, PROTO_BIT__TCP,
1047     nullptr,
1048     nullptr,
1049     nullptr,
1050     nullptr,
1051     HttpIpsOption::opt_ctor,
1052     HttpIpsOption::opt_dtor,
1053     nullptr
1054 };
1055 
1056 //-------------------------------------------------------------------------
1057 // http_true_ip
1058 //-------------------------------------------------------------------------
1059 
1060 static const Parameter http_true_ip_params[] =
1061 {
1062     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
1063         "this rule is limited to examining HTTP message headers" },
1064     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
1065         "parts of this rule examine HTTP message body" },
1066     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
1067         "parts of this rule examine HTTP message trailers" },
1068     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
1069 };
1070 
1071 #undef IPS_OPT
1072 #define IPS_OPT "http_true_ip"
1073 #undef IPS_HELP
1074 #define IPS_HELP "rule option to set the detection cursor to the final client IP address"
1075 
true_ip_mod_ctor()1076 static Module* true_ip_mod_ctor()
1077 {
1078     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_TRUE_IP, CAT_SET_OTHER,
1079         PSI_TRUE_IP, http_true_ip_params);
1080 }
1081 
1082 static const IpsApi true_ip_api =
1083 {
1084     {
1085         PT_IPS_OPTION,
1086         sizeof(IpsApi),
1087         IPSAPI_VERSION,
1088         1,
1089         API_RESERVED,
1090         API_OPTIONS,
1091         IPS_OPT,
1092         IPS_HELP,
1093         true_ip_mod_ctor,
1094         HttpRuleOptModule::mod_dtor
1095     },
1096     OPT_TYPE_DETECTION,
1097     0, PROTO_BIT__TCP,
1098     nullptr,
1099     nullptr,
1100     nullptr,
1101     nullptr,
1102     HttpIpsOption::opt_ctor,
1103     HttpIpsOption::opt_dtor,
1104     nullptr
1105 };
1106 
1107 //-------------------------------------------------------------------------
1108 // http_uri
1109 //-------------------------------------------------------------------------
1110 
1111 static const Parameter http_uri_params[] =
1112 {
1113     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
1114         "this rule is limited to examining HTTP message headers" },
1115     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
1116         "parts of this rule examine HTTP message body" },
1117     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
1118         "parts of this rule examine HTTP message trailers" },
1119     { "scheme", Parameter::PT_IMPLIED, nullptr, nullptr,
1120         "match against scheme section of URI only" },
1121     { "host", Parameter::PT_IMPLIED, nullptr, nullptr,
1122         "match against host section of URI only" },
1123     { "port", Parameter::PT_IMPLIED, nullptr, nullptr,
1124         "match against port section of URI only" },
1125     { "path", Parameter::PT_IMPLIED, nullptr, nullptr,
1126         "match against path section of URI only" },
1127     { "query", Parameter::PT_IMPLIED, nullptr, nullptr,
1128         "match against query section of URI only" },
1129     { "fragment", Parameter::PT_IMPLIED, nullptr, nullptr,
1130         "match against fragment section of URI only" },
1131     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
1132 };
1133 
1134 #undef IPS_OPT
1135 #define IPS_OPT "http_uri"
1136 #undef IPS_HELP
1137 #define IPS_HELP "rule option to set the detection cursor to the normalized URI buffer"
1138 
uri_mod_ctor()1139 static Module* uri_mod_ctor()
1140 {
1141     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_URI, CAT_SET_KEY, PSI_URI,
1142         http_uri_params);
1143 }
1144 
1145 static const IpsApi uri_api =
1146 {
1147     {
1148         PT_IPS_OPTION,
1149         sizeof(IpsApi),
1150         IPSAPI_VERSION,
1151         1,
1152         API_RESERVED,
1153         API_OPTIONS,
1154         IPS_OPT,
1155         IPS_HELP,
1156         uri_mod_ctor,
1157         HttpRuleOptModule::mod_dtor
1158     },
1159     OPT_TYPE_DETECTION,
1160     0, PROTO_BIT__TCP,
1161     nullptr,
1162     nullptr,
1163     nullptr,
1164     nullptr,
1165     HttpIpsOption::opt_ctor,
1166     HttpIpsOption::opt_dtor,
1167     nullptr
1168 };
1169 
1170 //-------------------------------------------------------------------------
1171 // http_version
1172 //-------------------------------------------------------------------------
1173 
1174 static const Parameter http_version_params[] =
1175 {
1176     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
1177         "match against the version from the request message even when examining the response" },
1178     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
1179         "this rule is limited to examining HTTP message headers" },
1180     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
1181         "parts of this rule examine HTTP message body" },
1182     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
1183         "parts of this rule examine HTTP message trailers" },
1184     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
1185 };
1186 
1187 #undef IPS_OPT
1188 #define IPS_OPT "http_version"
1189 #undef IPS_HELP
1190 #define IPS_HELP "rule option to set the detection cursor to the version buffer"
1191 
version_mod_ctor()1192 static Module* version_mod_ctor()
1193 {
1194     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_VERSION, CAT_SET_OTHER,
1195         PSI_VERSION, http_version_params);
1196 }
1197 
1198 static const IpsApi version_api =
1199 {
1200     {
1201         PT_IPS_OPTION,
1202         sizeof(IpsApi),
1203         IPSAPI_VERSION,
1204         1,
1205         API_RESERVED,
1206         API_OPTIONS,
1207         IPS_OPT,
1208         IPS_HELP,
1209         version_mod_ctor,
1210         HttpRuleOptModule::mod_dtor
1211     },
1212     OPT_TYPE_DETECTION,
1213     0, PROTO_BIT__TCP,
1214     nullptr,
1215     nullptr,
1216     nullptr,
1217     nullptr,
1218     HttpIpsOption::opt_ctor,
1219     HttpIpsOption::opt_dtor,
1220     nullptr
1221 };
1222 
1223 //-------------------------------------------------------------------------
1224 // js_data
1225 //-------------------------------------------------------------------------
1226 //
1227 
1228 #undef IPS_OPT
1229 #define IPS_OPT "js_data"
1230 #undef IPS_HELP
1231 #define IPS_HELP "rule option to set detection cursor to normalized JavaScript data"
js_data_mod_ctor()1232 static Module* js_data_mod_ctor()
1233 {
1234     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, BUFFER_JS_DATA, CAT_SET_JS_DATA,
1235         PSI_JS_DATA);
1236 }
1237 
1238 static const IpsApi js_data_api =
1239 {
1240     {
1241         PT_IPS_OPTION,
1242         sizeof(IpsApi),
1243         IPSAPI_VERSION,
1244         1,
1245         API_RESERVED,
1246         API_OPTIONS,
1247         IPS_OPT,
1248         IPS_HELP,
1249         js_data_mod_ctor,
1250         HttpRuleOptModule::mod_dtor
1251     },
1252     OPT_TYPE_DETECTION,
1253     0, PROTO_BIT__TCP,
1254     nullptr,
1255     nullptr,
1256     nullptr,
1257     nullptr,
1258     HttpIpsOption::opt_ctor,
1259     HttpIpsOption::opt_dtor,
1260     nullptr
1261 };
1262 
1263 //-------------------------------------------------------------------------
1264 // num_header_lines
1265 //-------------------------------------------------------------------------
1266 #undef IPS_OPT
1267 #define IPS_OPT "num_headers"
1268 #undef IPS_HELP
1269 #define IPS_HELP "rule option to perform range check on number of headers"
1270 
1271 static const Parameter http_num_hdrs_params[] =
1272 {
1273     { "~range", Parameter::PT_INTERVAL, hdrs_num_range.c_str(), nullptr,
1274         "check that number of headers of current buffer are in given range" },
1275     { "request", Parameter::PT_IMPLIED, nullptr, nullptr,
1276         "match against the version from the request message even when examining the response" },
1277     { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr,
1278         "this rule is limited to examining HTTP message headers" },
1279     { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr,
1280         "parts of this rule examine HTTP message body" },
1281     { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr,
1282         "parts of this rule examine HTTP message trailers" },
1283     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
1284 };
1285 
num_hdrs_mod_ctor()1286 static Module* num_hdrs_mod_ctor()
1287 {
1288     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_HDRS, CAT_SET_OTHER,
1289 	PSI_RANGE_NUM_HDRS, http_num_hdrs_params);
1290 }
1291 
1292 static const IpsApi num_headers_api =
1293 {
1294     {
1295         PT_IPS_OPTION,
1296         sizeof(IpsApi),
1297         IPSAPI_VERSION,
1298         1,
1299         API_RESERVED,
1300         API_OPTIONS,
1301         IPS_OPT,
1302         IPS_HELP,
1303         num_hdrs_mod_ctor,
1304         HttpRuleOptModule::mod_dtor
1305     },
1306     OPT_TYPE_DETECTION,
1307     0, PROTO_BIT__TCP,
1308     nullptr,
1309     nullptr,
1310     nullptr,
1311     nullptr,
1312     HttpIpsOption::opt_ctor,
1313     HttpIpsOption::opt_dtor,
1314     nullptr
1315 };
1316 
1317 //-------------------------------------------------------------------------
1318 // num_trailer_lines
1319 //-------------------------------------------------------------------------
1320 #undef IPS_OPT
1321 #define IPS_OPT "num_trailers"
1322 #undef IPS_HELP
1323 #define IPS_HELP "rule option to perform range check on number of trailers"
1324 
num_trailers_mod_ctor()1325 static Module* num_trailers_mod_ctor()
1326 {
1327     return new HttpRuleOptModule(IPS_OPT, IPS_HELP, HTTP_RANGE_NUM_TRAILERS, CAT_SET_OTHER,
1328 	PSI_RANGE_NUM_TRAILERS, http_num_hdrs_params);
1329 }
1330 
1331 static const IpsApi num_trailers_api =
1332 {
1333     {
1334         PT_IPS_OPTION,
1335         sizeof(IpsApi),
1336         IPSAPI_VERSION,
1337         1,
1338         API_RESERVED,
1339         API_OPTIONS,
1340         IPS_OPT,
1341         IPS_HELP,
1342         num_trailers_mod_ctor,
1343         HttpRuleOptModule::mod_dtor
1344     },
1345     OPT_TYPE_DETECTION,
1346     0, PROTO_BIT__TCP,
1347     nullptr,
1348     nullptr,
1349     nullptr,
1350     nullptr,
1351     HttpIpsOption::opt_ctor,
1352     HttpIpsOption::opt_dtor,
1353     nullptr
1354 };
1355 
1356 //-------------------------------------------------------------------------
1357 // plugins
1358 //-------------------------------------------------------------------------
1359 
1360 const BaseApi* ips_http_client_body = &client_body_api.base;
1361 const BaseApi* ips_http_cookie = &cookie_api.base;
1362 const BaseApi* ips_http_header = &header_api.base;
1363 const BaseApi* ips_http_method = &method_api.base;
1364 const BaseApi* ips_http_num_headers = &num_headers_api.base;
1365 const BaseApi* ips_http_num_trailers = &num_trailers_api.base;
1366 const BaseApi* ips_http_param = &param_api.base;
1367 const BaseApi* ips_http_raw_body = &raw_body_api.base;
1368 const BaseApi* ips_http_raw_cookie = &raw_cookie_api.base;
1369 const BaseApi* ips_http_raw_header = &raw_header_api.base;
1370 const BaseApi* ips_http_raw_request = &raw_request_api.base;
1371 const BaseApi* ips_http_raw_status = &raw_status_api.base;
1372 const BaseApi* ips_http_raw_trailer = &raw_trailer_api.base;
1373 const BaseApi* ips_http_raw_uri = &raw_uri_api.base;
1374 const BaseApi* ips_http_stat_code = &stat_code_api.base;
1375 const BaseApi* ips_http_stat_msg = &stat_msg_api.base;
1376 const BaseApi* ips_http_trailer = &trailer_api.base;
1377 const BaseApi* ips_http_true_ip = &true_ip_api.base;
1378 const BaseApi* ips_http_uri = &uri_api.base;
1379 const BaseApi* ips_http_version = &version_api.base;
1380 const BaseApi* ips_js_data = &js_data_api.base;
1381 
1382