1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-07-06 07:44:57 +03:00

Add custom HTTP header feature for HTTP proxy

A custom HTTP header can be used to bypass certain restrictions imposed on the network or to avoid speed limitations applied by the QoS.
This commit is contained in:
Davide Beatrici
2018-11-29 20:32:03 +01:00
parent 4be45342b7
commit aefbd2e903
29 changed files with 1665 additions and 120 deletions

View File

@ -1542,6 +1542,28 @@ bool IsInListStr(LIST *o, char *str)
return false;
}
bool IsInListUniStr(LIST *o, wchar_t *str)
{
UINT i;
// Validate arguments
if (o == NULL || str == NULL)
{
return false;
}
for (i = 0; i < LIST_NUM(o); i++)
{
wchar_t *s = LIST_DATA(o, i);
if (UniStrCmpi(s, str) == 0)
{
return true;
}
}
return false;
}
// Get the pointer by scanning by UINT pointer in the list
void *ListKeyToPointer(LIST *o, UINT key)
{

View File

@ -396,6 +396,7 @@ bool IsInList(LIST *o, void *p);
bool IsInListKey(LIST *o, UINT key);
void *ListKeyToPointer(LIST *o, UINT key);
bool IsInListStr(LIST *o, char *str);
bool IsInListUniStr(LIST *o, wchar_t *str);
bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr);
void AddInt(LIST *o, UINT i);
void AddInt64(LIST *o, UINT64 i);

View File

@ -20558,7 +20558,7 @@ HTTP_HEADER *RecvHttpHeader(SOCK *s)
str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
if (str == NULL)
{
goto LABEL_ERROR;
return NULL;
}
// Split into tokens
@ -20569,89 +20569,45 @@ HTTP_HEADER *RecvHttpHeader(SOCK *s)
}
Free(str);
str = 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
FreeToken(token);
return header;
}
// Get the subsequent lines
while (true)
{
UINT pos;
HTTP_VALUE *v;
char *value_name, *value_data;
str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
if (str == NULL)
{
goto LABEL_ERROR;
}
Trim(str);
if (StrLen(str) == 0)
if (IsEmptyStr(str))
{
// End of header
Free(str);
str = NULL;
break;
}
// Get the position of the colon
pos = SearchStr(str, ":", 0);
if (pos == INFINITE)
if (AddHttpValueStr(header, str) == false)
{
// The colon does not exist
goto LABEL_ERROR;
}
if ((pos + 1) >= StrLen(str))
{
// There is no data
goto LABEL_ERROR;
}
// Divide into the name and the data
value_name = Malloc(pos + 1);
Copy(value_name, str, pos);
value_name[pos] = 0;
value_data = &str[pos + 1];
v = NewHttpValue(value_name, value_data);
if (v == NULL)
{
Free(value_name);
goto LABEL_ERROR;
}
Free(value_name);
AddHttpValue(header, v);
Free(str);
}
FreeToken(token);
return header;
LABEL_ERROR:
// Memory release
if (token)
{
FreeToken(token);
}
if (str)
{
Free(str);
}
if (header)
{
FreeHttpHeader(header);
}
Free(str);
FreeToken(token);
FreeHttpHeader(header);
return NULL;
}
@ -20766,6 +20722,57 @@ void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *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)
{

View File

@ -1001,6 +1001,8 @@ struct HTTP_HEADER
#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
@ -1029,6 +1031,7 @@ int GetCurrentTimezoneWin32();
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);

View File

@ -2027,6 +2027,53 @@ void EnSafeStr(char *str, char replace)
}
}
// Replace '\r' and '\n' with the specified character.
// If the specified character is a space (unsafe), the original character is removed.
void EnSafeHttpHeaderValueStr(char *str, char replace)
{
UINT length = 0;
UINT index = 0;
// Validate arguments
if (str == NULL)
{
return;
}
length = StrLen(str);
while (index < length)
{
if (str[index] == '\r' || str[index] == '\n')
{
if (replace == ' ')
{
Move(&str[index], &str[index + 1], length - index);
}
else
{
str[index] = replace;
}
}
else if (str[index] == '\\')
{
if (str[index + 1] == 'r' || str[index + 1] == 'n')
{
if (replace == ' ')
{
Move(&str[index], &str[index + 2], length - index);
index--;
}
else
{
str[index] = str[index + 1] = replace;
index++;
}
}
}
index++;
}
}
// Operation check of string library
bool CheckStringLibrary()
{

View File

@ -177,6 +177,7 @@ void EnPrintableAsciiStr(char *str, char replace);
bool IsSafeChar(char c);
bool IsSafeStr(char *str);
void EnSafeStr(char *str, char replace);
void EnSafeHttpHeaderValueStr(char *str, char replace);
void TruncateCharFromStr(char *str, char replace);
char *CopyStr(char *str);
void BinToStr(char *str, UINT str_size, void *data, UINT data_size);