Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow CIDR/Netmask notation, allow commments after IP #155

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions admin/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,43 @@ public function sanitize_ip_addresses( $val ) {
*/
private function validate_ip_address( $ip_address ) {

return filter_var( $ip_address, FILTER_VALIDATE_IP );
$ip = trim(explode("#",$ip_address)[0]); // allow for comments after ip

if ($this->is_ip($ip)) {
return trim($ip_address);
}
else {
return "";
}

}

/**
* Is it a valid IP address? v4/v6 with subnet range.
*
* @param string $ip_address IP Address to check.
*
* @return bool True if its a valid IP address.
*/
private function is_ip( $ip_address ) {
// very basic validation of ranges.
if ( strpos( $ip_address, '/' ) ) {
$ip_parts = explode( '/', $ip_address );
if ( empty( $ip_parts[1] ) || ! is_numeric( $ip_parts[1] ) || strlen( $ip_parts[1] ) > 3 ) {
return false;
}
$ip_address = $ip_parts[0];
}

// confirm IP part is a valid IPv6 or IPv4 IP.
if ( empty( $ip_address ) || ! inet_pton( stripslashes( $ip_address ) ) ) {
return false;
}

return true;
}


/**
* Password Protected Section
*/
Expand Down Expand Up @@ -282,9 +315,9 @@ public function password_protected_password_field() {
*/
public function password_protected_allowed_ip_addresses_field() {

echo '<textarea name="password_protected_allowed_ip_addresses" id="password_protected_allowed_ip_addresses" rows="3" class="large-text" />' . get_option( 'password_protected_allowed_ip_addresses' ) . '</textarea>';
echo '<textarea name="password_protected_allowed_ip_addresses" id="password_protected_allowed_ip_addresses" rows="20" class="large-text" />' . get_option( 'password_protected_allowed_ip_addresses' ) . '</textarea>';

echo '<p class="description">' . esc_html__( 'Enter one IP address per line.', 'password-protected' );
echo '<p class="description">' . esc_html__( 'Enter one IP address per line. (IP/CIDR netmask notation is allowed eg. 127.0.0.0/24, comments are allowed after IP eg. 127.0.0.1 #Comment)', 'password-protected' );
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
echo ' ' . esc_html( sprintf( __( 'Your IP is address %s.', 'password-protected' ), $_SERVER['REMOTE_ADDR'] ) );
}
Expand Down
35 changes: 33 additions & 2 deletions password-protected.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,27 @@ public function allow_users( $bool ) {

}

/**
* Check if a given ip is in a network.
* Source: https://gist.github.com/tott/7684443
*
* @param string $ip IP to check in IPV4 format eg. 127.0.0.1.
* @param string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed.
* @return boolean true if the ip is in this range / false if not.
*/
public static function ip_in_range( $ip, $range ) {
if ( strpos( $range, '/' ) === false ) {
$range .= '/32';
}
// $range is in IP/CIDR format eg 127.0.0.1/24
list( $range, $netmask ) = explode( '/', $range, 2 );
$range_decimal = ip2long( $range );
$ip_decimal = ip2long( $ip );
$wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1;
$netmask_decimal = ~ $wildcard_decimal;
return ( ( $ip_decimal & $netmask_decimal ) === ( $range_decimal & $netmask_decimal ) );
}

/**
* Allow IP Addresses
*
Expand All @@ -226,8 +247,18 @@ public function allow_ip_addresses( $bool ) {

$ip_addresses = $this->get_allowed_ip_addresses();

if ( isset( $_SERVER['REMOTE_ADDR'] ) && in_array( $_SERVER['REMOTE_ADDR'], $ip_addresses ) ) {
$bool = false;
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {

$remote_ip = $_SERVER['REMOTE_ADDR'];

// iterate through the allow list.
foreach ( $ip_addresses as $line ) {
$line = trim(explode("#",$line)[0]); // allow for comments after ip
if ( $this->ip_in_range( $remote_ip, $line ) ) {
$bool = false;
}
}

}

return $bool;
Expand Down