diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db/sysdb.h | 64 | ||||
-rw-r--r-- | src/db/sysdb_ops.c | 484 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_accounts.c | 280 | ||||
-rw-r--r-- | src/providers/proxy.c | 306 | ||||
-rw-r--r-- | src/tests/sysdb-tests.c | 52 | ||||
-rw-r--r-- | src/tools/sss_sync_ops.c | 135 |
6 files changed, 430 insertions, 891 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 1e4e0c16..156dc0b8 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -411,30 +411,26 @@ int sysdb_get_new_id(TALLOC_CTX *mem_ctx, uint32_t *id); /* Add user (only basic attrs and w/o checks) */ -struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell); -int sysdb_add_basic_user_recv(struct tevent_req *req); +int sysdb_add_basic_user(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *ctx, + struct sss_domain_info *domain, + const char *name, + uid_t uid, gid_t gid, + const char *gecos, + const char *homedir, + const char *shell); /* Add user (all checks) */ -struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - int cache_timeout); -int sysdb_add_user_recv(struct tevent_req *req); +int sysdb_add_user(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *ctx, + struct sss_domain_info *domain, + const char *name, + uid_t uid, gid_t gid, + const char *gecos, + const char *homedir, + const char *shell, + struct sysdb_attrs *attrs, + int cache_timeout); /* Add group (only basic attrs and w/o checks) */ struct tevent_req *sysdb_add_basic_group_send(TALLOC_CTX *mem_ctx, @@ -468,19 +464,17 @@ int sysdb_set_group_gid(struct sysdb_handle *handle, const char *name, gid_t gid, sysdb_callback_t fn, void *pvt); -struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char *pwd, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - uint64_t cache_timeout); -int sysdb_store_user_recv(struct tevent_req *req); +int sysdb_store_user(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *ctx, + struct sss_domain_info *domain, + const char *name, + const char *pwd, + uid_t uid, gid_t gid, + const char *gecos, + const char *homedir, + const char *shell, + struct sysdb_attrs *attrs, + uint64_t cache_timeout); struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index ee86f972..6f8df5fe 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -790,52 +790,40 @@ done: /* =Add-Basic-User-NO-CHECKS============================================== */ -struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell) +int sysdb_add_basic_user(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *ctx, + struct sss_domain_info *domain, + const char *name, + uid_t uid, gid_t gid, + const char *gecos, + const char *homedir, + const char *shell) { - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; struct ldb_message *msg; int ret; - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - msg = ldb_msg_new(state); + msg = ldb_msg_new(mem_ctx); if (!msg) { - ERROR_OUT(ret, ENOMEM, fail); + return ENOMEM; } /* user dn */ - msg->dn = sysdb_user_dn(handle->ctx, msg, domain->name, name); + msg->dn = sysdb_user_dn(ctx, msg, domain->name, name); if (!msg->dn) { - ERROR_OUT(ret, ENOMEM, fail); + ERROR_OUT(ret, ENOMEM, done); } ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_USER_CLASS); - if (ret) goto fail; + if (ret) goto done; ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name); - if (ret) goto fail; + if (ret) goto done; ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid); - if (ret) goto fail; + if (ret) goto done; ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid); - if (ret) goto fail; + if (ret) goto done; /* We set gecos to be the same as fullname on user creation, * But we will not enforce coherency after that, it's up to @@ -843,270 +831,164 @@ struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx, * one of the 2 */ if (gecos && *gecos) { ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos); - if (ret) goto fail; + if (ret) goto done; ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos); - if (ret) goto fail; + if (ret) goto done; } if (homedir && *homedir) { ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir); - if (ret) goto fail; + if (ret) goto done; } if (shell && *shell) { ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell); - if (ret) goto fail; + if (ret) goto done; } /* creation time */ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, (unsigned long)time(NULL)); - if (ret) goto fail; + if (ret) goto done; + ret = ldb_add(ctx->ldb, msg); + ret = sysdb_error_to_errno(ret); - ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); +done: + if (ret) { + DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); } - tevent_req_set_callback(subreq, sysdb_op_default_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -int sysdb_add_basic_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); + talloc_zfree(msg); + return ret; } /* =Add-User-Function===================================================== */ -struct sysdb_add_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *name; - uid_t uid; - gid_t gid; - const char *gecos; - const char *homedir; - const char *shell; - struct sysdb_attrs *attrs; - - int cache_timeout; -}; - -static void sysdb_add_user_basic_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - int cache_timeout) +int sysdb_add_user(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *ctx, + struct sss_domain_info *domain, + const char *name, + uid_t uid, gid_t gid, + const char *gecos, + const char *homedir, + const char *shell, + struct sysdb_attrs *attrs, + int cache_timeout) { - struct tevent_req *req, *subreq; - struct sysdb_add_user_state *state; + TALLOC_CTX *tmpctx; struct ldb_message *msg; + struct sysdb_attrs *id_attrs; + uint32_t id; + time_t now; int ret; - req = tevent_req_create(mem_ctx, &state, struct sysdb_add_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->uid = uid; - state->gid = gid; - state->gecos = gecos; - state->homedir = homedir; - state->shell = shell; - state->attrs = attrs; - state->cache_timeout = cache_timeout; - - if (handle->ctx->mpg) { + if (ctx->mpg) { if (gid != 0) { DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n")); - ERROR_OUT(ret, EINVAL, fail); + return EINVAL; } - state->gid = state->uid; + gid = uid; } if (domain->id_max != 0 && uid != 0 && (uid < domain->id_min || uid > domain->id_max)) { DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n", uid, domain->id_min, domain->id_max)); - ERROR_OUT(ret, ERANGE, fail); + return ERANGE; } if (domain->id_max != 0 && gid != 0 && (gid < domain->id_min || gid > domain->id_max)) { DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n", gid, domain->id_min, domain->id_max)); - ERROR_OUT(ret, ERANGE, fail); + return ERANGE; } - if (handle->ctx->mpg) { + tmpctx = talloc_new(mem_ctx); + if (!tmpctx) { + return ENOMEM; + } + + if (ctx->mpg) { /* In MPG domains you can't have groups with the same name as users, * search if a group with the same name exists. * Don't worry about users, if we try to add a user with the same * name the operation will fail */ - ret = sysdb_search_group_by_name(state, handle->ctx, + ret = sysdb_search_group_by_name(tmpctx, ctx, domain, name, NULL, &msg); if (ret != ENOENT) { if (ret == EOK) ret = EEXIST; - goto fail; + goto done; } } /* check no other user with the same uid exist */ - if (state->uid != 0) { - ret = sysdb_search_user_by_uid(state, handle->ctx, + if (uid != 0) { + ret = sysdb_search_user_by_uid(tmpctx, ctx, domain, uid, NULL, &msg); if (ret != ENOENT) { if (ret == EOK) ret = EEXIST; - goto fail; + goto done; } } /* try to add the user */ - subreq = sysdb_add_basic_user_send(state, ev, handle, - domain, name, uid, gid, - gecos, homedir, shell); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req); - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_add_user_basic_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - struct sysdb_attrs *id_attrs; - uint32_t id; - time_t now; - int ret; - - ret = sysdb_add_basic_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } + ret = sysdb_add_basic_user(tmpctx, ctx, + domain, name, uid, gid, + gecos, homedir, shell); + if (ret) goto done; - if (state->uid == 0) { - ret = sysdb_get_new_id(state, state->handle->ctx, state->domain, &id); - if (ret) { - tevent_req_error(req, ret); - return; - } + if (uid == 0) { + ret = sysdb_get_new_id(tmpctx, ctx, domain, &id); + if (ret) goto done; - id_attrs = sysdb_new_attrs(state); + id_attrs = sysdb_new_attrs(tmpctx); if (!id_attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; + ret = ENOMEM; + goto done; } ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - if (state->handle->ctx->mpg) { + if (ret) goto done; + + if (ctx->mpg) { ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } + if (ret) goto done; } - ret = sysdb_set_user_attr(state, state->handle->ctx, - state->domain, state->name, - id_attrs, SYSDB_MOD_REP); - if (ret) { - tevent_req_error(req, ret); - } else { - tevent_req_done(req); - } - return; + ret = sysdb_set_user_attr(tmpctx, ctx, + domain, name, id_attrs, SYSDB_MOD_REP); + goto done; } - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - tevent_req_error(req, ENOMEM); - return; + if (!attrs) { + attrs = sysdb_new_attrs(tmpctx); + if (!attrs) { + ret = ENOMEM; + goto done; } } now = time(NULL); - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } + ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); + if (ret) goto done; - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE, - ((state->cache_timeout) ? - (now + state->cache_timeout) : 0)); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } + ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, + ((cache_timeout) ? + (now + cache_timeout) : 0)); + if (ret) goto done; - ret = sysdb_set_user_attr(state, state->handle->ctx, - state->domain, state->name, - state->attrs, SYSDB_MOD_REP); + ret = sysdb_set_user_attr(tmpctx, ctx, + domain, name, attrs, SYSDB_MOD_REP); + +done: if (ret) { DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; } - - tevent_req_done(req); -} - -int sysdb_add_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); + talloc_zfree(tmpctx); + return ret; } @@ -1441,174 +1323,104 @@ int sysdb_mod_group_member_recv(struct tevent_req *req) /* if one of the basic attributes is empty ("") as opposed to NULL, * this will just remove it */ -struct sysdb_store_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *name; - uid_t uid; - gid_t gid; - const char *gecos; - const char *homedir; - const char *shell; - struct sysdb_attrs *attrs; - - uint64_t cache_timeout; -}; - -static void sysdb_store_user_add_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char *pwd, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - uint64_t cache_timeout) +int sysdb_store_user(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *ctx, + struct sss_domain_info *domain, + const char *name, + const char *pwd, + uid_t uid, gid_t gid, + const char *gecos, + const char *homedir, + const char *shell, + struct sysdb_attrs *attrs, + uint64_t cache_timeout) { - struct tevent_req *req, *subreq; - struct sysdb_store_user_state *state; + TALLOC_CTX *tmpctx; struct ldb_message *msg; time_t now; int ret; - req = tevent_req_create(mem_ctx, &state, struct sysdb_store_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->uid = uid; - state->gid = gid; - state->gecos = gecos; - state->homedir = homedir; - state->shell = shell; - state->attrs = attrs; - state->cache_timeout = cache_timeout; + tmpctx = talloc_new(mem_ctx); + if (!tmpctx) { + return ENOMEM; + } if (pwd && (domain->legacy_passwords || !*pwd)) { - ret = sysdb_attrs_add_string(state->attrs, SYSDB_PWD, pwd); - if (ret) goto fail; + ret = sysdb_attrs_add_string(attrs, SYSDB_PWD, pwd); + if (ret) goto done; } - ret = sysdb_search_user_by_name(state, handle->ctx, + ret = sysdb_search_user_by_name(tmpctx, ctx, domain, name, NULL, &msg); if (ret && ret != ENOENT) { - goto fail; + goto done; } if (ret == ENOENT) { /* users doesn't exist, turn into adding a user */ - subreq = sysdb_add_user_send(state, state->ev, state->handle, - state->domain, state->name, - state->uid, state->gid, - state->gecos, state->homedir, - state->shell, state->attrs, - state->cache_timeout); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_store_user_add_done, req); - - return req; + ret = sysdb_add_user(tmpctx, ctx, domain, name, uid, gid, + gecos, homedir, shell, attrs, cache_timeout); + goto done; } /* the user exists, let's just replace attributes when set */ - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { + if (!attrs) { + attrs = sysdb_new_attrs(tmpctx); + if (!attrs) { ret = ENOMEM; - goto fail; + goto done; } } - if (state->uid) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_UIDNUM, state->uid); - if (ret) goto fail; + if (uid) { + ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid); + if (ret) goto done; } - if (state->gid) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid); - if (ret) goto fail; + if (gid) { + ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid); + if (ret) goto done; } - if (state->uid && !state->gid && state->handle->ctx->mpg) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->uid); - if (ret) goto fail; + if (uid && !gid && ctx->mpg) { + ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, uid); + if (ret) goto done; } - if (state->gecos) { - ret = sysdb_attrs_add_string(state->attrs, SYSDB_GECOS, state->gecos); - if (ret) goto fail; + if (gecos) { + ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos); + if (ret) goto done; } - if (state->homedir) { - ret = sysdb_attrs_add_string(state->attrs, - SYSDB_HOMEDIR, state->homedir); - if (ret) goto fail; + if (homedir) { + ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir); + if (ret) goto done; } - if (state->shell) { - ret = sysdb_attrs_add_string(state->attrs, SYSDB_SHELL, state->shell); - if (ret) goto fail; + if (shell) { + ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell); + if (ret) goto done; } now = time(NULL); - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now); - if (ret) goto fail; - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE, - ((state->cache_timeout) ? - (now + state->cache_timeout) : 0)); - if (ret) goto fail; - - ret = sysdb_set_user_attr(state, state->handle->ctx, - state->domain, state->name, - state->attrs, SYSDB_MOD_REP); - if (ret) { - goto fail; - } - - tevent_req_done(req); - tevent_req_post(req, ev); - return req; + ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); + if (ret) goto done; -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} + ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, + ((cache_timeout) ? + (now + cache_timeout) : 0)); + if (ret) goto done; -static void sysdb_store_user_add_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; + ret = sysdb_set_user_attr(tmpctx, ctx, + domain, name, attrs, SYSDB_MOD_REP); - ret = sysdb_add_user_recv(subreq); - talloc_zfree(subreq); +done: if (ret) { DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; } - - tevent_req_done(req); -} - -int sysdb_store_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); + talloc_zfree(tmpctx); + return ret; } /* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */ diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c index 56bd85fb..422e6a5d 100644 --- a/src/providers/ldap/sdap_async_accounts.c +++ b/src/providers/ldap/sdap_async_accounts.c @@ -25,34 +25,19 @@ /* ==Save-User-Entry====================================================== */ -struct sdap_save_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sdap_options *opts; - - struct sss_domain_info *dom; - - const char *name; - struct sysdb_attrs *attrs; - char *timestamp; -}; - -static void sdap_save_user_done(struct tevent_req *subreq); - - /* FIXME: support storing additional attributes */ - -static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sysdb_attrs *attrs, - bool is_initgr) +/* FIXME: support storing additional attributes */ + +static int sdap_save_user(TALLOC_CTX *memctx, + struct sysdb_ctx *ctx, + struct sdap_options *opts, + struct sss_domain_info *dom, + struct sysdb_attrs *attrs, + bool is_initgr, + char **_timestamp) { - struct tevent_req *req, *subreq; - struct sdap_save_user_state *state; struct ldb_message_element *el; int ret; + const char *name; const char *pwd; const char *gecos; const char *homedir; @@ -65,58 +50,49 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, int i; char *val = NULL; int cache_timeout; + char *timestamp = NULL; DEBUG(9, ("Save user\n")); - req = tevent_req_create(memctx, &state, struct sdap_save_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->dom = dom; - state->opts = opts; - state->attrs = attrs; - state->timestamp = NULL; - - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_NAME].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) { ret = EINVAL; goto fail; } - state->name = (const char *)el->values[0].data; + name = (const char *)el->values[0].data; - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_PWD].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) pwd = NULL; else pwd = (const char *)el->values[0].data; - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) gecos = NULL; else gecos = (const char *)el->values[0].data; - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_HOME].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) homedir = NULL; else homedir = (const char *)el->values[0].data; - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) shell = NULL; else shell = (const char *)el->values[0].data; - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_UID].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) { DEBUG(1, ("no uid provided for [%s] in domain [%s].\n", - state->name, dom->name)); + name, dom->name)); ret = EINVAL; goto fail; } @@ -131,17 +107,17 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, /* check that the uid is valid for this domain */ if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) { DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); + name)); ret = EINVAL; goto fail; } - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_GID].sys_name, &el); if (ret) goto fail; if (el->num_values == 0) { DEBUG(1, ("no gid provided for [%s] in domain [%s].\n", - state->name, dom->name)); + name, dom->name)); ret = EINVAL; goto fail; } @@ -156,26 +132,26 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, /* check that the gid is valid for this domain */ if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); + name)); ret = EINVAL; goto fail; } - user_attrs = sysdb_new_attrs(state); + user_attrs = sysdb_new_attrs(memctx); if (user_attrs == NULL) { ret = ENOMEM; goto fail; } - ret = sysdb_attrs_get_el(state->attrs, SYSDB_ORIG_DN, &el); + ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el); if (ret) { goto fail; } if (el->num_values == 0) { - DEBUG(7, ("Original DN is not available for [%s].\n", state->name)); + DEBUG(7, ("Original DN is not available for [%s].\n", name)); } else { DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n", - el->values[0].data, state->name)); + el->values[0].data, name)); ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, (const char *) el->values[0].data); if (ret) { @@ -183,16 +159,16 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, } } - ret = sysdb_attrs_get_el(state->attrs, SYSDB_MEMBEROF, &el); + ret = sysdb_attrs_get_el(attrs, SYSDB_MEMBEROF, &el); if (ret) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("Original memberOf is not available for [%s].\n", - state->name)); + name)); } else { DEBUG(7, ("Adding original memberOf attributes to [%s].\n", - state->name)); + name)); for (i = 0; i < el->num_values; i++) { ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF, (const char *) el->values[i].data); @@ -202,14 +178,14 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, } } - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, &el); if (ret) { goto fail; } if (el->num_values == 0) { DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n", - state->name)); + name)); } else { ret = sysdb_attrs_add_string(user_attrs, opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, @@ -217,21 +193,20 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, if (ret) { goto fail; } - state->timestamp = talloc_strdup(state, - (const char*)el->values[0].data); - if (!state->timestamp) { + timestamp = talloc_strdup(memctx, (const char*)el->values[0].data); + if (!timestamp) { ret = ENOMEM; goto fail; } } - ret = sysdb_attrs_get_el(state->attrs, + ret = sysdb_attrs_get_el(attrs, opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el); if (ret) { goto fail; } if (el->num_values == 0) { - DEBUG(7, ("User principle is not available for [%s].\n", state->name)); + DEBUG(7, ("User principle is not available for [%s].\n", name)); } else { upn = talloc_strdup(user_attrs, (const char*) el->values[0].data); if (!upn) { @@ -242,7 +217,7 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, make_realm_upper_case(upn); } DEBUG(7, ("Adding user principle [%s] to attributes of [%s].\n", - upn, state->name)); + upn, name)); ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn); if (ret) { goto fail; @@ -250,7 +225,7 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, } for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) { - ret = sysdb_attrs_get_el(state->attrs, opts->user_map[i].sys_name, &el); + ret = sysdb_attrs_get_el(attrs, opts->user_map[i].sys_name, &el); if (ret) { goto fail; } @@ -282,58 +257,22 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, } } - DEBUG(6, ("Storing info for user %s\n", state->name)); + DEBUG(6, ("Storing info for user %s\n", name)); - subreq = sysdb_store_user_send(state, state->ev, state->handle, - state->dom, state->name, pwd, - uid, gid, gecos, homedir, shell, - user_attrs, cache_timeout); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_save_user_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sdap_save_user_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_save_user_state *state = tevent_req_data(req, - struct sdap_save_user_state); - int ret; - - ret = sysdb_store_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to save user %s\n", state->name)); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static int sdap_save_user_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_save_user_state *state = tevent_req_data(req, - struct sdap_save_user_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); + ret = sysdb_store_user(memctx, ctx, dom, + name, pwd, uid, gid, gecos, homedir, shell, + user_attrs, cache_timeout); + if (ret) goto fail; - if (timestamp) { - *timestamp = talloc_steal(mem_ctx, state->timestamp); + if (_timestamp) { + *_timestamp = timestamp; } return EOK; + +fail: + DEBUG(2, ("Failed to save user %s\n", name)); + return ret; } @@ -347,7 +286,6 @@ struct sdap_save_users_state { struct sysdb_attrs **users; int count; - int cur; struct sysdb_handle *handle; @@ -355,8 +293,6 @@ struct sdap_save_users_state { }; static void sdap_save_users_trans(struct tevent_req *subreq); -static void sdap_save_users_store(struct tevent_req *req); -static void sdap_save_users_process(struct tevent_req *subreq); struct tevent_req *sdap_save_users_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct sss_domain_info *dom, @@ -377,7 +313,6 @@ struct tevent_req *sdap_save_users_send(TALLOC_CTX *memctx, state->dom = dom; state->users = users; state->count = num_users; - state->cur = 0; state->handle = NULL; state->higher_timestamp = NULL; @@ -396,7 +331,9 @@ static void sdap_save_users_trans(struct tevent_req *subreq) { struct tevent_req *req; struct sdap_save_users_state *state; + char *timestamp; int ret; + int i; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_save_users_state); @@ -408,73 +345,44 @@ static void sdap_save_users_trans(struct tevent_req *subreq) return; } - sdap_save_users_store(req); -} - -static void sdap_save_users_store(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct sdap_save_users_state *state; - - state = tevent_req_data(req, struct sdap_save_users_state); - - subreq = sdap_save_user_send(state, state->ev, state->handle, - state->opts, state->dom, - state->users[state->cur], false); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_save_users_process, req); -} - -static void sdap_save_users_process(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_save_users_state *state; - char *timestamp = NULL; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_save_users_state); + for (i = 0; i < state->count; i++) { + timestamp = NULL; - ret = sdap_save_user_recv(subreq, state, ×tamp); - talloc_zfree(subreq); + ret = sdap_save_user(state, state->sysdb, + state->opts, state->dom, + state->users[i], + false, ×tamp); - /* Do not fail completely on errors. - * Just report the failure to save and go on */ - if (ret) { - DEBUG(2, ("Failed to store user %d. Ignoring.\n", state->cur)); - } else { - DEBUG(9, ("User %d processed!\n", state->cur)); - } + /* Do not fail completely on errors. + * Just report the failure to save and go on */ + if (ret) { + DEBUG(2, ("Failed to store user %d. Ignoring.\n", i)); + } else { + DEBUG(9, ("User %d processed!\n", i)); + } - if (timestamp) { - if (state->higher_timestamp) { - if (strcmp(timestamp, state->higher_timestamp) > 0) { - talloc_zfree(state->higher_timestamp); - state->higher_timestamp = timestamp; + if (timestamp) { + if (state->higher_timestamp) { + if (strcmp(timestamp, state->higher_timestamp) > 0) { + talloc_zfree(state->higher_timestamp); + state->higher_timestamp = timestamp; + } else { + talloc_zfree(timestamp); + } } else { - talloc_zfree(timestamp); + state->higher_timestamp = timestamp; } - } else { - state->higher_timestamp = timestamp; } } - state->cur++; - if (state->cur < state->count) { - sdap_save_users_store(req); - } else { - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); + subreq = sysdb_transaction_commit_send(state, state->ev, + state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; } + /* sysdb_transaction_complete will call tevent_req_done(req) */ + tevent_req_set_callback(subreq, sysdb_transaction_complete, req); } static int sdap_save_users_recv(struct tevent_req *req, @@ -1780,7 +1688,6 @@ struct sdap_get_initgr_state { static void sdap_get_initgr_user(struct tevent_req *subreq); static void sdap_get_initgr_store(struct tevent_req *subreq); -static void sdap_get_initgr_commit(struct tevent_req *subreq); static void sdap_get_initgr_process(struct tevent_req *subreq); static void sdap_get_initgr_done(struct tevent_req *subreq); @@ -1903,33 +1810,16 @@ static void sdap_get_initgr_store(struct tevent_req *subreq) return; } - subreq = sdap_save_user_send(state, state->ev, state->handle, - state->opts, state->dom, - state->orig_user, true); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_commit, req); -} - -static void sdap_get_initgr_commit(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - int ret; - - DEBUG(9, ("Commit change\n")); - - ret = sdap_save_user_recv(subreq, NULL, NULL); - talloc_zfree(subreq); + ret = sdap_save_user(state, state->sysdb, + state->opts, state->dom, + state->orig_user, true, NULL); if (ret) { tevent_req_error(req, ret); return; } + DEBUG(9, ("Commit change\n")); + subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); if (!subreq) { tevent_req_error(req, ENOMEM); diff --git a/src/providers/proxy.c b/src/providers/proxy.c index 84a966a2..150639ce 100644 --- a/src/providers/proxy.c +++ b/src/providers/proxy.c @@ -345,7 +345,8 @@ static int proxy_default_recv(struct tevent_req *req) /* =Getpwnam-wrapper======================================================*/ static void get_pw_name_process(struct tevent_req *subreq); -static void get_pw_name_add_done(struct tevent_req *subreq); +static int delete_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, const char *name); static struct tevent_req *get_pw_name_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -389,7 +390,6 @@ static void get_pw_name_process(struct tevent_req *subreq) enum nss_status status; char *buffer; size_t buflen; - bool delete_user = false; int ret; DEBUG(7, ("Searching user by name (%s)\n", state->name)); @@ -423,7 +423,12 @@ static void get_pw_name_process(struct tevent_req *subreq) case NSS_STATUS_NOTFOUND: DEBUG(7, ("User %s not found.\n", state->name)); - delete_user = true; + ret = delete_user(state, state->sysdb, + state->domain, state->name); + if (ret) { + tevent_req_error(req, ret); + return; + } break; case NSS_STATUS_SUCCESS: @@ -437,28 +442,32 @@ static void get_pw_name_process(struct tevent_req *subreq) if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) || OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) { - DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); - delete_user = true; + DEBUG(2, ("User [%s] filtered out! (id out of range)\n", + state->name)); + ret = delete_user(state, state->sysdb, + state->domain, state->name); + if (ret) { + tevent_req_error(req, ret); + return; + } break; } - subreq = sysdb_store_user_send(state, state->ev, state->handle, - state->domain, - state->pwd->pw_name, - state->pwd->pw_passwd, - state->pwd->pw_uid, - state->pwd->pw_gid, - state->pwd->pw_gecos, - state->pwd->pw_dir, - state->pwd->pw_shell, - NULL, ctx->entry_cache_timeout); - if (!subreq) { - tevent_req_error(req, ENOMEM); + ret = sysdb_store_user(state, state->sysdb, + state->domain, + state->pwd->pw_name, + state->pwd->pw_passwd, + state->pwd->pw_uid, + state->pwd->pw_gid, + state->pwd->pw_gecos, + state->pwd->pw_dir, + state->pwd->pw_shell, + NULL, ctx->entry_cache_timeout); + if (ret) { + tevent_req_error(req, ret); return; } - tevent_req_set_callback(subreq, get_pw_name_add_done, req); - return; + break; case NSS_STATUS_UNAVAIL: /* "remote" backend unavailable. Enter offline mode */ @@ -466,63 +475,37 @@ static void get_pw_name_process(struct tevent_req *subreq) return; default: - break; + goto fail; } - 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) { - tevent_req_error(req, ENOMEM); - return; - } - - ret = sysdb_delete_entry(state->sysdb, dn, true); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, proxy_default_done, req); + subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); return; } + tevent_req_set_callback(subreq, proxy_default_done, req); + return; +fail: DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n", state->name, status)); tevent_req_error(req, EIO); } -static void get_pw_name_add_done(struct tevent_req *subreq) +static int delete_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, const char *name) { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct proxy_state *state = tevent_req_data(req, - struct proxy_state); - int ret; + struct ldb_dn *dn; - ret = sysdb_store_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } + DEBUG(7, ("User %s does not exist (or is invalid) on remote server," + " deleting!\n", name)); - subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; + dn = sysdb_user_dn(sysdb, mem_ctx, domain->name, name); + if (!dn) { + return ENOMEM; } - tevent_req_set_callback(subreq, proxy_default_done, req); + + return sysdb_delete_entry(sysdb, dn, true); } /* =Getpwuid-wrapper======================================================*/ @@ -572,7 +555,7 @@ static void get_pw_uid_process(struct tevent_req *subreq) enum nss_status status; char *buffer; size_t buflen; - bool delete_user = false; + bool del_user = false; int ret; DEBUG(7, ("Searching user by uid (%d)\n", state->uid)); @@ -607,7 +590,7 @@ static void get_pw_uid_process(struct tevent_req *subreq) case NSS_STATUS_NOTFOUND: DEBUG(7, ("User %d not found.\n", state->uid)); - delete_user = true; + del_user = true; break; case NSS_STATUS_SUCCESS: @@ -621,28 +604,27 @@ static void get_pw_uid_process(struct tevent_req *subreq) if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) || OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) { - DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); - delete_user = true; + DEBUG(2, ("User [%s] filtered out! (id out of range)\n", + state->pwd->pw_name)); + del_user = true; break; } - subreq = sysdb_store_user_send(state, state->ev, state->handle, - state->domain, - state->pwd->pw_name, - state->pwd->pw_passwd, - state->pwd->pw_uid, - state->pwd->pw_gid, - state->pwd->pw_gecos, - state->pwd->pw_dir, - state->pwd->pw_shell, - NULL, ctx->entry_cache_timeout); - if (!subreq) { - tevent_req_error(req, ENOMEM); + ret = sysdb_store_user(state, state->sysdb, + state->domain, + state->pwd->pw_name, + state->pwd->pw_passwd, + state->pwd->pw_uid, + state->pwd->pw_gid, + state->pwd->pw_gecos, + state->pwd->pw_dir, + state->pwd->pw_shell, + NULL, ctx->entry_cache_timeout); + if (ret) { + tevent_req_error(req, ret); return; } - tevent_req_set_callback(subreq, get_pw_name_add_done, req); - return; + break; case NSS_STATUS_UNAVAIL: /* "remote" backend unavailable. Enter offline mode */ @@ -656,7 +638,7 @@ static void get_pw_uid_process(struct tevent_req *subreq) return; } - if (delete_user) { + if (del_user) { DEBUG(7, ("User %d does not exist (or is invalid) on remote server," " deleting!\n", state->uid)); @@ -669,7 +651,15 @@ static void get_pw_uid_process(struct tevent_req *subreq) return; } tevent_req_set_callback(subreq, get_pw_uid_remove_done, req); + return; } + + subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, proxy_default_done, req); } static void get_pw_uid_remove_done(struct tevent_req *subreq) @@ -708,8 +698,6 @@ struct enum_users_state { size_t buflen; char *buffer; - - bool in_transaction; }; static void enum_users_process(struct tevent_req *subreq); @@ -748,8 +736,6 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *mem_ctx, goto fail; } - state->in_transaction = false; - status = ctx->ops.setpwent(); if (status != NSS_STATUS_SUCCESS) { tevent_req_error(req, EIO); @@ -782,23 +768,11 @@ static void enum_users_process(struct tevent_req *subreq) char *newbuf; int ret; - if (!state->in_transaction) { - ret = sysdb_transaction_recv(subreq, state, &state->handle); - if (ret) { - goto fail; - } - talloc_zfree(subreq); - - state->in_transaction = true; - } else { - ret = sysdb_store_user_recv(subreq); - if (ret) { - /* Do not fail completely on errors. - * Just report the failure to save and go on */ - DEBUG(2, ("Failed to store user. Ignoring.\n")); - } - talloc_zfree(subreq); + ret = sysdb_transaction_recv(subreq, state, &state->handle); + if (ret) { + goto fail; } + talloc_zfree(subreq); again: /* always zero out the pwd structure */ @@ -850,28 +824,29 @@ again: if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) || OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) { - DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->pwd->pw_name)); + DEBUG(2, ("User [%s] filtered out! (id out of range)\n", + state->pwd->pw_name)); goto again; /* skip */ } - subreq = sysdb_store_user_send(state, state->ev, state->handle, - state->domain, - state->pwd->pw_name, - state->pwd->pw_passwd, - state->pwd->pw_uid, - state->pwd->pw_gid, - state->pwd->pw_gecos, - state->pwd->pw_dir, - state->pwd->pw_shell, - NULL, ctx->entry_cache_timeout); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; + ret = sysdb_store_user(state, state->sysdb, + state->domain, + state->pwd->pw_name, + state->pwd->pw_passwd, + state->pwd->pw_uid, + state->pwd->pw_gid, + state->pwd->pw_gecos, + state->pwd->pw_dir, + state->pwd->pw_shell, + NULL, ctx->entry_cache_timeout); + if (ret) { + /* Do not fail completely on errors. + * Just report the failure to save and go on */ + DEBUG(2, ("Failed to store user %s. Ignoring.\n", + state->pwd->pw_name)); } - tevent_req_set_callback(subreq, enum_users_process, req); - return; + goto again; /* next */ case NSS_STATUS_UNAVAIL: /* "remote" backend unavailable. Enter offline mode */ @@ -1542,7 +1517,7 @@ fail: /* =Initgroups-wrapper====================================================*/ static void get_initgr_process(struct tevent_req *subreq); -static void get_initgr_groups_process(struct tevent_req *subreq); +static void get_initgr_groups_process(struct tevent_req *req); static void get_initgr_groups_done(struct tevent_req *subreq); static struct tevent_req *get_groups_by_gid_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -1605,7 +1580,6 @@ static void get_initgr_process(struct tevent_req *subreq) enum nss_status status; char *buffer; size_t buflen; - bool delete_user = false; int ret; ret = sysdb_transaction_recv(subreq, state, &state->handle); @@ -1636,7 +1610,13 @@ static void get_initgr_process(struct tevent_req *subreq) switch (status) { case NSS_STATUS_NOTFOUND: - delete_user = true; + DEBUG(7, ("User %s not found.\n", state->name)); + ret = delete_user(state, state->sysdb, + state->domain, state->name); + if (ret) { + tevent_req_error(req, ret); + return; + } break; case NSS_STATUS_SUCCESS: @@ -1646,27 +1626,33 @@ static void get_initgr_process(struct tevent_req *subreq) if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) || OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) { - DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); - delete_user = true; + DEBUG(2, ("User [%s] filtered out! (id out of range)\n", + state->name)); + ret = delete_user(state, state->sysdb, + state->domain, state->name); + if (ret) { + tevent_req_error(req, ret); + return; + } break; } - subreq = sysdb_store_user_send(state, state->ev, state->handle, - state->domain, - state->pwd->pw_name, - state->pwd->pw_passwd, - state->pwd->pw_uid, - state->pwd->pw_gid, - state->pwd->pw_gecos, - state->pwd->pw_dir, - state->pwd->pw_shell, - NULL, ctx->entry_cache_timeout); - if (!subreq) { - tevent_req_error(req, ENOMEM); + ret = sysdb_store_user(state, state->sysdb, + state->domain, + state->pwd->pw_name, + state->pwd->pw_passwd, + state->pwd->pw_uid, + state->pwd->pw_gid, + state->pwd->pw_gecos, + state->pwd->pw_dir, + state->pwd->pw_shell, + NULL, ctx->entry_cache_timeout); + if (ret) { + tevent_req_error(req, ret); return; } - tevent_req_set_callback(subreq, get_initgr_groups_process, req); + + get_initgr_groups_process(req); return; case NSS_STATUS_UNAVAIL: @@ -1675,43 +1661,26 @@ static void get_initgr_process(struct tevent_req *subreq) return; default: - break; + goto fail; } - if (delete_user) { - struct ldb_dn *dn; - - dn = sysdb_user_dn(state->sysdb, state, - state->domain->name, state->name); - if (!dn) { - tevent_req_error(req, ENOMEM); - return; - } - - ret = sysdb_delete_entry(state->sysdb, dn, true); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, proxy_default_done, req); + subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); return; } + tevent_req_set_callback(subreq, proxy_default_done, req); + return; +fail: DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n", state->name, status)); tevent_req_error(req, EIO); } -static void get_initgr_groups_process(struct tevent_req *subreq) +static void get_initgr_groups_process(struct tevent_req *req) { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); + struct tevent_req *subreq; struct proxy_state *state = tevent_req_data(req, struct proxy_state); struct proxy_ctx *ctx = state->ctx; @@ -1723,13 +1692,6 @@ static void get_initgr_groups_process(struct tevent_req *subreq) gid_t *gids; int ret; - ret = sysdb_store_user_recv(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - talloc_zfree(subreq); - num_gids = 0; limit = 4096; num = 4096; diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c index 519d1c4b..e75a415f 100644 --- a/src/tests/sysdb-tests.c +++ b/src/tests/sysdb-tests.c @@ -223,8 +223,6 @@ fail: data->finished = true; } -static void test_add_user_done(struct tevent_req *subreq); - static void test_add_user(struct tevent_req *subreq) { struct test_data *data = tevent_req_callback_data(subreq, @@ -242,34 +240,17 @@ static void test_add_user(struct tevent_req *subreq) homedir = talloc_asprintf(data, "/home/testuser%d", data->uid); gecos = talloc_asprintf(data, "Test User %d", data->uid); - subreq = sysdb_add_user_send(data, data->ev, data->handle, - data->ctx->domain, data->username, - data->uid, 0, - gecos, homedir, "/bin/bash", - NULL, 0); - if (!subreq) { - return test_return(data, ENOMEM); - } - tevent_req_set_callback(subreq, test_add_user_done, data); -} - -static void test_add_user_done(struct tevent_req *subreq) -{ - struct test_data *data = tevent_req_callback_data(subreq, struct test_data); - int ret; - - ret = sysdb_add_user_recv(subreq); - talloc_zfree(subreq); + ret = sysdb_add_user(data, data->handle->ctx, + data->ctx->domain, data->username, + data->uid, 0, gecos, homedir, "/bin/bash", + NULL, 0); return test_return(data, ret); } -static void test_store_user_done(struct tevent_req *subreq); - static void test_store_user(struct tevent_req *req) { struct test_data *data = tevent_req_callback_data(req, struct test_data); - struct tevent_req *subreq; char *homedir; char *gecos; int ret; @@ -282,26 +263,11 @@ static void test_store_user(struct tevent_req *req) homedir = talloc_asprintf(data, "/home/testuser%d", data->uid); gecos = talloc_asprintf(data, "Test User %d", data->uid); - subreq = sysdb_store_user_send(data, data->ev, data->handle, - data->ctx->domain, data->username, "x", - data->uid, 0, - gecos, homedir, - data->shell ? data->shell : "/bin/bash", - NULL, -1); - if (!subreq) { - test_return(data, ENOMEM); - return; - } - tevent_req_set_callback(subreq, test_store_user_done, data); -} - -static void test_store_user_done(struct tevent_req *subreq) -{ - struct test_data *data = tevent_req_callback_data(subreq, struct test_data); - int ret; - - ret = sysdb_store_user_recv(subreq); - talloc_zfree(subreq); + ret = sysdb_store_user(data, data->handle->ctx, + data->ctx->domain, data->username, "x", + data->uid, 0, gecos, homedir, + data->shell ? data->shell : "/bin/bash", + NULL, -1); return test_return(data, ret); } diff --git a/src/tools/sss_sync_ops.c b/src/tools/sss_sync_ops.c index b68bd4a6..86c17ce6 100644 --- a/src/tools/sss_sync_ops.c +++ b/src/tools/sss_sync_ops.c @@ -293,110 +293,6 @@ static int remove_from_groups_recv(struct tevent_req *req) } /* - * Add a user - */ -struct user_add_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - struct ops_ctx *data; -}; - -static void user_add_to_group_done(struct tevent_req *groupreq); -static void user_add_done(struct tevent_req *subreq); - -static struct tevent_req *user_add_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct user_add_state *state = NULL; - struct tevent_req *req; - struct tevent_req *subreq; - - req = tevent_req_create(mem_ctx, &state, struct user_add_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - subreq = sysdb_add_user_send(state, state->ev, state->handle, - state->data->domain, state->data->name, - state->data->uid, state->data->gid, - state->data->gecos, state->data->home, - state->data->shell, NULL, 0); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, user_add_done, req); - return req; -} - -static void user_add_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct user_add_state *state = tevent_req_data(req, - struct user_add_state); - int ret; - struct ldb_dn *member_dn; - struct tevent_req *groupreq; - - ret = sysdb_add_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->data->addgroups) { - member_dn = sysdb_user_dn(state->sysdb, state, - state->data->domain->name, - state->data->name); - if (!member_dn) { - tevent_req_error(req, ENOMEM); - return; - } - - groupreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, member_dn); - tevent_req_set_callback(groupreq, user_add_to_group_done, req); - return; - } - - return tevent_req_done(req); -} - -static void user_add_to_group_done(struct tevent_req *groupreq) -{ - struct tevent_req *req = tevent_req_callback_data(groupreq, - struct tevent_req); - int ret; - - ret = add_to_groups_recv(groupreq); - talloc_zfree(groupreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -static int user_add_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* * Modify a user */ struct user_mod_state { @@ -1049,23 +945,42 @@ int useradd(TALLOC_CTX *mem_ctx, int ret; struct tevent_req *req; struct sync_op_res *res = NULL; + struct ldb_dn *member_dn; res = talloc_zero(mem_ctx, struct sync_op_res); if (!res) { return ENOMEM; } - req = user_add_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; + ret = sysdb_add_user(res, sysdb, + data->domain, data->name, data->uid, data->gid, + data->gecos, data->home, data->shell, NULL, 0); + if (ret) { + goto done; } - tevent_req_set_callback(req, useradd_done, res); - SYNC_LOOP(res, ret); + if (data->addgroups) { + member_dn = sysdb_user_dn(sysdb, res, + data->domain->name, data->name); + if (!member_dn) { + ret = ENOMEM; + goto done; + } + + req = add_to_groups_send(res, ev, sysdb, handle, data, member_dn); + if (!req) { + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(req, useradd_done, res); + + SYNC_LOOP(res, ret); + } flush_nscd_cache(mem_ctx, NSCD_DB_PASSWD); flush_nscd_cache(mem_ctx, NSCD_DB_GROUP); +done: talloc_free(res); return ret; } @@ -1076,7 +991,7 @@ static void useradd_done(struct tevent_req *req) struct sync_op_res *res = tevent_req_callback_data(req, struct sync_op_res); - ret = user_add_recv(req); + ret = add_to_groups_recv(req); talloc_free(req); if (ret) { DEBUG(2, ("Adding user failed: %s (%d)\n", strerror(ret), ret)); |