Пример #1
0
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;
  uint32 data_size, start_off, end_off;

  depth++;

  /* check if we have anything to do first */
	
  if ( nk->num_subkeys == 0 )
    return true;

  /* move to the LF record */

  if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
    return false;

  /* backup and get the data_size */
	
  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    return false;
  start_off = hbin->ps.data_offset;
  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &lf->rec_size ))
    return false;

  if(!prs_uint8s("header", &hbin->ps, depth, 
		 lf->header, sizeof(lf->header)))
    return false;
		
  if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
    return false;

  if ( hbin->ps.io ) {
    if ( !(lf->hashes = (REGF_HASH_REC*)zcalloc(sizeof(REGF_HASH_REC), lf->num_keys )) )
      return false;
  }

  for ( i=0; i<lf->num_keys; i++ ) {
    if ( !prs_hash_rec( "hash_rec", &hbin->ps, depth, &lf->hashes[i] ) )
      return false;
  }

  end_off = hbin->ps.data_offset;

  /* data_size must be divisible by 8 and large enough to hold the original record */

  data_size = ((start_off - end_off) & 0xfffffff8 );
  /*  if ( data_size > lf->rec_size )*/
    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->rec_size));*/

  if ( !hbin->ps.io )
    hbin->dirty = true;

  return true;
}
Пример #2
0
static bool next_record( REGF_HBIN *hbin, const char *hdr, bool *eob )
{
  uint8 header[REC_HDR_SIZE] = "";
  uint32 record_size;
  uint32 curr_off, block_size;
  bool found = false;
  prs_struct *ps = &hbin->ps;
	
  curr_off = ps->data_offset;
  if ( curr_off == 0 )
    prs_set_offset( ps, HBIN_HEADER_REC_SIZE );

  /* assume that the current offset is at the reacord header 
     and we need to backup to read the record size */
  curr_off -= sizeof(uint32);

  block_size = ps->buffer_size;
  record_size = 0;
  while ( !found ) 
  {
    curr_off = curr_off+record_size;
    if ( curr_off >= block_size ) 
      break;

    if ( !prs_set_offset( &hbin->ps, curr_off) )
      return false;

    if ( !prs_uint32( "record_size", ps, 0, &record_size ) )
      return false;
    if ( !prs_uint8s("header", ps, 0, header, REC_HDR_SIZE ) )
      return false;

    if ( record_size & 0x80000000 ) {
      /* absolute_value(record_size) */
      record_size = (record_size ^ 0xffffffff) + 1;
    }

    if ( memcmp( header, hdr, REC_HDR_SIZE ) == 0 ) {
      found = true;
      curr_off += sizeof(uint32);
    }
  } 

  /* mark prs_struct as done ( at end ) if no more SK records */
  /* mark end-of-block as true */	
  if ( !found )
  {
    prs_set_offset( &hbin->ps, hbin->ps.buffer_size );
    *eob = true;
    return false;
  }

  if (!prs_set_offset(ps, curr_off))
    return false;

  return true;
}
Пример #3
0
static bool prs_regf_block(const char *desc, prs_struct *ps, 
			   int depth, REGF_FILE *file)
{
  depth++;
	
  if(!prs_uint8s("header", ps, depth, file->header, sizeof(file->header)))
    return false;
	
  /* yes, these values are always identical so store them only once */
	
  if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))
    return false;
  if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))
    return false;

  /* get the modtime */
	
  if ( !prs_set_offset( ps, 0x0c ) )
    return false;
  if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )
    return false;

  /* constants */
	
  if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))
    return false;
  if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))
    return false;
  if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))
    return false;
  if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))
    return false;

  /* get file offsets */
	
  if ( !prs_set_offset( ps, 0x24 ) )
    return false;
  if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))
    return false;
  if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))
    return false;
		
  /* one more constant */
	
  if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))
    return false;
		
  /* get the checksum */
	
  if ( !prs_set_offset( ps, 0x01fc ) )
    return false;
  if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))
    return false;
	
  return true;
}
Пример #4
0
BOOL smb_io_relstr(const char *desc, RPC_BUFFER *buffer, int depth, UNISTR *string)
{
	prs_struct *ps=&buffer->prs;
	
	if (MARSHALLING(ps)) {
		uint32 struct_offset = prs_offset(ps);
		uint32 relative_offset;
		
		buffer->string_at_end -= (size_of_relative_string(string) - 4);
		if(!prs_set_offset(ps, buffer->string_at_end))
			return False;
#if 0	/* JERRY */
		/*
		 * Win2k does not align strings in a buffer
		 * Tested against WinNT 4.0 SP 6a & 2k SP2  --jerry
		 */
		if (!prs_align(ps))
			return False;
#endif
		buffer->string_at_end = prs_offset(ps);
		
		/* write the string */
		if (!smb_io_unistr(desc, string, ps, depth))
			return False;

		if(!prs_set_offset(ps, struct_offset))
			return False;
		
		relative_offset=buffer->string_at_end - buffer->struct_start;
		/* write its offset */
		if (!prs_uint32("offset", ps, depth, &relative_offset))
			return False;
	}
	else {
		uint32 old_offset;
		
		/* read the offset */
		if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end)))
			return False;

		if (buffer->string_at_end == 0)
			return True;

		old_offset = prs_offset(ps);
		if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start))
			return False;

		/* read the string */
		if (!smb_io_unistr(desc, string, ps, depth))
			return False;

		if(!prs_set_offset(ps, old_offset))
			return False;
	}
	return True;
}
Пример #5
0
BOOL smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC **secdesc)
{
	prs_struct *ps= &buffer->prs;

	prs_debug(ps, depth, desc, "smb_io_relsecdesc");
	depth++;

	if (MARSHALLING(ps)) {
		uint32 struct_offset = prs_offset(ps);
		uint32 relative_offset;

		if (! *secdesc) {
			relative_offset = 0;
			if (!prs_uint32("offset", ps, depth, &relative_offset))
				return False;
			return True;
		}
		
		if (*secdesc != NULL) {
			buffer->string_at_end -= sec_desc_size(*secdesc);

			if(!prs_set_offset(ps, buffer->string_at_end))
				return False;
			/* write the secdesc */
			if (!sec_io_desc(desc, secdesc, ps, depth))
				return False;

			if(!prs_set_offset(ps, struct_offset))
				return False;
		}

		relative_offset=buffer->string_at_end - buffer->struct_start;
		/* write its offset */

		if (!prs_uint32("offset", ps, depth, &relative_offset))
			return False;
	} else {
		uint32 old_offset;
		
		/* read the offset */
		if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
			return False;

		old_offset = prs_offset(ps);
		if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
			return False;

		/* read the sd */
		if (!sec_io_desc(desc, secdesc, ps, depth))
			return False;

		if(!prs_set_offset(ps, old_offset))
			return False;
	}
	return True;
}
Пример #6
0
BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buffer)
{
	prs_debug(ps, depth, desc, "prs_rpcbuffer");
	depth++;

	/* reading */
	if (UNMARSHALLING(ps)) {
		buffer->size=0;
		buffer->string_at_end=0;
		
		if (!prs_uint32("size", ps, depth, &buffer->size))
			return False;
					
		/*
		 * JRA. I'm not sure if the data in here is in big-endian format if
		 * the client is big-endian. Leave as default (little endian) for now.
		 */

		if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL))
			return False;

		if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size))
			return False;

		if (!prs_set_offset(&buffer->prs, 0))
			return False;

		if (!prs_set_offset(ps, buffer->size+prs_offset(ps)))
			return False;

		buffer->string_at_end=buffer->size;
		
		return True;
	}
	else {
		BOOL ret = False;

		if (!prs_uint32("size", ps, depth, &buffer->size))
			goto out;

		if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size))
			goto out;

		ret = True;
	out:

		/* We have finished with the data in buffer->prs - free it. */
		prs_mem_free(&buffer->prs);

		return ret;
	}
}
Пример #7
0
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;
  uint32 data_size, start_off, end_off;


  depth++;

  if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
    return false;

  /* backup and get the data_size */
	
  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    return false;
  start_off = hbin->ps.data_offset;
  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &sk->rec_size ))
    return false;

  if (!prs_uint8s("header", ps, depth, sk->header, sizeof(sk->header)))
    return false;
  if ( !prs_uint16( "tag", ps, depth, &tag))
    return false;

  if ( !prs_uint32( "prev_sk_off", ps, depth, &sk->prev_sk_off))
    return false;
  if ( !prs_uint32( "next_sk_off", ps, depth, &sk->next_sk_off))
    return false;
  if ( !prs_uint32( "ref_count", ps, depth, &sk->ref_count))
    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;

  end_off = hbin->ps.data_offset;

  /* data_size must be divisible by 8 and large enough to hold the original record */

  data_size = ((start_off - end_off) & 0xfffffff8 );
  /*  if ( data_size > sk->rec_size )*/
    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, sk->rec_size));*/

  if ( !hbin->ps.io )
    hbin->dirty = true;

  return true;
}
Пример #8
0
static bool prs_hbin_block(const char *desc, prs_struct *ps, 
			   int depth, REGF_HBIN *hbin)
{
  uint32 block_size2;

  depth++;
	
  if(!prs_uint8s("header", ps, depth, hbin->header, sizeof(hbin->header)))
    return false;

  if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))
    return false;

  /* The dosreg.cpp comments say that the block size is at 0x1c.
     According to a WINXP NTUSER.dat file, this is wrong.  The block_size
     is at 0x08 */

  if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))
    return false;

  block_size2 = hbin->block_size;
  prs_set_offset( ps, 0x1c );
  if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))
    return false;

  if ( !ps->io )
    hbin->dirty = true;
	

  return true;
}
Пример #9
0
BOOL prs_copy_all_data_out(char *dst, prs_struct *src)
{
	uint32 len = prs_offset(src);

	if (!len)
		return True;

	prs_set_offset(src, 0);
	return prs_copy_data_out(dst, src, len);
}
Пример #10
0
BOOL smb_io_hdrbuf_post(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, 
				uint32 ptr_hdrbuf, uint32 max_len, uint32 len)
{
	if (!ps->io) {
		/* writing: go back and do a retrospective job.  i hate this */

		uint32 old_offset = prs_offset(ps);

		init_buf_hdr(hdr, max_len, len);
		if(!prs_set_offset(ps, ptr_hdrbuf))
			return False;
		if(!smb_io_hdrbuf(desc, hdr, ps, depth))
			return False;

		if(!prs_set_offset(ps, old_offset))
			return False;
	}

	return True;
}
Пример #11
0
/*******************************************************************
return the contents of a prs_struct in a DATA_BLOB
********************************************************************/
bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
{
	blob->length = prs_data_size(prs);
	blob->data = (uint8 *)TALLOC_ZERO_SIZE(mem_ctx, blob->length);
	
	/* set the pointer at the end of the buffer */
	prs_set_offset( prs, prs_data_size(prs) );

	if (!prs_copy_all_data_out((char *)blob->data, prs))
		return False;
	
	return True;
}
Пример #12
0
BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size)
{
	prs_struct *ps;
	uint32 extra_space;
	uint32 old_offset;
	
	/* if we don't need anything. don't do anything */
	
	if ( buffer_size == 0x0 )
		return True;

	if (!buffer) {
		return False;
	}

	ps= &buffer->prs;

	/* damn, I'm doing the reverse operation of prs_grow() :) */
	if (buffer_size < prs_data_size(ps))
		extra_space=0;
	else	
		extra_space = buffer_size - prs_data_size(ps);

	/*
	 * save the offset and move to the end of the buffer
	 * prs_grow() checks the extra_space against the offset
	 */
	old_offset=prs_offset(ps);	
	prs_set_offset(ps, prs_data_size(ps));
	
	if (!prs_grow(ps, extra_space))
		return False;

	prs_set_offset(ps, old_offset);

	buffer->string_at_end=prs_data_size(ps);

	return True;
}
Пример #13
0
/****************************************************************************
  query the security descriptor for a open file
 ****************************************************************************/
SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum, 
			    TALLOC_CTX *mem_ctx)
{
	char param[8];
	char *rparam=NULL, *rdata=NULL;
	unsigned int rparam_count=0, rdata_count=0;
	prs_struct pd;
	SEC_DESC *psd = NULL;

	SIVAL(param, 0, fnum);
	SIVAL(param, 4, 0x7);

	if (!cli_send_nt_trans(cli, 
			       NT_TRANSACT_QUERY_SECURITY_DESC, 
			       0, 
			       NULL, 0, 0,
			       param, 8, 4,
			       NULL, 0, 0x10000)) {
		DEBUG(1,("Failed to send NT_TRANSACT_QUERY_SECURITY_DESC\n"));
		goto cleanup;
	}


	if (!cli_receive_nt_trans(cli, 
				  &rparam, &rparam_count,
				  &rdata, &rdata_count)) {
		DEBUG(1,("Failed to recv NT_TRANSACT_QUERY_SECURITY_DESC\n"));
		goto cleanup;
	}

	prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL);
	prs_copy_data_in(&pd, rdata, rdata_count);
	prs_set_offset(&pd,0);

	if (!sec_io_desc("sd data", &psd, &pd, 1)) {
		DEBUG(1,("Failed to parse secdesc\n"));
		goto cleanup;
	}

 cleanup:

	SAFE_FREE(rparam);
	SAFE_FREE(rdata);

	prs_mem_free(&pd);
	return psd;
}
Пример #14
0
void rpcbuf_move(RPC_BUFFER *src, RPC_BUFFER **dest)
{
	if ( !src ) {
		*dest = NULL;
		return;
	}

	prs_switch_type( &src->prs, MARSHALL );

	if ( !prs_set_offset(&src->prs, 0) )
		return;

	prs_force_dynamic( &src->prs );
	prs_mem_clear( &src->prs );

	*dest = src;
}
Пример #15
0
BOOL smb_io_hdrbuf_pre(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, uint32 *offset)
{
	(*offset) = prs_offset(ps);
	if (ps->io) {

		/* reading. */

		if(!smb_io_hdrbuf(desc, hdr, ps, depth))
			return False;

	} else {

		/* writing. */

		if(!prs_set_offset(ps, prs_offset(ps) + (sizeof(uint32) * 2)))
			return False;
	}

	return True;
}
Пример #16
0
const REGF_NK_REC* regfi_iterator_cur_subkey(REGFI_ITERATOR* i)
{
  REGF_NK_REC* subkey;
  REGF_HBIN* hbin;
  uint32 nk_offset;

  /* see if there is anything left to report */
  if (!(i->cur_key) || (i->cur_key->subkeys_off==REGF_OFFSET_NONE)
      || (i->cur_subkey >= i->cur_key->num_subkeys))
    return NULL;

  nk_offset = i->cur_key->subkeys.hashes[i->cur_subkey].nk_off;

  /* find the HBIN block which should contain the nk record */
  hbin = lookup_hbin_block(i->f, nk_offset);
  if(!hbin)
  {
    /* XXX: should print out some kind of error message every time here */
    /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing offset [0x%x]\n", 
      i->cur_key->subkeys.hashes[i->cur_subkey].nk_off));*/
    return NULL;
  }
  
  if(!prs_set_offset(&hbin->ps, 
		     HBIN_HDR_SIZE + nk_offset - hbin->first_hbin_off))
    return NULL;
		
  if(!(subkey = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC))))
    return NULL;

  if(!hbin_prs_key(i->f, hbin, subkey))
  {
    regfi_key_free(subkey);
    return NULL;
  }

  return subkey;
}
Пример #17
0
static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, NET_USER_INFO_3 *info3)
{
	uint8 *info3_ndr;
	size_t len = response->length - sizeof(struct winbindd_response);
	prs_struct ps;
	if (len > 0) {
		info3_ndr = response->extra_data;
		if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) {
			return NT_STATUS_NO_MEMORY;
		}
		prs_copy_data_in(&ps, (char *)info3_ndr, len);
		prs_set_offset(&ps,0);
		if (!net_io_user_info3("", info3, &ps, 1, 3)) {
			DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n"));
			return NT_STATUS_UNSUCCESSFUL;
		}
		prs_mem_free(&ps);

		return NT_STATUS_OK;
	} else {
		DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}
}
Пример #18
0
BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
{
	uint32 old_offset;
	uint32 max_offset = 0; /* after we're done, move offset to end */
	uint32 tmp_offset = 0;
	
	SEC_DESC *psd;

	if (ppsd == NULL)
		return False;

	psd = *ppsd;

	if (psd == NULL) {
		if(UNMARSHALLING(ps)) {
			if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
				return False;
			*ppsd = psd;
		} else {
			/* Marshalling - just ignore. */
			return True;
		}
	}

	prs_debug(ps, depth, desc, "sec_io_desc");
	depth++;

#if 0	
	/*
	 * if alignment is needed, should be done by the the 
	 * caller.  Not here.  This caused me problems when marshalling
	 * printer info into a buffer.   --jerry
	 */
	if(!prs_align(ps))
		return False;
#endif
	
	/* start of security descriptor stored for back-calc offset purposes */
	old_offset = prs_offset(ps);

	if(!prs_uint16("revision ", ps, depth, &psd->revision))
		return False;

	if(!prs_uint16("type     ", ps, depth, &psd->type))
		return False;

	if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
		return False;

	if(!prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid))
		return False;

	if(!prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl))
		return False;

	if(!prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
		return False;

	max_offset = MAX(max_offset, prs_offset(ps));

	if (psd->off_owner_sid != 0) {

		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
			return False;

		if (UNMARSHALLING(ps)) {
			/* reading */
			if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
				return False;
		}

		if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
			return False;

		max_offset = MAX(max_offset, prs_offset(ps));

		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}

	if (psd->off_grp_sid != 0) {

		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
			return False;

		if (UNMARSHALLING(ps)) {
			/* reading */
			if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
				return False;
		}

		if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
			return False;
			
		max_offset = MAX(max_offset, prs_offset(ps));

		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}

	if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_sacl))
			return False;
		if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
			return False;
		max_offset = MAX(max_offset, prs_offset(ps));
		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}


	if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_dacl))
			return False;
		if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
			return False;
		max_offset = MAX(max_offset, prs_offset(ps));
		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}

	if(!prs_set_offset(ps, max_offset))
		return False;
	return True;
}
Пример #19
0
static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *values )
{
	DEVICEMODE	*devmode;
	prs_struct	prs;
	uint32		offset;
	UNISTR2		data;
	char 		*p;
	uint32 printer_status = PRINTER_STATUS_OK;
	
	regval_ctr_addvalue( values, "Attributes",       REG_DWORD, (char*)&info2->attributes,       sizeof(info2->attributes) );
	regval_ctr_addvalue( values, "Priority",         REG_DWORD, (char*)&info2->priority,         sizeof(info2->attributes) );
	regval_ctr_addvalue( values, "ChangeID",         REG_DWORD, (char*)&info2->changeid,         sizeof(info2->changeid) );
	regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
	
	/* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
	regval_ctr_addvalue( values, "Status",           REG_DWORD, (char*)&printer_status,          sizeof(info2->status) );

	regval_ctr_addvalue( values, "StartTime",        REG_DWORD, (char*)&info2->starttime,        sizeof(info2->starttime) );
	regval_ctr_addvalue( values, "UntilTime",        REG_DWORD, (char*)&info2->untiltime,        sizeof(info2->untiltime) );

	/* strip the \\server\ from this string */
	if ( !(p = strrchr( info2->printername, '\\' ) ) )
		p = info2->printername;
	else
		p++;
	init_unistr2( &data, p, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Print Processor",  REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

		
	/* use a prs_struct for converting the devmode and security 
	   descriptor to REG_BINARY */
	
	prs_init( &prs, RPC_MAX_PDU_FRAG_LEN, values, MARSHALL);

	/* stream the device mode */
		
	if ( (devmode = construct_dev_mode( info2->sharename )) != NULL ) {
		if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
			offset = prs_offset( &prs );
			regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
		}
	}
		
	prs_mem_clear( &prs );
	prs_set_offset( &prs, 0 );
		
	/* stream the printer security descriptor */
	
	if ( info2->secdesc_buf && info2->secdesc_buf->len )  {
		if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
			offset = prs_offset( &prs );
			regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&prs), offset );
		}
	}

	prs_mem_free( &prs );

	return;		
}
Пример #20
0
static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
{
    uint32 ss_padding_len = 0;
    size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
                      (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;

    if(!p->pipe_bound) {
        DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
        set_incoming_fault(p);
        return False;
    }

    /*
     * Check if we need to do authentication processing.
     * This is only done on requests, not binds.
     */

    /*
     * Read the RPC request header.
     */

    if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
        DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
        set_incoming_fault(p);
        return False;
    }

    switch(p->auth.auth_type) {
    case PIPE_AUTH_TYPE_NONE:
        break;

    case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
    case PIPE_AUTH_TYPE_NTLMSSP:
    {
        NTSTATUS status;
        if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
            DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
            DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
            set_incoming_fault(p);
            return False;
        }
        break;
    }

    case PIPE_AUTH_TYPE_SCHANNEL:
        if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
            DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
            set_incoming_fault(p);
            return False;
        }
        break;

    default:
        DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
        set_incoming_fault(p);
        return False;
    }

    /* Now we've done the sign/seal we can remove any padding data. */
    if (data_len > ss_padding_len) {
        data_len -= ss_padding_len;
    }

    /*
     * Check the data length doesn't go over the 15Mb limit.
     * increased after observing a bug in the Windows NT 4.0 SP6a
     * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
     * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002
     */

    if(prs_offset(&p->in_data.data) + data_len > MAX_RPC_DATA_SIZE) {
        DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
                 (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
        set_incoming_fault(p);
        return False;
    }

    /*
     * Append the data portion into the buffer and return.
     */

    if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
        DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
                 (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
        set_incoming_fault(p);
        return False;
    }

    if(p->hdr.flags & RPC_FLG_LAST) {
        bool ret = False;
        /*
         * Ok - we finally have a complete RPC stream.
         * Call the rpc command to process it.
         */

        /*
         * Ensure the internal prs buffer size is *exactly* the same
         * size as the current offset.
         */

        if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
            DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
            set_incoming_fault(p);
            return False;
        }

        /*
         * Set the parse offset to the start of the data and set the
         * prs_struct to UNMARSHALL.
         */

        prs_set_offset(&p->in_data.data, 0);
        prs_switch_type(&p->in_data.data, UNMARSHALL);

        /*
         * Process the complete data stream here.
         */

        free_pipe_context(p);

        if(pipe_init_outgoing_data(p)) {
            ret = api_pipe_request(p);
        }

        free_pipe_context(p);

        /*
         * We have consumed the whole data stream. Set back to
         * marshalling and set the offset back to the start of
         * the buffer to re-use it (we could also do a prs_mem_free()
         * and then re_init on the next start of PDU. Not sure which
         * is best here.... JRA.
         */

        prs_switch_type(&p->in_data.data, MARSHALL);
        prs_set_offset(&p->in_data.data, 0);
        return ret;
    }

    return True;
}
Пример #21
0
/*******************************************************************
 read a VK record which is contained in the HBIN block stored 
 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)
{
  int i;
  uint32 record_size;

  depth++;
  
  /* check if we have anything to do first */
  if(nk->num_values == 0)
    return true;
  	
  if(hbin->ps.io)
  {
    if (!(nk->values = (REGF_VK_REC*)zcalloc(sizeof(REGF_VK_REC), 
					      nk->num_values )))
      return false;
  }
  
  /* convert the offset to something relative to this HBIN block */
  if (!prs_set_offset(&hbin->ps, 
		      nk->values_off
		      + HBIN_HDR_SIZE
		      - hbin->first_hbin_off
		      - sizeof(uint32)))
  { return false; }

  if ( !hbin->ps.io ) 
  { 
    record_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
    record_size = (record_size - 1) ^ 0xFFFFFFFF;
  }

  if ( !prs_uint32( "record_size", &hbin->ps, depth, &record_size ) )
    return false;
  	
  for ( i=0; i<nk->num_values; i++ ) 
  {
    if ( !prs_uint32( "vk_off", &hbin->ps, depth, &nk->values[i].rec_off ) )
      return false;
  }

  for ( i=0; i<nk->num_values; i++ ) 
  {
    REGF_HBIN *sub_hbin = hbin;
    uint32 new_offset;
	
    if ( !hbin_contains_offset( hbin, nk->values[i].rec_off ) ) 
    {
      sub_hbin = lookup_hbin_block( file, nk->values[i].rec_off );
      if ( !sub_hbin ) 
      {
	/*DEBUG(0,("hbin_prs_vk_records: Failed to find HBIN block containing offset [0x%x]\n", 
	  nk->values[i].hbin_off));*/
	return false;
      }
    }
  	
    new_offset = nk->values[i].rec_off 
      + HBIN_HDR_SIZE 
      - sub_hbin->first_hbin_off;

    if (!prs_set_offset(&sub_hbin->ps, new_offset))
      return false;
    if (!hbin_prs_vk_rec("vk_rec", sub_hbin, depth, &nk->values[i], file))
      return false;
  }

  if ( !hbin->ps.io )
    hbin->dirty = true;

  return true;
}
Пример #22
0
BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16 **string)
{
	UNISTR chaine;
	
	prs_struct *ps=&buffer->prs;
	
	if (MARSHALLING(ps)) {
		uint32 struct_offset = prs_offset(ps);
		uint32 relative_offset;
		uint16 *p;
		uint16 *q;
		uint16 zero=0;
		p=*string;
		q=*string;

		/* first write the last 0 */
		buffer->string_at_end -= 2;
		if(!prs_set_offset(ps, buffer->string_at_end))
			return False;

		if(!prs_uint16("leading zero", ps, depth, &zero))
			return False;

		while (p && (*p!=0)) {	
			while (*q!=0)
				q++;

			/* Yes this should be malloc not talloc. Don't change. */

			chaine.buffer = (uint16 *)
				SMB_MALLOC((q-p+1)*sizeof(uint16));
			if (chaine.buffer == NULL)
				return False;

			memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16));

			buffer->string_at_end -= (q-p+1)*sizeof(uint16);

			if(!prs_set_offset(ps, buffer->string_at_end)) {
				SAFE_FREE(chaine.buffer);
				return False;
			}

			/* write the string */
			if (!smb_io_unistr(desc, &chaine, ps, depth)) {
				SAFE_FREE(chaine.buffer);
				return False;
			}
			q++;
			p=q;

			SAFE_FREE(chaine.buffer);
		}
		
		if(!prs_set_offset(ps, struct_offset))
			return False;
		
		relative_offset=buffer->string_at_end - buffer->struct_start;
		/* write its offset */
		if (!prs_uint32("offset", ps, depth, &relative_offset))
			return False;

	} else {

		/* UNMARSHALLING */

		uint32 old_offset;
		uint16 *chaine2=NULL;
		int l_chaine=0;
		int l_chaine2=0;
		size_t realloc_size = 0;

		*string=NULL;
				
		/* read the offset */
		if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
			return False;

		old_offset = prs_offset(ps);
		if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
			return False;
	
		do {
			if (!smb_io_unistr(desc, &chaine, ps, depth))
				return False;
			
			l_chaine=str_len_uni(&chaine);
			
			/* we're going to add two more bytes here in case this
			   is the last string in the array and we need to add 
			   an extra NULL for termination */
			if (l_chaine > 0) {
				realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);

				/* Yes this should be realloc - it's freed below. JRA */

				if((chaine2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) {
					return False;
				}
				memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16));
				l_chaine2+=l_chaine+1;
			}
		
		} while(l_chaine!=0);
		
		/* the end should be bould NULL terminated so add 
		   the second one here */
		if (chaine2)
		{
			chaine2[l_chaine2] = '\0';
			*string=(uint16 *)TALLOC_MEMDUP(prs_get_mem_context(ps),chaine2,realloc_size);
			if (!*string) {
				return False;
			}
			SAFE_FREE(chaine2);
		}

		if(!prs_set_offset(ps, old_offset))
			return False;
	}
	return True;
}
Пример #23
0
static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata,
			  uint32 fragment_start, int len, int auth_len, uint8 pkt_type,
			  int *pauth_padding_len)
{
	
	/*
	 * The following is that length of the data we must sign or seal.
	 * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN
	 * preceeding the auth_data.
	 */

	int data_len = len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;

	/*
	 * The start of the data to sign/seal is just after the RPC headers.
	 */
	char *reply_data = prs_data_p(rdata) + fragment_start + RPC_HEADER_LEN + RPC_HDR_REQ_LEN;

	RPC_HDR_AUTH rhdr_auth; 

	char *dp = prs_data_p(rdata) + fragment_start + len -
		RPC_HDR_AUTH_LEN - auth_len;
	prs_struct auth_verf;

	*pauth_padding_len = 0;

	if (auth_len == 0) {
		if (cli->pipe_auth_flags == 0) {
			/* move along, nothing to see here */
			return True;
		}

		DEBUG(2, ("No authenticaton header recienved on reply, but this pipe is authenticated\n"));
		return False;
	}

	DEBUG(5,("rpc_auth_pipe: pkt_type: %d len: %d auth_len: %d NTLMSSP %s schannel %s sign %s seal %s \n",
		 pkt_type, len, auth_len, 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NETSEC), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL)));

	if (dp - prs_data_p(rdata) > prs_data_size(rdata)) {
		DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n"));
		return False;
	}

	DEBUG(10,("rpc_auth_pipe: packet:\n"));
	dump_data(100, dp, auth_len);

	prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL);
	
	/* The endinness must be preserved. JRA. */
	prs_set_endian_data( &auth_verf, rdata->bigendian_data);
	
	/* Point this new parse struct at the auth section of the main 
	   parse struct - rather than copying it.  Avoids needing to
	   free it on every error
	*/
	prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */);
	prs_set_offset(&auth_verf, 0);

	{
		int auth_type;
		int auth_level;
		if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) {
			DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n"));
			return False;
		}

		/* Let the caller know how much padding at the end of the data */
		*pauth_padding_len = rhdr_auth.padding;
		
		/* Check it's the type of reply we were expecting to decode */

		get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
		if (rhdr_auth.auth_type != auth_type) {
			DEBUG(0, ("BAD auth type %d (should be %d)\n",
				  rhdr_auth.auth_type, auth_type));
			return False;
		}
		
		if (rhdr_auth.auth_level != auth_level) {
			DEBUG(0, ("BAD auth level %d (should be %d)\n", 
				  rhdr_auth.auth_level, auth_level));
			return False;
		}
	}

	if (pkt_type == RPC_BINDACK) {
		if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
			/* copy the next auth_len bytes into a buffer for 
			   later use */

			DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len);
			BOOL store_ok;

			/* save the reply away, for use a little later */
			prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len);

			store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state, 
									   ntlmssp_verf)));

			data_blob_free(&ntlmssp_verf);
			return store_ok;
		} 
		else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
			/* nothing to do here - we don't seem to be able to 
			   validate the bindack based on VL's comments */
			return True;
		}
	}
	
	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
		NTSTATUS nt_status;
		DATA_BLOB sig;
		if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) ||
		    (cli->pipe_auth_flags & AUTH_PIPE_SEAL)) {
			if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) {
				DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len));
				return False;
			}
			sig = data_blob(NULL, auth_len);
			prs_copy_data_out((char *)sig.data, &auth_verf, auth_len);
		}
	
		/*
		 * Unseal any sealed data in the PDU, not including the
		 * 8 byte auth_header or the auth_data.
		 */

		/*
		 * Now unseal and check the auth verifier in the auth_data at
		 * the end of the packet. 
		 */

		if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
			if (data_len < 0) {
				DEBUG(1, ("Can't unseal - data_len < 0!!\n"));
				return False;
			}
			nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state, 
								 (unsigned char *)reply_data, data_len,
								 &sig);
		} 
		else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
			nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state, 
								(const unsigned char *)reply_data, data_len,
								&sig);
		}

		data_blob_free(&sig);

		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(0, ("rpc_auth_pipe: could not validate "
				  "incoming NTLMSSP packet!\n"));
			return False;
		}
	}

	if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		RPC_AUTH_NETSEC_CHK chk;

		if (auth_len != RPC_AUTH_NETSEC_CHK_LEN) {
			DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len));
			return False;
		}

		if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", 
						&chk, &auth_verf, 0)) {
			DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling "
				  "RPC_AUTH_NETSECK_CHK failed\n"));
			return False;
		}

		if (!netsec_decode(&cli->auth_info,
				   cli->pipe_auth_flags,
				   SENDER_IS_ACCEPTOR,
				   &chk, reply_data, data_len)) {
			DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n"));
			return False;
		}

		cli->auth_info.seq_num++;

	}
	return True;
}
Пример #24
0
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;
  prs_struct *ps = &hbin->ps;
  uint32 data_size, start_off, end_off;

  depth++;

  /* backup and get the data_size */
	
  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    return false;
  start_off = hbin->ps.data_offset;
  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &vk->rec_size ))
    return false;

  if ( !prs_uint8s("header", ps, depth, vk->header, sizeof( vk->header )) )
    return false;

  if ( !hbin->ps.io )
    name_length = strlen(vk->valuename);

  if ( !prs_uint16( "name_length", ps, depth, &name_length ))
    return false;
  if ( !prs_uint32( "data_size", ps, depth, &vk->data_size ))
    return false;
  if ( !prs_uint32( "data_off", ps, depth, &vk->data_off ))
    return false;
  if ( !prs_uint32( "type", ps, depth, &vk->type))
    return false;
  if ( !prs_uint16( "flag", ps, depth, &vk->flag))
    return false;

  offset = ps->data_offset;
  offset += 2;	/* skip 2 bytes */
  prs_set_offset( ps, offset );

  /* get the name */

  if ( vk->flag&VK_FLAG_NAME_PRESENT ) {

    if ( hbin->ps.io ) {
      if ( !(vk->valuename = (char*)zcalloc(sizeof(char), name_length+1 )))
	return false;
    }
    if ( !prs_uint8s("name", ps, depth, 
		     (uint8*)vk->valuename, name_length) )
      return false;
  }

  end_off = hbin->ps.data_offset;

  /* get the data if necessary */

  if ( vk->data_size != 0 ) 
  {
    /* the data is stored in the offset if the size <= 4 */
    if ( !(vk->data_size & VK_DATA_IN_OFFSET) ) 
    {
      REGF_HBIN *hblock = hbin;
      uint32 data_rec_size;

      if ( hbin->ps.io ) 
      {
	if ( !(vk->data = (uint8*)zcalloc(sizeof(uint8), vk->data_size) ) )
	  return false;
      }

      /* this data can be in another hbin */
      if ( !hbin_contains_offset( hbin, vk->data_off ) ) 
      {
	if ( !(hblock = lookup_hbin_block( file, vk->data_off )) )
	  return false;
      }
      if (!(prs_set_offset(&hblock->ps, 
			   (vk->data_off
			    + HBIN_HDR_SIZE
			    - hblock->first_hbin_off)
			   - sizeof(uint32))))
      {	return false; }

      if ( !hblock->ps.io ) 
      {
	data_rec_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
	data_rec_size = ( data_rec_size - 1 ) ^ 0xFFFFFFFF;
      }
      if ( !prs_uint32( "data_rec_size", &hblock->ps, depth, &data_rec_size ))
	return false;
      if(!prs_uint8s("data", &hblock->ps, depth, 
		     vk->data, vk->data_size))
	return false;

      if ( !hblock->ps.io )
	hblock->dirty = true;
    }
    else 
    {
      if(!(vk->data = zcalloc(sizeof(uint8), 4)))
	return false;
      SIVAL( vk->data, 0, vk->data_off );
    }
		
  }

  /* data_size must be divisible by 8 and large enough to hold the original record */

  data_size = ((start_off - end_off ) & 0xfffffff8 );
  /* XXX: should probably print a warning here */
  /*if ( data_size !=  vk->rec_size )
    DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->rec_size));*/

  if ( !hbin->ps.io )
    hbin->dirty = true;

  return true;
}
Пример #25
0
static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
{
	BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
	size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
				(auth_verify ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;

	if(!p->pipe_bound) {
		DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
		set_incoming_fault(p);
		return False;
	}

	/*
	 * Check if we need to do authentication processing.
	 * This is only done on requests, not binds.
	 */

	/*
	 * Read the RPC request header.
	 */

	if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
		DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
		set_incoming_fault(p);
		return False;
	}

	if(p->ntlmssp_auth_validated && !api_pipe_auth_process(p, rpc_in_p)) {
		DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
		set_incoming_fault(p);
		return False;
	}

	if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) {

		/*
		 * Authentication _was_ requested and it already failed.
		 */

		DEBUG(0,("process_request_pdu: RPC request received on pipe %s "
			 "where authentication failed. Denying the request.\n",
			 p->name));
		set_incoming_fault(p);
		return False;
	}

	if (p->netsec_auth_validated && !api_pipe_netsec_process(p, rpc_in_p)) {
		DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
		set_incoming_fault(p);
		return False;
	}

	/*
	 * Check the data length doesn't go over the 15Mb limit.
	 * increased after observing a bug in the Windows NT 4.0 SP6a
	 * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
	 * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002
	 */
	
	if(prs_offset(&p->in_data.data) + data_len > 15*1024*1024) {
		DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
				(unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
		set_incoming_fault(p);
		return False;
	}

	/*
	 * Append the data portion into the buffer and return.
	 */

	if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
		DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
				(unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
		set_incoming_fault(p);
		return False;
	}

	if(p->hdr.flags & RPC_FLG_LAST) {
		BOOL ret = False;
		/*
		 * Ok - we finally have a complete RPC stream.
		 * Call the rpc command to process it.
		 */

		/*
		 * Ensure the internal prs buffer size is *exactly* the same
		 * size as the current offset.
		 */

 		if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data)))
		{
			DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
			set_incoming_fault(p);
			return False;
		}

		/*
		 * Set the parse offset to the start of the data and set the
		 * prs_struct to UNMARSHALL.
		 */

		prs_set_offset(&p->in_data.data, 0);
		prs_switch_type(&p->in_data.data, UNMARSHALL);

		/*
		 * Process the complete data stream here.
		 */

		free_pipe_context(p);

		if(pipe_init_outgoing_data(p))
			ret = api_pipe_request(p);

		free_pipe_context(p);

		/*
		 * We have consumed the whole data stream. Set back to
		 * marshalling and set the offset back to the start of
		 * the buffer to re-use it (we could also do a prs_mem_free()
		 * and then re_init on the next start of PDU. Not sure which
		 * is best here.... JRA.
		 */

		prs_switch_type(&p->in_data.data, MARSHALL);
		prs_set_offset(&p->in_data.data, 0);
		return ret;
	}

	return True;
}
Пример #26
0
static bool prs_nk_rec( const char *desc, prs_struct *ps, 
			int depth, REGF_NK_REC *nk )
{
  uint16 class_length, name_length;
  uint32 start;
  uint32 data_size, start_off, end_off;
  uint32 unknown_off = REGF_OFFSET_NONE;

  nk->hbin_off = ps->data_offset;
  start = nk->hbin_off;
	
  depth++;
	
  /* back up and get the data_size */	
  if ( !prs_set_offset( ps, ps->data_offset-sizeof(uint32)) )
    return false;
  start_off = ps->data_offset;
  if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))
    return false;
	
  if (!prs_uint8s("header", ps, depth, nk->header, sizeof(nk->header)))
    return false;
		
  if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))
    return false;
  if ( !smb_io_time( "mtime", &nk->mtime, ps, depth ))
    return false;
		
  if ( !prs_set_offset( ps, start+0x0010 ) )
    return false;
  if ( !prs_uint32( "parent_off", ps, depth, &nk->parent_off ))
    return false;
  if ( !prs_uint32( "num_subkeys", ps, depth, &nk->num_subkeys ))
    return false;
		
  if ( !prs_set_offset( ps, start+0x001c ) )
    return false;
  if ( !prs_uint32( "subkeys_off", ps, depth, &nk->subkeys_off ))
    return false;
  if ( !prs_uint32( "unknown_off", ps, depth, &unknown_off) )
    return false;
		
  if ( !prs_set_offset( ps, start+0x0024 ) )
    return false;
  if ( !prs_uint32( "num_values", ps, depth, &nk->num_values ))
    return false;
  if ( !prs_uint32( "values_off", ps, depth, &nk->values_off ))
    return false;
  if ( !prs_uint32( "sk_off", ps, depth, &nk->sk_off ))
    return false;
  if ( !prs_uint32( "classname_off", ps, depth, &nk->classname_off ))
    return false;

  if (!prs_uint32("max_bytes_subkeyname", ps, depth, &nk->max_bytes_subkeyname))
    return false;
  if ( !prs_uint32( "max_bytes_subkeyclassname", ps, 
		    depth, &nk->max_bytes_subkeyclassname))
  { return false; }
  if ( !prs_uint32( "max_bytes_valuename", ps, depth, &nk->max_bytes_valuename))
    return false;
  if ( !prs_uint32( "max_bytes_value", ps, depth, &nk->max_bytes_value))
    return false;
  if ( !prs_uint32( "unknown index", ps, depth, &nk->unk_index))
    return false;

  name_length = nk->keyname ? strlen(nk->keyname) : 0 ;
  class_length = nk->classname ? strlen(nk->classname) : 0 ;
  if ( !prs_uint16( "name_length", ps, depth, &name_length ))
    return false;
  if ( !prs_uint16( "class_length", ps, depth, &class_length ))
    return false;	
		
  if ( class_length ) 
  {
    /* XXX: why isn't this parsed? */
    ;;
  }
	
  if ( name_length ) 
  {
    if(ps->io && !(nk->keyname = (char*)zcalloc(sizeof(char), name_length+1)))
	return false;

    if(!prs_uint8s("name", ps, depth, (uint8*)nk->keyname, name_length))
      return false;

    if(ps->io)
      nk->keyname[name_length] = '\0';
  }

  end_off = ps->data_offset;

  /* data_size must be divisible by 8 and large enough to hold 
     the original record */

  data_size = ((start_off - end_off) & 0xfffffff8 );
  /*if ( data_size > nk->rec_size )
      DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));*/

  if ( !ps->io )
    nk->hbin->dirty = true;
  
  return true;
}
Пример #27
0
static REGF_HBIN* read_hbin_block( REGF_FILE *file, off_t offset )
{
  REGF_HBIN *hbin;
  uint32 record_size, curr_off, block_size, header=0;
	
  if ( !(hbin = (REGF_HBIN*)zalloc(sizeof(REGF_HBIN))) ) 
    return NULL;
  hbin->file_off = offset;
  hbin->free_off = -1;
		
  if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )
    return NULL;
	
  if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )
    return NULL;	

  /* this should be the same thing as hbin->block_size but just in case */

  block_size = hbin->ps.buffer_size;

  /* Find the available free space offset.  Always at the end,
     so walk the record list and stop when you get to the end.
     The end is defined by a record header of 0xffffffff.  The 
     previous 4 bytes contains the amount of free space remaining 
     in the hbin block. */

  /* remember that the record_size is in the 4 bytes preceeding the record itself */

  if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE-sizeof(uint32) ) )
    return false;

  record_size = 0;
  curr_off = hbin->ps.data_offset;
  while ( header != 0xffffffff ) {
    /* not done yet so reset the current offset to the 
       next record_size field */

    curr_off = curr_off+record_size;

    /* for some reason the record_size of the last record in
       an hbin block can extend past the end of the block
       even though the record fits within the remaining 
       space....aaarrrgggghhhhhh */

    if ( curr_off >= block_size ) {
      record_size = -1;
      curr_off = -1;
      break;
    }

    if ( !prs_set_offset( &hbin->ps, curr_off) )
      return false;

    if ( !prs_uint32( "rec_size", &hbin->ps, 0, &record_size ) )
      return false;
    if ( !prs_uint32( "header", &hbin->ps, 0, &header ) )
      return false;
		
    assert( record_size != 0 );

    if ( record_size & 0x80000000 ) {
      /* absolute_value(record_size) */
      record_size = (record_size ^ 0xffffffff) + 1;
    }
  }

  /* save the free space offset */

  if ( header == 0xffffffff ) {

    /* account for the fact that the curr_off is 4 bytes behind the actual 
       record header */

    hbin->free_off = curr_off + sizeof(uint32);
    hbin->free_size = record_size;
  }

  /*DEBUG(10,("read_hbin_block: free space offset == 0x%x\n", hbin->free_off));*/

  if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE )  )
    return false;
	
  return hbin;
}