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