aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/includes/acp/acp_users.php2
-rw-r--r--phpBB/includes/functions.php182
-rw-r--r--phpBB/includes/session.php18
-rw-r--r--phpBB/install/database_update.php7
-rw-r--r--phpBB/install/install_install.php3
5 files changed, 207 insertions, 5 deletions
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index 79c594ed6d..006c3617f7 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -56,7 +56,7 @@ class acp_users
$this->page_title = 'WHOIS';
$this->tpl_name = 'simple_body';
- $user_ip = request_var('user_ip', '');
+ $user_ip = phpbb_ip_normalise(request_var('user_ip', ''));
$domain = gethostbyaddr($user_ip);
$ipwhois = user_ipwhois($user_ip);
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 285c3938c1..41dad77141 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -3281,6 +3281,188 @@ function short_ipv6($ip, $length)
}
/**
+* Normalises an internet protocol address,
+* also checks whether the specified address is valid.
+*
+* IPv4 addresses are returned 'as is'.
+*
+* IPv6 addresses are normalised according to
+* A Recommendation for IPv6 Address Text Representation
+* http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07
+*
+* @param string $address IP address
+*
+* @return mixed false if specified address is not valid,
+* string otherwise
+*
+* @author bantu
+*/
+function phpbb_ip_normalise($address)
+{
+ $address = trim($address);
+
+ if (empty($address) || !is_string($address))
+ {
+ return false;
+ }
+
+ if (preg_match(get_preg_expression('ipv4'), $address))
+ {
+ return $address;
+ }
+
+ return phpbb_inet_ntop(phpbb_inet_pton($address));
+}
+
+/**
+* Wrapper for inet_ntop()
+*
+* Converts a packed internet address to a human readable representation
+* inet_ntop() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
+*
+* @param string $in_addr A 32bit IPv4, or 128bit IPv6 address.
+*
+* @return mixed false on failure,
+* string otherwise
+*
+* @author APTX
+*/
+function phpbb_inet_ntop($in_addr)
+{
+ $in_addr = bin2hex($in_addr);
+
+ switch (strlen($in_addr))
+ {
+ case 8:
+ return implode('.', array_map('hexdec', str_split($in_addr, 2)));
+
+ case 32:
+ if (substr($in_addr, 0, 24) === '00000000000000000000ffff')
+ {
+ return phpbb_inet_ntop(pack('H*', substr($in_addr, 24)));
+ }
+
+ $parts = str_split($in_addr, 4);
+ $parts = preg_replace('/^0+(?!$)/', '', $parts);
+ $ret = implode(':', $parts);
+
+ $matches = array();
+ preg_match_all('/(?<=:|^)(?::?0){2,}/', $ret, $matches, PREG_OFFSET_CAPTURE);
+ $matches = $matches[0];
+
+ if (empty($matches))
+ {
+ return $ret;
+ }
+
+ $longest_match = '';
+ $longest_match_offset = 0;
+ foreach ($matches as $match)
+ {
+ if (strlen($match[0]) > strlen($longest_match))
+ {
+ $longest_match = $match[0];
+ $longest_match_offset = $match[1];
+ }
+ }
+
+ $ret = substr_replace($ret, '', $longest_match_offset, strlen($longest_match));
+
+ if ($longest_match_offset == strlen($ret))
+ {
+ $ret .= ':';
+ }
+
+ if ($longest_match_offset == 0)
+ {
+ $ret = ':' . $ret;
+ }
+
+ return $ret;
+
+ default:
+ return false;
+ }
+}
+
+/**
+* Wrapper for inet_pton()
+*
+* Converts a human readable IP address to its packed in_addr representation
+* inet_pton() is supported by PHP since 5.1.0, since 5.3.0 also on Windows.
+*
+* @param string $address A human readable IPv4 or IPv6 address.
+*
+* @return mixed false if address is invalid,
+* in_addr representation of the given address otherwise (string)
+*
+* @author APTX
+*/
+function phpbb_inet_pton($address)
+{
+ $ret = '';
+ if (preg_match(get_preg_expression('ipv4'), $address))
+ {
+ foreach (explode('.', $address) as $part)
+ {
+ $ret .= ($part <= 0xF ? '0' : '') . dechex($part);
+ }
+
+ return pack('H*', $ret);
+ }
+
+ if (preg_match(get_preg_expression('ipv6'), $address))
+ {
+ $parts = explode(':', $address);
+ $missing_parts = 8 - sizeof($parts) + 1;
+
+ if (substr($address, 0, 2) === '::')
+ {
+ ++$missing_parts;
+ }
+
+ if (substr($address, -2) === '::')
+ {
+ ++$missing_parts;
+ }
+
+ $embedded_ipv4 = false;
+ $last_part = end($parts);
+
+ if (preg_match(get_preg_expression('ipv4'), $last_part))
+ {
+ $parts[sizeof($parts) - 1] = '';
+ $last_part = phpbb_inet_pton($last_part);
+ $embedded_ipv4 = true;
+ --$missing_parts;
+ }
+
+ foreach ($parts as $i => $part)
+ {
+ if (strlen($part))
+ {
+ $ret .= str_pad($part, 4, '0', STR_PAD_LEFT);
+ }
+ else if ($i && $i < sizeof($parts) - 1)
+ {
+ $ret .= str_repeat('0000', $missing_parts);
+ }
+ }
+
+ $ret = pack('H*', $ret);
+
+ if ($embedded_ipv4)
+ {
+ $ret .= $last_part;
+ }
+
+ return $ret;
+ }
+
+ return false;
+}
+
+/**
* Wrapper for php's checkdnsrr function.
*
* @param string $host Fully-Qualified Domain Name
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 0f1b1314c2..c4cc17d2a4 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -279,6 +279,24 @@ class session
foreach ($ips as $ip)
{
+ if (function_exists('phpbb_ip_normalise'))
+ {
+ // Normalise IP address
+ $ip = phpbb_ip_normalise($ip);
+
+ if (empty($ip))
+ {
+ // IP address is invalid.
+ break;
+ }
+
+ // IP address is valid.
+ $this->ip = $ip;
+
+ // Skip legacy code.
+ continue;
+ }
+
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
{
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index 9aa7a34f6b..b33c0f4a11 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -127,8 +127,11 @@ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
// We do not need this any longer, unset for safety purposes
unset($dbpasswd);
-$user->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
-$user->ip = (stripos($user->ip, '::ffff:') === 0) ? substr($user->ip, 7) : $user->ip;
+$user->ip = '';
+if (!empty($_SERVER['REMOTE_ADDR']))
+{
+ $user->ip = (function_exists('phpbb_ip_normalise')) ? phpbb_ip_normalise($_SERVER['REMOTE_ADDR']) : htmlspecialchars($_SERVER['REMOTE_ADDR']);
+}
$sql = "SELECT config_value
FROM " . CONFIG_TABLE . "
diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php
index eaad2ed7e0..8143ea7737 100644
--- a/phpBB/install/install_install.php
+++ b/phpBB/install/install_install.php
@@ -1235,8 +1235,7 @@ class install_install extends module
$current_time = time();
- $user_ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
- $user_ip = (stripos($user_ip, '::ffff:') === 0) ? substr($user_ip, 7) : $user_ip;
+ $user_ip = (!empty($_SERVER['REMOTE_ADDR'])) ? phpbb_ip_normalise($_SERVER['REMOTE_ADDR']) : '';
if ($data['script_path'] !== '/')
{