#include "includes.h"
#include "system/filesys.h"
#include "popt_common.h"
-#include "registry/reg_objects.h"
-#include "registry/regfio.h"
#include "../libcli/security/security.h"
-
-/* GLOBAL VARIABLES */
-
-struct dom_sid old_sid, new_sid;
-int change = 0, new_val = 0;
-int opt_verbose = False;
-
-/********************************************************************
-********************************************************************/
-
-static void verbose_output(const char *format, ...) PRINTF_ATTRIBUTE(1,2);
-static void verbose_output(const char *format, ...)
-{
- va_list args;
- char *var = NULL;
-
- if (!opt_verbose) {
- return;
- }
-
- va_start(args, format);
- if ((vasprintf(&var, format, args)) == -1) {
- va_end(args);
- return;
- }
-
- fprintf(stdout, "%s", var);
- va_end(args);
- SAFE_FREE(var);
-}
-
-/********************************************************************
-********************************************************************/
-
-static bool swap_sid_in_acl( struct security_descriptor *sd, struct dom_sid *s1, struct dom_sid *s2 )
-{
- struct security_acl *theacl;
- int i;
- bool update = False;
-
- verbose_output(" Owner SID: %s\n", sid_string_tos(sd->owner_sid));
- if ( dom_sid_equal( sd->owner_sid, s1 ) ) {
- sid_copy( sd->owner_sid, s2 );
- update = True;
- verbose_output(" New Owner SID: %s\n",
- sid_string_tos(sd->owner_sid));
-
- }
-
- verbose_output(" Group SID: %s\n", sid_string_tos(sd->group_sid));
- if ( dom_sid_equal( sd->group_sid, s1 ) ) {
- sid_copy( sd->group_sid, s2 );
- update = True;
- verbose_output(" New Group SID: %s\n",
- sid_string_tos(sd->group_sid));
- }
-
- theacl = sd->dacl;
- verbose_output(" DACL: %d entries:\n", theacl->num_aces);
- for ( i=0; i<theacl->num_aces; i++ ) {
- verbose_output(" Trustee SID: %s\n",
- sid_string_tos(&theacl->aces[i].trustee));
- if ( dom_sid_equal( &theacl->aces[i].trustee, s1 ) ) {
- sid_copy( &theacl->aces[i].trustee, s2 );
- update = True;
- verbose_output(" New Trustee SID: %s\n",
- sid_string_tos(&theacl->aces[i].trustee));
- }
- }
-
-#if 0
- theacl = sd->sacl;
- verbose_output(" SACL: %d entries: \n", theacl->num_aces);
- for ( i=0; i<theacl->num_aces; i++ ) {
- verbose_output(" Trustee SID: %s\n",
- sid_string_tos(&theacl->aces[i].trustee));
- if ( dom_sid_equal( &theacl->aces[i].trustee, s1 ) ) {
- sid_copy( &theacl->aces[i].trustee, s2 );
- update = True;
- verbose_output(" New Trustee SID: %s\n",
- sid_string_tos(&theacl->aces[i].trustee));
- }
- }
-#endif
- return update;
-}
-
-/********************************************************************
-********************************************************************/
-
-static bool copy_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
- REGF_NK_REC *parent, REGF_FILE *outfile,
- const char *parentpath )
-{
- REGF_NK_REC *key, *subkey;
- struct security_descriptor *new_sd;
- struct regval_ctr *values;
- struct regsubkey_ctr *subkeys;
- int i;
- char *path;
- WERROR werr;
-
- /* swap out the SIDs in the security descriptor */
-
- if (nk->sec_desc->sec_desc == NULL) {
- fprintf(stderr, "Invalid (NULL) security descriptor!\n");
- return false;
- }
-
- new_sd = security_descriptor_copy(outfile->mem_ctx,
- nk->sec_desc->sec_desc);
- if (new_sd == NULL) {
- fprintf(stderr, "Failed to copy security descriptor!\n");
- return False;
- }
-
- verbose_output("ACL for %s%s%s\n", parentpath, parent ? "\\" : "", nk->keyname);
- swap_sid_in_acl( new_sd, &old_sid, &new_sid );
-
- werr = regsubkey_ctr_init(NULL, &subkeys);
- if (!W_ERROR_IS_OK(werr)) {
- DEBUG(0,("copy_registry_tree: talloc() failure!\n"));
- return False;
- }
-
- werr = regval_ctr_init(subkeys, &values);
- if (!W_ERROR_IS_OK(werr)) {
- TALLOC_FREE( subkeys );
- DEBUG(0,("copy_registry_tree: talloc() failure!\n"));
- return False;
- }
-
- /* copy values into the struct regval_ctr */
-
- for ( i=0; i<nk->num_values; i++ ) {
- regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
- nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
- }
-
- /* copy subkeys into the struct regsubkey_ctr */
-
- while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
- regsubkey_ctr_addkey( subkeys, subkey->keyname );
- }
-
- key = regfio_write_key( outfile, nk->keyname, values, subkeys, new_sd, parent );
-
- /* write each one of the subkeys out */
-
- path = talloc_asprintf(subkeys, "%s%s%s",
- parentpath, parent ? "\\" : "",nk->keyname);
- if (!path) {
- TALLOC_FREE( subkeys );
- return false;
- }
-
- nk->subkey_index = 0;
- while ((subkey = regfio_fetch_subkey(infile, nk))) {
- if (!copy_registry_tree( infile, subkey, key, outfile, path)) {
- TALLOC_FREE(subkeys);
- return false;
- }
- }
-
- /* values is a talloc()'d child of subkeys here so just throw it all away */
-
- TALLOC_FREE( subkeys );
-
- verbose_output("[%s]\n", path);
-
- return True;
-}
+#include "../librpc/gen_ndr/ndr_security.h"
/*********************************************************************
*********************************************************************/
{
TALLOC_CTX *frame = talloc_stackframe();
int opt;
- REGF_FILE *infile, *outfile;
- REGF_NK_REC *nk;
+ int change = 0, new_val = 0;
+ struct dom_sid old_sid, new_sid;
+ DATA_BLOB old_blob, new_blob;
+ enum ndr_err_code ndr_err;
char *orig_filename, *new_filename;
+ uint8_t *buf;
+ size_t len;
+ size_t ofs;
+ int opt_verbose = False;
struct poptOption long_options[] = {
POPT_AUTOHELP
{ "change-sid", 'c', POPT_ARG_STRING, NULL, 'c', "Provides SID to change" },
exit(ENOMEM);
}
- if (!(infile = regfio_open( orig_filename, O_RDONLY, 0))) {
+ buf = (uint8_t *)file_load(orig_filename, &len, UINT32_MAX, frame);
+ if (buf == NULL) {
fprintf( stderr, "Failed to open %s!\n", orig_filename );
fprintf( stderr, "Error was (%s)\n", strerror(errno) );
exit (1);
}
- if ( !(outfile = regfio_open( new_filename, (O_RDWR|O_CREAT|O_TRUNC),
- (S_IRUSR|S_IWUSR) )) ) {
- fprintf( stderr, "Failed to open new file %s!\n", new_filename );
- fprintf( stderr, "Error was (%s)\n", strerror(errno) );
- exit (1);
- }
+ ndr_err = ndr_push_struct_blob(&old_blob, frame, &old_sid,
+ (ndr_push_flags_fn_t) ndr_push_security_descriptor);
+ ndr_err = ndr_push_struct_blob(&new_blob, frame, &new_sid,
+ (ndr_push_flags_fn_t) ndr_push_security_descriptor);
- /* actually do the update now */
+ if (new_blob.length > old_blob.length) {
- if ((nk = regfio_rootkey( infile )) == NULL) {
- fprintf(stderr, "Could not get rootkey\n");
- exit(3);
}
- if (!copy_registry_tree( infile, nk, NULL, outfile, "")) {
- fprintf(stderr, "Failed to write updated registry file!\n");
- exit(2);
+ if (new_blob.length < old_blob.length) {
+ static const uint8_t pad[1024];
+ size_t pad_len = old_blob.length - new_blob.length;
+ SMB_ASSERT(pad_len <= sizeof(pad));
+ data_blob_append(frame, &new_blob, pad, pad_len);
}
- /* cleanup */
+ SMB_ASSERT(new_blob.length == old_blob.length);
+
+ for (ofs=0; ofs < len;) {
+ uint8_t *p = &buf[ofs];
+ size_t remaining = len - ofs;
+ int cmp;
+
+ if (remaining < old_blob.length) {
+ break;
+ }
+
+ cmp = memcmp(p, old_blob.data, old_blob.length);
+ if (cmp != 0) {
+ ofs += 1;
+ continue;
+ }
+
+ if (opt_verbose) {
+ fprintf(stdout, "replace at ofs[%u]\n", (unsigned)ofs);
+ }
+
+ memcpy(p, new_blob.data, new_blob.length);
+ ofs += new_blob.length;
+ }
- regfio_close(infile);
- regfio_close(outfile);
+ file_save(new_filename, buf, len);
poptFreeContext(pc);