diff options
Diffstat (limited to 'rpc/rpc-lib/src')
| -rw-r--r-- | rpc/rpc-lib/src/auth-glusterfs.c | 22 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-clnt.c | 44 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/xdr-common.h | 30 | 
3 files changed, 88 insertions, 8 deletions
diff --git a/rpc/rpc-lib/src/auth-glusterfs.c b/rpc/rpc-lib/src/auth-glusterfs.c index db488434c98..f17b34f3e6c 100644 --- a/rpc/rpc-lib/src/auth-glusterfs.c +++ b/rpc/rpc-lib/src/auth-glusterfs.c @@ -184,8 +184,10 @@ auth_glusterfs_v2_request_init (rpcsvc_request_t *req, void *priv)  int auth_glusterfs_v2_authenticate (rpcsvc_request_t *req, void *priv)  {          struct auth_glusterfs_parms_v2  au = {0,}; -        int ret = RPCSVC_AUTH_REJECT; -        int i   = 0; +        int ret                            = RPCSVC_AUTH_REJECT; +        int i                              = 0; +        int max_groups                     = 0; +        int max_lk_owner_len               = 0;          if (!req)                  return ret; @@ -204,17 +206,23 @@ int auth_glusterfs_v2_authenticate (rpcsvc_request_t *req, void *priv)          req->lk_owner.len = au.lk_owner.lk_owner_len;          req->auxgidcount = au.groups.groups_len; -        if (req->auxgidcount > GF_MAX_AUX_GROUPS) { +        /* 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); + +        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, -                        GF_MAX_AUX_GROUPS); -                req->auxgidcount = GF_MAX_AUX_GROUPS; +                        max_groups); +                req->auxgidcount = max_groups;          } -        if (req->lk_owner.len > GF_MAX_LOCK_OWNER_LEN) { +        if (req->lk_owner.len > max_lk_owner_len) {                  gf_log ("", GF_LOG_WARNING, -                        "lkowner field > 1k, failing authentication"); +                        "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;          } diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c index 1e9f307be40..ff3231d7f8d 100644 --- a/rpc/rpc-lib/src/rpc-clnt.c +++ b/rpc/rpc-lib/src/rpc-clnt.c @@ -1095,17 +1095,34 @@ rpc_clnt_register_notify (struct rpc_clnt *rpc, rpc_clnt_notify_t fn,          return 0;  } +/* 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)  {          ssize_t ret = -1;          XDR     xdr; +        uint64_t ngroups = 0; +        int     max_groups = 0;          if ((!dest) || (!au))                  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; + +                GF_LOG_OCCASIONALLY (gf_auth_max_groups_log, +                                     THIS->name, GF_LOG_WARNING, +                                     "too many groups, reducing %ld -> %d", +                                     ngroups, max_groups); +        } +          if (!xdr_auth_glusterfs_parms_v2 (&xdr, au)) {                  gf_log (THIS->name, GF_LOG_WARNING,                          "failed to encode auth glusterfs elements"); @@ -1116,6 +1133,9 @@ xdr_serialize_glusterfs_auth (char *dest, struct auth_glusterfs_parms_v2 *au)          ret = (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base));  ret: +        if (ngroups) +                au->groups.groups_len = ngroups; +          return ret;  } @@ -1281,6 +1301,8 @@ rpc_clnt_record (struct rpc_clnt *clnt, call_frame_t *call_frame,          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; @@ -1307,6 +1329,28 @@ rpc_clnt_record (struct rpc_clnt *clnt, call_frame_t *call_frame,                  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.trans->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.trans->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.trans->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)); diff --git a/rpc/rpc-lib/src/xdr-common.h b/rpc/rpc-lib/src/xdr-common.h index 34dc9c6a228..f221192adbe 100644 --- a/rpc/rpc-lib/src/xdr-common.h +++ b/rpc/rpc-lib/src/xdr-common.h @@ -18,6 +18,7 @@  #include <rpc/types.h>  #include <sys/types.h> +#include <rpc/auth.h>  #include <rpc/xdr.h>  #include <sys/uio.h> @@ -34,7 +35,34 @@ enum gf_dump_procnum {  #define GLUSTER_DUMP_PROGRAM 123451501 /* Completely random */  #define GLUSTER_DUMP_VERSION 1 -#define GF_MAX_AUTH_BYTES   2048 +/* MAX_AUTH_BYTES is restricted to 400 bytes, see + * http://tools.ietf.org/html/rfc5531#section-8.2 */ +#define GF_MAX_AUTH_BYTES   MAX_AUTH_BYTES + +/* The size of an AUTH_GLUSTERFS_V2 structure: + * + *   1 | pid + *   1 | uid + *   1 | gid + *   1 | groups_len + *  XX | groups_val (GF_MAX_AUX_GROUPS=65535) + *   1 | lk_owner_len + *  YY | lk_owner_val (GF_MAX_LOCK_OWNER_LEN=1024) + * ----+------------------------------------------- + *   5 | total xdr-units + * + * one XDR-unit is defined as BYTES_PER_XDR_UNIT = 4 bytes + * MAX_AUTH_BYTES = 400 is the maximum, this is 100 xdr-units. + * XX + YY can be 95 to fill the 100 xdr-units. + * + * 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. + */ +#define GF_AUTH_GLUSTERFS_MAX_GROUPS(lk_owner_len) \ +           (95 - lk_owner_len) +#define GF_AUTH_GLUSTERFS_MAX_LKOWNER(groups_len)  \ +           (95 - groups_len)  #if GF_DARWIN_HOST_OS  #define xdr_u_quad_t xdr_u_int64_t  | 
