Note that for THE3GPP_IPV6_DNS_SERVERS we probably *do* need to handle
[obnox/wireshark/wip.git] / packet-dcerpc-mapi.c
index 362c921b0aa2d5bc80209023cc6a4f5ee575502a..dc3d4d519eccabbc0c48b88b15d1665c81385b7a 100644 (file)
@@ -2,22 +2,22 @@
  * Routines for MS Exchange MAPI
  * Copyright 2002, Ronnie Sahlberg
  *
- * $Id: packet-dcerpc-mapi.c,v 1.10 2002/06/04 07:03:44 guy Exp $
+ * $Id: packet-dcerpc-mapi.c,v 1.27 2004/02/25 09:31:05 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
- * 
+ *
  * 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 (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "prefs.h"
 
 static int proto_dcerpc_mapi = -1;
+static int hf_mapi_opnum = -1;
 static int hf_mapi_unknown_string = -1;
-static int hf_mapi_unknown_data = -1;
 static int hf_mapi_unknown_short = -1;
+static int hf_mapi_unknown_long = -1;
 static int hf_mapi_hnd = -1;
 static int hf_mapi_rc = -1;
 static int hf_mapi_encap_datalen = -1;
+static int hf_mapi_encrypted_data = -1;
 static int hf_mapi_decrypted_data_maxlen = -1;
 static int hf_mapi_decrypted_data_offset = -1;
 static int hf_mapi_decrypted_data_len = -1;
@@ -98,14 +100,14 @@ free_all_decrypted(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
 static guint
 mapi_decrypt_hash(gconstpointer k)
 {
-       mapi_decrypted_data_t *mdd=(mapi_decrypted_data_t *)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)
 {
-       mapi_decrypted_data_t *mdd1=(mapi_decrypted_data_t *)k1;
-       mapi_decrypted_data_t *mdd2=(mapi_decrypted_data_t *)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) );
@@ -137,12 +139,12 @@ mapi_decrypt_init(void)
 
 static int
 mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
        dcerpc_info *di;
        mapi_decrypted_data_t *mmd=NULL;
        guint32 len;
-       unsigned char *ptr;
+       const unsigned char *ptr;
        guint32 i;
        guint16 pdu_len;
        proto_item *it = NULL;
@@ -157,12 +159,16 @@ mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
        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);
 
+       if(len>(guint32)tvb_length_remaining(tvb, offset)){
+               len=tvb_length_remaining(tvb, offset);
+       }
+
        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);
-               ptr=(unsigned char *)tvb_get_ptr(tvb, offset, len);
                for(i=0;i<len;i++){
                        mmd->data[i]=ptr[i]^0xa5;
                }
@@ -179,7 +185,6 @@ mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
 
        add_new_data_source(pinfo, mmd->tvb, "Decrypted MAPI");
 
-
        /* decrypted PDU */
        /* All from 10 minutes eyeballing. This may be wrong.
           The PDU is NOT NDR encoded. So this completely new marshalling
@@ -187,15 +192,15 @@ mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
 
           It seems that ASCII text strings always are NULL terminated,
           also no obvious string-length-byte can be seen so it seems the
-          length of strings are determined by searching the terminating null 
+          length of strings are determined by searching the terminating null
           byte.
 
           The first two bytes of the PDU is the length of the PDU including
           the two length bytes.
           The third byte may be a subcommand byte ?
 
-          After the PDU comes, in requests a 4 byte thing. Which is either 
-          (not very often) 0xffffffff or something else. If it is 
+          After the PDU comes, in requests a 4 byte thing. Which is either
+          (not very often) 0xffffffff or something else. If it is
           'something else' these four bytes are repeated for the matching
           response packet.
           In some repsonse packets, this 4 byte trailer are sometimes followed
@@ -231,14 +236,13 @@ mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
 
 static int
 mapi_logon_rqst(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       dissect_ndr_nt_STRING_string, NDR_POINTER_REF,
-                       "unknown string", hf_mapi_unknown_string, -1);
+        offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+                       sizeof(guint8), hf_mapi_unknown_string, TRUE, NULL);
 
         DISSECT_UNKNOWN(tvb_length_remaining(tvb, offset));
-  
+
        return offset;
 }
 
@@ -247,22 +251,25 @@ There might be offsets/padding mismatched due to potential pointer expansions
 or padding bytes. Captures where this code breaks will tell us about that */
 static int
 mapi_logon_reply(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
        offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
-                                      hf_mapi_hnd, NULL, FALSE, FALSE);
+                                      hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
 
         DISSECT_UNKNOWN(20); /* this is 20 bytes, unless there are pointers */
 
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       dissect_ndr_nt_STRING_string, NDR_POINTER_REF,
-                       "unknown string", hf_mapi_unknown_string, -1);
+        offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+                       sizeof(guint8), hf_mapi_unknown_string, TRUE, NULL);
 
-        DISSECT_UNKNOWN(6); /* possibly 1 or 2 bytes padding here */
+        /* Was DISSECT_UNKNOWN(6), but the 1 or 2 bytes the comment that
+           was here referred to probably were padding, if they were seen;
+           in another capture, there are 5 bytes there - it's probably a
+           4-byte quantity, always aligned on a 4-byte boundary. */
+        offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+                       hf_mapi_unknown_long, NULL);
 
-        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                       dissect_ndr_nt_STRING_string, NDR_POINTER_REF,
-                       "unknown string", hf_mapi_unknown_string, -1);
+        offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+                       sizeof(guint8), hf_mapi_unknown_string, TRUE, NULL);
 
         DISSECT_UNKNOWN( tvb_length_remaining(tvb, offset)-4 );
 
@@ -273,18 +280,18 @@ mapi_logon_reply(tvbuff_t *tvb, int offset,
 }
 
 static int
-mapi_unknown_02_request(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+mapi_ec_do_rpc_request(tvbuff_t *tvb, int offset,
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
        offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
-                                      hf_mapi_hnd, NULL, FALSE, FALSE);
+                                      hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
 
        if(!mapi_decrypt){
                /* this is a unidimensional varying and conformant array of
-                  encrypted data */  
+                  encrypted data */
                        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                               dissect_ndr_nt_STRING_string, NDR_POINTER_REF,
-                               "unknown data", hf_mapi_unknown_data, -1);
+                               dissect_ndr_byte_array, NDR_POINTER_REF,
+                               "Encrypted data", hf_mapi_encrypted_data);
        } else {
                offset = mapi_decrypt_pdu(tvb, offset, pinfo, tree, drep);
        }
@@ -299,22 +306,22 @@ mapi_unknown_02_request(tvbuff_t *tvb, int offset,
        return offset;
 }
 static int
-mapi_unknown_02_reply(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+mapi_ec_do_rpc_reply(tvbuff_t *tvb, int offset,
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
        offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
-                                      hf_mapi_hnd, NULL, FALSE, FALSE);
+                                      hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
 
        if(!mapi_decrypt){
                /* this is a unidimensional varying and conformant array of
-                  encrypted data */  
+                  encrypted data */
                        offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-                               dissect_ndr_nt_STRING_string, NDR_POINTER_REF,
-                               "unknown data", hf_mapi_unknown_data, -1);
+                               dissect_ndr_byte_array, NDR_POINTER_REF,
+                               "Encrypted data", hf_mapi_encrypted_data);
        } else {
                offset = mapi_decrypt_pdu(tvb, offset, pinfo, tree, drep);
        }
-       
+
        /* length of encrypted data */
        offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
                        hf_mapi_encap_datalen, NULL);
@@ -327,20 +334,20 @@ mapi_unknown_02_reply(tvbuff_t *tvb, int offset,
 
 static int
 mapi_logoff_rqst(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
        offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
-                                      hf_mapi_hnd, NULL, FALSE, FALSE);
+                                      hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
 
        return offset;
 }
 
 static int
 mapi_logoff_reply(tvbuff_t *tvb, int offset,
-       packet_info *pinfo, proto_tree *tree, char *drep)
+       packet_info *pinfo, proto_tree *tree, guint8 *drep)
 {
        offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
-                                      hf_mapi_hnd, NULL, FALSE, FALSE);
+                                      hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
 
        offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
                        hf_mapi_rc, NULL);
@@ -350,30 +357,42 @@ mapi_logoff_reply(tvbuff_t *tvb, int offset,
 
 
 static dcerpc_sub_dissector dcerpc_mapi_dissectors[] = {
-        { MAPI_LOGON,          "Logon", 
+        { MAPI_EC_DO_CONNECT,  "EcDoConnect",
                mapi_logon_rqst,
                mapi_logon_reply },
-        { MAPI_LOGOFF,         "Logoff", 
+        { MAPI_EC_DO_DISCONNECT,"EcDoDisconnect",
                mapi_logoff_rqst,
                mapi_logoff_reply },
-        { MAPI_UNKNOWN_02,     "unknown_02", 
-               mapi_unknown_02_request,
-               mapi_unknown_02_reply },
-
+        { MAPI_EC_DO_RPC,      "EcDoRpc",
+               mapi_ec_do_rpc_request,
+               mapi_ec_do_rpc_reply },
+       { MAPI_EC_GET_MORE_RPC, "EcGetMoreRpc", NULL, NULL },
+       { MAPI_EC_REGISTER_PUSH_NOTIFICATION, "EcRRegisterPushNotification",
+               NULL, NULL },
+       { MAPI_EC_UNREGISTER_PUSH_NOTIFICATION, "EcRUnregisterPushNotification",
+               NULL, NULL },
+       { MAPI_EC_DUMMY_RPC, "EcDummyRpc", NULL, NULL },
+       { MAPI_EC_GET_DC_NAME, "EcRGetDCName", NULL, NULL },
+       { MAPI_EC_NET_GET_DC_NAME, "EcRNetGetDCName", NULL, NULL },
+       { MAPI_EC_DO_RPC_EXT, "EcDoRpcExt", NULL, NULL },
         {0, NULL, NULL,  NULL }
 };
 
-void 
+void
 proto_register_dcerpc_mapi(void)
 {
 
 static hf_register_info hf[] = {
+       { &hf_mapi_opnum,
+               { "Operation", "mapi.opnum", FT_UINT16, BASE_DEC,
+                 NULL, 0x0, "", HFILL }},
+
        { &hf_mapi_hnd,
-               { "Context Handle", "mapi.hnd", FT_BYTES, BASE_NONE, 
+               { "Context Handle", "mapi.hnd", FT_BYTES, BASE_NONE,
                NULL, 0x0, "", HFILL }},
 
        { &hf_mapi_rc,
-               { "Return code", "mapi.rc", FT_UINT32, BASE_HEX, 
+               { "Return code", "mapi.rc", FT_UINT32, BASE_HEX,
                VALS (NT_errors), 0x0, "", HFILL }},
 
        { &hf_mapi_unknown_string,
@@ -384,40 +403,44 @@ static hf_register_info hf[] = {
                { "Unknown short", "mapi.unknown_short", FT_UINT16, BASE_HEX,
                NULL, 0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
 
-       { &hf_mapi_unknown_data,
-               { "unknown encrypted data", "mapi.unknown_data", FT_BYTES, BASE_HEX,
-               NULL, 0, "Unknown data. If you know what this is, contact ethereal developers.", HFILL }},
+       { &hf_mapi_unknown_long,
+               { "Unknown long", "mapi.unknown_long", FT_UINT32, BASE_HEX,
+               NULL, 0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
 
        { &hf_mapi_encap_datalen,
-               { "Length", "mapi.encap_len", FT_UINT16, BASE_DEC, 
+               { "Length", "mapi.encap_len", FT_UINT16, BASE_DEC,
                NULL, 0x0, "Length of encapsulated/encrypted data", HFILL }},
 
+       { &hf_mapi_encrypted_data,
+               { "Encrypted data", "mapi.encrypted_data", FT_BYTES, BASE_HEX,
+               NULL, 0, "Encrypted data", HFILL }},
+
        { &hf_mapi_decrypted_data_maxlen,
-               { "Max Length", "mapi.decrypted.data.maxlen", FT_UINT32, BASE_DEC, 
+               { "Max Length", "mapi.decrypted.data.maxlen", FT_UINT32, BASE_DEC,
                NULL, 0x0, "Maximum size of buffer for decrypted data", HFILL }},
 
        { &hf_mapi_decrypted_data_offset,
-               { "Offset", "mapi.decrypted.data.offset", FT_UINT32, BASE_DEC, 
+               { "Offset", "mapi.decrypted.data.offset", FT_UINT32, BASE_DEC,
                NULL, 0x0, "Offset into buffer for decrypted data", HFILL }},
 
        { &hf_mapi_decrypted_data_len,
-               { "Length", "mapi.decrypted.data.len", FT_UINT32, BASE_DEC, 
+               { "Length", "mapi.decrypted.data.len", FT_UINT32, BASE_DEC,
                NULL, 0x0, "Used size of buffer for decrypted data", HFILL }},
 
        { &hf_mapi_decrypted_data,
-               { "Decrypted data", "mapi.decrypted.data", FT_BYTES, BASE_HEX, 
+               { "Decrypted data", "mapi.decrypted.data", FT_BYTES, BASE_HEX,
                NULL, 0x0, "Decrypted data", HFILL }},
 
        { &hf_mapi_pdu_len,
-               { "Length", "mapi.pdu.len", FT_UINT16, BASE_DEC, 
+               { "Length", "mapi.pdu.len", FT_UINT16, BASE_DEC,
                NULL, 0x0, "Size of the command PDU", HFILL }},
 
        { &hf_mapi_pdu_trailer,
-               { "Trailer", "mapi.pdu.trailer", FT_UINT32, BASE_HEX, 
+               { "Trailer", "mapi.pdu.trailer", FT_UINT32, BASE_HEX,
                NULL, 0x0, "If you know what this is, contact ethereal developers", HFILL }},
 
        { &hf_mapi_pdu_extra_trailer,
-               { "unknown", "mapi.pdu.extra_trailer", FT_BYTES, BASE_HEX, 
+               { "unknown", "mapi.pdu.extra_trailer", FT_BYTES, BASE_HEX,
                NULL, 0x0, "If you know what this is, contact ethereal developers", HFILL }}
        };
 
@@ -431,11 +454,11 @@ static hf_register_info hf[] = {
         proto_dcerpc_mapi = proto_register_protocol(
                 "Microsoft Exchange MAPI", "MAPI", "mapi");
 
-        proto_register_field_array(proto_dcerpc_mapi, hf, 
+        proto_register_field_array(proto_dcerpc_mapi, hf,
                                   array_length(hf));
         proto_register_subtree_array(ett, array_length(ett));
        mapi_module = prefs_register_protocol(proto_dcerpc_mapi, NULL);
-       prefs_register_bool_preference(mapi_module, "mapi_decrypt",
+       prefs_register_bool_preference(mapi_module, "decrypt",
                "Decrypt MAPI PDUs",
                "Whether the dissector should decrypt MAPI PDUs",
                &mapi_decrypt);
@@ -447,7 +470,7 @@ proto_reg_handoff_dcerpc_mapi(void)
 {
         /* Register protocol as dcerpc */
 
-        dcerpc_init_uuid(proto_dcerpc_mapi, ett_dcerpc_mapi, 
-                         &uuid_dcerpc_mapi, ver_dcerpc_mapi, 
-                         dcerpc_mapi_dissectors);
+        dcerpc_init_uuid(proto_dcerpc_mapi, ett_dcerpc_mapi,
+                         &uuid_dcerpc_mapi, ver_dcerpc_mapi,
+                         dcerpc_mapi_dissectors, hf_mapi_opnum);
 }