Skip to content

Commit

Permalink
SSSCTL: Add sssctl gpo-remove command
Browse files Browse the repository at this point in the history
Resolves: #4523

Signed-off-by: Samuel Cabrero <[email protected]>

Reviewed-by: Sumit Bose <[email protected]>
Reviewed-by: Tomáš Halman <[email protected]>
  • Loading branch information
scabrero authored and pbrezina committed Apr 26, 2024
1 parent be73599 commit afee68b
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/tools/sssctl/sssctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ int main(int argc, const char **argv)
SSS_TOOL_DELIMITER("GPOs related tools:"),
SSS_TOOL_COMMAND("gpo-show", "Information about cached GPO", 0, sssctl_gpo_show),
SSS_TOOL_COMMAND("gpo-list", "Enumerate cached GPOs", 0, sssctl_gpo_list),
SSS_TOOL_COMMAND("gpo-remove", "Remove cached GPO", 0, sssctl_gpo_remove),
#ifdef BUILD_PASSKEY
SSS_TOOL_DELIMITER("Passkey related tools:"),
SSS_TOOL_COMMAND_FLAGS("passkey-register", "Perform passkey registration", 0, sssctl_passkey_register, SSS_TOOL_FLAG_SKIP_CMD_INIT|SSS_TOOL_FLAG_SKIP_ROOT_CHECK),
Expand Down
4 changes: 4 additions & 0 deletions src/tools/sssctl/sssctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,8 @@ errno_t sssctl_gpo_list(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt);

errno_t sssctl_gpo_remove(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt);

#endif /* _SSSCTL_H_ */
209 changes: 209 additions & 0 deletions src/tools/sssctl/sssctl_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,215 @@ errno_t sssctl_gpo_list(struct sss_cmdline *cmdline,

ret = sssctl_gpo_traverse(tmp_ctx, domain_prompt, tool_ctx->domains,
sssctl_gpo_print, NULL);
done:
talloc_free(tmp_ctx);

return ret;
}

static bool confirm(const char *prompt)
{
char str[5];

fprintf(stdout, "%s [y/n]\n", prompt);
fflush(stdout);

if (fgets(str, sizeof(str), stdin) == NULL) {
return false;
}

if (str[strlen(str) - 1] == '\n') {
str[strlen(str) - 1] = '\0';
}

if (strcmp(str, "y") == 0 || strcmp(str, "yes") == 0) {
return true;
}

fprintf(stdout, "Aborted.\n");
fflush(stdout);

return false;
}

static errno_t sssctl_gpo_remove_entry(TALLOC_CTX *mem_ctx,
struct sss_domain_info *dom,
struct sysdb_attrs *entry)
{
TALLOC_CTX *tmp_ctx = NULL;
const char *gpo_name = NULL;
const char *gpo_guid = NULL;
const char *gpo_path = NULL;
char gpo_cache_realpath[PATH_MAX];
char gpo_realpath[PATH_MAX];
char *prompt = NULL;
errno_t ret;

tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) {
ERROR("talloc failed\n");
return ENOMEM;
}

ret = get_attr_string(tmp_ctx, entry, dom, SYSDB_GPO_GUID_ATTR, &gpo_guid);
if (ret != EOK) {
ERROR("Could not find GUID attribute from GPO entry\n");
ret = ENOENT;
goto done;
}

ret = get_attr_string(tmp_ctx, entry, dom, SYSDB_NAME, &gpo_name);
if (ret != EOK) {
ERROR("Could not find description attribute from GPO entry\n");
ret = ENOENT;
goto done;
}

prompt = talloc_asprintf(tmp_ctx,
"About to delete GPO entry named [%s] with GUID "
"[%s] from database. Proceed?",
gpo_name, gpo_guid);
if (prompt == NULL) {
ERROR("talloc failed\n");
ret = ENOMEM;
goto done;
}

if (!confirm(prompt)) {
ret = EOK;
goto done;
}

ret = sysdb_gpo_delete_gpo_by_guid(tmp_ctx, dom, gpo_guid);
if (ret != EOK) {
ERROR("Could not delete GPO entry from cache\n");
goto done;
}

ret = sysdb_attrs_get_string(entry, SYSDB_GPO_PATH_ATTR, &gpo_path);
if (ret == ENOENT) {
PRINT("The GPO path was not yet stored in cache. Please remove files "
"manually from [%s]\n", GPO_CACHE_PATH);
goto done;
} else if (ret != EOK) {
return ret;
}

if (realpath(gpo_path, gpo_realpath) == NULL) {
ret = errno;
ERROR("Could not determine real path for [%s]: %s\n", gpo_path, strerror(ret));
goto done;
}

if (realpath(GPO_CACHE_PATH, gpo_cache_realpath) == NULL) {
ret = errno;
ERROR("Could not determine real path for [%s]: %s\n", GPO_CACHE_PATH, strerror(ret));
goto done;
}

if (strncmp(gpo_realpath, gpo_cache_realpath, strlen(gpo_cache_realpath)) != 0) {
ERROR("The cached GPO path [%s] is not under [%s], ignoring.\n",
gpo_realpath, gpo_cache_realpath);
ret = EOK;
goto done;
}

prompt = talloc_asprintf(tmp_ctx,
"About to recursively delete GPO downloaded "
"files [%s]. Proceed?",
gpo_path);
if (prompt == NULL) {
ERROR("talloc failed\n");
ret = ENOMEM;
goto done;
}

if (!confirm(prompt)) {
ret = EOK;
goto done;
}

ret = sss_remove_tree(gpo_path);
if (ret != EOK) {
ERROR("Unable to remove downloaded GPO files: %s\n", sss_strerror(ret));
goto done;
}

done:
talloc_free(tmp_ctx);

return ret;
}

errno_t sssctl_gpo_remove(struct sss_cmdline *cmdline,
struct sss_tool_ctx *tool_ctx,
void *pvt)
{
TALLOC_CTX *tmp_ctx = NULL;
struct sssctl_cache_opts opts = {0};
const char *attr;
errno_t ret;
struct sssctl_object_info info[] = {
SSSCTL_CACHE_GPO_NAME,
SSSCTL_CACHE_GPO_GUID,
SSSCTL_CACHE_GPO_PATH,
SSSCTL_CACHE_GPO_VERSION,
SSSCTL_CACHE_GPO_TIMEOUT,
SSSCTL_CACHE_NULL
};
struct sysdb_attrs *entry = NULL;
struct sss_domain_info *dom = NULL;
struct poptOption options[] = {
{"guid", 'g', POPT_ARG_NONE, &opts.guid, 0, _("Search by GPO guid"), NULL },
POPT_TABLEEND
};
const char *extended_help =
"This command requires the domain name to be given because the "
"same policy name (or GUID) might exists in different domains.\nE.g.:\n"
" 'Default Domain Policy'@one.test\n"
" 'Default Domain Policy'@two.test";

tmp_ctx = talloc_new(tool_ctx);
if (tmp_ctx == NULL) {
return ENOMEM;
}

ret = parse_cmdline(cmdline, tool_ctx, options, extended_help, &opts.value,
&opts.domain);
if (ret != EOK) {
ERROR("Failed to parse command line: %s\n", sss_strerror(ret));
goto done;
}

if (opts.domain == NULL) {
ERROR("%s\n", extended_help);
return EINVAL;
}

attr = SYSDB_NAME;
if (opts.guid) {
attr = SYSDB_GPO_GUID_ATTR;
}

ret = sssctl_fetch_object(tmp_ctx, info, tool_ctx->domains, opts.domain,
sysdb_gpos_base_dn, CACHED_GPO, attr, opts.value,
&entry, &dom);
if (ret == ENOENT) {
PRINT(NOT_FOUND_MSG("GPO"), opts.value);
ret = EOK;
goto done;
} else if (ret != EOK) {
ERROR("Failed to fetch cache entry: %s\n", sss_strerror(ret));
goto done;
}

if (dom == NULL) {
ERROR("Could not determine object domain\n");
ret = ERR_DOMAIN_NOT_FOUND;
goto done;
}

ret = sssctl_gpo_remove_entry(tmp_ctx, dom, entry);

done:
talloc_free(tmp_ctx);
Expand Down

0 comments on commit afee68b

Please sign in to comment.