[core] $HTTP["remoteip"] must handle IPv6 w/o []

[core] $HTTP["remoteip"] must handle IPv6 w/o [] (existing behavior)
This was inadvertently broken in lighttpd 1.4.40 when IP address
normalization was added.

In $HTTP["remoteip"], IPv6 is now accepted with or without '[]'.
http_request_host_normalize() expects IPv6 with '[]', and config
processing at runtime expects COMP_HTTP_REMOTE_IP compared without '[]',
so '[]' is stripped (internally) after normalization
This commit is contained in:
Glenn Strauss 2016-07-21 01:42:35 -04:00
parent cb468d333c
commit cd33554b74
1 changed files with 41 additions and 6 deletions

View File

@ -114,6 +114,34 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
return op1;
}
static int configparser_remoteip_normalize_compat(buffer *rvalue) {
/* $HTTP["remoteip"] IPv6 accepted with or without '[]' for config compat
* http_request_host_normalize() expects IPv6 with '[]',
* and config processing at runtime expects COMP_HTTP_REMOTE_IP
* compared without '[]', so strip '[]' after normalization */
buffer *b = buffer_init();
int rc;
if (rvalue->ptr[0] != '[') {
buffer_append_string_len(b, CONST_STR_LEN("["));
buffer_append_string_buffer(b, rvalue);
buffer_append_string_len(b, CONST_STR_LEN("]"));
} else {
buffer_append_string_buffer(b, rvalue);
}
rc = http_request_host_normalize(b);
if (0 == rc) {
/* remove surrounding '[]' */
size_t blen = buffer_string_length(b);
if (blen > 1) buffer_copy_string_len(rvalue, b->ptr+1, blen-2);
}
buffer_free(b);
return rc;
}
}
%parse_failure {
@ -483,12 +511,14 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio
}
else if (COMP_HTTP_REMOTE_IP == dc->comp
&& (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE)) {
char * const slash = strchr(rvalue->ptr, '/');
if (NULL != slash && slash != rvalue->ptr){/*(skip AF_UNIX /path/file)*/
char * const slash = strchr(rvalue->ptr, '/'); /* CIDR mask */
char * const colon = strchr(rvalue->ptr, ':'); /* IPv6 */
if (NULL != slash && slash == rvalue->ptr){/*(skip AF_UNIX /path/file)*/
}
else if (NULL != slash) {
char *nptr;
const unsigned long nm_bits = strtoul(slash + 1, &nptr, 10);
if (*nptr || 0 == nm_bits
|| nm_bits > (rvalue->ptr[0] == '[' ? 128 : 32)) {
if (*nptr || 0 == nm_bits || nm_bits > (NULL != colon ? 128 : 32)) {
/*(also rejects (slash+1 == nptr) which results in nm_bits = 0)*/
fprintf(stderr, "invalid or missing netmask: %s\n", rvalue->ptr);
ctx->ok = 0;
@ -496,7 +526,9 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio
else {
int rc;
buffer_string_set_length(rvalue, (size_t)(slash - rvalue->ptr)); /*(truncate)*/
rc = http_request_host_normalize(rvalue);
rc = (NULL == colon)
? http_request_host_normalize(rvalue)
: configparser_remoteip_normalize_compat(rvalue);
buffer_append_string_len(rvalue, CONST_STR_LEN("/"));
buffer_append_int(rvalue, (int)nm_bits);
if (0 != rc) {
@ -506,7 +538,10 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio
}
}
else {
if (http_request_host_normalize(rvalue)) {
int rc = (NULL == colon)
? http_request_host_normalize(rvalue)
: configparser_remoteip_normalize_compat(rvalue);
if (0 != rc) {
fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
ctx->ok = 0;
}