diff options
| -rw-r--r-- | rpc/xdr/src/Makefile.am | 4 | ||||
| -rw-r--r-- | rpc/xdr/src/acl.x | 48 | ||||
| -rw-r--r-- | rpc/xdr/src/acl3-xdr.c | 94 | ||||
| -rw-r--r-- | rpc/xdr/src/acl3-xdr.h | 107 | ||||
| -rw-r--r-- | rpc/xdr/src/msg-nfs3.c | 29 | ||||
| -rw-r--r-- | rpc/xdr/src/msg-nfs3.h | 13 | ||||
| -rwxr-xr-x | tests/bugs/bug-847622.t | 25 | ||||
| -rw-r--r-- | xlators/nfs/server/src/Makefile.am | 3 | ||||
| -rw-r--r-- | xlators/nfs/server/src/acl3.c | 621 | ||||
| -rw-r--r-- | xlators/nfs/server/src/acl3.h | 30 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.c | 89 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.h | 9 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-generics.c | 16 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-generics.h | 10 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.c | 8 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.h | 15 | 
16 files changed, 1117 insertions, 4 deletions
diff --git a/rpc/xdr/src/Makefile.am b/rpc/xdr/src/Makefile.am index 7d3d00093..949e75e8d 100644 --- a/rpc/xdr/src/Makefile.am +++ b/rpc/xdr/src/Makefile.am @@ -14,7 +14,7 @@ libgfxdr_la_SOURCES =  xdr-generic.c rpc-common-xdr.c \  			glusterd1-xdr.c \  			portmap-xdr.c \  			nlm4-xdr.c xdr-nfs3.c msg-nfs3.c nsm-xdr.c \ -			nlmcbk-xdr.c +			nlmcbk-xdr.c acl3-xdr.c  noinst_HEADERS = xdr-generic.h rpc-common-xdr.h \  		glusterfs3-xdr.h glusterfs3.h \ @@ -22,4 +22,4 @@ noinst_HEADERS = xdr-generic.h rpc-common-xdr.h \  		glusterd1-xdr.h \  		portmap-xdr.h \  		nlm4-xdr.h xdr-nfs3.h msg-nfs3.h nsm-xdr.h \ -		nlmcbk-xdr.h +		nlmcbk-xdr.h acl3-xdr.h diff --git a/rpc/xdr/src/acl.x b/rpc/xdr/src/acl.x new file mode 100644 index 000000000..6cf4f1d3b --- /dev/null +++ b/rpc/xdr/src/acl.x @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012 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 + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + + +struct aclentry { +	int type; +	int uid; +	int perm; +}; + +struct getaclargs { +	netobj	fh; +	int		mask; +}; + +struct getaclreply { +	int status; +	int attr_follows; +	struct fattr3 attr; +	int	mask; +	int aclcount; +	struct aclentry aclentry<>; +	int daclcount; +	struct aclentry daclentry<>; +}; + +struct setaclargs { +	netobj fh; +	int mask; +	int aclcount; +	struct aclentry aclentry<>; +	int daclcount; +	struct aclentry daclentry<>; +}; + +struct setaclreply { +	int status; +	int attr_follows; +	struct fattr3 attr; +}; + diff --git a/rpc/xdr/src/acl3-xdr.c b/rpc/xdr/src/acl3-xdr.c new file mode 100644 index 000000000..8fbaeff16 --- /dev/null +++ b/rpc/xdr/src/acl3-xdr.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012 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 + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "acl3-xdr.h" + +bool_t +xdr_aclentry (XDR *xdrs, aclentry *objp) +{ +	 if (!xdr_int (xdrs, &objp->type)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->uid)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->perm)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_getaclargs (XDR *xdrs, getaclargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->fh)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->mask)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_getaclreply (XDR *xdrs, getaclreply *objp) +{ +	 if (!xdr_int (xdrs, &objp->status)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->attr_follows)) +		 return FALSE; +	 if (!xdr_fattr3 (xdrs, &objp->attr)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->mask)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->aclcount)) +		 return FALSE; +	 if (!xdr_array (xdrs, (char **)&objp->aclentry.aclentry_val, (u_int *) &objp->aclentry.aclentry_len, ~0, +		sizeof (aclentry), (xdrproc_t) xdr_aclentry)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->daclcount)) +		 return FALSE; +	 if (!xdr_array (xdrs, (char **)&objp->daclentry.daclentry_val, (u_int *) &objp->daclentry.daclentry_len, ~0, +		sizeof (aclentry), (xdrproc_t) xdr_aclentry)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_setaclargs (XDR *xdrs, setaclargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->fh)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->mask)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->aclcount)) +		 return FALSE; +	 if (!xdr_array (xdrs, (char **)&objp->aclentry.aclentry_val, (u_int *) &objp->aclentry.aclentry_len, ~0, +		sizeof (aclentry), (xdrproc_t) xdr_aclentry)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->daclcount)) +		 return FALSE; +	 if (!xdr_array (xdrs, (char **)&objp->daclentry.daclentry_val, (u_int *) &objp->daclentry.daclentry_len, ~0, +		sizeof (aclentry), (xdrproc_t) xdr_aclentry)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_setaclreply (XDR *xdrs, setaclreply *objp) +{ +	 if (!xdr_int (xdrs, &objp->status)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->attr_follows)) +		 return FALSE; +	 if (!xdr_fattr3 (xdrs, &objp->attr)) +		 return FALSE; +	return TRUE; +} diff --git a/rpc/xdr/src/acl3-xdr.h b/rpc/xdr/src/acl3-xdr.h new file mode 100644 index 000000000..7cebaed69 --- /dev/null +++ b/rpc/xdr/src/acl3-xdr.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012 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 + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _ACL_H_RPCGEN +#define _ACL_H_RPCGEN + +#include <rpc/rpc.h> +#include "xdr-nfs3.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct aclentry { +	int type; +	int uid; +	int perm; +}; +typedef struct aclentry aclentry; + +struct getaclargs { +	netobj fh; +	int mask; +}; +typedef struct getaclargs getaclargs; + +struct getaclreply { +	int status; +	int attr_follows; +	struct fattr3 attr; +	int mask; +	int aclcount; +	struct { +		u_int aclentry_len; +		struct aclentry *aclentry_val; +	} aclentry; +	int daclcount; +	struct { +		u_int daclentry_len; +		struct aclentry *daclentry_val; +	} daclentry; +}; +typedef struct getaclreply getaclreply; + +struct setaclargs { +	netobj fh; +	int mask; +	int aclcount; +	struct { +		u_int aclentry_len; +		struct aclentry *aclentry_val; +	} aclentry; +	int daclcount; +	struct { +		u_int daclentry_len; +		struct aclentry *daclentry_val; +	} daclentry; +}; +typedef struct setaclargs setaclargs; + +struct setaclreply { +	int status; +	int attr_follows; +	struct fattr3 attr; +}; +typedef struct setaclreply setaclreply; + +#define ACL3_NULL 0 +#define ACL3_GETACL 1 +#define ACL3_SETACL 2 +#define ACL3_PROC_COUNT 3 +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern  bool_t xdr_aclentry (XDR *, aclentry*); +extern  bool_t xdr_getaclargs (XDR *, getaclargs*); +extern  bool_t xdr_getaclreply (XDR *, getaclreply*); +extern  bool_t xdr_setaclargs (XDR *, setaclargs*); +extern  bool_t xdr_setaclreply (XDR *, setaclreply*); + +#else /* K&R C */ +extern bool_t xdr_aclentry (); +extern bool_t xdr_getaclargs (); +extern bool_t xdr_getaclreply (); +extern bool_t xdr_setaclargs (); +extern bool_t xdr_setaclreply (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_ACL_H_RPCGEN */ diff --git a/rpc/xdr/src/msg-nfs3.c b/rpc/xdr/src/msg-nfs3.c index 97e62040d..6cdb5d37e 100644 --- a/rpc/xdr/src/msg-nfs3.c +++ b/rpc/xdr/src/msg-nfs3.c @@ -541,3 +541,32 @@ xdr_to_nlm4_freeallargs (struct iovec inmsg, nlm4_freeallargs *args)          return xdr_to_generic (inmsg, (void*)args,                                 (xdrproc_t)xdr_nlm4_freeallargs);  } + +ssize_t +xdr_to_getaclargs (struct iovec inmsg, getaclargs *args) +{ +        return xdr_to_generic (inmsg, (void *) args, +                               (xdrproc_t)xdr_getaclargs); +} + +ssize_t +xdr_to_setaclargs (struct iovec inmsg, setaclargs *args) +{ +        return xdr_to_generic (inmsg, (void *) args, +                               (xdrproc_t)xdr_setaclargs); +} + +ssize_t +xdr_serialize_getaclreply (struct iovec inmsg, getaclreply *res) +{ +        return xdr_serialize_generic (inmsg, (void *) res, +                                      (xdrproc_t)xdr_getaclreply); +} + +ssize_t +xdr_serialize_setaclreply (struct iovec inmsg, setaclreply *res) +{ +        return xdr_serialize_generic (inmsg, (void *) res, +                                      (xdrproc_t)xdr_setaclreply); +} + diff --git a/rpc/xdr/src/msg-nfs3.h b/rpc/xdr/src/msg-nfs3.h index 8df777c6c..b8e2c9694 100644 --- a/rpc/xdr/src/msg-nfs3.h +++ b/rpc/xdr/src/msg-nfs3.h @@ -18,6 +18,7 @@  #include "xdr-nfs3.h"  #include "nlm4-xdr.h" +#include "acl3-xdr.h"  #include <sys/types.h>  #include <sys/uio.h> @@ -208,4 +209,16 @@ xdr_to_nlm4_res (struct iovec inmsg, nlm4_res *args);  extern ssize_t  xdr_to_nlm4_freeallargs (struct iovec inmsg, nlm4_freeallargs *args); +extern ssize_t +xdr_to_getaclargs (struct iovec inmsg, getaclargs *args); + +extern ssize_t +xdr_to_setaclargs (struct iovec inmsg, setaclargs *args); + +extern ssize_t +xdr_serialize_getaclreply (struct iovec inmsg, getaclreply *res); + +extern ssize_t +xdr_serialize_setaclreply (struct iovec inmsg, setaclreply *res); +  #endif diff --git a/tests/bugs/bug-847622.t b/tests/bugs/bug-847622.t new file mode 100755 index 000000000..138499527 --- /dev/null +++ b/tests/bugs/bug-847622.t @@ -0,0 +1,25 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/brick0 +TEST $CLI volume start $V0 + +sleep 5 + +TEST mount -t nfs -o vers=3,nolock $H0:/$V0 $N0 +cd $N0 + +# simple getfacl setfacl commands +TEST touch testfile +TEST setfacl -m u:14:r testfile +TEST getfacl testfile + +cd +TEST umount $N0 +cleanup + diff --git a/xlators/nfs/server/src/Makefile.am b/xlators/nfs/server/src/Makefile.am index e22489606..42f1ab5d2 100644 --- a/xlators/nfs/server/src/Makefile.am +++ b/xlators/nfs/server/src/Makefile.am @@ -4,11 +4,12 @@ nfsrpclibdir = $(top_srcdir)/rpc/rpc-lib/src  server_la_LDFLAGS = -module -avoidversion  server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c \  	nfs-generics.c mount3.c nfs3-fh.c nfs3.c nfs3-helpers.c nlm4.c \ -	nlmcbk_svc.c mount3udp_svc.c +	nlmcbk_svc.c mount3udp_svc.c acl3.c  server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la  noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h \  	mount3.h nfs3-fh.h nfs3.h nfs3-helpers.h nfs-mem-types.h nlm4.h +	acl3.h  AM_CPPFLAGS = $(GF_CPPFLAGS) \  	-DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\" \ diff --git a/xlators/nfs/server/src/acl3.c b/xlators/nfs/server/src/acl3.c new file mode 100644 index 000000000..46431a475 --- /dev/null +++ b/xlators/nfs/server/src/acl3.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2012 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 + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "defaults.h" +#include "rpcsvc.h" +#include "dict.h" +#include "xlator.h" +#include "nfs.h" +#include "mem-pool.h" +#include "logging.h" +#include "nfs-fops.h" +#include "inode.h" +#include "nfs3.h" +#include "nfs-mem-types.h" +#include "nfs3-helpers.h" +#include "nfs3-fh.h" +#include "nfs-generics.h" +#include "acl3.h" + + +typedef ssize_t (*acl3_serializer) (struct iovec outmsg, void *args); + +extern void nfs3_call_state_wipe (nfs3_call_state_t *cs); + +extern nfs3_call_state_t * +nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v); + +extern int +nfs3_fh_validate (struct nfs3_fh *fh); + +extern fattr3 +nfs3_stat_to_fattr3 (struct iatt *buf); + +#define acl3_validate_nfs3_state(request, state, status, label, retval) \ +        do      {                                                       \ +                state = rpcsvc_request_program_private (request);       \ +                if (!state) {                                           \ +                        gf_log (GF_ACL, GF_LOG_ERROR, "NFSv3 state "    \ +                                "missing from RPC request");            \ +                        rpcsvc_request_seterr (req, SYSTEM_ERR);        \ +                        status = NFS3ERR_SERVERFAULT;                   \ +                        goto label;                                     \ +                }                                                       \ +        } while (0);                                                    \ + +#define acl3_validate_gluster_fh(handle, status, errlabel)              \ +        do {                                                            \ +                if (!nfs3_fh_validate (handle)) {                       \ +                        status = NFS3ERR_SERVERFAULT;                   \ +                        goto errlabel;                                  \ +                }                                                       \ +        } while (0)                                                     \ + + +extern xlator_t * +nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh); + +#define acl3_map_fh_to_volume(nfs3state, handle, req, volume, status, label) \ +        do {                                                            \ +                char exportid[256], gfid[256];                          \ +                rpc_transport_t *trans = NULL;                          \ +                volume = nfs3_fh_to_xlator ((nfs3state), handle);      \ +                if (!volume) {                                          \ +                        uuid_unparse (handle->exportid, exportid);       \ +                        uuid_unparse (handle->gfid, gfid);               \ +                        trans = rpcsvc_request_transport (req);         \ +                        gf_log (GF_ACL, GF_LOG_ERROR, "Failed to map "  \ +                                "FH to vol: client=%s, exportid=%s, gfid=%s",\ +                                trans->peerinfo.identifier, exportid,   \ +                                gfid);                                  \ +                        gf_log (GF_ACL, GF_LOG_ERROR,                   \ +                                "Stale nfs client %s must be trying to "\ +                                "connect to a deleted volume, please "  \ +                                "unmount it.", trans->peerinfo.identifier);\ +                        status = NFS3ERR_STALE;                         \ +                        goto label;                                     \ +                } else {                                                \ +                        gf_log (GF_ACL, GF_LOG_TRACE, "FH to Volume: %s"\ +                                ,volume->name);                         \ +                        rpcsvc_request_set_private (req, volume);       \ +                }                                                       \ +        } while (0);                                                    \ + +#define acl3_volume_started_check(nfs3state, vlm, rtval, erlbl)         \ +        do {                                                            \ +              if ((!nfs_subvolume_started (nfs_state (nfs3state->nfsx), vlm))){\ +                      gf_log (GF_ACL, GF_LOG_ERROR, "Volume is disabled: %s",\ +                              vlm->name);                               \ +                      rtval = RPCSVC_ACTOR_IGNORE;                      \ +                      goto erlbl;                                       \ +              }                                                         \ +        } while (0)                                                     \ + +#define acl3_check_fh_resolve_status(cst, nfstat, erlabl)               \ +        do {                                                            \ +                xlator_t *xlatorp = NULL;                               \ +                char buf[256], gfid[256];                               \ +                rpc_transport_t *trans = NULL;                          \ +                if ((cst)->resolve_ret < 0) {                           \ +                        trans = rpcsvc_request_transport (cst->req);    \ +                        xlatorp = nfs3_fh_to_xlator (cst->nfs3state,    \ +                                                     &cst->resolvefh);  \ +                        uuid_unparse (cst->resolvefh.gfid, gfid);       \ +                        sprintf (buf, "(%s) %s : %s", trans->peerinfo.identifier,\ +                        xlatorp ? xlatorp->name : "ERR", gfid);         \ +                        gf_log (GF_ACL, GF_LOG_ERROR, "Unable to resolve FH"\ +                                ": %s", buf);                           \ +                        nfstat = nfs3_errno_to_nfsstat3 (cst->resolve_errno);\ +                        goto erlabl;                                    \ +                }                                                       \ +        } while (0)                                                     \ + +#define acl3_handle_call_state_init(nfs3state, calls, rq, v, opstat, errlabel)\ +        do {                                                            \ +                calls = nfs3_call_state_init ((nfs3state), (rq), v); \ +                if (!calls) {                                           \ +                        gf_log (GF_NLM, GF_LOG_ERROR, "Failed to "      \ +                                "init call state");                     \ +                        opstat = nlm4_failed;                           \ +                        rpcsvc_request_seterr (req, SYSTEM_ERR);        \ +                        goto errlabel;                                  \ +                }                                                       \ +        } while (0)                                                     \ + + +int +acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc) +{ +        struct iovec            outmsg = {0, }; +        struct iobuf            *iob = NULL; +        struct nfs3_state       *nfs3 = NULL; +        int                     ret = -1; +        struct iobref           *iobref = NULL; + +        if (!req) +                return -1; + +        nfs3 = (struct nfs3_state *)rpcsvc_request_program_private (req); +        if (!nfs3) { +                gf_log (GF_ACL, GF_LOG_ERROR, "mount state not found"); +                goto ret; +        } + +        /* First, get the io buffer into which the reply in arg will +         * be serialized. +         */ +        iob = iobuf_get (nfs3->iobpool); +        if (!iob) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Failed to get iobuf"); +                goto ret; +        } + +        iobuf_to_iovec (iob, &outmsg); +        /* Use the given serializer to translate the give C structure in arg +         * to XDR format which will be written into the buffer in outmsg. +         */ +        outmsg.iov_len = sfunc (outmsg, arg); + +        iobref = iobref_new (); +        if (iobref == NULL) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Failed to get iobref"); +                goto ret; +        } + +        iobref_add (iobref, iob); + +        /* Then, submit the message for transmission. */ +        ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref); +        if (ret == -1) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Reply submission failed"); +                goto ret; +        } + +        ret = 0; +ret: +        if (iob) +                iobuf_unref (iob); +        if (iobref) +                iobref_unref (iobref); + +        return ret; +} + + +int +acl3svc_null (rpcsvc_request_t *req) +{ +        struct iovec    dummyvec = {0, }; + +        if (!req) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Got NULL request!"); +                return 0; +        } +        rpcsvc_submit_generic (req, &dummyvec, 1,  NULL, 0, NULL); +        return 0; +} + +int +acl3_getacl_reply (nfs3_call_state_t *cs, getaclreply *reply) +{ +        acl3svc_submit_reply (cs->req, (void *)reply, +                              (acl3_serializer)xdr_serialize_getaclreply); +        return 0; +} + + +int +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; + +        cs = frame->local; +        if (op_ret == -1) { +                stat = nfs3_errno_to_nfsstat3 (op_errno); +                goto err; +        } + +        getaclreply = &cs->args.getaclreply; +        getaclreply->aclentry.aclentry_val = cs->aclentry; +        getaclreply->daclentry.daclentry_val = cs->daclentry; + +        /* FIXME: use posix_acl_from_xattr() */ +        data = dict_get (dict, "system.posix_acl_access"); +        if (data && (p = data_to_bin (data))) { +                /* POSIX_ACL_XATTR_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++; +                } +                getaclreply->aclcount = getaclreply->aclentry.aclentry_len = i; +        } +        i = 0; + +        data = dict_get (dict, "system.posix_acl_default"); +        if (data && (p = data_to_bin (data))) { +                /* POSIX_ACL_XATTR_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++; +                } +                getaclreply->daclcount = getaclreply->daclentry.daclentry_len = i; +        } + +        acl3_getacl_reply (cs, getaclreply); +        nfs3_call_state_wipe (cs); +        return 0; + +err: +        getaclreply->status = stat; +        acl3_getacl_reply (cs, getaclreply); +        nfs3_call_state_wipe (cs); +        return 0; +} + +int +acl3_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno, struct iatt *buf, +                  dict_t *xdata) +{ +        nfsstat3                        stat = NFS3ERR_SERVERFAULT; +        nfs3_call_state_t              *cs = NULL; +        getaclreply                     *getaclreply = NULL; +        int                             ret = -1; +        nfs_user_t                      nfu = {0, }; + +        cs = frame->local; +        if (op_ret == -1) { +                stat = nfs3_errno_to_nfsstat3 (op_errno); +                goto err; +        } + +        getaclreply = &cs->args.getaclreply; + +        getaclreply->attr_follows = 1; +        getaclreply->attr = nfs3_stat_to_fattr3 (buf); +        getaclreply->mask = 0xf; +        nfs_request_user_init (&nfu, cs->req); +        ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, NULL, NULL, +                            acl3_getacl_cbk, cs); +        if (ret == -1) { +                stat = nfs3_errno_to_nfsstat3 (op_errno); +                goto err; +        } +        return 0; +err: +        getaclreply->status = stat; +        acl3_getacl_reply (cs, getaclreply); +        nfs3_call_state_wipe (cs); +        return 0; +} + + +int +acl3_getacl_resume (void *carg) +{ +        int                             ret = -1; +        nfs3_call_state_t               *cs = NULL; +        nfsstat3                        stat = NFS3ERR_SERVERFAULT; +        nfs_user_t                      nfu = {0, }; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        acl3_check_fh_resolve_status (cs, stat, acl3err); +        nfs_request_user_init (&nfu, cs->req); + +        ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, +                        acl3_stat_cbk, cs); +        stat = -ret; +acl3err: +        if (ret < 0) { +                gf_log (GF_ACL, GF_LOG_ERROR, "unable to open_and_resume"); +                cs->args.getaclreply.status = nfs3_errno_to_nfsstat3 (stat); +                acl3_getacl_reply (cs, &cs->args.getaclreply); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + + +int +acl3svc_getacl (rpcsvc_request_t *req) +{ +        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, *fhp = NULL; +        getaclargs                      getaclargs; + +        if (!req) +                return ret; + +        acl3_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        memset (&getaclargs, 0, sizeof (getaclargs)); +        getaclargs.fh.n_bytes = (char *)&fh; +        if (xdr_to_getaclargs(req->msg[0], &getaclargs) <= 0) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Error decoding args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } +        fhp = &fh; +        acl3_validate_gluster_fh (&fh, stat, acl3err); +        acl3_map_fh_to_volume (nfs->nfs3state, fhp, req, +                               vol, stat, acl3err); +        acl3_handle_call_state_init (nfs->nfs3state, cs, req, +                                     vol, stat, rpcerr); + +        cs->vol = vol; +        acl3_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nfs3_fh_resolve_and_resume (cs, fhp, +                                          NULL, acl3_getacl_resume); + +acl3err: +        if (ret < 0) { +                gf_log (GF_ACL, GF_LOG_ERROR, "unable to resolve and resume"); +                cs->args.getaclreply.status = stat; +                acl3_getacl_reply (cs, &cs->args.getaclreply); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +rpcerr: +        return ret; +} + +int +acl3_setacl_cbk (call_frame_t *frame, void *cookie, +                 xlator_t *this, int32_t op_ret, int32_t op_errno, +                 dict_t *xdata) +{ +        nfs3_call_state_t               *cs = NULL; +        cs = frame->local; +        if (op_ret < 0) { +                cs->args.setaclreply.status = nfs3_errno_to_nfsstat3 (op_errno); +        } + +        acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply, +                              (acl3_serializer)xdr_serialize_setaclreply); +        return 0; +} + +int +acl3_setacl_resume (void *carg) +{ +        int                             ret = -1; +        nfs3_call_state_t               *cs = NULL; +        nfsstat3                        stat = NFS3ERR_SERVERFAULT; +        nfs_user_t                      nfu = {0, }; +        dict_t                          *xattr = NULL; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        acl3_check_fh_resolve_status (cs, stat, acl3err); +        nfs_request_user_init (&nfu, cs->req); +        xattr = dict_new(); +        if (cs->aclcount) +        ret = dict_set_static_bin (xattr, "system.posix_acl_access", cs->aclxattr, +                                   cs->aclcount * 8 + 4); +        if (cs->daclcount) +        ret = dict_set_static_bin (xattr, "system.posix_acl_default", cs->daclxattr, +                                   cs->daclcount * 8 + 4); + +        ret = nfs_setxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, xattr, +                            0, NULL, acl3_setacl_cbk, cs); +        dict_unref (xattr); + +acl3err: +        if (ret < 0) { +                stat = -ret; +                gf_log (GF_ACL, GF_LOG_ERROR, "unable to open_and_resume"); +                cs->args.setaclreply.status = nfs3_errno_to_nfsstat3 (stat); +                acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply, +                                      (acl3_serializer)xdr_serialize_setaclreply); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + + +int +acl3svc_setacl (rpcsvc_request_t *req) +{ +        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; +        struct nfs3_fh                 *fhp = NULL; +        setaclargs                      setaclargs; +        aclentry                        aclentry[NFS_ACL_MAX_ENTRIES]; +        struct aclentry                 daclentry[NFS_ACL_MAX_ENTRIES]; +        int                             *p = NULL, i = 0; + +        if (!req) +                return ret; + +        acl3_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        memset (&setaclargs, 0, sizeof (setaclargs)); +        memset (&fh, 0, sizeof (fh)); +        setaclargs.fh.n_bytes = (char *)&fh; +        setaclargs.aclentry.aclentry_val = aclentry; +        setaclargs.daclentry.daclentry_val = daclentry; +        if (xdr_to_setaclargs(req->msg[0], &setaclargs) <= 0) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Error decoding args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } +        fhp = &fh; +        acl3_validate_gluster_fh (fhp, stat, acl3err); +        acl3_map_fh_to_volume (nfs->nfs3state, fhp, req, +                               vol, stat, acl3err); +        acl3_handle_call_state_init (nfs->nfs3state, cs, req, +                                     vol, stat, rpcerr); + +        cs->vol = vol; +        acl3_volume_started_check (nfs3, vol, ret, rpcerr); + +        cs->aclcount = setaclargs.aclcount; +        cs->daclcount = setaclargs.daclcount; + +        if ((cs->aclcount > NFS_ACL_MAX_ENTRIES) || +                        (cs->daclcount > NFS_ACL_MAX_ENTRIES)) +                goto acl3err; +        /* FIXME: use posix_acl_to_xattr() */ +        p = (int *)cs->aclxattr; +        *(*(int **)&p)++ = POSIX_ACL_XATTR_VERSION; +        for (i = 0; i < cs->aclcount; i++) { +                *(*(short **)&p)++ = aclentry[i].type; +                *(*(short **)&p)++ = aclentry[i].perm; +                *(*(int **)&p)++ = aclentry[i].uid; +        } +        p = (int *)cs->daclxattr; +        *(*(int **)&p)++ = POSIX_ACL_XATTR_VERSION; +        for (i = 0; i < cs->daclcount; i++) { +                *(*(short **)&p)++ = daclentry[i].type; +                *(*(short **)&p)++ = daclentry[i].perm; +                *(*(int **)&p)++ = daclentry[i].uid; +        } + + +        ret = nfs3_fh_resolve_and_resume (cs, fhp, +                                          NULL, acl3_setacl_resume); + +acl3err: +        if (ret < 0) { +                gf_log (GF_ACL, GF_LOG_ERROR, "unable to resolve and resume"); +                cs->args.setaclreply.status = stat; +                acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply, +                                      (acl3_serializer)xdr_serialize_setaclreply); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +rpcerr: +        if (ret < 0) +                nfs3_call_state_wipe (cs); + +        return ret; +} + + + + +rpcsvc_actor_t  acl3svc_actors[ACL3_PROC_COUNT] = { +        {"NULL",       ACL3_NULL,      acl3svc_null,   NULL,   0}, +        {"GETACL",     ACL3_GETACL,    acl3svc_getacl, NULL,   0}, +        {"SETACL",     ACL3_SETACL,    acl3svc_setacl, NULL,   0}, +}; + +rpcsvc_program_t        acl3prog = { +        .progname       = "ACL3", +        .prognum        = ACL_PROGRAM, +        .progver        = ACL_V3, +        .progport       = GF_NFS3_PORT, +        .actors         = acl3svc_actors, +        .numactors      = ACL3_PROC_COUNT, +        .min_auth       = AUTH_NULL, +}; + +rpcsvc_program_t * +acl3svc_init(xlator_t *nfsx) +{ +        struct nfs3_state *ns = NULL; +        struct nfs_state *nfs = NULL; +        dict_t *options = NULL; +        int ret = -1; +        char *portstr = NULL; + +        nfs = (struct nfs_state*)nfsx->private; + +        ns = nfs->nfs3state; +        if (!ns) { +                gf_log (GF_ACL, GF_LOG_ERROR, "ACL3 init failed"); +                goto err; +        } +        acl3prog.private = ns; + +        options = dict_new (); + +        ret = gf_asprintf (&portstr, "%d", GF_ACL3_PORT); +        if (ret == -1) +                goto err; + +        ret = dict_set_dynstr (options, "transport.socket.listen-port", +                               portstr); +        if (ret == -1) +                goto err; +        ret = dict_set_str (options, "transport-type", "socket"); +        if (ret == -1) { +                gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error"); +                goto err; +        } + +        if (nfs->allow_insecure) { +                ret = dict_set_str (options, "rpc-auth-allow-insecure", "on"); +                if (ret == -1) { +                        gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error"); +                        goto err; +                } +                ret = dict_set_str (options, "rpc-auth.ports.insecure", "on"); +                if (ret == -1) { +                        gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error"); +                        goto err; +                } +        } + +        ret = dict_set_str (options, "transport.address-family", "inet"); +        if (ret == -1) { +                gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error"); +                goto err; +        } + +        rpcsvc_create_listeners (nfs->rpcsvc, options, "ACL"); +        if (ret == -1) { +                gf_log (GF_ACL, GF_LOG_ERROR, "Unable to create listeners"); +                dict_unref (options); +                goto err; +        } + +        return &acl3prog; +err: +        return NULL; +} diff --git a/xlators/nfs/server/src/acl3.h b/xlators/nfs/server/src/acl3.h new file mode 100644 index 000000000..b668723c8 --- /dev/null +++ b/xlators/nfs/server/src/acl3.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 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 + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + +#ifndef _ACL3_H +#define _ACL3_H + +#define GF_ACL3_PORT            38469 +#define GF_ACL                  GF_NFS"-ACL" + +#define ACL_PROGRAM 100227 +#define ACL_V3 3 + +#define ACL_USER_OBJ 0x1 +#define ACL_GROUP_OBJ 0x4 +#define ACL_OTHER_OBJ 0x20 + +#define POSIX_ACL_XATTR_VERSION 0x0002 +#define NFS_ACL_MAX_ENTRIES     1024 + +rpcsvc_program_t * +acl3svc_init(xlator_t *nfsx); + +#endif diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c index 5a2cf2862..df09d22bb 100644 --- a/xlators/nfs/server/src/nfs-fops.c +++ b/xlators/nfs/server/src/nfs-fops.c @@ -1539,6 +1539,95 @@ err:          return ret;  } +int32_t +nfs_fop_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                int32_t op_ret, int32_t op_errno, dict_t *dict, +                dict_t *xdata) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_getxattr_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (nfl, progcbk, frame); + +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, dict, xdata); + +        nfs_stack_destroy (nfl, frame); +        return 0; +} + + +int +nfs_fop_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, +                  char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!loc) || (!nfu)) +                return ret; + +        nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err); +        nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE (frame, nfs_fop_getxattr_cbk, xl, xl, xl->fops->getxattr, +                           loc, name, NULL); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (nfl, frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_setxattr_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (nfl, progcbk, frame); + +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, xdata); + +        nfs_stack_destroy (nfl, frame); +        return 0; +} + + +int +nfs_fop_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, +                  loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata, +                  fop_setxattr_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!loc) || (!nfu)) +                return ret; + +        nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err); +        nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE (frame, nfs_fop_setxattr_cbk, xl, xl, xl->fops->setxattr, +                           loc, dict, flags, xdata); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (nfl, frame); +        } + +        return ret; +} +  int32_t  nfs_fop_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, diff --git a/xlators/nfs/server/src/nfs-fops.h b/xlators/nfs/server/src/nfs-fops.h index b82805939..3ada863de 100644 --- a/xlators/nfs/server/src/nfs-fops.h +++ b/xlators/nfs/server/src/nfs-fops.h @@ -245,4 +245,13 @@ extern int  nfs_fop_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,              int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local); +extern int +nfs_fop_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, +                  char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local); + +extern int +nfs_fop_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, +                  loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata, +                  fop_setxattr_cbk_t cbk, void *local); +  #endif diff --git a/xlators/nfs/server/src/nfs-generics.c b/xlators/nfs/server/src/nfs-generics.c index 553cc7f39..7f79bba9b 100644 --- a/xlators/nfs/server/src/nfs-generics.c +++ b/xlators/nfs/server/src/nfs-generics.c @@ -166,6 +166,22 @@ nfs_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,  }  int +nfs_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, +              char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local) +{ +        return nfs_fop_getxattr (nfsx, xl, nfu, loc, name, xdata, cbk, local); +} + +int +nfs_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, +              loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata, +              fop_setxattr_cbk_t cbk, void *local) +{ +        return nfs_fop_setxattr (nfsx, xl, nfu, loc, dict, flags, xdata, cbk, +                                local); +} + +int  nfs_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,             int32_t datasync, fop_fsync_cbk_t cbk, void *local)  { diff --git a/xlators/nfs/server/src/nfs-generics.h b/xlators/nfs/server/src/nfs-generics.h index 11f191f5f..34e203a62 100644 --- a/xlators/nfs/server/src/nfs-generics.h +++ b/xlators/nfs/server/src/nfs-generics.h @@ -164,4 +164,14 @@ nfs_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,  extern int  nfs_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,          int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local); + +extern int +nfs_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc, +              char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local); + +extern int +nfs_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, +              loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata, +              fop_setxattr_cbk_t cbk, void *local); +  #endif diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index 033d95213..8fa69af6b 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -42,6 +42,7 @@  #include "nfs3-helpers.h"  #include "nlm4.h"  #include "options.h" +#include "acl3.h"  #define OPT_SERVER_AUX_GIDS             "nfs.server-aux-gids"  #define OPT_SERVER_GID_CACHE_TIMEOUT    "nfs.server.aux-gid-timeout" @@ -186,6 +187,13 @@ nfs_add_all_initiators (struct nfs_state *nfs)                  }          } +        ret = nfs_add_initer (&nfs->versions, acl3svc_init); +        if (ret == -1) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol" +                        " initializer"); +                goto ret; +        } +          ret = 0;  ret:          return ret; diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h index 78eb01b60..111542bc6 100644 --- a/xlators/nfs/server/src/nfs3.h +++ b/xlators/nfs/server/src/nfs3.h @@ -35,7 +35,8 @@  #include "xdr-nfs3.h"  #include "mem-pool.h"  #include "nlm4.h" - +#include "acl3-xdr.h" +#include "acl3.h"  #include <sys/statvfs.h>  #define GF_NFS3                 GF_NFS"-nfsv3" @@ -155,6 +156,10 @@ typedef union args_ {          nlm4_shareargs nlm4_shareargs;          nlm4_shareres nlm4_shareres;          nlm4_freeallargs nlm4_freeallargs; +        getaclargs getaclargs; +        setaclargs setaclargs; +        getaclreply getaclreply; +        setaclreply setaclreply;  } args; @@ -234,6 +239,14 @@ struct nfs3_local {          int                     monitor;          rpc_transport_t         *trans;          call_frame_t            *frame; + +        /* ACL */ +        aclentry                aclentry[NFS_ACL_MAX_ENTRIES]; +        aclentry                daclentry[NFS_ACL_MAX_ENTRIES]; +        int                     aclcount; +        char                    aclxattr[NFS_ACL_MAX_ENTRIES*8 + 4]; +        int                     daclcount; +        char                    daclxattr[NFS_ACL_MAX_ENTRIES*8 + 4];  };  #define nfs3_is_revalidate_lookup(cst) ((cst)->lookuptype == GF_NFS3_REVALIDATE)  | 
