From ccde2fdcbe240f8a20524461abea10c8c5c5a79f Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 2 Nov 2017 11:09:20 +0100 Subject: [PATCH 34/79] nss-idmap: allow empty buffer with SSS_NSS_EX_FLAG_INVALIDATE_CACHE Reviewed-by: Jakub Hrozek --- src/sss_client/idmap/sss_nss_ex.c | 89 ++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c index 148eb7b35ec236b6272dd203a0035399cfdef73d..dcd9619a8b07ced7498f61b7e809fa46ebffe09e 100644 --- a/src/sss_client/idmap/sss_nss_ex.c +++ b/src/sss_client/idmap/sss_nss_ex.c @@ -103,8 +103,11 @@ errno_t sss_nss_mc_get(struct nss_input *inp) } } -static int check_flags(uint32_t flags) +static int check_flags(struct nss_input *inp, uint32_t flags, + bool *skip_mc, bool *skip_data) { + bool no_data = false; + /* SSS_NSS_EX_FLAG_NO_CACHE and SSS_NSS_EX_FLAG_INVALIDATE_CACHE are * mutually exclusive */ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0 @@ -112,6 +115,52 @@ static int check_flags(uint32_t flags) return EINVAL; } + *skip_mc = false; + if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0 + || (flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) { + *skip_mc = true; + } + + switch(inp->cmd) { + case SSS_NSS_GETPWNAM: + case SSS_NSS_GETPWNAM_EX: + case SSS_NSS_GETPWUID: + case SSS_NSS_GETPWUID_EX: + if (inp->result.pwrep.buffer == NULL + || inp->result.pwrep.buflen == 0) { + no_data = true; + } + break; + case SSS_NSS_GETGRNAM: + case SSS_NSS_GETGRNAM_EX: + case SSS_NSS_GETGRGID: + case SSS_NSS_GETGRGID_EX: + if (inp->result.grrep.buffer == NULL + || inp->result.grrep.buflen == 0) { + no_data = true; + } + break; + case SSS_NSS_INITGR: + case SSS_NSS_INITGR_EX: + if (inp->result.initgrrep.ngroups == 0 + || inp->result.initgrrep.groups == NULL) { + return EINVAL; + } + break; + default: + return EINVAL; + } + + *skip_data = false; + /* Allow empty buffer with SSS_NSS_EX_FLAG_INVALIDATE_CACHE */ + if (no_data) { + if ((flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) { + *skip_data = true; + } else { + return ERANGE; + } + } + return 0; } @@ -128,18 +177,14 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout) gid_t *new_groups; size_t idx; bool skip_mc = false; + bool skip_data = false; - ret = check_flags(flags); + ret = check_flags(inp, flags, &skip_mc, &skip_data); if (ret != 0) { return ret; } - if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0 - || (flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) { - skip_mc = true; - } - - if (!skip_mc) { + if (!skip_mc && !skip_data) { ret = sss_nss_mc_get(inp); switch (ret) { case 0: @@ -159,7 +204,7 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout) sss_nss_timedlock(timeout, &time_left); - if (!skip_mc) { + if (!skip_mc && !skip_data) { /* previous thread might already initialize entry in mmap cache */ ret = sss_nss_mc_get(inp); switch (ret) { @@ -196,6 +241,12 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout) goto out; } + if (skip_data) { + /* No data requested, just return the return code */ + ret = 0; + goto out; + } + if (inp->cmd == SSS_NSS_INITGR || inp->cmd == SSS_NSS_INITGR_EX) { if ((*(inp->result.initgrrep.ngroups) - *(inp->result.initgrrep.start)) < num_results) { @@ -311,10 +362,6 @@ int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd, .result.pwrep.buffer = buffer, .result.pwrep.buflen = buflen}; - if (buffer == NULL || buflen == 0) { - return ERANGE; - } - ret = make_name_flag_req_data(name, flags, &inp.rd); if (ret != 0) { return ret; @@ -346,10 +393,6 @@ int sss_nss_getpwuid_timeout(uid_t uid, struct passwd *pwd, .result.pwrep.buffer = buffer, .result.pwrep.buflen = buflen}; - if (buffer == NULL || buflen == 0) { - return ERANGE; - } - SAFEALIGN_COPY_UINT32(&req_data[0], &uid, NULL); SAFEALIGN_COPY_UINT32(&req_data[1], &flags, NULL); *result = NULL; @@ -373,10 +416,6 @@ int sss_nss_getgrnam_timeout(const char *name, struct group *grp, .result.grrep.buffer = buffer, .result.grrep.buflen = buflen}; - if (buffer == NULL || buflen == 0) { - return ERANGE; - } - ret = make_name_flag_req_data(name, flags, &inp.rd); if (ret != 0) { return ret; @@ -407,10 +446,6 @@ int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp, .result.grrep.buffer = buffer, .result.grrep.buflen = buflen}; - if (buffer == NULL || buflen == 0) { - return ERANGE; - } - SAFEALIGN_COPY_UINT32(&req_data[0], &gid, NULL); SAFEALIGN_COPY_UINT32(&req_data[1], &flags, NULL); *result = NULL; @@ -434,10 +469,6 @@ int sss_nss_getgrouplist_timeout(const char *name, gid_t group, .input.name = name, .cmd = SSS_NSS_INITGR_EX}; - if (groups == NULL || ngroups == NULL || *ngroups == 0) { - return EINVAL; - } - ret = make_name_flag_req_data(name, flags, &inp.rd); if (ret != 0) { return ret; -- 2.15.1