summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-09-15 17:41:09 -0400
committerSimo Sorce <ssorce@redhat.com>2009-09-17 09:54:01 -0400
commit689f25c05d31b06ed3b0d5c55d6dda86ca3cf7da (patch)
treef8af994f27bcd630dc49fe0647d63fd8c783c06e
parentbf03904ed607286921d2a65dd66e72335e60c777 (diff)
downloadsssd-689f25c05d31b06ed3b0d5c55d6dda86ca3cf7da.tar.gz
sssd-689f25c05d31b06ed3b0d5c55d6dda86ca3cf7da.tar.xz
sssd-689f25c05d31b06ed3b0d5c55d6dda86ca3cf7da.zip
Better handle groups w/o members
There was a chance that groups w/o members could end up causing a failure to store the group. This would happen in case the structure used by glibc to fill up the group data was "dirty". Always memset structures before passing them to te libc and also check if there are any members, before calling the async function. Finally add some tracing at level 7 so that it is easier to follow what is going on in case of touble.
-rw-r--r--server/providers/proxy.c128
1 files changed, 122 insertions, 6 deletions
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index 8678856aa..80a2a5500 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -361,6 +361,8 @@ static void get_pw_name_process(struct tevent_req *subreq)
bool delete_user = false;
int ret;
+ DEBUG(7, ("Searching user by name (%s)\n", state->name));
+
ret = sysdb_transaction_recv(subreq, state, &state->handle);
if (ret) {
tevent_req_error(req, ret);
@@ -389,11 +391,16 @@ static void get_pw_name_process(struct tevent_req *subreq)
switch (status) {
case NSS_STATUS_NOTFOUND:
+ DEBUG(7, ("User %s not found.\n", state->name));
delete_user = true;
break;
case NSS_STATUS_SUCCESS:
+ DEBUG(7, ("User %s found: (%s, %d, %d)\n",
+ state->name, state->pwd->pw_name,
+ state->pwd->pw_uid, state->pwd->pw_gid));
+
/* uid=0 or gid=0 are invalid values */
if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
delete_user = true;
@@ -431,6 +438,9 @@ static void get_pw_name_process(struct tevent_req *subreq)
if (delete_user) {
struct ldb_dn *dn;
+ DEBUG(7, ("User %s does not exist (or is invalid) on remote server,"
+ " deleting!\n", state->name));
+
dn = sysdb_user_dn(state->sysdb, state,
state->domain->name, state->name);
if (!dn) {
@@ -542,6 +552,8 @@ static void get_pw_uid_process(struct tevent_req *subreq)
bool delete_user = false;
int ret;
+ DEBUG(7, ("Searching user by uid (%d)\n", state->uid));
+
ret = sysdb_transaction_recv(subreq, state, &state->handle);
if (ret) {
tevent_req_error(req, ret);
@@ -562,17 +574,25 @@ static void get_pw_uid_process(struct tevent_req *subreq)
return;
}
+ /* always zero out the pwd structure */
+ memset(state->pwd, 0, sizeof(struct passwd));
+
status = ctx->ops.getpwuid_r(state->uid, state->pwd,
buffer, buflen, &ret);
switch (status) {
case NSS_STATUS_NOTFOUND:
+ DEBUG(7, ("User %d not found.\n", state->uid));
delete_user = true;
break;
case NSS_STATUS_SUCCESS:
+ DEBUG(7, ("User %d found (%s, %d, %d)\n",
+ state->uid, state->pwd->pw_name,
+ state->pwd->pw_uid, state->pwd->pw_gid));
+
/* uid=0 or gid=0 are invalid values */
if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
delete_user = true;
@@ -608,6 +628,9 @@ static void get_pw_uid_process(struct tevent_req *subreq)
}
if (delete_user) {
+ DEBUG(7, ("User %d does not exist (or is invalid) on remote server,"
+ " deleting!\n", state->uid));
+
subreq = sysdb_delete_user_by_uid_send(state, state->ev,
state->handle,
state->domain,
@@ -673,6 +696,8 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *mem_ctx,
struct enum_users_state *state;
enum nss_status status;
+ DEBUG(7, ("Enumerating users\n"));
+
req = tevent_req_create(mem_ctx, &state, struct enum_users_state);
if (!req) return NULL;
@@ -747,6 +772,9 @@ static void enum_users_process(struct tevent_req *subreq)
}
again:
+ /* always zero out the pwd structure */
+ memset(state->pwd, 0, sizeof(struct passwd));
+
/* get entry */
status = ctx->ops.getpwent_r(state->pwd,
state->buffer, state->buflen, &ret);
@@ -769,7 +797,10 @@ again:
goto again;
case NSS_STATUS_NOTFOUND:
+
/* we are done here */
+ DEBUG(7, ("Enumeration completed.\n"));
+
ctx->ops.endpwent();
subreq = sysdb_transaction_commit_send(state, state->ev,
state->handle);
@@ -781,6 +812,10 @@ again:
return;
case NSS_STATUS_SUCCESS:
+
+ DEBUG(7, ("User found (%s, %d, %d)\n", state->pwd->pw_name,
+ state->pwd->pw_uid, state->pwd->pw_gid));
+
/* uid=0 or gid=0 are invalid values */
if (state->pwd->pw_uid == 0 || state->pwd->pw_gid == 0) {
goto again; /* skip */
@@ -820,6 +855,24 @@ fail:
/* =Getgrnam-wrapper======================================================*/
+#define DEBUG_GR_MEM(level, state) \
+ do { \
+ if (debug_level >= level) { \
+ if (!state->grp->gr_mem || !state->grp->gr_mem[0]) { \
+ DEBUG(level, ("Group %s has no members!\n", \
+ state->grp->gr_name)); \
+ } else { \
+ int i = 0; \
+ while (state->grp->gr_mem[i]) { \
+ /* count */ \
+ i++; \
+ } \
+ DEBUG(level, ("Group %s has %d members!\n", \
+ state->grp->gr_name, i)); \
+ } \
+ } \
+ } while(0)
+
static void get_gr_name_process(struct tevent_req *subreq);
static void get_gr_name_remove_done(struct tevent_req *subreq);
static void get_gr_name_add_done(struct tevent_req *subreq);
@@ -867,8 +920,11 @@ static void get_gr_name_process(struct tevent_req *subreq)
char *newbuf;
size_t buflen;
bool delete_group = false;
+ const char **members;
int ret;
+ DEBUG(7, ("Searching group by name (%s)\n", state->name));
+
ret = sysdb_transaction_recv(subreq, state, &state->handle);
if (ret) {
tevent_req_error(req, ret);
@@ -892,6 +948,9 @@ static void get_gr_name_process(struct tevent_req *subreq)
/* FIXME: should we move this call outside the transaction to keep the
* transaction as short as possible ? */
again:
+ /* always zero out the grp structure */
+ memset(state->grp, 0, sizeof(struct group));
+
status = ctx->ops.getgrnam_r(state->name, state->grp,
buffer, buflen, &ret);
@@ -914,23 +973,34 @@ again:
case NSS_STATUS_NOTFOUND:
+ DEBUG(7, ("Group %s not found.\n", state->name));
delete_group = true;
break;
case NSS_STATUS_SUCCESS:
+ DEBUG(7, ("Group %s found: (%s, %d)\n", state->name,
+ state->grp->gr_name, state->grp->gr_gid));
+
/* gid=0 is an invalid value */
if (state->grp->gr_gid == 0) {
delete_group = true;
break;
}
+ DEBUG_GR_MEM(7, state);
+
+ if (state->grp->gr_mem && state->grp->gr_mem[0]) {
+ members = (const char **)state->grp->gr_mem;
+ } else {
+ members = NULL;
+ }
+
subreq = sysdb_store_group_send(state, state->ev, state->handle,
state->domain,
state->grp->gr_name,
state->grp->gr_gid,
- (const char **)state->grp->gr_mem,
- NULL, NULL);
+ members, NULL, NULL);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
@@ -953,6 +1023,9 @@ again:
if (delete_group) {
struct ldb_dn *dn;
+ DEBUG(7, ("Group %s does not exist (or is invalid) on remote server,"
+ " deleting!\n", state->name));
+
dn = sysdb_group_dn(state->sysdb, state,
state->domain->name, state->name);
if (!dn) {
@@ -1063,8 +1136,11 @@ static void get_gr_gid_process(struct tevent_req *subreq)
char *newbuf;
size_t buflen;
bool delete_group = false;
+ const char **members;
int ret;
+ DEBUG(7, ("Searching group by gid (%d)\n", state->gid));
+
ret = sysdb_transaction_recv(subreq, state, &state->handle);
if (ret) {
tevent_req_error(req, ret);
@@ -1086,6 +1162,9 @@ static void get_gr_gid_process(struct tevent_req *subreq)
}
again:
+ /* always zero out the group structure */
+ memset(state->grp, 0, sizeof(struct group));
+
status = ctx->ops.getgrgid_r(state->gid, state->grp,
buffer, buflen, &ret);
@@ -1108,23 +1187,34 @@ again:
case NSS_STATUS_NOTFOUND:
+ DEBUG(7, ("Group %d not found.\n", state->gid));
delete_group = true;
break;
case NSS_STATUS_SUCCESS:
+ DEBUG(7, ("Group %d found (%s, %d)\n", state->gid,
+ state->grp->gr_name, state->grp->gr_gid));
+
/* gid=0 is an invalid value */
if (state->grp->gr_gid == 0) {
delete_group = true;
break;
}
+ DEBUG_GR_MEM(7, state);
+
+ if (state->grp->gr_mem && state->grp->gr_mem[0]) {
+ members = (const char **)state->grp->gr_mem;
+ } else {
+ members = NULL;
+ }
+
subreq = sysdb_store_group_send(state, state->ev, state->handle,
state->domain,
state->grp->gr_name,
state->grp->gr_gid,
- (const char **)state->grp->gr_mem,
- NULL, NULL);
+ members, NULL, NULL);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
@@ -1145,6 +1235,10 @@ again:
}
if (delete_group) {
+
+ DEBUG(7, ("Group %d does not exist (or is invalid) on remote server,"
+ " deleting!\n", state->gid));
+
subreq = sysdb_delete_group_by_gid_send(state, state->ev,
state->handle,
state->domain,
@@ -1210,6 +1304,8 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *mem_ctx,
struct enum_groups_state *state;
enum nss_status status;
+ DEBUG(7, ("Enumerating groups\n"));
+
req = tevent_req_create(mem_ctx, &state, struct enum_groups_state);
if (!req) return NULL;
@@ -1262,6 +1358,7 @@ static void enum_groups_process(struct tevent_req *subreq)
struct enum_groups_state);
struct proxy_ctx *ctx = state->ctx;
enum nss_status status;
+ const char **members;
char *newbuf;
int ret;
@@ -1285,6 +1382,9 @@ static void enum_groups_process(struct tevent_req *subreq)
}
again:
+ /* always zero out the grp structure */
+ memset(state->grp, 0, sizeof(struct group));
+
/* get entry */
status = ctx->ops.getgrent_r(state->grp,
state->buffer, state->buflen, &ret);
@@ -1307,7 +1407,10 @@ again:
goto again;
case NSS_STATUS_NOTFOUND:
+
/* we are done here */
+ DEBUG(7, ("Enumeration completed.\n"));
+
ctx->ops.endgrent();
subreq = sysdb_transaction_commit_send(state, state->ev,
state->handle);
@@ -1324,12 +1427,22 @@ again:
goto again; /* skip */
}
+ DEBUG(7, ("Group found (%s, %d)\n",
+ state->grp->gr_name, state->grp->gr_gid));
+
+ DEBUG_GR_MEM(7, state);
+
+ if (state->grp->gr_mem && state->grp->gr_mem[0]) {
+ members = (const char **)state->grp->gr_mem;
+ } else {
+ members = NULL;
+ }
+
subreq = sysdb_store_group_send(state, state->ev, state->handle,
state->domain,
state->grp->gr_name,
state->grp->gr_gid,
- (const char **)state->grp->gr_mem,
- NULL, NULL);
+ members, NULL, NULL);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
@@ -1739,6 +1852,9 @@ static struct tevent_req *get_group_from_gid_send(TALLOC_CTX *mem_ctx,
}
again:
+ /* always zero out the grp structure */
+ memset(state->grp, 0, sizeof(struct group));
+
status = ctx->ops.getgrgid_r(state->gid, state->grp,
buffer, buflen, &ret);