Coverage Report

Created: 2023-11-19 06:16

/src/FreeRDP/winpr/libwinpr/utils/wlog/PacketMessage.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * WinPR Logger
4
 *
5
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2015 Thincast Technologies GmbH
7
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21
22
#include <winpr/config.h>
23
24
#include "wlog.h"
25
26
#include "PacketMessage.h"
27
28
#include <winpr/wtypes.h>
29
#include <winpr/crt.h>
30
#include <winpr/file.h>
31
#include <winpr/stream.h>
32
33
#include "../../log.h"
34
#define TAG WINPR_TAG("utils.wlog")
35
36
#ifndef _WIN32
37
#include <sys/time.h>
38
#else
39
#include <time.h>
40
#include <sys/timeb.h>
41
#include <winpr/windows.h>
42
43
static int gettimeofday(struct timeval* tp, void* tz)
44
{
45
  struct _timeb timebuffer;
46
  _ftime(&timebuffer);
47
  tp->tv_sec = (long)timebuffer.time;
48
  tp->tv_usec = timebuffer.millitm * 1000;
49
  return 0;
50
}
51
#endif
52
53
static BOOL Pcap_Read_Header(wPcap* pcap, wPcapHeader* header)
54
0
{
55
0
  if (pcap && pcap->fp && fread((void*)header, sizeof(wPcapHeader), 1, pcap->fp) == 1)
56
0
    return TRUE;
57
0
  return FALSE;
58
0
}
59
60
/* currently unused code */
61
#if 0
62
static BOOL Pcap_Read_RecordHeader(wPcap* pcap, wPcapRecordHeader* record)
63
{
64
  if (pcap && pcap->fp && (fread((void*) record, sizeof(wPcapRecordHeader), 1, pcap->fp) == 1))
65
    return TRUE;
66
  return FALSE;
67
}
68
69
static BOOL Pcap_Read_Record(wPcap* pcap, wPcapRecord* record)
70
{
71
  if (pcap && pcap->fp)
72
  {
73
    if (!Pcap_Read_RecordHeader(pcap, &record->header))
74
      return FALSE;
75
    record->length = record->header.incl_len;
76
    record->data = malloc(record->length);
77
    if (!record->data)
78
      return FALSE;
79
    if (fread(record->data, record->length, 1, pcap->fp) != 1)
80
    {
81
      free(record->data);
82
      record->length = 0;
83
      record->data = NULL;
84
      return FALSE;
85
    }
86
  }
87
  return TRUE;
88
}
89
90
static BOOL Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length)
91
{
92
  wPcapRecord* record;
93
  struct timeval tp;
94
95
  if (!pcap->tail)
96
  {
97
    pcap->tail = (wPcapRecord*) calloc(1, sizeof(wPcapRecord));
98
    if (!pcap->tail)
99
      return FALSE;
100
    pcap->head = pcap->tail;
101
    pcap->record = pcap->head;
102
    record = pcap->tail;
103
  }
104
  else
105
  {
106
    record = (wPcapRecord*) calloc(1, sizeof(wPcapRecord));
107
    if (!record)
108
      return FALSE;
109
    pcap->tail->next = record;
110
    pcap->tail = record;
111
  }
112
113
  if (!pcap->record)
114
    pcap->record = record;
115
116
  record->data = data;
117
  record->length = length;
118
  record->header.incl_len = length;
119
  record->header.orig_len = length;
120
  gettimeofday(&tp, 0);
121
  record->header.ts_sec = tp.tv_sec;
122
  record->header.ts_usec = tp.tv_usec;
123
  return TRUE;
124
}
125
126
static BOOL Pcap_HasNext_Record(wPcap* pcap)
127
{
128
  if (pcap->file_size - (_ftelli64(pcap->fp)) <= 16)
129
    return FALSE;
130
131
  return TRUE;
132
}
133
134
static BOOL Pcap_GetNext_RecordHeader(wPcap* pcap, wPcapRecord* record)
135
{
136
  if (!Pcap_HasNext_Record(pcap) || !Pcap_Read_RecordHeader(pcap, &record->header))
137
    return FALSE;
138
139
  record->length = record->header.incl_len;
140
  return TRUE;
141
}
142
143
static BOOL Pcap_GetNext_RecordContent(wPcap* pcap, wPcapRecord* record)
144
{
145
  if (pcap && pcap->fp && fread(record->data, record->length, 1, pcap->fp) == 1)
146
    return TRUE;
147
148
  return FALSE;
149
}
150
151
static BOOL Pcap_GetNext_Record(wPcap* pcap, wPcapRecord* record)
152
{
153
  if (!Pcap_HasNext_Record(pcap))
154
    return FALSE;
155
156
  return Pcap_Read_Record(pcap, record);
157
}
158
#endif
159
160
static BOOL Pcap_Write_Header(wPcap* pcap, wPcapHeader* header)
161
0
{
162
0
  if (pcap && pcap->fp && fwrite((void*)header, sizeof(wPcapHeader), 1, pcap->fp) == 1)
163
0
    return TRUE;
164
0
  return FALSE;
165
0
}
166
167
static BOOL Pcap_Write_RecordHeader(wPcap* pcap, wPcapRecordHeader* record)
168
0
{
169
0
  if (pcap && pcap->fp && fwrite((void*)record, sizeof(wPcapRecordHeader), 1, pcap->fp) == 1)
170
0
    return TRUE;
171
0
  return FALSE;
172
0
}
173
174
static BOOL Pcap_Write_RecordContent(wPcap* pcap, wPcapRecord* record)
175
0
{
176
0
  if (pcap && pcap->fp && fwrite(record->data, record->length, 1, pcap->fp) == 1)
177
0
    return TRUE;
178
0
  return FALSE;
179
0
}
180
181
static BOOL Pcap_Write_Record(wPcap* pcap, wPcapRecord* record)
182
0
{
183
0
  return Pcap_Write_RecordHeader(pcap, &record->header) && Pcap_Write_RecordContent(pcap, record);
184
0
}
185
186
wPcap* Pcap_Open(char* name, BOOL write)
187
0
{
188
0
  wPcap* pcap = NULL;
189
0
  FILE* pcap_fp = winpr_fopen(name, write ? "w+b" : "rb");
190
191
0
  if (!pcap_fp)
192
0
  {
193
0
    WLog_ERR(TAG, "opening pcap file");
194
0
    return NULL;
195
0
  }
196
197
0
  pcap = (wPcap*)calloc(1, sizeof(wPcap));
198
199
0
  if (!pcap)
200
0
    goto out_fail;
201
202
0
  pcap->name = name;
203
0
  pcap->write = write;
204
0
  pcap->record_count = 0;
205
0
  pcap->fp = pcap_fp;
206
207
0
  if (write)
208
0
  {
209
0
    pcap->header.magic_number = PCAP_MAGIC_NUMBER;
210
0
    pcap->header.version_major = 2;
211
0
    pcap->header.version_minor = 4;
212
0
    pcap->header.thiszone = 0;
213
0
    pcap->header.sigfigs = 0;
214
0
    pcap->header.snaplen = 0xFFFFFFFF;
215
0
    pcap->header.network = 1; /* ethernet */
216
0
    if (!Pcap_Write_Header(pcap, &pcap->header))
217
0
      goto out_fail;
218
0
  }
219
0
  else
220
0
  {
221
0
    if (_fseeki64(pcap->fp, 0, SEEK_END) < 0)
222
0
      goto out_fail;
223
0
    pcap->file_size = (SSIZE_T)_ftelli64(pcap->fp);
224
0
    if (pcap->file_size < 0)
225
0
      goto out_fail;
226
0
    if (_fseeki64(pcap->fp, 0, SEEK_SET) < 0)
227
0
      goto out_fail;
228
0
    if (!Pcap_Read_Header(pcap, &pcap->header))
229
0
      goto out_fail;
230
0
  }
231
232
0
  return pcap;
233
234
0
out_fail:
235
0
  if (pcap_fp)
236
0
    fclose(pcap_fp);
237
0
  free(pcap);
238
0
  return NULL;
239
0
}
240
241
void Pcap_Flush(wPcap* pcap)
242
0
{
243
0
  if (!pcap || !pcap->fp)
244
0
    return;
245
246
0
  while (pcap->record)
247
0
  {
248
0
    if (!Pcap_Write_Record(pcap, pcap->record))
249
0
      return;
250
0
    pcap->record = pcap->record->next;
251
0
  }
252
253
0
  fflush(pcap->fp);
254
0
  return;
255
0
}
256
257
void Pcap_Close(wPcap* pcap)
258
0
{
259
0
  if (!pcap || !pcap->fp)
260
0
    return;
261
262
0
  Pcap_Flush(pcap);
263
0
  fclose(pcap->fp);
264
0
  free(pcap);
265
0
}
266
267
static BOOL WLog_PacketMessage_Write_EthernetHeader(wPcap* pcap, wEthernetHeader* ethernet)
268
0
{
269
0
  wStream* s;
270
0
  wStream sbuffer = { 0 };
271
0
  BYTE buffer[14] = { 0 };
272
0
  BOOL ret = TRUE;
273
274
0
  if (!pcap || !pcap->fp || !ethernet)
275
0
    return FALSE;
276
277
0
  s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
278
0
  if (!s)
279
0
    return FALSE;
280
0
  Stream_Write(s, ethernet->Destination, 6);
281
0
  Stream_Write(s, ethernet->Source, 6);
282
0
  Stream_Write_UINT16_BE(s, ethernet->Type);
283
0
  if (fwrite(buffer, sizeof(buffer), 1, pcap->fp) != 1)
284
0
    ret = FALSE;
285
286
0
  return ret;
287
0
}
288
289
static UINT16 IPv4Checksum(BYTE* ipv4, int length)
290
0
{
291
0
  UINT16 tmp16;
292
0
  long checksum = 0;
293
294
0
  while (length > 1)
295
0
  {
296
0
    tmp16 = *((UINT16*)ipv4);
297
0
    checksum += tmp16;
298
0
    length -= 2;
299
0
    ipv4 += 2;
300
0
  }
301
302
0
  if (length > 0)
303
0
    checksum += *ipv4;
304
305
0
  while (checksum >> 16)
306
0
    checksum = (checksum & 0xFFFF) + (checksum >> 16);
307
308
0
  return (UINT16)(~checksum);
309
0
}
310
311
static BOOL WLog_PacketMessage_Write_IPv4Header(wPcap* pcap, wIPv4Header* ipv4)
312
0
{
313
0
  wStream* s;
314
0
  wStream sbuffer = { 0 };
315
0
  BYTE buffer[20] = { 0 };
316
0
  int ret = TRUE;
317
318
0
  if (!pcap || !pcap->fp || !ipv4)
319
0
    return FALSE;
320
321
0
  s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
322
0
  if (!s)
323
0
    return FALSE;
324
0
  Stream_Write_UINT8(s, (ipv4->Version << 4) | ipv4->InternetHeaderLength);
325
0
  Stream_Write_UINT8(s, ipv4->TypeOfService);
326
0
  Stream_Write_UINT16_BE(s, ipv4->TotalLength);
327
0
  Stream_Write_UINT16_BE(s, ipv4->Identification);
328
0
  Stream_Write_UINT16_BE(s, (ipv4->InternetProtocolFlags << 13) | ipv4->FragmentOffset);
329
0
  Stream_Write_UINT8(s, ipv4->TimeToLive);
330
0
  Stream_Write_UINT8(s, ipv4->Protocol);
331
0
  Stream_Write_UINT16(s, ipv4->HeaderChecksum);
332
0
  Stream_Write_UINT32_BE(s, ipv4->SourceAddress);
333
0
  Stream_Write_UINT32_BE(s, ipv4->DestinationAddress);
334
0
  ipv4->HeaderChecksum = IPv4Checksum((BYTE*)buffer, 20);
335
0
  Stream_Rewind(s, 10);
336
0
  Stream_Write_UINT16(s, ipv4->HeaderChecksum);
337
338
0
  if (fwrite(buffer, sizeof(buffer), 1, pcap->fp) != 1)
339
0
    ret = FALSE;
340
341
0
  return ret;
342
0
}
343
344
static BOOL WLog_PacketMessage_Write_TcpHeader(wPcap* pcap, wTcpHeader* tcp)
345
0
{
346
0
  wStream* s;
347
0
  wStream sbuffer = { 0 };
348
0
  BYTE buffer[20] = { 0 };
349
0
  BOOL ret = TRUE;
350
351
0
  if (!pcap || !pcap->fp || !tcp)
352
0
    return FALSE;
353
354
0
  s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
355
0
  if (!s)
356
0
    return FALSE;
357
0
  Stream_Write_UINT16_BE(s, tcp->SourcePort);
358
0
  Stream_Write_UINT16_BE(s, tcp->DestinationPort);
359
0
  Stream_Write_UINT32_BE(s, tcp->SequenceNumber);
360
0
  Stream_Write_UINT32_BE(s, tcp->AcknowledgementNumber);
361
0
  Stream_Write_UINT8(s, (tcp->Offset << 4) | tcp->Reserved);
362
0
  Stream_Write_UINT8(s, tcp->TcpFlags);
363
0
  Stream_Write_UINT16_BE(s, tcp->Window);
364
0
  Stream_Write_UINT16_BE(s, tcp->Checksum);
365
0
  Stream_Write_UINT16_BE(s, tcp->UrgentPointer);
366
367
0
  if (pcap->fp)
368
0
  {
369
0
    if (fwrite(buffer, sizeof(buffer), 1, pcap->fp) != 1)
370
0
      ret = FALSE;
371
0
  }
372
373
0
  return ret;
374
0
}
375
376
static UINT32 g_InboundSequenceNumber = 0;
377
static UINT32 g_OutboundSequenceNumber = 0;
378
379
BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flags)
380
0
{
381
0
  wTcpHeader tcp;
382
0
  wIPv4Header ipv4;
383
0
  struct timeval tp;
384
0
  wPcapRecord record;
385
0
  wEthernetHeader ethernet;
386
0
  ethernet.Type = 0x0800;
387
388
0
  if (!pcap || !pcap->fp)
389
0
    return FALSE;
390
391
0
  if (flags & WLOG_PACKET_OUTBOUND)
392
0
  {
393
    /* 00:15:5D:01:64:04 */
394
0
    ethernet.Source[0] = 0x00;
395
0
    ethernet.Source[1] = 0x15;
396
0
    ethernet.Source[2] = 0x5D;
397
0
    ethernet.Source[3] = 0x01;
398
0
    ethernet.Source[4] = 0x64;
399
0
    ethernet.Source[5] = 0x04;
400
    /* 00:15:5D:01:64:01 */
401
0
    ethernet.Destination[0] = 0x00;
402
0
    ethernet.Destination[1] = 0x15;
403
0
    ethernet.Destination[2] = 0x5D;
404
0
    ethernet.Destination[3] = 0x01;
405
0
    ethernet.Destination[4] = 0x64;
406
0
    ethernet.Destination[5] = 0x01;
407
0
  }
408
0
  else
409
0
  {
410
    /* 00:15:5D:01:64:01 */
411
0
    ethernet.Source[0] = 0x00;
412
0
    ethernet.Source[1] = 0x15;
413
0
    ethernet.Source[2] = 0x5D;
414
0
    ethernet.Source[3] = 0x01;
415
0
    ethernet.Source[4] = 0x64;
416
0
    ethernet.Source[5] = 0x01;
417
    /* 00:15:5D:01:64:04 */
418
0
    ethernet.Destination[0] = 0x00;
419
0
    ethernet.Destination[1] = 0x15;
420
0
    ethernet.Destination[2] = 0x5D;
421
0
    ethernet.Destination[3] = 0x01;
422
0
    ethernet.Destination[4] = 0x64;
423
0
    ethernet.Destination[5] = 0x04;
424
0
  }
425
426
0
  ipv4.Version = 4;
427
0
  ipv4.InternetHeaderLength = 5;
428
0
  ipv4.TypeOfService = 0;
429
0
  ipv4.TotalLength = (UINT16)(length + 20 + 20);
430
0
  ipv4.Identification = 0;
431
0
  ipv4.InternetProtocolFlags = 0x02;
432
0
  ipv4.FragmentOffset = 0;
433
0
  ipv4.TimeToLive = 128;
434
0
  ipv4.Protocol = 6; /* TCP */
435
0
  ipv4.HeaderChecksum = 0;
436
437
0
  if (flags & WLOG_PACKET_OUTBOUND)
438
0
  {
439
0
    ipv4.SourceAddress = 0xC0A80196;      /* 192.168.1.150 */
440
0
    ipv4.DestinationAddress = 0x4A7D64C8; /* 74.125.100.200 */
441
0
  }
442
0
  else
443
0
  {
444
0
    ipv4.SourceAddress = 0x4A7D64C8;      /* 74.125.100.200 */
445
0
    ipv4.DestinationAddress = 0xC0A80196; /* 192.168.1.150 */
446
0
  }
447
448
0
  tcp.SourcePort = 3389;
449
0
  tcp.DestinationPort = 3389;
450
451
0
  if (flags & WLOG_PACKET_OUTBOUND)
452
0
  {
453
0
    tcp.SequenceNumber = g_OutboundSequenceNumber;
454
0
    tcp.AcknowledgementNumber = g_InboundSequenceNumber;
455
0
    g_OutboundSequenceNumber += length;
456
0
  }
457
0
  else
458
0
  {
459
0
    tcp.SequenceNumber = g_InboundSequenceNumber;
460
0
    tcp.AcknowledgementNumber = g_OutboundSequenceNumber;
461
0
    g_InboundSequenceNumber += length;
462
0
  }
463
464
0
  tcp.Offset = 5;
465
0
  tcp.Reserved = 0;
466
0
  tcp.TcpFlags = 0x0018;
467
0
  tcp.Window = 0x7FFF;
468
0
  tcp.Checksum = 0;
469
0
  tcp.UrgentPointer = 0;
470
0
  record.data = data;
471
0
  record.length = length;
472
0
  const size_t offset = 14 + 20 + 20;
473
0
  WINPR_ASSERT(record.length <= UINT32_MAX - offset);
474
0
  record.header.incl_len = (UINT32)record.length + offset;
475
0
  record.header.orig_len = (UINT32)record.length + offset;
476
0
  record.next = NULL;
477
0
  gettimeofday(&tp, 0);
478
0
  record.header.ts_sec = tp.tv_sec;
479
0
  record.header.ts_usec = tp.tv_usec;
480
0
  if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
481
0
      !WLog_PacketMessage_Write_EthernetHeader(pcap, &ethernet) ||
482
0
      !WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
483
0
      !WLog_PacketMessage_Write_TcpHeader(pcap, &tcp) || !Pcap_Write_RecordContent(pcap, &record))
484
0
    return FALSE;
485
0
  fflush(pcap->fp);
486
0
  return TRUE;
487
0
}