diff options
-rw-r--r-- | server/db/sysdb.h | 5 | ||||
-rw-r--r-- | server/db/sysdb_search.c | 2 | ||||
-rw-r--r-- | server/providers/data_provider.c | 8 | ||||
-rw-r--r-- | server/providers/proxy.c | 76 | ||||
-rw-r--r-- | server/responder/nss/nsssrv_cmd.c | 119 |
5 files changed, 160 insertions, 50 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h index 9e2cb39d..ec87ec07 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -107,11 +107,12 @@ SYSDB_USERPIC, \ SYSDB_LAST_UPDATE, \ NULL} -#define SYSDB_GRNAM_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ +#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ SYSDB_LAST_UPDATE, SYSDB_LEGACY_MEMBER, \ "objectClass", \ NULL} -#define SYSDB_GRPW_ATTRS {SYSDB_NAME, SYSDB_LAST_UPDATE, \ +#define SYSDB_GRPW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \ + SYSDB_LAST_UPDATE, \ "objectClass", \ NULL} diff --git a/server/db/sysdb_search.c b/server/db/sysdb_search.c index 42470b63..7dd467e8 100644 --- a/server/db/sysdb_search.c +++ b/server/db/sysdb_search.c @@ -481,7 +481,7 @@ static int get_grp_callback(struct ldb_request *req, static void grp_search(struct sysdb_req *sysreq, void *ptr) { struct sysdb_search_ctx *sctx; - static const char *attrs[] = SYSDB_GRNAM_ATTRS; + static const char *attrs[] = SYSDB_GRSRC_ATTRS; struct ldb_request *req; struct ldb_dn *base_dn; int ret; diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c index 183fdc4e..4614250c 100644 --- a/server/providers/data_provider.c +++ b/server/providers/data_provider.c @@ -604,14 +604,6 @@ static int dp_get_account_info(DBusMessage *message, struct sbus_conn_ctx *sconn goto respond; } - /* nothing to do for local */ - if (strcasecmp(domain, "LOCAL") == 0) { - dpret = DP_ERR_OK; - errmsg = "Success"; - ret = EOK; - goto respond; - } - /* all domains, fire off a request for each backend */ if (strcmp(domain, "*") == 0) { dpreq = talloc(dpcli->dpctx, struct dp_request); diff --git a/server/providers/proxy.c b/server/providers/proxy.c index cc1da169..c87b482f 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -310,6 +310,13 @@ static void get_pw_name(struct be_req *req, char *name) break; case NSS_STATUS_SUCCESS: + /* FIXME: verify user does not have uid=0 or gid=0 as these are invalid + * values */ + if (data->pwd->pw_uid == 0 || data->pwd->pw_gid == 0) { + ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data); + break; + } + ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data); break; @@ -360,6 +367,14 @@ static void get_pw_uid(struct be_req *req, uid_t uid) break; case NSS_STATUS_SUCCESS: + /* FIXME: verify user does not have gid=0 as these are invalid values */ + if (data->pwd->pw_gid == 0) { + data->dn = sysdb_user_dn(req->be_ctx->sysdb, data, + req->be_ctx->domain, data->pwd->pw_name); + ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data); + break; + } + ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data); break; @@ -427,6 +442,12 @@ retry: break; case NSS_STATUS_SUCCESS: + /* FIXME: verify user does not have uid=0 or gid=0 as these are invalid + * values */ + if (data->pwd->pw_uid == 0 || data->pwd->pw_gid == 0) { + goto retry; /* skip */ + } + ret = sysdb_legacy_store_user(req, data->req->be_ctx->domain, data->pwd->pw_name, data->pwd->pw_passwd, @@ -486,7 +507,7 @@ static void enum_users(struct be_req *req) } } -static void del_gr_uid(struct sysdb_req *req, void *pvt) +static void del_gr_gid(struct sysdb_req *req, void *pvt) { struct proxy_data *data = talloc_get_type(pvt, struct proxy_data); struct sysdb_ctx *ctx; @@ -561,6 +582,12 @@ static void get_gr_name(struct be_req *req, char *name) break; case NSS_STATUS_SUCCESS: + /* FIXME: verify group does not have gid=0 as this is invalid */ + if (data->grp->gr_gid == 0) { + ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data); + break; + } + ret = sysdb_transaction(data, req->be_ctx->sysdb, set_gr_name, data); break; @@ -607,10 +634,18 @@ static void get_gr_gid(struct be_req *req, gid_t gid) switch (status) { case NSS_STATUS_NOTFOUND: data->grp->gr_gid = gid; - ret = sysdb_transaction(data, req->be_ctx->sysdb, del_gr_uid, data); + ret = sysdb_transaction(data, req->be_ctx->sysdb, del_gr_gid, data); break; case NSS_STATUS_SUCCESS: + /* FIXME: verify group does not have gid=0 as this is invalid */ + if (data->grp->gr_gid == 0) { + data->dn = sysdb_group_dn(req->be_ctx->sysdb, data, + req->be_ctx->domain, data->grp->gr_name); + ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data); + break; + } + ret = sysdb_transaction(data, req->be_ctx->sysdb, set_gr_name, data); break; @@ -676,6 +711,10 @@ retry: break; case NSS_STATUS_SUCCESS: + /* FIXME: verify group does not have gid=0 as this is invalid */ + if (data->grp->gr_gid == 0) { + goto retry; + } ret = sysdb_legacy_store_group(req, data->req->be_ctx->domain, data->grp->gr_name, data->grp->gr_gid, @@ -835,14 +874,13 @@ static void get_user_groups(void *pvt, int error, struct ldb_result *ignore) return proxy_return(data, ENOMEM, NULL); gid = data->pwd->pw_gid; - name = talloc_strdup(data, data->pwd->pw_name); - if (!name) - return proxy_return(data, ENOMEM, NULL); + name = data->pwd->pw_name; retry: status = data->ctx->ops.initgroups_dyn(name, gid, &start, &num, &data->groups, limit, &ret); + switch (status) { case NSS_STATUS_TRYAGAIN: /* buffer too small ? */ @@ -916,9 +954,24 @@ static void get_initgr_user(struct be_req *req, char *name) break; case NSS_STATUS_SUCCESS: - data->next_fn = get_user_groups; - ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data); - break; + /* FIXME: verify user does not have uid=0 or gid=0 as these are invalid + * values */ + if (data->pwd->pw_uid == 0 || data->pwd->pw_gid == 0) { + ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data); + break; + } + + if (ctx->ops.initgroups_dyn) { + data->next_fn = get_user_groups; + ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data); + } else { + status = ctx->ops.setgrent(); + if (status != NSS_STATUS_SUCCESS) + return proxy_reply(req, EIO, "Operation failed"); + + ret = sysdb_transaction(data, req->be_ctx->sysdb, get_gr_entry, data); + break; + } default: DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n", @@ -1181,9 +1234,10 @@ int sssm_proxy_init(struct be_ctx *bectx, struct be_mod_ops **ops, void **pvt_da ctx->ops.initgroups_dyn = proxy_dlsym(handle, "_nss_%s_initgroups_dyn", libname); if (!ctx->ops.initgroups_dyn) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; + DEBUG(1, ("The '%s' library does not provides the " + "_nss_XXX_initgroups_dyn function!\n" + "initgroups will be slow as it will require " + "full groups enumeration!\n", libname)); } *ops = &proxy_mod_ops; diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c index 0a4703c9..26c51fac 100644 --- a/server/responder/nss/nsssrv_cmd.c +++ b/server/responder/nss/nsssrv_cmd.c @@ -192,6 +192,7 @@ static int fill_pwent(struct sss_packet *packet, int i, ret, num; bool add_domain = info->fqnames; const char *domain = info->name; + int ncret; if (add_domain) dom_len = strlen(domain) +1; @@ -214,16 +215,24 @@ static int fill_pwent(struct sss_packet *packet, } if (filter_users) { - ret = nss_ncache_check_user(nctx->ncache, + ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, domain, name); - if (ret == EEXIST) { + if (ncret == EEXIST) { DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n", name, domain)); continue; } } + /* check that the uid is valid for this domain */ + if ((info->id_min && (uid < info->id_min)) || + (info->id_max && (uid > info->id_max))) { + DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n", + name, domain)); + continue; + } + gecos = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL); homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL); shell = ldb_msg_find_attr_as_string(msg, SYSDB_SHELL, NULL); @@ -489,6 +498,7 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) uint8_t *body; size_t blen; int ret, num, i; + int ncret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); @@ -522,9 +532,9 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) if (domname) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, domname, cmdctx->name); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("User [%s] does not exist! (negative cache)\n", rawname)); ret = ENOENT; @@ -568,9 +578,9 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) for (i = 0; i < num; i++) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, domains[i], cmdctx->name); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("User [%s] does not exist! (neg cache)\n", rawname)); continue; @@ -850,6 +860,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) uint8_t *body; size_t blen; int i, num, ret; + int ncret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); @@ -885,9 +896,9 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) for (i = 0; i < num; i++) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout, cmdctx->id); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("Uid [%lu] does not exist! (negative cache)\n", (unsigned long)cmdctx->id)); continue; @@ -895,6 +906,15 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) info = btreemap_get_value(cctx->rctx->domain_map, domains[i]); + /* check that the uid is valid for this domain */ + if ((info->id_min && (cmdctx->id < info->id_min)) || + (info->id_max && (cmdctx->id > info->id_max))) { + DEBUG(4, ("Uid [%lu] does not exist in domain [%s]! " + "(id out of range)\n", + (unsigned long)cmdctx->id, domains[i])); + continue; + } + cmdctx->nr++; dctx = talloc_zero(cmdctx, struct nss_dom_ctx); @@ -1310,15 +1330,16 @@ static int fill_grent(struct sss_packet *packet, struct ldb_message *msg; uint8_t *body; const char *name; - uint32_t gid; + uint32_t gid, uid; size_t rsize, rp, blen, mnump; - int i, j, ret, num, memnum; + int i, j, n, ret, num, memnum; bool get_members; bool skip_members; size_t dom_len = 0; size_t name_len; bool add_domain = info->fqnames; const char *domain = info->name; + int ncret; if (add_domain) dom_len = strlen(domain) +1; @@ -1355,9 +1376,9 @@ static int fill_grent(struct sss_packet *packet, skip_members = false; if (filter_groups) { - ret = nss_ncache_check_group(nctx->ncache, + ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout, domain, name); - if (ret == EEXIST) { + if (ncret == EEXIST) { DEBUG(4, ("Group [%s@%s] filtered out! (negative cache)\n", name, domain)); skip_members = true; @@ -1365,6 +1386,15 @@ static int fill_grent(struct sss_packet *packet, } } + /* check that the gid is valid for this domain */ + if ((info->id_min && (gid < info->id_min)) || + (info->id_max && (gid > info->id_max))) { + DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n", + name, domain)); + skip_members = true; + continue; + } + /* fill in gid and name and set pointer for number of members */ name_len = strlen(name)+1; rsize = 2 * sizeof(uint32_t) + name_len +2; @@ -1402,8 +1432,18 @@ static int fill_grent(struct sss_packet *packet, if (el) { /* legacy */ memnum = el->num_values; - + n = 0; for (j = 0; j < memnum; j++) { + + ncret = nss_ncache_check_user(nctx->ncache, + nctx->neg_timeout, domain, + (char *)el->values[j].data); + if (ncret == EEXIST) { + DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n", + name, domain)); + continue; + } + rsize = el->values[j].length + 1; if (add_domain) { name_len = rsize; @@ -1424,10 +1464,12 @@ static int fill_grent(struct sss_packet *packet, memcpy(&body[rp], domain, dom_len); } body[blen-1] = '\0'; + + n++; } sss_packet_get_body(packet, &body, &blen); - ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */ + ((uint32_t *)(&body[mnump]))[0] = n; /* num members */ } else { get_members = true; @@ -1449,20 +1491,29 @@ static int fill_grent(struct sss_packet *packet, SYSDB_USER_CLASS)) { name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); - if (!name) { + uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); + if (!name || !uid) { DEBUG(1, ("Incomplete user object! Aborting\n")); num = 0; goto done; } - ret = nss_ncache_check_user(nctx->ncache, + ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, domain, name); - if (ret == EEXIST) { + if (ncret == EEXIST) { DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n", name, domain)); continue; } + /* check that the uid is valid for this domain */ + if ((info->id_min && (uid < info->id_min)) || + (info->id_max && (uid > info->id_max))) { + DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n", + name, domain)); + continue; + } + rsize = strlen(name) + 1; if (add_domain) { name_len = rsize; @@ -1706,6 +1757,7 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) uint8_t *body; size_t blen; int ret, num, i; + int ncret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); @@ -1738,9 +1790,9 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) if (domname) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout, domname, cmdctx->name); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("Group [%s] does not exist! (negative cache)\n", rawname)); ret = ENOENT; @@ -1783,9 +1835,9 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) for (i = 0; i < num; i++) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout, domains[i], cmdctx->name); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("Group [%s] does not exist! (negative cache)\n", rawname)); continue; @@ -2046,6 +2098,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) uint8_t *body; size_t blen; int i, num, ret; + int ncret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); @@ -2081,9 +2134,9 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) for (i = 0; i < num; i++) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout, cmdctx->id); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n", (unsigned long)cmdctx->id)); continue; @@ -2091,6 +2144,15 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) info = btreemap_get_value(cctx->rctx->domain_map, domains[i]); + /* check that the uid is valid for this domain */ + if ((info->id_min && (cmdctx->id < info->id_min)) || + (info->id_max && (cmdctx->id > info->id_max))) { + DEBUG(4, ("Gid [%lu] does not exist! (id out of range)\n", + (unsigned long)cmdctx->id)); + continue; + } + + cmdctx->nr++; dctx = talloc_zero(cmdctx, struct nss_dom_ctx); @@ -2787,6 +2849,7 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) uint8_t *body; size_t blen; int ret, num, i; + int ncret; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); @@ -2813,14 +2876,14 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) goto done; } DEBUG(4, ("Requesting info for [%s] from [%s]\n", - cmdctx->name, dctx->domain->name)); + cmdctx->name, domname ? : "<ALL>")); if (domname) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, domname, cmdctx->name); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("User [%s] does not exist! (negative cache)\n", rawname)); ret = ENOENT; @@ -2864,9 +2927,9 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) for (i = 0; i < num; i++) { /* verify this user has not yet been negatively cached, * or has been permanently filtered */ - ret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, + ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout, domains[i], cmdctx->name); - if (ret != ENOENT) { + if (ncret != ENOENT) { DEBUG(3, ("User does not exist! (neg cache)\n")); continue; } |