28
28
/* Disconnect client when it sends too many bad commands */
29
29
#define CLIENT_MAX_BAD_COMMANDS 3
31
const struct login_binary login_binary = {
33
.process_name = "managesieve-login",
31
struct managesieve_command {
34
(struct managesieve_client *client, const struct managesieve_arg *args);
37
void login_process_preinit(void)
39
login_set_roots = managesieve_login_settings_set_roots;
42
38
/* Skip incoming data until newline is found,
43
39
returns TRUE if newline was found. */
44
40
bool client_skip_line(struct managesieve_client *client)
102
static int cmd_starttls(struct managesieve_client *client)
100
static int cmd_starttls
101
(struct managesieve_client *client,
102
const struct managesieve_arg *args ATTR_UNUSED)
104
104
client_cmd_starttls(&client->common);
108
108
static int cmd_noop
109
(struct managesieve_client *client, struct managesieve_arg *args)
109
(struct managesieve_client *client,
110
const struct managesieve_arg *args)
111
112
const char *text;
112
113
string_t *resp_code;
114
if ( args[0].type == MANAGESIEVE_ARG_EOL ) {
115
if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) {
115
116
client_send_ok(&client->common, "NOOP Completed");
119
if ( args[1].type != MANAGESIEVE_ARG_EOL ) {
120
client_send_no(&client->common, "Too many arguments");
124
if ( (text = managesieve_arg_string(&args[0])) == NULL ) {
120
if ( !MANAGESIEVE_ARG_IS_EOL(&args[1]) )
123
if ( !managesieve_arg_get_string(&args[0], &text) ) {
125
124
client_send_no(&client->common, "Invalid echo tag.");
129
128
resp_code = t_str_new(256);
131
130
managesieve_quote_append_string(resp_code, text, FALSE);
133
132
client_send_okresp(&client->common, str_c(resp_code), "Done");
137
static int cmd_logout(struct managesieve_client *client)
136
static int cmd_logout
137
(struct managesieve_client *client,
138
const struct managesieve_arg *args ATTR_UNUSED)
139
140
client_send_ok(&client->common, "Logout completed.");
140
141
client_destroy(&client->common, "Aborted login");
144
static int client_command_execute
145
(struct managesieve_client *client, const char *cmd,
146
struct managesieve_arg *args)
148
cmd = t_str_ucase(cmd);
149
if (strcmp(cmd, "AUTHENTICATE") == 0)
150
return cmd_authenticate(client, args);
151
if (strcmp(cmd, "CAPABILITY") == 0)
152
return cmd_capability(client);
153
if (strcmp(cmd, "STARTTLS") == 0)
154
return cmd_starttls(client);
155
if (strcmp(cmd, "NOOP") == 0)
156
return cmd_noop(client, args);
157
if (strcmp(cmd, "LOGOUT") == 0)
158
return cmd_logout(client);
145
static struct managesieve_command commands[] = {
146
{ "AUTHENTICATE", cmd_authenticate, 1 },
147
{ "CAPABILITY", cmd_capability, -1 },
148
{ "STARTTLS", cmd_starttls, -1 },
149
{ "NOOP", cmd_noop, 0 },
150
{ "LOGOUT", cmd_logout, -1},
163
154
static bool client_handle_input(struct managesieve_client *client)
165
struct managesieve_arg *args;
156
const struct managesieve_arg *args = NULL;
170
161
i_assert(!client->common.authenticating);
172
163
if (client->cmd_finished) {
173
/* clear the previous command from memory. don't do this
174
immediately after handling command since we need the
175
cmd_tag to stay some time after authentication commands. */
164
/* clear the previous command from memory */
176
165
client->cmd_name = NULL;
166
client->cmd_parsed_args = FALSE;
177
168
managesieve_parser_reset(client->parser);
179
170
/* remove \r\n */
186
177
client->cmd_finished = FALSE;
189
if (client->cmd_name == NULL) {
180
if (client->cmd == NULL) {
181
struct managesieve_command *cmd;
182
const char *cmd_name;
190
184
client->cmd_name = managesieve_parser_read_word(client->parser);
191
185
if (client->cmd_name == NULL)
192
186
return FALSE; /* need more data */
188
cmd_name = t_str_ucase(client->cmd_name);
190
while ( cmd->name != NULL ) {
191
if ( strcmp(cmd->name, cmd_name) == 0 )
196
if ( cmd->name != NULL )
195
switch (managesieve_parser_read_args(client->parser, 0, 0, &args)) {
198
msg = managesieve_parser_get_error(client->parser, &fatal);
200
client_send_bye(&client->common, msg);
201
client_destroy(&client->common, t_strconcat("Disconnected: ",
200
if ( client->cmd != NULL && !client->cmd_parsed_args ) {
201
unsigned int arg_count =
202
( client->cmd->preparsed_args > 0 ? client->cmd->preparsed_args : 0 );
203
switch (managesieve_parser_read_args(client->parser, arg_count, 0, &args)) {
206
msg = managesieve_parser_get_error(client->parser, &fatal);
208
client_send_bye(&client->common, msg);
209
client_destroy(&client->common, t_strconcat("Disconnected: ",
214
client_send_no(&client->common, msg);
215
client->cmd_finished = TRUE;
216
client->skip_line = TRUE;
219
/* not enough data */
206
client_send_no(&client->common, msg);
223
if (arg_count == 0 ) {
224
/* we read the entire line - skip over the CRLF */
225
if (!client_skip_line(client))
228
/* get rid of it later */
229
client->skip_line = TRUE;
232
client->cmd_parsed_args = TRUE;
234
if (client->cmd->preparsed_args == -1) {
235
/* check absence of arguments */
236
if ( args[0].type != MANAGESIEVE_ARG_EOL )
241
if (client->cmd == NULL) {
207
243
client->cmd_finished = TRUE;
208
client->skip_line = TRUE;
211
/* not enough data */
246
ret = client->cmd->func(client, args);
248
client->cmd_finished = TRUE;
214
/* we read the entire line - skip over the CRLF */
215
if (!client_skip_line(client))
218
ret = client_command_execute(client, client->cmd_name, args);
220
client->cmd_finished = TRUE;
222
252
if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
223
253
client_send_bye(&client->common,
282
312
msieve_client->set = other_sets[0];
283
313
msieve_client->parser = managesieve_parser_create
284
(msieve_client->common.input, msieve_client->common.output,
285
MAX_MANAGESIEVE_LINE);
314
(msieve_client->common.input, MAX_MANAGESIEVE_LINE);
286
315
client->io = io_add(client->fd, IO_READ, client_input, client);
314
344
(struct managesieve_client *) client;
316
346
managesieve_parser_destroy(&msieve_client->parser);
317
msieve_client->parser =
318
managesieve_parser_create(msieve_client->common.input,
319
msieve_client->common.output, MAX_MANAGESIEVE_LINE);
347
msieve_client->parser = managesieve_parser_create
348
(msieve_client->common.input, MAX_MANAGESIEVE_LINE);
321
350
/* CRLF is lost from buffer when streams are reopened. */
322
351
msieve_client->skip_line = FALSE;
396
425
_client_send_response(client, prefix, resp_code, text);
399
void clients_init(void)
403
void clients_deinit(void)
428
static void managesieve_login_preinit(void)
430
login_set_roots = managesieve_login_settings_set_roots;
433
static void managesieve_login_init(void)
437
static void managesieve_login_deinit(void)
405
439
clients_destroy_all();
408
struct client_vfuncs client_vfuncs = {
442
static struct client_vfuncs managesieve_client_vfuncs = {
409
443
managesieve_client_alloc,
410
444
managesieve_client_create,
411
445
managesieve_client_destroy,
420
454
managesieve_proxy_parse_line
457
static const struct login_binary managesieve_login_binary = {
459
.process_name = "managesieve-login",
460
.default_port = 4190,
462
.client_vfuncs = &managesieve_client_vfuncs,
463
.preinit = managesieve_login_preinit,
464
.init = managesieve_login_init,
465
.deinit = managesieve_login_deinit
468
int main(int argc, char *argv[])
470
return login_binary_run(&managesieve_login_binary, argc, argv);