suricata
util-lua-http.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 Victor Julien <victor@inliniac.net>
22  *
23  */
24 
25 #include "suricata-common.h"
26 #include "debug.h"
27 #include "detect.h"
28 #include "pkt-var.h"
29 #include "conf.h"
30 
31 #include "threads.h"
32 #include "threadvars.h"
33 #include "tm-threads.h"
34 
35 #include "util-print.h"
36 #include "util-unittest.h"
37 
38 #include "util-debug.h"
39 
40 #include "output.h"
41 #include "app-layer-htp.h"
42 #include "app-layer.h"
43 #include "app-layer-parser.h"
44 #include "util-privs.h"
45 #include "util-buffer.h"
46 #include "util-proto-name.h"
47 #include "util-logopenfile.h"
48 #include "util-time.h"
49 
50 #ifdef HAVE_LUA
51 
52 #include <lua.h>
53 #include <lualib.h>
54 #include <lauxlib.h>
55 
56 #include "util-lua.h"
57 #include "util-lua-common.h"
58 #include "util-lua-http.h"
59 
60 static int HttpGetRequestHost(lua_State *luastate)
61 {
62  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
63  return LuaCallbackError(luastate, "error: protocol not http");
64 
65  htp_tx_t *tx = LuaStateGetTX(luastate);
66  if (tx == NULL)
67  return LuaCallbackError(luastate, "internal error: no tx");
68 
69  if (tx->request_hostname == NULL)
70  return LuaCallbackError(luastate, "no request hostname");
71 
72  return LuaPushStringBuffer(luastate,
73  bstr_ptr(tx->request_hostname), bstr_len(tx->request_hostname));
74 }
75 
76 static int HttpGetRequestUriRaw(lua_State *luastate)
77 {
78  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
79  return LuaCallbackError(luastate, "error: protocol not http");
80 
81  htp_tx_t *tx = LuaStateGetTX(luastate);
82  if (tx == NULL)
83  return LuaCallbackError(luastate, "internal error: no tx");
84 
85  if (tx->request_uri == NULL)
86  return LuaCallbackError(luastate, "no request uri");
87 
88  return LuaPushStringBuffer(luastate,
89  bstr_ptr(tx->request_uri), bstr_len(tx->request_uri));
90 }
91 
92 static int HttpGetRequestUriNormalized(lua_State *luastate)
93 {
94  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
95  return LuaCallbackError(luastate, "error: protocol not http");
96 
97  htp_tx_t *tx = LuaStateGetTX(luastate);
98  if (tx == NULL)
99  return LuaCallbackError(luastate, "internal error: no tx");
100 
101  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
102  if (htud == NULL)
103  return LuaCallbackError(luastate, "no htud in tx");
104 
105  if (htud->request_uri_normalized == NULL ||
106  bstr_ptr(htud->request_uri_normalized) == NULL ||
107  bstr_len(htud->request_uri_normalized) == 0)
108  return LuaCallbackError(luastate, "no normalized uri");
109 
110  return LuaPushStringBuffer(luastate,
111  bstr_ptr(htud->request_uri_normalized),
112  bstr_len(htud->request_uri_normalized));
113 }
114 
115 static int HttpGetRequestLine(lua_State *luastate)
116 {
117  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
118  return LuaCallbackError(luastate, "error: protocol not http");
119 
120  htp_tx_t *tx = LuaStateGetTX(luastate);
121  if (tx == NULL)
122  return LuaCallbackError(luastate, "internal error: no tx");
123 
124  if (tx->request_line == NULL)
125  return LuaCallbackError(luastate, "no request_line");
126 
127  return LuaPushStringBuffer(luastate,
128  bstr_ptr(tx->request_line), bstr_len(tx->request_line));
129 }
130 
131 static int HttpGetResponseLine(lua_State *luastate)
132 {
133  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
134  return LuaCallbackError(luastate, "error: protocol not http");
135 
136  htp_tx_t *tx = LuaStateGetTX(luastate);
137  if (tx == NULL)
138  return LuaCallbackError(luastate, "internal error: no tx");
139 
140  if (tx->response_line == NULL)
141  return LuaCallbackError(luastate, "no response_line");
142 
143  return LuaPushStringBuffer(luastate,
144  bstr_ptr(tx->response_line), bstr_len(tx->response_line));
145 }
146 
147 static int HttpGetHeader(lua_State *luastate, int dir)
148 {
149  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
150  return LuaCallbackError(luastate, "error: protocol not http");
151 
152  htp_tx_t *tx = LuaStateGetTX(luastate);
153  if (tx == NULL)
154  return LuaCallbackError(luastate, "internal error: no tx");
155 
156  const char *name = LuaGetStringArgument(luastate, 1);
157  if (name == NULL)
158  return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");
159 
160  htp_table_t *headers = tx->request_headers;
161  if (dir == 1)
162  headers = tx->response_headers;
163  if (headers == NULL)
164  return LuaCallbackError(luastate, "tx has no headers");
165 
166  htp_header_t *h = (htp_header_t *)htp_table_get_c(headers, name);
167  if (h == NULL || bstr_len(h->value) == 0)
168  return LuaCallbackError(luastate, "header not found");
169 
170  return LuaPushStringBuffer(luastate,
171  bstr_ptr(h->value), bstr_len(h->value));
172 }
173 
174 static int HttpGetRequestHeader(lua_State *luastate)
175 {
176  return HttpGetHeader(luastate, 0 /* request */);
177 }
178 
179 static int HttpGetResponseHeader(lua_State *luastate)
180 {
181  return HttpGetHeader(luastate, 1 /* response */);
182 }
183 
184 static int HttpGetRawHeaders(lua_State *luastate, int dir)
185 {
186  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
187  return LuaCallbackError(luastate, "error: protocol not http");
188 
189  htp_tx_t *tx = LuaStateGetTX(luastate);
190  if (tx == NULL)
191  return LuaCallbackError(luastate, "internal error: no tx");
192 
193  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
194  if (htud == NULL)
195  return LuaCallbackError(luastate, "no htud in tx");
196 
197  uint8_t *raw = htud->request_headers_raw;
198  uint32_t raw_len = htud->request_headers_raw_len;
199  if (dir == 1) {
200  raw = htud->response_headers_raw;
201  raw_len = htud->response_headers_raw_len;
202  }
203 
204  if (raw == NULL || raw_len == 0)
205  return LuaCallbackError(luastate, "no raw headers");
206 
207  return LuaPushStringBuffer(luastate, raw, raw_len);
208 }
209 
210 static int HttpGetRawRequestHeaders(lua_State *luastate)
211 {
212  return HttpGetRawHeaders(luastate, 0);
213 }
214 
215 static int HttpGetRawResponseHeaders(lua_State *luastate)
216 {
217  return HttpGetRawHeaders(luastate, 1);
218 }
219 
220 
221 static int HttpGetHeaders(lua_State *luastate, int dir)
222 {
223  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
224  return LuaCallbackError(luastate, "error: protocol not http");
225 
226  htp_tx_t *tx = LuaStateGetTX(luastate);
227  if (tx == NULL)
228  return LuaCallbackError(luastate, "internal error: no tx");
229 
230  htp_table_t *table = tx->request_headers;
231  if (dir == 1)
232  table = tx->response_headers;
233  if (tx->request_headers == NULL)
234  return LuaCallbackError(luastate, "no headers");
235 
236  lua_newtable(luastate);
237  htp_header_t *h = NULL;
238  size_t i = 0;
239  size_t no_of_headers = htp_table_size(table);
240  for (; i < no_of_headers; i++) {
241  h = htp_table_get_index(table, i, NULL);
242  LuaPushStringBuffer(luastate, bstr_ptr(h->name), bstr_len(h->name));
243  LuaPushStringBuffer(luastate, bstr_ptr(h->value), bstr_len(h->value));
244  lua_settable(luastate, -3);
245  }
246  return 1;
247 }
248 
249 /** \brief return request headers as lua table */
250 static int HttpGetRequestHeaders(lua_State *luastate)
251 {
252  return HttpGetHeaders(luastate, 0);
253 }
254 
255 /** \brief return response headers as lua table */
256 static int HttpGetResponseHeaders(lua_State *luastate)
257 {
258  return HttpGetHeaders(luastate, 1);
259 }
260 
261 static int HttpGetBody(lua_State *luastate, int dir)
262 {
263  HtpBody *body = NULL;
264 
265  if (!(LuaStateNeedProto(luastate, ALPROTO_HTTP)))
266  return LuaCallbackError(luastate, "error: protocol not http");
267 
268  htp_tx_t *tx = LuaStateGetTX(luastate);
269  if (tx == NULL)
270  return LuaCallbackError(luastate, "internal error: no tx");
271 
272  HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
273  if (htud == NULL)
274  return LuaCallbackError(luastate, "no htud in tx");
275 
276  if (dir == 0)
277  body = &htud->request_body;
278  else
279  body = &htud->response_body;
280 
281  if (body->first == NULL)
282  return LuaCallbackError(luastate, "no body");
283 
284  int index = 1;
285  HtpBodyChunk *chunk = body->first;
286  lua_newtable(luastate);
287  while (chunk != NULL) {
288  lua_pushinteger(luastate, index);
289 
290  const uint8_t *data = NULL;
291  uint32_t data_len = 0;
292  StreamingBufferSegmentGetData(body->sb, &chunk->sbseg, &data, &data_len);
293  LuaPushStringBuffer(luastate, data, data_len);
294 
295  lua_settable(luastate, -3);
296 
297  chunk = chunk->next;
298  index++;
299  }
300 
301  if (body->first && body->last) {
302  lua_pushinteger(luastate, body->first->sbseg.stream_offset);
303  lua_pushinteger(luastate, body->last->sbseg.stream_offset + body->last->sbseg.segment_len);
304  return 3;
305  } else {
306  return 1;
307  }
308 }
309 
310 static int HttpGetRequestBody(lua_State *luastate)
311 {
312  return HttpGetBody(luastate, 0);
313 }
314 
315 static int HttpGetResponseBody(lua_State *luastate)
316 {
317  return HttpGetBody(luastate, 1);
318 }
319 
320 /** \brief register http lua extensions in a luastate */
321 int LuaRegisterHttpFunctions(lua_State *luastate)
322 {
323  /* registration of the callbacks */
324  lua_pushcfunction(luastate, HttpGetRequestHeader);
325  lua_setglobal(luastate, "HttpGetRequestHeader");
326  lua_pushcfunction(luastate, HttpGetResponseHeader);
327  lua_setglobal(luastate, "HttpGetResponseHeader");
328  lua_pushcfunction(luastate, HttpGetRequestLine);
329  lua_setglobal(luastate, "HttpGetRequestLine");
330  lua_pushcfunction(luastate, HttpGetResponseLine);
331  lua_setglobal(luastate, "HttpGetResponseLine");
332  lua_pushcfunction(luastate, HttpGetRawRequestHeaders);
333  lua_setglobal(luastate, "HttpGetRawRequestHeaders");
334  lua_pushcfunction(luastate, HttpGetRawResponseHeaders);
335  lua_setglobal(luastate, "HttpGetRawResponseHeaders");
336  lua_pushcfunction(luastate, HttpGetRequestUriRaw);
337  lua_setglobal(luastate, "HttpGetRequestUriRaw");
338  lua_pushcfunction(luastate, HttpGetRequestUriNormalized);
339  lua_setglobal(luastate, "HttpGetRequestUriNormalized");
340  lua_pushcfunction(luastate, HttpGetRequestHeaders);
341  lua_setglobal(luastate, "HttpGetRequestHeaders");
342  lua_pushcfunction(luastate, HttpGetResponseHeaders);
343  lua_setglobal(luastate, "HttpGetResponseHeaders");
344  lua_pushcfunction(luastate, HttpGetRequestHost);
345  lua_setglobal(luastate, "HttpGetRequestHost");
346 
347  lua_pushcfunction(luastate, HttpGetRequestBody);
348  lua_setglobal(luastate, "HttpGetRequestBody");
349  lua_pushcfunction(luastate, HttpGetResponseBody);
350  lua_setglobal(luastate, "HttpGetResponseBody");
351  return 0;
352 }
353 
354 #endif /* HAVE_LUA */
uint32_t request_headers_raw_len
struct HtpBodyChunk_ * next
bstr * request_uri_normalized
StreamingBufferSegment sbseg
HtpBody request_body
uint8_t * request_headers_raw
HtpBody response_body
StreamingBuffer * sb
HtpBodyChunk * last
#define index
Definition: win32-misc.h:29
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
uint8_t * response_headers_raw
uint32_t response_headers_raw_len
HtpBodyChunk * first