~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to pigeonhole/src/managesieve-login/client.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/{control,rules}: enable PIE hardening.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
/* Disconnect client when it sends too many bad commands */
29
29
#define CLIENT_MAX_BAD_COMMANDS 3
30
30
 
31
 
const struct login_binary login_binary = {
32
 
        .protocol = "sieve",
33
 
        .process_name = "managesieve-login",
34
 
        .default_port = 4190
 
31
struct managesieve_command {
 
32
        const char *name;
 
33
        int (*func)
 
34
                (struct managesieve_client *client, const struct managesieve_arg *args);
 
35
        int preparsed_args;
35
36
};
36
37
 
37
 
void login_process_preinit(void)
38
 
{
39
 
        login_set_roots = managesieve_login_settings_set_roots;
40
 
}
41
 
 
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)
87
83
        } T_END;
88
84
}
89
85
 
90
 
static int cmd_capability(struct managesieve_client *client)
 
86
static int cmd_capability
 
87
(struct managesieve_client *client,
 
88
        const struct managesieve_arg *args ATTR_UNUSED)
91
89
{
92
90
        o_stream_cork(client->common.output);
93
91
 
99
97
        return 1;
100
98
}
101
99
 
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)
103
103
{
104
104
        client_cmd_starttls(&client->common);
105
105
        return 1;
106
106
}
107
107
 
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)
110
111
{
111
112
        const char *text;
112
113
        string_t *resp_code;
113
114
 
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");
116
 
                return TRUE;
117
 
        }
118
 
 
119
 
        if ( args[1].type != MANAGESIEVE_ARG_EOL ) {
120
 
                client_send_no(&client->common, "Too many arguments");
121
 
                return TRUE;
122
 
        }
123
 
 
124
 
        if ( (text = managesieve_arg_string(&args[0])) == NULL ) {
 
117
                return 1;
 
118
        }
 
119
 
 
120
        if ( !MANAGESIEVE_ARG_IS_EOL(&args[1]) )
 
121
                return -1;
 
122
 
 
123
        if ( !managesieve_arg_get_string(&args[0], &text) ) {
125
124
                client_send_no(&client->common, "Invalid echo tag.");
126
 
                return TRUE;
 
125
                return 1;
127
126
        }
128
127
 
129
128
        resp_code = t_str_new(256);
131
130
        managesieve_quote_append_string(resp_code, text, FALSE);
132
131
 
133
132
        client_send_okresp(&client->common, str_c(resp_code), "Done");
134
 
        return TRUE;
 
133
        return 1;
135
134
}
136
135
 
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)
138
139
{
139
140
        client_send_ok(&client->common, "Logout completed.");
140
141
        client_destroy(&client->common, "Aborted login");
141
142
        return 1;
142
143
}
143
144
 
144
 
static int client_command_execute
145
 
(struct managesieve_client *client, const char *cmd, 
146
 
        struct managesieve_arg *args)
147
 
{
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);
159
 
 
160
 
        return -1;
161
 
}
 
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},
 
151
        { NULL, NULL, 0}
 
152
};
162
153
 
163
154
static bool client_handle_input(struct managesieve_client *client)
164
155
{
165
 
        struct managesieve_arg *args;
 
156
        const struct managesieve_arg *args = NULL;
166
157
        const char *msg;
167
 
        int ret;
 
158
        int ret = 1;
168
159
        bool fatal;
169
160
 
170
161
        i_assert(!client->common.authenticating);
171
162
 
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;
 
167
                client->cmd = NULL;
177
168
                managesieve_parser_reset(client->parser);
178
169
 
179
170
                /* remove \r\n */
186
177
                client->cmd_finished = FALSE;
187
178
        }
188
179
 
189
 
        if (client->cmd_name == NULL) {
 
180
        if (client->cmd == NULL) {
 
181
                struct managesieve_command *cmd;
 
182
                const char *cmd_name;
 
183
                
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 */
 
187
 
 
188
                cmd_name = t_str_ucase(client->cmd_name);
 
189
                cmd = commands;
 
190
                while ( cmd->name != NULL ) {
 
191
                        if ( strcmp(cmd->name, cmd_name) == 0 )
 
192
                                break;
 
193
                        cmd++;
 
194
                }
 
195
        
 
196
                if ( cmd->name != NULL )
 
197
                        client->cmd = cmd;
193
198
        }
194
199
 
195
 
        switch (managesieve_parser_read_args(client->parser, 0, 0, &args)) {
196
 
        case -1:
197
 
                /* error */
198
 
                msg = managesieve_parser_get_error(client->parser, &fatal);
199
 
                if (fatal) {
200
 
                        client_send_bye(&client->common, msg);
201
 
                        client_destroy(&client->common, t_strconcat("Disconnected: ",
202
 
                                msg, NULL));
 
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)) {
 
204
                case -1:
 
205
                        /* error */
 
206
                        msg = managesieve_parser_get_error(client->parser, &fatal);
 
207
                        if (fatal) {
 
208
                                client_send_bye(&client->common, msg);
 
209
                                client_destroy(&client->common, t_strconcat("Disconnected: ",
 
210
                                        msg, NULL));
 
211
                                return FALSE;
 
212
                        }
 
213
 
 
214
                        client_send_no(&client->common, msg);
 
215
                        client->cmd_finished = TRUE;
 
216
                        client->skip_line = TRUE;
 
217
                        return TRUE;
 
218
                case -2:
 
219
                        /* not enough data */
203
220
                        return FALSE;
204
221
                }
205
222
 
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))
 
226
                                i_unreached();
 
227
                } else {
 
228
                        /* get rid of it later */
 
229
                        client->skip_line = TRUE;
 
230
                }
 
231
 
 
232
                client->cmd_parsed_args = TRUE;
 
233
 
 
234
                if (client->cmd->preparsed_args == -1) {
 
235
                        /* check absence of arguments */
 
236
                        if ( args[0].type != MANAGESIEVE_ARG_EOL )
 
237
                                ret = -1;
 
238
                }
 
239
        }
 
240
 
 
241
        if (client->cmd == NULL) {
 
242
                ret = -1;
207
243
                client->cmd_finished = TRUE;
208
 
                client->skip_line = TRUE;
209
 
                return TRUE;
210
 
        case -2:
211
 
                /* not enough data */
212
 
                return FALSE;
 
244
        } else {
 
245
                if (ret > 0)
 
246
                        ret = client->cmd->func(client, args);
 
247
                if (ret != 0)
 
248
                        client->cmd_finished = TRUE;
213
249
        }
214
 
        /* we read the entire line - skip over the CRLF */
215
 
        if (!client_skip_line(client))
216
 
                i_unreached();
217
 
 
218
 
        ret = client_command_execute(client, client->cmd_name, args);
219
 
 
220
 
        client->cmd_finished = TRUE;
 
250
 
221
251
        if (ret < 0) {
222
252
                if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
223
253
                        client_send_bye(&client->common,        
281
311
 
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);
287
316
}
288
317
 
306
335
        client_send_ok(client, client->set->login_greeting);
307
336
 
308
337
        o_stream_uncork(client->output);
 
338
        client->greeting_sent = TRUE;
309
339
}
310
340
 
311
341
static void managesieve_client_starttls(struct client *client)
314
344
                (struct managesieve_client *) client;
315
345
 
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);
320
349
 
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);
397
426
}
398
427
 
399
 
void clients_init(void)
400
 
{
401
 
}
402
 
 
403
 
void clients_deinit(void)
 
428
static void managesieve_login_preinit(void)
 
429
{
 
430
        login_set_roots = managesieve_login_settings_set_roots;
 
431
}
 
432
 
 
433
static void managesieve_login_init(void)
 
434
{
 
435
}
 
436
 
 
437
static void managesieve_login_deinit(void)
404
438
{
405
439
        clients_destroy_all();
406
440
}
407
441
 
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
421
455
};
422
456
 
423
 
 
 
457
static const struct login_binary managesieve_login_binary = {
 
458
        .protocol = "sieve",
 
459
        .process_name = "managesieve-login",
 
460
        .default_port = 4190,
 
461
 
 
462
        .client_vfuncs = &managesieve_client_vfuncs,
 
463
        .preinit = managesieve_login_preinit,
 
464
        .init = managesieve_login_init,
 
465
        .deinit = managesieve_login_deinit
 
466
};
 
467
 
 
468
int main(int argc, char *argv[])
 
469
{
 
470
        return login_binary_run(&managesieve_login_binary, argc, argv);
 
471
}