ACL to permissions patch



Hi guys,

  I've just realized that I forgot to apply a quite important patch to
  the ACL branch that we created before the 2.16 release.

  The patch makes the VFS to check the ACL entries - if present - when
  it calculates a file access permission.

  Right now, Nautilus is misbehaving on ACL enabled file systems
  because the gnome-vfs file module only checks the file permissions
  without checking the ACL entries.

  The patch is attach.  Is it okay to commit to HEAD?

--
Greetings, alo.
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-vfs/ChangeLog,v
retrieving revision 1.2545
diff -u -r1.2545 ChangeLog
--- ChangeLog	1 Dec 2006 22:26:16 -0000	1.2545
+++ ChangeLog	13 Dec 2006 13:51:49 -0000
@@ -1,3 +1,23 @@
+2006-12-13  Alvaro Lopez Ortega  <alvaro sun com>
+
+	* acinclude.m4: Added new macros to detect the type of the
+	getpwnam_r() and getgrnam_r() system calls.
+
+	* configure.in: Updated to use the new FW_CHECK_GRP and
+	FW_CHECK_PW macros.
+
+	* modules/file-method-acl.c (secure_getpwnam, secure_getgrnam):
+	Added to new functions that ensure thread safeness.
+
+	* modules/file-method-acl.h,
+	modules/file-method-acl.c (get_access_info_acl): This new
+	functions checks the ACL entries in order to fill up the file info
+	access information.
+
+	* modules/file-method.c (get_access_info): It has to check the ACL
+	information if present. It fixes some permission problems in
+	Nautilus when using ACL enabled file systems.
+	
 2006-12-01  Christian Neumair  <chris gnome-de org>
 
 	* libgnomevfs/gnome-vfs-unix-mounts.c:
Index: acinclude.m4
===================================================================
RCS file: /cvs/gnome/gnome-vfs/acinclude.m4,v
retrieving revision 1.10
diff -u -r1.10 acinclude.m4
--- acinclude.m4	26 Nov 2005 11:19:44 -0000	1.10
+++ acinclude.m4	13 Dec 2006 13:51:49 -0000
@@ -556,3 +556,89 @@
 
 
 dnl end of neon macros
+
+
+dnl
+dnl checks for password entry functions and header files
+dnl
+AC_DEFUN([FW_CHECK_PWD],
+[
+
+HAVE_GETPWNAM_R=""
+
+AC_MSG_CHECKING(for getpwnam_r with 5 parameters)
+AC_TRY_COMPILE([#include <pwd.h>
+#include <stdlib.h>],
+getpwnam_r(NULL,NULL,NULL,0,NULL);,AC_DEFINE(HAVE_GETPWNAM_R_5,1,Some systems have getpwnam_r) AC_DEFINE(HAVE_
+ETPWNAM_R,1,Some systems have getpwnam_r) AC_MSG_RESULT(yes); HAVE_GETPWNAM_R="yes", AC_MSG_RESULT(no))
+
+if ( test -z "$HAVE_GETPWNAM_R" )
+then
+       AC_MSG_CHECKING(for getpwnam_r with 4 parameters)
+       AC_TRY_COMPILE([#include <pwd.h>
+#include <stdlib.h>],
+getpwnam_r(NULL,NULL,NULL,0);,AC_DEFINE(HAVE_GETPWNAM_R_4,1,Some systems have getpwnam_r) AC_DEFINE(HAVE_GETPW
+AM_R,1,Some systems have getpwnam_r) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+fi
+
+HAVE_GETPWUID_R=""
+
+AC_MSG_CHECKING(for getpwuid_r with 5 parameters)
+AC_TRY_COMPILE([#include <pwd.h>
+#include <stdlib.h>],
+getpwuid_r(0,NULL,NULL,0,NULL);,AC_DEFINE(HAVE_GETPWUID_R_5,1,Some systems have getpwuid_r) AC_DEFINE(HAVE_GET
+WUID_R,1,Some systems have getpwuid_r) AC_MSG_RESULT(yes); HAVE_GETPWUID_R="yes", AC_MSG_RESULT(no))
+
+if ( test -z "$HAVE_GETPWUID_R" )
+then
+       AC_MSG_CHECKING(for getpwuid_r with 4 parameters)
+       AC_TRY_COMPILE([#include <pwd.h>
+#include <stdlib.h>],
+getpwuid_r(0,NULL,NULL,0);,AC_DEFINE(HAVE_GETPWUID_R_4,1,Some systems have getpwuid_r) AC_DEFINE(HAVE_GETPWUID
+R,1,Some systems have getpwuid_r) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+fi
+
+])
+
+
+dnl
+dnl checks for group entry functions and header files
+dnl
+AC_DEFUN([FW_CHECK_GRP],
+[
+
+HAVE_GETGRNAM_R=""
+
+AC_MSG_CHECKING(for getgrnam_r with 5 parameters)
+AC_TRY_COMPILE([#include <grp.h>
+#include <stdlib.h>],
+getgrnam_r(NULL,NULL,NULL,0,NULL);,AC_DEFINE(HAVE_GETGRNAM_R_5,1,Some systems have getgrnam_r) AC_DEFINE(HAVE_
+ETGRNAM_R,1,Some systems have getgrnam_r) AC_MSG_RESULT(yes); HAVE_GETGRNAM_R="yes", AC_MSG_RESULT(no))
+
+if ( test -z "$HAVE_GETGRNAM_R" )
+then
+       AC_MSG_CHECKING(for getgrnam_r with 4 parameters)
+       AC_TRY_COMPILE([#include <grp.h>
+#include <stdlib.h>],
+getgrnam_r(NULL,NULL,NULL,0);,AC_DEFINE(HAVE_GETGRNAM_R_4,1,Some systems have getgrnam_r) AC_DEFINE(HAVE_GETGR
+AM_R,1,Some systems have getgrnam_r) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+fi
+
+HAVE_GETGRGID_R=""
+
+AC_MSG_CHECKING(for getgrgid_r with 5 parameters)
+AC_TRY_COMPILE([#include <grp.h>
+#include <stdlib.h>],
+getgrgid_r(0,NULL,NULL,0,NULL);,AC_DEFINE(HAVE_GETGRGID_R_5,1,Some systems have getgrgid_r) AC_DEFINE(HAVE_GET
+RGID_R,1,Some systems have getgrgid_r) AC_MSG_RESULT(yes); HAVE_GETGRGID_R="yes", AC_MSG_RESULT(no))
+
+if ( test -z "$HAVE_GETGRGID_R" )
+then
+       AC_MSG_CHECKING(for getgrgid_r with 4 parameters)
+       AC_TRY_COMPILE([#include <grp.h>
+#include <stdlib.h>],
+getgrgid_r(0,NULL,NULL,0);,AC_DEFINE(HAVE_GETGRGID_R_4,1,Some systems have getgrgid_r) AC_DEFINE(HAVE_GETGRGID
+R,1,Some systems have getgrgid_r) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
+fi
+
+])
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-vfs/configure.in,v
retrieving revision 1.451
diff -u -r1.451 configure.in
--- configure.in	23 Nov 2006 12:58:57 -0000	1.451
+++ configure.in	13 Dec 2006 13:51:49 -0000
@@ -1092,52 +1092,10 @@
     AC_CHECK_FUNCS(acl_extended_file)
     
     AC_CHECK_HEADERS([pwd.h])
-    if test "$ac_cv_header_pwd_h" = "yes"; then
-	 	AC_CACHE_CHECK([for posix getpwuid_r],
-			ac_cv_func_posix_getpwuid_r,
-			[AC_TRY_RUN([
-#include <errno.h>
-#include <pwd.h>
-int main () { 
-    char buffer[10000];
-    struct passwd pwd, *pwptr = &pwd;
-    int error;
-    errno = 0;
-    error = getpwuid_r (0, &pwd, buffer, 
-                        sizeof (buffer), &pwptr);
-   return (error < 0 && errno == ENOSYS) 
-	   || error == ENOSYS; 
-}                               ],
-				[ac_cv_func_posix_getpwuid_r=yes],
-				[ac_cv_func_posix_getpwuid_r=no])])
-		dnl GLIB_ASSERT_SET(ac_cv_func_posix_getpwuid_r)
-		if test "$ac_cv_func_posix_getpwuid_r" = yes; then
-			AC_DEFINE(HAVE_POSIX_GETPWUID_R,1,
-				[Have POSIX function getpwuid_r])
-		else
-	 		AC_CACHE_CHECK([for nonposix getpwuid_r],
-				ac_cv_func_nonposix_getpwuid_r,
-				[AC_TRY_LINK([#include <pwd.h>],
-                                	[char buffer[10000];
-                                	struct passwd pwd;
-                                	getpwuid_r (0, &pwd, buffer, 
-                                        		sizeof (buffer));],
-					[ac_cv_func_nonposix_getpwuid_r=yes],
-					[ac_cv_func_nonposix_getpwuid_r=no])])
-			dnl GLIB_ASSERT_SET(ac_cv_func_nonposix_getpwuid_r)
-			if test "$ac_cv_func_nonposix_getpwuid_r" = yes; then
-				AC_DEFINE(HAVE_NONPOSIX_GETPWUID_R,1,
-					[Have non-POSIX function getpwuid_r])
-			fi
-		fi
-	fi 
+    FW_CHECK_PWD
 
-	AC_CHECK_HEADERS([grp.h])
-
-	AC_CHECK_FUNCS(getgrgid_r)
-	AC_CHECK_FUNCS(getgrnam_r)
-	AC_CHECK_FUNCS(getpwnam_r)
-	
+    AC_CHECK_HEADERS([grp.h])
+    FW_CHECK_GRP      
 fi
 
 AC_SUBST(ACL_LIBS)
Index: modules/file-method-acl.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/file-method-acl.c,v
retrieving revision 1.4
diff -u -r1.4 file-method-acl.c
--- modules/file-method-acl.c	23 Jul 2006 10:28:24 -0000	1.4
+++ modules/file-method-acl.c	13 Dec 2006 13:51:49 -0000
@@ -1013,3 +1013,225 @@
 }
 
 
+#ifndef HAVE_GETPWNAM_R
+G_LOCK_DEFINE (getpwnam_lock);
+#endif
+
+static int
+secure_getpwnam (const char *name, struct passwd *pwbuf, char *buf, size_t buflen)
+{
+#ifndef HAVE_GETPWNAM_R
+       size_t         pw_name_len   = 0;
+       size_t         pw_passwd_len = 0;
+       size_t         pw_gecos_len  = 0;
+       size_t         pw_dir_len    = 0;
+       size_t         pw_shell_len  = 0;
+       char          *ptr;
+       struct passwd *tmp;
+
+       G_LOCK(getpwnam_lock);
+
+       tmp = getpwnam (name);
+       if (tmp == NULL) 
+               return errno;
+
+       if (tmp->pw_name)   pw_name_len   = strlen(tmp->pw_name);
+       if (tmp->pw_passwd) pw_passwd_len = strlen(tmp->pw_passwd);
+       if (tmp->pw_gecos)  pw_gecos_len  = strlen(tmp->pw_gecos);
+       if (tmp->pw_dir)    pw_dir_len    = strlen(tmp->pw_dir);
+       if (tmp->pw_shell)  pw_shell_len  = strlen(tmp->pw_shell);
+
+       if ((pw_name_len + pw_passwd_len + 
+            pw_gecos_len + pw_dir_len + pw_shell_len) > buflen)
+               return ERANGE;
+
+       memset (buf, 0, buflen);
+       ptr = buf;       
+
+       if (tmp->pw_name) {
+               memcpy (ptr, tmp->pw_name, pw_name_len);
+               pwbuf->pw_name = ptr;
+               ptr += pw_name_len + 1;
+       }
+
+       if (tmp->pw_passwd) {
+               memcpy (ptr, tmp->pw_passwd, pw_passwd_len);
+               pwbuf->pw_passwd = ptr;
+               ptr += pw_passwd_len + 1;
+       }
+
+       if (tmp->pw_gecos) {
+               memcpy (ptr, tmp->pw_gecos, pw_gecos_len);
+               pwbuf->pw_gecos = ptr;
+               ptr += pw_gecos_len + 1;
+       }
+
+       if (tmp->pw_dir) {
+               memcpy (ptr, tmp->pw_dir, pw_dir_len);
+               pwbuf->pw_dir = ptr;
+               ptr += pw_dir_len + 1;
+       }
+
+
+       if (tmp->pw_shell) {
+               memcpy (ptr, tmp->pw_shell, pw_shell_len);
+               pwbuf->pw_shell = ptr;
+               ptr += pw_shell_len + 1;
+       }
+
+       G_UNLOCK(getpwnam_lock);
+       return 0;
+
+#elif HAVE_GETPWNAM_R_5
+       struct passwd *tmp;
+
+       return getpwnam_r (name, pwbuf, buf, buflen, &tmp);
+
+#elif HAVE_GETPWNAM_R_4
+
+       return getpwnam_r (name, pwbuf, buf, buflen);
+#endif
+
+       return 0;
+}
+
+
+#ifndef HAVE_GETGRNAM_R
+G_LOCK_DEFINE (getgrnam_lock);
+#endif
+
+static int
+secure_getgrnam (const char *name, struct group *grbuf, char *buf, size_t buflen)
+{
+#ifndef HAVE_GETGRNAM_R
+       size_t        gr_name_len   = 0;
+       size_t        gr_passwd_len = 0;
+       char         *ptr;
+       struct group *tmp;
+
+       G_LOCK(getgrnam_lock);
+
+       tmp = getgrnam (name);
+       if (tmp == NULL) 
+               return errno;
+
+       if (tmp->gr_name)   gr_name_len   = strlen(tmp->gr_name);
+       if (tmp->gr_passwd) gr_passwd_len = strlen(tmp->gr_passwd);
+
+       if ((gr_name_len + gr_passwd_len) > buflen)
+               return ERANGE;
+
+       memset (buf, 0, buflen);
+       ptr = buf;
+
+       grbuf->gr_gid = tmp->gr_gid;
+
+       if (tmp->gr_name) {
+               memcpy (ptr, tmp->gr_name, gr_name_len);
+               grbuf->gr_name = ptr;
+               ptr += gr_name_len + 1;
+       }
+
+       if (tmp->gr_passwd) {
+               memcpy (ptr, tmp->gr_passwd, gr_passwd_len);
+               grbuf->gr_passwd = ptr;
+               ptr += gr_passwd_len + 1;
+       }
+
+       // TODO: Duplicate char **tmp->gr_mem
+
+       G_UNLOCK(getgrnam_lock);
+       return 0;
+
+#elif HAVE_GETGRNAM_R_5
+       struct group *tmp;
+
+       return getgrnam_r (name, grbuf, buf, buflen, &tmp);
+
+#elif HAVE_GETGRNAM_R_4
+
+       return getgrnam_r (name, grbuf, buf, buflen);
+#endif
+
+       return 0;
+}
+
+void
+get_access_info_acl (GnomeVFSFileInfo *file_info,
+                     const gchar      *full_name)
+{
+         GList *acls, *iter;
+         GnomeVFSACL *acl;
+
+         acls = gnome_vfs_acl_get_ace_list (file_info->acl);
+
+         for (iter = acls; iter; iter = iter->next) {
+               int            i, re;
+               const char    *id;
+               uid_t          uid;
+               gid_t          gid;
+               struct group  *group;
+               GnomeVFSACE   *ace;
+               int            sup_groups_num;
+               gid_t          sup_groups[NGROUPS_MAX];
+               struct passwd *passwd;
+               struct passwd  pwd;
+               struct group   grp;
+               char           buf[1024];
+
+               ace = iter->data;
+               
+               id = gnome_vfs_ace_get_id (ace);
+               if (id == NULL) continue;
+
+               /* User */
+               re = secure_getpwnam (id, &pwd, buf, 1024);
+               if (re == 0) {
+                       uid = passwd->pw_uid;
+               } else {
+                       errno = 0;
+                       uid = atoi (id);
+                       if (errno != 0) 
+                               continue;
+               } 
+
+               /* Group */
+               group = secure_getgrnam (id, &grp, buf, 1024);
+               if (group != NULL) {
+                       gid = group->gr_gid;
+               } else {
+                       errno = 0;
+                       gid = atoi (id);
+                       if (errno != 0) 
+                               continue;
+               }
+
+                /* Suplementary groups */
+                sup_groups_num = getgroups(NGROUPS_MAX, sup_groups);
+
+               if ((file_info->uid == uid) ||
+                    (file_info->gid == gid)) 
+                {
+                       if (gnome_vfs_ace_check_perm (ace,GNOME_VFS_ACL_READ))
+                               file_info->permissions |= GNOME_VFS_PERM_ACCESS_READABLE;
+                       if (gnome_vfs_ace_check_perm (ace,GNOME_VFS_ACL_WRITE))
+                               file_info->permissions |= GNOME_VFS_PERM_ACCESS_WRITABLE;
+                       if (gnome_vfs_ace_check_perm (ace,GNOME_VFS_ACL_EXECUTE))
+                               file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE;
+               } 
+               
+
+               for (i = 0; i < sup_groups_num; i++) {
+                       if (gid == sup_groups[i]) {
+                               if (gnome_vfs_ace_check_perm (ace,GNOME_VFS_ACL_READ))
+                                       file_info->permissions |= GNOME_VFS_PERM_ACCESS_READABLE;
+                               if (gnome_vfs_ace_check_perm (ace,GNOME_VFS_ACL_WRITE))
+                                       file_info->permissions |= GNOME_VFS_PERM_ACCESS_WRITABLE;
+                               if (gnome_vfs_ace_check_perm (ace,GNOME_VFS_ACL_EXECUTE))
+                                       file_info->permissions |= GNOME_VFS_PERM_ACCESS_EXECUTABLE;
+                       }
+               }
+       }
+
+       gnome_vfs_acl_free_ace_list (acls);     
+}
Index: modules/file-method-acl.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/file-method-acl.h,v
retrieving revision 1.2
diff -u -r1.2 file-method-acl.h
--- modules/file-method-acl.h	8 Jun 2006 13:30:56 -0000	1.2
+++ modules/file-method-acl.h	13 Dec 2006 13:51:49 -0000
@@ -43,7 +43,9 @@
 			     const GnomeVFSFileInfo *info,
                              GnomeVFSContext         *context);
 
-G_END_DECLS
+void           get_access_info_acl (GnomeVFSFileInfo *info,
+				    const gchar      *path);
 
+G_END_DECLS
 
 #endif /*FILEACL_H*/
Index: modules/file-method.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/file-method.c,v
retrieving revision 1.162
diff -u -r1.162 file-method.c
--- modules/file-method.c	17 Oct 2006 09:54:59 -0000	1.162
+++ modules/file-method.c	13 Dec 2006 13:51:49 -0000
@@ -858,6 +858,10 @@
 			}
 		}
 	}
+
+	if (file_info->acl) {
+		get_access_info_acl (file_info, full_name);
+	}
 #endif
 
      file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACCESS;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]