suricata
util-lua-smtp.c
Go to the documentation of this file.
1 /* Copyright (C) 2014-2025 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 casec Bachelors group
22  * \author Lauritz Prag Sømme <lauritz24@me.com>
23  * \author Levi Tobiassen <levi.tobiassen@gmail.com>
24  * \author Stian Hoel Bergseth <stian.bergseth@hig.no>
25  * \author Vinjar Hillestad <vinjar.hillestad@hig.no>
26  */
27 
28 #include "suricata-common.h"
29 #include "app-layer-smtp.h"
30 
31 #include "util-lua.h"
32 #include "util-lua-common.h"
33 #include "util-lua-smtp.h"
34 
35 #include "lua.h"
36 #include "lauxlib.h"
37 
38 static const char smtp_tx_mt[] = "suricata:smtp:tx";
39 
40 struct LuaSmtpTx {
42 };
43 
44 static int LuaSmtpGetTx(lua_State *L)
45 {
46  if (!(LuaStateNeedProto(L, ALPROTO_SMTP))) {
47  return LuaCallbackError(L, "error: protocol not SMTP");
48  }
49 
50  Flow *flow = LuaStateGetFlow(L);
51  if (flow == NULL) {
52  return LuaCallbackError(L, "error: no flow found");
53  }
54 
55  SMTPState *state = (SMTPState *)FlowGetAppState(flow);
56  if (state == NULL) {
57  return LuaCallbackError(L, "error: no SMTP state");
58  }
59 
60  SMTPTransaction *tx = state->curr_tx;
61  if (tx == NULL) {
62  return LuaCallbackError(L, "error: no SMTP transaction found");
63  }
64 
65  struct LuaSmtpTx *lua_tx = (struct LuaSmtpTx *)lua_newuserdata(L, sizeof(*lua_tx));
66  if (lua_tx == NULL) {
67  return LuaCallbackError(L, "error: fail to allocate user data");
68  }
69  lua_tx->tx = tx;
70 
71  luaL_getmetatable(L, smtp_tx_mt);
72  lua_setmetatable(L, -2);
73 
74  return 1;
75 }
76 
77 static int LuaSmtpTxGetMimeField(lua_State *L)
78 {
79  struct LuaSmtpTx *tx = luaL_checkudata(L, 1, smtp_tx_mt);
80 
81  if (tx->tx->mime_state == NULL) {
82  return LuaCallbackError(L, "no mime state");
83  }
84 
85  const char *name = luaL_checkstring(L, 2);
86  if (name == NULL) {
87  return LuaCallbackError(L, "2nd argument missing, empty or wrong type");
88  }
89 
90  const uint8_t *field_value;
91  uint32_t field_len;
92  if (SCMimeSmtpGetHeader(tx->tx->mime_state, name, &field_value, &field_len)) {
93  return LuaPushStringBuffer(L, field_value, field_len);
94  }
95 
96  return LuaCallbackError(L, "request mime field not found");
97 }
98 
99 static int LuaSmtpTxGetMimeList(lua_State *L)
100 {
101  struct LuaSmtpTx *tx = luaL_checkudata(L, 1, smtp_tx_mt);
102 
103  if (tx->tx->mime_state == NULL) {
104  return LuaCallbackError(L, "no mime state");
105  }
106 
107  const uint8_t *field_name;
108  uint32_t field_len;
109  int num = 1;
110  lua_newtable(L);
111  while (SCMimeSmtpGetHeaderName(tx->tx->mime_state, &field_name, &field_len, (uint32_t)num)) {
112  if (field_len != 0) {
113  lua_pushinteger(L, num++);
114  LuaPushStringBuffer(L, field_name, field_len);
115  lua_settable(L, -3);
116  }
117  }
118  return 1;
119 }
120 
121 static int LuaSmtpTxGetMailFrom(lua_State *L)
122 {
123  struct LuaSmtpTx *tx = luaL_checkudata(L, 1, smtp_tx_mt);
124 
125  if (tx->tx->mail_from == NULL || tx->tx->mail_from_len == 0) {
126  lua_pushnil(L);
127  return 1;
128  }
129 
130  return LuaPushStringBuffer(L, tx->tx->mail_from, tx->tx->mail_from_len);
131 }
132 
133 static int LuaSmtpTxGetRcptList(lua_State *L)
134 {
135  struct LuaSmtpTx *tx = luaL_checkudata(L, 1, smtp_tx_mt);
136 
137  /* Create a new table in luastate for rcpt list */
138  lua_newtable(L);
139  /* rcpt var for iterator */
140  int u = 1;
141  SMTPString *rcpt;
142 
143  TAILQ_FOREACH (rcpt, &tx->tx->rcpt_to_list, next) {
144  lua_pushinteger(L, u++);
145  LuaPushStringBuffer(L, rcpt->str, rcpt->len);
146  lua_settable(L, -3);
147  }
148 
149  return 1;
150 }
151 
152 static const struct luaL_Reg smtptxlib[] = {
153  { "get_mime_field", LuaSmtpTxGetMimeField },
154  { "get_mime_list", LuaSmtpTxGetMimeList },
155  { "get_mail_from", LuaSmtpTxGetMailFrom },
156  { "get_rcpt_list", LuaSmtpTxGetRcptList },
157  { NULL, NULL },
158 };
159 
160 static const struct luaL_Reg smtplib[] = {
161  { "get_tx", LuaSmtpGetTx },
162  { NULL, NULL },
163 };
164 
166 {
167  luaL_newmetatable(L, smtp_tx_mt);
168  lua_pushvalue(L, -1);
169  lua_setfield(L, -2, "__index");
170  luaL_setfuncs(L, smtptxlib, 0);
171 
172  luaL_newlib(L, smtplib);
173  return 1;
174 }
SMTPState_
Definition: app-layer-smtp.h:116
util-lua-common.h
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
util-lua.h
LuaCallbackError
int LuaCallbackError(lua_State *luastate, const char *msg)
Definition: util-lua-common.c:59
Flow_
Flow data structure.
Definition: flow.h:356
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
LuaSmtpTx::tx
SMTPTransaction * tx
Definition: util-lua-smtp.c:41
lua_State
struct lua_State lua_State
Definition: suricata-common.h:523
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
SMTPTransaction_::mail_from
uint8_t * mail_from
Definition: app-layer-smtp.h:88
SMTPState_::curr_tx
SMTPTransaction * curr_tx
Definition: app-layer-smtp.h:118
SMTPTransaction_
Definition: app-layer-smtp.h:72
name
const char * name
Definition: tm-threads.c:2123
SMTPTransaction_::mail_from_len
uint16_t mail_from_len
Definition: app-layer-smtp.h:89
LuaSmtpTx
Definition: util-lua-smtp.c:40
util-lua-smtp.h
SMTPString_::len
uint16_t len
Definition: app-layer-smtp.h:67
suricata-common.h
SMTPString_
Definition: app-layer-smtp.h:65
SCLuaLoadSmtpLib
int SCLuaLoadSmtpLib(lua_State *L)
Definition: util-lua-smtp.c:165
LuaStateGetFlow
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition: util-lua.c:161
SMTPString_::str
uint8_t * str
Definition: app-layer-smtp.h:66
app-layer-smtp.h
LuaStateNeedProto
int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
Definition: util-lua-common.c:396
LuaPushStringBuffer
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition: util-lua.c:319
SMTPTransaction_::mime_state
MimeStateSMTP * mime_state
Definition: app-layer-smtp.h:85