nsssrv_cmd.c revision e61587a5d620310c09f226f43c9bb3008481bbe3
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin NSS Responder
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin This program is free software; you can redistribute it and/or modify
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin it under the terms of the GNU General Public License as published by
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin the Free Software Foundation; either version 3 of the License, or
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin (at your option) any later version.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin This program is distributed in the hope that it will be useful,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin but WITHOUT ANY WARRANTY; without even the implied warranty of
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin GNU General Public License for more details.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin You should have received a copy of the GNU General Public License
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin along with this program. If not, see <http://www.gnu.org/licenses/>.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic int nss_cmd_send_empty(struct nss_cmd_ctx *cmdctx)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinint nss_cmd_done(struct nss_cmd_ctx *cmdctx, int ret)
016241a6ee9c7b02ff94f30f90e705012ea08e41jsl /* all fine, just return here */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* async processing, just return here */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* very bad error */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin/***************************
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * Enumeration procedures *
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ***************************/
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin return setent_add_ref(memctx, getent_ctx, &getent_ctx->reqs, req);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinvoid nss_setent_notify_error(struct getent_ctx *getent_ctx, errno_t ret)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinvoid nss_setent_notify_done(struct getent_ctx *getent_ctx)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin/****************************************************************************
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * PASSWD db related functions
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ***************************************************************************/
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *id;
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin for (dom = nctx->rctx->domains; dom != NULL; dom = dom->next) {
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("Failed to enumerate users for domain [%s]\n", dom->name));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* names require more manipulation (build up fqname conditionally),
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * but uidNumber is unique and always resolvable too, so we use
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * that to update the cache, as it points to the same entry */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin id = ldb_msg_find_attr_as_string(res->msgs[i], SYSDB_UIDNUM, NULL);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("Failed to find uidNumber in %s.\n",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ret = sss_mmap_cache_pw_invalidate(nctx->pwd_mc_ctx, &key);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("Internal failure in memory cache code: %d [%s]\n",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic gid_t get_gid_override(struct ldb_message *msg,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic const char *get_homedir_override(TALLOC_CTX *mem_ctx,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *name,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *homedir;
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* Check whether we are unconditionally overriding the server
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * for home directory locations.
016241a6ee9c7b02ff94f30f90e705012ea08e41jsl return expand_homedir_template(mem_ctx, dom->override_homedir,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin return expand_homedir_template(mem_ctx, nctx->override_homedir,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* In the case of a NULL or empty homedir, check to see if
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * we have a fallback homedir to use.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin return expand_homedir_template(mem_ctx, dom->fallback_homedir,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin return expand_homedir_template(mem_ctx, nctx->fallback_homedir,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* Return the value we got from the provider */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic const char *get_shell_override(TALLOC_CTX *mem_ctx,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* Check whether we are unconditionally overriding the server
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * for the login shell.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin user_shell = ldb_msg_find_attr_as_string(msg, SYSDB_SHELL, NULL);
016241a6ee9c7b02ff94f30f90e705012ea08e41jsl /* Check whether there is a default shell specified */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin if (!nctx->allowed_shells && !nctx->vetoed_shells) return talloc_strdup(mem_ctx, user_shell);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin if (strcmp(nctx->vetoed_shells[i], user_shell) == 0) {
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(9, ("Using original shell '%s'\n", user_shell));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin if (strcmp(nctx->allowed_shells[i], user_shell) == 0) {
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(5, ("The shell '%s' is allowed but does not exist. "
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin return talloc_strdup(mem_ctx, nctx->shell_fallback);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(5, ("The shell '%s' is not allowed and does not exist.\n",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *tmpstr;
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *orig_name;
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *namefmt;
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin for (i = 0; i < *count; i++) {
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(SSSDBG_OP_FAILURE, ("Incomplete user object for %s[%llu]! Skipping\n",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin orig_name?orig_name:"<NULL>", (unsigned long long int)uid));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* first 2 fields (len and reserved), filled up later */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin tmpstr = sss_get_cased_name(tmp_ctx, orig_name, dom->case_sensitive);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("sss_get_cased_name failed, skipping\n"));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin tmpstr = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin tmpstr = get_homedir_override(tmp_ctx, msg, nctx, dom, name.str, uid);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin tmpstr = get_shell_override(tmp_ctx, msg, nctx, dom);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin rsize = 2 * sizeof(uint32_t) + name.len + gecos.len +
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* need more space, got creative with the print format ? */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* retry */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(1, ("Failed to generate a fully qualified name for user "
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin "[%s] in [%s]! Skipping user.\n", name.str, domain));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin to_sized_string(&fullname, (const char *)&body[rp]);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(1, ("Failed to store user %s(%s) in mmap cache!",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* if there are no results just return ENOENT,
32d8ef43efe6077a8c34efb5c34bbaa5742ca2bfrbowen * let the caller decide if this is the last packet or not */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic int nss_cmd_getpw_send_reply(struct nss_dom_ctx *dctx, bool filter)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic void nsssrv_dp_send_acct_req_done(struct tevent_req *req);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin/* FIXME: do not check res->count, but get in a msgs and check in parent */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin/* FIXME: do not sss_cmd_done, but return error and let parent do it */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin const char *opt_name,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* when searching for a user or netgroup, more than one reply is a
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin if ((req_type == SSS_DP_USER || req_type == SSS_DP_NETGR) &&
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(1, ("getpwXXX call returned more than one result!"
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin " DB Corrupted?\n"));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* if we have any reply let's check cache validity */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* if we have any reply let's check cache validity */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ret = sss_cmd_check_cache(res->msgs[0], nctx->cache_refresh_percent,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(SSSDBG_TRACE_FUNC, ("Cached entry is valid, returning..\n"));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(SSSDBG_CRIT_FAILURE, ("Error checking cache: %d\n", ret));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* No replies */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* EAGAIN (off band) or ENOENT (cache miss) -> check cache */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* No callback required
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * This was an out-of-band update. We'll return EOK
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * so the calling function can return the cached entry
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * immediately.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("Performing midpoint cache update on [%s]\n", opt_name));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin req = sss_dp_get_account_send(cctx, cctx->rctx, dctx->domain, true,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("Out of memory sending out-of-band data provider "
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin "request\n"));
32d8ef43efe6077a8c34efb5c34bbaa5742ca2bfrbowen /* This is non-fatal, so we'll continue here */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(SSSDBG_TRACE_FUNC, ("Updating cache out-of-band\n"));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* We don't need to listen for a reply, so we will free the
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * request here.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* This is a cache miss. Or the cache is expired.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * We need to get the updated user information before returning it.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* dont loop forever :-) */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* keep around current data in case backend is offline */
32d8ef43efe6077a8c34efb5c34bbaa5742ca2bfrbowen req = sss_dp_get_account_send(cctx, cctx->rctx, dctx->domain, true,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ("Out of memory sending data provider request\n"));
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin tevent_req_set_callback(req, nsssrv_dp_send_acct_req_done, cb_ctx);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic void nsssrv_dp_send_acct_req_done(struct tevent_req *req)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin tevent_req_callback_data(req, struct dp_callback_ctx);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin/* search for a user.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * ENOENT, if user is definitely not found
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * EAGAIN, if user is beeing fetched from backend via async operations
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * EOK, if found
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * anything else on a fatal error
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrinstatic int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* if it is a domainless search, skip domains that require fully
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * qualified names instead */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin if (!dom) break;
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* make sure we reset the check_provider flag when we check
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * a new domain */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin dctx->check_provider = NEED_CHECK_PROVIDER(dom->provider);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* make sure to update the dctx if we changed domain */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin name = sss_get_cased_name(cmdctx, cmdctx->name, dom->case_sensitive);
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* verify this user has not yet been negatively cached,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * or has been permanently filtered */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin ret = sss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* if neg cached, return we didn't find it */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(2, ("User [%s] does not exist in [%s]! (negative cache)\n",
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* if a multidomain search, try with next */
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin /* There are no further domains or this was a
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin * fully-qualified user request.
d9b843d090f14405079b4a61a493316cd3f1e5b9minfrin DEBUG(4, ("Requesting info for [%s@%s]\n", name, dom->name));
return EIO;
return EIO;
return ENOENT;
return ret;
if (dom) continue;
return ENOENT;
dctx);
return ret;
return EOK;
return ENOENT;
int ret;
if (err_maj) {
goto done;
goto done;
done:
if (ret) {
const char *rawname;
char *domname;
int ret;
if (!cmdctx) {
return ENOMEM;
if (!dctx) {
goto done;
goto done;
goto done;
goto done;
goto done;
if (domname) {
goto done;
goto done;
done:
goto done;
goto done;
if (domname) {
goto done;
done:
int ret;
while (dom) {
return ENOENT;
return EIO;
return EIO;
return ENOENT;
return ret;
return ENOENT;
dctx);
return ret;
return EOK;
return ENOENT;
int ret;
if (err_maj) {
goto done;
goto done;
done:
if (ret) {
int ret;
if (!cmdctx) {
return ENOMEM;
if (!dctx) {
goto done;
goto done;
goto done;
goto done;
done:
goto done;
done:
if (!cmdctx) {
return ENOMEM;
if (!req) {
goto done;
done:
if (!req) {
return NULL;
goto error;
goto error;
return NULL;
return req;
goto error;
if (!step_ctx) {
goto error;
return req;
return req;
void *pvt);
while (dom) {
if (!dom) break;
return EIO;
if (!dpreq) {
if(!cb_ctx) {
return ENOMEM;
return EAGAIN;
return ENOMEM;
if (!te) {
return EAGAIN;
return EOK;
void *pvt)
int ret;
if (err_maj) {
return EOK;
if (!cmdctx) {
return ENOMEM;
if (!req) {
return EIO;
return EOK;
int ret;
return EINVAL;
return ret;
return EOK;
true, false, msgs, &n);
none:
return ret;
int ret;
return ret;
done:
return EOK;
const char *id;
int ret;
SYSDB_CACHE_EXPIRE, 0);
if (!id) {
#define GID_ROFFSET 0
int *_memnum)
char *tmpstr;
if (add_domain) {
delim = 0;
dom_len = 0;
return ENOMEM;
if (add_domain) {
goto done;
if (add_domain) {
goto done;
delim += t;
goto done;
if (add_domain) {
memnum++;
ret = 0;
done:
return ret;
int *count)
const char *tmpstr;
const char *orig_name;
const char *namefmt;
if (add_domain) {
delim = 0;
dom_len = 0;
num = 0;
goto done;
rsize = 0;
for (i = 0; i < *count; i++) {
rsize = 0;
if (filter_groups) {
num = 0;
goto done;
if (add_domain) {
num = 0;
goto done;
rsize += t;
delim += t;
num = 0;
goto done;
rsize = 0;
memnum = 0;
if (el) {
&memnum);
num = 0;
goto done;
if (el) {
&memnum);
num = 0;
goto done;
if (memnum) {
num++;
done:
*count = i;
if (num == 0) {
return ENOENT;
return EOK;
int ret;
return EFAULT;
if (ret) {
return ret;
return EOK;
int ret;
while (dom) {
if (!dom) break;
return ENOENT;
return EIO;
return EIO;
return ENOENT;
return ret;
if (dom) continue;
return ENOENT;
dctx);
return ret;
return EOK;
return ENOENT;
int ret;
if (err_maj) {
goto done;
goto done;
done:
if (ret) {
const char *rawname;
char *domname;
int ret;
if (!cmdctx) {
return ENOMEM;
if (!dctx) {
goto done;
goto done;
goto done;
goto done;
goto done;
if (domname) {
goto done;
goto done;
done:
goto done;
goto done;
if (domname) {
goto done;
done:
int ret;
while (dom) {
return ENOENT;
return EIO;
return EIO;
return ENOENT;
return ret;
return ENOENT;
dctx);
return ret;
return EOK;
return ENOENT;
int ret;
if (err_maj) {
goto done;
goto done;
done:
if (ret) {
int ret;
if (!cmdctx) {
return ENOMEM;
if (!dctx) {
goto done;
goto done;
goto done;
goto done;
done:
goto done;
done:
if (!cmdctx) {
return ENOMEM;
if (!req) {
goto done;
done:
if (!req) {
return NULL;
goto error;
goto error;
return NULL;
return req;
goto error;
if (!step_ctx) {
goto error;
return req;
return req;
void *pvt);
while (dom) {
if (!dom) break;
return EIO;
if (!dpreq) {
if(!cb_ctx) {
return ENOMEM;
return EAGAIN;
return ENOMEM;
if (!te) {
return EAGAIN;
return EOK;
void *pvt)
int ret;
if (err_maj) {
return EOK;
none:
return ret;
int ret;
return EINVAL;
return ret;
return EOK;
if (!cmdctx) {
return ENOMEM;
if (!req) {
return EIO;
return EOK;
int ret;
return ret;
done:
return EOK;
bool changed = false;
int ret;
if (gnum == 0) {
changed = true;
if (id == 0) {
for (j = 0; j < gnum; j++) {
gids[j] = 0;
if (j >= gnum) {
changed = true;
if (!changed) {
for (j = 0; j < gnum; j++) {
if (gids[j] != 0) {
changed = true;
if (changed) {
for (i = 0; i < gnum; i++) {
int skipped = 0;
const char *posix;
return ENOENT;
return ret;
bindex = 0;
for (i = 0; i < num; i++) {
if (!gid) {
skipped++;
return EFAULT;
bindex++;
return EOK;
int ret;
return EFAULT;
if (ret) {
return ret;
return EOK;
int ret;
while (dom) {
if (!dom) break;
return ENOENT;
return EIO;
return EIO;
return ret;
if (dom) continue;
return ENOENT;
dctx);
return ret;
return EOK;
return ENOENT;
int ret;
if (err_maj) {
goto done;
goto done;
done:
if (ret) {
const char *rawname;
char *domname;
int ret;
if (!cmdctx) {
return ENOMEM;
if (!dctx) {
goto done;
goto done;
goto done;
goto done;
goto done;
if (domname) {
goto done;
goto done;
done:
goto done;
goto done;
if (domname) {
goto done;
done:
return nss_cli_protocol_version;
return nss_cmds;
return EINVAL;