mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-13 21:36:00 +03:00
Fixed minor behavior on the trasnformations and added sha1-mbedtls
This commit is contained in:
parent
f35d28b8d3
commit
967c8c90f2
@ -11,7 +11,8 @@ libmodsecurity_includesubdir = $(pkgincludedir)/collection/
|
||||
|
||||
libmbedtls_la_SOURCES = \
|
||||
utils/mbedtls/base64.c \
|
||||
utils/mbedtls/md5.c
|
||||
utils/mbedtls/md5.c \
|
||||
utils/mbedtls/sha1.c
|
||||
|
||||
libmbedtls_la_CFLAGS = -D MBEDTLS_CONFIG_FILE=\"mbed-tls-config.h\" -Iutils
|
||||
libmbedtls_la_CPPFLAGS =
|
||||
|
@ -36,26 +36,175 @@ namespace transformations {
|
||||
|
||||
std::string HtmlEntityDecode::evaluate(std::string value,
|
||||
Transaction *transaction) {
|
||||
std::string ret;
|
||||
unsigned char *input = NULL;
|
||||
|
||||
if (HtmlEntityDecodeInstantCache::getInstance().count(value) > 0) {
|
||||
return HtmlEntityDecodeInstantCache::getInstance().at(value);
|
||||
input = reinterpret_cast<unsigned char *>
|
||||
(malloc(sizeof(char) * value.length()+1));
|
||||
|
||||
if (input == NULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char *tmp = strdup(value.c_str());
|
||||
memcpy(input, value.c_str(), value.length()+1);
|
||||
|
||||
// FIXME: html_entities_decode_inplace is not working as expected
|
||||
// temporary disabled to perform the audit_log tests.
|
||||
// html_entities_decode_inplace((unsigned char *)tmp, value.size());
|
||||
std::string ret("");
|
||||
ret.assign(tmp);
|
||||
free(tmp);
|
||||
size_t i = inplace(input, value.length());
|
||||
|
||||
HtmlEntityDecodeInstantCache::getInstance().cache(value, ret);
|
||||
ret.assign(reinterpret_cast<char *>(input), i);
|
||||
free(input);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int HtmlEntityDecode::inplace(unsigned char *input, u_int64_t input_len) {
|
||||
unsigned char *d = input;
|
||||
int i, count;
|
||||
|
||||
if ((input == NULL) || (input_len <= 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = count = 0;
|
||||
while ((i < input_len) && (count < input_len)) {
|
||||
int z, copy = 1;
|
||||
|
||||
/* Require an ampersand and at least one character to
|
||||
* start looking into the entity.
|
||||
*/
|
||||
if ((input[i] == '&') && (i + 1 < input_len)) {
|
||||
int k, j = i + 1;
|
||||
|
||||
if (input[j] == '#') {
|
||||
/* Numerical entity. */
|
||||
copy++;
|
||||
|
||||
if (!(j + 1 < input_len)) {
|
||||
goto HTML_ENT_OUT; /* Not enough bytes. */
|
||||
}
|
||||
j++;
|
||||
|
||||
if ((input[j] == 'x') || (input[j] == 'X')) {
|
||||
/* Hexadecimal entity. */
|
||||
copy++;
|
||||
|
||||
if (!(j + 1 < input_len)) {
|
||||
goto HTML_ENT_OUT; /* Not enough bytes. */
|
||||
}
|
||||
j++; /* j is the position of the first digit now. */
|
||||
|
||||
k = j;
|
||||
while ((j < input_len) && (isxdigit(input[j]))) {
|
||||
j++;
|
||||
}
|
||||
if (j > k) { /* Do we have at least one digit? */
|
||||
/* Decode the entity. */
|
||||
char *x = NULL;
|
||||
x = reinterpret_cast<char *>(malloc(sizeof(char) *
|
||||
((j - k) + 1)));
|
||||
memset(x, '\0', (j - k) + 1);
|
||||
memcpy(x, (const char *)&input[k], j - k);
|
||||
*d++ = (unsigned char)strtol(x, NULL, 16);
|
||||
|
||||
count++;
|
||||
|
||||
/* Skip over the semicolon if it's there. */
|
||||
if ((j < input_len) && (input[j] == ';')) {
|
||||
i = j + 1;
|
||||
} else {
|
||||
i = j;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
} else {
|
||||
/* Decimal entity. */
|
||||
k = j;
|
||||
while ((j < input_len) && (isdigit(input[j]))) {
|
||||
j++;
|
||||
}
|
||||
if (j > k) { /* Do we have at least one digit? */
|
||||
/* Decode the entity. */
|
||||
char *x = NULL;
|
||||
x = reinterpret_cast<char *>(malloc(sizeof(char) *
|
||||
((j - k) + 1)));
|
||||
memset(x, '\0', (j - k) + 1);
|
||||
memcpy(x, (const char *)&input[k], j - k);
|
||||
*d++ = (unsigned char)strtol(x, NULL, 10);
|
||||
|
||||
count++;
|
||||
|
||||
/* Skip over the semicolon if it's there. */
|
||||
if ((j < input_len) && (input[j] == ';')) {
|
||||
i = j + 1;
|
||||
} else {
|
||||
i = j;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Text entity. */
|
||||
k = j;
|
||||
while ((j < input_len) && (isalnum(input[j]))) {
|
||||
j++;
|
||||
}
|
||||
if (j > k) { /* Do we have at least one digit? */
|
||||
char *x = NULL;
|
||||
x = reinterpret_cast<char *>(malloc(sizeof(char) *
|
||||
((j - k) + 1)));
|
||||
memset(x, '\0', (j - k) + 1);
|
||||
memcpy(x, (const char *)&input[k], j - k);
|
||||
|
||||
/* Decode the entity. */
|
||||
/* ENH What about others? */
|
||||
if (strcasecmp(x, "quot") == 0) {
|
||||
*d++ = '"';
|
||||
} else if (strcasecmp(x, "amp") == 0) {
|
||||
*d++ = '&';
|
||||
} else if (strcasecmp(x, "lt") == 0) {
|
||||
*d++ = '<';
|
||||
} else if (strcasecmp(x, "gt") == 0) {
|
||||
*d++ = '>';
|
||||
} else if (strcasecmp(x, "nbsp") == 0) {
|
||||
*d++ = NBSP;
|
||||
} else {
|
||||
/* We do no want to convert this entity,
|
||||
* copy the raw data over. */
|
||||
copy = j - k + 1;
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
/* Skip over the semicolon if it's there. */
|
||||
if ((j < input_len) && (input[j] == ';')) {
|
||||
i = j + 1;
|
||||
} else {
|
||||
i = j;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HTML_ENT_OUT:
|
||||
|
||||
for (z = 0; ((z < copy) && (count < input_len)); z++) {
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace transformations
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
||||
|
@ -30,25 +30,6 @@ namespace actions {
|
||||
namespace transformations {
|
||||
|
||||
|
||||
class HtmlEntityDecodeInstantCache :
|
||||
public std::unordered_map<std::string, std::string> {
|
||||
public:
|
||||
static HtmlEntityDecodeInstantCache& getInstance() {
|
||||
static HtmlEntityDecodeInstantCache instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void cache(const std::string& value, const std::string& out) {
|
||||
emplace(value, out);
|
||||
if (size() > 100) {
|
||||
erase(begin());
|
||||
}
|
||||
}
|
||||
private:
|
||||
HtmlEntityDecodeInstantCache() {}
|
||||
};
|
||||
|
||||
|
||||
class HtmlEntityDecode : public Transformation {
|
||||
public:
|
||||
explicit HtmlEntityDecode(std::string action)
|
||||
@ -56,6 +37,8 @@ class HtmlEntityDecode : public Transformation {
|
||||
|
||||
std::string evaluate(std::string exp,
|
||||
Transaction *transaction) override;
|
||||
|
||||
static int inplace(unsigned char *input, u_int64_t input_len);
|
||||
};
|
||||
|
||||
|
||||
|
@ -36,21 +36,133 @@ namespace transformations {
|
||||
|
||||
std::string JsDecode::evaluate(std::string value,
|
||||
Transaction *transaction) {
|
||||
std::string ret;
|
||||
unsigned char *input = NULL;
|
||||
|
||||
char *val = reinterpret_cast<char *>(
|
||||
malloc(sizeof(char) * value.size() + 1));
|
||||
memcpy(val, value.c_str(), value.size() + 1);
|
||||
val[value.size()] = '\0';
|
||||
input = reinterpret_cast<unsigned char *>
|
||||
(malloc(sizeof(char) * value.length()+1));
|
||||
|
||||
js_decode_nonstrict_inplace((unsigned char *)val, value.size());
|
||||
std::string ret("");
|
||||
ret.assign(val);
|
||||
free(val);
|
||||
if (input == NULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
memcpy(input, value.c_str(), value.length()+1);
|
||||
|
||||
size_t i = inplace(input, value.length());
|
||||
|
||||
ret.assign(reinterpret_cast<char *>(input), i);
|
||||
free(input);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int JsDecode::inplace(unsigned char *input, u_int64_t input_len) {
|
||||
unsigned char *d = (unsigned char *)input;
|
||||
int64_t i, count;
|
||||
|
||||
i = count = 0;
|
||||
while (i < input_len) {
|
||||
if (input[i] == '\\') {
|
||||
/* Character is an escape. */
|
||||
|
||||
if ((i + 5 < input_len) && (input[i + 1] == 'u')
|
||||
&& (VALID_HEX(input[i + 2])) && (VALID_HEX(input[i + 3]))
|
||||
&& (VALID_HEX(input[i + 4])) && (VALID_HEX(input[i + 5]))) {
|
||||
/* \uHHHH */
|
||||
|
||||
/* Use only the lower byte. */
|
||||
*d = x2c(&input[i + 4]);
|
||||
|
||||
/* Full width ASCII (ff01 - ff5e) needs 0x20 added */
|
||||
if ((*d > 0x00) && (*d < 0x5f)
|
||||
&& ((input[i + 2] == 'f') || (input[i + 2] == 'F'))
|
||||
&& ((input[i + 3] == 'f') || (input[i + 3] == 'F'))) {
|
||||
(*d) += 0x20;
|
||||
}
|
||||
|
||||
d++;
|
||||
count++;
|
||||
i += 6;
|
||||
} else if ((i + 3 < input_len) && (input[i + 1] == 'x')
|
||||
&& VALID_HEX(input[i + 2]) && VALID_HEX(input[i + 3])) {
|
||||
/* \xHH */
|
||||
*d++ = x2c(&input[i + 2]);
|
||||
count++;
|
||||
i += 4;
|
||||
} else if ((i + 1 < input_len) && ISODIGIT(input[i + 1])) {
|
||||
/* \OOO (only one byte, \000 - \377) */
|
||||
char buf[4];
|
||||
int j = 0;
|
||||
|
||||
while ((i + 1 + j < input_len) && (j < 3)) {
|
||||
buf[j] = input[i + 1 + j];
|
||||
j++;
|
||||
if (!ISODIGIT(input[i + 1 + j])) break;
|
||||
}
|
||||
buf[j] = '\0';
|
||||
|
||||
if (j > 0) {
|
||||
/* Do not use 3 characters if we will be > 1 byte */
|
||||
if ((j == 3) && (buf[0] > '3')) {
|
||||
j = 2;
|
||||
buf[j] = '\0';
|
||||
}
|
||||
*d++ = (unsigned char)strtol(buf, NULL, 8);
|
||||
i += 1 + j;
|
||||
count++;
|
||||
}
|
||||
} else if (i + 1 < input_len) {
|
||||
/* \C */
|
||||
unsigned char c = input[i + 1];
|
||||
switch (input[i + 1]) {
|
||||
case 'a' :
|
||||
c = '\a';
|
||||
break;
|
||||
case 'b' :
|
||||
c = '\b';
|
||||
break;
|
||||
case 'f' :
|
||||
c = '\f';
|
||||
break;
|
||||
case 'n' :
|
||||
c = '\n';
|
||||
break;
|
||||
case 'r' :
|
||||
c = '\r';
|
||||
break;
|
||||
case 't' :
|
||||
c = '\t';
|
||||
break;
|
||||
case 'v' :
|
||||
c = '\v';
|
||||
break;
|
||||
/* The remaining (\?,\\,\',\") are just a removal
|
||||
* of the escape char which is default.
|
||||
*/
|
||||
}
|
||||
|
||||
*d++ = c;
|
||||
i += 2;
|
||||
count++;
|
||||
} else {
|
||||
/* Not enough bytes */
|
||||
while (i < input_len) {
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace transformations
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
||||
|
@ -35,6 +35,7 @@ class JsDecode : public Transformation {
|
||||
|
||||
std::string evaluate(std::string exp,
|
||||
Transaction *transaction) override;
|
||||
static int inplace(unsigned char *input, u_int64_t input_len);
|
||||
};
|
||||
|
||||
} // namespace transformations
|
||||
|
@ -40,11 +40,7 @@ Sha1::Sha1(std::string action)
|
||||
std::string Sha1::evaluate(std::string value,
|
||||
Transaction *transaction) {
|
||||
|
||||
Utils::SHA1 sha1;
|
||||
sha1.update(&value);
|
||||
std::string sha1_bin = sha1.final_bin();
|
||||
|
||||
return sha1_bin;
|
||||
return Utils::Sha1::digest(value);
|
||||
}
|
||||
|
||||
} // namespace transformations
|
||||
|
@ -110,8 +110,8 @@ Transformation* Transformation::instantiate(std::string a) {
|
||||
IF_MATCH(trimLeft) { return new TrimLeft(a); }
|
||||
IF_MATCH(trimRight) { return new TrimRight(a); }
|
||||
IF_MATCH(trim) { return new Trim(a); }
|
||||
IF_MATCH(urlDecode) { return new UrlDecode(a); }
|
||||
IF_MATCH(urlDecodeUni) { return new UrlDecodeUni(a); }
|
||||
IF_MATCH(urlDecode) { return new UrlDecode(a); }
|
||||
IF_MATCH(urlEncode) { return new UrlEncode(a); }
|
||||
IF_MATCH(utf8ToUnicode) { return new Utf8ToUnicode(a); }
|
||||
|
||||
|
@ -36,18 +36,155 @@ namespace transformations {
|
||||
|
||||
std::string UrlDecodeUni::evaluate(std::string value,
|
||||
Transaction *transaction) {
|
||||
int changed = 0;
|
||||
char *tmp = strdup(value.c_str());
|
||||
urldecode_uni_nonstrict_inplace_ex(transaction, (unsigned char *)tmp,
|
||||
value.size(), &changed);
|
||||
std::string ret("");
|
||||
ret.assign(tmp);
|
||||
free(tmp);
|
||||
std::string ret;
|
||||
unsigned char *input = NULL;
|
||||
|
||||
input = reinterpret_cast<unsigned char *>
|
||||
(malloc(sizeof(char) * value.length()+1));
|
||||
|
||||
if (input == NULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
memcpy(input, value.c_str(), value.length()+1);
|
||||
|
||||
size_t i = inplace(input, value.length(), transaction);
|
||||
|
||||
ret.assign(reinterpret_cast<char *>(input), i);
|
||||
free(input);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* IMP1 Assumes NUL-terminated
|
||||
*/
|
||||
int UrlDecodeUni::inplace(unsigned char *input, u_int64_t input_len,
|
||||
Transaction *transaction) {
|
||||
unsigned char *d = input;
|
||||
int64_t i, count, fact, j, xv;
|
||||
int Code, hmap = -1;
|
||||
|
||||
if (input == NULL) return -1;
|
||||
|
||||
i = count = 0;
|
||||
while (i < input_len) {
|
||||
if (input[i] == '%') {
|
||||
if ((i + 1 < input_len) &&
|
||||
((input[i + 1] == 'u') || (input[i + 1] == 'U'))) {
|
||||
/* Character is a percent sign. */
|
||||
/* IIS-specific %u encoding. */
|
||||
if (i + 5 < input_len) {
|
||||
/* We have at least 4 data bytes. */
|
||||
if ((VALID_HEX(input[i + 2])) &&
|
||||
(VALID_HEX(input[i + 3])) &&
|
||||
(VALID_HEX(input[i + 4])) &&
|
||||
(VALID_HEX(input[i + 5]))) {
|
||||
Code = 0;
|
||||
fact = 1;
|
||||
|
||||
if (transaction
|
||||
&& transaction->m_rules->unicode_map_table != NULL
|
||||
&& transaction->m_rules->unicode_codepage > 0) {
|
||||
for (j = 5; j >= 2; j--) {
|
||||
if (isxdigit((input[i+j]))) {
|
||||
if (input[i+j] >= 97) {
|
||||
xv = (input[i+j] - 97) + 10;
|
||||
} else if (input[i+j] >= 65) {
|
||||
xv = (input[i+j] - 65) + 10;
|
||||
} else {
|
||||
xv = (input[i+j]) - 48;
|
||||
}
|
||||
Code += (xv * fact);
|
||||
fact *= 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (Code >= 0 && Code <= 65535) {
|
||||
Rules *r = transaction->m_rules;
|
||||
hmap = r->unicode_map_table[Code];
|
||||
}
|
||||
}
|
||||
|
||||
if (hmap != -1) {
|
||||
*d = hmap;
|
||||
} else {
|
||||
/* We first make use of the lower byte here,
|
||||
* ignoring the higher byte. */
|
||||
*d = x2c(&input[i + 4]);
|
||||
|
||||
/* Full width ASCII (ff01 - ff5e)
|
||||
* needs 0x20 added */
|
||||
if ((*d > 0x00) && (*d < 0x5f)
|
||||
&& ((input[i + 2] == 'f')
|
||||
|| (input[i + 2] == 'F'))
|
||||
&& ((input[i + 3] == 'f')
|
||||
|| (input[i + 3] == 'F'))) {
|
||||
(*d) += 0x20;
|
||||
}
|
||||
}
|
||||
d++;
|
||||
count++;
|
||||
i += 6;
|
||||
} else {
|
||||
/* Invalid data, skip %u. */
|
||||
*d++ = input[i++];
|
||||
*d++ = input[i++];
|
||||
count += 2;
|
||||
}
|
||||
} else {
|
||||
/* Not enough bytes (4 data bytes), skip %u. */
|
||||
*d++ = input[i++];
|
||||
*d++ = input[i++];
|
||||
count += 2;
|
||||
}
|
||||
} else {
|
||||
/* Standard URL encoding. */
|
||||
/* Are there enough bytes available? */
|
||||
if (i + 2 < input_len) {
|
||||
/* Yes. */
|
||||
|
||||
/* Decode a %xx combo only if it is valid.
|
||||
*/
|
||||
char c1 = input[i + 1];
|
||||
char c2 = input[i + 2];
|
||||
|
||||
if (VALID_HEX(c1) && VALID_HEX(c2)) {
|
||||
*d++ = x2c(&input[i + 1]);
|
||||
count++;
|
||||
i += 3;
|
||||
} else {
|
||||
/* Not a valid encoding, skip this % */
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
/* Not enough bytes available, skip this % */
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Character is not a percent sign. */
|
||||
if (input[i] == '+') {
|
||||
*d++ = ' ';
|
||||
} else {
|
||||
*d++ = input[i];
|
||||
}
|
||||
|
||||
count++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
} // namespace transformations
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
||||
|
@ -30,11 +30,11 @@ namespace transformations {
|
||||
|
||||
class UrlDecodeUni : public Transformation {
|
||||
public:
|
||||
explicit UrlDecodeUni(std::string action)
|
||||
: Transformation(action) { }
|
||||
explicit UrlDecodeUni(std::string action) : Transformation(action) { }
|
||||
|
||||
std::string evaluate(std::string exp,
|
||||
Transaction *transaction) override;
|
||||
std::string evaluate(std::string exp, Transaction *transaction) override;
|
||||
static int inplace(unsigned char *input, u_int64_t input_len,
|
||||
Transaction *transaction);
|
||||
};
|
||||
|
||||
} // namespace transformations
|
||||
|
@ -58,15 +58,14 @@ namespace modsecurity {
|
||||
void UniqueId::fillUniqueId() {
|
||||
std::string macAddress;
|
||||
std::string name;
|
||||
Utils::SHA1 sha1;
|
||||
std::string data;
|
||||
|
||||
macAddress = ethernetMacAddress();
|
||||
name = machineName();
|
||||
|
||||
sha1.update(&macAddress);
|
||||
sha1.update(&name);
|
||||
data = macAddress + name;
|
||||
|
||||
this->uniqueId_str = sha1.final();
|
||||
this->uniqueId_str = Utils::Sha1::hexdigest(data);
|
||||
}
|
||||
|
||||
// Based on:
|
||||
|
392
src/utils.cc
392
src/utils.cc
@ -254,115 +254,6 @@ double cpu_seconds(void) {
|
||||
}
|
||||
|
||||
|
||||
int js_decode_nonstrict_inplace(unsigned char *input, int64_t input_len) {
|
||||
unsigned char *d = (unsigned char *)input;
|
||||
int64_t i, count;
|
||||
|
||||
if (input == NULL) return -1;
|
||||
|
||||
i = count = 0;
|
||||
while (i < input_len) {
|
||||
if (input[i] == '\\') {
|
||||
/* Character is an escape. */
|
||||
|
||||
if ((i + 5 < input_len) && (input[i + 1] == 'u')
|
||||
&& (VALID_HEX(input[i + 2])) && (VALID_HEX(input[i + 3]))
|
||||
&& (VALID_HEX(input[i + 4])) && (VALID_HEX(input[i + 5]))) {
|
||||
/* \uHHHH */
|
||||
|
||||
/* Use only the lower byte. */
|
||||
*d = x2c(&input[i + 4]);
|
||||
|
||||
/* Full width ASCII (ff01 - ff5e) needs 0x20 added */
|
||||
if ((*d > 0x00) && (*d < 0x5f)
|
||||
&& ((input[i + 2] == 'f') || (input[i + 2] == 'F'))
|
||||
&& ((input[i + 3] == 'f') || (input[i + 3] == 'F'))) {
|
||||
(*d) += 0x20;
|
||||
}
|
||||
|
||||
d++;
|
||||
count++;
|
||||
i += 6;
|
||||
} else if ((i + 3 < input_len) && (input[i + 1] == 'x')
|
||||
&& VALID_HEX(input[i + 2]) && VALID_HEX(input[i + 3])) {
|
||||
/* \xHH */
|
||||
*d++ = x2c(&input[i + 2]);
|
||||
count++;
|
||||
i += 4;
|
||||
} else if ((i + 1 < input_len) && ISODIGIT(input[i + 1])) {
|
||||
/* \OOO (only one byte, \000 - \377) */
|
||||
char buf[4];
|
||||
int j = 0;
|
||||
|
||||
while ((i + 1 + j < input_len) && (j < 3)) {
|
||||
buf[j] = input[i + 1 + j];
|
||||
j++;
|
||||
if (!ISODIGIT(input[i + 1 + j])) break;
|
||||
}
|
||||
buf[j] = '\0';
|
||||
|
||||
if (j > 0) {
|
||||
/* Do not use 3 characters if we will be > 1 byte */
|
||||
if ((j == 3) && (buf[0] > '3')) {
|
||||
j = 2;
|
||||
buf[j] = '\0';
|
||||
}
|
||||
*d++ = (unsigned char)strtol(buf, NULL, 8);
|
||||
i += 1 + j;
|
||||
count++;
|
||||
}
|
||||
} else if (i + 1 < input_len) {
|
||||
/* \C */
|
||||
unsigned char c = input[i + 1];
|
||||
switch (input[i + 1]) {
|
||||
case 'a' :
|
||||
c = '\a';
|
||||
break;
|
||||
case 'b' :
|
||||
c = '\b';
|
||||
break;
|
||||
case 'f' :
|
||||
c = '\f';
|
||||
break;
|
||||
case 'n' :
|
||||
c = '\n';
|
||||
break;
|
||||
case 'r' :
|
||||
c = '\r';
|
||||
break;
|
||||
case 't' :
|
||||
c = '\t';
|
||||
break;
|
||||
case 'v' :
|
||||
c = '\v';
|
||||
break;
|
||||
/* The remaining (\?,\\,\',\") are just a removal
|
||||
* of the escape char which is default.
|
||||
*/
|
||||
}
|
||||
|
||||
*d++ = c;
|
||||
i += 2;
|
||||
count++;
|
||||
} else {
|
||||
/* Not enough bytes */
|
||||
while (i < input_len) {
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode a string that contains CSS-escaped characters.
|
||||
*
|
||||
@ -503,157 +394,6 @@ int css_decode_inplace(unsigned char *input, int64_t input_len) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* IMP1 Assumes NUL-terminated
|
||||
*/
|
||||
int html_entities_decode_inplace(unsigned char *input, int input_len) {
|
||||
unsigned char *d = input;
|
||||
int i, count;
|
||||
|
||||
if ((input == NULL) || (input_len <= 0)) return 0;
|
||||
|
||||
i = count = 0;
|
||||
while ((i < input_len) && (count < input_len)) {
|
||||
int z, copy = 1;
|
||||
|
||||
/* Require an ampersand and at least one character to
|
||||
* start looking into the entity.
|
||||
*/
|
||||
if ((input[i] == '&') && (i + 1 < input_len)) {
|
||||
int k, j = i + 1;
|
||||
|
||||
if (input[j] == '#') {
|
||||
/* Numerical entity. */
|
||||
copy++;
|
||||
|
||||
if (!(j + 1 < input_len)) {
|
||||
/* Not enough bytes. */
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
j++;
|
||||
|
||||
if ((input[j] == 'x') || (input[j] == 'X')) {
|
||||
/* Hexadecimal entity. */
|
||||
copy++;
|
||||
|
||||
if (!(j + 1 < input_len)) {
|
||||
/* Not enough bytes. */
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
j++; /* j is the position of the first digit now. */
|
||||
|
||||
k = j;
|
||||
while ((j < input_len) && (isxdigit(input[j]))) j++;
|
||||
if (j > k) { /* Do we have at least one digit? */
|
||||
char *x;
|
||||
/* Decode the entity. */
|
||||
/* char *x = apr_pstrmemdup(mp,
|
||||
* (const char *)&input[k], j - k); */
|
||||
x = reinterpret_cast<char *>(malloc(sizeof(char) *
|
||||
(j - k)));
|
||||
memcpy(x, (const char *)&input[k], j - k);
|
||||
*d++ = (unsigned char)strtol(x, NULL, 16);
|
||||
count++;
|
||||
free(x);
|
||||
/* Skip over the semicolon if it's there. */
|
||||
if ((j < input_len) && (input[j] == ';')) {
|
||||
i = j + 1;
|
||||
} else {
|
||||
i = j;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
} else {
|
||||
/* Decimal entity. */
|
||||
k = j;
|
||||
while ((j < input_len) && (isdigit(input[j]))) j++;
|
||||
if (j > k) { /* Do we have at least one digit? */
|
||||
/* Decode the entity. */
|
||||
char *x = NULL;
|
||||
/* char *x = apr_pstrmemdup(mp,
|
||||
* (const char *)&input[k], j - k); */
|
||||
x = reinterpret_cast<char *>(malloc(sizeof(char) *
|
||||
(j - k)));
|
||||
memcpy(x, (const char *)&input[k], j - k);
|
||||
*d++ = (unsigned char)strtol(x, NULL, 10);
|
||||
count++;
|
||||
free(x);
|
||||
/* Skip over the semicolon if it's there. */
|
||||
if ((j < input_len) && (input[j] == ';')) {
|
||||
i = j + 1;
|
||||
} else {
|
||||
i = j;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Text entity. */
|
||||
|
||||
k = j;
|
||||
while ((j < input_len) && (isalnum(input[j]))) j++;
|
||||
if (j > k) { /* Do we have at least one digit? */
|
||||
/* char *x = apr_pstrmemdup(mp,
|
||||
* (const char *)&input[k], j - k); */
|
||||
char *x = NULL;
|
||||
x = reinterpret_cast<char *>(malloc(sizeof(char) *
|
||||
(j - k)));
|
||||
memcpy(x, (const char *)&input[k], j - k);
|
||||
|
||||
/* Decode the entity. */
|
||||
/* ENH What about others? */
|
||||
if (strcasecmp(x, "quot") == 0) {
|
||||
*d++ = '"';
|
||||
} else if (strcasecmp(x, "amp") == 0) {
|
||||
*d++ = '&';
|
||||
} else if (strcasecmp(x, "lt") == 0) {
|
||||
*d++ = '<';
|
||||
} else if (strcasecmp(x, "gt") == 0) {
|
||||
*d++ = '>';
|
||||
} else if (strcasecmp(x, "nbsp") == 0) {
|
||||
*d++ = NBSP;
|
||||
} else {
|
||||
/* We do no want to convert this entity,
|
||||
* copy the raw data over. */
|
||||
copy = j - k + 1;
|
||||
free(x);
|
||||
goto HTML_ENT_OUT;
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
/* Skip over the semicolon if it's there. */
|
||||
if ((j < input_len) && (input[j] == ';')) {
|
||||
i = j + 1;
|
||||
} else {
|
||||
i = j;
|
||||
}
|
||||
|
||||
free(x);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
HTML_ENT_OUT:
|
||||
for (z = 0; ((z < copy) && (count < input_len)); z++) {
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* IMP1 Assumes NUL-terminated
|
||||
@ -869,138 +609,6 @@ std::string string_to_hex(const std::string& input) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* IMP1 Assumes NUL-terminated
|
||||
*/
|
||||
int urldecode_uni_nonstrict_inplace_ex(Transaction *transaction,
|
||||
unsigned char *input, int64_t input_len, int *changed) {
|
||||
unsigned char *d = input;
|
||||
int64_t i, count, fact, j, xv;
|
||||
int Code, hmap = -1;
|
||||
|
||||
*changed = 0;
|
||||
|
||||
if (input == NULL) return -1;
|
||||
|
||||
i = count = 0;
|
||||
while (i < input_len) {
|
||||
if (input[i] == '%') {
|
||||
if ((i + 1 < input_len) &&
|
||||
((input[i + 1] == 'u') || (input[i + 1] == 'U'))) {
|
||||
/* Character is a percent sign. */
|
||||
/* IIS-specific %u encoding. */
|
||||
if (i + 5 < input_len) {
|
||||
/* We have at least 4 data bytes. */
|
||||
if ((VALID_HEX(input[i + 2])) &&
|
||||
(VALID_HEX(input[i + 3])) &&
|
||||
(VALID_HEX(input[i + 4])) &&
|
||||
(VALID_HEX(input[i + 5]))) {
|
||||
Code = 0;
|
||||
fact = 1;
|
||||
|
||||
if (transaction
|
||||
&& transaction->m_rules->unicode_map_table != NULL
|
||||
&& transaction->m_rules->unicode_codepage > 0) {
|
||||
for (j = 5; j >= 2; j--) {
|
||||
if (isxdigit((input[i+j]))) {
|
||||
if (input[i+j] >= 97) {
|
||||
xv = (input[i+j] - 97) + 10;
|
||||
} else if (input[i+j] >= 65) {
|
||||
xv = (input[i+j] - 65) + 10;
|
||||
} else {
|
||||
xv = (input[i+j]) - 48;
|
||||
}
|
||||
Code += (xv * fact);
|
||||
fact *= 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (Code >= 0 && Code <= 65535) {
|
||||
Rules *r = transaction->m_rules;
|
||||
hmap = r->unicode_map_table[Code];
|
||||
}
|
||||
}
|
||||
|
||||
if (hmap != -1) {
|
||||
*d = hmap;
|
||||
} else {
|
||||
/* We first make use of the lower byte here,
|
||||
* ignoring the higher byte. */
|
||||
*d = x2c(&input[i + 4]);
|
||||
|
||||
/* Full width ASCII (ff01 - ff5e)
|
||||
* needs 0x20 added */
|
||||
if ((*d > 0x00) && (*d < 0x5f)
|
||||
&& ((input[i + 2] == 'f')
|
||||
|| (input[i + 2] == 'F'))
|
||||
&& ((input[i + 3] == 'f')
|
||||
|| (input[i + 3] == 'F'))) {
|
||||
(*d) += 0x20;
|
||||
}
|
||||
}
|
||||
d++;
|
||||
count++;
|
||||
i += 6;
|
||||
*changed = 1;
|
||||
} else {
|
||||
/* Invalid data, skip %u. */
|
||||
*d++ = input[i++];
|
||||
*d++ = input[i++];
|
||||
count += 2;
|
||||
}
|
||||
} else {
|
||||
/* Not enough bytes (4 data bytes), skip %u. */
|
||||
*d++ = input[i++];
|
||||
*d++ = input[i++];
|
||||
count += 2;
|
||||
}
|
||||
} else {
|
||||
/* Standard URL encoding. */
|
||||
/* Are there enough bytes available? */
|
||||
if (i + 2 < input_len) {
|
||||
/* Yes. */
|
||||
|
||||
/* Decode a %xx combo only if it is valid.
|
||||
*/
|
||||
char c1 = input[i + 1];
|
||||
char c2 = input[i + 2];
|
||||
|
||||
if (VALID_HEX(c1) && VALID_HEX(c2)) {
|
||||
*d++ = x2c(&input[i + 1]);
|
||||
count++;
|
||||
i += 3;
|
||||
*changed = 1;
|
||||
} else {
|
||||
/* Not a valid encoding, skip this % */
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
/* Not enough bytes available, skip this % */
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Character is not a percent sign. */
|
||||
if (input[i] == '+') {
|
||||
*d++ = ' ';
|
||||
*changed = 1;
|
||||
} else {
|
||||
*d++ = input[i];
|
||||
}
|
||||
|
||||
count++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
std::string limitTo(int amount, const std::string &str) {
|
||||
std::string ret;
|
||||
|
||||
|
448
src/utils/mbedtls/sha1.c
Normal file
448
src/utils/mbedtls/sha1.c
Normal file
@ -0,0 +1,448 @@
|
||||
/*
|
||||
* FIPS-180-1 compliant SHA-1 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* The SHA-1 standard was published by NIST in 1993.
|
||||
*
|
||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
|
||||
#include "mbedtls/sha1.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#if !defined(MBEDTLS_SHA1_ALT)
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
static void mbedtls_zeroize( void *v, size_t n ) {
|
||||
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_BE
|
||||
#define GET_UINT32_BE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
||||
| ( (uint32_t) (b)[(i) + 3] ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
|
||||
const mbedtls_sha1_context *src )
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 context setup
|
||||
*/
|
||||
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
ctx->state[4] = 0xC3D2E1F0;
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_SHA1_PROCESS_ALT)
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
uint32_t temp, W[16], A, B, C, D, E;
|
||||
|
||||
GET_UINT32_BE( W[ 0], data, 0 );
|
||||
GET_UINT32_BE( W[ 1], data, 4 );
|
||||
GET_UINT32_BE( W[ 2], data, 8 );
|
||||
GET_UINT32_BE( W[ 3], data, 12 );
|
||||
GET_UINT32_BE( W[ 4], data, 16 );
|
||||
GET_UINT32_BE( W[ 5], data, 20 );
|
||||
GET_UINT32_BE( W[ 6], data, 24 );
|
||||
GET_UINT32_BE( W[ 7], data, 28 );
|
||||
GET_UINT32_BE( W[ 8], data, 32 );
|
||||
GET_UINT32_BE( W[ 9], data, 36 );
|
||||
GET_UINT32_BE( W[10], data, 40 );
|
||||
GET_UINT32_BE( W[11], data, 44 );
|
||||
GET_UINT32_BE( W[12], data, 48 );
|
||||
GET_UINT32_BE( W[13], data, 52 );
|
||||
GET_UINT32_BE( W[14], data, 56 );
|
||||
GET_UINT32_BE( W[15], data, 60 );
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define R(t) \
|
||||
( \
|
||||
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
|
||||
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
|
||||
( W[t & 0x0F] = S(temp,1) ) \
|
||||
)
|
||||
|
||||
#define P(a,b,c,d,e,x) \
|
||||
{ \
|
||||
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define K 0x5A827999
|
||||
|
||||
P( A, B, C, D, E, W[0] );
|
||||
P( E, A, B, C, D, W[1] );
|
||||
P( D, E, A, B, C, W[2] );
|
||||
P( C, D, E, A, B, W[3] );
|
||||
P( B, C, D, E, A, W[4] );
|
||||
P( A, B, C, D, E, W[5] );
|
||||
P( E, A, B, C, D, W[6] );
|
||||
P( D, E, A, B, C, W[7] );
|
||||
P( C, D, E, A, B, W[8] );
|
||||
P( B, C, D, E, A, W[9] );
|
||||
P( A, B, C, D, E, W[10] );
|
||||
P( E, A, B, C, D, W[11] );
|
||||
P( D, E, A, B, C, W[12] );
|
||||
P( C, D, E, A, B, W[13] );
|
||||
P( B, C, D, E, A, W[14] );
|
||||
P( A, B, C, D, E, W[15] );
|
||||
P( E, A, B, C, D, R(16) );
|
||||
P( D, E, A, B, C, R(17) );
|
||||
P( C, D, E, A, B, R(18) );
|
||||
P( B, C, D, E, A, R(19) );
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
#define K 0x6ED9EBA1
|
||||
|
||||
P( A, B, C, D, E, R(20) );
|
||||
P( E, A, B, C, D, R(21) );
|
||||
P( D, E, A, B, C, R(22) );
|
||||
P( C, D, E, A, B, R(23) );
|
||||
P( B, C, D, E, A, R(24) );
|
||||
P( A, B, C, D, E, R(25) );
|
||||
P( E, A, B, C, D, R(26) );
|
||||
P( D, E, A, B, C, R(27) );
|
||||
P( C, D, E, A, B, R(28) );
|
||||
P( B, C, D, E, A, R(29) );
|
||||
P( A, B, C, D, E, R(30) );
|
||||
P( E, A, B, C, D, R(31) );
|
||||
P( D, E, A, B, C, R(32) );
|
||||
P( C, D, E, A, B, R(33) );
|
||||
P( B, C, D, E, A, R(34) );
|
||||
P( A, B, C, D, E, R(35) );
|
||||
P( E, A, B, C, D, R(36) );
|
||||
P( D, E, A, B, C, R(37) );
|
||||
P( C, D, E, A, B, R(38) );
|
||||
P( B, C, D, E, A, R(39) );
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) ((x & y) | (z & (x | y)))
|
||||
#define K 0x8F1BBCDC
|
||||
|
||||
P( A, B, C, D, E, R(40) );
|
||||
P( E, A, B, C, D, R(41) );
|
||||
P( D, E, A, B, C, R(42) );
|
||||
P( C, D, E, A, B, R(43) );
|
||||
P( B, C, D, E, A, R(44) );
|
||||
P( A, B, C, D, E, R(45) );
|
||||
P( E, A, B, C, D, R(46) );
|
||||
P( D, E, A, B, C, R(47) );
|
||||
P( C, D, E, A, B, R(48) );
|
||||
P( B, C, D, E, A, R(49) );
|
||||
P( A, B, C, D, E, R(50) );
|
||||
P( E, A, B, C, D, R(51) );
|
||||
P( D, E, A, B, C, R(52) );
|
||||
P( C, D, E, A, B, R(53) );
|
||||
P( B, C, D, E, A, R(54) );
|
||||
P( A, B, C, D, E, R(55) );
|
||||
P( E, A, B, C, D, R(56) );
|
||||
P( D, E, A, B, C, R(57) );
|
||||
P( C, D, E, A, B, R(58) );
|
||||
P( B, C, D, E, A, R(59) );
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
#define K 0xCA62C1D6
|
||||
|
||||
P( A, B, C, D, E, R(60) );
|
||||
P( E, A, B, C, D, R(61) );
|
||||
P( D, E, A, B, C, R(62) );
|
||||
P( C, D, E, A, B, R(63) );
|
||||
P( B, C, D, E, A, R(64) );
|
||||
P( A, B, C, D, E, R(65) );
|
||||
P( E, A, B, C, D, R(66) );
|
||||
P( D, E, A, B, C, R(67) );
|
||||
P( C, D, E, A, B, R(68) );
|
||||
P( B, C, D, E, A, R(69) );
|
||||
P( A, B, C, D, E, R(70) );
|
||||
P( E, A, B, C, D, R(71) );
|
||||
P( D, E, A, B, C, R(72) );
|
||||
P( C, D, E, A, B, R(73) );
|
||||
P( B, C, D, E, A, R(74) );
|
||||
P( A, B, C, D, E, R(75) );
|
||||
P( E, A, B, C, D, R(76) );
|
||||
P( D, E, A, B, C, R(77) );
|
||||
P( C, D, E, A, B, R(78) );
|
||||
P( B, C, D, E, A, R(79) );
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
}
|
||||
#endif /* !MBEDTLS_SHA1_PROCESS_ALT */
|
||||
|
||||
/*
|
||||
* SHA-1 process buffer
|
||||
*/
|
||||
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha1_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
mbedtls_sha1_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
|
||||
static const unsigned char sha1_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-1 final digest
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha1_update( ctx, sha1_padding, padn );
|
||||
mbedtls_sha1_update( ctx, msglen, 8 );
|
||||
|
||||
PUT_UINT32_BE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_BE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_BE( ctx->state[2], output, 8 );
|
||||
PUT_UINT32_BE( ctx->state[3], output, 12 );
|
||||
PUT_UINT32_BE( ctx->state[4], output, 16 );
|
||||
}
|
||||
|
||||
#endif /* !MBEDTLS_SHA1_ALT */
|
||||
|
||||
/*
|
||||
* output = SHA-1( input buffer )
|
||||
*/
|
||||
void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
|
||||
{
|
||||
mbedtls_sha1_context ctx;
|
||||
|
||||
mbedtls_sha1_init( &ctx );
|
||||
mbedtls_sha1_starts( &ctx );
|
||||
mbedtls_sha1_update( &ctx, input, ilen );
|
||||
mbedtls_sha1_finish( &ctx, output );
|
||||
mbedtls_sha1_free( &ctx );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
/*
|
||||
* FIPS-180-1 test vectors
|
||||
*/
|
||||
static const unsigned char sha1_test_buf[3][57] =
|
||||
{
|
||||
{ "abc" },
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
|
||||
{ "" }
|
||||
};
|
||||
|
||||
static const int sha1_test_buflen[3] =
|
||||
{
|
||||
3, 56, 1000
|
||||
};
|
||||
|
||||
static const unsigned char sha1_test_sum[3][20] =
|
||||
{
|
||||
{ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
|
||||
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
|
||||
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
|
||||
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
|
||||
{ 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
|
||||
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
|
||||
};
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
int mbedtls_sha1_self_test( int verbose )
|
||||
{
|
||||
int i, j, buflen, ret = 0;
|
||||
unsigned char buf[1024];
|
||||
unsigned char sha1sum[20];
|
||||
mbedtls_sha1_context ctx;
|
||||
|
||||
mbedtls_sha1_init( &ctx );
|
||||
|
||||
/*
|
||||
* SHA-1
|
||||
*/
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " SHA-1 test #%d: ", i + 1 );
|
||||
|
||||
mbedtls_sha1_starts( &ctx );
|
||||
|
||||
if( i == 2 )
|
||||
{
|
||||
memset( buf, 'a', buflen = 1000 );
|
||||
|
||||
for( j = 0; j < 1000; j++ )
|
||||
mbedtls_sha1_update( &ctx, buf, buflen );
|
||||
}
|
||||
else
|
||||
mbedtls_sha1_update( &ctx, sha1_test_buf[i],
|
||||
sha1_test_buflen[i] );
|
||||
|
||||
mbedtls_sha1_finish( &ctx, sha1sum );
|
||||
|
||||
if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
exit:
|
||||
mbedtls_sha1_free( &ctx );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#endif /* MBEDTLS_SHA1_C */
|
136
src/utils/mbedtls/sha1.h
Normal file
136
src/utils/mbedtls/sha1.h
Normal file
@ -0,0 +1,136 @@
|
||||
/**
|
||||
* \file sha1.h
|
||||
*
|
||||
* \brief SHA-1 cryptographic hash function
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#ifndef MBEDTLS_SHA1_H
|
||||
#define MBEDTLS_SHA1_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if !defined(MBEDTLS_SHA1_ALT)
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[5]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
}
|
||||
mbedtls_sha1_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be initialized
|
||||
*/
|
||||
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be cleared
|
||||
*/
|
||||
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) a SHA-1 context
|
||||
*
|
||||
* \param dst The destination context
|
||||
* \param src The context to be cloned
|
||||
*/
|
||||
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
|
||||
const mbedtls_sha1_context *src );
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief SHA-1 process buffer
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] );
|
||||
|
||||
/* Internal use */
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* MBEDTLS_SHA1_ALT */
|
||||
#include "sha1_alt.h"
|
||||
#endif /* MBEDTLS_SHA1_ALT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( input buffer )
|
||||
*
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] );
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int mbedtls_sha1_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* mbedtls_sha1.h */
|
@ -13,271 +13,43 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/** TODO: Reimplement this on the same terms and/or check if we use it. */
|
||||
/*
|
||||
sha1.cpp - source code of
|
||||
|
||||
============
|
||||
SHA-1 in C++
|
||||
============
|
||||
|
||||
100% Public Domain.
|
||||
|
||||
Original C Code
|
||||
-- Steve Reid <steve@edmweb.com>
|
||||
Small changes to fit into bglibs
|
||||
-- Bruce Guenter <bruce@untroubled.org>
|
||||
Translation to simpler C++ Code
|
||||
-- Volker Grabsch <vog@notjusthosting.com>
|
||||
*/
|
||||
|
||||
#include "src/utils/sha1.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include "src/utils/mbedtls/sha1.h"
|
||||
|
||||
namespace modsecurity {
|
||||
namespace Utils {
|
||||
|
||||
SHA1::SHA1() {
|
||||
reset();
|
||||
|
||||
std::string Sha1::hexdigest(std::string& input) {
|
||||
unsigned char digest[20];
|
||||
|
||||
mbedtls_sha1(reinterpret_cast<const unsigned char *>(input.c_str()),
|
||||
input.size(), digest);
|
||||
|
||||
char buf[41];
|
||||
for (int i=0; i<20; i++) {
|
||||
sprintf(buf+i*2, "%02x", digest[i]);
|
||||
}
|
||||
buf[40] = 0;
|
||||
|
||||
return std::string(buf, 40);
|
||||
}
|
||||
|
||||
|
||||
void SHA1::update(std::string *s) {
|
||||
std::istringstream is(*s);
|
||||
update(&is);
|
||||
std::string Sha1::digest(std::string& input) {
|
||||
unsigned char output[20];
|
||||
std::string ret;
|
||||
|
||||
mbedtls_sha1(reinterpret_cast<const unsigned char *>(input.c_str()),
|
||||
input.size(), output);
|
||||
|
||||
ret.assign(reinterpret_cast<const char *>(output), 20);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void SHA1::update(std::istream *is) {
|
||||
std::string rest_of_buffer;
|
||||
read(is, &rest_of_buffer, BLOCK_BYTES - buffer.size());
|
||||
buffer += rest_of_buffer;
|
||||
|
||||
while (*is) {
|
||||
uint32_t block[BLOCK_INTS];
|
||||
buffer_to_block(buffer, block);
|
||||
transform(block);
|
||||
read(is, &buffer, BLOCK_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string SHA1::final_bin(bool toReset = true) {
|
||||
/* Total number of hashed bits */
|
||||
uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8;
|
||||
|
||||
/* Padding */
|
||||
buffer += 0x80;
|
||||
unsigned int orig_size = buffer.size();
|
||||
while (buffer.size() < BLOCK_BYTES) {
|
||||
buffer += static_cast<char>(0x00);
|
||||
}
|
||||
|
||||
uint32_t block[BLOCK_INTS];
|
||||
buffer_to_block(buffer, block);
|
||||
|
||||
if (orig_size > BLOCK_BYTES - 8) {
|
||||
transform(block);
|
||||
for (unsigned int i = 0; i < BLOCK_INTS - 2; i++) {
|
||||
block[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append total_bits, split this uint64_t into two uint32_t */
|
||||
block[BLOCK_INTS - 1] = total_bits;
|
||||
block[BLOCK_INTS - 2] = (total_bits >> 32);
|
||||
transform(block);
|
||||
|
||||
if (toReset) {
|
||||
/* Reset for next run */
|
||||
reset();
|
||||
}
|
||||
|
||||
std::string bin;
|
||||
bin.append((const char*) digest, BLOCK_INTS);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
|
||||
std::string SHA1::final() {
|
||||
final_bin(false);
|
||||
|
||||
/* Hex std::string */
|
||||
std::ostringstream result;
|
||||
for (unsigned int i = 0; i < DIGEST_INTS; i++) {
|
||||
result << std::hex << std::setfill('0') << std::setw(8);
|
||||
result << (digest[i] & 0xffffffff);
|
||||
}
|
||||
|
||||
/* Reset for next run */
|
||||
reset();
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
||||
void SHA1::reset() {
|
||||
/* SHA1 initialization constants */
|
||||
digest[0] = 0x67452301;
|
||||
digest[1] = 0xefcdab89;
|
||||
digest[2] = 0x98badcfe;
|
||||
digest[3] = 0x10325476;
|
||||
digest[4] = 0xc3d2e1f0;
|
||||
|
||||
/* Reset counters */
|
||||
transforms = 0;
|
||||
buffer = "";
|
||||
}
|
||||
|
||||
|
||||
void SHA1::transform(uint32_t block[BLOCK_BYTES]) {
|
||||
/* Copy digest[] to working vars */
|
||||
uint32_t a = digest[0];
|
||||
uint32_t b = digest[1];
|
||||
uint32_t c = digest[2];
|
||||
uint32_t d = digest[3];
|
||||
uint32_t e = digest[4];
|
||||
|
||||
/* Help macros */
|
||||
#define rol(value, bits) (((value) << (bits)) \
|
||||
| (((value) & 0xffffffff) >> (32 - (bits))))
|
||||
|
||||
#define blk(i) (block[i&15] = rol(block[(i+13)&15] \
|
||||
^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i&15], 1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v, w, x, y, z, i) z += ((w&(x^y))^y) + block[i] \
|
||||
+ 0x5a827999 + rol(v, 5); w = rol(w, 30);
|
||||
#define R1(v, w, x, y, z, i) z += ((w&(x^y))^y) + blk(i) \
|
||||
+ 0x5a827999 + rol(v, 5); w = rol(w, 30);
|
||||
#define R2(v, w, x, y, z, i) z += (w^x^y) + blk(i) \
|
||||
+ 0x6ed9eba1 + rol(v, 5); w = rol(w, 30);
|
||||
#define R3(v, w, x, y, z, i) z += (((w|x)&y)|(w&x)) + blk(i) \
|
||||
+ 0x8f1bbcdc + rol(v, 5); w = rol(w, 30);
|
||||
#define R4(v, w, x, y, z, i) z += (w^x^y) + blk(i) \
|
||||
+ 0xca62c1d6 + rol(v, 5); w = rol(w, 30);
|
||||
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a, b, c, d, e, 0);
|
||||
R0(e, a, b, c, d, 1);
|
||||
R0(d, e, a, b, c, 2);
|
||||
R0(c, d, e, a, b, 3);
|
||||
R0(b, c, d, e, a, 4);
|
||||
R0(a, b, c, d, e, 5);
|
||||
R0(e, a, b, c, d, 6);
|
||||
R0(d, e, a, b, c, 7);
|
||||
R0(c, d, e, a, b, 8);
|
||||
R0(b, c, d, e, a, 9);
|
||||
R0(a, b, c, d, e, 10);
|
||||
R0(e, a, b, c, d, 11);
|
||||
R0(d, e, a, b, c, 12);
|
||||
R0(c, d, e, a, b, 13);
|
||||
R0(b, c, d, e, a, 14);
|
||||
R0(a, b, c, d, e, 15);
|
||||
R1(e, a, b, c, d, 16);
|
||||
R1(d, e, a, b, c, 17);
|
||||
R1(c, d, e, a, b, 18);
|
||||
R1(b, c, d, e, a, 19);
|
||||
R2(a, b, c, d, e, 20);
|
||||
R2(e, a, b, c, d, 21);
|
||||
R2(d, e, a, b, c, 22);
|
||||
R2(c, d, e, a, b, 23);
|
||||
R2(b, c, d, e, a, 24);
|
||||
R2(a, b, c, d, e, 25);
|
||||
R2(e, a, b, c, d, 26);
|
||||
R2(d, e, a, b, c, 27);
|
||||
R2(c, d, e, a, b, 28);
|
||||
R2(b, c, d, e, a, 29);
|
||||
R2(a, b, c, d, e, 30);
|
||||
R2(e, a, b, c, d, 31);
|
||||
R2(d, e, a, b, c, 32);
|
||||
R2(c, d, e, a, b, 33);
|
||||
R2(b, c, d, e, a, 34);
|
||||
R2(a, b, c, d, e, 35);
|
||||
R2(e, a, b, c, d, 36);
|
||||
R2(d, e, a, b, c, 37);
|
||||
R2(c, d, e, a, b, 38);
|
||||
R2(b, c, d, e, a, 39);
|
||||
R3(a, b, c, d, e, 40);
|
||||
R3(e, a, b, c, d, 41);
|
||||
R3(d, e, a, b, c, 42);
|
||||
R3(c, d, e, a, b, 43);
|
||||
R3(b, c, d, e, a, 44);
|
||||
R3(a, b, c, d, e, 45);
|
||||
R3(e, a, b, c, d, 46);
|
||||
R3(d, e, a, b, c, 47);
|
||||
R3(c, d, e, a, b, 48);
|
||||
R3(b, c, d, e, a, 49);
|
||||
R3(a, b, c, d, e, 50);
|
||||
R3(e, a, b, c, d, 51);
|
||||
R3(d, e, a, b, c, 52);
|
||||
R3(c, d, e, a, b, 53);
|
||||
R3(b, c, d, e, a, 54);
|
||||
R3(a, b, c, d, e, 55);
|
||||
R3(e, a, b, c, d, 56);
|
||||
R3(d, e, a, b, c, 57);
|
||||
R3(c, d, e, a, b, 58);
|
||||
R3(b, c, d, e, a, 59);
|
||||
R4(a, b, c, d, e, 60);
|
||||
R4(e, a, b, c, d, 61);
|
||||
R4(d, e, a, b, c, 62);
|
||||
R4(c, d, e, a, b, 63);
|
||||
R4(b, c, d, e, a, 64);
|
||||
R4(a, b, c, d, e, 65);
|
||||
R4(e, a, b, c, d, 66);
|
||||
R4(d, e, a, b, c, 67);
|
||||
R4(c, d, e, a, b, 68);
|
||||
R4(b, c, d, e, a, 69);
|
||||
R4(a, b, c, d, e, 70);
|
||||
R4(e, a, b, c, d, 71);
|
||||
R4(d, e, a, b, c, 72);
|
||||
R4(c, d, e, a, b, 73);
|
||||
R4(b, c, d, e, a, 74);
|
||||
R4(a, b, c, d, e, 75);
|
||||
R4(e, a, b, c, d, 76);
|
||||
R4(d, e, a, b, c, 77);
|
||||
R4(c, d, e, a, b, 78);
|
||||
R4(b, c, d, e, a, 79);
|
||||
|
||||
/* Add the working vars back into digest[] */
|
||||
digest[0] += a;
|
||||
digest[1] += b;
|
||||
digest[2] += c;
|
||||
digest[3] += d;
|
||||
digest[4] += e;
|
||||
|
||||
/* Count the number of transformations */
|
||||
transforms++;
|
||||
}
|
||||
|
||||
|
||||
void SHA1::buffer_to_block(const std::string &buffer,
|
||||
uint32_t block[BLOCK_BYTES]) {
|
||||
/* Convert the std::string (byte buffer) to a uint32_t array (MSB) */
|
||||
for (unsigned int i = 0; i < BLOCK_INTS; i++) {
|
||||
block[i] = (buffer[4 * i + 3] & 0xff)
|
||||
| (buffer[4 * i + 2] & 0xff) << 8
|
||||
| (buffer[4 * i + 1] & 0xff) << 16
|
||||
| (buffer[4 * i + 0] & 0xff) << 24;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SHA1::read(std::istream *is, std::string *s, int k_max) {
|
||||
char sbuf[BLOCK_BYTES];
|
||||
|
||||
if (k_max > BLOCK_BYTES) {
|
||||
return;
|
||||
}
|
||||
|
||||
is->read(sbuf, k_max);
|
||||
s->assign(sbuf, is->gcount());
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace modsecurity
|
||||
|
||||
|
@ -13,23 +13,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/** TODO: Reimplement this on the same terms and/or check if we use it. */
|
||||
/*
|
||||
sha1.h - header of
|
||||
|
||||
============
|
||||
SHA-1 in C++
|
||||
============
|
||||
|
||||
100% Public Domain.
|
||||
|
||||
Original C Code
|
||||
-- Steve Reid <steve@edmweb.com>
|
||||
Small changes to fit into bglibs
|
||||
-- Bruce Guenter <bruce@untroubled.org>
|
||||
Translation to simpler C++ Code
|
||||
-- Volker Grabsch <vog@notjusthosting.com>
|
||||
*/
|
||||
|
||||
#ifndef SRC_UTILS_SHA1_H_
|
||||
#define SRC_UTILS_SHA1_H_
|
||||
@ -41,35 +24,12 @@
|
||||
namespace modsecurity {
|
||||
namespace Utils {
|
||||
|
||||
class SHA1 {
|
||||
class Sha1 {
|
||||
public:
|
||||
SHA1();
|
||||
void update(std::string *s);
|
||||
void update(std::istream *is);
|
||||
std::string final();
|
||||
std::string final_bin() {
|
||||
return final_bin(true);
|
||||
}
|
||||
std::string final_bin(bool reset);
|
||||
Sha1() { }
|
||||
|
||||
private:
|
||||
/* number of 32bit integers per SHA1 digest */
|
||||
static const unsigned int DIGEST_INTS = 5;
|
||||
/* number of 32bit integers per SHA1 block */
|
||||
static const unsigned int BLOCK_INTS = 16;
|
||||
static const unsigned int BLOCK_BYTES = BLOCK_INTS * 4;
|
||||
|
||||
uint32_t digest[DIGEST_INTS];
|
||||
std::string buffer;
|
||||
uint64_t transforms;
|
||||
|
||||
void reset();
|
||||
void transform(uint32_t block[BLOCK_BYTES]);
|
||||
|
||||
static void buffer_to_block(const std::string &buffer,
|
||||
uint32_t block[BLOCK_BYTES]);
|
||||
|
||||
void read(std::istream *is, std::string *s, int max);
|
||||
static std::string hexdigest(std::string& input);
|
||||
static std::string digest(std::string& input);
|
||||
};
|
||||
|
||||
} // namespace Utils
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c3e867bf45248c1f8a31ab4d9c32b9d0c7102ff2
|
||||
Subproject commit aab4a899f6fdc20fe683d1a35195e2b182ceb2f7
|
@ -58,6 +58,37 @@ void replaceAll(std::string *s, const std::string &search,
|
||||
}
|
||||
|
||||
|
||||
void json2bin(std::string *str) {
|
||||
std::regex re("\\\\x([a-z0-9A-Z]{2})");
|
||||
std::regex re2("\\\\u([a-z0-9A-Z]{4})");
|
||||
std::smatch match;
|
||||
|
||||
while (std::regex_search(*str, match, re) && match.size() > 1) {
|
||||
unsigned int p;
|
||||
std::string toBeReplaced = match.str();
|
||||
toBeReplaced.erase(0, 2);
|
||||
sscanf(toBeReplaced.c_str(), "%x", &p);
|
||||
replaceAll(str, match.str(), p);
|
||||
}
|
||||
while (std::regex_search(*str, match, re2) && match.size() > 1) {
|
||||
unsigned int p;
|
||||
std::string toBeReplaced = match.str();
|
||||
toBeReplaced.erase(0, 2);
|
||||
sscanf(toBeReplaced.c_str(), "%4x", &p);
|
||||
replaceAll(str, match.str(), p);
|
||||
}
|
||||
|
||||
/*
|
||||
replaceAll(str, "\\0", '\0');
|
||||
replaceAll(str, "\\b", '\b');
|
||||
replaceAll(str, "\\t", '\t');
|
||||
replaceAll(str, "\\n", '\n');
|
||||
replaceAll(str, "\\r", '\r');
|
||||
*/
|
||||
// replaceAll(str, "\\f", '\f');
|
||||
}
|
||||
|
||||
|
||||
std::string UnitTest::print() {
|
||||
std::stringstream i;
|
||||
|
||||
@ -99,27 +130,7 @@ UnitTest *UnitTest::from_yajl_node(yajl_val &node) {
|
||||
u->param = YAJL_GET_STRING(val);
|
||||
} else if (strcmp(key, "input") == 0) {
|
||||
u->input = YAJL_GET_STRING(val);
|
||||
/*
|
||||
* Converting \\u0000 to \0 due to the following gcc bug:
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53690
|
||||
*
|
||||
*/
|
||||
replaceAll(&(u->input), "\\0", '\0');
|
||||
replaceAll(&(u->input), "\\xe4", '\xe4');
|
||||
replaceAll(&(u->input), "\\x03", '\x03');
|
||||
replaceAll(&(u->input), "\\xbf", '\xbf');
|
||||
replaceAll(&(u->input), "\\xc9", '\xc9');
|
||||
replaceAll(&(u->input), "\\x3b", '\x3b');
|
||||
replaceAll(&(u->input), "\\xFF", '\xff');
|
||||
replaceAll(&(u->input), "\\u0000", '\0');
|
||||
replaceAll(&(u->input), "\\u0001", '\u0001');
|
||||
replaceAll(&(u->input), "\\u0002", '\u0002');
|
||||
replaceAll(&(u->input), "\\u0003", '\u0003');
|
||||
replaceAll(&(u->input), "\\u0004", '\u0004');
|
||||
replaceAll(&(u->input), "\\u0005", '\u0005');
|
||||
replaceAll(&(u->input), "\\u0006", '\u0006');
|
||||
replaceAll(&(u->input), "\\u0007", '\u0007');
|
||||
replaceAll(&(u->input), "\\b", '\b');
|
||||
json2bin(&u->input);
|
||||
} else if (strcmp(key, "name") == 0) {
|
||||
u->name = YAJL_GET_STRING(val);
|
||||
} else if (strcmp(key, "type") == 0) {
|
||||
@ -128,23 +139,12 @@ UnitTest *UnitTest::from_yajl_node(yajl_val &node) {
|
||||
u->ret = YAJL_GET_INTEGER(val);
|
||||
} else if (strcmp(key, "output") == 0) {
|
||||
u->output = std::string(YAJL_GET_STRING(val));
|
||||
std::string *in = &u->output;
|
||||
json2bin(&u->output);
|
||||
/*
|
||||
* Converting \\u0000 to \0 due to the following gcc bug:
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53690
|
||||
*
|
||||
*/
|
||||
std::regex re("\\\\x([a-z0-9A-Z]{2})");
|
||||
std::smatch match;
|
||||
while (std::regex_search(*in, match, re) && match.size() > 1) {
|
||||
unsigned int p;
|
||||
std::string toBeReplaced = match.str();
|
||||
toBeReplaced.erase(0, 2);
|
||||
sscanf(toBeReplaced.c_str(), "%x", &p);
|
||||
replaceAll(in, match.str(), p);
|
||||
}
|
||||
replaceAll(&(u->output), "\\u0000", '\0');
|
||||
replaceAll(&(u->output), "\\0", '\0');
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user