Skip to content

Commit 831e598

Browse files
author
Felipe Zimmerle
committed
Optimization on the status engine call
The status string was too long. By removing meaningless stuff, such as: runtime version of Lua, we have reduced the length of the status string. Limitations were also placed regarding the size of the ModSecurity version. Big queries may lead to failure, due to restrictions of "gethostbyname". There is also a bit of code cosmetics in this patch: big functions were broken into smaller.
1 parent dcc63a3 commit 831e598

File tree

1 file changed

+149
-92
lines changed

1 file changed

+149
-92
lines changed

Diff for: apache2/msc_status_engine.c

+149-92
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
#include <sys/utsname.h>
3030
#include <sys/types.h>
3131
#include <sys/socket.h>
32-
#if ! defined(IFT_ETHER)
33-
#define IFT_ETHER 0x6/* Ethernet CSMACD */
32+
#ifndef IFT_ETHER
33+
#define IFT_ETHER 0x6 /* Ethernet CSMACD */
3434
#endif
3535
#endif
3636

@@ -42,7 +42,7 @@
4242

4343
// Bese32 encode, based on:
4444
// https://code.google.com/p/google-authenticator/source/browse/libpam/base32.c
45-
void DSOLOCAL msc_status_engine_base32_encode(char *encoded,
45+
int DSOLOCAL msc_status_engine_base32_encode(char *encoded,
4646
const char *data, int len) {
4747
int buffer;
4848
int count = 0;
@@ -51,6 +51,11 @@ void DSOLOCAL msc_status_engine_base32_encode(char *encoded,
5151

5252
buffer = data[0];
5353

54+
if (encoded == NULL && len == 0) {
55+
len = length * 3;
56+
count++;
57+
}
58+
5459
if (length > 0) {
5560
int next = 1;
5661
int bitsLeft = 8;
@@ -69,27 +74,48 @@ void DSOLOCAL msc_status_engine_base32_encode(char *encoded,
6974
}
7075
index = 0x1f & (buffer >> (bitsLeft - 5));
7176
bitsLeft -= 5;
72-
result[count++] = msc_status_engine_basis_32[index];
77+
if (encoded != NULL) {
78+
result[count] = msc_status_engine_basis_32[index];
79+
}
80+
count++;
7381
}
7482
}
75-
if (count < len) {
83+
if (count < len && encoded != NULL) {
7684
result[count] = '\000';
7785
}
86+
87+
return count;
7888
}
7989

80-
void DSOLOCAL msc_status_engine_fill_with_dots(char *encoded_with_dots,
90+
int DSOLOCAL msc_status_engine_fill_with_dots(char *encoded_with_dots,
8191
const char *data, int len, int space)
8292
{
8393
int i;
8494
int count = 0;
8595

96+
if (encoded_with_dots == NULL) {
97+
if (len == 0 && data != NULL) {
98+
len = strlen(data);
99+
}
100+
else if (len == 0 && data == NULL) {
101+
count = -1;
102+
goto return_length;
103+
}
104+
105+
count = len/space + len + 1;
106+
goto return_length;
107+
}
108+
86109
for (i = 0; i < strlen(data) && i < len; i++) {
87110
if (i % space == 0 && i != 0) {
88111
encoded_with_dots[count++] = '.';
89112
}
90113
encoded_with_dots[count++] = data[i];
91114
}
92115
encoded_with_dots[count] = '\0';
116+
117+
return_length:
118+
return count;
93119
}
94120

95121

@@ -103,7 +129,9 @@ int DSOLOCAL msc_status_engine_machine_name(char *machine_name, size_t len) {
103129
memset(machine_name, '\0', sizeof(char) * len);
104130

105131
#ifdef WIN32
106-
GetComputerName(machine_name, &lenComputerName);
132+
if (GetComputerName(machine_name, &lenComputerName) == 0) {
133+
goto failed;
134+
}
107135
#else
108136
static struct utsname u;
109137

@@ -227,7 +255,6 @@ int DSOLOCAL msc_status_engine_mac_address (unsigned char *mac)
227255
free(pAdapterInfo);
228256
#endif
229257

230-
done:
231258
return 0;
232259

233260
failed:
@@ -296,137 +323,167 @@ int DSOLOCAL msc_status_engine_unique_id (unsigned char *digest)
296323
return ret;
297324
}
298325

299-
int msc_status_engine_call (void) {
326+
int DSOLOCAL msc_beacon_string (char *beacon_string, int beacon_string_max_len) {
300327
char *apr = NULL;
301328
const char *apr_loaded = NULL;
302329
char pcre[7];
303330
const char *pcre_loaded = NULL;
304331
char *lua = NULL;
305-
char *lua_loaded = NULL;
306332
char *libxml = NULL;
307-
char *libxml_loaded = NULL;
308333
char *modsec = NULL;
309334
const char *apache = NULL;
310-
char *id = NULL;
311-
char *beacon_string = NULL;
312-
int beacon_string_len = 0;
313-
char *beacon_string_encoded = NULL;
314-
char *beacon_string_ready = NULL;
315-
char *beacon_string_encoded_splitted = NULL;
316-
int ret = 0;
335+
char id[(APR_SHA1_DIGESTSIZE*2) + 1];
336+
int beacon_string_len = -1;
317337

318338
apr = APR_VERSION_STRING;
319339
apr_loaded = apr_version_string();
320-
340+
apr_snprintf(pcre, 7, "%d.%d", PCRE_MAJOR, PCRE_MINOR);
321341
pcre_loaded = pcre_version();
322-
apr_snprintf(pcre, 7, "%2d.%2d ", PCRE_MAJOR, PCRE_MINOR);
323342
#ifdef WITH_LUA
324343
lua = LUA_VERSION;
325344
#endif
326-
lua_loaded = 0;
327-
328345
libxml = LIBXML_DOTTED_VERSION;
329-
libxml_loaded = 0;
330-
331346
modsec = MODSEC_VERSION;
347+
#ifdef WIN32
348+
apache = "IIS";
349+
#else
332350
apache = apache_get_server_version();
351+
#endif
333352

334-
id = malloc(sizeof(char)*((2*APR_SHA1_DIGESTSIZE)+1));
335-
if (!id) {
336-
ret = -1;
337-
goto failed_id;
353+
/* 6 represents: strlen("(null)") */
354+
beacon_string_len = (modsec ? strlen(modsec) : 6) +
355+
(apache ? strlen(apache) : 6) + (apr ? strlen(apr) : 6) +
356+
(apr_loaded ? strlen(apr_loaded) : 6) + (pcre ? strlen(pcre) : 6) +
357+
(pcre_loaded ? strlen(pcre_loaded) : 6) + (lua ? strlen(lua) : 6) +
358+
(libxml ? strlen(libxml) : 6) + (APR_SHA1_DIGESTSIZE * 2);
359+
360+
beacon_string_len = beacon_string_len + /* null terminator: */ 1 +
361+
/* comma: */ 6 +
362+
/* slash: */ 2;
363+
364+
if (beacon_string == NULL || beacon_string_max_len == 0) {
365+
goto return_length;
338366
}
339367

340-
memset(id, '\0', sizeof(char)*((2*APR_SHA1_DIGESTSIZE)+1));
368+
memset(id, '\0', sizeof(char)*((2 * APR_SHA1_DIGESTSIZE) + /* \0: */ 1));
341369
if (msc_status_engine_unique_id(id)) {
342370
sprintf(id, "unique id failed");
343371
}
344372

345-
beacon_string_len = (modsec ? strlen(modsec) : 6) + (apache ? strlen(apache) : 6) +
346-
(apr ? strlen(apr) : 6) + (apr_loaded ? strlen(apr_loaded) : 6) +
347-
(pcre ? strlen(pcre) : 6) + (pcre_loaded ? strlen(pcre_loaded) : 6) +
348-
(lua ? strlen(lua) : 6) + (lua_loaded ? strlen(lua_loaded) : 6) +
349-
(libxml ? strlen(libxml) : 6) + (libxml_loaded ? strlen(libxml_loaded) : 6) +
350-
(id ? strlen(id) : 6);
373+
apr_snprintf(beacon_string, beacon_string_max_len,
374+
"%.25s,%s,%s/%s,%s/%s,%s,%s,%s",
375+
modsec, apache, apr, apr_loaded, pcre, pcre_loaded, lua, libxml, id);
351376

352-
#ifdef WIN32
353-
beacon_string = malloc(sizeof(char)*(beacon_string_len+1+10+4));
354-
if (!beacon_string) {
355-
goto failed_beacon_string;
377+
return_length:
378+
return beacon_string_len;
379+
}
380+
381+
int DSOLOCAL msc_status_engine_prepare_hostname (char *hostname, const char *plain_data,
382+
int max_length)
383+
{
384+
int str_enc_len = 0;
385+
int str_enc_spl_len = 0;
386+
char *tmp = NULL;
387+
int length = -1;
388+
389+
str_enc_len = msc_status_engine_base32_encode(NULL, plain_data, 0);
390+
391+
str_enc_spl_len = msc_status_engine_fill_with_dots(NULL, NULL, str_enc_len,
392+
STATUS_ENGINE_DNS_IN_BETWEEN_DOTS);
393+
if (str_enc_spl_len < 0) {
394+
goto failed_enc_spl_len;
356395
}
357396

358-
apr_snprintf(beacon_string, beacon_string_len+1+10+4,
359-
"%s,IIS,%s/%s,%s/%s,%s/%s,%s/%s,%s",
360-
modsec, apr, apr_loaded, pcre, pcre_loaded, lua, lua_loaded,
361-
libxml, libxml_loaded, id);
362-
#else
363-
beacon_string = malloc(sizeof(char)*(beacon_string_len+1+10));
364-
if (!beacon_string) {
365-
goto failed_beacon_string;
397+
length = str_enc_spl_len + strlen(STATUS_ENGINE_DNS_SUFFIX) +
398+
/* epoch: */ 10 + /* dots: */ 2 + /* terminator: */ 1 -
399+
/* removed unsed terminators from str_enc and str_enc_spl: */ 2;
400+
401+
if (hostname == NULL || max_length == 0) {
402+
goto return_length;
366403
}
367404

368-
apr_snprintf(beacon_string, beacon_string_len+1+10,
369-
"%s,%s,%s/%s,%s/%s,%s/%s,%s/%s,%s",
370-
modsec, apache, apr, apr_loaded, pcre, pcre_loaded, lua, lua_loaded,
371-
libxml, libxml_loaded, id);
372-
#endif
405+
memset(hostname, '\0', sizeof(char) * max_length);
373406

374-
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
375-
"ModSecurity: StatusEngine call: \"%s\"", beacon_string);
407+
msc_status_engine_base32_encode(hostname, plain_data, str_enc_len);
376408

377-
beacon_string_encoded = malloc(sizeof(char)*(strlen(beacon_string)*3));
378-
if (!beacon_string_encoded) {
379-
goto failed_beacon_string_encoded;
409+
tmp = strdup(hostname);
410+
if (tmp == NULL) {
411+
length = -1;
412+
goto failed_strdup;
380413
}
381-
msc_status_engine_base32_encode(beacon_string_encoded, beacon_string,
382-
strlen(beacon_string)*3);
383414

384-
beacon_string_encoded_splitted = malloc (sizeof(char) *
385-
((strlen(beacon_string_encoded)/STATUS_ENGINE_DNS_IN_BETWEEN_DOTS) +
386-
strlen(beacon_string_encoded) + 1 + 1));
387-
if (!beacon_string_encoded_splitted) {
388-
goto failed_beacon_string_encoded_splitted;
415+
str_enc_spl_len = msc_status_engine_fill_with_dots(hostname, tmp, max_length,
416+
STATUS_ENGINE_DNS_IN_BETWEEN_DOTS);
417+
if (str_enc_spl_len < 0) {
418+
length = -1;
419+
goto failed_enc_spl;
389420
}
390421

391-
msc_status_engine_fill_with_dots(beacon_string_encoded_splitted,
392-
beacon_string_encoded,
393-
(strlen(beacon_string_encoded)/STATUS_ENGINE_DNS_IN_BETWEEN_DOTS) +
394-
strlen(beacon_string_encoded) + 1 + 1,
395-
STATUS_ENGINE_DNS_IN_BETWEEN_DOTS);
422+
apr_snprintf(hostname, max_length, "%s.%lu.%s", hostname, time(NULL),
423+
STATUS_ENGINE_DNS_SUFFIX);
396424

397-
beacon_string_ready = malloc (sizeof(char) *
398-
strlen(beacon_string_encoded_splitted) +
399-
strlen(STATUS_ENGINE_DNS_SUFFIX) + 10 + 1);
425+
failed_enc_spl:
426+
free(tmp);
427+
failed_strdup:
428+
return_length:
429+
failed_enc_spl_len:
430+
return length;
431+
}
400432

401-
if (!beacon_string_ready) {
402-
goto failed_beacon_string_ready;
433+
int msc_status_engine_call (void) {
434+
char *beacon_str = NULL;
435+
int beacon_str_len = 0;
436+
char *hostname = NULL;
437+
int hostname_len = 0;
438+
int ret = -1;
439+
440+
/* Retrieve the beacon string */
441+
beacon_str_len = msc_beacon_string(NULL, 0);
442+
443+
beacon_str = malloc(sizeof(char) * beacon_str_len);
444+
if (beacon_str == NULL) {
445+
goto failed_beacon_string_malloc;
403446
}
447+
msc_beacon_string(beacon_str, beacon_str_len);
404448

405-
apr_snprintf(beacon_string_ready, strlen(beacon_string_encoded_splitted) +
406-
strlen(STATUS_ENGINE_DNS_SUFFIX) + 12 + 1, "%s.%lu.%s",
407-
beacon_string_encoded_splitted, time(NULL),
408-
STATUS_ENGINE_DNS_SUFFIX);
449+
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
450+
"ModSecurity: StatusEngine call: \"%s\"", beacon_str);
409451

410-
if (gethostbyname(beacon_string_ready)) {
452+
/* Get beacon string in the format of a hostname */
453+
hostname_len = msc_status_engine_prepare_hostname(NULL, beacon_str, 0);
454+
if (hostname_len < 0) {
455+
goto failed_hostname_len;
456+
}
457+
458+
hostname = malloc(sizeof(char) * hostname_len);
459+
if (hostname == NULL) {
460+
goto failed_hostname_malloc;
461+
}
462+
hostname_len = msc_status_engine_prepare_hostname(hostname, beacon_str,
463+
hostname_len);
464+
if (hostname_len < 0) {
465+
goto failed_hostname;
466+
}
467+
468+
/* Perform the DNS query. */
469+
if (gethostbyname(hostname)) {
411470
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
412471
"ModSecurity: StatusEngine call successfully sent. For more " \
413472
"information visit: http://%s/", STATUS_ENGINE_DNS_SUFFIX);
414473
} else {
415474
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
416475
"ModSecurity: StatusEngine call failed. Query: %s",
417-
beacon_string_ready);
418-
}
419-
420-
free(beacon_string_ready);
421-
failed_beacon_string_ready:
422-
free(beacon_string_encoded_splitted);
423-
failed_beacon_string_encoded_splitted:
424-
free(beacon_string_encoded);
425-
failed_beacon_string_encoded:
426-
free(beacon_string);
427-
failed_beacon_string:
428-
free(id);
429-
failed_id:
476+
hostname);
477+
}
478+
479+
ret = 0;
480+
481+
failed_hostname:
482+
free(hostname);
483+
failed_hostname_malloc:
484+
failed_hostname_len:
485+
free(beacon_str);
486+
failed_beacon_string_malloc:
430487

431488
return ret;
432489
}

0 commit comments

Comments
 (0)