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