/*1* Copyright 2016 Chris Torek <[email protected]>2* All rights reserved3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted providing that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED15* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY17* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,21* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING22* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE23* POSSIBILITY OF SUCH DAMAGE.24*/2526/*27* General ACL support for 9P2000.L.28*29* We mostly use Linux's xattr name space and nfs4 ACL bits, as30* these are the most general forms available.31*32* Linux requests attributes named33*34* "system.posix_acl_default"35* "system.posix_acl_access"36*37* to get POSIX style ACLs, and:38*39* "system.nfs4_acl"40*41* to get NFSv4 style ACLs. The v9fs client does not explicitly42* ask for the latter, but if you use the Ubuntu nfs4-acl-tools43* package, it should be able to read and write these.44*45* For the record, the Linux kernel source code also shows:46*47* - Lustre uses "trusted.*", with "*" matching "lov", "lma",48* "lmv", "dmv", "link", "fid", "version", "som", "hsm", and49* "lfsck_namespace".50*51* - ceph has a name tree of the form "ceph.<type>.<name>" with52* <type,name> pairs like <"dir","entries">, <"dir","files>,53* <"file","layout">, and so on.54*55* - ext4 uses the POSIX names, plus some special ext4-specific56* goop that might not get externalized.57*58* - NFS uses both the POSIX names and the NFSv4 ACLs. However,59* what it mainly does is have nfsd generate fake NFSv4 ACLs60* from POSIX ACLs. If you run an NFS client, the client61* relies on the server actually implementing the ACLs, and62* lets nfs4-acl-tools read and write the system.nfs4_acl xattr63* data. If you run an NFS server off, e.g., an ext4 file system,64* the server looks for the system.nfs4_acl xattr, serves that65* out if found, and otherwise just generates the fakes.66*67* - "security.*" and "selinux.*" are reserved.68*69* - "security.capability" is the name for capabilities.70*71* - sockets use "system.sockprotoname".72*/7374#if defined(__APPLE__)75#define HAVE_POSIX_ACLS76#define HAVE_DARWIN_ACLS77#endif7879#if defined(__FreeBSD__)80#define HAVE_POSIX_ACLS81#define HAVE_FREEBSD_ACLS82#endif8384#include <sys/types.h>85#include <sys/acl.h> /* XXX assumes existence of sys/acl.h */8687/*88* An ACL consists of a number of ACEs that grant some kind of89* "allow" or "deny" to some specific entity.90*91* The number of ACEs is potentially unlimited, although in practice92* they tend not to be that long.93*94* It's the responsibility of the back-end to supply the ACL95* for each test. However, the ACL may be in some sort of96* system-specific form. It's the responsibility of some97* (system-specific) code to translate it to *this* form, after98* which the backend may use l9p_acl_check_access() to get99* access granted or denied (and, eventually, audits and alarms100* recorded and raises, although that's yet to be designed).101*102* The reason for all this faffing-about with formats is so that103* we can *report* the ACLs using Linux 9p style xattrs.104*/105106struct l9p_acl;107struct l9p_fid;108109void l9p_acl_free(struct l9p_acl *);110111/*112* An ACL is made up of ACEs.113*114* Each ACE has:115*116* - a type: allow, deny, audit, alarm117* - a set of flags118* - permissions bits: a "mask"119* - an optional, nominally-variable-length identity120*121* The last part is especially tricky and currently has limited122* support here: it's always a 16 byte field on Darwin, and just123* a uint32_t on BSD (should be larger, really). Linux supports124* very large, actually-variable-size values; we'll deal with125* this later, maybe.126*127* We will define the mask first, below, since these are also the bits128* passed in for the accmask argument to l9p_acl_check_access().129*/130131/*132* ACL entry mask, and accmask argument flags.133*134* NB: not every bit is implemented, but they are all here because135* they are all defined as part of an NFSv4 ACL entry, which is136* more or less a superset of a POSIX ACL entry. This means you137* can put a complete NFSv4 ACL in and we can reproduce it.138*139* Note that the LIST_DIRECTORY, ADD_FILE, and ADD_SUBDIRECTORY bits140* apply only to a directory, while the READ_DATA, WRITE_DATA, and141* APPEND_DATA bits apply only to a file. See aca_parent/aca_child142* below.143*/144#define L9P_ACE_READ_DATA 0x00001145#define L9P_ACE_LIST_DIRECTORY 0x00001 /* same as READ_DATA */146#define L9P_ACE_WRITE_DATA 0x00002147#define L9P_ACE_ADD_FILE 0x00002 /* same as WRITE_DATA */148#define L9P_ACE_APPEND_DATA 0x00004149#define L9P_ACE_ADD_SUBDIRECTORY 0x00004 /* same as APPEND_DATA */150#define L9P_ACE_READ_NAMED_ATTRS 0x00008151#define L9P_ACE_WRITE_NAMED_ATTRS 0x00010152#define L9P_ACE_EXECUTE 0x00020153#define L9P_ACE_DELETE_CHILD 0x00040154#define L9P_ACE_READ_ATTRIBUTES 0x00080155#define L9P_ACE_WRITE_ATTRIBUTES 0x00100156#define L9P_ACE_WRITE_RETENTION 0x00200 /* not used here */157#define L9P_ACE_WRITE_RETENTION_HOLD 0x00400 /* not used here */158/* 0x00800 unused? */159#define L9P_ACE_DELETE 0x01000160#define L9P_ACE_READ_ACL 0x02000161#define L9P_ACE_WRITE_ACL 0x04000162#define L9P_ACE_WRITE_OWNER 0x08000163#define L9P_ACE_SYNCHRONIZE 0x10000 /* not used here */164165/*166* This is not an ACE bit, but is used with the access checking167* below. It represents a request to unlink (delete child /168* delete) an entity, and is equivalent to asking for *either*169* (not both) permission.170*/171#define L9P_ACOP_UNLINK (L9P_ACE_DELETE_CHILD | L9P_ACE_DELETE)172173/*174* Access checking takes a lot of arguments, so they are175* collected into a "struct" here.176*177* The aca_parent and aca_pstat fields may/must be NULL if the178* operation itself does not involve "directory" permissions.179* The aca_child and aca_cstat fields may/must be NULL if the180* operation does not involve anything *but* a directory. This181* is how we decide whether you're interested in L9P_ACE_READ_DATA182* vs L9P_ACE_LIST_DIRECTORY, for instance.183*184* Note that it's OK for both parent and child to be directories185* (as is the case when we're adding or deleting a subdirectory).186*/187struct l9p_acl_check_args {188uid_t aca_uid; /* the uid that is requesting access */189gid_t aca_gid; /* the gid that is requesting access */190gid_t *aca_groups; /* the additional group-set, if any */191size_t aca_ngroups; /* number of groups in group-set */192struct l9p_acl *aca_parent; /* ACLs associated with parent/dir */193struct stat *aca_pstat; /* stat data for parent/dir */194struct l9p_acl *aca_child; /* ACLs associated with file */195struct stat *aca_cstat; /* stat data for file */196int aca_aclmode; /* mode checking bits, see below */197bool aca_superuser; /* alway allow uid==0 in STAT_MODE */198};199200/*201* Access checking mode bits in aca_checkmode. If you enable202* ACLs, they are used first, optionally with ZFS style ACLs.203* This means that even if aca_superuser is set, if an ACL denies204* permission to uid 0, permission is really denied.205*206* NFS style ACLs run before POSIX style ACLs (though POSIX207* ACLs aren't done yet anyway).208*209* N.B.: you probably want L9P_ACL_ZFS, especially when operating210* with a ZFS file system on FreeBSD.211*/212#define L9P_ACM_NFS_ACL 0x0001 /* enable NFS ACL checking */213#define L9P_ACM_ZFS_ACL 0x0002 /* use ZFS ACL unlink semantics */214#define L9P_ACM_POSIX_ACL 0x0004 /* enable POSIX ACL checking (notyet) */215#define L9P_ACM_STAT_MODE 0x0008 /* enable st_mode bits */216217/*218* Requests to access some file or directory must provide:219*220* - An operation. This should usually be just one bit from the221* L9P_ACE_* bit-sets above, or our special L9P_ACOP_UNLINK.222* For a few file-open operations it may be multiple bits,223* e.g., both read and write data.224* - The identity of the accessor: uid + gid + gid-set.225* - The type of access desired: this may be multiple bits.226* - The parent directory, if applicable.227* - The child file/dir being accessed, if applicable.228* - stat data for parent and/or child, if applicable.229*230* The ACLs and/or stat data of the parent and/or child get used231* here, so the caller must provide them. We should have a way to232* cache these on fids, but not yet. The parent and child233* arguments are a bit tricky; see the code in genacl.c.234*/235int l9p_acl_check_access(int32_t op, struct l9p_acl_check_args *args);236237/*238* When falling back to POSIX ACL or Unix-style permissions239* testing, it's nice to collapse the above detailed permissions240* into simple read/write/execute bits (value 0..7). We provide241* a small utility function that does this.242*/243int l9p_ace_mask_to_rwx(int32_t);244245/*246* The rest of the data in an ACE.247*/248249/* type in ace_type */250#define L9P_ACET_ACCESS_ALLOWED 0251#define L9P_ACET_ACCESS_DENIED 1252#define L9P_ACET_SYSTEM_AUDIT 2253#define L9P_ACET_SYSTEM_ALARM 3254255/* flags in ace_flags */256#define L9P_ACEF_FILE_INHERIT_ACE 0x001257#define L9P_ACEF_DIRECTORY_INHERIT_ACE 0x002258#define L9P_ACEF_NO_PROPAGATE_INHERIT_ACE 0x004259#define L9P_ACEF_INHERIT_ONLY_ACE 0x008260#define L9P_ACEF_SUCCESSFUL_ACCESS_ACE_FLAG 0x010261#define L9P_ACEF_FAILED_ACCESS_ACE_FLAG 0x020262#define L9P_ACEF_IDENTIFIER_GROUP 0x040263#define L9P_ACEF_OWNER 0x080264#define L9P_ACEF_GROUP 0x100265#define L9P_ACEF_EVERYONE 0x200266267#if defined(__APPLE__)268# define L9P_ACE_IDSIZE 16 /* but, how do we map Darwin uuid? */269#else270# define L9P_ACE_IDSIZE 4271#endif272273struct l9p_ace {274uint16_t ace_type; /* ACL entry type */275uint16_t ace_flags; /* ACL entry flags */276uint32_t ace_mask; /* ACL entry mask */277uint32_t ace_idsize; /* length of ace_idbytes */278unsigned char ace_idbytes[L9P_ACE_IDSIZE];279};280281#define L9P_ACLTYPE_NFSv4 1 /* currently the only valid type */282struct l9p_acl {283uint32_t acl_acetype; /* reserved for future expansion */284uint32_t acl_nace; /* number of occupied ACEs */285uint32_t acl_aceasize; /* actual size of ACE array */286struct l9p_ace acl_aces[]; /* variable length ACE array */287};288289/*290* These are the system-specific converters.291*292* Right now the backend needs to just find BSD NFSv4 ACLs293* and convert them before each operation that needs to be294* tested.295*/296#if defined(HAVE_DARWIN_ACLS)297struct l9p_acl *l9p_darwin_nfsv4acl_to_acl(acl_t acl);298#endif299300#if defined(HAVE_FREEBSD_ACLS)301struct l9p_acl *l9p_freebsd_nfsv4acl_to_acl(acl_t acl);302#endif303304#if defined(HAVE_POSIX_ACLS) && 0 /* not yet */305struct l9p_acl *l9p_posix_acl_to_acl(acl_t acl);306#endif307308309