*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "regfio.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_REGISTRY
+
/*******************************************************************
*
* TODO : Right now this code basically ignores classnames.
return -1;
}
- if ( (size_t)file_offset >= sbuf.st_size )
+ if ( (size_t)file_offset >= sbuf.st_ex_size )
return -1;
- /* if block_size == 0, we are parsnig HBIN records and need
+ /* if block_size == 0, we are parsing HBIN records and need
to read some of the header to get the block_size from there */
if ( block_size == 0 ) {
- uint8 hdr[0x20];
+ char hdr[0x20];
if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));
return -1;
}
- prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );
+ if (!prs_init( ps, block_size, file->mem_ctx, UNMARSHALL )) {
+ DEBUG(0,("read_block: prs_init() failed! (%s)\n", strerror(errno) ));
+ return -1;
+ }
buffer = prs_data_p( ps );
bytes_read = returned = 0;
/*******************************************************************
*******************************************************************/
-static BOOL write_hbin_block( REGF_FILE *file, REGF_HBIN *hbin )
+static bool write_hbin_block( REGF_FILE *file, REGF_HBIN *hbin )
{
if ( !hbin->dirty )
return True;
/*******************************************************************
*******************************************************************/
-static BOOL hbin_block_close( REGF_FILE *file, REGF_HBIN *hbin )
+static bool hbin_block_close( REGF_FILE *file, REGF_HBIN *hbin )
{
REGF_HBIN *p;
/*******************************************************************
*******************************************************************/
-static BOOL prs_regf_block( const char *desc, prs_struct *ps, int depth, REGF_FILE *file )
+static bool prs_regf_block( const char *desc, prs_struct *ps, int depth, REGF_FILE *file )
{
prs_debug(ps, depth, desc, "prs_regf_block");
depth++;
- if ( !prs_uint8s( True, "header", ps, depth, file->header, sizeof( file->header )) )
+ if ( !prs_uint8s( True, "header", ps, depth, (uint8*)file->header, sizeof( file->header )) )
return False;
/* yes, these values are always identical so store them only once */
/*******************************************************************
*******************************************************************/
-static BOOL prs_hbin_block( const char *desc, prs_struct *ps, int depth, REGF_HBIN *hbin )
+static bool prs_hbin_block( const char *desc, prs_struct *ps, int depth, REGF_HBIN *hbin )
{
uint32 block_size2;
prs_debug(ps, depth, desc, "prs_regf_block");
depth++;
- if ( !prs_uint8s( True, "header", ps, depth, hbin->header, sizeof( hbin->header )) )
+ if ( !prs_uint8s( True, "header", ps, depth, (uint8*)hbin->header, sizeof( hbin->header )) )
return False;
if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))
/*******************************************************************
*******************************************************************/
-static BOOL prs_nk_rec( const char *desc, prs_struct *ps, int depth, REGF_NK_REC *nk )
+static bool prs_nk_rec( const char *desc, prs_struct *ps, int depth, REGF_NK_REC *nk )
{
uint16 class_length, name_length;
uint32 start;
if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))
return False;
- if ( !prs_uint8s( True, "header", ps, depth, nk->header, sizeof( nk->header )) )
+ if ( !prs_uint8s( True, "header", ps, depth, (uint8*)nk->header, sizeof( nk->header )) )
return False;
if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))
return False;
}
- if ( !prs_uint8s( True, "name", ps, depth, nk->keyname, name_length) )
+ if ( !prs_uint8s( True, "name", ps, depth, (uint8*)nk->keyname, name_length) )
return False;
if ( UNMARSHALLING(ps) )
/*******************************************************************
*******************************************************************/
-static BOOL read_regf_block( REGF_FILE *file )
+static bool read_regf_block( REGF_FILE *file )
{
prs_struct ps;
uint32 checksum;
return False;
record_size = 0;
+ header = 0;
curr_off = prs_offset( &hbin->ps );
while ( header != 0xffffffff ) {
/* not done yet so reset the current offset to the
}
/*******************************************************************
- Input a randon offset and receive the correpsonding HBIN
+ Input a random offset and receive the corresponding HBIN
block for it
*******************************************************************/
-static BOOL hbin_contains_offset( REGF_HBIN *hbin, uint32 offset )
+static bool hbin_contains_offset( REGF_HBIN *hbin, uint32 offset )
{
if ( !hbin )
return False;
}
/*******************************************************************
- Input a randon offset and receive the correpsonding HBIN
+ Input a random offset and receive the corresponding HBIN
block for it
*******************************************************************/
/* start with the open list */
for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
- DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%x]\n", hbin->file_off, (uint32)hbin ));
+ DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%lx]\n", hbin->file_off, (unsigned long)hbin ));
if ( hbin_contains_offset( hbin, offset ) )
return hbin;
}
/*******************************************************************
*******************************************************************/
-static BOOL prs_hash_rec( const char *desc, prs_struct *ps, int depth, REGF_HASH_REC *hash )
+static bool prs_hash_rec( const char *desc, prs_struct *ps, int depth, REGF_HASH_REC *hash )
{
prs_debug(ps, depth, desc, "prs_hash_rec");
depth++;
/*******************************************************************
*******************************************************************/
-static BOOL hbin_prs_lf_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk )
+static bool hbin_prs_lf_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk )
{
int i;
REGF_LF_REC *lf = &nk->subkeys;
if ( !prs_uint32( "rec_size", &hbin->ps, depth, &lf->rec_size ))
return False;
- if ( !prs_uint8s( True, "header", &hbin->ps, depth, lf->header, sizeof( lf->header )) )
+ if ( !prs_uint8s( True, "header", &hbin->ps, depth, (uint8*)lf->header, sizeof( lf->header )) )
return False;
if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
return False;
if ( UNMARSHALLING(&hbin->ps) ) {
- if ( !(lf->hashes = PRS_ALLOC_MEM( &hbin->ps, REGF_HASH_REC, lf->num_keys )) )
- return False;
+ if (lf->num_keys) {
+ if ( !(lf->hashes = PRS_ALLOC_MEM( &hbin->ps, REGF_HASH_REC, lf->num_keys )) )
+ return False;
+ } else {
+ lf->hashes = NULL;
+ }
}
for ( i=0; i<lf->num_keys; i++ ) {
/*******************************************************************
*******************************************************************/
-static BOOL hbin_prs_sk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_SK_REC *sk )
+static bool hbin_prs_sk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_SK_REC *sk )
{
prs_struct *ps = &hbin->ps;
uint16 tag = 0xFFFF;
if ( !prs_uint32( "rec_size", &hbin->ps, depth, &sk->rec_size ))
return False;
- if ( !prs_uint8s( True, "header", ps, depth, sk->header, sizeof( sk->header )) )
+ if ( !prs_uint8s( True, "header", ps, depth, (uint8*)sk->header, sizeof( sk->header )) )
return False;
if ( !prs_uint16( "tag", ps, depth, &tag))
return False;
if ( !prs_uint32( "size", ps, depth, &sk->size))
return False;
- if ( !sec_io_desc( "sec_desc", &sk->sec_desc, ps, depth ))
- return False;
+ {
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx = prs_get_mem_context(&hbin->ps);
+ DATA_BLOB blob;
+
+ if (MARSHALLING(&hbin->ps)) {
+ status = marshall_sec_desc(mem_ctx,
+ sk->sec_desc,
+ &blob.data, &blob.length);
+ if (!NT_STATUS_IS_OK(status))
+ return False;
+ if (!prs_copy_data_in(&hbin->ps, (const char *)blob.data, blob.length))
+ return False;
+ } else {
+ blob = data_blob_const(prs_data_p(&hbin->ps),
+ prs_data_size(&hbin->ps));
+ status = unmarshall_sec_desc(mem_ctx,
+ blob.data, blob.length,
+ &sk->sec_desc);
+ if (!NT_STATUS_IS_OK(status))
+ return False;
+ prs_set_offset(&hbin->ps, blob.length);
+ }
+ }
end_off = prs_offset( &hbin->ps );
/*******************************************************************
*******************************************************************/
-static BOOL hbin_prs_vk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_VK_REC *vk, REGF_FILE *file )
+static bool hbin_prs_vk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_VK_REC *vk, REGF_FILE *file )
{
uint32 offset;
uint16 name_length;
if ( !prs_uint32( "rec_size", &hbin->ps, depth, &vk->rec_size ))
return False;
- if ( !prs_uint8s( True, "header", ps, depth, vk->header, sizeof( vk->header )) )
+ if ( !prs_uint8s( True, "header", ps, depth, (uint8*)vk->header, sizeof( vk->header )) )
return False;
if ( MARSHALLING(&hbin->ps) )
if ( !(vk->valuename = PRS_ALLOC_MEM( ps, char, name_length+1 )))
return False;
}
- if ( !prs_uint8s( True, "name", ps, depth, vk->valuename, name_length ) )
+ if ( !prs_uint8s( True, "name", ps, depth, (uint8*)vk->valuename, name_length ) )
return False;
}
/* get the data if necessary */
if ( vk->data_size != 0 ) {
- BOOL charmode = False;
+ bool charmode = False;
if ( (vk->type == REG_SZ) || (vk->type == REG_MULTI_SZ) )
charmode = True;
in the prs_struct *ps.
*******************************************************************/
-static BOOL hbin_prs_vk_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk, REGF_FILE *file )
+static bool hbin_prs_vk_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk, REGF_FILE *file )
{
int i;
uint32 record_size;
REGF_SK_REC *p;
for ( p=file->sec_desc_list; p; p=p->next ) {
- if ( sec_desc_equal( p->sec_desc, sd ) )
+ if ( security_descriptor_equal( p->sec_desc, sd ) )
return p;
}
/*******************************************************************
*******************************************************************/
-static BOOL hbin_prs_key( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk )
+static bool hbin_prs_key( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk )
{
int depth = 0;
REGF_HBIN *sub_hbin;
/*******************************************************************
*******************************************************************/
-static BOOL next_record( REGF_HBIN *hbin, const char *hdr, BOOL *eob )
+static bool next_record( REGF_HBIN *hbin, const char *hdr, bool *eob )
{
- char header[REC_HDR_SIZE] = "";
+ uint8 header[REC_HDR_SIZE];
uint32 record_size;
uint32 curr_off, block_size;
- BOOL found = False;
+ bool found = False;
prs_struct *ps = &hbin->ps;
curr_off = prs_offset( ps );
if ( curr_off == 0 )
prs_set_offset( ps, HBIN_HEADER_REC_SIZE );
- /* assume that the current offset is at the reacord header
+ /* assume that the current offset is at the record header
and we need to backup to read the record size */
curr_off -= sizeof(uint32);
block_size = prs_data_size( ps );
record_size = 0;
+ memset( header, 0x0, sizeof(uint8)*REC_HDR_SIZE );
while ( !found ) {
curr_off = curr_off+record_size;
/*******************************************************************
*******************************************************************/
-static BOOL next_nk_record( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk, BOOL *eob )
+static bool next_nk_record( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk, bool *eob )
{
if ( next_record( hbin, "nk", eob ) && hbin_prs_key( file, hbin, nk ) )
return True;
block header to disk
*******************************************************************/
-static BOOL init_regf_block( REGF_FILE *file )
+static bool init_regf_block( REGF_FILE *file )
{
prs_struct ps;
- BOOL result = True;
+ bool result = True;
if ( !prs_init( &ps, REGF_BLOCKSIZE, file->mem_ctx, MARSHALL ) )
return False;
/* cleanup for a file opened for write */
- if ( file->open_flags & (O_WRONLY|O_RDWR) ) {
+ if ((file->fd != -1) && (file->open_flags & (O_WRONLY|O_RDWR))) {
prs_struct ps;
REGF_SK_REC *sk;
/* nothing tdo do if there is no open file */
- if ( !file || (file->fd == -1) )
+ if (file->fd == -1)
return 0;
fd = file->fd;
REGF_NK_REC *nk;
REGF_HBIN *hbin;
uint32 offset = REGF_BLOCKSIZE;
- BOOL found = False;
- BOOL eob;
+ bool found = False;
+ bool eob;
if ( !file )
return NULL;
return NULL;
}
- hbin->file_off = sbuf.st_size;
+ hbin->file_off = sbuf.st_ex_size;
hbin->free_off = HBIN_HEADER_REC_SIZE;
hbin->free_size = block_size - hbin->free_off + sizeof(uint32);;
{
REGF_HBIN *hbin, *p_hbin;
uint32 block_off;
- BOOL cached;
+ bool cached;
/* check open block list */
/* allocate in multiples of REGF_ALLOC_BLOCK; make sure (size + hbin_header) fits */
- alloc_size = ((size+HBIN_HEADER_REC_SIZE) / REGF_ALLOC_BLOCK ) + REGF_ALLOC_BLOCK;
+ alloc_size = (((size+HBIN_HEADER_REC_SIZE) / REGF_ALLOC_BLOCK ) + 1 ) * REGF_ALLOC_BLOCK;
if ( !(hbin = regf_hbin_allocate( file, alloc_size )) ) {
DEBUG(0,("find_free_space: regf_hbin_allocate() failed!\n"));
/* the record size is sizeof(hdr) + name + static members + data_size_field */
- size = sizeof(uint32)*5 + sec_desc_size( sd ) + sizeof(uint32);
+ size = sizeof(uint32)*5 + ndr_size_security_descriptor(sd, NULL, 0) + sizeof(uint32);
/* multiple of 8 */
size_mod8 = size & 0xfffffff8;
/*******************************************************************
*******************************************************************/
-static BOOL create_vk_record( REGF_FILE *file, REGF_VK_REC *vk, REGISTRY_VALUE *value )
+static bool create_vk_record(REGF_FILE *file, REGF_VK_REC *vk,
+ struct regval_blob *value)
{
char *name = regval_name(value);
REGF_HBIN *data_hbin;
if ( vk->data_size > sizeof(uint32) ) {
uint32 data_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
- vk->data = TALLOC_MEMDUP( file->mem_ctx, regval_data_p(value), vk->data_size );
+ vk->data = (uint8 *)TALLOC_MEMDUP( file->mem_ctx,
+ regval_data_p(value),
+ vk->data_size );
+ if (vk->data == NULL) {
+ return False;
+ }
/* go ahead and store the offset....we'll pick this hbin block back up when
we stream the data */
- data_hbin = find_free_space(file, data_size );
+ if ((data_hbin = find_free_space(file, data_size )) == NULL) {
+ return False;
+ }
vk->data_off = prs_offset( &data_hbin->ps ) + data_hbin->first_hbin_off - HBIN_HDR_SIZE;
}
else {
+ /* make sure we don't try to copy from a NULL value pointer */
+
+ if ( vk->data_size != 0 )
+ memcpy( &vk->data_off, regval_data_p(value), sizeof(uint32) );
vk->data_size |= VK_DATA_IN_OFFSET;
- memcpy( &vk->data_off, regval_data_p(value), sizeof(uint32) );
}
return True;
static int hashrec_cmp( REGF_HASH_REC *h1, REGF_HASH_REC *h2 )
{
- return StrnCaseCmp( h1->keycheck, h2->keycheck, sizeof(uint32) );
+ return StrCaseCmp( h1->fullname, h2->fullname );
}
/*******************************************************************
*******************************************************************/
- REGF_NK_REC* regfio_write_key( REGF_FILE *file, const char *name,
- REGVAL_CTR *values, REGSUBKEY_CTR *subkeys,
+ REGF_NK_REC* regfio_write_key( REGF_FILE *file, const char *name,
+ struct regval_ctr *values, struct regsubkey_ctr *subkeys,
SEC_DESC *sec_desc, REGF_NK_REC *parent )
{
REGF_NK_REC *nk;
- REGF_HBIN *vlist_hbin;
+ REGF_HBIN *vlist_hbin = NULL;
uint32 size;
if ( !(nk = TALLOC_ZERO_P( file->mem_ctx, REGF_NK_REC )) )
size = nk_record_data_size( nk );
nk->rec_size = ( size - 1 ) ^ 0XFFFFFFFF;
- nk->hbin = find_free_space( file, size );
+ if ((nk->hbin = find_free_space( file, size )) == NULL) {
+ return NULL;
+ }
nk->hbin_off = prs_offset( &nk->hbin->ps );
/* Update the hash record in the parent */
hash->nk_off = prs_offset( &nk->hbin->ps ) + nk->hbin->first_hbin_off - HBIN_HDR_SIZE;
memcpy( hash->keycheck, name, sizeof(uint32) );
+ hash->fullname = talloc_strdup( file->mem_ctx, name );
parent->subkey_index++;
/* sort the list by keyname */
if ( sec_desc ) {
uint32 sk_size = sk_record_data_size( sec_desc );
REGF_HBIN *sk_hbin;
- REGF_SK_REC *tmp = NULL;
/* search for it in the existing list of sd's */
if ( (nk->sec_desc = find_sk_record_by_sec_desc( file, sec_desc )) == NULL ) {
/* not found so add it to the list */
- sk_hbin = find_free_space( file, sk_size );
+ if (!(sk_hbin = find_free_space( file, sk_size ))) {
+ return NULL;
+ }
if ( !(nk->sec_desc = TALLOC_ZERO_P( file->mem_ctx, REGF_SK_REC )) )
return NULL;
nk->sec_desc->ref_count = 0;
/* size value must be self-inclusive */
- nk->sec_desc->size = sec_desc_size(sec_desc) + sizeof(uint32);
-
- DLIST_ADD_END( file->sec_desc_list, nk->sec_desc, tmp );
+ nk->sec_desc->size = ndr_size_security_descriptor(sec_desc, NULL, 0)
+ + sizeof(uint32);
- /* initialize offsets */
+ DLIST_ADD_END( file->sec_desc_list, nk->sec_desc, REGF_SK_REC *);
- nk->sec_desc->prev_sk_off = nk->sec_desc->sk_off;
- nk->sec_desc->next_sk_off = nk->sec_desc->sk_off;
-
- /* now update the offsets for us and the previous sd in the list */
+ /* update the offsets for us and the previous sd in the list.
+ if this is the first record, then just set the next and prev
+ offsets to ourself. */
if ( nk->sec_desc->prev ) {
REGF_SK_REC *prev = nk->sec_desc->prev;
nk->sec_desc->prev_sk_off = prev->hbin_off + prev->hbin->first_hbin_off - HBIN_HDR_SIZE;
- prev->next_sk_off = nk->sk_off;
+ prev->next_sk_off = nk->sec_desc->sk_off;
+
+ /* the end must loop around to the front */
+ nk->sec_desc->next_sk_off = file->sec_desc_list->sk_off;
+
+ /* and first must loop around to the tail */
+ file->sec_desc_list->prev_sk_off = nk->sec_desc->sk_off;
+ } else {
+ nk->sec_desc->prev_sk_off = nk->sec_desc->sk_off;
+ nk->sec_desc->next_sk_off = nk->sec_desc->sk_off;
}
}
- /* dump the reference count */
+ /* bump the reference count +1 */
nk->sk_off = nk->sec_desc->sk_off;
nk->sec_desc->ref_count++;
uint32 namelen;
int i;
- nk->subkeys.hbin = find_free_space( file, lf_size );
+ if (!(nk->subkeys.hbin = find_free_space( file, lf_size ))) {
+ return NULL;
+ }
nk->subkeys.hbin_off = prs_offset( &nk->subkeys.hbin->ps );
nk->subkeys.rec_size = (lf_size-1) ^ 0xFFFFFFFF;
nk->subkeys_off = prs_offset( &nk->subkeys.hbin->ps ) + nk->subkeys.hbin->first_hbin_off - HBIN_HDR_SIZE;
memcpy( nk->subkeys.header, "lf", REC_HDR_SIZE );
nk->subkeys.num_keys = nk->num_subkeys;
- if ( !(nk->subkeys.hashes = TALLOC_ZERO_ARRAY( file->mem_ctx, REGF_HASH_REC, nk->subkeys.num_keys )) )
- return NULL;
+ if (nk->subkeys.num_keys) {
+ if ( !(nk->subkeys.hashes = TALLOC_ZERO_ARRAY( file->mem_ctx, REGF_HASH_REC, nk->subkeys.num_keys )) )
+ return NULL;
+ } else {
+ nk->subkeys.hashes = NULL;
+ }
nk->subkey_index = 0;
/* update the max_bytes_subkey{name,classname} fields */
uint32 vlist_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
int i;
- vlist_hbin = find_free_space( file, vlist_size );
+ if (!(vlist_hbin = find_free_space( file, vlist_size ))) {
+ return NULL;
+ }
nk->values_off = prs_offset( &vlist_hbin->ps ) + vlist_hbin->first_hbin_off - HBIN_HDR_SIZE;
- if ( !(nk->values = TALLOC_ARRAY( file->mem_ctx, REGF_VK_REC, nk->num_values )) )
- return NULL;
+ if (nk->num_values) {
+ if ( !(nk->values = TALLOC_ARRAY( file->mem_ctx, REGF_VK_REC, nk->num_values )) )
+ return NULL;
+ } else {
+ nk->values = NULL;
+ }
/* create the vk records */
for ( i=0; i<nk->num_values; i++ ) {
uint32 vk_size, namelen, datalen;
- REGISTRY_VALUE *r;
+ struct regval_blob *r;
r = regval_ctr_specific_value( values, i );
create_vk_record( file, &nk->values[i], r );
nk->max_bytes_valuename = namelen * 2;
datalen = regval_size( r );
- if ( datalen*2 > nk->max_bytes_value )
- nk->max_bytes_value = datalen * 2;
+ if ( datalen > nk->max_bytes_value )
+ nk->max_bytes_value = datalen;
}
}