Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-http2.c
Line
Count
Source
1
/* packet-http2.c
2
 * Routines for HTTP2 dissection
3
 * Copyright 2013, Alexis La Goutte <alexis.lagoutte@gmail.com>
4
 * Copyright 2013, Stephen Ludin <sludin@ludin.org>
5
 * Copyright 2014, Daniel Stenberg <daniel@haxx.se>
6
 * Copyright 2014, Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
/*
16
 * The information used comes from:
17
 * RFC7540: Hypertext Transfer Protocol version 2 (HTTP/2)
18
 * RFC7541: HTTP Header Compression for HTTP/2
19
 * RFC7838: HTTP Alternative Services
20
 *
21
 * TODO
22
* Enhance display of Data
23
* Reassembling of continuation frame (and other frame)
24
* Add same tap and ping/pong time response
25
*/
26
27
#include "config.h"
28
#define WS_LOG_DOMAIN "packet-http2"
29
30
#include <epan/packet.h>
31
#include <epan/expert.h>
32
#include <epan/prefs.h>
33
#include <epan/proto_data.h>
34
#include <epan/exceptions.h>
35
#include "packet-http.h" /* for getting status reason-phrase */
36
#include "packet-http2.h"
37
#include "packet-media-type.h"
38
39
#ifdef HAVE_NGHTTP2
40
#include <epan/uat.h>
41
#include <epan/charsets.h>
42
#include <epan/decode_as.h>
43
#include <nghttp2/nghttp2.h>
44
#include <epan/export_object.h>
45
#endif
46
47
#include <epan/tap.h>
48
#include <epan/stats_tree.h>
49
#include <epan/reassemble.h>
50
#include <epan/follow.h>
51
#include <epan/addr_resolv.h>
52
53
#include "packet-e212.h"
54
#include "packet-tcp.h"
55
#include "packet-tls.h"
56
#include "wsutil/pint.h"
57
#include "wsutil/strtoi.h"
58
#include "wsutil/str_util.h"
59
#include <wsutil/unicode-utils.h>
60
#include <wsutil/wsjson.h>
61
#include <wsutil/array.h>
62
63
#ifdef HAVE_NGHTTP2
64
#define http2_header_repr_type_VALUE_STRING_LIST(XXX)                   \
65
    XXX(HTTP2_HD_NONE, 0x00, "")                                        \
66
    XXX(HTTP2_HD_INDEXED, 0x01, "Indexed Header Field")                 \
67
    XXX(HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME, 0x02, "Literal Header Field with Incremental Indexing - Indexed Name") \
68
    XXX(HTTP2_HD_LITERAL_INDEXING_NEW_NAME, 0x03, "Literal Header Field with Incremental Indexing - New Name") \
69
    XXX(HTTP2_HD_LITERAL_INDEXED_NAME, 0x04, "Literal Header Field without Indexing - Indexed Name") \
70
    XXX(HTTP2_HD_LITERAL_NEW_NAME, 0x05, "Literal Header Field without Indexing - New Name") \
71
    XXX(HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME, 0x06, "Literal Header Field never Indexed - Indexed Name") \
72
    XXX(HTTP2_HD_LITERAL_NEVER_INDEXING_NEW_NAME, 0x07, "Literal Header Field never Indexed - New Name") \
73
    XXX(HTTP2_HD_HEADER_TABLE_SIZE_UPDATE, 0x08, "Maximum Header Table Size Change")
74
75
VALUE_STRING_ENUM(http2_header_repr_type);
76
VALUE_STRING_ARRAY(http2_header_repr_type);
77
78
/*
79
 * Decompression of zlib or brotli encoded entities.
80
 */
81
#if defined(HAVE_ZLIB) || defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI) || defined(HAVE_ZSTD)
82
static bool http2_decompress_body = true;
83
#else
84
static bool http2_decompress_body;
85
#endif
86
87
/* Track 3GPP session over 5G Service Based Interfaces */
88
static bool http2_3gpp_session = false;
89
90
/* Relation between notifyuri -> imsi */
91
static wmem_map_t* http2_notifyuri_imsi;
92
93
/* Relation between location -> imsi */
94
static wmem_map_t* http2_location_imsi;
95
96
/* Try to dissect reassembled http2.data.data according to content-type later */
97
static dissector_table_t media_type_dissector_table;
98
99
static int http_eo_tap;
100
#endif
101
102
/* Some protocols on top of http2 require http2 streams to remain open. For example, the stream
103
 * mode gRPC method (like ETCD watch stream). These kinds of subdissectors need http2 dissector
104
 * to reassemble http2.data.data according to the desegment_offset and desegment_len fields of the
105
 * pinfo returned from them. Subdissectors can register its content-type in this table.
106
 * Note: Subdissector can set pinfo->desegment_len to DESEGMENT_ONE_MORE_SEGMENT or
107
 * to missing nbytes of the head length if entire length of message is undetermined. */
108
static dissector_table_t streaming_content_type_dissector_table;
109
110
static dissector_table_t stream_id_content_type_dissector_table;
111
112
#ifdef HAVE_NGHTTP2
113
/* The type of reassembly mode contains:
114
 *  - HTTP2_DATA_REASSEMBLY_MODE_END_STREAM   Complete reassembly at the end of stream. (default)
115
 *  - HTTP2_DATA_REASSEMBLY_MODE_STREAMING    Determined by the desegment_offset and desegment_len fields returned from subdissector.
116
 */
117
enum http2_data_reassembly_mode_t {
118
    HTTP2_DATA_REASSEMBLY_MODE_END_STREAM  = 0, /* default */
119
    HTTP2_DATA_REASSEMBLY_MODE_STREAMING   = 1
120
};
121
122
static enum http2_data_reassembly_mode_t
123
http2_get_data_reassembly_mode(const char* content_type)
124
{
125
    return dissector_get_string_handle(streaming_content_type_dissector_table, content_type) ?
126
            HTTP2_DATA_REASSEMBLY_MODE_STREAMING : HTTP2_DATA_REASSEMBLY_MODE_END_STREAM;
127
}
128
#endif
129
130
/* Decompressed header field */
131
typedef struct {
132
    /* one of http2_header_repr_type */
133
    int type;
134
    /* encoded (compressed) length */
135
    int length;
136
    union {
137
        struct {
138
            /* header data */
139
            char *data;
140
            /* length of data */
141
            unsigned datalen;
142
            /* name index or name/value index if type is one of
143
               HTTP2_HD_INDEXED and HTTP2_HD_*_INDEXED_NAMEs */
144
            unsigned idx;
145
        } data;
146
        /* header table size if type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE */
147
        unsigned header_table_size;
148
    } table;
149
} http2_header_t;
150
151
/* Context to decode header representation */
152
typedef struct {
153
    /* one of http2_header_repr_type */
154
    int type;
155
    /* final or temporal result of decoding integer */
156
    unsigned integer;
157
    /* next bit shift to made when decoding integer */
158
    unsigned next_shift;
159
    /* true if integer decoding was completed */
160
    bool complete;
161
} http2_header_repr_info_t;
162
163
/* Cached decompressed header data in one packet_info */
164
typedef struct {
165
    /* list of pointer to wmem_array_t, which is array of
166
       http2_header_t */
167
    wmem_list_t *header_list;
168
    /* This points to the list frame containing current decompressed
169
       header for dissecting later. */
170
    wmem_list_frame_t *current;
171
    /* Bytes decompressed if we exceeded MAX_HTTP2_HEADER_SIZE */
172
    unsigned header_size_reached;
173
    /* Bytes decompressed if we had not exceeded MAX_HTTP2_HEADER_SIZE */
174
    unsigned header_size_attempted;
175
    /* true if we found >= MAX_HTTP2_HEADER_LINES */
176
    bool header_lines_exceeded;
177
} http2_header_data_t;
178
179
/* In-flight SETTINGS data. */
180
typedef struct {
181
    /* header table size last seen in SETTINGS */
182
    uint32_t header_table_size;
183
    /* minimum header table size in SETTINGS */
184
    uint32_t min_header_table_size;
185
    /* nonzero if header_table_size has effective value. */
186
    int has_header_table_size;
187
} http2_settings_t;
188
189
#ifdef HAVE_NGHTTP2
190
typedef uint64_t http2_frame_num_t;
191
192
/* struct for per-stream, per-direction DATA frame reassembly */
193
typedef struct {
194
    http2_frame_num_t data_initiated_in;
195
    bool has_transfer_encoded_body;
196
    /* streaming_reassembly_info only used for STREAMING reassembly mode */
197
    streaming_reassembly_info_t* streaming_reassembly_info;
198
} http2_data_stream_reassembly_info_t;
199
200
/* struct for per-stream, per-direction entity body info */
201
typedef struct {
202
    char *content_type;
203
    char *content_type_parameters;
204
    char *content_encoding;
205
    bool is_partial_content;
206
} http2_data_stream_body_info_t;
207
208
/* struct to track header state, so we know if continuation frames are part
209
 * of a HEADERS frame or a PUSH_PROMISE.
210
 */
211
typedef struct {
212
    /* Only track the latest received because we only use this on the first
213
     * pass. We could keep all the data in a wmem_list_t if we needed it on
214
     * later passes. */
215
    http2_frame_num_t header_start_in;
216
    http2_frame_num_t header_end_in;
217
    uint32_t stream_id; /* Normally the same as the parent http2_stream_info_t
218
                        * During a PUSH_PROMISE, this is the promised stream. */
219
    /* list of pointer to wmem_array_t, which is array of http2_header_t
220
    * that come from all HEADERS and CONTINUATION frames. */
221
    wmem_list_t *stream_header_list;
222
    /* fake header info */
223
    http2_frame_num_t fake_headers_initiated_fn;
224
    wmem_array_t* fake_headers;
225
} http2_header_stream_info_t;
226
227
/* struct to reference uni-directional per-stream info */
228
typedef struct {
229
    http2_data_stream_body_info_t data_stream_body_info;
230
    http2_data_stream_reassembly_info_t data_stream_reassembly_info;
231
    http2_header_stream_info_t header_stream_info;
232
    bool is_window_initialized;
233
    /* Current window size of the one-way session */
234
    int32_t current_window_size;
235
} http2_oneway_stream_info_t;
236
237
/* struct to hold per-stream information for both directions */
238
typedef struct {
239
    /* index into http2_oneway_stream_info_t struct is based off
240
     * http2_session_t.fwd_flow, available by calling select_http2_flow_index().
241
     * The index could be for either client or server, depending on when
242
     * the capture is started but the index will be consistent for the lifetime
243
     * of the http2_session_t */
244
    http2_oneway_stream_info_t oneway_stream_info[2];
245
    bool is_stream_http_connect;
246
    uint32_t stream_id;
247
    uint32_t request_in_frame_num;
248
    uint32_t response_in_frame_num;
249
    nstime_t request_ts;
250
    enum http2_data_reassembly_mode_t reassembly_mode;
251
    char *scheme;
252
    char *authority;
253
    char *path;
254
    const char *imsi;
255
    const char *referenceid;
256
    const char *location;
257
    const char *protocol;
258
    dissector_handle_t next_handle; /**< Protocol from extended CONNECT */
259
    http_upgrade_info_t *upgrade_info; /**< Data for new protocol */
260
} http2_stream_info_t;
261
#endif
262
/* struct to hold data per HTTP/2 session */
263
typedef struct {
264
    /* We need to distinguish the direction of the flow to keep track
265
       of in-flight SETTINGS and HPACK inflater objects.  To achieve
266
       this, we use fwd member of tcp_analysis.  In the first packet,
267
       we record fwd of tcp_analysis.  Later, if processing
268
       packet_info has fwd of tcp_analysis equal to the recorded fwd,
269
       we use index 0 of settings_queue and hd_inflater.  We keep
270
       track of SETTINGS frame sent in this direction in
271
       settings_queue[0] and inflate header block using
272
       hd_inflater[0].  Otherwise, we use settings_queue[1] and
273
       hd_inflater[1]. */
274
    wmem_queue_t *settings_queue[2];
275
#ifdef HAVE_NGHTTP2
276
    nghttp2_hd_inflater *hd_inflater[2];
277
    http2_header_repr_info_t header_repr_info[2];
278
    wmem_map_t *per_stream_info;
279
    bool        fix_dynamic_table[2];
280
#endif
281
    uint32_t current_stream_id;
282
    tcp_flow_t *fwd_flow;
283
    /* Initial window size of new streams (in both directions) */
284
    uint32_t initial_new_stream_window_size[2];
285
    /* Current window size of the connection (in both directions) */
286
    int32_t current_connection_window_size[2];
287
} http2_session_t;
288
289
typedef struct http2_follow_tap_data {
290
    tvbuff_t *tvb;
291
    uint64_t stream_id;
292
} http2_follow_tap_data_t;
293
294
typedef struct http2_adjust_window {
295
    int32_t windowSizeDiff;
296
    uint32_t flow_index;
297
    bool overflow;
298
} http2_adjust_window_t;
299
300
#ifdef HAVE_NGHTTP2
301
/* Decode as functions */
302
static void *
303
http2_current_stream_id_value(packet_info* pinfo)
304
{
305
    return GUINT_TO_POINTER(http2_get_stream_id(pinfo));
306
}
307
308
static void
309
http2_streamid_prompt(packet_info* pinfo, char* result)
310
{
311
312
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "stream (%u)", http2_get_stream_id(pinfo));
313
}
314
315
static void
316
decode_as_http2_populate_list(const char* table_name _U_, decode_as_add_to_list_func add_to_list, void *ui_element)
317
{
318
    decode_as_default_populate_list("media_type", add_to_list, ui_element);
319
}
320
321
#endif /*HAVE_NGHTTP2*/
322
323
static GHashTable* streamid_hash;
324
325
void proto_register_http2(void);
326
void proto_reg_handoff_http2(void);
327
328
struct HTTP2Tap {
329
    uint8_t type;
330
};
331
332
static int http2_tap;
333
static int http2_follow_tap;
334
335
static const char* st_str_http2 = "HTTP2";
336
static const char* st_str_http2_type = "Type";
337
338
static int st_node_http2 = -1;
339
static int st_node_http2_type = -1;
340
341
444
#define PROTO_DATA_KEY_HEADER 0
342
169
#define PROTO_DATA_KEY_WINDOW_SIZE_CONNECTION_BEFORE 1
343
#define PROTO_DATA_KEY_WINDOW_SIZE_STREAM_BEFORE 2
344
345
/* Packet Header */
346
static int proto_http2;
347
static int hf_http2_stream;
348
static int hf_http2_length;
349
static int hf_http2_type;
350
static int hf_http2_r;
351
static int hf_http2_streamid;
352
static int hf_http2_magic;
353
static int hf_http2_unknown;
354
/* Flags */
355
static int hf_http2_flags;
356
static int hf_http2_flags_end_stream;
357
static int hf_http2_flags_end_headers;
358
static int hf_http2_flags_padded;
359
static int hf_http2_flags_priority;
360
static int hf_http2_flags_settings_ack;
361
static int hf_http2_flags_ping_ack;
362
static int hf_http2_flags_unused;
363
static int hf_http2_flags_unused_settings;
364
static int hf_http2_flags_unused_ping;
365
static int hf_http2_flags_unused_continuation;
366
static int hf_http2_flags_unused_push_promise;
367
static int hf_http2_flags_unused_data;
368
static int hf_http2_flags_unused_headers;
369
370
/* generic */
371
static int hf_http2_padding;
372
static int hf_http2_pad_length;
373
374
static int hf_http2_weight;
375
static int hf_http2_weight_real;
376
static int hf_http2_stream_dependency;
377
static int hf_http2_excl_dependency;
378
/* Data */
379
static int hf_http2_data_segment;
380
static int hf_http2_data_data;
381
static int hf_http2_data_padding;
382
static int hf_http2_body_fragments;
383
static int hf_http2_body_fragment;
384
static int hf_http2_body_fragment_overlap;
385
static int hf_http2_body_fragment_overlap_conflicts;
386
static int hf_http2_body_fragment_multiple_tails;
387
static int hf_http2_body_fragment_too_long_fragment;
388
static int hf_http2_body_fragment_error;
389
static int hf_http2_body_fragment_count;
390
static int hf_http2_body_reassembled_in;
391
static int hf_http2_body_reassembled_length;
392
static int hf_http2_body_reassembled_data;
393
/* Headers */
394
static int hf_http2_headers;
395
static int hf_http2_headers_padding;
396
static int hf_http2_header;
397
static int hf_http2_header_length;
398
static int hf_http2_header_count;
399
static int hf_http2_header_name_length;
400
static int hf_http2_header_name;
401
static int hf_http2_header_value_length;
402
static int hf_http2_header_value;
403
static int hf_http2_header_unescaped;
404
static int hf_http2_header_repr;
405
static int hf_http2_header_index;
406
static int hf_http2_header_table_size_update;
407
static int hf_http2_header_table_size;
408
static int hf_http2_fake_header_count;
409
static int hf_http2_fake_header;
410
static int hf_http2_header_request_full_uri;
411
/* RST Stream */
412
static int hf_http2_rst_stream_error;
413
/* Settings */
414
static int hf_http2_settings;
415
static int hf_http2_settings_identifier;
416
static int hf_http2_settings_header_table_size;
417
static int hf_http2_settings_enable_push;
418
static int hf_http2_settings_max_concurrent_streams;
419
static int hf_http2_settings_initial_window_size;
420
static int hf_http2_settings_max_frame_size;
421
static int hf_http2_settings_max_header_list_size;
422
static int hf_http2_settings_extended_connect;
423
static int hf_http2_settings_no_rfc7540_priorities;
424
static int hf_http2_settings_tls_reneg_permitted;
425
static int hf_http2_settings_unknown;
426
/* Push Promise */
427
static int hf_http2_push_promise_r;
428
static int hf_http2_push_promise_promised_stream_id;
429
static int hf_http2_push_promise_header;
430
static int hf_http2_push_promise_padding;
431
/* Ping */
432
static int hf_http2_ping;
433
static int hf_http2_pong;
434
/* Goaway */
435
static int hf_http2_goaway_r;
436
static int hf_http2_goaway_last_stream_id;
437
static int hf_http2_goaway_error;
438
static int hf_http2_goaway_addata;
439
/* Window Update */
440
static int hf_http2_window_update_r;
441
static int hf_http2_window_update_window_size_increment;
442
/* Continuation */
443
static int hf_http2_continuation_header;
444
static int hf_http2_continuation_padding;
445
/* Altsvc */
446
static int hf_http2_altsvc_origin_len;
447
static int hf_http2_altsvc_origin;
448
static int hf_http2_altsvc_field_value;
449
/* Calculated */
450
static int hf_http2_calculated_window_size_connection_before;
451
static int hf_http2_calculated_window_size_connection_after;
452
static int hf_http2_calculated_window_size_stream_before;
453
static int hf_http2_calculated_window_size_stream_after;
454
#if HAVE_NGHTTP2
455
/* HTTP2 header static fields */
456
static int hf_http2_headers_status;
457
static int hf_http2_headers_path;
458
static int hf_http2_headers_method;
459
static int hf_http2_headers_scheme;
460
static int hf_http2_headers_protocol;
461
static int hf_http2_headers_accept;
462
static int hf_http2_headers_accept_charset;
463
static int hf_http2_headers_accept_encoding;
464
static int hf_http2_headers_accept_language;
465
static int hf_http2_headers_accept_ranges;
466
static int hf_http2_headers_access_control_allow_origin;
467
static int hf_http2_headers_age;
468
static int hf_http2_headers_allow;
469
static int hf_http2_headers_authorization;
470
static int hf_http2_headers_authority;
471
static int hf_http2_headers_cache_control;
472
static int hf_http2_headers_content_disposition;
473
static int hf_http2_headers_content_encoding;
474
static int hf_http2_headers_content_language;
475
static int hf_http2_headers_content_length;
476
static int hf_http2_headers_content_location;
477
static int hf_http2_headers_content_range;
478
static int hf_http2_headers_content_type;
479
static int hf_http2_headers_cookie;
480
static int hf_http2_headers_date;
481
static int hf_http2_headers_etag;
482
static int hf_http2_headers_expect;
483
static int hf_http2_headers_expires;
484
static int hf_http2_headers_from;
485
static int hf_http2_headers_if_match;
486
static int hf_http2_headers_if_modified_since;
487
static int hf_http2_headers_if_none_match;
488
static int hf_http2_headers_if_range;
489
static int hf_http2_headers_if_unmodified_since;
490
static int hf_http2_headers_last_modified;
491
static int hf_http2_headers_link;
492
static int hf_http2_headers_location;
493
static int hf_http2_headers_max_forwards;
494
static int hf_http2_headers_proxy_authenticate;
495
static int hf_http2_headers_proxy_authorization;
496
static int hf_http2_headers_range;
497
static int hf_http2_headers_referer;
498
static int hf_http2_headers_refresh;
499
static int hf_http2_headers_retry_after;
500
static int hf_http2_headers_server;
501
static int hf_http2_headers_set_cookie;
502
static int hf_http2_headers_strict_transport_security;
503
static int hf_http2_headers_user_agent;
504
static int hf_http2_headers_vary;
505
static int hf_http2_headers_via;
506
static int hf_http2_headers_www_authenticate;
507
#endif
508
/* Blocked */
509
/* Origin */
510
static int hf_http2_origin;
511
static int hf_http2_origin_origin_len;
512
static int hf_http2_origin_origin;
513
/* Priority Update */
514
static int hf_http2_priority_update_stream_id;
515
static int hf_http2_priority_update_field_value;
516
/* Generated fields */
517
static int hf_http2_time;
518
static int hf_http2_request_in;
519
static int hf_http2_response_in;
520
521
/*
522
 * These values *should* be large enough to handle most use cases while
523
 * keeping hostile traffic from consuming too many resources. If that's
524
 * not the case we can convert them to preferences. Current (Feb 2016)
525
 * client and server limits:
526
 *
527
 * Apache: 8K (LimitRequestFieldSize), 100 lines (LimitRequestFields)
528
 * Chrome: 256K?
529
 * Firefox: Unknown
530
 * IIS: 16K (MaxRequestBytes)
531
 * Nginx: 8K (large_client_header_buffers)
532
 * Safari: Unknown
533
 * Tomcat: 8K (maxHttpHeaderSize)
534
 */
535
#define MAX_HTTP2_HEADER_SIZE (256 * 1024)
536
#define MAX_HTTP2_HEADER_LINES 200
537
static expert_field ei_http2_header_size;
538
static expert_field ei_http2_header_lines;
539
static expert_field ei_http2_body_decompression_failed;
540
static expert_field ei_http2_reassembly_error;
541
static expert_field ei_http2_window_size;
542
543
static int ett_http2;
544
static int ett_http2_header;
545
static int ett_http2_headers;
546
static int ett_http2_flags;
547
static int ett_http2_settings;
548
static int ett_http2_encoded_entity;
549
static int ett_http2_body_fragment;
550
static int ett_http2_body_fragments;
551
static int ett_http2_origin;
552
553
#ifdef HAVE_NGHTTP2
554
static const fragment_items http2_body_fragment_items = {
555
    /* Fragment subtrees */
556
    &ett_http2_body_fragment,
557
    &ett_http2_body_fragments,
558
    /* Fragment fields */
559
    &hf_http2_body_fragments,
560
    &hf_http2_body_fragment,
561
    &hf_http2_body_fragment_overlap,
562
    &hf_http2_body_fragment_overlap_conflicts,
563
    &hf_http2_body_fragment_multiple_tails,
564
    &hf_http2_body_fragment_too_long_fragment,
565
    &hf_http2_body_fragment_error,
566
    &hf_http2_body_fragment_count,
567
    &hf_http2_body_reassembled_in,
568
    &hf_http2_body_reassembled_length,
569
    &hf_http2_body_reassembled_data,
570
    "Body fragments"
571
};
572
573
/* Due to HPACK compression, we may get lots of relatively large
574
   header fields (e.g., 4KiB).  Allocating each of them requires lots
575
   of memory.  The maximum compression is achieved in HPACK by
576
   referencing header field stored in dynamic table by one or two
577
   bytes.  We reduce memory usage by caching header field in this
578
   wmem_map_t to reuse its memory region when we see the same header
579
   field next time. */
580
static wmem_map_t *http2_hdrcache_map;
581
/* Header name_length + name + value_length + value */
582
static char *http2_header_pstr;
583
#endif
584
585
#ifdef HAVE_NGHTTP2
586
/* Stuff for generation/handling of fields for HTTP2 headers */
587
588
enum header_field_type {
589
    val_string,
590
    val_uint64
591
};
592
593
typedef struct _header_field_t {
594
    char* header_name;
595
    enum header_field_type header_type;
596
    char* header_desc;
597
} header_field_t;
598
599
static header_field_t* header_fields;
600
static unsigned num_header_fields;
601
static unsigned num_header_fields_cleanup;
602
603
static GHashTable* header_fields_hash;
604
605
static bool
606
header_fields_update_cb(void *r, char **err)
607
{
608
    header_field_t *rec = (header_field_t *)r;
609
    char c;
610
611
    if (rec->header_name == NULL) {
612
        *err = g_strdup("Header name can't be empty");
613
        return false;
614
    }
615
616
    g_strstrip(rec->header_name);
617
    if (rec->header_name[0] == 0) {
618
        *err = g_strdup("Header name can't be empty");
619
        return false;
620
    }
621
622
    /* Check for invalid characters (to avoid asserting out when
623
     * registering the field).
624
     */
625
    c = proto_check_field_name(rec->header_name);
626
    if (c) {
627
        *err = ws_strdup_printf("Header name can't contain '%c'", c);
628
        return false;
629
    }
630
631
    /* If the hash table is empty(e.g. on startup), do not try to check a value */
632
    if (header_fields_hash != NULL) {
633
        const int *entry = (const int *) g_hash_table_lookup(header_fields_hash, rec->header_name);
634
        if (entry != NULL) {
635
            *err = ws_strdup_printf("This header field is already defined in UAT or it is a static header field");
636
            return false;
637
        }
638
    }
639
640
    *err = NULL;
641
    return true;
642
}
643
644
static void *
645
header_fields_copy_cb(void* n, const void* o, size_t siz _U_)
646
{
647
    header_field_t* new_rec = (header_field_t*)n;
648
    const header_field_t* old_rec = (const header_field_t*)o;
649
650
    new_rec->header_name = g_strdup(old_rec->header_name);
651
    new_rec->header_type = old_rec->header_type;
652
    new_rec->header_desc = g_strdup(old_rec->header_desc);
653
654
    return new_rec;
655
}
656
657
static void
658
header_fields_free_cb(void*r)
659
{
660
    header_field_t* rec = (header_field_t*)r;
661
662
    g_hash_table_remove(header_fields_hash, rec->header_name);
663
664
    g_free(rec->header_name);
665
    g_free(rec->header_desc);
666
667
}
668
669
static hf_register_info* hf_uat;
670
671
static void
672
deregister_header_fields(void)
673
{
674
    if (hf_uat) {
675
        for (unsigned i = 0; i < num_header_fields_cleanup; ++i) {
676
            proto_deregister_field(proto_http2, *(hf_uat[i].p_id));
677
            g_free(hf_uat[i].p_id);
678
        }
679
        proto_add_deregistered_data(hf_uat);
680
        hf_uat = NULL;
681
        num_header_fields_cleanup = 0;
682
    }
683
684
    /* header_fields_hash also contains the static header list (used for
685
     * look ups to avoid duplicate entries, so we don't destroy it here.
686
     * The dynamic entries are removed from the hash table in
687
     * header_fields_free_cb().
688
     */
689
}
690
691
static void
692
header_fields_post_update_cb(void)
693
{
694
    int* hf_id;
695
    char* header_name;
696
    char* header_name_key;
697
698
    deregister_header_fields();
699
700
    /* Add to hash table headers from UAT */
701
    if (num_header_fields) {
702
        hf_uat = g_new0(hf_register_info, num_header_fields);
703
        num_header_fields_cleanup = num_header_fields;
704
705
        for (unsigned i = 0; i < num_header_fields; i++) {
706
            hf_id = g_new(int,1);
707
            *hf_id = 0;
708
            header_name = g_strdup(header_fields[i].header_name);
709
            header_name_key = g_ascii_strdown(header_name, -1);
710
711
            hf_uat[i].p_id = hf_id;
712
            hf_uat[i].hfinfo.name = header_name;
713
            hf_uat[i].hfinfo.abbrev = ws_strdup_printf("http2.headers.%s", header_name);
714
            switch(header_fields[i].header_type) {
715
                case val_uint64:
716
                    hf_uat[i].hfinfo.type = FT_UINT64;
717
                    hf_uat[i].hfinfo.display = BASE_DEC;
718
                    break;
719
                default: // string
720
                    hf_uat[i].hfinfo.type = FT_STRING;
721
                    hf_uat[i].hfinfo.display = BASE_NONE;
722
                    break;
723
            }
724
            hf_uat[i].hfinfo.strings = NULL;
725
            hf_uat[i].hfinfo.bitmask = 0;
726
            hf_uat[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc);
727
            HFILL_INIT(hf_uat[i]);
728
729
            g_hash_table_insert(header_fields_hash, header_name_key, hf_id);
730
        }
731
732
        proto_register_field_array(proto_http2, hf_uat, num_header_fields);
733
    }
734
}
735
736
static void
737
header_fields_reset_cb(void)
738
{
739
    deregister_header_fields();
740
}
741
742
static void
743
register_static_headers(void) {
744
    header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
745
                                               g_free, NULL);
746
747
    /* Here hf[x].hfinfo.name is a header method which is used as key
748
     * for matching ids while processing HTTP2 packets */
749
    static hf_register_info hf[] = {
750
        {
751
            &hf_http2_headers_authority,
752
            {":authority", "http2.headers.authority",
753
                FT_STRING, BASE_NONE, NULL, 0x0,
754
                "Authority portion of the target URI", HFILL}
755
        },
756
        {
757
            &hf_http2_headers_status,
758
                {":status", "http2.headers.status",
759
                 FT_UINT16, BASE_DEC, NULL, 0x0,
760
                 NULL, HFILL}
761
        },
762
        {
763
            &hf_http2_headers_path,
764
                {":path", "http2.headers.path",
765
                 FT_STRING, BASE_NONE, NULL, 0x0,
766
                 NULL, HFILL}
767
        },
768
        {
769
            &hf_http2_headers_method,
770
                {":method", "http2.headers.method",
771
                 FT_STRING, BASE_NONE, NULL, 0x0,
772
                 NULL, HFILL}
773
        },
774
        {
775
            &hf_http2_headers_scheme,
776
                {":scheme", "http2.headers.scheme",
777
                 FT_STRING, BASE_NONE, NULL, 0x0,
778
                 NULL, HFILL}
779
        },
780
        {
781
            &hf_http2_headers_protocol,
782
                {":protocol", "http2.headers.protocol",
783
                 FT_STRING, BASE_NONE, NULL, 0x0,
784
                 NULL, HFILL}
785
        },
786
        {
787
            &hf_http2_headers_accept,
788
                {"accept", "http2.headers.accept",
789
                 FT_STRING, BASE_NONE, NULL, 0x0,
790
                 "Media types that are acceptable to the user agent", HFILL}
791
        },
792
        {
793
            &hf_http2_headers_accept_charset,
794
                {"accept-charset", "http2.headers.accept_charset",
795
                 FT_STRING, BASE_NONE, NULL, 0x0,
796
                 "Acceptable charsets in textual responses for the user agent", HFILL}
797
        },
798
        {
799
            &hf_http2_headers_accept_encoding,
800
                {"accept-encoding", "http2.headers.accept_encoding",
801
                 FT_STRING, BASE_NONE, NULL, 0x0,
802
                 "Acceptable content codings (like compression) in responses for the user agent", HFILL}
803
        },
804
        {
805
            &hf_http2_headers_accept_language,
806
                {"accept-language", "http2.headers.accept_language",
807
                 FT_STRING, BASE_NONE, NULL, 0x0,
808
                 "Preferred natural languages for the user agent", HFILL}
809
        },
810
        {
811
            &hf_http2_headers_accept_ranges,
812
                {"accept-ranges", "http2.headers.accept_ranges",
813
                 FT_STRING, BASE_NONE, NULL, 0x0,
814
                 "Bytes range which server may use for partial data transfer", HFILL}
815
        },
816
        {
817
            &hf_http2_headers_access_control_allow_origin,
818
                {"access-control-allow-origin", "http2.headers.access_control_allow_origin",
819
                 FT_STRING, BASE_NONE, NULL, 0x0,
820
                 "Origin control for cross-origin resource sharing", HFILL}
821
        },
822
        {
823
            &hf_http2_headers_age,
824
                {"age", "http2.headers.age",
825
                 FT_UINT64, BASE_DEC, NULL, 0x0,
826
                 "Time in seconds which was spent for transferring data through proxy", HFILL}
827
        },
828
        {
829
            &hf_http2_headers_allow,
830
                {"allow", "http2.headers.allow",
831
                 FT_STRING, BASE_NONE, NULL, 0x0,
832
                 "List of allowed methods for request", HFILL}
833
        },
834
        {
835
            &hf_http2_headers_authorization,
836
                {"authorization", "http2.headers.authorization",
837
                 FT_STRING, BASE_NONE, NULL, 0x0,
838
                 "Credentials for a server-side authorization", HFILL}
839
        },
840
        {
841
            &hf_http2_headers_cache_control,
842
                {"cache-control", "http2.headers.cache_control",
843
                 FT_STRING, BASE_NONE, NULL, 0x0,
844
                 "Request or response directives for a cache control", HFILL}
845
        },
846
        {
847
            &hf_http2_headers_content_disposition,
848
                {"content-disposition", "http2.headers.content_disposition",
849
                 FT_STRING, BASE_NONE, NULL, 0x0,
850
                 "Indicates that response will be displayed as page or downloaded with dialog box", HFILL}
851
        },
852
        {
853
            &hf_http2_headers_content_encoding,
854
                {"content-encoding", "http2.headers.content_encoding",
855
                 FT_STRING, BASE_NONE, NULL, 0x0,
856
                 NULL, HFILL}
857
        },
858
        {
859
            &hf_http2_headers_content_language,
860
                {"content-language", "http2.headers.content_language",
861
                 FT_STRING, BASE_NONE, NULL, 0x0,
862
                 NULL, HFILL}
863
        },
864
        {
865
            &hf_http2_headers_content_length,
866
                {"content-length", "http2.headers.content_length",
867
                 FT_UINT64, BASE_DEC, NULL, 0x0,
868
                 "Size of body in bytes", HFILL}
869
        },
870
        {
871
            &hf_http2_headers_content_location,
872
                {"content-location", "http2.headers.content_location",
873
                 FT_STRING, BASE_NONE, NULL, 0x0,
874
                 "Alternative URL for a response data", HFILL}
875
        },
876
        {
877
            &hf_http2_headers_content_range,
878
                {"content-range", "http2.headers.content_range",
879
                 FT_STRING, BASE_NONE, NULL, 0x0,
880
                 "Range of bytes which was sent by server for partial data transfer", HFILL}
881
        },
882
        {
883
            &hf_http2_headers_content_type,
884
                {"content-type", "http2.headers.content_type",
885
                 FT_STRING, BASE_NONE, NULL, 0x0,
886
                 "MIME type of response", HFILL}
887
        },
888
        {
889
            &hf_http2_headers_cookie,
890
                {"cookie", "http2.headers.cookie",
891
                 FT_STRING, BASE_NONE, NULL, 0x0,
892
                 "Stored cookies", HFILL}
893
        },
894
        {
895
            &hf_http2_headers_date,
896
                {"date", "http2.headers.date",
897
                 FT_STRING, BASE_NONE, NULL, 0x0,
898
                 "Date and time at which the data was originated", HFILL}
899
        },
900
        {
901
            &hf_http2_headers_etag,
902
                {"etag", "http2.headers.etag",
903
                 FT_STRING, BASE_NONE, NULL, 0x0,
904
                 "Directive for version indication of resource", HFILL}
905
        },
906
        {
907
            &hf_http2_headers_expect,
908
                {"expect", "http2.headers.expect",
909
                 FT_STRING, BASE_NONE, NULL, 0x0,
910
                 "Expectations that need to be fulfilled for correct request", HFILL}
911
        },
912
        {
913
            &hf_http2_headers_expires,
914
                {"expires", "http2.headers.expires",
915
                 FT_STRING, BASE_NONE, NULL, 0x0,
916
                 "Data after which resource will be stale", HFILL}
917
        },
918
        {
919
            &hf_http2_headers_from,
920
                {"from", "http2.headers.from",
921
                 FT_STRING, BASE_NONE, NULL, 0x0,
922
                 "Email of a person who responsible for a requesting data", HFILL}
923
        },
924
        {
925
            &hf_http2_headers_if_match,
926
                {"if-match", "http2.headers.if_match",
927
                 FT_STRING, BASE_NONE, NULL, 0x0,
928
                 "Mechanism for requesting data matched by a list of ETags", HFILL}
929
        },
930
        {
931
            &hf_http2_headers_if_modified_since,
932
                {"if-modified-since", "http2.headers.if_modified_since",
933
                 FT_STRING, BASE_NONE, NULL, 0x0,
934
                 "Resource will be sent with status code 200 if it was modified otherwise with status code 304", HFILL}
935
        },
936
        {
937
            &hf_http2_headers_if_none_match,
938
                {"if-none-match", "http2.headers.if_none_match",
939
                 FT_STRING, BASE_NONE, NULL, 0x0,
940
                 "Mechanism for requesting data not matched by a list of ETags", HFILL}
941
        },
942
        {
943
            &hf_http2_headers_if_range,
944
                {"if-range", "http2.headers.if_range",
945
                 FT_STRING, BASE_NONE, NULL, 0x0,
946
                 "Mechanism for a range request which is used to check if a resource was modified", HFILL}
947
        },
948
        {
949
            &hf_http2_headers_if_unmodified_since,
950
                {"if-unmodified-since", "http2.headers.if_unmodified_since",
951
                 FT_STRING, BASE_NONE, NULL, 0x0,
952
                 "Resource will be processed if it was not modified otherwise 412 error will be returned", HFILL}
953
        },
954
        {
955
            &hf_http2_headers_last_modified,
956
                {"last-modified", "http2.headers.last_modified",
957
                 FT_STRING, BASE_NONE, NULL, 0x0,
958
                 "Date and time at which the origin server believes the resource was last modified", HFILL}
959
        },
960
        {
961
            &hf_http2_headers_link,
962
                {"link", "http2.headers.link",
963
                 FT_STRING, BASE_NONE, NULL, 0x0,
964
                 "Mechanism for indicating that resource will be preloaded", HFILL}
965
        },
966
        {
967
            &hf_http2_headers_location,
968
                {"location", "http2.headers.location",
969
                 FT_STRING, BASE_NONE, NULL, 0x0,
970
                 "Mechanism for indicating that client will be redirected", HFILL}
971
        },
972
        {
973
            &hf_http2_headers_max_forwards,
974
                {"max-forwards", "http2.headers.max_forwards",
975
                 FT_UINT64, BASE_DEC, NULL, 0x0,
976
                 "Mechanism for limiting the number of proxies", HFILL}
977
        },
978
        {
979
            &hf_http2_headers_proxy_authenticate,
980
                {"proxy-authenticate", "http2.headers.proxy_authenticate",
981
                 FT_STRING, BASE_NONE, NULL, 0x0,
982
                 "Authentication method that should be used to gain access to a resource behind a proxy server", HFILL}
983
        },
984
        {
985
            &hf_http2_headers_proxy_authorization,
986
                {"proxy-authorization", "http2.headers.proxy_authorization",
987
                 FT_STRING, BASE_NONE, NULL, 0x0,
988
                 "Credentials for a proxy-side authorization", HFILL}
989
        },
990
        {
991
            &hf_http2_headers_range,
992
                {"range", "http2.headers.range",
993
                 FT_STRING, BASE_NONE, NULL, 0x0,
994
                 "Range of resource bytes that server should return", HFILL}
995
        },
996
        {
997
            &hf_http2_headers_referer,
998
                {"referer", "http2.headers.referer",
999
                 FT_STRING, BASE_NONE, NULL, 0x0,
1000
                 "Address of the previous web page", HFILL}
1001
        },
1002
        {
1003
            &hf_http2_headers_refresh,
1004
                {"refresh", "http2.headers.refresh",
1005
                 FT_STRING, BASE_NONE, NULL, 0x0,
1006
                 "Time in seconds after which client will be redirected by given url", HFILL}
1007
        },
1008
        {
1009
            &hf_http2_headers_retry_after,
1010
                {"retry-after", "http2.headers.retry_after",
1011
                 FT_STRING, BASE_NONE, NULL, 0x0,
1012
                 "Mechanism to indicate when resource expected to be available", HFILL}
1013
        },
1014
        {
1015
            &hf_http2_headers_server,
1016
                {"server", "http2.headers.server",
1017
                 FT_STRING, BASE_NONE, NULL, 0x0,
1018
                 "Information about server software", HFILL}
1019
        },
1020
        {
1021
            &hf_http2_headers_set_cookie,
1022
                {"set-cookie", "http2.headers.set_cookie",
1023
                 FT_STRING, BASE_NONE, NULL, 0x0,
1024
                 "Send a cookie to the client", HFILL}
1025
        },
1026
        {
1027
            &hf_http2_headers_strict_transport_security,
1028
                {"strict-transport-security", "http2.headers.strict_transport_security",
1029
                 FT_STRING, BASE_NONE, NULL, 0x0,
1030
                 "HSTS indicates that resource should be accessed only using HTTPS", HFILL}
1031
        },
1032
        {
1033
            &hf_http2_headers_user_agent,
1034
                {"user-agent", "http2.headers.user_agent",
1035
                 FT_STRING, BASE_NONE, NULL, 0x0,
1036
                 "Information about client software", HFILL}
1037
        },
1038
        {
1039
            &hf_http2_headers_vary,
1040
                {"vary", "http2.headers.vary",
1041
                 FT_STRING, BASE_NONE, NULL, 0x0,
1042
                 "Mechanism for selecting which header will be used for content negotiation algorithm", HFILL}
1043
        },
1044
        {
1045
            &hf_http2_headers_via,
1046
                {"via", "http2.headers.via",
1047
                 FT_STRING, BASE_NONE, NULL, 0x0,
1048
                 "Additional information for loop detection and protocol capabilities in proxy requests", HFILL}
1049
        },
1050
        {
1051
            &hf_http2_headers_www_authenticate,
1052
                {"www-authenticate", "http2.headers.www_authenticate",
1053
                 FT_STRING, BASE_NONE, NULL, 0x0,
1054
                 "Authentication method that should be used to gain access to a resource", HFILL}
1055
        }
1056
    };
1057
    char* header_name;
1058
    for (unsigned i = 0; i < G_N_ELEMENTS(hf); ++i) {
1059
        header_name = g_strdup(hf[i].hfinfo.name);
1060
1061
        g_hash_table_insert(header_fields_hash, header_name, &hf[i].hfinfo.id);
1062
    }
1063
    proto_register_field_array(proto_http2, hf, G_N_ELEMENTS(hf));
1064
}
1065
1066
UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)
1067
UAT_VS_DEF(header_fields, header_type, header_field_t, enum header_field_type, val_string, "string")
1068
UAT_CSTRING_CB_DEF(header_fields, header_desc, header_field_t)
1069
1070
/* message/stream direction (to or from server) vals */
1071
#define http2_direction_type_vals_VALUE_STRING_LIST(XXX)    \
1072
    XXX(DIRECTION_IN, 0, "IN")  \
1073
    XXX(DIRECTION_OUT, 1, "OUT")
1074
1075
typedef VALUE_STRING_ENUM(http2_direction_type_vals) http2_direction_type;
1076
VALUE_STRING_ARRAY(http2_direction_type_vals);
1077
1078
/* The fake headers will be used if the HEADERS frame before the first DATA is missing. */
1079
typedef struct {
1080
    range_t* server_port_range;
1081
    uint32_t stream_id; /* 0 means applicable to all streams */
1082
    http2_direction_type direction;
1083
    char* header_name;
1084
    char* header_value;
1085
    bool override; /* override existing header */
1086
    bool enable; /* enable or disable this rule */
1087
} http2_fake_header_t;
1088
1089
static http2_fake_header_t* http2_fake_headers;
1090
static unsigned num_http2_fake_headers;
1091
1092
static void*
1093
http2_fake_headers_copy_cb(void* n, const void* o, size_t siz _U_)
1094
{
1095
    http2_fake_header_t* new_rec = (http2_fake_header_t*)n;
1096
    const http2_fake_header_t* old_rec = (const http2_fake_header_t*)o;
1097
1098
    /* copy values like uint32_t */
1099
    memcpy(new_rec, old_rec, sizeof(http2_fake_header_t));
1100
1101
    if (old_rec->server_port_range)
1102
        new_rec->server_port_range = range_copy(NULL, old_rec->server_port_range);
1103
1104
    new_rec->header_name = g_strdup(old_rec->header_name);
1105
    new_rec->header_value = g_strdup(old_rec->header_value);
1106
1107
    return new_rec;
1108
}
1109
1110
static bool
1111
http2_fake_headers_update_cb(void* r, char** err)
1112
{
1113
    http2_fake_header_t* rec = (http2_fake_header_t*)r;
1114
    static range_t* empty;
1115
1116
    empty = range_empty(NULL);
1117
    if (ranges_are_equal(rec->server_port_range, empty)) {
1118
        *err = g_strdup("Must specify server port(s) (like 50051 or 50051,60051-60054)");
1119
        wmem_free(NULL, empty);
1120
        return false;
1121
    }
1122
1123
    wmem_free(NULL, empty);
1124
1125
    /* Check header_name */
1126
    if (rec->header_name == NULL) {
1127
        *err = g_strdup("Header name can't be empty");
1128
        return false;
1129
    }
1130
1131
    g_strstrip(rec->header_name);
1132
    if (rec->header_name[0] == 0) {
1133
        *err = g_strdup("Header name can't be empty");
1134
        return false;
1135
    }
1136
1137
    /* check value */
1138
    if (rec->header_value == NULL) {
1139
        *err = g_strdup("Header value can't be empty");
1140
        return false;
1141
    }
1142
1143
    g_strstrip(rec->header_value);
1144
    if (rec->header_name[0] == 0) {
1145
        *err = g_strdup("Header value can't be empty");
1146
        return false;
1147
    }
1148
1149
    *err = NULL;
1150
    return true;
1151
}
1152
1153
static void
1154
http2_fake_headers_free_cb(void* r)
1155
{
1156
    http2_fake_header_t* rec = (http2_fake_header_t*)r;
1157
1158
    wmem_free(NULL, rec->server_port_range);
1159
    g_free(rec->header_name);
1160
    g_free(rec->header_value);
1161
}
1162
1163
UAT_RANGE_CB_DEF(http2_fake_headers, server_port_range, http2_fake_header_t)
1164
UAT_DEC_CB_DEF(http2_fake_headers, stream_id, http2_fake_header_t)
1165
UAT_VS_DEF(http2_fake_headers, direction, http2_fake_header_t, http2_direction_type,
1166
    DIRECTION_IN, try_val_to_str(DIRECTION_IN, http2_direction_type_vals))
1167
UAT_CSTRING_CB_DEF(http2_fake_headers, header_name, http2_fake_header_t)
1168
UAT_CSTRING_CB_DEF(http2_fake_headers, header_value, http2_fake_header_t)
1169
UAT_BOOL_CB_DEF(http2_fake_headers, override, http2_fake_header_t)
1170
UAT_BOOL_CB_DEF(http2_fake_headers, enable, http2_fake_header_t)
1171
1172
static const char*
1173
get_fake_header_value(packet_info* pinfo, const char* name, bool the_other_direction, bool* override)
1174
{
1175
    if (num_http2_fake_headers == 0) {
1176
        return NULL;
1177
    }
1178
1179
    http2_direction_type direction;
1180
    range_t* server_port_range;
1181
    uint32_t stream_id = http2_get_stream_id(pinfo);
1182
1183
    for (unsigned i = 0; i < num_http2_fake_headers; i++) {
1184
        http2_fake_header_t* fake_header = http2_fake_headers + i;
1185
1186
        if (fake_header->enable == false ||
1187
            (fake_header->stream_id > 0 && fake_header->stream_id != stream_id)) {
1188
            continue;
1189
        }
1190
1191
        server_port_range = fake_header->server_port_range;
1192
        if (value_is_in_range(server_port_range, pinfo->destport)) {
1193
            direction = the_other_direction ? DIRECTION_OUT : DIRECTION_IN;
1194
        } else if (value_is_in_range(server_port_range, pinfo->srcport)) {
1195
            direction = the_other_direction ? DIRECTION_IN : DIRECTION_OUT;
1196
        } else {
1197
            continue;
1198
        }
1199
1200
        if (fake_header->direction == direction && strcmp(fake_header->header_name, name) == 0) {
1201
            if(override) {
1202
                *override = fake_header->override;
1203
            }
1204
            return wmem_strdup(pinfo->pool, fake_header->header_value);
1205
        }
1206
    }
1207
1208
    return NULL;
1209
}
1210
#endif
1211
1212
static void
1213
http2_init_protocol(void)
1214
14
{
1215
    /* Init hash table with mapping of stream id -> frames count for Follow HTTP2 */
1216
14
    streamid_hash = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)g_hash_table_destroy);
1217
14
}
1218
1219
static void
1220
0
http2_cleanup_protocol(void) {
1221
0
    g_hash_table_destroy(streamid_hash);
1222
0
}
1223
1224
static dissector_handle_t http2_handle;
1225
static dissector_handle_t data_handle;
1226
1227
static reassembly_table http2_body_reassembly_table;
1228
static reassembly_table http2_streaming_reassembly_table;
1229
1230
717
#define FRAME_HEADER_LENGTH     9
1231
4.33k
#define MAGIC_FRAME_LENGTH      24
1232
250
#define MAGIC_FRAME_FIRST_LINE  16
1233
56
#define MASK_HTTP2_RESERVED     0x80000000
1234
286
#define MASK_HTTP2_STREAMID     0X7FFFFFFF
1235
42
#define MASK_HTTP2_PRIORITY     0X7FFFFFFF
1236
1237
/* Header Type Code */
1238
289
#define HTTP2_DATA              0
1239
26
#define HTTP2_HEADERS           1
1240
4
#define HTTP2_PRIORITY          2
1241
6
#define HTTP2_RST_STREAM        3
1242
56
#define HTTP2_SETTINGS          4
1243
8
#define HTTP2_PUSH_PROMISE      5
1244
7
#define HTTP2_PING              6
1245
6
#define HTTP2_GOAWAY            7
1246
15
#define HTTP2_WINDOW_UPDATE     8
1247
4
#define HTTP2_CONTINUATION      9
1248
12
#define HTTP2_ALTSVC            0xA
1249
17
#define HTTP2_ORIGIN            0xC
1250
16
#define HTTP2_PRIORITY_UPDATE   0x10
1251
1252
static const value_string http2_type_vals[] = {
1253
    { HTTP2_DATA,            "DATA" },
1254
    { HTTP2_HEADERS,         "HEADERS" },
1255
    { HTTP2_PRIORITY,        "PRIORITY" },
1256
    { HTTP2_RST_STREAM,      "RST_STREAM" },
1257
    { HTTP2_SETTINGS,        "SETTINGS" },
1258
    { HTTP2_PUSH_PROMISE,    "PUSH_PROMISE" },
1259
    { HTTP2_PING,            "PING" },
1260
    { HTTP2_GOAWAY,          "GOAWAY" },
1261
    { HTTP2_WINDOW_UPDATE,   "WINDOW_UPDATE" },
1262
    { HTTP2_CONTINUATION,    "CONTINUATION" },
1263
    { HTTP2_ALTSVC,          "ALTSVC" },
1264
    { HTTP2_ORIGIN,          "ORIGIN" },
1265
    { HTTP2_PRIORITY_UPDATE, "PRIORITY_UPDATE" },
1266
    { 0, NULL }
1267
};
1268
1269
/* Flags */
1270
59
#define HTTP2_FLAGS_ACK         0x01 /* for PING and SETTINGS */
1271
1272
42
#define HTTP2_FLAGS_END_STREAM  0x01
1273
56
#define HTTP2_FLAGS_END_HEADERS 0x04
1274
219
#define HTTP2_FLAGS_PADDED      0x08
1275
45
#define HTTP2_FLAGS_PRIORITY    0x20
1276
1277
14
#define HTTP2_FLAGS_UNUSED 0xFF
1278
14
#define HTTP2_FLAGS_UNUSED_SETTINGS (~HTTP2_FLAGS_ACK & 0xFF)
1279
14
#define HTTP2_FLAGS_UNUSED_PING (~HTTP2_FLAGS_ACK & 0xFF)
1280
14
#define HTTP2_FLAGS_UNUSED_CONTINUATION (~HTTP2_FLAGS_END_HEADERS & 0xFF)
1281
#define HTTP2_FLAGS_UNUSED_PUSH_PROMISE \
1282
14
    (~(HTTP2_FLAGS_END_HEADERS | HTTP2_FLAGS_PADDED) & 0xFF)
1283
#define HTTP2_FLAGS_UNUSED_DATA \
1284
14
    (~(HTTP2_FLAGS_END_STREAM | HTTP2_FLAGS_PADDED) & 0xFF)
1285
#define HTTP2_FLAGS_UNUSED_HEADERS \
1286
14
    (~(HTTP2_FLAGS_END_STREAM | HTTP2_FLAGS_END_HEADERS | \
1287
14
       HTTP2_FLAGS_PADDED | HTTP2_FLAGS_PRIORITY) & 0xFF)
1288
1289
#define HTTP2_FLAGS_R           0xFF
1290
#define HTTP2_FLAGS_R1          0xFE
1291
#define HTTP2_FLAGS_R2          0xFA
1292
#define HTTP2_FLAGS_R4          0xFB
1293
1294
/* header matching helpers */
1295
#define IS_HTTP2_END_STREAM(flags)   (flags & HTTP2_FLAGS_END_STREAM)
1296
1297
/* Magic Header : PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n */
1298
static    uint8_t kMagicHello[] = {
1299
        0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,
1300
        0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,
1301
        0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
1302
};
1303
1304
/* Error Codes */
1305
#define EC_NO_ERROR             0x0
1306
#define EC_PROTOCOL_ERROR       0x1
1307
#define EC_INTERNAL_ERROR       0x2
1308
#define EC_FLOW_CONTROL_ERROR   0x3
1309
#define EC_SETTINGS_TIMEOUT     0x4
1310
#define EC_STREAM_CLOSED        0x5
1311
#define EC_FRAME_SIZE_ERROR     0x6
1312
#define EC_REFUSED_STREAM       0x7
1313
#define EC_CANCEL               0x8
1314
#define EC_COMPRESSION_ERROR    0x9
1315
#define EC_CONNECT_ERROR        0xa
1316
#define EC_ENHANCE_YOUR_CALM    0xb
1317
#define EC_INADEQUATE_SECURITY  0xc
1318
#define EC_HTTP_1_1_REQUIRED    0xd
1319
1320
1321
static const value_string http2_error_codes_vals[] = {
1322
    { EC_NO_ERROR,              "NO_ERROR" },
1323
    { EC_PROTOCOL_ERROR,        "PROTOCOL_ERROR" },
1324
    { EC_INTERNAL_ERROR,        "INTERNAL_ERROR" },
1325
    { EC_FLOW_CONTROL_ERROR,    "FLOW_CONTROL_ERROR" },
1326
    { EC_SETTINGS_TIMEOUT,      "SETTINGS_TIMEOUT" },
1327
    { EC_STREAM_CLOSED,         "STREAM_CLOSED" },
1328
    { EC_FRAME_SIZE_ERROR,      "FRAME_SIZE_ERROR" },
1329
    { EC_REFUSED_STREAM,        "REFUSED_STREAM" },
1330
    { EC_CANCEL,                "CANCEL" },
1331
    { EC_COMPRESSION_ERROR,     "COMPRESSION_ERROR" },
1332
    { EC_CONNECT_ERROR,         "CONNECT_ERROR" },
1333
    { EC_ENHANCE_YOUR_CALM,     "ENHANCE_YOUR_CALM" },
1334
    { EC_INADEQUATE_SECURITY,   "INADEQUATE_SECURITY" },
1335
    { EC_HTTP_1_1_REQUIRED,     "HTTP_1_1_REQUIRED" },
1336
    { 0, NULL }
1337
};
1338
1339
/* Settings */
1340
9
#define HTTP2_SETTINGS_HEADER_TABLE_SIZE        1
1341
14
#define HTTP2_SETTINGS_ENABLE_PUSH              2
1342
17
#define HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS   3
1343
14
#define HTTP2_SETTINGS_INITIAL_WINDOW_SIZE      4
1344
6
#define HTTP2_SETTINGS_MAX_FRAME_SIZE           5
1345
11
#define HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE     6
1346
11
#define HTTP2_SETTINGS_EXTENDED_CONNECT         8 /* RFC 8441 */
1347
0
#define HTTP2_SETTINGS_NO_RFC7540_PRIORITIES    9 /* RFC 9218 */
1348
2
#define HTTP2_SETTINGS_TLS_RENEG_PERMITTED     16 /* MS-HTTP2E */
1349
1350
static const value_string http2_settings_vals[] = {
1351
    { HTTP2_SETTINGS_HEADER_TABLE_SIZE,      "Header table size" },
1352
    { HTTP2_SETTINGS_ENABLE_PUSH,            "Enable PUSH" },
1353
    { HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, "Max concurrent streams" },
1354
    { HTTP2_SETTINGS_INITIAL_WINDOW_SIZE,    "Initial Windows size" },
1355
    { HTTP2_SETTINGS_MAX_FRAME_SIZE,         "Max frame size" },
1356
    { HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,   "Max header list size" },
1357
    { HTTP2_SETTINGS_EXTENDED_CONNECT,       "Extended CONNECT" },
1358
    { HTTP2_SETTINGS_NO_RFC7540_PRIORITIES,  "No RFC7540 Priorities" },
1359
    { HTTP2_SETTINGS_TLS_RENEG_PERMITTED,    "TLS Renegotiation Permitted" },
1360
    { 0, NULL }
1361
};
1362
1363
static const value_string http2_tls_reneg_permitted_vals[] = {
1364
    { 0x00, "Disabled" },
1365
    { 0x01, "Client-initiated acceptable" },
1366
    { 0x02, "Server-initiated acceptable" },
1367
    { 0x03, "Initiation from any party acceptable" },
1368
    { 0, NULL }
1369
};
1370
1371
/*
1372
 * "When an HTTP/2 connection is first established, new streams
1373
 *  are created with an initial flow-control window size of 65,535
1374
 *  octets. The connection flow-control window is also 65,535
1375
 *  octets. Both endpoints can adjust the initial window size for
1376
 *  new streams by including a value for SETTINGS_INITIAL_WINDOW_SIZE
1377
 *  in the SETTINGS frame. The connection flow-control window can
1378
 *  only be changed using WINDOW_UPDATE frames."
1379
 * https://www.ietf.org/rfc/rfc9113.html#section-6.9.2-1
1380
 */
1381
244
#define INITIAL_WINDOW_SIZE 65535
1382
1383
static uint32_t
1384
select_http2_flow_index(packet_info *pinfo, http2_session_t *h2session)
1385
145
{
1386
145
    struct tcp_analysis *tcpd;
1387
1388
145
    tcpd = get_tcp_conversation_data(NULL, pinfo);
1389
1390
145
    if(tcpd->fwd == h2session->fwd_flow) {
1391
145
        return 0;
1392
145
    } else {
1393
0
        return 1;
1394
0
    }
1395
145
}
1396
1397
#ifdef HAVE_NGHTTP2
1398
static bool
1399
hd_inflate_del_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data)
1400
{
1401
    nghttp2_hd_inflate_del((nghttp2_hd_inflater*)user_data);
1402
    http2_hdrcache_map = NULL;
1403
    http2_header_pstr = NULL;
1404
1405
    return false;
1406
}
1407
1408
static http2_stream_info_t*
1409
get_stream_info_for_id(packet_info *pinfo, http2_session_t *http2_session, bool initializeOppositeDirection, uint32_t stream_id)
1410
{
1411
    wmem_map_t *stream_map = http2_session->per_stream_info;
1412
    uint32_t flow_index = select_http2_flow_index(pinfo, http2_session);
1413
1414
    http2_stream_info_t *stream_info = (http2_stream_info_t *)wmem_map_lookup(stream_map, GINT_TO_POINTER(stream_id));
1415
    if (stream_info == NULL) {
1416
        stream_info = wmem_new0(wmem_file_scope(), http2_stream_info_t);
1417
        stream_info->oneway_stream_info[0].header_stream_info.stream_header_list = wmem_list_new(wmem_file_scope());
1418
        stream_info->oneway_stream_info[1].header_stream_info.stream_header_list = wmem_list_new(wmem_file_scope());
1419
        stream_info->stream_id = stream_id;
1420
        stream_info->oneway_stream_info[0].header_stream_info.stream_id = stream_id;
1421
        stream_info->oneway_stream_info[1].header_stream_info.stream_id = stream_id;
1422
        stream_info->reassembly_mode = HTTP2_DATA_REASSEMBLY_MODE_END_STREAM;
1423
        stream_info->oneway_stream_info[0].is_window_initialized = false;
1424
        stream_info->oneway_stream_info[0].current_window_size = INITIAL_WINDOW_SIZE;
1425
        stream_info->oneway_stream_info[1].is_window_initialized = false;
1426
        stream_info->oneway_stream_info[1].current_window_size = INITIAL_WINDOW_SIZE;
1427
        nstime_set_unset(&(stream_info->request_ts));
1428
        wmem_map_insert(stream_map, GINT_TO_POINTER(stream_id), stream_info);
1429
    }
1430
1431
    /* The first time the stream info is requested for a
1432
     * particular direction, initialize the window size
1433
     * in that direction to the current initial window size for
1434
     * that direction. Flip what we're checking around if
1435
     * initializeOppositeDirection is true.
1436
     */
1437
    if (initializeOppositeDirection) {
1438
        flow_index ^= 1;
1439
    }
1440
    if (!stream_info->oneway_stream_info[flow_index].is_window_initialized) {
1441
        stream_info->oneway_stream_info[flow_index].current_window_size = http2_session->initial_new_stream_window_size[flow_index];
1442
        stream_info->oneway_stream_info[flow_index].is_window_initialized = true;
1443
    }
1444
1445
    return stream_info;
1446
}
1447
1448
static http2_stream_info_t*
1449
get_stream_info(packet_info *pinfo, http2_session_t *http2_session, bool initializeOppositeDirection)
1450
{
1451
    uint32_t stream_id = http2_session->current_stream_id;
1452
1453
    return get_stream_info_for_id(pinfo, http2_session, initializeOppositeDirection, stream_id);
1454
}
1455
#endif
1456
1457
static http2_session_t*
1458
get_http2_session(packet_info *pinfo, conversation_t* conversation)
1459
325
{
1460
325
    http2_session_t *h2session;
1461
1462
325
    h2session = (http2_session_t*)conversation_get_proto_data(conversation,
1463
325
                                                              proto_http2);
1464
1465
325
    if(!h2session) {
1466
61
        struct tcp_analysis *tcpd;
1467
1468
61
        tcpd = get_tcp_conversation_data(conversation, pinfo);
1469
1470
61
        h2session = wmem_new0(wmem_file_scope(), http2_session_t);
1471
1472
#ifdef HAVE_NGHTTP2
1473
        nghttp2_hd_inflate_new(&h2session->hd_inflater[0]);
1474
        nghttp2_hd_inflate_new(&h2session->hd_inflater[1]);
1475
1476
        wmem_register_callback(wmem_file_scope(), hd_inflate_del_cb,
1477
                               h2session->hd_inflater[0]);
1478
        wmem_register_callback(wmem_file_scope(), hd_inflate_del_cb,
1479
                               h2session->hd_inflater[1]);
1480
        h2session->per_stream_info = wmem_map_new(wmem_file_scope(),
1481
                                                  g_direct_hash,
1482
                                                  g_direct_equal);
1483
        /* Unless found otherwise, assume that some earlier Header Block
1484
         * Fragments were missing and that recovery should be attempted. */
1485
        h2session->fix_dynamic_table[0] = true;
1486
        h2session->fix_dynamic_table[1] = true;
1487
#endif
1488
1489
61
        h2session->fwd_flow = tcpd->fwd;
1490
61
        h2session->settings_queue[0] = wmem_queue_new(wmem_file_scope());
1491
61
        h2session->settings_queue[1] = wmem_queue_new(wmem_file_scope());
1492
61
        h2session->initial_new_stream_window_size[0] = INITIAL_WINDOW_SIZE;
1493
61
        h2session->initial_new_stream_window_size[1] = INITIAL_WINDOW_SIZE;
1494
61
        h2session->current_connection_window_size[0] = INITIAL_WINDOW_SIZE;
1495
61
        h2session->current_connection_window_size[1] = INITIAL_WINDOW_SIZE;
1496
1497
61
        conversation_add_proto_data(conversation, proto_http2, h2session);
1498
61
    }
1499
1500
325
    return h2session;
1501
325
}
1502
1503
#ifdef HAVE_NGHTTP2
1504
uint32_t
1505
http2_get_stream_id(packet_info *pinfo)
1506
{
1507
    conversation_t *conversation;
1508
    http2_session_t *h2session;
1509
1510
    conversation = find_conversation_pinfo(pinfo, 0);
1511
    if (!conversation) {
1512
        return 0;
1513
    }
1514
1515
    h2session = (http2_session_t*)conversation_get_proto_data(conversation, proto_http2);
1516
    if (!h2session) {
1517
        return 0;
1518
    }
1519
1520
    return h2session->current_stream_id;
1521
}
1522
1523
void
1524
http2_set_stream_imsi(packet_info *pinfo, char* imsi)
1525
{
1526
    conversation_t *conversation;
1527
    http2_session_t *h2session;
1528
    http2_stream_info_t *stream_info;
1529
1530
    conversation = find_conversation_pinfo(pinfo, 0);
1531
    if (!conversation) {
1532
        return;
1533
    }
1534
1535
    h2session = (http2_session_t*)conversation_get_proto_data(conversation, proto_http2);
1536
    if (!h2session) {
1537
        return;
1538
    }
1539
1540
    stream_info = get_stream_info(pinfo, h2session, false);
1541
    if (!stream_info) {
1542
        return;
1543
    }
1544
1545
    stream_info->imsi = wmem_strdup(wmem_file_scope(), imsi);
1546
}
1547
1548
void http2_add_notifyuri_imsi(char* notifyuri, const char* imsi)
1549
{
1550
    if(http2_3gpp_session) {
1551
        wmem_map_insert(http2_notifyuri_imsi,
1552
                        wmem_strdup(wmem_file_scope(), notifyuri),
1553
                        wmem_strdup(wmem_file_scope(), imsi));
1554
    }
1555
}
1556
1557
static char*
1558
http2_get_imsi_from_notifyuri(const char* notifyuri)
1559
{
1560
    char *imsi = NULL;
1561
    if(http2_3gpp_session) {
1562
        imsi = (char *)wmem_map_lookup(http2_notifyuri_imsi,notifyuri);
1563
    }
1564
    return imsi;
1565
}
1566
1567
static void
1568
http2_add_location_imsi(char* location, const char* imsi)
1569
{
1570
    if(http2_3gpp_session) {
1571
        wmem_map_insert(http2_location_imsi,
1572
                        wmem_strdup(wmem_file_scope(), location),
1573
                        wmem_strdup(wmem_file_scope(), imsi));
1574
    }
1575
}
1576
1577
char*
1578
http2_get_imsi_from_location(const char* location)
1579
{
1580
    char *imsi = NULL;
1581
    if(http2_3gpp_session) {
1582
        imsi = (char *)wmem_map_lookup(http2_location_imsi, location);
1583
    }
1584
    return imsi;
1585
}
1586
1587
const char*
1588
http2_get_stream_imsi(packet_info *pinfo)
1589
{
1590
    conversation_t *conversation;
1591
    http2_session_t *h2session;
1592
    http2_stream_info_t *stream_info;
1593
    const char *imsi = NULL;
1594
1595
    conversation = find_conversation_pinfo(pinfo, 0);
1596
    if (!conversation) {
1597
        return NULL;
1598
    }
1599
1600
    h2session = (http2_session_t*)conversation_get_proto_data(conversation, proto_http2);
1601
    if (!h2session) {
1602
        return NULL;
1603
    }
1604
1605
    stream_info = get_stream_info(pinfo, h2session, false);
1606
    if (!stream_info) {
1607
        return NULL;
1608
    }
1609
1610
    if(stream_info->imsi && (strcmp(stream_info->imsi, "") != 0)) {
1611
        imsi = stream_info->imsi;
1612
    }
1613
1614
    if(!imsi && stream_info->referenceid && (strcmp(stream_info->referenceid, "") != 0)) {
1615
        imsi = http2_get_imsi_from_location(stream_info->referenceid);
1616
    }
1617
1618
    if(!imsi && stream_info->path && (strcmp(stream_info->path, "") != 0)) {
1619
        imsi = http2_get_imsi_from_notifyuri(stream_info->path);
1620
    }
1621
    return imsi;
1622
}
1623
1624
static const char*
1625
http2_get_request_full_uri(packet_info *pinfo, http2_session_t *http2_session, uint32_t stream_id)
1626
{
1627
    const char* uri = NULL;
1628
    http2_stream_info_t *stream_info = get_stream_info_for_id(pinfo, http2_session, false, stream_id);
1629
    if (stream_info && stream_info->authority) {
1630
        /* RFC9113 8.3.1:
1631
           "All HTTP/2 requests MUST include exactly one valid value for the
1632
           ":method", ":scheme", and ":path" pseudo-header fields, unless they
1633
           are CONNECT requests"
1634
           RFC8441 4:
1635
           "On requests that contain the :protocol pseudo-header field, the
1636
           :scheme and :path pseudo-header fields of the target URI (see
1637
           Section 5) MUST also be included."
1638
        */
1639
        if (stream_info->is_stream_http_connect && !stream_info->protocol) {
1640
            uri = wmem_strdup(pinfo->pool, stream_info->authority);
1641
        } else {
1642
            uri = wmem_strdup_printf(pinfo->pool, "%s://%s%s", stream_info->scheme, stream_info->authority, stream_info->path);
1643
        }
1644
    }
1645
    return uri;
1646
}
1647
#else /* ! HAVE_NGHTTP2 */
1648
uint32_t
1649
http2_get_stream_id(packet_info *pinfo _U_)
1650
0
{
1651
0
    return 0;
1652
0
}
1653
1654
void
1655
http2_set_stream_imsi(packet_info *pinfo _U_, char* imsi _U_)
1656
0
{
1657
0
    return;
1658
0
}
1659
1660
void http2_add_notifyuri_imsi(char* notifyuri _U_, const char* imsi _U_)
1661
0
{
1662
0
    return;
1663
0
}
1664
1665
char*
1666
http2_get_imsi_from_notifyuri(const char* notifyuri _U_)
1667
0
{
1668
0
    return NULL;
1669
0
}
1670
1671
void http2_add_location_imsi(char* location _U_, const char* imsi _U_)
1672
0
{
1673
0
    return;
1674
0
}
1675
1676
char*
1677
http2_get_imsi_from_location(const char* location _U_)
1678
0
{
1679
0
    return NULL;
1680
0
}
1681
1682
const char*
1683
http2_get_stream_imsi(packet_info *pinf _U_)
1684
0
{
1685
0
    return NULL;
1686
0
}
1687
1688
static const char*
1689
http2_get_request_full_uri(packet_info *pinfo _U_, http2_session_t *http2_session _U_, uint32_t stream_id _U_)
1690
187
{
1691
187
    return NULL;
1692
187
}
1693
#endif /* ! HAVE_NGHTTP2 */
1694
1695
#ifdef HAVE_NGHTTP2
1696
static const char*
1697
get_real_header_value(packet_info* pinfo, const char* name, bool the_other_direction);
1698
1699
static http2_frame_num_t
1700
get_http2_frame_num(tvbuff_t *tvb, packet_info *pinfo)
1701
{
1702
    /* HTTP2 frames are identified as follows:
1703
     *
1704
     * +--- 32 bits ---+--------- 8 bits -------+----- 24 bits -----+
1705
     * |  pinfo->num   | pinfo->curr_layer_num  |  tvb->raw_offset  |
1706
     * +------------------------------------------------------------+
1707
     *
1708
     * This allows for a single HTTP2 frame to be uniquely identified across a capture with the
1709
     * added benefit that the number will always be increasing from the previous HTTP2 frame so
1710
     * we can use "<" and ">" comparisons to determine before and after in time.
1711
     *
1712
     * pinfo->curr_layer_num is used to deliberate when we have multiple TLS records in a
1713
     * single (non-http2) frame. This ends up being dissected using two separate TVBs
1714
     * (so tvb->raw_offset isn't useful) and then end up being the same pinfo->num.
1715
     *
1716
     * I have seen instances where the pinfo->curr_layer_num can change between the first and second
1717
     * pass of a packet so this needs to be taken into account when this is used as an identifier.
1718
     */
1719
    return (((uint64_t)pinfo->num) << 32) + (((uint64_t)pinfo->curr_layer_num) << 24) + ((uint64_t)tvb_raw_offset(tvb));
1720
}
1721
1722
static http2_oneway_stream_info_t*
1723
get_oneway_stream_info_for_id(packet_info *pinfo, http2_session_t* http2_session, bool the_other_direction, uint32_t stream_id)
1724
{
1725
    http2_stream_info_t *http2_stream_info = get_stream_info_for_id(pinfo, http2_session, false, stream_id);
1726
    uint32_t flow_index = select_http2_flow_index(pinfo, http2_session);
1727
    if (the_other_direction) {
1728
        /* need stream info of the other direction,
1729
        so set index from 0 to 1, or from 1 to 0 */
1730
        flow_index ^= 1;
1731
    }
1732
1733
    return &http2_stream_info->oneway_stream_info[flow_index];
1734
}
1735
1736
static http2_oneway_stream_info_t*
1737
get_oneway_stream_info(packet_info *pinfo, http2_session_t* http2_session, bool the_other_direction)
1738
{
1739
    return get_oneway_stream_info_for_id(pinfo, http2_session, the_other_direction, http2_session->current_stream_id);
1740
}
1741
1742
static http2_data_stream_body_info_t*
1743
get_data_stream_body_info_for_id(packet_info *pinfo, http2_session_t* http2_session, uint32_t stream_id)
1744
{
1745
    return &(get_oneway_stream_info_for_id(pinfo, http2_session, false, stream_id)->data_stream_body_info);
1746
}
1747
1748
static http2_data_stream_body_info_t*
1749
get_data_stream_body_info(packet_info *pinfo, http2_session_t* http2_session)
1750
{
1751
    return &(get_oneway_stream_info(pinfo, http2_session, false)->data_stream_body_info);
1752
}
1753
1754
static http2_data_stream_reassembly_info_t*
1755
get_data_reassembly_info_for_id(packet_info *pinfo, http2_session_t* http2_session, uint32_t stream_id)
1756
{
1757
    return &(get_oneway_stream_info_for_id(pinfo, http2_session, false, stream_id)->data_stream_reassembly_info);
1758
}
1759
1760
static http2_data_stream_reassembly_info_t*
1761
get_data_reassembly_info(packet_info *pinfo, http2_session_t* http2_session)
1762
{
1763
    return &(get_oneway_stream_info(pinfo, http2_session, false)->data_stream_reassembly_info);
1764
}
1765
1766
static http2_header_stream_info_t*
1767
get_header_stream_info_for_id(packet_info *pinfo, http2_session_t* http2_session,bool the_other_direction, uint32_t stream_id)
1768
{
1769
    return &(get_oneway_stream_info_for_id(pinfo, http2_session, the_other_direction, stream_id)->header_stream_info);
1770
}
1771
1772
static http2_header_stream_info_t*
1773
get_header_stream_info(packet_info *pinfo, http2_session_t* http2_session,bool the_other_direction)
1774
{
1775
    return &(get_oneway_stream_info(pinfo, http2_session, the_other_direction)->header_stream_info);
1776
}
1777
1778
static void
1779
push_settings(packet_info *pinfo, http2_session_t *h2session,
1780
              http2_settings_t *settings)
1781
{
1782
    wmem_queue_t *queue;
1783
    uint32_t flow_index;
1784
1785
    flow_index = select_http2_flow_index(pinfo, h2session);
1786
1787
    queue = h2session->settings_queue[flow_index];
1788
1789
    wmem_queue_push(queue, settings);
1790
}
1791
1792
static void
1793
apply_and_pop_settings(packet_info *pinfo, http2_session_t *h2session)
1794
{
1795
    wmem_queue_t *queue;
1796
    http2_settings_t *settings;
1797
    nghttp2_hd_inflater *inflater;
1798
    uint32_t flow_index;
1799
1800
    /* When header table size is applied, it affects the inflater of
1801
       opposite side. */
1802
1803
    flow_index = select_http2_flow_index(pinfo, h2session);
1804
1805
    inflater = h2session->hd_inflater[flow_index];
1806
1807
    queue = h2session->settings_queue[flow_index ^ 1];
1808
1809
    if(wmem_queue_count(queue) == 0) {
1810
        return;
1811
    }
1812
1813
    settings = (http2_settings_t*)wmem_queue_pop(queue);
1814
1815
    if(settings->has_header_table_size) {
1816
        if(settings->min_header_table_size < settings->header_table_size) {
1817
            nghttp2_hd_inflate_change_table_size
1818
                (inflater, settings->min_header_table_size);
1819
        }
1820
1821
        nghttp2_hd_inflate_change_table_size(inflater,
1822
                                             settings->header_table_size);
1823
    }
1824
}
1825
1826
/* Decode integer from buf at position p, using prefix bits.  This
1827
   function can be called several times if buf does not contain whole
1828
   integer.  header_repr_info remembers the result of previous call.
1829
   Returns the number bytes processed. */
1830
static unsigned read_integer(http2_header_repr_info_t *header_repr_info,
1831
                          const uint8_t *buf, unsigned len, unsigned p, unsigned prefix)
1832
{
1833
    unsigned k = (1 << prefix) - 1;
1834
    unsigned n = header_repr_info->integer;
1835
    unsigned shift = header_repr_info->next_shift;
1836
1837
    if(n == 0) {
1838
        DISSECTOR_ASSERT(p < len);
1839
1840
        if((buf[p] & k) != k) {
1841
            header_repr_info->integer = buf[p] & k;
1842
            header_repr_info->complete = true;
1843
            return p + 1;
1844
        }
1845
1846
        n = k;
1847
1848
        ++p;
1849
    }
1850
1851
    for(; p < len; ++p, shift += 7) {
1852
        n += (buf[p] & 0x7F) << shift;
1853
1854
        if((buf[p] & 0x80) == 0) {
1855
            header_repr_info->complete = true;
1856
            ++p;
1857
            break;
1858
        }
1859
    }
1860
1861
    header_repr_info->integer = n;
1862
    header_repr_info->next_shift = shift;
1863
    return p;
1864
}
1865
1866
static void
1867
reset_http2_header_repr_info(http2_header_repr_info_t *header_repr_info)
1868
{
1869
    header_repr_info->type = HTTP2_HD_NONE;
1870
    header_repr_info->integer = 0;
1871
    header_repr_info->next_shift = 0;
1872
    header_repr_info->complete = false;
1873
}
1874
1875
/* Reads zero or more header table size update and optionally header
1876
   representation information.  This function returns when first
1877
   header representation is decoded or buf is processed completely.
1878
   This function returns the number bytes processed for header table
1879
   size update. */
1880
static unsigned
1881
process_http2_header_repr_info(wmem_array_t *headers,
1882
                               http2_header_repr_info_t *header_repr_info,
1883
                               const uint8_t *buf, unsigned len)
1884
{
1885
    unsigned i;
1886
    unsigned start;
1887
1888
    if(header_repr_info->type != HTTP2_HD_NONE &&
1889
       header_repr_info->type != HTTP2_HD_HEADER_TABLE_SIZE_UPDATE &&
1890
       header_repr_info->complete) {
1891
        return 0;
1892
    }
1893
1894
    start = 0;
1895
1896
    for(i = 0; i < len;) {
1897
        if(header_repr_info->type == HTTP2_HD_NONE) {
1898
            unsigned char c = buf[i];
1899
            if((c & 0xE0) == 0x20) {
1900
                header_repr_info->type = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE;
1901
1902
                i = read_integer(header_repr_info, buf, len, i, 5);
1903
            } else if(c & 0x80) {
1904
                header_repr_info->type = HTTP2_HD_INDEXED;
1905
                i = read_integer(header_repr_info, buf, len, i, 7);
1906
            } else if(c == 0x40 || c == 0 || c == 0x10) {
1907
                /* New name */
1908
                header_repr_info->complete = true;
1909
                if(c & 0x40) {
1910
                    header_repr_info->type = HTTP2_HD_LITERAL_INDEXING_NEW_NAME;
1911
                } else if((c & 0xF0) == 0x10) {
1912
                    header_repr_info->type = HTTP2_HD_LITERAL_NEVER_INDEXING_NEW_NAME;
1913
                } else {
1914
                    header_repr_info->type = HTTP2_HD_LITERAL_NEW_NAME;
1915
                }
1916
            } else {
1917
                /* indexed name */
1918
                if(c & 0x40) {
1919
                    header_repr_info->type = HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME;
1920
                    i = read_integer(header_repr_info, buf, len, i, 6);
1921
                } else if((c & 0xF0) == 0x10) {
1922
                    header_repr_info->type = HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME;
1923
                    i = read_integer(header_repr_info, buf, len, i, 4);
1924
                } else {
1925
                    header_repr_info->type = HTTP2_HD_LITERAL_INDEXED_NAME;
1926
                    i = read_integer(header_repr_info, buf, len, i, 4);
1927
                }
1928
            }
1929
        } else {
1930
            i = read_integer(header_repr_info, buf, len, i, 8);
1931
        }
1932
1933
        if(header_repr_info->complete) {
1934
            if(header_repr_info->type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE) {
1935
                http2_header_t *out;
1936
1937
                out = wmem_new(wmem_file_scope(), http2_header_t);
1938
1939
                out->type = header_repr_info->type;
1940
                out->length = i - start;
1941
                out->table.header_table_size = header_repr_info->integer;
1942
1943
                wmem_array_append(headers, out, 1);
1944
1945
                reset_http2_header_repr_info(header_repr_info);
1946
                /* continue to decode header table size update or
1947
                   first header encoding is encountered. */
1948
                start = i;
1949
            } else {
1950
                /* Break on first header encoding */
1951
                break;
1952
            }
1953
        }
1954
    }
1955
1956
    return start;
1957
}
1958
1959
static size_t http2_hdrcache_length(const void *vv)
1960
{
1961
    const uint8_t *v = (const uint8_t *)vv;
1962
    uint32_t namelen, valuelen;
1963
1964
    namelen = pntohu32(v);
1965
    valuelen = pntohu32(v + sizeof(namelen) + namelen);
1966
1967
    return namelen + valuelen + sizeof(namelen) + sizeof(valuelen);
1968
}
1969
1970
static unsigned http2_hdrcache_hash(const void *key)
1971
{
1972
    return wmem_strong_hash((const uint8_t *)key, http2_hdrcache_length(key));
1973
}
1974
1975
static gboolean http2_hdrcache_equal(const void *lhs, const void *rhs)
1976
{
1977
    const uint8_t *a = (const uint8_t *)lhs;
1978
    const uint8_t *b = (const uint8_t *)rhs;
1979
    size_t alen = http2_hdrcache_length(a);
1980
    size_t blen = http2_hdrcache_length(b);
1981
1982
    return alen == blen && memcmp(a, b, alen) == 0;
1983
}
1984
1985
/* If we are in a HEADERS or PUSH_PROMISE context, return the stream id
1986
 * the headers describe. (For PUSH_PROMISE or CONTIUATIONs thereof, this
1987
 * is the promised stream id.) Otherwise return 0.
1988
 */
1989
static uint32_t
1990
is_in_header_context(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* h2session)
1991
{
1992
    http2_header_stream_info_t *stream_info = get_header_stream_info(pinfo, h2session, false);
1993
    if (get_http2_frame_num(tvb, pinfo) >= stream_info->header_start_in) {
1994
        /* We either haven't established the frame that the headers end in so we are currently in the HEADERS context,
1995
         * or if we have, it should be equal or less that the current frame number */
1996
        if (stream_info->header_end_in == 0 || get_http2_frame_num(tvb, pinfo) <= stream_info->header_end_in) {
1997
            return stream_info->stream_id;
1998
        }
1999
    }
2000
    return 0;
2001
}
2002
2003
/* Extracts only the media-type from a content-type header. EG:
2004
   "text/html"                  returns "text/html"
2005
   "text/html; charset=utf-8"   returns "text/html"
2006
2007
   Allocates file-scoped string when called as its only called when the header population is done.
2008
*/
2009
static char*
2010
get_content_type_only(const char *content_type, size_t content_type_str_len) {
2011
    char *cp = wmem_strndup(wmem_file_scope(), content_type, content_type_str_len);
2012
    char *start = cp;
2013
2014
    while (*cp != '\0' && *cp != ';' && !g_ascii_isspace(*cp)) {
2015
        *cp = g_ascii_tolower(*cp);
2016
        ++cp;
2017
    }
2018
    *cp = '\0';
2019
2020
    return start;
2021
}
2022
2023
/* Extracts the parameters from a content-type or returns NULL. EG:
2024
2025
   "text/html; charset=utf-8"   returns "charset=utf-8"
2026
   "text/html"                  returns NULL
2027
   "text/html; "                returns NULL
2028
2029
   Allocates file-scoped string when called as its only called when the header population is done.
2030
*/
2031
static char*
2032
get_content_type_parameters_only(const char *content_type, size_t content_type_str_len) {
2033
    char *cp = wmem_strndup(wmem_file_scope(), content_type, content_type_str_len);
2034
2035
    /* Get past the first part of the content type EG: "text/html" */
2036
    while (*cp != '\0' && *cp != ';' && !g_ascii_isspace(*cp)) {
2037
        ++cp;
2038
    }
2039
2040
    /* No parameters */
2041
    if(*cp == '\0') {
2042
        return NULL;
2043
    }
2044
2045
    /* Move past the first ";" or any whitespace */
2046
    while (*cp == ';' || g_ascii_isspace(*cp)) {
2047
        ++cp;
2048
    }
2049
2050
    /* Didn't end up getting any parameters, we just had trailing whitespace or a semicolon after the content-type */
2051
    if (*cp == '\0') {
2052
        return NULL;
2053
    }
2054
2055
    return cp;
2056
}
2057
2058
/* Populates HTTP/2 header information for the given stream. For frames
2059
 * associated with HEADERS this is the current frame, but for PUSH_PROMISE
2060
 * populate information for the promised stream id.
2061
 */
2062
static void
2063
populate_http_header_tracking(tvbuff_t *tvb, packet_info *pinfo, http2_session_t *h2session,
2064
                                   const char *header_name, const char *header_value, uint32_t stream_id, const bool override)
2065
{
2066
    http2_stream_info_t *stream_info = get_stream_info_for_id(pinfo, h2session, false, stream_id);
2067
    http2_data_stream_body_info_t *body_info = get_data_stream_body_info_for_id(pinfo, h2session, stream_id);
2068
    http2_data_stream_reassembly_info_t *reassembly_info = get_data_reassembly_info_for_id(pinfo, h2session, stream_id);
2069
2070
    /* header_value is after validation as UTF-8, so the length may have
2071
     * changed due to REPLACEMENT CHARACTERS on packets with errors.
2072
     */
2073
    size_t header_value_length = strlen(header_value);
2074
2075
    /* Populate the content encoding used so we can uncompress the body later if required */
2076
    if (strcmp(header_name, HTTP2_HEADER_CONTENT_ENCODING) == 0) {
2077
        if (body_info->content_encoding == NULL || override == true) {
2078
            body_info->content_encoding = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2079
        }
2080
    }
2081
2082
    /* Store the frame number so we can enhance the display of request/response */
2083
    if (strcmp(header_name, HTTP2_HEADER_METHOD) == 0) {
2084
        stream_info->request_in_frame_num = pinfo->num;
2085
        stream_info->request_ts = pinfo->abs_ts;
2086
    }
2087
    if (strcmp(header_name, HTTP2_HEADER_STATUS) == 0) {
2088
        stream_info->response_in_frame_num = pinfo->num;
2089
    }
2090
2091
    /* Is this a partial content? */
2092
    if (strcmp(header_name, HTTP2_HEADER_STATUS) == 0 &&
2093
                strcmp(header_value, HTTP2_HEADER_STATUS_PARTIAL_CONTENT) == 0) {
2094
        body_info->is_partial_content = true;
2095
    }
2096
2097
    /* Was this header used to initiate transfer of data frames? We'll use this later for reassembly */
2098
    if (strcmp(header_name, HTTP2_HEADER_STATUS) == 0 ||
2099
                strcmp(header_name, HTTP2_HEADER_METHOD) == 0 ||
2100
                /* If we are in the middle of a stream assume there might be data transfer */
2101
                strcmp(header_name, HTTP2_HEADER_UNKNOWN) == 0){
2102
        if (reassembly_info->data_initiated_in == 0) {
2103
            reassembly_info->data_initiated_in = get_http2_frame_num(tvb, pinfo);
2104
        }
2105
    }
2106
2107
    /* Do we have transfer encoding of bodies? We don't support reassembling these so mark it as such. */
2108
    if (strcmp(header_name, HTTP2_HEADER_TRANSFER_ENCODING) == 0) {
2109
        reassembly_info->has_transfer_encoded_body = true;
2110
    }
2111
2112
    /* Store away if the stream is associated with a CONNECT request */
2113
    if (strcmp(header_name, HTTP2_HEADER_METHOD) == 0 &&
2114
                strcmp(header_value, HTTP2_HEADER_METHOD_CONNECT) == 0) {
2115
        stream_info->is_stream_http_connect = true;
2116
    }
2117
2118
    /* Prepare dissector for extended CONNECT protocol */
2119
    if (stream_info->is_stream_http_connect
2120
        && strcmp(header_name, HTTP2_HEADER_PROTOCOL) == 0) {
2121
        stream_info->protocol = header_value;
2122
        stream_info->next_handle = http_upgrade_dissector(header_value);
2123
        stream_info->upgrade_info = wmem_new0(wmem_file_scope(), http_upgrade_info_t);
2124
        stream_info->upgrade_info->server_port = pinfo->destport;
2125
        stream_info->upgrade_info->http_version = 2;
2126
        stream_info->upgrade_info->get_header_value = http2_get_header_value;
2127
    }
2128
2129
    /* Populate the content type so we can dissect the body later */
2130
    if (strcmp(header_name, HTTP2_HEADER_CONTENT_TYPE) == 0) {
2131
        if (body_info->content_type == NULL || override == true) {
2132
            body_info->content_type = get_content_type_only(header_value, header_value_length);
2133
            body_info->content_type_parameters = get_content_type_parameters_only(header_value, header_value_length);
2134
            stream_info->reassembly_mode = http2_get_data_reassembly_mode(body_info->content_type);
2135
            dissector_handle_t handle = dissector_get_string_handle(media_type_dissector_table, body_info->content_type);
2136
            if (handle) {
2137
                dissector_add_uint("http2.streamid", stream_info->stream_id, handle);
2138
            }
2139
        }
2140
    }
2141
2142
    if (strcmp(header_name, HTTP2_HEADER_PATH) == 0) {
2143
        stream_info->path = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2144
2145
        if(http2_3gpp_session) {
2146
            /* 3GPP Supi look up */
2147
            /* If no Supi found the try look in referenceId mapping */
2148
            GMatchInfo *match_info_imsi;
2149
            GMatchInfo *match_info_referenceid;
2150
            static GRegex *regex_imsi = NULL;
2151
            static GRegex *regex_referenceid = NULL;
2152
            char *matched_imsi = NULL;
2153
            char *matched_referenceid = NULL;
2154
2155
            /* 3GPP TS 29.571
2156
            * String identifying a Supi that shall contain either an IMSI, a network specific identifier,
2157
            * a Global Cable Identifier (GCI) or a Global Line Identifier (GLI) as specified in clause 2.2A of 3GPP TS 23.003.
2158
            *
2159
            * We are interested in IMSI and will be formatted as follows:
2160
            *   Pattern: '^imsi-[0-9]{5,15}$'
2161
            */
2162
            if (regex_imsi == NULL) {
2163
                regex_imsi = g_regex_new (
2164
                    ".*imsi-([0-9]{5,15}).*",
2165
                    G_REGEX_CASELESS | G_REGEX_FIRSTLINE, 0, NULL);
2166
            }
2167
            if (regex_referenceid == NULL) {
2168
                regex_referenceid = g_regex_new (
2169
                    ".*\\/(referenceid|chargingdata|sm-contexts|sm-policies|pdu-sessions)\\/([A-Za-z0-9\\-.]+).*",
2170
                    G_REGEX_CASELESS | G_REGEX_FIRSTLINE, 0, NULL);
2171
            }
2172
2173
            g_regex_match(regex_imsi, stream_info->path, 0, &match_info_imsi);
2174
            g_regex_match(regex_referenceid, stream_info->path, 0, &match_info_referenceid);
2175
2176
            if (g_match_info_matches(match_info_imsi)) {
2177
                matched_imsi = g_match_info_fetch(match_info_imsi, 1); //will be empty string if imsi is not in supi
2178
                if (matched_imsi && (strcmp(matched_imsi, "") != 0)) {
2179
                    stream_info->imsi = wmem_strdup(wmem_file_scope(), matched_imsi);
2180
                }
2181
                g_free(matched_imsi);
2182
            } else if (g_match_info_matches(match_info_referenceid)) {
2183
                matched_referenceid = g_match_info_fetch(match_info_referenceid, 2); //will be empty string if referenceid is not found
2184
                if (matched_referenceid && (strcmp(matched_referenceid, "") != 0)) {
2185
                    stream_info->referenceid = wmem_strdup(wmem_file_scope(), matched_referenceid);
2186
                }
2187
                g_free(matched_referenceid);
2188
            }
2189
            g_regex_unref(regex_imsi);
2190
            g_regex_unref(regex_referenceid);
2191
        }
2192
    }
2193
2194
    if (strcmp(header_name, HTTP2_HEADER_LOCATION) == 0) {
2195
        stream_info->location = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2196
2197
        if(http2_3gpp_session && stream_info->imsi) {
2198
            /* Try lookup location mapping */
2199
            GMatchInfo *match_info_location;
2200
            static GRegex *regex_location = NULL;
2201
            char *matched_location = NULL;
2202
2203
            if (regex_location == NULL) {
2204
                regex_location = g_regex_new (
2205
                    ".*\\/(chargingdata|sm-contexts|sm-policies|pdu-sessions)\\/([A-Za-z0-9\\-.]+).*",
2206
                    G_REGEX_CASELESS | G_REGEX_FIRSTLINE, 0, NULL);
2207
            }
2208
2209
            g_regex_match(regex_location, stream_info->location, 0, &match_info_location);
2210
2211
            if (g_match_info_matches(match_info_location)) {
2212
                matched_location = g_match_info_fetch(match_info_location, 2); //will be empty string if location is not found
2213
                if (matched_location && (strcmp(matched_location, "") != 0)) {
2214
                    http2_add_location_imsi(matched_location, stream_info->imsi);
2215
                }
2216
                g_free(matched_location);
2217
            }
2218
            g_regex_unref(regex_location);
2219
        }
2220
    }
2221
2222
    if (strcmp(header_name, HTTP2_HEADER_STATUS) == 0) {
2223
        char *status = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2224
2225
        if(http2_3gpp_session) {
2226
            /* 3GPP Supi look up */
2227
            /* If no Supi found the try look in referenceId mapping */
2228
            GMatchInfo *match_info_imsi;
2229
            GMatchInfo *match_info_referenceid;
2230
            static GRegex *regex_imsi = NULL;
2231
            static GRegex *regex_referenceid = NULL;
2232
            char *matched_imsi = NULL;
2233
            char *matched_referenceid = NULL;
2234
2235
            /* 3GPP TS 29.571
2236
            * String identifying a Supi that shall contain either an IMSI, a network specific identifier,
2237
            * a Global Cable Identifier (GCI) or a Global Line Identifier (GLI) as specified in clause 2.2A of 3GPP TS 23.003.
2238
            *
2239
            * We are interested in IMSI and will be formatted as follows:
2240
            *   Pattern: '^imsi-[0-9]{5,15}$'
2241
            */
2242
            if (regex_imsi == NULL) {
2243
                regex_imsi = g_regex_new (
2244
                    ".*imsi-([0-9]{5,15}).*",
2245
                    G_REGEX_CASELESS | G_REGEX_FIRSTLINE, 0, NULL);
2246
            }
2247
            if (regex_referenceid == NULL) {
2248
                regex_referenceid = g_regex_new (
2249
                    ".*\\/(referenceid|chargingdata|sm-contexts|sm-policies|pdu-sessions)\\/([A-Za-z0-9\\-.]+).*",
2250
                    G_REGEX_CASELESS | G_REGEX_FIRSTLINE, 0, NULL);
2251
            }
2252
2253
            g_regex_match(regex_imsi, status, 0, &match_info_imsi);
2254
            g_regex_match(regex_referenceid, status, 0, &match_info_referenceid);
2255
2256
            if (g_match_info_matches(match_info_imsi)) {
2257
                matched_imsi = g_match_info_fetch(match_info_imsi, 1); //will be empty string if imsi is not in supi
2258
                if (matched_imsi && (strcmp(matched_imsi, "") != 0)) {
2259
                    stream_info->imsi = wmem_strdup(wmem_file_scope(), matched_imsi);
2260
                }
2261
                g_free(matched_imsi);
2262
            } else if (g_match_info_matches(match_info_referenceid)) {
2263
                matched_referenceid = g_match_info_fetch(match_info_referenceid, 2); //will be empty string if referenceid is not found
2264
                if (matched_referenceid && (strcmp(matched_referenceid, "") != 0)) {
2265
                    stream_info->referenceid = wmem_strdup(wmem_file_scope(), matched_referenceid);
2266
                }
2267
                g_free(matched_referenceid);
2268
            }
2269
            g_regex_unref(regex_imsi);
2270
            g_regex_unref(regex_referenceid);
2271
        }
2272
    }
2273
2274
    if (strcmp(header_name, HTTP2_HEADER_3GPP_SBI_CORRELATION_INFO) == 0) {
2275
        char *correlation_info = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2276
2277
        if(http2_3gpp_session) {
2278
            /* 3GPP Supi look up */
2279
            GMatchInfo *match_info_imsi;
2280
            static GRegex *regex_imsi = NULL;
2281
            char *matched_imsi = NULL;
2282
2283
            /* 3GPP TS 29.571
2284
            * String identifying a Supi that shall contain either an IMSI, a network specific identifier,
2285
            * a Global Cable Identifier (GCI) or a Global Line Identifier (GLI) as specified in clause 2.2A of 3GPP TS 23.003.
2286
            *
2287
            * We are interested in IMSI and will be formatted as follows:
2288
            *   Pattern: '^imsi-[0-9]{5,15}$'
2289
            */
2290
            if (regex_imsi == NULL) {
2291
                regex_imsi = g_regex_new (
2292
                    ".*imsi-([0-9]{5,15}).*",
2293
                    G_REGEX_CASELESS | G_REGEX_FIRSTLINE, 0, NULL);
2294
            }
2295
2296
            g_regex_match(regex_imsi, correlation_info, 0, &match_info_imsi);
2297
2298
            if (g_match_info_matches(match_info_imsi)) {
2299
                matched_imsi = g_match_info_fetch(match_info_imsi, 1); //will be empty string if imsi is not in supi
2300
                if (matched_imsi && (strcmp(matched_imsi, "") != 0)) {
2301
                    stream_info->imsi = wmem_strdup(wmem_file_scope(), matched_imsi);
2302
                }
2303
                g_free(matched_imsi);
2304
            }
2305
            g_regex_unref(regex_imsi);
2306
        }
2307
    }
2308
2309
    if (strcmp(header_name, HTTP2_HEADER_AUTHORITY) == 0) {
2310
        stream_info->authority = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2311
    }
2312
2313
    if (strcmp(header_name, HTTP2_HEADER_SCHEME) == 0) {
2314
        stream_info->scheme = wmem_strndup(wmem_file_scope(), header_value, header_value_length);
2315
    }
2316
}
2317
2318
static void
2319
try_append_method_path_info(packet_info *pinfo, proto_tree *tree,
2320
                        const char *method_header_value, const char *path_header_value)
2321
{
2322
    if (method_header_value != NULL && path_header_value != NULL) {
2323
        /* append request information to info column (for example, HEADERS: GET /demo/1.jpg) */
2324
        col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s %s", method_header_value, path_header_value);
2325
        /* append request information to Stream node */
2326
        proto_item_append_text(tree, ", %s %s", method_header_value, path_header_value);
2327
    }
2328
}
2329
2330
static proto_item*
2331
try_add_named_header_field(proto_tree *tree, tvbuff_t *tvb, int offset, uint32_t length, const char *header_name, const char *header_value)
2332
{
2333
    int hf_id;
2334
    header_field_info *hfi;
2335
    proto_item* ti = NULL;
2336
2337
    const int *entry = (const int*) g_hash_table_lookup(header_fields_hash, header_name);
2338
    if (entry == NULL) {
2339
        return NULL;
2340
    }
2341
2342
    hf_id = *entry;
2343
2344
    hfi = proto_registrar_get_nth(hf_id);
2345
    DISSECTOR_ASSERT(hfi != NULL);
2346
2347
    if (FT_IS_UINT32(hfi->type)) {
2348
        uint32_t value;
2349
        if (ws_strtou32(header_value, NULL, &value)) {
2350
            ti = proto_tree_add_uint(tree, hf_id, tvb, offset, length, value);
2351
        }
2352
    } else if (FT_IS_UINT(hfi->type)) {
2353
        uint64_t value;
2354
        if (ws_strtou64(header_value, NULL, &value)) {
2355
            ti = proto_tree_add_uint64(tree, hf_id, tvb, offset, length, value);
2356
        }
2357
    } else {
2358
        ti = proto_tree_add_item(tree, hf_id, tvb, offset, length, ENC_BIG_ENDIAN);
2359
    }
2360
    return ti;
2361
}
2362
2363
static void
2364
fix_partial_header_dissection_support(nghttp2_hd_inflater *hd_inflater, bool *fix_it)
2365
{
2366
    /* Workaround is not necessary or has already been applied, skip. */
2367
    if (!*fix_it) {
2368
        return;
2369
    }
2370
    *fix_it = false;
2371
2372
    /* Sanity-check: the workaround should fill an empty dynamic table only and
2373
     * not evict existing entries. It is expected to be empty given that this is
2374
     * the first time processing headers, but double-check just to be sure.
2375
     */
2376
    if (nghttp2_hd_inflate_get_dynamic_table_size(hd_inflater) != 0) {
2377
        // Dynamic table is non-empty, do not touch it!
2378
        return;
2379
    }
2380
2381
    /* Support dissection of headers where the capture starts in the middle of a
2382
     * TCP stream. In that case, the Headers Block Fragment might reference
2383
     * earlier dynamic table entries unknown to the decompressor. To avoid a
2384
     * fatal error that breaks all future header dissection in this connection,
2385
     * populate the dynamic table with some dummy entries.
2386
     * See also https://github.com/nghttp2/nghttp2/issues/1389
2387
     *
2388
     * The number of entries in the dynamic table is dependent on the maximum
2389
     * table size (SETTINGS_HEADER_TABLE_SIZE, defaults to 4096 bytes) and the
2390
     * size of individual entries (32 + name length + value length where 32 is
2391
     * the overhead from RFC 7541, Section 4.1). Since earlier header fields in
2392
     * the dynamic table are unknown, we will try to use a small dummy header
2393
     * field to maximize the number of entries: "<unknown>" with no value.
2394
     *
2395
     * The binary instruction to insert this is defined in Figure 7 of RFC 7541.
2396
     */
2397
    static const uint8_t dummy_header[] = "\x40"
2398
                                         "\x09"      /* Name String Length */
2399
                                         HTTP2_HEADER_UNKNOWN /* Name String */
2400
                                         "\0";       /* Value Length */
2401
    const int dummy_header_size = sizeof(dummy_header) - 1;
2402
    const int dummy_entries_to_add = (int)(nghttp2_hd_inflate_get_max_dynamic_table_size(hd_inflater) / (32 + dummy_header_size - 3));
2403
    for (int i = dummy_entries_to_add - 1; i >= 0; --i) {
2404
        nghttp2_nv nv;
2405
        int inflate_flags = 0;
2406
        int rv = (int)nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags,
2407
                                             dummy_header, dummy_header_size,
2408
                                             i == 0);
2409
        if (rv != dummy_header_size) {
2410
            ws_log(WS_LOG_DOMAIN, LOG_LEVEL_WARNING,
2411
                  "unexpected decompression state: %d != %d", rv,
2412
                  dummy_header_size);
2413
            break;
2414
        }
2415
    }
2416
    nghttp2_hd_inflate_end_headers(hd_inflater);
2417
}
2418
2419
static void
2420
inflate_http2_header_block(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, proto_tree *tree,
2421
                           unsigned headlen, http2_session_t *h2session, uint8_t flags)
2422
{
2423
    uint8_t *headbuf;
2424
    proto_tree *header_tree;
2425
    proto_item *header, *ti, *ti_named_field;
2426
    uint32_t header_name_length;
2427
    uint32_t header_value_length;
2428
    const char *header_name;
2429
    const char *header_value;
2430
    int hoffset = 0;
2431
    nghttp2_hd_inflater *hd_inflater;
2432
    tvbuff_t *header_tvb = NULL;
2433
    int rv;
2434
    int header_len = 0;
2435
    int final;
2436
    uint32_t flow_index;
2437
    http2_header_data_t *header_data;
2438
    http2_header_repr_info_t *header_repr_info;
2439
    wmem_list_t *header_list;
2440
    wmem_array_t *headers;
2441
    unsigned i;
2442
    const char *method_header_value = NULL;
2443
    const char *path_header_value = NULL;
2444
    http2_header_stream_info_t* header_stream_info;
2445
    char *header_unescaped = NULL;
2446
2447
    if (!http2_hdrcache_map) {
2448
        http2_hdrcache_map = wmem_map_new(wmem_file_scope(), http2_hdrcache_hash, http2_hdrcache_equal);
2449
    }
2450
2451
    header_data = (http2_header_data_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_HEADER);
2452
    header_list = header_data->header_list;
2453
2454
    if(!PINFO_FD_VISITED(pinfo)) {
2455
        /* This packet has not been processed yet, which means this is
2456
           the first linear scan.  We do header decompression only
2457
           once in linear scan and cache the result.  If we don't
2458
           cache, already processed data will be fed into decompressor
2459
           again and again since dissector will be called randomly.
2460
           This makes context out-of-sync. */
2461
        int decompressed_bytes = 0;
2462
2463
        /* Make sure the length isn't too large. */
2464
        tvb_ensure_bytes_exist(tvb, offset, headlen);
2465
        headbuf = (uint8_t*)wmem_alloc(pinfo->pool, headlen);
2466
        tvb_memcpy(tvb, headbuf, offset, headlen);
2467
2468
        flow_index = select_http2_flow_index(pinfo, h2session);
2469
        hd_inflater = h2session->hd_inflater[flow_index];
2470
        header_repr_info = &h2session->header_repr_info[flow_index];
2471
2472
        fix_partial_header_dissection_support(hd_inflater, &h2session->fix_dynamic_table[flow_index]);
2473
2474
        final = flags & HTTP2_FLAGS_END_HEADERS;
2475
2476
        headers = wmem_array_sized_new(wmem_file_scope(), sizeof(http2_header_t), 16);
2477
2478
        for(;;) {
2479
            nghttp2_nv nv;
2480
            int inflate_flags = 0;
2481
2482
            if (wmem_array_get_count(headers) >= MAX_HTTP2_HEADER_LINES) {
2483
                header_data->header_lines_exceeded = true;
2484
                break;
2485
            }
2486
2487
            rv = (int)nghttp2_hd_inflate_hd2(hd_inflater, &nv,
2488
                                             &inflate_flags, headbuf, headlen, final);
2489
2490
            if(rv < 0) {
2491
                break;
2492
            }
2493
2494
            headbuf += rv;
2495
            headlen -= rv;
2496
2497
            rv -= process_http2_header_repr_info(headers, header_repr_info, headbuf - rv, rv);
2498
2499
            if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
2500
                char *cached_pstr;
2501
                uint32_t len;
2502
                unsigned datalen = (unsigned)(4 + nv.namelen + 4 + nv.valuelen);
2503
                http2_header_t *out;
2504
2505
                if (decompressed_bytes + datalen >= MAX_HTTP2_HEADER_SIZE) {
2506
                    header_data->header_size_reached = decompressed_bytes;
2507
                    header_data->header_size_attempted = decompressed_bytes + datalen;
2508
                    break;
2509
                }
2510
2511
                out = wmem_new(wmem_file_scope(), http2_header_t);
2512
2513
                out->type = header_repr_info->type;
2514
                out->length = rv;
2515
                out->table.data.idx = header_repr_info->integer;
2516
2517
                out->table.data.datalen = datalen;
2518
                decompressed_bytes += datalen;
2519
2520
                /* Prepare buffer... with the following format
2521
                   name length (uint32)
2522
                   name (string)
2523
                   value length (uint32)
2524
                   value (string)
2525
                */
2526
                http2_header_pstr = (char *)wmem_realloc(wmem_file_scope(), http2_header_pstr, out->table.data.datalen);
2527
2528
                /* nv.namelen and nv.valuelen are of size_t.  In order
2529
                   to get length in 4 bytes, we have to copy it to
2530
                   uint32_t. */
2531
                len = (uint32_t)nv.namelen;
2532
                phtonu32((uint8_t*)&http2_header_pstr[0], len);
2533
                memcpy(&http2_header_pstr[4], nv.name, nv.namelen);
2534
2535
                len = (uint32_t)nv.valuelen;
2536
                phtonu32((uint8_t*)&http2_header_pstr[4 + nv.namelen], len);
2537
                memcpy(&http2_header_pstr[4 + nv.namelen + 4], nv.value, nv.valuelen);
2538
2539
                cached_pstr = (char *)wmem_map_lookup(http2_hdrcache_map, http2_header_pstr);
2540
                if (cached_pstr) {
2541
                    out->table.data.data = cached_pstr;
2542
                } else {
2543
                    wmem_map_insert(http2_hdrcache_map, http2_header_pstr, http2_header_pstr);
2544
                    out->table.data.data = http2_header_pstr;
2545
                    http2_header_pstr = NULL;
2546
                }
2547
2548
                wmem_array_append(headers, out, 1);
2549
2550
                reset_http2_header_repr_info(header_repr_info);
2551
            }
2552
            if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
2553
                nghttp2_hd_inflate_end_headers(hd_inflater);
2554
                break;
2555
            }
2556
            if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
2557
               headlen == 0) {
2558
                break;
2559
            }
2560
        }
2561
2562
        wmem_list_append(header_list, headers);
2563
2564
        if(!header_data->current) {
2565
            header_data->current = wmem_list_head(header_list);
2566
        }
2567
2568
        /* add this packet headers to stream header list */
2569
        /* If this is a PUSH_PROMISE frame (or a CONTINUATION of a PUSH_PROMISE
2570
         * field block), we don't want to add it to this list, but to the list
2571
         * for the promised stream.
2572
         */
2573
        uint32_t header_stream_id = is_in_header_context(tvb, pinfo, h2session);
2574
        if (header_stream_id == 0) {
2575
            header_stream_id = h2session->current_stream_id;
2576
        }
2577
        header_stream_info = get_header_stream_info_for_id(pinfo, h2session, false, header_stream_id);
2578
        if (header_stream_info) {
2579
            wmem_list_append(header_stream_info->stream_header_list, headers);
2580
        }
2581
2582
    } else if (header_data->current) {
2583
        headers = (wmem_array_t*)wmem_list_frame_data(header_data->current);
2584
2585
        header_data->current = wmem_list_frame_next(header_data->current);
2586
2587
        if(!header_data->current) {
2588
            header_data->current = wmem_list_head(header_list);
2589
        }
2590
    } else {
2591
        return;
2592
    }
2593
2594
    if(wmem_array_get_count(headers) == 0) {
2595
        return;
2596
    }
2597
2598
    for(i = 0; i < wmem_array_get_count(headers); ++i) {
2599
        http2_header_t *in;
2600
        tvbuff_t *next_tvb;
2601
2602
        in = (http2_header_t*)wmem_array_index(headers, i);
2603
2604
        if(in->type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE) {
2605
            continue;
2606
        }
2607
2608
        header_len += in->table.data.datalen;
2609
2610
        /* Now setup the tvb buffer to have the new data */
2611
        next_tvb = tvb_new_child_real_data(tvb, (uint8_t*)in->table.data.data, in->table.data.datalen, in->table.data.datalen);
2612
        if (!header_tvb) {
2613
            header_tvb = tvb_new_composite();
2614
        }
2615
        tvb_composite_append(header_tvb, next_tvb);
2616
    }
2617
2618
2619
    if (!header_tvb) {
2620
        return;
2621
    }
2622
2623
    tvb_composite_finalize(header_tvb);
2624
    add_new_data_source(pinfo, header_tvb, "Decompressed Header");
2625
2626
    ti = proto_tree_add_uint(tree, hf_http2_header_length, header_tvb, hoffset, 1, header_len);
2627
    proto_item_set_generated(ti);
2628
2629
    if (header_data->header_size_attempted > 0) {
2630
        expert_add_info_format(pinfo, ti, &ei_http2_header_size,
2631
                               "Decompression stopped after %u bytes (%u attempted).",
2632
                               header_data->header_size_reached,
2633
                               header_data->header_size_attempted);
2634
    }
2635
2636
    ti = proto_tree_add_uint(tree, hf_http2_header_count, header_tvb, hoffset, 1, wmem_array_get_count(headers));
2637
    proto_item_set_generated(ti);
2638
2639
    if (header_data->header_lines_exceeded) {
2640
        expert_add_info(pinfo, ti, &ei_http2_header_lines);
2641
    }
2642
2643
    wmem_strbuf_t* headers_buf = wmem_strbuf_create(pinfo->pool);
2644
    wmem_strbuf_t* header_buf;
2645
2646
    for(i = 0; i < wmem_array_get_count(headers); ++i) {
2647
        http2_header_t *in = (http2_header_t*)wmem_array_index(headers, i);
2648
2649
        if(in->type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE) {
2650
            header = proto_tree_add_item(tree, hf_http2_header_table_size_update, tvb, offset, in->length, ENC_NA);
2651
2652
            header_tree = proto_item_add_subtree(header, ett_http2_headers);
2653
2654
            proto_tree_add_uint(header_tree, hf_http2_header_table_size, tvb, offset, in->length, in->table.header_table_size);
2655
2656
            offset += in->length;
2657
            continue;
2658
        }
2659
2660
        /* Populate tree with header name/value details. */
2661
        /* Add 'Header' subtree with description. */
2662
2663
        header = proto_tree_add_item(tree, hf_http2_header, tvb, offset, in->length, ENC_NA);
2664
2665
        header_tree = proto_item_add_subtree(header, ett_http2_headers);
2666
2667
        /* header value length */
2668
        proto_tree_add_item_ret_uint(header_tree, hf_http2_header_name_length, header_tvb, hoffset, 4, ENC_BIG_ENDIAN, &header_name_length);
2669
        hoffset += 4;
2670
2671
        /* Add header name. */
2672
        proto_tree_add_item_ret_string(header_tree, hf_http2_header_name, header_tvb, hoffset, header_name_length, ENC_ASCII|ENC_NA, pinfo->pool, (const uint8_t**)&header_name);
2673
        hoffset += header_name_length;
2674
2675
        /* header value length */
2676
        proto_tree_add_item_ret_uint(header_tree, hf_http2_header_value_length, header_tvb, hoffset, 4, ENC_BIG_ENDIAN, &header_value_length);
2677
        hoffset += 4;
2678
2679
        /* Add header value. */
2680
        proto_tree_add_item_ret_string(header_tree, hf_http2_header_value, header_tvb, hoffset, header_value_length, ENC_ASCII|ENC_NA, pinfo->pool, (const uint8_t**)&header_value);
2681
        // check if field is http2 header https://tools.ietf.org/html/rfc7541#appendix-A
2682
        ti_named_field = try_add_named_header_field(header_tree, header_tvb, hoffset, header_value_length, header_name, header_value);
2683
2684
        /* Add header unescaped. */
2685
        header_unescaped = g_uri_unescape_string(header_value, NULL);
2686
        if (header_unescaped != NULL) {
2687
            char *header_unescaped_valid = (char*)ws_utf8_make_valid(pinfo->pool, (uint8_t*)header_unescaped, strlen(header_unescaped));
2688
            ti = proto_tree_add_string(header_tree, hf_http2_header_unescaped, header_tvb, hoffset, header_value_length, header_unescaped_valid);
2689
            proto_item_set_generated(ti);
2690
            g_free(header_unescaped);
2691
        }
2692
        hoffset += header_value_length;
2693
2694
        /* Track HEADER and CONTINUATION frames part thereof for this stream id.
2695
         * For PUSH_PROMISE and CONTINUATION frames thereof, add to the promised stream id.
2696
         * Only do it for the first pass in case the current layer changes, altering where the headers frame number,
2697
         * http2_frame_num_t points to. */
2698
        uint32_t header_stream_id;
2699
        if (!PINFO_FD_VISITED(pinfo) && (header_stream_id = is_in_header_context(tvb, pinfo, h2session))) {
2700
            populate_http_header_tracking(tvb, pinfo, h2session, header_name, header_value, header_stream_id, false);
2701
        }
2702
2703
        /* Add encoding representation */
2704
        // This should probably be a bitmask for the first bits, see https://tools.ietf.org/html/rfc7541#section-6
2705
        proto_tree_add_string(header_tree, hf_http2_header_repr, tvb, offset, 1, http2_header_repr_type[in->type].strptr);
2706
2707
        if(in->type == HTTP2_HD_INDEXED ||
2708
           in->type == HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME ||
2709
           in->type == HTTP2_HD_LITERAL_INDEXED_NAME ||
2710
           in->type == HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME) {
2711
            /* Only for HTTP2_HD_INDEXED, the index value covers the full
2712
             * "in->length". In other cases, it is a subset. For simplicity,
2713
             * just select 1 octet (this might not be accurate though). */
2714
            unsigned index_length = in->length;
2715
            if (in->type != HTTP2_HD_INDEXED) {
2716
                index_length = 1;
2717
            }
2718
            proto_tree_add_uint(header_tree, hf_http2_header_index, tvb, offset, index_length, in->table.data.idx);
2719
        }
2720
2721
        header_buf = wmem_strbuf_new(pinfo->pool, header_name);
2722
        wmem_strbuf_append_printf(header_buf, ": %s", header_value);
2723
        proto_item_append_text(header, ": %s", wmem_strbuf_get_str(header_buf));
2724
        wmem_strbuf_append_printf(headers_buf, "%s\n", wmem_strbuf_finalize(header_buf));
2725
2726
        /* Display :method, :path and :status in info column (just like http1.1 dissector does)*/
2727
        if (strcmp(header_name, HTTP2_HEADER_METHOD) == 0) {
2728
            method_header_value = header_value;
2729
            try_append_method_path_info(pinfo, tree, method_header_value, path_header_value);
2730
        }
2731
        else if (strcmp(header_name, HTTP2_HEADER_PATH) == 0) {
2732
            path_header_value = header_value;
2733
            try_append_method_path_info(pinfo, tree, method_header_value, path_header_value);
2734
            http_add_path_components_to_tree(header_tvb, pinfo, ti_named_field, hoffset - header_value_length, header_value_length);
2735
        }
2736
        else if (strcmp(header_name, HTTP2_HEADER_STATUS) == 0) {
2737
            const char* reason_phase = val_to_str_const((unsigned)strtoul(header_value, NULL, 10), vals_http_status_code, "Unknown");
2738
            /* append response status and reason phrase to info column (for example, HEADERS: 200 OK) */
2739
            col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s %s", header_value, reason_phase);
2740
            /* append response status and reason phrase to header_tree and Stream node */
2741
            proto_item_append_text(header_tree, " %s", reason_phase);
2742
            proto_item_append_text(tree, ", %s %s", header_value, reason_phase);
2743
        }
2744
2745
        offset += in->length;
2746
    }
2747
2748
    if (have_tap_listener(http2_follow_tap)) {
2749
        http2_follow_tap_data_t* follow_data = wmem_new0(pinfo->pool, http2_follow_tap_data_t);
2750
2751
        wmem_strbuf_append(headers_buf, "\n");
2752
        follow_data->tvb = tvb_new_child_real_data(header_tvb,
2753
            (const uint8_t*)wmem_strbuf_get_str(headers_buf), (unsigned)wmem_strbuf_get_len(headers_buf),
2754
            (int)wmem_strbuf_get_len(headers_buf));
2755
        follow_data->stream_id = h2session->current_stream_id;
2756
2757
        tap_queue_packet(http2_follow_tap, pinfo, follow_data);
2758
    }
2759
}
2760
2761
/* If the initial/first HEADERS frame (containing ":method" or ":status" header) of this direction is not received
2762
 * (normally because of starting capturing after a long-lived HTTP2 stream like gRPC streaming call has been established),
2763
 * we initialize the information in direction of the stream with the fake headers of wireshark http2 preferences.
2764
 * In an other situation, some http2 headers are unable to be parse in current HEADERS frame because previous HEADERS
2765
 * frames were not captured that causing HPACK index table not completed. Fake headers can also be used in this situation.
2766
 */
2767
static void
2768
try_init_stream_with_fake_headers(tvbuff_t* tvb, packet_info* pinfo, http2_session_t* h2session, proto_tree* tree, unsigned offset)
2769
{
2770
    if (num_http2_fake_headers == 0) {
2771
        return;
2772
    }
2773
2774
    http2_direction_type direction;
2775
    range_t* server_port_range;
2776
    uint32_t stream_id = h2session->current_stream_id;
2777
    wmem_array_t* indexes = NULL; /* the indexes of fake headers matching this stream and direction */
2778
    proto_item* ti, * ti_header;
2779
    proto_tree* header_tree;
2780
    http2_frame_num_t http2_frame_num = get_http2_frame_num(tvb, pinfo);
2781
2782
    http2_header_stream_info_t* header_stream_info = get_header_stream_info(pinfo, h2session, false);
2783
    http2_data_stream_reassembly_info_t* reassembly_info = get_data_reassembly_info(pinfo, h2session);
2784
2785
    if (!PINFO_FD_VISITED(pinfo) && header_stream_info->fake_headers_initiated_fn == 0) {
2786
        header_stream_info->fake_headers_initiated_fn = http2_frame_num;
2787
        if (reassembly_info->data_initiated_in == 0) {
2788
            /* At this time, the data_initiated_in has not been set,
2789
             * indicating that the previous initial HEADERS frame has been lost.
2790
             * We try to use fake headers to initialize stream reassembly info. */
2791
            reassembly_info->data_initiated_in = http2_frame_num;
2792
        }
2793
2794
        /* Initialize with fake headers in this frame.
2795
         * Use only those fake headers that do not appear. */
2796
        header_stream_info->fake_headers = wmem_array_sized_new(wmem_file_scope(), sizeof(http2_fake_header_t*), 16);
2797
2798
        for (unsigned i = 0; i < num_http2_fake_headers; ++i) {
2799
            http2_fake_header_t* fake_header = http2_fake_headers + i;
2800
            if (fake_header->enable == false ||
2801
                (fake_header->stream_id > 0 && fake_header->stream_id != stream_id)) {
2802
                continue;
2803
            }
2804
2805
            server_port_range = fake_header->server_port_range;
2806
            if (value_is_in_range(server_port_range, pinfo->destport)) {
2807
                direction = DIRECTION_IN;
2808
            } else if (value_is_in_range(server_port_range, pinfo->srcport)) {
2809
                direction = DIRECTION_OUT;
2810
            } else {
2811
                continue;
2812
            }
2813
2814
            if (fake_header->direction != direction) {
2815
                continue;
2816
            }
2817
2818
            /* now match one */
2819
            if (get_real_header_value(pinfo, fake_header->header_name, false) && fake_header->override == false) {
2820
                /* If this header already appears, the fake header is ignored, unless we want to override. */
2821
                continue;
2822
            }
2823
2824
            populate_http_header_tracking(tvb, pinfo, h2session,
2825
                fake_header->header_name, fake_header->header_value, h2session->current_stream_id, fake_header->override);
2826
2827
            wmem_array_append(header_stream_info->fake_headers, &fake_header, 1);
2828
        }
2829
    }
2830
2831
    if (header_stream_info->fake_headers_initiated_fn == http2_frame_num) {
2832
        indexes = header_stream_info->fake_headers;
2833
        /* Try to add the tree item of fake headers. */
2834
        if (indexes) {
2835
            unsigned total_matching_fake_headers = wmem_array_get_count(indexes);
2836
2837
            ti = proto_tree_add_uint(tree, hf_http2_fake_header_count, tvb, offset, 0, total_matching_fake_headers);
2838
            proto_item_append_text(ti, " (Using fake headers because previous initial HEADERS frame is missing)");
2839
            proto_item_set_generated(ti);
2840
2841
            for (unsigned i = 0; i < total_matching_fake_headers; ++i) {
2842
                http2_fake_header_t* header = *(http2_fake_header_t**)wmem_array_index(indexes, i);
2843
2844
                ti_header = proto_tree_add_item(tree, hf_http2_fake_header, tvb, offset, 0, ENC_NA);
2845
                header_tree = proto_item_add_subtree(ti_header, ett_http2_header);
2846
                proto_item_append_text(ti_header, ": %s: %s", header->header_name, header->header_value);
2847
                proto_item_set_generated(ti_header);
2848
2849
                ti = proto_tree_add_string(header_tree, hf_http2_header_name, tvb, offset, 0, header->header_name);
2850
                proto_item_set_generated(ti);
2851
                ti = proto_tree_add_string(header_tree, hf_http2_header_value, tvb, offset, 0, header->header_value);
2852
                proto_item_set_generated(ti);
2853
            }
2854
        }
2855
    }
2856
}
2857
2858
static void
2859
dissect_http2_add_assoc_imsi_to_tracked_3gpp_session(tvbuff_t *tvb, proto_tree *http2_tree, http2_stream_info_t *stream_info) {
2860
    /* Add Associate IMSI */
2861
    if (http2_3gpp_session) {
2862
        char *imsi = NULL;
2863
        if(stream_info->imsi && (strcmp(stream_info->imsi, "") != 0)) {
2864
            add_assoc_imsi_item(tvb, http2_tree, stream_info->imsi);
2865
        } else if (stream_info->referenceid && (strcmp(stream_info->referenceid, "") != 0) && (imsi = http2_get_imsi_from_location(stream_info->referenceid))) {
2866
            add_assoc_imsi_item(tvb, http2_tree, imsi);
2867
        } else if (stream_info->path && (strcmp(stream_info->path, "") != 0) && (imsi = http2_get_imsi_from_notifyuri(stream_info->path))) {
2868
            add_assoc_imsi_item(tvb, http2_tree, imsi);
2869
        }
2870
    }
2871
}
2872
#endif
2873
2874
static char*
2875
http2_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream)
2876
0
{
2877
0
    http2_session_t *h2session;
2878
0
    struct tcp_analysis *tcpd;
2879
0
    conversation_t* conversation;
2880
2881
    /* XXX: Since TCP doesn't use the endpoint API (and HTTP2 is
2882
     * over TCP), we can only look up using the current pinfo addresses
2883
     * and ports. We don't want to create a new conversion or stream.
2884
     * Eventually the endpoint API should support storing multiple
2885
     * endpoints and TCP should be changed to use the endpoint API.
2886
     */
2887
0
    if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||
2888
0
        (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))
2889
0
        && (pinfo->ptype == PT_TCP) &&
2890
0
        (conversation=find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, CONVERSATION_TCP, pinfo->srcport, pinfo->destport, 0)) != NULL)
2891
0
    {
2892
0
        h2session = get_http2_session(pinfo, conversation);
2893
0
        tcpd = get_tcp_conversation_data(conversation, pinfo);
2894
2895
0
        if (tcpd == NULL)
2896
0
            return NULL;
2897
0
        if (h2session == NULL)
2898
0
            return NULL;
2899
2900
0
        *stream = tcpd->stream;
2901
0
        *sub_stream = h2session->current_stream_id;
2902
0
        return ws_strdup_printf("tcp.stream eq %u and http2.streamid eq %u", tcpd->stream, h2session->current_stream_id);
2903
0
    }
2904
2905
0
    return NULL;
2906
0
}
2907
2908
static uint32_t
2909
get_http2_stream_count(unsigned streamid)
2910
0
{
2911
0
    uint32_t result = 0;
2912
0
    uint32_t key;
2913
0
    GHashTable *entry;
2914
0
    GList *entry_set, *it;
2915
2916
0
    entry = (GHashTable*)g_hash_table_lookup(streamid_hash, GUINT_TO_POINTER(streamid));
2917
0
    if (entry != NULL) {
2918
0
        entry_set = g_hash_table_get_keys(entry);
2919
2920
        /* this is a doubly-linked list, g_list_sort has the same time complexity */
2921
0
        for (it = entry_set; it != NULL; it = it->next) {
2922
0
            key = GPOINTER_TO_UINT(it->data);
2923
0
            result = key > result ? key : result;
2924
0
        }
2925
0
        g_list_free(entry_set);
2926
0
    }
2927
2928
0
    return result;
2929
0
}
2930
2931
static bool
2932
is_http2_stream_contains(unsigned streamid, int sub_stream_id)
2933
0
{
2934
0
    GHashTable *entry;
2935
2936
0
    entry = (GHashTable*)g_hash_table_lookup(streamid_hash, GUINT_TO_POINTER(streamid));
2937
0
    if (entry == NULL) {
2938
0
        return false;
2939
0
    }
2940
2941
0
    if (!g_hash_table_contains(entry, GINT_TO_POINTER(sub_stream_id))) {
2942
0
        return false;
2943
0
    }
2944
2945
0
    return true;
2946
0
}
2947
2948
bool
2949
http2_get_stream_id_le(unsigned streamid, unsigned sub_stream_id, unsigned *sub_stream_id_out)
2950
0
{
2951
    // HTTP/2 Stream IDs are always 31 bit.
2952
0
    int max_id = (int)get_http2_stream_count(streamid);
2953
0
    int id = (int)(sub_stream_id & MASK_HTTP2_STREAMID);
2954
0
    if (id > max_id) {
2955
0
        id = max_id;
2956
0
    }
2957
0
    for (; id >= 0; id--) {
2958
0
        if (is_http2_stream_contains(streamid, id)) {
2959
0
            *sub_stream_id_out = (unsigned)id;
2960
0
            return true;
2961
0
        }
2962
0
    }
2963
0
    return false;
2964
0
}
2965
2966
bool
2967
http2_get_stream_id_ge(unsigned streamid, unsigned sub_stream_id, unsigned *sub_stream_id_out)
2968
0
{
2969
    // HTTP/2 Stream IDs are always 31 bit.
2970
0
    int max_id = (int)get_http2_stream_count(streamid);
2971
0
    for (int id = (int)(sub_stream_id & MASK_HTTP2_STREAMID); id <= max_id; id++) {
2972
0
        if (is_http2_stream_contains(streamid, id)) {
2973
0
            *sub_stream_id_out = (unsigned)id;
2974
0
            return true;
2975
0
        }
2976
0
    }
2977
0
    return false;
2978
0
}
2979
2980
static bool
2981
http2_get_sub_stream_id(unsigned streamid, unsigned sub_stream_id, bool le, unsigned *sub_stream_id_out)
2982
0
{
2983
0
    if (le) {
2984
0
        return http2_get_stream_id_le(streamid, sub_stream_id, sub_stream_id_out);
2985
0
    } else {
2986
0
        return http2_get_stream_id_ge(streamid, sub_stream_id, sub_stream_id_out);
2987
0
    }
2988
0
}
2989
2990
static char*
2991
http2_follow_index_filter(unsigned stream, unsigned sub_stream)
2992
0
{
2993
0
    return ws_strdup_printf("tcp.stream eq %u and http2.streamid eq %u", stream, sub_stream);
2994
0
}
2995
2996
static tap_packet_status
2997
follow_http2_tap_listener(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data, tap_flags_t flags)
2998
0
{
2999
0
    follow_info_t *follow_info = (follow_info_t *)tapdata;
3000
0
    const http2_follow_tap_data_t *follow_data = (const http2_follow_tap_data_t *)data;
3001
3002
0
    if (follow_info->substream_id != SUBSTREAM_UNUSED &&
3003
0
        follow_info->substream_id != follow_data->stream_id) {
3004
0
        return TAP_PACKET_DONT_REDRAW;
3005
0
    }
3006
3007
0
    return follow_tvb_tap_listener(tapdata, pinfo, NULL, follow_data->tvb, flags);
3008
0
}
3009
3010
static uint8_t
3011
dissect_http2_header_flags(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree, unsigned offset, uint8_t type)
3012
270
{
3013
3014
270
    uint64_t flags_val;
3015
270
    int* const * fields;
3016
3017
270
    static int* const http2_hdr_flags[] = {
3018
270
        &hf_http2_flags_unused_headers,
3019
270
        &hf_http2_flags_priority,
3020
270
        &hf_http2_flags_padded,
3021
270
        &hf_http2_flags_end_headers,
3022
270
        &hf_http2_flags_end_stream,
3023
270
        NULL
3024
270
    };
3025
3026
270
    static int* const http2_data_flags[] = {
3027
270
        &hf_http2_flags_unused_data,
3028
270
        &hf_http2_flags_padded,
3029
270
        &hf_http2_flags_end_stream,
3030
270
        NULL
3031
270
    };
3032
3033
270
    static int* const http2_settings_flags[] = {
3034
270
        &hf_http2_flags_unused_settings,
3035
270
        &hf_http2_flags_settings_ack,
3036
270
        NULL
3037
270
    };
3038
3039
270
    static int* const http2_push_promise_flags[] = {
3040
270
        &hf_http2_flags_unused_push_promise,
3041
270
        &hf_http2_flags_padded,
3042
270
        &hf_http2_flags_end_headers,
3043
270
        NULL
3044
270
    };
3045
3046
270
    static int* const http2_continuation_flags[] = {
3047
270
        &hf_http2_flags_unused_continuation,
3048
270
        &hf_http2_flags_padded,
3049
270
        &hf_http2_flags_end_headers,
3050
270
        NULL
3051
270
    };
3052
3053
270
    static int* const http2_ping_flags[] = {
3054
270
        &hf_http2_flags_unused_ping,
3055
270
        &hf_http2_flags_ping_ack,
3056
270
        NULL
3057
270
    };
3058
3059
270
    static int* const http2_unused_flags[] = {
3060
270
        &hf_http2_flags_unused,
3061
270
        NULL
3062
270
    };
3063
3064
3065
3066
270
    switch(type){
3067
145
        case HTTP2_DATA:
3068
145
            fields = http2_data_flags;
3069
145
            break;
3070
13
        case HTTP2_HEADERS:
3071
13
            fields = http2_hdr_flags;
3072
13
            break;
3073
28
        case HTTP2_SETTINGS:
3074
28
            fields = http2_settings_flags;
3075
28
            break;
3076
4
        case HTTP2_PUSH_PROMISE:
3077
4
            fields = http2_push_promise_flags;
3078
4
            break;
3079
2
        case HTTP2_CONTINUATION:
3080
2
            fields = http2_continuation_flags;
3081
2
            break;
3082
4
        case HTTP2_PING:
3083
4
            fields = http2_ping_flags;
3084
4
            break;
3085
2
        case HTTP2_PRIORITY:
3086
4
        case HTTP2_RST_STREAM:
3087
5
        case HTTP2_GOAWAY:
3088
10
        case HTTP2_WINDOW_UPDATE:
3089
11
        case HTTP2_ALTSVC:
3090
14
        case HTTP2_ORIGIN:
3091
15
        case HTTP2_PRIORITY_UPDATE:
3092
74
        default:
3093
            /* Does not define any flags */
3094
74
            fields = http2_unused_flags;
3095
74
            break;
3096
270
    }
3097
3098
270
    proto_tree_add_bitmask_with_flags_ret_uint64(http2_tree, tvb, offset, hf_http2_flags,
3099
270
        ett_http2_flags, fields, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_INT, &flags_val);
3100
270
    return (uint8_t)flags_val;
3101
3102
270
}
3103
3104
/* helper function to get the padding data for the frames that feature them */
3105
static unsigned
3106
dissect_frame_padding(tvbuff_t *tvb, uint16_t *padding, proto_tree *http2_tree,
3107
                      unsigned offset, uint8_t flags)
3108
163
{
3109
163
    proto_item *ti;
3110
163
    unsigned pad_len = 0;
3111
3112
163
    *padding = 0;
3113
3114
163
    if(flags & HTTP2_FLAGS_PADDED)
3115
15
    {
3116
15
        *padding = tvb_get_uint8(tvb, offset); /* read a single octet */
3117
15
        proto_tree_add_item(http2_tree, hf_http2_padding, tvb, offset, 1, ENC_BIG_ENDIAN);
3118
15
        offset++;
3119
15
        pad_len ++;
3120
15
    }
3121
163
    ti = proto_tree_add_uint(http2_tree, hf_http2_pad_length, tvb, offset-pad_len, pad_len, *padding);
3122
163
    proto_item_set_generated(ti);
3123
3124
163
    return offset;
3125
163
}
3126
3127
/* helper function to get the priority dependence for the frames that feature them:
3128
   HEADERS and PRIORITY */
3129
static unsigned
3130
dissect_frame_prio(tvbuff_t *tvb, proto_tree *http2_tree, unsigned offset, uint8_t flags)
3131
15
{
3132
15
    proto_tree *ti;
3133
15
    uint8_t weight;
3134
3135
15
    if(flags & HTTP2_FLAGS_PRIORITY)
3136
9
    {
3137
9
        proto_tree_add_item(http2_tree, hf_http2_excl_dependency, tvb, offset, 4, ENC_BIG_ENDIAN);
3138
9
        proto_tree_add_item(http2_tree, hf_http2_stream_dependency, tvb, offset, 4, ENC_BIG_ENDIAN);
3139
9
        offset += 4;
3140
9
        proto_tree_add_item(http2_tree, hf_http2_weight, tvb, offset, 1, ENC_BIG_ENDIAN);
3141
9
        weight = tvb_get_uint8(tvb, offset);
3142
        /* 6.2: Weight:  An 8-bit weight for the stream; Add one to the value to obtain a weight between 1 and 256 */
3143
9
        ti = proto_tree_add_uint(http2_tree, hf_http2_weight_real, tvb, offset, 1, weight+1);
3144
9
        proto_item_set_generated(ti);
3145
9
        offset++;
3146
9
    }
3147
3148
15
    return offset;
3149
15
}
3150
3151
#ifdef HAVE_NGHTTP2
3152
3153
static streaming_reassembly_info_t*
3154
get_streaming_reassembly_info(packet_info* pinfo, http2_session_t* http2_session)
3155
{
3156
    http2_data_stream_reassembly_info_t* data_reassembly_info =
3157
        &get_oneway_stream_info(pinfo, http2_session, false)->data_stream_reassembly_info;
3158
3159
    if (data_reassembly_info->streaming_reassembly_info == NULL) {
3160
        data_reassembly_info->streaming_reassembly_info = streaming_reassembly_info_new();
3161
    }
3162
3163
    return data_reassembly_info->streaming_reassembly_info;
3164
}
3165
3166
enum body_uncompression {
3167
    BODY_UNCOMPRESSION_NONE,
3168
    BODY_UNCOMPRESSION_ZLIB,
3169
    BODY_UNCOMPRESSION_BROTLI,
3170
    BODY_UNCOMPRESSION_ZSTD
3171
};
3172
3173
static enum body_uncompression
3174
get_body_uncompression_info(packet_info *pinfo, http2_session_t* h2session)
3175
{
3176
    http2_data_stream_body_info_t *body_info = get_data_stream_body_info(pinfo, h2session);
3177
    char *content_encoding = body_info->content_encoding;
3178
3179
    /* Check we have a content-encoding header appropriate as well as checking if this is partial content.
3180
     * We can't decompress part of a gzip encoded entity */
3181
    /* XXX - Should there be an expert info if a body is compressed but support
3182
     * for that decompression method was not compiled in? */
3183
    if (!http2_decompress_body || body_info->is_partial_content == true || content_encoding == NULL) {
3184
        return BODY_UNCOMPRESSION_NONE;
3185
    }
3186
#ifdef HAVE_ZLIBNG
3187
    if (strncmp(content_encoding, "gzip", 4) == 0 || strncmp(content_encoding, "deflate", 7) == 0) {
3188
        return BODY_UNCOMPRESSION_ZLIB;
3189
    }
3190
#endif
3191
#ifdef HAVE_ZLIB
3192
    if (strncmp(content_encoding, "gzip", 4) == 0 || strncmp(content_encoding, "deflate", 7) == 0) {
3193
        return BODY_UNCOMPRESSION_ZLIB;
3194
    }
3195
#endif
3196
#ifdef HAVE_BROTLI
3197
    if (strncmp(content_encoding, "br", 2) == 0) {
3198
        return BODY_UNCOMPRESSION_BROTLI;
3199
    }
3200
#endif
3201
#ifdef HAVE_ZSTD
3202
    if (strncmp(content_encoding, "zstd", 4) == 0) {
3203
        return BODY_UNCOMPRESSION_ZSTD;
3204
    }
3205
#endif
3206
3207
    return BODY_UNCOMPRESSION_NONE;
3208
}
3209
3210
/* Try to dissect reassembled http2.data.data according to content_type. */
3211
static void
3212
dissect_body_data(proto_tree *tree, packet_info *pinfo, http2_session_t* h2session, tvbuff_t *tvb,
3213
                  const int start, int length, const unsigned encoding, bool streaming_mode)
3214
{
3215
    http2_data_stream_body_info_t *body_info = get_data_stream_body_info(pinfo, h2session);
3216
    http2_stream_info_t *stream_info = get_stream_info(pinfo, h2session, false);
3217
    char *content_type = body_info->content_type;
3218
    media_content_info_t metadata_used_for_media_type_handle = { MEDIA_CONTAINER_HTTP_OTHERS, body_info->content_type_parameters, NULL, NULL };
3219
    http_eo_t *eo_info;
3220
    uint32_t stream_id;
3221
3222
    stream_id = http2_get_stream_id(pinfo);
3223
    if (!streaming_mode)
3224
        proto_tree_add_item(tree, hf_http2_data_data, tvb, start, length, encoding);
3225
3226
    if (have_tap_listener(http2_follow_tap)) {
3227
        http2_follow_tap_data_t *follow_data = wmem_new0(pinfo->pool, http2_follow_tap_data_t);
3228
3229
        follow_data->tvb = tvb_new_subset_length(tvb, start, length);
3230
        follow_data->stream_id = stream_id;
3231
3232
        tap_queue_packet(http2_follow_tap, pinfo, follow_data);
3233
    }
3234
3235
    if (have_tap_listener(http_eo_tap)) {
3236
        eo_info = wmem_new0(pinfo->pool, http_eo_t);
3237
3238
        eo_info->filename = stream_info->path;
3239
        eo_info->hostname = stream_info->authority;
3240
        eo_info->content_type = content_type;
3241
        eo_info->payload = tvb_new_subset_length(tvb, start, length);
3242
3243
        tap_queue_packet(http_eo_tap, pinfo, eo_info);
3244
    }
3245
3246
    tvbuff_t *data_tvb = tvb_new_subset_length(tvb, start, length);
3247
    if (content_type != NULL) {
3248
        /* add it to STREAM level */
3249
        proto_tree* ptree = proto_tree_get_parent_tree(tree);
3250
        dissector_try_string_with_data((streaming_mode ? streaming_content_type_dissector_table : media_type_dissector_table),
3251
            content_type, data_tvb, pinfo,
3252
            ptree, true, &metadata_used_for_media_type_handle);
3253
    } else {
3254
        if (!dissector_try_uint_with_data(stream_id_content_type_dissector_table, stream_id,
3255
            data_tvb, pinfo, proto_tree_get_parent_tree(tree), true, &metadata_used_for_media_type_handle))
3256
        {
3257
            /* Try heuristics */
3258
            /* Check for possible boundary string */
3259
            if (tvb_strneql(data_tvb, 0, "--", 2) == 0) {
3260
                int next_offset;
3261
                int boundary_len = tvb_find_line_end(data_tvb, 0, -1, &next_offset, true);
3262
                if ((boundary_len > 4) && (boundary_len < 70)){
3263
                    boundary_len = boundary_len - 2; /* ignore ending CRLF*/
3264
                    /* We have a potential boundary string */
3265
                    const char *boundary = (char*)tvb_get_string_enc(pinfo->pool, data_tvb, 2, boundary_len, ENC_ASCII | ENC_NA);
3266
                    if (tvb_strneql(data_tvb, (length - 4) - boundary_len, boundary, boundary_len) == 0) {
3267
                        /* We have multipart/mixed */
3268
                        /* Populate the content type so we can dissect the body later */
3269
                        body_info->content_type = wmem_strndup(wmem_file_scope(), "multipart/mixed", 15);
3270
                        body_info->content_type_parameters = wmem_strdup_printf(wmem_file_scope(), "boundary=\"%s\"", boundary);
3271
                        metadata_used_for_media_type_handle.media_str = body_info->content_type_parameters;
3272
                        dissector_try_uint_with_data(stream_id_content_type_dissector_table, stream_id,
3273
                            data_tvb, pinfo, proto_tree_get_parent_tree(tree), true, &metadata_used_for_media_type_handle);
3274
                    }
3275
                }
3276
                return;
3277
            } /* Not multipart/mixed*/
3278
            /* check for json, from RFC 4627
3279
             * A JSON text is a serialized object or array.
3280
             * JSON-text = object / array
3281
             * These are the six structural characters:
3282
             * begin-array     = ws %x5B ws  ; [ left square bracket
3283
             * begin-object    = ws %x7B ws  ; { left curly bracket
3284
             * :
3285
             * Insignificant whitespace is allowed before or after any of the six
3286
             * structural characters.
3287
             * ws = *(
3288
             *  %x20 /              ; Space
3289
             *  %x09 /              ; Horizontal tab
3290
             *  %x0A /              ; Line feed or New line
3291
             *  %x0D                ; Carriage return
3292
             * )
3293
             */
3294
            int offset = 0;
3295
            offset = tvb_skip_wsp(data_tvb, 0, length);
3296
            uint8_t oct = tvb_get_uint8(data_tvb, offset);
3297
            if ((oct == 0x5b) || (oct == 0x7b)) {
3298
                /* Potential json */
3299
                const uint8_t* buf = tvb_get_string_enc(pinfo->pool, tvb, 0, length, ENC_ASCII);
3300
3301
                if (json_validate(buf, length) == true) {
3302
                    body_info->content_type = wmem_strndup(wmem_file_scope(), "application/json", 16);
3303
                    dissector_handle_t handle = dissector_get_string_handle(media_type_dissector_table, body_info->content_type);
3304
                    metadata_used_for_media_type_handle.media_str = body_info->content_type_parameters;
3305
                    if (handle) {
3306
                        dissector_add_uint("http2.streamid", stream_info->stream_id, handle);
3307
                    }
3308
                    dissector_try_uint_with_data(stream_id_content_type_dissector_table, stream_id,
3309
                        data_tvb, pinfo, proto_tree_get_parent_tree(tree), true, &metadata_used_for_media_type_handle);
3310
                }
3311
                return;
3312
            }
3313
        }
3314
    }
3315
}
3316
3317
static void
3318
dissect_http2_data_full_body(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* h2session, proto_tree *http2_tree)
3319
{
3320
    if (!tvb) {
3321
        return;
3322
    }
3323
3324
    int datalen = tvb_reported_length(tvb);
3325
3326
    enum body_uncompression uncompression = get_body_uncompression_info(pinfo, h2session);
3327
    if (uncompression != BODY_UNCOMPRESSION_NONE) {
3328
        proto_item *compressed_proto_item = NULL;
3329
3330
        tvbuff_t *uncompressed_tvb = NULL;
3331
        if (uncompression == BODY_UNCOMPRESSION_ZLIB) {
3332
            uncompressed_tvb = tvb_child_uncompress_zlib(tvb, tvb, 0, datalen);
3333
        } else if (uncompression == BODY_UNCOMPRESSION_BROTLI) {
3334
            uncompressed_tvb = tvb_child_uncompress_brotli(tvb, tvb, 0, datalen);
3335
        } else if (uncompression == BODY_UNCOMPRESSION_ZSTD) {
3336
            uncompressed_tvb = tvb_child_uncompress_zstd(tvb, tvb, 0, datalen);
3337
        }
3338
3339
        http2_data_stream_body_info_t *body_info = get_data_stream_body_info(pinfo, h2session);
3340
        char *compression_method = body_info->content_encoding;
3341
3342
        proto_tree *compressed_entity_tree = proto_tree_add_subtree_format(http2_tree, tvb, 0, datalen, ett_http2_encoded_entity,
3343
            &compressed_proto_item, "Content-encoded entity body (%s): %u bytes",
3344
            compression_method == NULL ? "unknown" : compression_method, datalen
3345
        );
3346
3347
        if (uncompressed_tvb != NULL) {
3348
            unsigned uncompressed_length = tvb_captured_length(uncompressed_tvb);
3349
            add_new_data_source(pinfo, uncompressed_tvb, "Uncompressed entity body");
3350
            proto_item_append_text(compressed_proto_item, " -> %u bytes", uncompressed_length);
3351
            dissect_body_data(compressed_entity_tree, pinfo, h2session, uncompressed_tvb, 0, uncompressed_length, ENC_NA, false);
3352
3353
        } else {
3354
            proto_tree_add_expert(compressed_entity_tree, pinfo, &ei_http2_body_decompression_failed, tvb, 0, datalen);
3355
            dissect_body_data(compressed_entity_tree, pinfo, h2session, tvb, 0, datalen, ENC_NA, false);
3356
        }
3357
    } else {
3358
        dissect_body_data(http2_tree, pinfo, h2session, tvb, 0, datalen, ENC_NA, false);
3359
    }
3360
3361
}
3362
3363
static int
3364
should_attempt_to_reassemble_data_frame(http2_data_stream_reassembly_info_t *reassembly, packet_info *pinfo _U_,
3365
   http2_session_t* http2_session)
3366
{
3367
    /* If we haven't captured the header frame with the request/response we don't know how many data
3368
     * frames we might have lost before processing */
3369
    if (reassembly->data_initiated_in == 0) {
3370
        return false;
3371
    }
3372
3373
    /* For now, do not reassemble transfer encoded bodies. Chunked encoding is explicitly disallowed by RFC7540,
3374
     * section 8.1. Additionally, section 8.1.2.2 specifies that the only valid value for the TE header (indicating
3375
     * which transfer-encoding is allowed) is trailers, suggesting transfer coding other than chunked (gzip,
3376
     * deflate, etc) are not allowed */
3377
    if (reassembly->has_transfer_encoded_body) {
3378
        return false;
3379
    }
3380
3381
    /* Is this data frame part of an established tunnel? Don't try to reassemble the data if that is the case */
3382
    http2_stream_info_t *stream_info = get_stream_info(pinfo, http2_session, false);
3383
    if (stream_info->is_stream_http_connect) {
3384
        return false;
3385
    }
3386
3387
    return true;
3388
}
3389
3390
static uint32_t
3391
get_reassembly_id_from_stream(packet_info *pinfo, http2_session_t* session)
3392
{
3393
    http2_stream_info_t *stream_info = get_stream_info(pinfo, session, false);
3394
    uint32_t flow_index = select_http2_flow_index(pinfo, session);
3395
3396
    /* With a stream ID being 31 bits, use the most significant bit to determine the flow direction of the
3397
     * stream. We use this for the ID in the body reassembly using the reassemble API */
3398
    return stream_info->stream_id | (flow_index << 31);
3399
}
3400
3401
/*
3402
 * Like process_reassembled_data() in reassemble.[ch], but ignores the layer
3403
 * number, which is not always stable in HTTP/2, if multiple TLS records are
3404
 * in the same frame.
3405
 */
3406
static tvbuff_t*
3407
http2_process_reassembled_data(tvbuff_t *tvb, const int offset, packet_info *pinfo,
3408
  const char *name, fragment_head *fd_head, const fragment_items *fit,
3409
  bool *update_col_infop, proto_tree *tree)
3410
{
3411
    tvbuff_t* next_tvb;
3412
    bool update_col_info;
3413
    proto_item* frag_tree_item;
3414
3415
    if (fd_head != NULL) {
3416
        /*
3417
         * OK, we've reassembled this.
3418
         * Is this something that's been reassembled from more
3419
         * than one fragment?
3420
         */
3421
        if (fd_head->next != NULL) {
3422
            /*
3423
             * Yes.
3424
             * Allocate a new tvbuff, referring to the
3425
             * reassembled payload, and set
3426
             * the tvbuff to the list of tvbuffs to which
3427
             * the tvbuff we were handed refers, so it'll get
3428
             * cleaned up when that tvbuff is cleaned up.
3429
             */
3430
            next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
3431
3432
            /* Add the defragmented data to the data source list. */
3433
            add_new_data_source(pinfo, next_tvb, name);
3434
3435
            /* show all fragments */
3436
            if (fd_head->flags & FD_BLOCKSEQUENCE) {
3437
                update_col_info = !show_fragment_seq_tree(
3438
                    fd_head, fit, tree, pinfo, next_tvb, &frag_tree_item);
3439
            }
3440
            else {
3441
                update_col_info = !show_fragment_tree(fd_head,
3442
                    fit, tree, pinfo, next_tvb, &frag_tree_item);
3443
            }
3444
        }
3445
        else {
3446
            /*
3447
             * No.
3448
             * Return a tvbuff with the payload, a subset of the tvbuff
3449
             * passed in.
3450
             */
3451
            int len;
3452
            if (fd_head->flags & FD_BLOCKSEQUENCE) {
3453
                len = fd_head->len;
3454
            } else {
3455
                // XXX Do the non-seq functions have this optimization?
3456
                len = fd_head->datalen;
3457
            }
3458
            next_tvb = tvb_new_subset_length(tvb, offset, len);
3459
            pinfo->fragmented = false;  /* one-fragment packet */
3460
            update_col_info = true;
3461
        }
3462
        if (update_col_infop != NULL)
3463
            *update_col_infop = update_col_info;
3464
    } else {
3465
        /*
3466
         * We don't have the complete reassembled payload, or this
3467
         * isn't the final frame of that payload.
3468
         */
3469
        next_tvb = NULL;
3470
        /* process_reassembled_data() in reassemble.[ch] adds reassembled_in
3471
         * here, but the reas_in_layer_num is often unstable in HTTP/2 now so
3472
         * we rely on the stream end flag (that's why we have this function).
3473
         *
3474
         * Perhaps we could DISSECTOR_ASSERT() in this path, we shouldn't
3475
         * get here.
3476
         */
3477
    }
3478
    return next_tvb;
3479
}
3480
3481
static tvbuff_t*
3482
reassemble_http2_data_into_full_frame(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* http2_session, proto_tree *http2_tree, unsigned offset,
3483
                                      uint8_t flags, unsigned datalen)
3484
{
3485
    http2_data_stream_reassembly_info_t *reassembly = get_data_reassembly_info(pinfo, http2_session);
3486
3487
    /* There are a number of conditions as to why we may not want to reassemble DATA frames */
3488
    if (!should_attempt_to_reassemble_data_frame(reassembly, pinfo, http2_session)) {
3489
        return NULL;
3490
    }
3491
3492
    /* Continue to add fragments, checking if we have any more fragments */
3493
    uint32_t reassembly_id = get_reassembly_id_from_stream(pinfo, http2_session);
3494
    fragment_head *head = NULL;
3495
    if (IS_HTTP2_END_STREAM(flags) && datalen == 0) {
3496
        /* Workaround displaying "[Frame: N (no data)]" for a HTTP2 frame that contains no data but ends the stream */
3497
        head = fragment_end_seq_next(&http2_body_reassembly_table, pinfo, reassembly_id, NULL);
3498
    } else {
3499
        head = fragment_add_seq_next(&http2_body_reassembly_table, tvb, offset, pinfo, reassembly_id, NULL,
3500
                                     datalen, !IS_HTTP2_END_STREAM(flags));
3501
    }
3502
3503
    /* Only call this if its the last DATA frame (END_STREAM) as the check in process_reassembled_data() will
3504
     * incorrectly match for frames that exist in the same packet as the final DATA frame and incorrectly add
3505
     * reassembly information to those dissection trees */
3506
    if (head && IS_HTTP2_END_STREAM(flags)) {
3507
        return http2_process_reassembled_data(tvb, offset, pinfo, "Reassembled body", head,
3508
                                              &http2_body_fragment_items, NULL, http2_tree);
3509
    }
3510
3511
    /* Add frame where reassembly happened. process_reassembled_data() does this automatically if the reassembled
3512
     * packet matches the packet that is calling the function, but makes some incorrect assumptions for multiple
3513
     * fragments contained in the same packet */
3514
    if (head) {
3515
        proto_tree_add_uint(http2_tree, hf_http2_body_reassembled_in, tvb, 0, 0,
3516
                            head->reassembled_in);
3517
    }
3518
3519
    /* Reassembly not complete yet*/
3520
    return NULL;
3521
}
3522
3523
static void
3524
dissect_http2_data_partial_body(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* http2_session, proto_tree *http2_tree, unsigned offset, int length,
3525
                                uint8_t flags)
3526
{
3527
    http2_data_stream_reassembly_info_t *reassembly = get_data_reassembly_info(pinfo, http2_session);
3528
    http2_stream_info_t *stream_info = get_stream_info(pinfo, http2_session, false);
3529
3530
    /* Is the frame part of a body that is going to be reassembled? */
3531
    if(!IS_HTTP2_END_STREAM(flags) && !stream_info->is_stream_http_connect) {
3532
        proto_item_append_text(http2_tree, " (partial entity body)");
3533
    }
3534
3535
    /* If we somehow got a transfer-encoded body, display it here */
3536
    if (reassembly->has_transfer_encoded_body) {
3537
        proto_item_append_text(http2_tree, " (transfer-encoded body)");
3538
    }
3539
3540
    /* Is this part of a tunneled connection? */
3541
    if (stream_info->is_stream_http_connect) {
3542
        proto_item_append_text(http2_tree, " (tunneled data)");
3543
    }
3544
3545
    proto_tree_add_item(http2_tree, hf_http2_data_data, tvb, offset, length, ENC_NA);
3546
3547
    if (stream_info->next_handle) {
3548
        stream_info->upgrade_info->from_server = select_http2_flow_index(pinfo, http2_session) == 1;
3549
        call_dissector_only(stream_info->next_handle, tvb_new_subset_remaining(tvb, offset), pinfo, proto_tree_get_parent_tree(proto_tree_get_parent_tree(http2_tree)), stream_info->upgrade_info);
3550
    }
3551
}
3552
3553
static void
3554
check_reassembly_completion_status(tvbuff_t* tvb, packet_info* pinfo, proto_tree* http2_tree,
3555
    unsigned offset, uint8_t flags, int length, streaming_reassembly_info_t* reassembly_info)
3556
{
3557
    int more_bytes_expected = additional_bytes_expected_to_complete_reassembly(reassembly_info);
3558
3559
    if (IS_HTTP2_END_STREAM(flags) && more_bytes_expected) {
3560
        if (more_bytes_expected == DESEGMENT_ONE_MORE_SEGMENT) {
3561
            proto_tree_add_expert_format(http2_tree, pinfo, &ei_http2_reassembly_error, tvb, offset, length,
3562
                "Reassembling HTTP2 body for subdissector failed, more bytes are missing before END_STREAM.");
3563
        } else {
3564
            proto_tree_add_expert_format(http2_tree, pinfo, &ei_http2_reassembly_error, tvb, offset, length,
3565
                "Reassembling HTTP2 body for subdissector failed, %d bytes are missing before END_STREAM.",
3566
                more_bytes_expected);
3567
        }
3568
    }
3569
}
3570
3571
/* Streaming reassembly of HTTP2 DATA will handle many cases. The most complicated one is:
3572
 *
3573
 * +--------------------------------------------- HTTP2 DATA payload ---------------------------------------------+
3574
 * | Part1: end of a multisegment PDU | Part2: one or more non-fragment PDUs | Part3: begin of a multisegment PDU |
3575
 * +----------------------------------+--------------------------------------+------------------------------------+
3576
 * Note: we use short name 'MSP' for 'Multisegment PDU', and 'NFP' for 'Non-fragment PDU'.
3577
 *
3578
 * In this case, one HTTP2 DATA payload contains:
3579
 *   Part1: At the begin of the DATA, there is the last part of a multisegment PDU.
3580
 *   Part2: The middle part of DATA payload contains one or more non-fragment PDUs.
3581
 *   Part3: At the tail of the DATA, there is the begin of a new multisegment PDU.
3582
 * All of three parts are optional. For example, one DATA could contain only Part1, Part2 or Part3; or contain
3583
 * Part1 and Part2 without Part3; or contain Part1 and Part3 without Part2; or contain Part2 and Part3 without
3584
 * Part1.
3585
 *
3586
 * And another case is the entire DATA is one of middle parts of a multisegment PDU. We call it MoMSP. Following
3587
 * case shows a multisegment PDU composed of Part3 + MoMSP + MoMSP + MoMSP + Part1:
3588
 *
3589
 *                 +-------------------------------- One Multisegment PDU ---------------------------------+
3590
 *                 |                                                                                       |
3591
 * +----- HTTP2 DATA1 -----+   +------------- HTTP2 DATA2 -----------+  +- DATA3 -+  +- DATA4 -+   +- HTTP2 DATA5 -+
3592
 * | Part1 | Part2 | Part3 |   | MoMSP: middle of a multisegment PDU |  |  MoMSP  |  |  MoMSP  |   | Part1 | Part3 |
3593
 * +-------+-------+-------+   +-------------------------------------+  +---------+  +---------+   +---------------+
3594
 *                 |                                                                                       |
3595
 *                 +---------------------------------------------------------------------------------------+
3596
 *
3597
 * Subdissector behave: The pinfo->desegment_len should contain the estimated number of additional bytes required
3598
 * for completing the PDU. and set pinfo->desegment_offset to the offset in the tvbuff at which the dissector will
3599
 * continue processing when next called. Next time the subdissector is called, it will be passed a tvbuff composed
3600
 * of the end of the data from the previous tvbuff together with desegment_len more bytes. If the dissector cannot
3601
 * tell how many more bytes it will need, it should set pinfo->desegment_len to additional bytes required for parsing
3602
 * message head or just DESEGMENT_ONE_MORE_SEGMENT. It will then be called again as soon as more data becomes available.
3603
 * Please refer to comments of the declaration of reassemble_streaming_data_and_call_subdissector() function in
3604
 * 'epan/reassemble.h' for more requirements about subdissectors.
3605
 */
3606
static void
3607
reassemble_http2_data_according_to_subdissector(tvbuff_t* tvb, packet_info* pinfo, http2_session_t* http2_session,
3608
                                                proto_tree* http2_tree, unsigned offset, uint8_t flags, int length)
3609
{
3610
    const char* saved_match_string = pinfo->match_string;
3611
    http2_frame_num_t cur_frame_num = get_http2_frame_num(tvb, pinfo);
3612
3613
    proto_tree_add_bytes_format(http2_tree, hf_http2_data_data, tvb, offset,
3614
        length, NULL, "DATA payload (%u byte%s)", length, plurality(length, "", "s"));
3615
3616
    http2_data_stream_body_info_t* body_info = get_data_stream_body_info(pinfo, http2_session);
3617
    char* content_type = body_info->content_type;
3618
    media_content_info_t metadata_used_for_media_type_handle = {
3619
        MEDIA_CONTAINER_HTTP_OTHERS, body_info->content_type_parameters, NULL, NULL
3620
    };
3621
    streaming_reassembly_info_t* reassembly_info = get_streaming_reassembly_info(pinfo, http2_session);
3622
3623
    dissector_handle_t subdissector_handle = dissector_get_string_handle(streaming_content_type_dissector_table, content_type);
3624
    if (subdissector_handle == NULL) {
3625
        /* We didn't get the content type, possibly because of byte errors.
3626
         * Note that the content type is per direction (as it should be)
3627
         * but reassembly_mode is set the same for *both* directions.
3628
         *
3629
         * We could try to set it to the content type used in the other
3630
         * direction, but among other things, if this is the request,
3631
         * we might be getting here for the first time on the second pass,
3632
         * and reassemble_streaming_data_and_call_subdissector() asserts in
3633
         *
3634
         * Just set it to data for now to avoid an assert from a NULL handle.
3635
         */
3636
        subdissector_handle = data_handle;
3637
    }
3638
    /* XXX - Do we still need to set this? */
3639
    pinfo->match_string = content_type;
3640
3641
    reassemble_streaming_data_and_call_subdissector(
3642
        tvb, pinfo, offset, length, http2_tree, proto_tree_get_parent_tree(http2_tree),
3643
        http2_streaming_reassembly_table, reassembly_info, (uint64_t)cur_frame_num,
3644
        subdissector_handle, proto_tree_get_parent_tree(http2_tree), &metadata_used_for_media_type_handle,
3645
        "HTTP2 body", &http2_body_fragment_items, hf_http2_data_segment);
3646
3647
    pinfo->match_string = saved_match_string;
3648
3649
    if (IS_HTTP2_END_STREAM(flags)) {
3650
        check_reassembly_completion_status(tvb, pinfo, http2_tree, offset, flags, length, reassembly_info);
3651
    }
3652
}
3653
3654
static void
3655
dissect_http2_data_body(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* h2session, proto_tree *http2_tree, unsigned offset, uint8_t flags, int length)
3656
{
3657
    try_init_stream_with_fake_headers(tvb, pinfo, h2session, http2_tree, offset);
3658
3659
    http2_stream_info_t *stream_info = get_stream_info(pinfo, h2session, false);
3660
    if (stream_info->reassembly_mode == HTTP2_DATA_REASSEMBLY_MODE_STREAMING) {
3661
        reassemble_http2_data_according_to_subdissector(tvb, pinfo, h2session, http2_tree, offset, flags, length);
3662
        return;
3663
    }
3664
3665
    tvbuff_t *data_tvb = reassemble_http2_data_into_full_frame(tvb, pinfo, h2session, http2_tree, offset, flags, length);
3666
3667
    if (data_tvb != NULL) {
3668
        dissect_http2_data_full_body(data_tvb, pinfo, h2session, http2_tree);
3669
    } else {
3670
        dissect_http2_data_partial_body(tvb, pinfo, h2session, http2_tree, offset, length, flags);
3671
    }
3672
}
3673
3674
/* Get real header value from current or the other direction stream_header_list */
3675
static const char*
3676
get_real_header_value(packet_info* pinfo, const char* name, bool the_other_direction)
3677
{
3678
    http2_header_stream_info_t* header_stream_info;
3679
    wmem_list_frame_t* frame;
3680
    wmem_array_t* headers;
3681
    unsigned i;
3682
    uint32_t name_len;
3683
    uint32_t value_len;
3684
    http2_header_t *hdr;
3685
    char* data;
3686
3687
    conversation_t* conversation = find_or_create_conversation(pinfo);
3688
    header_stream_info = get_header_stream_info(pinfo, get_http2_session(pinfo, conversation), the_other_direction);
3689
    if (!header_stream_info) {
3690
        return NULL;
3691
    }
3692
3693
    for (frame = wmem_list_head(header_stream_info->stream_header_list);
3694
        frame;
3695
        frame = wmem_list_frame_next(frame))
3696
    {   /* each frame contains one HEADERS or CONTINUATION frame's headers */
3697
        headers = (wmem_array_t*)wmem_list_frame_data(frame);
3698
        if (!headers) {
3699
            continue;
3700
        }
3701
3702
        for (i = 0; i < wmem_array_get_count(headers); ++i) {
3703
            hdr = (http2_header_t*)wmem_array_index(headers, i);
3704
            if (hdr->type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE) {
3705
                continue;
3706
            }
3707
3708
            /* parsing data as format:
3709
                   name length (uint32)
3710
                   name (string)
3711
                   value length (uint32)
3712
                   value (string)
3713
            */
3714
            data = (char*) hdr->table.data.data;
3715
            name_len = pntohu32(data);
3716
            if (strlen(name) == name_len && strncmp(data + 4, name, name_len) == 0) {
3717
                value_len = pntohu32(data + 4 + name_len);
3718
                if (4 + name_len + 4 + value_len == hdr->table.data.datalen) {
3719
                    /* return value */
3720
                    return (const char*)get_ascii_string(pinfo->pool, (uint8_t*)(data + 4 + name_len + 4), value_len);
3721
                }
3722
                else {
3723
                    return NULL; /* unexpected error */
3724
                }
3725
            }
3726
        }
3727
    }
3728
3729
    return NULL;
3730
}
3731
3732
/* Get header value from current or the other direction stream_header_list */
3733
const char*
3734
http2_get_header_value(packet_info *pinfo, const char* name, bool the_other_direction)
3735
{
3736
    bool override = false;
3737
    const char* real_value = get_real_header_value(pinfo, name, the_other_direction);
3738
    const char* fake_value = get_fake_header_value(pinfo, name, the_other_direction, &override);
3739
    if (real_value && override == false) {
3740
        return real_value;
3741
    } else if (fake_value) {
3742
        return fake_value;
3743
    }
3744
    return NULL;
3745
}
3746
#else
3747
static void
3748
dissect_http2_data_body(tvbuff_t *tvb, packet_info *pinfo _U_, http2_session_t* http2_session _U_, proto_tree *http2_tree, unsigned offset, uint8_t flags _U_, int datalen)
3749
136
{
3750
136
    proto_tree_add_item(http2_tree, hf_http2_data_data, tvb, offset, datalen, ENC_NA);
3751
136
}
3752
3753
const char*
3754
http2_get_header_value(packet_info *pinfo _U_, const char* name _U_, bool the_other_direction _U_)
3755
0
{
3756
0
    return NULL;
3757
0
}
3758
#endif
3759
3760
/* Increment or decrement the accumulated connection and/or stream window
3761
 * sizes based on the flow direction, stream ID and increaseWindow parameter.
3762
 * In other words, if increaseWindow is true, then we're processing a
3763
 * WINDOW_UPDATE frame; otherwise, we're processing a DATA frame. (Window
3764
 * size changes from a SETTINGS frame are handled in adjust_existing_window.)
3765
 */
3766
static void
3767
adjust_window_size(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* http2_session, proto_tree *http2_tree, uint32_t adjustment, bool increaseWindow)
3768
131
{
3769
131
    proto_item *ti;
3770
131
    uint32_t flow_index = select_http2_flow_index(pinfo, http2_session);
3771
    /* This SHOULD NOT overflow because the adjustment value is a 31-bit
3772
     * unsigned integer. */
3773
131
    int32_t finalAdjustment = ((increaseWindow ? 1 : -1) * (int32_t)adjustment);
3774
3775
131
    if (increaseWindow) {
3776
        /* The WINDOW_UPDATE comes in for the other direction */
3777
4
        flow_index ^= 1;
3778
4
    }
3779
3780
    /* "The sender MUST NOT send a flow-controlled frame with a length that
3781
     * exceeds the space available in either of the flow-control windows...
3782
     * A sender MUST NOT allow a flow-control window to exceed 2^31-1 octets."
3783
     * https://datatracker.ietf.org/doc/html/rfc9113#section-6.9.1
3784
     * "A sender MUST track the negative flow-control window [from a SETTINGS
3785
     * frame with SETTINGS_INITIAL_WINDOW_SIZE] and MUST NOT send new
3786
     * flow-controlled frames until.. the flow-control window... become[s]
3787
     * positive."
3788
     * https://datatracker.ietf.org/doc/html/rfc9113#section-6.9.2
3789
     */
3790
3791
    /* Always decrease the connection window after sending data,
3792
     * but only increase the connection window for a WINDOW_UPDATE on stream 0 (the connection). */
3793
131
    if (!increaseWindow || http2_session->current_stream_id == 0) {
3794
130
        int32_t* window_size_connection_before = p_get_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_WINDOW_SIZE_CONNECTION_BEFORE);
3795
130
        int32_t window_size_connection_after;
3796
130
        bool window_size_overflow = false;
3797
3798
130
        if (!window_size_connection_before) {
3799
            /* There may be multiple passes, so we must use proto_data to keep state */
3800
39
            window_size_connection_before = wmem_new0(wmem_file_scope(), int32_t);
3801
39
            (*window_size_connection_before) = http2_session->current_connection_window_size[flow_index];
3802
39
            if (ckd_add(&http2_session->current_connection_window_size[flow_index], http2_session->current_connection_window_size[flow_index], finalAdjustment)) {
3803
                /* Overflow in the negative direction is unlikely, but check. */
3804
1
                http2_session->current_connection_window_size[flow_index] = increaseWindow ? INT32_MAX : INT32_MIN;
3805
1
            }
3806
39
            p_add_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_WINDOW_SIZE_CONNECTION_BEFORE, window_size_connection_before);
3807
39
        }
3808
3809
130
        proto_item_set_generated(proto_tree_add_int(http2_tree, hf_http2_calculated_window_size_connection_before,
3810
130
                                                    tvb, 0, 0, (*window_size_connection_before)));
3811
3812
130
        if (ckd_add(&window_size_connection_after, *window_size_connection_before, finalAdjustment)) {
3813
1
            window_size_connection_after = increaseWindow ? INT32_MAX : INT32_MIN;
3814
1
            window_size_overflow = true;
3815
1
        }
3816
3817
130
        ti = proto_tree_add_int(http2_tree, hf_http2_calculated_window_size_connection_after,
3818
130
                                                    tvb, 0, 0, window_size_connection_after);
3819
3820
130
        proto_item_set_generated(ti);
3821
3822
130
        if (window_size_overflow) {
3823
1
            expert_add_info(pinfo, ti, &ei_http2_window_size);
3824
129
        } else if (window_size_connection_after < 0) {
3825
0
            expert_add_info_format(pinfo, ti, &ei_http2_window_size, "Flow-controlled frame received with length that exceeds the calculated connection window size");
3826
0
        }
3827
130
    }
3828
3829
#ifdef HAVE_NGHTTP2
3830
    /* Always decrease the stream window after sending data,
3831
     * but only increase the stream window for a WINDOW_UPDATE on stream > 0 (not the connection). */
3832
    if (!increaseWindow || http2_session->current_stream_id > 0) {
3833
        http2_stream_info_t *http2_stream_info = get_stream_info(pinfo, http2_session, increaseWindow);
3834
        int32_t* window_size_stream_before = p_get_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_WINDOW_SIZE_STREAM_BEFORE);
3835
        int32_t window_size_stream_after;
3836
        bool window_size_overflow = false;
3837
3838
        if (!window_size_stream_before) {
3839
            /* There may be multiple passes, so we must use proto_data to keep state */
3840
            window_size_stream_before = wmem_new0(wmem_file_scope(), int32_t);
3841
            (*window_size_stream_before) = http2_stream_info->oneway_stream_info[flow_index].current_window_size;
3842
            if (ckd_add(&http2_stream_info->oneway_stream_info[flow_index].current_window_size, http2_stream_info->oneway_stream_info[flow_index].current_window_size, finalAdjustment)) {
3843
                http2_session->current_connection_window_size[flow_index] = increaseWindow ? INT32_MAX : INT32_MIN;
3844
            }
3845
            p_add_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_WINDOW_SIZE_STREAM_BEFORE, window_size_stream_before);
3846
        }
3847
3848
        proto_item_set_generated(proto_tree_add_int(http2_tree, hf_http2_calculated_window_size_stream_before, tvb, 0, 0,
3849
                                                    (*window_size_stream_before)));
3850
3851
        if (ckd_add(&window_size_stream_after, *window_size_stream_before, finalAdjustment)) {
3852
            window_size_stream_after = increaseWindow ? INT32_MAX : INT32_MIN;
3853
            window_size_overflow = true;
3854
        }
3855
3856
        ti = proto_tree_add_int(http2_tree, hf_http2_calculated_window_size_stream_after, tvb, 0, 0,
3857
                                                    window_size_stream_after);
3858
3859
        proto_item_set_generated(ti);
3860
        if (window_size_overflow) {
3861
            expert_add_info(pinfo, ti, &ei_http2_window_size);
3862
        } else if (window_size_stream_after < 0) {
3863
            expert_add_info_format(pinfo, ti, &ei_http2_window_size, "Flow-controlled frame received with length that exceeds the calculated stream window size");
3864
        }
3865
    }
3866
#endif
3867
131
}
3868
3869
/* Data (0) */
3870
static int
3871
dissect_http2_data(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* http2_session, proto_tree *http2_tree,
3872
                   unsigned offset, uint8_t flags)
3873
144
{
3874
144
    uint16_t padding;
3875
144
    int datalen;
3876
3877
144
    offset = dissect_frame_padding(tvb, &padding, http2_tree, offset, flags);
3878
144
    datalen = tvb_reported_length_remaining(tvb, offset + padding);
3879
3880
144
    dissect_http2_data_body(tvb_new_subset_length(tvb, offset, datalen), pinfo, http2_session, http2_tree, 0, flags, datalen);
3881
3882
144
    offset += datalen;
3883
3884
144
    if (padding) {
3885
3
        proto_tree_add_item(http2_tree, hf_http2_data_padding, tvb, offset, padding, ENC_NA);
3886
3
        offset += padding;
3887
3
    }
3888
3889
144
    adjust_window_size(tvb, pinfo, http2_session, http2_tree, (uint32_t)datalen, false);
3890
3891
144
    return offset;
3892
144
}
3893
3894
/* Headers */
3895
static int
3896
#ifdef HAVE_NGHTTP2
3897
dissect_http2_headers(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* h2session, proto_tree *http2_tree,
3898
                      unsigned offset, uint8_t flags)
3899
#else
3900
dissect_http2_headers(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* h2session _U_, proto_tree *http2_tree,
3901
                      unsigned offset, uint8_t flags)
3902
#endif
3903
13
{
3904
13
    uint16_t padding;
3905
13
    int headlen;
3906
#ifdef HAVE_NGHTTP2
3907
    fragment_head *head;
3908
    http2_stream_info_t *info;
3909
    streaming_reassembly_info_t *reassembly_info;
3910
3911
    /* Trailing headers coming after a DATA stream should have END_STREAM set. DATA should be complete
3912
     * so try to reassemble DATA fragments if that is the case */
3913
    if(IS_HTTP2_END_STREAM(flags)) {
3914
        info = get_stream_info(pinfo, h2session, false);
3915
        switch (info->reassembly_mode) {
3916
        case HTTP2_DATA_REASSEMBLY_MODE_END_STREAM:
3917
            head = fragment_end_seq_next(&http2_body_reassembly_table, pinfo, get_reassembly_id_from_stream(pinfo, h2session), NULL);
3918
            if(head) {
3919
                tvbuff_t *reassembled_data = process_reassembled_data(tvb, 0, pinfo, "Reassembled body", head,
3920
                                                                      &http2_body_fragment_items, NULL, http2_tree);
3921
                dissect_http2_data_full_body(reassembled_data, pinfo, h2session, http2_tree);
3922
            }
3923
            break;
3924
3925
        case HTTP2_DATA_REASSEMBLY_MODE_STREAMING:
3926
            reassembly_info = get_streaming_reassembly_info(pinfo, h2session);
3927
            check_reassembly_completion_status(tvb, pinfo, http2_tree, offset, flags, tvb_reported_length(tvb), reassembly_info);
3928
            break;
3929
3930
        default:
3931
            /* do nothing */
3932
            break;
3933
        }
3934
    }
3935
3936
    /* Mark this frame as the first header frame seen and last if the END_HEADERS flag
3937
     * is set. We use this to ensure when we read header values, we are not reading ones
3938
     * that have come from a PUSH_PROMISE header (and associated CONTINUATION frames) */
3939
    if (!PINFO_FD_VISITED(pinfo)) {
3940
        http2_header_stream_info_t *header_stream_info = get_header_stream_info(pinfo, h2session, false);
3941
        header_stream_info->header_start_in = get_http2_frame_num(tvb, pinfo);
3942
        if (flags & HTTP2_FLAGS_END_HEADERS) {
3943
            header_stream_info->header_end_in = get_http2_frame_num(tvb, pinfo);
3944
        } else {
3945
            header_stream_info->header_end_in = 0;
3946
        }
3947
        header_stream_info->stream_id = h2session->current_stream_id;
3948
    }
3949
#endif
3950
3951
13
    offset = dissect_frame_padding(tvb, &padding, http2_tree, offset, flags);
3952
13
    offset = dissect_frame_prio(tvb, http2_tree, offset, flags);
3953
3954
13
    headlen = tvb_reported_length_remaining(tvb, offset);
3955
13
    if (headlen < padding) {
3956
        /* XXX - what error *should* be reported here? */
3957
0
        THROW(ReportedBoundsError);
3958
0
    }
3959
13
    headlen -= padding;
3960
13
    proto_tree_add_item(http2_tree, hf_http2_headers, tvb, offset, headlen, ENC_NA);
3961
3962
#ifdef HAVE_NGHTTP2
3963
    /* decompress the header block */
3964
    inflate_http2_header_block(tvb, pinfo, offset, http2_tree, headlen, h2session, flags);
3965
3966
    http2_stream_info_t *stream_info = get_stream_info(pinfo, h2session, false);
3967
3968
    /* Display request/response links */
3969
    if (pinfo->num > stream_info->request_in_frame_num && stream_info->request_in_frame_num > 0) {
3970
        /* Response frame */
3971
        if (! nstime_is_unset(&(stream_info->request_ts))) {
3972
            nstime_t delta;
3973
3974
            nstime_delta(&delta, &pinfo->abs_ts, &(stream_info->request_ts));
3975
            proto_item_set_generated(proto_tree_add_time(http2_tree, hf_http2_time, tvb, 0, 0, &delta));
3976
        }
3977
        proto_item_set_generated(proto_tree_add_uint(http2_tree, hf_http2_request_in, tvb, 0, 0, stream_info->request_in_frame_num));
3978
    }
3979
    if (pinfo->num == stream_info->request_in_frame_num && stream_info->response_in_frame_num > 0) {
3980
        /* Request frame */
3981
        proto_item_set_generated(proto_tree_add_uint(http2_tree, hf_http2_response_in, tvb, 0, 0, stream_info->response_in_frame_num));
3982
    }
3983
3984
#else
3985
13
    proto_tree_add_expert_format(http2_tree, pinfo, &ei_http2_header_size, tvb, offset, headlen,
3986
13
            "Wireshark must be built with nghttp2 for HTTP/2 HEADERS support");
3987
13
#endif
3988
3989
13
    offset += headlen;
3990
3991
13
    if (padding) {
3992
0
        proto_tree_add_item(http2_tree, hf_http2_headers_padding, tvb, offset, padding, ENC_NA);
3993
0
        offset += padding;
3994
0
    }
3995
3996
13
    return offset;
3997
13
}
3998
3999
/* Priority */
4000
static int
4001
dissect_http2_priority(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree,
4002
                       unsigned offset, uint8_t flags)
4003
2
{
4004
    /* we pretend the HTTP2_FLAGS_PRIORITY flag is set to share the dissect
4005
       function */
4006
2
    offset = dissect_frame_prio(tvb, http2_tree, offset,
4007
2
                                flags | HTTP2_FLAGS_PRIORITY);
4008
2
    return offset;
4009
2
}
4010
4011
/* RST Stream */
4012
static int
4013
dissect_http2_rst_stream(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree, unsigned offset, uint8_t flags _U_)
4014
2
{
4015
4016
2
    proto_tree_add_item(http2_tree, hf_http2_rst_stream_error, tvb, offset, 4, ENC_BIG_ENDIAN);
4017
2
    offset += 4;
4018
4019
2
    return offset;
4020
2
}
4021
4022
#ifdef HAVE_NGHTTP2
4023
static void
4024
adjust_existing_window(void *key _U_, void *value, void *userData)
4025
{
4026
    http2_stream_info_t *stream_info = (http2_stream_info_t *)value;
4027
    http2_adjust_window_t *adjustWindow = (http2_adjust_window_t *)userData;
4028
    /* "A change to SETTINGS_INITIAL_WINDOW_SIZE can cause the available space
4029
     * in a flow-control window to become negative," so do not add an expert
4030
     * info here for becoming negative, but do later if a flow-controlled frame
4031
     * is sent before the calculated window becomes positive.
4032
     * https://datatracker.ietf.org/doc/html/rfc9113#section-6.9.2
4033
     *
4034
     * This can overflow in extremely unusual situations.
4035
     */
4036
    if (ckd_add(&stream_info->oneway_stream_info[adjustWindow->flow_index].current_window_size, stream_info->oneway_stream_info[adjustWindow->flow_index].current_window_size, adjustWindow->windowSizeDiff)) {
4037
        adjustWindow->overflow = true;
4038
    }
4039
}
4040
#endif
4041
4042
/* Settings */
4043
static int
4044
#ifdef HAVE_NGHTTP2
4045
dissect_http2_settings(tvbuff_t* tvb, packet_info* pinfo _U_, http2_session_t* h2session, proto_tree* http2_tree, unsigned offset, uint8_t flags)
4046
#else
4047
dissect_http2_settings(tvbuff_t* tvb, packet_info* pinfo _U_, http2_session_t* h2session _U_, proto_tree* http2_tree, unsigned offset, uint8_t flags _U_)
4048
#endif
4049
28
{
4050
28
    uint32_t settingsid;
4051
28
    proto_item *ti_settings;
4052
28
    proto_tree *settings_tree;
4053
#ifdef HAVE_NGHTTP2
4054
    uint32_t header_table_size;
4055
    uint32_t min_header_table_size;
4056
    int header_table_size_found;
4057
4058
    header_table_size_found = 0;
4059
    header_table_size = 0;
4060
    min_header_table_size = 0xFFFFFFFFu;
4061
#endif
4062
4063
1.45k
    while(tvb_reported_length_remaining(tvb, offset) > 0){
4064
4065
1.45k
        ti_settings = proto_tree_add_item(http2_tree, hf_http2_settings, tvb, offset, 6, ENC_NA);
4066
1.45k
        settings_tree = proto_item_add_subtree(ti_settings, ett_http2_settings);
4067
1.45k
        proto_tree_add_item(settings_tree, hf_http2_settings_identifier, tvb, offset, 2, ENC_BIG_ENDIAN);
4068
1.45k
        settingsid = tvb_get_ntohs(tvb, offset);
4069
1.45k
        proto_item_append_text(ti_settings, " - %s",
4070
1.45k
                               val_to_str(pinfo->pool, settingsid, http2_settings_vals, "Unknown (%u)") );
4071
1.45k
        offset += 2;
4072
4073
4074
1.45k
        switch(settingsid){
4075
9
            case HTTP2_SETTINGS_HEADER_TABLE_SIZE:
4076
9
                proto_tree_add_item(settings_tree, hf_http2_settings_header_table_size, tvb, offset, 4, ENC_BIG_ENDIAN);
4077
4078
#ifdef HAVE_NGHTTP2
4079
                /* We only care the last header table size in SETTINGS */
4080
                header_table_size_found = 1;
4081
                header_table_size = tvb_get_ntohl(tvb, offset);
4082
                if(min_header_table_size > header_table_size) {
4083
                    min_header_table_size = header_table_size;
4084
                }
4085
#endif
4086
9
            break;
4087
14
            case HTTP2_SETTINGS_ENABLE_PUSH:
4088
14
                proto_tree_add_item(settings_tree, hf_http2_settings_enable_push, tvb, offset, 4, ENC_BIG_ENDIAN);
4089
14
            break;
4090
17
            case HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
4091
17
                proto_tree_add_item(settings_tree, hf_http2_settings_max_concurrent_streams, tvb, offset, 4, ENC_BIG_ENDIAN);
4092
17
            break;
4093
14
            case HTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
4094
14
                {
4095
14
                    uint32_t newInitialWindowSize;
4096
14
                    proto_item *ti;
4097
4098
14
                    ti = proto_tree_add_item_ret_uint(settings_tree, hf_http2_settings_initial_window_size, tvb, offset, 4, ENC_BIG_ENDIAN, &newInitialWindowSize);
4099
14
                    if (newInitialWindowSize > INT32_MAX) {
4100
                        /* The value here explicitly is 32-bits and can exceed
4101
                         * the maximum value (which is a connection error),
4102
                         * unlike the WINDOW UPDATE frame where it is a 31-bit
4103
                         * value with a reserved bit and bitmask.
4104
                         * https://datatracker.ietf.org/doc/html/rfc9113#SETTINGS_INITIAL_WINDOW_SIZE
4105
                         */
4106
3
                        expert_add_info_format(pinfo, ti, &ei_http2_window_size, "Initial window size exceeds maximum size (" G_STRINGIFY(INT32_MAX) ")");
4107
                        /* Prevent windowSizeDiff from overflowing. */
4108
3
                        newInitialWindowSize = INT32_MAX;
4109
3
                    }
4110
4111
14
                    if (h2session) {
4112
14
                        uint32_t flow_index = select_http2_flow_index(pinfo, h2session);
4113
4114
                        /* This new initial window size will be applied to
4115
                         * any new future streams going in the other direction.
4116
                         * Note that this setting does not apply to the connection:
4117
                         * https://lists.w3.org/Archives/Public/ietf-http-wg/2023JanMar/0003.html
4118
                         */
4119
14
                        flow_index ^= 1;
4120
4121
#ifdef HAVE_NGHTTP2
4122
                        {
4123
                            uint32_t previousInitialWindowSize = h2session->initial_new_stream_window_size[flow_index];
4124
                            int32_t windowSizeDiff = newInitialWindowSize - previousInitialWindowSize;
4125
4126
                            /* "When the value of SETTINGS_INITIAL_WINDOW_SIZE changes,
4127
                            *  a receiver MUST adjust the size of all stream flow-control
4128
                            *  windows that it maintains by the difference between the
4129
                            *  new value and the old value."
4130
                            * https://www.ietf.org/rfc/rfc9113.html#section-6.9.2-3
4131
                            */
4132
                            if (windowSizeDiff != 0) {
4133
                                http2_adjust_window_t userData;
4134
4135
                                userData.windowSizeDiff = windowSizeDiff;
4136
                                userData.flow_index = flow_index;
4137
                                userData.overflow = false;
4138
4139
                                wmem_map_foreach(h2session->per_stream_info, adjust_existing_window, &userData);
4140
                                if (userData.overflow) {
4141
                                    expert_add_info(pinfo, ti, &ei_http2_window_size);
4142
                                }
4143
                            }
4144
                        }
4145
#endif
4146
4147
14
                        h2session->initial_new_stream_window_size[flow_index] = newInitialWindowSize;
4148
14
                    }
4149
14
                }
4150
14
            break;
4151
6
            case HTTP2_SETTINGS_MAX_FRAME_SIZE:
4152
6
                proto_tree_add_item(settings_tree, hf_http2_settings_max_frame_size, tvb, offset, 4, ENC_BIG_ENDIAN);
4153
6
            break;
4154
11
            case HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
4155
11
                proto_tree_add_item(settings_tree, hf_http2_settings_max_header_list_size, tvb, offset, 4, ENC_BIG_ENDIAN);
4156
11
            break;
4157
11
            case HTTP2_SETTINGS_EXTENDED_CONNECT:
4158
11
                proto_tree_add_item(settings_tree, hf_http2_settings_extended_connect, tvb, offset, 4, ENC_BIG_ENDIAN);
4159
11
            break;
4160
0
            case HTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
4161
0
                proto_tree_add_item(settings_tree, hf_http2_settings_no_rfc7540_priorities, tvb, offset, 4, ENC_BIG_ENDIAN);
4162
0
            break;
4163
2
            case HTTP2_SETTINGS_TLS_RENEG_PERMITTED:
4164
2
                proto_tree_add_item(settings_tree, hf_http2_settings_tls_reneg_permitted, tvb, offset, 4, ENC_BIG_ENDIAN);
4165
2
            break;
4166
1.36k
            default:
4167
1.36k
                proto_tree_add_item(settings_tree, hf_http2_settings_unknown, tvb, offset, 4, ENC_BIG_ENDIAN);
4168
1.36k
            break;
4169
1.45k
        }
4170
1.42k
        proto_item_append_text(ti_settings, " : %u", tvb_get_ntohl(tvb, offset));
4171
1.42k
        offset += 4;
4172
1.42k
    }
4173
4174
#ifdef HAVE_NGHTTP2
4175
    if(!PINFO_FD_VISITED(pinfo)&&(h2session != NULL)) {
4176
4177
        if(flags & HTTP2_FLAGS_ACK) {
4178
            apply_and_pop_settings(pinfo, h2session);
4179
        } else {
4180
            http2_settings_t *settings;
4181
4182
            settings = wmem_new(wmem_file_scope(), http2_settings_t);
4183
4184
            settings->min_header_table_size = min_header_table_size;
4185
            settings->header_table_size = header_table_size;
4186
            settings->has_header_table_size = header_table_size_found;
4187
4188
            push_settings(pinfo, h2session, settings);
4189
        }
4190
    }
4191
#endif
4192
4193
0
    return offset;
4194
28
}
4195
4196
void
4197
0
dissect_http2_settings_ext(tvbuff_t* tvb, packet_info* pinfo _U_, proto_tree* http2_tree, unsigned offset) {
4198
0
    dissect_http2_settings(tvb, pinfo, NULL, http2_tree, offset, 0);
4199
0
}
4200
4201
/* Push Promise */
4202
static int
4203
#ifdef HAVE_NGHTTP2
4204
dissect_http2_push_promise(tvbuff_t *tvb, packet_info *pinfo _U_, http2_session_t* h2session, proto_tree *http2_tree,
4205
                           unsigned offset, uint8_t flags _U_)
4206
#else
4207
dissect_http2_push_promise(tvbuff_t *tvb, packet_info *pinfo _U_, http2_session_t* h2session _U_, proto_tree *http2_tree,
4208
                           unsigned offset, uint8_t flags _U_)
4209
#endif
4210
4
{
4211
4
    uint16_t padding;
4212
4
    int headlen;
4213
4
    uint32_t promised_stream_id;
4214
4215
4
    offset = dissect_frame_padding(tvb, &padding, http2_tree, offset, flags);
4216
4217
4
    proto_tree_add_item(http2_tree, hf_http2_push_promise_r, tvb, offset, 4, ENC_BIG_ENDIAN);
4218
4
    proto_tree_add_item_ret_uint(http2_tree, hf_http2_push_promise_promised_stream_id, tvb,
4219
4
                        offset, 4, ENC_BIG_ENDIAN, &promised_stream_id);
4220
#ifdef HAVE_NGHTTP2
4221
    if (!PINFO_FD_VISITED(pinfo)) {
4222
        http2_header_stream_info_t *header_stream_info = get_header_stream_info(pinfo, h2session, false);
4223
        header_stream_info->header_start_in = get_http2_frame_num(tvb, pinfo);
4224
        if (flags & HTTP2_FLAGS_END_HEADERS) {
4225
            header_stream_info->header_end_in = get_http2_frame_num(tvb, pinfo);
4226
        } else {
4227
            header_stream_info->header_end_in = 0;
4228
        }
4229
        header_stream_info->stream_id = promised_stream_id;
4230
    }
4231
#endif
4232
4
    offset += 4;
4233
4234
4
    headlen = tvb_reported_length_remaining(tvb, offset);
4235
4
    if (headlen < padding) {
4236
        /* XXX - what error *should* be reported here? */
4237
0
        THROW(ReportedBoundsError);
4238
0
    }
4239
4
    headlen -= padding;
4240
4
    proto_tree_add_item(http2_tree, hf_http2_push_promise_header, tvb, offset, headlen,
4241
4
                        ENC_NA);
4242
4243
#ifdef HAVE_NGHTTP2
4244
    inflate_http2_header_block(tvb, pinfo, offset, http2_tree, headlen, h2session, flags);
4245
4246
    /* Display request/response links */
4247
    /* For PUSH_PROMISE, the response is on the promised stream ID. The
4248
     * response is also in the same direction as the request.
4249
     */
4250
    http2_stream_info_t *stream_info = get_stream_info_for_id(pinfo, h2session, false, promised_stream_id);
4251
4252
    if (pinfo->num == stream_info->request_in_frame_num && stream_info->response_in_frame_num > 0) {
4253
        /* Request frame */
4254
        proto_item_set_generated(proto_tree_add_uint(http2_tree, hf_http2_response_in, tvb, 0, 0, stream_info->response_in_frame_num));
4255
    }
4256
4257
    const char *uri = http2_get_request_full_uri(pinfo, h2session, promised_stream_id);
4258
    if (uri) {
4259
        proto_item *uri_ti = proto_tree_add_string_format(http2_tree, hf_http2_header_request_full_uri, tvb, 0, 0, uri, "Full promised request URI: %s", uri);
4260
        proto_item_set_url(uri_ti);
4261
        proto_item_set_generated(uri_ti);
4262
    }
4263
4264
    /* Add Associate IMSI */
4265
    dissect_http2_add_assoc_imsi_to_tracked_3gpp_session(tvb, http2_tree, stream_info);
4266
#endif
4267
4268
4
    offset += headlen;
4269
4270
4
    if (padding) {
4271
0
        proto_tree_add_item(http2_tree, hf_http2_push_promise_padding, tvb,
4272
0
                            offset, padding, ENC_NA);
4273
0
    }
4274
4275
4
    offset +=  tvb_reported_length_remaining(tvb, offset);
4276
4277
4
    return offset;
4278
4
}
4279
4280
/* Ping */
4281
static int
4282
dissect_http2_ping(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree,
4283
                   unsigned offset, uint8_t flags)
4284
3
{
4285
    /* TODO : Add Response time */
4286
3
    if(flags & HTTP2_FLAGS_ACK)
4287
1
    {
4288
1
            proto_tree_add_item(http2_tree, hf_http2_pong, tvb, offset, 8, ENC_NA);
4289
2
    }else{
4290
2
            proto_tree_add_item(http2_tree, hf_http2_ping, tvb, offset, 8, ENC_NA);
4291
2
    }
4292
3
    offset += 8;
4293
4294
3
    return offset;
4295
3
}
4296
4297
/* Goaway */
4298
static int
4299
dissect_http2_goaway(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree, unsigned offset, uint8_t flags _U_)
4300
1
{
4301
4302
1
    proto_tree_add_item(http2_tree, hf_http2_goaway_r, tvb, offset, 4, ENC_BIG_ENDIAN);
4303
1
    proto_tree_add_item(http2_tree, hf_http2_goaway_last_stream_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4304
1
    offset += 4;
4305
4306
1
    proto_tree_add_item(http2_tree, hf_http2_goaway_error, tvb, offset, 4, ENC_BIG_ENDIAN);
4307
1
    offset += 4;
4308
1
    if(tvb_reported_length_remaining(tvb, offset) > 0)
4309
1
    {
4310
1
        proto_tree_add_item(http2_tree, hf_http2_goaway_addata , tvb, offset, -1, ENC_NA);
4311
1
        offset += tvb_reported_length_remaining(tvb, offset);
4312
1
    }
4313
1
    return offset;
4314
1
}
4315
4316
/* Window Update */
4317
static int
4318
dissect_http2_window_update(tvbuff_t *tvb, packet_info *pinfo, http2_session_t* http2_session, proto_tree *http2_tree, unsigned offset, uint8_t flags _U_)
4319
5
{
4320
5
    uint32_t wsi;
4321
5
    proto_item *ti;
4322
4323
5
    proto_tree_add_item(http2_tree, hf_http2_window_update_r, tvb, offset, 4, ENC_BIG_ENDIAN);
4324
5
    ti = proto_tree_add_item_ret_uint(http2_tree, hf_http2_window_update_window_size_increment, tvb, offset, 4, ENC_BIG_ENDIAN, &wsi);
4325
5
    if (wsi == 0) {
4326
        /* "A receiver MUST treat the receipt of a WINDOW_UPDATE frame with a
4327
         * flow-control window increment of 0 as a stream error of type
4328
         * PROTOCOL_ERROR."
4329
         * https://datatracker.ietf.org/doc/html/rfc9113#section-6.9 */
4330
0
        expert_add_info_format(pinfo, ti, &ei_http2_window_size, "Window increment value of 0");
4331
0
    }
4332
5
    offset += 4;
4333
4334
5
    adjust_window_size(tvb, pinfo, http2_session, http2_tree, wsi, true);
4335
4336
5
    return offset;
4337
5
}
4338
4339
static int
4340
#ifdef HAVE_NGHTTP2
4341
dissect_http2_continuation(tvbuff_t *tvb, packet_info *pinfo _U_, http2_session_t* h2session, proto_tree *http2_tree, unsigned offset, uint8_t flags)
4342
#else
4343
dissect_http2_continuation(tvbuff_t *tvb, packet_info *pinfo _U_, http2_session_t* h2session _U_, proto_tree *http2_tree, unsigned offset, uint8_t flags)
4344
#endif
4345
2
{
4346
2
    uint16_t padding;
4347
2
    int headlen;
4348
#ifdef HAVE_NGHTTP2
4349
    /* Mark this as the last CONTINUATION frame for a HEADERS frame. This is used to know the context when we read
4350
     * header (is the source a HEADER frame or a PUSH_PROMISE frame?) */
4351
    if (!PINFO_FD_VISITED(pinfo) && flags & HTTP2_FLAGS_END_HEADERS) {
4352
        http2_header_stream_info_t *stream_info = get_header_stream_info(pinfo, h2session, false);
4353
        if (stream_info->header_start_in != 0 && stream_info->header_end_in == 0) {
4354
            stream_info->header_end_in = get_http2_frame_num(tvb, pinfo);
4355
        }
4356
    }
4357
4358
#endif
4359
4360
2
    offset = dissect_frame_padding(tvb, &padding, http2_tree, offset, flags);
4361
4362
2
    headlen = tvb_reported_length_remaining(tvb, offset);
4363
2
    if (headlen < padding) {
4364
        /* XXX - what error *should* be reported here? */
4365
0
        THROW(ReportedBoundsError);
4366
0
    }
4367
2
    headlen -= padding;
4368
2
    proto_tree_add_item(http2_tree, hf_http2_continuation_header, tvb, offset, headlen, ENC_NA);
4369
4370
#ifdef HAVE_NGHTTP2
4371
    inflate_http2_header_block(tvb, pinfo, offset, http2_tree, headlen, h2session, flags);
4372
#endif
4373
4374
2
    offset +=  headlen;
4375
4376
2
    if (padding) {
4377
0
        proto_tree_add_item(http2_tree, hf_http2_continuation_padding, tvb, offset, padding, ENC_NA);
4378
0
        offset += padding;
4379
0
    }
4380
4381
2
    return offset;
4382
2
}
4383
4384
4385
/* Altsvc */
4386
static int
4387
dissect_http2_altsvc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree,
4388
                     unsigned offset, uint8_t flags _U_, uint16_t length)
4389
1
{
4390
1
    uint32_t origin_len;
4391
1
    int remain = length;
4392
4393
1
    proto_tree_add_item_ret_uint(http2_tree, hf_http2_altsvc_origin_len, tvb, offset, 2, ENC_BIG_ENDIAN, &origin_len);
4394
1
    offset += 2;
4395
1
    remain -= 2;
4396
4397
1
    proto_tree_add_item(http2_tree, hf_http2_altsvc_origin, tvb, offset, origin_len, ENC_ASCII);
4398
1
    offset += origin_len;
4399
1
    remain -= origin_len;
4400
4401
1
    if(remain) {
4402
1
        proto_tree_add_item(http2_tree, hf_http2_altsvc_field_value, tvb, offset, remain, ENC_ASCII);
4403
1
        offset += remain;
4404
1
    }
4405
4406
1
    return offset;
4407
1
}
4408
4409
/* Origin */
4410
static int
4411
dissect_http2_origin(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree,
4412
                     unsigned offset, uint8_t flags _U_)
4413
3
{
4414
3
    uint32_t origin_len;
4415
4416
3
    proto_item *ti_origin_entry;
4417
3
    proto_tree *origin_entry_tree;
4418
4419
20
    while(tvb_reported_length_remaining(tvb, offset) > 0){
4420
4421
17
        ti_origin_entry = proto_tree_add_item(http2_tree, hf_http2_origin, tvb, offset, 6, ENC_NA);
4422
17
        origin_entry_tree = proto_item_add_subtree(ti_origin_entry, ett_http2_origin);
4423
4424
17
        proto_tree_add_item_ret_uint(origin_entry_tree, hf_http2_origin_origin_len, tvb, offset, 2, ENC_BIG_ENDIAN, &origin_len);
4425
17
        offset += 2;
4426
4427
17
        proto_tree_add_item(origin_entry_tree, hf_http2_origin_origin, tvb, offset, origin_len, ENC_ASCII);
4428
17
        offset += origin_len;
4429
17
    }
4430
4431
3
    return offset;
4432
3
}
4433
4434
/* Priority Update */
4435
static int
4436
dissect_http2_priority_update(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *http2_tree,
4437
                              unsigned offset, uint8_t flags _U_, uint16_t length)
4438
1
{
4439
1
    int remain = length;
4440
4441
1
    proto_tree_add_item(http2_tree, hf_http2_priority_update_stream_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4442
1
    offset += 4;
4443
1
    remain -= 4;
4444
4445
1
    proto_tree_add_item(http2_tree, hf_http2_priority_update_field_value, tvb, offset, remain, ENC_ASCII);
4446
1
    offset += remain;
4447
4448
1
    return offset;
4449
1
}
4450
4451
4452
int
4453
dissect_http2_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ )
4454
355
{
4455
355
    proto_item *ti;
4456
355
    proto_tree *http2_tree;
4457
355
    unsigned offset = 0;
4458
355
    uint8_t type, flags;
4459
355
    uint16_t length;
4460
355
    uint32_t streamid;
4461
355
    struct HTTP2Tap *http2_stats;
4462
355
    GHashTable* entry;
4463
355
    struct tcp_analysis* tcpd;
4464
355
    conversation_t* conversation = find_or_create_conversation(pinfo);
4465
355
    bool use_follow_tap = true;
4466
4467
355
    ti = proto_tree_add_item(tree, proto_http2, tvb, 0, -1, ENC_NA);
4468
4469
355
    http2_tree = proto_item_add_subtree(ti, ett_http2);
4470
4471
355
    if(!p_get_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_HEADER)) {
4472
89
        http2_header_data_t *header_data;
4473
4474
89
        header_data = wmem_new0(wmem_file_scope(), http2_header_data_t);
4475
89
        header_data->header_list = wmem_list_new(wmem_file_scope());
4476
4477
89
        p_add_proto_data(wmem_file_scope(), pinfo, proto_http2, PROTO_DATA_KEY_HEADER, header_data);
4478
89
    }
4479
4480
4481
    /* 4.1 Frame Format
4482
         0                   1                   2                   3
4483
         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4484
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4485
        |                 Length (24)                   |
4486
        +---------------+---------------+---------------+
4487
        |   Type (8)    |   Flags (8)   |
4488
        +-+-+-----------+---------------+-------------------------------+
4489
        |R|                 Stream Identifier (31)                      |
4490
        +=+=============================================================+
4491
        |                   Frame Payload (0...)                      ...
4492
        +---------------------------------------------------------------+
4493
    */
4494
355
    ti = proto_tree_add_item(http2_tree, hf_http2_stream, tvb, 0, -1, ENC_NA);
4495
4496
355
    http2_tree = proto_item_add_subtree(ti, ett_http2_header);
4497
4498
    /* 3.5 Connection Header
4499
       Upon establishment of a TCP connection and determination that
4500
       HTTP/2 will be used by both peers, each endpoint MUST send a
4501
       connection preface as a final confirmation and to establish the
4502
       initial SETTINGS parameters for the HTTP/2 connection.
4503
     */
4504
    /* tvb_memeql makes certain there are enough bytes in the buffer.
4505
     * returns -1 if there are not enough bytes or if there is not a
4506
     * match.  Returns 0 on a match
4507
     */
4508
355
    if (tvb_memeql(tvb, offset, kMagicHello, MAGIC_FRAME_LENGTH) == 0 )
4509
83
    {
4510
83
        col_append_sep_str( pinfo->cinfo, COL_INFO, ", ", "Magic" );
4511
4512
83
        proto_item_set_len(ti, MAGIC_FRAME_LENGTH);
4513
83
        proto_item_append_text(ti, ": Magic");
4514
4515
83
        proto_tree_add_item(http2_tree, hf_http2_magic, tvb, offset, MAGIC_FRAME_LENGTH, ENC_ASCII);
4516
4517
83
        return MAGIC_FRAME_LENGTH;
4518
83
    }
4519
4520
272
    proto_tree_add_item(http2_tree, hf_http2_length, tvb, offset, 3, ENC_BIG_ENDIAN);
4521
272
    length = tvb_get_ntoh24(tvb, offset);
4522
272
    offset += 3;
4523
4524
272
    proto_tree_add_item(http2_tree, hf_http2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4525
272
    type = tvb_get_uint8(tvb, offset);
4526
4527
272
    int type_idx;
4528
272
    const char *type_str = try_val_to_str_idx(type, http2_type_vals, &type_idx);
4529
272
    if (type_str == NULL) {
4530
59
        type_str = wmem_strdup_printf(pinfo->pool, "Unknown type (%d)", type);
4531
59
    }
4532
4533
272
    offset += 1;
4534
4535
272
    flags = dissect_http2_header_flags(tvb, pinfo, http2_tree, offset, type);
4536
272
    offset += 1;
4537
4538
272
    proto_tree_add_item(http2_tree, hf_http2_r, tvb, offset, 4, ENC_BIG_ENDIAN);
4539
272
    proto_tree_add_item(http2_tree, hf_http2_streamid, tvb, offset, 4, ENC_BIG_ENDIAN);
4540
272
    streamid = tvb_get_ntohl(tvb, offset) & MASK_HTTP2_STREAMID;
4541
272
    proto_item_append_text(ti, ": %s, Stream ID: %u, Length %u", type_str, streamid, length);
4542
272
    offset += 4;
4543
4544
    /* append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3] */
4545
272
    col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s[%u]", type_str, streamid);
4546
4547
    /* fill hash table with stream ids and skip all unknown frames */
4548
272
    tcpd = get_tcp_conversation_data(conversation, pinfo);
4549
272
    if (tcpd != NULL && type_idx != -1) {
4550
209
        entry = (GHashTable*)g_hash_table_lookup(streamid_hash, GUINT_TO_POINTER(tcpd->stream));
4551
209
        if (entry == NULL) {
4552
54
            entry = g_hash_table_new(NULL, NULL);
4553
54
            g_hash_table_insert(streamid_hash, GUINT_TO_POINTER(tcpd->stream), entry);
4554
54
        }
4555
4556
209
        g_hash_table_add(entry, GUINT_TO_POINTER(streamid));
4557
209
    }
4558
4559
    /* Mark the current stream, used for per-stream processing later in the dissection */
4560
272
    http2_session_t *http2_session = get_http2_session(pinfo, conversation);
4561
272
    http2_session->current_stream_id = streamid;
4562
4563
    /* Collect stats */
4564
272
    http2_stats = wmem_new0(pinfo->pool, struct HTTP2Tap);
4565
272
    http2_stats->type = type;
4566
4567
272
    switch(type){
4568
144
        case HTTP2_DATA: /* Data (0) */
4569
144
            dissect_http2_data(tvb, pinfo, http2_session, http2_tree, offset, flags);
4570
#ifdef HAVE_NGHTTP2
4571
            use_follow_tap = false;
4572
#endif
4573
144
        break;
4574
4575
13
        case HTTP2_HEADERS: /* Headers (1) */
4576
13
            dissect_http2_headers(tvb, pinfo, http2_session, http2_tree, offset, flags);
4577
#ifdef HAVE_NGHTTP2
4578
            use_follow_tap = false;
4579
#endif
4580
13
        break;
4581
4582
2
        case HTTP2_PRIORITY: /* Priority (2) */
4583
2
            dissect_http2_priority(tvb, pinfo, http2_tree, offset, flags);
4584
2
        break;
4585
4586
2
        case HTTP2_RST_STREAM: /* RST Stream (3) */
4587
2
            dissect_http2_rst_stream(tvb, pinfo, http2_tree, offset, flags);
4588
2
        break;
4589
4590
28
        case HTTP2_SETTINGS: /* Settings (4) */
4591
28
            dissect_http2_settings(tvb, pinfo, http2_session, http2_tree, offset, flags);
4592
28
        break;
4593
4594
4
        case HTTP2_PUSH_PROMISE: /* PUSH Promise (5) */
4595
4
            dissect_http2_push_promise(tvb, pinfo, http2_session, http2_tree, offset, flags);
4596
#ifdef HAVE_NGHTTP2
4597
            use_follow_tap = false;
4598
#endif
4599
4
        break;
4600
4601
3
        case HTTP2_PING: /* Ping (6) */
4602
3
            dissect_http2_ping(tvb, pinfo, http2_tree, offset, flags);
4603
3
        break;
4604
4605
1
        case HTTP2_GOAWAY: /* Goaway (7) */
4606
1
            dissect_http2_goaway(tvb, pinfo, http2_tree, offset, flags);
4607
1
        break;
4608
4609
5
        case HTTP2_WINDOW_UPDATE: /* Window Update (8) */
4610
5
            dissect_http2_window_update(tvb, pinfo, http2_session, http2_tree, offset, flags);
4611
5
        break;
4612
4613
2
        case HTTP2_CONTINUATION: /* Continuation (9) */
4614
2
            dissect_http2_continuation(tvb, pinfo, http2_session, http2_tree, offset, flags);
4615
#ifdef HAVE_NGHTTP2
4616
            use_follow_tap = false;
4617
#endif
4618
2
        break;
4619
4620
1
        case HTTP2_ALTSVC: /* ALTSVC (10) */
4621
1
            dissect_http2_altsvc(tvb, pinfo, http2_tree, offset, flags, length);
4622
1
        break;
4623
4624
3
        case HTTP2_ORIGIN: /* ORIGIN (12) */
4625
3
            dissect_http2_origin(tvb, pinfo, http2_tree, offset, flags);
4626
3
        break;
4627
4628
1
        case HTTP2_PRIORITY_UPDATE: /* Priority Update (16) */
4629
1
            dissect_http2_priority_update(tvb, pinfo, http2_tree, offset, flags, length);
4630
1
        break;
4631
4632
55
        default:
4633
55
            proto_tree_add_item(http2_tree, hf_http2_unknown, tvb, offset, -1, ENC_NA);
4634
55
        break;
4635
272
    }
4636
187
    const char *uri = http2_get_request_full_uri(pinfo, http2_session, streamid);
4637
187
    if (uri) {
4638
0
        proto_item *uri_ti = proto_tree_add_string(http2_tree, hf_http2_header_request_full_uri, tvb, 0, 0, uri);
4639
0
        proto_item_set_url(uri_ti);
4640
0
        proto_item_set_generated(uri_ti);
4641
0
    }
4642
4643
#ifdef HAVE_NGHTTP2
4644
    http2_stream_info_t *stream_info = get_stream_info_for_id(pinfo, http2_session, false, streamid);
4645
4646
    /* Add Associate IMSI */
4647
    dissect_http2_add_assoc_imsi_to_tracked_3gpp_session(tvb, http2_tree, stream_info);
4648
#endif
4649
4650
187
    tap_queue_packet(http2_tap, pinfo, http2_stats);
4651
4652
    /* HEADERS, CONTINUATION, and PUSH_PROMISE frames are compressed,
4653
     * and sent to the follow tap inside inflate_http2_header_block.
4654
     */
4655
187
    if (have_tap_listener(http2_follow_tap) && use_follow_tap) {
4656
0
        http2_follow_tap_data_t *follow_data = wmem_new0(pinfo->pool, http2_follow_tap_data_t);
4657
4658
0
        follow_data->tvb = tvb;
4659
0
        follow_data->stream_id = streamid;
4660
4661
0
        tap_queue_packet(http2_follow_tap, pinfo, follow_data);
4662
0
    }
4663
4664
187
    return tvb_captured_length(tvb);
4665
272
}
4666
4667
static unsigned get_http2_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
4668
                                   int offset, void *data _U_)
4669
356
{
4670
356
        if ( tvb_memeql( tvb, offset, kMagicHello, FRAME_HEADER_LENGTH ) == 0 ) {
4671
            /* We're only guaranteed to have FRAME_HEADER_LENGTH here, but if
4672
             * those bytes match it's not a legal ordinary frame so it's
4673
             * sufficient. If we're here, we've already decided this is HTTP/2
4674
             * via heuristics or setting HTTP/2 to the port.
4675
             */
4676
94
            return MAGIC_FRAME_LENGTH;
4677
94
        }
4678
4679
262
        return (unsigned)tvb_get_ntoh24(tvb, offset) + FRAME_HEADER_LENGTH;
4680
356
}
4681
4682
4683
static int
4684
dissect_http2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4685
              void *data)
4686
99
{
4687
    /* XXX - We really want to set COL_PROTOCOL only for the first PDU (so
4688
     * as not to set it on the first pass if the frame is rejected due to
4689
     * segmentation), but tcp_dissect_pdus doesn't make that easy.
4690
     * Maybe tcp_dissect_pdus() set the protocol column for the first
4691
     * PDU to either a string or the protocol short name?
4692
     *
4693
     * Should tcp_dissect_pdus() set a fence after each PDU?
4694
     * If so the col_clear could be moved inside dissect_http2_pdu.
4695
     */
4696
99
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HTTP2");
4697
99
    col_clear(pinfo->cinfo, COL_INFO);
4698
4699
99
    tcp_dissect_pdus(tvb, pinfo, tree, true, FRAME_HEADER_LENGTH,
4700
99
                     get_http2_message_len, dissect_http2_pdu, data);
4701
4702
99
    return tvb_captured_length(tvb);
4703
99
}
4704
4705
static bool
4706
dissect_http2_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4707
3.66k
{
4708
3.66k
    conversation_t *conversation;
4709
3.66k
    http2_session_t *session;
4710
4711
3.66k
    conversation = find_or_create_conversation(pinfo);
4712
3.66k
    session = (http2_session_t *)conversation_get_proto_data(conversation,
4713
3.66k
                                                             proto_http2);
4714
    /* A http2 conversation was previously started, assume it is still active */
4715
3.66k
    if (session) {
4716
34
      dissect_http2(tvb, pinfo, tree, data);
4717
34
      return true;
4718
34
    }
4719
4720
3.63k
    if (tvb_memeql(tvb, 0, kMagicHello, MAGIC_FRAME_LENGTH) != 0) {
4721
        /* we couldn't find the Magic Hello (PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n). */
4722
3.57k
        return false;
4723
3.57k
    }
4724
4725
    /* Remember http2 conversation. */
4726
56
    get_http2_session(pinfo, conversation);
4727
56
    dissect_http2(tvb, pinfo, tree, data);
4728
4729
56
    return true;
4730
3.63k
}
4731
4732
static bool
4733
dissect_http2_heur_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4734
254
{
4735
254
    conversation_t *conversation;
4736
254
    http2_session_t *session;
4737
4738
254
    conversation = find_or_create_conversation(pinfo);
4739
254
    session = (http2_session_t *)conversation_get_proto_data(conversation,
4740
254
                                                             proto_http2);
4741
    /* A http2 conversation was previously started, assume it is still active */
4742
254
    if (session) {
4743
4
      dissect_http2(tvb, pinfo, tree, data);
4744
4
      return true;
4745
4
    }
4746
4747
    /* The HTTP dissector should hand us at least one line, but possibly only
4748
     * the first (if the TCP segment length is absurdly small.) 16 bytes is
4749
     * still enough to call this HTTP/2.
4750
     */
4751
250
    if (tvb_memeql(tvb, 0, kMagicHello, MAGIC_FRAME_FIRST_LINE) != 0) {
4752
        /* we couldn't find the Magic Hello (PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n). */
4753
245
        return false;
4754
245
    }
4755
4756
    /* Remember http2 conversation. */
4757
5
    get_http2_session(pinfo, conversation);
4758
4759
    /* XXX - Ideally we'd set the conversation dissector so that TCP calls
4760
     * HTTP/2 directly instead of HTTP. (Note we don't call this path for
4761
     * upgraded connections, which still go through the HTTP dissector.)
4762
     * That would change pinfo->curr_layer_num for this first packet on the
4763
     * second pass, though, so we'd want to make sure we're using
4764
     * curr_proto_layer_num or similar to avoid that being an issue,
4765
     * e.g. on reassembly of HEADERS or DATA sent along with this frame.
4766
     * So for now we have the HTTP dissector call the HTTP/2 dissector.
4767
     */
4768
    //conversation_set_dissector_from_frame_number(conversation, pinfo->num, http2_handle);
4769
5
    dissect_http2(tvb, pinfo, tree, data);
4770
4771
5
    return true;
4772
250
}
4773
4774
static bool
4775
dissect_http2_heur_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4776
0
{
4777
0
    struct tlsinfo *tlsinfo = (struct tlsinfo *) data;
4778
0
    if (dissect_http2_heur(tvb, pinfo, tree, NULL)) {
4779
0
        *(tlsinfo->app_handle) = http2_handle;
4780
0
        return true;
4781
0
    }
4782
0
    return false;
4783
0
}
4784
4785
void
4786
proto_register_http2(void)
4787
14
{
4788
4789
14
    static hf_register_info hf[] = {
4790
        /* Packet Header */
4791
14
        { &hf_http2_stream,
4792
14
            { "Stream", "http2.stream",
4793
14
               FT_NONE, BASE_NONE, NULL, 0x0,
4794
14
              NULL, HFILL }
4795
14
        },
4796
14
        { &hf_http2_length,
4797
14
            { "Length", "http2.length",
4798
14
              FT_UINT24, BASE_DEC, NULL, 0x0,
4799
14
              "The length (24 bits) of the frame payload (The 9 octets of the frame header are not included)", HFILL }
4800
14
        },
4801
14
        { &hf_http2_type,
4802
14
            { "Type", "http2.type",
4803
14
               FT_UINT8, BASE_DEC, VALS(http2_type_vals), 0x0,
4804
14
              "The frame type determines how the remainder of the frame header and payload are interpreted", HFILL }
4805
14
        },
4806
14
        { &hf_http2_r,
4807
14
            { "Reserved", "http2.r",
4808
14
               FT_UINT32, BASE_HEX, NULL, MASK_HTTP2_RESERVED,
4809
14
              "The semantics of this bit are undefined and the bit MUST remain unset (0) when sending and MUST be ignored when receiving", HFILL }
4810
14
        },
4811
4812
14
        { &hf_http2_weight,
4813
14
            { "Weight", "http2.headers.weight",
4814
14
               FT_UINT8, BASE_DEC, NULL, 0x0,
4815
14
              "An 8-bit weight for the identified priority", HFILL }
4816
14
        },
4817
14
        { &hf_http2_weight_real,
4818
14
            { "Weight real", "http2.headers.weight_real",
4819
14
               FT_UINT8, BASE_DEC, NULL, 0x0,
4820
14
              "Real Weight value (Add one to value)", HFILL }
4821
14
        },
4822
14
        { &hf_http2_streamid,
4823
14
            { "Stream Identifier", "http2.streamid",
4824
14
               FT_UINT32, BASE_DEC, NULL, MASK_HTTP2_STREAMID,
4825
14
              "A 31-bit stream identifier", HFILL }
4826
14
        },
4827
14
        { &hf_http2_magic,
4828
14
            { "Magic", "http2.magic",
4829
14
               FT_STRING, BASE_NONE, NULL, 0x0,
4830
14
              NULL, HFILL }
4831
14
        },
4832
14
        { &hf_http2_unknown,
4833
14
            { "Unknown", "http2.unknown",
4834
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
4835
14
              NULL, HFILL }
4836
14
        },
4837
        /* Flags */
4838
14
        { &hf_http2_flags,
4839
14
            { "Flags", "http2.flags",
4840
14
               FT_UINT8, BASE_HEX, NULL, 0x0,
4841
14
              "Flags are assigned semantics specific to the indicated frame type", HFILL }
4842
14
        },
4843
14
        { &hf_http2_flags_end_stream,
4844
14
            { "End Stream", "http2.flags.end_stream",
4845
14
              FT_BOOLEAN, 8, NULL, HTTP2_FLAGS_END_STREAM,
4846
14
              "Indicates that this frame is the last that the endpoint will send for the identified stream", HFILL }
4847
14
        },
4848
14
        { &hf_http2_flags_end_headers,
4849
14
            { "End Headers", "http2.flags.eh",
4850
14
              FT_BOOLEAN, 8, NULL, HTTP2_FLAGS_END_HEADERS,
4851
14
              "Indicates that this frame contains an entire header block  and is not followed by any CONTINUATION frames.", HFILL }
4852
14
        },
4853
14
        { &hf_http2_flags_padded,
4854
14
            { "Padded", "http2.flags.padded",
4855
14
              FT_BOOLEAN, 8, NULL, HTTP2_FLAGS_PADDED,
4856
14
              "Indicates that the Pad Length field is present", HFILL }
4857
14
        },
4858
14
        { &hf_http2_flags_priority,
4859
14
            { "Priority", "http2.flags.priority",
4860
14
               FT_BOOLEAN, 8, NULL, HTTP2_FLAGS_PRIORITY,
4861
14
              "Indicates that the Exclusive Flag (E), Stream Dependency, and Weight fields are present", HFILL }
4862
14
        },
4863
4864
14
        { &hf_http2_flags_ping_ack,
4865
14
            { "ACK", "http2.flags.ack.ping",
4866
14
               FT_BOOLEAN, 8, NULL, HTTP2_FLAGS_ACK,
4867
14
              "Set indicates that this PING frame is a PING response", HFILL }
4868
14
        },
4869
14
        { &hf_http2_flags_unused,
4870
14
            { "Unused", "http2.flags.unused",
4871
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED,
4872
14
              "Must be zero", HFILL }
4873
14
        },
4874
14
        { &hf_http2_flags_unused_settings,
4875
14
            { "Unused", "http2.flags.unused_settings",
4876
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED_SETTINGS,
4877
14
              "Must be zero", HFILL }
4878
14
        },
4879
14
        { &hf_http2_flags_unused_ping,
4880
14
            { "Unused", "http2.flags.unused_ping",
4881
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED_PING,
4882
14
              "Must be zero", HFILL }
4883
14
        },
4884
14
        { &hf_http2_flags_unused_continuation,
4885
14
            { "Unused", "http2.flags.unused_continuation",
4886
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED_CONTINUATION,
4887
14
              "Must be zero", HFILL }
4888
14
        },
4889
14
        { &hf_http2_flags_unused_push_promise,
4890
14
            { "Unused", "http2.flags.unused_push_promise",
4891
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED_PUSH_PROMISE,
4892
14
              "Must be zero", HFILL }
4893
14
        },
4894
14
        { &hf_http2_flags_unused_data,
4895
14
            { "Unused", "http2.flags.unused_data",
4896
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED_DATA,
4897
14
              "Must be zero", HFILL }
4898
14
        },
4899
14
        { &hf_http2_flags_unused_headers,
4900
14
            { "Unused", "http2.flags.unused_headers",
4901
14
               FT_UINT8, BASE_HEX, NULL, HTTP2_FLAGS_UNUSED_HEADERS,
4902
14
              "Must be zero", HFILL }
4903
14
        },
4904
14
        { &hf_http2_flags_settings_ack,
4905
14
            { "ACK", "http2.flags.ack.settings",
4906
14
               FT_BOOLEAN, 8, NULL, HTTP2_FLAGS_ACK,
4907
14
              "Indicates that this frame acknowledges receipt and application of the peer's SETTINGS frame", HFILL }
4908
14
        },
4909
14
        { &hf_http2_padding,
4910
14
            { "Pad Length", "http2.padding",
4911
14
              FT_UINT8, BASE_HEX, NULL, 0x0,
4912
14
              "Padding size", HFILL }
4913
14
        },
4914
14
        { &hf_http2_pad_length,
4915
14
            { "Pad Length", "http2.pad_length",
4916
14
              FT_UINT16, BASE_DEC, NULL, 0x0,
4917
14
              NULL, HFILL }
4918
14
        },
4919
14
        { &hf_http2_excl_dependency,
4920
14
            { "Exclusive", "http2.exclusive",
4921
14
              FT_BOOLEAN, 32, NULL, 0x80000000,
4922
14
              "A single bit flag indicates that the stream dependency is exclusive", HFILL }
4923
14
        },
4924
14
        { &hf_http2_stream_dependency,
4925
14
            { "Stream Dependency", "http2.stream_dependency",
4926
14
              FT_UINT32, BASE_DEC, NULL, 0x7FFFFFFF,
4927
14
              "An identifier for the stream that this stream depends on", HFILL }
4928
14
        },
4929
4930
        /* Data */
4931
14
        { &hf_http2_data_segment,
4932
14
          { "DATA segment", "http2.data.segment",
4933
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
4934
14
            "A data segment used in reassembly", HFILL}
4935
14
        },
4936
14
        { &hf_http2_data_data,
4937
14
            { "Data", "http2.data.data",
4938
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
4939
14
              "Application data", HFILL }
4940
14
        },
4941
14
        { &hf_http2_data_padding,
4942
14
            { "Padding", "http2.data.padding",
4943
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
4944
14
              "Padding octets", HFILL }
4945
14
        },
4946
        /* Body fragments */
4947
14
        { &hf_http2_body_fragments,
4948
14
            { "Body fragments", "http2.body.fragments",
4949
14
              FT_NONE, BASE_NONE, NULL, 0x0,
4950
14
              NULL, HFILL }
4951
14
        },
4952
14
        { &hf_http2_body_fragment,
4953
14
            { "Body fragment", "http2.body.fragment",
4954
14
              FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4955
14
              NULL, HFILL }
4956
14
        },
4957
14
        { &hf_http2_body_fragment_overlap,
4958
14
            { "Body fragment overlap", "http2.body.fragment.overlap",
4959
14
              FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4960
14
              NULL, HFILL }
4961
14
        },
4962
14
        { &hf_http2_body_fragment_overlap_conflicts,
4963
14
            { "Body fragment overlapping with conflicting data", "http2.body.fragment.overlap.conflicts",
4964
14
              FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4965
14
              NULL, HFILL }
4966
14
        },
4967
14
        { &hf_http2_body_fragment_multiple_tails,
4968
14
            { "Body has multiple tail fragments", "http2.body.fragment.multiple_tails",
4969
14
              FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4970
14
              NULL, HFILL }
4971
14
        },
4972
14
        { &hf_http2_body_fragment_too_long_fragment,
4973
14
            { "Body fragment too long", "http2.body.fragment.too_long_fragment",
4974
14
              FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4975
14
              NULL, HFILL }
4976
14
        },
4977
14
        { &hf_http2_body_fragment_error,
4978
14
            { "Body defragment error", "http2.body.fragment.error",
4979
14
              FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4980
14
              NULL, HFILL }
4981
14
        },
4982
14
        { &hf_http2_body_fragment_count,
4983
14
            { "Body fragment count", "http2.body.fragment.count",
4984
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
4985
14
              NULL, HFILL }
4986
14
        },
4987
14
        { &hf_http2_body_reassembled_in,
4988
14
            { "Reassembled body in frame", "http2.body.reassembled.in",
4989
14
              FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4990
14
              "Reassembled body in frame number", HFILL }
4991
14
        },
4992
14
        { &hf_http2_body_reassembled_length,
4993
14
            { "Reassembled body length", "http2.body.reassembled.length",
4994
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
4995
14
              "Reassembled body in frame number", HFILL }
4996
14
        },
4997
14
        { &hf_http2_body_reassembled_data,
4998
14
            { "Reassembled body data", "http2.body.reassembled.data",
4999
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5000
14
              "Reassembled body data for multisegment PDU spanning across DATAs", HFILL }
5001
14
        },
5002
5003
        /* Headers */
5004
14
        { &hf_http2_headers,
5005
14
            { "Header Block Fragment", "http2.headers",
5006
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5007
14
              "A header block fragment", HFILL }
5008
14
        },
5009
14
        { &hf_http2_headers_padding,
5010
14
            { "Padding", "http2.headers.padding",
5011
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5012
14
              "Padding octets", HFILL }
5013
14
        },
5014
14
        { &hf_http2_header,
5015
14
            { "Header", "http2.header",
5016
14
               FT_NONE, BASE_NONE, NULL, 0x0,
5017
14
               NULL, HFILL }
5018
14
        },
5019
14
        { &hf_http2_header_length,
5020
14
            { "Header Length", "http2.header.length",
5021
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5022
14
               NULL, HFILL }
5023
14
        },
5024
14
        { &hf_http2_header_count,
5025
14
            { "Header Count", "http2.header.count",
5026
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5027
14
               NULL, HFILL }
5028
14
        },
5029
14
        { &hf_http2_header_name_length,
5030
14
            { "Name Length", "http2.header.name.length",
5031
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5032
14
              NULL, HFILL }
5033
14
        },
5034
14
        { &hf_http2_header_name,
5035
14
            { "Name", "http2.header.name",
5036
14
              FT_STRING, BASE_NONE, NULL, 0x0,
5037
14
              NULL, HFILL }
5038
14
        },
5039
14
        { &hf_http2_header_value_length,
5040
14
            { "Value Length", "http2.header.value.length",
5041
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5042
14
              NULL, HFILL }
5043
14
        },
5044
14
        { &hf_http2_header_value,
5045
14
            { "Value", "http2.header.value",
5046
14
              FT_STRING, BASE_NONE, NULL, 0x0,
5047
14
              NULL, HFILL }
5048
14
        },
5049
14
        { &hf_http2_header_unescaped,
5050
14
            { "Unescaped", "http2.header.unescaped",
5051
14
              FT_STRING, BASE_NONE, NULL, 0x0,
5052
14
              NULL, HFILL }
5053
14
        },
5054
14
        { &hf_http2_header_repr,
5055
14
            { "Representation", "http2.header.repr",
5056
14
              FT_STRING, BASE_NONE, NULL, 0x0,
5057
14
              NULL, HFILL }
5058
14
        },
5059
14
        { &hf_http2_header_index,
5060
14
            { "Index", "http2.header.index",
5061
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5062
14
              NULL, HFILL }
5063
14
        },
5064
14
        { &hf_http2_header_table_size_update,
5065
14
            { "Header table size update", "http2.header_table_size_update",
5066
14
               FT_NONE, BASE_NONE, NULL, 0x0,
5067
14
               NULL, HFILL }
5068
14
        },
5069
14
        { &hf_http2_header_table_size,
5070
14
            { "Header table size", "http2.header_table_size_update.header_table_size",
5071
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5072
14
               NULL, HFILL }
5073
14
        },
5074
14
        { &hf_http2_fake_header_count,
5075
14
            { "Fake Header Count", "http2.fake.header.count",
5076
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5077
14
               NULL, HFILL }
5078
14
        },
5079
14
        { &hf_http2_fake_header,
5080
14
            { "Fake Header", "http2.fake.header",
5081
14
               FT_NONE, BASE_NONE, NULL, 0x0,
5082
14
               NULL, HFILL }
5083
14
        },
5084
14
        { &hf_http2_header_request_full_uri,
5085
14
            { "Full request URI", "http2.request.full_uri",
5086
14
              FT_STRING, BASE_NONE, NULL, 0x0,
5087
14
              "The full requested URI (including host name)", HFILL }
5088
14
        },
5089
5090
        /* RST Stream */
5091
14
        { &hf_http2_rst_stream_error,
5092
14
            { "Error", "http2.rst_stream.error",
5093
14
               FT_UINT32, BASE_DEC, VALS(http2_error_codes_vals), 0x0,
5094
14
              "The error code indicates why the stream is being terminated", HFILL }
5095
14
        },
5096
5097
        /* Settings */
5098
14
        { &hf_http2_settings,
5099
14
            { "Settings", "http2.settings",
5100
14
               FT_NONE, BASE_NONE, NULL, 0x0,
5101
14
              NULL, HFILL }
5102
14
        },
5103
14
        { &hf_http2_settings_identifier,
5104
14
            { "Settings Identifier", "http2.settings.id",
5105
14
               FT_UINT16, BASE_DEC, VALS(http2_settings_vals), 0x0,
5106
14
              NULL, HFILL }
5107
14
        },
5108
14
        { &hf_http2_settings_header_table_size,
5109
14
            { "Header table size", "http2.settings.header_table_size",
5110
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5111
14
              "Allows the sender to inform the remote endpoint of the size of the header compression table used to decode header blocks. The initial value is 4096 bytes", HFILL }
5112
14
        },
5113
14
        { &hf_http2_settings_enable_push,
5114
14
            { "Enable PUSH", "http2.settings.enable_push",
5115
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5116
14
              "The initial value is 1, which indicates that push is permitted", HFILL }
5117
14
        },
5118
14
        { &hf_http2_settings_max_concurrent_streams,
5119
14
            { "Max concurrent streams", "http2.settings.max_concurrent_streams",
5120
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5121
14
              "Indicates the maximum number of concurrent streams that the sender will allow", HFILL }
5122
14
        },
5123
14
        { &hf_http2_settings_initial_window_size,
5124
14
            { "Initial Window Size", "http2.settings.initial_window_size",
5125
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5126
14
              "Indicates the sender's initial window size (in bytes) for stream level flow control", HFILL }
5127
14
        },
5128
14
        { &hf_http2_settings_max_frame_size,
5129
14
            { "Max frame size", "http2.settings.max_frame_size",
5130
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5131
14
              "Indicates the size of the largest frame payload that the sender will allow", HFILL }
5132
14
        },
5133
14
        { &hf_http2_settings_max_header_list_size,
5134
14
            { "Max header list size", "http2.settings.max_header_list_size",
5135
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5136
14
              "This advisory setting informs a peer of the maximum size of header list that the sender is prepared to accept.", HFILL }
5137
14
        },
5138
14
        { &hf_http2_settings_extended_connect,
5139
14
            { "Extended CONNECT", "http2.settings.extended_connect",
5140
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5141
14
              "Indicates support for the extended CONNECT method extension defined RFC 8441.", HFILL }
5142
14
        },
5143
14
        { &hf_http2_settings_no_rfc7540_priorities,
5144
14
            { "No RFC7540 Priorities", "http2.settings.no_rfc7540_priorities",
5145
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
5146
14
              NULL, HFILL }
5147
14
        },
5148
14
        { &hf_http2_settings_tls_reneg_permitted,
5149
14
            { "TLS Renegotiation Permitted", "http2.settings.tls_reneg_permitted",
5150
14
              FT_UINT32, BASE_DEC, VALS(http2_tls_reneg_permitted_vals), 0x0,
5151
14
              "Indicates the sender's capability and willingness to employ TLS renegotiation", HFILL }
5152
14
        },
5153
14
        { &hf_http2_settings_unknown,
5154
14
            { "Unknown Settings", "http2.settings.unknown",
5155
14
               FT_UINT32, BASE_DEC, NULL, 0x0,
5156
14
              NULL, HFILL }
5157
14
        },
5158
5159
        /* Push Promise */
5160
14
        { &hf_http2_push_promise_r,
5161
14
            { "Reserved", "http2.push_promise.r",
5162
14
               FT_UINT32, BASE_HEX, NULL, MASK_HTTP2_RESERVED,
5163
14
              "Must be zero", HFILL }
5164
14
        },
5165
5166
14
        { &hf_http2_push_promise_promised_stream_id,
5167
14
            { "Promised-Stream-ID", "http2.push_promise.promised_stream_id",
5168
14
               FT_UINT32, BASE_DEC, NULL, MASK_HTTP2_PRIORITY,
5169
14
              "Identifies the stream the endpoint intends to start sending frames for", HFILL }
5170
14
        },
5171
14
        { &hf_http2_push_promise_header,
5172
14
            { "Header Block Fragment", "http2.push_promise.header",
5173
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5174
14
              "Containing request header fields", HFILL }
5175
14
        },
5176
14
        { &hf_http2_push_promise_padding,
5177
14
            { "Padding", "http2.push_promise.padding",
5178
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5179
14
              "Padding octets", HFILL }
5180
14
        },
5181
5182
        /* Ping / Pong */
5183
14
        { &hf_http2_ping,
5184
14
            { "Ping", "http2.ping",
5185
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5186
14
              NULL, HFILL }
5187
14
        },
5188
14
        { &hf_http2_pong,
5189
14
            { "Pong", "http2.pong",
5190
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5191
14
              NULL, HFILL }
5192
14
        },
5193
5194
        /* Goaway */
5195
14
        { &hf_http2_goaway_r,
5196
14
            { "Reserved", "http2.goaway.r",
5197
14
               FT_UINT32, BASE_HEX, NULL, MASK_HTTP2_RESERVED,
5198
14
              "Must be zero", HFILL }
5199
14
        },
5200
14
        { &hf_http2_goaway_last_stream_id,
5201
14
            { "Last-Stream-ID", "http2.goaway.last_stream_id",
5202
14
               FT_UINT32, BASE_DEC, NULL, MASK_HTTP2_PRIORITY,
5203
14
              "Contains the highest numbered stream identifier for which the sender of the GOAWAY frame has received frames on and might have taken some action on", HFILL }
5204
14
        },
5205
14
        { &hf_http2_goaway_error,
5206
14
            { "Error", "http2.goaway.error",
5207
14
               FT_UINT32, BASE_DEC, VALS(http2_error_codes_vals), 0x0,
5208
14
              "The error code indicates the reason for closing the connection", HFILL }
5209
14
        },
5210
14
        { &hf_http2_goaway_addata,
5211
14
            { "Additional Debug Data", "http2.goaway.addata",
5212
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5213
14
              NULL, HFILL }
5214
14
        },
5215
5216
        /* Window Update */
5217
14
        { &hf_http2_window_update_r,
5218
14
            { "Reserved", "http2.window_update.r",
5219
14
               FT_UINT32, BASE_HEX, NULL, MASK_HTTP2_RESERVED,
5220
14
              "Must be zero", HFILL }
5221
14
        },
5222
14
        { &hf_http2_window_update_window_size_increment,
5223
14
            { "Window Size Increment", "http2.window_update.window_size_increment",
5224
14
               FT_UINT32, BASE_DEC, NULL, MASK_HTTP2_PRIORITY,
5225
14
              "Indicating the number of bytes that the sender can transmit in addition to the existing flow control window", HFILL }
5226
14
        },
5227
5228
        /* Continuation */
5229
14
        { &hf_http2_continuation_header,
5230
14
            { "Header Block Fragment", "http2.continuation.header",
5231
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5232
14
              "Continues a HEADERS or PUSH_PROMISE field block", HFILL }
5233
14
        },
5234
14
        { &hf_http2_continuation_padding,
5235
14
            { "Padding", "http2.continuation.padding",
5236
14
               FT_BYTES, BASE_NONE, NULL, 0x0,
5237
14
              "Padding octets", HFILL }
5238
14
        },
5239
5240
        /* ALTSVC */
5241
14
        { &hf_http2_altsvc_origin_len,
5242
14
            { "Origin Length", "http2.altsvc.origin.len",
5243
14
               FT_UINT16, BASE_DEC, NULL, 0x0,
5244
14
              "indicating the length, in octets, of the Origin field.", HFILL }
5245
14
        },
5246
14
        { &hf_http2_altsvc_origin,
5247
14
            { "Origin", "http2.altsvc.origin",
5248
14
               FT_STRING, BASE_NONE, NULL, 0x0,
5249
14
              "A sequence of characters containing ASCII serialisation of an "
5250
14
              "origin that the alternate service is applicable to.", HFILL }
5251
14
        },
5252
14
        { &hf_http2_altsvc_field_value,
5253
14
            { "Field/Value", "http2.altsvc.field_value",
5254
14
               FT_STRING, BASE_NONE, NULL, 0x0,
5255
14
              "A sequence of octets containing a value identical to the Alt-Svc field value", HFILL }
5256
14
        },
5257
5258
        /* Origin */
5259
14
        { &hf_http2_origin,
5260
14
            { "Origin", "http2.origin",
5261
14
               FT_NONE, BASE_NONE, NULL, 0x0,
5262
14
              NULL, HFILL }
5263
14
        },
5264
14
        { &hf_http2_origin_origin_len,
5265
14
            { "Origin Length", "http2.origin.origin_len",
5266
14
               FT_UINT16, BASE_DEC, NULL, 0x0,
5267
14
              "indicating the length, in octets, of the Origin field.", HFILL }
5268
14
        },
5269
14
        { &hf_http2_origin_origin,
5270
14
            { "Origin", "http2.origin.origin",
5271
14
               FT_STRING, BASE_NONE, NULL, 0x0,
5272
14
              "A sequence of characters containing ASCII serialisation of an "
5273
14
              "origin that server is authoritative for.", HFILL }
5274
14
        },
5275
5276
        /* Priority Update */
5277
14
        { &hf_http2_priority_update_stream_id,
5278
14
            { "Priority Update Stream ID", "http2.priority_update_stream_id",
5279
14
              FT_UINT64, BASE_DEC, NULL, 0x0,
5280
14
              NULL, HFILL }
5281
14
        },
5282
14
        { &hf_http2_priority_update_field_value,
5283
14
            { "Priority Update Field Value", "http2.priority_update_field_value",
5284
14
              FT_STRING, BASE_NONE, NULL, 0x0,
5285
14
              NULL, HFILL }
5286
14
        },
5287
14
        { &hf_http2_time,
5288
14
          { "Time since request", "http2.time",
5289
14
            FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
5290
14
            "Time since the request was sent", HFILL }
5291
14
        },
5292
14
        { &hf_http2_request_in,
5293
14
            { "Request in frame", "http2.request_in",
5294
14
              FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
5295
14
              "This frame is a response to a HTTP2 request contained in frame with this number", HFILL }
5296
14
        },
5297
14
        { &hf_http2_response_in,
5298
14
            { "Response in frame", "http2.response_in",
5299
14
              FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
5300
14
              "This request will be responded in the frame with this number", HFILL }
5301
14
        },
5302
5303
        /* Calculated */
5304
14
        { &hf_http2_calculated_window_size_connection_before,
5305
14
            { "Connection window size (before)", "http2.calculated.connection.window_size.before",
5306
14
              FT_INT32, BASE_DEC, NULL, 0x0,
5307
14
              "The sender's current window size (in bytes) for this connection (before sending)", HFILL }
5308
14
        },
5309
14
        { &hf_http2_calculated_window_size_connection_after,
5310
14
            { "Connection window size (after)", "http2.calculated.connection.window_size.after",
5311
14
              FT_INT32, BASE_DEC, NULL, 0x0,
5312
14
              "The sender's current window size (in bytes) for this connection (after sending)", HFILL }
5313
14
        },
5314
14
        { &hf_http2_calculated_window_size_stream_before,
5315
14
            { "Stream window size (before)", "http2.calculated.stream.window_size.before",
5316
14
              FT_INT32, BASE_DEC, NULL, 0x0,
5317
14
              "The sender's current window size (in bytes) for this stream (before sending)", HFILL }
5318
14
        },
5319
14
        { &hf_http2_calculated_window_size_stream_after,
5320
14
            { "Stream window size (after)", "http2.calculated.stream.window_size.after",
5321
14
              FT_INT32, BASE_DEC, NULL, 0x0,
5322
14
              "The sender's current window size (in bytes) for this stream (after sending)", HFILL }
5323
14
        },
5324
14
    };
5325
5326
14
    static int *ett[] = {
5327
14
        &ett_http2,
5328
14
        &ett_http2_header,
5329
14
        &ett_http2_headers,
5330
14
        &ett_http2_flags,
5331
14
        &ett_http2_settings,
5332
14
        &ett_http2_encoded_entity,
5333
14
        &ett_http2_body_fragment,
5334
14
        &ett_http2_body_fragments,
5335
14
        &ett_http2_origin
5336
14
    };
5337
5338
    /* Setup protocol expert items */
5339
    /*
5340
     * Excessive header size or lines could mean a decompression bomb. Should
5341
     * these be PI_SECURITY instead?
5342
     */
5343
14
    static ei_register_info ei[] = {
5344
14
        { &ei_http2_header_size,
5345
14
          { "http2.header_size_exceeded", PI_UNDECODED, PI_ERROR,
5346
14
            "Decompression stopped.", EXPFILL }
5347
14
        },
5348
14
        { &ei_http2_header_lines,
5349
14
          { "http2.header_lines_exceeded", PI_UNDECODED, PI_ERROR,
5350
14
            "Decompression stopped after " G_STRINGIFY(MAX_HTTP2_HEADER_LINES) " header lines.", EXPFILL }
5351
14
        },
5352
14
        { &ei_http2_body_decompression_failed,
5353
14
          { "http2.body_decompression_failed", PI_UNDECODED, PI_WARN,
5354
14
            "Body decompression failed", EXPFILL }
5355
14
        },
5356
14
        { &ei_http2_reassembly_error,
5357
14
          { "http2.reassembly_error", PI_UNDECODED, PI_WARN,
5358
14
            "Reassembly failed", EXPFILL }
5359
14
        },
5360
14
        { &ei_http2_window_size,
5361
14
          { "http2.window_size_exceeded", PI_PROTOCOL, PI_WARN,
5362
14
            "Calculated window size exceeded maximum size (" G_STRINGIFY(INT32_MAX) ")", EXPFILL }
5363
14
        }
5364
14
    };
5365
5366
14
    module_t *http2_module;
5367
14
    expert_module_t *expert_http2;
5368
5369
14
    proto_http2 = proto_register_protocol("HyperText Transfer Protocol 2", "HTTP2", "http2");
5370
5371
14
    proto_register_field_array(proto_http2, hf, array_length(hf));
5372
14
    proto_register_subtree_array(ett, array_length(ett));
5373
5374
14
    http2_module = prefs_register_protocol(proto_http2, NULL);
5375
5376
14
    expert_http2 = expert_register_protocol(proto_http2);
5377
14
    expert_register_field_array(expert_http2, ei, array_length(ei));
5378
5379
14
    prefs_register_obsolete_preference(http2_module, "heuristic_http2");
5380
5381
#ifdef HAVE_NGHTTP2
5382
    uat_t* headers_uat;
5383
5384
    static const value_string http2_custom_type_vals[] = {
5385
        { val_string,   "string" },
5386
        { val_uint64,   "unsigned 64-bit integer" },
5387
        { 0x00, NULL }
5388
    };
5389
5390
    static uat_field_t custom_header_uat_fields[] = {
5391
        UAT_FLD_CSTRING(header_fields, header_name, "Header name", "HTTP2 header name"),
5392
        UAT_FLD_VS(header_fields, header_type, "Header type", http2_custom_type_vals, "Field type"),
5393
        UAT_FLD_CSTRING(header_fields, header_desc, "Field desc", "Description of the value contained in the header"),
5394
        UAT_END_FIELDS
5395
    };
5396
5397
    headers_uat = uat_new("Custom HTTP2 Header Fields",
5398
                          sizeof(header_field_t),
5399
                          "custom_http2_header_fields",
5400
                          true,
5401
                          &header_fields,
5402
                          &num_header_fields,
5403
                          /* specifies named fields, so affects dissection
5404
                             and the set of named fields */
5405
                          UAT_AFFECTS_DISSECTION|UAT_AFFECTS_FIELDS,
5406
                          NULL,
5407
                          header_fields_copy_cb,
5408
                          header_fields_update_cb,
5409
                          header_fields_free_cb,
5410
                          header_fields_post_update_cb,
5411
                          header_fields_reset_cb,
5412
                          custom_header_uat_fields
5413
    );
5414
5415
    prefs_register_uat_preference(http2_module, "custom_http2_header_fields", "Custom HTTP2 header fields",
5416
        "A table to define custom HTTP2 header for which fields can be setup and used for filtering/data extraction etc.",
5417
        headers_uat);
5418
5419
    uat_t* fake_headers_uat;
5420
5421
    static uat_field_t http2_fake_header_uat_fields[] = {
5422
        UAT_FLD_RANGE(http2_fake_headers, server_port_range, "Server ports", 0xFFFF,
5423
                      "Server ports providing HTTP2 service"),
5424
        UAT_FLD_DEC(http2_fake_headers, stream_id, "Stream ID",
5425
                    "The HTTP2 Stream ID this rule will apply to. The 0 means applicable to all streams."),
5426
        UAT_FLD_VS(http2_fake_headers, direction, "Direction", http2_direction_type_vals,
5427
                   "This rule applies to the message sent to (IN) or from (OUT) server."),
5428
        UAT_FLD_CSTRING(http2_fake_headers, header_name, "Header name", "HTTP2 header name"),
5429
        UAT_FLD_CSTRING(http2_fake_headers, header_value, "Header value", "HTTP2 header value"),
5430
        UAT_FLD_BOOL(http2_fake_headers, override, "Override", "Override existing header"),
5431
        UAT_FLD_BOOL(http2_fake_headers, enable, "Enable", "Enable this rule"),
5432
        UAT_END_FIELDS
5433
    };
5434
5435
    fake_headers_uat = uat_new("HTTP2 Fake Headers",
5436
        sizeof(http2_fake_header_t),
5437
        "http2_fake_headers",
5438
        true,
5439
        &http2_fake_headers,
5440
        &num_http2_fake_headers,
5441
        UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS,
5442
        NULL,
5443
        http2_fake_headers_copy_cb,
5444
        http2_fake_headers_update_cb,
5445
        http2_fake_headers_free_cb,
5446
        NULL,
5447
        NULL,
5448
        http2_fake_header_uat_fields
5449
    );
5450
5451
    prefs_register_uat_preference(http2_module, "fake_headers", "HTTP2 Fake Headers",
5452
        "A table to define HTTP2 fake headers for parsing a HTTP2 stream conversation that first HEADERS frame is missing.",
5453
        fake_headers_uat);
5454
5455
    prefs_register_bool_preference(http2_module, "3gpp_session",
5456
        "Track 3GPP session over 5G Service Based Interfaces.",
5457
        "Will map IMSI from Supi to referenceid in path or location, if match found then field \"Association IMSI\"(e212.assoc.imsi) will be added to all messages"
5458
        " within the same stream",
5459
        &http2_3gpp_session);
5460
5461
#if defined(HAVE_ZLIB) || defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI) || defined(HAVE_ZSTD)
5462
    prefs_register_bool_preference(http2_module, "decompress_body",
5463
        "Uncompress entity bodies",
5464
        "Whether to uncompress entity bodies that are compressed "
5465
        "using \"Content-Encoding: \"",
5466
        &http2_decompress_body);
5467
#else
5468
    prefs_register_obsolete_preference(http2_module, "decompress_body");
5469
#endif
5470
5471
    http2_notifyuri_imsi = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
5472
    http2_location_imsi = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
5473
5474
    /* Fill hash table with static headers */
5475
    register_static_headers();
5476
5477
    /* Decode As handling */
5478
    static build_valid_func http2_current_stream_values[1] = { http2_current_stream_id_value };
5479
    static decode_as_value_t http2_da_stream_id_values[1] = { {http2_streamid_prompt, 1, http2_current_stream_values} };
5480
    static decode_as_t http2_da_stream_id = { "http2", "http2.streamid", 1, 0, http2_da_stream_id_values, "HTTP2", "Stream ID as",
5481
                                       decode_as_http2_populate_list, decode_as_default_reset, decode_as_default_change, NULL, NULL, NULL };
5482
    register_decode_as(&http2_da_stream_id);
5483
#endif
5484
5485
14
    register_init_routine(&http2_init_protocol);
5486
14
    register_cleanup_routine(&http2_cleanup_protocol);
5487
5488
14
    http2_handle = register_dissector("http2", dissect_http2, proto_http2);
5489
5490
14
    reassembly_table_register(&http2_body_reassembly_table,
5491
14
                              &addresses_ports_reassembly_table_functions);
5492
14
    reassembly_table_register(&http2_streaming_reassembly_table,
5493
14
                              &addresses_ports_reassembly_table_functions);
5494
5495
14
    streaming_content_type_dissector_table =
5496
14
        register_dissector_table("streaming_content_type",
5497
14
            "Data Transmitted over HTTP2 in Streaming Mode", proto_http2, FT_STRING, STRING_CASE_SENSITIVE);
5498
5499
14
    stream_id_content_type_dissector_table =
5500
14
        register_dissector_table("http2.streamid", "HTTP2 content type in stream", proto_http2, FT_UINT32, BASE_DEC);
5501
5502
14
    http2_tap = register_tap("http2");
5503
14
    http2_follow_tap = register_tap("http2_follow");
5504
5505
14
    register_follow_stream(proto_http2, "http2_follow", http2_follow_conv_filter, http2_follow_index_filter, tcp_follow_address_filter,
5506
14
                           tcp_port_to_display, follow_http2_tap_listener, get_tcp_stream_count,
5507
14
                           http2_get_sub_stream_id);
5508
14
}
5509
5510
static void http2_stats_tree_init(stats_tree* st)
5511
0
{
5512
0
    st_node_http2 = stats_tree_create_node(st, st_str_http2, 0, STAT_DT_INT, true);
5513
0
    st_node_http2_type = stats_tree_create_pivot(st, st_str_http2_type, st_node_http2);
5514
5515
0
}
5516
5517
static tap_packet_status http2_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
5518
0
{
5519
0
    const struct HTTP2Tap *pi = (const struct HTTP2Tap *)p;
5520
0
    tick_stat_node(st, st_str_http2, 0, false);
5521
0
    stats_tree_tick_pivot(st, st_node_http2_type,
5522
0
            val_to_str(pinfo->pool, pi->type, http2_type_vals, "Unknown type (%d)"));
5523
5524
0
    return TAP_PACKET_REDRAW;
5525
0
}
5526
5527
void
5528
proto_reg_handoff_http2(void)
5529
14
{
5530
#ifdef HAVE_NGHTTP2
5531
    media_type_dissector_table = find_dissector_table("media_type");
5532
#endif
5533
5534
14
    data_handle = find_dissector("data");
5535
5536
14
    dissector_add_uint_range_with_preference("tcp.port", "", http2_handle);
5537
14
    dissector_add_for_decode_as("tcp.port", http2_handle);
5538
5539
    /*
5540
     * SSL/TLS Application-Layer Protocol Negotiation (ALPN) protocol ID.
5541
     */
5542
14
    dissector_add_string("tls.alpn", "h2", http2_handle);
5543
14
    dissector_add_string("http.upgrade", "h2", http2_handle);
5544
14
    dissector_add_string("http.upgrade", "h2c", http2_handle);
5545
14
    dissector_add_string("http.upgrade", "HTTP/2.0", http2_handle);
5546
5547
14
    heur_dissector_add("tls", dissect_http2_heur_ssl, "HTTP2 over TLS", "http2_tls", proto_http2, HEURISTIC_ENABLE);
5548
14
    heur_dissector_add("tcp", dissect_http2_heur, "HTTP2 over TCP", "http2_tcp", proto_http2, HEURISTIC_ENABLE);
5549
14
    heur_dissector_add("http", dissect_http2_heur_http, "HTTP2 on an HTTP port", "http2_http", proto_http2, HEURISTIC_ENABLE);
5550
5551
14
    stats_tree_register("http2", "http2", "HTTP2", 0, http2_stats_tree_packet, http2_stats_tree_init, NULL);
5552
5553
#ifdef HAVE_NGHTTP2
5554
    register_eo_t *http_eo = get_eo_by_name("http");
5555
    if (http_eo) {
5556
        http_eo_tap = find_tap_id(get_eo_tap_listener_name(http_eo));
5557
    }
5558
#endif
5559
14
}
5560
5561
/*
5562
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
5563
 *
5564
 * Local variables:
5565
 * c-basic-offset: 4
5566
 * tab-width: 8
5567
 * indent-tabs-mode: nil
5568
 * End:
5569
 *
5570
 * vi: set shiftwidth=4 tabstop=8 expandtab:
5571
 * :indentSize=4:tabSize=8:noTabs=true:
5572
 */