in src/common/commonutils/ProxyUtils.c [32:338]
bool ParseHttpProxyData(const char* proxyData, char** proxyHostAddress, int* proxyPort, char** proxyUsername, char** proxyPassword, OsConfigLogHandle log)
{
// We accept the proxy data string to be in one of two following formats:
//
// "http://server:port"
// "http://username:password@server:port"
//
// ..where the prefix must be either lowercase "http" or uppercase "HTTP"
// ..and username and password can contain '@' characters escaped as "\\@"
//
// For example:
//
// "http://username\\@mail.foo:p\\@ssw\\@rd@server:port" where username is "username@mail.foo" and password is "p@ssw@rd"
const char httpPrefix[] = "http://";
const char httpUppercasePrefix[] = "HTTP://";
int proxyDataLength = 0;
int prefixLength = 0;
bool isBadAlphaNum = false;
int credentialsSeparatorCounter = 0;
int columnCounter = 0;
char* credentialsSeparator = NULL;
char* firstColumn = NULL;
char* lastColumn = NULL;
char* afterPrefix = NULL;
char* hostAddress = NULL;
char* port = NULL;
char* username = NULL;
char* password = NULL;
int hostAddressLength = 0;
int portLength = 0;
int portNumber = 0;
int usernameLength = 0;
int passwordLength = 0;
int i = 0;
bool result = false;
if ((NULL == proxyData) || (NULL == proxyHostAddress) || (NULL == proxyPort))
{
OsConfigLogError(log, "ParseHttpProxyData called with invalid arguments");
return result;
}
// Initialize output arguments
*proxyHostAddress = NULL;
*proxyPort = 0;
if (proxyUsername)
{
*proxyUsername = NULL;
}
if (proxyPassword)
{
*proxyPassword = NULL;
}
// Check for required prefix and invalid characters and if any found then immediately fail
proxyDataLength = strlen(proxyData);
prefixLength = strlen(httpPrefix);
if (proxyDataLength <= prefixLength)
{
OsConfigLogError(log, "Unsupported proxy data (%s), too short", proxyData);
return NULL;
}
if (strncmp(proxyData, httpPrefix, prefixLength) && strncmp(proxyData, httpUppercasePrefix, strlen(httpUppercasePrefix)))
{
OsConfigLogError(log, "Unsupported proxy data (%s), no %s prefix", proxyData, httpPrefix);
return NULL;
}
for (i = 0; i < proxyDataLength; i++)
{
if (('.' == proxyData[i]) || ('/' == proxyData[i]) || ('\\' == proxyData[i]) || ('_' == proxyData[i]) ||
('-' == proxyData[i]) || ('$' == proxyData[i]) || ('!' == proxyData[i]) || (isalnum(proxyData[i])))
{
continue;
}
else if ('@' == proxyData[i])
{
// not valid as first character
if (0 == i)
{
OsConfigLogError(log, "Unsupported proxy data (%s), invalid '@' prefix", proxyData);
isBadAlphaNum = true;
break;
}
// '\@' can be used to insert '@' characters in username or password
else if ((i > 0) && ('\\' != proxyData[i - 1]))
{
if (NULL == credentialsSeparator)
{
credentialsSeparator = (char*)&(proxyData[i]);
}
credentialsSeparatorCounter += 1;
if (credentialsSeparatorCounter > 1)
{
OsConfigLogError(log, "Unsupported proxy data (%s), too many '@' characters", proxyData);
isBadAlphaNum = true;
break;
}
}
}
else if (':' == proxyData[i])
{
columnCounter += 1;
if (columnCounter > 3)
{
OsConfigLogError(log, "Unsupported proxy data (%s), too many ':' characters", proxyData);
isBadAlphaNum = true;
break;
}
}
else
{
OsConfigLogError(log, "Unsupported proxy data (%s), unsupported character '%c' at position %d", proxyData, proxyData[i], i);
isBadAlphaNum = true;
break;
}
}
if ((0 == columnCounter) && (false == isBadAlphaNum))
{
OsConfigLogError(log, "Unsupported proxy data (%s), missing ':'", proxyData);
isBadAlphaNum = true;
}
if (isBadAlphaNum)
{
return NULL;
}
afterPrefix = (char*)(proxyData + prefixLength);
firstColumn = strchr(afterPrefix, ':');
lastColumn = strrchr(afterPrefix, ':');
// If the '@' credentials separator is not already found, try the first one if any
if (NULL == credentialsSeparator)
{
credentialsSeparator = strchr(afterPrefix, '@');
}
// If found, bump over the first character that is the separator itself
if (firstColumn && (strlen(firstColumn) > 0))
{
firstColumn += 1;
}
if (lastColumn && (strlen(lastColumn) > 0))
{
lastColumn += 1;
}
if (credentialsSeparator && (strlen(credentialsSeparator) > 0))
{
credentialsSeparator += 1;
}
if ((proxyData >= firstColumn) ||
(afterPrefix >= firstColumn) ||
(firstColumn > lastColumn) ||
(credentialsSeparator && (firstColumn >= credentialsSeparator)) ||
(credentialsSeparator && (credentialsSeparator >= lastColumn)) ||
(credentialsSeparator && (firstColumn == lastColumn)) ||
(credentialsSeparator && (0 == strlen(credentialsSeparator))) ||
((credentialsSeparator ? strlen("A:A@A:A") : strlen("A:A")) > strlen(afterPrefix)) ||
(1 > strlen(lastColumn)) ||
(1 > strlen(firstColumn)))
{
OsConfigLogError(log, "Unsupported proxy data (%s) format", afterPrefix);
}
else
{
{
if (credentialsSeparator)
{
// username:password@server:port
usernameLength = (int)(firstColumn - afterPrefix - 1);
if (usernameLength > 0)
{
if (NULL != (username = (char*)malloc(usernameLength + 1)))
{
memcpy(username, afterPrefix, usernameLength);
username[usernameLength] = 0;
RemoveProxyStringEscaping(username);
usernameLength = strlen(username);
}
else
{
OsConfigLogError(log, "Cannot allocate memory for HTTP_PROXY_OPTIONS.username: %d", errno);
}
}
passwordLength = (int)(credentialsSeparator - firstColumn - 1);
if (passwordLength > 0)
{
if (NULL != (password = (char*)malloc(passwordLength + 1)))
{
memcpy(password, firstColumn, passwordLength);
password[passwordLength] = 0;
RemoveProxyStringEscaping(password);
passwordLength = strlen(password);
}
else
{
OsConfigLogError(log, "Cannot allocate memory for HTTP_PROXY_OPTIONS.password: %d", errno);
}
}
hostAddressLength = (int)(lastColumn - credentialsSeparator - 1);
if (hostAddressLength > 0)
{
if (NULL != (hostAddress = (char*)malloc(hostAddressLength + 1)))
{
memcpy(hostAddress, credentialsSeparator, hostAddressLength);
hostAddress[hostAddressLength] = 0;
}
else
{
OsConfigLogError(log, "Cannot allocate memory for HTTP_PROXY_OPTIONS.host_address: %d", errno);
}
}
portLength = (int)strlen(lastColumn);
if (portLength > 0)
{
if (NULL != (port = (char*)malloc(portLength + 1)))
{
memcpy(port, lastColumn, portLength);
port[portLength] = 0;
portNumber = strtol(port, NULL, 10);
}
else
{
OsConfigLogError(log, "Cannot allocate memory for HTTP_PROXY_OPTIONS.port string copy: %d", errno);
}
}
}
else
{
// server:port
hostAddressLength = (int)(firstColumn - afterPrefix - 1);
if (hostAddressLength > 0)
{
if (NULL != (hostAddress = (char*)malloc(hostAddressLength + 1)))
{
memcpy(hostAddress, afterPrefix, hostAddressLength);
hostAddress[hostAddressLength] = 0;
}
else
{
OsConfigLogError(log, "Cannot allocate memory for HTTP_PROXY_OPTIONS.host_address: %d", errno);
}
}
portLength = (int)strlen(firstColumn);
if (portLength > 0)
{
if (NULL != (port = (char*)malloc(portLength + 1)))
{
memcpy(port, firstColumn, portLength);
port[portLength] = 0;
portNumber = strtol(port, NULL, 10);
}
else
{
OsConfigLogError(log, "Cannot allocate memory for HTTP_PROXY_OPTIONS.port string copy: %d", errno);
}
}
}
*proxyHostAddress = hostAddress;
*proxyPort = portNumber;
if (proxyUsername && proxyPassword)
{
*proxyUsername = username;
*proxyPassword = password;
}
OsConfigLogInfo(log, "HTTP proxy host|address: %s (%d)", *proxyHostAddress, hostAddressLength);
OsConfigLogInfo(log, "HTTP proxy port: %d", *proxyPort);
OsConfigLogDebug(log, "HTTP proxy username: %s (%d)", *proxyUsername, usernameLength);
OsConfigLogDebug(log, "HTTP proxy password: %s (%d)", *proxyPassword, passwordLength);
FREE_MEMORY(port);
result = true;
}
}
return result;
}