annotate src/lib/eacces-error.c @ 12050:8db227a70bec

access_get_error(): Fixed to give better error messages with relative paths.
author Timo Sirainen <tss@iki.fi>
date Tue, 31 Aug 2010 20:04:10 +0100
parents 4f90b4114450
children 447bce266022
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
10582
615eef3139c2 Updated copyright notices to include year 2010.
Timo Sirainen <tss@iki.fi>
parents: 10553
diff changeset
1 /* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
2
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
3 #include "lib.h"
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
4 #include "str.h"
10502
13be6ac759ee Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents: 10210
diff changeset
5 #include "abspath.h"
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
6 #include "restrict-access.h"
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
7 #include "eacces-error.h"
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
8
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
9 #include <sys/stat.h>
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
10 #include <unistd.h>
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
11 #include <pwd.h>
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
12 #include <grp.h>
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
13
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
14 static bool is_in_group(gid_t gid)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
15 {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
16 const gid_t *gids;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
17 unsigned int i, count;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
18
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
19 if (getegid() == gid)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
20 return TRUE;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
21
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
22 gids = restrict_get_groups_list(&count);
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
23 for (i = 0; i < count; i++) {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
24 if (gids[i] == gid)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
25 return TRUE;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
26 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
27 return FALSE;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
28 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
29
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
30 static int test_access(const char *path, int mode, string_t *errmsg)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
31 {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
32 struct stat st;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
33
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
34 if (getuid() == geteuid()) {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
35 if (access(path, mode) == 0)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
36 return 0;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
37
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
38 if (errno != EACCES) {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
39 str_printfa(errmsg, " access(%s, %d) failed: %m",
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
40 path, mode);
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
41 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
42 return -1;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
43 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
44
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
45 /* access() uses real uid, not effective uid.
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
46 we'll have to do these checks manually. */
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
47 switch (mode) {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
48 case X_OK:
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
49 if (stat(t_strconcat(path, "/test", NULL), &st) == 0)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
50 return 0;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
51 if (errno == ENOENT || errno == ENOTDIR)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
52 return 0;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
53 if (errno != EACCES)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
54 str_printfa(errmsg, " stat(%s/test) failed: %m", path);
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
55 return -1;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
56 case R_OK:
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
57 mode = 04;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
58 break;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
59 case W_OK:
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
60 mode = 02;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
61 break;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
62 default:
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
63 i_unreached();
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
64 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
65
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
66 if (stat(path, &st) < 0) {
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
67 str_printfa(errmsg, " stat(%s) failed: %m", path);
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
68 return -1;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
69 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
70
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
71 if (st.st_uid == geteuid())
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
72 st.st_mode = (st.st_mode & 0700) >> 6;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
73 else if (is_in_group(st.st_gid))
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
74 st.st_mode = (st.st_mode & 0070) >> 3;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
75 else
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
76 st.st_mode = (st.st_mode & 0007);
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
77
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
78 if ((st.st_mode & mode) != 0)
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
79 return 0;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
80 errno = EACCES;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
81 return -1;
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
82 }
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
83
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
84 static const char *
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
85 eacces_error_get_full(const char *func, const char *path, bool creating)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
86 {
9589
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
87 const char *prev_path = path, *dir, *p;
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
88 const char *pw_name = NULL, *gr_name = NULL;
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
89 const struct passwd *pw;
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
90 const struct group *group;
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
91 string_t *errmsg;
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
92 struct stat st, dir_st;
9537
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
93 int orig_errno, ret = -1;
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
94
9537
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
95 orig_errno = errno;
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
96 errmsg = t_str_new(256);
9589
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
97 str_printfa(errmsg, "%s(%s)", func, path);
12050
8db227a70bec access_get_error(): Fixed to give better error messages with relative paths.
Timo Sirainen <tss@iki.fi>
parents: 12004
diff changeset
98 dir = "/";
9589
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
99 if (*path != '/') {
10502
13be6ac759ee Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents: 10210
diff changeset
100 if (t_get_current_dir(&dir) == 0)
9589
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
101 str_printfa(errmsg, " in directory %s", dir);
12050
8db227a70bec access_get_error(): Fixed to give better error messages with relative paths.
Timo Sirainen <tss@iki.fi>
parents: 12004
diff changeset
102 if (strchr(path, '/') == NULL) {
8db227a70bec access_get_error(): Fixed to give better error messages with relative paths.
Timo Sirainen <tss@iki.fi>
parents: 12004
diff changeset
103 /* we have no path. do the file access checks anyway. */
8db227a70bec access_get_error(): Fixed to give better error messages with relative paths.
Timo Sirainen <tss@iki.fi>
parents: 12004
diff changeset
104 ret = 0;
8db227a70bec access_get_error(): Fixed to give better error messages with relative paths.
Timo Sirainen <tss@iki.fi>
parents: 12004
diff changeset
105 }
9589
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
106 }
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
107 str_printfa(errmsg, " failed: Permission denied (euid=%s",
f564209e9396 eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents: 9537
diff changeset
108 dec2str(geteuid()));
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
109
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
110 pw = getpwuid(geteuid());
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
111 if (pw != NULL) {
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
112 pw_name = t_strdup(pw->pw_name);
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
113 str_printfa(errmsg, "(%s)", pw_name);
12004
4f90b4114450 eaccess_error_get(): If UID/GID doesn't have name, show it as <unknown>
Timo Sirainen <tss@iki.fi>
parents: 10819
diff changeset
114 } else {
4f90b4114450 eaccess_error_get(): If UID/GID doesn't have name, show it as <unknown>
Timo Sirainen <tss@iki.fi>
parents: 10819
diff changeset
115 str_append(errmsg, "(<unknown>)");
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
116 }
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
117
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
118 str_printfa(errmsg, " egid=%s", dec2str(getegid()));
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
119 group = getgrgid(getegid());
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
120 if (group != NULL) {
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
121 gr_name = t_strdup(group->gr_name);
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
122 str_printfa(errmsg, "(%s)", gr_name);
12004
4f90b4114450 eaccess_error_get(): If UID/GID doesn't have name, show it as <unknown>
Timo Sirainen <tss@iki.fi>
parents: 10819
diff changeset
123 } else {
4f90b4114450 eaccess_error_get(): If UID/GID doesn't have name, show it as <unknown>
Timo Sirainen <tss@iki.fi>
parents: 10819
diff changeset
124 str_append(errmsg, "(<unknown>)");
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
125 }
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
126
12050
8db227a70bec access_get_error(): Fixed to give better error messages with relative paths.
Timo Sirainen <tss@iki.fi>
parents: 12004
diff changeset
127 memset(&dir_st, 0, sizeof(dir_st));
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
128 while ((p = strrchr(prev_path, '/')) != NULL) {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
129 dir = t_strdup_until(prev_path, p);
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
130 ret = stat(dir, &st);
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
131 if (ret == 0)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
132 break;
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
133 if (errno == EACCES) {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
134 /* see if we have access to parent directory */
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
135 } else if (errno == ENOENT && creating) {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
136 /* probably mkdir_parents() failed here, find the first
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
137 parent directory we couldn't create */
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
138 } else {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
139 /* some other error, can't handle it */
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
140 str_printfa(errmsg, " stat(%s) failed: %m", dir);
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
141 break;
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
142 }
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
143 prev_path = dir;
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
144 dir = "/";
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
145 dir_st = st;
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
146 }
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
147
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
148 if (ret == 0) {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
149 /* dir is the first parent directory we can stat() */
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
150 if (test_access(dir, X_OK, errmsg) < 0) {
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
151 if (errno == EACCES)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
152 str_printfa(errmsg, " missing +x perm: %s", dir);
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
153 } else if (creating && test_access(dir, W_OK, errmsg) < 0) {
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
154 if (errno == EACCES)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
155 str_printfa(errmsg, " missing +w perm: %s", dir);
9501
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
156 } else if (prev_path == path &&
e22e36a61fdd eacces_error_get*() works now properly when process's real uid != effective uid.
Timo Sirainen <tss@iki.fi>
parents: 8759
diff changeset
157 test_access(path, R_OK, errmsg) < 0) {
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
158 if (errno == EACCES)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
159 str_printfa(errmsg, " missing +r perm: %s", path);
9534
8760bc0b1c3a eacces_error_get(): Check also if user had write permissions to the given file.
Timo Sirainen <tss@iki.fi>
parents: 9501
diff changeset
160 } else if (!creating && test_access(path, W_OK, errmsg) < 0) {
8760bc0b1c3a eacces_error_get(): Check also if user had write permissions to the given file.
Timo Sirainen <tss@iki.fi>
parents: 9501
diff changeset
161 /* this produces a wrong error if the operation didn't
8760bc0b1c3a eacces_error_get(): Check also if user had write permissions to the given file.
Timo Sirainen <tss@iki.fi>
parents: 9501
diff changeset
162 actually need write permissions, but we don't know
8760bc0b1c3a eacces_error_get(): Check also if user had write permissions to the given file.
Timo Sirainen <tss@iki.fi>
parents: 9501
diff changeset
163 it here.. */
8760bc0b1c3a eacces_error_get(): Check also if user had write permissions to the given file.
Timo Sirainen <tss@iki.fi>
parents: 9501
diff changeset
164 if (errno == EACCES)
8760bc0b1c3a eacces_error_get(): Check also if user had write permissions to the given file.
Timo Sirainen <tss@iki.fi>
parents: 9501
diff changeset
165 str_printfa(errmsg, " missing +w perm: %s", path);
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
166 } else
10210
66eaf7b1e36b eaccess_error*(): Error message updated.
Timo Sirainen <tss@iki.fi>
parents: 9589
diff changeset
167 str_printfa(errmsg, " UNIX perms appear ok, "
66eaf7b1e36b eaccess_error*(): Error message updated.
Timo Sirainen <tss@iki.fi>
parents: 9589
diff changeset
168 "some security policy wrong?");
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
169 }
10819
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
170 if (dir_st.st_uid != geteuid()) {
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
171 if (pw_name != NULL &&
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
172 (pw = getpwuid(dir_st.st_uid)) != NULL &&
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
173 strcmp(pw->pw_name, pw_name) == 0) {
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
174 str_printfa(errmsg, ", conflicting dir uid=%s(%s)",
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
175 dec2str(dir_st.st_uid), pw_name);
10819
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
176 } else {
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
177 str_append(errmsg, ", euid is not dir owner");
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
178 }
10819
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
179 } else {
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
180 str_append(errmsg, ", euid is dir owner");
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
181 }
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
182 if (gr_name != NULL && dir_st.st_gid != getegid()) {
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
183 group = getgrgid(dir_st.st_gid);
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
184 if (group != NULL && strcmp(group->gr_name, gr_name) == 0) {
10819
6a8ee83cbc8c eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents: 10582
diff changeset
185 str_printfa(errmsg, ", conflicting dir gid=%s(%s)",
10553
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
186 dec2str(dir_st.st_gid), gr_name);
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
187 }
b8966b8133f2 eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents: 10502
diff changeset
188 }
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
189 str_append_c(errmsg, ')');
9537
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
190 errno = orig_errno;
8759
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
191 return str_c(errmsg);
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
192 }
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
193
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
194 const char *eacces_error_get(const char *func, const char *path)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
195 {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
196 return eacces_error_get_full(func, path, FALSE);
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
197 }
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
198
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
199 const char *eacces_error_get_creating(const char *func, const char *path)
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
200 {
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
201 return eacces_error_get_full(func, path, TRUE);
6ec819adfde3 Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
202 }
9537
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
203
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
204 const char *eperm_error_get_chgrp(const char *func, const char *path,
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
205 gid_t gid, const char *gid_origin)
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
206 {
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
207 string_t *errmsg;
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
208 const struct group *group;
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
209 int orig_errno = errno;
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
210
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
211 errmsg = t_str_new(256);
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
212
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
213 str_printfa(errmsg, "%s(%s, -1, %s", func, path, dec2str(gid));
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
214 group = getgrgid(gid);
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
215 if (group != NULL)
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
216 str_printfa(errmsg, "(%s)", group->gr_name);
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
217
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
218 str_printfa(errmsg, ") failed: Operation not permitted (egid=%s",
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
219 dec2str(getegid()));
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
220 group = getgrgid(getegid());
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
221 if (group != NULL)
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
222 str_printfa(errmsg, "(%s)", group->gr_name);
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
223 if (gid_origin != NULL)
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
224 str_printfa(errmsg, ", group based on %s", gid_origin);
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
225 str_append_c(errmsg, ')');
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
226 errno = orig_errno;
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
227 return str_c(errmsg);
b373de4973cd Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents: 9534
diff changeset
228 }