summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-04-01 10:21:20 -0400
committerSimo Sorce <ssorce@redhat.com>2009-04-01 11:03:08 -0400
commit4c056813c8afee16038b6d197f29ae12817c0488 (patch)
treec54f1df0946ae0becefdbd48292faba3b7a95c50 /server
parent499e4d63fe57875338777f0ac4455693307b4c56 (diff)
downloadsssd-4c056813c8afee16038b6d197f29ae12817c0488.tar.gz
sssd-4c056813c8afee16038b6d197f29ae12817c0488.tar.xz
sssd-4c056813c8afee16038b6d197f29ae12817c0488.zip
Add way to use files as a proxy backend fro LOCAL
Makes LOCAL a normal backend removing some special handling. Fix/Add id range filtering and name filtering Filters uid=0 and gid=0 in the proxy backend as 0 is invalid within sysdb and was causing getxxent calls to fail completely. Fix nss_ncache_check_xxx calls to avoid dirtying the 'ret' variable and causing some unwanted failures. Change sysdb to always return the uid number when searching member entries so that id range filtering can be perfomed also in group searhes (does not work with legacy backends)
Diffstat (limited to 'server')
-rw-r--r--server/db/sysdb.h5
-rw-r--r--server/db/sysdb_search.c2
-rw-r--r--server/providers/data_provider.c8
-rw-r--r--server/providers/proxy.c76
-rw-r--r--server/responder/nss/nsssrv_cmd.c119
5 files changed, 160 insertions, 50 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index 9e2cb39d2..ec87ec07a 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 42470b635..7dd467e87 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 183fdc4e5..4614250c7 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 cc1da1691..c87b482f0 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 0a4703c93..26c51fac8 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;
}