Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-kerberos4.c
Line
Count
Source
1
/* packet-kerberos4.c
2
 * Routines for Kerberos v4 packet dissection
3
 *
4
 * Ronnie Sahlberg 2004
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
/*
13
 * PDU structure based on the document:
14
 *
15
 * Athena Technical Plan
16
 * Section E.2.1
17
 * Kerberos Authentication and Authorization System
18
 * by S. P. Miller, B. C. Neuman, J. I. Schiller, and J. H. Saltzer
19
 *
20
 * http://web.mit.edu/Saltzer/www/publications/athenaplan/e.2.1.pdf
21
 *
22
 * 7. Appendix I Design Specifications
23
 */
24
25
#include "config.h"
26
27
#include <epan/packet.h>
28
29
void proto_register_krb4(void);
30
void proto_reg_handoff_krb4(void);
31
32
static int proto_krb4;
33
static int hf_krb4_version;
34
static int hf_krb4_auth_msg_type;
35
static int hf_krb4_m_type;
36
static int hf_krb4_byte_order;
37
static int hf_krb4_name;
38
static int hf_krb4_instance;
39
static int hf_krb4_realm;
40
static int hf_krb4_time_sec;
41
static int hf_krb4_exp_date;
42
static int hf_krb4_req_date;
43
static int hf_krb4_lifetime;
44
static int hf_krb4_s_name;
45
static int hf_krb4_s_instance;
46
static int hf_krb4_kvno;
47
static int hf_krb4_length;
48
static int hf_krb4_ticket_length;
49
static int hf_krb4_request_length;
50
static int hf_krb4_ticket_blob;
51
static int hf_krb4_request_blob;
52
static int hf_krb4_encrypted_blob;
53
static int hf_krb4_unknown_transarc_blob;
54
55
static int ett_krb4;
56
static int ett_krb4_auth_msg_type;
57
58
static dissector_handle_t krb4_handle;
59
60
16
#define UDP_PORT_KRB4    750
61
24
#define TRANSARC_SPECIAL_VERSION 0x63
62
63
static const value_string byte_order_vals[] = {
64
  { 0,  "Big Endian" },
65
  { 1,  "Little Endian" },
66
  { 0,  NULL }
67
};
68
69
0
#define AUTH_MSG_KDC_REQUEST    1
70
6
#define AUTH_MSG_KDC_REPLY    2
71
5
#define AUTH_MSG_APPL_REQUEST   3
72
4
#define AUTH_MSG_APPL_REQUEST_MUTUAL  4
73
4
#define AUTH_MSG_ERR_REPLY    5
74
6
#define AUTH_MSG_PRIVATE    6
75
6
#define AUTH_MSG_SAFE     7
76
6
#define AUTH_MSG_APPL_ERR   8
77
8
#define AUTH_MSG_DIE      63
78
static const value_string m_type_vals[] = {
79
  { AUTH_MSG_KDC_REQUEST,   "KDC Request" },
80
  { AUTH_MSG_KDC_REPLY,   "KDC Reply" },
81
  { AUTH_MSG_APPL_REQUEST,  "Appl Request" },
82
  { AUTH_MSG_APPL_REQUEST_MUTUAL, "Appl Request Mutual" },
83
  { AUTH_MSG_ERR_REPLY,   "Err Reply" },
84
  { AUTH_MSG_PRIVATE,   "Private" },
85
  { AUTH_MSG_SAFE,    "Safe" },
86
  { AUTH_MSG_APPL_ERR,    "Appl Err" },
87
  { AUTH_MSG_DIE,     "Die" },
88
  { 0,  NULL }
89
};
90
91
92
static int
93
dissect_krb4_string(packet_info *pinfo _U_, int hf_index, proto_tree *tree, tvbuff_t *tvb, int offset)
94
7
{
95
7
  unsigned length;
96
7
  proto_tree_add_item_ret_length(tree, hf_index, tvb, offset, -1, ENC_ASCII|ENC_NA, &length);
97
98
7
  return offset + length;
99
7
}
100
101
static int
102
dissect_krb4_kdc_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, const unsigned encoding, int version)
103
0
{
104
0
  uint8_t  lifetime;
105
106
0
  if(version==TRANSARC_SPECIAL_VERSION){
107
0
    proto_tree_add_item(tree, hf_krb4_unknown_transarc_blob, tvb, offset, 8, ENC_NA);
108
0
    offset+=8;
109
0
  }
110
111
  /* Name */
112
0
  offset=dissect_krb4_string(pinfo, hf_krb4_name, tree, tvb, offset);
113
114
  /* Instance */
115
0
  offset=dissect_krb4_string(pinfo, hf_krb4_instance, tree, tvb, offset);
116
117
  /* Realm */
118
0
  offset=dissect_krb4_string(pinfo, hf_krb4_realm, tree, tvb, offset);
119
120
  /* Time sec */
121
0
  proto_tree_add_item(tree, hf_krb4_time_sec, tvb, offset, 4, ENC_TIME_SECS|encoding);
122
0
  offset+=4;
123
124
  /* lifetime */
125
0
  lifetime=tvb_get_uint8(tvb, offset);
126
0
  proto_tree_add_uint_format_value(tree, hf_krb4_lifetime, tvb, offset, 1, lifetime, "%d (%d minutes)", lifetime, lifetime*5);
127
0
  offset++;
128
129
  /* service Name */
130
0
  offset=dissect_krb4_string(pinfo, hf_krb4_s_name, tree, tvb, offset);
131
132
  /* service Instance */
133
0
  offset=dissect_krb4_string(pinfo, hf_krb4_s_instance, tree, tvb, offset);
134
135
0
  return offset;
136
0
}
137
138
139
static int
140
dissect_krb4_kdc_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, const unsigned encoding)
141
3
{
142
3
  uint32_t length;
143
144
  /* Name */
145
3
  offset=dissect_krb4_string(pinfo, hf_krb4_name, tree, tvb, offset);
146
147
  /* Instance */
148
3
  offset=dissect_krb4_string(pinfo, hf_krb4_instance, tree, tvb, offset);
149
150
  /* Realm */
151
3
  offset=dissect_krb4_string(pinfo, hf_krb4_realm, tree, tvb, offset);
152
153
  /* Time sec */
154
3
  proto_tree_add_item(tree, hf_krb4_time_sec, tvb, offset, 4, ENC_TIME_SECS|encoding);
155
3
  offset+=4;
156
157
  /*XXX unknown byte here */
158
3
  offset++;
159
160
  /* exp date */
161
3
  proto_tree_add_item(tree, hf_krb4_exp_date, tvb, offset, 4, ENC_TIME_SECS|encoding);
162
3
  offset+=4;
163
164
  /* kvno */
165
3
  proto_tree_add_item(tree, hf_krb4_kvno, tvb, offset, 1, ENC_BIG_ENDIAN);
166
3
  offset++;
167
168
  /* length2 */
169
3
  proto_tree_add_item_ret_uint(tree, hf_krb4_length, tvb, offset, 2, encoding, &length);
170
3
  offset+=2;
171
172
  /* encrypted blob */
173
3
  proto_tree_add_item(tree, hf_krb4_encrypted_blob, tvb, offset, length, ENC_NA);
174
3
  offset+=length;
175
176
3
  return offset;
177
3
}
178
179
180
static int
181
dissect_krb4_appl_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, const unsigned encoding)
182
1
{
183
1
  uint8_t  tlen, rlen;
184
1
  uint8_t  lifetime;
185
186
  /* kvno */
187
1
  proto_tree_add_item(tree, hf_krb4_kvno, tvb, offset, 1, ENC_BIG_ENDIAN);
188
1
  offset++;
189
190
  /* Realm */
191
1
  offset=dissect_krb4_string(pinfo, hf_krb4_realm, tree, tvb, offset);
192
193
  /* ticket length */
194
1
  tlen=tvb_get_uint8(tvb, offset);
195
1
  proto_tree_add_item(tree, hf_krb4_ticket_length, tvb, offset, 1, ENC_BIG_ENDIAN);
196
1
  offset++;
197
198
  /* request length */
199
1
  rlen=tvb_get_uint8(tvb, offset);
200
1
  proto_tree_add_item(tree, hf_krb4_request_length, tvb, offset, 1, ENC_BIG_ENDIAN);
201
1
  offset++;
202
203
  /* ticket */
204
1
  proto_tree_add_item(tree, hf_krb4_ticket_blob, tvb, offset, tlen, ENC_NA);
205
1
  offset+=tlen;
206
207
  /* request */
208
1
  proto_tree_add_item(tree, hf_krb4_request_blob, tvb, offset, rlen, ENC_NA);
209
1
  offset+=rlen;
210
211
  /* request time */
212
1
  proto_tree_add_item(tree, hf_krb4_req_date, tvb, offset, 4, ENC_TIME_SECS|encoding);
213
1
  offset+=4;
214
215
  /* lifetime */
216
1
  lifetime=tvb_get_uint8(tvb, offset);
217
1
  proto_tree_add_uint_format_value(tree, hf_krb4_lifetime, tvb, offset, 1, lifetime, "%d (%d minutes)", lifetime, lifetime*5);
218
1
  offset++;
219
220
  /* service Name */
221
1
  offset=dissect_krb4_string(pinfo, hf_krb4_s_name, tree, tvb, offset);
222
223
  /* service Instance */
224
1
  offset=dissect_krb4_string(pinfo, hf_krb4_s_instance, tree, tvb, offset);
225
226
1
  return offset;
227
1
}
228
229
230
231
static int
232
dissect_krb4_auth_msg_type(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int version)
233
6
{
234
6
  proto_tree *tree;
235
6
  proto_item *item;
236
6
  uint32_t     auth_msg_type;
237
6
  char       *str_type;
238
239
6
  item = proto_tree_add_item_ret_uint(parent_tree, hf_krb4_auth_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN, &auth_msg_type);
240
6
  tree = proto_item_add_subtree(item, ett_krb4_auth_msg_type);
241
242
6
  str_type = val_to_str(pinfo->pool, auth_msg_type >> 1, m_type_vals, "Unknown (0x%04x)");
243
244
  /* m_type */
245
6
  proto_tree_add_item(tree, hf_krb4_m_type, tvb, offset, 1, ENC_BIG_ENDIAN);
246
6
  col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s",
247
6
     (version==TRANSARC_SPECIAL_VERSION)?"TRANSARC-":"", str_type);
248
6
  proto_item_append_text(item, " %s%s",
249
6
     (version==TRANSARC_SPECIAL_VERSION)?"TRANSARC-":"", str_type);
250
251
  /* byte order */
252
6
  proto_tree_add_item(tree, hf_krb4_byte_order, tvb, offset, 1, ENC_BIG_ENDIAN);
253
6
  proto_item_append_text(item, " (%s)", val_to_str(pinfo->pool, auth_msg_type&0x01, byte_order_vals, "Unknown (0x%04x)"));
254
255
6
  offset++;
256
6
  return offset;
257
6
}
258
259
static int
260
dissect_krb4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
261
21
{
262
21
  proto_tree *tree;
263
21
  proto_item *item;
264
21
  uint8_t     version, opcode;
265
21
  int         offset = 0;
266
21
  unsigned    encoding;
267
268
  /* this should better have the value 4 or it might be a weirdo
269
   * Transarc AFS special unknown thing.
270
   */
271
21
  version=tvb_get_uint8(tvb, offset);
272
21
  if((version!=4)&&(version!=TRANSARC_SPECIAL_VERSION)){
273
12
    return 0;
274
12
  }
275
276
9
  opcode=tvb_get_uint8(tvb, offset+1);
277
9
  switch(opcode>>1){
278
0
  case AUTH_MSG_KDC_REQUEST:
279
3
  case AUTH_MSG_KDC_REPLY:
280
4
  case AUTH_MSG_APPL_REQUEST:
281
4
  case AUTH_MSG_APPL_REQUEST_MUTUAL:
282
4
  case AUTH_MSG_ERR_REPLY:
283
5
  case AUTH_MSG_PRIVATE:
284
5
  case AUTH_MSG_SAFE:
285
5
  case AUTH_MSG_APPL_ERR:
286
6
  case AUTH_MSG_DIE:
287
6
    break;
288
3
  default:
289
3
    return 0;
290
9
  }
291
292
  /* create a tree for krb4 */
293
6
  item = proto_tree_add_item(parent_tree, proto_krb4, tvb, offset, -1, ENC_NA);
294
6
  tree = proto_item_add_subtree(item, ett_krb4);
295
296
6
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB4");
297
6
  col_clear(pinfo->cinfo, COL_INFO);
298
299
  /* version */
300
6
  proto_tree_add_item(tree, hf_krb4_version, tvb, offset, 1, ENC_BIG_ENDIAN);
301
6
  offset++;
302
303
  /* auth_msg_type */
304
6
  offset = dissect_krb4_auth_msg_type(pinfo, tree, tvb, offset, version);
305
306
6
  encoding = opcode&0x01 ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN;
307
6
  switch(opcode>>1){
308
0
  case AUTH_MSG_KDC_REQUEST:
309
0
    offset = dissect_krb4_kdc_request(pinfo, tree, tvb, offset, encoding, version);
310
0
    break;
311
3
  case AUTH_MSG_KDC_REPLY:
312
3
    offset = dissect_krb4_kdc_reply(pinfo, tree, tvb, offset, encoding);
313
3
    break;
314
1
  case AUTH_MSG_APPL_REQUEST:
315
1
    offset = dissect_krb4_appl_request(pinfo, tree, tvb, offset, encoding);
316
1
    break;
317
0
  case AUTH_MSG_APPL_REQUEST_MUTUAL:
318
0
  case AUTH_MSG_ERR_REPLY:
319
1
  case AUTH_MSG_PRIVATE:
320
1
  case AUTH_MSG_SAFE:
321
1
  case AUTH_MSG_APPL_ERR:
322
2
  case AUTH_MSG_DIE:
323
2
    break;
324
6
  }
325
2
  return offset;
326
6
}
327
328
void
329
proto_register_krb4(void)
330
16
{
331
16
  static hf_register_info hf[] = {
332
16
    { &hf_krb4_version,
333
16
      { "Version", "krb4.version",
334
16
        FT_UINT8, BASE_DEC, NULL, 0x0,
335
16
        "Kerberos(v4) version number", HFILL }},
336
16
    { &hf_krb4_auth_msg_type,
337
16
      { "Msg Type", "krb4.auth_msg_type",
338
16
        FT_UINT8, BASE_HEX, NULL, 0x0,
339
16
        "Message Type/Byte Order", HFILL }},
340
16
    { &hf_krb4_m_type,
341
16
      { "M Type", "krb4.m_type",
342
16
        FT_UINT8, BASE_HEX, VALS(m_type_vals), 0xfe,
343
16
        "Message Type", HFILL }},
344
16
    { &hf_krb4_byte_order,
345
16
      { "Byte Order", "krb4.byte_order",
346
16
        FT_UINT8, BASE_HEX, VALS(byte_order_vals), 0x01,
347
16
        NULL, HFILL }},
348
16
    { &hf_krb4_name,
349
16
      { "Name", "krb4.name",
350
16
        FT_STRINGZ, BASE_NONE, NULL, 0x00,
351
16
        NULL, HFILL }},
352
16
    { &hf_krb4_instance,
353
16
      { "Instance", "krb4.instance",
354
16
        FT_STRINGZ, BASE_NONE, NULL, 0x00,
355
16
        NULL, HFILL }},
356
16
    { &hf_krb4_realm,
357
16
      { "Realm", "krb4.realm",
358
16
        FT_STRINGZ, BASE_NONE, NULL, 0x00,
359
16
        NULL, HFILL }},
360
16
    { &hf_krb4_time_sec,
361
16
      { "Time Sec", "krb4.time_sec",
362
16
        FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
363
16
        NULL, HFILL }},
364
16
    { &hf_krb4_exp_date,
365
16
      { "Exp Date", "krb4.exp_date",
366
16
        FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
367
16
        NULL, HFILL }},
368
16
    { &hf_krb4_req_date,
369
16
      { "Req Date", "krb4.req_date",
370
16
        FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
371
16
        NULL, HFILL }},
372
16
    { &hf_krb4_lifetime,
373
16
      { "Lifetime", "krb4.lifetime",
374
16
        FT_UINT8, BASE_DEC, NULL, 0x00,
375
16
        "Lifetime (in 5 min units)", HFILL }},
376
16
    { &hf_krb4_s_name,
377
16
      { "Service Name", "krb4.s_name",
378
16
        FT_STRINGZ, BASE_NONE, NULL, 0x00,
379
16
        NULL, HFILL }},
380
16
    { &hf_krb4_s_instance,
381
16
      { "Service Instance", "krb4.s_instance",
382
16
        FT_STRINGZ, BASE_NONE, NULL, 0x00,
383
16
        NULL, HFILL }},
384
16
    { &hf_krb4_kvno,
385
16
      { "Kvno", "krb4.kvno",
386
16
        FT_UINT8, BASE_DEC, NULL, 0x00,
387
16
        "Key Version No", HFILL }},
388
16
    { &hf_krb4_length,
389
16
      { "Length", "krb4.length",
390
16
        FT_UINT32, BASE_DEC, NULL, 0x00,
391
16
        "Length of encrypted blob", HFILL }},
392
16
    { &hf_krb4_ticket_length,
393
16
      { "Ticket Length", "krb4.ticket.length",
394
16
        FT_UINT8, BASE_DEC, NULL, 0x00,
395
16
        "Length of ticket", HFILL }},
396
16
    { &hf_krb4_request_length,
397
16
      { "Request Length", "krb4.request.length",
398
16
        FT_UINT8, BASE_DEC, NULL, 0x00,
399
16
        "Length of request", HFILL }},
400
16
    { &hf_krb4_ticket_blob,
401
16
      { "Ticket Blob", "krb4.ticket.blob",
402
16
        FT_BYTES, BASE_NONE, NULL, 0x00,
403
16
        NULL, HFILL }},
404
16
    { &hf_krb4_request_blob,
405
16
      { "Request Blob", "krb4.request.blob",
406
16
        FT_BYTES, BASE_NONE, NULL, 0x00,
407
16
        NULL, HFILL }},
408
16
    { &hf_krb4_encrypted_blob,
409
16
      { "Encrypted Blob", "krb4.encrypted_blob",
410
16
        FT_BYTES, BASE_NONE, NULL, 0x00,
411
16
        NULL, HFILL }},
412
16
    { &hf_krb4_unknown_transarc_blob,
413
16
      { "Unknown Transarc Blob", "krb4.unknown_transarc_blob",
414
16
        FT_BYTES, BASE_NONE, NULL, 0x00,
415
16
        "Unknown blob only present in Transarc packets", HFILL }},
416
16
  };
417
16
  static int *ett[] = {
418
16
    &ett_krb4,
419
16
    &ett_krb4_auth_msg_type,
420
16
  };
421
422
16
  proto_krb4 = proto_register_protocol("Kerberos v4", "KRB4", "krb4");
423
16
  krb4_handle = register_dissector("krb4", dissect_krb4, proto_krb4);
424
16
  proto_register_field_array(proto_krb4, hf, array_length(hf));
425
16
  proto_register_subtree_array(ett, array_length(ett));
426
16
}
427
428
void
429
proto_reg_handoff_krb4(void)
430
16
{
431
16
  dissector_add_uint_with_preference("udp.port", UDP_PORT_KRB4, krb4_handle);
432
16
}
433
434
/*
435
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
436
 *
437
 * Local variables:
438
 * c-basic-offset: 8
439
 * tab-width: 8
440
 * indent-tabs-mode: t
441
 * End:
442
 *
443
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
444
 * :indentSize=8:tabSize=8:noTabs=false:
445
 */