Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rmi.c
Line
Count
Source
1
/* packet-rmi.c
2
 * Routines for java rmiregistry dissection
3
 * Copyright 2002, Michael Stiller <ms@2scale.net>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
15
#include <epan/packet.h>
16
17
#include "packet-rmi.h"
18
19
void proto_register_rmi(void);
20
void proto_reg_handoff_rmi(void);
21
22
static dissector_handle_t rmi_handle;
23
24
static void
25
dissect_ser(tvbuff_t *tvb, proto_tree *tree);
26
27
static rmi_type
28
get_rmi_type(tvbuff_t *tvb, unsigned offset, unsigned datalen);
29
30
/* Initialize the protocol and registered fields */
31
static int proto_rmi;
32
static int proto_ser;
33
static int hf_rmi_magic;
34
static int hf_rmi_version;
35
static int hf_rmi_protocol;
36
static int hf_rmi_inputmessage;
37
static int hf_rmi_outputmessage;
38
static int hf_rmi_epid_length;
39
static int hf_rmi_epid_hostname;
40
static int hf_rmi_epid_port;
41
static int hf_rmi_serialization_data;
42
static int hf_rmi_unique_identifier;
43
44
static int hf_ser_magic;
45
static int hf_ser_version;
46
47
/* Initialize the subtree pointers */
48
static int ett_rmi;
49
static int ett_rmi_magic;
50
static int ett_rmi_version;
51
static int ett_rmi_inputmessage;
52
static int ett_rmi_outputmessage;
53
static int ett_rmi_epid_length;
54
static int ett_rmi_epid_hostname;
55
static int ett_rmi_epid_port;
56
static int ett_rmi_endpoint_identifier;
57
58
static int ett_ser;
59
60
/*
61
 * See
62
 *
63
 *     http://java.sun.com/products/jdk/1.2/docs/guide/rmi/spec/rmi-protocol.doc1.html
64
 *
65
 * for RMI, and
66
 *
67
 *     http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/protocol.doc.html
68
 *
69
 * for the serialization protocol.
70
 */
71
72
14
#define TCP_PORT_RMI   1099
73
74
static const value_string rmi_protocol_str[] = {
75
    {RMI_OUTPUTSTREAM_PROTOCOL_STREAM,    "StreamProtocol"},
76
    {RMI_OUTPUTSTREAM_PROTOCOL_SINGLEOP,  "SingleOpProtocol"},
77
    {RMI_OUTPUTSTREAM_PROTOCOL_MULTIPLEX, "MultiPlexProtocol"},
78
    {0, NULL}
79
};
80
81
static const value_string rmi_output_message_str[] = {
82
    {RMI_OUTPUTSTREAM_MESSAGE_CALL,       "Call"},
83
    {RMI_OUTPUTSTREAM_MESSAGE_PING,       "Ping"},
84
    {RMI_OUTPUTSTREAM_MESSAGE_DGCACK,     "DgcAck"},
85
    {0, NULL}
86
};
87
88
static const value_string rmi_input_message_str[] = {
89
    {RMI_INPUTSTREAM_MESSAGE_ACK,          "ProtocolAck"},
90
    {RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED, "ProtocolNotSupported"},
91
    {RMI_INPUTSTREAM_MESSAGE_RETURNDATA,   "ReturnData"},
92
    {RMI_INPUTSTREAM_MESSAGE_PINGACK,      "PingAck"},
93
    {0, NULL}
94
};
95
96
static int
97
dissect_rmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
98
0
{
99
0
    proto_item *ti;
100
0
    proto_tree *rmi_tree;
101
102
0
    tvbuff_t   *next_tvb;
103
104
0
    unsigned    offset = 0;
105
0
    unsigned    next_offset;
106
0
    unsigned    datalen;
107
108
0
    uint16_t    version, len, port;
109
0
    uint8_t     message, proto;
110
111
0
    rmi_type    rmitype;
112
113
/* Make entries in Protocol column and Info column on summary display */
114
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMI");
115
116
0
    tvb_find_line_end_remaining(tvb, offset, &datalen, &next_offset);
117
118
0
    rmitype = get_rmi_type(tvb, offset, datalen);
119
120
0
    switch(rmitype) {
121
0
    case RMI_OUTPUTSTREAM:
122
0
        version = tvb_get_ntohs(tvb,4);
123
0
        col_add_fstr(pinfo->cinfo, COL_INFO,
124
0
                     "JRMI, Version: %d, ", version);
125
126
0
        proto   = tvb_get_uint8(tvb, 6);
127
0
        col_append_str(pinfo->cinfo, COL_INFO,
128
0
                       val_to_str_const(proto, rmi_protocol_str,
129
0
                                        "Unknown protocol"));
130
0
        break;
131
0
    case RMI_OUTPUTMESSAGE:
132
0
        message = tvb_get_uint8(tvb,0);
133
0
        col_set_str(pinfo->cinfo, COL_INFO,
134
0
                    "JRMI, ");
135
0
        col_append_str(pinfo->cinfo, COL_INFO,
136
0
                       val_to_str_const(message, rmi_output_message_str,
137
0
                                        "Unknown message"));
138
0
        break;
139
0
    case RMI_INPUTSTREAM:
140
0
        message = tvb_get_uint8(tvb,0);
141
0
        col_set_str(pinfo->cinfo, COL_INFO,
142
0
                    "JRMI, ");
143
0
        col_append_str(pinfo->cinfo, COL_INFO,
144
0
                       val_to_str_const(message, rmi_input_message_str,
145
0
                                        "Unknown message"));
146
0
        break;
147
0
    case SERIALIZATION_DATA:
148
0
        version = tvb_get_ntohs(tvb,2);
149
0
        col_add_fstr(pinfo->cinfo, COL_INFO,
150
0
                     "Serialization data, Version: %d", version);
151
0
        break;
152
0
    default:
153
0
        col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
154
0
        break;
155
0
    }
156
157
0
    if (tree) {
158
0
        ti = proto_tree_add_item(tree, proto_rmi, tvb, 0, -1, ENC_NA);
159
0
        rmi_tree = proto_item_add_subtree(ti, ett_rmi);
160
0
        switch(rmitype) {
161
0
        case RMI_OUTPUTSTREAM:
162
            /* XXX - uint, or string? */
163
0
            proto_tree_add_item(rmi_tree, hf_rmi_magic,
164
0
                                tvb, offset,     4, ENC_BIG_ENDIAN);
165
0
            proto_tree_add_item(rmi_tree, hf_rmi_version,
166
0
                                tvb, offset + 4, 2, ENC_BIG_ENDIAN);
167
0
            proto_tree_add_item(rmi_tree, hf_rmi_protocol,
168
0
                                tvb, offset + 6, 1, ENC_BIG_ENDIAN);
169
0
            break;
170
0
        case RMI_INPUTSTREAM:
171
0
            message = tvb_get_uint8(tvb, 0);
172
0
            proto_tree_add_uint(rmi_tree, hf_rmi_inputmessage,
173
0
                                tvb, offset, 1, message);
174
0
            if(message == RMI_INPUTSTREAM_MESSAGE_ACK) {
175
0
                proto_tree* endpoint_tree = proto_tree_add_subtree(rmi_tree, tvb, offset + 1, -1,
176
0
                                    ett_rmi_endpoint_identifier, NULL, "EndPointIdentifier");
177
                /* MESSAGE_ACK should include EndpointIdentifier */
178
0
                len = tvb_get_ntohs(tvb, 1);
179
0
                proto_tree_add_uint(endpoint_tree, hf_rmi_epid_length,
180
0
                                    tvb, offset + 1, 2, len);
181
0
                if (len > 0) {
182
0
                    proto_tree_add_item(endpoint_tree, hf_rmi_epid_hostname,
183
0
                                      tvb, offset + 3, len, ENC_ASCII);
184
0
                } else {
185
0
                    proto_tree_add_string(endpoint_tree, hf_rmi_epid_hostname,
186
0
                                      tvb, offset + 3, len, "[Empty]");
187
0
                }
188
189
0
                port = tvb_get_ntohs(tvb, offset + len + 5);
190
0
                proto_tree_add_uint(endpoint_tree, hf_rmi_epid_port,
191
0
                                    tvb, offset + len + 5, 2, port);
192
0
            }
193
0
            if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) {
194
0
                proto_tree_add_bytes_format(rmi_tree, hf_rmi_serialization_data, tvb, offset + 1, -1,
195
0
                                    NULL, "Serialization Data");
196
0
                next_tvb = tvb_new_subset_remaining(tvb, offset + 1);
197
0
                dissect_ser(next_tvb, tree);
198
0
            }
199
0
            break;
200
0
        case RMI_OUTPUTMESSAGE:
201
0
            message = tvb_get_uint8(tvb, 0);
202
0
            proto_tree_add_uint(rmi_tree, hf_rmi_outputmessage,
203
0
                                tvb, offset, 1, message);
204
0
            if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) {
205
0
                proto_tree_add_bytes_format(rmi_tree, hf_rmi_serialization_data, tvb, offset + 1, -1,
206
0
                                    NULL, "Serialization Data");
207
                /* XXX */
208
0
                next_tvb = tvb_new_subset_remaining(tvb, offset + 1);
209
0
                dissect_ser(next_tvb, tree);
210
0
            }
211
0
            if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
212
0
                proto_tree_add_item(rmi_tree, hf_rmi_unique_identifier, tvb, offset + 1, -1, ENC_NA);
213
0
            }
214
0
            break;
215
0
        case SERIALIZATION_DATA:
216
0
            dissect_ser(tvb, tree);
217
0
            break;
218
0
        default:
219
0
            break;
220
0
        }
221
0
    }
222
0
    return tvb_captured_length(tvb);
223
0
}
224
225
static void
226
dissect_ser(tvbuff_t *tvb, proto_tree *tree)
227
0
{
228
0
    proto_item *ti;
229
0
    proto_tree *ser_tree;
230
231
0
    unsigned offset;
232
233
0
    offset = 0;
234
235
0
    if(tree) {
236
0
        ti = proto_tree_add_item(tree, proto_ser, tvb, 0, -1, ENC_NA);
237
0
        ser_tree = proto_item_add_subtree(ti, ett_ser);
238
0
        proto_tree_add_item(ser_tree, hf_ser_magic,
239
0
                            tvb, offset,     2, ENC_BIG_ENDIAN);
240
0
        proto_tree_add_item(ser_tree, hf_ser_version,
241
0
                            tvb, offset + 2, 2, ENC_BIG_ENDIAN);
242
243
0
    }
244
0
}
245
246
static rmi_type
247
get_rmi_type(tvbuff_t *tvb, unsigned offset, unsigned datalen)
248
0
{
249
0
    uint16_t ser_magic;
250
0
    unsigned char  data[4];
251
252
0
    tvb_memcpy(tvb, data, offset, (datalen > 4) ? 4 : datalen);
253
254
0
    if (datalen >= 2) {
255
0
        ser_magic = data[0] << 8 | data[1];
256
0
        if (ser_magic == SER_STREAM_MAGIC) {
257
0
            return SERIALIZATION_DATA;
258
0
        }
259
0
    }
260
0
    if (datalen >= 4) {
261
0
        if(memcmp(data, RMI_MAGIC, 4) == 0) {
262
0
            return RMI_OUTPUTSTREAM;
263
0
        }
264
0
    }
265
0
    if (datalen >= 1) {
266
0
        if (data[0] == RMI_INPUTSTREAM_MESSAGE_ACK ||
267
0
            data[0] == RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED ||
268
0
            data[0] == RMI_INPUTSTREAM_MESSAGE_RETURNDATA ||
269
0
            data[0] == RMI_INPUTSTREAM_MESSAGE_PINGACK) {
270
0
            return RMI_INPUTSTREAM;
271
0
        }
272
0
    }
273
0
    if (datalen >= 1) {
274
0
        if (data[0] == RMI_OUTPUTSTREAM_MESSAGE_CALL ||
275
0
            data[0] == RMI_OUTPUTSTREAM_MESSAGE_PING ||
276
0
            data[0] == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
277
0
            return RMI_OUTPUTMESSAGE;
278
0
        }
279
0
    }
280
0
    return CONTINUATION;
281
0
}
282
283
void
284
proto_register_rmi(void)
285
14
{
286
287
14
    static hf_register_info hf[] = {
288
14
        { &hf_rmi_magic,
289
14
          { "Magic",   "rmi.magic",
290
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
291
14
            "RMI Header Magic", HFILL }},
292
14
        { &hf_rmi_version,
293
14
          { "Version", "rmi.version",
294
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
295
14
            "RMI Protocol Version", HFILL }},
296
14
        { &hf_rmi_protocol,
297
14
          { "Protocol","rmi.protocol",
298
14
            FT_UINT8, BASE_HEX, VALS(rmi_protocol_str), 0x0,
299
14
            "RMI Protocol Type", HFILL }},
300
14
        { &hf_rmi_inputmessage,
301
14
          { "Input Stream Message", "rmi.inputstream.message",
302
14
            FT_UINT8, BASE_HEX, VALS(rmi_input_message_str), 0x0,
303
14
            "RMI Inputstream Message Token", HFILL }},
304
14
        { &hf_rmi_outputmessage,
305
14
          { "Output Stream Message", "rmi.outputstream.message",
306
14
            FT_UINT8, BASE_HEX, VALS(rmi_output_message_str), 0x0,
307
14
            "RMI Outputstream Message token", HFILL }},
308
14
        { &hf_rmi_epid_length,
309
14
          { "Length", "rmi.endpoint_id.length",
310
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
311
14
            "RMI Endpointidentifier Length", HFILL }},
312
14
        { &hf_rmi_epid_hostname,
313
14
          { "Hostname", "rmi.endpoint_id.hostname",
314
14
            FT_STRING, BASE_NONE, NULL, 0x0,
315
14
            "RMI Endpointidentifier Hostname", HFILL }},
316
14
        { &hf_rmi_epid_port,
317
14
          { "Port", "rmi.endpoint_id.port",
318
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
319
14
            "RMI Endpointidentifier Port", HFILL }},
320
14
        { &hf_rmi_serialization_data,
321
14
          { "Serialization Data", "rmi.serialization_data",
322
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
323
14
            NULL, HFILL }},
324
14
        { &hf_rmi_unique_identifier,
325
14
          { "UniqueIdentifier", "rmi.unique_identifier",
326
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
327
14
            NULL, HFILL }},
328
329
14
        { &hf_ser_magic,
330
14
          { "Magic",   "rmi.ser.magic",
331
14
            FT_UINT16, BASE_HEX, NULL, 0x0,
332
14
            "Java Serialization Magic", HFILL }},
333
14
        { &hf_ser_version,
334
14
          { "Version", "rmi.ser.version",
335
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
336
14
            "Java Serialization Version", HFILL }},
337
14
    };
338
339
14
    static int *ett[] = {
340
14
        &ett_rmi,
341
14
        &ett_rmi_magic,
342
14
        &ett_rmi_version,
343
14
        &ett_rmi_inputmessage,
344
14
        &ett_rmi_outputmessage,
345
14
        &ett_rmi_epid_length,
346
14
        &ett_rmi_epid_hostname,
347
14
        &ett_rmi_epid_port,
348
14
        &ett_ser,
349
14
        &ett_rmi_endpoint_identifier,
350
14
    };
351
352
14
    proto_rmi = proto_register_protocol("Java RMI", "RMI", "rmi");
353
14
    proto_ser = proto_register_protocol_in_name_only("Java Serialization", "Serialization",
354
14
                                        "serialization", proto_rmi, FT_PROTOCOL);
355
14
    proto_register_field_array(proto_rmi, hf, array_length(hf));
356
14
    proto_register_subtree_array(ett, array_length(ett));
357
358
14
    rmi_handle = register_dissector("rmi", dissect_rmi, proto_rmi);
359
14
}
360
361
void
362
proto_reg_handoff_rmi(void)
363
14
{
364
14
    dissector_add_uint_with_preference("tcp.port", TCP_PORT_RMI, rmi_handle);
365
14
}
366
367
/*
368
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
369
 *
370
 * Local variables:
371
 * c-basic-offset: 4
372
 * tab-width: 8
373
 * indent-tabs-mode: nil
374
 * End:
375
 *
376
 * vi: set shiftwidth=4 tabstop=8 expandtab:
377
 * :indentSize=4:tabSize=8:noTabs=true:
378
 */