summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO17
-rw-r--r--configure.ac9
-rw-r--r--daemon/Makefile.am2
-rw-r--r--daemon/acl.c175
-rw-r--r--generator/actions.ml82
-rw-r--r--po/POTFILES1
-rw-r--r--src/MAX_PROC_NR2
7 files changed, 274 insertions, 14 deletions
diff --git a/TODO b/TODO
index 4ba003a7..d0939bcf 100644
--- a/TODO
+++ b/TODO
@@ -588,20 +588,11 @@ is very poorly designed and essentially impossible for us to use:
particularly if we also want to maintain backwards compatibility with
Ruby 1.8, and/or maintain volatile VALUEs on the stack.
-ACLs and capabilities
----------------------
-
-We need to model both filesystem ACLs and filesystem capabilities
-through the API. This is particularly important in order to be able
-to implement SCAP.
-
-ACLs can be read and written using the acl(5) library and the
-functions like acl_set_file(3) etc.
+Filesystem capabilities
+-----------------------
-Setting the ACL on a file sets the extended attribute
-'system.posix_acl_access' to a binary blob. The kernel has a whole
-bunch of complex code that seems to interpret these
-(linux/fs/posix_acl.c).
+We need to model filesystem capabilities through the API. This is
+particularly important in order to be able to implement SCAP.
Filesystem capabilities can be read and written using the libcap(3)
library and functions like cap_get_file, cap_set_file.
diff --git a/configure.ac b/configure.ac
index 1869430d..6f930f5b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -692,6 +692,15 @@ AC_CHECK_LIB([magic],[magic_file],
],
[AC_MSG_WARN([libmagic not found, some core features will be disabled])])
+dnl POSIX acl library (highly recommended)
+AC_CHECK_LIB([acl],[acl_from_text],
+ [AC_CHECK_HEADER([sys/acl.h],
+ [AC_SUBST([ACL_LIBS], [-lacl])
+ AC_DEFINE([HAVE_ACL], [1], [Define to 1 if the POSIX acl library is available.])
+ ], [])
+ ],
+ [AC_MSG_WARN([POSIX acl library not found])])
+
dnl libvirt (highly recommended)
AC_ARG_WITH([libvirt],
[AS_HELP_STRING([--without-libvirt],
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index a57e6f4f..2f70c8ee 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -88,6 +88,7 @@ endif
guestfsd_SOURCES = \
9p.c \
+ acl.c \
actions.h \
available.c \
augeas.c \
@@ -181,6 +182,7 @@ guestfsd_SOURCES = \
guestfsd_LDADD = \
liberrnostring.a \
libprotocol.a \
+ $(ACL_LIBS) \
$(SELINUX_LIB) \
$(AUGEAS_LIBS) \
$(HIVEX_LIBS) \
diff --git a/daemon/acl.c b/daemon/acl.c
new file mode 100644
index 00000000..710d3857
--- /dev/null
+++ b/daemon/acl.c
@@ -0,0 +1,175 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "guestfs_protocol.h"
+#include "daemon.h"
+#include "actions.h"
+#include "optgroups.h"
+
+#if defined(HAVE_ACL)
+
+#include <sys/types.h>
+#include <sys/acl.h>
+
+int
+optgroup_acl_available (void)
+{
+ return 1;
+}
+
+char *
+do_acl_get_file (const char *path, const char *acltype)
+{
+ acl_type_t t;
+ acl_t acl;
+ char *r, *ret;
+
+ if (STREQ (acltype, "access"))
+ t = ACL_TYPE_ACCESS;
+ else if (STREQ (acltype, "default"))
+ t = ACL_TYPE_DEFAULT;
+ else {
+ reply_with_error ("invalid acltype parameter: %s", acltype);
+ return NULL;
+ }
+
+ CHROOT_IN;
+ acl = acl_get_file (path, t);
+ CHROOT_OUT;
+
+ if (acl == NULL) {
+ reply_with_perror ("%s", path);
+ return NULL;
+ }
+
+ r = acl_to_text (acl, NULL);
+ if (r == NULL) {
+ reply_with_perror ("acl_to_text");
+ acl_free (acl);
+ return NULL;
+ }
+
+ acl_free (acl);
+
+ /* 'r' is not an ordinary pointer that can be freed with free(3)!
+ * In the current implementation of libacl, if you try to do that it
+ * will segfault. We have to duplicate this into an ordinary
+ * buffer, then call acl_free (r).
+ */
+ ret = strdup (r);
+ if (ret == NULL) {
+ reply_with_perror ("strdup");
+ acl_free (r);
+ return NULL;
+ }
+ acl_free (r);
+
+ return ret; /* caller frees */
+}
+
+int
+do_acl_set_file (const char *path, const char *acltype, const char *aclstr)
+{
+ acl_type_t t;
+ acl_t acl;
+ int r;
+
+ if (STREQ (acltype, "access"))
+ t = ACL_TYPE_ACCESS;
+ else if (STREQ (acltype, "default"))
+ t = ACL_TYPE_DEFAULT;
+ else {
+ reply_with_error ("invalid acltype parameter: %s", acltype);
+ return -1;
+ }
+
+ acl = acl_from_text (aclstr);
+ if (acl == NULL) {
+ reply_with_perror ("could not parse acl string: %s: acl_from_text", aclstr);
+ return -1;
+ }
+
+ CHROOT_IN;
+ r = acl_set_file (path, t, acl);
+ CHROOT_OUT;
+
+ if (r == -1) {
+ reply_with_perror ("%s", path);
+ acl_free (acl);
+ return -1;
+ }
+
+ acl_free (acl);
+
+ return 0;
+}
+
+int
+do_acl_delete_def_file (const char *dir)
+{
+ int r;
+
+ CHROOT_IN;
+ r = acl_delete_def_file (dir);
+ CHROOT_OUT;
+
+ if (r == -1) {
+ reply_with_perror ("%s", dir);
+ return -1;
+ }
+
+ return 0;
+}
+
+#else /* no acl library */
+
+/* Note that the wrapper code (daemon/stubs.c) ensures that the
+ * functions below are never called because
+ * optgroup_acl_available returns false.
+ */
+int
+optgroup_acl_available (void)
+{
+ return 0;
+}
+
+char *
+do_acl_get_file (const char *path, const char *acltype)
+{
+ abort ();
+}
+
+int
+do_acl_set_file (const char *path, const char *acltype, const char *acl)
+{
+ abort ();
+}
+
+int
+do_acl_delete_def_file (const char *dir)
+{
+ abort ();
+}
+
+#endif /* no acl library */
diff --git a/generator/actions.ml b/generator/actions.ml
index 020dd947..0a222273 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -10408,6 +10408,88 @@ Make the C<lost+found> directory, normally in the root directory
of an ext2/3/4 filesystem. C<mountpoint> is the directory under
which we try to create the C<lost+found> directory." };
+ { defaults with
+ name = "acl_get_file";
+ style = RString "acl", [Pathname "path"; String "acltype"], [];
+ proc_nr = Some 375;
+ optional = Some "acl";
+ tests = []; (* tested by acl_set_file *)
+ shortdesc = "get the POSIX ACL attached to a file";
+ longdesc = "\
+This function returns the POSIX Access Control List (ACL) attached
+to C<path>. The ACL is returned in \"long text form\" (see L<acl(5)>).
+
+The C<acltype> parameter may be:
+
+=over 4
+
+=item C<access>
+
+Return the ordinary (access) ACL for any file, directory or
+other filesystem object.
+
+=item C<default>
+
+Return the default ACL. Normally this only makes sense if
+C<path> is a directory.
+
+=back" };
+
+ { defaults with
+ name = "acl_set_file";
+ style = RErr, [Pathname "path"; String "acltype"; String "acl"], [];
+ proc_nr = Some 376;
+ optional = Some "acl";
+ tests = [
+ InitScratchFS, Always, TestRun (
+ [["touch"; "/acl_set_file_0"];
+ ["acl_set_file"; "/acl_set_file_0"; "access"; "user::r-x,group::r-x,other::r-x"];
+ ["acl_get_file"; "/acl_set_file_0"; "access"]]);
+ ];
+ shortdesc = "set the POSIX ACL attached to a file";
+ longdesc = "\
+This function sets the POSIX Access Control List (ACL) attached
+to C<path>. The C<acl> parameter is the new ACL in either
+\"long text form\" or \"short text form\" (see L<acl(5)>).
+
+The C<acltype> parameter may be:
+
+=over 4
+
+=item C<access>
+
+Set the ordinary (access) ACL for any file, directory or
+other filesystem object.
+
+=item C<default>
+
+Set the default ACL. Normally this only makes sense if
+C<path> is a directory.
+
+=back" };
+
+ { defaults with
+ name = "acl_delete_def_file";
+ style = RErr, [Pathname "dir"], [];
+ proc_nr = Some 377;
+ optional = Some "acl";
+ tests = [
+ (* Documentation for libacl says this should fail, but it doesn't.
+ * Therefore disable this test.
+ *)
+ InitScratchFS, Disabled, TestLastFail (
+ [["touch"; "/acl_delete_def_file_0"];
+ ["acl_delete_def_file"; "/acl_delete_def_file_0"]]);
+ InitScratchFS, Always, TestRun (
+ [["mkdir"; "/acl_delete_def_file_1"];
+ ["acl_set_file"; "/acl_delete_def_file_1"; "default"; "user::r-x,group::r-x,other::r-x"];
+ ["acl_delete_def_file"; "/acl_delete_def_file_1"]]);
+ ];
+ shortdesc = "delete the default POSIX ACL of a directory";
+ longdesc = "\
+This function deletes the default POSIX Access Control List (ACL)
+attached to directory C<dir>." };
+
]
(* Non-API meta-commands available only in guestfish.
diff --git a/po/POTFILES b/po/POTFILES
index ece787a8..7e289eb9 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -4,6 +4,7 @@ cat/virt-cat.c
cat/virt-filesystems.c
cat/virt-ls.c
daemon/9p.c
+daemon/acl.c
daemon/augeas.c
daemon/available.c
daemon/base64.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 38a45c3e..66a899ac 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-374
+377