summaryrefslogtreecommitdiffstats
path: root/server/tools/sss_useradd.c
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2009-09-14 23:03:35 +0200
committerStephen Gallagher <sgallagh@redhat.com>2009-09-21 10:35:07 -0400
commit8f035b043dbd4eb631b64c4d7dcdb35272e35142 (patch)
tree3d1bbd6c615f3514d486bba4c83ce2d7b42ffd23 /server/tools/sss_useradd.c
parentdb329e0f8a35c23416acedaca3683392b0114c92 (diff)
downloadsssd-8f035b043dbd4eb631b64c4d7dcdb35272e35142.tar.gz
sssd-8f035b043dbd4eb631b64c4d7dcdb35272e35142.tar.xz
sssd-8f035b043dbd4eb631b64c4d7dcdb35272e35142.zip
Decouple synchronous sysdb interface from tools
Instead of working directly with async code in tools, create synchronous wrappers that could be used by tools and python bindings. Also resolves many issues with code duplication in tools and thus fixes ticket #87
Diffstat (limited to 'server/tools/sss_useradd.c')
-rw-r--r--server/tools/sss_useradd.c248
1 files changed, 59 insertions, 189 deletions
diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c
index 2ce1607df..becf205aa 100644
--- a/server/tools/sss_useradd.c
+++ b/server/tools/sss_useradd.c
@@ -43,27 +43,27 @@
static void get_gid_callback(void *ptr, int error, struct ldb_result *res)
{
- struct ops_ctx *data = talloc_get_type(ptr, struct ops_ctx);
+ struct tools_ctx *tctx = talloc_get_type(ptr, struct tools_ctx);
if (error) {
- data->error = error;
+ tctx->error = error;
return;
}
switch (res->count) {
case 0:
- data->error = ENOENT;
+ tctx->error = ENOENT;
break;
case 1:
- data->gid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
- if (data->gid == 0) {
- data->error = ERANGE;
+ tctx->octx->gid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0);
+ if (tctx->octx->gid == 0) {
+ tctx->error = ERANGE;
}
break;
default:
- data->error = EFAULT;
+ tctx->error = EFAULT;
break;
}
}
@@ -72,32 +72,32 @@ static void get_gid_callback(void *ptr, int error, struct ldb_result *res)
* is given, returns that as integer (rationale: shadow-utils)
* On error, returns -EINVAL
*/
-static int get_gid(struct ops_ctx *data, const char *groupname)
+static int get_gid(struct tools_ctx *tctx, const char *groupname)
{
char *end_ptr;
int ret;
errno = 0;
- data->gid = strtoul(groupname, &end_ptr, 10);
+ tctx->octx->gid = strtoul(groupname, &end_ptr, 10);
if (groupname == '\0' || *end_ptr != '\0' ||
- errno != 0 || data->gid == 0) {
+ errno != 0 || tctx->octx->gid == 0) {
/* Does not look like a gid - find the group name */
- ret = sysdb_getgrnam(data, data->ctx->sysdb,
- data->domain, groupname,
- get_gid_callback, data);
+ ret = sysdb_getgrnam(tctx->octx, tctx->sysdb,
+ tctx->octx->domain, groupname,
+ get_gid_callback, tctx);
if (ret != EOK) {
DEBUG(1, ("sysdb_getgrnam failed: %d\n", ret));
goto done;
}
- data->error = EOK;
- data->gid = 0;
- while ((data->error == EOK) && (data->gid == 0)) {
- tevent_loop_once(data->ctx->ev);
+ tctx->error = EOK;
+ tctx->octx->gid = 0;
+ while ((tctx->error == EOK) && (tctx->octx->gid == 0)) {
+ tevent_loop_once(tctx->ev);
}
- if (data->error) {
+ if (tctx->error) {
DEBUG(1, ("sysdb_getgrnam failed: %d\n", ret));
goto done;
}
@@ -107,131 +107,40 @@ done:
return ret;
}
-static void add_user_req_done(struct tevent_req *req)
+static void add_user_transaction(struct tevent_req *req)
{
- struct ops_ctx *data = tevent_req_callback_data(req, struct ops_ctx);
-
- data->error = sysdb_transaction_commit_recv(req);
- data->done = true;
-}
-
-static void add_user_terminate(struct ops_ctx *data, int error)
-{
- struct tevent_req *req;
-
- if (error != EOK) {
- goto fail;
- }
-
- req = sysdb_transaction_commit_send(data, data->ctx->ev, data->handle);
- if (!req) {
- error = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(req, add_user_req_done, data);
-
- return;
-
-fail:
- /* free transaction */
- talloc_zfree(data->handle);
-
- data->error = error;
- data->done = true;
-}
-
-static void add_user_done(struct tevent_req *subreq);
-static void add_to_groups(struct ops_ctx *data);
-static void add_to_groups_done(struct tevent_req *req);
-
-static void add_user(struct tevent_req *req)
-{
- struct ops_ctx *data = tevent_req_callback_data(req, struct ops_ctx);
- struct tevent_req *subreq;
- int ret;
-
- ret = sysdb_transaction_recv(req, data, &data->handle);
- if (ret != EOK) {
- return add_user_terminate(data, ret);
- }
-
- subreq = sysdb_add_user_send(data, data->ctx->ev, data->handle,
- data->domain, data->name,
- data->uid, data->gid,
- data->gecos, data->home,
- data->shell, NULL);
- if (!subreq) {
- add_user_terminate(data, ENOMEM);
- }
- tevent_req_set_callback(subreq, add_user_done, data);
-}
-
-static void add_user_done(struct tevent_req *subreq)
-{
- struct ops_ctx *data = tevent_req_callback_data(subreq, struct ops_ctx);
int ret;
-
- ret = sysdb_add_user_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- return add_user_terminate(data, ret);
- }
-
- if (data->groups) {
- return add_to_groups(data);
- }
-
- return add_user_terminate(data, ret);
-}
-
-static void add_to_groups(struct ops_ctx *data)
-{
- struct ldb_dn *parent_dn;
- struct ldb_dn *member_dn;
+ struct tools_ctx *tctx = tevent_req_callback_data(req,
+ struct tools_ctx);
struct tevent_req *subreq;
- member_dn = sysdb_user_dn(data->ctx->sysdb, data,
- data->domain->name, data->name);
- if (!member_dn) {
- return add_user_terminate(data, ENOMEM);
+ ret = sysdb_transaction_recv(req, tctx, &tctx->handle);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ talloc_zfree(req);
- parent_dn = sysdb_group_dn(data->ctx->sysdb, data,
- data->domain->name,
- data->groups[data->cur]);
- if (!parent_dn) {
- return add_user_terminate(data, ENOMEM);
+ /* useradd */
+ ret = useradd(tctx, tctx->ev,
+ tctx->sysdb, tctx->handle, tctx->octx);
+ if (ret != EOK) {
+ goto fail;
}
- subreq = sysdb_mod_group_member_send(data, data->ctx->ev, data->handle,
- member_dn, parent_dn,
- LDB_FLAG_MOD_ADD);
+ subreq = sysdb_transaction_commit_send(tctx, tctx->ev, tctx->handle);
if (!subreq) {
- return add_user_terminate(data, ENOMEM);
- }
- tevent_req_set_callback(subreq, add_to_groups_done, data);
-}
-
-static void add_to_groups_done(struct tevent_req *subreq)
-{
- struct ops_ctx *data = tevent_req_callback_data(subreq, struct ops_ctx);
- int ret;
-
- ret = sysdb_mod_group_member_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- return add_user_terminate(data, ret);
- }
-
- /* go on to next group */
- data->cur++;
-
- /* check if we added all of them */
- if (data->groups[data->cur] == NULL) {
- return add_user_terminate(data, EOK);
+ ret = ENOMEM;
+ goto fail;
}
+ tevent_req_set_callback(subreq, tools_transaction_done, tctx);
+ return;
- return add_to_groups(data);
+fail:
+ /* free transaction and signal error */
+ talloc_zfree(tctx->handle);
+ tctx->transaction_done = true;
+ tctx->error = ret;
}
int main(int argc, const char **argv)
@@ -241,7 +150,6 @@ int main(int argc, const char **argv)
const char *pc_gecos = NULL;
const char *pc_home = NULL;
char *pc_shell = NULL;
- char *basedir = NULL;
int pc_debug = 0;
const char *pc_username = NULL;
struct poptOption long_options[] = {
@@ -256,8 +164,8 @@ int main(int argc, const char **argv)
POPT_TABLEEND
};
poptContext pc = NULL;
- struct ops_ctx *data = NULL;
struct tevent_req *req;
+ struct tools_ctx *tctx = NULL;
char *groups = NULL;
int ret;
@@ -302,7 +210,7 @@ int main(int argc, const char **argv)
CHECK_ROOT(ret, debug_prg_name);
- ret = init_sss_tools(&data);
+ ret = init_sss_tools(&tctx);
if (ret != EOK) {
DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret)));
ERROR("Error initializing the tools\n");
@@ -311,7 +219,7 @@ int main(int argc, const char **argv)
}
/* if the domain was not given as part of FQDN, default to local domain */
- ret = get_domain(data, pc_username);
+ ret = parse_name_domain(tctx, pc_username);
if (ret != EOK) {
ERROR("Cannot get domain information\n");
ret = EXIT_FAILURE;
@@ -319,7 +227,7 @@ int main(int argc, const char **argv)
}
if (groups) {
- ret = parse_groups(data, groups, &data->groups);
+ ret = parse_groups(tctx, groups, &tctx->octx->addgroups);
if (ret != EOK) {
DEBUG(1, ("Cannot parse groups to add the user to\n"));
ERROR("Internal error while parsing parameters\n");
@@ -329,7 +237,7 @@ int main(int argc, const char **argv)
/* Same as shadow-utils useradd, -g can specify gid or group name */
if (pc_group != NULL) {
- ret = get_gid(data, pc_group);
+ ret = get_gid(tctx, pc_group);
if (ret != EOK) {
ERROR("Cannot get group information for the user\n");
ret = EXIT_FAILURE;
@@ -337,80 +245,42 @@ int main(int argc, const char **argv)
}
}
- data->uid = pc_uid;
+ tctx->octx->uid = pc_uid;
/*
* Fills in defaults for ops_ctx user did not specify.
- * FIXME - Should this originate from the confdb or another config?
*/
- if (!pc_gecos) {
- pc_gecos = data->name;
- }
- data->gecos = talloc_strdup(data, pc_gecos);
- if (!data->gecos) {
- ret = EXIT_FAILURE;
- goto fini;
- }
-
- if (pc_home) {
- data->home = talloc_strdup(data, pc_home);
- } else {
- ret = confdb_get_string(data->ctx->confdb, data,
- CONFDB_DFL_SECTION, DFL_BASEDIR_ATTR,
- DFL_BASEDIR_VAL, &basedir);
- if (ret != EOK) {
- ret = EXIT_FAILURE;
- goto fini;
- }
- data->home = talloc_asprintf(data, "%s/%s", basedir, data->name);
- if (!data->home) {
- ret = EXIT_FAILURE;
- goto fini;
- }
- }
- if (!data->home) {
- ret = EXIT_FAILURE;
- goto fini;
- }
-
- if (!pc_shell) {
- ret = confdb_get_string(data->ctx->confdb, data,
- CONFDB_DFL_SECTION, DFL_SHELL_ATTR,
- DFL_SHELL_VAL, &pc_shell);
- if (ret != EOK) {
- ret = EXIT_FAILURE;
- goto fini;
- }
- }
- data->shell = talloc_strdup(data, pc_shell);
- if (!data->shell) {
+ ret = useradd_defaults(tctx, tctx->confdb, tctx->octx,
+ pc_gecos, pc_home, pc_shell);
+ if (ret != EOK) {
+ ERROR("Cannot set default values\n");
ret = EXIT_FAILURE;
goto fini;
}
/* arguments processed, go on to actual work */
- if (id_in_range(data->uid, data->domain) != EOK) {
+ if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) {
ERROR("The selected UID is outside the allowed range\n");
ret = EXIT_FAILURE;
goto fini;
}
/* useradd */
- req = sysdb_transaction_send(data, data->ctx->ev, data->ctx->sysdb);
+ req = sysdb_transaction_send(tctx->octx, tctx->ev, tctx->sysdb);
if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not modify user.\n");
ret = EXIT_FAILURE;
goto fini;
}
- tevent_req_set_callback(req, add_user, data);
+ tevent_req_set_callback(req, add_user_transaction, tctx);
- while (!data->done) {
- tevent_loop_once(data->ctx->ev);
+ while (!tctx->transaction_done) {
+ tevent_loop_once(tctx->ev);
}
- if (data->error) {
- ret = data->error;
+ if (tctx->error) {
+ ret = tctx->error;
switch (ret) {
case EEXIST:
ERROR("A user with the same name or UID already exists\n");
@@ -430,7 +300,7 @@ int main(int argc, const char **argv)
fini:
poptFreeContext(pc);
- talloc_free(data);
+ talloc_free(tctx);
free(groups);
exit(ret);
}