From: Timo Sirainen Date: Mon, 16 Aug 2010 15:49:29 +0000 (+0100) Subject: master: Give better error messages for unknown users/groups. X-Git-Tag: 2.0.1~41 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=89025037c48afe9ea64ed73d208d619db6b0ccfd;p=thirdparty%2Fdovecot%2Fcore.git master: Give better error messages for unknown users/groups. --- diff --git a/src/lib-master/service-settings.h b/src/lib-master/service-settings.h index 6998b99cf4..e1c9c4e408 100644 --- a/src/lib-master/service-settings.h +++ b/src/lib-master/service-settings.h @@ -2,6 +2,12 @@ #define SERVICE_SETTINGS_H /* */ +enum service_user_default { + SERVICE_USER_DEFAULT_NONE = 0, + SERVICE_USER_DEFAULT_INTERNAL, + SERVICE_USER_DEFAULT_LOGIN +}; + enum service_type { SERVICE_TYPE_UNKNOWN, SERVICE_TYPE_LOG, @@ -55,6 +61,7 @@ struct service_settings { /* internal to master: */ struct master_settings *master_set; enum service_type parsed_type; + enum service_user_default user_default; unsigned int login_dump_core:1; }; ARRAY_DEFINE_TYPE(service_settings, struct service_settings *); diff --git a/src/master/master-settings.c b/src/master/master-settings.c index 95cac3093e..be642327c8 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -239,15 +239,21 @@ const struct setting_parser_info master_setting_parser_info = { /* */ static void -expand_user(const char **user, const struct master_settings *set) +expand_user(const char **user, enum service_user_default *default_r, + const struct master_settings *set) { /* $variable expansion is typically done by doveconf, but these variables can come from built-in settings, so we need to expand them here */ - if (strcmp(*user, "$default_internal_user") == 0) + if (strcmp(*user, "$default_internal_user") == 0) { *user = set->default_internal_user; - else if (strcmp(*user, "$default_login_user") == 0) + *default_r = SERVICE_USER_DEFAULT_INTERNAL; + } else if (strcmp(*user, "$default_login_user") == 0) { *user = set->default_login_user; + *default_r = SERVICE_USER_DEFAULT_LOGIN; + } else { + *default_r = SERVICE_USER_DEFAULT_NONE; + } } static void @@ -257,6 +263,7 @@ fix_file_listener_paths(ARRAY_TYPE(file_listener_settings) *l, { struct file_listener_settings *const *sets; unsigned int base_dir_len = strlen(master_set->base_dir); + enum service_user_default user_default; if (!array_is_created(l)) return; @@ -264,7 +271,7 @@ fix_file_listener_paths(ARRAY_TYPE(file_listener_settings) *l, array_foreach(l, sets) { struct file_listener_settings *set = *sets; - expand_user(&set->user, master_set); + expand_user(&set->user, &user_default, master_set); if (*set->path != '/') { set->path = p_strconcat(pool, master_set->base_dir, "/", set->path, NULL); @@ -401,7 +408,7 @@ master_settings_verify(void *_set, pool_t pool, const char **error_r) return FALSE; } } - expand_user(&service->user, set); + expand_user(&service->user, &service->user_default, set); service_set_login_dump_core(service); } set->protocols_split = p_strsplit_spaces(pool, set->protocols, " "); diff --git a/src/master/service.c b/src/master/service.c index e3f4729aba..e1689aaaa6 100644 --- a/src/master/service.c +++ b/src/master/service.c @@ -38,6 +38,7 @@ service_create_file_listener(struct service *service, const char **error_r) { struct service_listener *l; + const char *set_name; gid_t gid; l = p_new(service->list->pool, struct service_listener, 1); @@ -47,10 +48,18 @@ service_create_file_listener(struct service *service, l->set.fileset.set = set; if (get_uidgid(set->user, &l->set.fileset.uid, &gid, error_r) < 0) - return NULL; - if (get_gid(set->group, &l->set.fileset.gid, error_r) < 0) - return NULL; - return l; + set_name = "user"; + else if (get_gid(set->group, &l->set.fileset.gid, error_r) < 0) + set_name = "group"; + else + return l; + + *error_r = t_strdup_printf( + "%s (See service %s { %s_listener %s { %s } } setting)", + *error_r, service->set->name, + type == SERVICE_LISTENER_UNIX ? "unix" : "fifo", + set->path, set_name); + return NULL; } static int @@ -169,6 +178,26 @@ service_create_inet_listeners(struct service *service, return 0; } +static int service_get_groups(const char *groups, pool_t pool, + const char **gids_r, const char **error_r) +{ + const char *const *tmp; + string_t *str; + gid_t gid; + + str = t_str_new(64); + for (tmp = t_strsplit(groups, ","); *tmp != NULL; tmp++) { + if (get_gid(*tmp, &gid, error_r) < 0) + return -1; + + if (str_len(str) > 0) + str_append_c(str, ','); + str_append(str, dec2str(gid)); + } + *gids_r = p_strdup(pool, str_c(str)); + return 0; +} + static struct service * service_create(pool_t pool, const struct service_settings *set, struct service_list *service_list, const char **error_r) @@ -178,8 +207,6 @@ service_create(pool_t pool, const struct service_settings *set, struct inet_listener_settings *const *inet_listeners; struct service *service; struct service_listener *l; - const char *const *tmp; - string_t *str; unsigned int i, unix_count, fifo_count, inet_count; service = p_new(pool, struct service, 1); @@ -215,30 +242,48 @@ service_create(pool_t pool, const struct service_settings *set, } /* default gid to user's primary group */ - if (get_uidgid(set->user, &service->uid, &service->gid, error_r) < 0) + if (get_uidgid(set->user, &service->uid, &service->gid, error_r) < 0) { + switch (set->user_default) { + case SERVICE_USER_DEFAULT_NONE: + *error_r = t_strdup_printf( + "%s (See service %s { user } setting)", + *error_r, set->name); + break; + case SERVICE_USER_DEFAULT_INTERNAL: + *error_r = t_strconcat(*error_r, + " (See default_internal_user setting)", NULL); + break; + case SERVICE_USER_DEFAULT_LOGIN: + *error_r = t_strconcat(*error_r, + " (See default_login_user setting)", NULL); + break; + } return NULL; + } if (*set->group != '\0') { - if (get_gid(set->group, &service->gid, error_r) < 0) + if (get_gid(set->group, &service->gid, error_r) < 0) { + *error_r = t_strdup_printf( + "%s (See service %s { group } setting)", + *error_r, set->name); return NULL; + } } if (get_gid(set->privileged_group, &service->privileged_gid, - error_r) < 0) + error_r) < 0) { + *error_r = t_strdup_printf( + "%s (See service %s { privileged_group } setting)", + *error_r, set->name); return NULL; + } if (*set->extra_groups != '\0') { - str = t_str_new(64); - tmp = t_strsplit(set->extra_groups, ","); - for (; *tmp != NULL; tmp++) { - gid_t gid; - - if (get_gid(*tmp, &gid, error_r) < 0) - return NULL; - - if (str_len(str) > 0) - str_append_c(str, ','); - str_append(str, dec2str(gid)); + if (service_get_groups(set->extra_groups, pool, + &service->extra_gids, error_r) < 0) { + *error_r = t_strdup_printf( + "%s (See service %s { extra_groups } setting)", + *error_r, set->name); + return NULL; } - service->extra_gids = p_strdup(pool, str_c(str)); } if (*set->executable == '/')