You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
4.6 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. /*
  2. * Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  18. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #include <stdio.h>
  30. #include <stdlib.h> /* malloc() */
  31. #include <string.h> /* strncpy() */
  32. #include <strings.h> /* strncasecmp() */
  33. #include <ctype.h> /* isblank() */
  34. #include "http.h"
  35. #include "protocol.h"
  36. #define SERVER_NAME_LEN 256
  37. static int parse_http_header(const char *, size_t, char **);
  38. static int get_header(const char *, const char *, int, char **);
  39. static int next_header(const char **, int *);
  40. static const protocol_t http_protocol_st = {
  41. .default_port = 80,
  42. .parse_packet = &parse_http_header,
  43. };
  44. const protocol_t *const http_protocol = &http_protocol_st;
  45. /*
  46. * Parses a HTTP request for the Host: header
  47. *
  48. * Returns:
  49. * >=0 - length of the hostname and updates *hostname
  50. * caller is responsible for freeing *hostname
  51. * -1 - Incomplete request
  52. * -2 - No Host header included in this request
  53. * -3 - Invalid hostname pointer
  54. * -4 - malloc failure
  55. * < -4 - Invalid HTTP request
  56. *
  57. */
  58. static int
  59. parse_http_header(const char *data, size_t data_len, char **hostname)
  60. {
  61. int result, i;
  62. if (hostname == NULL)
  63. return -3;
  64. if (data_len == 0)
  65. return -1;
  66. result = get_header("Host:", data, data_len, hostname);
  67. if (result < 0)
  68. return result;
  69. /*
  70. * if the user specifies the port in the request, it is included here.
  71. * Host: example.com:80
  72. * so we trim off port portion
  73. */
  74. for (i = result - 1; i >= 0; i--)
  75. if ((*hostname)[i] == ':') {
  76. (*hostname)[i] = '\0';
  77. result = i;
  78. break;
  79. }
  80. return result;
  81. }
  82. static int
  83. get_header(const char *header, const char *data, int data_len, char **value)
  84. {
  85. int len, header_len;
  86. header_len = strlen(header);
  87. /* loop through headers stopping at first blank line */
  88. while ((len = next_header(&data, &data_len)) != 0)
  89. if (len > header_len && strncasecmp(header, data, header_len) == 0) {
  90. /* Eat leading whitespace */
  91. while (header_len < len && isblank((unsigned char)data[header_len]))
  92. header_len++;
  93. *value = malloc(len - header_len + 1);
  94. if (*value == NULL)
  95. return -4;
  96. strncpy(*value, data + header_len, len - header_len);
  97. (*value)[len - header_len] = '\0';
  98. return len - header_len;
  99. }
  100. /* If there is no data left after reading all the headers then we do not
  101. * have a complete HTTP request, there must be a blank line */
  102. if (data_len == 0)
  103. return -1;
  104. return -2;
  105. }
  106. static int
  107. next_header(const char **data, int *len)
  108. {
  109. int header_len;
  110. /* perhaps we can optimize this to reuse the value of header_len, rather
  111. * than scanning twice.
  112. * Walk our data stream until the end of the header */
  113. while (*len > 2 && (*data)[0] != '\r' && (*data)[1] != '\n') {
  114. (*len)--;
  115. (*data)++;
  116. }
  117. /* advanced past the <CR><LF> pair */
  118. *data += 2;
  119. *len -= 2;
  120. /* Find the length of the next header */
  121. header_len = 0;
  122. while (*len > header_len + 1
  123. && (*data)[header_len] != '\r'
  124. && (*data)[header_len + 1] != '\n')
  125. header_len++;
  126. return header_len;
  127. }