#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_PARSE
void rpcbuf_init(RPC_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
{
buffer->size = size;
buffer->string_at_end = size;
prs_init(&buffer->prs, size, ctx, MARSHALL);
buffer->struct_start = prs_offset(&buffer->prs);
}
BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buffer)
{
prs_debug(ps, depth, desc, "prs_rpcbuffer");
depth++;
if (UNMARSHALLING(ps)) {
buffer->size=0;
buffer->string_at_end=0;
if (!prs_uint32("size", ps, depth, &buffer->size))
return False;
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:
prs_mem_free(&buffer->prs);
return ret;
}
}
BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **buffer)
{
uint32 data_p;
data_p = *buffer ? 0xf000baaa : 0;
if ( !prs_uint32("ptr", ps, depth, &data_p ))
return False;
if ( !data_p )
return True;
if ( UNMARSHALLING(ps) ) {
if ( !(*buffer = PRS_ALLOC_MEM(ps, RPC_BUFFER, 1)) )
return False;
} else {
if (!*buffer) {
return True;
}
}
return prs_rpcbuffer( desc, ps, depth, *buffer);
}
BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size)
{
prs_struct *ps;
uint32 extra_space;
uint32 old_offset;
if ( buffer_size == 0x0 )
return True;
if (!buffer) {
return False;
}
ps= &buffer->prs;
if (buffer_size < prs_data_size(ps))
extra_space=0;
else
extra_space = buffer_size - prs_data_size(ps);
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;
}
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;
}
uint32 rpcbuf_get_size(RPC_BUFFER *buffer)
{
return (buffer->size);
}
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
if (!prs_align(ps))
return False;
#endif
buffer->string_at_end = prs_offset(ps);
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;
if (!prs_uint32("offset", ps, depth, &relative_offset))
return False;
}
else {
uint32 old_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;
if (!smb_io_unistr(desc, string, ps, depth))
return False;
if(!prs_set_offset(ps, old_offset))
return False;
}
return True;
}
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;
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++;
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;
}
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;
if (!prs_uint32("offset", ps, depth, &relative_offset))
return False;
} else {
uint32 old_offset;
uint16 *chaine2=NULL;
int l_chaine=0;
int l_chaine2=0;
size_t realloc_size = 0;
*string=NULL;
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);
if (l_chaine > 0) {
realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);
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);
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;
}
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;
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;
if (!prs_uint32("offset", ps, depth, &relative_offset))
return False;
} else {
uint32 old_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;
if (!sec_io_desc(desc, secdesc, ps, depth))
return False;
if(!prs_set_offset(ps, old_offset))
return False;
}
return True;
}
uint32 size_of_relative_string(UNISTR *string)
{
uint32 size=0;
size=str_len_uni(string);
size=size+1;
size=size*2;
size=size+4;
#if 0
#endif
return size;
}