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:
parent
c3d6ffc533
commit
2f90e9ecb8
@ -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;
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user