mail-process.c revision 76b43e4417bab52e913da39b5f5bc2a130d3f149
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "common.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "array.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "hash.h"
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen#include "fd-close-on-exec.h"
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen#include "env-util.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "str.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "network.h"
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen#include "mountpoint.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "restrict-access.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "restrict-process-size.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "home-expand.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "var-expand.h"
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen#include "mail-process.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "master-login-interface.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "login-process.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "log.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <stdlib.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <unistd.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <grp.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <syslog.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <sys/stat.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#ifdef HAVE_SYS_RESOURCE_H
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen# include <sys/resource.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#endif
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen/* Timeout chdir() completely after this many seconds */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#define CHDIR_TIMEOUT 30
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen/* Give a warning about chdir() taking a while if it took longer than this
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen many seconds to finish. */
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen#define CHDIR_WARN_SECS 10
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainenstruct mail_process_group {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen /* process.type + user + remote_ip identifies this process group */
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen struct child_process process;
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen char *user;
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen struct ip_addr remote_ip;
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* processes array acts also as refcount */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_DEFINE(processes, pid_t);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen};
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen/* type+user -> struct mail_process_group */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct hash_table *mail_process_groups;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic unsigned int mail_process_count = 0;
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainenstatic unsigned int mail_process_group_hash(const void *p)
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen{
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen const struct mail_process_group *group = p;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen return str_hash(group->user) ^ group->process.type ^
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen net_ip_hash(&group->remote_ip);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int mail_process_group_cmp(const void *p1, const void *p2)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen const struct mail_process_group *group1 = p1, *group2 = p2;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen ret = strcmp(group1->user, group2->user);
3561c7bb472a78af74d755219cc0fc71c85ff5c2Timo Sirainen if (ret == 0)
14b1d2a2634e75b988078baee1e8ad678de28a04Timo Sirainen ret = group1->process.type - group2->process.type;
45af47783693b3ba2768c5ad34eeff68132382d0Timo Sirainen if (ret == 0 && !net_ip_compare(&group1->remote_ip, &group2->remote_ip))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = -1;
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen return ret;
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen}
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainenstatic struct mail_process_group *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenmail_process_group_lookup(enum process_type type, const char *user,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct ip_addr *ip)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_process_group lookup_group;
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen lookup_group.process.type = type;
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen lookup_group.user = t_strdup_noconst(user);
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen lookup_group.remote_ip = *ip;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return hash_lookup(mail_process_groups, &lookup_group);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct mail_process_group *
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenmail_process_group_create(enum process_type type, const char *user,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen const struct ip_addr *ip)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_process_group *group;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen group = i_new(struct mail_process_group, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen group->process.type = type;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen group->user = i_strdup(user);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen group->remote_ip = *ip;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_array_init(&group->processes, 10);
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen hash_insert(mail_process_groups, group, group);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return group;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen}
8b3a4836da0b032673918941cb49c956d3b89b25Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenmail_process_group_add(struct mail_process_group *group, pid_t pid)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_count++;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_append(&group->processes, &pid, 1);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen child_process_add(pid, &group->process);
47255691575e06a1c95ce78ff0a1b502199de3abTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainenstatic void mail_process_group_free(struct mail_process_group *group)
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_free(&group->processes);
307ec6c2c319e3335ddb1a7aca2d2884fe17fae0Timo Sirainen i_free(group->user);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen i_free(group);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainenstatic bool validate_uid_gid(struct settings *set, uid_t uid, gid_t gid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *user)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (uid == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("user %s: Logins with UID 0 not permitted", user);
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen return FALSE;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen }
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen
2faaca21fb49df0f1da859090246866b111cee1eTimo Sirainen if (set->login_uid == uid && master_uid != uid) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("user %s: Logins with login_user's UID %s "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "not permitted (see http://wiki.dovecot.org/UserIds).",
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen user, dec2str(uid));
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return FALSE;
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen }
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen if (uid < (uid_t)set->first_valid_uid ||
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen (set->last_valid_uid != 0 && uid > (uid_t)set->last_valid_uid)) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen i_error("user %s: Logins with UID %s not permitted "
cd8a262bdd0b55a3bf53d9aa54fc3008a61d7f8dTimo Sirainen "(see first_valid_uid in config file).",
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen user, dec2str(uid));
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen return FALSE;
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen }
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen if (gid < (gid_t)set->first_valid_gid ||
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen (set->last_valid_gid != 0 && gid > (gid_t)set->last_valid_gid)) {
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen i_error("user %s: Logins for users with primary group ID %s "
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen "not permitted (see first_valid_gid in config file).",
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen user, dec2str(gid));
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen return FALSE;
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen }
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen return TRUE;
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen}
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainenstatic bool validate_chroot(struct settings *set, const char *dir)
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen{
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen const char *const *chroot_dirs;
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen if (*dir == '\0')
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen return FALSE;
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen if (*set->valid_chroot_dirs == '\0')
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen return FALSE;
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen chroot_dirs = t_strsplit(set->valid_chroot_dirs, ":");
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen while (*chroot_dirs != NULL) {
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen if (**chroot_dirs != '\0' &&
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen return TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen chroot_dirs++;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic const struct var_expand_table *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenget_var_expand_table(const char *protocol,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *user, const char *home,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *local_ip, const char *remote_ip,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen pid_t pid, uid_t uid)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen static struct var_expand_table static_tab[] = {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'u', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'n', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'd', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 's', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'h', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'l', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'r', NULL },
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen { 'p', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { 'i', NULL },
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen { '\0', NULL }
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen };
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen struct var_expand_table *tab;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab = t_malloc(sizeof(static_tab));
14b1d2a2634e75b988078baee1e8ad678de28a04Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[0].value = user;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[1].value = user == NULL ? NULL : t_strcut(user, '@');
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[2].value = user == NULL ? NULL : strchr(user, '@');
14b1d2a2634e75b988078baee1e8ad678de28a04Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[3].value = t_str_ucase(protocol);
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[4].value = home != NULL ? home :
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen "/HOME_DIRECTORY_USED_BUT_NOT_GIVEN_BY_USERDB";
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[5].value = local_ip;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[6].value = remote_ip;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen tab[7].value = dec2str(pid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen tab[8].value = dec2str(uid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen return tab;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic const char *
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainenexpand_mail_env(const char *env, const struct var_expand_table *table)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen string_t *str;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *p;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen str = t_str_new(256);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* it's either type:data or just data */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen p = strchr(env, ':');
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (p != NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (env != p) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_append_c(str, *env);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env++;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_append_c(str, *env++);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
70df8f39fb3db7c49b18c855178f8172176a037aTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (env[0] == '~' &&
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (env[1] == '/' || env[1] == '\0' || env[1] == ':')) {
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen /* expand home */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env = t_strconcat("%h", env+1, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* expand %vars */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen var_expand(str, env, table);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen return str_c(str);
3561c7bb472a78af74d755219cc0fc71c85ff5c2Timo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainenstatic void
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainenenv_put_namespace(struct namespace_settings *ns, const char *default_location,
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen const struct var_expand_table *table)
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen{
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen const char *location;
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen unsigned int i;
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen string_t *str;
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen if (default_location == NULL)
2e652d2651b2800f99a17dcb3014a009fe4660d3Timo Sirainen default_location = "";
14b1d2a2634e75b988078baee1e8ad678de28a04Timo Sirainen
14b1d2a2634e75b988078baee1e8ad678de28a04Timo Sirainen for (i = 1; ns != NULL; i++, ns = ns->next) {
14b1d2a2634e75b988078baee1e8ad678de28a04Timo Sirainen location = *ns->location != '\0' ? ns->location :
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen default_location;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen location = expand_mail_env(location, table);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen env_put(t_strdup_printf("NAMESPACE_%u=%s", i, location));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ns->separator != NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env_put(t_strdup_printf("NAMESPACE_%u_SEP=%s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i, ns->separator));
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ns->type != NULL) {
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen env_put(t_strdup_printf("NAMESPACE_%u_TYPE=%s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i, ns->type));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ns->prefix != NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* expand variables, eg. ~%u/ can be useful */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str = t_str_new(256);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_printfa(str, "NAMESPACE_%u_PREFIX=", i);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen var_expand(str, ns->prefix, table);
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen env_put(str_c(str));
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen }
307ec6c2c319e3335ddb1a7aca2d2884fe17fae0Timo Sirainen if (ns->inbox)
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen env_put(t_strdup_printf("NAMESPACE_%u_INBOX=1", i));
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen if (ns->hidden)
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen env_put(t_strdup_printf("NAMESPACE_%u_HIDDEN=1", i));
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen if (ns->list)
45af47783693b3ba2768c5ad34eeff68132382d0Timo Sirainen env_put(t_strdup_printf("NAMESPACE_%u_LIST=1", i));
45af47783693b3ba2768c5ad34eeff68132382d0Timo Sirainen if (ns->subscriptions)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env_put(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS=1",
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen i));
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainenmail_process_set_environment(struct settings *set, const char *mail,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct var_expand_table *var_expand_table,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen bool dump_capability)
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen{
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen const char *const *envs;
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen string_t *str;
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen unsigned int i, count;
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen env_put(t_strconcat("MAIL_CACHE_FIELDS=",
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen set->mail_cache_fields, NULL));
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen env_put(t_strconcat("MAIL_NEVER_CACHE_FIELDS=",
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen set->mail_never_cache_fields, NULL));
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen env_put(t_strdup_printf("MAIL_CACHE_MIN_MAIL_COUNT=%u",
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen set->mail_cache_min_mail_count));
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen env_put(t_strdup_printf("MAILBOX_IDLE_CHECK_INTERVAL=%u",
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen set->mailbox_idle_check_interval));
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen env_put(t_strdup_printf("MAIL_MAX_KEYWORD_LENGTH=%u",
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen set->mail_max_keyword_length));
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen if (set->protocol == MAIL_PROTOCOL_IMAP) {
808fab19464062a665af85df5e147c6b64b1c348Timo Sirainen env_put(t_strdup_printf("IMAP_MAX_LINE_LENGTH=%u",
08e9fec5ba9e1a26e658c4224207d666b6ced27dTimo Sirainen set->imap_max_line_length));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (*set->imap_capability != '\0') {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env_put(t_strconcat("IMAP_CAPABILITY=",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen set->imap_capability, NULL));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(t_strconcat("IMAP_CLIENT_WORKAROUNDS=",
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen set->imap_client_workarounds, NULL));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(t_strconcat("IMAP_LOGOUT_FORMAT=",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set->imap_logout_format, NULL));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->protocol == MAIL_PROTOCOL_POP3) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(t_strconcat("POP3_CLIENT_WORKAROUNDS=",
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen set->pop3_client_workarounds, NULL));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(t_strconcat("POP3_LOGOUT_FORMAT=",
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen set->pop3_logout_format, NULL));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->pop3_no_flag_updates)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("POP3_NO_FLAG_UPDATES=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->pop3_reuse_xuidl)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("POP3_REUSE_XUIDL=1");
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen if (set->pop3_enable_last)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("POP3_ENABLE_LAST=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->pop3_lock_session)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("POP3_LOCK_SESSION=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen /* We care about POP3 UIDL format in all process types */
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(t_strconcat("POP3_UIDL_FORMAT=", set->pop3_uidl_format, NULL));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->mail_save_crlf)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("MAIL_SAVE_CRLF=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->mmap_disable)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("MMAP_DISABLE=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->dotlock_use_excl)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("DOTLOCK_USE_EXCL=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->fsync_disable)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("FSYNC_DISABLE=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->mail_nfs_storage)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("MAIL_NFS_STORAGE=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->mail_nfs_index)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("MAIL_NFS_INDEX=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->mailbox_list_index_disable)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("MAILBOX_LIST_INDEX_DISABLE=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->maildir_stat_dirs)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("MAILDIR_STAT_DIRS=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->maildir_copy_with_hardlinks)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("MAILDIR_COPY_WITH_HARDLINKS=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->maildir_copy_preserve_filename)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put("MAILDIR_COPY_PRESERVE_FILENAME=1");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (set->mail_debug)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("DEBUG=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->mail_full_filesystem_access)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("FULL_FILESYSTEM_ACCESS=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->mbox_dirty_syncs)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("MBOX_DIRTY_SYNCS=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->mbox_very_dirty_syncs)
5e32f3d9e2c58b6db53cc3b063c9ee73949207caTimo Sirainen env_put("MBOX_VERY_DIRTY_SYNCS=1");
5e32f3d9e2c58b6db53cc3b063c9ee73949207caTimo Sirainen if (set->mbox_lazy_writes)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("MBOX_LAZY_WRITES=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* when running dump-capability log still points to stderr,
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen and io_add()ing it might break (epoll_ctl() gives EPERM) */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->shutdown_clients && !dump_capability)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("STDERR_CLOSE_SHUTDOWN=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen (void)umask(set->umask);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("LOCK_METHOD=", set->lock_method, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("MBOX_READ_LOCKS=", set->mbox_read_locks, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("MBOX_WRITE_LOCKS=", set->mbox_write_locks, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strdup_printf("MBOX_LOCK_TIMEOUT=%u",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set->mbox_lock_timeout));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strdup_printf("MBOX_DOTLOCK_CHANGE_TIMEOUT=%u",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set->mbox_dotlock_change_timeout));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strdup_printf("MBOX_MIN_INDEX_SIZE=%u",
0afe75cd8ea1814ba5711196ef749f93a140c01cTimo Sirainen set->mbox_min_index_size));
0afe75cd8ea1814ba5711196ef749f93a140c01cTimo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strdup_printf("DBOX_ROTATE_SIZE=%u",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set->dbox_rotate_size));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strdup_printf("DBOX_ROTATE_MIN_SIZE=%u",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set->dbox_rotate_min_size));
0afe75cd8ea1814ba5711196ef749f93a140c01cTimo Sirainen env_put(t_strdup_printf("DBOX_ROTATE_DAYS=%u",
0afe75cd8ea1814ba5711196ef749f93a140c01cTimo Sirainen set->dbox_rotate_days));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (*set->mail_plugins != '\0') {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("MAIL_PLUGIN_DIR=",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set->mail_plugin_dir, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("MAIL_PLUGINS=", set->mail_plugins, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* user given environment - may be malicious. virtual_user comes from
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen auth process, but don't trust that too much either. Some auth
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mechanism might allow leaving extra data there. */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if ((mail == NULL || *mail == '\0') && *set->mail_location != '\0')
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mail = expand_mail_env(set->mail_location, var_expand_table);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("MAIL=", mail, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (set->server->namespaces != NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put_namespace(set->server->namespaces,
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mail, var_expand_table);
ea918d503ae61496e10103935028d3cc6419f1cbTimo Sirainen }
ea918d503ae61496e10103935028d3cc6419f1cbTimo Sirainen
ea918d503ae61496e10103935028d3cc6419f1cbTimo Sirainen str = t_str_new(256);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen envs = array_get(&set->plugin_envs, &count);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_assert((count % 2) == 0);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen for (i = 0; i < count; i += 2) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen str_truncate(str, 0);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen var_expand(str, envs[i+1], var_expand_table);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat(t_str_ucase(envs[i]), "=",
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen str_c(str), NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenvoid mail_process_exec(const char *protocol, const char *section)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen struct server_settings *server = settings_root;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen const struct var_expand_table *var_expand_table;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen struct settings *set;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen const char *executable;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (strcmp(protocol, "ext") == 0) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* external binary. section contains path for it. */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (section == NULL)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_fatal("External binary parameter not given");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set = server->defaults;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen executable = section;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen } else {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (section != NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen for (; server != NULL; server = server->next) {
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen if (strcmp(server->name, section) == 0)
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen break;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (server == NULL)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_fatal("Section not found: '%s'", section);
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen }
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (strcmp(protocol, "imap") == 0)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set = server->imap;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else if (strcmp(protocol, "pop3") == 0)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen set = server->pop3;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen i_fatal("Unknown protocol: '%s'", protocol);
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen executable = set->mail_executable;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen }
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen var_expand_table =
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen get_var_expand_table(protocol, getenv("USER"), getenv("HOME"),
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen getenv("TCPLOCALIP"),
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen getenv("TCPREMOTEIP"),
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen getpid(), geteuid());
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* set up logging */
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (*set->log_path == '\0')
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put("USE_SYSLOG=1");
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen env_put(t_strconcat("LOGFILE=", set->log_path, NULL));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (*set->info_log_path != '\0')
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen env_put(t_strconcat("INFOLOGFILE=", set->info_log_path, NULL));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (*set->mail_log_prefix != '\0') {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen string_t *str = t_str_new(256);
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen str_append(str, "LOG_PREFIX=");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen var_expand(str, set->mail_log_prefix, var_expand_table);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen env_put(str_c(str));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen mail_process_set_environment(set, getenv("MAIL"), var_expand_table,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen FALSE);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen client_process_exec(executable, "");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen}
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenstatic void nfs_warn_if_found(const char *mail, const char *full_home_dir)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen{
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen struct mountpoint point;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen const char *path;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (mail == NULL || *mail == '\0')
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen path = full_home_dir;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen else {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen path = strstr(mail, ":INDEX=");
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (path != NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* indexes set separately */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen path += 7;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (strncmp(path, "MEMORY", 6) == 0)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen } else {
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen path = strchr(mail, ':');
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (path == NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* autodetection for path */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen path = mail;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen } else {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* format:path */
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen path++;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen path = home_expand_tilde(t_strcut(path, ':'), full_home_dir);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen if (mountpoint_get(path, pool_datastack_create(), &point) <= 0)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen if (point.type == NULL || strcasecmp(point.type, "NFS") != 0)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen i_fatal("Mailbox indexes in %s are in NFS mount. "
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen "You must set mmap_disable=yes to avoid index corruptions. "
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen "If you're sure this check was wrong, set nfs_check=no.", path);
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen}
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenenum master_login_status
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainencreate_mail_process(enum process_type process_type, struct settings *set,
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen int socket, const struct ip_addr *local_ip,
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen const struct ip_addr *remote_ip,
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen const char *user, const char *const *args,
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen bool dump_capability)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen const struct var_expand_table *var_expand_table;
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen const char *p, *addr, *mail, *chroot_dir, *home_dir, *full_home_dir;
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen const char *system_user;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen struct mail_process_group *process_group;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen char title[1024];
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen struct log_io *log;
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen string_t *str;
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen pid_t pid;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen uid_t uid;
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen gid_t gid;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen ARRAY_DEFINE(extra_args, const char *);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen unsigned int i, count, left, process_count;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen int ret, log_fd, nice, chdir_errno;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen bool home_given, nfs_check;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen i_assert(process_type == PROCESS_TYPE_IMAP ||
472f3cbaaa2ba84e2241da0747630d391e120c84Timo Sirainen process_type == PROCESS_TYPE_POP3);
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen if (mail_process_count == set->max_mail_processes) {
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen i_error("Maximum number of mail processes exceeded");
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen }
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen /* check process limit for this user */
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen process_group = dump_capability ? NULL :
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen mail_process_group_lookup(process_type, user, remote_ip);
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen process_count = process_group == NULL ? 0 :
eb729968680f4a36616ce8c60848c3b6c407f791Timo Sirainen array_count(&process_group->processes);
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen if (process_count >= set->mail_max_userip_connections &&
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen set->mail_max_userip_connections != 0)
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen return MASTER_LOGIN_STATUS_MAX_CONNECTIONS;
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen
a3e96a912e8a058a7372eda55ffc95d54269bd3cTimo Sirainen t_array_init(&extra_args, 16);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen mail = home_dir = chroot_dir = system_user = "";
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen uid = (uid_t)-1; gid = (gid_t)-1; nice = 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen home_given = FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (; *args != NULL; args++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strncmp(*args, "home=", 5) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen home_dir = *args + 5;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen home_given = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (strncmp(*args, "mail=", 5) == 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen mail = *args + 5;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else if (strncmp(*args, "chroot=", 7) == 0)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen chroot_dir = *args + 7;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen else if (strncmp(*args, "nice=", 5) == 0)
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen nice = atoi(*args + 5);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else if (strncmp(*args, "system_user=", 12) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen system_user = *args + 12;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else if (strncmp(*args, "uid=", 4) == 0) {
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen if (uid != (uid_t)-1) {
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen i_error("uid specified multiple times for %s",
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen user);
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen }
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen uid = (uid_t)strtoul(*args + 4, NULL, 10);
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen } else if (strncmp(*args, "gid=", 4) == 0)
8601cb6dafd4e8960c91b3c082af3095cfbebe74Timo Sirainen gid = (gid_t)strtoul(*args + 4, NULL, 10);
8601cb6dafd4e8960c91b3c082af3095cfbebe74Timo Sirainen else {
8601cb6dafd4e8960c91b3c082af3095cfbebe74Timo Sirainen const char *arg = *args;
8601cb6dafd4e8960c91b3c082af3095cfbebe74Timo Sirainen array_append(&extra_args, &arg, 1);
8601cb6dafd4e8960c91b3c082af3095cfbebe74Timo Sirainen }
8601cb6dafd4e8960c91b3c082af3095cfbebe74Timo Sirainen }
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen /* if uid/gid wasn't returned, use the defaults */
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen if (uid == (uid_t)-1) {
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen uid = set->mail_uid_t;
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen if (uid == (uid_t)-1) {
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen i_error("User %s is missing UID (set mail_uid)", user);
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen }
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen }
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen if (gid == (gid_t)-1) {
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen gid = set->mail_gid_t;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen if (gid == (gid_t)-1) {
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen i_error("User %s is missing GID (set mail_gid)", user);
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen }
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen }
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen if (*chroot_dir == '\0' && (p = strstr(home_dir, "/./")) != NULL) {
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen /* wu-ftpd like <chroot>/./<home> */
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen chroot_dir = t_strdup_until(home_dir, p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen home_dir = p + 2;
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen } else if (*chroot_dir != '\0' && *home_dir != '/') {
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen /* home directories should never be relative, but force this
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen with chroots. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen home_dir = t_strconcat("/", home_dir, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!dump_capability) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!validate_uid_gid(set, uid, gid, user))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (*chroot_dir == '\0' && *set->mail_chroot != '\0')
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen chroot_dir = set->mail_chroot;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen if (*chroot_dir != '\0') {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!validate_chroot(set, chroot_dir)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Invalid chroot directory '%s' (user %s) "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "(see valid_chroot_dirs in config file)",
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen chroot_dir, user);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (set->mail_drop_priv_before_exec) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Can't chroot to directory '%s' (user %s) "
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen "with mail_drop_priv_before_exec=yes",
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen chroot_dir, user);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7be1a5530fcb414588fbe90eaed65eff83e84737Timo Sirainen
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen if (!dump_capability) {
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen log_fd = log_create_pipe(&log, set->mail_log_max_lines_per_sec);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen if (log_fd == -1)
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen } else {
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen log = NULL;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen log_fd = dup(STDERR_FILENO);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen if (log_fd == -1) {
45af47783693b3ba2768c5ad34eeff68132382d0Timo Sirainen i_error("dup() failed: %m");
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen }
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen fd_close_on_exec(log_fd, TRUE);
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen }
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen /* See if we need to do the initial NFS check. We want to do this only
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen once, so the check code needs to be before fork(). */
a1893588a73d32a322153f5a2f7a16ef2c724979Timo Sirainen if (set->nfs_check && !set->mmap_disable && !dump_capability) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen set->nfs_check = FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen nfs_check = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen nfs_check = FALSE;
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen }
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen pid = fork();
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen if (pid < 0) {
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen i_error("fork() failed: %m");
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen (void)close(log_fd);
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen }
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen var_expand_table =
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen get_var_expand_table(process_names[process_type],
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen user, home_given ? home_dir : NULL,
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen net_ip2addr(local_ip),
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen net_ip2addr(remote_ip),
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen pid != 0 ? pid : getpid(), uid);
3ef4aca8cae3e335e1fe53591049cb80b299c459Timo Sirainen str = t_str_new(128);
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (pid != 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* master */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen var_expand(str, set->mail_log_prefix, var_expand_table);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!dump_capability) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen log_set_prefix(log, str_c(str));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen log_set_pid(log, pid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (process_group == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen process_group =
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_group_create(process_type,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen user,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen remote_ip);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_group_add(process_group, pid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (void)close(log_fd);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return MASTER_LOGIN_STATUS_OK;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#ifdef HAVE_SETPRIORITY
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (nice != 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (setpriority(PRIO_PROCESS, 0, nice) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("setpriority(%d) failed: %m", nice);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#endif
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!dump_capability) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_append(str, "master-");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen var_expand(str, set->mail_log_prefix, var_expand_table);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen log_set_prefix(log, str_c(str));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen child_process_init_env();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* move the client socket into stdin and stdout fds, log to stderr */
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (dup2(dump_capability ? null_fd : socket, 0) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("dup2(stdin) failed: %m");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (dup2(socket, 1) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("dup2(stdout) failed: %m");
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (dup2(log_fd, 2) < 0)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen i_fatal("dup2(stderr) failed: %m");
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen for (i = 0; i < 3; i++)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen fd_close_on_exec(i, FALSE);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* setup environment - set the most important environment first
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen (paranoia about filling up environment without noticing) */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen restrict_access_set_env(system_user, uid, gid, chroot_dir,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen set->first_valid_gid, set->last_valid_gid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen set->mail_extra_groups);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen restrict_process_size(set->mail_process_size, (unsigned int)-1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (dump_capability)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env_put("DUMP_CAPABILITY=1");
bb4045cb95c33c3a888c50dce461554391129794Timo Sirainen
bb4045cb95c33c3a888c50dce461554391129794Timo Sirainen if (*home_dir == '\0') {
bb4045cb95c33c3a888c50dce461554391129794Timo Sirainen full_home_dir = "";
bb4045cb95c33c3a888c50dce461554391129794Timo Sirainen ret = -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen full_home_dir = *chroot_dir == '\0' ? home_dir :
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen t_strconcat(chroot_dir, home_dir, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* NOTE: if home directory is NFS-mounted, we might not
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen have access to it as root. Change the effective UID and GID
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen temporarily to make it work. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (uid != master_uid) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (setegid(gid) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("setegid(%s) failed: %m", dec2str(gid));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (seteuid(uid) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("seteuid(%s) failed: %m", dec2str(uid));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen alarm(CHDIR_TIMEOUT);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = chdir(full_home_dir);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen chdir_errno = errno;
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen if ((left = alarm(0)) < CHDIR_TIMEOUT - CHDIR_WARN_SECS) {
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen i_warning("chdir(%s) blocked for %u secs",
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen full_home_dir, CHDIR_TIMEOUT - left);
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen }
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen /* Change UID back. No need to change GID back, it doesn't
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen really matter. */
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen if (uid != master_uid && seteuid(master_uid) < 0)
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen i_fatal("seteuid(%s) failed: %m", dec2str(master_uid));
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen /* If user's home directory doesn't exist and we're not
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen trying to chroot anywhere, fallback to /tmp as the mails
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen could be stored elsewhere. The ENOTDIR check is mostly for
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen /dev/null home directory. */
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen if (ret < 0 && (*chroot_dir != '\0' ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen !(ENOTFOUND(chdir_errno) ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen chdir_errno == EINTR))) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen errno = chdir_errno;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("chdir(%s) failed with uid %s: %m",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen full_home_dir, dec2str(uid));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* We still have to change to some directory where we have
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen rx-access. /tmp should exist everywhere. */
8576eb5abb66178f251c00209e564c7673c0e4cfTimo Sirainen if (chdir("/tmp") < 0)
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen i_fatal("chdir(/tmp) failed: %m");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_set_environment(set, mail, var_expand_table,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dump_capability);
8576eb5abb66178f251c00209e564c7673c0e4cfTimo Sirainen
8576eb5abb66178f251c00209e564c7673c0e4cfTimo Sirainen /* extra args. uppercase key value. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen args = array_get(&extra_args, &count);
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (*args[i] == '=') {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* Should be caught by dovecot-auth already */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("Userdb returned data with empty key (%s)",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen args[i]);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen p = strchr(args[i], '=');
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen if (p == NULL) {
79490ec1a58241d6011fa36713ca651d795855c3Timo Sirainen /* boolean */
79490ec1a58241d6011fa36713ca651d795855c3Timo Sirainen env_put(t_strconcat(t_str_ucase(args[i]), "=1", NULL));
79490ec1a58241d6011fa36713ca651d795855c3Timo Sirainen
79490ec1a58241d6011fa36713ca651d795855c3Timo Sirainen } else {
79490ec1a58241d6011fa36713ca651d795855c3Timo Sirainen /* key=value */
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen env_put(t_strconcat(t_str_ucase(
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen t_strdup_until(args[i], p)), p, NULL));
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen }
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen }
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen if (nfs_check) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* ideally we should check all of the namespaces,
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen but for now don't bother. */
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen const char *mail_location = getenv("NAMESPACE_1");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mail_location == NULL)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen mail_location = getenv("MAIL");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen nfs_warn_if_found(mail_location, full_home_dir);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen env_put("LOGGED_IN=1");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env_put(t_strconcat("HOME=", home_dir, NULL));
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen env_put(t_strconcat("USER=", user, NULL));
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen addr = net_ip2addr(remote_ip);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen env_put(t_strconcat("IP=", addr, NULL));
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen if (!set->verbose_proctitle)
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen title[0] = '\0';
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen else {
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen if (addr == NULL)
69f6407b20f623193981d672c26fa722ee75d941Timo Sirainen addr = "??";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_snprintf(title, sizeof(title), "[%s %s]", user, addr);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen /* make sure we don't leak syslog fd, but do it last so that
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen any errors above will be logged */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen closelog();
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (set->mail_drop_priv_before_exec)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen restrict_access_by_env(TRUE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen client_process_exec(set->mail_executable, title);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen set->mail_executable);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* not reached */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return MASTER_LOGIN_STATUS_INTERNAL_ERROR;
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainenmail_process_destroyed(struct child_process *process,
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen pid_t pid, bool abnormal_exit ATTR_UNUSED)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_process_group *group = (struct mail_process_group *)process;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen const pid_t *pids;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen unsigned int i, count;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen pids = array_get(&group->processes, &count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (count == 1) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen /* last process in this group */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen i_assert(pids[0] == pid);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen hash_remove(mail_process_groups, group);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_group_free(group);
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (pids[i] == pid)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(i != count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_delete(&group->processes, i, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_count--;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mail_processes_init(void)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_groups = hash_create(default_pool, default_pool, 0,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_group_hash,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_group_cmp);
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen child_process_set_destroy_callback(PROCESS_TYPE_IMAP,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_destroyed);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen child_process_set_destroy_callback(PROCESS_TYPE_POP3,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_destroyed);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mail_processes_deinit(void)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct hash_iterate_context *iter;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen void *key, *value;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen iter = hash_iterate_init(mail_process_groups);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (hash_iterate(iter, &key, &value)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_process_group *group = value;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_process_group_free(group);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen hash_iterate_deinit(&iter);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen hash_destroy(&mail_process_groups);
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen