📄 regf.c
字号:
while (i--) { /* Get subkey information. */ error = regf_get_subkey_by_index(parent_nk, sk, 0, (const char **)&sk_name, NULL, NULL); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Can't retrieve subkey by index.\n")); return error; } /* Delete subkey. */ error = regf_del_key(sk, sk_name); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Can't delete key '%s'.\n", sk_name)); return error; } talloc_free(sk_name); } } if (key->nk->values_offset != -1) { char *val_name; struct hive_key *sk = (struct hive_key *)key; DATA_BLOB data; int i = key->nk->num_values; while (i--) { /* Get value information. */ error = regf_get_value(parent_nk, sk, 0, (const char **)&val_name, NULL, &data); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Can't retrieve value by index.\n")); return error; } /* Delete value. */ error = regf_del_value(sk, val_name); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Can't delete value '%s'.\n", val_name)); return error; } talloc_free(val_name); } } /* Delete it from the subkey list. */ error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset, key->offset, &parent_nk->subkeys_offset); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n")); return error; } /* Re-store parent key */ parent_nk->num_subkeys--; hbin_store_tdr_resize(private_data->hive, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, parent_nk); if (key->nk->clsname_offset != -1) { hbin_free(private_data->hive, key->nk->clsname_offset); } hbin_free(private_data->hive, key->offset); return regf_save_hbin(private_data->hive);}static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent, const char *name, const char *classname, struct security_descriptor *sec_desc, struct hive_key **ret){ const struct regf_key_data *private_data = (const struct regf_key_data *)parent; struct nk_block *parent_nk = private_data->nk, nk; struct nk_block *root; struct regf_data *regf = private_data->hive; uint32_t offset; WERROR error; nk.header = "nk"; nk.type = REG_SUB_KEY; unix_to_nt_time(&nk.last_change, time(NULL)); nk.uk1 = 0; nk.parent_offset = private_data->offset; nk.num_subkeys = 0; nk.uk2 = 0; nk.subkeys_offset = -1; nk.unknown_offset = -1; nk.num_values = 0; nk.values_offset = -1; memset(nk.unk3, 0, 5); nk.clsname_offset = -1; /* FIXME: fill in */ nk.clsname_length = 0; nk.key_name = name; /* Get the security descriptor of the root key */ root = talloc_zero(ctx, struct nk_block); W_ERROR_HAVE_NO_MEMORY(root); if (!hbin_get_tdr(regf, regf->header->data_offset, root, (tdr_pull_fn_t)tdr_pull_nk_block, root)) { DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset)); return WERR_GENERAL_FAILURE; } nk.sk_offset = root->sk_offset; talloc_free(root); /* Store the new nk key */ offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk); error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset, &parent_nk->subkeys_offset); if (!W_ERROR_IS_OK(error)) { hbin_free(regf, offset); return error; } parent_nk->num_subkeys++; /* Since the subkey offset of the parent can change, store it again */ hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, nk.parent_offset, parent_nk); *ret = (struct hive_key *)regf_get_key(ctx, regf, offset); return regf_save_hbin(private_data->hive);}static WERROR regf_set_value(struct hive_key *key, const char *name, uint32_t type, const DATA_BLOB data){ struct regf_key_data *private_data = (struct regf_key_data *)key; struct regf_data *regf = private_data->hive; struct nk_block *nk = private_data->nk; struct vk_block vk; uint32_t i; uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1; DATA_BLOB values; ZERO_STRUCT(vk); /* find the value offset, if it exists */ if (nk->values_offset != -1) { values = hbin_get(regf, nk->values_offset); for (i = 0; i < nk->num_values; i++) { tmp_vk_offset = IVAL(values.data, i * 4); if (!hbin_get_tdr(regf, tmp_vk_offset, private_data, (tdr_pull_fn_t)tdr_pull_vk_block, &vk)) { DEBUG(0, ("Unable to get VK block at %d\n", tmp_vk_offset)); return WERR_GENERAL_FAILURE; } if (strcmp(vk.data_name, name) == 0) { old_vk_offset = tmp_vk_offset; break; } } /* Free data, if any */ if (!(vk.data_length & 0x80000000)) { hbin_free(regf, vk.data_offset); } } if (old_vk_offset == -1) { vk.header = "vk"; vk.name_length = strlen(name); if (name != NULL && name[0] != 0) { vk.flag = 1; vk.data_name = name; } else { vk.data_name = NULL; vk.flag = 0; } } /* Set the type and data */ vk.data_length = data.length; vk.data_type = type; if (type == REG_DWORD) { vk.data_length |= 0x80000000; vk.data_offset = *(uint32_t *)data.data; } else { /* Store data somewhere */ vk.data_offset = hbin_store(regf, data); } if (old_vk_offset == -1) { /* Store new vk */ vk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_vk_block, &vk); } else { /* Store vk at offset */ vk_offset = hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_vk_block, old_vk_offset ,&vk); } /* Re-allocate the value list */ if (nk->values_offset == -1) { nk->values_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_uint32, &vk_offset); nk->num_values = 1; } else { /* Change if we're changing, otherwise we're adding the value */ if (old_vk_offset != -1) { /* Find and overwrite the offset. */ for (i = 0; i < nk->num_values; i++) { if (IVAL(values.data, i * 4) == old_vk_offset) { SIVAL(values.data, i * 4, vk_offset); break; } } } else { /* Create a new value list */ DATA_BLOB value_list; value_list.length = (nk->num_values+1)*4; value_list.data = (uint8_t *)talloc_array(private_data, uint32_t, nk->num_values+1); W_ERROR_HAVE_NO_MEMORY(value_list.data); memcpy(value_list.data, values.data, nk->num_values * 4); SIVAL(value_list.data, nk->num_values * 4, vk_offset); nk->num_values++; nk->values_offset = hbin_store_resize(regf, nk->values_offset, value_list); } } hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block, private_data->offset, nk); return regf_save_hbin(private_data->hive);}static WERROR regf_save_hbin(struct regf_data *regf){ struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience); int i; W_ERROR_HAVE_NO_MEMORY(push); if (lseek(regf->fd, 0, SEEK_SET) == -1) { DEBUG(0, ("Error lseeking in regf file\n")); return WERR_GENERAL_FAILURE; } /* Recompute checksum */ if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) { DEBUG(0, ("Failed to push regf header\n")); return WERR_GENERAL_FAILURE; } regf->header->chksum = regf_hdr_checksum(push->data.data); talloc_free(push); if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience, (tdr_push_fn_t)tdr_push_regf_hdr, regf->header))) { DEBUG(0, ("Error writing registry file header\n")); return WERR_GENERAL_FAILURE; } if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) { DEBUG(0, ("Error lseeking to 0x1000 in regf file\n")); return WERR_GENERAL_FAILURE; } for (i = 0; regf->hbins[i]; i++) { if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience, (tdr_push_fn_t)tdr_push_hbin_block, regf->hbins[i]))) { DEBUG(0, ("Error writing HBIN block\n")); return WERR_GENERAL_FAILURE; } } return WERR_OK;}WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, struct smb_iconv_convenience *iconv_convenience, const char *location, int minor_version, struct hive_key **key){ struct regf_data *regf; struct regf_hdr *regf_hdr; struct nk_block nk; struct sk_block sk; WERROR error; DATA_BLOB data; struct security_descriptor *sd; uint32_t sk_offset; regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); regf->iconv_convenience = iconv_convenience; W_ERROR_HAVE_NO_MEMORY(regf); DEBUG(5, ("Attempting to create registry file\n")); /* Get the header */ regf->fd = creat(location, 0644); if (regf->fd == -1) { DEBUG(0,("Could not create file: %s, %s\n", location, strerror(errno))); talloc_free(regf); return WERR_GENERAL_FAILURE; } regf_hdr = talloc_zero(regf, struct regf_hdr); W_ERROR_HAVE_NO_MEMORY(regf_hdr); regf_hdr->REGF_ID = "regf"; unix_to_nt_time(®f_hdr->modtime, time(NULL)); regf_hdr->version.major = 1; regf_hdr->version.minor = minor_version; regf_hdr->last_block = 0x1000; /* Block size */ regf_hdr->description = talloc_strdup(regf_hdr, "Registry created by Samba 4"); W_ERROR_HAVE_NO_MEMORY(regf_hdr->description); regf_hdr->chksum = 0; regf->header = regf_hdr; /* Create all hbin blocks */ regf->hbins = talloc_array(regf, struct hbin_block *, 1); W_ERROR_HAVE_NO_MEMORY(regf->hbins); regf->hbins[0] = NULL; nk.header = "nk"; nk.type = REG_SUB_KEY; unix_to_nt_time(&nk.last_change, time(NULL)); nk.uk1 = 0; nk.parent_offset = -1; nk.num_subkeys = 0; nk.uk2 = 0; nk.subkeys_offset = -1; nk.unknown_offset = -1; nk.num_values = 0; nk.values_offset = -1; memset(nk.unk3, 0, 5); nk.clsname_offset = -1; nk.clsname_length = 0; nk.sk_offset = 0x80; nk.key_name = "SambaRootKey"; /* * It should be noted that changing the key_name to something shorter * creates a shorter nk block, which makes the position of the sk block * change. All Windows registries I've seen have the sk at 0x80. * I therefore recommend that our regf files share that offset -- Wilco */ /* Create a security descriptor. */ sd = security_descriptor_dacl_create(regf, 0, NULL, NULL, SID_NT_AUTHENTICATED_USERS, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_GENERIC_ALL, SEC_ACE_FLAG_OBJECT_INHERIT, NULL); /* Push the security descriptor to a blob */ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL, sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { DEBUG(0, ("Unable to push security descriptor\n")); return WERR_GENERAL_FAILURE; } ZERO_STRUCT(sk); sk.header = "sk"; sk.prev_offset = 0x80; sk.next_offset = 0x80; sk.ref_cnt = 1; sk.rec_size = data.length; sk.sec_desc = data.data; /* Store the new nk key */ regf->header->data_offset = hbin_store_tdr(regf, (tdr_push_fn_t)tdr_push_nk_block, &nk); /* Store the sk block */ sk_offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_sk_block, &sk); if (sk_offset != 0x80) { DEBUG(0, ("Error storing sk block, should be at 0x80, stored at 0x%x\n", nk.sk_offset)); return WERR_GENERAL_FAILURE; } *key = (struct hive_key *)regf_get_key(parent_ctx, regf, regf->header->data_offset); error = regf_save_hbin(regf); if (!W_ERROR_IS_OK(error)) { return error; } /* We can drop our own reference now that *key will have created one */ talloc_free(regf); return WERR_OK;}WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, struct smb_iconv_convenience *iconv_convenience, struct hive_key **key){ struct regf_data *regf; struct regf_hdr *regf_hdr; struct tdr_pull *pull; int i; regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); regf->iconv_convenience = iconv_convenience; W_ERROR_HAVE_NO_MEMORY(regf); DEBUG(5, ("Attempting to load registry file\n")); /* Get the header */ regf->fd = open(location, O_RDWR); if (regf->fd == -1) { DEBUG(0,("Could not load file: %s, %s\n", location, strerror(errno))); talloc_free(regf); return WERR_GENERAL_FAILURE; } pull = tdr_pull_init(regf, regf->iconv_convenience); pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, regf); if (pull->data.data == NULL) { DEBUG(0, ("Error reading data\n")); talloc_free(regf); return WERR_GENERAL_FAILURE; } regf_hdr = talloc(regf, struct regf_hdr); W_ERROR_HAVE_NO_MEMORY(regf_hdr); if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) { talloc_free(regf); return WERR_GENERAL_FAILURE; } regf->header = regf_hdr; if (strcmp(regf_hdr->REGF_ID, "regf") != 0) { DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n", regf_hdr->REGF_ID, location)); talloc_free(regf); return WERR_GENERAL_FAILURE; } /* Validate the header ... */ if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) { DEBUG(0, ("Registry file checksum error: %s: %d,%d\n", location, regf_hdr->chksum, regf_hdr_checksum(pull->data.data))); talloc_free(regf); return WERR_GENERAL_FAILURE; } pull->offset = 0x1000; i = 0; /* Read in all hbin blocks */ regf->hbins = talloc_array(regf, struct hbin_block *, 1); W_ERROR_HAVE_NO_MEMORY(regf->hbins); regf->hbins[0] = NULL; while (pull->offset < pull->data.length && pull->offset <= regf->header->last_block) { struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block); W_ERROR_HAVE_NO_MEMORY(hbin); if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) { DEBUG(0, ("[%d] Error parsing HBIN block\n", i)); talloc_free(regf); return WERR_FOOBAR; } if (strcmp(hbin->HBIN_ID, "hbin") != 0) { DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n", i, hbin->HBIN_ID)); talloc_free(regf); return WERR_FOOBAR; } regf->hbins[i] = hbin; i++; regf->hbins = talloc_realloc(regf, regf->hbins, struct hbin_block *, i+2); regf->hbins[i] = NULL; } talloc_free(pull); DEBUG(1, ("%d HBIN blocks read\n", i)); *key = (struct hive_key *)regf_get_key(parent_ctx, regf, regf->header->data_offset); /* We can drop our own reference now that *key will have created one */ talloc_free(regf); return WERR_OK;}static struct hive_operations reg_backend_regf = { .name = "regf", .get_key_info = regf_get_info, .enum_key = regf_get_subkey_by_index, .get_key_by_name = regf_get_subkey_by_name, .get_value_by_name = regf_get_value_by_name, .enum_value = regf_get_value, .get_sec_desc = regf_get_sec_desc, .set_sec_desc = regf_set_sec_desc, .add_key = regf_add_key, .set_value = regf_set_value, .del_key = regf_del_key, .delete_value = regf_del_value,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -