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

« back to all changes in this revision

Viewing changes to src/login-common/client-common.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:
1
 
/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "login-common.h"
4
4
#include "hostpid.h"
5
5
#include "llist.h"
6
6
#include "istream.h"
7
7
#include "ostream.h"
 
8
#include "iostream-rawlog.h"
8
9
#include "process-title.h"
 
10
#include "buffer.h"
9
11
#include "str.h"
 
12
#include "base64.h"
10
13
#include "str-sanitize.h"
11
14
#include "safe-memset.h"
12
15
#include "var-expand.h"
25
28
 
26
29
static void client_idle_disconnect_timeout(struct client *client)
27
30
{
28
 
        client_send_line(client, CLIENT_CMD_REPLY_BYE,
29
 
                         "Disconnected for inactivity.");
30
 
        client_destroy(client, "Disconnected: Inactivity");
 
31
        const char *user_reason, *destroy_reason;
 
32
        unsigned int secs;
 
33
 
 
34
        if (client->master_tag != 0) {
 
35
                secs = ioloop_time - client->auth_finished;
 
36
                user_reason = "Timeout while finishing login.";
 
37
                destroy_reason = t_strdup_printf(
 
38
                        "Timeout while finishing login (waited %u secs)", secs);
 
39
                client_log_err(client, destroy_reason);
 
40
        } else if (client->auth_request != NULL) {
 
41
                user_reason =
 
42
                        "Disconnected for inactivity during authentication.";
 
43
                destroy_reason =
 
44
                        "Disconnected: Inactivity during authentication";
 
45
        } else if (client->login_proxy != NULL) {
 
46
                secs = ioloop_time - client->created;
 
47
                user_reason = "Timeout while finishing login.";
 
48
                destroy_reason = t_strdup_printf(
 
49
                        "proxy: Logging in to %s:%u timed out "
 
50
                        "(state=%u, duration=%us)",
 
51
                        login_proxy_get_host(client->login_proxy),
 
52
                        login_proxy_get_port(client->login_proxy),
 
53
                        client->proxy_state, secs);
 
54
                client_log_err(client, destroy_reason);
 
55
        } else {
 
56
                user_reason = "Disconnected for inactivity.";
 
57
                destroy_reason = "Disconnected: Inactivity";
 
58
        }
 
59
        client_send_line(client, CLIENT_CMD_REPLY_BYE, user_reason);
 
60
        client_destroy(client, destroy_reason);
31
61
}
32
62
 
33
63
static void client_open_streams(struct client *client)
36
66
                i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
37
67
        client->output =
38
68
                o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
 
69
 
 
70
        if (login_rawlog_dir != NULL) {
 
71
                if (iostream_rawlog_create(login_rawlog_dir, &client->input,
 
72
                                           &client->output) < 0)
 
73
                        login_rawlog_dir = NULL;
 
74
        }
39
75
}
40
76
 
41
77
struct client *
47
83
 
48
84
        i_assert(fd != -1);
49
85
 
50
 
        client = client_vfuncs.alloc(pool);
51
 
        client->v = client_vfuncs;
 
86
        client = login_binary->client_vfuncs->alloc(pool);
 
87
        client->v = *login_binary->client_vfuncs;
52
88
        if (client->v.auth_send_challenge == NULL)
53
89
                client->v.auth_send_challenge = client_auth_send_challenge;
54
90
        if (client->v.auth_parse_response == NULL)
146
182
 
147
183
        if (client->login_proxy != NULL)
148
184
                login_proxy_free(&client->login_proxy);
149
 
        if (client->ssl_proxy != NULL)
150
 
                ssl_proxy_free(&client->ssl_proxy);
151
185
        client->v.destroy(client);
152
 
        if (client_unref(&client) &&
153
 
            master_service_get_service_count(master_service) == 1) {
 
186
        if (client_unref(&client) && initial_service_count == 1) {
154
187
                /* as soon as this connection is done with proxying
155
188
                   (or whatever), the process will die. there's no need for
156
 
                   authentication anymore, so close the connection. */
157
 
                auth_client_disconnect(auth_client);
 
189
                   authentication anymore, so close the connection.
 
190
                   do this only with initial service_count=1, in case there
 
191
                   are other clients with pending authentications */
 
192
                auth_client_disconnect(auth_client, "unnecessary connection");
158
193
        }
159
194
        login_client_destroyed();
160
195
        login_refresh_proctitle();
192
227
        *_client = NULL;
193
228
 
194
229
        i_assert(client->destroyed);
195
 
        i_assert(client->ssl_proxy == NULL);
196
230
        i_assert(client->login_proxy == NULL);
197
231
 
 
232
        if (client->ssl_proxy != NULL)
 
233
                ssl_proxy_free(&client->ssl_proxy);
198
234
        if (client->input != NULL)
199
235
                i_stream_unref(&client->input);
200
236
        if (client->output != NULL)
204
240
        i_free(client->proxy_master_user);
205
241
        i_free(client->virtual_user);
206
242
        i_free(client->auth_mech_name);
 
243
        i_free(client->master_data_prefix);
207
244
        pool_unref(&client->pool);
208
245
 
209
246
        i_assert(clients_count > 0);
236
273
        client_destroy(client, "Disconnected: Connection queue full");
237
274
}
238
275
 
239
 
void clients_destroy_all(void)
 
276
void clients_destroy_all_reason(const char *reason)
240
277
{
241
278
        struct client *client, *next;
242
279
 
243
280
        for (client = clients; client != NULL; client = next) {
244
281
                next = client->next;
245
 
                client_destroy(client, "Disconnected: Shutting down");
 
282
                client_destroy(client, reason);
246
283
        }
247
284
}
248
285
 
 
286
void clients_destroy_all(void)
 
287
{
 
288
        clients_destroy_all_reason("Disconnected: Shutting down");
 
289
}
 
290
 
249
291
static void client_start_tls(struct client *client)
250
292
{
251
293
        int fd_ssl;
254
296
        if (!client_unref(&client) || client->destroyed)
255
297
                return;
256
298
 
257
 
        fd_ssl = ssl_proxy_alloc(client->fd, &client->ip,
 
299
        fd_ssl = ssl_proxy_alloc(client->fd, &client->ip, client->pool,
258
300
                                 client->set, &client->ssl_proxy);
259
301
        if (fd_ssl == -1) {
260
302
                client_send_line(client, CLIENT_CMD_REPLY_BYE,
336
378
        return clients_count;
337
379
}
338
380
 
 
381
const char *client_get_session_id(struct client *client)
 
382
{
 
383
        buffer_t *buf, *base64_buf;
 
384
        struct timeval tv;
 
385
        uint64_t timestamp;
 
386
        unsigned int i;
 
387
 
 
388
        if (client->session_id != NULL)
 
389
                return client->session_id;
 
390
 
 
391
        buf = buffer_create_dynamic(pool_datastack_create(), 24);
 
392
        base64_buf = buffer_create_dynamic(pool_datastack_create(), 24*2);
 
393
 
 
394
        if (gettimeofday(&tv, NULL) < 0)
 
395
                i_fatal("gettimeofday(): %m");
 
396
        timestamp = tv.tv_usec + (long long)tv.tv_sec * 1000ULL*1000ULL;
 
397
 
 
398
        /* add lowest 48 bits of the timestamp. this gives us a bit less than
 
399
           9 years until it wraps */
 
400
        for (i = 0; i < 48; i += 8)
 
401
                buffer_append_c(buf, (timestamp >> i) & 0xff);
 
402
 
 
403
        buffer_append_c(buf, client->remote_port & 0xff);
 
404
        buffer_append_c(buf, (client->remote_port >> 16) & 0xff);
 
405
#ifdef HAVE_IPV6
 
406
        if (IPADDR_IS_V6(&client->ip))
 
407
                buffer_append(buf, &client->ip.u.ip6, sizeof(client->ip.u.ip6));
 
408
        else
 
409
#endif
 
410
                buffer_append(buf, &client->ip.u.ip4, sizeof(client->ip.u.ip4));
 
411
        base64_encode(buf->data, buf->used, base64_buf);
 
412
        client->session_id = p_strdup(client->pool, str_c(base64_buf));
 
413
        return client->session_id;
 
414
}
 
415
 
 
416
static struct var_expand_table login_var_expand_empty_tab[] = {
 
417
        { 'u', NULL, "user" },
 
418
        { 'n', NULL, "username" },
 
419
        { 'd', NULL, "domain" },
 
420
        { 's', NULL, "service" },
 
421
        { 'h', NULL, "home" },
 
422
        { 'l', NULL, "lip" },
 
423
        { 'r', NULL, "rip" },
 
424
        { 'p', NULL, "pid" },
 
425
        { 'm', NULL, "mech" },
 
426
        { 'a', NULL, "lport" },
 
427
        { 'b', NULL, "rport" },
 
428
        { 'c', NULL, "secured" },
 
429
        { 'k', NULL, "ssl_security" },
 
430
        { 'e', NULL, "mail_pid" },
 
431
        { '\0', NULL, "session" },
 
432
        { '\0', NULL, NULL }
 
433
};
 
434
 
339
435
static const struct var_expand_table *
340
436
get_var_expand_table(struct client *client)
341
437
{
342
 
        static struct var_expand_table static_tab[] = {
343
 
                { 'u', NULL, "user" },
344
 
                { 'n', NULL, "username" },
345
 
                { 'd', NULL, "domain" },
346
 
                { 's', NULL, "service" },
347
 
                { 'h', NULL, "home" },
348
 
                { 'l', NULL, "lip" },
349
 
                { 'r', NULL, "rip" },
350
 
                { 'p', NULL, "pid" },
351
 
                { 'm', NULL, "mech" },
352
 
                { 'a', NULL, "lport" },
353
 
                { 'b', NULL, "rport" },
354
 
                { 'c', NULL, "secured" },
355
 
                { 'k', NULL, "ssl_security" },
356
 
                { 'e', NULL, "mail_pid" },
357
 
                { '\0', NULL, NULL }
358
 
        };
359
438
        struct var_expand_table *tab;
360
439
        unsigned int i;
361
440
 
362
 
        tab = t_malloc(sizeof(static_tab));
363
 
        memcpy(tab, static_tab, sizeof(static_tab));
 
441
        tab = t_malloc(sizeof(login_var_expand_empty_tab));
 
442
        memcpy(tab, login_var_expand_empty_tab,
 
443
               sizeof(login_var_expand_empty_tab));
364
444
 
365
445
        if (client->virtual_user != NULL) {
366
446
                tab[0].value = client->virtual_user;
371
451
                for (i = 0; i < 3; i++)
372
452
                        tab[i].value = str_sanitize(tab[i].value, 80);
373
453
        }
374
 
        tab[3].value = login_binary.protocol;
 
454
        tab[3].value = login_binary->protocol;
375
455
        tab[4].value = getenv("HOME");
376
456
        tab[5].value = net_ip2addr(&client->local_ip);
377
457
        tab[6].value = net_ip2addr(&client->ip);
397
477
        }
398
478
        tab[13].value = client->mail_pid == 0 ? "" :
399
479
                dec2str(client->mail_pid);
 
480
        tab[14].value = client_get_session_id(client);
400
481
        return tab;
401
482
}
402
483
 
403
 
static bool have_key(const struct var_expand_table *table, const char *str)
 
484
static bool have_username_key(const char *str)
404
485
{
405
486
        char key;
406
 
        unsigned int i;
407
487
 
408
 
        key = var_get_key(str);
409
 
        for (i = 0; table[i].key != '\0'; i++) {
410
 
                if (table[i].key == key) {
411
 
                        return table[i].value != NULL &&
412
 
                                table[i].value[0] != '\0';
 
488
        for (; *str != '\0'; str++) {
 
489
                if (str[0] == '%' && str[1] != '\0') {
 
490
                        str++;
 
491
                        key = var_get_key(str);
 
492
                        if (key == 'u' || key == 'n')
 
493
                                return TRUE;
413
494
                }
414
495
        }
415
496
        return FALSE;
425
506
        };
426
507
        const struct var_expand_table *var_expand_table;
427
508
        struct var_expand_table *tab;
428
 
        const char *p;
429
509
        char *const *e;
430
 
        string_t *str;
 
510
        string_t *str, *str2;
 
511
        unsigned int pos;
431
512
 
432
513
        var_expand_table = get_var_expand_table(client);
433
514
 
435
516
        memcpy(tab, static_tab, sizeof(static_tab));
436
517
 
437
518
        str = t_str_new(256);
 
519
        str2 = t_str_new(128);
438
520
        for (e = client->set->log_format_elements_split; *e != NULL; e++) {
439
 
                for (p = *e; *p != '\0'; p++) {
440
 
                        if (*p != '%' || p[1] == '\0')
 
521
                pos = str_len(str);
 
522
                var_expand(str, *e, var_expand_table);
 
523
                if (have_username_key(*e)) {
 
524
                        /* username is added even if it's empty */
 
525
                } else {
 
526
                        str_truncate(str2, 0);
 
527
                        var_expand(str2, *e, login_var_expand_empty_tab);
 
528
                        if (strcmp(str_c(str)+pos, str_c(str2)) == 0) {
 
529
                                /* empty %variables, don't add */
 
530
                                str_truncate(str, pos);
441
531
                                continue;
442
 
 
443
 
                        p++;
444
 
                        if (have_key(var_expand_table, p)) {
445
 
                                if (str_len(str) > 0)
446
 
                                        str_append(str, ", ");
447
 
                                var_expand(str, *e, var_expand_table);
448
 
                                break;
449
532
                        }
450
533
                }
 
534
 
 
535
                if (str_len(str) > 0)
 
536
                        str_append(str, ", ");
451
537
        }
452
538
 
 
539
        if (str_len(str) > 0)
 
540
                str_truncate(str, str_len(str)-2);
 
541
 
453
542
        tab[0].value = t_strdup(str_c(str));
454
543
        tab[1].value = msg;
455
544
        str_truncate(str, 0);
472
561
        } T_END;
473
562
}
474
563
 
 
564
void client_log_warn(struct client *client, const char *msg)
 
565
{
 
566
        T_BEGIN {
 
567
                i_warning("%s", client_get_log_str(client, msg));
 
568
        } T_END;
 
569
}
 
570
 
475
571
bool client_is_trusted(struct client *client)
476
572
{
477
573
        const char *const *net;
497
593
 
498
594
const char *client_get_extra_disconnect_reason(struct client *client)
499
595
{
 
596
        unsigned int auth_secs = client->auth_first_started == 0 ? 0 :
 
597
                ioloop_time - client->auth_first_started;
 
598
 
500
599
        if (client->set->auth_ssl_require_client_cert &&
501
600
            client->ssl_proxy != NULL) {
502
601
                if (ssl_proxy_has_broken_client_cert(client->ssl_proxy))
505
604
                        return "(client didn't send a cert)";
506
605
        }
507
606
 
508
 
        if (client->auth_attempts == 0)
509
 
                return "(no auth attempts)";
 
607
        if (!client->greeting_sent)
 
608
                return t_strdup_printf(
 
609
                        "(disconnected before greeting, waited %u secs)",
 
610
                        (unsigned int)(ioloop_time - client->created));
 
611
 
 
612
        if (client->auth_attempts == 0) {
 
613
                return t_strdup_printf("(no auth attempts in %u secs)",
 
614
                        (unsigned int)(ioloop_time - client->created));
 
615
        }
510
616
 
511
617
        /* some auth attempts without SSL/TLS */
512
618
        if (client->auth_tried_disabled_plaintext)
513
 
                return "(tried to use disabled plaintext auth)";
 
619
                return "(tried to use disallowed plaintext auth)";
514
620
        if (client->set->auth_ssl_require_client_cert &&
515
621
            client->ssl_proxy == NULL)
516
622
                return "(cert required, client didn't start TLS)";
517
623
        if (client->auth_tried_unsupported_mech)
518
624
                return "(tried to use unsupported auth mechanism)";
519
 
        if (client->auth_request != NULL && client->auth_attempts == 1)
520
 
                return "(disconnected while authenticating)";
 
625
        if (client->auth_waiting && client->auth_attempts == 1) {
 
626
                return t_strdup_printf("(client didn't finish SASL auth, "
 
627
                                       "waited %u secs)", auth_secs);
 
628
        }
 
629
        if (client->auth_request != NULL && client->auth_attempts == 1) {
 
630
                return t_strdup_printf("(disconnected while authenticating, "
 
631
                                       "waited %u secs)", auth_secs);
 
632
        }
 
633
        if (client->authenticating && client->auth_attempts == 1) {
 
634
                return t_strdup_printf("(disconnected while finishing login, "
 
635
                                       "waited %u secs)", auth_secs);
 
636
        }
521
637
        if (client->auth_try_aborted && client->auth_attempts == 1)
522
638
                return "(aborted authentication)";
 
639
        if (client->auth_process_comm_fail)
 
640
                return "(auth process communication failure)";
523
641
 
524
 
        return t_strdup_printf("(auth failed, %u attempts)",
525
 
                               client->auth_attempts);
 
642
        if (client->proxy_auth_failed)
 
643
                return "(proxy dest auth failed)";
 
644
        if (client->auth_successes > 0) {
 
645
                return t_strdup_printf("(internal failure, %u succesful auths)",
 
646
                                       client->auth_successes);
 
647
        }
 
648
        if (client->auth_user_disabled)
 
649
                return "(user disabled)";
 
650
        if (client->auth_pass_expired)
 
651
                return "(password expired)";
 
652
        return t_strdup_printf("(auth failed, %u attempts in %u secs)",
 
653
                               client->auth_attempts, auth_secs);
526
654
}
527
655
 
528
656
void client_send_line(struct client *client, enum client_cmd_reply reply,