Mercurial > dovecot > core-2.2
annotate src/lib/eacces-error.c @ 10819:6a8ee83cbc8c HEAD
eacces_error_get*(): Mention if euid is parent directory's owner.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 01 Mar 2010 00:34:43 +0200 |
parents | 615eef3139c2 |
children | 4f90b4114450 |
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); |
f564209e9396
eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents:
9537
diff
changeset
|
98 if (*path != '/') { |
10502
13be6ac759ee
Added t_get_current_dir() and use it instead of getcwd().
Timo Sirainen <tss@iki.fi>
parents:
10210
diff
changeset
|
99 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
|
100 str_printfa(errmsg, " in directory %s", dir); |
f564209e9396
eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents:
9537
diff
changeset
|
101 } |
f564209e9396
eacces_error_get*(): Show current directory if path is relative.
Timo Sirainen <tss@iki.fi>
parents:
9537
diff
changeset
|
102 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
|
103 dec2str(geteuid())); |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
104 |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
105 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
|
106 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
|
107 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
|
108 str_printfa(errmsg, "(%s)", 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
|
109 } |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
110 |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
111 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
|
112 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
|
113 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
|
114 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
|
115 str_printfa(errmsg, "(%s)", 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
|
116 } |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
117 |
10553
b8966b8133f2
eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents:
10502
diff
changeset
|
118 dir = "/"; 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
|
119 while ((p = strrchr(prev_path, '/')) != NULL) { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
120 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
|
121 ret = stat(dir, &st); |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
122 if (ret == 0) |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
123 break; |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
124 if (errno == EACCES) { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
125 /* 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
|
126 } else if (errno == ENOENT && creating) { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
127 /* 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
|
128 parent directory we couldn't create */ |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
129 } else { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
130 /* 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
|
131 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
|
132 break; |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
133 } |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
134 prev_path = dir; |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
135 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
|
136 dir_st = st; |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
137 } |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
138 |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
139 if (ret == 0) { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
140 /* 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
|
141 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
|
142 if (errno == EACCES) |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
143 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
|
144 } 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
|
145 if (errno == EACCES) |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
146 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
|
147 } 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
|
148 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
|
149 if (errno == EACCES) |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
150 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
|
151 } 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
|
152 /* 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
|
153 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
|
154 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
|
155 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
|
156 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
|
157 } else |
10210
66eaf7b1e36b
eaccess_error*(): Error message updated.
Timo Sirainen <tss@iki.fi>
parents:
9589
diff
changeset
|
158 str_printfa(errmsg, " UNIX perms appear ok, " |
66eaf7b1e36b
eaccess_error*(): Error message updated.
Timo Sirainen <tss@iki.fi>
parents:
9589
diff
changeset
|
159 "some security policy wrong?"); |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
160 } |
10819
6a8ee83cbc8c
eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents:
10582
diff
changeset
|
161 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
|
162 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
|
163 (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
|
164 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
|
165 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
|
166 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
|
167 } else { |
6a8ee83cbc8c
eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents:
10582
diff
changeset
|
168 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
|
169 } |
10819
6a8ee83cbc8c
eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents:
10582
diff
changeset
|
170 } else { |
6a8ee83cbc8c
eacces_error_get*(): Mention if euid is parent directory's owner.
Timo Sirainen <tss@iki.fi>
parents:
10582
diff
changeset
|
171 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
|
172 } |
b8966b8133f2
eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents:
10502
diff
changeset
|
173 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
|
174 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
|
175 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
|
176 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
|
177 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
|
178 } |
b8966b8133f2
eacces_error_get*(): Check and warn if multiple uids/gids have same name.
Timo Sirainen <tss@iki.fi>
parents:
10502
diff
changeset
|
179 } |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
180 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
|
181 errno = orig_errno; |
8759
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
182 return str_c(errmsg); |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
183 } |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
184 |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
185 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
|
186 { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
187 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
|
188 } |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
189 |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
190 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
|
191 { |
6ec819adfde3
Moved user-friendly EACCES error message generation to lib/.
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
192 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
|
193 } |
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
|
194 |
b373de4973cd
Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents:
9534
diff
changeset
|
195 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
|
196 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
|
197 { |
b373de4973cd
Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents:
9534
diff
changeset
|
198 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
|
199 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
|
200 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
|
201 |
b373de4973cd
Whenever file's group changing fails, show the group origin in the error message.
Timo Sirainen <tss@iki.fi>
parents:
9534
diff
changeset
|
202 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
|
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 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
|
205 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
|
206 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
|
207 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
|
208 |
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 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
|
210 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
|
211 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
|
212 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
|
213 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
|
214 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
|
215 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
|
216 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
|
217 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
|
218 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
|
219 } |