committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 14 additions and 597 deletions
Split View
Diff Options
-
2debian/copyright
-
7src/CMakeLists.txt
-
11src/Makefile.am
-
1src/common.h
-
153src/http.c
-
34src/http.h
-
70src/local.c
-
1src/local.h
-
36src/protocol.h
-
3src/server.c
-
1src/server.h
-
259src/tls.c
-
33src/tls.h
@ -1,153 +0,0 @@ |
|||
/* |
|||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net> |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include "config.h" |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> /* malloc() */ |
|||
#include <string.h> /* strncpy() */ |
|||
#include <strings.h> /* strncasecmp() */ |
|||
#include <ctype.h> /* isblank(), isdigit() */ |
|||
|
|||
#include "http.h" |
|||
#include "protocol.h" |
|||
|
|||
static int parse_http_header(const char *, size_t, char **); |
|||
static int get_header(const char *, const char *, int, char **); |
|||
static int next_header(const char **, int *); |
|||
|
|||
static const protocol_t http_protocol_st = { |
|||
.default_port = 80, |
|||
.parse_packet = &parse_http_header, |
|||
}; |
|||
const protocol_t *const http_protocol = &http_protocol_st; |
|||
|
|||
/* |
|||
* Parses a HTTP request for the Host: header |
|||
* |
|||
* Returns: |
|||
* >=0 - length of the hostname and updates *hostname |
|||
* caller is responsible for freeing *hostname |
|||
* -1 - Incomplete request |
|||
* -2 - No Host header included in this request |
|||
* -3 - Invalid hostname pointer |
|||
* -4 - malloc failure |
|||
* < -4 - Invalid HTTP request |
|||
* |
|||
*/ |
|||
static int |
|||
parse_http_header(const char *data, size_t data_len, char **hostname) |
|||
{ |
|||
int result, i; |
|||
|
|||
if (hostname == NULL) |
|||
return -3; |
|||
|
|||
if (data_len == 0) |
|||
return -1; |
|||
|
|||
result = get_header("Host:", data, data_len, hostname); |
|||
if (result < 0) |
|||
return result; |
|||
|
|||
/* |
|||
* if the user specifies the port in the request, it is included here. |
|||
* Host: example.com:80 |
|||
* Host: [2001:db8::1]:8080 |
|||
* so we trim off port portion |
|||
*/ |
|||
for (i = result - 1; i >= 0; i--) |
|||
if ((*hostname)[i] == ':') { |
|||
(*hostname)[i] = '\0'; |
|||
result = i; |
|||
break; |
|||
} else if (!isdigit((*hostname)[i])) { |
|||
break; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
static int |
|||
get_header(const char *header, const char *data, int data_len, char **value) |
|||
{ |
|||
int len, header_len; |
|||
|
|||
header_len = strlen(header); |
|||
|
|||
/* loop through headers stopping at first blank line */ |
|||
while ((len = next_header(&data, &data_len)) != 0) |
|||
if (len > header_len && strncasecmp(header, data, header_len) == 0) { |
|||
/* Eat leading whitespace */ |
|||
while (header_len < len && isblank((unsigned char)data[header_len])) |
|||
header_len++; |
|||
|
|||
*value = malloc(len - header_len + 1); |
|||
if (*value == NULL) |
|||
return -4; |
|||
|
|||
strncpy(*value, data + header_len, len - header_len); |
|||
(*value)[len - header_len] = '\0'; |
|||
|
|||
return len - header_len; |
|||
} |
|||
|
|||
/* If there is no data left after reading all the headers then we do not |
|||
* have a complete HTTP request, there must be a blank line */ |
|||
if (data_len == 0) |
|||
return -1; |
|||
|
|||
return -2; |
|||
} |
|||
|
|||
static int |
|||
next_header(const char **data, int *len) |
|||
{ |
|||
int header_len; |
|||
|
|||
/* perhaps we can optimize this to reuse the value of header_len, rather |
|||
* than scanning twice. |
|||
* Walk our data stream until the end of the header */ |
|||
while (*len > 2 && (*data)[0] != '\r' && (*data)[1] != '\n') { |
|||
(*len)--; |
|||
(*data)++; |
|||
} |
|||
|
|||
/* advanced past the <CR><LF> pair */ |
|||
*data += 2; |
|||
*len -= 2; |
|||
|
|||
/* Find the length of the next header */ |
|||
header_len = 0; |
|||
while (*len > header_len + 1 |
|||
&& (*data)[header_len] != '\r' |
|||
&& (*data)[header_len + 1] != '\n') |
|||
header_len++; |
|||
|
|||
return header_len; |
|||
} |
@ -1,34 +0,0 @@ |
|||
/* |
|||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net> |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#ifndef HTTP_H |
|||
#define HTTP_H |
|||
|
|||
#include <stdio.h> |
|||
#include "protocol.h" |
|||
|
|||
const protocol_t *const http_protocol; |
|||
|
|||
#endif |
@ -1,36 +0,0 @@ |
|||
/* |
|||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net> |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#ifndef PROTOCOL_H |
|||
#define PROTOCOL_H |
|||
|
|||
#define MAX_HOSTNAME_LEN 256 |
|||
|
|||
typedef struct protocol { |
|||
const int default_port; |
|||
int(*const parse_packet) (const char *, size_t, char **); |
|||
} protocol_t; |
|||
|
|||
#endif |
@ -1,259 +0,0 @@ |
|||
/* |
|||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net> |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
/* |
|||
* This is a minimal TLS implementation intended only to parse the server name |
|||
* extension. This was created based primarily on Wireshark dissection of a |
|||
* TLS handshake and RFC4366. |
|||
*/ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include "config.h" |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> /* malloc() */ |
|||
#include <string.h> /* strncpy() */ |
|||
#ifndef __MINGW32__ |
|||
#include <sys/socket.h> |
|||
#endif |
|||
|
|||
#include "tls.h" |
|||
#include "protocol.h" |
|||
#include "utils.h" |
|||
|
|||
#define TLS_HEADER_LEN 5 |
|||
#define TLS_HANDSHAKE_CONTENT_TYPE 0x16 |
|||
#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01 |
|||
|
|||
#ifndef MIN |
|||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
|||
#endif |
|||
|
|||
extern int verbose; |
|||
|
|||
static int parse_tls_header(const char *, size_t, char **); |
|||
static int parse_extensions(const char *, size_t, char **); |
|||
static int parse_server_name_extension(const char *, size_t, char **); |
|||
|
|||
static const protocol_t tls_protocol_st = { |
|||
.default_port = 443, |
|||
.parse_packet = &parse_tls_header, |
|||
}; |
|||
const protocol_t *const tls_protocol = &tls_protocol_st; |
|||
|
|||
/* Parse a TLS packet for the Server Name Indication extension in the client |
|||
* hello handshake, returning the first servername found (pointer to static |
|||
* array) |
|||
* |
|||
* Returns: |
|||
* >=0 - length of the hostname and updates *hostname |
|||
* caller is responsible for freeing *hostname |
|||
* -1 - Incomplete request |
|||
* -2 - No Host header included in this request |
|||
* -3 - Invalid hostname pointer |
|||
* -4 - malloc failure |
|||
* < -4 - Invalid TLS client hello |
|||
*/ |
|||
static int |
|||
parse_tls_header(const char *data, size_t data_len, char **hostname) |
|||
{ |
|||
char tls_content_type; |
|||
char tls_version_major; |
|||
char tls_version_minor; |
|||
size_t pos = TLS_HEADER_LEN; |
|||
size_t len; |
|||
|
|||
if (hostname == NULL) |
|||
return -3; |
|||
|
|||
/* Check that our TCP payload is at least large enough for a TLS header */ |
|||
if (data_len < TLS_HEADER_LEN) |
|||
return -1; |
|||
|
|||
/* SSL 2.0 compatible Client Hello |
|||
* |
|||
* High bit of first byte (length) and content type is Client Hello |
|||
* |
|||
* See RFC5246 Appendix E.2 |
|||
*/ |
|||
if (data[0] & 0x80 && data[2] == 1) { |
|||
if (verbose) |
|||
LOGI("Received SSL 2.0 Client Hello which can not support SNI."); |
|||
return -2; |
|||
} |
|||
|
|||
tls_content_type = data[0]; |
|||
if (tls_content_type != TLS_HANDSHAKE_CONTENT_TYPE) { |
|||
if (verbose) |
|||
LOGI("Request did not begin with TLS handshake."); |
|||
return -5; |
|||
} |
|||
|
|||
tls_version_major = data[1]; |
|||
tls_version_minor = data[2]; |
|||
if (tls_version_major < 3) { |
|||
if (verbose) |
|||
LOGI("Received SSL %d.%d handshake which can not support SNI.", |
|||
tls_version_major, tls_version_minor); |
|||
|
|||
return -2; |
|||
} |
|||
|
|||
/* TLS record length */ |
|||
len = ((unsigned char)data[3] << 8) + |
|||
(unsigned char)data[4] + TLS_HEADER_LEN; |
|||
data_len = MIN(data_len, len); |
|||
|
|||
/* Check we received entire TLS record length */ |
|||
if (data_len < len) |
|||
return -1; |
|||
|
|||
/* |
|||
* Handshake |
|||
*/ |
|||
if (pos + 1 > data_len) { |
|||
return -5; |
|||
} |
|||
if (data[pos] != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { |
|||
if (verbose) |
|||
LOGI("Not a client hello"); |
|||
|
|||
return -5; |
|||
} |
|||
|
|||
/* Skip past fixed length records: |
|||
* 1 Handshake Type |
|||
* 3 Length |
|||
* 2 Version (again) |
|||
* 32 Random |
|||
* to Session ID Length |
|||
*/ |
|||
pos += 38; |
|||
|
|||
/* Session ID */ |
|||
if (pos + 1 > data_len) |
|||
return -5; |
|||
len = (unsigned char)data[pos]; |
|||
pos += 1 + len; |
|||
|
|||
/* Cipher Suites */ |
|||
if (pos + 2 > data_len) |
|||
return -5; |
|||
len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1]; |
|||
pos += 2 + len; |
|||
|
|||
/* Compression Methods */ |
|||
if (pos + 1 > data_len) |
|||
return -5; |
|||
len = (unsigned char)data[pos]; |
|||
pos += 1 + len; |
|||
|
|||
if (pos == data_len && tls_version_major == 3 && tls_version_minor == 0) { |
|||
if (verbose) |
|||
LOGI("Received SSL 3.0 handshake without extensions"); |
|||
return -2; |
|||
} |
|||
|
|||
/* Extensions */ |
|||
if (pos + 2 > data_len) |
|||
return -5; |
|||
len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1]; |
|||
pos += 2; |
|||
|
|||
if (pos + len > data_len) |
|||
return -5; |
|||
return parse_extensions(data + pos, len, hostname); |
|||
} |
|||
|
|||
static int |
|||
parse_extensions(const char *data, size_t data_len, char **hostname) |
|||
{ |
|||
size_t pos = 0; |
|||
size_t len; |
|||
|
|||
/* Parse each 4 bytes for the extension header */ |
|||
while (pos + 4 <= data_len) { |
|||
/* Extension Length */ |
|||
len = ((unsigned char)data[pos + 2] << 8) + |
|||
(unsigned char)data[pos + 3]; |
|||
|
|||
/* Check if it's a server name extension */ |
|||
if (data[pos] == 0x00 && data[pos + 1] == 0x00) { |
|||
/* There can be only one extension of each type, so we break |
|||
* our state and move p to beinnging of the extension here */ |
|||
if (pos + 4 + len > data_len) |
|||
return -5; |
|||
return parse_server_name_extension(data + pos + 4, len, hostname); |
|||
} |
|||
pos += 4 + len; /* Advance to the next extension header */ |
|||
} |
|||
/* Check we ended where we expected to */ |
|||
if (pos != data_len) |
|||
return -5; |
|||
|
|||
return -2; |
|||
} |
|||
|
|||
static int |
|||
parse_server_name_extension(const char *data, size_t data_len, |
|||
char **hostname) |
|||
{ |
|||
size_t pos = 2; /* skip server name list length */ |
|||
size_t len; |
|||
|
|||
while (pos + 3 < data_len) { |
|||
len = ((unsigned char)data[pos + 1] << 8) + |
|||
(unsigned char)data[pos + 2]; |
|||
|
|||
if (pos + 3 + len > data_len) |
|||
return -5; |
|||
|
|||
switch (data[pos]) { /* name type */ |
|||
case 0x00: /* host_name */ |
|||
*hostname = malloc(len + 1); |
|||
if (*hostname == NULL) { |
|||
ERROR("malloc() failure"); |
|||
return -4; |
|||
} |
|||
|
|||
strncpy(*hostname, data + pos + 3, len); |
|||
|
|||
(*hostname)[len] = '\0'; |
|||
|
|||
return len; |
|||
default: |
|||
if (verbose) |
|||
LOGI("Unknown server name extension name type: %d", |
|||
data[pos]); |
|||
} |
|||
pos += 3 + len; |
|||
} |
|||
/* Check we ended where we expected to */ |
|||
if (pos != data_len) |
|||
return -5; |
|||
|
|||
return -2; |
|||
} |
@ -1,33 +0,0 @@ |
|||
/* |
|||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net> |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* |
|||
* 1. Redistributions of source code must retain the above copyright notice, |
|||
* this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#ifndef TLS_H |
|||
#define TLS_H |
|||
|
|||
#include "protocol.h" |
|||
|
|||
const protocol_t *const tls_protocol; |
|||
|
|||
#endif |
Write
Preview
Loading…
Cancel
Save