X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source%2Frpc_parse%2Fparse_prs.c;h=b22b1faa3fba6ca4a6dec3c9978662af74870c2a;hb=5c6c8e1fe93;hp=088c8f08fbe3398ea8b1291b2baba96fad7fdec6;hpb=4576e6843b67c5919823307a196b1582b78fdeaf;p=samba.git diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c index 088c8f08fbe..b22b1faa3fb 100644 --- a/source/rpc_parse/parse_prs.c +++ b/source/rpc_parse/parse_prs.c @@ -8,7 +8,7 @@ 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, @@ -17,8 +17,7 @@ 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 . */ #include "includes.h" @@ -123,6 +122,10 @@ BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io) /******************************************************************* Delete the memory in a parse structure - if we own it. + + NOTE: Contrary to the somewhat confusing naming, this function is not + intended for freeing memory allocated by prs_alloc_mem(). That memory + is attached to the talloc context given by ps->mem_ctx. ********************************************************************/ void prs_mem_free(prs_struct *ps) @@ -156,9 +159,10 @@ char *prs_alloc_mem(prs_struct *ps, size_t size, unsigned int count) { char *ret = NULL; - if (size) { + if (size && count) { /* We can't call the type-safe version here. */ - ret = _talloc_zero_array(ps->mem_ctx, size, count, "parse_prs"); + ret = (char *)_talloc_zero_array(ps->mem_ctx, size, count, + "parse_prs"); } return ret; } @@ -207,16 +211,21 @@ BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize) return prs_force_grow(ps, newsize - ps->buffer_size); if (newsize < ps->buffer_size) { - char *new_data_p = SMB_REALLOC(ps->data_p, newsize); - /* if newsize is zero, Realloc acts like free() & returns NULL*/ - if (new_data_p == NULL && newsize != 0) { - DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n", - (unsigned int)newsize)); - DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno))); - return False; - } - ps->data_p = new_data_p; ps->buffer_size = newsize; + + /* newsize == 0 acts as a free and set pointer to NULL */ + if (newsize == 0) { + SAFE_FREE(ps->data_p); + } else { + ps->data_p = (char *)SMB_REALLOC(ps->data_p, newsize); + + if (ps->data_p == NULL) { + DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n", + (unsigned int)newsize)); + DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno))); + return False; + } + } } return True; @@ -230,7 +239,6 @@ BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize) BOOL prs_grow(prs_struct *ps, uint32 extra_space) { uint32 new_size; - char *new_data; ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space); @@ -261,11 +269,11 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space) new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space); - if((new_data = SMB_MALLOC(new_size)) == NULL) { + if((ps->data_p = (char *)SMB_MALLOC(new_size)) == NULL) { DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size)); return False; } - memset(new_data, '\0', (size_t)new_size ); + memset(ps->data_p, '\0', (size_t)new_size ); } else { /* * If the current buffer size is bigger than the space needed, just @@ -273,16 +281,15 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space) */ new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space); - if ((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) { + if ((ps->data_p = (char *)SMB_REALLOC(ps->data_p, new_size)) == NULL) { DEBUG(0,("prs_grow: Realloc failure for size %u.\n", (unsigned int)new_size)); return False; } - memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); + memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); } ps->buffer_size = new_size; - ps->data_p = new_data; return True; } @@ -296,7 +303,6 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space) BOOL prs_force_grow(prs_struct *ps, uint32 extra_space) { uint32 new_size = ps->buffer_size + extra_space; - char *new_data; if(!UNMARSHALLING(ps) || !ps->is_dynamic) { DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n", @@ -304,16 +310,15 @@ BOOL prs_force_grow(prs_struct *ps, uint32 extra_space) return False; } - if((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) { + if((ps->data_p = (char *)SMB_REALLOC(ps->data_p, new_size)) == NULL) { DEBUG(0,("prs_force_grow: Realloc failure for size %u.\n", (unsigned int)new_size)); return False; } - memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); + memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size)); ps->buffer_size = new_size; - ps->data_p = new_data; return True; } @@ -606,12 +611,12 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) if (q == NULL) return False; - if (UNMARSHALLING(ps)) + if (UNMARSHALLING(ps)) *data8 = CVAL(q,0); else SCVAL(q,0,*data8); - DEBUG(5,("%s%04x %s: %02x\n", tab_depth(depth), ps->data_offset, name, *data8)); + DEBUG(5,("%s%04x %s: %02x\n", tab_depth(depth), ps->data_offset, name, *data8)); ps->data_offset += 1; @@ -623,9 +628,10 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) ********************************************************************/ BOOL prs_pointer( const char *name, prs_struct *ps, int depth, - void **data, size_t data_size, + void *dta, size_t data_size, BOOL(*prs_fn)(const char*, prs_struct*, int, void*) ) { + void ** data = (void **)dta; uint32 data_p; /* output f000baaa to stream if the pointer is non-zero. */ @@ -641,8 +647,12 @@ BOOL prs_pointer( const char *name, prs_struct *ps, int depth, return True; if (UNMARSHALLING(ps)) { - if ( !(*data = PRS_ALLOC_MEM_VOID(ps, data_size)) ) - return False; + if (data_size) { + if ( !(*data = PRS_ALLOC_MEM(ps, char, data_size)) ) + return False; + } else { + *data = NULL; + } } return prs_fn(name, ps, depth, *data); @@ -707,6 +717,35 @@ BOOL prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32) return True; } +/******************************************************************* + Stream an int32. + ********************************************************************/ + +BOOL prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32) +{ + char *q = prs_mem_get(ps, sizeof(int32)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) + *data32 = RIVALS(q,0); + else + *data32 = IVALS(q,0); + } else { + if (ps->bigendian_data) + RSIVALS(q,0,*data32); + else + SIVALS(q,0,*data32); + } + + DEBUG(5,("%s%04x %s: %08x\n", tab_depth(depth), ps->data_offset, name, *data32)); + + ps->data_offset += sizeof(int32); + + return True; +} + /******************************************************************* Stream a NTSTATUS ********************************************************************/ @@ -737,6 +776,37 @@ BOOL prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status) return True; } +/******************************************************************* + Stream a DCE error code + ********************************************************************/ + +BOOL prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status) +{ + char *q = prs_mem_get(ps, sizeof(uint32)); + if (q == NULL) + return False; + + if (UNMARSHALLING(ps)) { + if (ps->bigendian_data) + *status = NT_STATUS(RIVAL(q,0)); + else + *status = NT_STATUS(IVAL(q,0)); + } else { + if (ps->bigendian_data) + RSIVAL(q,0,NT_STATUS_V(*status)); + else + SIVAL(q,0,NT_STATUS_V(*status)); + } + + DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name, + dcerpc_errstr(NT_STATUS_V(*status)))); + + ps->data_offset += sizeof(uint32); + + return True; +} + + /******************************************************************* Stream a WERROR ********************************************************************/ @@ -953,16 +1023,16 @@ BOOL prs_buffer5(BOOL charmode, const char *name, prs_struct *ps, int depth, BUF if (q == NULL) return False; + /* If the string is empty, we don't have anything to stream */ + if (str->buf_len==0) + return True; + if (UNMARSHALLING(ps)) { str->buffer = PRS_ALLOC_MEM(ps,uint16,str->buf_len); if (str->buffer == NULL) return False; } - /* If the string is empty, we don't have anything to stream */ - if (str->buf_len==0) - return True; - p = (char *)str->buffer; dbg_rw_punival(charmode, name, depth, ps, q, p, str->buf_len); @@ -992,6 +1062,8 @@ BOOL prs_regval_buffer(BOOL charmode, const char *name, prs_struct *ps, int dept buf->buffer = PRS_ALLOC_MEM(ps, uint16, buf->buf_max_len); if ( buf->buffer == NULL ) return False; + } else { + buf->buffer = NULL; } } @@ -1019,9 +1091,16 @@ BOOL prs_string2(BOOL charmode, const char *name, prs_struct *ps, int depth, STR if (str->str_str_len > str->str_max_len) { return False; } - str->buffer = PRS_ALLOC_MEM(ps,unsigned char, str->str_max_len); - if (str->buffer == NULL) - return False; + if (str->str_max_len) { + str->buffer = PRS_ALLOC_MEM(ps,unsigned char, str->str_max_len); + if (str->buffer == NULL) + return False; + } else { + str->buffer = NULL; + /* Return early to ensure Coverity isn't confused. */ + DEBUG(5,("%s%04x %s: \n", tab_depth(depth), ps->data_offset, name)); + return True; + } } if (UNMARSHALLING(ps)) { @@ -1066,9 +1145,13 @@ BOOL prs_unistr2(BOOL charmode, const char *name, prs_struct *ps, int depth, UNI if (str->uni_str_len > str->uni_max_len) { return False; } - str->buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_max_len); - if (str->buffer == NULL) - return False; + if (str->uni_max_len) { + str->buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_max_len); + if (str->buffer == NULL) + return False; + } else { + str->buffer = NULL; + } } p = (char *)str->buffer; @@ -1093,9 +1176,13 @@ BOOL prs_unistr3(BOOL charmode, const char *name, UNISTR3 *str, prs_struct *ps, return False; if (UNMARSHALLING(ps)) { - str->str.buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_str_len); - if (str->str.buffer == NULL) - return False; + if (str->uni_str_len) { + str->str.buffer = PRS_ALLOC_MEM(ps,uint16,str->uni_str_len); + if (str->str.buffer == NULL) + return False; + } else { + str->str.buffer = NULL; + } } p = (char *)str->str.buffer; @@ -1269,32 +1356,35 @@ BOOL prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_ ps->data_offset += len+1; - dump_data(5+depth, q, len); + dump_data(5+depth, (uint8 *)q, len); return True; } -BOOL prs_string_alloc(const char *name, prs_struct *ps, int depth, - const char **str) +BOOL prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str) { size_t len; char *tmp_str; - if (UNMARSHALLING(ps)) + if (UNMARSHALLING(ps)) { len = strlen(&ps->data_p[ps->data_offset]); - else + } else { len = strlen(*str); + } tmp_str = PRS_ALLOC_MEM(ps, char, len+1); - if (tmp_str == NULL) + if (tmp_str == NULL) { return False; + } - if (MARSHALLING(ps)) + if (MARSHALLING(ps)) { strncpy(tmp_str, *str, len); + } - if (!prs_string(name, ps, depth, tmp_str, len+1)) + if (!prs_string(name, ps, depth, tmp_str, len+1)) { return False; + } *str = tmp_str; return True; @@ -1388,32 +1478,29 @@ BOOL prs_uint32_post(const char *name, prs_struct *ps, int depth, uint32 *data32 } /* useful function to store a structure in rpc wire format */ -int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps) +int tdb_prs_store(TDB_CONTEXT *tdb, TDB_DATA kbuf, prs_struct *ps) { - TDB_DATA kbuf, dbuf; - kbuf.dptr = keystr; - kbuf.dsize = strlen(keystr)+1; - dbuf.dptr = ps->data_p; - dbuf.dsize = prs_offset(ps); - return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + TDB_DATA dbuf; + dbuf.dptr = (uint8 *)ps->data_p; + dbuf.dsize = prs_offset(ps); + return tdb_trans_store(tdb, kbuf, dbuf, TDB_REPLACE); } /* useful function to fetch a structure into rpc wire format */ -int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *mem_ctx) +int tdb_prs_fetch(TDB_CONTEXT *tdb, TDB_DATA kbuf, prs_struct *ps, TALLOC_CTX *mem_ctx) { - TDB_DATA kbuf, dbuf; - kbuf.dptr = keystr; - kbuf.dsize = strlen(keystr)+1; + TDB_DATA dbuf; - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - return -1; + prs_init(ps, 0, mem_ctx, UNMARSHALL); - prs_init(ps, 0, mem_ctx, UNMARSHALL); - prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True); + dbuf = tdb_fetch(tdb, kbuf); + if (!dbuf.dptr) + return -1; - return 0; -} + prs_give_memory(ps, (char *)dbuf.dptr, dbuf.dsize, True); + + return 0; +} /******************************************************************* hash a stream. @@ -1428,13 +1515,13 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, int len) #ifdef DEBUG_PASSWORD DEBUG(100, ("prs_hash1\n")); - dump_data(100, ps->sess_key, 16); - dump_data(100, q, len); + dump_data(100, (uint8 *)ps->sess_key, 16); + dump_data(100, (uint8 *)q, len); #endif - SamOEMhash((uchar *) q, ps->sess_key, len); + SamOEMhash((uchar *) q, (const unsigned char *)ps->sess_key, len); #ifdef DEBUG_PASSWORD - dump_data(100, q, len); + dump_data(100, (uint8 *)q, len); #endif return True; @@ -1452,7 +1539,7 @@ static void schannel_digest(struct schannel_auth_struct *a, uchar digest_final[16]) { uchar whole_packet_digest[16]; - static uchar zeros[4]; + static const uchar zeros[4] = { 0, }; struct MD5Context ctx3; /* verfiy the signature on the packet by MD5 over various bits */ @@ -1481,7 +1568,7 @@ static void schannel_get_sealing_key(struct schannel_auth_struct *a, RPC_AUTH_SCHANNEL_CHK *verf, uchar sealing_key[16]) { - static uchar zeros[4]; + static const uchar zeros[4] = { 0, }; uchar digest2[16]; uchar sess_kf0[16]; int i; @@ -1508,7 +1595,7 @@ static void schannel_get_sealing_key(struct schannel_auth_struct *a, static void schannel_deal_with_seq_num(struct schannel_auth_struct *a, RPC_AUTH_SCHANNEL_CHK *verf) { - static uchar zeros[4]; + static const uchar zeros[4] = { 0, }; uchar sequence_key[16]; uchar digest1[16]; @@ -1559,7 +1646,7 @@ void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l uchar digest_final[16]; uchar confounder[8]; uchar seq_num[8]; - static const uchar nullbytes[8]; + static const uchar nullbytes[8] = { 0, }; static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE; static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE; @@ -1679,9 +1766,9 @@ BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l checksum after the decode, below */ DEBUG(2, ("schannel_decode: FAILED: packet sequence number:\n")); - dump_data(2, (const char*)verf->seq_num, sizeof(verf->seq_num)); + dump_data(2, verf->seq_num, sizeof(verf->seq_num)); DEBUG(2, ("should be:\n")); - dump_data(2, (const char*)seq_num, sizeof(seq_num)); + dump_data(2, seq_num, sizeof(seq_num)); return False; } @@ -1689,9 +1776,9 @@ BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l if (memcmp(verf->sig, schannel_sig, sizeof(verf->sig))) { /* Validate that the other end sent the expected header */ DEBUG(2, ("schannel_decode: FAILED: packet header:\n")); - dump_data(2, (const char*)verf->sig, sizeof(verf->sig)); + dump_data(2, verf->sig, sizeof(verf->sig)); DEBUG(2, ("should be:\n")); - dump_data(2, (const char*)schannel_sig, sizeof(schannel_sig)); + dump_data(2, schannel_sig, sizeof(schannel_sig)); return False; } @@ -1728,3 +1815,35 @@ BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_l return (memcmp(digest_final, verf->packet_digest, sizeof(verf->packet_digest)) == 0); } + +/******************************************************************* +creates a new prs_struct containing a DATA_BLOB +********************************************************************/ +BOOL prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + if (!prs_init( prs, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL )) + return False; + + + if (!prs_copy_data_in(prs, (char *)blob->data, blob->length)) + return False; + + return True; +} + +/******************************************************************* +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; +}