1 /* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
2
3 #include "common.h"
4 #include "array.h"
5 #include "env-util.h"
6 #include "istream.h"
7 #include "net.h"
8 #include "str.h"
9 #include "ipwd.h"
10 #include "mkdir-parents.h"
11 #include "safe-mkdir.h"
12 #include "restrict-process-size.h"
13 #include "settings-parser.h"
14 #include "master-settings.h"
15
16 #include <stddef.h>
17 #include <dirent.h>
18 #include <unistd.h>
19 #include <sys/stat.h>
20 #include <sys/wait.h>
21
22 static bool master_settings_verify(void *_set, pool_t pool,
23 const char **error_r);
24
25 extern const struct setting_parser_info service_setting_parser_info;
26
27 #undef DEF
28 #define DEF(type, name) \
29 SETTING_DEFINE_STRUCT_##type(#name, name, struct file_listener_settings)
30
31 static const struct setting_define file_listener_setting_defines[] = {
32 DEF(STR, path),
33 DEF(UINT_OCT, mode),
34 DEF(STR, user),
35 DEF(STR, group),
36
37 SETTING_DEFINE_LIST_END
38 };
39
40 static const struct file_listener_settings file_listener_default_settings = {
41 .path = "",
42 .mode = 0600,
43 .user = "",
44 .group = "",
45 };
46
47 static const struct setting_parser_info file_listener_setting_parser_info = {
48 .defines = file_listener_setting_defines,
49 .defaults = &file_listener_default_settings,
50
51 .type_offset = offsetof(struct file_listener_settings, path),
52 .struct_size = sizeof(struct file_listener_settings),
53
54 .parent_offset = SIZE_MAX,
55 .parent = &service_setting_parser_info
56 };
57
58 #undef DEF
59 #define DEF(type, name) \
60 SETTING_DEFINE_STRUCT_##type(#name, name, struct inet_listener_settings)
61
62 static const struct setting_define inet_listener_setting_defines[] = {
63 DEF(STR, name),
64 DEF(STR, address),
65 DEF(IN_PORT, port),
66 DEF(BOOL, ssl),
67 DEF(BOOL, reuse_port),
68 DEF(BOOL, haproxy),
69
70 SETTING_DEFINE_LIST_END
71 };
72
73 static const struct inet_listener_settings inet_listener_default_settings = {
74 .name = "",
75 .address = "",
76 .port = 0,
77 .ssl = FALSE,
78 .reuse_port = FALSE,
79 .haproxy = FALSE
80 };
81
82 static const struct setting_parser_info inet_listener_setting_parser_info = {
83 .defines = inet_listener_setting_defines,
84 .defaults = &inet_listener_default_settings,
85
86 .type_offset = offsetof(struct inet_listener_settings, name),
87 .struct_size = sizeof(struct inet_listener_settings),
88
89 .parent_offset = SIZE_MAX,
90 .parent = &service_setting_parser_info
91 };
92
93 #undef DEF
94 #undef DEFLIST_UNIQUE
95 #define DEF(type, name) \
96 SETTING_DEFINE_STRUCT_##type(#name, name, struct service_settings)
97 #define DEFLIST_UNIQUE(field, name, defines) \
98 { .type = SET_DEFLIST_UNIQUE, .key = name, \
99 .offset = offsetof(struct service_settings, field), \
100 .list_info = defines }
101
102 static const struct setting_define service_setting_defines[] = {
103 DEF(STR, name),
104 DEF(STR, protocol),
105 DEF(STR, type),
106 DEF(STR, executable),
107 DEF(STR, user),
108 DEF(STR, group),
109 DEF(STR, privileged_group),
110 DEF(STR, extra_groups),
111 DEF(STR, chroot),
112
113 DEF(BOOL, drop_priv_before_exec),
114
115 DEF(UINT, process_min_avail),
116 DEF(UINT, process_limit),
117 DEF(UINT, client_limit),
118 DEF(UINT, service_count),
119 DEF(TIME, idle_kill),
120 DEF(SIZE, vsz_limit),
121
122 DEFLIST_UNIQUE(unix_listeners, "unix_listener",
123 &file_listener_setting_parser_info),
124 DEFLIST_UNIQUE(fifo_listeners, "fifo_listener",
125 &file_listener_setting_parser_info),
126 DEFLIST_UNIQUE(inet_listeners, "inet_listener",
127 &inet_listener_setting_parser_info),
128
129 SETTING_DEFINE_LIST_END
130 };
131
132 static const struct service_settings service_default_settings = {
133 .name = "",
134 .protocol = "",
135 .type = "",
136 .executable = "",
137 .user = "",
138 .group = "",
139 .privileged_group = "",
140 .extra_groups = "",
141 .chroot = "",
142
143 .drop_priv_before_exec = FALSE,
144
145 .process_min_avail = 0,
146 .process_limit = 0,
147 .client_limit = 0,
148 .service_count = 0,
149 .idle_kill = 0,
150 .vsz_limit = UOFF_T_MAX,
151
152 .unix_listeners = ARRAY_INIT,
153 .fifo_listeners = ARRAY_INIT,
154 .inet_listeners = ARRAY_INIT
155 };
156
157 const struct setting_parser_info service_setting_parser_info = {
158 .defines = service_setting_defines,
159 .defaults = &service_default_settings,
160
161 .type_offset = offsetof(struct service_settings, name),
162 .struct_size = sizeof(struct service_settings),
163
164 .parent_offset = offsetof(struct service_settings, master_set),
165 .parent = &master_setting_parser_info
166 };
167
168 #undef DEF
169 #undef DEFLIST_UNIQUE
170 #define DEF(type, name) \
171 SETTING_DEFINE_STRUCT_##type(#name, name, struct master_settings)
172 #define DEFLIST_UNIQUE(field, name, defines) \
173 { .type = SET_DEFLIST_UNIQUE, .key = name, \
174 .offset = offsetof(struct master_settings, field), \
175 .list_info = defines }
176
177 static const struct setting_define master_setting_defines[] = {
178 DEF(STR, base_dir),
179 DEF(STR, state_dir),
180 DEF(STR, libexec_dir),
181 DEF(STR, instance_name),
182 DEF(STR, protocols),
183 DEF(STR, listen),
184 DEF(ENUM, ssl),
185 DEF(STR, default_internal_user),
186 DEF(STR, default_internal_group),
187 DEF(STR, default_login_user),
188 DEF(UINT, default_process_limit),
189 DEF(UINT, default_client_limit),
190 DEF(TIME, default_idle_kill),
191 DEF(SIZE, default_vsz_limit),
192
193 DEF(BOOL, version_ignore),
194
195 DEF(UINT, first_valid_uid),
196 DEF(UINT, last_valid_uid),
197 DEF(UINT, first_valid_gid),
198 DEF(UINT, last_valid_gid),
199
200 DEFLIST_UNIQUE(services, "service", &service_setting_parser_info),
201
202 SETTING_DEFINE_LIST_END
203 };
204
205 static const struct master_settings master_default_settings = {
206 .base_dir = PKG_RUNDIR,
207 .state_dir = PKG_STATEDIR,
208 .libexec_dir = PKG_LIBEXECDIR,
209 .instance_name = PACKAGE,
210 .protocols = "imap pop3 lmtp",
211 .listen = "*, ::",
212 .ssl = "yes:no:required",
213 .default_internal_user = "dovecot",
214 .default_internal_group = "dovecot",
215 .default_login_user = "dovenull",
216 .default_process_limit = 100,
217 .default_client_limit = 1000,
218 .default_idle_kill = 60,
219 .default_vsz_limit = 256*1024*1024,
220
221 .version_ignore = FALSE,
222
223 .first_valid_uid = 500,
224 .last_valid_uid = 0,
225 .first_valid_gid = 1,
226 .last_valid_gid = 0,
227
228 #ifndef CONFIG_BINARY
229 .services = ARRAY_INIT
230 #else
231 .services = { { &config_all_services_buf,
232 sizeof(struct service_settings *) } },
233 #endif
234 };
235
236 const struct setting_parser_info master_setting_parser_info = {
237 .module_name = "master",
238 .defines = master_setting_defines,
239 .defaults = &master_default_settings,
240
241 .type_offset = SIZE_MAX,
242 .struct_size = sizeof(struct master_settings),
243
244 .parent_offset = SIZE_MAX,
245
246 .check_func = master_settings_verify
247 };
248
249 /* <settings checks> */
250 static void
expand_user(const char ** user,enum service_user_default * default_r,const struct master_settings * set)251 expand_user(const char **user, enum service_user_default *default_r,
252 const struct master_settings *set)
253 {
254 /* $variable expansion is typically done by doveconf, but these
255 variables can come from built-in settings, so we need to expand
256 them here */
257 if (strcmp(*user, "$default_internal_user") == 0) {
258 *user = set->default_internal_user;
259 *default_r = SERVICE_USER_DEFAULT_INTERNAL;
260 } else if (strcmp(*user, "$default_login_user") == 0) {
261 *user = set->default_login_user;
262 *default_r = SERVICE_USER_DEFAULT_LOGIN;
263 } else {
264 *default_r = SERVICE_USER_DEFAULT_NONE;
265 }
266 }
267
268 static void
expand_group(const char ** group,const struct master_settings * set)269 expand_group(const char **group, const struct master_settings *set)
270 {
271 /* $variable expansion is typically done by doveconf, but these
272 variables can come from built-in settings, so we need to expand
273 them here */
274 if (strcmp(*group, "$default_internal_group") == 0)
275 *group = set->default_internal_group;
276 }
277
278 static bool
fix_file_listener_paths(ARRAY_TYPE (file_listener_settings)* l,pool_t pool,const struct master_settings * master_set,ARRAY_TYPE (const_string)* all_listeners,const char ** error_r)279 fix_file_listener_paths(ARRAY_TYPE(file_listener_settings) *l,
280 pool_t pool, const struct master_settings *master_set,
281 ARRAY_TYPE(const_string) *all_listeners,
282 const char **error_r)
283 {
284 struct file_listener_settings *set;
285 size_t base_dir_len = strlen(master_set->base_dir);
286 enum service_user_default user_default;
287
288 if (!array_is_created(l))
289 return TRUE;
290
291 array_foreach_elem(l, set) {
292 if (set->path[0] == '\0') {
293 *error_r = "path must not be empty";
294 return FALSE;
295 }
296
297 expand_user(&set->user, &user_default, master_set);
298 expand_group(&set->group, master_set);
299 if (*set->path != '/') {
300 set->path = p_strconcat(pool, master_set->base_dir, "/",
301 set->path, NULL);
302 } else if (strncmp(set->path, master_set->base_dir,
303 base_dir_len) == 0 &&
304 set->path[base_dir_len] == '/') {
305 i_warning("You should remove base_dir prefix from "
306 "unix_listener: %s", set->path);
307 }
308 if (set->mode != 0)
309 array_push_back(all_listeners, &set->path);
310 }
311 return TRUE;
312 }
313
add_inet_listeners(ARRAY_TYPE (inet_listener_settings)* l,ARRAY_TYPE (const_string)* all_listeners)314 static void add_inet_listeners(ARRAY_TYPE(inet_listener_settings) *l,
315 ARRAY_TYPE(const_string) *all_listeners)
316 {
317 struct inet_listener_settings *set;
318 const char *str;
319
320 if (!array_is_created(l))
321 return;
322
323 array_foreach_elem(l, set) {
324 if (set->port != 0) {
325 str = t_strdup_printf("%u:%s", set->port, set->address);
326 array_push_back(all_listeners, &str);
327 }
328 }
329 }
330
master_settings_parse_type(struct service_settings * set,const char ** error_r)331 static bool master_settings_parse_type(struct service_settings *set,
332 const char **error_r)
333 {
334 if (*set->type == '\0')
335 set->parsed_type = SERVICE_TYPE_UNKNOWN;
336 else if (strcmp(set->type, "log") == 0)
337 set->parsed_type = SERVICE_TYPE_LOG;
338 else if (strcmp(set->type, "config") == 0)
339 set->parsed_type = SERVICE_TYPE_CONFIG;
340 else if (strcmp(set->type, "anvil") == 0)
341 set->parsed_type = SERVICE_TYPE_ANVIL;
342 else if (strcmp(set->type, "login") == 0)
343 set->parsed_type = SERVICE_TYPE_LOGIN;
344 else if (strcmp(set->type, "startup") == 0)
345 set->parsed_type = SERVICE_TYPE_STARTUP;
346 else if (strcmp(set->type, "worker") == 0)
347 set->parsed_type = SERVICE_TYPE_WORKER;
348 else {
349 *error_r = t_strconcat("Unknown service type: ",
350 set->type, NULL);
351 return FALSE;
352 }
353 return TRUE;
354 }
355
service_set_login_dump_core(struct service_settings * set)356 static void service_set_login_dump_core(struct service_settings *set)
357 {
358 const char *p;
359
360 if (set->parsed_type != SERVICE_TYPE_LOGIN)
361 return;
362
363 p = strstr(set->executable, " -D");
364 if (p != NULL && (p[3] == '\0' || p[3] == ' '))
365 set->login_dump_core = TRUE;
366 }
367
368 static bool
services_have_protocol(struct master_settings * set,const char * name)369 services_have_protocol(struct master_settings *set, const char *name)
370 {
371 struct service_settings *service;
372
373 array_foreach_elem(&set->services, service) {
374 if (strcmp(service->protocol, name) == 0)
375 return TRUE;
376 }
377 return FALSE;
378 }
379
380 #ifdef CONFIG_BINARY
381 static const struct service_settings *
master_default_settings_get_service(const char * name)382 master_default_settings_get_service(const char *name)
383 {
384 extern struct master_settings master_default_settings;
385 struct service_settings *set;
386
387 array_foreach_elem(&master_default_settings.services, set) {
388 if (strcmp(set->name, name) == 0)
389 return set;
390 }
391 return NULL;
392 }
393 #endif
394
395 static unsigned int
service_get_client_limit(struct master_settings * set,const char * name)396 service_get_client_limit(struct master_settings *set, const char *name)
397 {
398 struct service_settings *service;
399
400 array_foreach_elem(&set->services, service) {
401 if (strcmp(service->name, name) == 0) {
402 if (service->client_limit != 0)
403 return service->client_limit;
404 else
405 return set->default_client_limit;
406 }
407 }
408 return set->default_client_limit;
409 }
410
411 static bool
master_settings_verify(void * _set,pool_t pool,const char ** error_r)412 master_settings_verify(void *_set, pool_t pool, const char **error_r)
413 {
414 static bool warned_auth = FALSE, warned_anvil = FALSE;
415 struct master_settings *set = _set;
416 struct service_settings *const *services;
417 const char *const *strings;
418 ARRAY_TYPE(const_string) all_listeners;
419 struct passwd pw;
420 unsigned int i, j, count, client_limit, process_limit;
421 unsigned int max_auth_client_processes, max_anvil_client_processes;
422 string_t *max_auth_client_processes_reason = t_str_new(64);
423 string_t *max_anvil_client_processes_reason = t_str_new(64);
424 size_t len;
425 #ifdef CONFIG_BINARY
426 const struct service_settings *default_service;
427 #else
428 rlim_t fd_limit;
429 const char *max_client_limit_source = "default_client_limit";
430 unsigned int max_client_limit = set->default_client_limit;
431 #endif
432
433 if (*set->listen == '\0') {
434 *error_r = "listen can't be set empty";
435 return FALSE;
436 }
437
438 len = strlen(set->base_dir);
439 if (len > 0 && set->base_dir[len-1] == '/') {
440 /* drop trailing '/' */
441 set->base_dir = p_strndup(pool, set->base_dir, len - 1);
442 }
443
444 if (set->last_valid_uid != 0 &&
445 set->first_valid_uid > set->last_valid_uid) {
446 *error_r = "first_valid_uid can't be larger than last_valid_uid";
447 return FALSE;
448 }
449 if (set->last_valid_gid != 0 &&
450 set->first_valid_gid > set->last_valid_gid) {
451 *error_r = "first_valid_gid can't be larger than last_valid_gid";
452 return FALSE;
453 }
454
455 if (i_getpwnam(set->default_login_user, &pw) == 0) {
456 *error_r = t_strdup_printf("default_login_user doesn't exist: %s",
457 set->default_login_user);
458 return FALSE;
459 }
460 if (i_getpwnam(set->default_internal_user, &pw) == 0) {
461 *error_r = t_strdup_printf("default_internal_user doesn't exist: %s",
462 set->default_internal_user);
463 return FALSE;
464 }
465
466 /* check that we have at least one service. the actual service
467 structure validity is checked later while creating them. */
468 if (!array_is_created(&set->services) ||
469 array_count(&set->services) == 0) {
470 *error_r = "No services defined";
471 return FALSE;
472 }
473 services = array_get(&set->services, &count);
474 for (i = 0; i < count; i++) {
475 struct service_settings *service = services[i];
476
477 if (*service->name == '\0') {
478 *error_r = t_strdup_printf(
479 "Service #%d is missing name", i);
480 return FALSE;
481 }
482 if (!master_settings_parse_type(service, error_r))
483 return FALSE;
484 for (j = 0; j < i; j++) {
485 if (strcmp(service->name, services[j]->name) == 0) {
486 *error_r = t_strdup_printf(
487 "Duplicate service name: %s",
488 service->name);
489 return FALSE;
490 }
491 }
492 expand_user(&service->user, &service->user_default, set);
493 expand_group(&service->extra_groups, set);
494 service_set_login_dump_core(service);
495 }
496 set->protocols_split = p_strsplit_spaces(pool, set->protocols, " ");
497 if (set->protocols_split[0] != NULL &&
498 strcmp(set->protocols_split[0], "none") == 0 &&
499 set->protocols_split[1] == NULL)
500 set->protocols_split[0] = NULL;
501
502 for (i = 0; set->protocols_split[i] != NULL; i++) {
503 if (!services_have_protocol(set, set->protocols_split[i])) {
504 *error_r = t_strdup_printf("protocols: "
505 "Unknown protocol: %s",
506 set->protocols_split[i]);
507 return FALSE;
508 }
509 }
510 t_array_init(&all_listeners, 64);
511 max_auth_client_processes = 0;
512 max_anvil_client_processes = 2; /* blocking, nonblocking pipes */
513 for (i = 0; i < count; i++) {
514 struct service_settings *service = services[i];
515
516 if (*service->protocol != '\0' &&
517 !str_array_find((const char **)set->protocols_split,
518 service->protocol)) {
519 /* protocol not enabled, ignore its settings */
520 continue;
521 }
522
523 if (*service->executable != '/' &&
524 *service->executable != '\0') {
525 service->executable =
526 p_strconcat(pool, set->libexec_dir, "/",
527 service->executable, NULL);
528 }
529 if (*service->chroot != '/' && *service->chroot != '\0') {
530 service->chroot =
531 p_strconcat(pool, set->base_dir, "/",
532 service->chroot, NULL);
533 }
534 if (service->drop_priv_before_exec &&
535 *service->chroot != '\0') {
536 *error_r = t_strdup_printf("service(%s): "
537 "drop_priv_before_exec=yes can't be "
538 "used with chroot", service->name);
539 return FALSE;
540 }
541 process_limit = service->process_limit;
542 if (process_limit == 0)
543 process_limit = set->default_process_limit;
544 if (service->process_min_avail > process_limit) {
545 *error_r = t_strdup_printf("service(%s): "
546 "process_min_avail is higher than process_limit",
547 service->name);
548 return FALSE;
549 }
550 if (service->vsz_limit < 1024*1024 && service->vsz_limit != 0) {
551 *error_r = t_strdup_printf("service(%s): "
552 "vsz_limit is too low", service->name);
553 return FALSE;
554 }
555
556 #ifdef CONFIG_BINARY
557 default_service =
558 master_default_settings_get_service(service->name);
559 if (default_service != NULL &&
560 default_service->process_limit_1 && process_limit > 1) {
561 *error_r = t_strdup_printf("service(%s): "
562 "process_limit must be 1", service->name);
563 return FALSE;
564 }
565 #else
566 if (max_client_limit < service->client_limit) {
567 max_client_limit = service->client_limit;
568 max_client_limit_source = t_strdup_printf(
569 "service %s { client_limit }", service->name);
570 }
571 #endif
572
573 if (*service->protocol != '\0') {
574 /* each imap/pop3/lmtp process can use up a connection,
575 although if service_count=1 it's only temporary.
576 imap-hibernate doesn't do any auth lookups. */
577 if ((service->service_count != 1 ||
578 strcmp(service->type, "login") == 0) &&
579 strcmp(service->name, "imap-hibernate") != 0) {
580 str_printfa(max_auth_client_processes_reason,
581 " + service %s { process_limit=%u }",
582 service->name, process_limit);
583 max_auth_client_processes += process_limit;
584 }
585 }
586 if (strcmp(service->type, "login") == 0 ||
587 strcmp(service->name, "auth") == 0) {
588 max_anvil_client_processes += process_limit;
589 str_printfa(max_anvil_client_processes_reason,
590 " + service %s { process_limit=%u }",
591 service->name, process_limit);
592 }
593
594 if (!fix_file_listener_paths(&service->unix_listeners, pool,
595 set, &all_listeners, error_r)) {
596 *error_r = t_strdup_printf("service(%s): unix_listener: %s",
597 service->name, *error_r);
598 return FALSE;
599 }
600 if (!fix_file_listener_paths(&service->fifo_listeners, pool,
601 set, &all_listeners, error_r)) {
602 *error_r = t_strdup_printf("service(%s): fifo_listener: %s",
603 service->name, *error_r);
604 return FALSE;
605 }
606 add_inet_listeners(&service->inet_listeners, &all_listeners);
607 }
608
609 client_limit = service_get_client_limit(set, "auth");
610 if (client_limit < max_auth_client_processes && !warned_auth) {
611 warned_auth = TRUE;
612 str_delete(max_auth_client_processes_reason, 0, 3);
613 i_warning("service auth { client_limit=%u } is lower than "
614 "required under max. load (%u). "
615 "Counted for protocol services with service_count != 1: %s",
616 client_limit, max_auth_client_processes,
617 str_c(max_auth_client_processes_reason));
618 }
619
620 client_limit = service_get_client_limit(set, "anvil");
621 if (client_limit < max_anvil_client_processes && !warned_anvil) {
622 warned_anvil = TRUE;
623 str_delete(max_anvil_client_processes_reason, 0, 3);
624 i_warning("service anvil { client_limit=%u } is lower than "
625 "required under max. load (%u). Counted with: %s",
626 client_limit, max_anvil_client_processes,
627 str_c(max_anvil_client_processes_reason));
628 }
629 #ifndef CONFIG_BINARY
630 if (restrict_get_fd_limit(&fd_limit) == 0 &&
631 fd_limit < (rlim_t)max_client_limit) {
632 i_warning("fd limit (ulimit -n) is lower than required "
633 "under max. load (%u < %u), because of %s",
634 (unsigned int)fd_limit, max_client_limit,
635 max_client_limit_source);
636 }
637 #endif
638
639 /* check for duplicate listeners */
640 array_sort(&all_listeners, i_strcmp_p);
641 strings = array_get(&all_listeners, &count);
642 for (i = 1; i < count; i++) {
643 if (strcmp(strings[i-1], strings[i]) == 0) {
644 *error_r = t_strdup_printf("duplicate listener: %s",
645 strings[i]);
646 return FALSE;
647 }
648 }
649 return TRUE;
650 }
651 /* </settings checks> */
652
653 static bool
login_want_core_dumps(const struct master_settings * set,gid_t * gid_r)654 login_want_core_dumps(const struct master_settings *set, gid_t *gid_r)
655 {
656 struct service_settings *service;
657 const char *error;
658 bool cores = FALSE;
659 uid_t uid;
660
661 *gid_r = (gid_t)-1;
662
663 array_foreach_elem(&set->services, service) {
664 if (service->parsed_type == SERVICE_TYPE_LOGIN) {
665 if (service->login_dump_core)
666 cores = TRUE;
667 (void)get_uidgid(service->user, &uid, gid_r, &error);
668 if (*service->group != '\0')
669 (void)get_gid(service->group, gid_r, &error);
670 }
671 }
672 return cores;
673 }
674
675 static bool
settings_have_auth_unix_listeners_in(const struct master_settings * set,const char * dir)676 settings_have_auth_unix_listeners_in(const struct master_settings *set,
677 const char *dir)
678 {
679 struct service_settings *service;
680 struct file_listener_settings *u;
681 size_t dir_len = strlen(dir);
682
683 array_foreach_elem(&set->services, service) {
684 if (array_is_created(&service->unix_listeners)) {
685 array_foreach_elem(&service->unix_listeners, u) {
686 if (strncmp(u->path, dir, dir_len) == 0 &&
687 u->path[dir_len] == '/')
688 return TRUE;
689 }
690 }
691 }
692 return FALSE;
693 }
694
unlink_sockets(const char * path,const char * prefix)695 static void unlink_sockets(const char *path, const char *prefix)
696 {
697 DIR *dirp;
698 struct dirent *dp;
699 struct stat st;
700 string_t *str;
701 size_t prefix_len;
702
703 dirp = opendir(path);
704 if (dirp == NULL) {
705 i_error("opendir(%s) failed: %m", path);
706 return;
707 }
708
709 prefix_len = strlen(prefix);
710 str = t_str_new(256);
711 while ((dp = readdir(dirp)) != NULL) {
712 if (dp->d_name[0] == '.')
713 continue;
714
715 if (strncmp(dp->d_name, prefix, prefix_len) != 0)
716 continue;
717
718 str_truncate(str, 0);
719 str_printfa(str, "%s/%s", path, dp->d_name);
720 if (lstat(str_c(str), &st) < 0) {
721 if (errno != ENOENT)
722 i_error("lstat(%s) failed: %m", str_c(str));
723 continue;
724 }
725 if (!S_ISSOCK(st.st_mode))
726 continue;
727
728 /* try to avoid unlinking sockets if someone's already
729 listening in them. do this only at startup, because
730 when SIGHUPing a child process might catch the new
731 connection before it notices that it's supposed
732 to die. */
733 if (!startup_finished) {
734 int fd = net_connect_unix(str_c(str));
735 if (fd != -1 || errno != ECONNREFUSED) {
736 i_fatal("Dovecot is already running? "
737 "Socket already exists: %s",
738 str_c(str));
739 }
740 }
741
742 i_unlink_if_exists(str_c(str));
743 }
744 (void)closedir(dirp);
745 }
746
747 static void
mkdir_login_dir(const struct master_settings * set,const char * login_dir)748 mkdir_login_dir(const struct master_settings *set, const char *login_dir)
749 {
750 mode_t mode;
751 gid_t gid;
752
753 if (settings_have_auth_unix_listeners_in(set, login_dir)) {
754 /* we are not using external authentication, so make sure the
755 login directory exists with correct permissions and it's
756 empty. with external auth we wouldn't want to delete
757 existing sockets or break the permissions required by the
758 auth server. */
759 mode = login_want_core_dumps(set, &gid) ? 0770 : 0750;
760 if (safe_mkdir(login_dir, mode, master_uid, gid) == 0) {
761 i_warning("Corrected permissions for login directory "
762 "%s", login_dir);
763 }
764
765 unlink_sockets(login_dir, "");
766 } else {
767 /* still make sure that login directory exists */
768 if (mkdir(login_dir, 0755) < 0 && errno != EEXIST)
769 i_fatal("mkdir(%s) failed: %m", login_dir);
770 }
771 }
772
master_settings_do_fixes(const struct master_settings * set)773 void master_settings_do_fixes(const struct master_settings *set)
774 {
775 const char *empty_dir;
776 struct stat st;
777
778 /* since base dir is under /var/run by default, it may have been
779 deleted. */
780 if (mkdir_parents(set->base_dir, 0755) < 0 && errno != EEXIST)
781 i_fatal("mkdir(%s) failed: %m", set->base_dir);
782 /* allow base_dir to be a symlink, so don't use lstat() */
783 if (stat(set->base_dir, &st) < 0)
784 i_fatal("stat(%s) failed: %m", set->base_dir);
785 if (!S_ISDIR(st.st_mode))
786 i_fatal("%s is not a directory", set->base_dir);
787 if ((st.st_mode & 0755) != 0755) {
788 i_warning("Fixing permissions of %s to be world-readable",
789 set->base_dir);
790 if (chmod(set->base_dir, 0755) < 0)
791 i_error("chmod(%s) failed: %m", set->base_dir);
792 }
793
794 /* Make sure our permanent state directory exists */
795 if (mkdir_parents(set->state_dir, 0755) < 0 && errno != EEXIST)
796 i_fatal("mkdir(%s) failed: %m", set->state_dir);
797
798 mkdir_login_dir(set, t_strconcat(set->base_dir, "/login", NULL));
799 mkdir_login_dir(set, t_strconcat(set->base_dir, "/token-login", NULL));
800
801 empty_dir = t_strconcat(set->base_dir, "/empty", NULL);
802 if (safe_mkdir(empty_dir, 0755, master_uid, getegid()) == 0) {
803 i_warning("Corrected permissions for empty directory "
804 "%s", empty_dir);
805 }
806 }
807