changes from acl-2.2.29-CITI_NFS4_ALL-2: * Fix for ACL mapping on directories (thanks to Simon Vallet) --- Makefile | 4 debian/changelog | 6 debian/control | 2 exports | 59 +++ include/builddefs.in | 2 include/libacl_nfs4.h | 144 ++++++++ include/nfs4.h | 397 ++++++++++++++++++++++++ libacl/Makefile | 34 +- libacl/__posix_acl_from_nfs4_xattr.c | 60 +++ libacl/acl_extended_file.c | 4 libacl/acl_get_fd.c | 50 ++- libacl/acl_get_file.c | 46 ++ libacl/acl_n4tp_ace_count.c | 57 +++ libacl/acl_n4tp_ace_trans.c | 76 ++++ libacl/acl_n4tp_acl_trans.c | 178 +++++++++++ libacl/acl_n4tp_get_whotype.c | 73 ++++ libacl/acl_n4tp_set_mode.c | 98 ++++++ libacl/acl_n4tp_set_who.c | 89 +++++ libacl/acl_nfs4_add_ace.c | 83 +++++ libacl/acl_nfs4_add_pair.c | 60 +++ libacl/acl_nfs4_copy_acl.c | 88 +++++ libacl/acl_nfs4_entries.c | 48 ++ libacl/acl_nfs4_free.c | 61 +++ libacl/acl_nfs4_get_accessmask.c | 46 ++ libacl/acl_nfs4_get_flags.c | 46 ++ libacl/acl_nfs4_get_type.c | 47 ++ libacl/acl_nfs4_get_who.c | 103 ++++++ libacl/acl_nfs4_get_whotype.c | 60 +++ libacl/acl_nfs4_new.c | 58 +++ libacl/acl_nfs4_print.c | 204 ++++++++++++ libacl/acl_nfs4_print_ace.c | 202 ++++++++++++ libacl/acl_nfs4_print_fd.c | 210 ++++++++++++ libacl/acl_nfs4_remove_ace.c | 50 +++ libacl/acl_nfs4_set_who.c | 92 +++++ libacl/acl_nfs4_string2ace.c | 297 ++++++++++++++++++ libacl/acl_nfs4_utils.c | 566 +++++++++++++++++++++++++++++++++++ libacl/acl_nfs4_xattr_load.c | 191 +++++++++++ libacl/acl_nfs4_xattr_pack.c | 163 ++++++++++ libacl/acl_nfs4_xattr_size.c | 91 +++++ libacl/acl_ptn4_acl_trans.c | 505 +++++++++++++++++++++++++++++++ libacl/acl_ptn4_get_mask.c | 81 +++++ libacl/acl_set_fd.c | 33 ++ libacl/acl_set_file.c | 67 ++++ libacl/libacl_nfs4.h | 143 ++++++++ nfs4_getfacl/Makefile | 51 +++ nfs4_getfacl/nfs4_getfacl.c | 198 ++++++++++++ nfs4_setfacl/Makefile | 50 +++ nfs4_setfacl/nfs4_setfacl.c | 313 +++++++++++++++++++ 48 files changed, 5561 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 06e31a6..4e11daf 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,8 @@ LSRCFILES = configure configure.in acloc LDIRT = config.log .dep config.status config.cache confdefs.h conftest* \ Logs/* built .census install.* install-dev.* install-lib.* *.gz -SUBDIRS = include libmisc libacl getfacl setfacl chacl m4 man doc po \ - test examples build debian +SUBDIRS = include libmisc libacl getfacl setfacl nfs4_getfacl nfs4_setfacl \ + chacl m4 man doc po test examples build debian default: $(CONFIGURE) ifeq ($(HAVE_BUILDDEFS), no) diff --git a/debian/changelog b/debian/changelog index 66e16b7..c431d66 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +acl (2.2.37.nfsv4-1) unstable; urgency=low + + * Add support for NFSv4 ACLs + + -- J. Bruce Fields Tue, 9 May 2006 11:52:32 -0400 + acl (2.2.37-1) unstable; urgency=low * New upstream release diff --git a/debian/control b/debian/control index 5ff00bc..1d0f356 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: acl Section: utils Priority: optional Maintainer: Nathan Scott -Build-Depends: autoconf, debhelper (>= 5), gettext, libtool, libattr1-dev (>= 2.4.4) +Build-Depends: autoconf, debhelper (>= 5), gettext, libtool, libattr1-dev (>= 2.4.4), libnfsidmap-dev Standards-Version: 3.5.9 Package: acl diff --git a/exports b/exports index 59c1311..104aeaa 100644 --- a/exports +++ b/exports @@ -67,3 +67,62 @@ ACL_1.1 { perm_copy_fd; perm_copy_file; } ACL_1.0; + +ACL_1.2 { + global: + acl_nfs4_add_ace; + acl_nfs4_add_pair; + acl_nfs4_free; + acl_nfs4_new; + acl_nfs4_set_dir; + acl_nfs4_set_who; + acl_nfs4_copy_acl; + acl_nfs4_xattr_load; + acl_nfs4_xattr_pack; + acl_nfs4_xattr_size; + acl_nfs4_remove_ace; + + acl_n4tp_acl_trans; + acl_n4tp_set_mode; + acl_n4tp_ace_count; + acl_n4tp_ace_trans; + acl_n4tp_set_who; + acl_n4tp_get_whotype; + + acl_ptn4_get_mask; + acl_ptn4_acl_trans; + + acl_nfs4_get_next_ace; + acl_nfs4_get_first_ace; + acl_nfs4_get_dir; + acl_nfs4_get_whotype; + acl_nfs4_get_who; + acl_nfs4_get_flags; + acl_nfs4_entries; + acl_nfs4_get_accessmask; + acl_nfs4_get_type; + + acl_nfs4_print; + acl_nfs4_print_ace; + acl_nfs4_print_fd; + + local: + __posix_acl_from_nfs4_xattr; + complementary_ace_pair; + same_who; + nfs4_get_gid_from_who; + nfs4_get_uid_from_who; + nfs4_get_who_from_uid; + nfs4_get_who_from_gid; + __nfs4_get_local_uid_from_who; + __nfs4_get_foreign_uid_from_who; + __nfs4_get_local_gid_from_who; + __nfs4_get_foreign_gid_from_who; + is_who_local; + + user_obj_from_v4; + users_from_v4; + group_obj_and_groups_from_v4; + mask_from_v4; + other_from_v4; +} ACL_1.1; diff --git a/include/builddefs.in b/include/builddefs.in index 65319c8..9aab6cf 100644 --- a/include/builddefs.in +++ b/include/builddefs.in @@ -65,7 +65,7 @@ endif GCFLAGS = $(OPTIMIZER) $(DEBUG) -funsigned-char -fno-strict-aliasing -Wall \ -DVERSION=\"$(PKG_VERSION)\" -DLOCALEDIR=\"$(PKG_LOCALE_DIR)\" \ - -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include + -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include -DUSE_NFSV4_TRANS # Global, Platform, Local CFLAGS CFLAGS += $(GCFLAGS) $(PCFLAGS) $(LCFLAGS) diff --git a/include/libacl_nfs4.h b/include/libacl_nfs4.h new file mode 100644 index 0000000..3888a27 --- /dev/null +++ b/include/libacl_nfs4.h @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* mode bit translations: */ +#define NFS4_READ_MODE NFS4_ACE_READ_DATA +#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA \ + | NFS4_ACE_APPEND_DATA | NFS4_ACE_DELETE_CHILD) +#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE +#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | \ + NFS4_ACE_SYNCHRONIZE) +#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL) + +/* flags used to simulate posix default ACLs */ +#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ + | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE) + +#define NFS4_ACE_MASK_IGNORE (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \ + | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS) +/* XXX not sure about the following. Note that e.g. DELETE_CHILD is wrong in + * general (should only be ignored on files). */ +#define MASK_EQUAL(mask1, mask2) \ + (((mask1) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \ + ~NFS4_ACE_DELETE_CHILD) \ + == ((mask2) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \ + ~NFS4_ACE_DELETE_CHILD)) + +/* Maximum length of the ace->who attribute */ +#define NFS4_ACL_WHO_LENGTH_MAX 2048 +#define NFS4_ACL_WHO_BUFFER_LEN_GUESS 255 + +/* NFS4 acl xattr name */ +#define ACL_NFS4_XATTR "system.nfs4_acl" + +/* Macro for finding empty tailqs */ +#define TAILQ_IS_EMPTY(head) (head.tqh_first == NULL) + +/* Flags to pass certain properties around */ +#define NFS4_ACL_NOFLAGS 0x00 +#define NFS4_ACL_ISFILE 0x00 +#define NFS4_ACL_ISDIR 0x01 +#define NFS4_ACL_OWNER 0x02 +#define NFS4_ACL_REQUEST_DEFAULT 0x04 +#define NFS4_ACL_RAW 0x01 + +#define NFS4_XDR_MOD 4 + +typedef u_int32_t u32; + +enum { ACL_NFS4_NOT_USED = 0, + ACL_NFS4_USED +}; + +struct ace_container { + struct nfs4_ace *ace; + TAILQ_ENTRY(ace_container) l_ace; +}; + +TAILQ_HEAD(ace_container_list_head, ace_container); + +/**** Public functions ****/ + +/** Manipulation functions **/ +extern int acl_nfs4_add_ace(struct nfs4_acl *, u32, u32, u32, int, char*); +extern int acl_nfs4_add_pair(struct nfs4_acl *, int, u32, int, char*); +extern void acl_nfs4_free(struct nfs4_acl *); +extern struct nfs4_acl *acl_nfs4_new(u32); +extern int acl_nfs4_set_who(struct nfs4_ace*, int, char*); +extern struct nfs4_acl *acl_nfs4_copy_acl(struct nfs4_acl *); +extern struct nfs4_acl *acl_nfs4_xattr_load(char *, int, u32); +extern int acl_nfs4_xattr_pack(struct nfs4_acl *, char**); +extern int acl_nfs4_xattr_size(struct nfs4_acl *); +extern int acl_nfs4_remove_ace(struct nfs4_acl * acl, struct nfs4_ace * ace); + +/** Conversion functions **/ + +/* nfs4 -> posix */ +extern acl_t acl_n4tp_acl_trans(struct nfs4_acl *, acl_type_t); +extern int acl_n4tp_set_mode(acl_entry_t pace, u32 nfs4_access_mask, + int iflags); +extern int acl_n4tp_ace_count(struct nfs4_acl *n4acl); +extern int acl_n4tp_ace_trans(struct nfs4_ace *ace, acl_t *pacl, + acl_tag_t tag, int iflags); +extern int acl_n4tp_set_who(acl_entry_t ace, char* who, + acl_tag_t who_type); +extern acl_tag_t acl_n4tp_get_whotype(struct nfs4_ace *ace); + +/* posix -> nfs4 */ +extern int acl_ptn4_get_mask(u32* mask, acl_permset_t perms, + int iflags); +extern struct nfs4_acl *acl_ptn4_acl_trans(acl_t, acl_type_t, u32, char*); +extern int acl_nfs4_string2ace(char *ace_buf, struct nfs4_acl **nacl_p); + + +/** Access Functions **/ +extern inline struct nfs4_ace * + acl_nfs4_get_next_ace(struct nfs4_ace **); +extern inline struct nfs4_ace * + acl_nfs4_get_first_ace(struct nfs4_acl *); +extern inline int acl_nfs4_get_whotype(char*); +extern int acl_nfs4_get_who(struct nfs4_ace*, int*, char**); +extern inline int acl_nfs4_get_flags(struct nfs4_ace *, u32 *); +extern inline int acl_nfs4_entries(struct nfs4_acl *); +extern inline int acl_nfs4_get_accessmask(struct nfs4_ace * ace, u32 * mask); +extern int acl_nfs4_get_type(struct nfs4_ace * ace, u32 * type); + +/** Display Functions **/ +extern void acl_nfs4_print(struct nfs4_acl * acl); +extern int acl_nfs4_print_ace(struct nfs4_ace * ace, u32 is_dir); +extern int acl_nfs4_print_fd(struct nfs4_acl *acl, FILE * fd); + +/**** Private(?) functions ****/ +acl_t __posix_acl_from_nfs4_xattr(char*, int, acl_type_t, u32); +int complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny); +int same_who(struct nfs4_ace *a, struct nfs4_ace *b); + +/* These will change */ +int nfs4_get_gid_from_who(gid_t* gid, const char * who); +int nfs4_get_uid_from_who(uid_t* uid, const char * who); +char * nfs4_get_who_from_uid(uid_t); +char * nfs4_get_who_from_gid(gid_t); +int __nfs4_get_local_uid_from_who(uid_t* uid, const char * who); +int __nfs4_get_foreign_uid_from_who(uid_t* uid, const char * who); +int __nfs4_get_local_gid_from_who(gid_t* gid, const char * who); +int __nfs4_get_foreign_gid_from_who(gid_t* gid, const char * who); +int is_who_local(const char * who); +/* End change */ + +int user_obj_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace **n4ace, + acl_t *pacl, int iflags); +int users_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + struct nfs4_ace **mask_ace, acl_t *pacl, int iflags); +int group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, + struct nfs4_ace ** n4ace_p, struct nfs4_ace **mask_ace, acl_t *pacl, int iflags); +int mask_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + struct nfs4_ace **mask_ace, acl_t *pacl, int iflags); +int other_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + acl_t *pacl, int iflags); diff --git a/include/nfs4.h b/include/nfs4.h new file mode 100644 index 0000000..43a6418 --- /dev/null +++ b/include/nfs4.h @@ -0,0 +1,397 @@ +/* + * NFSv4 protocol definitions. + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Kendrick Smith + * Andy Adamson + */ + +#include +#include + +#ifndef _LINUX_NFS4_H +#define _LINUX_NFS4_H + +#define NFS4_VERIFIER_SIZE 8 +#define NFS4_FHSIZE 128 +#define NFS4_MAXNAMLEN NAME_MAX + +#define NFS4_ACCESS_READ 0x0001 +#define NFS4_ACCESS_LOOKUP 0x0002 +#define NFS4_ACCESS_MODIFY 0x0004 +#define NFS4_ACCESS_EXTEND 0x0008 +#define NFS4_ACCESS_DELETE 0x0010 +#define NFS4_ACCESS_EXECUTE 0x0020 + +#define NFS4_FH_PERISTENT 0x0000 +#define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001 +#define NFS4_FH_VOLATILE_ANY 0x0002 +#define NFS4_FH_VOL_MIGRATION 0x0004 +#define NFS4_FH_VOL_RENAME 0x0008 + +#define NFS4_OPEN_RESULT_CONFIRM 0x0002 + +#define NFS4_SHARE_ACCESS_READ 0x0001 +#define NFS4_SHARE_ACCESS_WRITE 0x0002 +#define NFS4_SHARE_ACCESS_BOTH 0x0003 +#define NFS4_SHARE_DENY_READ 0x0001 +#define NFS4_SHARE_DENY_WRITE 0x0002 +#define NFS4_SHARE_DENY_BOTH 0x0003 + +#define NFS4_SET_TO_SERVER_TIME 0 +#define NFS4_SET_TO_CLIENT_TIME 1 + +#define NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE 0 +#define NFS4_ACE_ACCESS_DENIED_ACE_TYPE 1 +#define NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE 2 +#define NFS4_ACE_SYSTEM_ALARM_ACE_TYPE 3 + +#define ACL4_SUPPORT_ALLOW_ACL 0x01 +#define ACL4_SUPPORT_DENY_ACL 0x02 +#define ACL4_SUPPORT_AUDIT_ACL 0x04 +#define ACL4_SUPPORT_ALARM_ACL 0x08 + +#define NFS4_ACE_FILE_INHERIT_ACE 0x00000001 +#define NFS4_ACE_DIRECTORY_INHERIT_ACE 0x00000002 +#define NFS4_ACE_NO_PROPAGATE_INHERIT_ACE 0x00000004 +#define NFS4_ACE_INHERIT_ONLY_ACE 0x00000008 +#define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010 +#define NFS4_ACE_FAILED_ACCESS_ACE_FLAG 0x00000020 +#define NFS4_ACE_IDENTIFIER_GROUP 0x00000040 +#define NFS4_ACE_OWNER 0x00000080 +#define NFS4_ACE_GROUP 0x00000100 +#define NFS4_ACE_EVERYONE 0x00000200 + +#define NFS4_ACE_READ_DATA 0x00000001 +#define NFS4_ACE_LIST_DIRECTORY 0x00000001 +#define NFS4_ACE_WRITE_DATA 0x00000002 +#define NFS4_ACE_ADD_FILE 0x00000002 +#define NFS4_ACE_APPEND_DATA 0x00000004 +#define NFS4_ACE_ADD_SUBDIRECTORY 0x00000004 +#define NFS4_ACE_READ_NAMED_ATTRS 0x00000008 +#define NFS4_ACE_WRITE_NAMED_ATTRS 0x00000010 +#define NFS4_ACE_EXECUTE 0x00000020 +#define NFS4_ACE_DELETE_CHILD 0x00000040 +#define NFS4_ACE_READ_ATTRIBUTES 0x00000080 +#define NFS4_ACE_WRITE_ATTRIBUTES 0x00000100 +#define NFS4_ACE_DELETE 0x00010000 +#define NFS4_ACE_READ_ACL 0x00020000 +#define NFS4_ACE_WRITE_ACL 0x00040000 +#define NFS4_ACE_WRITE_OWNER 0x00080000 +#define NFS4_ACE_SYNCHRONIZE 0x00100000 +#define NFS4_ACE_GENERIC_READ 0x00120081 +#define NFS4_ACE_GENERIC_WRITE 0x00160106 +#define NFS4_ACE_GENERIC_EXECUTE 0x001200A0 +#define NFS4_ACE_MASK_ALL 0x001F01FF + +enum nfs4_acl_whotype { + NFS4_ACL_WHO_NAMED = 0, + NFS4_ACL_WHO_OWNER, + NFS4_ACL_WHO_GROUP, + NFS4_ACL_WHO_EVERYONE, +}; + +#define NFS4_ACL_WHO_OWNER_STRING "OWNER@" +#define NFS4_ACL_WHO_GROUP_STRING "GROUP@" +#define NFS4_ACL_WHO_EVERYONE_STRING "EVERYONE@" + +struct nfs4_ace { + u_int32_t type; + u_int32_t flag; + u_int32_t access_mask; + char* who; + TAILQ_ENTRY(nfs4_ace) l_ace; +}; + +TAILQ_HEAD(ace_list_head, nfs4_ace); + +struct nfs4_acl { + u_int32_t naces; + u_int32_t is_directory; + struct ace_list_head ace_head; +}; + +typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier; +typedef struct { char data[16]; } nfs4_stateid; + +enum nfs_opnum4 { + OP_ACCESS = 3, + OP_CLOSE = 4, + OP_COMMIT = 5, + OP_CREATE = 6, + OP_DELEGPURGE = 7, + OP_DELEGRETURN = 8, + OP_GETATTR = 9, + OP_GETFH = 10, + OP_LINK = 11, + OP_LOCK = 12, + OP_LOCKT = 13, + OP_LOCKU = 14, + OP_LOOKUP = 15, + OP_LOOKUPP = 16, + OP_NVERIFY = 17, + OP_OPEN = 18, + OP_OPENATTR = 19, + OP_OPEN_CONFIRM = 20, + OP_OPEN_DOWNGRADE = 21, + OP_PUTFH = 22, + OP_PUTPUBFH = 23, + OP_PUTROOTFH = 24, + OP_READ = 25, + OP_READDIR = 26, + OP_READLINK = 27, + OP_REMOVE = 28, + OP_RENAME = 29, + OP_RENEW = 30, + OP_RESTOREFH = 31, + OP_SAVEFH = 32, + OP_SECINFO = 33, + OP_SETATTR = 34, + OP_SETCLIENTID = 35, + OP_SETCLIENTID_CONFIRM = 36, + OP_VERIFY = 37, + OP_WRITE = 38, + OP_RELEASE_LOCKOWNER = 39, + OP_ILLEGAL = 10044, +}; + +enum nfsstat4 { + NFS4_OK = 0, + NFS4ERR_PERM = 1, + NFS4ERR_NOENT = 2, + NFS4ERR_IO = 5, + NFS4ERR_NXIO = 6, + NFS4ERR_ACCESS = 13, + NFS4ERR_EXIST = 17, + NFS4ERR_XDEV = 18, + /* Unused/reserved 19 */ + NFS4ERR_NOTDIR = 20, + NFS4ERR_ISDIR = 21, + NFS4ERR_INVAL = 22, + NFS4ERR_FBIG = 27, + NFS4ERR_NOSPC = 28, + NFS4ERR_ROFS = 30, + NFS4ERR_MLINK = 31, + NFS4ERR_NAMETOOLONG = 63, + NFS4ERR_NOTEMPTY = 66, + NFS4ERR_DQUOT = 69, + NFS4ERR_STALE = 70, + NFS4ERR_BADHANDLE = 10001, + NFS4ERR_BAD_COOKIE = 10003, + NFS4ERR_NOTSUPP = 10004, + NFS4ERR_TOOSMALL = 10005, + NFS4ERR_SERVERFAULT = 10006, + NFS4ERR_BADTYPE = 10007, + NFS4ERR_DELAY = 10008, + NFS4ERR_SAME = 10009, + NFS4ERR_DENIED = 10010, + NFS4ERR_EXPIRED = 10011, + NFS4ERR_LOCKED = 10012, + NFS4ERR_GRACE = 10013, + NFS4ERR_FHEXPIRED = 10014, + NFS4ERR_SHARE_DENIED = 10015, + NFS4ERR_WRONGSEC = 10016, + NFS4ERR_CLID_INUSE = 10017, + NFS4ERR_RESOURCE = 10018, + NFS4ERR_MOVED = 10019, + NFS4ERR_NOFILEHANDLE = 10020, + NFS4ERR_MINOR_VERS_MISMATCH = 10021, + NFS4ERR_STALE_CLIENTID = 10022, + NFS4ERR_STALE_STATEID = 10023, + NFS4ERR_OLD_STATEID = 10024, + NFS4ERR_BAD_STATEID = 10025, + NFS4ERR_BAD_SEQID = 10026, + NFS4ERR_NOT_SAME = 10027, + NFS4ERR_LOCK_RANGE = 10028, + NFS4ERR_SYMLINK = 10029, + NFS4ERR_RESTOREFH = 10030, + NFS4ERR_LEASE_MOVED = 10031, + NFS4ERR_ATTRNOTSUPP = 10032, + NFS4ERR_NO_GRACE = 10033, + NFS4ERR_RECLAIM_BAD = 10034, + NFS4ERR_RECLAIM_CONFLICT = 10035, + NFS4ERR_BADXDR = 10036, + NFS4ERR_LOCKS_HELD = 10037, + NFS4ERR_OPENMODE = 10038, + NFS4ERR_BADOWNER = 10039, + NFS4ERR_BADCHAR = 10040, + NFS4ERR_BADNAME = 10041, + NFS4ERR_BAD_RANGE = 10042, + NFS4ERR_LOCK_NOTSUPP = 10043, + NFS4ERR_OP_ILLEGAL = 10044, + NFS4ERR_DEADLOCK = 10045, + NFS4ERR_FILE_OPEN = 10046, + NFS4ERR_ADMIN_REVOKED = 10047, + NFS4ERR_CB_PATH_DOWN = 10048 +}; + +/* + * Note: NF4BAD is not actually part of the protocol; it is just used + * internally by nfsd. + */ +enum nfs_ftype4 { + NF4BAD = 0, + NF4REG = 1, /* Regular File */ + NF4DIR = 2, /* Directory */ + NF4BLK = 3, /* Special File - block device */ + NF4CHR = 4, /* Special File - character device */ + NF4LNK = 5, /* Symbolic Link */ + NF4SOCK = 6, /* Special File - socket */ + NF4FIFO = 7, /* Special File - fifo */ + NF4ATTRDIR = 8, /* Attribute Directory */ + NF4NAMEDATTR = 9 /* Named Attribute */ +}; + +enum open_claim_type4 { + NFS4_OPEN_CLAIM_NULL = 0, + NFS4_OPEN_CLAIM_PREVIOUS = 1, + NFS4_OPEN_CLAIM_DELEGATE_CUR = 2, + NFS4_OPEN_CLAIM_DELEGATE_PREV = 3 +}; + +enum opentype4 { + NFS4_OPEN_NOCREATE = 0, + NFS4_OPEN_CREATE = 1 +}; + +enum createmode4 { + NFS4_CREATE_UNCHECKED = 0, + NFS4_CREATE_GUARDED = 1, + NFS4_CREATE_EXCLUSIVE = 2 +}; + +enum limit_by4 { + NFS4_LIMIT_SIZE = 1, + NFS4_LIMIT_BLOCKS = 2 +}; + +enum open_delegation_type4 { + NFS4_OPEN_DELEGATE_NONE = 0, + NFS4_OPEN_DELEGATE_READ = 1, + NFS4_OPEN_DELEGATE_WRITE = 2 +}; + +enum lock_type4 { + NFS4_UNLOCK_LT = 0, + NFS4_READ_LT = 1, + NFS4_WRITE_LT = 2, + NFS4_READW_LT = 3, + NFS4_WRITEW_LT = 4 +}; + + +/* Mandatory Attributes */ +#define FATTR4_WORD0_SUPPORTED_ATTRS (1UL << 0) +#define FATTR4_WORD0_TYPE (1UL << 1) +#define FATTR4_WORD0_FH_EXPIRE_TYPE (1UL << 2) +#define FATTR4_WORD0_CHANGE (1UL << 3) +#define FATTR4_WORD0_SIZE (1UL << 4) +#define FATTR4_WORD0_LINK_SUPPORT (1UL << 5) +#define FATTR4_WORD0_SYMLINK_SUPPORT (1UL << 6) +#define FATTR4_WORD0_NAMED_ATTR (1UL << 7) +#define FATTR4_WORD0_FSID (1UL << 8) +#define FATTR4_WORD0_UNIQUE_HANDLES (1UL << 9) +#define FATTR4_WORD0_LEASE_TIME (1UL << 10) +#define FATTR4_WORD0_RDATTR_ERROR (1UL << 11) + +/* Recommended Attributes */ +#define FATTR4_WORD0_ACL (1UL << 12) +#define FATTR4_WORD0_ACLSUPPORT (1UL << 13) +#define FATTR4_WORD0_ARCHIVE (1UL << 14) +#define FATTR4_WORD0_CANSETTIME (1UL << 15) +#define FATTR4_WORD0_CASE_INSENSITIVE (1UL << 16) +#define FATTR4_WORD0_CASE_PRESERVING (1UL << 17) +#define FATTR4_WORD0_CHOWN_RESTRICTED (1UL << 18) +#define FATTR4_WORD0_FILEHANDLE (1UL << 19) +#define FATTR4_WORD0_FILEID (1UL << 20) +#define FATTR4_WORD0_FILES_AVAIL (1UL << 21) +#define FATTR4_WORD0_FILES_FREE (1UL << 22) +#define FATTR4_WORD0_FILES_TOTAL (1UL << 23) +#define FATTR4_WORD0_FS_LOCATIONS (1UL << 24) +#define FATTR4_WORD0_HIDDEN (1UL << 25) +#define FATTR4_WORD0_HOMOGENEOUS (1UL << 26) +#define FATTR4_WORD0_MAXFILESIZE (1UL << 27) +#define FATTR4_WORD0_MAXLINK (1UL << 28) +#define FATTR4_WORD0_MAXNAME (1UL << 29) +#define FATTR4_WORD0_MAXREAD (1UL << 30) +#define FATTR4_WORD0_MAXWRITE (1UL << 31) +#define FATTR4_WORD1_MIMETYPE (1UL << 0) +#define FATTR4_WORD1_MODE (1UL << 1) +#define FATTR4_WORD1_NO_TRUNC (1UL << 2) +#define FATTR4_WORD1_NUMLINKS (1UL << 3) +#define FATTR4_WORD1_OWNER (1UL << 4) +#define FATTR4_WORD1_OWNER_GROUP (1UL << 5) +#define FATTR4_WORD1_QUOTA_HARD (1UL << 6) +#define FATTR4_WORD1_QUOTA_SOFT (1UL << 7) +#define FATTR4_WORD1_QUOTA_USED (1UL << 8) +#define FATTR4_WORD1_RAWDEV (1UL << 9) +#define FATTR4_WORD1_SPACE_AVAIL (1UL << 10) +#define FATTR4_WORD1_SPACE_FREE (1UL << 11) +#define FATTR4_WORD1_SPACE_TOTAL (1UL << 12) +#define FATTR4_WORD1_SPACE_USED (1UL << 13) +#define FATTR4_WORD1_SYSTEM (1UL << 14) +#define FATTR4_WORD1_TIME_ACCESS (1UL << 15) +#define FATTR4_WORD1_TIME_ACCESS_SET (1UL << 16) +#define FATTR4_WORD1_TIME_BACKUP (1UL << 17) +#define FATTR4_WORD1_TIME_CREATE (1UL << 18) +#define FATTR4_WORD1_TIME_DELTA (1UL << 19) +#define FATTR4_WORD1_TIME_METADATA (1UL << 20) +#define FATTR4_WORD1_TIME_MODIFY (1UL << 21) +#define FATTR4_WORD1_TIME_MODIFY_SET (1UL << 22) +#define FATTR4_WORD1_MOUNTED_ON_FILEID (1UL << 23) + +#define NFSPROC4_NULL 0 +#define NFSPROC4_COMPOUND 1 +#define NFS4_MINOR_VERSION 0 +#define NFS4_DEBUG 1 + +#ifdef __KERNEL__ + +/* Index of predefined Linux client operations */ + +enum { + NFSPROC4_CLNT_NULL = 0, /* Unused */ + NFSPROC4_CLNT_READ, + NFSPROC4_CLNT_WRITE, + NFSPROC4_CLNT_COMMIT, + NFSPROC4_CLNT_OPEN, + NFSPROC4_CLNT_OPEN_CONFIRM, + NFSPROC4_CLNT_OPEN_RECLAIM, + NFSPROC4_CLNT_OPEN_DOWNGRADE, + NFSPROC4_CLNT_CLOSE, + NFSPROC4_CLNT_SETATTR, + NFSPROC4_CLNT_FSINFO, + NFSPROC4_CLNT_RENEW, + NFSPROC4_CLNT_SETCLIENTID, + NFSPROC4_CLNT_SETCLIENTID_CONFIRM, + NFSPROC4_CLNT_LOCK, + NFSPROC4_CLNT_LOCKT, + NFSPROC4_CLNT_LOCKU, + NFSPROC4_CLNT_ACCESS, + NFSPROC4_CLNT_GETATTR, + NFSPROC4_CLNT_LOOKUP, + NFSPROC4_CLNT_LOOKUP_ROOT, + NFSPROC4_CLNT_REMOVE, + NFSPROC4_CLNT_RENAME, + NFSPROC4_CLNT_LINK, + NFSPROC4_CLNT_CREATE, + NFSPROC4_CLNT_PATHCONF, + NFSPROC4_CLNT_STATFS, + NFSPROC4_CLNT_READLINK, + NFSPROC4_CLNT_READDIR, + NFSPROC4_CLNT_SERVER_CAPS, + NFSPROC4_CLNT_DELEGRETURN, + NFSPROC4_CLNT_GETACL, + NFSPROC4_CLNT_SETACL, +}; + +#endif +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/libacl/Makefile b/libacl/Makefile index 5ac4810..ff86e67 100644 --- a/libacl/Makefile +++ b/libacl/Makefile @@ -8,19 +8,41 @@ LTLDFLAGS += -Wl,--version-script,$(TOPD include $(TOPDIR)/include/builddefs LTLIBRARY = libacl.la -LTLIBS = -lattr $(LIBMISC) +LTLIBS = -lattr -lnfsidmap $(LIBMISC) LTDEPENDENCIES = $(LIBMISC) -LT_CURRENT = 2 +LT_CURRENT = 3 LT_REVISION = 0 -LT_AGE = 1 +LT_AGE = 2 + +CFILES = $(POSIX_CFILES) $(LIBACL_CFILES) $(LIBACL_NFS4_CFILES) \ + $(INTERNAL_CFILES) perm_copy_fd.c perm_copy_file.c -CFILES = $(POSIX_CFILES) $(LIBACL_CFILES) $(INTERNAL_CFILES) \ - perm_copy_fd.c perm_copy_file.c HFILES = libobj.h libacl.h byteorder.h __acl_from_xattr.h __acl_to_xattr.h \ - perm_copy.h + perm_copy.h $(LIBACL_NFS4_HFILES) LCFLAGS = -include perm_copy.h +LIBACL_NFS4_CFILES = \ + acl_n4tp_ace_count.c acl_nfs4_get_type.c \ + acl_n4tp_ace_trans.c acl_nfs4_get_who.c \ + acl_n4tp_acl_trans.c acl_nfs4_get_whotype.c \ + acl_n4tp_get_whotype.c acl_nfs4_new.c \ + acl_n4tp_set_mode.c acl_nfs4_print.c \ + acl_n4tp_set_who.c acl_nfs4_print_ace.c \ + acl_nfs4_add_ace.c acl_nfs4_remove_ace.c \ + acl_nfs4_add_pair.c \ + acl_nfs4_copy_acl.c acl_nfs4_set_who.c \ + acl_nfs4_entries.c acl_nfs4_utils.c \ + acl_nfs4_free.c acl_nfs4_xattr_load.c \ + acl_nfs4_get_accessmask.c acl_nfs4_xattr_pack.c \ + acl_nfs4_xattr_size.c \ + acl_nfs4_get_flags.c acl_ptn4_acl_trans.c \ + acl_ptn4_get_mask.c __posix_acl_from_nfs4_xattr.c \ + acl_nfs4_print_fd.c acl_nfs4_string2ace.c + + +LIBACL_NFS4_HFILES = libacl_nfs4.h nfs4.h + POSIX_CFILES = \ acl_add_perm.c acl_calc_mask.c acl_clear_perms.c acl_copy_entry.c \ acl_copy_ext.c acl_copy_int.c acl_create_entry.c acl_delete_def_file.c \ diff --git a/libacl/__posix_acl_from_nfs4_xattr.c b/libacl/__posix_acl_from_nfs4_xattr.c new file mode 100644 index 0000000..8941024 --- /dev/null +++ b/libacl/__posix_acl_from_nfs4_xattr.c @@ -0,0 +1,60 @@ +/* + * NFSv4 ACL Code + * Convert NFSv4 xattr values to a posix ACL + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "libacl_nfs4.h" + +/* xattr_v is a char buffer filled with the nfsv4 xattr value. + * xattr_size should be the byte count of the length of the xattr_v + * data size. xattr_v may be larger than bytes, but only + * the first bytes will be read. is the posix acl + * type requested. Currently either default, or access */ + +acl_t __posix_acl_from_nfs4_xattr(char* xattr_v, + int xattr_size, acl_type_t ptype, u32 is_dir) +{ + struct nfs4_acl * nfsacl = NULL; + acl_t pacl; + + nfsacl = acl_nfs4_xattr_load(xattr_v, xattr_size, is_dir); + if(nfsacl == NULL) { + return NULL; + } + + pacl = acl_n4tp_acl_trans(nfsacl, ptype); + + return pacl; +} + diff --git a/libacl/acl_extended_file.c b/libacl/acl_extended_file.c index 1850aa2..527b42f 100644 --- a/libacl/acl_extended_file.c +++ b/libacl/acl_extended_file.c @@ -33,6 +33,10 @@ acl_extended_file(const char *path_p) int base_size = sizeof(acl_ea_header) + 3 * sizeof(acl_ea_entry); int retval; + /* XXX: Ugh: what's the easiest way to do this, taking + * into account default acl's, and that length alone won't do this? + * Also I'm a little uncomfortable with the amount of #ifdef + * NFS4 stuff that's going on. We need a cleaner separation. */ retval = getxattr(path_p, ACL_EA_ACCESS, NULL, 0); if (retval < 0 && errno != ENOATTR && errno != ENODATA) return -1; diff --git a/libacl/acl_get_fd.c b/libacl/acl_get_fd.c index b424bfd..6b057cd 100644 --- a/libacl/acl_get_fd.c +++ b/libacl/acl_get_fd.c @@ -28,6 +28,10 @@ #include #include "libacl.h" #include "__acl_from_xattr.h" +#ifdef USE_NFSV4_TRANS + #include "libacl_nfs4.h" +#endif + #include "byteorder.h" #include "acl_ea.h" @@ -38,31 +42,59 @@ acl_get_fd(int fd) { const size_t size_guess = acl_ea_size(16); char *ext_acl_p = alloca(size_guess); + char *name = ACL_EA_ACCESS; int retval; + int nfsv4acls; if (!ext_acl_p) return NULL; - retval = fgetxattr(fd, ACL_EA_ACCESS, ext_acl_p, size_guess); + +#ifdef USE_NFSV4_TRANS + retval = fgetxattr(fd, ACL_NFS4_XATTR, ext_acl_p, size_guess); + if(retval == -1 && (errno == ENOATTR || errno == EOPNOTSUPP)) { + nfsv4acls = ACL_NFS4_NOT_USED; + retval = fgetxattr(fd, name, ext_acl_p, size_guess); + } else { + nfsv4acls = ACL_NFS4_USED; + name = ACL_NFS4_XATTR; + } +#else + retval = fgetxattr(fd, name, ext_acl_p, size_guess); +#endif + if (retval == -1 && errno == ERANGE) { - retval = fgetxattr(fd, ACL_EA_ACCESS, NULL, 0); + retval = fgetxattr(fd, name, NULL, 0); if (retval > 0) { ext_acl_p = alloca(retval); if (!ext_acl_p) return NULL; - retval = fgetxattr(fd, ACL_EA_ACCESS, ext_acl_p,retval); + retval = fgetxattr(fd, name, ext_acl_p, retval); } } if (retval > 0) { - acl_t acl = __acl_from_xattr(ext_acl_p, retval); - return acl; +#ifdef USE_NFSV4_TRANS + if(nfsv4acls == ACL_NFS4_USED) { + acl_t acl = __posix_acl_from_nfs4_xattr(ext_acl_p, retval, + ACL_TYPE_ACCESS, NFS4_ACL_ISFILE); + + return acl; + } + else +#endif + { + acl_t acl = __acl_from_xattr(ext_acl_p, retval); + return acl; + } } else if (retval == 0 || errno == ENOATTR || errno == ENODATA) { struct stat st; - if (fstat(fd, &st) == 0) - return acl_from_mode(st.st_mode); - else + if (fstat(fd, &st) != 0) { return NULL; - } else + } + + return acl_from_mode(st.st_mode); + } else { return NULL; + } } diff --git a/libacl/acl_get_file.c b/libacl/acl_get_file.c index 8895e90..15da288 100644 --- a/libacl/acl_get_file.c +++ b/libacl/acl_get_file.c @@ -28,6 +28,10 @@ #include #include "libacl.h" #include "__acl_from_xattr.h" +#ifdef USE_NFSV4_TRANS + #include "libacl_nfs4.h" +#endif + #include "byteorder.h" #include "acl_ea.h" @@ -40,6 +44,8 @@ acl_get_file(const char *path_p, acl_typ char *ext_acl_p = alloca(size_guess); const char *name; int retval; + int nfsv4acls; + int iflags; switch(type) { case ACL_TYPE_ACCESS: @@ -55,8 +61,20 @@ acl_get_file(const char *path_p, acl_typ if (!ext_acl_p) return NULL; +#ifdef USE_NFSV4_TRANS + retval = getxattr(path_p, ACL_NFS4_XATTR, ext_acl_p, size_guess); + if((retval == -1) && (errno == ENOATTR || errno == EOPNOTSUPP)) { + nfsv4acls = ACL_NFS4_NOT_USED; + retval = getxattr(path_p, name, ext_acl_p, size_guess); + } else { + nfsv4acls = ACL_NFS4_USED; + name = ACL_NFS4_XATTR; + } +#else retval = getxattr(path_p, name, ext_acl_p, size_guess); - if (retval == -1 && errno == ERANGE) { +#endif + + if ((retval == -1) && (errno == ERANGE)) { retval = getxattr(path_p, name, NULL, 0); if (retval > 0) { ext_acl_p = alloca(retval); @@ -66,9 +84,29 @@ acl_get_file(const char *path_p, acl_typ } } if (retval > 0) { - acl_t acl = __acl_from_xattr(ext_acl_p, retval); - return acl; - } else if (retval == 0 || errno == ENOATTR || errno == ENODATA) { +#ifdef USE_NFSV4_TRANS + if(nfsv4acls == ACL_NFS4_USED) { + struct stat st; + + iflags = NFS4_ACL_ISFILE; + + if (stat(path_p, &st) != 0) + return NULL; + + if (S_ISDIR(st.st_mode)) + iflags = NFS4_ACL_ISDIR; + + acl_t acl = __posix_acl_from_nfs4_xattr(ext_acl_p, retval, type, + iflags); + return acl; + } + else +#endif + { + acl_t acl = __acl_from_xattr(ext_acl_p, retval); + return acl; + } + } else if ((retval == 0) || (errno == ENOATTR) || (errno == ENODATA)) { struct stat st; if (stat(path_p, &st) != 0) diff --git a/libacl/acl_n4tp_ace_count.c b/libacl/acl_n4tp_ace_count.c new file mode 100644 index 0000000..ecce637 --- /dev/null +++ b/libacl/acl_n4tp_ace_count.c @@ -0,0 +1,57 @@ +/* + * NFSv4 ACL Code + * Calculate the POSIX ACE count based upon the assumption that + * POSIX<->NFSv4 ACL translation has been the standard on the + * server/client. This would break against other servers? + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "libacl_nfs4.h" + +int acl_n4tp_ace_count(struct nfs4_acl *n4acl) +{ + if (n4acl->naces == 0) + return 0; + if (n4acl->naces == 6) /* owner, owner group, and other only */ + return 3; + else { /* Otherwise there must be a mask entry. */ + /* Also, the remaining entries are for named users and + * groups, and come in threes (mask, allow, deny): */ + if (n4acl->naces < 7) + return -1; + if ((n4acl->naces - 7) % 3) + return -1; + return 4 + (n4acl->naces - 7)/3; + } +} + diff --git a/libacl/acl_n4tp_ace_trans.c b/libacl/acl_n4tp_ace_trans.c new file mode 100644 index 0000000..c5cc4da --- /dev/null +++ b/libacl/acl_n4tp_ace_trans.c @@ -0,0 +1,76 @@ +/* + * NFSv4 ACL Code + * Translate an NFSv4 ace to a POSIX ace. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libacl_nfs4.h" + +int acl_n4tp_ace_trans(struct nfs4_ace *ace, acl_t *pacl, acl_tag_t tag, + int iflags) +{ + int result; + acl_entry_t new_ace; + + + if(ace == NULL || pacl == NULL || *pacl == NULL) { + errno = EINVAL; + goto failed; + } + + result = acl_create_entry(pacl, &new_ace); + if(result < 0) + goto failed; + + result = acl_set_tag_type(new_ace, tag); + if(result < 0) + goto ace_failed; + + result = acl_n4tp_set_mode(new_ace, ace->access_mask, iflags); + if(result < 0) + goto ace_failed; + + if(tag == ACL_USER || tag == ACL_GROUP) { + result = acl_n4tp_set_who(new_ace, ace->who, tag); + if(result < 0) + goto ace_failed; + } + + return 0; + +ace_failed: + acl_delete_entry(*pacl, new_ace); + +failed: + return -1; +} + diff --git a/libacl/acl_n4tp_acl_trans.c b/libacl/acl_n4tp_acl_trans.c new file mode 100644 index 0000000..8963db3 --- /dev/null +++ b/libacl/acl_n4tp_acl_trans.c @@ -0,0 +1,178 @@ +/* + * NFSv4 ACL Code + * Convert NFSv4 ACL to a POSIX ACL + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "libacl_nfs4.h" + +acl_t acl_n4tp_acl_trans(struct nfs4_acl * nacl_p, acl_type_t ptype) +{ + + acl_t pacl_p = NULL; + acl_t * pacl_pp; + struct nfs4_acl * temp_acl; + int naces = -1; + int num_aces; + int ace_num; + struct nfs4_ace * cur_ace = NULL; + struct nfs4_ace * mask_ace = NULL; + struct nfs4_ace * temp_ace = NULL; + int result; + u32 flags; + u32 iflags = NFS4_ACL_NOFLAGS; + u32 is_dir; + + if(nacl_p == NULL) { + errno = EINVAL; + goto failed; + } + + if(ptype == ACL_TYPE_DEFAULT) + { + if (nacl_p->is_directory) + { + iflags |= NFS4_ACL_REQUEST_DEFAULT; + } else { + /* If it's not a directory, a default acl won't make sense */ + errno = EINVAL; + goto failed; + } + } + + /* Copy the nfs4 acl so we can delete bits without borking the original */ + temp_acl = acl_nfs4_copy_acl(nacl_p); + if(temp_acl == NULL) + goto failed; + + num_aces = acl_nfs4_entries(temp_acl); + + /* Strip or keep inheritance aces depending upon the type of posix acl + * requested */ + cur_ace = acl_nfs4_get_first_ace(temp_acl); + ace_num = 1; + + while(1) { + if(cur_ace == NULL) { + if(ace_num > num_aces) + break; + else + goto free_failed; + } + + /* get the next ace now because we may be freeing the current ace */ + temp_ace = cur_ace; + acl_nfs4_get_next_ace(&cur_ace); + + result = acl_nfs4_get_flags(temp_ace, &flags); + if( result < 0 ) + goto free_failed; + + if(iflags & NFS4_ACL_REQUEST_DEFAULT) + { + if((flags & NFS4_INHERITANCE_FLAGS) != NFS4_INHERITANCE_FLAGS) { + result = acl_nfs4_remove_ace(temp_acl, temp_ace); + if(result < 0) + goto free_failed; + } + } + else + { + if((flags & NFS4_INHERITANCE_FLAGS) == NFS4_INHERITANCE_FLAGS) { + result = acl_nfs4_remove_ace(temp_acl, temp_ace); + if(result < 0) + goto free_failed; + } + } + + ace_num++; + } + + + naces = acl_n4tp_ace_count(temp_acl); + if (naces < 0) { + errno = EINVAL; + goto free_failed; + } + + if (naces == 0) + return acl_init(0); + + pacl_p = acl_init(naces); + + if(pacl_p == NULL) + goto free_failed; + + pacl_pp = &pacl_p; + + cur_ace = acl_nfs4_get_first_ace(temp_acl); + + result = user_obj_from_v4(temp_acl, &cur_ace, pacl_pp, iflags); + if(result < 0) + goto acl_free_failed; + + result = users_from_v4(temp_acl, &cur_ace, &mask_ace, pacl_pp, iflags); + if(result < 0) + goto acl_free_failed; + + result = group_obj_and_groups_from_v4(temp_acl, &cur_ace, + &mask_ace, pacl_pp, iflags); + if(result < 0) + goto acl_free_failed; + + result = mask_from_v4(temp_acl, &cur_ace, &mask_ace, pacl_pp, iflags); + if(result < 0) + goto acl_free_failed; + + result = other_from_v4(temp_acl, &cur_ace, pacl_pp, iflags); + if(result < 0) + goto acl_free_failed; + + result = acl_valid(*pacl_pp); + if(result < 0) + goto acl_free_failed; + + acl_nfs4_free(temp_acl); + + return *pacl_pp; + +acl_free_failed: + acl_free(*pacl_pp); + +free_failed: + acl_nfs4_free(temp_acl); + +failed: + return NULL; +} + diff --git a/libacl/acl_n4tp_get_whotype.c b/libacl/acl_n4tp_get_whotype.c new file mode 100644 index 0000000..fd553c6 --- /dev/null +++ b/libacl/acl_n4tp_get_whotype.c @@ -0,0 +1,73 @@ +/* + * NFSv4 ACL Code + * Convert NFSv4 ACE who to a POSIX ACE whotype + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "libacl_nfs4.h" + +acl_tag_t acl_n4tp_get_whotype(struct nfs4_ace *ace) +{ + int nfs4type; + int result; + + if(ace == NULL) + goto inval_failed; + + if(ace->who == NULL || strlen(ace->who) <= 0) + goto inval_failed; + + result = acl_nfs4_get_who(ace, &nfs4type, NULL); + if ( result < 0 ) + goto failed; + + switch (nfs4type) { + case NFS4_ACL_WHO_NAMED: + return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ? + ACL_GROUP : ACL_USER); + case NFS4_ACL_WHO_OWNER: + return ACL_USER_OBJ; + case NFS4_ACL_WHO_GROUP: + return ACL_GROUP_OBJ; + case NFS4_ACL_WHO_EVERYONE: + return ACL_OTHER; + } + +inval_failed: + errno = EINVAL; + +failed: + return -1; +} + + diff --git a/libacl/acl_n4tp_set_mode.c b/libacl/acl_n4tp_set_mode.c new file mode 100644 index 0000000..bef5e23 --- /dev/null +++ b/libacl/acl_n4tp_set_mode.c @@ -0,0 +1,98 @@ +/* + * NFSv4 ACL Code + * Set posix ACL mode based on NFSv4 mask + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "libacl_nfs4.h" + +int acl_n4tp_set_mode(acl_entry_t pace, u32 nfs4_access_mask, int iflags) +{ + /* XXX we might also want to ignore DELETE_CHILD on non-directories */ + /* XXX also add special interpretation to EXECUTE on directories */ + u32 ignore = NFS4_ACE_SYNCHRONIZE; + u32 new_mask; + acl_permset_t perms; + int result; + + if((iflags & NFS4_ACL_ISDIR) != NFS4_ACL_ISDIR) + ignore |= NFS4_ACE_DELETE_CHILD; + + nfs4_access_mask |= ignore; + + result = acl_get_permset(pace, &perms); + if(result < 0) + goto failed; + + result = acl_clear_perms(perms); + if(result < 0) + goto failed; + + if ((nfs4_access_mask & NFS4_READ_MODE) == NFS4_READ_MODE) { + result = acl_add_perm(perms, ACL_READ); + if(result < 0) + goto failed; + } + + if ((nfs4_access_mask & NFS4_WRITE_MODE) == NFS4_WRITE_MODE) { + result = acl_add_perm(perms, ACL_WRITE); + if(result < 0) + goto failed; + } + + if ((nfs4_access_mask & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE) { + result = acl_add_perm(perms, ACL_EXECUTE); + if(result < 0) + goto failed; + } + + result = acl_ptn4_get_mask(&new_mask, perms, iflags); + if(result < 0) + goto failed; + + new_mask |= ignore; + + if (!MASK_EQUAL(nfs4_access_mask, new_mask)) { + errno = EINVAL; + goto failed; + } + + result = acl_set_permset(pace, perms); + if(result < 0) + goto failed; + + return 0; + +failed: + return -1; +} + diff --git a/libacl/acl_n4tp_set_who.c b/libacl/acl_n4tp_set_who.c new file mode 100644 index 0000000..241ef71 --- /dev/null +++ b/libacl/acl_n4tp_set_who.c @@ -0,0 +1,89 @@ +/* + * NFSv4 ACL Code + * Set the POSIX ACE who based on the whotype and NFS who attr. + * Translation is done using the NFS4 mapping functions. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "libacl_nfs4.h" + +#define PATH_IDMAPDCONF "/etc/idmapd.conf" +char *conf_path = PATH_IDMAPDCONF; + +int acl_n4tp_set_who(acl_entry_t ace, char* who, acl_tag_t who_type) +{ + int result; + uid_t uid; + gid_t gid; + + if(ace == NULL || who == NULL) { + errno = EINVAL; + goto failed; + } + + switch(who_type) { + case ACL_USER: + result = nfs4_init_name_mapping(NULL); + if (result < 0) + goto failed; + result = nfs4_name_to_uid(who, &uid); + if(result < 0) + goto failed; + result = acl_set_qualifier(ace, (void *) &uid); + if(result < 0) + goto failed; + break; + case ACL_GROUP: + result = nfs4_init_name_mapping(NULL); + if (result < 0) + goto failed; + result = nfs4_name_to_gid(who, &gid); + if(result < 0) + goto failed; + result = acl_set_qualifier(ace, (void *) &gid); + if(result < 0) + goto failed; + break; + default: + errno = EINVAL; + goto failed; + } + + return 0; + +failed: + return -1; +} + + diff --git a/libacl/acl_nfs4_add_ace.c b/libacl/acl_nfs4_add_ace.c new file mode 100644 index 0000000..4c1ff9a --- /dev/null +++ b/libacl/acl_nfs4_add_ace.c @@ -0,0 +1,83 @@ +/* + * NFSv4 ACL Code + * Add an ace to the acl + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * J. Bruce Fields + * Nathaniel Gallaher + * Jeff Sedlak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libacl_nfs4.h" + +int +acl_nfs4_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, + int whotype, char* who) +{ + struct nfs4_ace *ace; + int result; + + if(acl == NULL) + { + errno = EINVAL; + return -1; + } + + if ((ace = malloc(sizeof(*ace))) == NULL) + { + errno = ENOMEM; + return -1; + } + + ace->type = type; + ace->flag = flag; + + if( type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE ) + access_mask = access_mask & ~(NFS4_ACE_MASK_IGNORE); + + + /* Castrate delete_child if we aren't a directory */ + if (!acl->is_directory) + access_mask &= ~NFS4_ACE_DELETE_CHILD; + + + ace->access_mask = access_mask & NFS4_ACE_MASK_ALL; + + result = acl_nfs4_set_who(ace, whotype, who); + if(result < 0) + return -1; + + TAILQ_INSERT_TAIL(&acl->ace_head, ace, l_ace); + acl->naces++; + + return 0; +} + diff --git a/libacl/acl_nfs4_add_pair.c b/libacl/acl_nfs4_add_pair.c new file mode 100644 index 0000000..d849fb9 --- /dev/null +++ b/libacl/acl_nfs4_add_pair.c @@ -0,0 +1,60 @@ +/* + * Add a pair of aces to the acl. The ace masks are complements of each other + * This keeps us from walking off the end of the acl + * + * Copyright (c) 2004 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * J. Bruce Fields + * Nathaniel Gallaher + * Jeff Sedlak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, the following disclaimer, and + * any and all other licensing or copyright notices included in + * any files in this distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "libacl_nfs4.h" + +int +acl_nfs4_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int ownertype, + char* owner) +{ + int error; + + error = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, + eflag, mask, ownertype, owner); + if (error < 0) + return error; + error = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, + eflag, ~mask, ownertype, owner); + return error; +} + + diff --git a/libacl/acl_nfs4_copy_acl.c b/libacl/acl_nfs4_copy_acl.c new file mode 100644 index 0000000..a3dd939 --- /dev/null +++ b/libacl/acl_nfs4_copy_acl.c @@ -0,0 +1,88 @@ +/* + * NFSv4 ACL Code + * Deep copy an NFS4 ACL + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libacl_nfs4.h" + +struct nfs4_acl * acl_nfs4_copy_acl(struct nfs4_acl * nacl) +{ + struct nfs4_acl * new_acl; + struct nfs4_ace * ace; + u32 nace; + u32 num_aces; + u32 is_dir; + int result; + + if(nacl == NULL) { + errno = EINVAL; + goto failed; + } + + num_aces = acl_nfs4_entries(nacl); + if(num_aces < 0) + goto failed; + + new_acl = acl_nfs4_new(nacl->is_directory); + if(new_acl == NULL) + goto failed; + + ace = acl_nfs4_get_first_ace(nacl); + nace = 1; + + while(1) + { + if(ace == NULL) { + if(nace > num_aces) + break; + else + goto free_failed; + } + + result = acl_nfs4_add_ace(new_acl, ace->type, ace->flag, + ace->access_mask, acl_nfs4_get_whotype(ace->who), ace->who); + if(result < 0) + goto free_failed; + + acl_nfs4_get_next_ace(&ace); + nace++; + } + + return new_acl; + +free_failed: + acl_nfs4_free(new_acl); + +failed: + return NULL; +} diff --git a/libacl/acl_nfs4_entries.c b/libacl/acl_nfs4_entries.c new file mode 100644 index 0000000..2dffa9f --- /dev/null +++ b/libacl/acl_nfs4_entries.c @@ -0,0 +1,48 @@ +/* NFS4 ACL code + * Function returns the number of aces in an acl + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +inline int acl_nfs4_entries(struct nfs4_acl * acl) +{ + if(acl == NULL) + { + errno = EINVAL; + return -1; + } + + return acl->naces; +} + diff --git a/libacl/acl_nfs4_free.c b/libacl/acl_nfs4_free.c new file mode 100644 index 0000000..9cab808 --- /dev/null +++ b/libacl/acl_nfs4_free.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * J. Bruce Fields + * Nathaniel Gallaher + * Jeff Sedlak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, the following disclaimer, and + * any and all other licensing or copyright notices included in + * any files in this distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "libacl_nfs4.h" + +void +acl_nfs4_free(struct nfs4_acl *acl) +{ + struct nfs4_ace *ace; + + if (!acl) + return; + + while (!TAILQ_IS_EMPTY(acl->ace_head)) { + ace = (acl)->ace_head.tqh_first; + + TAILQ_REMOVE( &(acl->ace_head), ace, l_ace); + free(ace->who); + free(ace); + } + + free(acl); + + return; +} + diff --git a/libacl/acl_nfs4_get_accessmask.c b/libacl/acl_nfs4_get_accessmask.c new file mode 100644 index 0000000..f677f56 --- /dev/null +++ b/libacl/acl_nfs4_get_accessmask.c @@ -0,0 +1,46 @@ +/* NFS4 ACL code + * Accessor for ace access_mask. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +inline int acl_nfs4_get_accessmask(struct nfs4_ace * ace, u32 * mask) +{ + if(mask == NULL || ace == NULL) + { + errno = EINVAL; + return -1; + } + *mask = ace->access_mask; + return 0; +} diff --git a/libacl/acl_nfs4_get_flags.c b/libacl/acl_nfs4_get_flags.c new file mode 100644 index 0000000..06577a9 --- /dev/null +++ b/libacl/acl_nfs4_get_flags.c @@ -0,0 +1,46 @@ +/* NFS4 ACL code + * Accessor for ace flags. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +inline int acl_nfs4_get_flags(struct nfs4_ace * ace, u32 * flags) +{ + if(flags == NULL || ace == NULL) + { + errno = EINVAL; + return -1; + } + *flags = ace->flag; + return 0; +} diff --git a/libacl/acl_nfs4_get_type.c b/libacl/acl_nfs4_get_type.c new file mode 100644 index 0000000..9fd698f --- /dev/null +++ b/libacl/acl_nfs4_get_type.c @@ -0,0 +1,47 @@ +/* NFS4 ACL Code + * Accessor for ace type + * + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +int acl_nfs4_get_type(struct nfs4_ace * ace, u32 * type) +{ + if(ace == NULL || type == NULL) + { + errno = EINVAL; + return -1; + } + *type = ace->type; + return 0; +} diff --git a/libacl/acl_nfs4_get_who.c b/libacl/acl_nfs4_get_who.c new file mode 100644 index 0000000..8c21b16 --- /dev/null +++ b/libacl/acl_nfs4_get_who.c @@ -0,0 +1,103 @@ +/* + * NFSv4 ACL Code + * Read the who value from the ace and return its type and optionally + * its value. + * + * Ace is a reference to the ace to extract the who value from. + * Type is a reference where the value of the whotype will be stored. + * Who is a double reference that should either be passed as NULL + * (and thus no who string will be returned) or as a pointer to a + * char* where the who string will be allocated. This string must be + * freed by the caller. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libacl_nfs4.h" + +int acl_nfs4_get_who(struct nfs4_ace* ace, int* type, char** who) +{ + int itype; + char* iwho = NULL; + int wholen; + + if(ace == NULL || ace->who == NULL) + goto inval_failed; + + itype = acl_nfs4_get_whotype(ace->who); + + if(type != NULL) { + *type = itype; + } + + + if(who == NULL) + return 0; + + switch(itype) + { + case NFS4_ACL_WHO_NAMED: + iwho = ace->who; + break; + case NFS4_ACL_WHO_OWNER: + iwho = NFS4_ACL_WHO_OWNER_STRING; + break; + case NFS4_ACL_WHO_GROUP: + iwho = NFS4_ACL_WHO_GROUP_STRING; + break; + case NFS4_ACL_WHO_EVERYONE: + iwho = NFS4_ACL_WHO_EVERYONE_STRING; + break; + default: + goto inval_failed; + } + + wholen = strlen(iwho); + if(wholen < 0) + goto inval_failed; + + (*who) = (char *) malloc(sizeof(char) * (wholen + 1)); + if((*who) == NULL) { + errno = ENOMEM; + goto failed; + } + + strcpy((*who), iwho); + + return 0; + +inval_failed: + errno = EINVAL; + +failed: + return -1; +} + diff --git a/libacl/acl_nfs4_get_whotype.c b/libacl/acl_nfs4_get_whotype.c new file mode 100644 index 0000000..10574f8 --- /dev/null +++ b/libacl/acl_nfs4_get_whotype.c @@ -0,0 +1,60 @@ +/* + * NFSv4 ACL Code + * Get the whotype of the who string passed + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * J. Bruce Fields + * Nathaniel Gallaher + * Jeff Sedlak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libacl_nfs4.h" + +inline int +acl_nfs4_get_whotype(char *p) +{ + if(0 == strcmp(p, NFS4_ACL_WHO_OWNER_STRING) && + strlen(p) == strlen(NFS4_ACL_WHO_OWNER_STRING)) { + return NFS4_ACL_WHO_OWNER; + } + if(0 == strcmp(p, NFS4_ACL_WHO_GROUP_STRING) && + strlen(p) == strlen(NFS4_ACL_WHO_GROUP_STRING)) { + return NFS4_ACL_WHO_GROUP; + } + if(0 == strcmp(p, NFS4_ACL_WHO_EVERYONE_STRING) && + strlen(p) == strlen(NFS4_ACL_WHO_EVERYONE_STRING)) { + return NFS4_ACL_WHO_EVERYONE; + } + + return NFS4_ACL_WHO_NAMED; +} + + diff --git a/libacl/acl_nfs4_new.c b/libacl/acl_nfs4_new.c new file mode 100644 index 0000000..658a282 --- /dev/null +++ b/libacl/acl_nfs4_new.c @@ -0,0 +1,58 @@ +/* + * Common NFSv4 ACL handling code. + * Create a new NFSv4 ACL + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Marius Aamodt Eriksen + * J. Bruce Fields + * Nathaniel Gallaher + * Jeff Sedlak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include "libacl_nfs4.h" + +struct nfs4_acl * +acl_nfs4_new(u32 is_dir) +{ + struct nfs4_acl *acl; + + if ((acl = malloc(sizeof(*acl))) == NULL) + return NULL; + + acl->naces = 0; + acl->is_directory = is_dir; + + TAILQ_INIT(&acl->ace_head); + + return acl; +} + diff --git a/libacl/acl_nfs4_print.c b/libacl/acl_nfs4_print.c new file mode 100644 index 0000000..8ec794e --- /dev/null +++ b/libacl/acl_nfs4_print.c @@ -0,0 +1,204 @@ +/* + * NFSv4 ACL Code + * Print the contents of an nfs4 ACL + * + * Permission mapping: + * r - NFS4_ACE_READ_DATA + * l - NFS4_ACE_LIST_DIRECTORY + * w - NFS4_ACE_WRITE_DATA + * f - NFS4_ACE_ADD_FILE + * a - NFS4_ACE_APPEND_DATA + * s - NFS4_ACE_ADD_SUBDIRECTORY + * n - NFS4_ACE_READ_NAMED_ATTRS + * N - NFS4_ACE_WRITE_NAMED_ATTRS + * x - NFS4_ACE_EXECUTE + * D - NFS4_ACE_DELETE_CHILD + * t - NFS4_ACE_READ_ATTRIBUTES + * T - NFS4_ACE_WRITE_ATTRIBUTES + * d - NFS4_ACE_DELETE + * c - NFS4_ACE_READ_ACL + * C - NFS4_ACE_WRITE_ACL + * o - NFS4_ACE_WRITE_OWNER + * y - NFS4_ACE_SYNCHRONIZE + * + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + +void acl_nfs4_print(struct nfs4_acl * acl) +{ + struct nfs4_ace* ace; + int naces; + int ace_count = 0; + int result; + char * who; + u32 type; + u32 flag; + u32 mask; + + naces = acl_nfs4_entries(acl); + + ace = acl_nfs4_get_first_ace(acl); + + ace_count++; + + while(1) + { + if(ace == NULL) { + if( naces > ace_count ) + goto unexp_failed; + else + break; + } + + printf("%d: ", ace_count); + + result = acl_nfs4_get_type(ace, &type); + if(result != 0) + goto unexp_failed; + + switch(type) + { + case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE: + printf("A:"); + break; + case NFS4_ACE_ACCESS_DENIED_ACE_TYPE: + printf("D:"); + break; + case NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE: + printf("U:"); + break; + case NFS4_ACE_SYSTEM_ALARM_ACE_TYPE: + printf("L:"); + break; + default: + printf("Bad Ace Type:%d\n", type); + goto unexp_failed; + } + + result = acl_nfs4_get_flags(ace, &flag); + if(result != 0) + goto unexp_failed; + + if(flag & NFS4_ACE_FILE_INHERIT_ACE) + printf("f"); + if(flag & NFS4_ACE_DIRECTORY_INHERIT_ACE) + printf("d"); + if(flag & NFS4_ACE_NO_PROPAGATE_INHERIT_ACE) + printf("p"); + if(flag & NFS4_ACE_INHERIT_ONLY_ACE) + printf("i"); + if(flag & NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG) + printf("S"); + if(flag & NFS4_ACE_FAILED_ACCESS_ACE_FLAG) + printf("F"); + if(flag & NFS4_ACE_IDENTIFIER_GROUP) + printf("g"); + if(flag & NFS4_ACE_OWNER) + printf("O"); + if(flag & NFS4_ACE_GROUP) + printf("G"); + if(flag & NFS4_ACE_EVERYONE) + printf("E"); + + printf(":"); + + result = acl_nfs4_get_who(ace, NULL, &who); + if(result != 0) + goto unexp_failed; + + printf("%s:", who); + free(who); + + + + result = acl_nfs4_get_accessmask(ace, &mask); + if(result != 0) + goto unexp_failed; + + if (acl->is_directory) + { + if(mask & NFS4_ACE_LIST_DIRECTORY) + printf("l"); + if(mask & NFS4_ACE_ADD_FILE) + printf("f"); + if(mask & NFS4_ACE_ADD_SUBDIRECTORY) + printf("s"); + if(mask & NFS4_ACE_DELETE_CHILD) + printf("D"); + } + else + { + if(mask & NFS4_ACE_READ_DATA) + printf("r"); + if(mask & NFS4_ACE_WRITE_DATA) + printf("w"); + if(mask & NFS4_ACE_APPEND_DATA) + printf("a"); + } + if(mask & NFS4_ACE_READ_NAMED_ATTRS) + printf("n"); + if(mask & NFS4_ACE_WRITE_NAMED_ATTRS) + printf("N"); + if(mask & NFS4_ACE_EXECUTE) + printf("x"); + if(mask & NFS4_ACE_READ_ATTRIBUTES) + printf("t"); + if(mask & NFS4_ACE_WRITE_ATTRIBUTES) + printf("T"); + if(mask & NFS4_ACE_DELETE) + printf("d"); + if(mask & NFS4_ACE_READ_ACL) + printf("c"); + if(mask & NFS4_ACE_WRITE_ACL) + printf("C"); + if(mask & NFS4_ACE_WRITE_OWNER) + printf("o"); + if(mask & NFS4_ACE_SYNCHRONIZE) + printf("y"); + printf("\n"); + + acl_nfs4_get_next_ace(&ace); + + ace_count++; + } + + return; + +unexp_failed: + printf("An unexpected failure has occurred. \n"); + + return; +} diff --git a/libacl/acl_nfs4_print_ace.c b/libacl/acl_nfs4_print_ace.c new file mode 100644 index 0000000..e9d07c8 --- /dev/null +++ b/libacl/acl_nfs4_print_ace.c @@ -0,0 +1,202 @@ +/* + * NFSv4 ACL Code + * Print the contents of an nfs4 ACE + * + * Permission mapping: + * r - NFS4_ACE_READ_DATA + * l - NFS4_ACE_LIST_DIRECTORY + * w - NFS4_ACE_WRITE_DATA + * f - NFS4_ACE_ADD_FILE + * a - NFS4_ACE_APPEND_DATA + * s - NFS4_ACE_ADD_SUBDIRECTORY + * n - NFS4_ACE_READ_NAMED_ATTRS + * N - NFS4_ACE_WRITE_NAMED_ATTRS + * x - NFS4_ACE_EXECUTE + * D - NFS4_ACE_DELETE_CHILD + * t - NFS4_ACE_READ_ATTRIBUTES + * T - NFS4_ACE_WRITE_ATTRIBUTES + * d - NFS4_ACE_DELETE + * c - NFS4_ACE_READ_ACL + * C - NFS4_ACE_WRITE_ACL + * o - NFS4_ACE_WRITE_OWNER + * y - NFS4_ACE_SYNCHRONIZE + * + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +int acl_nfs4_print_ace(struct nfs4_ace * ace, u32 is_dir) +{ + int result; + char * who; + char * whotype_s; + char * type_s; + u32 type; + u32 flag; + u32 whotype; + u32 mask; + + + result = acl_nfs4_get_who(ace, &whotype, &who); + if(result != 0) + goto unexp_failed; + + switch(whotype) + { + case NFS4_ACL_WHO_NAMED: + whotype_s = "NFS4_ACL_WHO_NAMED"; + break; + case NFS4_ACL_WHO_OWNER: + whotype_s = "NFS4_ACL_WHO_OWNER"; + break; + case NFS4_ACL_WHO_GROUP: + whotype_s = "NFS4_ACL_WHO_GROUP"; + break; + case NFS4_ACL_WHO_EVERYONE: + whotype_s = "NFS4_ACL_WHO_EVERYONE"; + break; + default: + free(who); + printf("Bad whotype: %d", whotype); + goto unexp_failed; + } + printf(" Whotype:\t%s\n", whotype_s); + printf(" Who:\t\t%s\n", who); + free(who); + + result = acl_nfs4_get_type(ace, &type); + if(result != 0) + goto unexp_failed; + + switch(type) + { + case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE: + type_s = "ACCESS_ALLOWED"; + break; + case NFS4_ACE_ACCESS_DENIED_ACE_TYPE: + type_s = "ACCESS_DENIED"; + break; + case NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE: + type_s = "SYSTEM_AUDIT"; + break; + case NFS4_ACE_SYSTEM_ALARM_ACE_TYPE: + type_s = "SYSTEM_ALARM"; + break; + default: + printf("Bad Ace Type:%d\n", type); + goto unexp_failed; + } + printf(" Type:\t\t%s\n", type_s); + + result = acl_nfs4_get_flags(ace, &flag); + if(result != 0) + goto unexp_failed; + + printf(" Flags:\n"); + + if(flag & NFS4_ACE_FILE_INHERIT_ACE) + printf("\t\tNFS4_ACE_FILE_INHERIT_ACE\n"); + if(flag & NFS4_ACE_DIRECTORY_INHERIT_ACE) + printf("\t\tNFS4_ACE_DIRECTORY_INHERIT_ACE\n"); + if(flag & NFS4_ACE_NO_PROPAGATE_INHERIT_ACE) + printf("\t\tNFS4_ACE_NO_PROPAGATE_INHERIT_ACE\n"); + if(flag & NFS4_ACE_INHERIT_ONLY_ACE) + printf("\t\tNFS4_ACE_INHERIT_ONLY_ACE\n"); + if(flag & NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG) + printf("\t\tNFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG\n"); + if(flag & NFS4_ACE_FAILED_ACCESS_ACE_FLAG) + printf("\t\tNFS4_ACE_FAILED_ACCESS_ACE_FLAG\n"); + if(flag & NFS4_ACE_IDENTIFIER_GROUP) + printf("\t\tNFS4_ACE_IDENTIFIER_GROUP\n"); + if(flag & NFS4_ACE_OWNER) + printf("\t\tNFS4_ACE_OWNER\n"); + if(flag & NFS4_ACE_GROUP) + printf("\t\tNFS4_ACE_GROUP\n"); + if(flag & NFS4_ACE_EVERYONE) + printf("\t\tNFS4_ACE_EVERYONE\n"); + + result = acl_nfs4_get_accessmask(ace, &mask); + if(result != 0) + goto unexp_failed; + + printf(" Perms:\t"); + + if(is_dir & NFS4_ACL_ISDIR) + { + if(mask & NFS4_ACE_LIST_DIRECTORY) + printf("l"); + if(mask & NFS4_ACE_ADD_FILE) + printf("f"); + if(mask & NFS4_ACE_ADD_SUBDIRECTORY) + printf("s"); + if(mask & NFS4_ACE_DELETE_CHILD) + printf("D"); + } + else + { + if(mask & NFS4_ACE_READ_DATA) + printf("r"); + if(mask & NFS4_ACE_WRITE_DATA) + printf("w"); + if(mask & NFS4_ACE_APPEND_DATA) + printf("a"); + } + if(mask & NFS4_ACE_READ_NAMED_ATTRS) + printf("n"); + if(mask & NFS4_ACE_WRITE_NAMED_ATTRS) + printf("N"); + if(mask & NFS4_ACE_EXECUTE) + printf("x"); + if(mask & NFS4_ACE_READ_ATTRIBUTES) + printf("t"); + if(mask & NFS4_ACE_WRITE_ATTRIBUTES) + printf("T"); + if(mask & NFS4_ACE_DELETE) + printf("d"); + if(mask & NFS4_ACE_READ_ACL) + printf("c"); + if(mask & NFS4_ACE_WRITE_ACL) + printf("C"); + if(mask & NFS4_ACE_WRITE_OWNER) + printf("o"); + if(mask & NFS4_ACE_SYNCHRONIZE) + printf("y"); + printf("\n"); + + return 0; + +unexp_failed: + return -1; +} + diff --git a/libacl/acl_nfs4_print_fd.c b/libacl/acl_nfs4_print_fd.c new file mode 100644 index 0000000..299e571 --- /dev/null +++ b/libacl/acl_nfs4_print_fd.c @@ -0,0 +1,210 @@ +/* + * NFSv4 ACL Code + * Print the contents of an nfs4 ACL to a particular file descriptor + * + * Permission mapping: + * r - NFS4_ACE_READ_DATA + * l - NFS4_ACE_LIST_DIRECTORY + * w - NFS4_ACE_WRITE_DATA + * f - NFS4_ACE_ADD_FILE + * a - NFS4_ACE_APPEND_DATA + * s - NFS4_ACE_ADD_SUBDIRECTORY + * n - NFS4_ACE_READ_NAMED_ATTRS + * N - NFS4_ACE_WRITE_NAMED_ATTRS + * x - NFS4_ACE_EXECUTE + * D - NFS4_ACE_DELETE_CHILD + * t - NFS4_ACE_READ_ATTRIBUTES + * T - NFS4_ACE_WRITE_ATTRIBUTES + * d - NFS4_ACE_DELETE + * c - NFS4_ACE_READ_ACL + * C - NFS4_ACE_WRITE_ACL + * o - NFS4_ACE_WRITE_OWNER + * y - NFS4_ACE_SYNCHRONIZE + * + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + +int acl_nfs4_print_fd(struct nfs4_acl * acl, FILE *fd) +{ + struct nfs4_ace* ace; + int naces; + int ace_count = 0; + int result; + char * who; + u32 type; + u32 flag; + u32 mask; + + if((acl == NULL) || (fd == NULL)) + { + errno= EINVAL; + goto unexp_failed; + } + + naces = acl_nfs4_entries(acl); + + ace = acl_nfs4_get_first_ace(acl); + + ace_count++; + + while(1) + { + if(ace == NULL) { + if( naces > ace_count ) + goto unexp_failed; + else + break; + } + + fprintf(fd, "%d: ", ace_count); + + result = acl_nfs4_get_type(ace, &type); + if(result != 0) + goto unexp_failed; + + switch(type) + { + case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE: + fprintf(fd, "A:"); + break; + case NFS4_ACE_ACCESS_DENIED_ACE_TYPE: + fprintf(fd, "D:"); + break; + case NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE: + fprintf(fd, "U:"); + break; + case NFS4_ACE_SYSTEM_ALARM_ACE_TYPE: + fprintf(fd, "L:"); + break; + default: + fprintf(fd, "Bad Ace Type:%d\n", type); + goto unexp_failed; + } + + result = acl_nfs4_get_flags(ace, &flag); + if(result != 0) + goto unexp_failed; + + if(flag & NFS4_ACE_FILE_INHERIT_ACE) + fprintf(fd, "f"); + if(flag & NFS4_ACE_DIRECTORY_INHERIT_ACE) + fprintf(fd, "d"); + if(flag & NFS4_ACE_NO_PROPAGATE_INHERIT_ACE) + fprintf(fd, "p"); + if(flag & NFS4_ACE_INHERIT_ONLY_ACE) + fprintf(fd, "i"); + if(flag & NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG) + fprintf(fd, "S"); + if(flag & NFS4_ACE_FAILED_ACCESS_ACE_FLAG) + fprintf(fd, "F"); + if(flag & NFS4_ACE_IDENTIFIER_GROUP) + fprintf(fd, "g"); + if(flag & NFS4_ACE_OWNER) + fprintf(fd, "O"); + if(flag & NFS4_ACE_GROUP) + fprintf(fd, "G"); + if(flag & NFS4_ACE_EVERYONE) + fprintf(fd, "E"); + + fprintf(fd, ":"); + + result = acl_nfs4_get_who(ace, NULL, &who); + if(result != 0) + goto unexp_failed; + + fprintf(fd, "%s:", who); + free(who); + + + + result = acl_nfs4_get_accessmask(ace, &mask); + if(result != 0) + goto unexp_failed; + + if(acl->is_directory) + { + if(mask & NFS4_ACE_LIST_DIRECTORY) + fprintf(fd, "l"); + if(mask & NFS4_ACE_ADD_FILE) + fprintf(fd, "f"); + if(mask & NFS4_ACE_ADD_SUBDIRECTORY) + fprintf(fd, "s"); + if(mask & NFS4_ACE_DELETE_CHILD) + fprintf(fd, "D"); + } + else + { + if(mask & NFS4_ACE_READ_DATA) + fprintf(fd, "r"); + if(mask & NFS4_ACE_WRITE_DATA) + fprintf(fd, "w"); + if(mask & NFS4_ACE_APPEND_DATA) + fprintf(fd, "a"); + } + if(mask & NFS4_ACE_READ_NAMED_ATTRS) + fprintf(fd, "n"); + if(mask & NFS4_ACE_WRITE_NAMED_ATTRS) + fprintf(fd, "N"); + if(mask & NFS4_ACE_EXECUTE) + fprintf(fd, "x"); + if(mask & NFS4_ACE_READ_ATTRIBUTES) + fprintf(fd, "t"); + if(mask & NFS4_ACE_WRITE_ATTRIBUTES) + fprintf(fd, "T"); + if(mask & NFS4_ACE_DELETE) + fprintf(fd, "d"); + if(mask & NFS4_ACE_READ_ACL) + fprintf(fd, "c"); + if(mask & NFS4_ACE_WRITE_ACL) + fprintf(fd, "C"); + if(mask & NFS4_ACE_WRITE_OWNER) + fprintf(fd, "o"); + if(mask & NFS4_ACE_SYNCHRONIZE) + fprintf(fd, "y"); + fprintf(fd, "\n"); + + acl_nfs4_get_next_ace(&ace); + + ace_count++; + } + + return 0; + +unexp_failed: + printf("An unexpected failure has occurred. \n"); + + return -1; +} diff --git a/libacl/acl_nfs4_remove_ace.c b/libacl/acl_nfs4_remove_ace.c new file mode 100644 index 0000000..dc4bc48 --- /dev/null +++ b/libacl/acl_nfs4_remove_ace.c @@ -0,0 +1,50 @@ +/* + * NFSv4 ACL Code + * Remove an ace from an NFS4 ACL + * + * Copyright (c) 2004 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, the following disclaimer, and + * any and all other licensing or copyright notices included in + * any files in this distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "libacl_nfs4.h" + +int acl_nfs4_remove_ace(struct nfs4_acl * acl, struct nfs4_ace * ace) +{ + TAILQ_REMOVE( &acl->ace_head, ace, l_ace); + free(ace->who); + free(ace); + acl->naces--; + + return 0; +} + diff --git a/libacl/acl_nfs4_set_who.c b/libacl/acl_nfs4_set_who.c new file mode 100644 index 0000000..c0ddfa7 --- /dev/null +++ b/libacl/acl_nfs4_set_who.c @@ -0,0 +1,92 @@ +/* + * NFSv4 ACL Code + * Write the who entry in the nfs4 ace. Who is a user supplied buffer + * containing a named who entry (null terminated string) if type is + * set to NFS4_ACL_WHO_NAMED. Otherwise, the who buffer is not used. + * The user supplied who buffer must be freed by the caller. + * + * This code allocates the who buffer used in the ace. This must be freed + * upon ace removal by the ace_remove or acl_free. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libacl_nfs4.h" + +int acl_nfs4_set_who(struct nfs4_ace* ace, int type, char* who) +{ + char* iwho = NULL; + int wholen; + + if(ace == NULL) + goto inval_failed; + + switch(type) + { + case NFS4_ACL_WHO_NAMED: + if(who == NULL) + goto inval_failed; + iwho = who; + break; + case NFS4_ACL_WHO_OWNER: + iwho = NFS4_ACL_WHO_OWNER_STRING; + break; + case NFS4_ACL_WHO_GROUP: + iwho = NFS4_ACL_WHO_GROUP_STRING; + break; + case NFS4_ACL_WHO_EVERYONE: + iwho = NFS4_ACL_WHO_EVERYONE_STRING; + break; + default: + goto inval_failed; + } + + wholen = strlen(iwho); + if(wholen < 1) + goto inval_failed; + + ace->who = (char *) malloc(sizeof(char) * (wholen + 1)); + if(ace->who == NULL) { + errno = ENOMEM; + goto failed; + } + + strcpy(ace->who, iwho); + + return 0; + +inval_failed: + errno = EINVAL; + +failed: + return -1; +} + diff --git a/libacl/acl_nfs4_string2ace.c b/libacl/acl_nfs4_string2ace.c new file mode 100644 index 0000000..101bc73 --- /dev/null +++ b/libacl/acl_nfs4_string2ace.c @@ -0,0 +1,297 @@ +/* + * NFSv4 ACL Code + * Print the contents of an nfs4 ACE + * + * Permission mapping: + * r - NFS4_ACE_READ_DATA + * l - NFS4_ACE_LIST_DIRECTORY + * w - NFS4_ACE_WRITE_DATA + * f - NFS4_ACE_ADD_FILE + * a - NFS4_ACE_APPEND_DATA + * s - NFS4_ACE_ADD_SUBDIRECTORY + * n - NFS4_ACE_READ_NAMED_ATTRS + * N - NFS4_ACE_WRITE_NAMED_ATTRS + * x - NFS4_ACE_EXECUTE + * D - NFS4_ACE_DELETE_CHILD + * t - NFS4_ACE_READ_ATTRIBUTES + * T - NFS4_ACE_WRITE_ATTRIBUTES + * d - NFS4_ACE_DELETE + * c - NFS4_ACE_READ_ACL + * C - NFS4_ACE_WRITE_ACL + * o - NFS4_ACE_WRITE_OWNER + * y - NFS4_ACE_SYNCHRONIZE + * + * + * Copyright (c) 2005 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +/* + * An array of pointers to hold the parsed acetype, aceflag, acewho and + * acemask. + */ +#define NUMFIELDS 4 +#define TYPE_INDEX 0 +#define FLAG_INDEX 1 +#define WHO_INDEX 2 +#define MASK_INDEX 3 + +void +free_fields(char *fields[NUMFIELDS]) +{ +int i; + + for(i=0; i< NUMFIELDS; i++) + if(fields[i] != NULL) + free(fields[i]); +} + +int +parse_alloc_fields(char *buf, char *fields[NUMFIELDS]) +{ + char *prev, *next; + int len, i,j; + + if (!buf) + return -EINVAL; + + memset(fields, 0, sizeof(fields)); + prev = buf; + for(i=0; i < 3; i++) { + next = strchr(prev, ':'); + len = next - prev; + for(j=0; j 0) + memcpy(fields[i], prev, len); + fields[i][len] = 0; + prev = ++next; + } + next = strchr(prev, '\n'); + len = next - prev; + fields[NUMFIELDS - 1] = malloc(len + 1); + if (len > 0) + memcpy(fields[NUMFIELDS - 1], prev, len); + fields[NUMFIELDS - 1][len] = 0; + return 0; +out_free: + free_fields(fields); + return -ENOMEM; +} + +/* + * returns the length of acewho on success, -1 on failure + */ + +int acl_nfs4_string2ace(char *ace_buf, struct nfs4_acl **nacl_p) +{ + int ret, is_dir = (*nacl_p)->is_directory; + char *fields[NUMFIELDS]; + u32 type, flags = 0, mask = 0; + char *bufp; + int buflen; + + /* remove ace index number */ + bufp = strchr(ace_buf, ':'); + bufp++; + + ret = parse_alloc_fields(bufp, fields); + if (ret < 0) { + printf("Scanning ACE string %s failed\n", bufp); + goto out_fail; + } + + switch(*fields[TYPE_INDEX]) + { + case 'A': + type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; + break; + case 'D': + type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; + break; + case 'U': + type = NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE; + break; + case 'L': + type = NFS4_ACE_SYSTEM_ALARM_ACE_TYPE; + break; + default: + printf("Bad Ace Type:%c\n", *fields[TYPE_INDEX]); + goto out_fail; + } + + bufp = fields[FLAG_INDEX]; + for( buflen = strlen(fields[FLAG_INDEX]); buflen > 0; buflen--) + { + switch(*bufp) + { + case 'f': + flags |= NFS4_ACE_FILE_INHERIT_ACE; + break; + case 'd': + flags |= NFS4_ACE_DIRECTORY_INHERIT_ACE; + break; + case 'p': + flags |= NFS4_ACE_NO_PROPAGATE_INHERIT_ACE; + break; + case 'i': + flags |= NFS4_ACE_INHERIT_ONLY_ACE; + break; + case 'S': + flags |= NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG; + break; + case 'F': + flags |= NFS4_ACE_FAILED_ACCESS_ACE_FLAG; + break; + case 'g': + flags |= NFS4_ACE_IDENTIFIER_GROUP; + break; + case 'O': + flags |= NFS4_ACE_OWNER; + break; + case 'G': + flags |= NFS4_ACE_GROUP; + break; + case 'E': + flags |= NFS4_ACE_EVERYONE; + break; + default: + printf("Bad Ace Type:%c\n", *bufp); + goto out_fail; + } + bufp++; + } + + bufp = fields[MASK_INDEX]; + for( buflen = strlen(fields[MASK_INDEX]); buflen > 0; buflen--) + { + ret = -EINVAL; + switch(*bufp) + { + case 'l': + if(!(is_dir & NFS4_ACL_ISDIR)) + goto out_not_dir; + mask |= NFS4_ACE_LIST_DIRECTORY; + break; + case 'f': + if(!(is_dir & NFS4_ACL_ISDIR)) + goto out_not_dir; + mask |= NFS4_ACE_ADD_FILE; + break; + case 's': + if(!(is_dir & NFS4_ACL_ISDIR)) + goto out_not_dir; + mask |= NFS4_ACE_ADD_SUBDIRECTORY; + break; + case 'D': + if(!(is_dir & NFS4_ACL_ISDIR)) + goto out_not_dir; + mask |= NFS4_ACE_DELETE_CHILD; + break; + case 'r': + if((is_dir & NFS4_ACL_ISFILE)) + goto out_not_file; + mask |= NFS4_ACE_READ_DATA; + break; + case 'w': + if((is_dir & NFS4_ACL_ISFILE)) + goto out_not_file; + mask |= NFS4_ACE_WRITE_DATA; + break; + case 'a': + if((is_dir & NFS4_ACL_ISFILE)) + goto out_not_file; + mask |= NFS4_ACE_APPEND_DATA; + break; + case 'n': + mask |= NFS4_ACE_READ_NAMED_ATTRS; + break; + case 'N': + mask |= NFS4_ACE_WRITE_NAMED_ATTRS; + break; + case 'x': + mask |= NFS4_ACE_EXECUTE; + break; + case 't': + mask |= NFS4_ACE_READ_ATTRIBUTES; + break; + case 'T': + mask |= NFS4_ACE_WRITE_ATTRIBUTES; + break; + case 'd': + mask |= NFS4_ACE_DELETE; + break; + case 'c': + mask |= NFS4_ACE_READ_ACL; + break; + case 'C': + mask |= NFS4_ACE_WRITE_ACL; + break; + case 'o': + mask |= NFS4_ACE_WRITE_OWNER; + break; + case 'y': + mask |= NFS4_ACE_SYNCHRONIZE; + break; + default: + printf("Bad Ace Mask:%c\n", *bufp); + goto out_fail; + } + bufp++; + } + + if(acl_nfs4_add_ace(*nacl_p, type, flags, mask, + acl_nfs4_get_whotype(fields[WHO_INDEX]), + fields[WHO_INDEX]) < 0) { + goto out_fail; + } + + ret = strlen(fields[WHO_INDEX]); +out_fail: + free_fields(fields); + return ret; + +out_not_dir: + printf("Bad Ace Mask Directory %c mask on file\n", *bufp); + goto out_fail; +out_not_file: + printf("Bad Ace Mask File %c mask on Directory\n", *bufp); + goto out_fail; +} diff --git a/libacl/acl_nfs4_utils.c b/libacl/acl_nfs4_utils.c new file mode 100644 index 0000000..49238ee --- /dev/null +++ b/libacl/acl_nfs4_utils.c @@ -0,0 +1,566 @@ +#include +#include "libacl_nfs4.h" + +int user_obj_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace **n4ace, + acl_t *pacl, int iflags) +{ + struct nfs4_ace *ace = *n4ace; + struct nfs4_ace *ace2; + + if (ace == NULL) + goto inval_out; + + if (pacl == NULL || *pacl == NULL) + goto inval_out; + + if (acl_n4tp_get_whotype(ace) != ACL_USER_OBJ) + goto inval_out; + + if(acl_n4tp_ace_trans(ace, pacl, ACL_USER_OBJ, iflags|NFS4_ACL_OWNER) < 0) + goto out; + + ace2 = acl_nfs4_get_next_ace(n4ace); + if (ace2 == NULL) + goto inval_out; + + if (!complementary_ace_pair(ace, ace2)) + goto inval_out; + + ace2 = acl_nfs4_get_next_ace(n4ace); + + return 0; + +inval_out: + errno = EINVAL; +out: + return -1; +} + +/* public */ +inline struct nfs4_ace * acl_nfs4_get_next_ace(struct nfs4_ace ** ace) +{ + if(ace == NULL || (*ace) == NULL) + return NULL; + + (*ace) = (*ace)->l_ace.tqe_next; + return *ace; +} + +/* public */ +inline struct nfs4_ace * acl_nfs4_get_first_ace(struct nfs4_acl * acl) +{ + if(acl == NULL) + return NULL; + + return acl->ace_head.tqh_first; +} + + + + +int nfs4_get_gid_from_who(gid_t* gid, const char * who) +{ + int islocal; + int result; + + if(who == NULL || gid == NULL) { + errno = EINVAL; + goto failed; + } + + islocal = is_who_local(who); + if(islocal < 0) + goto failed; + else if (islocal == 1) + result = __nfs4_get_local_gid_from_who(gid, who); + else + result = __nfs4_get_foreign_gid_from_who(gid, who); + + if(result < 0) + goto failed; + + return 0; + +failed: + return -1; +} + +int __nfs4_get_local_gid_from_who(gid_t* gid, const char * who) +{ + /* XXX Just trim things at the @. We need to pull the local domain + * name from the conf file for comparison, and handle foriegn names + * as well. Tie this in with idmapd and gssvcd */ + /* Special whos? */ + + struct group * grent; + char * gname_buf = NULL; + int gname_buflen; + char * char_pos = NULL; + int char_posi; + + + if(who == NULL) { + errno = EINVAL; + goto failed; + } + + gname_buflen = strlen(who); + if(gname_buflen <= 0) { + errno = EINVAL; + goto failed; + } + + char_pos = strchr(who, '@'); + char_posi = char_pos - who; + + if((gname_buf = (char*) malloc(sizeof(char) * (char_posi + 1))) == NULL) + { + errno = ENOMEM; + goto failed; + } + + strncpy(gname_buf, who, char_posi); + gname_buf[char_posi] = '\0'; + + grent = getgrnam(gname_buf); + free(gname_buf); + + if(grent == NULL) + goto failed; + + *gid = grent->gr_gid; + + return 0; + +failed: + return -1; +} + +int __nfs4_get_foreign_gid_from_who(gid_t* gid, const char * who) +{ + return -1; +} + + +int nfs4_get_uid_from_who(uid_t* uid, const char * who) +{ + int islocal; + int result; + + if(who == NULL || uid == NULL) { + errno = EINVAL; + goto failed; + } + + islocal = is_who_local(who); + if(islocal < 0) + goto failed; + else if (islocal == 1) + result = __nfs4_get_local_uid_from_who(uid, who); + else + result = __nfs4_get_foreign_uid_from_who(uid, who); + + if(result < 0) + goto failed; + + return 0; + +failed: + return -1; +} + +int __nfs4_get_local_uid_from_who(uid_t* uid, const char * who) +{ + /* XXX Just trim things at the @. We need to pull the local domain + * name from the conf file for comparison, and handle foriegn names + * as well. Tie this in with idmapd and gssvcd */ + /* Special whos? */ + + char* lname_buf; + char* char_pos; + int lname_buflen; + struct passwd *pwent; + int char_posi; + + if(who == NULL) { + errno = EINVAL; + goto failed; + } + + lname_buflen = strlen(who); + if(lname_buflen <= 0) { + errno = EINVAL; + goto failed; + } + + char_pos = strchr(who, '@'); + char_posi = char_pos - who; + + if((lname_buf = (char*) malloc(sizeof(char) * (char_posi + 1))) == NULL) + { + errno = ENOMEM; + goto failed; + } + + strncpy(lname_buf, who, char_posi); + lname_buf[char_posi] = '\0'; + + pwent = getpwnam(lname_buf); + free(lname_buf); + + if(pwent == NULL) + goto failed; + + *uid = pwent->pw_uid; + + return 0; + +failed: + return -1; +} + + + +int is_who_local(const char * who) +{ + /* -1 on error, 0 for no, 1 for yes */ + /* TODO: Compare domain to local domain */ + if(who == NULL){ + errno = EINVAL; + return -1; + } + + if(strchr(who, '@') == NULL) { + errno = EINVAL; + return -1; + } + + return 1; +} + +int __nfs4_get_foreign_uid_from_who(uid_t* uid, const char * who) +{ + /* TODO: Make this work */ + return -1; +} + + + +int users_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + struct nfs4_ace **mask_ace, acl_t *pacl, int iflags) +{ + struct nfs4_ace *ace, *ace2; + int result; + + ace = *n4ace_p; + + if (ace == NULL) { + goto inval_failed; + } + + while (ace != NULL && acl_n4tp_get_whotype(ace) == ACL_USER) { + if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) + goto inval_failed; + if (*mask_ace && + !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask)) + goto inval_failed; + *mask_ace = ace; + + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) + goto inval_failed; + result = acl_n4tp_ace_trans(ace, pacl, ACL_USER, iflags); + if (result < 0) + goto failed; + + ace2 = acl_nfs4_get_next_ace(n4ace_p); + if (ace2 == NULL) + goto failed; + if (!complementary_ace_pair(ace, ace2)) + goto failed; + if ((*mask_ace)->flag != ace2->flag || + !same_who(*mask_ace, ace2)) + goto failed; + ace = acl_nfs4_get_next_ace(n4ace_p); + } + + return 0; + +inval_failed: + errno = EINVAL; + +failed: + return -1; +} + +int complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny) +{ + return MASK_EQUAL(allow->access_mask, ~deny->access_mask) && + allow->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && + deny->type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE && + allow->flag == deny->flag && + same_who(allow, deny); +} + +int same_who(struct nfs4_ace *a, struct nfs4_ace *b) +{ + if(!strcmp(a->who, b->who) && strlen(a->who) == strlen(b->who)) + return 1; + return 0; +} + +int group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, + struct nfs4_ace ** n4ace_p, struct nfs4_ace **mask_ace, + acl_t *pacl, int iflags) +{ + struct nfs4_ace *ace, *ace2; + int num_aces; + struct ace_container_list_head ace_list; + struct ace_container *ace_c = NULL; + int result; + + TAILQ_INIT(&ace_list); + + ace = *n4ace_p; + + num_aces = acl_n4tp_ace_count(n4acl); + + if(num_aces < 0) + goto inval_failed; + + /* group owner (mask and allow aces) */ + + if (num_aces != 3) { + /* then the group owner should be preceded by mask */ + if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) + goto inval_failed; + + /* If we already got a mask, and it doesn't match this one... */ + if (*mask_ace && + !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask)) + goto inval_failed; + *mask_ace = ace; + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + + if ((*mask_ace)->flag != ace->flag || !same_who(*mask_ace, ace)) + goto inval_failed; + } + + if (acl_n4tp_get_whotype(ace) != ACL_GROUP_OBJ) + goto inval_failed; + + if((ace_c = malloc(sizeof(struct ace_container))) == NULL) { + errno = ENOMEM; + goto failed; + } + ace_c->ace = ace; + + TAILQ_INSERT_TAIL(&ace_list, ace_c, l_ace); + + if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) + goto inval_failed; + + result = acl_n4tp_ace_trans(ace, pacl, ACL_GROUP_OBJ, iflags); + if (result < 0) + goto inval_failed; + + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + + /* groups (mask and allow aces) */ + + while (acl_n4tp_get_whotype(ace) == ACL_GROUP) { + if (*mask_ace == NULL) + goto inval_failed; + + if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE || + !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask)) + goto inval_failed; + *mask_ace = ace; + + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + + if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE || + !same_who(ace, *mask_ace)) + goto inval_failed; + + if((ace_c = malloc(sizeof(struct ace_container))) == NULL) { + errno = ENOMEM; + goto failed; + } + ace_c->ace = ace; + + TAILQ_INSERT_TAIL(&ace_list, ace_c, l_ace); + + result = acl_n4tp_ace_trans(ace, pacl, ACL_GROUP, iflags); + if (result < 0) + goto inval_failed; + + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + } + + /* group owner (deny ace) */ + + if (acl_n4tp_get_whotype(ace) != ACL_GROUP_OBJ) + goto inval_failed; + + ace_c = ace_list.tqh_first; + ace2 = ace_c->ace; + if (!complementary_ace_pair(ace2, ace)) + goto inval_failed; + TAILQ_REMOVE(&ace_list, ace_c, l_ace); + free(ace_c); + + /* groups (deny aces) */ + + while (!TAILQ_IS_EMPTY(ace_list)) { + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + if (acl_n4tp_get_whotype(ace) != ACL_GROUP) + goto inval_failed; + ace_c = ace_list.tqh_first; + ace2 = ace_c->ace; + if (!complementary_ace_pair(ace2, ace)) + goto inval_failed; + TAILQ_REMOVE(&ace_list, ace_c, l_ace); + free(ace_c); + } + + ace = acl_nfs4_get_next_ace(n4ace_p); + if (ace == NULL) + goto inval_failed; + if (acl_n4tp_get_whotype(ace) != ACL_OTHER) + goto inval_failed; + + return 0; + +inval_failed: + errno = EINVAL; + +failed: + while (!TAILQ_IS_EMPTY(ace_list)) { + ace_c = ace_list.tqh_first; + TAILQ_REMOVE(&ace_list, ace_c, l_ace); + free(ace_c); + } + return -1; +} + +int +other_from_v4(struct nfs4_acl *n4acl, + struct nfs4_ace ** n4ace_p, acl_t *pacl, int iflags) +{ + int result; + struct nfs4_ace *ace, *ace2; + + ace = *n4ace_p; + if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) + goto inval_failed; + + result = acl_n4tp_ace_trans(ace, pacl, ACL_OTHER, iflags); + if (result < 0) + goto failed; + + ace2 = acl_nfs4_get_next_ace(n4ace_p); + if (ace2 == NULL) + goto inval_failed; + + if (!complementary_ace_pair(ace, ace2)) + goto inval_failed; + + return 0; + +inval_failed: + errno = EINVAL; + +failed: + return -1; +} + +int mask_from_v4(struct nfs4_acl *n4acl, + struct nfs4_ace ** n4ace_p, struct nfs4_ace **mask_ace, + acl_t *pacl, int iflags) +{ + int result; + struct nfs4_ace *ace; + + ace = *n4ace_p; + if (acl_n4tp_ace_count(n4acl) != 3) { + if (*mask_ace == NULL) + goto inval_failed; + (*mask_ace)->access_mask = ~(*mask_ace)->access_mask; + + result = acl_n4tp_ace_trans(*mask_ace, pacl, ACL_MASK, iflags); + if(result < 0) + goto failed; + + //ace = acl_nfs4_get_next_ace(n4ace_p); + //if (ace == NULL) + // goto inval_failed; + } + + return 0; + +inval_failed: + errno = EINVAL; + +failed: + return -1; +} + + +/* +static inline int +match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who) +{ + switch (ace->whotype) { + case NFS4_ACL_WHO_NAMED: + return who == ace->who; + case NFS4_ACL_WHO_OWNER: + return who == owner; + case NFS4_ACL_WHO_GROUP: + return who == group; + case NFS4_ACL_WHO_EVERYONE: + return 1; + default: + return 0; + } +} +*/ +/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */ +/* +int +nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group, + uid_t who, u32 mask) +{ + struct nfs4_ace *ace; + u32 allowed = 0; + + list_for_each_entry(ace, &acl->ace_head, l_ace) { + if (!match_who(ace, group, owner, who)) + continue; + switch (ace->type) { + case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE: + allowed |= ace->access_mask; + if ((allowed & mask) == mask) + return 0; + break; + case NFS4_ACE_ACCESS_DENIED_ACE_TYPE: + if (ace->access_mask & mask) + return -EACCES; + break; + } + } + return -EACCES; +} +*/ diff --git a/libacl/acl_nfs4_xattr_load.c b/libacl/acl_nfs4_xattr_load.c new file mode 100644 index 0000000..e045cd2 --- /dev/null +++ b/libacl/acl_nfs4_xattr_load.c @@ -0,0 +1,191 @@ +/* + * NFSv4 ACL Code + * Convert NFSv4 xattr values to a posix ACL + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include "libacl_nfs4.h" + + +struct nfs4_acl * acl_nfs4_xattr_load( + char * xattr_v, + int xattr_size, + u32 is_dir) +{ + struct nfs4_acl * nacl_p; + char* bufp = xattr_v; + int bufs = xattr_size; + u32 ace_n; + u32 wholen; + char* who; + int d_ptr; + u32 num_aces; + + u32 type, flag, access_mask; + + if(xattr_size < sizeof(u32)) { + errno = EINVAL; + return NULL; + } + + if((nacl_p = acl_nfs4_new(is_dir)) == NULL) { + errno = ENOMEM; + return NULL; + } + + /* Grab the number of aces in the acl */ + num_aces = (u32)ntohl(*((u32*)(bufp))); + +#ifdef LIBACL_NFS4_DEBUG + printf(" Got number of aces: %d\n", nacl_p->naces); +#endif + + + d_ptr = sizeof(u32); + bufp += d_ptr; + bufs -= d_ptr; + + for(ace_n = 0; num_aces > ace_n ; ace_n++) + { +#ifdef LIBACL_NFS4_DEBUG + printf(" Getting Ace #%d of %d\n", ace_n, num_aces); +#endif + /* Get the acl type */ + if(bufs <= 0) { + errno = EINVAL; + goto bad_xattr_val; + } + + type = (u32)ntohl(*((u32*)bufp)); +#ifdef LIBACL_NFS4_DEBUG + printf(" Type: %x\n", type); +#endif + + d_ptr = sizeof(u32); + bufp += d_ptr; + bufs -= d_ptr; + + /* Get the acl flag */ + if(bufs <= 0) { + errno = EINVAL; + goto bad_xattr_val; + } + + flag = (u32)ntohl(*((u32*)bufp)); +#ifdef LIBACL_NFS4_DEBUG + printf(" Flag: %x\n", flag); +#endif + + bufp += d_ptr; + bufs -= d_ptr; + + /* Get the access mask */ + + if(bufs <= 0) { + errno = EINVAL; + goto bad_xattr_val; + } + + access_mask = (u32)ntohl(*((u32*)bufp)); +#ifdef LIBACL_NFS4_DEBUG + printf(" Access Mask: %x\n", access_mask); +#endif + + bufp += d_ptr; + bufs -= d_ptr; + + /* Get the who string length*/ + if(bufs <= 0) { + errno = EINVAL; + goto bad_xattr_val; + } + + wholen = (u32)ntohl(*((u32*)bufp)); +#ifdef LIBACL_NFS4_DEBUG + printf(" Wholen: %d\n", wholen); +#endif + + bufp += d_ptr; + bufs -= d_ptr; + + /* Get the who string */ + if(bufs <= 0) { + errno = EINVAL; + goto bad_xattr_val; + } + + who = (char *) malloc((wholen+1) * sizeof(char)); + if(who == NULL) + { + errno = ENOMEM; + goto bad_xattr_val; + } + + memcpy(who, bufp, wholen); + + who[wholen] = '\0'; + +#ifdef LIBACL_NFS4_DEBUG + printf(" Who: %s\n", who); +#endif + + d_ptr = ((wholen / sizeof(u32))*sizeof(u32)); + if(wholen % sizeof(u32) != 0) + d_ptr += sizeof(u32); + + bufp += d_ptr; + bufs -= d_ptr; + + /* Make sure we aren't outside our domain */ + if(bufs < 0) { + free(who); + goto bad_xattr_val; + } + + if(acl_nfs4_add_ace(nacl_p, type, flag, access_mask, acl_nfs4_get_whotype(who), who) < 0) { + free(who); + goto bad_xattr_val; + } + + free(who); + } + + return nacl_p; + +bad_xattr_val: + /* We bailed for some reason */ + acl_nfs4_free(nacl_p); + return NULL; +} diff --git a/libacl/acl_nfs4_xattr_pack.c b/libacl/acl_nfs4_xattr_pack.c new file mode 100644 index 0000000..4fb705e --- /dev/null +++ b/libacl/acl_nfs4_xattr_pack.c @@ -0,0 +1,163 @@ +/* + * NFSv4 ACL Code + * Pack an NFS4 ACL into an XDR encoded buffer. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +int acl_nfs4_xattr_pack(struct nfs4_acl * acl, char** bufp) +{ + struct nfs4_ace * ace; + int buflen; + int rbuflen; + int num_aces; + int ace_num; + int wholen; + int result; + char* p; + char* who; + u32 tmp; + + if(acl == NULL || bufp == NULL) + { + errno = EINVAL; + goto failed; + } + + buflen = acl_nfs4_xattr_size(acl); + if(buflen < 0) + { + goto failed; + } + + *bufp = (char*) malloc(buflen); + if(*bufp == NULL) { + errno = ENOMEM; + goto failed; + } + + p = *bufp; + + num_aces = acl_nfs4_entries(acl); + + *((u32*)p) = htonl(num_aces); + + rbuflen = sizeof(u32); + p += sizeof(u32); + + ace = acl_nfs4_get_first_ace(acl); + ace_num = 1; + + while(1) + { + if(ace == NULL) + { + if(ace_num > num_aces) { + break; + } else { + errno = ENODATA; + goto failed; + } + } + + result = acl_nfs4_get_type(ace, &tmp); + if(result < 0) { + goto free_failed; + } + *((u32*)p) = htonl(tmp); + p += sizeof(u32); + rbuflen += sizeof(u32); + + result = acl_nfs4_get_flags(ace, &tmp); + if(result < 0) { + goto free_failed; + } + + *((u32*)p) = htonl(tmp); + p += sizeof(u32); + rbuflen += sizeof(u32); + + result = acl_nfs4_get_accessmask(ace, &tmp); + if(result < 0) { + goto free_failed; + } + + *((u32*)p) = htonl(tmp); + p += sizeof(u32); + rbuflen += sizeof(u32); + + result = acl_nfs4_get_who(ace, NULL, &who); + if(result < 0) { + goto free_failed; + } + + wholen = strlen(who); + *((u32*)p) = htonl(wholen); + rbuflen += sizeof(u32); + + p += sizeof(u32); + + memcpy(p, who, wholen); + free(who); + + p += (wholen / NFS4_XDR_MOD) * NFS4_XDR_MOD; + if(wholen % NFS4_XDR_MOD) { + p += NFS4_XDR_MOD; + } + + rbuflen += (wholen / NFS4_XDR_MOD) * NFS4_XDR_MOD; + if(wholen % NFS4_XDR_MOD) { + rbuflen += NFS4_XDR_MOD; + } + + acl_nfs4_get_next_ace(&ace); + ace_num++; + } + + if (buflen != rbuflen) + { + goto free_failed; + } + return buflen; + +free_failed: + free(*bufp); + *bufp = NULL; + +failed: + return -1; +} + + + diff --git a/libacl/acl_nfs4_xattr_size.c b/libacl/acl_nfs4_xattr_size.c new file mode 100644 index 0000000..f8c82ec --- /dev/null +++ b/libacl/acl_nfs4_xattr_size.c @@ -0,0 +1,91 @@ +/* + * NFSv4 ACL Code + * Return the expected xattr XDR encoded size of the nfs acl. Used for + * figuring the size of the xattr buffer. + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +int acl_nfs4_xattr_size(struct nfs4_acl * acl) +{ + int size = 0; + struct nfs4_ace * ace; + int ace_num; + int num_aces; + + if(acl == NULL) { + errno = EINVAL; + goto failed; + } + + /* Space for number of aces */ + size += sizeof(u32); + + ace = acl_nfs4_get_first_ace(acl); + ace_num = 1; + + num_aces = acl_nfs4_entries(acl); + + while(1) + { + if(ace == NULL) { + if(ace_num > num_aces) { + break; + } else { + errno = ENODATA; + goto failed; + } + } + + /* space for type, flag, and mask */ + size += (3 * sizeof(u32)); + + /* space for strlen */ + size += sizeof(u32); + + /* space for the who string... xdr encoded */ + size += (strlen(ace->who) / NFS4_XDR_MOD) * NFS4_XDR_MOD * sizeof(char); + if(strlen(ace->who) % NFS4_XDR_MOD) { + size += NFS4_XDR_MOD; + } + + acl_nfs4_get_next_ace(&ace); + ace_num++; + } + + return size; + +failed: + return -1; +} + diff --git a/libacl/acl_ptn4_acl_trans.c b/libacl/acl_ptn4_acl_trans.c new file mode 100644 index 0000000..21bc3b9 --- /dev/null +++ b/libacl/acl_ptn4_acl_trans.c @@ -0,0 +1,505 @@ +/* + * NFSv4 ACL Code + * Convert a posix ACL to an NFSv4 ACL + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * J. Bruce Fields + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "libacl_nfs4.h" + +struct nfs4_acl * +acl_ptn4_acl_trans(acl_t pacl, acl_type_t type, u32 is_dir, char *nfs_domain) +{ + struct nfs4_acl *acl; + int eflag; + u32 mask, mask_mask = 0; + int num_aces; + int result, result2; + u32 iflags = NFS4_ACL_NOFLAGS; + + acl_entry_t pace_p; + acl_tag_t ace_type; + acl_permset_t perms; + + char who_buf_static[NFS4_ACL_WHO_BUFFER_LEN_GUESS]; + char *who_buf = NULL; + int who_buflen; + int who_buflen_static = NFS4_ACL_WHO_BUFFER_LEN_GUESS; + uid_t * uid_p; + gid_t * gid_p; + + eflag = 0; + + if(type == ACL_TYPE_DEFAULT) + { + eflag = NFS4_INHERITANCE_FLAGS; + iflags |= NFS4_ACL_REQUEST_DEFAULT; + } + + if(is_dir & NFS4_ACL_ISDIR) + { + iflags |= NFS4_ACL_ISDIR; + } + + + if (pacl == NULL || (acl_valid(pacl) < 0 || acl_entries(pacl) == 0)) { + errno = EINVAL; + goto failed; + } + + acl = acl_nfs4_new(is_dir); + if (acl == NULL) { + errno = ENOMEM; + goto failed; + } + + /* Start Conversion */ + + /* 3 aces minimum (mode bits) */ + num_aces = acl_entries(pacl); + if(num_aces < 3) { + errno = EINVAL; + goto free_failed; + } + + /* Get the mask entry */ + + result = acl_get_entry(pacl, ACL_FIRST_ENTRY, &pace_p); + if(result < 0) + goto free_failed; + + while(result > 0 && mask_mask == 0) { + result = acl_get_tag_type(pace_p, &ace_type); + if(result < 0) + goto free_failed; + + if(ace_type == ACL_MASK) { + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask_mask, perms, iflags); + if(result < 0) + goto free_failed; + + mask_mask = ~mask_mask; + } + + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result < 0) + goto free_failed; + } + + /* Get the file owner entry */ + result = acl_get_entry(pacl, ACL_FIRST_ENTRY, &pace_p); + if(result < 0) + goto free_failed; + + result = acl_get_tag_type(pace_p, &ace_type); + if(result < 0) + goto free_failed; + + if(ace_type != ACL_USER_OBJ) { + errno = EINVAL; + goto free_failed; + } + + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags | NFS4_ACL_OWNER); + if(result < 0) + goto free_failed; + + result = acl_nfs4_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, NULL); + + if (result < 0) + goto free_failed; + + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result < 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + + while (ace_type == ACL_USER && result > 0) { + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags); + if(result < 0) + goto free_failed; + + uid_p = acl_get_qualifier(pace_p); + + who_buf = who_buf_static; + who_buflen = who_buflen_static; + + result = nfs4_init_name_mapping(NULL); + result = nfs4_uid_to_name(*uid_p, nfs_domain, who_buf, who_buflen); + + + while(result == -ENOBUFS) + { + if(who_buf != who_buf_static) + { + free(who_buf); + } + + /* Increase the size by a full buflen unit */ + who_buflen += who_buflen_static; + who_buf = malloc(who_buflen); + + if(who_buf == NULL) + { + result = -ENOMEM; + break; + } + + result = nfs4_init_name_mapping(NULL); + result = nfs4_uid_to_name(*uid_p, nfs_domain, who_buf, who_buflen); + + } + acl_free(uid_p); + if(result < 0) + { + errno = -result; + goto free_failed; + } + + if(who_buf == NULL) + goto free_failed; + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, + eflag, mask_mask, NFS4_ACL_WHO_NAMED, who_buf); + if (result < 0) { + if(who_buf != who_buf_static) + { + free(who_buf); + } + goto free_failed; + } + + result = acl_nfs4_add_pair(acl, eflag, mask, NFS4_ACL_WHO_NAMED, + who_buf); + if(who_buf != who_buf_static) + { + free(who_buf); + } + if (result < 0) + goto free_failed; + + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + + } + + /* In the case of groups, we apply allow ACEs first, then deny ACEs, + * since a user can be in more than one group. */ + + /* allow ACEs */ + + if (num_aces > 3) { + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + + if(ace_type != ACL_GROUP_OBJ) { + errno = EINVAL; + goto free_failed; + } + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, + NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, + NFS4_ACL_WHO_GROUP, NULL); + + if (result < 0) + goto free_failed; + } + + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags); + if(result < 0) + goto free_failed; + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, + NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, NFS4_ACL_WHO_GROUP, NULL); + + if (result < 0) + goto free_failed; + + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + + while (ace_type == ACL_GROUP && result > 0) { + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags); + if(result < 0) + goto free_failed; + + gid_p = acl_get_qualifier(pace_p); + + who_buf = who_buf_static; + who_buflen = who_buflen_static; + + result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen); + + + while(result == -ENOBUFS) + { + if(who_buf != who_buf_static) + { + free(who_buf); + } + + /* Increase the size by a full buflen unit */ + who_buflen += who_buflen_static; + who_buf = malloc(who_buflen); + + if(who_buf == NULL) + { + result = -ENOMEM; + break; + } + + result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen); + } + + acl_free(gid_p); + + if(result < 0) + { + errno = -result; + goto free_failed; + } + + if(who_buf == NULL) + goto free_failed; + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, + NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, + NFS4_ACL_WHO_NAMED, who_buf); + if (result < 0) { + if(who_buf != who_buf_static) + { + free(who_buf); + } + goto free_failed; + } + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, + NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, + NFS4_ACL_WHO_NAMED, who_buf); + + if(who_buf != who_buf_static) + { + free(who_buf); + } + + if (result < 0) + goto free_failed; + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + } + + /* deny ACEs */ + + result = acl_get_entry(pacl, ACL_FIRST_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + + while(ace_type != ACL_GROUP_OBJ && result > 0) { + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + } + + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags); + if(result < 0) + goto free_failed; + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, + NFS4_ACE_IDENTIFIER_GROUP | eflag, ~mask, NFS4_ACL_WHO_GROUP, + NULL); + + if (result < 0) + goto free_failed; + + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + + while (ace_type == ACL_GROUP && result > 0) { + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags); + if(result < 0) + goto free_failed; + + gid_p = acl_get_qualifier(pace_p); + + who_buf = who_buf_static; + who_buflen = who_buflen_static; + + result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen); + + + while(result == -ENOBUFS) + { + if(who_buf != who_buf_static) + { + free(who_buf); + } + + /* Increase the size by a full buflen unit */ + who_buflen += who_buflen_static; + who_buf = malloc(who_buflen); + + if(who_buf == NULL) + { + result = -ENOMEM; + break; + } + + result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen); + } + + acl_free(gid_p); + + if(result < 0) + { + errno = -result; + goto free_failed; + } + + if(who_buf == NULL) + goto free_failed; + + result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, + NFS4_ACE_IDENTIFIER_GROUP | eflag, ~mask, + NFS4_ACL_WHO_NAMED, who_buf); + if(who_buf != who_buf_static) + { + free(who_buf); + } + if (result < 0) + goto free_failed; + + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + } + + if(ace_type == ACL_MASK) { + result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p); + if(result <= 0) + goto free_failed; + + result2 = acl_get_tag_type(pace_p, &ace_type); + if(result2 < 0) + goto free_failed; + } + + if(ace_type != ACL_OTHER) { + errno = EINVAL; + goto free_failed; + } + + result = acl_get_permset(pace_p, &perms); + if(result < 0) + goto free_failed; + + result = acl_ptn4_get_mask(&mask, perms, iflags); + if(result < 0) + goto free_failed; + + result = acl_nfs4_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, NULL); + + return acl; + +free_failed: + acl_nfs4_free(acl); + +failed: + return NULL; +} + + diff --git a/libacl/acl_ptn4_get_mask.c b/libacl/acl_ptn4_get_mask.c new file mode 100644 index 0000000..bee0a97 --- /dev/null +++ b/libacl/acl_ptn4_get_mask.c @@ -0,0 +1,81 @@ +/* + * NFSv4 ACL Code + * Translate POSIX permissions to an NFSv4 mask + * + * Copyright (c) 2002, 2003 The Regents of the University of Michigan. + * All rights reserved. + * + * Nathaniel Gallaher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +int acl_ptn4_get_mask(u32* mask, acl_permset_t perms, int iflags) +{ + int result; + + *mask = NFS4_ANYONE_MODE; + + if(perms == NULL) { + errno = EINVAL; + goto failed; + } + + if (iflags & NFS4_ACL_OWNER) + *mask |= NFS4_OWNER_MODE; + + result = acl_get_perm(perms, ACL_READ); + if(result < 0) + goto failed; + else if(result == 1) + *mask |= NFS4_READ_MODE; + + result = acl_get_perm(perms, ACL_WRITE); + if(result < 0) + goto failed; + else if(result == 1) { + *mask |= NFS4_WRITE_MODE; + if(iflags & NFS4_ACL_ISDIR) + *mask |= NFS4_ACE_DELETE_CHILD; + } + + result = acl_get_perm(perms, ACL_EXECUTE); + if(result < 0) + goto failed; + else if(result == 1) + *mask |= NFS4_EXECUTE_MODE; + + return 0; + +failed: + return -1; +} + + + diff --git a/libacl/acl_set_fd.c b/libacl/acl_set_fd.c index 7df0c17..f71cbbe 100644 --- a/libacl/acl_set_fd.c +++ b/libacl/acl_set_fd.c @@ -24,6 +24,11 @@ #include #include "libacl.h" #include "__acl_to_xattr.h" +#ifdef USE_NFSV4_TRANS + #include "libacl_nfs4.h" + #include +#endif + #include "byteorder.h" #include "acl_ea.h" @@ -37,10 +42,38 @@ acl_set_fd(int fd, acl_t acl) const char *name = ACL_EA_ACCESS; size_t size; int error; +#ifdef USE_NFSV4_TRANS + int retval; + struct nfs4_acl * nacl; +#endif if (!acl_obj_p) return -1; + +#ifdef USE_NFSV4_TRANS + retval = fgetxattr(fd, ACL_NFS4_XATTR, NULL, 0); + + if(retval == -1 && (errno == ENOATTR || errno == EOPNOTSUPP)) { + ext_acl_p = __acl_to_xattr(acl_obj_p, &size); + } else { + char domain[NFS4_MAX_DOMAIN_LEN]; + nfs4_init_name_mapping(NULL); + error = nfs4_get_default_domain(NULL, domain, sizeof(domain)); + if (error) + return -1; + nacl = acl_ptn4_acl_trans(acl, ACL_TYPE_ACCESS, NFS4_ACL_ISFILE, + domain); + if(nacl == NULL) + return -1; + + size = acl_nfs4_xattr_pack(nacl, &ext_acl_p); + name = ACL_NFS4_XATTR; + acl_nfs4_free(nacl); + } +#else ext_acl_p = __acl_to_xattr(acl_obj_p, &size); +#endif + if (!ext_acl_p) return -1; error = fsetxattr(fd, name, (char *)ext_acl_p, size, 0); diff --git a/libacl/acl_set_file.c b/libacl/acl_set_file.c index 20d7ee3..b72b320 100644 --- a/libacl/acl_set_file.c +++ b/libacl/acl_set_file.c @@ -26,6 +26,11 @@ #include #include "libacl.h" #include "__acl_to_xattr.h" +#ifdef USE_NFSV4_TRANS + #include "libacl_nfs4.h" + #include +#endif + #include "byteorder.h" #include "acl_ea.h" @@ -39,9 +44,16 @@ acl_set_file(const char *path_p, acl_typ const char *name; size_t size; int error; + struct stat st; +#ifdef USE_NFSV4_TRANS + int retval; + struct nfs4_acl * nacl; + int is_dir = NFS4_ACL_ISFILE; +#endif if (!acl_obj_p) return -1; + switch (type) { case ACL_TYPE_ACCESS: name = ACL_EA_ACCESS; @@ -54,8 +66,56 @@ acl_set_file(const char *path_p, acl_typ return -1; } + +#ifdef USE_NFSV4_TRANS + retval = getxattr(path_p, ACL_NFS4_XATTR, NULL, 0); + + if(retval == -1 && (errno == ENOATTR || errno == EOPNOTSUPP)) { + if (type == ACL_TYPE_DEFAULT) { + + if (stat(path_p, &st) != 0) + return -1; + + /* Only directories may have default ACLs. */ + if (!S_ISDIR(st.st_mode)) { + errno = EACCES; + return -1; + } + } + + ext_acl_p = __acl_to_xattr(acl_obj_p, &size); + } else { + char domain[NFS4_MAX_DOMAIN_LEN]; + + if (stat(path_p, &st) != 0) + return -1; + + if (S_ISDIR(st.st_mode)) { + is_dir = NFS4_ACL_ISDIR; + } + + if(type == ACL_TYPE_DEFAULT) + { + if(!(is_dir & NFS4_ACL_ISDIR)) + { + errno = EACCES; + return -1; + } + } + + nfs4_init_name_mapping(NULL); + error = nfs4_get_default_domain(NULL, domain, sizeof(domain)); + nacl = acl_ptn4_acl_trans(acl, type, is_dir, domain); + if(nacl == NULL) + return -1; + + size = acl_nfs4_xattr_pack(nacl, &ext_acl_p); + name = ACL_NFS4_XATTR; + acl_nfs4_free(nacl); + } +#else + if (type == ACL_TYPE_DEFAULT) { - struct stat st; if (stat(path_p, &st) != 0) return -1; @@ -68,9 +128,12 @@ acl_set_file(const char *path_p, acl_typ } ext_acl_p = __acl_to_xattr(acl_obj_p, &size); +#endif + if (!ext_acl_p) return -1; - error = setxattr(path_p, name, (char *)ext_acl_p, size, 0); + + error = setxattr(path_p, name, (char *)ext_acl_p, size, XATTR_REPLACE); free(ext_acl_p); return error; } diff --git a/libacl/libacl_nfs4.h b/libacl/libacl_nfs4.h new file mode 100644 index 0000000..641dae6 --- /dev/null +++ b/libacl/libacl_nfs4.h @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* mode bit translations: */ +#define NFS4_READ_MODE NFS4_ACE_READ_DATA +#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA \ + | NFS4_ACE_APPEND_DATA | NFS4_ACE_DELETE_CHILD) +#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE +#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | \ + NFS4_ACE_SYNCHRONIZE) +#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL) + +/* flags used to simulate posix default ACLs */ +#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ + | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE) + +#define NFS4_ACE_MASK_IGNORE (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \ + | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS) +/* XXX not sure about the following. Note that e.g. DELETE_CHILD is wrong in + * general (should only be ignored on files). */ +#define MASK_EQUAL(mask1, mask2) \ + (((mask1) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \ + ~NFS4_ACE_DELETE_CHILD) \ + == ((mask2) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \ + ~NFS4_ACE_DELETE_CHILD)) + +/* Maximum length of the ace->who attribute */ +#define NFS4_ACL_WHO_LENGTH_MAX 2048 +#define NFS4_ACL_WHO_BUFFER_LEN_GUESS 255 + +/* NFS4 acl xattr name */ +#define ACL_NFS4_XATTR "system.nfs4_acl" + +/* Macro for finding empty tailqs */ +#define TAILQ_IS_EMPTY(head) (head.tqh_first == NULL) + +/* Flags to pass certain properties around */ +#define NFS4_ACL_NOFLAGS 0x00 +#define NFS4_ACL_ISFILE 0x00 +#define NFS4_ACL_ISDIR 0x01 +#define NFS4_ACL_OWNER 0x02 +#define NFS4_ACL_REQUEST_DEFAULT 0x04 +#define NFS4_ACL_RAW 0x01 + +#define NFS4_XDR_MOD 4 + +typedef u_int32_t u32; + +enum { ACL_NFS4_NOT_USED = 0, + ACL_NFS4_USED +}; + +struct ace_container { + struct nfs4_ace *ace; + TAILQ_ENTRY(ace_container) l_ace; +}; + +TAILQ_HEAD(ace_container_list_head, ace_container); + +/**** Public functions ****/ + +/** Manipulation functions **/ +extern int acl_nfs4_add_ace(struct nfs4_acl *, u32, u32, u32, int, char*); +extern int acl_nfs4_add_pair(struct nfs4_acl *, int, u32, int, char*); +extern void acl_nfs4_free(struct nfs4_acl *); +extern struct nfs4_acl *acl_nfs4_new(u32); +extern int acl_nfs4_set_who(struct nfs4_ace*, int, char*); +extern struct nfs4_acl *acl_nfs4_copy_acl(struct nfs4_acl *); +extern struct nfs4_acl *acl_nfs4_xattr_load(char *, int, u32); +extern int acl_nfs4_xattr_pack(struct nfs4_acl *, char**); +extern int acl_nfs4_xattr_size(struct nfs4_acl *); +extern int acl_nfs4_remove_ace(struct nfs4_acl * acl, struct nfs4_ace * ace); + +/** Conversion functions **/ + +/* nfs4 -> posix */ +extern acl_t acl_n4tp_acl_trans(struct nfs4_acl *, acl_type_t); +extern int acl_n4tp_set_mode(acl_entry_t pace, u32 nfs4_access_mask, + int iflags); +extern int acl_n4tp_ace_count(struct nfs4_acl *n4acl); +extern int acl_n4tp_ace_trans(struct nfs4_ace *ace, acl_t *pacl, + acl_tag_t tag, int iflags); +extern int acl_n4tp_set_who(acl_entry_t ace, char* who, + acl_tag_t who_type); +extern acl_tag_t acl_n4tp_get_whotype(struct nfs4_ace *ace); + +/* posix -> nfs4 */ +extern int acl_ptn4_get_mask(u32* mask, acl_permset_t perms, + int iflags); +extern struct nfs4_acl *acl_ptn4_acl_trans(acl_t, acl_type_t, u32, char*); + + +/** Access Functions **/ +extern inline struct nfs4_ace * + acl_nfs4_get_next_ace(struct nfs4_ace **); +extern inline struct nfs4_ace * + acl_nfs4_get_first_ace(struct nfs4_acl *); +extern inline int acl_nfs4_get_whotype(char*); +extern int acl_nfs4_get_who(struct nfs4_ace*, int*, char**); +extern inline int acl_nfs4_get_flags(struct nfs4_ace *, u32 *); +extern inline int acl_nfs4_entries(struct nfs4_acl *); +extern inline int acl_nfs4_get_accessmask(struct nfs4_ace * ace, u32 * mask); +extern int acl_nfs4_get_type(struct nfs4_ace * ace, u32 * type); + +/** Display Functions **/ +extern void acl_nfs4_print(struct nfs4_acl * acl); +extern int acl_nfs4_print_ace(struct nfs4_ace * ace, u32 is_dir); +extern int acl_nfs4_print_fd(struct nfs4_acl *acl, FILE * fd); + +/**** Private(?) functions ****/ +acl_t __posix_acl_from_nfs4_xattr(char*, int, acl_type_t, u32); +int complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny); +int same_who(struct nfs4_ace *a, struct nfs4_ace *b); + +/* These will change */ +int nfs4_get_gid_from_who(gid_t* gid, const char * who); +int nfs4_get_uid_from_who(uid_t* uid, const char * who); +char * nfs4_get_who_from_uid(uid_t); +char * nfs4_get_who_from_gid(gid_t); +int __nfs4_get_local_uid_from_who(uid_t* uid, const char * who); +int __nfs4_get_foreign_uid_from_who(uid_t* uid, const char * who); +int __nfs4_get_local_gid_from_who(gid_t* gid, const char * who); +int __nfs4_get_foreign_gid_from_who(gid_t* gid, const char * who); +int is_who_local(const char * who); +/* End change */ + +int user_obj_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace **n4ace, + acl_t *pacl, int iflags); +int users_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + struct nfs4_ace **mask_ace, acl_t *pacl, int iflags); +int group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, + struct nfs4_ace ** n4ace_p, struct nfs4_ace **mask_ace, acl_t *pacl, int iflags); +int mask_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + struct nfs4_ace **mask_ace, acl_t *pacl, int iflags); +int other_from_v4(struct nfs4_acl *n4acl, struct nfs4_ace ** n4ace_p, + acl_t *pacl, int iflags); diff --git a/nfs4_getfacl/Makefile b/nfs4_getfacl/Makefile new file mode 100644 index 0000000..143db05 --- /dev/null +++ b/nfs4_getfacl/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, +# Mountain View, CA 94043, or: +# +# http://www.sgi.com +# +# For further information regarding this notice, see: +# +# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# + +TOPDIR = .. +include $(TOPDIR)/include/builddefs + +LTCOMMAND = nfs4_getfacl +CFILES = nfs4_getfacl.c +HFILES = libacl_nfs4.h nfs4.h + +LLDLIBS = $(LIBACL) $(LIBATTR) +LTDEPENDENCIES = $(LIBACL) + +default: $(LTCOMMAND) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 -d $(PKG_BIN_DIR) + $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) + +install-dev install-lib: diff --git a/nfs4_getfacl/nfs4_getfacl.c b/nfs4_getfacl/nfs4_getfacl.c new file mode 100644 index 0000000..aee0594 --- /dev/null +++ b/nfs4_getfacl/nfs4_getfacl.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include "acl_ea.h" +#include "libacl_nfs4.h" +#include + + +char* execname; + +void useage(void); + +int main(int argc, char** argv) +{ + char *ext_acl_p; + char *name; + char * path_p = argv[argc-1]; + int retval; + struct nfs4_acl * nacl; + struct stat st; + u32 iflags; + int result; + char * savefile_s = NULL; + FILE *fd; + int option_index = 1; + int opt; + struct option opt_a[] = { + {"help", 0, NULL, 'h'}}; + + execname = argv[0]; + + while(1) + { + opt = getopt_long(argc, argv, "f:h", opt_a, NULL); + + if(opt == -1) + { + /* Allow one undefined option. This is the file parameter + * at the end */ + if(option_index < (argc - 1)) + { + while (option_index < argc) + { + printf("Unrecognized option: %s\n", argv[option_index++]); + } + goto useage_failed; + } + else + { + break; + } + } + + + switch(opt) + { + case 'h': + goto useage_failed; + break; + + case 'f': + if(savefile_s != NULL) + { + printf("Output file specified twice. Aborting.\n"); + goto failed; + } + + savefile_s = optarg; + break; + + default: + goto useage_failed; + break; + } + + option_index = optind; + + } + + + + if(argc < 2) { + printf("You must specify a path\n"); + goto useage_failed; + } + + if(savefile_s != NULL) + { + result = stat(savefile_s, &st); + if(result == 0) { + printf("Warning: input file already exists\n"); + } + fd = fopen(savefile_s, "w+"); + if(fd == NULL) + { + printf("Failed opening output file %s\n", savefile_s); + goto failed; + } + } else { + fd = stdout; + } + + + + result = stat(path_p, &st); + if(result < 0) { + printf("Invalid filename.\n"); + goto useage_failed; + } + + retval = getxattr(path_p, ACL_NFS4_XATTR, NULL, 0); + if(retval == -1 && errno == ENOATTR) { + printf("Attribute not found on file.\n"); + exit(1); + } else if ( retval == -1 && errno == EOPNOTSUPP) { + printf("Operation to request attribute not supported.\n"); + exit(1); + } else if ( retval == -1 ) { + printf("%d\n", errno); + perror("Failed getxattr operation\n"); + exit(1); + } else { + name = ACL_NFS4_XATTR; + } + + ext_acl_p = malloc(retval); + if (!ext_acl_p) { + printf("Failed to allocate memory\n"); + exit(1); + } + + retval = getxattr(path_p, name, ext_acl_p, retval); + + if(retval == -1 && errno == ENOATTR) { + printf("Attribute not found on file.\n"); + goto free_failed; + } else if ( retval == -1 && errno == EOPNOTSUPP) { + printf("Operation to request attribute not supported.\n"); + goto free_failed; + } else if ( retval == -1 ) { + perror("Failed getxattr operation\n"); + goto free_failed; + } else { + stat(path_p, &st); + + iflags = NFS4_ACL_ISFILE; + if(st.st_mode & S_IFDIR) + { + iflags = NFS4_ACL_ISDIR; + } + nacl = acl_nfs4_xattr_load(ext_acl_p, retval, iflags); + if(nacl == NULL) { + perror("Failed to extract nfs4acl from xattr"); + } + acl_nfs4_print_fd(nacl, fd); + free(ext_acl_p); + return 0; + } + +useage_failed: + useage(); + return 1; + + +free_failed: + free(ext_acl_p); + +failed: + return 1; +} + +void useage() +{ + printf("Useage: %s [-f ] \n", execname); + printf("Prints the NFSv4 acl entry for the given path.\n"); + printf(" Permission letter mapping:\n"); + printf(" r - NFS4_ACE_READ_DATA\n"); + printf(" w - NFS4_ACE_WRITE_DATA\n"); + printf(" a - NFS4_ACE_APPEND_DATA\n"); + printf(" x - NFS4_ACE_EXECUTE\n"); + printf(" d - NFS4_ACE_DELETE\n"); + printf(" l - NFS4_ACE_LIST_DIRECTORY\n"); + printf(" f - NFS4_ACE_ADD_FILE\n"); + printf(" s - NFS4_ACE_ADD_SUBDIRECTORY\n"); + printf(" n - NFS4_ACE_READ_NAMED_ATTRS\n"); + printf(" N - NFS4_ACE_WRITE_NAMED_ATTRS\n"); + printf(" D - NFS4_ACE_DELETE_CHILD\n"); + printf(" t - NFS4_ACE_READ_ATTRIBUTES\n"); + printf(" T - NFS4_ACE_WRITE_ATTRIBUTES\n"); + printf(" c - NFS4_ACE_READ_ACL\n"); + printf(" C - NFS4_ACE_WRITE_ACL\n"); + printf(" o - NFS4_ACE_WRITE_OWNER\n"); + printf(" y - NFS4_ACE_SYNCHRONIZE\n"); + return; +} + diff --git a/nfs4_setfacl/Makefile b/nfs4_setfacl/Makefile new file mode 100644 index 0000000..b1c22fe --- /dev/null +++ b/nfs4_setfacl/Makefile @@ -0,0 +1,50 @@ +# +# Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, +# Mountain View, CA 94043, or: +# +# http://www.sgi.com +# +# For further information regarding this notice, see: +# +# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# + +TOPDIR = .. +include $(TOPDIR)/include/builddefs + +LTCOMMAND = nfs4_setfacl +CFILES = nfs4_setfacl.c +#HFILES = + +LLDLIBS = $(LIBACL) $(LIBATTR) $(LIBMISC) +LTDEPENDENCIES = $(LIBACL) $(LIBMISC) + +default: $(LTCOMMAND) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 -d $(PKG_BIN_DIR) + $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) +install-dev install-lib: diff --git a/nfs4_setfacl/nfs4_setfacl.c b/nfs4_setfacl/nfs4_setfacl.c new file mode 100644 index 0000000..f8df0a6 --- /dev/null +++ b/nfs4_setfacl/nfs4_setfacl.c @@ -0,0 +1,313 @@ +#include +#include +#include +#include +#include +#include "libacl_nfs4.h" +#include "nfs4.h" +#include + +extern int errno; + +/* Actions */ +#define NO_ACTION 0 +#define MODIFY_ACTION 1 +#define SUBSTITUTE_ACTION 2 +#define REMOVE_ACTION 3 + +/* Walks */ +#define DEFAULT_WALK 0 /* Follow symbolic link args, + Skip links in subdirectories */ +#define LOGICAL_WALK 1 /* Follow all symbolic links */ +#define PHYSICAL_WALK 2 /* Skip all symbolic links */ + +/* Recursion */ +#define NO_RECURSIVE 0 +#define YES_RECURSIVE 1 + +/* Translation formats */ +#define NO_TRANS 0 /* Straight NFSv4 ACL rules */ +#define POSIX_LINUX_TRANS 1 /* Use NFSv4 POSIX Linux format */ + +#define u32 u_int32_t + +typedef struct mod_ace_s mod_ace; +struct mod_ace_s { + mod_ace* next; + int cvals; + char* user; + u32 flags; + u32 permissions; + int line; +}; + + +void useage(void); + +int load_from_file(FILE*, struct nfs4_acl**); + +int main(int argc, char** argv) +{ + int opt, res; + int trans_type = NO_TRANS; + int do_recursive = NO_RECURSIVE; + int walk_type = DEFAULT_WALK; + int action = NO_ACTION; + FILE *s_fd; + char* spec_file = NULL; + char* mod_string = NULL; + struct nfs4_acl *nacl; + struct stat st; + char *xdrbuf; + char * path_p = argv[argc-1]; + + while(1) + { + opt = getopt(argc, argv, "jLm:M:PRS:x:X:"); + + if(opt == -1) { + if(optind >= argc) { + useage(); + goto failed; + } + break; + } + else if (opt == ':') { + useage(); + goto failed; + } + else if (opt == '?') { + useage(); + goto failed; + } + + /* We have a good option */ + switch(opt) { + case 'j': + trans_type = POSIX_LINUX_TRANS; + break; + + case 'L': + if(walk_type != DEFAULT_WALK) { + fprintf(stderr, "More than one Walk type specified\n"); + useage(); + goto failed; + } + walk_type = LOGICAL_WALK; + break; + + case 'm': + if(action != NO_ACTION) { + fprintf(stderr, "More than one action specified\n"); + useage(); + goto failed; + } + action = MODIFY_ACTION; + mod_string = optarg; + break; + + case 'M': + if(action != NO_ACTION) { + fprintf(stderr, "More than one action specified\n"); + useage(); + goto failed; + } + action = MODIFY_ACTION; + spec_file = optarg; + s_fd = fopen (spec_file, "r"); + if(s_fd == NULL) { + fprintf(stderr, "Access error on spec file: %s\n", spec_file); + goto failed; + } + break; + + case 'P': + if(walk_type != DEFAULT_WALK) { + fprintf(stderr, "More than one walk type specified\n"); + useage(); + goto failed; + } + walk_type = PHYSICAL_WALK; + break; + + case 'R': + do_recursive = YES_RECURSIVE; + break; + + case 'S': + if(action != NO_ACTION) { + fprintf(stderr, "More than one action specified\n"); + useage(); + goto failed; + } + action = SUBSTITUTE_ACTION; + spec_file = optarg; + s_fd = fopen (spec_file, "r"); + if(s_fd == NULL) { + fprintf(stderr, "Access error on spec file: %s \n", spec_file); + goto failed; + } + break; + + case 'x': + if(action != NO_ACTION) { + fprintf(stderr, "More than one action specified\n"); + useage(); + goto failed; + } + action = REMOVE_ACTION; + mod_string = optarg; + + case 'X': + if(action != NO_ACTION) { + fprintf(stderr, "More than one action specified\n"); + useage(); + goto failed; + } + action = REMOVE_ACTION; + spec_file = optarg; + s_fd = fopen (spec_file, "r"); + if(s_fd == NULL) { + fprintf(stderr, "Access error on spec file: %s\n", spec_file); + goto failed; + } + break; + } + } + + if(action == NO_ACTION) { + fprintf(stderr, "No action specified\n"); + useage(); + goto failed; + } + + res = stat(path_p, &st); + if(res < 0) { + printf("Invalid filename: %s\n", path_p); + goto useage_failed; + } + + if((nacl = acl_nfs4_new(st.st_mode & S_IFDIR ? 0 : 1)) == NULL) { + printf("Failed to allocate memory\n"); + errno = ENOMEM; + goto failed; + } + + /* XXX for now, only spec file input allowed */ + + if((s_fd != NULL) && (res = load_from_file(s_fd, &nacl) < 0)) { + fprintf(stderr, + "Failed loading ACL from spec file %s. Aborting.\n", + spec_file); + goto failed_free; + } else if (s_fd == NULL) { + fprintf(stderr, "Partial Implementation: No spec file specified, Aborting.\n"); + goto failed_free; + } + + res = acl_nfs4_xattr_pack(nacl, &xdrbuf); + if (res <= 0) { + printf("Failed to populate xattr from nfs4acl\n"); + goto failed_free; + } + + res = setxattr(path_p, ACL_NFS4_XATTR, (char *)xdrbuf, res, + XATTR_REPLACE); + if ((res == -1 && errno == EOPNOTSUPP) || (res == -10032)) + printf("Operation to request attribute not supported.\n"); + else if (res == -1 && errno == ENOATTR) + printf("Attribute not found on file.\n"); + else if (res == -1) + perror("Failed setxattr operation\n"); + else if(res < -1) + printf("Failed setxattr operation %d\n", res); + + free(xdrbuf); + acl_nfs4_free(nacl); + return res; + +useage_failed: + useage(); + +failed: + return 1; + +failed_free: + acl_nfs4_free(nacl); + goto failed; +} + +/* NFS4_MAX_ACESIZE + * : 4 of these + * index 2 (no more than 99 ACES in an ACL !) + * type 2 (space + Type letter) + * flag 10 (total number of flag characters) + * who 128 XXX what should this be? NAME_MAX is 255 ... + * mask 14 ( total number of dir + common mask characters) + * + * which equals 160 + * + * plus 1 for fgets, but let's make it 2... + * + * 162 is the current grand total. + */ + +#define NFS4_MAX_ACESIZE 4 + 2 + 2 + 10 + 128 + 14 + 2 + + +/* + * load_from_file - read ACE entries from spec file into struct nfs4_acl + * + * inputs + * fd: spec_file holding ACL created by nfs4_getfacl and modified by user. + * nacl_p: holds the modified ACL to be passed to setxattr. + * output + * total length of all acewho OR -1 on error. + * + * XXX: fgets ace_buf of size 128 to hold on ACE. is this big enough? + */ +int load_from_file(FILE* fd, struct nfs4_acl **nacl_p) +{ + char ace_buf[NFS4_MAX_ACESIZE]; + int naces = 0, res; + int total_who_len = 0; + + memset(ace_buf, 0, NFS4_MAX_ACESIZE); + /* grab each ACE, one per line in fd */ + while (fgets(ace_buf, NFS4_MAX_ACESIZE, fd) != NULL) + { + /* process each ACE */ + res = acl_nfs4_string2ace(ace_buf, nacl_p); + if(res < 0) + return -1; + memset(ace_buf, 0, NFS4_MAX_ACESIZE); + naces++; + total_who_len += res; + } + if(naces == 0) + return -1; + (*nacl_p)->naces = naces; + return total_who_len; +} + +void useage(void) +{ + fprintf(stderr, "Useage (under development): nfs4_setfacl [-j] -M spec_file file ...\n"); + fprintf(stderr, " -M apply modified NFSv4 ACL from spec file\n"); +} + +#if 0 +void useage(void) +{ + fprintf(stderr, "Useage: nfs4_setfacl [-jRLP] [{-m|-x} acl_spec] [{-M|-X} acl_file] file ...\n"); + fprintf(stderr, " -m modify the current ACL(s) of file(s)\n"); + fprintf(stderr, " -M file read ACL entries to modify from spec file\n"); + fprintf(stderr, " -x remove entries from the ACL(s) of file(s)\n"); + fprintf(stderr, " -X file read ACL entries to remove from spec file\n"); + fprintf(stderr, " -j format ACL to LINUX POSIX translation spec\n"); + fprintf(stderr, " -R recurse into subdirectories\n"); + fprintf(stderr, " -L logical walk, follow symbolic links\n"); + fprintf(stderr, " -P physical walk, do not follow symbolic links\n"); + return; +} +#endif