Coverage Report

Created: 2023-01-25 06:41

/src/PcapPlusPlus/Packet++/src/HttpLayer.cpp
Line
Count
Source (jump to first uncovered line)
1
11.7k
#define LOG_MODULE PacketLogModuleHttpLayer
2
3
#include "Logger.h"
4
#include "GeneralUtils.h"
5
#include "HttpLayer.h"
6
#include <string.h>
7
#include <algorithm>
8
#include <stdlib.h>
9
#include <exception>
10
11
namespace pcpp
12
{
13
14
15
// -------- Class HttpMessage -----------------
16
17
18
HeaderField* HttpMessage::addField(const std::string& fieldName, const std::string& fieldValue)
19
0
{
20
0
  if (getFieldByName(fieldName) != NULL)
21
0
  {
22
0
    PCPP_LOG_ERROR("Field '" << fieldName << "' already exists!");
23
0
    return NULL;
24
0
  }
25
26
0
  return TextBasedProtocolMessage::addField(fieldName, fieldValue);
27
0
}
28
29
HeaderField* HttpMessage::addField(const HeaderField& newField)
30
0
{
31
0
  if (getFieldByName(newField.getFieldName()) != NULL)
32
0
  {
33
0
    PCPP_LOG_ERROR("Field '" << newField.getFieldName() << "' already exists!");
34
0
    return NULL;
35
0
  }
36
37
0
  return TextBasedProtocolMessage::addField(newField);
38
0
}
39
40
HeaderField* HttpMessage::insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue)
41
0
{
42
0
  if (getFieldByName(fieldName) != NULL)
43
0
  {
44
0
    PCPP_LOG_ERROR("Field '" << fieldName << "' already exists!");
45
0
    return NULL;
46
0
  }
47
48
0
  return TextBasedProtocolMessage::insertField(prevField, fieldName, fieldValue);
49
0
}
50
51
HeaderField* HttpMessage::insertField(HeaderField* prevField, const HeaderField& newField)
52
0
{
53
0
  if (getFieldByName(newField.getFieldName()) != NULL)
54
0
  {
55
0
    PCPP_LOG_ERROR("Field '" << newField.getFieldName() << "' already exists!");
56
0
    return NULL;
57
0
  }
58
59
0
  return TextBasedProtocolMessage::insertField(prevField, newField);
60
0
}
61
62
63
64
// -------- Class HttpRequestLayer -----------------
65
66
HttpRequestLayer::HttpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : HttpMessage(data, dataLen, prevLayer, packet)
67
7.55k
{
68
7.55k
  m_Protocol = HTTPRequest;
69
7.55k
  m_FirstLine = new HttpRequestFirstLine(this);
70
7.55k
  m_FieldsOffset = m_FirstLine->getSize();
71
7.55k
  parseFields();
72
7.55k
}
73
74
HttpRequestLayer::HttpRequestLayer(HttpMethod method, std::string uri, HttpVersion version)
75
0
{
76
0
  m_Protocol = HTTPRequest;
77
0
  m_FirstLine = new HttpRequestFirstLine(this, method, version, uri);
78
0
  m_FieldsOffset = m_FirstLine->getSize();
79
0
}
80
81
HttpRequestLayer::HttpRequestLayer(const HttpRequestLayer& other) : HttpMessage(other)
82
0
{
83
0
  m_FirstLine = new HttpRequestFirstLine(this);
84
0
}
85
86
HttpRequestLayer& HttpRequestLayer::operator=(const HttpRequestLayer& other)
87
0
{
88
0
  HttpMessage::operator=(other);
89
90
0
  if (m_FirstLine != NULL)
91
0
    delete m_FirstLine;
92
93
0
  m_FirstLine = new HttpRequestFirstLine(this);
94
95
0
  return *this;
96
0
}
97
98
99
std::string HttpRequestLayer::getUrl() const
100
0
{
101
0
  HeaderField* hostField = getFieldByName(PCPP_HTTP_HOST_FIELD);
102
0
  if (hostField == NULL)
103
0
    return m_FirstLine->getUri();
104
105
0
  return hostField->getFieldValue() + m_FirstLine->getUri();
106
0
}
107
108
HttpRequestLayer::~HttpRequestLayer()
109
7.55k
{
110
7.55k
  delete m_FirstLine;
111
7.55k
}
112
113
std::string HttpRequestLayer::toString() const
114
0
{
115
0
  static const int maxLengthToPrint = 120;
116
0
  std::string result = "HTTP request, ";
117
0
  int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line
118
0
  if (size <= 0)
119
0
  {
120
0
    result += std::string("CORRUPT DATA");
121
0
    return result;
122
0
  }
123
0
  if (size <= maxLengthToPrint)
124
0
  {
125
0
    char* firstLine = new char[size+1];
126
0
    strncpy(firstLine, (char*)m_Data, size);
127
0
    firstLine[size] = 0;
128
0
    result += std::string(firstLine);
129
0
    delete[] firstLine;
130
0
  }
131
0
  else
132
0
  {
133
0
    char firstLine[maxLengthToPrint+1];
134
0
    strncpy(firstLine, (char*)m_Data, maxLengthToPrint-3);
135
0
    firstLine[maxLengthToPrint-3] = '.';
136
0
    firstLine[maxLengthToPrint-2] = '.';
137
0
    firstLine[maxLengthToPrint-1] = '.';
138
0
    firstLine[maxLengthToPrint] = 0;
139
0
    result += std::string(firstLine);
140
0
  }
141
142
0
  return result;
143
0
}
144
145
146
147
148
149
150
151
// -------- Class HttpRequestFirstLine -----------------
152
153
154
const std::string MethodEnumToString[9] = {
155
    "GET",
156
    "HEAD",
157
    "POST",
158
    "PUT",
159
    "DELETE",
160
    "TRACE",
161
    "OPTIONS",
162
    "CONNECT",
163
    "PATCH"
164
};
165
166
const std::string VersionEnumToString[3] = {
167
    "0.9",
168
    "1.0",
169
    "1.1"
170
};
171
172
HttpRequestFirstLine::HttpRequestFirstLine(HttpRequestLayer* httpRequest) : m_HttpRequest(httpRequest)
173
7.55k
{
174
7.55k
  m_Method = parseMethod((char*)m_HttpRequest->m_Data, m_HttpRequest->getDataLen());
175
7.55k
  if (m_Method == HttpRequestLayer::HttpMethodUnknown)
176
0
  {
177
0
    m_UriOffset = -1;
178
0
    PCPP_LOG_DEBUG("Couldn't resolve HTTP request method");
179
0
    m_IsComplete = false;
180
0
    m_Version = HttpVersionUnknown;
181
0
    m_VersionOffset = -1;
182
0
    m_FirstLineEndOffset = m_HttpRequest->getDataLen();
183
0
    return;
184
0
  }
185
7.55k
  else
186
7.55k
    m_UriOffset = MethodEnumToString[m_Method].length() + 1;
187
188
7.55k
  parseVersion();
189
7.55k
  if(m_VersionOffset < 0)
190
2.49k
  {
191
2.49k
    m_IsComplete = false;
192
2.49k
    m_FirstLineEndOffset = m_HttpRequest->getDataLen();
193
2.49k
    return;
194
2.49k
  }
195
196
5.05k
  char* endOfFirstLine;
197
5.05k
  if ((endOfFirstLine = (char*)memchr((char*)(m_HttpRequest->m_Data + m_VersionOffset), '\n', m_HttpRequest->m_DataLen-(size_t)m_VersionOffset)) != NULL)
198
208
  {
199
208
    m_FirstLineEndOffset = endOfFirstLine - (char*)m_HttpRequest->m_Data + 1;
200
208
    m_IsComplete = true;
201
208
  }
202
4.85k
  else
203
4.85k
  {
204
4.85k
    m_FirstLineEndOffset = m_HttpRequest->getDataLen();
205
4.85k
    m_IsComplete = false;
206
4.85k
  }
207
208
5.05k
  if (Logger::getInstance().isDebugEnabled(PacketLogModuleHttpLayer))
209
0
  {
210
0
    std::string method = m_Method == HttpRequestLayer::HttpMethodUnknown? "Unknown" : MethodEnumToString[m_Method];
211
0
    PCPP_LOG_DEBUG(
212
0
      "Method='" << method << "'; "
213
0
      << "HTTP version='" << VersionEnumToString[m_Version] << "'; "
214
0
      << "URI='" << getUri() << "'");
215
0
  }
216
5.05k
}
217
218
HttpRequestFirstLine::HttpRequestFirstLine(HttpRequestLayer* httpRequest, HttpRequestLayer::HttpMethod method, HttpVersion version, std::string uri)
219
0
try   // throw(HttpRequestFirstLineException)
220
0
{
221
0
  if (method == HttpRequestLayer::HttpMethodUnknown)
222
0
  {
223
0
    m_Exception.setMessage("Method supplied was HttpMethodUnknown");
224
0
    throw m_Exception;
225
0
  }
226
227
0
  if (version == HttpVersionUnknown)
228
0
  {
229
0
    m_Exception.setMessage("Version supplied was HttpVersionUnknown");
230
0
    throw m_Exception;
231
0
  }
232
233
0
  m_HttpRequest = httpRequest;
234
235
0
  m_Method = method;
236
0
  m_Version = version;
237
238
0
  std::string firstLine = MethodEnumToString[m_Method] + " " + uri + " "  + "HTTP/" + VersionEnumToString[m_Version] + "\r\n";
239
240
0
  m_UriOffset =  MethodEnumToString[m_Method].length() + 1;
241
0
  m_FirstLineEndOffset = firstLine.length();
242
0
  m_VersionOffset = m_UriOffset + uri.length() + 6;
243
244
0
  m_HttpRequest->m_DataLen = firstLine.length();
245
0
  m_HttpRequest->m_Data = new uint8_t[m_HttpRequest->m_DataLen];
246
0
  memcpy(m_HttpRequest->m_Data, firstLine.c_str(), m_HttpRequest->m_DataLen);
247
248
0
  m_IsComplete = true;
249
0
}
250
0
catch(const HttpRequestFirstLineException&)
251
0
{
252
0
  throw;
253
0
}
254
0
catch(...)
255
0
{
256
0
  std::terminate();
257
0
}
258
259
HttpRequestLayer::HttpMethod HttpRequestFirstLine::parseMethod(char* data, size_t dataLen)
260
34.1k
{
261
34.1k
  if (dataLen < 4)
262
205
  {
263
205
    return HttpRequestLayer::HttpMethodUnknown;
264
205
  }
265
266
33.8k
  switch (data[0])
267
33.8k
  {
268
188
  case 'G':
269
188
    if (data[1] == 'E' && data[2] == 'T' && data[3] == ' ')
270
30
      return HttpRequestLayer::HttpGET;
271
158
    else
272
158
      return HttpRequestLayer::HttpMethodUnknown;
273
0
    break;
274
275
1.80k
  case 'D':
276
1.80k
    if (dataLen < 7)
277
198
      return HttpRequestLayer::HttpMethodUnknown;
278
1.60k
    else if (data[1] == 'E' && data[2] == 'L' && data[3] == 'E' && data[4] == 'T' && data[5] == 'E' && data[6] == ' ')
279
62
      return HttpRequestLayer::HttpDELETE;
280
1.54k
    else
281
1.54k
      return HttpRequestLayer::HttpMethodUnknown;
282
0
    break;
283
284
1.21k
  case 'C':
285
1.21k
    if (dataLen < 8)
286
250
      return HttpRequestLayer::HttpMethodUnknown;
287
960
    else if (data[1] == 'O' && data[2] == 'N' && data[3] == 'N' && data[4] == 'E' && data[5] == 'C' && data[6] == 'T' && data[7] == ' ')
288
2
      return HttpRequestLayer::HttpCONNECT;
289
958
    else
290
958
      return HttpRequestLayer::HttpMethodUnknown;
291
0
    break;
292
293
3.40k
  case 'T':
294
3.40k
    if (dataLen < 6)
295
204
      return HttpRequestLayer::HttpMethodUnknown;
296
3.20k
    else if (data[1] == 'R' && data[2] == 'A' && data[3] == 'C' && data[4] == 'E' && data[5] == ' ')
297
426
      return HttpRequestLayer::HttpTRACE;
298
2.77k
    else
299
2.77k
      return HttpRequestLayer::HttpMethodUnknown;
300
0
    break;
301
302
303
5.60k
  case 'H':
304
5.60k
    if (dataLen < 5)
305
214
      return HttpRequestLayer::HttpMethodUnknown;
306
5.38k
    else if (data[1] == 'E' && data[2] == 'A' && data[3] == 'D' && data[4] == ' ')
307
1.19k
      return HttpRequestLayer::HttpHEAD;
308
4.19k
    else
309
4.19k
      return HttpRequestLayer::HttpMethodUnknown;
310
0
    break;
311
312
2.55k
  case 'O':
313
2.55k
    if (dataLen < 8)
314
238
      return HttpRequestLayer::HttpMethodUnknown;
315
2.31k
    else if (data[1] == 'P' && data[2] == 'T' && data[3] == 'I' && data[4] == 'O' && data[5] == 'N' && data[6] == 'S' && data[7] == ' ')
316
190
      return HttpRequestLayer::HttpOPTIONS;
317
2.12k
    else
318
2.12k
      return HttpRequestLayer::HttpMethodUnknown;
319
0
    break;
320
321
17.4k
  case 'P':
322
17.4k
    switch (data[1])
323
17.4k
    {
324
13.4k
    case 'U':
325
13.4k
      if (data[2] == 'T' && data[3] == ' ')
326
12.6k
        return HttpRequestLayer::HttpPUT;
327
833
      else
328
833
        return HttpRequestLayer::HttpMethodUnknown;
329
0
      break;
330
331
729
    case 'O':
332
729
      if (dataLen < 5)
333
206
        return HttpRequestLayer::HttpMethodUnknown;
334
523
      else if (data[2] == 'S' && data[3] == 'T' && data[4] == ' ')
335
14
        return HttpRequestLayer::HttpPOST;
336
509
      else
337
509
        return HttpRequestLayer::HttpMethodUnknown;
338
0
      break;
339
340
2.92k
    case 'A':
341
2.92k
      if (dataLen < 6)
342
194
        return HttpRequestLayer::HttpMethodUnknown;
343
2.73k
      else if (data[2] == 'T' && data[3] == 'C' && data[4] == 'H' && data[5] == ' ')
344
554
        return HttpRequestLayer::HttpPATCH;
345
2.17k
      else
346
2.17k
        return HttpRequestLayer::HttpMethodUnknown;
347
0
      break;
348
349
348
    default:
350
348
      return HttpRequestLayer::HttpMethodUnknown;
351
17.4k
    }
352
0
    break;
353
354
1.66k
  default:
355
1.66k
    return HttpRequestLayer::HttpMethodUnknown;
356
33.8k
  }
357
33.8k
}
358
359
void HttpRequestFirstLine::parseVersion()
360
7.55k
{
361
7.55k
  char* data = (char*)(m_HttpRequest->m_Data + m_UriOffset);
362
7.55k
  char* verPos = cross_platform_memmem(data, m_HttpRequest->getDataLen() - m_UriOffset, " HTTP/", 6);
363
7.55k
  if (verPos == NULL)
364
2.11k
  {
365
2.11k
    m_Version = HttpVersionUnknown;
366
2.11k
    m_VersionOffset = -1;
367
2.11k
    return;
368
2.11k
  }
369
370
  // verify packet doesn't end before the version, meaning still left place for " HTTP/x.y" (9 chars)
371
5.44k
  if ((verPos + 9 - (char*)m_HttpRequest->m_Data) > m_HttpRequest->getDataLen())
372
383
  {
373
383
    m_Version = HttpVersionUnknown;
374
383
    m_VersionOffset = -1;
375
383
    return;
376
383
  }
377
378
  //skip " HTTP/" (6 chars)
379
5.05k
  verPos += 6;
380
5.05k
  switch (verPos[0])
381
5.05k
  {
382
1.22k
  case '0':
383
1.22k
    if (verPos[1] == '.' && verPos[2] == '9')
384
11
      m_Version = ZeroDotNine;
385
1.21k
    else
386
1.21k
      m_Version = HttpVersionUnknown;
387
1.22k
    break;
388
389
2.77k
  case '1':
390
2.77k
    if (verPos[1] == '.' && verPos[2] == '0')
391
67
      m_Version = OneDotZero;
392
2.71k
    else if (verPos[1] == '.' && verPos[2] == '1')
393
1.55k
      m_Version = OneDotOne;
394
1.15k
    else
395
1.15k
      m_Version = HttpVersionUnknown;
396
2.77k
    break;
397
398
1.06k
  default:
399
1.06k
    m_Version = HttpVersionUnknown;
400
5.05k
  }
401
402
5.05k
  m_VersionOffset = verPos - (char*)m_HttpRequest->m_Data;
403
5.05k
}
404
405
bool HttpRequestFirstLine::setMethod(HttpRequestLayer::HttpMethod newMethod)
406
0
{
407
0
  if (newMethod == HttpRequestLayer::HttpMethodUnknown)
408
0
  {
409
0
    PCPP_LOG_ERROR("Requested method is HttpMethodUnknown");
410
0
    return false;
411
0
  }
412
413
  //extend or shorten layer
414
0
  int lengthDifference = MethodEnumToString[newMethod].length() - MethodEnumToString[m_Method].length();
415
0
  if (lengthDifference > 0)
416
0
  {
417
0
    if (!m_HttpRequest->extendLayer(0, lengthDifference))
418
0
    {
419
0
      PCPP_LOG_ERROR("Cannot change layer size");
420
0
      return false;
421
0
    }
422
0
  }
423
0
  else if (lengthDifference < 0)
424
0
  {
425
0
    if (!m_HttpRequest->shortenLayer(0, 0-lengthDifference))
426
0
    {
427
0
      PCPP_LOG_ERROR("Cannot change layer size");
428
0
      return false;
429
430
0
    }
431
0
  }
432
433
0
  if (lengthDifference != 0)
434
0
    m_HttpRequest->shiftFieldsOffset(m_HttpRequest->getFirstField(), lengthDifference);
435
436
0
  memcpy(m_HttpRequest->m_Data, MethodEnumToString[newMethod].c_str(), MethodEnumToString[newMethod].length());
437
438
0
  m_Method = newMethod;
439
0
  m_UriOffset += lengthDifference;
440
0
  m_VersionOffset += lengthDifference;
441
442
0
  return true;
443
0
}
444
445
std::string HttpRequestFirstLine::getUri() const
446
0
{
447
0
  std::string result;
448
0
  if (m_UriOffset != -1 && m_VersionOffset != -1)
449
0
    result.assign((const char*)m_HttpRequest->m_Data + m_UriOffset, m_VersionOffset - 6 - m_UriOffset);
450
451
  //else first line is illegal, return empty string
452
453
0
  return result;
454
0
}
455
456
bool HttpRequestFirstLine::setUri(std::string newUri)
457
0
{
458
  // make sure the new URI begins with "/"
459
0
  if (newUri.compare(0, 1, "/") != 0)
460
0
    newUri = "/" + newUri;
461
462
  //extend or shorten layer
463
0
  std::string currentUri = getUri();
464
0
  int lengthDifference = newUri.length() - currentUri.length();
465
0
  if (lengthDifference > 0)
466
0
  {
467
0
    if (!m_HttpRequest->extendLayer(m_UriOffset, lengthDifference))
468
0
    {
469
0
      PCPP_LOG_ERROR("Cannot change layer size");
470
0
      return false;
471
0
    }
472
0
  }
473
0
  else if (lengthDifference < 0)
474
0
  {
475
0
    if (!m_HttpRequest->shortenLayer(m_UriOffset, 0-lengthDifference))
476
0
    {
477
0
      PCPP_LOG_ERROR("Cannot change layer size");
478
0
      return false;
479
0
    }
480
0
  }
481
482
0
  if (lengthDifference != 0)
483
0
    m_HttpRequest->shiftFieldsOffset(m_HttpRequest->getFirstField(), lengthDifference);
484
485
0
  memcpy(m_HttpRequest->m_Data + m_UriOffset, newUri.c_str(), newUri.length());
486
487
0
  m_VersionOffset += lengthDifference;
488
489
0
  return true;
490
0
}
491
492
void HttpRequestFirstLine::setVersion(HttpVersion newVersion)
493
0
{
494
0
  if (m_VersionOffset == -1)
495
0
    return;
496
497
0
  if (newVersion == HttpVersionUnknown)
498
0
    return;
499
500
0
  char* verPos = (char*)(m_HttpRequest->m_Data + m_VersionOffset);
501
0
  memcpy(verPos, VersionEnumToString[newVersion].c_str(), 3);
502
503
0
  m_Version = newVersion;
504
0
}
505
506
507
508
509
510
511
// -------- Class HttpResponseLayer -----------------
512
513
514
515
const std::string StatusCodeEnumToString[80] = {
516
    "Continue",
517
    "Switching Protocols",
518
    "Processing",
519
    "OK",
520
    "Created",
521
    "Accepted",
522
    "Non-Authoritative Information",
523
    "No Content",
524
    "Reset Content",
525
    "Partial Content",
526
    "Multi-Status",
527
    "Already Reported",
528
    "IM Used",
529
    "Multiple Choices",
530
    "Moved Permanently",
531
    "Found",
532
    "See Other",
533
    "Not Modified",
534
    "Use Proxy",
535
    "Switch Proxy",
536
    "Temporary Redirect",
537
    "Permanent Redirect",
538
    "Bad Request",
539
    "Unauthorized",
540
    "Payment Required",
541
    "Forbidden",
542
    "Not Found",
543
    "Method Not Allowed",
544
    "Not Acceptable",
545
    "Proxy Authentication Required",
546
    "Request Timeout",
547
    "Conflict",
548
    "Gone",
549
    "Length Required",
550
    "Precondition Failed",
551
    "Request Entity Too Large",
552
    "Request-URI Too Long",
553
    "Unsupported Media Type",
554
    "Requested Range Not Satisfiable",
555
    "Expectation Failed",
556
    "I'm a teapot",
557
    "Authentication Timeout",
558
    "Method Failure",
559
    "Unprocessable Entity",
560
    "Locked",
561
    "Failed Dependency",
562
    "Upgrade Required",
563
    "Precondition Required",
564
    "Too Many Requests",
565
    "Request Header Fields Too Large",
566
    "Login Timeout",
567
    "No Response",
568
    "Retry With",
569
    "Blocked by Windows Parental Controls",
570
    "Unavailable For Legal Reasons",
571
    "Request Header Too Large",
572
    "Cert Error",
573
    "No Cert",
574
    "HTTP to HTTPS",
575
    "Token expired/invalid",
576
    "Client Closed Request",
577
    "Internal Server Error",
578
    "Not Implemented",
579
    "Bad Gateway",
580
    "Service Unavailable",
581
    "Gateway Timeout",
582
    "HTTP Version Not Supported",
583
    "Variant Also Negotiates",
584
    "Insufficient Storage",
585
    "Loop Detected",
586
    "Bandwidth Limit Exceeded",
587
    "Not Extended",
588
    "Network Authentication Required",
589
    "Origin Error",
590
    "Web server is down",
591
    "Connection timed out",
592
    "Proxy Declined Request",
593
    "A timeout occurred",
594
    "Network read timeout error",
595
    "Network connect timeout error"
596
};
597
598
599
const int StatusCodeEnumToInt[80] = {
600
    100,
601
    101,
602
    102,
603
    200,
604
    201,
605
    202,
606
    203,
607
    204,
608
    205,
609
    206,
610
    207,
611
    208,
612
    226,
613
    300,
614
    301,
615
    302,
616
    303,
617
    304,
618
    305,
619
    306,
620
    307,
621
    308,
622
    400,
623
    401,
624
    402,
625
    403,
626
    404,
627
    405,
628
    406,
629
    407,
630
    408,
631
    409,
632
    410,
633
    411,
634
    412,
635
    413,
636
    414,
637
    415,
638
    416,
639
    417,
640
    418,
641
    419,
642
    420,
643
    422,
644
    423,
645
    424,
646
    426,
647
    428,
648
    429,
649
    431,
650
    440,
651
    444,
652
    449,
653
    450,
654
    451,
655
    494,
656
    495,
657
    496,
658
    497,
659
    498,
660
    499,
661
    500,
662
    501,
663
    502,
664
    503,
665
    504,
666
    505,
667
    506,
668
    507,
669
    508,
670
    509,
671
    510,
672
    511,
673
    520,
674
    521,
675
    522,
676
    523,
677
    524,
678
    598,
679
    599
680
};
681
682
683
684
HttpResponseLayer::HttpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet)  : HttpMessage(data, dataLen, prevLayer, packet)
685
13.3k
{
686
13.3k
  m_Protocol = HTTPResponse;
687
13.3k
  m_FirstLine = new HttpResponseFirstLine(this);
688
13.3k
  m_FieldsOffset = m_FirstLine->getSize();
689
13.3k
  parseFields();
690
13.3k
}
691
692
HttpResponseLayer::HttpResponseLayer(HttpVersion version, HttpResponseLayer::HttpResponseStatusCode statusCode, std::string statusCodeString)
693
0
{
694
0
  m_Protocol = HTTPResponse;
695
0
  m_FirstLine = new HttpResponseFirstLine(this, version, statusCode, statusCodeString);
696
0
  m_FieldsOffset = m_FirstLine->getSize();
697
0
}
698
699
HttpResponseLayer::~HttpResponseLayer()
700
13.3k
{
701
13.3k
  delete m_FirstLine;
702
13.3k
}
703
704
705
HttpResponseLayer::HttpResponseLayer(const HttpResponseLayer& other) : HttpMessage(other)
706
0
{
707
0
  m_FirstLine = new HttpResponseFirstLine(this);
708
0
}
709
710
HttpResponseLayer& HttpResponseLayer::operator=(const HttpResponseLayer& other)
711
0
{
712
0
  HttpMessage::operator=(other);
713
714
0
  if (m_FirstLine != NULL)
715
0
    delete m_FirstLine;
716
717
0
  m_FirstLine = new HttpResponseFirstLine(this);
718
719
0
  return *this;
720
0
}
721
722
723
HeaderField* HttpResponseLayer::setContentLength(int contentLength, const std::string &prevFieldName)
724
0
{
725
0
  std::ostringstream contentLengthAsString;
726
0
  contentLengthAsString << contentLength;
727
0
  std::string contentLengthFieldName(PCPP_HTTP_CONTENT_LENGTH_FIELD);
728
0
  HeaderField* contentLengthField = getFieldByName(contentLengthFieldName);
729
0
  if (contentLengthField == NULL)
730
0
  {
731
0
    HeaderField* prevField = getFieldByName(prevFieldName);
732
0
    contentLengthField = insertField(prevField, PCPP_HTTP_CONTENT_LENGTH_FIELD, contentLengthAsString.str());
733
0
  }
734
0
  else
735
0
    contentLengthField->setFieldValue(contentLengthAsString.str());
736
737
0
  return contentLengthField;
738
0
}
739
740
int HttpResponseLayer::getContentLength() const
741
0
{
742
0
  std::string contentLengthFieldName(PCPP_HTTP_CONTENT_LENGTH_FIELD);
743
0
  std::transform(contentLengthFieldName.begin(), contentLengthFieldName.end(), contentLengthFieldName.begin(), ::tolower);
744
0
  HeaderField* contentLengthField = getFieldByName(contentLengthFieldName);
745
0
  if (contentLengthField != NULL)
746
0
    return atoi(contentLengthField->getFieldValue().c_str());
747
0
  return 0;
748
0
}
749
750
std::string HttpResponseLayer::toString() const
751
0
{
752
0
  static const int maxLengthToPrint = 120;
753
0
  std::string result = "HTTP response, ";
754
0
  int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line
755
0
  if (size <= maxLengthToPrint)
756
0
  {
757
0
    char* firstLine = new char[size+1];
758
0
    strncpy(firstLine, (char*)m_Data, size);
759
0
    firstLine[size] = 0;
760
0
    result += std::string(firstLine);
761
0
    delete[] firstLine;
762
0
  }
763
0
  else
764
0
  {
765
0
    char firstLine[maxLengthToPrint+1];
766
0
    strncpy(firstLine, (char*)m_Data, maxLengthToPrint-3);
767
0
    firstLine[maxLengthToPrint-3] = '.';
768
0
    firstLine[maxLengthToPrint-2] = '.';
769
0
    firstLine[maxLengthToPrint-1] = '.';
770
0
    firstLine[maxLengthToPrint] = 0;
771
0
    result += std::string(firstLine);
772
0
  }
773
774
0
  return result;
775
0
}
776
777
778
779
780
781
782
783
784
// -------- Class HttpResponseFirstLine -----------------
785
786
787
788
int HttpResponseFirstLine::getStatusCodeAsInt() const
789
0
{
790
0
  return StatusCodeEnumToInt[m_StatusCode];
791
0
}
792
793
std::string HttpResponseFirstLine::getStatusCodeString() const
794
0
{
795
0
  std::string result;
796
0
  const int statusStringOffset = 13;
797
0
  if (m_StatusCode != HttpResponseLayer::HttpStatusCodeUnknown)
798
0
  {
799
0
    int statusStringEndOffset = m_FirstLineEndOffset - 2;
800
0
    if ((*(m_HttpResponse->m_Data + statusStringEndOffset)) != '\r')
801
0
      statusStringEndOffset++;
802
0
    result.assign((char*)(m_HttpResponse->m_Data + statusStringOffset), statusStringEndOffset-statusStringOffset);
803
0
  }
804
805
  //else first line is illegal, return empty string
806
807
0
  return result;
808
0
}
809
810
bool HttpResponseFirstLine::setStatusCode(HttpResponseLayer::HttpResponseStatusCode newStatusCode, std::string statusCodeString)
811
0
{
812
0
  if (newStatusCode == HttpResponseLayer::HttpStatusCodeUnknown)
813
0
  {
814
0
    PCPP_LOG_ERROR("Requested status code is HttpStatusCodeUnknown");
815
0
    return false;
816
0
  }
817
818
  //extend or shorten layer
819
820
0
  size_t statusStringOffset = 13;
821
0
  if (statusCodeString == "")
822
0
    statusCodeString = StatusCodeEnumToString[newStatusCode];
823
0
  int lengthDifference = statusCodeString.length() - getStatusCodeString().length();
824
0
  if (lengthDifference > 0)
825
0
  {
826
0
    if (!m_HttpResponse->extendLayer(statusStringOffset, lengthDifference))
827
0
    {
828
0
      PCPP_LOG_ERROR("Cannot change layer size");
829
0
      return false;
830
0
    }
831
0
  }
832
0
  else if (lengthDifference < 0)
833
0
  {
834
0
    if (!m_HttpResponse->shortenLayer(statusStringOffset, 0-lengthDifference))
835
0
    {
836
0
      PCPP_LOG_ERROR("Cannot change layer size");
837
0
      return false;
838
839
0
    }
840
0
  }
841
842
0
  if (lengthDifference != 0)
843
0
    m_HttpResponse->shiftFieldsOffset(m_HttpResponse->getFirstField(), lengthDifference);
844
845
  // copy status string
846
0
  memcpy(m_HttpResponse->m_Data+statusStringOffset, statusCodeString.c_str(), statusCodeString.length());
847
848
  // change status code
849
0
  std::ostringstream statusCodeAsString;
850
0
  statusCodeAsString << StatusCodeEnumToInt[newStatusCode];
851
0
  memcpy(m_HttpResponse->m_Data+9, statusCodeAsString.str().c_str(), 3);
852
853
0
  m_StatusCode = newStatusCode;
854
855
0
  m_FirstLineEndOffset += lengthDifference;
856
857
0
  return true;
858
859
0
}
860
861
void HttpResponseFirstLine::setVersion(HttpVersion newVersion)
862
0
{
863
0
  if (newVersion == HttpVersionUnknown)
864
0
    return;
865
866
0
  char* verPos = (char*)(m_HttpResponse->m_Data + 5);
867
0
  memcpy(verPos, VersionEnumToString[newVersion].c_str(), 3);
868
869
0
  m_Version = newVersion;
870
0
}
871
872
HttpResponseLayer::HttpResponseStatusCode HttpResponseFirstLine::validateStatusCode(char* data, size_t dataLen, HttpResponseLayer::HttpResponseStatusCode potentialCode)
873
67.3k
{
874
67.3k
  if (dataLen < 1 || data[0] != ' ')
875
40.6k
    return HttpResponseLayer::HttpStatusCodeUnknown;
876
877
26.7k
  return potentialCode;
878
67.3k
}
879
880
HttpResponseLayer::HttpResponseStatusCode HttpResponseFirstLine::parseStatusCode(char* data, size_t dataLen)
881
97.9k
{
882
97.9k
  if (parseVersion(data, dataLen) == HttpVersionUnknown)
883
17.8k
    return HttpResponseLayer::HttpStatusCodeUnknown;
884
885
  // minimum data should be 12B long: "HTTP/x.y XXX"
886
80.0k
  if (dataLen < 12)
887
219
    return HttpResponseLayer::HttpStatusCodeUnknown;
888
889
79.8k
  char* statusCodeData = data + 9;
890
79.8k
  size_t statusCodeDataLen = dataLen - 9;
891
892
79.8k
  switch (statusCodeData[0])
893
79.8k
  {
894
3.30k
  case '1':
895
3.30k
    switch (statusCodeData[1])
896
3.30k
    {
897
1.83k
    case '0':
898
1.83k
      switch (statusCodeData[2])
899
1.83k
      {
900
241
      case '0':
901
241
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http100Continue);
902
862
      case '1':
903
862
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http101SwitchingProtocols);
904
660
      case '2':
905
660
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http102Processing);
906
74
      default:
907
74
        return HttpResponseLayer::HttpStatusCodeUnknown;
908
1.83k
      };
909
910
0
      break;
911
912
1.46k
    default:
913
1.46k
      return HttpResponseLayer::HttpStatusCodeUnknown;
914
3.30k
    };
915
916
0
    break;
917
6.66k
  case '2':
918
6.66k
    switch (statusCodeData[1])
919
6.66k
    {
920
5.34k
    case '0':
921
5.34k
      switch (statusCodeData[2])
922
5.34k
      {
923
258
      case '0':
924
258
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http200OK);
925
780
      case '1':
926
780
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http201Created);
927
704
      case '2':
928
704
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http202Accepted);
929
738
      case '3':
930
738
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http203NonAuthoritativeInformation);
931
378
      case '4':
932
378
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http204NoContent);
933
823
      case '5':
934
823
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http205ResetContent);
935
511
      case '6':
936
511
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http206PartialContent);
937
536
      case '7':
938
536
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http207MultiStatus);
939
541
      case '8':
940
541
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http208AlreadyReported);
941
76
      default:
942
76
        return HttpResponseLayer::HttpStatusCodeUnknown;
943
944
5.34k
      };
945
946
0
      break;
947
1.06k
    case '2':
948
1.06k
      switch (statusCodeData[2])
949
1.06k
      {
950
832
      case '6':
951
832
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http226IMUsed);
952
231
      default:
953
231
        return HttpResponseLayer::HttpStatusCodeUnknown;
954
1.06k
      };
955
956
0
      break;
957
958
260
    default:
959
260
      return HttpResponseLayer::HttpStatusCodeUnknown;
960
961
6.66k
    };
962
963
0
    break;
964
965
8.96k
  case '3':
966
8.96k
    switch (statusCodeData[1])
967
8.96k
    {
968
8.32k
    case '0':
969
8.32k
      switch (statusCodeData[2])
970
8.32k
      {
971
854
      case '0':
972
854
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http300MultipleChoices);
973
815
      case '1':
974
815
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http301MovedPermanently);
975
741
      case '2':
976
741
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http302);
977
1.22k
      case '3':
978
1.22k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http303SeeOther);
979
394
      case '4':
980
394
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http304NotModified);
981
1.90k
      case '5':
982
1.90k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http305UseProxy);
983
894
      case '6':
984
894
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http306SwitchProxy);
985
770
      case '7':
986
770
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http307TemporaryRedirect);
987
466
      case '8':
988
466
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http308PermanentRedirect);
989
255
      default:
990
255
        return HttpResponseLayer::HttpStatusCodeUnknown;
991
992
8.32k
      };
993
994
0
      break;
995
996
638
    default:
997
638
      return HttpResponseLayer::HttpStatusCodeUnknown;
998
8.96k
    };
999
1000
0
    break;
1001
1002
36.6k
  case '4':
1003
36.6k
    switch (statusCodeData[1])
1004
36.6k
    {
1005
9.71k
    case '0':
1006
9.71k
      switch (statusCodeData[2])
1007
9.71k
      {
1008
750
      case '0':
1009
750
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http400BadRequest);
1010
538
      case '1':
1011
538
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http401Unauthorized);
1012
1.41k
      case '2':
1013
1.41k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http402PaymentRequired);
1014
596
      case '3':
1015
596
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http403Forbidden);
1016
1.70k
      case '4':
1017
1.70k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http404NotFound);
1018
820
      case '5':
1019
820
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http405MethodNotAllowed);
1020
676
      case '6':
1021
676
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http406NotAcceptable);
1022
968
      case '7':
1023
968
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http407ProxyAuthenticationRequired);
1024
984
      case '8':
1025
984
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http408RequestTimeout);
1026
745
      case '9':
1027
745
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http409Conflict);
1028
511
      default:
1029
511
        return HttpResponseLayer::HttpStatusCodeUnknown;
1030
1031
9.71k
      };
1032
1033
0
      break;
1034
1035
9.54k
    case '1':
1036
9.54k
      switch (statusCodeData[2])
1037
9.54k
      {
1038
901
      case '0':
1039
901
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http410Gone);
1040
827
      case '1':
1041
827
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http411LengthRequired);
1042
919
      case '2':
1043
919
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http412PreconditionFailed);
1044
848
      case '3':
1045
848
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http413RequestEntityTooLarge);
1046
1.55k
      case '4':
1047
1.55k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http414RequestURITooLong);
1048
551
      case '5':
1049
551
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http415UnsupportedMediaType);
1050
199
      case '6':
1051
199
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http416RequestedRangeNotSatisfiable);
1052
722
      case '7':
1053
722
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http417ExpectationFailed);
1054
930
      case '8':
1055
930
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http418Imateapot);
1056
1.65k
      case '9':
1057
1.65k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http419AuthenticationTimeout);
1058
429
      default:
1059
429
        return HttpResponseLayer::HttpStatusCodeUnknown;
1060
1061
9.54k
      };
1062
1063
0
      break;
1064
1065
4.87k
    case '2':
1066
4.87k
      switch (statusCodeData[2])
1067
4.87k
      {
1068
605
      case '0':
1069
605
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http420);
1070
593
      case '2':
1071
593
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http422UnprocessableEntity);
1072
450
      case '3':
1073
450
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http423Locked);
1074
624
      case '4':
1075
624
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http424FailedDependency);
1076
961
      case '6':
1077
961
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http426UpgradeRequired);
1078
548
      case '8':
1079
548
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http428PreconditionRequired);
1080
598
      case '9':
1081
598
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http429TooManyRequests);
1082
500
      default:
1083
500
        return HttpResponseLayer::HttpStatusCodeUnknown;
1084
1085
4.87k
      };
1086
1087
0
      break;
1088
1089
1.87k
    case '3':
1090
1.87k
      return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http431RequestHeaderFieldsTooLarge);
1091
1092
3.30k
    case '4':
1093
3.30k
      switch (statusCodeData[2])
1094
3.30k
      {
1095
661
      case '0':
1096
661
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http440LoginTimeout);
1097
1.63k
      case '4':
1098
1.63k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http444NoResponse);
1099
552
      case '9':
1100
552
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http449RetryWith);
1101
457
      default:
1102
457
        return HttpResponseLayer::HttpStatusCodeUnknown;
1103
3.30k
      };
1104
1105
0
      break;
1106
1107
1.85k
    case '5':
1108
1.85k
      switch (statusCodeData[2])
1109
1.85k
      {
1110
703
      case '0':
1111
703
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http450BlockedByWindowsParentalControls);
1112
603
      case '1':
1113
603
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http451);
1114
544
      default:
1115
544
        return HttpResponseLayer::HttpStatusCodeUnknown;
1116
1.85k
      };
1117
1118
0
      break;
1119
1120
4.51k
    case '9':
1121
4.51k
      switch (statusCodeData[2])
1122
4.51k
      {
1123
478
      case '4':
1124
478
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http494RequestHeaderTooLarge);
1125
475
      case '5':
1126
475
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http495CertError);
1127
499
      case '6':
1128
499
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http496NoCert);
1129
350
      case '7':
1130
350
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http497HTTPtoHTTPS);
1131
1.07k
      case '8':
1132
1.07k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http498TokenExpiredInvalid);
1133
1.04k
      case '9':
1134
1.04k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http499);
1135
589
      default:
1136
589
        return HttpResponseLayer::HttpStatusCodeUnknown;
1137
4.51k
      };
1138
1139
0
      break;
1140
1141
1.01k
    default:
1142
1.01k
      return HttpResponseLayer::HttpStatusCodeUnknown;
1143
36.6k
    };
1144
1145
0
    break;
1146
1147
22.1k
  case '5':
1148
22.1k
    switch (statusCodeData[1])
1149
22.1k
    {
1150
12.1k
    case '0':
1151
12.1k
      switch (statusCodeData[2])
1152
12.1k
      {
1153
502
      case '0':
1154
502
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http500InternalServerError);
1155
1.29k
      case '1':
1156
1.29k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http501NotImplemented);
1157
167
      case '2':
1158
167
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http502BadGateway);
1159
1.16k
      case '3':
1160
1.16k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http503ServiceUnavailable);
1161
757
      case '4':
1162
757
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http504GatewayTimeout);
1163
1.47k
      case '5':
1164
1.47k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http505HTTPVersionNotSupported);
1165
785
      case '6':
1166
785
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http506VariantAlsoNegotiates);
1167
853
      case '7':
1168
853
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http507InsufficientStorage);
1169
507
      case '8':
1170
507
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http508LoopDetected);
1171
4.04k
      case '9':
1172
4.04k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http509BandwidthLimitExceeded);
1173
576
      default:
1174
576
        return HttpResponseLayer::HttpStatusCodeUnknown;
1175
1176
12.1k
      };
1177
1178
0
      break;
1179
1180
2.48k
    case '1':
1181
2.48k
      switch (statusCodeData[2])
1182
2.48k
      {
1183
650
      case '0':
1184
650
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http510NotExtended);
1185
1.50k
      case '1':
1186
1.50k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http511NetworkAuthenticationRequired);
1187
332
      default:
1188
332
        return HttpResponseLayer::HttpStatusCodeUnknown;
1189
2.48k
      };
1190
1191
0
      break;
1192
1193
3.66k
    case '2':
1194
3.66k
      switch (statusCodeData[2])
1195
3.66k
      {
1196
489
      case '0':
1197
489
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http520OriginError);
1198
673
      case '1':
1199
673
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http521WebServerIsDown);
1200
585
      case '2':
1201
585
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http522ConnectionTimedOut);
1202
410
      case '3':
1203
410
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http523ProxyDeclinedRequest);
1204
952
      case '4':
1205
952
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http524aTimeoutOccurred);
1206
558
      default:
1207
558
        return HttpResponseLayer::HttpStatusCodeUnknown;
1208
3.66k
      };
1209
1210
0
      break;
1211
1212
2.65k
    case '9':
1213
2.65k
      switch (statusCodeData[2])
1214
2.65k
      {
1215
1.42k
      case '8':
1216
1.42k
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http598NetworkReadTimeoutError);
1217
585
      case '9':
1218
585
        return validateStatusCode(statusCodeData+3, statusCodeDataLen-3, HttpResponseLayer::Http599NetworkConnectTimeoutError);
1219
648
      default:
1220
648
        return HttpResponseLayer::HttpStatusCodeUnknown;
1221
2.65k
      };
1222
1223
0
      break;
1224
1225
1.19k
    default:
1226
1.19k
      return HttpResponseLayer::HttpStatusCodeUnknown;
1227
22.1k
    };
1228
1229
0
    break;
1230
1231
2.12k
  default:
1232
2.12k
    return HttpResponseLayer::HttpStatusCodeUnknown;
1233
79.8k
  }
1234
1235
0
  return HttpResponseLayer::HttpStatusCodeUnknown;
1236
79.8k
}
1237
1238
HttpResponseFirstLine::HttpResponseFirstLine(HttpResponseLayer* httpResponse) : m_HttpResponse(httpResponse)
1239
13.3k
{
1240
13.3k
  m_Version = parseVersion((char*)m_HttpResponse->m_Data, m_HttpResponse->getDataLen());
1241
13.3k
  if (m_Version == HttpVersionUnknown)
1242
0
  {
1243
0
    m_StatusCode = HttpResponseLayer::HttpStatusCodeUnknown;
1244
0
  }
1245
13.3k
  else
1246
13.3k
  {
1247
13.3k
    m_StatusCode = parseStatusCode((char*)m_HttpResponse->m_Data, m_HttpResponse->getDataLen());
1248
13.3k
  }
1249
1250
1251
13.3k
  char* endOfFirstLine;
1252
13.3k
  if ((endOfFirstLine = (char*)memchr((char*)(m_HttpResponse->m_Data), '\n', m_HttpResponse->m_DataLen)) != NULL)
1253
2.87k
  {
1254
2.87k
    m_FirstLineEndOffset = endOfFirstLine - (char*)m_HttpResponse->m_Data + 1;
1255
2.87k
    m_IsComplete = true;
1256
2.87k
  }
1257
10.5k
  else
1258
10.5k
  {
1259
10.5k
    m_FirstLineEndOffset = m_HttpResponse->getDataLen();
1260
10.5k
    m_IsComplete = false;
1261
10.5k
  }
1262
1263
13.3k
  if (Logger::getInstance().isDebugEnabled(PacketLogModuleHttpLayer))
1264
0
  {
1265
0
    std::string version = (m_Version == HttpVersionUnknown ? "Unknown" : VersionEnumToString[m_Version]);
1266
0
    int statusCode = (m_StatusCode == HttpResponseLayer::HttpStatusCodeUnknown ? 0 : StatusCodeEnumToInt[m_StatusCode]);
1267
0
    PCPP_LOG_DEBUG("Version='" << version << "'; Status code=" << statusCode << " '" << getStatusCodeString() << "'");
1268
0
  }
1269
13.3k
}
1270
1271
1272
HttpResponseFirstLine::HttpResponseFirstLine(HttpResponseLayer* httpResponse,  HttpVersion version, HttpResponseLayer::HttpResponseStatusCode statusCode, std::string statusCodeString)
1273
0
{
1274
0
  if (statusCode == HttpResponseLayer::HttpStatusCodeUnknown)
1275
0
  {
1276
0
    m_Exception.setMessage("Status code supplied was HttpStatusCodeUnknown");
1277
0
    throw m_Exception;
1278
0
  }
1279
1280
0
  if (version == HttpVersionUnknown)
1281
0
  {
1282
0
    m_Exception.setMessage("Version supplied was HttpVersionUnknown");
1283
0
    throw m_Exception;
1284
0
  }
1285
1286
0
  m_HttpResponse = httpResponse;
1287
1288
0
  m_StatusCode = statusCode;
1289
0
  m_Version = version;
1290
1291
0
  std::ostringstream statusCodeAsString;
1292
0
  statusCodeAsString << StatusCodeEnumToInt[m_StatusCode];
1293
0
  if (statusCodeString == "")
1294
0
    statusCodeString = StatusCodeEnumToString[m_StatusCode];
1295
0
  std::string firstLine = "HTTP/" + VersionEnumToString[m_Version] + " " + statusCodeAsString.str() + " " +  statusCodeString +  "\r\n";
1296
1297
0
  m_FirstLineEndOffset = firstLine.length();
1298
1299
0
  m_HttpResponse->m_DataLen = firstLine.length();
1300
0
  m_HttpResponse->m_Data = new uint8_t[m_HttpResponse->m_DataLen];
1301
0
  memcpy(m_HttpResponse->m_Data, firstLine.c_str(), m_HttpResponse->m_DataLen);
1302
1303
0
  m_IsComplete = true;
1304
0
}
1305
1306
HttpVersion HttpResponseFirstLine::parseVersion(char* data, size_t dataLen)
1307
111k
{
1308
111k
  if (dataLen < 8) // "HTTP/x.y"
1309
362
  {
1310
362
    PCPP_LOG_DEBUG("HTTP response length < 8, cannot identify version");
1311
362
    return HttpVersionUnknown;
1312
362
  }
1313
1314
110k
  if (data[0] != 'H' || data[1] != 'T' || data[2] != 'T' || data[3] != 'P' || data[4] != '/')
1315
11.3k
  {
1316
11.3k
    PCPP_LOG_DEBUG("HTTP response does not begin with 'HTTP/'");
1317
11.3k
    return HttpVersionUnknown;
1318
11.3k
  }
1319
1320
99.5k
  char* verPos = data + 5;
1321
99.5k
  switch (verPos[0])
1322
99.5k
  {
1323
22.8k
  case '0':
1324
22.8k
    if (verPos[1] == '.' && verPos[2] == '9')
1325
20.6k
      return ZeroDotNine;
1326
2.11k
    else
1327
2.11k
      return HttpVersionUnknown;
1328
0
    break;
1329
1330
75.5k
  case '1':
1331
75.5k
    if (verPos[1] == '.' && verPos[2] == '0')
1332
57.2k
      return OneDotZero;
1333
18.2k
    else if (verPos[1] == '.' && verPos[2] == '1')
1334
15.4k
      return OneDotOne;
1335
2.81k
    else
1336
2.81k
      return HttpVersionUnknown;
1337
0
    break;
1338
1339
1.21k
  default:
1340
1.21k
    return HttpVersionUnknown;
1341
99.5k
  }
1342
99.5k
}
1343
1344
} // namespace pcpp