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:
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user