Don't save the decrypted data on the first pass and use it on subsequent

references to a packet - just re-"decrypt" it (not a lot of work, given
the sophisticated encryption MAPI uses).  We don't save decrypted data
for non-trivial encryptions, so there's not much of a reason to save it
here - and the code to save it was at least sometimes not finding it
again, causing crashes.

Set the length and reported length of the decrypted data tvbuff
appropriately.

svn path=/trunk/; revision=11812
This commit is contained in:
Guy Harris 2004-08-23 01:04:46 +00:00
parent 10411e9790
commit 8bf8cd97ce
1 changed files with 40 additions and 98 deletions

View File

@ -72,80 +72,18 @@ static guint16 ver_dcerpc_mapi = 0;
/* decryption */
static gboolean mapi_decrypt = FALSE;
static GMemChunk *mapi_decrypted_data_chunk = NULL;
static int mapi_decrypted_data_init_count = 200;
static GHashTable *mapi_decrypted_table = NULL;
typedef struct {
guint32 frame;
guint32 callid;
tvbuff_t *tvb;
unsigned char *data;
} mapi_decrypted_data_t;
static gboolean
free_all_decrypted(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
{
mapi_decrypted_data_t *mdd=(mapi_decrypted_data_t *)key_arg;
if(mdd->tvb){
tvb_free(mdd->tvb);
mdd->tvb=NULL;
}
if(mdd->data){
g_free(mdd->data);
mdd->data=NULL;
}
return TRUE;
}
static guint
mapi_decrypt_hash(gconstpointer k)
{
const mapi_decrypted_data_t *mdd=(const mapi_decrypted_data_t *)k;
return mdd->frame;
}
static gint
mapi_decrypt_equal(gconstpointer k1, gconstpointer k2)
{
const mapi_decrypted_data_t *mdd1=(const mapi_decrypted_data_t *)k1;
const mapi_decrypted_data_t *mdd2=(const mapi_decrypted_data_t *)k2;
return ( (mdd1->frame==mdd2->frame)
&&(mdd1->callid==mdd2->callid) );
}
static void
mapi_decrypt_init(void)
{
if(mapi_decrypted_table){
g_hash_table_foreach_remove(mapi_decrypted_table,
free_all_decrypted, NULL);
} else {
mapi_decrypted_table=g_hash_table_new(mapi_decrypt_hash,
mapi_decrypt_equal);
}
if(mapi_decrypted_data_chunk){
g_mem_chunk_destroy(mapi_decrypted_data_chunk);
mapi_decrypted_data_chunk=NULL;
}
if(mapi_decrypt){
mapi_decrypted_data_chunk=g_mem_chunk_new("mapi_decrypt_chunk",
sizeof(mapi_decrypted_data_t),
mapi_decrypted_data_init_count*sizeof(mapi_decrypted_data_t),
G_ALLOC_ONLY);
}
}
static int
mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep)
{
dcerpc_info *di;
mapi_decrypted_data_t *mmd=NULL;
guint32 len;
const unsigned char *ptr;
guint32 i;
guint8 *decrypted_data;
tvbuff_t *decrypted_tvb;
guint32 length;
gint len, reported_len;
const guint8 *ptr;
gint i;
guint16 pdu_len;
proto_item *it = NULL;
proto_tree *tr = NULL;
@ -157,33 +95,38 @@ mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_maxlen, NULL);
offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_offset, NULL);
offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_len, &len);
offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_len, &length);
if(len>(guint32)tvb_length_remaining(tvb, offset)){
len=tvb_length_remaining(tvb, offset);
len = tvb_length_remaining(tvb, offset);
reported_len = tvb_reported_length_remaining(tvb, offset);
if((guint32)reported_len > length)
reported_len = length;
if(len > reported_len)
len = reported_len;
ptr=tvb_get_ptr(tvb, offset, len);
decrypted_data=g_malloc(len);
for(i=0;i<len;i++){
/*
* Now *that's* secure encryption!
*/
decrypted_data[i]=ptr[i]^0xa5;
}
if(!pinfo->fd->flags.visited){
ptr=(const unsigned char *)tvb_get_ptr(tvb, offset, len);
mmd=g_mem_chunk_alloc(mapi_decrypted_data_chunk);
mmd->callid=di->call_id;
mmd->frame=pinfo->fd->num;
mmd->data=g_malloc(len);
for(i=0;i<len;i++){
mmd->data[i]=ptr[i]^0xa5;
}
mmd->tvb=tvb_new_real_data(mmd->data, len, len);
g_hash_table_insert(mapi_decrypted_table, mmd, mmd);
}
/* Allocate a new tvbuff, referring to the decrypted data. */
decrypted_tvb=tvb_new_real_data(decrypted_data, len, reported_len);
if(!mmd){
mapi_decrypted_data_t mmd_key;
mmd_key.callid=di->call_id;
mmd_key.frame=pinfo->fd->num;
mmd=g_hash_table_lookup(mapi_decrypted_table, &mmd_key);
}
/* Arrange that the allocated packet data copy be freed when the
tvbuff is freed. */
tvb_set_free_cb(decrypted_tvb, g_free);
add_new_data_source(pinfo, mmd->tvb, "Decrypted MAPI");
/* Add the tvbuff to the list of tvbuffs to which the tvbuff we
were handed refers, so it'll get cleaned up when that tvbuff
is cleaned up. */
tvb_set_child_real_data_tvbuff(tvb, decrypted_tvb);
/* Add the decrypted data to the data source list. */
add_new_data_source(pinfo, decrypted_tvb, "Decrypted MAPI");
/* decrypted PDU */
/* All from 10 minutes eyeballing. This may be wrong.
@ -214,18 +157,18 @@ mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
special meaning?
More work needs to be done in this area.
*/
it=proto_tree_add_text(tree, mmd->tvb, 0, len, "Decrypted MAPI PDU");
it=proto_tree_add_text(tree, decrypted_tvb, 0, len, "Decrypted MAPI PDU");
tr=proto_item_add_subtree(it, ett_mapi_decrypted_pdu);
pdu_len=tvb_get_letohs(mmd->tvb, 0);
proto_tree_add_uint(tr, hf_mapi_pdu_len, mmd->tvb, 0, 2, pdu_len);
pdu_len=tvb_get_letohs(decrypted_tvb, 0);
proto_tree_add_uint(tr, hf_mapi_pdu_len, decrypted_tvb, 0, 2, pdu_len);
/*XXX call dissector here */
proto_tree_add_item(tr, hf_mapi_decrypted_data, mmd->tvb, 2, pdu_len-2, FALSE);
proto_tree_add_item(tr, hf_mapi_decrypted_data, decrypted_tvb, 2, pdu_len-2, FALSE);
proto_tree_add_item(tr, hf_mapi_pdu_trailer, mmd->tvb, pdu_len, 4, FALSE);
if(len>((guint32)pdu_len+4)){
proto_tree_add_item(tr, hf_mapi_pdu_extra_trailer, mmd->tvb, pdu_len+4, len-(pdu_len+4), FALSE);
proto_tree_add_item(tr, hf_mapi_pdu_trailer, decrypted_tvb, pdu_len, 4, FALSE);
if(len>((gint)pdu_len+4)){
proto_tree_add_item(tr, hf_mapi_pdu_extra_trailer, decrypted_tvb, pdu_len+4, len-(pdu_len+4), FALSE);
}
@ -462,7 +405,6 @@ static hf_register_info hf[] = {
"Decrypt MAPI PDUs",
"Whether the dissector should decrypt MAPI PDUs",
&mapi_decrypt);
register_init_routine(mapi_decrypt_init);
}
void