1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-26 19:39:53 +03:00

Mayaqua: move HTTP functions from "Network" to "HTTP"

This commit is contained in:
Davide Beatrici 2019-10-20 02:17:42 +02:00
parent c3d6ffc533
commit 2f90e9ecb8
4 changed files with 919 additions and 936 deletions

View File

@ -2,6 +2,11 @@
#include <Mayaqua/Mayaqua.h> #include <Mayaqua/Mayaqua.h>
static char http_404_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>404 Not Found</TITLE>\r\n</HEAD><BODY>\r\n<H1>Not Found</H1>\r\nThe requested URL $TARGET$ was not found on this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_403_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access $TARGET$\r\non this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_500_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>500 Server Error</TITLE>\r\n</HEAD><BODY>\r\n<H1>Server Error</H1>\r\nServer Error<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_501_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n$METHOD$ to $TARGET$ not supported.<P>\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
// MIME list from https://www.freeformatter.com/mime-types-list.html // MIME list from https://www.freeformatter.com/mime-types-list.html
static const HTTP_MIME_TYPE http_mime_types[] = static const HTTP_MIME_TYPE http_mime_types[] =
{ {
@ -721,3 +726,852 @@ char *GetMimeTypeFromFileName(char *filename)
return NULL; return NULL;
} }
// Generate the date and time string for the HTTP header
void GetHttpDateStr(char *str, UINT size, UINT64 t)
{
SYSTEMTIME s;
static char *wday[] =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
};
static char *month[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec",
};
// Validate arguments
if (str == NULL)
{
return;
}
UINT64ToSystem(&s, t);
Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
s.wHour, s.wMinute, s.wSecond);
}
// Replace unsafe characters in target
void ReplaceUnsafeCharInHttpTarget(char *target)
{
UINT i;
for(i = 0; target[i] ; i++) {
if(target[i] == '<')
target[i] = '(';
else if(target[i] == '>')
target[i] = ')';
}
}
// Create an HTTP header
HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
{
return NewHttpHeaderEx(method, target, version, false);
}
HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort)
{
HTTP_HEADER *header;
// Validate arguments
if (method == NULL || target == NULL || version == NULL)
{
return NULL;
}
header = ZeroMalloc(sizeof(HTTP_HEADER));
header->Method = CopyStr(method);
header->Target = CopyStr(target);
header->Version = CopyStr(version);
header->ValueList = NewListFast(no_sort ? NULL : CompareHttpValue);
return header;
}
// Release the HTTP header
void FreeHttpHeader(HTTP_HEADER *header)
{
UINT i;
HTTP_VALUE **values;
// Validate arguments
if (header == NULL)
{
return;
}
Free(header->Method);
Free(header->Target);
Free(header->Version);
values = ToArray(header->ValueList);
for (i = 0;i < LIST_NUM(header->ValueList);i++)
{
FreeHttpValue(values[i]);
}
Free(values);
ReleaseList(header->ValueList);
Free(header);
}
// Create a new HTTP value
HTTP_VALUE *NewHttpValue(char *name, char *data)
{
HTTP_VALUE *v;
// Validate arguments
if (name == NULL || data == NULL)
{
return NULL;
}
v = ZeroMalloc(sizeof(HTTP_VALUE));
v->Name = CopyStr(name);
v->Data = CopyStr(data);
Trim(v->Name);
Trim(v->Data);
return v;
}
// Release the HTTP value
void FreeHttpValue(HTTP_VALUE *value)
{
// Validate arguments
if (value == NULL)
{
return;
}
Free(value->Data);
Free(value->Name);
Free(value);
}
// Comparison function of the HTTP value
int CompareHttpValue(void *p1, void *p2)
{
HTTP_VALUE *v1, *v2;
if (p1 == NULL || p2 == NULL)
{
return 0;
}
v1 = *(HTTP_VALUE **)p1;
v2 = *(HTTP_VALUE **)p2;
if (v1 == NULL || v2 == NULL)
{
return 0;
}
return StrCmpi(v1->Name, v2->Name);
}
// Look for an HTTP value in an HTTP header
HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
{
HTTP_VALUE *v, t;
// Validate arguments
if (header == NULL || name == NULL)
{
return NULL;
}
t.Name = name;
v = Search(header->ValueList, &t);
if (v == NULL)
{
return NULL;
}
return v;
}
// Add an HTTP value to the HTTP header
void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
{
// Validate arguments
if (header == NULL || value == NULL)
{
return;
}
if (LIST_NUM(header->ValueList) < HTTP_HEADER_MAX_LINES)
{
Insert(header->ValueList, value);
}
else
{
FreeHttpValue(value);
}
}
// Adds the HTTP value contained in the string to the HTTP header
bool AddHttpValueStr(HTTP_HEADER* header, char *string)
{
HTTP_VALUE *value = NULL;
UINT pos = 0;
char *value_name = NULL;
char *value_data = NULL;
// Validate arguments
if (header == NULL || IsEmptyStr(string))
{
return false;
}
// Sanitize string
EnSafeHttpHeaderValueStr(string, ' ');
// Get the position of the colon
pos = SearchStr(string, ":", 0);
if (pos == INFINITE)
{
// The colon does not exist
return false;
}
if ((pos + 1) >= StrLen(string))
{
// There is no data
return false;
}
// Divide into the name and the data
value_name = Malloc(pos + 1);
Copy(value_name, string, pos);
value_name[pos] = 0;
value_data = &string[pos + 1];
value = NewHttpValue(value_name, value_data);
if (value == NULL)
{
Free(value_name);
return false;
}
Free(value_name);
AddHttpValue(header, value);
return true;
}
// Get the Content-Length value from the HTTP header
UINT GetContentLength(HTTP_HEADER *header)
{
UINT ret;
HTTP_VALUE *v;
// Validate arguments
if (header == NULL)
{
return 0;
}
v = GetHttpValue(header, "Content-Length");
if (v == NULL)
{
return 0;
}
ret = ToInt(v->Data);
return ret;
}
// Send HTTP data
bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
{
char *header_str;
BUF *b;
bool ret;
// Validate arguments
if (s == NULL || header == NULL || (post_size != 0 && post_data == NULL))
{
return false;
}
// Check whether the Content-Length exists?
if (GetHttpValue(header, "Content-Length") == NULL)
{
char tmp[MAX_SIZE];
// Add because it does not exist
ToStr(tmp, post_size);
AddHttpValue(header, NewHttpValue("Content-Length", tmp));
}
// Convert the header to string
header_str = HttpHeaderToStr(header);
if (header_str == NULL)
{
return false;
}
b = NewBuf();
WriteBuf(b, header_str, StrLen(header_str));
Free(header_str);
// Append the data
WriteBuf(b, post_data, post_size);
// Send
ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
FreeBuf(b);
return ret;
}
// Convert an HTTP header to a string
char *HttpHeaderToStr(HTTP_HEADER *header)
{
BUF *b;
char *tmp;
UINT i;
char *s;
// Validate arguments
if (header == NULL)
{
return NULL;
}
tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
b = NewBuf();
// Header
Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
"%s %s %s\r\n", header->Method, header->Target, header->Version);
WriteBuf(b, tmp, StrLen(tmp));
// Value
for (i = 0;i < LIST_NUM(header->ValueList);i++)
{
HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
"%s: %s\r\n", v->Name, v->Data);
WriteBuf(b, tmp, StrLen(tmp));
}
// Trailing newline
WriteBuf(b, "\r\n", 2);
s = Malloc(b->Size + 1);
Copy(s, b->Buf, b->Size);
s[b->Size] = 0;
FreeBuf(b);
Free(tmp);
return s;
}
// Send the HTTP header
bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
{
char *str;
bool ret;
// Validate arguments
if (s == NULL || header == NULL)
{
return false;
}
// Convert to string
str = HttpHeaderToStr(header);
// Transmission
ret = SendAll(s, str, StrLen(str), s->SecureMode);
Free(str);
return ret;
}
// Receive an HTTP header
HTTP_HEADER *RecvHttpHeader(SOCK *s)
{
TOKEN_LIST *token = NULL;
char *str = NULL;
HTTP_HEADER *header = NULL;
// Validate arguments
if (s == NULL)
{
return NULL;
}
// Get the first line
str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
if (str == NULL)
{
return NULL;
}
// Split into tokens
token = ParseToken(str, " ");
FreeSafe(PTR_TO_PTR(str));
if (token->NumTokens < 3)
{
FreeToken(token);
return NULL;
}
// Creating a header object
header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
FreeToken(token);
if (StrCmpi(header->Version, "HTTP/0.9") == 0)
{
// The header ends with this line
return header;
}
// Get the subsequent lines
while (true)
{
str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
Trim(str);
if (IsEmptyStr(str))
{
// End of header
FreeSafe(PTR_TO_PTR(str));
break;
}
if (AddHttpValueStr(header, str) == false)
{
FreeSafe(PTR_TO_PTR(str));
FreeHttpHeader(header);
header = NULL;
break;
}
FreeSafe(PTR_TO_PTR(str));
}
return header;
}
// Send a PACK to the server
bool HttpClientSend(SOCK *s, PACK *p)
{
BUF *b;
bool ret;
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char ip_str[MAX_SIZE];
// Validate arguments
if (s == NULL || p == NULL)
{
return false;
}
IPToStr(ip_str, sizeof(ip_str), &s->RemoteIP);
CreateDummyValue(p);
b = PackToBuf(p);
if (b == NULL)
{
return false;
}
h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Host", ip_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
ret = PostHttp(s, h, b->Buf, b->Size);
FreeHttpHeader(h);
FreeBuf(b);
return ret;
}
// Receive a PACK from the server
PACK *HttpClientRecv(SOCK *s)
{
BUF *b;
PACK *p;
HTTP_HEADER *h;
UINT size;
UCHAR *tmp;
HTTP_VALUE *v;
// Validate arguments
if (s == NULL)
{
return NULL;
}
h = RecvHttpHeader(s);
if (h == NULL)
{
return NULL;
}
if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
StrCmpi(h->Target, "200") != 0)
{
FreeHttpHeader(h);
return NULL;
}
v = GetHttpValue(h, "Content-Type");
if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
{
FreeHttpHeader(h);
return NULL;
}
size = GetContentLength(h);
if (size == 0 || size > MAX_PACK_SIZE)
{
FreeHttpHeader(h);
return NULL;
}
tmp = MallocEx(size, true);
if (RecvAll(s, tmp, size, s->SecureMode) == false)
{
Free(tmp);
FreeHttpHeader(h);
return NULL;
}
b = NewBuf();
WriteBuf(b, tmp, size);
Free(tmp);
FreeHttpHeader(h);
SeekBuf(b, 0, 0);
p = BufToPack(b);
FreeBuf(b);
return p;
}
// Send a PACK to the client
bool HttpServerSend(SOCK *s, PACK *p)
{
BUF *b;
bool ret;
HTTP_HEADER *h;
char date_str[MAX_SIZE];
// Validate arguments
if (s == NULL || p == NULL)
{
return false;
}
CreateDummyValue(p);
b = PackToBuf(p);
if (b == NULL)
{
return false;
}
h = NewHttpHeader("HTTP/1.1", "200", "OK");
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
ret = PostHttp(s, h, b->Buf, b->Size);
FreeHttpHeader(h);
FreeBuf(b);
return ret;
}
// Receive a PACK from the client
PACK *HttpServerRecv(SOCK *s)
{
return HttpServerRecvEx(s, 0);
}
PACK *HttpServerRecvEx(SOCK *s, UINT max_data_size)
{
BUF *b;
PACK *p;
HTTP_HEADER *h;
UINT size;
UCHAR *tmp;
HTTP_VALUE *v;
UINT num_noop = 0;
if (max_data_size == 0) max_data_size = HTTP_PACK_MAX_SIZE;
// Validate arguments
if (s == NULL)
{
return NULL;
}
START:
h = RecvHttpHeader(s);
if (h == NULL)
{
goto BAD_REQUEST;
}
if (StrCmpi(h->Method, "POST") != 0 ||
StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
StrCmpi(h->Version, "HTTP/1.1") != 0)
{
FreeHttpHeader(h);
goto BAD_REQUEST;
}
v = GetHttpValue(h, "Content-Type");
if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
{
FreeHttpHeader(h);
goto BAD_REQUEST;
}
size = GetContentLength(h);
if (size == 0 || (size > max_data_size))
{
FreeHttpHeader(h);
goto BAD_REQUEST;
}
tmp = MallocEx(size, true);
if (RecvAll(s, tmp, size, s->SecureMode) == false)
{
Free(tmp);
FreeHttpHeader(h);
return NULL;
}
b = NewBuf();
WriteBuf(b, tmp, size);
Free(tmp);
FreeHttpHeader(h);
SeekBuf(b, 0, 0);
p = BufToPack(b);
FreeBuf(b);
// Determine whether it's a NOOP
if (PackGetInt(p, "noop") != 0)
{
Debug("recv: noop\n");
FreePack(p);
p = PackError(0);
PackAddInt(p, "noop", 1);
if (HttpServerSend(s, p) == false)
{
FreePack(p);
return NULL;
}
FreePack(p);
num_noop++;
if (num_noop > MAX_NOOP_PER_SESSION)
{
return NULL;
}
goto START;
}
return p;
BAD_REQUEST:
// Return an error
return NULL;
}
// Send "403 Forbidden" error
bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
{
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char *str;
UINT str_size;
char port_str[MAX_SIZE];
bool ret;
char host[MAX_SIZE];
UINT port;
// Validate arguments
if (s == NULL || target == NULL)
{
return false;
}
// Get the host name
//GetMachineName(host, MAX_SIZE);
Zero(host, sizeof(host));
IPToStr(host, sizeof(host), &s->LocalIP);
// Get the port number
port = s->LocalPort;
// Creating a header
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
// Creating a Data
str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
str = Malloc(str_size);
StrCpy(str, str_size, http_403_str);
// TARGET
ReplaceUnsafeCharInHttpTarget(target);
ReplaceStri(str, str_size, str, "$TARGET$", target);
// HOST
ReplaceStri(str, str_size, str, "$HOST$", host);
// PORT
ToStr(port_str, port);
ReplaceStri(str, str_size, str, "$PORT$", port_str);
// Transmission
ret = PostHttp(s, h, str, StrLen(str));
FreeHttpHeader(h);
Free(str);
return ret;
}
// Send "404 Not Found" error
bool HttpSendNotFound(SOCK *s, char *target)
{
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char *str;
UINT str_size;
char port_str[MAX_SIZE];
bool ret;
char host[MAX_SIZE];
UINT port;
// Validate arguments
if (s == NULL || target == NULL)
{
return false;
}
// Get the host name
//GetMachineName(host, MAX_SIZE);
Zero(host, sizeof(host));
IPToStr(host, sizeof(host), &s->LocalIP);
// Get the port number
port = s->LocalPort;
// Creating a header
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
// Creating a Data
str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
str = Malloc(str_size);
StrCpy(str, str_size, http_404_str);
// TARGET
ReplaceUnsafeCharInHttpTarget(target);
ReplaceStri(str, str_size, str, "$TARGET$", target);
// HOST
ReplaceStri(str, str_size, str, "$HOST$", host);
// PORT
ToStr(port_str, port);
ReplaceStri(str, str_size, str, "$PORT$", port_str);
// Transmission
ret = PostHttp(s, h, str, StrLen(str));
FreeHttpHeader(h);
Free(str);
return ret;
}
// Send "501 Not Implemented" error
bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
{
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char *str;
UINT str_size;
char port_str[MAX_SIZE];
bool ret;
char host[MAX_SIZE];
UINT port;
// Validate arguments
if (s == NULL || target == NULL)
{
return false;
}
// Get the host name
//GetMachineName(host, MAX_SIZE);
Zero(host, sizeof(host));
IPToStr(host, sizeof(host), &s->LocalIP);
// Get the port number
port = s->LocalPort;
// Creating a header
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
// Creating a Data
str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
str = Malloc(str_size);
StrCpy(str, str_size, http_501_str);
// TARGET
ReplaceUnsafeCharInHttpTarget(target);
ReplaceStri(str, str_size, str, "$TARGET$", target);
// HOST
ReplaceStri(str, str_size, str, "$HOST$", host);
// PORT
ToStr(port_str, port);
ReplaceStri(str, str_size, str, "$PORT$", port_str);
// METHOD
ReplaceStri(str, str_size, str, "$METHOD$", method);
// VERSION
ReplaceStri(str, str_size, str, "$VERSION$", version);
// Transmission
ret = PostHttp(s, h, str, StrLen(str));
FreeHttpHeader(h);
Free(str);
return ret;
}

View File

@ -1,6 +1,47 @@
#ifndef HTTP_H #ifndef HTTP_H
#define HTTP_H #define HTTP_H
#define DEFAULT_USER_AGENT "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0"
#define DEFAULT_ACCEPT "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-powerpoint, application/vnd.ms-excel, */*"
#define DEFAULT_ENCODING "gzip, deflate"
#define HTTP_CONTENT_TYPE "text/html; charset=iso-8859-1"
#define HTTP_CONTENT_TYPE2 "application/octet-stream"
#define HTTP_CONTENT_TYPE3 "image/jpeg"
#define HTTP_CONTENT_TYPE4 "text/html"
#define HTTP_CONTENT_TYPE5 "message/rfc822"
#define HTTP_KEEP_ALIVE "timeout=15; max=19"
#define HTTP_VPN_TARGET "/vpnsvc/vpn.cgi"
#define HTTP_VPN_TARGET2 "/vpnsvc/connect.cgi"
#define HTTP_VPN_TARGET_POSTDATA "VPNCONNECT"
#define HTTP_SAITAMA "/saitama.jpg"
#define HTTP_PICTURES "/picture"
// Maximum size of the custom HTTP header
#define HTTP_CUSTOM_HEADER_MAX_SIZE 1024
// Maximum size of a single line in the HTTP header
#define HTTP_HEADER_LINE_MAX_SIZE 4096
// Maximum number of lines in the HTTP header
#define HTTP_HEADER_MAX_LINES 128
// Maximum size of the random number to be included in the PACK
#define HTTP_PACK_RAND_SIZE_MAX 1000
// Maximum PACK size in the HTTP
#define HTTP_PACK_MAX_SIZE 65536
// HTTP value
struct HTTP_VALUE
{
char *Name; // Name
char *Data; // Data
};
// HTTP header
struct HTTP_HEADER
{
char *Method; // Method
char *Target; // Target
char *Version; // Version
LIST *ValueList; // Value list
};
// MIME type // MIME type
struct HTTP_MIME_TYPE struct HTTP_MIME_TYPE
{ {
@ -9,5 +50,29 @@ struct HTTP_MIME_TYPE
}; };
char *GetMimeTypeFromFileName(char *filename); char *GetMimeTypeFromFileName(char *filename);
void GetHttpDateStr(char *str, UINT size, UINT64 t);
void ReplaceUnsafeCharInHttpTarget(char *target);
HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version);
HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort);
void FreeHttpHeader(HTTP_HEADER *header);
HTTP_VALUE *NewHttpValue(char *name, char *data);
void FreeHttpValue(HTTP_VALUE *value);
int CompareHttpValue(void *p1, void *p2);
HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name);
void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value);
bool AddHttpValueStr(HTTP_HEADER* header, char *string);
UINT GetContentLength(HTTP_HEADER *header);
bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size);
char *HttpHeaderToStr(HTTP_HEADER *header);
bool SendHttpHeader(SOCK *s, HTTP_HEADER *header);
HTTP_HEADER *RecvHttpHeader(SOCK *s);
bool HttpClientSend(SOCK *s, PACK *p);
PACK *HttpClientRecv(SOCK *s);
bool HttpServerSend(SOCK *s, PACK *p);
PACK *HttpServerRecv(SOCK *s);
PACK *HttpServerRecvEx(SOCK *s, UINT max_data_size);
bool HttpSendForbidden(SOCK *s, char *target, char *server_id);
bool HttpSendNotFound(SOCK *s, char *target);
bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version);
#endif #endif

View File

@ -76,13 +76,7 @@ struct ROUTE_CHANGE_DATA
#endif // IPV6_V6ONLY #endif // IPV6_V6ONLY
#endif // UNIX_SOLARIS #endif // UNIX_SOLARIS
// HTTP constant // HTTP constant
static char http_404_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>404 Not Found</TITLE>\r\n</HEAD><BODY>\r\n<H1>Not Found</H1>\r\nThe requested URL $TARGET$ was not found on this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_403_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access $TARGET$\r\non this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_500_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>500 Server Error</TITLE>\r\n</HEAD><BODY>\r\n<H1>Server Error</H1>\r\nServer Error<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_501_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n$METHOD$ to $TARGET$ not supported.<P>\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
static char http_detect_server_startwith[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access "; static char http_detect_server_startwith[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access ";
static char http_detect_server_tag_future[] = "9C37197CA7C2428388C2E6E59B829B30"; static char http_detect_server_tag_future[] = "9C37197CA7C2428388C2E6E59B829B30";
@ -19945,109 +19939,6 @@ void FlushTubeFlushList(TUBE_FLUSH_LIST *f)
DeleteAll(f->List); DeleteAll(f->List);
} }
// The server receives a PACK from the client
PACK *HttpServerRecv(SOCK *s)
{
return HttpServerRecvEx(s, 0);
}
PACK *HttpServerRecvEx(SOCK *s, UINT max_data_size)
{
BUF *b;
PACK *p;
HTTP_HEADER *h;
UINT size;
UCHAR *tmp;
HTTP_VALUE *v;
UINT num_noop = 0;
if (max_data_size == 0) max_data_size = HTTP_PACK_MAX_SIZE;
// Validate arguments
if (s == NULL)
{
return NULL;
}
START:
h = RecvHttpHeader(s);
if (h == NULL)
{
goto BAD_REQUEST;
}
if (StrCmpi(h->Method, "POST") != 0 ||
StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
StrCmpi(h->Version, "HTTP/1.1") != 0)
{
FreeHttpHeader(h);
goto BAD_REQUEST;
}
v = GetHttpValue(h, "Content-Type");
if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
{
FreeHttpHeader(h);
goto BAD_REQUEST;
}
size = GetContentLength(h);
if (size == 0 || (size > max_data_size))
{
FreeHttpHeader(h);
goto BAD_REQUEST;
}
tmp = MallocEx(size, true);
if (RecvAll(s, tmp, size, s->SecureMode) == false)
{
Free(tmp);
FreeHttpHeader(h);
return NULL;
}
b = NewBuf();
WriteBuf(b, tmp, size);
Free(tmp);
FreeHttpHeader(h);
SeekBuf(b, 0, 0);
p = BufToPack(b);
FreeBuf(b);
// Determine whether it's a NOOP
if (PackGetInt(p, "noop") != 0)
{
Debug("recv: noop\n");
FreePack(p);
p = PackError(0);
PackAddInt(p, "noop", 1);
if (HttpServerSend(s, p) == false)
{
FreePack(p);
return NULL;
}
FreePack(p);
num_noop++;
if (num_noop > MAX_NOOP_PER_SESSION)
{
return NULL;
}
goto START;
}
return p;
BAD_REQUEST:
// Return an error
return NULL;
}
// Store the error value into PACK // Store the error value into PACK
PACK *PackError(UINT error) PACK *PackError(UINT error)
{ {
@ -20071,68 +19962,6 @@ UINT GetErrorFromPack(PACK *p)
return PackGetInt(p, "error"); return PackGetInt(p, "error");
} }
// Client receives a PACK from the server
PACK *HttpClientRecv(SOCK *s)
{
BUF *b;
PACK *p;
HTTP_HEADER *h;
UINT size;
UCHAR *tmp;
HTTP_VALUE *v;
// Validate arguments
if (s == NULL)
{
return NULL;
}
h = RecvHttpHeader(s);
if (h == NULL)
{
return NULL;
}
if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
StrCmpi(h->Target, "200") != 0)
{
FreeHttpHeader(h);
return NULL;
}
v = GetHttpValue(h, "Content-Type");
if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
{
FreeHttpHeader(h);
return NULL;
}
size = GetContentLength(h);
if (size == 0 || size > MAX_PACK_SIZE)
{
FreeHttpHeader(h);
return NULL;
}
tmp = MallocEx(size, true);
if (RecvAll(s, tmp, size, s->SecureMode) == false)
{
Free(tmp);
FreeHttpHeader(h);
return NULL;
}
b = NewBuf();
WriteBuf(b, tmp, size);
Free(tmp);
FreeHttpHeader(h);
SeekBuf(b, 0, 0);
p = BufToPack(b);
FreeBuf(b);
return p;
}
// Create an entry to PACK for the dummy // Create an entry to PACK for the dummy
void CreateDummyValue(PACK *p) void CreateDummyValue(PACK *p)
{ {
@ -20153,497 +19982,6 @@ void CreateDummyValue(PACK *p)
Free(buf); Free(buf);
} }
// Client sends a PACK to the server
bool HttpClientSend(SOCK *s, PACK *p)
{
BUF *b;
bool ret;
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char ip_str[MAX_SIZE];
// Validate arguments
if (s == NULL || p == NULL)
{
return false;
}
IPToStr(ip_str, sizeof(ip_str), &s->RemoteIP);
CreateDummyValue(p);
b = PackToBuf(p);
if (b == NULL)
{
return false;
}
h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Host", ip_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
ret = PostHttp(s, h, b->Buf, b->Size);
FreeHttpHeader(h);
FreeBuf(b);
return ret;
}
// Server sends a PACK to the client
bool HttpServerSend(SOCK *s, PACK *p)
{
BUF *b;
bool ret;
HTTP_HEADER *h;
char date_str[MAX_SIZE];
// Validate arguments
if (s == NULL || p == NULL)
{
return false;
}
CreateDummyValue(p);
b = PackToBuf(p);
if (b == NULL)
{
return false;
}
h = NewHttpHeader("HTTP/1.1", "200", "OK");
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
ret = PostHttp(s, h, b->Buf, b->Size);
FreeHttpHeader(h);
FreeBuf(b);
return ret;
}
// Replace unsafe characters in target
void ReplaceUnsafeCharInTarget(char *target){
UINT i;
for(i = 0; target[i] ; i++) {
if(target[i] == '<')
target[i] = '(';
else if(target[i] == '>')
target[i] = ')';
}
}
// Sending the 501 Not Implemented error
bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
{
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char *str;
UINT str_size;
char port_str[MAX_SIZE];
bool ret;
char host[MAX_SIZE];
UINT port;
// Validate arguments
if (s == NULL || target == NULL)
{
return false;
}
// Get the host name
//GetMachineName(host, MAX_SIZE);
Zero(host, sizeof(host));
IPToStr(host, sizeof(host), &s->LocalIP);
// Get the port number
port = s->LocalPort;
// Creating a header
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
// Creating a Data
str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
str = Malloc(str_size);
StrCpy(str, str_size, http_501_str);
// TARGET
ReplaceUnsafeCharInTarget(target);
ReplaceStri(str, str_size, str, "$TARGET$", target);
// HOST
ReplaceStri(str, str_size, str, "$HOST$", host);
// PORT
ToStr(port_str, port);
ReplaceStri(str, str_size, str, "$PORT$", port_str);
// METHOD
ReplaceStri(str, str_size, str, "$METHOD$", method);
// VERSION
ReplaceStri(str, str_size, str, "$VERSION$", version);
// Transmission
ret = PostHttp(s, h, str, StrLen(str));
FreeHttpHeader(h);
Free(str);
return ret;
}
// Sending a 404 Not Found error
bool HttpSendNotFound(SOCK *s, char *target)
{
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char *str;
UINT str_size;
char port_str[MAX_SIZE];
bool ret;
char host[MAX_SIZE];
UINT port;
// Validate arguments
if (s == NULL || target == NULL)
{
return false;
}
// Get the host name
//GetMachineName(host, MAX_SIZE);
Zero(host, sizeof(host));
IPToStr(host, sizeof(host), &s->LocalIP);
// Get the port number
port = s->LocalPort;
// Creating a header
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
// Creating a Data
str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
str = Malloc(str_size);
StrCpy(str, str_size, http_404_str);
// TARGET
ReplaceUnsafeCharInTarget(target);
ReplaceStri(str, str_size, str, "$TARGET$", target);
// HOST
ReplaceStri(str, str_size, str, "$HOST$", host);
// PORT
ToStr(port_str, port);
ReplaceStri(str, str_size, str, "$PORT$", port_str);
// Transmission
ret = PostHttp(s, h, str, StrLen(str));
FreeHttpHeader(h);
Free(str);
return ret;
}
// Sending a 403 Forbidden error
bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
{
HTTP_HEADER *h;
char date_str[MAX_SIZE];
char *str;
UINT str_size;
char port_str[MAX_SIZE];
bool ret;
char host[MAX_SIZE];
UINT port;
// Validate arguments
if (s == NULL || target == NULL)
{
return false;
}
// Get the host name
//GetMachineName(host, MAX_SIZE);
Zero(host, sizeof(host));
IPToStr(host, sizeof(host), &s->LocalIP);
// Get the port number
port = s->LocalPort;
// Creating a header
GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
AddHttpValue(h, NewHttpValue("Date", date_str));
AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
// Creating a Data
str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
str = Malloc(str_size);
StrCpy(str, str_size, http_403_str);
// TARGET
ReplaceUnsafeCharInTarget(target);
ReplaceStri(str, str_size, str, "$TARGET$", target);
// HOST
ReplaceStri(str, str_size, str, "$HOST$", host);
// PORT
ToStr(port_str, port);
ReplaceStri(str, str_size, str, "$PORT$", port_str);
// Transmission
ret = PostHttp(s, h, str, StrLen(str));
FreeHttpHeader(h);
Free(str);
return ret;
}
// Get the date and time string for the HTTP header
void GetHttpDateStr(char *str, UINT size, UINT64 t)
{
SYSTEMTIME s;
static char *wday[] =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
};
static char *month[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec",
};
// Validate arguments
if (str == NULL)
{
return;
}
UINT64ToSystem(&s, t);
Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
s.wHour, s.wMinute, s.wSecond);
}
// Get the Content-Length from the HTTP header
UINT GetContentLength(HTTP_HEADER *header)
{
UINT ret;
HTTP_VALUE *v;
// Validate arguments
if (header == NULL)
{
return 0;
}
v = GetHttpValue(header, "Content-Length");
if (v == NULL)
{
return 0;
}
ret = ToInt(v->Data);
return ret;
}
// Send the data in the HTTP
bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
{
char *header_str;
BUF *b;
bool ret;
// Validate arguments
if (s == NULL || header == NULL || (post_size != 0 && post_data == NULL))
{
return false;
}
// Check whether the Content-Length exists?
if (GetHttpValue(header, "Content-Length") == NULL)
{
char tmp[MAX_SIZE];
// Add because it does not exist
ToStr(tmp, post_size);
AddHttpValue(header, NewHttpValue("Content-Length", tmp));
}
// Convert the header to string
header_str = HttpHeaderToStr(header);
if (header_str == NULL)
{
return false;
}
b = NewBuf();
WriteBuf(b, header_str, StrLen(header_str));
Free(header_str);
// Append the data
WriteBuf(b, post_data, post_size);
// Send
ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
FreeBuf(b);
return ret;
}
// Convert a HTTP header to a string
char *HttpHeaderToStr(HTTP_HEADER *header)
{
BUF *b;
char *tmp;
UINT i;
char *s;
// Validate arguments
if (header == NULL)
{
return NULL;
}
tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
b = NewBuf();
// Header
Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
"%s %s %s\r\n", header->Method, header->Target, header->Version);
WriteBuf(b, tmp, StrLen(tmp));
// Value
for (i = 0;i < LIST_NUM(header->ValueList);i++)
{
HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
"%s: %s\r\n", v->Name, v->Data);
WriteBuf(b, tmp, StrLen(tmp));
}
// Trailing newline
WriteBuf(b, "\r\n", 2);
s = Malloc(b->Size + 1);
Copy(s, b->Buf, b->Size);
s[b->Size] = 0;
FreeBuf(b);
Free(tmp);
return s;
}
// Send the HTTP header
bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
{
char *str;
bool ret;
// Validate arguments
if (s == NULL || header == NULL)
{
return false;
}
// Convert to string
str = HttpHeaderToStr(header);
// Transmission
ret = SendAll(s, str, StrLen(str), s->SecureMode);
Free(str);
return ret;
}
// Receive an HTTP header
HTTP_HEADER *RecvHttpHeader(SOCK *s)
{
TOKEN_LIST *token = NULL;
char *str = NULL;
HTTP_HEADER *header = NULL;
// Validate arguments
if (s == NULL)
{
return NULL;
}
// Get the first line
str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
if (str == NULL)
{
return NULL;
}
// Split into tokens
token = ParseToken(str, " ");
FreeSafe(PTR_TO_PTR(str));
if (token->NumTokens < 3)
{
FreeToken(token);
return NULL;
}
// Creating a header object
header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
FreeToken(token);
if (StrCmpi(header->Version, "HTTP/0.9") == 0)
{
// The header ends with this line
return header;
}
// Get the subsequent lines
while (true)
{
str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
Trim(str);
if (IsEmptyStr(str))
{
// End of header
FreeSafe(PTR_TO_PTR(str));
break;
}
if (AddHttpValueStr(header, str) == false)
{
FreeSafe(PTR_TO_PTR(str));
FreeHttpHeaderSafe(&header);
break;
}
FreeSafe(PTR_TO_PTR(str));
}
return header;
}
// Receive a line // Receive a line
char *RecvLine(SOCK *s, UINT max_size) char *RecvLine(SOCK *s, UINT max_size)
{ {
@ -20695,207 +20033,6 @@ char *RecvLine(SOCK *s, UINT max_size)
} }
} }
// Creating a new HTTP value
HTTP_VALUE *NewHttpValue(char *name, char *data)
{
HTTP_VALUE *v;
// Validate arguments
if (name == NULL || data == NULL)
{
return NULL;
}
v = ZeroMalloc(sizeof(HTTP_VALUE));
v->Name = CopyStr(name);
v->Data = CopyStr(data);
Trim(v->Name);
Trim(v->Data);
return v;
}
// Look for the HTTP value from the HTTP header
HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
{
HTTP_VALUE *v, t;
// Validate arguments
if (header == NULL || name == NULL)
{
return NULL;
}
t.Name = name;
v = Search(header->ValueList, &t);
if (v == NULL)
{
return NULL;
}
return v;
}
// Add a HTTP value to the HTTP header
void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
{
// Validate arguments
if (header == NULL || value == NULL)
{
return;
}
if (LIST_NUM(header->ValueList) < HTTP_HEADER_MAX_LINES)
{
Insert(header->ValueList, value);
}
else
{
FreeHttpValue(value);
}
}
// Adds the HTTP value contained in the string to the HTTP header
bool AddHttpValueStr(HTTP_HEADER* header, char *string)
{
HTTP_VALUE *value = NULL;
UINT pos = 0;
char *value_name = NULL;
char *value_data = NULL;
// Validate arguments
if (header == NULL || IsEmptyStr(string))
{
return false;
}
// Sanitize string
EnSafeHttpHeaderValueStr(string, ' ');
// Get the position of the colon
pos = SearchStr(string, ":", 0);
if (pos == INFINITE)
{
// The colon does not exist
return false;
}
if ((pos + 1) >= StrLen(string))
{
// There is no data
return false;
}
// Divide into the name and the data
value_name = Malloc(pos + 1);
Copy(value_name, string, pos);
value_name[pos] = 0;
value_data = &string[pos + 1];
value = NewHttpValue(value_name, value_data);
if (value == NULL)
{
Free(value_name);
return false;
}
Free(value_name);
AddHttpValue(header, value);
return true;
}
// Create an HTTP header
HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
{
return NewHttpHeaderEx(method, target, version, false);
}
HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort)
{
HTTP_HEADER *header;
// Validate arguments
if (method == NULL || target == NULL || version == NULL)
{
return NULL;
}
header = ZeroMalloc(sizeof(HTTP_HEADER));
header->Method = CopyStr(method);
header->Target = CopyStr(target);
header->Version = CopyStr(version);
header->ValueList = NewListFast(no_sort ? NULL : CompareHttpValue);
return header;
}
// Comparison function of the HTTP value
int CompareHttpValue(void *p1, void *p2)
{
HTTP_VALUE *v1, *v2;
if (p1 == NULL || p2 == NULL)
{
return 0;
}
v1 = *(HTTP_VALUE **)p1;
v2 = *(HTTP_VALUE **)p2;
if (v1 == NULL || v2 == NULL)
{
return 0;
}
return StrCmpi(v1->Name, v2->Name);
}
// Release the HTTP value
void FreeHttpValue(HTTP_VALUE *value)
{
// Validate arguments
if (value == NULL)
{
return;
}
Free(value->Data);
Free(value->Name);
Free(value);
}
// Release the HTTP header
void FreeHttpHeader(HTTP_HEADER *header)
{
UINT i;
HTTP_VALUE **values;
// Validate arguments
if (header == NULL)
{
return;
}
Free(header->Method);
Free(header->Target);
Free(header->Version);
values = ToArray(header->ValueList);
for (i = 0;i < LIST_NUM(header->ValueList);i++)
{
FreeHttpValue(values[i]);
}
Free(values);
ReleaseList(header->ValueList);
Free(header);
}
// Release the HTTP header and set pointer's value to NULL
void FreeHttpHeaderSafe(HTTP_HEADER **header)
{
FreeHttpHeader(*header);
*header = NULL;
}
// Receive a PACK // Receive a PACK
PACK *RecvPack(SOCK *s) PACK *RecvPack(SOCK *s)
{ {

View File

@ -874,53 +874,6 @@ struct NIC_ENTRY
UCHAR MacAddress[6]; UCHAR MacAddress[6];
}; };
// HTTP value
struct HTTP_VALUE
{
char *Name; // Name
char *Data; // Data
};
// HTTP header
struct HTTP_HEADER
{
char *Method; // Method
char *Target; // Target
char *Version; // Version
LIST *ValueList; // Value list
};
// HTTPS server / client related string constant
#define DEFAULT_USER_AGENT "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0"
#define DEFAULT_ACCEPT "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-powerpoint, application/vnd.ms-excel, */*"
#define DEFAULT_ENCODING "gzip, deflate"
#define HTTP_CONTENT_TYPE "text/html; charset=iso-8859-1"
#define HTTP_CONTENT_TYPE2 "application/octet-stream"
#define HTTP_CONTENT_TYPE3 "image/jpeg"
#define HTTP_CONTENT_TYPE4 "text/html"
#define HTTP_CONTENT_TYPE5 "message/rfc822"
#define HTTP_KEEP_ALIVE "timeout=15; max=19"
#define HTTP_VPN_TARGET "/vpnsvc/vpn.cgi"
#define HTTP_VPN_TARGET2 "/vpnsvc/connect.cgi"
#define HTTP_VPN_TARGET_POSTDATA "VPNCONNECT"
#define HTTP_SAITAMA "/saitama.jpg"
#define HTTP_PICTURES "/picture"
// Maximum size of the custom HTTP header
#define HTTP_CUSTOM_HEADER_MAX_SIZE 1024
// Maximum size of a single line in the HTTP header
#define HTTP_HEADER_LINE_MAX_SIZE 4096
// Maximum number of lines in the HTTP header
#define HTTP_HEADER_MAX_LINES 128
// Maximum size of the random number to be included in the PACK
#define HTTP_PACK_RAND_SIZE_MAX 1000
// Maximum PACK size in the HTTP
#define HTTP_PACK_MAX_SIZE 65536
int GetCurrentTimezone(); int GetCurrentTimezone();
bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UINT sni_size); bool GetSniNameFromSslPacket(UCHAR *packet_buf, UINT packet_size, char *sni, UINT sni_size);
@ -934,16 +887,6 @@ bool IsUseAlternativeHostname();
int GetCurrentTimezoneWin32(); int GetCurrentTimezoneWin32();
#endif // OS_WIN32 #endif // OS_WIN32
HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name);
void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value);
bool AddHttpValueStr(HTTP_HEADER* header, char *string);
HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version);
HTTP_HEADER *NewHttpHeaderEx(char *method, char *target, char *version, bool no_sort);
int CompareHttpValue(void *p1, void *p2);
void FreeHttpValue(HTTP_VALUE *value);
void FreeHttpHeader(HTTP_HEADER *header);
void FreeHttpHeaderSafe(HTTP_HEADER **header);
bool SendPack(SOCK *s, PACK *p); bool SendPack(SOCK *s, PACK *p);
PACK *RecvPack(SOCK *s); PACK *RecvPack(SOCK *s);
PACK *RecvPackWithHash(SOCK *s); PACK *RecvPackWithHash(SOCK *s);
@ -954,23 +897,7 @@ PACK *PackError(UINT error);
void CreateDummyValue(PACK *p); void CreateDummyValue(PACK *p);
HTTP_VALUE *NewHttpValue(char *name, char *data);
char *RecvLine(SOCK *s, UINT max_size); char *RecvLine(SOCK *s, UINT max_size);
HTTP_HEADER *RecvHttpHeader(SOCK *s);
bool SendHttpHeader(SOCK *s, HTTP_HEADER *header);
char *HttpHeaderToStr(HTTP_HEADER *header);
bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size);
UINT GetContentLength(HTTP_HEADER *header);
void GetHttpDateStr(char *str, UINT size, UINT64 t);
bool HttpSendForbidden(SOCK *s, char *target, char *server_id);
bool HttpSendNotFound(SOCK *s, char *target);
bool HttpSendBody(SOCK *s, void *data, UINT size, char *contents_type);
bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version);
bool HttpServerSend(SOCK *s, PACK *p);
bool HttpClientSend(SOCK *s, PACK *p);
PACK *HttpServerRecv(SOCK *s);
PACK *HttpServerRecvEx(SOCK *s, UINT max_data_size);
PACK *HttpClientRecv(SOCK *s);
bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname); bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname);
bool GetDnsProxyIPAddressForJapanBFlets(IP *ip_ret, UINT timeout, bool *cancel); bool GetDnsProxyIPAddressForJapanBFlets(IP *ip_ret, UINT timeout, bool *cancel);