. */ /** * Methods return this if they succeed */ if (@defined('AA_PP_DEBUG')) return; define('AA_PP_DEBUG', 0); /** * Methods return this if they succeed */ define('ACLF', chr(13) . chr(10)); register_activation_hook(__FILE__, 'aa_pp_activate'); register_deactivation_hook(__FILE__, 'aa_pp_deactivate'); add_action('admin_menu', 'aa_pp_setup_options'); if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) add_action('admin_head', 'aa_pp_admin_header'); /** * aa_pp_admin_header() * * @return */ function aa_pp_admin_header() { global $wpdb, $aa_PP, $aa_SIDS; if (!current_user_can(8)) die(__("You are not allowed to be here without upload permissions")); if (!user_can_access_admin_page()) { do_action('admin_page_access_denied'); wp_die(__('You do not have sufficient permissions to access this page.')); } $aa_PP = get_option('askapache_password_protect'); $aa_SIDS = get_option('askapache_password_protect_sids'); $action = ''; foreach (array('activate-selected', 'deactivate-selected', 'delete-selected', 'move-read', 'move-setup', 'move-sid', 'move-test', 'move-contact') as $action_key) { if (isset($_POST[$action_key])) { $action = $action_key; break; } } if (isset($_GET['deactivate-sid'])) $action = 'deactivate-sid'; if (isset($_GET['activate-sid'])) $action = 'activate-sid'; if (isset($_POST['step'])) $aa_PP['step'] = $_POST['step']; if (!empty($action)) { switch ($action) { case 'move-setup': check_admin_referer('askapache-move-area'); $aa_PP['step'] = 'setup'; break; case 'move-sid': check_admin_referer('askapache-move-area'); $aa_PP['step'] = 'sid'; break; case 'move-read': check_admin_referer('askapache-move-area'); $aa_PP['step'] = 'read'; break; case 'move-test': check_admin_referer('askapache-move-area'); $aa_PP['step'] = 'welcome'; break; case 'move-contact': check_admin_referer('askapache-move-area'); $aa_PP['step'] = 'contact'; break; case 'activate-sid': $sid = (int)$_GET['activate-sid']; check_admin_referer('activate-sid_' . $sid); aa_pp_activate_sid($sid); break; case 'deactivate-sid': $sid = (int)$_GET['deactivate-sid']; check_admin_referer('deactivate-sid_' . $sid); aa_pp_deactivate_sid($sid); break; case 'activate-selected': check_admin_referer('askapache-bulk-sids'); break; case 'deactivate-selected': check_admin_referer('askapache-bulk-sids'); break; } } if ($_SERVER['REQUEST_METHOD'] == 'POST') aa_pp_get_post_values(); } /** * aa_pp_get_post_values() * * @return */ function aa_pp_get_post_values() { global $aa_PP, $aa_SIDS; if (isset($_POST['a_user']) && !empty($_POST['a_user'])) $aa_PP['user'] = preg_replace('|[^a-z0-9 _.\-@]|i', '', strip_tags($_POST['a_user'])); if (isset($_POST['a_authdomain']) && !empty($_POST['a_authdomain'])) $aa_PP['authdomain'] = $_POST['a_authdomain']; if (isset($_POST['a_authtype'])) { if (in_array(strtolower($_POST['a_authtype']), array('digest', 'basic'))) $aa_PP['authtype'] = $_POST['a_authtype']; if (strtolower($aa_PP['authtype']) == 'digest') $aa_PP['algorithm'] = 'md5'; } if (isset($_POST['a_authname']) && !empty($_POST['a_authname'])) { $aa_PP['authname'] = preg_replace('|[^a-z0-9 _.=\-@]|i', '', strip_tags($_POST['a_authname'])); if (strlen($aa_PP['authname']) > 65) $aa_PP['authname'] = substr($aa_PP['authname'], 0, 65); } if (isset($_POST['a_algorithm'])) { if (in_array(strtolower($_POST['a_algorithm']), array('crypt', 'md5', 'sha1'))) $aa_PP['algorithm'] = strip_tags($_POST['a_algorithm']); } if (isset($_POST['a_authuserfile'])) { $d = strip_tags($_POST['a_authuserfile']); if (!empty($d) && file_exists($d) && @touch($d)) { $aa_PP['authuserfile'] = $d; } } if (isset($_POST['a_pass'])) { $htpasswd = aa_pp_hashit($aa_PP['authtype'], $aa_PP['user'], $_POST['a_pass'], $aa_PP['authname']); aa_pp_file_put_c($aa_PP['authuserfile'], $htpasswd, true); if (isset($_POST['aa_protect_wpadmin'])) aa_pp_activate_sid(900000, $aa_PP['admin_htaccess']); if (isset($_POST['aa_protect_wplogin'])) aa_pp_activate_sid(800000, $aa_PP['root_htaccess']); echo ''; } update_option('askapache_password_protect', $aa_PP); $aa_SIDS = get_option('askapache_password_protect_sids'); } /** * aa_pp_gen_sid() * * @param mixed $incoming * @return */ function aa_pp_gen_sid($incoming) { global $aa_PP, $aa_SIDS; if (strtolower($aa_PP['authtype']) == 'basic') $replacement = 'AuthType %authtype%%n%AuthName "%authname%"%n%AuthUserFile %authuserfile%%n%Require user %user%'; else $replacement = 'AuthType %authtype%%n%AuthName "%authname%"%n%AuthDigestDomain %authdomain%%n%AuthDigestFile %authuserfile%%n%Require user %user%'; $aa_S = array('%n%', '%authname%', '%user%', '%authuserfile%', '%relative_root%', '%scheme%', '%authdomain%', '%host%', '%authtype%', '%generate_auth%'); $aa_R = array("\n", $aa_PP['authname'], $aa_PP['user'], $aa_PP['authuserfile'], $aa_PP['root_path'], $aa_PP['scheme'], $aa_PP['authdomain'], $aa_PP['host'], $aa_PP['authtype'], $replacement); return str_replace($aa_S, $aa_R, str_replace($aa_S, $aa_R, $incoming)); } /** * aa_pp_deactivate_sid() * * @param mixed $sid * @param mixed $file * @return */ function aa_pp_deactivate_sid($sid, $file = false) { global $aa_PP; if (!$file) $file = $aa_PP['root_htaccess']; if ((int)$sid == 900000) $file = $aa_PP['admin_htaccess']; $file = (@is_readable($file)) ? realpath(rtrim($file, '/')) : rtrim($file, '/'); if (!is_readable($file)) return false; aa_pp_notify("Deleting {$sid} from $file"); $result = array(); if ($markerdata = @explode("\n", @implode('', @file($file)))) { $state = false; if (!$f = @fopen($file, 'w')) return aa_pp_debug("aa_pp_deactivate_sid couldnt fopen {$file}"); $x = false; foreach ($markerdata as $n => $line) { if (strpos($line, "# +SID {$sid}") !== false) $state = true; if (!$state) fwrite($f, $line . "\n"); if (strpos($line, "# -SID {$sid}") !== false) $state = false; } } @$_POST['notice']='Deactivated '.$sid; return fclose($f); } /** * aa_pp_active_sids() * * @param mixed $file * @param string $sid * @return */ function aa_pp_active_sids($file = false, $sid = ' ') { global $aa_PP, $aa_SIDS; $result = array(); $files = array($aa_PP['root_htaccess'], $aa_PP['admin_htaccess']); foreach ($files as $f) { if ($markerdata = @explode("\n", @implode('', @file($f)))) { foreach ($markerdata as $line) { $si = (int)str_replace('# +SID ', '', rtrim($line)); if (strpos($line, "# +SID{$sid}") !== false) $result[] = $si; } } } return array_unique($result); } /** * aa_pp_activate_sid() * * @param mixed $sid * @param mixed $file * @return */ function aa_pp_activate_sid($sid, $file = false) { global $aa_PP, $aa_SIDS; if (!$file) $file = $aa_PP['root_htaccess']; if ((int)$sid == 900000) $file = $aa_PP['admin_htaccess']; aa_pp_notify("activate_sid {$sid} in file {$file}"); $rules = aa_pp_gen_sid(explode("\n", $aa_SIDS[(int)$sid]['Rules'])); @$_POST['notice']='Activate '.$sid; return(!aa_pp_insert_sids($file, $sid, $rules)) ? aa_pp_debug('Failed to activate ' . $sid) : true; } /** * aa_pp_sid_management() * * @return */ function aa_pp_sid_management() { global $aa_PP, $aa_SIDS; ?>
| {$plugins[$sid]['Name']} | {$plugins[$sid]['Version']} | {$plugins[$sid]['Description']} |
"; if (!empty($action_links)) echo implode(' | ', $action_links); echo ' |
Warning
Many of these modules can result in disabling or blocking other parts of your site. Please don't experiment on a production server until the upgrade comes out in a couple weeks. Let me know of any bugs.. webmaster@
Upcoming
This version was released early for all you who wanted it. As you can see, its been refactored from top to bottom.
I'm finally mostly happy with the system now used by this plugin to update/modify/and use the different modules. The old code just wasn't future-proofed enough. This new version is based very much off of the WordPress Plugins code, so it is future proofed.
This "Improvements" page is the start of whats to come, basically each of the security modules (and there are a LOT of great mod_security ones coming) will have their own very basic settings. So you can tweak the settings. If someone finds an improvement they can send it for review. New ideas and modules can be submitted here also.
Checks different software to make sure its compatible with this plugin.
"; echo($wp_version < 2.6) ? $info : $aok; echo " WordPress Version " . $wp_version . ""; $apache_version = preg_replace('|Apache/?([0-9.-]*?) (.*)|i', '\\1', $_SERVER['SERVER_SOFTWARE']); echo "The tests performed by this page are currently required to determine your servers capabilities to make sure we don't crash your server. The utmost care was taken to make these tests work for everyone running Apache, which is crazy hard because we are testing server configuration settings programmatically from a php binary without access to server configuration settings.
So we achieve this by modifying your server's .htaccess configuration file and then making special HTTP requests to your server which result in specific HTTP responses which tell us if the configuration changes failed or succeeded. The most widely allowed (by web hosts) and compatible 4+5 php function that provides access to sockets is fsockopen, so it is required. The next version will fallback to curl, but if your web host has disabled fsockopen you can bet you don't have curl.
"; echo($atest) ? $aok : $fail; echo " Fsockopen Networking Functionality"; echo "If any of these checks fail this plugin will not work. Both your /.htaccess and /wp-admin/.htaccess files must be writable for this plugin, those are the only 2 files this plugin absolutely must be able to modify. If any of the other checks fail you will need to manually create a folder named askapache in your /wp-content/ folder and make it writable.
"; echo($atest) ? $aok : $fail; echo " /wp-admin/.htaccess file writable"; $htaccess_test2 = $atest = (@is_writable($aa_PP['root_htaccess']) || @touch($aa_PP['root_htaccess'])) ? 1 : 0; echo "Your php installation should have all of these. The md5 is the only one absolutely required, otherwise I can't create the neccessary password files for you.
"; echo($atest) ? $aok : $warn; echo " CRYPT Encryption Function Available"; $aa_PP['md5_support'] = $atest = (aa_pp_checkfunction('md5')) ? 1 : 0; echo "These tests determine with a high degree of accuracy whether or not your server is able to handle .htaccess files, and also checks for various Apache modules that extend the functionality of this plugin. The 2 modules you really want to have are mod_rewrite and mod_auth_digest. In future versions of this plugin, we will be utilizing the advanced security features of mod_security more and more, so if you don't have it, bug your web host about it non-stop ;)
"; echo($atest) ? $aok : $fail; echo " Creating .htaccess test files"; $tester = new AskApache_Net; $aa_PP['htaccess_support'] = $atest = ($tester->sockit("{$test_url_base}test.gif") == 200) ? 1 : 0; echo "Now we know the encryption and apache module capabilities of your site. This test literally logs in to your server using Digest Authenticationts, providing the ultimate answer as to if your server supports this scheme.
"; echo($atest) ? $aok : $fail; echo " Creating digest htpasswd test file"; $tester = new AskApache_Net; $tester->authtype = ''; $tester->sockit(str_replace('://', '://testDIGEST:testDIGEST@', $test_url_base) . 'digest_auth_test.gif'); $tester->authtype = 'Digest'; $rg = ($tester->sockit(str_replace('://', '://testDIGEST:testDIGEST@', $test_url_base) . 'digest_auth_test.gif') == 200) ? 1 : 0; $tester = new AskApache_Net; $rb = ($tester->sockit($test_url_base . 'digest_auth_test.gif') == 401) ? 1 : 0; $aa_PP['digest_support'] = $atest = ($rb && $rg) ? 1 : 0; echo "Basic Authentication uses the .htpasswd file to store your encrypted password. These checks perform actual logins to your server using a different .htpasswd encryption each time.
"; echo($atest) ? $aok : $fail; echo " Creating basic htpasswd test file"; $tester = new AskApache_Net; $rb = ($tester->sockit($test_url_base . 'basic_auth_test.gif') == 401) ? 1 : 0; if ($aa_PP['crypt_support'] != 0) { $tester = new AskApache_Net; $rg = ($tester->sockit(str_replace('://', '://testCRYPT:testCRYPT@', $test_url_base) . 'basic_auth_test.gif') == 200) ? 1 : 0; $aa_PP['crypt_support'] = $atest = ($rb && $rg) ? 1 : 0; echo "Some information about your php.ini settings. The following settings may need to be tweaked. Likely they are fine.
"; echo(empty($open_basedir)) ? $aok : $info; echo " open_basedir on/off {$open_basedir}"; $safe_mode = @ini_get('safe_mode'); echo "';
print_r($this->request_headers);
print_r($this->response_headers);
echo '';
}
return(int)$this->response_code;
}
/**
* AskApache_Net::get_response_code()
*
* @return
*/
function get_response_code()
{
$status = null;
preg_match('/HTTP.*([0-9]{3}).*/', $this->response_headers[0], $status);
$this->response_code = $status[1];
return $this->response_code;
}
/**
* AskApache_Net::get_response_headers()
*
* @return
*/
function get_response_headers()
{
return $this->response_headers;
}
/**
* AskApache_Net::get_response_body()
*
* @return
*/
function get_response_body()
{
return $this->response;
}
/**
* AskApache_Net::set_speed()
*
* @param mixed $speed
* @return
*/
function set_speed($speed)
{
$this->_speed = round($speed * 1024);
}
/**
* AskApache_Net::_connect()
*
* @return
*/
function _connect()
{
$fp = null;
if (false === ($fp = @fsockopen($this->socket['ip'], $this->socket['port'], $errno, $errstr, $this->_fp_timeout)) || !is_resource($fp))
{
switch ($errno)
{
case - 3:
$err = "Socket creation failed";
break;
case - 4:
$err = "DNS lookup failure";
break;
case - 5:
$err = "Connection refused or timed out";
break;
case 111:
$err = "Connection refused";
break;
case 113:
$err = "No route to host";
break;
case 110:
$err = "Connection timed out";
break;
case 104:
$err = "Connection reset by client";
break;
default:
$err = "Connection failed";
break;
}
echo "Fsockopen failed! [{$errno}] {$err} ({$errstr})";
return false;
}
$this->_fp = $fp;
return true;
}
/**
* AskApache_Net::_disconnect()
*
* @return
*/
function _disconnect()
{
return(@fclose($this->_fp));
}
/**
* AskApache_Net::_rx()
*
* @return
*/
function _rx()
{
$buf = $response = '';
while (!feof($this->_fp) && $buf = @fread($this->_fp, $this->_speed))
{
$response .= $buf;
sleep(1);
}
$g = strpos($response, ACLF . ACLF);
$headers = substr($response, 0, $g);
$this->response = substr($response, $g, (strlen($response) - $g));
$this->response_headers = explode(ACLF, $headers);
}
/**
* AskApache_Net::_tx()
*
* @param mixed $request
* @return
*/
function _tx($request = null)
{
$g = false;
$g = (!is_null($request)) ? @fwrite($this->_fp, $request, strlen($request)) : @fwrite($this->_fp, $this->request, strlen($this->request));
return(bool)$g;
}
/**
* AskApache_Net::_build_sock()
*
* @param mixed $url
* @return
*/
function _build_sock($url)
{
if (!$u_bits = parse_url($url))
return false;
if (AA_PP_DEBUG)
{
echo '';
print_r($u_bits);
echo '';
}
if (empty($u_bits['url']))
$u_bits['url'] = (!empty($this->socket['url'])) ? $this->socket['url'] : 'url';
if (empty($u_bits['method']))
$u_bits['method'] = (!empty($this->socket['method'])) ? $this->socket['method'] : 'GET';
if (empty($u_bits['protocol']))
$u_bits['protocol'] = (!empty($this->socket['protocol'])) ? $this->socket['protocol'] : '1.0';
if (empty($u_bits['host']))
$u_bits['host'] = (!empty($this->socket['host'])) ? $this->socket['host'] : $_SERVER['HTTP_HOST'];
if (empty($u_bits['ip']))
$u_bits['ip'] = (!empty($this->socket['ip'])) ? $this->socket['ip'] : $this->_get_ip($u_bits['host']);
if (empty($u_bits['scheme']))
$u_bits['scheme'] = (!empty($this->socket['scheme'])) ? $this->socket['scheme'] : 'http';
if (empty($u_bits['port']))
$u_bits['port'] = (!empty($this->socket['port'])) ? $this->socket['port'] : $_SERVER['SERVER_PORT'];
if (empty($u_bits['path']))
$u_bits['path'] = (!empty($this->socket['path'])) ? $this->socket['path'] : '/';
if (empty($u_bits['ua']))
$u_bits['ua'] = (!empty($this->socket['ua'])) ? $this->socket['ua'] : 'Mozilla/5.0 (compatible; AskApache_Net/1.0; http://www.askapache.com)';
if (empty($u_bits['referer']))
$u_bits['referer'] = (!empty($this->socket['referer'])) ? $this->socket['referer'] : 'http://www.askapache.com';
if (!empty($u_bits['user']))
$this->socket['user'] = $u_bits['user'];
else
$u_bits['user'] = (!empty($this->socket['user'])) ? $this->socket['user'] : '';
if (!empty($u_bits['pass']))
$this->socket['pass'] = $u_bits['pass'];
else
$u_bits['pass'] = (!empty($this->socket['pass'])) ? $this->socket['pass'] : '';
if (empty($u_bits['fragment']))
$u_bits['fragment'] = (!empty($this->socket['fragment'])) ? $this->socket['fragment'] : '';
if (!empty($u_bits['query']))
$u_bits['path'] .= '?' . $u_bits['query'];
else
$u_bits['path'] .= (!empty($this->socket['query'])) ? '?' . $this->socket['query'] : '';
if (AA_PP_DEBUG)
{
echo '';
print_r($u_bits);
echo '';
}
$this->socket = $u_bits;
return true;
}
/**
* AskApache_Net::_build_request()
*
* @return
*/
function _build_request()
{
$_request_headers = array();
$_request_headers[] = $this->socket['method'] . " " . $this->socket['path'] . " HTTP/" . $this->socket['protocol'];
$_request_headers[] = "Host: " . $this->socket['host'];
$_request_headers[] = "User-Agent: " . $this->socket['ua'];
$_request_headers[] = 'Accept: application/xhtml+xml,text/html;q=0.9,*/*;q=0.5';
$_request_headers[] = 'Accept-Language: en-us,en;q=0.5';
$_request_headers[] = 'Accept-Encoding: none';
$_request_headers[] = 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7';
$_request_headers[] = 'Referer: ' . $this->socket['referer'];
if (!empty($this->socket['user']) && !empty($this->socket['pass']))
{
if ($this->authtype == 'Basic')
$_request_headers[] = 'Authorization: Basic ' . base64_encode($this->socket['user'] . ":" . $this->socket['pass']);
elseif ($this->authtype == 'Digest')
$_request_headers[] = $this->getdigest();
}
$this->request_headers = $_request_headers;
$this->request = join(ACLF, $_request_headers) . ACLF . ACLF;
return true;
}
/**
* AskApache_Net::_get_ip()
*
* @param mixed $host
* @return
*/
function _get_ip($host)
{
$hostip = @gethostbyname($host);
$ip = ($hostip == $host) ? $host : long2ip(ip2long($hostip));
return $ip;
}
/**
* AskApache_Net::_set_sock_time()
*
* @return
*/
function _set_sock_time()
{
@ini_set("default_socket_timeout", $this->_read_timeout);
if (function_exists("socket_set_timeout"))
@socket_set_timeout($this->_fp, $this->_read_timeout);
elseif (function_exists("stream_set_timeout"))
@stream_set_timeout($this->_fp, $this->_read_timeout);
return true;
}
/**
* AskApache_Net::getdigest()
*
* @return
*/
function getdigest()
{
foreach ($this->response_headers as $num => $header)
{
if (preg_match('/WWW-Authenticate: Digest/i', $header))
$this->dh = $dh = substr($header, 25);
}
$dh = $this->dh;
$this->socket['protocol'] = '1.1';
$mydigest = $this->digests;
if (preg_match('/realm="([^"]*?)"/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['realm'] = $match[1];
}
if (preg_match('/nonce="([^"]*?)"/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['nonce'] = $match[1];
}
if (preg_match('/cnonce="([^"]*?)"/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['cnonce'] = $match[1];
}
if (preg_match('/algorithm=(MD5|MD5-sess),/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['algorithm'] = $match[1];
}
if (preg_match('/domain="([^"]*?)"/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['domain'] = $match[1];
}
if (preg_match('/opaque="([^"]*?)"/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['opaque'] = $match[1];
}
if (preg_match('/qop=[\'\"]?(auth|auth-int)[\'\"]?/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['qop'] = $match[1];
}
if (preg_match('/nc=([0-9]*?)/i', $dh, $match))
{
if (isset($match[1]) && !empty($match[1]))
$mydigest['nc'] = $match[1];
}
$mydigest['uri'] = $this->socket['path'];
$mydigest['A1'] = md5($this->socket['user'] . ':' . $mydigest['realm'] . ':' . $this->socket['pass']);
$mydigest['A2'] = md5($this->socket['method'] . ':' . $this->socket['path']);
$mydigest['response'] = md5($mydigest['A1'] . ':' . $mydigest['nonce'] . ':' . $mydigest['nc'] . ':' . $mydigest['cnonce'] . ':' . $mydigest['qop'] . ':' . $mydigest['A2']);
$this->digests = $mydigest;
$ah = 'Authorization: Digest username="' . $this->socket['user'] . '", realm="' . $mydigest['realm'] . '", nonce="' . $mydigest['nonce'] . '", uri="' . $mydigest['uri'] . '"';
$ah .= ', algorithm=' . $mydigest['algorithm'] . ', response="' . $mydigest['response'] . '"';
$ah .= ', qop=' . $mydigest['qop'] . ', nc=' . $mydigest['nc'];
if (!empty($mydigest['cnonce']))
$ah .= ', cnonce="' . $mydigest['cnonce'] . '"';
if (!empty($mydigest['opaque']))
$ah .= ', opaque="' . $mydigest['opaque'] . '"';
if (AA_PP_DEBUG)
{
echo '';
echo $ah . "\n";
print_r($mydigest);
echo '';
}
return $ah;
}
}
}
?>