summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/db/sysdb.h4
-rw-r--r--server/responder/nss/nsssrv.h4
-rw-r--r--server/responder/nss/nsssrv_cmd.c611
3 files changed, 318 insertions, 301 deletions
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index 80a446fa..c87b0b4e 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -87,6 +87,7 @@
SYSDB_GIDNUM, SYSDB_FULLNAME, \
SYSDB_HOMEDIR, SYSDB_SHELL, \
SYSDB_LAST_UPDATE, \
+ "objectClass", \
NULL}
#define SYSDB_USER_ATTRS {SYSDB_USER_ATTR_DEFAULTGROUP, \
SYSDB_USER_ATTR_GECOS, \
@@ -102,12 +103,15 @@
NULL}
#define SYSDB_GRNAM_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
SYSDB_LAST_UPDATE, SYSDB_LEGACY_MEMBER, \
+ "objectClass", \
NULL}
#define SYSDB_GRPW_ATTRS {SYSDB_NAME, SYSDB_LAST_UPDATE, \
+ "objectClass", \
NULL}
#define SYSDB_INITGR_ATTR "memberof"
#define SYSDB_INITGR_ATTRS {SYSDB_GIDNUM, SYSDB_LAST_UPDATE, \
+ "objectClass", \
NULL}
#define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE
diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h
index e08d8d29..b1f1ff7d 100644
--- a/server/responder/nss/nsssrv.h
+++ b/server/responder/nss/nsssrv.h
@@ -48,7 +48,8 @@
#define NSS_ENUM_ALL 0x03
struct sysdb_ctx;
-struct getent_ctx;
+struct getpwent_ctx;
+struct getgrent_ctx;
struct nss_ctx {
struct tevent_context *ev;
@@ -82,6 +83,7 @@ struct cli_ctx {
struct tevent_fd *cfde;
struct sockaddr_un addr;
struct cli_request *creq;
+ struct getent_ctx *pctx;
struct getent_ctx *gctx;
};
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 46af6d50..8b04f813 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -37,18 +37,23 @@ struct nss_cmd_ctx {
int nr;
};
+struct dom_ctx {
+ const char *domain;
+ struct ldb_result *res;
+ int cur;
+};
+
struct getent_ctx {
- struct ldb_result *pwds;
- struct ldb_result *grps;
- int pwd_cur;
- int grp_cur;
+ struct dom_ctx *doms;
+ int num;
+ int cur;
};
struct nss_dom_ctx {
struct nss_cmd_ctx *cmdctx;
- const char *domain;
+ struct sss_domain_info *domain;
+ bool add_domain;
bool check_provider;
- bool legacy;
};
struct nss_cmd_table {
@@ -89,6 +94,12 @@ static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
return; \
} while(0)
+static bool nss_add_domain(struct sss_domain_info *info)
+{
+ /* FIXME: we want to actually retrieve this bool from some conf */
+ return (strcasecmp(info->name, "LOCAL") != 0);
+}
+
static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname)
{
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
@@ -121,11 +132,9 @@ static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname)
return EINVAL;
}
+ dctx->domain = info;
+ dctx->add_domain = nss_add_domain(info);
dctx->check_provider = strcasecmp(domain, "LOCAL");
- dctx->legacy = info->legacy;
-
- dctx->domain = talloc_strdup(dctx, domain);
- if (!dctx->domain) return ENOMEM;
if (delim) {
cmdctx->name = talloc_strndup(cmdctx, fullname, delim-fullname);
@@ -169,6 +178,8 @@ static int nss_cmd_get_version(struct cli_ctx *cctx)
***************************************************************************/
static int fill_pwent(struct sss_packet *packet,
+ bool add_domain,
+ const char *domain,
struct ldb_message **msgs,
int count)
{
@@ -182,8 +193,11 @@ static int fill_pwent(struct sss_packet *packet,
uint64_t gid;
size_t rsize, rp, blen;
size_t s1, s2, s3, s4;
+ size_t dom_len = 0;
int i, ret, num;
+ if (add_domain) dom_len = strlen(domain) +1;
+
/* first 2 fields (len and reserved), filled up later */
ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
rp = 2*sizeof(uint32_t);
@@ -210,6 +224,7 @@ static int fill_pwent(struct sss_packet *packet,
s3 = strlen(homedir) + 1;
s4 = strlen(shell) + 1;
rsize = 2*sizeof(uint64_t) +s1 + 2 + s2 + s3 +s4;
+ if (add_domain) rsize += dom_len;
ret = sss_packet_grow(packet, rsize);
if (ret != EOK) {
@@ -223,6 +238,11 @@ static int fill_pwent(struct sss_packet *packet,
rp += 2*sizeof(uint64_t);
memcpy(&body[rp], name, s1);
rp += s1;
+ if (add_domain) {
+ body[rp-1] = NSS_DOMAIN_DELIM;
+ memcpy(&body[rp], domain, dom_len);
+ rp += dom_len;
+ }
memcpy(&body[rp], "x", 2);
rp += 2;
memcpy(&body[rp], fullname, s2);
@@ -301,7 +321,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getpwnam_dp_callback, dctx,
- timeout, dctx->domain, NSS_DP_USER,
+ timeout, dctx->domain->name, NSS_DP_USER,
cmdctx->name, 0);
if (ret != EOK) {
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
@@ -339,7 +359,10 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
if (ret != EOK) {
NSS_CMD_FATAL_ERROR(cctx);
}
- ret = fill_pwent(cctx->creq->out, res->msgs, res->count);
+ ret = fill_pwent(cctx->creq->out,
+ dctx->add_domain,
+ dctx->domain->name,
+ res->msgs, res->count);
sss_packet_set_error(cctx->creq->out, ret);
break;
@@ -372,8 +395,8 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_getpwnam_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -420,11 +443,11 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
goto done;
}
DEBUG(4, ("Requesting info for [%s] from [%s]\n",
- cmdctx->name, dctx->domain));
+ cmdctx->name, dctx->domain->name));
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_getpwnam_callback, dctx);
if (ret != EOK) {
@@ -516,7 +539,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getpwuid_dp_callback, dctx,
- timeout, dctx->domain, NSS_DP_USER,
+ timeout, dctx->domain->name, NSS_DP_USER,
NULL, cmdctx->id);
if (ret != EOK) {
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
@@ -559,7 +582,10 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
NSS_CMD_FATAL_ERROR(cctx);
}
- ret = fill_pwent(cctx->creq->out, res->msgs, res->count);
+ ret = fill_pwent(cctx->creq->out,
+ dctx->add_domain,
+ dctx->domain->name,
+ res->msgs, res->count);
sss_packet_set_error(cctx->creq->out, ret);
break;
@@ -596,8 +622,8 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->id,
- dctx->legacy,
+ dctx->domain->name, cmdctx->id,
+ dctx->domain->legacy,
nss_cmd_getpwuid_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -658,18 +684,16 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx)
if (!dctx) return ENOMEM;
dctx->cmdctx = cmdctx;
- dctx->domain = talloc_strdup(dctx, domains[i]);
- if (!dctx->domain) return ENOMEM;
+ dctx->domain = info;
+ dctx->add_domain = nss_add_domain(info);
dctx->check_provider = strcasecmp(domains[i], "LOCAL");
- dctx->legacy = info->legacy;
-
DEBUG(4, ("Requesting info for [%lu@%s]\n",
- cmdctx->id, dctx->domain));
+ cmdctx->id, dctx->domain->name));
ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->id,
- dctx->legacy,
+ dctx->domain->name, cmdctx->id,
+ dctx->domain->legacy,
nss_cmd_getpwuid_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -697,17 +721,16 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx)
* even if the data is still being fetched
* - make getpwent() wait on the mutex
*/
-static void nss_cmd_getpwent_callback(void *ptr, int status,
- struct ldb_result *res);
+static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx);
static void nss_cmd_setpwent_callback(void *ptr, int status,
- struct ldb_result *res)
+ struct ldb_result *res)
{
- struct nss_cmd_ctx *cmdctx = talloc_get_type(ptr, struct nss_cmd_ctx);
+ struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
+ struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
- struct getent_ctx *gctx = cctx->gctx;
- struct ldb_result *store = gctx->pwds;
- int i, j, c, ret;
+ struct getent_ctx *pctx = cctx->pctx;
+ int ret;
cmdctx->nr--;
@@ -730,21 +753,14 @@ static void nss_cmd_setpwent_callback(void *ptr, int status,
return;
}
- if (store) {
- c = store->count + res->count;
- store->msgs = talloc_realloc(store, store->msgs,
- struct ldb_message *, c);
- if (!store->msgs) NSS_CMD_FATAL_ERROR(cctx);
+ pctx->doms = talloc_realloc(pctx, pctx->doms, struct dom_ctx, pctx->num +1);
+ if (!pctx->doms) NSS_CMD_FATAL_ERROR(cctx);
- for (i = store->count, j = 0; i < c; i++, j++) {
- store->msgs[i] = talloc_steal(store->msgs, res->msgs[j]);
- if (!store->msgs[i]) NSS_CMD_FATAL_ERROR(cctx);
- }
- store->count = c;
- talloc_free(res);
- } else {
- gctx->pwds = talloc_steal(gctx, res);
- }
+ pctx->doms[pctx->num].domain = dctx->domain->name;
+ pctx->doms[pctx->num].res = talloc_steal(pctx->doms, res);
+ pctx->doms[pctx->num].cur = 0;
+
+ pctx->num++;
/* do not reply until all domain searches are done */
if (cmdctx->nr) return;
@@ -755,8 +771,8 @@ static void nss_cmd_setpwent_callback(void *ptr, int status,
if (cmdctx->immediate) {
/* this was a getpwent call w/o setpwent,
* return immediately one result */
- nss_cmd_getpwent_callback(ptr, status, res);
-
+ ret = nss_cmd_getpwent_immediate(cmdctx);
+ if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
return;
}
@@ -788,8 +804,8 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_enumpwent(cmdctx, cctx->nctx->sysdb,
- dctx->domain, dctx->legacy, NULL,
- nss_cmd_setpwent_callback, cmdctx);
+ dctx->domain->name, dctx->domain->legacy, NULL,
+ nss_cmd_setpwent_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -806,7 +822,7 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
struct sss_domain_info *info;
struct nss_cmd_ctx *cmdctx;
struct nss_dom_ctx *dctx;
- struct getent_ctx *gctx;
+ struct getent_ctx *pctx;
const char **domains;
time_t now = time(NULL);
bool cached = false;
@@ -821,19 +837,13 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
}
cmdctx->cctx = cctx;
- if (cctx->gctx == NULL) {
- gctx = talloc_zero(cctx, struct getent_ctx);
- if (!gctx) {
- talloc_free(cmdctx);
- return ENOMEM;
- }
- cctx->gctx = gctx;
- }
- if (cctx->gctx->pwds) {
- talloc_free(cctx->gctx->pwds);
- cctx->gctx->pwds = NULL;
- cctx->gctx->pwd_cur = 0;
+ talloc_free(cctx->pctx);
+ cctx->pctx = talloc_zero(cctx, struct getent_ctx);
+ if (!cctx->pctx) {
+ talloc_free(cmdctx);
+ return ENOMEM;
}
+ pctx = cctx->pctx;
cmdctx->immediate = immediate;
@@ -868,14 +878,14 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
if (!dctx) return ENOMEM;
dctx->cmdctx = cmdctx;
- dctx->domain = talloc_strdup(dctx, domains[i]);
- if (!dctx->domain) return ENOMEM;
+ dctx->domain = info;
+ dctx->add_domain = nss_add_domain(info);
+
if (cached) {
dctx->check_provider = false;
} else {
dctx->check_provider = strcasecmp(domains[i], "LOCAL");
}
- dctx->legacy = info->legacy;
if (dctx->check_provider) {
timeout = SSS_CLI_SOCKET_TIMEOUT/(i+2);
@@ -885,8 +895,9 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
NULL, 0);
} else {
ret = sysdb_enumpwent(dctx, cctx->nctx->sysdb,
- dctx->domain, dctx->legacy, NULL,
- nss_cmd_setpwent_callback, cmdctx);
+ dctx->domain->name,
+ dctx->domain->legacy, NULL,
+ nss_cmd_setpwent_callback, dctx);
}
if (ret != EOK) {
/* FIXME: shutdown ? */
@@ -924,27 +935,43 @@ static int nss_cmd_setpwent(struct cli_ctx *cctx)
static int nss_cmd_retpwent(struct cli_ctx *cctx, int num)
{
- struct getent_ctx *gctx = cctx->gctx;
- int n, ret;
+ struct getent_ctx *pctx = cctx->pctx;
+ struct ldb_message **msgs = NULL;
+ struct dom_ctx *pdom;
+ const char *dom = NULL;
+ bool add = false;
+ int n = 0;
+
+ if (pctx->cur >= pctx->num) goto done;
+
+ pdom = &pctx->doms[pctx->cur];
+
+ n = pdom->res->count - pdom->cur;
+ if (n == 0 && (pctx->cur+1 < pctx->num)) {
+ pctx->cur++;
+ pdom = &pctx->doms[pctx->cur];
+ n = pdom->res->count - pdom->cur;
+ }
+
+ if (!n) goto done;
- n = gctx->pwds->count - gctx->pwd_cur;
if (n > num) n = num;
- ret = fill_pwent(cctx->creq->out,
- &(gctx->pwds->msgs[gctx->pwd_cur]), n);
- gctx->pwd_cur += n;
+ msgs = &(pdom->res->msgs[pdom->cur]);
+ pdom->cur += n;
- return ret;
+ add = (pdom->domain != NULL);
+ dom = pdom->domain;
+
+done:
+ return fill_pwent(cctx->creq->out, add, dom, msgs, n);
}
/* used only if a process calls getpwent() without first calling setpwent()
*/
-static void nss_cmd_getpwent_callback(void *ptr, int status,
- struct ldb_result *res)
+static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx)
{
- struct nss_cmd_ctx *cmdctx = talloc_get_type(ptr, struct nss_cmd_ctx);
struct cli_ctx *cctx = cmdctx->cctx;
- struct getent_ctx *gctx = cctx->gctx;
uint8_t *body;
size_t blen;
uint32_t num;
@@ -953,7 +980,7 @@ static void nss_cmd_getpwent_callback(void *ptr, int status,
/* get max num of entries to return in one call */
sss_packet_get_body(cctx->creq->in, &body, &blen);
if (blen != sizeof(uint32_t)) {
- NSS_CMD_FATAL_ERROR(cctx);
+ return EINVAL;
}
num = *((uint32_t *)body);
@@ -962,54 +989,29 @@ static void nss_cmd_getpwent_callback(void *ptr, int status,
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
-
- if (status != LDB_SUCCESS) {
- sss_packet_set_error(cctx->creq->out, status);
- goto done;
+ return ret;
}
- gctx->pwds = talloc_steal(gctx, res);
-
ret = nss_cmd_retpwent(cctx, num);
- sss_packet_set_error(cctx->creq->out, ret);
-done:
+ sss_packet_set_error(cctx->creq->out, ret);
nss_cmd_done(cmdctx);
+
+ return EOK;
}
static int nss_cmd_getpwent(struct cli_ctx *cctx)
{
struct nss_cmd_ctx *cmdctx;
- struct getent_ctx *gctx;
- uint8_t *body;
- size_t blen;
- uint32_t num;
- int ret;
DEBUG(4, ("Requesting info for all accounts\n"));
- /* get max num of entries to return in one call */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen != sizeof(uint32_t)) {
- return EINVAL;
- }
- num = *((uint32_t *)body);
-
/* see if we need to trigger an implicit setpwent() */
- if (cctx->gctx == NULL || cctx->gctx->pwds == NULL) {
- if (cctx->gctx == NULL) {
- gctx = talloc_zero(cctx, struct getent_ctx);
- if (!gctx) {
- return ENOMEM;
- }
- cctx->gctx = gctx;
- }
- if (cctx->gctx->pwds == NULL) {
- ret = nss_cmd_setpwent_ext(cctx, true);
- return ret;
- }
+ if (cctx->gctx == NULL) {
+ cctx->gctx = talloc_zero(cctx, struct getent_ctx);
+ if (!cctx->gctx) return ENOMEM;
+
+ return nss_cmd_setpwent_ext(cctx, true);
}
cmdctx = talloc(cctx, struct nss_cmd_ctx);
@@ -1018,18 +1020,7 @@ static int nss_cmd_getpwent(struct cli_ctx *cctx)
}
cmdctx->cctx = cctx;
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
-
- ret = nss_cmd_retpwent(cctx, num);
- sss_packet_set_error(cctx->creq->out, ret);
- nss_cmd_done(cmdctx);
- return EOK;
+ return nss_cmd_getpwent_immediate(cmdctx);
}
static int nss_cmd_endpwent(struct cli_ctx *cctx)
@@ -1050,13 +1041,11 @@ static int nss_cmd_endpwent(struct cli_ctx *cctx)
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
- if (cctx->gctx == NULL) goto done;
- if (cctx->gctx->pwds == NULL) goto done;
+ if (cctx->pctx == NULL) goto done;
/* free results and reset */
- talloc_free(cctx->gctx->pwds);
- cctx->gctx->pwds = NULL;
- cctx->gctx->pwd_cur = 0;
+ talloc_free(cctx->pctx);
+ cctx->pctx = NULL;
done:
nss_cmd_done(cmdctx);
@@ -1068,6 +1057,8 @@ done:
***************************************************************************/
static int fill_grent(struct sss_packet *packet,
+ bool add_domain,
+ const char *domain,
struct ldb_message **msgs,
int count)
{
@@ -1078,8 +1069,11 @@ static int fill_grent(struct sss_packet *packet,
uint64_t gid;
size_t rsize, rp, blen, mnump;
int i, j, ret, num, memnum;
- bool get_group = true;
- bool memnum_set = false;
+ bool get_members;
+ size_t dom_len = 0;
+ size_t name_len;
+
+ if (add_domain) dom_len = strlen(domain) +1;
/* first 2 fields (len and reserved), filled up later */
ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
@@ -1087,10 +1081,20 @@ static int fill_grent(struct sss_packet *packet,
num = 0;
mnump = 0;
+ get_members = false;
for (i = 0; i < count; i++) {
msg = msgs[i];
- if (get_group) {
+ /* new group */
+ if (ldb_msg_check_string_attribute(msg, "objectClass",
+ SYSDB_GROUP_CLASS)) {
+ if (get_members) {
+ /* this marks the end of a previous group */
+ sss_packet_get_body(packet, &body, &blen);
+ ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
+ get_members = false;
+ }
+
/* find group name/gid */
name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
@@ -1102,20 +1106,34 @@ static int fill_grent(struct sss_packet *packet,
}
/* fill in gid and name and set pointer for number of members */
- rsize = sizeof(uint64_t) + sizeof(uint32_t) + strlen(name)+1 +2;
+ name_len = strlen(name)+1;
+ rsize = sizeof(uint64_t) + sizeof(uint32_t) + name_len +2;
+ if (add_domain) rsize += dom_len;
+
ret = sss_packet_grow(packet, rsize);
sss_packet_get_body(packet, &body, &blen);
+
+ /* 0-7: 64bit number gid */
rp = blen - rsize;
((uint64_t *)(&body[rp]))[0] = gid;
rp += sizeof(uint64_t);
+
+ /* 8-11: 32bit unsigned number of members */
((uint32_t *)(&body[rp]))[0] = 0; /* init members num to 0 */
mnump = rp; /* keep around members num pointer to set later */
rp += sizeof(uint32_t);
- memcpy(&body[rp], name, strlen(name)+1);
- body[blen-2] = 'x'; /* group passwd field */
- body[blen-1] = '\0';
- memnum_set = false;
+ /* 12-X: sequence of strings (name, passwd, mem..) */
+ memcpy(&body[rp], name, name_len);
+ rp += name_len;
+ if (add_domain) {
+ body[rp-1] = NSS_DOMAIN_DELIM;
+ memcpy(&body[rp], domain, dom_len);
+ rp += dom_len;
+ }
+ body[rp] = 'x'; /* group passwd field */
+ body[rp+1] = '\0';
+
memnum = 0;
num++;
@@ -1127,6 +1145,10 @@ static int fill_grent(struct sss_packet *packet,
for (j = 0; j < memnum; j++) {
rsize = el->values[j].length + 1;
+ if (add_domain) {
+ name_len = rsize;
+ rsize += dom_len;
+ }
ret = sss_packet_grow(packet, rsize);
if (ret != EOK) {
num = 0;
@@ -1136,54 +1158,75 @@ static int fill_grent(struct sss_packet *packet,
sss_packet_get_body(packet, &body, &blen);
rp = blen - rsize;
memcpy(&body[rp], el->values[j].data, el->values[j].length);
+ if (add_domain) {
+ rp += name_len;
+ body[rp-1] = NSS_DOMAIN_DELIM;
+ memcpy(&body[rp], domain, dom_len);
+ }
body[blen-1] = '\0';
}
sss_packet_get_body(packet, &body, &blen);
((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
- memnum_set = true;
} else {
- get_group = false;
+ get_members = true;
}
continue;
}
- name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ if (!get_members) {
+ DEBUG(1, ("Wrong object found on stack! Aborting\n"));
+ num = 0;
+ goto done;
+ }
- if (!name) {
- /* last member of previous group found, or error.
- * set next element to be a group, and eventually
- * fail there if here start bogus entries */
- get_group = true;
- i--;
+ /* member */
+ if (ldb_msg_check_string_attribute(msg, "objectClass",
+ SYSDB_USER_CLASS)) {
+
+ name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ if (!name) {
+ DEBUG(1, ("Incomplete user object! Aborting\n"));
+ num = 0;
+ goto done;
+ }
+
+ rsize = strlen(name) + 1;
+ if (add_domain) {
+ name_len = rsize;
+ rsize += dom_len;
+ }
+
+ ret = sss_packet_grow(packet, rsize);
+ if (ret != EOK) {
+ num = 0;
+ goto done;
+ }
sss_packet_get_body(packet, &body, &blen);
- ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
- memnum_set = true;
- continue;
- }
+ rp = blen - rsize;
+ memcpy(&body[rp], name, rsize);
+ if (add_domain) {
+ body[rp-1] = NSS_DOMAIN_DELIM;
+ memcpy(&body[rp], domain, dom_len);
+ rp += dom_len;
+ }
- rsize = strlen(name) + 1;
+ memnum++;
- ret = sss_packet_grow(packet, rsize);
- if (ret != EOK) {
- num = 0;
- goto done;
+ continue;
}
- sss_packet_get_body(packet, &body, &blen);
- rp = blen - rsize;
- memcpy(&body[rp], name, rsize);
- memnum++;
+ DEBUG(1, ("Wrong object found on stack! Aborting\n"));
+ num = 0;
+ goto done;
}
- if (!memnum_set) {
+ if (mnump) {
/* fill in the last group member count */
- if (mnump != 0) {
- sss_packet_get_body(packet, &body, &blen);
- ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
- }
+ sss_packet_get_body(packet, &body, &blen);
+ ((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
}
done:
@@ -1244,7 +1287,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getgrnam_dp_callback, dctx,
- timeout, dctx->domain, NSS_DP_GROUP,
+ timeout, dctx->domain->name, NSS_DP_GROUP,
cmdctx->name, 0);
if (ret != EOK) {
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
@@ -1287,7 +1330,10 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
NSS_CMD_FATAL_ERROR(cctx);
}
- ret = fill_grent(cctx->creq->out, res->msgs, res->count);
+ ret = fill_grent(cctx->creq->out,
+ dctx->add_domain,
+ dctx->domain->name,
+ res->msgs, res->count);
sss_packet_set_error(cctx->creq->out, ret);
}
@@ -1311,8 +1357,8 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_getgrnam_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1359,11 +1405,11 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
goto done;
}
DEBUG(4, ("Requesting info for [%s] from [%s]\n",
- cmdctx->name, dctx->domain));
+ cmdctx->name, dctx->domain->name));
ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_getgrnam_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1445,7 +1491,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getgrgid_dp_callback, dctx,
- timeout, dctx->domain, NSS_DP_GROUP,
+ timeout, dctx->domain->name, NSS_DP_GROUP,
NULL, cmdctx->id);
if (ret != EOK) {
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
@@ -1491,7 +1537,10 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
NSS_CMD_FATAL_ERROR(cctx);
}
- ret = fill_grent(cctx->creq->out, res->msgs, res->count);
+ ret = fill_grent(cctx->creq->out,
+ dctx->add_domain,
+ dctx->domain->name,
+ res->msgs, res->count);
sss_packet_set_error(cctx->creq->out, ret);
}
@@ -1519,8 +1568,8 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->id,
- dctx->legacy,
+ dctx->domain->name, cmdctx->id,
+ dctx->domain->legacy,
nss_cmd_getgrgid_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1578,17 +1627,16 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx)
if (!dctx) return ENOMEM;
dctx->cmdctx = cmdctx;
- dctx->domain = talloc_strdup(dctx, domains[i]);
- if (!dctx->domain) return ENOMEM;
+ dctx->domain = info;
+ dctx->add_domain = nss_add_domain(info);
dctx->check_provider = strcasecmp(domains[i], "LOCAL");
- dctx->legacy = info->legacy;
DEBUG(4, ("Requesting info for [%lu@%s]\n",
- cmdctx->id, dctx->domain));
+ cmdctx->id, dctx->domain->name));
ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->id,
- dctx->legacy,
+ dctx->domain->name, cmdctx->id,
+ dctx->domain->legacy,
nss_cmd_getgrgid_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1616,17 +1664,17 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx)
* even if the data is still being fetched
* - make getgrent() wait on the mutex
*/
-static void nss_cmd_getgrent_callback(void *ptr, int status,
- struct ldb_result *res);
+
+static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx);
static void nss_cmd_setgrent_callback(void *ptr, int status,
struct ldb_result *res)
{
- struct nss_cmd_ctx *cmdctx = talloc_get_type(ptr, struct nss_cmd_ctx);
+ struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
+ struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
struct getent_ctx *gctx = cctx->gctx;
- struct ldb_result *store = gctx->grps;
- int i, j, c, ret;
+ int ret;
cmdctx->nr--;
@@ -1649,21 +1697,14 @@ static void nss_cmd_setgrent_callback(void *ptr, int status,
return;
}
- if (store) {
- c = store->count + res->count;
- store->msgs = talloc_realloc(store, store->msgs,
- struct ldb_message *, c);
- if (!store->msgs) NSS_CMD_FATAL_ERROR(cctx);
+ gctx->doms = talloc_realloc(gctx, gctx->doms, struct dom_ctx, gctx->num +1);
+ if (!gctx->doms) NSS_CMD_FATAL_ERROR(cctx);
- for (i = store->count, j = 0; i < c; i++, j++) {
- store->msgs[i] = talloc_steal(store->msgs, res->msgs[j]);
- if (!store->msgs[i]) NSS_CMD_FATAL_ERROR(cctx);
- }
- store->count = c;
- talloc_free(res);
- } else {
- gctx->grps = talloc_steal(gctx, res);
- }
+ gctx->doms[gctx->num].domain = dctx->domain->name;
+ gctx->doms[gctx->num].res = talloc_steal(gctx->doms, res);
+ gctx->doms[gctx->num].cur = 0;
+
+ gctx->num++;
/* do not reply until all domain searches are done */
if (cmdctx->nr) return;
@@ -1674,7 +1715,8 @@ static void nss_cmd_setgrent_callback(void *ptr, int status,
if (cmdctx->immediate) {
/* this was a getgrent call w/o setgrent,
* return immediately one result */
- nss_cmd_getgrent_callback(ptr, status, res);
+ ret = nss_cmd_getgrent_immediate(cmdctx);
+ if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
return;
}
@@ -1706,8 +1748,8 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_enumgrent(dctx, cctx->nctx->sysdb,
- dctx->domain, dctx->legacy,
- nss_cmd_setgrent_callback, cmdctx);
+ dctx->domain->name, dctx->domain->legacy,
+ nss_cmd_setgrent_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1739,19 +1781,13 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
}
cmdctx->cctx = cctx;
- if (cctx->gctx == NULL) {
- gctx = talloc_zero(cctx, struct getent_ctx);
- if (!gctx) {
- talloc_free(cmdctx);
- return ENOMEM;
- }
- cctx->gctx = gctx;
- }
- if (cctx->gctx->grps) {
- talloc_free(cctx->gctx->grps);
- cctx->gctx->grps = NULL;
- cctx->gctx->grp_cur = 0;
+ talloc_free(cctx->gctx);
+ cctx->gctx = talloc_zero(cctx, struct getent_ctx);
+ if (!cctx->gctx) {
+ talloc_free(cmdctx);
+ return ENOMEM;
}
+ gctx = cctx->gctx;
cmdctx->immediate = immediate;
@@ -1786,14 +1822,14 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
if (!dctx) return ENOMEM;
dctx->cmdctx = cmdctx;
- dctx->domain = talloc_strdup(dctx, domains[i]);
- if (!dctx->domain) return ENOMEM;
+ dctx->domain = info;
+ dctx->add_domain = nss_add_domain(info);
+
if (cached) {
dctx->check_provider = false;
} else {
dctx->check_provider = strcasecmp(domains[i], "LOCAL");
}
- dctx->legacy = info->legacy;
if (dctx->check_provider) {
timeout = SSS_CLI_SOCKET_TIMEOUT/(i+2);
@@ -1803,8 +1839,8 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
NULL, 0);
} else {
ret = sysdb_enumgrent(dctx, cctx->nctx->sysdb,
- dctx->domain, dctx->legacy,
- nss_cmd_setgrent_callback, cmdctx);
+ dctx->domain->name, dctx->domain->legacy,
+ nss_cmd_setgrent_callback, dctx);
}
if (ret != EOK) {
/* FIXME: shutdown ? */
@@ -1841,26 +1877,42 @@ static int nss_cmd_setgrent(struct cli_ctx *cctx)
static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
{
struct getent_ctx *gctx = cctx->gctx;
- int n, ret;
+ struct ldb_message **msgs = NULL;
+ struct dom_ctx *gdom;
+ const char *dom = NULL;
+ bool add = false;
+ int n = 0;
+
+ if (gctx->cur >= gctx->num) goto done;
+
+ gdom = &gctx->doms[gctx->cur];
+
+ n = gdom->res->count - gdom->cur;
+ if (n == 0 && (gctx->cur+1 < gctx->num)) {
+ gctx->cur++;
+ gdom = &gctx->doms[gctx->cur];
+ n = gdom->res->count - gdom->cur;
+ }
+
+ if (!n) goto done;
- n = gctx->grps->count - gctx->grp_cur;
if (n > num) n = num;
- ret = fill_grent(cctx->creq->out,
- &(gctx->grps->msgs[gctx->grp_cur]), n);
- gctx->grp_cur += n;
+ msgs = &(gdom->res->msgs[gdom->cur]);
+ gdom->cur += n;
- return ret;
+ add = (gdom->domain != NULL);
+ dom = gdom->domain;
+
+done:
+ return fill_grent(cctx->creq->out, add, dom, msgs, n);
}
/* used only if a process calls getpwent() without first calling setpwent()
- * in this case we basically trigger an implicit setpwent() */
-static void nss_cmd_getgrent_callback(void *ptr, int status,
- struct ldb_result *res)
+ */
+static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx)
{
- struct nss_cmd_ctx *cmdctx = talloc_get_type(ptr, struct nss_cmd_ctx);
struct cli_ctx *cctx = cmdctx->cctx;
- struct getent_ctx *gctx = cctx->gctx;
uint8_t *body;
size_t blen;
uint32_t num;
@@ -1869,11 +1921,7 @@ static void nss_cmd_getgrent_callback(void *ptr, int status,
/* get max num of entries to return in one call */
sss_packet_get_body(cctx->creq->in, &body, &blen);
if (blen != sizeof(uint32_t)) {
- ret = nss_cmd_send_error(cmdctx, EIO);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- nss_cmd_done(cmdctx);
+ return EINVAL;
}
num = *((uint32_t *)body);
@@ -1882,54 +1930,29 @@ static void nss_cmd_getgrent_callback(void *ptr, int status,
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
-
- if (status != LDB_SUCCESS) {
- sss_packet_set_error(cctx->creq->out, status);
- goto done;
+ return ret;
}
- gctx->grps = talloc_steal(gctx, res);
-
ret = nss_cmd_retgrent(cctx, num);
- sss_packet_set_error(cctx->creq->out, ret);
-done:
+ sss_packet_set_error(cctx->creq->out, ret);
nss_cmd_done(cmdctx);
+
+ return EOK;
}
static int nss_cmd_getgrent(struct cli_ctx *cctx)
{
struct nss_cmd_ctx *cmdctx;
- struct getent_ctx *gctx;
- uint8_t *body;
- size_t blen;
- uint32_t num;
- int ret;
DEBUG(4, ("Requesting info for all groups\n"));
- /* get max num of entries to return in one call */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen != sizeof(uint32_t)) {
- return EINVAL;
- }
- num = *((uint32_t *)body);
-
/* see if we need to trigger an implicit setpwent() */
- if (cctx->gctx == NULL || cctx->gctx->grps == NULL) {
- if (cctx->gctx == NULL) {
- gctx = talloc_zero(cctx, struct getent_ctx);
- if (!gctx) {
- return ENOMEM;
- }
- cctx->gctx = gctx;
- }
- if (cctx->gctx->grps == NULL) {
- ret = nss_cmd_setgrent_ext(cctx, true);
- return ret;
- }
+ if (cctx->gctx == NULL) {
+ cctx->gctx = talloc_zero(cctx, struct getent_ctx);
+ if (!cctx->gctx) return ENOMEM;
+
+ return nss_cmd_setgrent_ext(cctx, true);
}
cmdctx = talloc(cctx, struct nss_cmd_ctx);
@@ -1938,18 +1961,7 @@ static int nss_cmd_getgrent(struct cli_ctx *cctx)
}
cmdctx->cctx = cctx;
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
-
- ret = nss_cmd_retgrent(cctx, num);
- sss_packet_set_error(cctx->creq->out, ret);
- nss_cmd_done(cmdctx);
- return EOK;
+ return nss_cmd_getgrent_immediate(cmdctx);
}
static int nss_cmd_endgrent(struct cli_ctx *cctx)
@@ -1971,12 +1983,10 @@ static int nss_cmd_endgrent(struct cli_ctx *cctx)
&cctx->creq->out);
if (cctx->gctx == NULL) goto done;
- if (cctx->gctx->grps == NULL) goto done;
/* free results and reset */
- talloc_free(cctx->gctx->grps);
- cctx->gctx->grps = NULL;
- cctx->gctx->grp_cur = 0;
+ talloc_free(cctx->gctx);
+ cctx->gctx = NULL;
done:
nss_cmd_done(cmdctx);
@@ -2051,8 +2061,8 @@ static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_initgroups(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_initgr_callback, cmdctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -2084,8 +2094,8 @@ static void nss_cmd_getinitnam_callback(uint16_t err_maj, uint32_t err_min,
}
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_getinit_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -2144,7 +2154,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getinitnam_callback, dctx,
- timeout, dctx->domain, NSS_DP_USER,
+ timeout, dctx->domain->name, NSS_DP_USER,
cmdctx->name, 0);
if (ret != EOK) {
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
@@ -2180,7 +2190,8 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getinitgr_callback, dctx,
- timeout, dctx->domain, NSS_DP_INITGROUPS,
+ timeout, dctx->domain->name,
+ NSS_DP_INITGROUPS,
cmdctx->name, 0);
if (ret != EOK) {
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
@@ -2240,11 +2251,11 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
goto done;
}
DEBUG(4, ("Requesting info for [%s] from [%s]\n",
- cmdctx->name, dctx->domain));
+ cmdctx->name, dctx->domain->name));
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
- dctx->domain, cmdctx->name,
- dctx->legacy,
+ dctx->domain->name, cmdctx->name,
+ dctx->domain->legacy,
nss_cmd_getinit_callback, dctx);
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));