From fa5725cdb011fb57c97457a82be6be6bd7077f5a Mon Sep 17 00:00:00 2001 From: Noel Power Date: Tue, 14 Nov 2023 09:12:01 +0000 Subject: [PATCH] s3/utils: Add support to smbcacls to restore dacls from file Allow smbcacls to restore dacls to a directory from file created by with smbcacls '--save' or icalcs /save Signed-off-by: Noel Power Reviewed-by: Andrew Bartlett --- source3/utils/smbcacls.c | 168 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 2 deletions(-) diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 40f71fbdbb6..0575a254c29 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -2001,6 +2001,164 @@ out: return result; } +struct restore_dacl { + const char *path; + struct security_descriptor *sd; +}; + +/* + * Restore dacls from 'savefile' produced by + * 'icacls name /save' or 'smbcacls --save' + */ +static int cacl_restore(struct cli_state *cli, + struct cli_credentials *creds, + bool numeric, const char *restorefile) +{ + int restore_fd; + int result; + struct save_restore_stats stats = { 0 }; + + char **lines = NULL; + char *content = NULL; + char *convert_content = NULL; + size_t content_size; + struct restore_dacl *entries = NULL; + int numlines, i = 0; + bool ok; + struct dom_sid *sid = NULL; + + if (restorefile == NULL) { + DBG_ERR("No restore file specified\n"); + result = EXIT_FAILED; + goto out; + } + + if (test_args) { + result = EXIT_OK; + goto out; + } + + restore_fd = open(restorefile, O_RDONLY, S_IRUSR | S_IWUSR); + if (restore_fd < 0) { + DBG_ERR("Failed to open %s.\n", restorefile); + result = EXIT_FAILED; + goto out; + } + + content = fd_load(restore_fd, &content_size, 0, talloc_tos()); + + close(restore_fd); + + if (content == NULL) { + DBG_ERR("Failed to load content from %s.\n", restorefile); + result = EXIT_FAILED; + goto out; + } + + ok = convert_string_talloc(talloc_tos(), + CH_UTF16, + CH_UNIX, + content, + utf16_len_n(content, content_size), + (void **)(void *)&convert_content, + &content_size); + + TALLOC_FREE(content); + + if (!ok) { + DBG_ERR("Failed to convert content from %s " + "to CH_UNIX.\n", restorefile); + result = EXIT_FAILED; + goto out; + } + + lines = file_lines_parse(convert_content, + content_size, &numlines, talloc_tos()); + + if (lines == NULL) { + DBG_ERR("Failed to parse lines from content of %s.", + restorefile); + result = EXIT_FAILED; + goto out; + } + + entries = talloc_zero_array(lines, struct restore_dacl, numlines / 2); + + if (entries == NULL) { + DBG_ERR("error processing %s, out of memory\n", restorefile); + result = EXIT_FAILED; + goto out; + } + + sid = get_domain_sid(cli); + + while (i < numlines) { + int index = i / 2; + int first_line = (i % 2) == 0; + + if (first_line) { + char *tmp = NULL; + tmp = lines[i]; + /* line can be blank if root of share */ + if (strlen(tmp) == 0) { + entries[index].path = talloc_strdup(lines, + "\\"); + } else { + entries[index].path = lines[i]; + } + } else { + entries[index].sd = sddl_decode(lines, lines[i], sid); + entries[index].sd->type |= + SEC_DESC_DACL_AUTO_INHERIT_REQ; + entries[index].sd->type |= SEC_DESC_SACL_AUTO_INHERITED; + } + i++; + } + for (i = 0; i < (numlines / 2); i++) { + int mode = SMB_ACL_SET; + int set_result; + struct cli_state *targetcli = NULL; + char *targetpath = NULL; + NTSTATUS status; + + /* check for dfs */ + status = cli_resolve_path(talloc_tos(), + "", + creds, + cli, + entries[i].path, + &targetcli, &targetpath); + + if (!NT_STATUS_IS_OK(status)) { + printf("Error failed to process file: %s\n", + entries[i].path); + stats.failure += 1; + continue; + } + + set_result = cacl_set_from_sd(targetcli, + targetpath, + entries[i].sd, mode, numeric); + + if (set_result == EXIT_OK) { + printf("Successfully processed file: %s\n", + entries[i].path); + stats.success += 1; + } else { + printf("Error failed to process file: %s\n", + entries[i].path); + stats.failure += 1; + } + } + + result = EXIT_OK; +out: + TALLOC_FREE(lines); + fprintf(stdout, "Successfully processed %d files: " + "Failed processing %d files\n", stats.success, stats.failure); + return result; +} + /**************************************************************************** main program ****************************************************************************/ @@ -2382,9 +2540,15 @@ int main(int argc, char *argv[]) numeric); } } else { - if (save_file) { + if (save_file || restore_file) { sddl = 1; - result = cacl_dump_dacl(cli, creds, filename); + if (save_file) { + result = cacl_dump_dacl(cli, creds, filename); + } else { + result = cacl_restore(targetcli, + creds, + numeric, restore_file); + } } else { result = cacl_dump(targetcli, targetfile, numeric); } -- 2.34.1