Back to index

glibc  2.9
euidaccess.c
Go to the documentation of this file.
00001 /* Check if effective user id can access file
00002    Copyright (C) 1990,1991,1995-2001,2005,2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 /* Written by David MacKenzie and Torbjorn Granlund.
00021    Adapted for GNU C library by Roland McGrath.  */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 # include <config.h>
00025 #endif
00026 
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 
00030 #ifdef S_IEXEC
00031 # ifndef S_IXUSR
00032 #  define S_IXUSR S_IEXEC
00033 # endif
00034 # ifndef S_IXGRP
00035 #  define S_IXGRP (S_IEXEC >> 3)
00036 # endif
00037 # ifndef S_IXOTH
00038 #  define S_IXOTH (S_IEXEC >> 6)
00039 # endif
00040 #endif /* S_IEXEC */
00041 
00042 #if defined HAVE_UNISTD_H || defined _LIBC
00043 # include <unistd.h>
00044 #endif
00045 
00046 #ifndef _POSIX_VERSION
00047 uid_t getuid ();
00048 gid_t getgid ();
00049 uid_t geteuid ();
00050 gid_t getegid ();
00051 #endif /* not POSIX_VERSION */
00052 
00053 #include <errno.h>
00054 #ifndef errno
00055 extern int errno;
00056 #endif
00057 #ifndef __set_errno
00058 # define __set_errno(val) errno = (val)
00059 #endif
00060 
00061 #if defined EACCES && !defined EACCESS
00062 # define EACCESS EACCES
00063 #endif
00064 
00065 #ifndef F_OK
00066 # define F_OK 0
00067 # define X_OK 1
00068 # define W_OK 2
00069 # define R_OK 4
00070 #endif
00071 
00072 #if !defined S_IROTH && defined R_OK
00073 # define S_IROTH R_OK
00074 #endif
00075 #if !defined S_IWOTH && defined W_OK
00076 # define S_IWOTH W_OK
00077 #endif
00078 #if !defined S_IXOTH && defined X_OK
00079 # define S_IXOTH X_OK
00080 #endif
00081 
00082 
00083 #ifdef _LIBC
00084 
00085 # define group_member __group_member
00086 # define euidaccess __euidaccess
00087 
00088 #else
00089 
00090 /* The user's real user id. */
00091 static uid_t uid;
00092 
00093 /* The user's real group id. */
00094 static gid_t gid;
00095 
00096 /* The user's effective user id. */
00097 static uid_t euid;
00098 
00099 /* The user's effective group id. */
00100 static gid_t egid;
00101 
00102 /* Nonzero if UID, GID, EUID, and EGID have valid values. */
00103 static int have_ids;
00104 
00105 # ifdef HAVE_GETGROUPS
00106 int group_member ();
00107 # else
00108 #  define group_member(gid) 0
00109 # endif
00110 
00111 #endif
00112 
00113 
00114 /* Return 0 if the user has permission of type MODE on file PATH;
00115    otherwise, return -1 and set `errno' to EACCESS.
00116    Like access, except that it uses the effective user and group
00117    id's instead of the real ones, and it does not check for read-only
00118    filesystem, text busy, etc. */
00119 
00120 int
00121 euidaccess (path, mode)
00122      const char *path;
00123      int mode;
00124 {
00125   struct stat64 stats;
00126   int granted;
00127 
00128 #ifdef _LIBC
00129   uid_t euid;
00130   gid_t egid;
00131 #else
00132   if (have_ids == 0)
00133     {
00134       have_ids = 1;
00135       uid = getuid ();
00136       gid = getgid ();
00137       euid = geteuid ();
00138       egid = getegid ();
00139     }
00140 
00141   if (uid == euid && gid == egid)
00142     /* If we are not set-uid or set-gid, access does the same.  */
00143     return access (path, mode);
00144 #endif
00145 
00146   if (stat64 (path, &stats))
00147     return -1;
00148 
00149   mode &= (X_OK | W_OK | R_OK);    /* Clear any bogus bits. */
00150 #if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH
00151   ?error Oops, portability assumptions incorrect.
00152 #endif
00153 
00154   if (mode == F_OK)
00155     return 0;               /* The file exists. */
00156 
00157 #ifdef _LIBC
00158   /* Now we need the IDs.  */
00159   euid = __geteuid ();
00160   egid = __getegid ();
00161 
00162   if (__getuid () == euid && __getgid () == egid)
00163     /* If we are not set-uid or set-gid, access does the same.  */
00164     return __access (path, mode);
00165 #endif
00166 
00167   /* The super-user can read and write any file, and execute any file
00168      that anyone can execute. */
00169   if (euid == 0 && ((mode & X_OK) == 0
00170                   || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
00171     return 0;
00172 
00173   if (euid == stats.st_uid)
00174     granted = (unsigned int) (stats.st_mode & (mode << 6)) >> 6;
00175   else if (egid == stats.st_gid || group_member (stats.st_gid))
00176     granted = (unsigned int) (stats.st_mode & (mode << 3)) >> 3;
00177   else
00178     granted = (stats.st_mode & mode);
00179   /* XXX Add support for ACLs.  */
00180   if (granted == mode)
00181     return 0;
00182   __set_errno (EACCESS);
00183   return -1;
00184 }
00185 #undef euidaccess
00186 #undef eaccess
00187 #ifdef weak_alias
00188 weak_alias (__euidaccess, euidaccess)
00189 weak_alias (__euidaccess, eaccess)
00190 #endif
00191 
00192 #ifdef TEST
00193 # include <stdio.h>
00194 # include <errno.h>
00195 # include "error.h"
00196 
00197 char *program_name;
00198 
00199 int
00200 main (argc, argv)
00201      int argc;
00202      char **argv;
00203 {
00204   char *file;
00205   int mode;
00206   int err;
00207 
00208   program_name = argv[0];
00209   if (argc < 3)
00210     abort ();
00211   file = argv[1];
00212   mode = atoi (argv[2]);
00213 
00214   err = euidaccess (file, mode);
00215   printf ("%d\n", err);
00216   if (err != 0)
00217     error (0, errno, "%s", file);
00218   exit (0);
00219 }
00220 #endif