diff options
-rw-r--r-- | libglusterfs/src/stack.h | 5 | ||||
-rw-r--r-- | rpc/rpc-lib/src/auth-glusterfs.c | 145 | ||||
-rw-r--r-- | rpc/rpc-lib/src/rpc-clnt.c | 297 | ||||
-rw-r--r-- | rpc/rpc-lib/src/rpc-clnt.h | 4 | ||||
-rw-r--r-- | rpc/rpc-lib/src/rpcsvc-auth.c | 12 | ||||
-rw-r--r-- | rpc/rpc-lib/src/rpcsvc.h | 10 | ||||
-rw-r--r-- | rpc/rpc-lib/src/xdr-common.h | 12 | ||||
-rw-r--r-- | rpc/rpc-lib/src/xdr-rpc.h | 1 | ||||
-rw-r--r-- | rpc/xdr/src/glusterfs4-xdr.x | 25 | ||||
-rw-r--r-- | rpc/xdr/src/libgfxdr.sym | 1 | ||||
-rw-r--r-- | xlators/nfs/server/src/nfs-fops.c | 3 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-handshake.c | 25 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 3 |
13 files changed, 413 insertions, 130 deletions
diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h index 251a5c25e85..4a3a788f5ee 100644 --- a/libglusterfs/src/stack.h +++ b/libglusterfs/src/stack.h @@ -117,6 +117,11 @@ struct _call_stack { struct timespec tv; xlator_t *err_xl; int32_t error; + + uint32_t flags; /* use it wisely, think of it as a mechanism to + send information over the wire too */ + struct timespec ctime; /* timestamp, most probably set at + creation of stack. */ }; diff --git a/rpc/rpc-lib/src/auth-glusterfs.c b/rpc/rpc-lib/src/auth-glusterfs.c index 5670b8e840b..78f283557b0 100644 --- a/rpc/rpc-lib/src/auth-glusterfs.c +++ b/rpc/rpc-lib/src/auth-glusterfs.c @@ -16,6 +16,7 @@ #include "xdr-rpc.h" #include "xdr-common.h" #include "rpc-common-xdr.h" +#include "glusterfs4-xdr.h" /* V1 */ @@ -189,8 +190,10 @@ int auth_glusterfs_v2_authenticate (rpcsvc_request_t *req, void *priv) req->auxgidcount = au.groups.groups_len; /* the number of groups and size of lk_owner depend on each other */ - max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (req->lk_owner.len); - max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (req->auxgidcount); + max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (req->lk_owner.len, + AUTH_GLUSTERFS_v2); + max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (req->auxgidcount, + AUTH_GLUSTERFS_v2); if (req->auxgidcount > max_groups) { gf_log ("", GF_LOG_WARNING, @@ -263,3 +266,141 @@ rpcsvc_auth_glusterfs_v2_init (rpcsvc_t *svc, dict_t *options) { return &rpcsvc_auth_glusterfs_v2; } + +/* V3 */ + +ssize_t +xdr_to_glusterfs_auth_v3 (char *buf, struct auth_glusterfs_params_v3 *req) +{ + XDR xdr; + ssize_t ret = -1; + + if ((!buf) || (!req)) + return -1; + + xdrmem_create (&xdr, buf, GF_MAX_AUTH_BYTES, XDR_DECODE); + if (!xdr_auth_glusterfs_params_v3 (&xdr, req)) { + gf_log ("", GF_LOG_WARNING, + "failed to decode glusterfs v3 parameters"); + ret = -1; + goto ret; + } + + ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base)); +ret: + return ret; +} + +int +auth_glusterfs_v3_request_init (rpcsvc_request_t *req, void *priv) +{ + return 0; +} + +int auth_glusterfs_v3_authenticate (rpcsvc_request_t *req, void *priv) +{ + struct auth_glusterfs_params_v3 au = {0,}; + int ret = RPCSVC_AUTH_REJECT; + int i = 0; + int max_groups = 0; + int max_lk_owner_len = 0; + + if (!req) + return ret; + + ret = xdr_to_glusterfs_auth_v3 (req->cred.authdata, &au); + if (ret == -1) { + gf_log ("", GF_LOG_WARNING, + "failed to decode glusterfs credentials"); + ret = RPCSVC_AUTH_REJECT; + goto err; + } + + req->pid = au.pid; + req->uid = au.uid; + req->gid = au.gid; + req->lk_owner.len = au.lk_owner.lk_owner_len; + req->auxgidcount = au.groups.groups_len; + + /* the number of groups and size of lk_owner depend on each other */ + max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (req->lk_owner.len, + AUTH_GLUSTERFS_v3); + max_lk_owner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (req->auxgidcount, + AUTH_GLUSTERFS_v3); + + if (req->auxgidcount > max_groups) { + gf_log ("", GF_LOG_WARNING, + "more than max aux gids found (%d) , truncating it " + "to %d and continuing", au.groups.groups_len, + max_groups); + req->auxgidcount = max_groups; + } + + if (req->lk_owner.len > max_lk_owner_len) { + gf_log ("", GF_LOG_WARNING, + "lkowner field to big (%d), depends on the number of " + "groups (%d), failing authentication", + req->lk_owner.len, req->auxgidcount); + ret = RPCSVC_AUTH_REJECT; + goto err; + } + + if (req->auxgidcount > SMALL_GROUP_COUNT) { + req->auxgidlarge = GF_CALLOC(req->auxgidcount, + sizeof(req->auxgids[0]), + gf_common_mt_auxgids); + req->auxgids = req->auxgidlarge; + } else { + req->auxgids = req->auxgidsmall; + } + + if (!req->auxgids) { + gf_log ("auth-glusterfs-v2", GF_LOG_WARNING, + "cannot allocate gid list"); + ret = RPCSVC_AUTH_REJECT; + goto err; + } + + for (i = 0; i < req->auxgidcount; ++i) + req->auxgids[i] = au.groups.groups_val[i]; + + for (i = 0; i < au.lk_owner.lk_owner_len; ++i) + req->lk_owner.data[i] = au.lk_owner.lk_owner_val[i]; + + /* All new things, starting glusterfs-4.0.0 */ + req->flags = au.flags; + req->ctime.tv_sec = au.ctime_sec; + req->ctime.tv_nsec = au.ctime_nsec; + + gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d" + ", gid: %d, owner: %s, flags: %d", + req->pid, req->uid, req->gid, lkowner_utoa (&req->lk_owner), + req->flags); + ret = RPCSVC_AUTH_ACCEPT; +err: + /* TODO: instead use alloca() for these variables */ + free (au.groups.groups_val); + free (au.lk_owner.lk_owner_val); + + return ret; +} + +rpcsvc_auth_ops_t auth_glusterfs_ops_v3 = { + .transport_init = NULL, + .request_init = auth_glusterfs_v3_request_init, + .authenticate = auth_glusterfs_v3_authenticate +}; + +rpcsvc_auth_t rpcsvc_auth_glusterfs_v3 = { + .authname = "AUTH_GLUSTERFS-v3", + .authnum = AUTH_GLUSTERFS_v3, + .authops = &auth_glusterfs_ops_v3, + .authprivate = NULL +}; + + +rpcsvc_auth_t * +rpcsvc_auth_glusterfs_v3_init (rpcsvc_t *svc, dict_t *options) +{ + return &rpcsvc_auth_glusterfs_v3; +} diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c index 498f6b05f92..35125a25109 100644 --- a/rpc/rpc-lib/src/rpc-clnt.c +++ b/rpc/rpc-lib/src/rpc-clnt.c @@ -937,6 +937,10 @@ rpc_clnt_notify (rpc_transport_t *trans, void *mydata, case RPC_TRANSPORT_DISCONNECT: { rpc_clnt_handle_disconnect (clnt, conn); + /* reset auth_type to use v2 (if its not auth-null), it + would be set to appropriate type in handshake again */ + if (clnt->auth_value) + clnt->auth_value = AUTH_GLUSTERFS_v2; break; } @@ -1161,7 +1165,11 @@ rpc_clnt_new (dict_t *options, xlator_t *owner, char *name, goto out; } - rpc->auth_null = dict_get_str_boolean (options, "auth-null", 0); + /* This is handled to make sure we have modularity in getting the + auth data changed */ + gf_boolean_t auth_null = dict_get_str_boolean(options, "auth-null", 0); + + rpc->auth_value = (auth_null) ? 0 : AUTH_GLUSTERFS_v2; rpc = rpc_clnt_ref (rpc); INIT_LIST_HEAD (&rpc->programs); @@ -1236,51 +1244,177 @@ rpc_clnt_register_notify (struct rpc_clnt *rpc, rpc_clnt_notify_t fn, /* used for GF_LOG_OCCASIONALLY() */ static int gf_auth_max_groups_log = 0; -ssize_t -xdr_serialize_glusterfs_auth (char *dest, struct auth_glusterfs_parms_v2 *au) +static inline int +setup_glusterfs_auth_param_v3 (call_frame_t *frame, + auth_glusterfs_params_v3 *au, + int lk_owner_len, char *owner_data) +{ + int ret = -1; + unsigned int max_groups = 0; + int max_lkowner_len = 0; + + au->pid = frame->root->pid; + au->uid = frame->root->uid; + au->gid = frame->root->gid; + + au->flags = frame->root->flags; + au->ctime_sec = frame->root->ctime.tv_sec; + au->ctime_nsec = frame->root->ctime.tv_nsec; + + au->lk_owner.lk_owner_val = owner_data; + au->lk_owner.lk_owner_len = lk_owner_len; + au->groups.groups_val = frame->root->groups; + au->groups.groups_len = frame->root->ngrps; + + /* The number of groups and the size of lk_owner depend on oneother. + * We can truncate the groups, but should not touch the lk_owner. */ + max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (lk_owner_len, AUTH_GLUSTERFS_v3); + if (au->groups.groups_len > max_groups) { + GF_LOG_OCCASIONALLY (gf_auth_max_groups_log, "rpc-auth", + GF_LOG_WARNING, "truncating grouplist " + "from %d to %d", au->groups.groups_len, + max_groups); + + au->groups.groups_len = max_groups; + } + + max_lkowner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (au->groups.groups_len, + AUTH_GLUSTERFS_v3); + if (lk_owner_len > max_lkowner_len) { + gf_log ("rpc-clnt", GF_LOG_ERROR, "lkowner field is too " + "big (%d), it does not fit in the rpc-header", + au->lk_owner.lk_owner_len); + errno = E2BIG; + goto out; + } + + ret = 0; +out: + return ret; +} + +static inline int +setup_glusterfs_auth_param_v2 (call_frame_t *frame, + auth_glusterfs_parms_v2 *au, + int lk_owner_len, char *owner_data) +{ + unsigned int max_groups = 0; + int max_lkowner_len = 0; + int ret = -1; + + au->pid = frame->root->pid; + au->uid = frame->root->uid; + au->gid = frame->root->gid; + + au->lk_owner.lk_owner_val = owner_data; + au->lk_owner.lk_owner_len = lk_owner_len; + au->groups.groups_val = frame->root->groups; + au->groups.groups_len = frame->root->ngrps; + + /* The number of groups and the size of lk_owner depend on oneother. + * We can truncate the groups, but should not touch the lk_owner. */ + max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (lk_owner_len, AUTH_GLUSTERFS_v2); + if (au->groups.groups_len > max_groups) { + GF_LOG_OCCASIONALLY (gf_auth_max_groups_log, "rpc-auth", + GF_LOG_WARNING, "truncating grouplist " + "from %d to %d", au->groups.groups_len, + max_groups); + + au->groups.groups_len = max_groups; + } + + max_lkowner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (au->groups.groups_len, + AUTH_GLUSTERFS_v2); + if (lk_owner_len > max_lkowner_len) { + gf_log ("rpc-auth", GF_LOG_ERROR, "lkowner field is too " + "big (%d), it does not fit in the rpc-header", + au->lk_owner.lk_owner_len); + errno = E2BIG; + goto out; + } + + ret = 0; +out: + return ret; +} + + +static ssize_t +xdr_serialize_glusterfs_auth (struct rpc_clnt *clnt, call_frame_t *frame, + char *dest) { ssize_t ret = -1; XDR xdr; - u_long ngroups = 0; - int max_groups = 0; + char owner[4] = {0,}; + int32_t pid = 0; + char *lk_owner_data = NULL; + int lk_owner_len = 0; - if ((!dest) || (!au)) + if ((!dest)) return -1; - max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (au->lk_owner.lk_owner_len); - xdrmem_create (&xdr, dest, GF_MAX_AUTH_BYTES, XDR_ENCODE); - if (au->groups.groups_len > max_groups) { - ngroups = au->groups.groups_len; - au->groups.groups_len = max_groups; + if (frame->root->lk_owner.len) { + lk_owner_data = frame->root->lk_owner.data; + lk_owner_len = frame->root->lk_owner.len; + } else { + pid = frame->root->pid; + owner[0] = (char)(pid & 0xff); + owner[1] = (char)((pid >> 8) & 0xff); + owner[2] = (char)((pid >> 16) & 0xff); + owner[3] = (char)((pid >> 24) & 0xff); - GF_LOG_OCCASIONALLY (gf_auth_max_groups_log, - THIS->name, GF_LOG_WARNING, - "too many groups, reducing %ld -> %d", - ngroups, max_groups); + lk_owner_data = owner; + lk_owner_len = 4; } - if (!xdr_auth_glusterfs_parms_v2 (&xdr, au)) { + if (clnt->auth_value == AUTH_GLUSTERFS_v2) { + auth_glusterfs_parms_v2 au_v2 = {0,}; + + ret = setup_glusterfs_auth_param_v2 (frame, &au_v2, + lk_owner_len, + lk_owner_data); + if (ret) + goto out; + if (!xdr_auth_glusterfs_parms_v2 (&xdr, &au_v2)) { + gf_log (THIS->name, GF_LOG_WARNING, + "failed to encode auth glusterfs elements"); + ret = -1; + goto out; + } + } else if (clnt->auth_value == AUTH_GLUSTERFS_v3) { + auth_glusterfs_params_v3 au_v3 = {0,}; + + ret = setup_glusterfs_auth_param_v3 (frame, &au_v3, + lk_owner_len, + lk_owner_data); + if (ret) + goto out; + + if (!xdr_auth_glusterfs_params_v3 (&xdr, &au_v3)) { + gf_log (THIS->name, GF_LOG_WARNING, + "failed to encode auth glusterfs elements"); + ret = -1; + goto out; + } + } else { gf_log (THIS->name, GF_LOG_WARNING, "failed to encode auth glusterfs elements"); ret = -1; - goto ret; + goto out; } ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base)); -ret: - if (ngroups) - au->groups.groups_len = ngroups; - +out: return ret; } int -rpc_clnt_fill_request (int prognum, int progver, int procnum, - uint64_t xid, struct auth_glusterfs_parms_v2 *au, +rpc_clnt_fill_request (struct rpc_clnt *clnt, int prognum, int progver, + int procnum, uint64_t xid, call_frame_t *fr, struct rpc_msg *request, char *auth_data) { int ret = -1; @@ -1299,25 +1433,21 @@ rpc_clnt_fill_request (int prognum, int progver, int procnum, request->rm_call.cb_vers = progver; request->rm_call.cb_proc = procnum; - /* TODO: Using AUTH_(GLUSTERFS/NULL) in a kludgy way for time-being. - * Make it modular in future so it is easy to plug-in new - * authentication schemes. - */ - if (auth_data) { - ret = xdr_serialize_glusterfs_auth (auth_data, au); + if (!clnt->auth_value) { + request->rm_call.cb_cred.oa_flavor = AUTH_NULL; + request->rm_call.cb_cred.oa_base = NULL; + request->rm_call.cb_cred.oa_length = 0; + } else { + ret = xdr_serialize_glusterfs_auth (clnt, fr, auth_data); if (ret == -1) { - gf_log ("rpc-clnt", GF_LOG_DEBUG, - "cannot encode credentials"); + gf_log ("rpc-clnt", GF_LOG_WARNING, + "cannot encode auth credentials"); goto out; } - request->rm_call.cb_cred.oa_flavor = AUTH_GLUSTERFS_v2; + request->rm_call.cb_cred.oa_flavor = clnt->auth_value; request->rm_call.cb_cred.oa_base = auth_data; request->rm_call.cb_cred.oa_length = ret; - } else { - request->rm_call.cb_cred.oa_flavor = AUTH_NULL; - request->rm_call.cb_cred.oa_base = NULL; - request->rm_call.cb_cred.oa_length = 0; } request->rm_call.cb_verf.oa_flavor = AUTH_NONE; request->rm_call.cb_verf.oa_base = NULL; @@ -1365,9 +1495,9 @@ out: struct iobuf * -rpc_clnt_record_build_record (struct rpc_clnt *clnt, int prognum, int progver, +rpc_clnt_record_build_record (struct rpc_clnt *clnt, call_frame_t *fr, + int prognum, int progver, int procnum, size_t hdrsize, uint64_t xid, - struct auth_glusterfs_parms_v2 *au, struct iovec *recbuf) { struct rpc_msg request = {0, }; @@ -1379,17 +1509,13 @@ rpc_clnt_record_build_record (struct rpc_clnt *clnt, int prognum, int progver, size_t xdr_size = 0; char auth_data[GF_MAX_AUTH_BYTES] = {0, }; - if ((!clnt) || (!recbuf) || (!au)) { + if ((!clnt) || (!recbuf)) { goto out; } /* Fill the rpc structure and XDR it into the buffer got above. */ - if (clnt->auth_null) - ret = rpc_clnt_fill_request (prognum, progver, procnum, - xid, NULL, &request, NULL); - else - ret = rpc_clnt_fill_request (prognum, progver, procnum, - xid, au, &request, auth_data); + ret = rpc_clnt_fill_request (clnt, prognum, progver, procnum, + xid, fr, &request, auth_data); if (ret == -1) { gf_log (clnt->conn.name, GF_LOG_WARNING, @@ -1431,80 +1557,21 @@ out: } -struct iobuf * +static inline struct iobuf * rpc_clnt_record (struct rpc_clnt *clnt, call_frame_t *call_frame, rpc_clnt_prog_t *prog, int procnum, size_t hdrlen, struct iovec *rpchdr, uint64_t callid) { - struct auth_glusterfs_parms_v2 au = {0, }; - struct iobuf *request_iob = NULL; - char owner[4] = {0,}; - int max_groups = 0; - int max_lkowner_len = 0; if (!prog || !rpchdr || !call_frame) { - goto out; - } - - au.pid = call_frame->root->pid; - au.uid = call_frame->root->uid; - au.gid = call_frame->root->gid; - au.groups.groups_len = call_frame->root->ngrps; - au.lk_owner.lk_owner_len = call_frame->root->lk_owner.len; - - if (au.groups.groups_len) - au.groups.groups_val = call_frame->root->groups; - - if (call_frame->root->lk_owner.len) - au.lk_owner.lk_owner_val = call_frame->root->lk_owner.data; - else { - owner[0] = (char)(au.pid & 0xff); - owner[1] = (char)((au.pid >> 8) & 0xff); - owner[2] = (char)((au.pid >> 16) & 0xff); - owner[3] = (char)((au.pid >> 24) & 0xff); - - au.lk_owner.lk_owner_val = owner; - au.lk_owner.lk_owner_len = 4; - } - - /* The number of groups and the size of lk_owner depend on oneother. - * We can truncate the groups, but should not touch the lk_owner. */ - max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS (au.lk_owner.lk_owner_len); - if (au.groups.groups_len > max_groups) { - GF_LOG_OCCASIONALLY (gf_auth_max_groups_log, clnt->conn.name, - GF_LOG_WARNING, "truncating grouplist " - "from %d to %d", au.groups.groups_len, - max_groups); - - au.groups.groups_len = max_groups; - } - - max_lkowner_len = GF_AUTH_GLUSTERFS_MAX_LKOWNER (au.groups.groups_len); - if (au.lk_owner.lk_owner_len > max_lkowner_len) { - gf_log (clnt->conn.name, GF_LOG_ERROR, "lkowner field is too " - "big (%d), it does not fit in the rpc-header", - au.lk_owner.lk_owner_len); - errno = E2BIG; - goto out; - } - - gf_log (clnt->conn.name, GF_LOG_TRACE, "Auth Info: pid: %u, uid: %d" - ", gid: %d, owner: %s", au.pid, au.uid, au.gid, - lkowner_utoa (&call_frame->root->lk_owner)); - - request_iob = rpc_clnt_record_build_record (clnt, prog->prognum, - prog->progver, - procnum, hdrlen, - callid, &au, - rpchdr); - if (!request_iob) { - gf_log (clnt->conn.name, GF_LOG_WARNING, - "cannot build rpc-record"); - goto out; + return NULL; } -out: - return request_iob; + return rpc_clnt_record_build_record (clnt, call_frame, + prog->prognum, + prog->progver, + procnum, hdrlen, + callid, rpchdr); } int @@ -1887,6 +1954,10 @@ rpc_clnt_disable (struct rpc_clnt *rpc) if (trans) { rpc_transport_disconnect (trans, _gf_true); + /* reset auth_type to use v2 (if its not auth-null), it + would be set to appropriate type in handshake again */ + if (rpc->auth_value) + rpc->auth_value = AUTH_GLUSTERFS_v2; } if (unref) @@ -1946,6 +2017,10 @@ rpc_clnt_disconnect (struct rpc_clnt *rpc) if (trans) { rpc_transport_disconnect (trans, _gf_true); + /* reset auth_type to use v2 (if its not auth-null), it + would be set to appropriate type in handshake again */ + if (rpc->auth_value) + rpc->auth_value = AUTH_GLUSTERFS_v2; } if (unref) rpc_clnt_unref (rpc); diff --git a/rpc/rpc-lib/src/rpc-clnt.h b/rpc/rpc-lib/src/rpc-clnt.h index 6503ca5a573..867592122cd 100644 --- a/rpc/rpc-lib/src/rpc-clnt.h +++ b/rpc/rpc-lib/src/rpc-clnt.h @@ -15,6 +15,7 @@ #include "rpc-transport.h" #include "timer.h" #include "xdr-common.h" +#include "glusterfs3.h" typedef enum { RPC_CLNT_CONNECT, @@ -188,12 +189,11 @@ typedef struct rpc_clnt { glusterfs_ctx_t *ctx; gf_atomic_t refcount; - int auth_null; + int auth_value; char disabled; xlator_t *owner; } rpc_clnt_t; - struct rpc_clnt *rpc_clnt_new (dict_t *options, xlator_t *owner, char *name, uint32_t reqpool_size); diff --git a/rpc/rpc-lib/src/rpcsvc-auth.c b/rpc/rpc-lib/src/rpcsvc-auth.c index bfff0bc557f..ef9b35f56ad 100644 --- a/rpc/rpc-lib/src/rpcsvc-auth.c +++ b/rpc/rpc-lib/src/rpcsvc-auth.c @@ -22,6 +22,8 @@ extern rpcsvc_auth_t * rpcsvc_auth_glusterfs_init (rpcsvc_t *svc, dict_t *options); extern rpcsvc_auth_t * rpcsvc_auth_glusterfs_v2_init (rpcsvc_t *svc, dict_t *options); +extern rpcsvc_auth_t * +rpcsvc_auth_glusterfs_v3_init (rpcsvc_t *svc, dict_t *options); int rpcsvc_auth_add_initer (struct list_head *list, char *idfier, @@ -69,6 +71,15 @@ rpcsvc_auth_add_initers (rpcsvc_t *svc) goto err; } + ret = rpcsvc_auth_add_initer (&svc->authschemes, "auth-glusterfs-v3", + (rpcsvc_auth_initer_t) + rpcsvc_auth_glusterfs_v3_init); + if (ret == -1) { + gf_log (GF_RPCSVC, GF_LOG_ERROR, + "Failed to add AUTH_GLUSTERFS-v3"); + goto err; + } + ret = rpcsvc_auth_add_initer (&svc->authschemes, "auth-unix", (rpcsvc_auth_initer_t) rpcsvc_auth_unix_init); @@ -507,6 +518,7 @@ rpcsvc_auth_unix_auxgids (rpcsvc_request_t *req, int *arrlen) case AUTH_UNIX: case AUTH_GLUSTERFS: case AUTH_GLUSTERFS_v2: + case AUTH_GLUSTERFS_v3: break; default: gf_log ("rpc", GF_LOG_DEBUG, "auth type not unix or glusterfs"); diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h index 533e6bde374..878eea28999 100644 --- a/rpc/rpc-lib/src/rpcsvc.h +++ b/rpc/rpc-lib/src/rpcsvc.h @@ -250,6 +250,16 @@ struct rpcsvc_request { /* request queue in rpcsvc */ struct list_head request_list; + + /* Things passed to rpc layer from client */ + + /* @flags: Can be used for binary data passed in xdata to be + passed here instead */ + unsigned int flags; + + /* ctime: origin of time on the client side, ideally this is + the one we should consider for time */ + struct timespec ctime; }; #define rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->prog)) diff --git a/rpc/rpc-lib/src/xdr-common.h b/rpc/rpc-lib/src/xdr-common.h index dd93110190f..db6b5f1a0d2 100644 --- a/rpc/rpc-lib/src/xdr-common.h +++ b/rpc/rpc-lib/src/xdr-common.h @@ -54,11 +54,15 @@ enum gf_dump_procnum { * Note that the on-wire protocol has tighter requirements than the internal * structures. It is possible for xlators to use more groups and a bigger * lk_owner than that can be sent by a GlusterFS-client. + * + * ------- + * On v3, there are 4 more units, and hence it will be 9 xdr-units */ -#define GF_AUTH_GLUSTERFS_MAX_GROUPS(lk_owner_len) \ - (95 - lk_owner_len) -#define GF_AUTH_GLUSTERFS_MAX_LKOWNER(groups_len) \ - (95 - groups_len) +#define GF_AUTH_GLUSTERFS_MAX_GROUPS(lk_len, type) \ + ((type == AUTH_GLUSTERFS_v2) ? (95 - lk_len) : (91 - lk_len)) +#define GF_AUTH_GLUSTERFS_MAX_LKOWNER(groups_len, type) \ + ((type == AUTH_GLUSTERFS_v2) ? (95 - groups_len) : (91 - groups_len)) + #ifdef GF_LINUX_HOST_OS #define xdr_u_int32_t xdr_uint32_t diff --git a/rpc/rpc-lib/src/xdr-rpc.h b/rpc/rpc-lib/src/xdr-rpc.h index ec24ca8200a..5560e89328f 100644 --- a/rpc/rpc-lib/src/xdr-rpc.h +++ b/rpc/rpc-lib/src/xdr-rpc.h @@ -31,6 +31,7 @@ typedef enum { AUTH_GLUSTERFS = 5, AUTH_GLUSTERFS_v2 = 390039, /* using a number from 'unused' range, from the list available in RFC5531 */ + AUTH_GLUSTERFS_v3 = 390040, /* this too is unused */ } gf_rpc_authtype_t; /* Converts a given network buffer from its XDR format to a structure diff --git a/rpc/xdr/src/glusterfs4-xdr.x b/rpc/xdr/src/glusterfs4-xdr.x index ef0cfde0802..9e3223b58b5 100644 --- a/rpc/xdr/src/glusterfs4-xdr.x +++ b/rpc/xdr/src/glusterfs4-xdr.x @@ -33,6 +33,31 @@ union gfx_value switch (gf_dict_data_type_t type) { opaque other<>; }; +/* AUTH */ +/* This is used in the rpc header part itself, And not program payload. + Avoid sending large data load here. Allowed maximum is 400 bytes. + Ref: http://tools.ietf.org/html/rfc5531#section-8.2 + this is also handled in xdr-common.h +*/ +struct auth_glusterfs_params_v3 { + int pid; + unsigned int uid; + unsigned int gid; + + /* flags */ + /* Makes sense to use it for each bits */ + /* 0x1 == IS_INTERNAL? */ + /* Another 31 bits are reserved */ + unsigned int flags; + + /* birth time of the frame / call */ + unsigned int ctime_nsec; /* good to have 32bit for this */ + unsigned hyper ctime_sec; + + unsigned int groups<>; + opaque lk_owner<>; +}; + struct gfx_dict_pair { opaque key<>; gfx_value value; diff --git a/rpc/xdr/src/libgfxdr.sym b/rpc/xdr/src/libgfxdr.sym index 83f1efc732a..f6aa300544a 100644 --- a/rpc/xdr/src/libgfxdr.sym +++ b/rpc/xdr/src/libgfxdr.sym @@ -1,5 +1,6 @@ xdr_auth_glusterfs_parms xdr_auth_glusterfs_parms_v2 +xdr_auth_glusterfs_params_v3 xdr_changelog_event_req xdr_changelog_event_rsp xdr_changelog_probe_req diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c index 601f29fcef9..7c2aab53573 100644 --- a/xlators/nfs/server/src/nfs-fops.c +++ b/xlators/nfs/server/src/nfs-fops.c @@ -44,7 +44,8 @@ nfs_fix_groups (xlator_t *this, call_stack_t *root) } /* RPC enforces the GF_AUTH_GLUSTERFS_MAX_GROUPS limit */ - max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS(root->lk_owner.len); + max_groups = GF_AUTH_GLUSTERFS_MAX_GROUPS(root->lk_owner.len, + AUTH_GLUSTERFS_v2); agl = gid_cache_lookup(&priv->gid_cache, root->uid, 0, 0); if (agl) { diff --git a/xlators/protocol/client/src/client-handshake.c b/xlators/protocol/client/src/client-handshake.c index 68ea20ffed7..2d779fa39b7 100644 --- a/xlators/protocol/client/src/client-handshake.c +++ b/xlators/protocol/client/src/client-handshake.c @@ -20,6 +20,7 @@ #include "portmap-xdr.h" #include "rpc-common-xdr.h" #include "client-messages.h" +#include "xdr-rpc.h" #define CLIENT_REOPEN_MAX_ATTEMPTS 1024 extern rpc_clnt_prog_t clnt3_3_fop_prog; @@ -1482,35 +1483,39 @@ select_server_supported_programs (xlator_t *this, gf_prog_detail *prog) while (trav) { /* Select 'programs' */ if ((clnt3_3_fop_prog.prognum == trav->prognum) && - (clnt3_3_fop_prog.progver == trav->progver)) { + (clnt3_3_fop_prog.progver == trav->progver) && + !conf->fops) { conf->fops = &clnt3_3_fop_prog; - gf_msg (this->name, GF_LOG_INFO, 0, - PC_MSG_VERSION_INFO, "Using Program %s, " - "Num (%"PRId64"), Version (%"PRId64")", - trav->progname, trav->prognum, trav->progver); + if (conf->rpc) + conf->rpc->auth_value = AUTH_GLUSTERFS_v2; ret = 0; } if ((clnt4_0_fop_prog.prognum == trav->prognum) && (clnt4_0_fop_prog.progver == trav->progver)) { conf->fops = &clnt4_0_fop_prog; - gf_msg (this->name, GF_LOG_INFO, 0, - PC_MSG_VERSION_INFO, "Using Program %s," - " Num (%"PRId64"), Version (%"PRId64")", - trav->progname, trav->prognum, trav->progver); + if (conf->rpc) + conf->rpc->auth_value = AUTH_GLUSTERFS_v3; ret = 0; /* this is latest program, lets use it */ goto out; } if (ret) { - gf_msg_trace (this->name, 0, + gf_msg_debug (this->name, 0, "%s (%"PRId64") not supported", trav->progname, trav->progver); } trav = trav->next; } + if (!ret) + gf_msg (this->name, GF_LOG_INFO, 0, + PC_MSG_VERSION_INFO, "Using Program %s," + " Num (%d), Version (%d)", + conf->fops->progname, conf->fops->prognum, + conf->fops->progver); + out: return ret; } diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index 7ff5f16e7f0..1f9e9e8acb2 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -507,6 +507,9 @@ get_frame_from_request (rpcsvc_request_t *req) sizeof (trans->peerinfo.identifier)); } + /* more fields, for the clients which are 3.x series this will be 0 */ + frame->root->flags = req->flags; + frame->root->ctime = req->ctime; frame->local = req; |