1 /* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "ioloop.h"
5 #include "array.h"
6 #include "base64.h"
7 #include "hostpid.h"
8 #include "module-dir.h"
9 #include "restrict-access.h"
10 #include "eacces-error.h"
11 #include "ipwd.h"
12 #include "str.h"
13 #include "time-util.h"
14 #include "sleep.h"
15 #include "var-expand.h"
16 #include "dict.h"
17 #include "settings-parser.h"
18 #include "auth-master.h"
19 #include "master-service-private.h"
20 #include "master-service-settings.h"
21 #include "master-service-ssl-settings.h"
22 #include "master-service-settings-cache.h"
23 #include "mail-user.h"
24 #include "mail-namespace.h"
25 #include "mail-storage.h"
26 #include "mail-storage-service.h"
27
28 #include <sys/stat.h>
29 #include <time.h>
30
31 #ifdef HAVE_SYS_TIME_H
32 # include <sys/time.h>
33 #endif
34 #ifdef HAVE_SYS_RESOURCE_H
35 # include <sys/resource.h>
36 #endif
37
38 /* If time moves backwards more than this, kill ourself instead of sleeping. */
39 #define MAX_TIME_BACKWARDS_SLEEP_MSECS (5*1000)
40 #define MAX_NOWARN_FORWARD_MSECS (10*1000)
41
42 #define ERRSTR_INVALID_USER_SETTINGS \
43 "Invalid user settings. Refer to server log for more information."
44
45 struct mail_storage_service_privileges {
46 uid_t uid;
47 gid_t gid;
48 const char *uid_source, *gid_source;
49
50 const char *home;
51 const char *chroot;
52 };
53
54 struct mail_storage_service_ctx {
55 pool_t pool;
56 struct master_service *service;
57 const char *default_log_prefix;
58
59 struct auth_master_connection *conn, *iter_conn;
60 struct auth_master_user_list_ctx *auth_list;
61 const struct setting_parser_info **set_roots;
62 enum mail_storage_service_flags flags;
63
64 const char *set_cache_module, *set_cache_service;
65 struct master_service_settings_cache *set_cache;
66
67 pool_t userdb_next_pool;
68 const char *const **userdb_next_fieldsp;
69
70 bool debug:1;
71 bool log_initialized:1;
72 bool config_permission_denied:1;
73 };
74
75 struct mail_storage_service_user {
76 pool_t pool;
77 int refcount;
78
79 struct mail_storage_service_ctx *service_ctx;
80 struct mail_storage_service_input input;
81 enum mail_storage_service_flags flags;
82
83 struct event *event;
84 ARRAY(struct event *) event_stack;
85 struct ioloop_context *ioloop_ctx;
86 const char *log_prefix, *auth_mech, *auth_token, *auth_user;
87
88 const char *system_groups_user, *uid_source, *gid_source;
89 const char *chdir_path;
90 const struct mail_user_settings *user_set;
91 const struct master_service_ssl_settings *ssl_set;
92 const struct setting_parser_info *user_info;
93 struct setting_parser_context *set_parser;
94
95 unsigned int session_id_counter;
96
97 bool anonymous:1;
98 bool admin:1;
99 };
100
101 struct module *mail_storage_service_modules = NULL;
102 static struct mail_storage_service_ctx *storage_service_global = NULL;
103
104 static int
105 mail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
106 string_t *str, const char *format,
107 struct mail_storage_service_user *user,
108 const struct mail_storage_service_input *input,
109 const struct mail_storage_service_privileges *priv,
110 const char **error_r);
111
112 static bool
mail_user_set_get_mail_debug(const struct setting_parser_info * user_info,const struct mail_user_settings * user_set)113 mail_user_set_get_mail_debug(const struct setting_parser_info *user_info,
114 const struct mail_user_settings *user_set)
115 {
116 const struct mail_storage_settings *mail_set;
117
118 mail_set = mail_user_set_get_driver_settings(user_info, user_set,
119 MAIL_STORAGE_SET_DRIVER_NAME);
120 return mail_set->mail_debug;
121 }
122
set_keyval(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,const char * key,const char * value)123 static void set_keyval(struct mail_storage_service_ctx *ctx,
124 struct mail_storage_service_user *user,
125 const char *key, const char *value)
126 {
127 struct setting_parser_context *set_parser = user->set_parser;
128
129 if (master_service_set_has_config_override(ctx->service, key)) {
130 /* this setting was already overridden with -o parameter */
131 e_debug(user->event,
132 "Ignoring overridden (-o) userdb setting: %s",
133 key);
134 return;
135 }
136
137 if (settings_parse_keyvalue(set_parser, key, value) < 0) {
138 i_fatal("Invalid userdb input %s=%s: %s", key, value,
139 settings_parser_get_error(set_parser));
140 }
141 }
142
set_line(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,const char * line)143 static int set_line(struct mail_storage_service_ctx *ctx,
144 struct mail_storage_service_user *user,
145 const char *line)
146 {
147 struct setting_parser_context *set_parser = user->set_parser;
148 const char *key, *orig_key, *append_value = NULL;
149 size_t len;
150 int ret;
151
152 if (strchr(line, '=') == NULL)
153 line = t_strconcat(line, "=yes", NULL);
154 orig_key = key = t_strcut(line, '=');
155
156 len = strlen(key);
157 if (len > 0 && key[len-1] == '+') {
158 /* key+=value */
159 append_value = line + len + 1;
160 key = t_strndup(key, len-1);
161 }
162
163 if (!settings_parse_is_valid_key(set_parser, key)) {
164 /* assume it's a plugin setting */
165 key = t_strconcat("plugin/", key, NULL);
166 line = t_strconcat("plugin/", line, NULL);
167 }
168
169 if (master_service_set_has_config_override(ctx->service, key)) {
170 /* this setting was already overridden with -o parameter */
171 e_debug(user->event, "Ignoring overridden (-o) userdb setting: %s",
172 key);
173 return 1;
174 }
175
176 if (append_value != NULL) {
177 const void *value;
178 enum setting_type type;
179
180 value = settings_parse_get_value(set_parser, key, &type);
181 if (value != NULL && type == SET_STR) {
182 const char *const *strp = value;
183
184 line = t_strdup_printf("%s=%s%s",
185 key, *strp, append_value);
186 } else {
187 e_error(user->event, "Ignoring %s userdb setting. "
188 "'+' can only be used for strings.", orig_key);
189 }
190 }
191
192 ret = settings_parse_line(set_parser, line);
193 if (ret >= 0) {
194 if (strstr(key, "pass") != NULL) {
195 /* possibly a password field (e.g. imapc_password).
196 hide the value. */
197 line = t_strconcat(key, "=<hidden>", NULL);
198 }
199 e_debug(user->event, ret == 0 ?
200 "Unknown userdb setting: %s" :
201 "Added userdb setting: %s", line);
202 }
203 return ret;
204 }
205
validate_chroot(const struct mail_user_settings * user_set,const char * dir)206 static bool validate_chroot(const struct mail_user_settings *user_set,
207 const char *dir)
208 {
209 const char *const *chroot_dirs;
210
211 if (*dir == '\0')
212 return FALSE;
213
214 if (*user_set->valid_chroot_dirs == '\0')
215 return FALSE;
216
217 chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
218 while (*chroot_dirs != NULL) {
219 if (**chroot_dirs != '\0' &&
220 str_begins(dir, *chroot_dirs))
221 return TRUE;
222 chroot_dirs++;
223 }
224 return FALSE;
225 }
226
227 static int
user_reply_handle(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,const struct auth_user_reply * reply,const char ** error_r)228 user_reply_handle(struct mail_storage_service_ctx *ctx,
229 struct mail_storage_service_user *user,
230 const struct auth_user_reply *reply,
231 const char **error_r)
232 {
233 const char *home = reply->home;
234 const char *chroot = reply->chroot;
235 const char *const *str, *line, *p;
236 unsigned int i, count;
237 int ret = 0;
238
239 if (reply->uid != (uid_t)-1) {
240 if (reply->uid == 0) {
241 *error_r = "userdb returned 0 as uid";
242 return -1;
243 }
244 user->uid_source = "userdb lookup";
245 set_keyval(ctx, user, "mail_uid", dec2str(reply->uid));
246 }
247 if (reply->gid != (uid_t)-1) {
248 user->gid_source = "userdb lookup";
249 set_keyval(ctx, user, "mail_gid", dec2str(reply->gid));
250 }
251
252 if (home != NULL && chroot == NULL &&
253 *user->user_set->valid_chroot_dirs != '\0' &&
254 (p = strstr(home, "/./")) != NULL) {
255 /* wu-ftpd like <chroot>/./<home> - check only if there's even
256 a possibility of using them (non-empty valid_chroot_dirs) */
257 chroot = t_strdup_until(home, p);
258 home = p + 2;
259 }
260
261 if (home != NULL)
262 set_keyval(ctx, user, "mail_home", home);
263
264 if (chroot != NULL) {
265 if (!validate_chroot(user->user_set, chroot)) {
266 *error_r = t_strdup_printf(
267 "userdb returned invalid chroot directory: %s "
268 "(see valid_chroot_dirs setting)", chroot);
269 return -1;
270 }
271 set_keyval(ctx, user, "mail_chroot", chroot);
272 }
273
274 user->anonymous = reply->anonymous;
275
276 str = array_get(&reply->extra_fields, &count);
277 for (i = 0; i < count; i++) {
278 line = str[i];
279 if (str_begins(line, "system_groups_user=")) {
280 user->system_groups_user =
281 p_strdup(user->pool, line + 19);
282 } else if (str_begins(line, "chdir=")) {
283 user->chdir_path = p_strdup(user->pool, line+6);
284 } else if (str_begins(line, "nice=")) {
285 #ifdef HAVE_SETPRIORITY
286 int n;
287 if (str_to_int(line + 5, &n) < 0) {
288 e_error(user->event,
289 "userdb returned invalid nice value %s",
290 line + 5);
291 } else if (n != 0) {
292 if (setpriority(PRIO_PROCESS, 0, n) < 0)
293 e_error(user->event,
294 "setpriority(%d) failed: %m", n);
295 }
296 #endif
297 } else if (str_begins(line, "auth_mech=")) {
298 user->auth_mech = p_strdup(user->pool, line+10);
299 } else if (str_begins(line, "auth_token=")) {
300 user->auth_token = p_strdup(user->pool, line+11);
301 } else if (str_begins(line, "auth_user=")) {
302 user->auth_user = p_strdup(user->pool, line+10);
303 } else if (str_begins(line, "admin=")) {
304 user->admin = line[6] == 'y' || line[6] == 'Y' ||
305 line[6] == '1';
306 } else T_BEGIN {
307 ret = set_line(ctx, user, line);
308 } T_END;
309 if (ret < 0)
310 break;
311 }
312
313 if (ret < 0) {
314 *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
315 str[i], settings_parser_get_error(user->set_parser));
316 }
317 return ret;
318 }
319
320 static int
service_auth_userdb_lookup(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input,pool_t pool,const char ** user,const char * const ** fields_r,const char ** error_r)321 service_auth_userdb_lookup(struct mail_storage_service_ctx *ctx,
322 const struct mail_storage_service_input *input,
323 pool_t pool, const char **user,
324 const char *const **fields_r,
325 const char **error_r)
326 {
327 struct auth_user_info info;
328 const char *new_username;
329 int ret;
330
331 i_zero(&info);
332 info.service = input->service != NULL ? input->service :
333 ctx->service->name;
334 info.local_ip = input->local_ip;
335 info.remote_ip = input->remote_ip;
336 info.local_port = input->local_port;
337 info.remote_port = input->remote_port;
338 info.forward_fields = input->forward_fields;
339 info.debug = input->debug;
340
341 ret = auth_master_user_lookup(ctx->conn, *user, &info, pool,
342 &new_username, fields_r);
343 if (ret > 0) {
344 if (strcmp(*user, new_username) != 0) {
345 if (ctx->debug)
346 i_debug("changed username to %s", new_username);
347 *user = t_strdup(new_username);
348 }
349 *user = new_username;
350 } else if (ret == 0)
351 *error_r = "Unknown user";
352 else if (**fields_r != NULL) {
353 *error_r = t_strdup(**fields_r);
354 ret = -2;
355 } else {
356 *error_r = MAIL_ERRSTR_CRITICAL_MSG;
357 }
358 return ret;
359 }
360
parse_uid(const char * str,uid_t * uid_r,const char ** error_r)361 static bool parse_uid(const char *str, uid_t *uid_r, const char **error_r)
362 {
363 struct passwd pw;
364
365 if (str_to_uid(str, uid_r) == 0)
366 return TRUE;
367
368 switch (i_getpwnam(str, &pw)) {
369 case -1:
370 *error_r = t_strdup_printf("getpwnam(%s) failed: %m", str);
371 return FALSE;
372 case 0:
373 *error_r = t_strconcat("Unknown UNIX UID user: ", str, NULL);
374 return FALSE;
375 default:
376 *uid_r = pw.pw_uid;
377 return TRUE;
378 }
379 }
380
parse_gid(const char * str,gid_t * gid_r,const char ** error_r)381 static bool parse_gid(const char *str, gid_t *gid_r, const char **error_r)
382 {
383 struct group gr;
384
385 if (str_to_gid(str, gid_r) == 0)
386 return TRUE;
387
388 switch (i_getgrnam(str, &gr)) {
389 case -1:
390 *error_r = t_strdup_printf("getgrnam(%s) failed: %m", str);
391 return FALSE;
392 case 0:
393 *error_r = t_strconcat("Unknown UNIX GID group: ", str, NULL);
394 return FALSE;
395 default:
396 *gid_r = gr.gr_gid;
397 return TRUE;
398 }
399 }
400
401 static const struct var_expand_table *
get_var_expand_table(struct master_service * service,struct mail_storage_service_user * user,const struct mail_storage_service_input * input,const struct mail_storage_service_privileges * priv)402 get_var_expand_table(struct master_service *service,
403 struct mail_storage_service_user *user,
404 const struct mail_storage_service_input *input,
405 const struct mail_storage_service_privileges *priv)
406 {
407 const char *username = t_strcut(input->username, '@');
408 const char *domain = i_strchr_to_next(input->username, '@');
409 const char *uid = priv == NULL ? NULL :
410 dec2str(priv->uid == (uid_t)-1 ? geteuid() : priv->uid);
411 const char *gid = priv == NULL ? NULL :
412 dec2str(priv->gid == (gid_t)-1 ? getegid() : priv->gid);
413
414 const char *auth_user, *auth_username, *auth_domain;
415 if (user == NULL || user->auth_user == NULL) {
416 auth_user = input->username;
417 auth_username = username;
418 auth_domain = domain;
419 } else {
420 auth_user = user->auth_user;
421 auth_username = t_strcut(user->auth_user, '@');
422 auth_domain = i_strchr_to_next(user->auth_user, '@');
423 }
424
425 const struct var_expand_table stack_tab[] = {
426 { 'u', input->username, "user" },
427 { 'n', username, "username" },
428 { 'd', domain, "domain" },
429 { 's', service->name, "service" },
430 { 'l', net_ip2addr(&input->local_ip), "lip" },
431 { 'r', net_ip2addr(&input->remote_ip), "rip" },
432 { 'p', my_pid, "pid" },
433 { 'i', uid, "uid" },
434 { '\0', gid, "gid" },
435 { '\0', input->session_id, "session" },
436 { '\0', auth_user, "auth_user" },
437 { '\0', auth_username, "auth_username" },
438 { '\0', auth_domain, "auth_domain" },
439 /* aliases: */
440 { '\0', net_ip2addr(&input->local_ip), "local_ip" },
441 { '\0', net_ip2addr(&input->remote_ip), "remote_ip" },
442 { '\0', NULL, NULL }
443 };
444 struct var_expand_table *tab;
445
446 tab = t_malloc_no0(sizeof(stack_tab));
447 memcpy(tab, stack_tab, sizeof(stack_tab));
448 return tab;
449 }
450
451 const struct var_expand_table *
mail_storage_service_get_var_expand_table(struct mail_storage_service_ctx * ctx,struct mail_storage_service_input * input)452 mail_storage_service_get_var_expand_table(struct mail_storage_service_ctx *ctx,
453 struct mail_storage_service_input *input)
454 {
455 struct mail_storage_service_privileges priv;
456
457 i_zero(&priv);
458 priv.uid = (uid_t)-1;
459 priv.gid = (gid_t)-1;
460 return get_var_expand_table(ctx->service, NULL, input, &priv);
461 }
462
463 static bool
user_expand_varstr(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,struct mail_storage_service_privileges * priv,const char * str,const char ** value_r,const char ** error_r)464 user_expand_varstr(struct mail_storage_service_ctx *ctx,
465 struct mail_storage_service_user *user,
466 struct mail_storage_service_privileges *priv,
467 const char *str, const char **value_r, const char **error_r)
468 {
469 string_t *value;
470 int ret;
471
472 if (*str == SETTING_STRVAR_EXPANDED[0]) {
473 *value_r = str + 1;
474 return TRUE;
475 }
476
477 i_assert(*str == SETTING_STRVAR_UNEXPANDED[0]);
478
479 value = t_str_new(256);
480 ret = mail_storage_service_var_expand(ctx, value, str + 1, user,
481 &user->input, priv, error_r);
482 *value_r = str_c(value);
483 return ret > 0;
484 }
485
486 static int
service_parse_privileges(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,struct mail_storage_service_privileges * priv_r,const char ** error_r)487 service_parse_privileges(struct mail_storage_service_ctx *ctx,
488 struct mail_storage_service_user *user,
489 struct mail_storage_service_privileges *priv_r,
490 const char **error_r)
491 {
492 const struct mail_user_settings *set = user->user_set;
493 uid_t uid = (uid_t)-1;
494 gid_t gid = (gid_t)-1;
495 const char *error;
496
497 i_zero(priv_r);
498 if (*set->mail_uid != '\0') {
499 if (!parse_uid(set->mail_uid, &uid, error_r)) {
500 *error_r = t_strdup_printf("%s (from %s)", *error_r,
501 user->uid_source);
502 return -1;
503 }
504 if (uid < (uid_t)set->first_valid_uid ||
505 (set->last_valid_uid != 0 &&
506 uid > (uid_t)set->last_valid_uid)) {
507 *error_r = t_strdup_printf(
508 "Mail access for users with UID %s not permitted "
509 "(see first_valid_uid in config file, uid from %s).",
510 dec2str(uid), user->uid_source);
511 return -1;
512 }
513 }
514 priv_r->uid = uid;
515 priv_r->uid_source = user->uid_source;
516
517 if (*set->mail_gid != '\0') {
518 if (!parse_gid(set->mail_gid, &gid, error_r)) {
519 *error_r = t_strdup_printf("%s (from %s)", *error_r,
520 user->gid_source);
521 return -1;
522 }
523 if (gid < (gid_t)set->first_valid_gid ||
524 (set->last_valid_gid != 0 &&
525 gid > (gid_t)set->last_valid_gid)) {
526 *error_r = t_strdup_printf(
527 "Mail access for users with GID %s not permitted "
528 "(see first_valid_gid in config file, gid from %s).",
529 dec2str(gid), user->gid_source);
530 return -1;
531 }
532 }
533 priv_r->gid = gid;
534 priv_r->gid_source = user->gid_source;
535
536 /* variable strings are expanded in mail_user_init(),
537 but we need the home and chroot sooner so do them separately here. */
538 if (!user_expand_varstr(ctx, user, priv_r, user->user_set->mail_home,
539 &priv_r->home, &error)) {
540 *error_r = t_strdup_printf(
541 "Failed to expand mail_home '%s': %s",
542 user->user_set->mail_home, error);
543 return -1;
544 }
545 if (!user_expand_varstr(ctx, user, priv_r, user->user_set->mail_chroot,
546 &priv_r->chroot, &error)) {
547 *error_r = t_strdup_printf(
548 "Failed to expand mail_chroot '%s': %s",
549 user->user_set->mail_chroot, error);
550 return -1;
551 }
552 return 0;
553 }
554
mail_storage_service_seteuid_root(void)555 static void mail_storage_service_seteuid_root(void)
556 {
557 if (seteuid(0) < 0) {
558 i_fatal("mail-storage-service: "
559 "Failed to restore temporarily dropped root privileges: "
560 "seteuid(0) failed: %m");
561 }
562 }
563
564 static int
service_drop_privileges(struct mail_storage_service_user * user,struct mail_storage_service_privileges * priv,bool allow_root,bool keep_setuid_root,bool setenv_only,const char ** error_r)565 service_drop_privileges(struct mail_storage_service_user *user,
566 struct mail_storage_service_privileges *priv,
567 bool allow_root, bool keep_setuid_root,
568 bool setenv_only, const char **error_r)
569 {
570 const struct mail_user_settings *set = user->user_set;
571 struct restrict_access_settings rset;
572 uid_t current_euid, setuid_uid = 0;
573 const char *cur_chroot, *error;
574
575 current_euid = geteuid();
576 restrict_access_init(&rset);
577 restrict_access_get_env(&rset);
578 rset.allow_setuid_root = keep_setuid_root;
579 if (priv->uid != (uid_t)-1) {
580 rset.uid = priv->uid;
581 rset.uid_source = priv->uid_source;
582 } else if (rset.uid == (uid_t)-1 &&
583 !allow_root && current_euid == 0) {
584 *error_r = "User is missing UID (see mail_uid setting)";
585 return -1;
586 }
587 if (priv->gid != (gid_t)-1) {
588 rset.gid = priv->gid;
589 rset.gid_source = priv->gid_source;
590 } else if (rset.gid == (gid_t)-1 && !allow_root &&
591 set->first_valid_gid > 0 && getegid() == 0) {
592 *error_r = "User is missing GID (see mail_gid setting)";
593 return -1;
594 }
595 if (*set->mail_privileged_group != '\0') {
596 if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
597 &error)) {
598 *error_r = t_strdup_printf(
599 "%s (in mail_privileged_group setting)", error);
600 return -1;
601 }
602 }
603 if (*set->mail_access_groups != '\0') {
604 rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
605 rset.extra_groups, NULL);
606 }
607
608 rset.first_valid_gid = set->first_valid_gid;
609 rset.last_valid_gid = set->last_valid_gid;
610 rset.chroot_dir = *priv->chroot == '\0' ? NULL : priv->chroot;
611 rset.system_groups_user = user->system_groups_user;
612
613 cur_chroot = restrict_access_get_current_chroot();
614 if (cur_chroot != NULL) {
615 /* we're already chrooted. make sure the chroots are equal. */
616 if (rset.chroot_dir == NULL) {
617 *error_r = "Process is already chrooted, "
618 "can't un-chroot for this user";
619 return -1;
620 }
621 if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
622 *error_r = t_strdup_printf(
623 "Process is already chrooted to %s, "
624 "can't chroot to %s", cur_chroot, priv->chroot);
625 return -1;
626 }
627 /* chrooting to same directory where we're already chrooted */
628 rset.chroot_dir = NULL;
629 }
630
631 if (!allow_root &&
632 (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
633 *error_r = "Mail access not allowed for root";
634 return -1;
635 }
636
637 if (keep_setuid_root) {
638 if (current_euid != rset.uid && rset.uid != (uid_t)-1) {
639 if (current_euid != 0) {
640 /* we're changing the UID,
641 switch back to root first */
642 mail_storage_service_seteuid_root();
643 }
644 setuid_uid = rset.uid;
645 }
646 rset.uid = (uid_t)-1;
647 allow_root = TRUE;
648 }
649 if (!setenv_only) {
650 restrict_access(&rset, allow_root ? RESTRICT_ACCESS_FLAG_ALLOW_ROOT : 0,
651 *priv->home == '\0' ? NULL : priv->home);
652 } else {
653 restrict_access_set_env(&rset);
654 }
655 if (setuid_uid != 0 && !setenv_only) {
656 if (seteuid(setuid_uid) < 0)
657 i_fatal("mail-storage-service: seteuid(%s) failed: %m",
658 dec2str(setuid_uid));
659 }
660 return 0;
661 }
662
663 static int
mail_storage_service_init_post(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,struct mail_storage_service_privileges * priv,const char * session_id_suffix,struct mail_user ** mail_user_r,const char ** error_r)664 mail_storage_service_init_post(struct mail_storage_service_ctx *ctx,
665 struct mail_storage_service_user *user,
666 struct mail_storage_service_privileges *priv,
667 const char *session_id_suffix,
668 struct mail_user **mail_user_r,
669 const char **error_r)
670 {
671 const char *home = priv->home;
672 struct mail_user_connection_data conn_data;
673 struct mail_user *mail_user;
674 int ret;
675
676 i_zero(&conn_data);
677 conn_data.local_ip = &user->input.local_ip;
678 conn_data.remote_ip = &user->input.remote_ip;
679 conn_data.local_port = user->input.local_port;
680 conn_data.remote_port = user->input.remote_port;
681 conn_data.secured = user->input.conn_secured;
682 conn_data.ssl_secured = user->input.conn_ssl_secured;
683
684 /* NOTE: if more user initialization is added, add it also to
685 mail_user_dup() */
686 mail_user = mail_user_alloc_nodup_set(user->event, user->input.username,
687 user->user_info, user->user_set);
688 mail_user->_service_user = user;
689 mail_storage_service_user_ref(user);
690 mail_user_set_home(mail_user, *home == '\0' ? NULL : home);
691 mail_user_set_vars(mail_user, ctx->service->name, &conn_data);
692 mail_user->uid = priv->uid == (uid_t)-1 ? geteuid() : priv->uid;
693 mail_user->gid = priv->gid == (gid_t)-1 ? getegid() : priv->gid;
694 mail_user->anonymous = user->anonymous;
695 mail_user->admin = user->admin;
696 mail_user->auth_mech = p_strdup(mail_user->pool, user->auth_mech);
697 mail_user->auth_token = p_strdup(mail_user->pool, user->auth_token);
698 mail_user->auth_user = p_strdup(mail_user->pool, user->auth_user);
699 if (user->input.session_create_time != 0) {
700 mail_user->session_create_time =
701 user->input.session_create_time;
702 mail_user->session_restored = TRUE;
703 }
704
705 if (session_id_suffix == NULL) {
706 if (user->session_id_counter++ == 0) {
707 mail_user->session_id =
708 p_strdup(mail_user->pool, user->input.session_id);
709 } else {
710 mail_user->session_id =
711 p_strdup_printf(mail_user->pool, "%s:%u",
712 user->input.session_id,
713 user->session_id_counter);
714 }
715 } else
716 mail_user->session_id =
717 p_strdup_printf(mail_user->pool, "%s:%s",
718 user->input.session_id,
719 session_id_suffix);
720 event_add_str(user->event, "session", mail_user->session_id);
721
722 mail_user->userdb_fields = user->input.userdb_fields == NULL ? NULL :
723 p_strarray_dup(mail_user->pool, user->input.userdb_fields);
724
725 string_t *str = t_str_new(64);
726
727 str_printfa(str, "Effective uid=%s, gid=%s, home=%s",
728 dec2str(geteuid()), dec2str(getegid()), home);
729 if (*priv->chroot != '\0')
730 str_printfa(str, ", chroot=%s", priv->chroot);
731 e_debug(mail_user->event, "%s", str_c(str));
732
733 if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
734 (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) == 0) {
735 /* we don't want to write core files to any users' home
736 directories since they could contain information about other
737 users' mails as well. so do no chdiring to home. */
738 } else if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR) == 0) {
739 /* If possible chdir to home directory, so that core file
740 could be written in case we crash.
741
742 fallback to chdir()ing to root directory. this is needed
743 because the current directory may not be accessible after
744 dropping privileges, and for example unlink_directory()
745 requires ability to open the current directory. */
746 const char *chdir_path = user->chdir_path != NULL ?
747 user->chdir_path : home;
748
749 if (chdir_path[0] == '\0') {
750 if (chdir("/") < 0)
751 e_error(user->event, "chdir(/) failed: %m");
752 } else if (chdir(chdir_path) < 0) {
753 if (errno == EACCES) {
754 e_error(user->event, "%s",
755 eacces_error_get("chdir",
756 t_strconcat(chdir_path, "/", NULL)));
757 } else if (errno != ENOENT)
758 e_error(user->event, "chdir(%s) failed: %m",
759 chdir_path);
760 else
761 e_debug(mail_user->event, "Home dir not found: %s", chdir_path);
762
763 if (chdir("/") < 0)
764 e_error(user->event, "chdir(/) failed: %m");
765 }
766 }
767
768 T_BEGIN {
769 ret = mail_user_init(mail_user, error_r);
770 } T_END_PASS_STR_IF(ret < 0, error_r);
771 if (ret < 0) {
772 mail_user_unref(&mail_user);
773 return -1;
774 }
775 if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES) == 0) {
776 if (mail_namespaces_init(mail_user, error_r) < 0) {
777 mail_user_deinit(&mail_user);
778 return -1;
779 }
780 }
781
782 *mail_user_r = mail_user;
783 return 0;
784 }
785
mail_storage_service_io_activate_user(struct mail_storage_service_user * user)786 void mail_storage_service_io_activate_user(struct mail_storage_service_user *user)
787 {
788 io_loop_context_activate(user->ioloop_ctx);
789 }
790
mail_storage_service_io_deactivate_user(struct mail_storage_service_user * user)791 void mail_storage_service_io_deactivate_user(struct mail_storage_service_user *user)
792 {
793 io_loop_context_deactivate(user->ioloop_ctx);
794 }
795
796 static void
mail_storage_service_io_activate_user_cb(struct mail_storage_service_user * user)797 mail_storage_service_io_activate_user_cb(struct mail_storage_service_user *user)
798 {
799 event_push_global(user->event);
800 if (array_is_created(&user->event_stack)) {
801 struct event *const *events;
802 unsigned int i, count;
803
804 /* push the global events from stack in reverse order */
805 events = array_get(&user->event_stack, &count);
806 for (i = count; i > 0; i--)
807 event_push_global(events[i-1]);
808 array_clear(&user->event_stack);
809 }
810 if (user->log_prefix != NULL)
811 i_set_failure_prefix("%s", user->log_prefix);
812 }
813
814 static void
mail_storage_service_io_deactivate_user_cb(struct mail_storage_service_user * user)815 mail_storage_service_io_deactivate_user_cb(struct mail_storage_service_user *user)
816 {
817 struct event *event;
818
819 /* ioloop context is always global, so we can't push one ioloop context
820 on top of another one. We'll need to rewind the global event stack
821 until we've reached the event that started this context. We'll push
822 these global events back when the user's context is activated
823 again. (We'll assert-crash if the user is freed before these
824 global events have been popped.) */
825 while ((event = event_get_global()) != user->event) {
826 i_assert(event != NULL);
827 if (!array_is_created(&user->event_stack))
828 i_array_init(&user->event_stack, 4);
829 array_push_back(&user->event_stack, &event);
830 event_pop_global(event);
831 }
832 event_pop_global(user->event);
833 if (user->log_prefix != NULL)
834 i_set_failure_prefix("%s", user->service_ctx->default_log_prefix);
835 }
836
field_get_default(const char * data)837 static const char *field_get_default(const char *data)
838 {
839 const char *p;
840
841 p = strchr(data, ':');
842 if (p == NULL)
843 return "";
844 else {
845 /* default value given */
846 return p+1;
847 }
848 }
849
mail_storage_service_fields_var_expand(const char * data,const char * const * fields)850 const char *mail_storage_service_fields_var_expand(const char *data,
851 const char *const *fields)
852 {
853 const char *field_name = t_strcut(data, ':');
854 unsigned int i;
855 size_t field_name_len;
856
857 if (fields == NULL)
858 return field_get_default(data);
859
860 field_name_len = strlen(field_name);
861 for (i = 0; fields[i] != NULL; i++) {
862 if (strncmp(fields[i], field_name, field_name_len) == 0 &&
863 fields[i][field_name_len] == '=')
864 return fields[i] + field_name_len+1;
865 }
866 return field_get_default(data);
867 }
868
869 static int
mail_storage_service_input_var_userdb(const char * data,void * context,const char ** value_r,const char ** error_r ATTR_UNUSED)870 mail_storage_service_input_var_userdb(const char *data, void *context,
871 const char **value_r,
872 const char **error_r ATTR_UNUSED)
873 {
874 struct mail_storage_service_user *user = context;
875
876 *value_r = mail_storage_service_fields_var_expand(data,
877 user == NULL ? NULL : user->input.userdb_fields);
878 return 1;
879 }
880
881 static int
mail_storage_service_var_expand(struct mail_storage_service_ctx * ctx,string_t * str,const char * format,struct mail_storage_service_user * user,const struct mail_storage_service_input * input,const struct mail_storage_service_privileges * priv,const char ** error_r)882 mail_storage_service_var_expand(struct mail_storage_service_ctx *ctx,
883 string_t *str, const char *format,
884 struct mail_storage_service_user *user,
885 const struct mail_storage_service_input *input,
886 const struct mail_storage_service_privileges *priv,
887 const char **error_r)
888 {
889 static const struct var_expand_func_table func_table[] = {
890 { "userdb", mail_storage_service_input_var_userdb },
891 { NULL, NULL }
892 };
893 return var_expand_with_funcs(str, format,
894 get_var_expand_table(ctx->service, user, input, priv),
895 func_table, user, error_r);
896 }
897
898 const char *
mail_storage_service_user_get_log_prefix(struct mail_storage_service_user * user)899 mail_storage_service_user_get_log_prefix(struct mail_storage_service_user *user)
900 {
901 i_assert(user->log_prefix != NULL);
902 return user->log_prefix;
903 }
904
905 static void
mail_storage_service_init_log(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,struct mail_storage_service_privileges * priv)906 mail_storage_service_init_log(struct mail_storage_service_ctx *ctx,
907 struct mail_storage_service_user *user,
908 struct mail_storage_service_privileges *priv)
909 {
910 const char *error;
911
912 T_BEGIN {
913 string_t *str;
914
915 str = t_str_new(256);
916 (void)mail_storage_service_var_expand(ctx, str,
917 user->user_set->mail_log_prefix,
918 user, &user->input, priv, &error);
919 user->log_prefix = p_strdup(user->pool, str_c(str));
920 } T_END;
921 if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) != 0)
922 return;
923
924 ctx->log_initialized = TRUE;
925 master_service_init_log_with_prefix(ctx->service, user->log_prefix);
926 /* replace the whole log prefix with mail_log_prefix */
927 event_replace_log_prefix(user->event, user->log_prefix);
928
929 if (master_service_get_client_limit(master_service) == 1)
930 i_set_failure_send_prefix(user->log_prefix);
931 }
932
933 static void
mail_storage_service_time_moved(const struct timeval * old_time,const struct timeval * new_time)934 mail_storage_service_time_moved(const struct timeval *old_time,
935 const struct timeval *new_time)
936 {
937 long long diff = timeval_diff_usecs(new_time, old_time);
938
939 if (diff > 0) {
940 if ((diff / 1000) > MAX_NOWARN_FORWARD_MSECS)
941 i_warning("Time jumped forwards %lld.%06lld seconds",
942 diff / 1000000, diff % 1000000);
943 return;
944 }
945 diff = -diff;
946
947 if ((diff / 1000) > MAX_TIME_BACKWARDS_SLEEP_MSECS) {
948 i_fatal("Time just moved backwards by %lld.%06lld seconds. "
949 "This might cause a lot of problems, "
950 "so I'll just kill myself now. "
951 "http://wiki2.dovecot.org/TimeMovedBackwards",
952 diff / 1000000, diff % 1000000);
953 } else {
954 i_error("Time just moved backwards by %lld.%06lld seconds. "
955 "I'll sleep now until we're back in present. "
956 "http://wiki2.dovecot.org/TimeMovedBackwards",
957 diff / 1000000, diff % 1000000);
958
959 i_sleep_usecs(diff);
960 }
961 }
962
963 struct mail_storage_service_ctx *
mail_storage_service_init(struct master_service * service,const struct setting_parser_info * set_roots[],enum mail_storage_service_flags flags)964 mail_storage_service_init(struct master_service *service,
965 const struct setting_parser_info *set_roots[],
966 enum mail_storage_service_flags flags)
967 {
968 struct mail_storage_service_ctx *ctx;
969 const char *version;
970 pool_t pool;
971 unsigned int count;
972
973 version = master_service_get_version_string(service);
974 if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) {
975 i_fatal("Version mismatch: libdovecot-storage.so is '%s', "
976 "while the running Dovecot binary is '%s'",
977 PACKAGE_VERSION, version);
978 }
979
980 if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
981 getuid() != 0) {
982 /* service { user } isn't root. the permission drop can't be
983 temporary. */
984 flags &= ENUM_NEGATE(MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP);
985 }
986
987 (void)umask(0077);
988 io_loop_set_time_moved_callback(current_ioloop,
989 mail_storage_service_time_moved);
990
991 mail_storage_init();
992
993 pool = pool_alloconly_create("mail storage service", 2048);
994 ctx = p_new(pool, struct mail_storage_service_ctx, 1);
995 ctx->pool = pool;
996 ctx->service = service;
997 ctx->flags = flags;
998
999 /* @UNSAFE */
1000 if (set_roots == NULL)
1001 count = 0;
1002 else
1003 for (count = 0; set_roots[count] != NULL; count++) ;
1004 ctx->set_roots =
1005 p_new(pool, const struct setting_parser_info *, count + 2);
1006 ctx->set_roots[0] = &mail_user_setting_parser_info;
1007 if (set_roots != NULL) {
1008 memcpy(ctx->set_roots + 1, set_roots,
1009 sizeof(*ctx->set_roots) * count);
1010 }
1011
1012 /* note: we may not have read any settings yet, so this logging
1013 may still be going to wrong location */
1014 const char *configured_name =
1015 master_service_get_configured_name(service);
1016 ctx->default_log_prefix =
1017 p_strdup_printf(pool, "%s(%s): ", configured_name, my_pid);
1018
1019 /* do all the global initialization. delay initializing plugins until
1020 we drop privileges the first time. */
1021 if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0)
1022 master_service_init_log_with_prefix(service, ctx->default_log_prefix);
1023 dict_drivers_register_builtin();
1024 if (storage_service_global == NULL)
1025 storage_service_global = ctx;
1026 return ctx;
1027 }
1028
1029 struct auth_master_connection *
mail_storage_service_get_auth_conn(struct mail_storage_service_ctx * ctx)1030 mail_storage_service_get_auth_conn(struct mail_storage_service_ctx *ctx)
1031 {
1032 i_assert(ctx->conn != NULL);
1033 return ctx->conn;
1034 }
1035
1036 static enum mail_storage_service_flags
mail_storage_service_input_get_flags(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input)1037 mail_storage_service_input_get_flags(struct mail_storage_service_ctx *ctx,
1038 const struct mail_storage_service_input *input)
1039 {
1040 enum mail_storage_service_flags flags;
1041
1042 flags = (ctx->flags & ENUM_NEGATE(input->flags_override_remove)) |
1043 input->flags_override_add;
1044 if (input->no_userdb_lookup) {
1045 /* FIXME: for API backwards compatibility only */
1046 flags &= ENUM_NEGATE(MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP);
1047 }
1048 return flags;
1049 }
1050
mail_storage_service_read_settings(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input,pool_t pool,const struct setting_parser_info ** user_info_r,const struct setting_parser_context ** parser_r,const char ** error_r)1051 int mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
1052 const struct mail_storage_service_input *input,
1053 pool_t pool,
1054 const struct setting_parser_info **user_info_r,
1055 const struct setting_parser_context **parser_r,
1056 const char **error_r)
1057 {
1058 struct master_service_settings_input set_input;
1059 const struct setting_parser_info *const *roots;
1060 struct master_service_settings_output set_output;
1061 const struct dynamic_settings_parser *dyn_parsers;
1062 enum mail_storage_service_flags flags;
1063 unsigned int i;
1064
1065 ctx->config_permission_denied = FALSE;
1066
1067 flags = input == NULL ? ctx->flags :
1068 mail_storage_service_input_get_flags(ctx, input);
1069
1070 i_zero(&set_input);
1071 set_input.roots = ctx->set_roots;
1072 set_input.preserve_user = TRUE;
1073 /* settings reader may exec doveconf, which is going to clear
1074 environment, and if we're not doing a userdb lookup we want to
1075 use $HOME */
1076 set_input.preserve_home =
1077 (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
1078 set_input.use_sysexits =
1079 (flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;
1080 set_input.no_ssl_ca =
1081 (flags & MAIL_STORAGE_SERVICE_FLAG_NO_SSL_CA) != 0;
1082
1083 if (input != NULL) {
1084 set_input.module = input->module;
1085 set_input.service = input->service;
1086 set_input.username = input->username;
1087 set_input.local_ip = input->local_ip;
1088 set_input.remote_ip = input->remote_ip;
1089 }
1090 if (input == NULL) {
1091 /* global settings read - don't create a cache for thi */
1092 } else if (ctx->set_cache == NULL) {
1093 ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
1094 ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
1095 ctx->set_cache = master_service_settings_cache_init(
1096 ctx->service, set_input.module, set_input.service);
1097 } else {
1098 /* already looked up settings at least once.
1099 we really shouldn't be execing anymore. */
1100 set_input.never_exec = TRUE;
1101 }
1102
1103 dyn_parsers = mail_storage_get_dynamic_parsers(pool);
1104 if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
1105 null_strcmp(set_input.service, ctx->set_cache_service) == 0 &&
1106 ctx->set_cache != NULL) {
1107 if (master_service_settings_cache_read(ctx->set_cache,
1108 &set_input, dyn_parsers,
1109 parser_r, error_r) < 0) {
1110 *error_r = t_strdup_printf(
1111 "Error reading configuration: %s", *error_r);
1112 return -1;
1113 }
1114 } else {
1115 settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
1116 if (master_service_settings_read(ctx->service, &set_input,
1117 &set_output, error_r) < 0) {
1118 *error_r = t_strdup_printf(
1119 "Error reading configuration: %s", *error_r);
1120 ctx->config_permission_denied =
1121 set_output.permission_denied;
1122 return -1;
1123 }
1124 *parser_r = ctx->service->set_parser;
1125 }
1126
1127 roots = settings_parser_get_roots(*parser_r);
1128 for (i = 0; roots[i] != NULL; i++) {
1129 if (strcmp(roots[i]->module_name,
1130 mail_user_setting_parser_info.module_name) == 0) {
1131 *user_info_r = roots[i];
1132 return 0;
1133 }
1134 }
1135 i_unreached();
1136 return -1;
1137 }
1138
mail_storage_service_set_auth_conn(struct mail_storage_service_ctx * ctx,struct auth_master_connection * conn)1139 void mail_storage_service_set_auth_conn(struct mail_storage_service_ctx *ctx,
1140 struct auth_master_connection *conn)
1141 {
1142 i_assert(ctx->conn == NULL);
1143 i_assert(mail_user_auth_master_conn == NULL);
1144
1145 ctx->conn = conn;
1146 mail_user_auth_master_conn = conn;
1147 }
1148
1149 static void
mail_storage_service_first_init(struct mail_storage_service_ctx * ctx,const struct setting_parser_info * user_info,const struct mail_user_settings * user_set,enum mail_storage_service_flags service_flags)1150 mail_storage_service_first_init(struct mail_storage_service_ctx *ctx,
1151 const struct setting_parser_info *user_info,
1152 const struct mail_user_settings *user_set,
1153 enum mail_storage_service_flags service_flags)
1154 {
1155 enum auth_master_flags flags = 0;
1156
1157 ctx->debug = mail_user_set_get_mail_debug(user_info, user_set) ||
1158 (service_flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0;
1159 if (ctx->debug)
1160 flags |= AUTH_MASTER_FLAG_DEBUG;
1161 if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT) != 0)
1162 flags |= AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT;
1163 mail_storage_service_set_auth_conn(ctx,
1164 auth_master_init(user_set->auth_socket_path, flags));
1165 }
1166
1167 static int
mail_storage_service_load_modules(struct mail_storage_service_ctx * ctx,const struct setting_parser_info * user_info,const struct mail_user_settings * user_set,const char ** error_r)1168 mail_storage_service_load_modules(struct mail_storage_service_ctx *ctx,
1169 const struct setting_parser_info *user_info,
1170 const struct mail_user_settings *user_set,
1171 const char **error_r)
1172 {
1173 struct module_dir_load_settings mod_set;
1174
1175 if (*user_set->mail_plugins == '\0')
1176 return 0;
1177 if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0)
1178 return 0;
1179
1180 i_zero(&mod_set);
1181 mod_set.abi_version = DOVECOT_ABI_VERSION;
1182 mod_set.binary_name = master_service_get_name(ctx->service);
1183 mod_set.setting_name = "mail_plugins";
1184 mod_set.require_init_funcs = TRUE;
1185 mod_set.debug = mail_user_set_get_mail_debug(user_info, user_set);
1186
1187 return module_dir_try_load_missing(&mail_storage_service_modules,
1188 user_set->mail_plugin_dir,
1189 user_set->mail_plugins,
1190 &mod_set, error_r);
1191 }
1192
extra_field_key_cmp_p(const char * const * s1,const char * const * s2)1193 static int extra_field_key_cmp_p(const char *const *s1, const char *const *s2)
1194 {
1195 const char *p1 = *s1, *p2 = *s2;
1196
1197 for (; *p1 == *p2; p1++, p2++) {
1198 if (*p1 == '\0')
1199 return 0;
1200 }
1201 if (*p1 == '=')
1202 return -1;
1203 if (*p2 == '=')
1204 return 1;
1205 return *p1 - *p2;
1206 }
1207
1208 static void
mail_storage_service_set_log_prefix(struct mail_storage_service_ctx * ctx,const struct mail_user_settings * user_set,struct mail_storage_service_user * user,const struct mail_storage_service_input * input,const struct mail_storage_service_privileges * priv)1209 mail_storage_service_set_log_prefix(struct mail_storage_service_ctx *ctx,
1210 const struct mail_user_settings *user_set,
1211 struct mail_storage_service_user *user,
1212 const struct mail_storage_service_input *input,
1213 const struct mail_storage_service_privileges *priv)
1214 {
1215 string_t *str;
1216 const char *error;
1217
1218 str = t_str_new(256);
1219 (void)mail_storage_service_var_expand(ctx, str, user_set->mail_log_prefix,
1220 user, input, priv, &error);
1221 i_set_failure_prefix("%s", str_c(str));
1222 }
1223
1224 static const char *
mail_storage_service_generate_session_id(pool_t pool,const char * prefix)1225 mail_storage_service_generate_session_id(pool_t pool, const char *prefix)
1226 {
1227 guid_128_t guid;
1228 size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
1229 string_t *str = str_new(pool, MAX_BASE64_ENCODED_SIZE(prefix_len + 1 + sizeof(guid)));
1230
1231 if (prefix != NULL)
1232 str_printfa(str, "%s:", prefix);
1233
1234 guid_128_generate(guid);
1235 base64_encode(guid, sizeof(guid), str);
1236 /* remove the trailing "==" */
1237 i_assert(str_data(str)[str_len(str)-2] == '=');
1238 str_truncate(str, str_len(str)-2);
1239 return str_c(str);
1240
1241 }
1242
1243 static int
mail_storage_service_lookup_real(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input,bool update_log_prefix,struct mail_storage_service_user ** user_r,const char ** error_r)1244 mail_storage_service_lookup_real(struct mail_storage_service_ctx *ctx,
1245 const struct mail_storage_service_input *input,
1246 bool update_log_prefix,
1247 struct mail_storage_service_user **user_r,
1248 const char **error_r)
1249 {
1250 enum mail_storage_service_flags flags;
1251 struct mail_storage_service_user *user;
1252 const char *username = input->username;
1253 const struct setting_parser_info *user_info;
1254 const struct mail_user_settings *user_set;
1255 const char *const *userdb_fields, *error;
1256 struct auth_user_reply reply;
1257 const struct setting_parser_context *set_parser;
1258 void **sets;
1259 pool_t user_pool, temp_pool;
1260 int ret = 1;
1261
1262 user_pool = pool_alloconly_create(MEMPOOL_GROWING"mail storage service user", 1024*6);
1263 flags = mail_storage_service_input_get_flags(ctx, input);
1264
1265 if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
1266 geteuid() != 0) {
1267 /* we dropped privileges only temporarily. switch back to root
1268 before reading settings, so we'll definitely have enough
1269 permissions to connect to the config socket. */
1270 mail_storage_service_seteuid_root();
1271 }
1272
1273 if (mail_storage_service_read_settings(ctx, input, user_pool,
1274 &user_info, &set_parser,
1275 error_r) < 0) {
1276 if (ctx->config_permission_denied) {
1277 /* just restart and maybe next time we will open the
1278 config socket before dropping privileges */
1279 i_fatal("%s", *error_r);
1280 }
1281 pool_unref(&user_pool);
1282 return -1;
1283 }
1284
1285 if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
1286 !ctx->log_initialized) {
1287 /* initialize logging again, in case we only read the
1288 settings for the first above */
1289 ctx->log_initialized = TRUE;
1290 master_service_init_log_with_prefix(ctx->service,
1291 ctx->default_log_prefix);
1292 update_log_prefix = TRUE;
1293 }
1294 sets = master_service_settings_parser_get_others(master_service,
1295 set_parser);
1296 user_set = sets[0];
1297
1298 if (update_log_prefix)
1299 mail_storage_service_set_log_prefix(ctx, user_set, NULL, input, NULL);
1300
1301 if (ctx->conn == NULL)
1302 mail_storage_service_first_init(ctx, user_info, user_set, flags);
1303 /* load global plugins */
1304 if (mail_storage_service_load_modules(ctx, user_info, user_set, error_r) < 0) {
1305 pool_unref(&user_pool);
1306 return -1;
1307 }
1308
1309 if (ctx->userdb_next_pool == NULL)
1310 temp_pool = pool_alloconly_create("userdb lookup", 2048);
1311 else {
1312 temp_pool = ctx->userdb_next_pool;
1313 ctx->userdb_next_pool = NULL;
1314 pool_ref(temp_pool);
1315 }
1316 if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
1317 ret = service_auth_userdb_lookup(ctx, input, temp_pool,
1318 &username, &userdb_fields, error_r);
1319 if (ret <= 0) {
1320 pool_unref(&temp_pool);
1321 pool_unref(&user_pool);
1322 return ret;
1323 }
1324 if (ctx->userdb_next_fieldsp != NULL)
1325 *ctx->userdb_next_fieldsp = userdb_fields;
1326 } else {
1327 userdb_fields = input->userdb_fields;
1328 }
1329
1330 user = p_new(user_pool, struct mail_storage_service_user, 1);
1331 user->refcount = 1;
1332 user->service_ctx = ctx;
1333 user->pool = user_pool;
1334 user->input = *input;
1335 user->input.userdb_fields = userdb_fields == NULL ? NULL :
1336 p_strarray_dup(user_pool, userdb_fields);
1337 user->input.username = p_strdup(user_pool, username);
1338 user->input.session_id = p_strdup(user_pool, input->session_id);
1339 if (user->input.session_id == NULL) {
1340 user->input.session_id =
1341 mail_storage_service_generate_session_id(user_pool,
1342 input->session_id_prefix);
1343 }
1344 user->input.session_create_time = input->session_create_time;
1345 user->user_info = user_info;
1346 user->flags = flags;
1347
1348 user->set_parser = settings_parser_dup(set_parser, user_pool);
1349
1350 sets = master_service_settings_parser_get_others(master_service,
1351 user->set_parser);
1352 user->user_set = sets[0];
1353 user->ssl_set = master_service_ssl_settings_get_from_parser(user->set_parser);
1354 user->gid_source = "mail_gid setting";
1355 user->uid_source = "mail_uid setting";
1356 /* Create an event that will be used as the default event for logging.
1357 This event won't be a parent to any other events - mail_user.event
1358 will be used for that. */
1359 user->event = event_create(input->event_parent);
1360 event_set_forced_debug(user->event,
1361 user->service_ctx->debug || (flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0);
1362 event_add_fields(user->event, (const struct event_add_field []){
1363 { .key = "user", .value = user->input.username },
1364 { .key = "session", .value = user->input.session_id },
1365 { .key = NULL }
1366 });
1367
1368 if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
1369 (void)settings_parse_line(user->set_parser, "mail_debug=yes");
1370
1371 if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
1372 const char *home = getenv("HOME");
1373 if (home != NULL)
1374 set_keyval(ctx, user, "mail_home", home);
1375 }
1376
1377 if (userdb_fields != NULL) {
1378 auth_user_fields_parse(userdb_fields, temp_pool, &reply);
1379 array_sort(&reply.extra_fields, extra_field_key_cmp_p);
1380 if (user_reply_handle(ctx, user, &reply, &error) < 0) {
1381 *error_r = t_strdup_printf(
1382 "Invalid settings in userdb: %s", error);
1383 ret = -2;
1384 }
1385 }
1386 if (ret > 0 && !settings_parser_check(user->set_parser, user_pool, &error)) {
1387 *error_r = t_strdup_printf(
1388 "Invalid settings (probably caused by userdb): %s", error);
1389 ret = -2;
1390 }
1391 pool_unref(&temp_pool);
1392
1393 /* load per-user plugins */
1394 if (ret > 0) {
1395 if (mail_storage_service_load_modules(ctx, user_info,
1396 user->user_set,
1397 error_r) < 0) {
1398 ret = -2;
1399 }
1400 }
1401 if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS) != 0 &&
1402 user_set->mail_plugins[0] != '\0') {
1403 /* mail_storage_service_load_modules() already avoids loading
1404 plugins when the _NO_PLUGINS flag is set. However, it's
1405 possible that the plugins are already loaded, because the
1406 plugin loading is a global state. This is especially true
1407 with doveadm, which loads the mail_plugins immediately at
1408 startup so it can find commands registered by plugins. It's
1409 fine that extra plugins are loaded - we'll just need to
1410 prevent any of their hooks from being called. One easy way
1411 to do this is just to clear out the mail_plugins setting: */
1412 (void)settings_parse_line(user->set_parser, "mail_plugins=");
1413 }
1414
1415 if (ret < 0)
1416 mail_storage_service_user_unref(&user);
1417 *user_r = user;
1418 return ret;
1419 }
1420
mail_storage_service_lookup(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input,struct mail_storage_service_user ** user_r,const char ** error_r)1421 int mail_storage_service_lookup(struct mail_storage_service_ctx *ctx,
1422 const struct mail_storage_service_input *input,
1423 struct mail_storage_service_user **user_r,
1424 const char **error_r)
1425 {
1426 char *old_log_prefix = i_strdup(i_get_failure_prefix());
1427 bool update_log_prefix;
1428 int ret;
1429
1430 if (io_loop_get_current_context(current_ioloop) == NULL) {
1431 /* no user yet. log prefix should be just "imap:" or something
1432 equally unhelpful. we don't know the proper log format yet,
1433 but initialize it to something better until we know it. */
1434 const char *session_id =
1435 input->session_id != NULL ? input->session_id :
1436 (input->session_id_prefix != NULL ?
1437 input->session_id_prefix : NULL);
1438 i_set_failure_prefix("%s(%s%s%s): ",
1439 master_service_get_name(ctx->service), input->username,
1440 session_id == NULL ? "" : t_strdup_printf(",%s", session_id),
1441 input->remote_ip.family == 0 ? "" :
1442 t_strdup_printf(",%s", net_ip2addr(&input->remote_ip)));
1443 update_log_prefix = TRUE;
1444 } else {
1445 /* we might be here because we're doing a user lookup for a
1446 shared user. the log prefix is likely already usable, so
1447 just append our own without replacing the whole thing. */
1448 i_set_failure_prefix("%suser-lookup(%s): ",
1449 old_log_prefix, input->username);
1450 update_log_prefix = FALSE;
1451 }
1452
1453 T_BEGIN {
1454 ret = mail_storage_service_lookup_real(ctx, input,
1455 update_log_prefix, user_r, error_r);
1456 } T_END_PASS_STR_IF(ret < 0, error_r);
1457 i_set_failure_prefix("%s", old_log_prefix);
1458 i_free(old_log_prefix);
1459 return ret;
1460 }
1461
mail_storage_service_save_userdb_fields(struct mail_storage_service_ctx * ctx,pool_t pool,const char * const ** userdb_fields_r)1462 void mail_storage_service_save_userdb_fields(struct mail_storage_service_ctx *ctx,
1463 pool_t pool, const char *const **userdb_fields_r)
1464 {
1465 i_assert(pool != NULL);
1466 i_assert(userdb_fields_r != NULL);
1467
1468 ctx->userdb_next_pool = pool;
1469 ctx->userdb_next_fieldsp = userdb_fields_r;
1470 *userdb_fields_r = NULL;
1471 }
1472
1473 static int
mail_storage_service_next_real(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,const char * session_id_suffix,struct mail_user ** mail_user_r,const char ** error_r)1474 mail_storage_service_next_real(struct mail_storage_service_ctx *ctx,
1475 struct mail_storage_service_user *user,
1476 const char *session_id_suffix,
1477 struct mail_user **mail_user_r,
1478 const char **error_r)
1479 {
1480 struct mail_storage_service_privileges priv;
1481 const char *error;
1482 size_t len;
1483 bool allow_root =
1484 (user->flags & MAIL_STORAGE_SERVICE_FLAG_ALLOW_ROOT) != 0;
1485 bool temp_priv_drop =
1486 (user->flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0;
1487 bool use_chroot;
1488
1489 if (service_parse_privileges(ctx, user, &priv, error_r) < 0)
1490 return -2;
1491
1492 if (*priv.home != '/' && *priv.home != '\0') {
1493 *error_r = t_strdup_printf(
1494 "Relative home directory paths not supported: %s",
1495 priv.home);
1496 return -2;
1497 }
1498
1499 /* we can't chroot if we want to switch between users. there's
1500 not much point either (from security point of view). but if we're
1501 already chrooted, we'll just have to continue and hope that the
1502 current chroot is the same as the wanted chroot */
1503 use_chroot = !temp_priv_drop ||
1504 restrict_access_get_current_chroot() != NULL;
1505
1506 len = strlen(priv.chroot);
1507 if (len > 2 && strcmp(priv.chroot + len - 2, "/.") == 0 &&
1508 strncmp(priv.home, priv.chroot, len - 2) == 0) {
1509 /* mail_chroot = /chroot/. means that the home dir already
1510 contains the chroot dir. remove it from home. */
1511 if (use_chroot) {
1512 priv.home += len - 2;
1513 if (*priv.home == '\0')
1514 priv.home = "/";
1515 priv.chroot = t_strndup(priv.chroot, len - 2);
1516
1517 set_keyval(ctx, user, "mail_home", priv.home);
1518 set_keyval(ctx, user, "mail_chroot", priv.chroot);
1519 }
1520 } else if (len > 0 && !use_chroot) {
1521 /* we're not going to chroot. fix home directory so we can
1522 access it. */
1523 if (*priv.home == '\0' || strcmp(priv.home, "/") == 0)
1524 priv.home = priv.chroot;
1525 else
1526 priv.home = t_strconcat(priv.chroot, priv.home, NULL);
1527 priv.chroot = "";
1528 set_keyval(ctx, user, "mail_home", priv.home);
1529 }
1530
1531 mail_storage_service_init_log(ctx, user, &priv);
1532
1533 /* create ioloop context regardless of logging. it's also used by
1534 stats plugin. */
1535 if (user->ioloop_ctx == NULL) {
1536 user->ioloop_ctx = io_loop_context_new(current_ioloop);
1537 io_loop_context_add_callbacks(user->ioloop_ctx,
1538 mail_storage_service_io_activate_user_cb,
1539 mail_storage_service_io_deactivate_user_cb,
1540 user);
1541 }
1542 io_loop_context_switch(user->ioloop_ctx);
1543
1544 if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
1545 if (service_drop_privileges(user, &priv,
1546 allow_root, temp_priv_drop,
1547 FALSE, &error) < 0) {
1548 *error_r = t_strdup_printf(
1549 "Couldn't drop privileges: %s", error);
1550 return -1;
1551 }
1552 if (!temp_priv_drop ||
1553 (user->flags & MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS) != 0)
1554 restrict_access_allow_coredumps(TRUE);
1555 }
1556
1557 /* privileges are dropped. initialize plugins that haven't been
1558 initialized yet. */
1559 module_dir_init(mail_storage_service_modules);
1560
1561 if (mail_storage_service_init_post(ctx, user, &priv,
1562 session_id_suffix,
1563 mail_user_r, error_r) < 0)
1564 return -2;
1565 return 0;
1566 }
1567
mail_storage_service_next(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,struct mail_user ** mail_user_r,const char ** error_r)1568 int mail_storage_service_next(struct mail_storage_service_ctx *ctx,
1569 struct mail_storage_service_user *user,
1570 struct mail_user **mail_user_r,
1571 const char **error_r)
1572 {
1573 return mail_storage_service_next_with_session_suffix(ctx,
1574 user,
1575 NULL,
1576 mail_user_r,
1577 error_r);
1578 }
1579
mail_storage_service_next_with_session_suffix(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user,const char * session_id_suffix,struct mail_user ** mail_user_r,const char ** error_r)1580 int mail_storage_service_next_with_session_suffix(struct mail_storage_service_ctx *ctx,
1581 struct mail_storage_service_user *user,
1582 const char *session_id_suffix,
1583 struct mail_user **mail_user_r,
1584 const char **error_r)
1585 {
1586 char *old_log_prefix = i_strdup(i_get_failure_prefix());
1587 int ret;
1588
1589 mail_storage_service_set_log_prefix(ctx, user->user_set, user,
1590 &user->input, NULL);
1591 i_set_failure_prefix("%s", old_log_prefix);
1592 T_BEGIN {
1593 ret = mail_storage_service_next_real(ctx, user,
1594 session_id_suffix,
1595 mail_user_r, error_r);
1596 } T_END_PASS_STR_IF(ret < 0, error_r);
1597 if ((user->flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) != 0)
1598 i_set_failure_prefix("%s", old_log_prefix);
1599 i_free(old_log_prefix);
1600 return ret;
1601 }
1602
mail_storage_service_restrict_setenv(struct mail_storage_service_ctx * ctx,struct mail_storage_service_user * user)1603 void mail_storage_service_restrict_setenv(struct mail_storage_service_ctx *ctx,
1604 struct mail_storage_service_user *user)
1605 {
1606 struct mail_storage_service_privileges priv;
1607 const char *error;
1608
1609 if (service_parse_privileges(ctx, user, &priv, &error) < 0)
1610 i_fatal("user %s: %s", user->input.username, error);
1611 if (service_drop_privileges(user, &priv,
1612 TRUE, FALSE, TRUE, &error) < 0)
1613 i_fatal("user %s: %s", user->input.username, error);
1614 }
1615
mail_storage_service_lookup_next(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input,struct mail_storage_service_user ** user_r,struct mail_user ** mail_user_r,const char ** error_r)1616 int mail_storage_service_lookup_next(struct mail_storage_service_ctx *ctx,
1617 const struct mail_storage_service_input *input,
1618 struct mail_storage_service_user **user_r,
1619 struct mail_user **mail_user_r,
1620 const char **error_r)
1621 {
1622 struct mail_storage_service_user *user;
1623 int ret;
1624
1625 ret = mail_storage_service_lookup(ctx, input, &user, error_r);
1626 if (ret <= 0)
1627 return ret;
1628
1629 ret = mail_storage_service_next(ctx, user, mail_user_r, error_r);
1630 if (ret < 0) {
1631 mail_storage_service_user_unref(&user);
1632 return ret;
1633 }
1634 *user_r = user;
1635 return 1;
1636 }
1637
mail_storage_service_user_ref(struct mail_storage_service_user * user)1638 void mail_storage_service_user_ref(struct mail_storage_service_user *user)
1639 {
1640 i_assert(user->refcount > 0);
1641 user->refcount++;
1642 }
1643
mail_storage_service_user_unref(struct mail_storage_service_user ** _user)1644 void mail_storage_service_user_unref(struct mail_storage_service_user **_user)
1645 {
1646 struct mail_storage_service_user *user = *_user;
1647
1648 *_user = NULL;
1649
1650 i_assert(user->refcount > 0);
1651 if (--user->refcount > 0)
1652 return;
1653
1654 if (user->ioloop_ctx != NULL) {
1655 if (io_loop_get_current_context(current_ioloop) == user->ioloop_ctx)
1656 mail_storage_service_io_deactivate_user(user);
1657 io_loop_context_remove_callbacks(user->ioloop_ctx,
1658 mail_storage_service_io_activate_user_cb,
1659 mail_storage_service_io_deactivate_user_cb, user);
1660 io_loop_context_unref(&user->ioloop_ctx);
1661 }
1662
1663 if (array_is_created(&user->event_stack)) {
1664 i_assert(array_count(&user->event_stack) == 0);
1665 array_free(&user->event_stack);
1666 }
1667 settings_parser_deinit(&user->set_parser);
1668 event_unref(&user->event);
1669 pool_unref(&user->pool);
1670 }
1671
mail_storage_service_init_settings(struct mail_storage_service_ctx * ctx,const struct mail_storage_service_input * input)1672 void mail_storage_service_init_settings(struct mail_storage_service_ctx *ctx,
1673 const struct mail_storage_service_input *input)
1674 {
1675 const struct setting_parser_info *user_info;
1676 const struct mail_user_settings *user_set;
1677 const struct setting_parser_context *set_parser;
1678 const char *error;
1679 pool_t temp_pool;
1680 void **sets;
1681
1682 if (ctx->conn != NULL)
1683 return;
1684
1685 temp_pool = pool_alloconly_create("service all settings", 4096);
1686 if (mail_storage_service_read_settings(ctx, input, temp_pool,
1687 &user_info, &set_parser,
1688 &error) < 0)
1689 i_fatal("%s", error);
1690 sets = master_service_settings_parser_get_others(master_service,
1691 set_parser);
1692 user_set = sets[0];
1693
1694 mail_storage_service_first_init(ctx, user_info, user_set, ctx->flags);
1695 pool_unref(&temp_pool);
1696 }
1697
1698 static int
mail_storage_service_all_iter_deinit(struct mail_storage_service_ctx * ctx)1699 mail_storage_service_all_iter_deinit(struct mail_storage_service_ctx *ctx)
1700 {
1701 int ret = 0;
1702
1703 if (ctx->auth_list != NULL) {
1704 ret = auth_master_user_list_deinit(&ctx->auth_list);
1705 auth_master_deinit(&ctx->iter_conn);
1706 }
1707 return ret;
1708 }
1709
mail_storage_service_all_init_mask(struct mail_storage_service_ctx * ctx,const char * user_mask_hint)1710 void mail_storage_service_all_init_mask(struct mail_storage_service_ctx *ctx,
1711 const char *user_mask_hint)
1712 {
1713 enum auth_master_flags flags = 0;
1714
1715 (void)mail_storage_service_all_iter_deinit(ctx);
1716 mail_storage_service_init_settings(ctx, NULL);
1717
1718 /* create a new connection, because the iteration might take a while
1719 and we might want to do USER lookups during it, which don't mix
1720 well in the same connection. */
1721 if (ctx->debug)
1722 flags |= AUTH_MASTER_FLAG_DEBUG;
1723 ctx->iter_conn = auth_master_init(auth_master_get_socket_path(ctx->conn),
1724 flags);
1725 ctx->auth_list = auth_master_user_list_init(ctx->iter_conn,
1726 user_mask_hint, NULL);
1727 }
1728
mail_storage_service_all_next(struct mail_storage_service_ctx * ctx,const char ** username_r)1729 int mail_storage_service_all_next(struct mail_storage_service_ctx *ctx,
1730 const char **username_r)
1731 {
1732 i_assert((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0);
1733
1734 *username_r = auth_master_user_list_next(ctx->auth_list);
1735 if (*username_r != NULL)
1736 return 1;
1737 return mail_storage_service_all_iter_deinit(ctx);
1738 }
1739
mail_storage_service_deinit(struct mail_storage_service_ctx ** _ctx)1740 void mail_storage_service_deinit(struct mail_storage_service_ctx **_ctx)
1741 {
1742 struct mail_storage_service_ctx *ctx = *_ctx;
1743
1744 *_ctx = NULL;
1745 (void)mail_storage_service_all_iter_deinit(ctx);
1746 if (ctx->conn != NULL) {
1747 if (mail_user_auth_master_conn == ctx->conn)
1748 mail_user_auth_master_conn = NULL;
1749 auth_master_deinit(&ctx->conn);
1750 }
1751 if (ctx->set_cache != NULL)
1752 master_service_settings_cache_deinit(&ctx->set_cache);
1753
1754 if (storage_service_global == ctx)
1755 storage_service_global = NULL;
1756 pool_unref(&ctx->pool);
1757
1758 module_dir_unload(&mail_storage_service_modules);
1759 mail_storage_deinit();
1760 dict_drivers_unregister_builtin();
1761 }
1762
mail_storage_service_get_global(void)1763 struct mail_storage_service_ctx *mail_storage_service_get_global(void)
1764 {
1765 return storage_service_global;
1766 }
1767
mail_storage_service_user_get_set(struct mail_storage_service_user * user)1768 void **mail_storage_service_user_get_set(struct mail_storage_service_user *user)
1769 {
1770 return master_service_settings_parser_get_others(master_service,
1771 user->set_parser);
1772 }
1773
1774 const struct mail_storage_settings *
mail_storage_service_user_get_mail_set(struct mail_storage_service_user * user)1775 mail_storage_service_user_get_mail_set(struct mail_storage_service_user *user)
1776 {
1777 return mail_user_set_get_driver_settings(
1778 user->user_info, user->user_set,
1779 MAIL_STORAGE_SET_DRIVER_NAME);
1780 }
1781
1782 const struct mail_storage_service_input *
mail_storage_service_user_get_input(struct mail_storage_service_user * user)1783 mail_storage_service_user_get_input(struct mail_storage_service_user *user)
1784 {
1785 return &user->input;
1786 }
1787
1788 struct setting_parser_context *
mail_storage_service_user_get_settings_parser(struct mail_storage_service_user * user)1789 mail_storage_service_user_get_settings_parser(struct mail_storage_service_user *user)
1790 {
1791 return user->set_parser;
1792 }
1793
1794 const struct master_service_ssl_settings *
mail_storage_service_user_get_ssl_settings(struct mail_storage_service_user * user)1795 mail_storage_service_user_get_ssl_settings(struct mail_storage_service_user *user)
1796 {
1797 return user->ssl_set;
1798 }
1799
1800 struct mail_storage_service_ctx *
mail_storage_service_user_get_service_ctx(struct mail_storage_service_user * user)1801 mail_storage_service_user_get_service_ctx(struct mail_storage_service_user *user)
1802 {
1803 return user->service_ctx;
1804 }
1805
mail_storage_service_user_get_pool(struct mail_storage_service_user * user)1806 pool_t mail_storage_service_user_get_pool(struct mail_storage_service_user *user)
1807 {
1808 return user->pool;
1809 }
1810
mail_storage_service_get_settings(struct master_service * service)1811 void *mail_storage_service_get_settings(struct master_service *service)
1812 {
1813 void **sets, *set;
1814
1815 T_BEGIN {
1816 sets = master_service_settings_get_others(service);
1817 set = sets[1];
1818 } T_END;
1819 return set;
1820 }
1821
mail_storage_service_user_set_setting(struct mail_storage_service_user * user,const char * key,const char * value,const char ** error_r)1822 int mail_storage_service_user_set_setting(struct mail_storage_service_user *user,
1823 const char *key,
1824 const char *value,
1825 const char **error_r)
1826 {
1827 int ret = settings_parse_keyvalue(user->set_parser, key, value);
1828 *error_r = settings_parser_get_error(user->set_parser);
1829 return ret;
1830 }
1831
1832 const char *
mail_storage_service_get_log_prefix(struct mail_storage_service_ctx * ctx)1833 mail_storage_service_get_log_prefix(struct mail_storage_service_ctx *ctx)
1834 {
1835 return ctx->default_log_prefix;
1836 }
1837