summaryrefslogtreecommitdiffstats
path: root/xlators/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/nfs')
-rw-r--r--xlators/nfs/server/src/acl3.c294
1 files changed, 201 insertions, 93 deletions
diff --git a/xlators/nfs/server/src/acl3.c b/xlators/nfs/server/src/acl3.c
index a9843c710..59c7637e3 100644
--- a/xlators/nfs/server/src/acl3.c
+++ b/xlators/nfs/server/src/acl3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
+ * Copyright (c) 2012-2013 Red Hat, Inc. <http://www.redhat.com>
* This file is part of GlusterFS.
*
* This file is licensed to you under your choice of the GNU Lesser
@@ -28,7 +28,15 @@
#include "nfs3-fh.h"
#include "nfs-generics.h"
#include "acl3.h"
+#include "byte-order.h"
+static int
+acl3_nfs_acl_to_xattr (aclentry *ace, void *xattrbuf,
+ int aclcount, int defacl);
+
+static int
+acl3_nfs_acl_from_xattr (aclentry *ace, void *xattrbuf,
+ int bufsize, int defacl);
typedef ssize_t (*acl3_serializer) (struct iovec outmsg, void *args);
@@ -233,12 +241,12 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, dict_t *dict,
dict_t *xdata)
{
- nfsstat3 stat = NFS3ERR_SERVERFAULT;
- nfs3_call_state_t *cs = NULL;
- data_t *data = NULL;
- int *p = NULL;
- int i = 0;
- getaclreply *getaclreply = NULL;
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ nfs3_call_state_t *cs = NULL;
+ data_t *data = NULL;
+ getaclreply *getaclreply = NULL;
+ int aclcount = 0;
+ int defacl = 1; /* DEFAULT ACL */
if (!frame->local) {
gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument,"
@@ -255,32 +263,40 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
getaclreply->aclentry.aclentry_val = cs->aclentry;
getaclreply->daclentry.daclentry_val = cs->daclentry;
- /* FIXME: use posix_acl_from_xattr() */
+ /* getfacl: NFS USER ACL */
data = dict_get (dict, POSIX_ACL_ACCESS_XATTR);
- if (data && (p = data_to_bin (data))) {
- /* POSIX_ACL_VERSION */
- p++;
- while ((char *)p < (data->data + data->len)) {
- getaclreply->aclentry.aclentry_val[i].type = *(*(short **)&p)++;
- getaclreply->aclentry.aclentry_val[i].perm = *(*(short **)&p)++;
- getaclreply->aclentry.aclentry_val[i].uid = *(*(int **)&p)++;
- i++;
+ if (data && data->data) {
+ aclcount = acl3_nfs_acl_from_xattr (cs->aclentry,
+ data->data,
+ data->len,
+ !defacl);
+ if (aclcount < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR,
+ "Failed to get USER ACL");
+ stat = nfs3_errno_to_nfsstat3 (-aclcount);
+ goto err;
}
- getaclreply->aclcount = getaclreply->aclentry.aclentry_len = i;
+
+ getaclreply->aclcount = aclcount;
+ getaclreply->aclentry.aclentry_len = aclcount;
}
- i = 0;
+ /* getfacl: NFS DEFAULT ACL */
data = dict_get (dict, POSIX_ACL_DEFAULT_XATTR);
- if (data && (p = data_to_bin (data))) {
- /* POSIX_ACL_VERSION */
- p++;
- while ((char *)p < (data->data + data->len)) {
- getaclreply->daclentry.daclentry_val[i].type = *(*(short **)&p)++;
- getaclreply->daclentry.daclentry_val[i].perm = *(*(short **)&p)++;
- getaclreply->daclentry.daclentry_val[i].uid = *(*(int **)&p)++;
- i++;
+ if (data && data->data) {
+ aclcount = acl3_nfs_acl_from_xattr (cs->daclentry,
+ data->data,
+ data->len,
+ defacl);
+ if (aclcount < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR,
+ "Failed to get DEFAULT ACL");
+ stat = nfs3_errno_to_nfsstat3 (-aclcount);
+ goto err;
}
- getaclreply->daclcount = getaclreply->daclentry.daclentry_len = i;
+
+ getaclreply->daclcount = aclcount;
+ getaclreply->daclentry.daclentry_len = aclcount;
}
acl3_getacl_reply (cs, getaclreply);
@@ -481,20 +497,19 @@ acl3err:
int
acl3svc_setacl (rpcsvc_request_t *req)
{
- xlator_t *vol = NULL;
+ xlator_t *vol = NULL;
struct nfs_state *nfs = NULL;
nfs3_state_t *nfs3 = NULL;
- nfs3_call_state_t *cs = NULL;
- int ret = RPCSVC_ACTOR_ERROR;
- nfsstat3 stat = NFS3ERR_SERVERFAULT;
- struct nfs3_fh fh;
+ nfs3_call_state_t *cs = NULL;
+ int ret = RPCSVC_ACTOR_ERROR;
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ struct nfs3_fh fh;
struct nfs3_fh *fhp = NULL;
- setaclargs setaclargs;
- aclentry *aclentry = NULL;
- struct aclentry *daclentry = NULL;
- int i = 0;
- struct posix_acl_xattr_header *bufheader = NULL;
- struct posix_acl_xattr_entry *bufentry = NULL;
+ setaclargs setaclargs;
+ aclentry *aclentry = NULL;
+ struct aclentry *daclentry = NULL;
+ int aclerrno = 0;
+ int defacl = 1;
if (!req)
return ret;
@@ -534,64 +549,27 @@ acl3svc_setacl (rpcsvc_request_t *req)
cs->aclcount = setaclargs.aclcount;
cs->daclcount = setaclargs.daclcount;
- if ((cs->aclcount > NFS_ACL_MAX_ENTRIES) ||
- (cs->daclcount > NFS_ACL_MAX_ENTRIES))
+ /* setfacl: NFS USER ACL */
+ aclerrno = acl3_nfs_acl_to_xattr (aclentry,
+ cs->aclxattr,
+ cs->aclcount,
+ !defacl);
+ if (aclerrno < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to set USER ACL");
+ stat = nfs3_errno_to_nfsstat3 (-aclerrno);
goto acl3err;
- /* FIXME: use posix_acl_to_xattr() */
- /* Populate xattr buffer for user ACL */
- bufheader = (struct posix_acl_xattr_header *)(cs->aclxattr);
- bufheader->version = htole32(POSIX_ACL_VERSION);
- bufentry = bufheader->entries;
- for (i = 0; i < cs->aclcount; i++) {
- int uaceuid;
- const struct aclentry *uace = &aclentry[i];
- switch (uace->type) {
- case POSIX_ACL_USER:
- case POSIX_ACL_GROUP:
- uaceuid = uace->uid;
- break;
- default:
- uaceuid = POSIX_ACL_UNDEFINED_ID;
- break;
- }
- bufentry->tag = htole16(uace->type);
- bufentry->perm = htole16(uace->perm);
- bufentry->id = htole32(uaceuid);
-
- bufentry++;
- }
-
- /* Populate xattr buffer for Default ACL */
- bufheader = (struct posix_acl_xattr_header *)(cs->daclxattr);
- bufheader->version = htole32(POSIX_ACL_VERSION);
- bufentry = bufheader->entries;
- for (i = 0; i < cs->daclcount; i++) {
- int daceuid;
- int dacetype;
- const struct aclentry *dace = &daclentry[i];
- /*
- * For "default ACL", NFSv3 handles the 'type' differently
- * i.e. by logical OR'ing 'type' with NFS_ACL_DEFAULT.
- * Which the backend File system does not understand and
- * that needs to be masked OFF.
- */
- dacetype = (dace->type & ~(NFS_ACL_DEFAULT));
- switch (dacetype) {
- case POSIX_ACL_USER:
- case POSIX_ACL_GROUP:
- daceuid = dace->uid;
- break;
- default:
- daceuid = POSIX_ACL_UNDEFINED_ID;
- break;
- }
- bufentry->tag = htole16(dacetype);
- bufentry->perm = htole16(dace->perm);
- bufentry->id = htole32(daceuid);
-
- bufentry++;
}
+ /* setfacl: NFS DEFAULT ACL */
+ aclerrno = acl3_nfs_acl_to_xattr (daclentry,
+ cs->daclxattr,
+ cs->daclcount,
+ defacl);
+ if (aclerrno < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to set DEFAULT ACL");
+ stat = nfs3_errno_to_nfsstat3 (-aclerrno);
+ goto acl3err;
+ }
ret = nfs3_fh_resolve_and_resume (cs, fhp,
NULL, acl3_setacl_resume);
@@ -706,3 +684,133 @@ acl3svc_init(xlator_t *nfsx)
err:
return NULL;
}
+
+static int
+acl3_nfs_acl_to_xattr (aclentry *ace, /* ACL entries to be read */
+ void *xattrbuf, /* XATTR buf to be populated */
+ int aclcount, /* No of ACLs to be read */
+ int defacl) /* 1 if DEFAULT ACL */
+{
+ int idx = 0;
+ posix_acl_xattr_header *xheader = NULL;
+ posix_acl_xattr_entry *xentry = NULL;
+
+ if ((!ace) || (!xattrbuf))
+ return (-EINVAL);
+
+ /* ACL count is ZERO, nothing to do */
+ if (!aclcount)
+ return (0);
+
+ if ((aclcount < 0) || (aclcount > NFS_ACL_MAX_ENTRIES))
+ return (-EINVAL);
+
+ xheader = (posix_acl_xattr_header *) (xattrbuf);
+ xentry = (posix_acl_xattr_entry *) (xheader + 1);
+
+ /*
+ * For "default ACL", NFSv3 handles the 'type' differently
+ * i.e. by logical OR'ing 'type' with NFS_ACL_DEFAULT.
+ * Which the backend File system does not understand and
+ * that needs to be masked OFF.
+ */
+ xheader->version = POSIX_ACL_XATTR_VERSION;
+
+ for (idx = 0; idx < aclcount; idx++) {
+ xentry->tag = ace->type;
+ if (defacl)
+ xentry->tag &= ~NFS_ACL_DEFAULT;
+ xentry->perm = ace->perm;
+
+ switch (xentry->tag) {
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP:
+ if (xentry->perm & ~S_IRWXO)
+ return (-EINVAL);
+ xentry->id = ace->uid;
+ break;
+ case POSIX_ACL_USER_OBJ:
+ case POSIX_ACL_GROUP_OBJ:
+ case POSIX_ACL_OTHER:
+ if (xentry->perm & ~S_IRWXO)
+ return (-EINVAL);
+ xentry->id = POSIX_ACL_UNDEFINED_ID;
+ break;
+ case POSIX_ACL_MASK:
+ /* Solaris sometimes sets additional bits in
+ * the mask.
+ */
+ xentry->perm &= S_IRWXO;
+ xentry->id = POSIX_ACL_UNDEFINED_ID;
+ break;
+ default:
+ return (-EINVAL);
+ }
+
+ xentry++;
+ ace++;
+ }
+
+ /* SUCCESS */
+ return (0);
+}
+
+static int
+acl3_nfs_acl_from_xattr (aclentry *ace, /* ACL entries to be filled */
+ void *xattrbuf, /* XATTR buf to be read */
+ int bufsize, /* Size of XATTR buffer */
+ int defacl) /* 1 if DEFAULT ACL */
+{
+ int idx = 0;
+ ssize_t aclcount = 0;
+ posix_acl_xattr_header *xheader = NULL;
+ posix_acl_xattr_entry *xentry = NULL;
+
+ if ((!xattrbuf) || (!ace))
+ return (-EINVAL);
+
+ aclcount = posix_acl_xattr_count (bufsize);
+ if ((aclcount < 0) || (aclcount > NFS_ACL_MAX_ENTRIES))
+ return (-EINVAL);
+
+ xheader = (posix_acl_xattr_header *) (xattrbuf);
+ xentry = (posix_acl_xattr_entry *) (xheader + 1);
+
+ /* Check for supported POSIX ACL xattr version */
+ if (xheader->version != POSIX_ACL_XATTR_VERSION)
+ return (-ENOSYS);
+
+ for (idx = 0; idx < (int)aclcount; idx++) {
+ ace->type = xentry->tag;
+ if (defacl) {
+ /*
+ * SET the NFS_ACL_DEFAULT flag for default
+ * ACL which was masked OFF during setfacl().
+ */
+ ace->type |= NFS_ACL_DEFAULT;
+ }
+ ace->perm = (xentry->perm & S_IRWXO);
+
+ switch (xentry->tag) {
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP:
+ ace->uid = xentry->id;
+ break;
+ case POSIX_ACL_USER_OBJ:
+ case POSIX_ACL_GROUP_OBJ:
+ case POSIX_ACL_MASK:
+ case POSIX_ACL_OTHER:
+ ace->uid = POSIX_ACL_UNDEFINED_ID;
+ break;
+ default:
+ return (-EINVAL);
+ }
+
+
+ xentry++;
+ ace++;
+ }
+
+ /* SUCCESS: ACL count */
+ return aclcount;
+}