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

« back to all changes in this revision

Viewing changes to src/lib-storage/mail-storage-service.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) 2009-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "ioloop.h"
38
38
#define ERRSTR_INVALID_USER_SETTINGS \
39
39
        "Invalid user settings. Refer to server log for more information."
40
40
 
 
41
struct mail_storage_service_privileges {
 
42
        uid_t uid;
 
43
        gid_t gid;
 
44
        const char *uid_source, *gid_source;
 
45
 
 
46
        const char *home;
 
47
        const char *chroot;
 
48
};
 
49
 
41
50
struct mail_storage_service_ctx {
42
51
        pool_t pool;
43
52
        struct master_service *service;
 
53
        const char *default_log_prefix;
 
54
 
44
55
        struct auth_master_connection *conn;
45
56
        struct auth_master_user_list_ctx *auth_list;
46
57
        const struct setting_parser_info **set_roots;
55
66
 
56
67
struct mail_storage_service_user {
57
68
        pool_t pool;
 
69
        struct mail_storage_service_ctx *service_ctx;
58
70
        struct mail_storage_service_input input;
59
71
        enum mail_storage_service_flags flags;
60
72
 
 
73
        struct ioloop_context *ioloop_ctx;
 
74
        const char *log_prefix;
 
75
 
61
76
        const char *system_groups_user, *uid_source, *gid_source;
62
77
        const struct mail_user_settings *user_set;
63
78
        const struct setting_parser_info *user_info;
157
172
 
158
173
        ret = settings_parse_line(set_parser, line);
159
174
        if (mail_debug && ret >= 0) {
 
175
                if (strstr(key, "pass") != NULL) {
 
176
                        /* possibly a password field (e.g. imapc_password).
 
177
                           hide the value. */
 
178
                        line = t_strconcat(key, "=<hidden>", NULL);
 
179
                }
160
180
                i_debug(ret == 0 ?
161
181
                        "Unknown userdb setting: %s" :
162
182
                        "Added userdb setting: %s", line);
233
253
        }
234
254
 
235
255
        str = array_get(&reply->extra_fields, &count);
236
 
        for (i = 0; i < count && ret >= 0; i++) {
 
256
        for (i = 0; i < count; i++) {
237
257
                line = str[i];
238
258
                if (strncmp(line, "system_groups_user=", 19) == 0) {
239
259
                        user->system_groups_user =
250
270
                } else T_BEGIN {
251
271
                        ret = set_line(ctx, user, line);
252
272
                } T_END;
 
273
                if (ret < 0)
 
274
                        break;
253
275
        }
254
276
 
255
277
        if (ret < 0) {
337
359
        }
338
360
}
339
361
 
 
362
static const struct var_expand_table *
 
363
get_var_expand_table(struct master_service *service,
 
364
                     struct mail_storage_service_input *input,
 
365
                     struct mail_storage_service_privileges *priv)
 
366
{
 
367
        static struct var_expand_table static_tab[] = {
 
368
                { 'u', NULL, "user" },
 
369
                { 'n', NULL, "username" },
 
370
                { 'd', NULL, "domain" },
 
371
                { 's', NULL, "service" },
 
372
                { 'l', NULL, "lip" },
 
373
                { 'r', NULL, "rip" },
 
374
                { 'p', NULL, "pid" },
 
375
                { 'i', NULL, "uid" },
 
376
                { '\0', NULL, "gid" },
 
377
                { '\0', NULL, "session" },
 
378
                { '\0', NULL, NULL }
 
379
        };
 
380
        struct var_expand_table *tab;
 
381
 
 
382
        tab = t_malloc(sizeof(static_tab));
 
383
        memcpy(tab, static_tab, sizeof(static_tab));
 
384
 
 
385
        tab[0].value = input->username;
 
386
        tab[1].value = t_strcut(input->username, '@');
 
387
        tab[2].value = strchr(input->username, '@');
 
388
        if (tab[2].value != NULL) tab[2].value++;
 
389
        tab[3].value = service->name;
 
390
        tab[4].value = net_ip2addr(&input->local_ip);
 
391
        tab[5].value = net_ip2addr(&input->remote_ip);
 
392
        tab[6].value = my_pid;
 
393
        tab[7].value = dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
 
394
        tab[8].value = dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
 
395
        tab[9].value = input->session_id;
 
396
        return tab;
 
397
}
 
398
 
 
399
const struct var_expand_table *
 
400
mail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx,
 
401
                                          struct mail_storage_service_input *input)
 
402
{
 
403
        struct mail_storage_service_privileges priv;
 
404
 
 
405
        memset(&priv, 0, sizeof(priv));
 
406
        priv.uid = (uid_t)-1;
 
407
        priv.gid = (gid_t)-1;
 
408
        return get_var_expand_table(ctx->service, input, &priv);
 
409
}
 
410
 
 
411
static const char *
 
412
user_expand_varstr(struct master_service *service,
 
413
                   struct mail_storage_service_input *input,
 
414
                   struct mail_storage_service_privileges *priv,
 
415
                   const char *str)
 
416
{
 
417
        string_t *ret;
 
418
 
 
419
        if (*str == SETTING_STRVAR_EXPANDED[0])
 
420
                return str + 1;
 
421
 
 
422
        i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
 
423
 
 
424
        ret = t_str_new(256);
 
425
        var_expand(ret, str + 1, get_var_expand_table(service, input, priv));
 
426
        return str_c(ret);
 
427
}
 
428
 
 
429
static int
 
430
service_parse_privileges(struct mail_storage_service_ctx *ctx,
 
431
                         struct mail_storage_service_user *user,
 
432
                         struct mail_storage_service_privileges *priv_r,
 
433
                         const char **error_r)
 
434
{
 
435
        const struct mail_user_settings *set = user->user_set;
 
436
        uid_t uid = (uid_t)-1;
 
437
        gid_t gid = (gid_t)-1;
 
438
 
 
439
        memset(priv_r, 0, sizeof(*priv_r));
 
440
        if (*set->mail_uid != '\0') {
 
441
                if (!parse_uid(set->mail_uid, &uid, error_r)) {
 
442
                        *error_r = t_strdup_printf("%s (from %s)", *error_r,
 
443
                                                   user->uid_source);
 
444
                        return -1;
 
445
                }
 
446
                if (uid < (uid_t)set->first_valid_uid ||
 
447
                    (set->last_valid_uid != 0 &&
 
448
                     uid > (uid_t)set->last_valid_uid)) {
 
449
                        *error_r = t_strdup_printf(
 
450
                                "Mail access for users with UID %s not permitted "
 
451
                                "(see first_valid_uid in config file, uid from %s).",
 
452
                                dec2str(uid), user->uid_source);
 
453
                        return -1;
 
454
                }
 
455
        }
 
456
        priv_r->uid = uid;
 
457
        priv_r->uid_source = user->uid_source;
 
458
 
 
459
        if (*set->mail_gid != '\0') {
 
460
                if (!parse_gid(set->mail_gid, &gid, error_r)) {
 
461
                        *error_r = t_strdup_printf("%s (from %s)", *error_r,
 
462
                                                   user->gid_source);
 
463
                        return -1;
 
464
                }
 
465
                if (gid < (gid_t)set->first_valid_gid ||
 
466
                    (set->last_valid_gid != 0 &&
 
467
                     gid > (gid_t)set->last_valid_gid)) {
 
468
                        *error_r = t_strdup_printf(
 
469
                                "Mail access for users with GID %s not permitted "
 
470
                                "(see first_valid_gid in config file, gid from %s).",
 
471
                                dec2str(gid), user->gid_source);
 
472
                        return -1;
 
473
                }
 
474
        }
 
475
        priv_r->gid = gid;
 
476
        priv_r->gid_source = user->gid_source;
 
477
 
 
478
        /* variable strings are expanded in mail_user_init(),
 
479
           but we need the home and chroot sooner so do them separately here. */
 
480
        priv_r->home = user_expand_varstr(ctx->service, &user->input, priv_r,
 
481
                                          user->user_set->mail_home);
 
482
        priv_r->chroot = user_expand_varstr(ctx->service, &user->input, priv_r,
 
483
                                            user->user_set->mail_chroot);
 
484
        return 0;
 
485
}
 
486
 
340
487
static int
341
488
service_drop_privileges(struct mail_storage_service_user *user,
342
 
                        const struct mail_user_settings *set,
343
 
                        const char *home, const char *chroot,
 
489
                        struct mail_storage_service_privileges *priv,
344
490
                        bool disallow_root, bool keep_setuid_root,
345
491
                        bool setenv_only, const char **error_r)
346
492
{
 
493
        const struct mail_user_settings *set = user->user_set;
347
494
        struct restrict_access_settings rset;
348
495
        uid_t current_euid, setuid_uid = 0;
349
496
        const char *cur_chroot, *error;
351
498
        current_euid = geteuid();
352
499
        restrict_access_init(&rset);
353
500
        restrict_access_get_env(&rset);
354
 
        if (*set->mail_uid != '\0') {
355
 
                if (!parse_uid(set->mail_uid, &rset.uid, &error)) {
356
 
                        *error_r = t_strdup_printf("%s (from %s)", error,
357
 
                                                   user->uid_source);
358
 
                        return -1;
359
 
                }
360
 
                if (rset.uid < (uid_t)set->first_valid_uid ||
361
 
                    (set->last_valid_uid != 0 &&
362
 
                     rset.uid > (uid_t)set->last_valid_uid)) {
363
 
                        *error_r = t_strdup_printf(
364
 
                                "Mail access for users with UID %s not permitted "
365
 
                                "(see first_valid_uid in config file, uid from %s).",
366
 
                                dec2str(rset.uid), user->uid_source);
367
 
                        return -1;
368
 
                }
369
 
                rset.uid_source = user->uid_source;
 
501
        if (priv->uid != (uid_t)-1) {
 
502
                rset.uid = priv->uid;
 
503
                rset.uid_source = priv->uid_source;
370
504
        } else if (rset.uid == (uid_t)-1 &&
371
 
                   disallow_root && current_euid == 0) {
 
505
                 disallow_root && current_euid == 0) {
372
506
                *error_r = "User is missing UID (see mail_uid setting)";
373
507
                return -1;
374
508
        }
375
 
        if (*set->mail_gid != '\0') {
376
 
                if (!parse_gid(set->mail_gid, &rset.gid, &error)) {
377
 
                        *error_r = t_strdup_printf("%s (from %s)", error,
378
 
                                                   user->gid_source);
379
 
                        return -1;
380
 
                }
381
 
                if (rset.gid < (gid_t)set->first_valid_gid ||
382
 
                    (set->last_valid_gid != 0 &&
383
 
                     rset.gid > (gid_t)set->last_valid_gid)) {
384
 
                        *error_r = t_strdup_printf(
385
 
                                "Mail access for users with GID %s not permitted "
386
 
                                "(see first_valid_gid in config file, gid from %s).",
387
 
                                dec2str(rset.gid), user->gid_source);
388
 
                        return -1;
389
 
                }
390
 
                rset.gid_source = user->gid_source;
 
509
        if (priv->gid != (gid_t)-1) {
 
510
                rset.gid = priv->gid;
 
511
                rset.gid_source = priv->gid_source;
391
512
        } else if (rset.gid == (gid_t)-1 && disallow_root &&
392
513
                   set->first_valid_gid > 0 && getegid() == 0) {
393
514
                *error_r = "User is missing GID (see mail_gid setting)";
408
529
 
409
530
        rset.first_valid_gid = set->first_valid_gid;
410
531
        rset.last_valid_gid = set->last_valid_gid;
411
 
        rset.chroot_dir = *chroot == '\0' ? NULL : chroot;
 
532
        rset.chroot_dir = *priv->chroot == '\0' ? NULL : priv->chroot;
412
533
        rset.system_groups_user = user->system_groups_user;
413
534
 
414
535
        cur_chroot = restrict_access_get_current_chroot();
422
543
                if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
423
544
                        *error_r = t_strdup_printf(
424
545
                                "Process is already chrooted to %s, "
425
 
                                "can't chroot to %s", cur_chroot, chroot);
 
546
                                "can't chroot to %s", cur_chroot, priv->chroot);
426
547
                        return -1;
427
548
                }
428
549
                /* chrooting to same directory where we're already chrooted */
449
570
                disallow_root = FALSE;
450
571
        }
451
572
        if (!setenv_only) {
452
 
                restrict_access(&rset, *home == '\0' ? NULL : home,
 
573
                restrict_access(&rset, *priv->home == '\0' ? NULL : priv->home,
453
574
                                disallow_root);
454
575
        } else {
455
576
                restrict_access_set_env(&rset);
464
585
static int
465
586
mail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
466
587
                               struct mail_storage_service_user *user,
467
 
                               const char *home, struct mail_user **mail_user_r,
 
588
                               struct mail_storage_service_privileges *priv,
 
589
                               struct mail_user **mail_user_r,
468
590
                               const char **error_r)
469
591
{
470
592
        const struct mail_storage_settings *mail_set;
 
593
        const char *home = priv->home;
471
594
        struct mail_user *mail_user;
472
595
 
473
596
        mail_user = mail_user_alloc(user->input.username, user->user_info,
474
597
                                    user->user_set);
475
598
        mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
476
 
        mail_user_set_vars(mail_user, geteuid(), ctx->service->name,
 
599
        mail_user_set_vars(mail_user, ctx->service->name,
477
600
                           &user->input.local_ip, &user->input.remote_ip);
 
601
        mail_user->uid = priv->uid == (uid_t)-1 ? geteuid() : priv->uid;
 
602
        mail_user->gid = priv->gid == (gid_t)-1 ? getegid() : priv->gid;
478
603
 
479
604
        mail_set = mail_user_set_get_storage_set(mail_user);
480
605
 
481
606
        if (mail_set->mail_debug) {
482
 
                i_debug("Effective uid=%s, gid=%s, home=%s",
483
 
                        dec2str(geteuid()), dec2str(getegid()), home);
 
607
                string_t *str = t_str_new(64);
 
608
 
 
609
                str_printfa(str, "Effective uid=%s, gid=%s, home=%s",
 
610
                            dec2str(geteuid()), dec2str(getegid()), home);
 
611
                if (*priv->chroot != '\0')
 
612
                        str_printfa(str, ", chroot=%s", priv->chroot);
 
613
                i_debug("%s", str_c(str));
484
614
        }
485
615
 
486
616
        if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
517
647
        return 0;
518
648
}
519
649
 
520
 
static const struct var_expand_table *
521
 
get_var_expand_table(struct master_service *service,
522
 
                     struct mail_storage_service_input *input)
 
650
static void mail_storage_service_io_activate(void *context)
523
651
{
524
 
        static struct var_expand_table static_tab[] = {
525
 
                { 'u', NULL, "user" },
526
 
                { 'n', NULL, "username" },
527
 
                { 'd', NULL, "domain" },
528
 
                { 's', NULL, "service" },
529
 
                { 'l', NULL, "lip" },
530
 
                { 'r', NULL, "rip" },
531
 
                { 'p', NULL, "pid" },
532
 
                { 'i', NULL, "uid" },
533
 
                { '\0', NULL, NULL }
534
 
        };
535
 
        struct var_expand_table *tab;
536
 
 
537
 
        tab = t_malloc(sizeof(static_tab));
538
 
        memcpy(tab, static_tab, sizeof(static_tab));
539
 
 
540
 
        tab[0].value = input->username;
541
 
        tab[1].value = t_strcut(input->username, '@');
542
 
        tab[2].value = strchr(input->username, '@');
543
 
        if (tab[2].value != NULL) tab[2].value++;
544
 
        tab[3].value = service->name;
545
 
        tab[4].value = net_ip2addr(&input->local_ip);
546
 
        tab[5].value = net_ip2addr(&input->remote_ip);
547
 
        tab[6].value = my_pid;
548
 
        tab[7].value = dec2str(geteuid());
549
 
        return tab;
 
652
        struct mail_storage_service_user *user = context;
 
653
 
 
654
        i_set_failure_prefix(user->log_prefix);
550
655
}
551
656
 
552
 
static const char *
553
 
user_expand_varstr(struct master_service *service,
554
 
                   struct mail_storage_service_input *input, const char *str)
 
657
static void mail_storage_service_io_deactivate(void *context)
555
658
{
556
 
        string_t *ret;
557
 
 
558
 
        if (*str == SETTING_STRVAR_EXPANDED[0])
559
 
                return str + 1;
560
 
 
561
 
        i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
562
 
 
563
 
        ret = t_str_new(256);
564
 
        var_expand(ret, str + 1, get_var_expand_table(service, input));
565
 
        return str_c(ret);
 
659
        struct mail_storage_service_user *user = context;
 
660
 
 
661
        i_set_failure_prefix(user->service_ctx->default_log_prefix);
566
662
}
567
663
 
568
664
static void
569
665
mail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
570
 
                              struct mail_storage_service_user *user)
 
666
                              struct mail_storage_service_user *user,
 
667
                              struct mail_storage_service_privileges *priv)
571
668
{
572
669
        ctx->log_initialized = TRUE;
573
670
        T_BEGIN {
574
671
                string_t *str;
575
 
                struct ioloop_log *log;
576
672
 
577
673
                str = t_str_new(256);
578
674
                var_expand(str, user->user_set->mail_log_prefix,
579
 
                           get_var_expand_table(ctx->service, &user->input));
580
 
                master_service_init_log(ctx->service, str_c(str));
581
 
 
582
 
                log = io_loop_log_new(current_ioloop);
583
 
                io_loop_log_set_prefix(log, str_c(str));
584
 
                io_loop_log_unref(&log);
 
675
                           get_var_expand_table(ctx->service, &user->input, priv));
 
676
                user->log_prefix = p_strdup(user->pool, str_c(str));
585
677
        } T_END;
 
678
 
 
679
        master_service_init_log(ctx->service, user->log_prefix);
 
680
 
 
681
        if (master_service_get_client_limit(master_service) == 1)
 
682
                i_set_failure_send_prefix(user->log_prefix);
 
683
        user->ioloop_ctx = io_loop_context_new(current_ioloop);
 
684
        io_loop_context_add_callbacks(user->ioloop_ctx,
 
685
                                      mail_storage_service_io_activate,
 
686
                                      mail_storage_service_io_deactivate,
 
687
                                      user);
586
688
}
587
689
 
588
690
static void mail_storage_service_time_moved(time_t old_time, time_t new_time)
658
760
        if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0) {
659
761
                /* note: we may not have read any settings yet, so this logging
660
762
                   may still be going to wrong location */
661
 
                const char *log_prefix = t_strconcat(service->name, ": ", NULL);
662
 
 
663
 
                master_service_init_log(service, log_prefix);
664
 
                io_loop_set_default_log_prefix(current_ioloop, log_prefix);
 
763
                ctx->default_log_prefix =
 
764
                        p_strconcat(pool, service->name, ": ", NULL);
 
765
                master_service_init_log(service, ctx->default_log_prefix);
665
766
        }
666
767
        dict_drivers_register_builtin();
667
768
        return ctx;
813
914
                                        user_set->mail_plugins, &mod_set);
814
915
}
815
916
 
 
917
static int extra_field_key_cmp_p(const char *const *s1, const char *const *s2)
 
918
{
 
919
        const char *p1 = *s1, *p2 = *s2;
 
920
 
 
921
        for (; *p1 == *p2; p1++, p2++) {
 
922
                if (*p1 == '\0')
 
923
                        return 0;
 
924
        }
 
925
        if (*p1 == '=')
 
926
                return -1;
 
927
        if (*p2 == '=')
 
928
                return 1;
 
929
        return *p1 - *p2;
 
930
}
 
931
 
816
932
int mail_storage_service_lookup(struct mail_storage_service_ctx *ctx,
817
933
                                const struct mail_storage_service_input *input,
818
934
                                struct mail_storage_service_user **user_r,
829
945
        pool_t user_pool, temp_pool;
830
946
        int ret = 1;
831
947
 
832
 
        user_pool = pool_alloconly_create("mail storage service user", 1024*5);
 
948
        user_pool = pool_alloconly_create("mail storage service user", 1024*8);
833
949
 
834
950
        if (mail_storage_service_read_settings(ctx, input, user_pool,
835
951
                                               &user_info, &set_parser,
871
987
        }
872
988
 
873
989
        user = p_new(user_pool, struct mail_storage_service_user, 1);
 
990
        user->service_ctx = ctx;
874
991
        user->pool = user_pool;
875
992
        user->input = *input;
876
993
        user->input.userdb_fields = NULL;
897
1014
 
898
1015
        if (userdb_fields != NULL) {
899
1016
                auth_user_fields_parse(userdb_fields, temp_pool, &reply);
 
1017
                array_sort(&reply.extra_fields, extra_field_key_cmp_p);
900
1018
                if (user_reply_handle(ctx, user, &reply, &error) < 0) {
901
1019
                        i_error("user %s: Invalid settings in userdb: %s",
902
1020
                                username, error);
920
1038
                              struct mail_storage_service_user *user,
921
1039
                              struct mail_user **mail_user_r)
922
1040
{
923
 
        const struct mail_user_settings *user_set = user->user_set;
924
 
        const char *home, *chroot, *error;
 
1041
        struct mail_storage_service_privileges priv;
 
1042
        const char *error;
925
1043
        unsigned int len;
926
1044
        bool disallow_root =
927
1045
                (user->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0;
929
1047
                (user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0;
930
1048
        bool use_chroot;
931
1049
 
932
 
        /* variable strings are expanded in mail_user_init(),
933
 
           but we need the home and chroot sooner so do them separately here. */
934
 
        home = user_expand_varstr(ctx->service, &user->input,
935
 
                                  user_set->mail_home);
936
 
        chroot = user_expand_varstr(ctx->service, &user->input,
937
 
                                    user_set->mail_chroot);
 
1050
        if (service_parse_privileges(ctx, user, &priv, &error) < 0) {
 
1051
                i_error("user %s: %s", user->input.username, error);
 
1052
                return -2;
 
1053
        }
938
1054
 
939
 
        if (*home != '/' && *home != '\0') {
 
1055
        if (*priv.home != '/' && *priv.home != '\0') {
940
1056
                i_error("user %s: "
941
1057
                        "Relative home directory paths not supported: %s",
942
 
                        user->input.username, home);
 
1058
                        user->input.username, priv.home);
943
1059
                return -2;
944
1060
        }
945
1061
 
950
1066
        use_chroot = !temp_priv_drop ||
951
1067
                restrict_access_get_current_chroot() != NULL;
952
1068
 
953
 
        len = strlen(chroot);
954
 
        if (len > 2 && strcmp(chroot + len - 2, "/.") == 0 &&
955
 
            strncmp(home, chroot, len - 2) == 0) {
 
1069
        len = strlen(priv.chroot);
 
1070
        if (len > 2 && strcmp(priv.chroot + len - 2, "/.") == 0 &&
 
1071
            strncmp(priv.home, priv.chroot, len - 2) == 0) {
956
1072
                /* mail_chroot = /chroot/. means that the home dir already
957
1073
                   contains the chroot dir. remove it from home. */
958
1074
                if (use_chroot) {
959
 
                        home += len - 2;
960
 
                        if (*home == '\0')
961
 
                                home = "/";
962
 
                        chroot = t_strndup(chroot, len - 2);
 
1075
                        priv.home += len - 2;
 
1076
                        if (*priv.home == '\0')
 
1077
                                priv.home = "/";
 
1078
                        priv.chroot = t_strndup(priv.chroot, len - 2);
963
1079
 
964
 
                        set_keyval(ctx, user, "mail_home", home);
965
 
                        set_keyval(ctx, user, "mail_chroot", chroot);
 
1080
                        set_keyval(ctx, user, "mail_home", priv.home);
 
1081
                        set_keyval(ctx, user, "mail_chroot", priv.chroot);
966
1082
                }
967
1083
        } else if (len > 0 && !use_chroot) {
968
1084
                /* we're not going to chroot. fix home directory so we can
969
1085
                   access it. */
970
 
                if (*home == '\0' || strcmp(home, "/") == 0)
971
 
                        home = chroot;
 
1086
                if (*priv.home == '\0' || strcmp(priv.home, "/") == 0)
 
1087
                        priv.home = priv.chroot;
972
1088
                else
973
 
                        home = t_strconcat(chroot, home, NULL);
974
 
                chroot = "";
975
 
                set_keyval(ctx, user, "mail_home", home);
 
1089
                        priv.home = t_strconcat(priv.chroot, priv.home, NULL);
 
1090
                priv.chroot = "";
 
1091
                set_keyval(ctx, user, "mail_home", priv.home);
976
1092
        }
977
1093
 
978
1094
        if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0)
979
 
                mail_storage_service_init_log(ctx, user);
 
1095
                mail_storage_service_init_log(ctx, user, &priv);
980
1096
 
981
1097
        if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
982
 
                if (service_drop_privileges(user, user_set, home, chroot,
 
1098
                if (service_drop_privileges(user, &priv,
983
1099
                                            disallow_root, temp_priv_drop,
984
1100
                                            FALSE, &error) < 0) {
985
1101
                        i_error("user %s: Couldn't drop privileges: %s",
995
1111
           initialized yet. */
996
1112
        module_dir_init(mail_storage_service_modules);
997
1113
 
998
 
        if (mail_storage_service_init_post(ctx, user, home,
 
1114
        if (mail_storage_service_init_post(ctx, user, &priv,
999
1115
                                           mail_user_r, &error) < 0) {
1000
1116
                i_error("user %s: Initialization failed: %s",
1001
1117
                        user->input.username, error);
1007
1123
void mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
1008
1124
                                          struct mail_storage_service_user *user)
1009
1125
{
1010
 
        const struct mail_user_settings *user_set = user->user_set;
1011
 
        const char *home, *chroot, *error;
1012
 
 
1013
 
        home = user_expand_varstr(ctx->service, &user->input,
1014
 
                                  user_set->mail_home);
1015
 
        chroot = user_expand_varstr(ctx->service, &user->input,
1016
 
                                    user_set->mail_chroot);
1017
 
 
1018
 
        if (service_drop_privileges(user, user_set, home, chroot,
1019
 
                                    FALSE, FALSE, TRUE,
1020
 
                                    &error) < 0)
1021
 
                i_fatal("%s", error);
 
1126
        struct mail_storage_service_privileges priv;
 
1127
        const char *error;
 
1128
 
 
1129
        if (service_parse_privileges(ctx, user, &priv, &error) < 0)
 
1130
                i_fatal("user %s: %s", user->input.username, error);
 
1131
        if (service_drop_privileges(user, &priv,
 
1132
                                    FALSE, FALSE, TRUE, &error) < 0)
 
1133
                i_fatal("user %s: %s", user->input.username, error);
1022
1134
}
1023
1135
 
1024
1136
int mail_storage_service_lookup_next(struct mail_storage_service_ctx *ctx,
1050
1162
        struct mail_storage_service_user *user = *_user;
1051
1163
 
1052
1164
        *_user = NULL;
 
1165
 
 
1166
        if (user->ioloop_ctx != NULL) {
 
1167
                io_loop_context_remove_callbacks(user->ioloop_ctx,
 
1168
                        mail_storage_service_io_activate,
 
1169
                        mail_storage_service_io_deactivate, user);
 
1170
                io_loop_context_unref(&user->ioloop_ctx);
 
1171
        }
1053
1172
        settings_parser_deinit(&user->set_parser);
1054
1173
        pool_unref(&user->pool);
1055
1174
}
1084
1203
                (void)auth_master_user_list_deinit(&ctx->auth_list);
1085
1204
        mail_storage_service_init_settings(ctx, NULL);
1086
1205
 
1087
 
        ctx->auth_list = auth_master_user_list_init(ctx->conn);
 
1206
        ctx->auth_list = auth_master_user_list_init(ctx->conn, NULL, NULL);
1088
1207
        return auth_master_user_list_count(ctx->auth_list);
1089
1208
}
1090
1209