]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
master: Give better error messages for unknown users/groups.
authorTimo Sirainen <tss@iki.fi>
Mon, 16 Aug 2010 15:49:29 +0000 (16:49 +0100)
committerTimo Sirainen <tss@iki.fi>
Mon, 16 Aug 2010 15:49:29 +0000 (16:49 +0100)
src/lib-master/service-settings.h
src/master/master-settings.c
src/master/service.c

index 6998b99cf4b4d5071652b7a6a0b50d99e66a7386..e1c9c4e4087bfbbbbc4b11e5e485c5ace6749d90 100644 (file)
@@ -2,6 +2,12 @@
 #define SERVICE_SETTINGS_H
 
 /* <settings checks> */
+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 *);
index 95cac3093e0f6f37346a6c26ce01d1d1d0513598..be642327c8459dbc78954d0139943acdd690ad2c 100644 (file)
@@ -239,15 +239,21 @@ const struct setting_parser_info master_setting_parser_info = {
 
 /* <settings checks> */
 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, " ");
index e3f4729abaadf9bd236a27556d8b9a8477a625ee..e1689aaaa61f885bdd06f431bba60d5d21f301f9 100644 (file)
@@ -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 == '/')