diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/tools/sss_groupadd.c | 34 | ||||
-rw-r--r-- | server/tools/sss_groupdel.c | 34 | ||||
-rw-r--r-- | server/tools/sss_groupmod.c | 47 | ||||
-rw-r--r-- | server/tools/sss_useradd.c | 33 | ||||
-rw-r--r-- | server/tools/sss_userdel.c | 33 | ||||
-rw-r--r-- | server/tools/sss_usermod.c | 54 | ||||
-rw-r--r-- | server/tools/tools_util.c | 125 | ||||
-rw-r--r-- | server/tools/tools_util.h | 17 |
8 files changed, 289 insertions, 88 deletions
diff --git a/server/tools/sss_groupadd.c b/server/tools/sss_groupadd.c index b7994080..05f814a7 100644 --- a/server/tools/sss_groupadd.c +++ b/server/tools/sss_groupadd.c @@ -158,6 +158,7 @@ int main(int argc, const char **argv) struct tevent_req *req; struct ops_ctx *data = NULL; int ret = EXIT_SUCCESS; + const char *pc_groupname = NULL; debug_prg_name = argv[0]; @@ -199,24 +200,43 @@ int main(int argc, const char **argv) debug_level = pc_debug; /* groupname is an argument, not option */ - data->name = poptGetArg(pc); - if (data->name == NULL) { + pc_groupname = poptGetArg(pc); + if (pc_groupname == NULL) { usage(pc, _("Specify group to add\n")); ret = EXIT_FAILURE; goto fini; } + ret = parse_name_domain(data, pc_groupname); + if (ret != EOK) { + ret = EXIT_FAILURE; + goto fini; + } + data->gid = pc_gid; - /* arguments processed, go on to actual work */ - ret = find_domain_for_id(ctx, data->gid, &dom); + ret = get_domain_by_id(data->ctx, data->gid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain && data->gid && data->domain != dom) { + ERROR("Selected domain %s conflicts with selected GID %llu\n", + data->domain->name, (unsigned long long int) data->gid); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain == NULL && dom) { + data->domain = dom; + } + + ret = get_domain_type(data->ctx, data->domain); switch (ret) { case ID_IN_LOCAL: - data->domain = dom; break; case ID_IN_LEGACY_LOCAL: - data->domain = dom; case ID_OUTSIDE: ret = groupadd_legacy(data); if(ret != EOK) { @@ -231,7 +251,7 @@ int main(int argc, const char **argv) goto fini; default: - DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret)); + DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret)); ERROR("Error looking up domain\n"); ret = EXIT_FAILURE; goto fini; diff --git a/server/tools/sss_groupdel.c b/server/tools/sss_groupdel.c index a8b93578..96782084 100644 --- a/server/tools/sss_groupdel.c +++ b/server/tools/sss_groupdel.c @@ -147,6 +147,7 @@ int main(int argc, const char **argv) struct tevent_req *req; struct sss_domain_info *dom; struct group *grp_info; + const char *pc_groupname = NULL; poptContext pc = NULL; struct poptOption long_options[] = { @@ -195,27 +196,48 @@ int main(int argc, const char **argv) debug_level = pc_debug; - data->name = poptGetArg(pc); - if(data->name == NULL) { + pc_groupname = poptGetArg(pc); + if(pc_groupname == NULL) { usage(pc, _("Specify group to delete\n")); ret = EXIT_FAILURE; goto fini; } + ret = parse_name_domain(data, pc_groupname); + if (ret != EOK) { + ret = EXIT_FAILURE; + goto fini; + } + /* arguments processed, go on to actual work */ grp_info = getgrnam(data->name); if (grp_info) { data->gid = grp_info->gr_gid; } - ret = find_domain_for_id(ctx, data->gid, &dom); + /* arguments processed, go on to actual work */ + ret = get_domain_by_id(data->ctx, data->gid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain && data->gid && data->domain != dom) { + ERROR("Selected domain %s conflicts with selected GID %llu\n", + data->domain->name, (unsigned long long int) data->gid); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain == NULL && dom) { + data->domain = dom; + } + + ret = get_domain_type(data->ctx, data->domain); switch (ret) { case ID_IN_LOCAL: - data->domain = dom; break; case ID_IN_LEGACY_LOCAL: - data->domain = dom; case ID_OUTSIDE: ret = groupdel_legacy(data); if(ret != EOK) { @@ -232,7 +254,7 @@ int main(int argc, const char **argv) goto fini; default: - DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret)); + DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret)); ERROR("Error looking up domain\n"); ret = EXIT_FAILURE; goto fini; diff --git a/server/tools/sss_groupmod.c b/server/tools/sss_groupmod.c index d6088846..5420fc03 100644 --- a/server/tools/sss_groupmod.c +++ b/server/tools/sss_groupmod.c @@ -261,7 +261,8 @@ static void add_to_groups_done(struct tevent_req *req) } static int groupmod_legacy(struct tools_ctx *tools_ctx, - struct ops_ctx *ctx, int old_domain) + struct ops_ctx *ctx, + struct sss_domain_info *old_domain) { int ret = EOK; char *command = NULL; @@ -276,8 +277,13 @@ static int groupmod_legacy(struct tools_ctx *tools_ctx, } if (ctx->gid) { - ret = find_domain_for_id(tools_ctx, ctx->gid, &dom); - if (ret == old_domain) { + ret = get_domain_by_id(tools_ctx, ctx->gid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + talloc_free(command); + return EINVAL; + } + if (dom == old_domain) { APPEND_PARAM(command, GROUPMOD_GID, ctx->gid); } else { ERROR("Changing gid only allowed inside the same domain\n"); @@ -329,6 +335,7 @@ int main(int argc, const char **argv) int ret; struct group *grp_info; gid_t old_gid = 0; + const char *pc_groupname = NULL; debug_prg_name = argv[0]; @@ -389,13 +396,19 @@ int main(int argc, const char **argv) } /* groupname is an argument without --option */ - data->name = poptGetArg(pc); - if (data->name == NULL) { + pc_groupname = poptGetArg(pc); + if (pc_groupname == NULL) { usage(pc, _("Specify group to modify\n")); ret = EXIT_FAILURE; goto fini; } + ret = parse_name_domain(data, pc_groupname); + if (ret != EOK) { + ret = EXIT_FAILURE; + goto fini; + } + data->gid = pc_gid; /* arguments processed, go on to actual work */ @@ -404,16 +417,30 @@ int main(int argc, const char **argv) old_gid = grp_info->gr_gid; } - ret = find_domain_for_id(ctx, old_gid, &dom); + ret = get_domain_by_id(data->ctx, data->gid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain && data->gid && data->domain != dom) { + ERROR("Selected domain %s conflicts with selected GID %llu\n", + data->domain->name, (unsigned long long int) data->gid); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain == NULL && dom) { + data->domain = dom; + } + + ret = get_domain_type(data->ctx, data->domain); switch (ret) { case ID_IN_LOCAL: - data->domain = dom; break; case ID_IN_LEGACY_LOCAL: - data->domain = dom; case ID_OUTSIDE: - ret = groupmod_legacy(ctx, data, ret); + ret = groupmod_legacy(ctx, data, data->domain); if(ret != EOK) { ERROR("Cannot delete group from domain using the legacy tools\n"); } @@ -426,7 +453,7 @@ int main(int argc, const char **argv) goto fini; default: - DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret)); + DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret)); ERROR("Error looking up domain\n"); ret = EXIT_FAILURE; goto fini; diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c index 22698e6f..35dcee76 100644 --- a/server/tools/sss_useradd.c +++ b/server/tools/sss_useradd.c @@ -327,6 +327,7 @@ int main(int argc, const char **argv) char *pc_shell = NULL; char *basedir = NULL; int pc_debug = 0; + const char *pc_username = NULL; struct poptOption long_options[] = { POPT_AUTOHELP { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0, _("The debug level to run with"), NULL }, @@ -401,13 +402,19 @@ int main(int argc, const char **argv) } /* username is an argument without --option */ - data->name = poptGetArg(pc); - if (data->name == NULL) { + pc_username = poptGetArg(pc); + if (pc_username == NULL) { usage(pc, (_("Specify user to add\n"))); ret = EXIT_FAILURE; goto fini; } + ret = parse_name_domain(data, pc_username); + if (ret != EOK) { + ret = EXIT_FAILURE; + goto fini; + } + /* Same as shadow-utils useradd, -g can specify gid or group name */ if (pc_group != NULL) { ret = get_gid(data, pc_group); @@ -470,14 +477,28 @@ int main(int argc, const char **argv) } /* arguments processed, go on to actual work */ - ret = find_domain_for_id(ctx, data->uid, &dom); + ret = get_domain_by_id(data->ctx, data->uid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain && data->uid && data->domain != dom) { + ERROR("Selected domain %s conflicts with selected UID %llu\n", + data->domain->name, (unsigned long long int) data->uid); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain == NULL && dom) { + data->domain = dom; + } + + ret = get_domain_type(data->ctx, data->domain); switch (ret) { case ID_IN_LOCAL: - data->domain = dom; break; case ID_IN_LEGACY_LOCAL: - data->domain = dom; case ID_OUTSIDE: ret = useradd_legacy(data, groups); if(ret != EOK) { @@ -492,7 +513,7 @@ int main(int argc, const char **argv) goto fini; default: - DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret)); + DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret)); ERROR("Error looking up domain\n"); ret = EXIT_FAILURE; goto fini; diff --git a/server/tools/sss_userdel.c b/server/tools/sss_userdel.c index f7cb7571..be35b4fa 100644 --- a/server/tools/sss_userdel.c +++ b/server/tools/sss_userdel.c @@ -147,6 +147,7 @@ int main(int argc, const char **argv) struct tevent_req *req; struct sss_domain_info *dom; struct passwd *pwd_info; + const char *pc_username = NULL; int pc_debug = 0; poptContext pc = NULL; @@ -196,27 +197,47 @@ int main(int argc, const char **argv) debug_level = pc_debug; - data->name = poptGetArg(pc); - if (data->name == NULL) { + pc_username = poptGetArg(pc); + if (pc_username == NULL) { usage(pc, _("Specify user to delete\n")); ret = EXIT_FAILURE; goto fini; } + ret = parse_name_domain(data, pc_username); + if (ret != EOK) { + ret = EXIT_FAILURE; + goto fini; + } + /* arguments processed, go on to actual work */ pwd_info = getpwnam(data->name); if (pwd_info) { data->uid = pwd_info->pw_uid; } - ret = find_domain_for_id(ctx, data->uid, &dom); + ret = get_domain_by_id(data->ctx, data->uid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain && data->uid && data->domain != dom) { + ERROR("Selected domain %s conflicts with selected UID %llu\n", + data->domain->name, (unsigned long long int) data->uid); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain == NULL && dom) { + data->domain = dom; + } + + ret = get_domain_type(data->ctx, data->domain); switch (ret) { case ID_IN_LOCAL: - data->domain = dom; break; case ID_IN_LEGACY_LOCAL: - data->domain = dom; case ID_OUTSIDE: ret = userdel_legacy(data); if(ret != EOK) { @@ -233,7 +254,7 @@ int main(int argc, const char **argv) goto fini; default: - DEBUG(1, ("Unknown return code %d from find_domain_for_id\n", ret)); + DEBUG(1, ("Unknown return code %d from get_domain_type\n", ret)); ERROR("Error looking up domain\n"); ret = EXIT_FAILURE; goto fini; diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c index ca6463fa..0e1055dd 100644 --- a/server/tools/sss_usermod.c +++ b/server/tools/sss_usermod.c @@ -289,7 +289,8 @@ static void add_to_groups_done(struct tevent_req *req) static int usermod_legacy(struct tools_ctx *tools_ctx, struct ops_ctx *ctx, uid_t uid, gid_t gid, const char *gecos, const char *home, - const char *shell, int lock, int old_domain) + const char *shell, int lock, + struct sss_domain_info *old_domain) { int ret = EOK; char *command = NULL; @@ -298,8 +299,13 @@ static int usermod_legacy(struct tools_ctx *tools_ctx, struct ops_ctx *ctx, APPEND_STRING(command, USERMOD); if (uid) { - ret = find_domain_for_id(tools_ctx, uid, &dom); - if (ret == old_domain) { + ret = get_domain_by_id(tools_ctx, ctx->gid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + talloc_free(command); + return EINVAL; + } + if (dom == old_domain) { APPEND_PARAM(command, USERMOD_UID, uid); } else { ERROR("Changing uid only allowed inside the same domain\n"); @@ -309,8 +315,13 @@ static int usermod_legacy(struct tools_ctx *tools_ctx, struct ops_ctx *ctx, } if (gid) { - ret = find_domain_for_id(tools_ctx, gid, &dom); - if (ret == old_domain) { + ret = get_domain_by_id(tools_ctx, ctx->gid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + talloc_free(command); + return EINVAL; + } + if (dom == old_domain) { APPEND_PARAM(command, USERMOD_GID, gid); } else { ERROR("Changing gid only allowed inside the same domain\n"); @@ -381,6 +392,7 @@ int main(int argc, const char **argv) int ret; struct passwd *pwd_info; uid_t old_uid = 0; + const char *pc_username = NULL; debug_prg_name = argv[0]; @@ -452,29 +464,49 @@ int main(int argc, const char **argv) } /* username is an argument without --option */ - data->name = poptGetArg(pc); - if (data->name == NULL) { + pc_username = poptGetArg(pc); + if (pc_username == NULL) { usage(pc, _("Specify user to modify\n")); ret = EXIT_FAILURE; goto fini; } + ret = parse_name_domain(data, pc_username); + if (ret != EOK) { + ret = EXIT_FAILURE; + goto fini; + } + pwd_info = getpwnam(data->name); if (pwd_info) { old_uid = pwd_info->pw_uid; } - ret = find_domain_for_id(ctx, old_uid, &dom); + ret = get_domain_by_id(data->ctx, data->uid, &dom); + if (ret != EOK) { + ERROR("Cannot get domain info\n"); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain && data->uid && data->domain != dom) { + ERROR("Selected domain %s conflicts with selected UID %llu\n", + data->domain->name, (unsigned long long int) data->uid); + ret = EXIT_FAILURE; + goto fini; + } + if (data->domain == NULL && dom) { + data->domain = dom; + } + + ret = get_domain_type(data->ctx, data->domain); switch (ret) { case ID_IN_LOCAL: - data->domain = dom; break; case ID_IN_LEGACY_LOCAL: - data->domain = dom; case ID_OUTSIDE: ret = usermod_legacy(ctx, data, pc_uid, pc_gid, pc_gecos, - pc_home, pc_shell, pc_lock, ret); + pc_home, pc_shell, pc_lock, data->domain); if(ret != EOK) { ERROR("Cannot delete user from domain using the legacy tools\n"); } diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c index b580300b..1e0e91de 100644 --- a/server/tools/tools_util.c +++ b/server/tools/tools_util.c @@ -69,52 +69,61 @@ static int is_domain_local_legacy(struct tools_ctx *ctx, struct sss_domain_info return -1; } -enum id_domain find_domain_for_id(struct tools_ctx *ctx, - uint32_t id, - struct sss_domain_info **dom_ret) +enum id_domain get_domain_type(struct tools_ctx *ctx, + struct sss_domain_info *dom) +{ + if (dom == NULL) { + return ID_OUTSIDE; + } + + if (strcasecmp(dom->provider, "local") == 0) { + return ID_IN_LOCAL; + } else if (is_domain_local_legacy(ctx, dom) == 0) { + return ID_IN_LEGACY_LOCAL; + } + + return ID_IN_OTHER; +} + +static struct sss_domain_info *get_local_domain(struct tools_ctx *ctx) { struct sss_domain_info *dom = NULL; - if (id) { - /* ID specified, find which domain it's in */ - for (dom = ctx->domains; dom; dom = dom->next) { - if (id < dom->id_min || id > dom->id_max) { - continue; - } else { - if (strcasecmp(dom->provider, "local") == 0) { - *dom_ret = dom; - return ID_IN_LOCAL; - } else if (is_domain_local_legacy(ctx, dom) == 0) { - *dom_ret = dom; - return ID_IN_LEGACY_LOCAL; - } else { - *dom_ret = dom; - return ID_IN_OTHER; - } - } - } - if (dom == NULL) { - *dom_ret = NULL; - return ID_OUTSIDE; + /* No ID specified, find LOCAL */ + for (dom = ctx->domains; dom; dom = dom->next) { + if (strcasecmp(dom->provider, "local") == 0) { + break; } - } else { - /* No ID specified, find LOCAL */ + } + + return dom; +} + +int get_domain_by_id(struct tools_ctx *ctx, + uint32_t id, + struct sss_domain_info **_dom) +{ + struct sss_domain_info *dom = NULL; + int ret = EOK; + + if (id) { for (dom = ctx->domains; dom; dom = dom->next) { - if (strcasecmp(dom->provider, "local") == 0) { - *dom_ret = dom; - return ID_IN_LOCAL; + if (id >= dom->id_min && id <= dom->id_max) { + break; } } + } + + if (dom == NULL && id == 0) { + dom = get_local_domain(ctx); if (dom == NULL) { - DEBUG(1, ("Could not get LOCAL domain info\n")); - *dom_ret = dom; - return ID_ERROR; + DEBUG(1, ("Cannot find local domain info\n")); + ret = ENOENT; } } - /* We should never end up here */ - *dom_ret = NULL; - return ID_ERROR; + *_dom = dom; + return ret; } int setup_db(struct tools_ctx **tools_ctx) @@ -229,6 +238,40 @@ int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out) return EOK; } +int parse_name_domain(struct ops_ctx *octx, + const char *fullname) +{ + int ret; + char *domain = NULL; + struct sss_domain_info *dom; + + ret = sss_parse_name(octx, octx->ctx->snctx, fullname, &domain, &octx->name); + if (ret != EOK) { + DEBUG(0, ("Cannot parse full name\n")); + return ret; + } + DEBUG(5, ("Parsed username: %s\n", octx->name)); + + if (domain) { + DEBUG(5, ("Parsed domain: %s\n", domain)); + + /* Got string domain name, find corresponding sss_domain_info */ + for (dom = octx->ctx->domains; dom; dom = dom->next) { + if (strcasecmp(dom->name, domain) == 0) { + DEBUG(6, ("Found sss_domain_info for given domain name\n")); + octx->domain = dom; + break; + } + } + if (octx->domain == NULL) { + DEBUG(0, ("Invalid domain %s specified in FQDN\n", domain)); + return EINVAL; + } + } + + return EOK; +} + int set_locale(void) { char *c; @@ -253,18 +296,26 @@ int set_locale(void) return EOK; } -int init_sss_tools(struct tools_ctx **ctx) +int init_sss_tools(struct tools_ctx **_ctx) { int ret; + struct tools_ctx *ctx; /* Connect to the database */ - ret = setup_db(ctx); + ret = setup_db(&ctx); if (ret != EOK) { DEBUG(1, ("Could not set up database\n")); ret = EXIT_FAILURE; goto fini; } + ret = sss_names_init(ctx, ctx->confdb, &ctx->snctx); + if (ret != EOK) { + DEBUG(1, ("Could not set up parsing\n")); + goto fini; + } + + *_ctx = ctx; ret = EOK; fini: return ret; diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h index 5bf3b384..772ba36b 100644 --- a/server/tools/tools_util.h +++ b/server/tools/tools_util.h @@ -44,6 +44,7 @@ struct tools_ctx { struct tevent_context *ev; struct confdb_ctx *confdb; struct sysdb_ctx *sysdb; + struct sss_names_ctx *snctx; struct sss_domain_info *domains; }; @@ -53,7 +54,7 @@ struct ops_ctx { struct tevent_context *ev; struct sss_domain_info *domain; - const char *name; + char *name; uid_t uid; gid_t gid; char *gecos; @@ -71,7 +72,7 @@ struct ops_ctx { bool done; }; -int init_sss_tools(struct tools_ctx **ctx); +int init_sss_tools(struct tools_ctx **_ctx); int setup_db(struct tools_ctx **ctx); @@ -79,10 +80,16 @@ void usage(poptContext pc, const char *error); int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out); -enum id_domain find_domain_for_id(struct tools_ctx *ctx, - uint32_t id, - struct sss_domain_info **dom_ret); +enum id_domain get_domain_type(struct tools_ctx *ctx, + struct sss_domain_info *dom); + +int get_domain_by_id(struct tools_ctx *ctx, + uint32_t id, + struct sss_domain_info **_dom); int set_locale(void); +int parse_name_domain(struct ops_ctx *octx, + const char *fullname); + #endif /* __TOOLS_UTIL_H__ */ |