]>
Commit | Line | Data |
---|---|---|
f166d865 | 1 | /* Check if effective user id can access file |
04277e02 | 2 | Copyright (C) 1990-2019 Free Software Foundation, Inc. |
f166d865 | 3 | This file is part of the GNU C Library. |
3bbceb12 | 4 | |
f166d865 | 5 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
3bbceb12 | 9 | |
f166d865 UD |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
3bbceb12 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
3bbceb12 RM |
18 | |
19 | /* Written by David MacKenzie and Torbjorn Granlund. | |
20 | Adapted for GNU C library by Roland McGrath. */ | |
21 | ||
22 | #ifdef HAVE_CONFIG_H | |
fec53fc5 | 23 | # include <config.h> |
3bbceb12 RM |
24 | #endif |
25 | ||
26 | #include <sys/types.h> | |
27 | #include <sys/stat.h> | |
28 | ||
29 | #ifdef S_IEXEC | |
fec53fc5 UD |
30 | # ifndef S_IXUSR |
31 | # define S_IXUSR S_IEXEC | |
32 | # endif | |
33 | # ifndef S_IXGRP | |
34 | # define S_IXGRP (S_IEXEC >> 3) | |
35 | # endif | |
36 | # ifndef S_IXOTH | |
37 | # define S_IXOTH (S_IEXEC >> 6) | |
38 | # endif | |
3bbceb12 RM |
39 | #endif /* S_IEXEC */ |
40 | ||
fec53fc5 UD |
41 | #if defined HAVE_UNISTD_H || defined _LIBC |
42 | # include <unistd.h> | |
3bbceb12 RM |
43 | #endif |
44 | ||
cb21f242 | 45 | #ifndef _POSIX_VERSION |
3bbceb12 RM |
46 | uid_t getuid (); |
47 | gid_t getgid (); | |
48 | uid_t geteuid (); | |
49 | gid_t getegid (); | |
3bbceb12 RM |
50 | #endif /* not POSIX_VERSION */ |
51 | ||
52 | #include <errno.h> | |
53 | #ifndef errno | |
54 | extern int errno; | |
55 | #endif | |
c4029823 | 56 | #ifndef __set_errno |
fec53fc5 | 57 | # define __set_errno(val) errno = (val) |
c4029823 | 58 | #endif |
3bbceb12 | 59 | |
fec53fc5 UD |
60 | #if defined EACCES && !defined EACCESS |
61 | # define EACCESS EACCES | |
3bbceb12 RM |
62 | #endif |
63 | ||
64 | #ifndef F_OK | |
fec53fc5 UD |
65 | # define F_OK 0 |
66 | # define X_OK 1 | |
67 | # define W_OK 2 | |
68 | # define R_OK 4 | |
3bbceb12 RM |
69 | #endif |
70 | ||
fec53fc5 | 71 | #if !defined S_IROTH && defined R_OK |
b8fe19fa RM |
72 | # define S_IROTH R_OK |
73 | #endif | |
fec53fc5 | 74 | #if !defined S_IWOTH && defined W_OK |
b8fe19fa RM |
75 | # define S_IWOTH W_OK |
76 | #endif | |
fec53fc5 | 77 | #if !defined S_IXOTH && defined X_OK |
b8fe19fa RM |
78 | # define S_IXOTH X_OK |
79 | #endif | |
80 | ||
3bbceb12 RM |
81 | |
82 | #ifdef _LIBC | |
83 | ||
fec53fc5 UD |
84 | # define group_member __group_member |
85 | # define euidaccess __euidaccess | |
3bbceb12 RM |
86 | |
87 | #else | |
88 | ||
89 | /* The user's real user id. */ | |
90 | static uid_t uid; | |
91 | ||
92 | /* The user's real group id. */ | |
93 | static gid_t gid; | |
94 | ||
95 | /* The user's effective user id. */ | |
96 | static uid_t euid; | |
97 | ||
98 | /* The user's effective group id. */ | |
99 | static gid_t egid; | |
100 | ||
101 | /* Nonzero if UID, GID, EUID, and EGID have valid values. */ | |
c4563d2d | 102 | static int have_ids; |
3bbceb12 | 103 | |
fec53fc5 UD |
104 | # ifdef HAVE_GETGROUPS |
105 | int group_member (); | |
106 | # else | |
107 | # define group_member(gid) 0 | |
108 | # endif | |
109 | ||
110 | #endif | |
111 | ||
3bbceb12 RM |
112 | |
113 | /* Return 0 if the user has permission of type MODE on file PATH; | |
114 | otherwise, return -1 and set `errno' to EACCESS. | |
115 | Like access, except that it uses the effective user and group | |
116 | id's instead of the real ones, and it does not check for read-only | |
117 | filesystem, text busy, etc. */ | |
118 | ||
119 | int | |
bd2260a2 | 120 | euidaccess (const char *path, int mode) |
3bbceb12 | 121 | { |
8edf6e0d | 122 | struct stat64 stats; |
3bbceb12 RM |
123 | int granted; |
124 | ||
125 | #ifdef _LIBC | |
fec53fc5 UD |
126 | uid_t euid; |
127 | gid_t egid; | |
3bbceb12 RM |
128 | #else |
129 | if (have_ids == 0) | |
130 | { | |
131 | have_ids = 1; | |
132 | uid = getuid (); | |
133 | gid = getgid (); | |
134 | euid = geteuid (); | |
135 | egid = getegid (); | |
136 | } | |
3bbceb12 RM |
137 | |
138 | if (uid == euid && gid == egid) | |
139 | /* If we are not set-uid or set-gid, access does the same. */ | |
140 | return access (path, mode); | |
11336c16 | 141 | #endif |
3bbceb12 | 142 | |
8edf6e0d | 143 | if (stat64 (path, &stats)) |
3bbceb12 RM |
144 | return -1; |
145 | ||
146 | mode &= (X_OK | W_OK | R_OK); /* Clear any bogus bits. */ | |
147 | #if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH | |
148 | ?error Oops, portability assumptions incorrect. | |
149 | #endif | |
150 | ||
151 | if (mode == F_OK) | |
152 | return 0; /* The file exists. */ | |
153 | ||
11336c16 UD |
154 | #ifdef _LIBC |
155 | /* Now we need the IDs. */ | |
fec53fc5 UD |
156 | euid = __geteuid (); |
157 | egid = __getegid (); | |
2e0e802a UD |
158 | |
159 | if (__getuid () == euid && __getgid () == egid) | |
160 | /* If we are not set-uid or set-gid, access does the same. */ | |
161 | return __access (path, mode); | |
11336c16 UD |
162 | #endif |
163 | ||
3bbceb12 RM |
164 | /* The super-user can read and write any file, and execute any file |
165 | that anyone can execute. */ | |
166 | if (euid == 0 && ((mode & X_OK) == 0 | |
167 | || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) | |
168 | return 0; | |
169 | ||
170 | if (euid == stats.st_uid) | |
fec53fc5 | 171 | granted = (unsigned int) (stats.st_mode & (mode << 6)) >> 6; |
3bbceb12 | 172 | else if (egid == stats.st_gid || group_member (stats.st_gid)) |
fec53fc5 | 173 | granted = (unsigned int) (stats.st_mode & (mode << 3)) >> 3; |
3bbceb12 RM |
174 | else |
175 | granted = (stats.st_mode & mode); | |
fec53fc5 | 176 | /* XXX Add support for ACLs. */ |
3bbceb12 RM |
177 | if (granted == mode) |
178 | return 0; | |
c4029823 | 179 | __set_errno (EACCESS); |
3bbceb12 RM |
180 | return -1; |
181 | } | |
f166d865 | 182 | #undef euidaccess |
cb483e04 | 183 | #undef eaccess |
f166d865 UD |
184 | #ifdef weak_alias |
185 | weak_alias (__euidaccess, euidaccess) | |
cb483e04 | 186 | weak_alias (__euidaccess, eaccess) |
f166d865 | 187 | #endif |
3bbceb12 RM |
188 | \f |
189 | #ifdef TEST | |
fec53fc5 UD |
190 | # include <stdio.h> |
191 | # include <errno.h> | |
192 | # include "error.h" | |
3bbceb12 RM |
193 | |
194 | char *program_name; | |
195 | ||
196 | int | |
bd2260a2 | 197 | main (int argc, char **argv) |
3bbceb12 RM |
198 | { |
199 | char *file; | |
200 | int mode; | |
201 | int err; | |
202 | ||
203 | program_name = argv[0]; | |
204 | if (argc < 3) | |
205 | abort (); | |
206 | file = argv[1]; | |
207 | mode = atoi (argv[2]); | |
208 | ||
209 | err = euidaccess (file, mode); | |
210 | printf ("%d\n", err); | |
211 | if (err != 0) | |
212 | error (0, errno, "%s", file); | |
213 | exit (0); | |
214 | } | |
215 | #endif |