suricata
app-layer-htp-xff.c
Go to the documentation of this file.
1 /* Copyright (C) 2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
22  * \author Duarte Silva <duarte.silva@serializing.me>
23  */
24 
25 #include "suricata-common.h"
26 #include "conf.h"
27 
28 #include "app-layer-parser.h"
29 #include "app-layer-htp.h"
30 #include "app-layer-htp-xff.h"
31 
32 #include "util-misc.h"
33 #include "util-unittest.h"
34 #include "app-layer-protos.h"
35 #include "htp/htp_rs.h"
36 #include "util-debug.h"
37 
38 /** Default XFF header name */
39 #define XFF_DEFAULT "X-Forwarded-For"
40 
41 static int HttpXFFGetIPFromTxAux(htp_tx_t *tx, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
42 {
43  return htp_xff_get_ip(
44  tx, xff_cfg->flags & XFF_REVERSE, xff_cfg->header, (uint8_t *)dstbuf, dstbuflen);
45 }
46 
47 /**
48  * \brief Function to return XFF IP if any in the selected transaction. The
49  * caller needs to lock the flow.
50  * \retval 1 if the IP has been found and returned in dstbuf
51  * \retval 0 if the IP has not being found or error
52  */
54  const Flow *f, uint64_t tx_id, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
55 {
56  HtpState *htp_state = NULL;
57  uint64_t total_txs = 0;
58  htp_tx_t *tx = NULL;
59 
60  htp_state = (HtpState *)FlowGetAppState(f);
61 
62  if (htp_state == NULL) {
63  SCLogDebug("no http state, XFF IP cannot be retrieved");
64  return 0;
65  }
66 
67  total_txs = AppLayerParserGetTxCnt(f, htp_state);
68  if (tx_id >= total_txs)
69  return 0;
70 
71  tx = AppLayerParserGetTx(f->proto, ALPROTO_HTTP1, htp_state, tx_id);
72  if (tx == NULL) {
73  SCLogDebug("tx is NULL, XFF cannot be retrieved");
74  return 0;
75  }
76  return HttpXFFGetIPFromTxAux(tx, xff_cfg, dstbuf, dstbuflen);
77 }
78 
79 /**
80  * \brief Function to return XFF IP if any. The caller needs to lock the flow.
81  * \retval 1 if the IP has been found and returned in dstbuf
82  * \retval 0 if the IP has not being found or error
83  */
84 int HttpXFFGetIP(const Flow *f, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
85 {
86  HtpState *htp_state = (HtpState *)FlowGetAppState(f);
87  if (htp_state == NULL) {
88  SCLogDebug("no http state, XFF IP cannot be retrieved");
89  goto end;
90  }
91 
92  uint64_t tx_id = AppLayerParserGetMinId(f->alparser);
93  const uint64_t total_txs = AppLayerParserGetTxCnt(f, htp_state);
96  memset(&state, 0, sizeof(state));
97 
98  while (1) {
100  IterFunc(f->proto, f->alproto, f->alstate, tx_id, total_txs, &state);
101  if (ires.tx_ptr == NULL)
102  break;
103 
104  if (HttpXFFGetIPFromTxAux(ires.tx_ptr, xff_cfg, dstbuf, dstbuflen) == 1)
105  return 1;
106 
107  tx_id = ires.tx_id + 1;
108  }
109 
110 end:
111  return 0; // Not found
112 }
113 
114 /**
115  * \brief Function to return XFF configuration from a configuration node.
116  */
117 void HttpXFFGetCfg(SCConfNode *conf, HttpXFFCfg *result)
118 {
119  BUG_ON(result == NULL);
120 
121  SCConfNode *xff_node = NULL;
122 
123  if (conf != NULL)
124  xff_node = SCConfNodeLookupChild(conf, "xff");
125 
126  if (xff_node != NULL && SCConfNodeChildValueIsTrue(xff_node, "enabled")) {
127  const char *xff_mode = SCConfNodeLookupChildValue(xff_node, "mode");
128 
129  if (xff_mode != NULL && strcasecmp(xff_mode, "overwrite") == 0) {
130  result->flags |= XFF_OVERWRITE;
131  } else {
132  if (xff_mode == NULL) {
133  SCLogWarning("The XFF mode hasn't been defined, falling back to extra-data mode");
134  }
135  else if (strcasecmp(xff_mode, "extra-data") != 0) {
136  SCLogWarning(
137  "The XFF mode %s is invalid, falling back to extra-data mode", xff_mode);
138  }
139  result->flags |= XFF_EXTRADATA;
140  }
141 
142  const char *xff_deployment = SCConfNodeLookupChildValue(xff_node, "deployment");
143 
144  if (xff_deployment != NULL && strcasecmp(xff_deployment, "forward") == 0) {
145  result->flags |= XFF_FORWARD;
146  } else {
147  if (xff_deployment == NULL) {
148  SCLogWarning("The XFF deployment hasn't been defined, falling back to reverse "
149  "proxy deployment");
150  }
151  else if (strcasecmp(xff_deployment, "reverse") != 0) {
152  SCLogWarning("The XFF mode %s is invalid, falling back to reverse proxy deployment",
153  xff_deployment);
154  }
155  result->flags |= XFF_REVERSE;
156  }
157 
158  const char *xff_header = SCConfNodeLookupChildValue(xff_node, "header");
159 
160  if (xff_header != NULL) {
161  result->header = (char *) xff_header;
162  } else {
163  SCLogWarning("The XFF header hasn't been defined, using the default %s", XFF_DEFAULT);
164  result->header = XFF_DEFAULT;
165  }
166  } else {
167  result->flags = XFF_DISABLED;
168  }
169 }
XFF_REVERSE
#define XFF_REVERSE
Definition: app-layer-htp-xff.h:35
XFF_EXTRADATA
#define XFF_EXTRADATA
Definition: app-layer-htp-xff.h:31
HttpXFFGetCfg
void HttpXFFGetCfg(SCConfNode *conf, HttpXFFCfg *result)
Function to return XFF configuration from a configuration node.
Definition: app-layer-htp-xff.c:117
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
AppLayerGetTxIterator
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto, const AppProto alproto)
Definition: app-layer-parser.c:783
Flow_::proto
uint8_t proto
Definition: flow.h:382
Flow_
Flow data structure.
Definition: flow.h:360
SCConfNodeChildValueIsTrue
int SCConfNodeChildValueIsTrue(const SCConfNode *node, const char *key)
Test if a configuration node has a true value.
Definition: conf.c:922
XFF_FORWARD
#define XFF_FORWARD
Definition: app-layer-htp-xff.h:37
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:878
AppLayerGetTxIterTuple::tx_ptr
void * tx_ptr
Definition: app-layer-parser.h:160
util-unittest.h
HtpState_
Definition: app-layer-htp.h:183
HttpXFFGetIP
int HttpXFFGetIP(const Flow *f, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
Function to return XFF IP if any. The caller needs to lock the flow.
Definition: app-layer-htp-xff.c:84
app-layer-htp-xff.h
XFF_DEFAULT
#define XFF_DEFAULT
Definition: app-layer-htp-xff.c:39
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:484
app-layer-htp.h
util-debug.h
AppLayerGetTxIterTuple::tx_id
uint64_t tx_id
Definition: app-layer-parser.h:161
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
app-layer-parser.h
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:331
AppLayerGetTxIterState
Definition: app-layer-parser.h:148
conf.h
HttpXFFCfg_::header
const char * header
Definition: app-layer-htp-xff.h:43
XFF_OVERWRITE
#define XFF_OVERWRITE
Definition: app-layer-htp-xff.h:33
AppLayerGetTxIterTuple
Definition: app-layer-parser.h:159
HttpXFFCfg_
Definition: app-layer-htp-xff.h:41
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1219
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:850
suricata-common.h
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
HttpXFFCfg_::flags
uint8_t flags
Definition: app-layer-htp-xff.h:42
Flow_::alstate
void * alstate
Definition: flow.h:485
app-layer-protos.h
AppLayerGetTxIteratorFunc
AppLayerGetTxIterTuple(* AppLayerGetTxIteratorFunc)(const uint8_t ipproto, const AppProto alproto, void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
tx iterator prototype
Definition: app-layer-parser.h:232
HttpXFFGetIPFromTx
int HttpXFFGetIPFromTx(const Flow *f, uint64_t tx_id, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
Function to return XFF IP if any in the selected transaction. The caller needs to lock the flow.
Definition: app-layer-htp-xff.c:53
util-misc.h
AppLayerParserGetMinId
uint64_t AppLayerParserGetMinId(AppLayerParserState *pstate)
Definition: app-layer-parser.c:798
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
SCConfNode_
Definition: conf.h:37
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1212
XFF_DISABLED
#define XFF_DISABLED
Definition: app-layer-htp-xff.h:29
f
Flow f
Definition: fuzz_dataset.c:32