From: Timo Sirainen Date: Fri, 5 Dec 2008 22:20:02 +0000 (+0200) Subject: Improved "Permission denied" error handling. It'll now show also the uid/gid name. X-Git-Tag: 1.2.alpha5~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e9f0cf3cc3ce546e8a433990c92dd9be6665df6;p=thirdparty%2Fdovecot%2Fcore.git Improved "Permission denied" error handling. It'll now show also the uid/gid name. Also moved the code to mail-error.c and used it when listing mailboxes. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/cydir/cydir-storage.c b/src/lib-storage/index/cydir/cydir-storage.c index 682a0d90e5..651480fda9 100644 --- a/src/lib-storage/index/cydir/cydir-storage.c +++ b/src/lib-storage/index/cydir/cydir-storage.c @@ -94,7 +94,7 @@ static int cydir_create(struct mail_storage *_storage, const char *data, "Root mail directory doesn't exist: %s", list_set.root_dir); } else if (errno == EACCES) { - *error_r = mail_storage_eacces_msg("stat", + *error_r = mail_error_eacces_msg("stat", list_set.root_dir); } else { *error_r = t_strdup_printf( @@ -106,7 +106,7 @@ static int cydir_create(struct mail_storage *_storage, const char *data, } else if (mkdir_parents(list_set.root_dir, CREATE_MODE) == 0 || errno == EEXIST) { } else if (errno == EACCES) { - *error_r = mail_storage_eacces_msg("mkdir", list_set.root_dir); + *error_r = mail_error_eacces_msg("mkdir", list_set.root_dir); return -1; } else { *error_r = t_strdup_printf("mkdir(%s) failed: %m", @@ -206,7 +206,7 @@ cydir_mailbox_open(struct mail_storage *_storage, const char *name, T_MAIL_ERR_MAILBOX_NOT_FOUND(name)); } else if (errno == EACCES) { mail_storage_set_critical(_storage, "%s", - mail_storage_eacces_msg("stat", path)); + mail_error_eacces_msg("stat", path)); } else { mail_storage_set_critical(_storage, "stat(%s) failed: %m", path); diff --git a/src/lib-storage/index/dbox/dbox-storage.c b/src/lib-storage/index/dbox/dbox-storage.c index 132b4503a8..7fc4585cfc 100644 --- a/src/lib-storage/index/dbox/dbox-storage.c +++ b/src/lib-storage/index/dbox/dbox-storage.c @@ -107,7 +107,7 @@ static int dbox_create(struct mail_storage *_storage, const char *data, "Root mail directory doesn't exist: %s", list_set.root_dir); } else if (errno == EACCES) { - *error_r = mail_storage_eacces_msg("stat", + *error_r = mail_error_eacces_msg("stat", list_set.root_dir); } else { *error_r = t_strdup_printf( @@ -120,8 +120,8 @@ static int dbox_create(struct mail_storage *_storage, const char *data, CREATE_MODE) == 0 || errno == EEXIST) { } else if (errno == EACCES) { if (_storage->ns->type != NAMESPACE_SHARED) { - *error_r = mail_storage_eacces_msg("mkdir", - list_set.root_dir); + *error_r = mail_error_eacces_msg("mkdir", + list_set.root_dir); return -1; } /* can't create a new user, but we don't want to fail @@ -308,7 +308,7 @@ dbox_mailbox_open(struct mail_storage *_storage, const char *name, T_MAIL_ERR_MAILBOX_NOT_FOUND(name)); } else if (errno == EACCES) { mail_storage_set_critical(_storage, "%s", - mail_storage_eacces_msg("stat", path)); + mail_error_eacces_msg("stat", path)); } else { mail_storage_set_critical(_storage, "stat(%s) failed: %m", path); diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index a2127bf32e..e9a6c2e5b1 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -145,7 +145,7 @@ get_index_dir(struct mail_storage *storage, const char *name, } if (errno == EACCES) { mail_storage_set_critical(storage, "%s", - mail_storage_eacces_msg("stat", index_dir)); + mail_error_eacces_msg("stat", index_dir)); return NULL; } diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index 224f4d4686..aeb500f906 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -211,8 +211,8 @@ maildir_create(struct mail_storage *_storage, const char *data, if (stat(list_set.root_dir, &st) == 0) { /* ok */ } else if (errno == EACCES) { - *error_r = mail_storage_eacces_msg("stat", - list_set.root_dir); + *error_r = mail_error_eacces_msg("stat", + list_set.root_dir); return -1; } else if (errno == ENOENT) { *error_r = t_strdup_printf( @@ -341,7 +341,7 @@ static int maildir_check_tmp(struct mail_storage *storage, const char *dir) return 0; if (errno == EACCES) { mail_storage_set_critical(storage, "%s", - mail_storage_eacces_msg("stat", path)); + mail_error_eacces_msg("stat", path)); return -1; } mail_storage_set_critical(storage, "stat(%s) failed: %m", path); diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index 0f5ed87fa1..d5e2b7f752 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -344,8 +344,8 @@ mbox_get_list_settings(struct mailbox_list_settings *list_set, if (lstat(list_set->root_dir, &st) == 0) { /* yep, go ahead */ } else if (errno == EACCES) { - *error_r = mail_storage_eacces_msg("lstat", - list_set->root_dir); + *error_r = mail_error_eacces_msg("lstat", + list_set->root_dir); return -1; } else if (errno != ENOENT && errno != ENOTDIR) { *error_r = t_strdup_printf("lstat(%s) failed: %m", @@ -502,7 +502,7 @@ static int verify_inbox(struct mail_storage *storage) return -1; } else if (errno == EACCES) { mail_storage_set_critical(storage, "%s", - mail_storage_eacces_msg("open", inbox_path)); + mail_error_eacces_msg("open", inbox_path)); return -1; } else if (errno != EEXIST) { mail_storage_set_critical(storage, diff --git a/src/lib-storage/list/mailbox-list-maildir-iter.c b/src/lib-storage/list/mailbox-list-maildir-iter.c index 8273e37277..c76e2a9a2c 100644 --- a/src/lib-storage/list/mailbox-list-maildir-iter.c +++ b/src/lib-storage/list/mailbox-list-maildir-iter.c @@ -133,7 +133,10 @@ maildir_fill_readdir(struct maildir_list_iterate_context *ctx, dirp = opendir(ctx->dir); if (dirp == NULL) { - if (errno != ENOENT) { + if (errno == EACCES) { + mailbox_list_set_critical(ctx->ctx.list, "%s", + mail_error_eacces_msg("opendir", ctx->dir)); + } else if (errno != ENOENT) { mailbox_list_set_critical(ctx->ctx.list, "opendir(%s) failed: %m", ctx->dir); return -1; diff --git a/src/lib-storage/mail-error.c b/src/lib-storage/mail-error.c index 3c40be7e5f..13df519816 100644 --- a/src/lib-storage/mail-error.c +++ b/src/lib-storage/mail-error.c @@ -1,8 +1,14 @@ /* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "str.h" #include "mail-error.h" +#include +#include +#include +#include + bool mail_error_from_errno(enum mail_error *error_r, const char **error_string_r) { @@ -21,3 +27,45 @@ bool mail_error_from_errno(enum mail_error *error_r, } return TRUE; } + +const char *mail_error_eacces_msg(const char *func, const char *path) +{ + const char *prev_path = path, *dir = "/", *p; + const struct passwd *pw; + const struct group *group; + string_t *errmsg; + struct stat st; + int ret = -1; + + errmsg = t_str_new(256); + str_printfa(errmsg, "%s(%s) failed: Permission denied (euid=%s", + func, path, dec2str(geteuid())); + + pw = getpwuid(geteuid()); + if (pw != NULL) + str_printfa(errmsg, "(%s)", pw->pw_name); + + str_printfa(errmsg, " egid=%s", dec2str(getegid())); + group = getgrgid(getegid()); + if (group != NULL) + str_printfa(errmsg, "(%s)", group->gr_name); + + while ((p = strrchr(prev_path, '/')) != NULL) { + dir = t_strdup_until(prev_path, p); + ret = stat(dir, &st); + if (ret == 0 || errno != EACCES) + break; + prev_path = dir; + dir = "/"; + } + + if (ret == 0) { + if (access(dir, X_OK) < 0 && errno == EACCES) + str_printfa(errmsg, " missing +x perm: %s", dir); + else if (prev_path == path && + access(path, R_OK) < 0 && errno == EACCES) + str_printfa(errmsg, " missing +r perm: %s", path); + } + str_append_c(errmsg, ')'); + return str_c(errmsg); +} diff --git a/src/lib-storage/mail-error.h b/src/lib-storage/mail-error.h index 0a65febe8b..213cef3f12 100644 --- a/src/lib-storage/mail-error.h +++ b/src/lib-storage/mail-error.h @@ -48,4 +48,7 @@ enum mail_error { bool mail_error_from_errno(enum mail_error *error_r, const char **error_string_r); +/* Build a helpful error message for a failed EACCESS syscall. */ +const char *mail_error_eacces_msg(const char *func, const char *path); + #endif diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h index 3b41fa8e12..2f56a6b753 100644 --- a/src/lib-storage/mail-storage-private.h +++ b/src/lib-storage/mail-storage-private.h @@ -380,8 +380,6 @@ const char *mail_generate_guid_string(void); void mail_set_expunged(struct mail *mail); void mailbox_set_deleted(struct mailbox *box); -const char *mail_storage_eacces_msg(const char *func, const char *path); - enum mailbox_list_flags mail_storage_get_list_flags(enum mail_storage_flags storage_flags); diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 6dbff9c1e6..b2e2f3774b 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -3,7 +3,6 @@ #include "lib.h" #include "ioloop.h" #include "array.h" -#include "str.h" #include "var-expand.h" #include "mail-index-private.h" #include "mailbox-list-private.h" @@ -13,7 +12,6 @@ #include "mailbox-search-result-private.h" #include -#include #include #define DEFAULT_MAX_KEYWORD_LENGTH 50 @@ -931,32 +929,3 @@ void mailbox_set_deleted(struct mailbox *box) "Mailbox was deleted under us"); box->mailbox_deleted = TRUE; } - -const char *mail_storage_eacces_msg(const char *func, const char *path) -{ - const char *prev_path = path, *dir = "/", *p; - string_t *errmsg = t_str_new(256); - struct stat st; - int ret = -1; - - str_printfa(errmsg, "%s(%s) failed: Permission denied (euid=%s egid=%s", - func, path, dec2str(geteuid()), dec2str(getegid())); - while ((p = strrchr(prev_path, '/')) != NULL) { - dir = t_strdup_until(prev_path, p); - ret = stat(dir, &st); - if (ret == 0 || errno != EACCES) - break; - prev_path = dir; - dir = "/"; - } - - if (ret == 0) { - if (access(dir, X_OK) < 0 && errno == EACCES) - str_printfa(errmsg, " missing +x perm: %s", dir); - else if (prev_path == path && - access(path, R_OK) < 0 && errno == EACCES) - str_printfa(errmsg, " missing +r perm: %s", path); - } - str_append_c(errmsg, ')'); - return str_c(errmsg); -}