PageRenderTime 68ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/justjs/wp-content/plugins/askapache-password-protect/askapache-password-protect.php

https://github.com/jkreska/test1
PHP | 2269 lines | 1674 code | 346 blank | 249 comment | 352 complexity | ea848229c023828fc09bf41737fe970e MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. Plugin Name: AskApache Password Protect
  4. Plugin URI: http://www.askapache.com/htaccess/htaccess-security-block-spam-hackers.html
  5. Description: Advanced Security: Password Protection, Anti-Spam, Anti-Exploits, more to come...
  6. Version: 4.6.5.2
  7. Author: AskApache
  8. Author URI: http://www.askapache.com/
  9. */
  10. /**
  11. * AskApache Password Protect WordPress Plugin for .htaccess Files
  12. * Copyright (C) 2008 AskApache.comi
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation, either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. */
  27. if ( defined( 'AA_PP_DEBUG' ) ) return;
  28. // define( 'AA_PP_LOG_FILE', ABSPATH.'/askapache-passpro-log.txt' ); // set this to any file to log to
  29. define( 'AA_PP_DEBUG', false ); // set this to 1 for verbose debugging
  30. define( 'AA_PP_NET_DEBUG', false ); // set this to 1 for verbose network debugging
  31. register_activation_hook( __FILE__, 'aa_pp_activate' );
  32. register_deactivation_hook( __FILE__, 'aa_pp_deactivate' );
  33. add_action( 'admin_menu', 'aa_pp_setup_options' );
  34. if ( strpos( $_SERVER['REQUEST_URI'], basename( __FILE__ ) ) !== false ) add_action( 'admin_head', 'aa_pp_admin_header' );
  35. if ( !defined('WP_CONTENT_DIR') ) define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
  36. /**
  37. * aa_pp_setup_options()
  38. *
  39. * @return
  40. */
  41. function aa_pp_setup_options()
  42. {
  43. add_filter( 'plugin_action_links', 'aa_pp_plugin_settings', 10, 2 );
  44. add_options_page( __( 'AskApache Password Protection', 'askapache-password-protection' ), __( 'AA PassPro', 'askapache-password-protection' ), 8, basename( __FILE__ ), 'aa_pp_main_page' );
  45. }
  46. /**
  47. * aa_pp_plugin_settings()
  48. *
  49. * @param mixed $links
  50. * @param mixed $file
  51. * @return
  52. */
  53. function aa_pp_plugin_settings( $links, $file )
  54. {
  55. static $this_plugin;
  56. if ( !$this_plugin ) $this_plugin = plugin_basename( __FILE__ );
  57. if ( $file == $this_plugin ) $links = array_merge( array( '<a href="' . attribute_escape( 'options-general.php?page=askapache-password-protect.php' ) . '">Settings</a>' ), $links );
  58. return $links;
  59. }
  60. /**
  61. * aa_pp_deactivate()
  62. *
  63. * @return
  64. */
  65. function aa_pp_deactivate()
  66. {
  67. global $aa_PP, $aa_SIDS;
  68. $aa_PP = get_option( 'askapache_password_protect' );
  69. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  70. aa_pp_deactivate_sid( 'PASSPRO', 'ASKAPACHE ', $aa_PP['root_htaccess'] );
  71. aa_pp_deactivate_sid( 'PASSPRO', 'ASKAPACHE ', $aa_PP['admin_htaccess'] );
  72. delete_option( 'askapache_password_protect' );
  73. delete_option( 'askapache_password_protect_sids' );
  74. }
  75. /**
  76. * aa_pp_activate()
  77. *
  78. * @return
  79. */
  80. function aa_pp_activate()
  81. {
  82. global $wpdb, $aa_PP, $aa_SIDS;
  83. $aa_PP = $s = $aa_SIDS = array();
  84. foreach ( array( 'home_folder', 'wpadmin_folder', 'htpasswd_file', 'htaccess_file', 'original_htpasswd', 'original_htaccess', 'plugin_message', 'plugin_version', 'home', 'wpadmin', 'htpasswd_f', 'htaccess_f', 'user', 'plugin_message', 'home_folder', 'wpadmin_folder', 'htpasswd_file', 'htaccess_file', 'original_htpasswd', 'original_htaccess', 'plugin_message', 'plugin_version', 'pp_docroot_htaccess', 'pp_wp_includes_htaccess', 'pp_wp_content_htaccess', 'pp_wp_includes_htaccess', 'pp_main_base64', 'pp_ok' ) as $option ) delete_option( 'aa_'.$option );
  85. $home = get_option( 'siteurl' );
  86. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "home: $home" );
  87. $su = parse_url( $home );
  88. $path = ( !isset( $su['path'] ) || empty( $su['path'] ) ) ? '/' : rtrim( $su['path'], '/' ) . '/';
  89. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "path: $path" );
  90. $scheme = ( isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on' && $su['scheme'] == 'https' ) ? 'https' : 'http';
  91. $home_path = rtrim( get_home_path(), '/' ) . '/';
  92. $hu = str_replace( $scheme . '://', '', $home );
  93. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "hu: $hu" );
  94. $url = $scheme . '://' . rtrim( str_replace( rtrim( $path, '/' ), '', $hu ), '/' );
  95. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "url: $url" );
  96. $authdomain = "/ {$url}/";
  97. update_option( 'askapache_password_protect', array(
  98. 'step' => 'welcome',
  99. 'setup_complete' => 0,
  100. 'scheme' => $scheme,
  101. 'host' => $su['host'],
  102. 'root_path' => $path,
  103. 'home_path' => $home_path,
  104. 'test_dir' => WP_CONTENT_DIR.'/askapache',
  105. 'root_htaccess' => $home_path . '.htaccess',
  106. 'admin_htaccess' => $home_path . 'wp-admin/.htaccess',
  107. 'admin_mail' => get_option( 'admin_email' ),
  108. 'authdomain' => $authdomain,
  109. 'authname' => 'Protected By AskApache',
  110. 'authuserfile' => $home_path . '.htpasswda3',
  111. 'authuserdigest' => 'AuthDigestFile',
  112. 'algorithm' => 'md5',
  113. 'key' => wp_hash_password( wp_generate_password() ),
  114. 'htaccess_support' => 0,
  115. 'mod_alias_support' => 0,
  116. 'mod_rewrite_support' => 0,
  117. 'mod_security_support' => 0,
  118. 'mod_auth_digest_support' => 0,
  119. 'basic_support' => 0,
  120. 'digest_support' => 0,
  121. 'crypt_support' => 0,
  122. 'sha1_support' => 0,
  123. 'md5_support' => 0,
  124. 'revision_support' => 0,
  125. 'apache_version' => '',
  126. 'revisions' => array(),
  127. 'plugin_data' => get_plugin_data( __FILE__ ),
  128. ) );
  129. update_option( 'askapache_password_protect_sids', array(
  130. 60000001 => array( 'Version' => '1.3',
  131. 'Name' => 'Directory Protection',
  132. 'Description' => 'Enable the DirectoryIndex Protection, preventing directory index listings and defaulting.',
  133. 'Rules' =>
  134. 'Options -Indexes%n%' .
  135. 'DirectoryIndex index.html index.php %relative_root%index.php'
  136. ),
  137. 60000002 => array( 'Version' => '1.0',
  138. 'Name' => 'Loop Stopping Code',
  139. 'Description' => 'Stops Internal Redirect Loops',
  140. 'Rules' =>
  141. 'RewriteCond %{ENV:REDIRECT_STATUS} 200%n%' .
  142. 'RewriteRule .* - [L]%n%'
  143. ),
  144. 10140001 => array( 'Version' => '1.1',
  145. 'Name' => 'Stop Hotlinking',
  146. 'Description' => 'Denies any request for static files (images, css, etc) if referrer is not local site or empty.',
  147. 'Rules' =>
  148. 'RewriteCond %{HTTP_REFERER} !^$%n%' .
  149. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  150. 'RewriteCond %{HTTP_REFERER} !^%scheme%://%host%.*$ [NC]%n%' .
  151. 'RewriteRule \.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$ - [F,NS,L]'
  152. ),
  153. 20030001 => array( 'Version' => '1.3',
  154. 'Name' => 'Password Protect wp-login.php',
  155. 'Description' => 'Requires a valid user/pass to access the login page..',
  156. 'Rules' =>
  157. '<Files wp-login.php>%n%' .
  158. 'Satisfy Any%n%' .
  159. '%generate_auth%%n%' .
  160. '</Files>'
  161. ),
  162. 21030002 => array( 'Version' => '1.3',
  163. 'Name' => 'Password Protect wp-admin',
  164. 'Description' => 'Requires a valid user/pass to access any non-static (css, js, images) file in this directory...',
  165. 'Rules' =>
  166. '%generate_auth%%n%' .
  167. '<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$">%n%' .
  168. 'Allow from All%n%' .
  169. '</FilesMatch>%n%' .
  170. '<FilesMatch "(async-upload|admin-ajax)\.php$">%n%' .
  171. '<IfModule mod_security.c>%n%' .
  172. 'SecFilterEngine Off%n%' .
  173. '</IfModule>%n%' .
  174. 'Allow from All%n%' .
  175. '</FilesMatch>'
  176. ),
  177. 30140003 => array( 'Version' => '1.1',
  178. 'Name' => 'Forbid Proxies',
  179. 'Description' => 'Denies POST Request using a Proxy Server. Can access site, but not comment. See <a href="http://perishablepress.com/press/2008/04/20/how-to-block-proxy-servers-via-htaccess/">Perishable Press</a>',
  180. 'Rules' =>
  181. 'RewriteCond %{HTTP:VIA}%{HTTP:FORWARDED}%{HTTP:USERAGENT_VIA}%{HTTP:X_FORWARDED_FOR}%{HTTP:PROXY_CONNECTION} !^$ [OR]%n%' .
  182. 'RewriteCond %{HTTP:XPROXY_CONNECTION}%{HTTP:HTTP_PC_REMOTE_ADDR}%{HTTP:HTTP_CLIENT_IP} !^$%n%' .
  183. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  184. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  185. 'RewriteRule .* - [F,NS,L]'
  186. ),
  187. 30140004 => array( 'Version' => '1.1',
  188. 'Name' => 'Real wp-comments-post.php',
  189. 'Description' => 'Denies any POST attempt made to a non-existing wp-comments-post.php..',
  190. 'Rules' =>
  191. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ %relative_root%.*/wp-comments-post\.php.*\ HTTP/ [NC]%n%' .
  192. 'RewriteRule .* - [F,NS,L]'
  193. ),
  194. 30140005 => array( 'Version' => '1.1',
  195. 'Name' => 'BAD Content Length',
  196. 'Description' => 'Denies any POST request that doesnt have a Content-Length Header..',
  197. 'Rules' =>
  198. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  199. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  200. 'RewriteCond %{HTTP:Content-Length} ^$%n%' .
  201. 'RewriteRule .* - [F,NS,L]'
  202. ),
  203. 30140006 => array( 'Version' => '1.1',
  204. 'Name' => 'BAD Content Type',
  205. 'Description' => 'Denies any POST request with a content type other than application/x-www-form-urlencoded|multipart/form-data..',
  206. 'Rules' =>
  207. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  208. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  209. 'RewriteCond %{HTTP:Content-Type} !^(application/x-www-form-urlencoded|multipart/form-data.*(boundary.*)?)$ [NC]%n%' .
  210. 'RewriteRule .* - [F,NS,L]'
  211. ),
  212. 30140007 => array( 'Version' => '1.1',
  213. 'Name' => 'NO HOST:',
  214. 'Description' => 'Denies requests that dont contain a HTTP HOST Header...',
  215. 'Rules' =>
  216. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  217. 'RewriteCond %{HTTP_HOST} ^$%n%' .
  218. 'RewriteRule .* - [F,NS,L]'
  219. ),
  220. 30140008 => array( 'Version' => '1.1',
  221. 'Name' => 'No UserAgent, No Post',
  222. 'Description' => 'Denies POST requests by blank user-agents. May prevent a small number of visitors from POSTING.',
  223. 'Rules' =>
  224. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  225. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  226. 'RewriteCond %{HTTP_USER_AGENT} ^-?$%n%' .
  227. 'RewriteRule .* - [F,NS,L]'
  228. ),
  229. 30140009 => array( 'Version' => '1.1',
  230. 'Name' => 'No Referer, No Comment',
  231. 'Description' => 'Denies any comment attempt with a blank HTTP_REFERER field, highly indicative of spam. May prevent some visitors from POSTING.',
  232. 'Rules' =>
  233. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*/wp-comments-post\.php.*\ HTTP/ [NC]%n%' .
  234. 'RewriteCond %{HTTP_REFERER} ^-?$%n%' .
  235. 'RewriteRule .* - [F,NS,L]'
  236. ),
  237. 30140010 => array( 'Version' => '1.1',
  238. 'Name' => 'Trackback Spam',
  239. 'Description' => 'Denies obvious trackback spam. See <a href="http://ocaoimh.ie/2008/07/03/more-ways-to-stop-spammers-and-unwanted-traffic/">Holy Shmoly!</a>',
  240. 'Rules' =>
  241. 'RewriteCond %{HTTP_USER_AGENT} ^.*(opera|mozilla|firefox|msie|safari).*$ [NC,OR]%n%' .
  242. 'RewriteCond %{HTTP_USER_AGENT} ^-?$%n%' .
  243. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+/trackback/?\ HTTP/ [NC]%n%' .
  244. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  245. 'RewriteRule .* - [F,NS,L]'
  246. ),
  247. 40140011 => array( 'Version' => '1.2',
  248. 'Name' => 'Protect wp-content',
  249. 'Description' => 'Denies any Direct request for files ending in .php with a 403 Forbidden.. May break plugins/themes',
  250. 'Rules' =>
  251. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ %relative_root%wp-content/.*$ [NC]%n%' .
  252. 'RewriteCond %{REQUEST_FILENAME} !^.+(flexible-upload-wp25js|media)\.php$%n%' .
  253. 'RewriteCond %{REQUEST_FILENAME} ^.+\.(php|html|htm|txt)$%n%' .
  254. 'RewriteRule .* - [F,NS,L]'
  255. ),
  256. 40140012 => array( 'Version' => '1.2',
  257. 'Name' => 'Protect wp-includes',
  258. 'Description' => 'Denies any Direct request for files ending in .php with a 403 Forbidden.. May break plugins/themes',
  259. 'Rules' =>
  260. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ %relative_root%wp-includes/.*$ [NC]%n%' .
  261. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ %relative_root%wp-includes/js/.+/.+\ HTTP/ [NC]%n%' .
  262. 'RewriteCond %{REQUEST_FILENAME} ^.+\.php$%n%' .
  263. 'RewriteRule .* - [F,NS,L]'
  264. ),
  265. 40140013 => array( 'Version' => '1.1',
  266. 'Name' => 'Common Exploit',
  267. 'Description' => 'Block common exploit requests with 403 Forbidden. These can help alot, may break some plugins.',
  268. 'Rules' =>
  269. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  270. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ ///.*\ HTTP/ [NC,OR]%n%' .
  271. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+\?\=?(http|ftp|ssl|https):/.*\ HTTP/ [NC,OR]%n%' .
  272. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\?.*\ HTTP/ [NC,OR]%n%' .
  273. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(asp|ini|dll).*\ HTTP/ [NC,OR]%n%' .
  274. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(htpasswd|htaccess|aahtpasswd).*\ HTTP/ [NC]%n%' .
  275. 'RewriteRule .* - [F,NS,L]'
  276. ),
  277. 50140001 => array( 'Version' => '1.1',
  278. 'Name' => 'Safe Request Methods',
  279. 'Description' => 'Denies any request not using <a href="/online-tools/request-method-scanner/">GET,PROPFIND,POST,OPTIONS,PUT,HEAD</a>..',
  280. 'Rules' =>
  281. 'RewriteCond %{REQUEST_METHOD} !^(GET|HEAD|POST|PROPFIND|OPTIONS|PUT)$ [NC]%n%' .
  282. 'RewriteRule .* - [F,NS,L]'
  283. ),
  284. 50140002 => array( 'Version' => '1.1',
  285. 'Name' => 'HTTP PROTOCOL',
  286. 'Description' => 'Denies any badly formed HTTP PROTOCOL in the request, 0.9, 1.0, and 1.1 only..',
  287. 'Rules' =>
  288. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ .+\ HTTP/(0\.9|1\.0|1\.1) [NC]%n%' .
  289. 'RewriteRule .* - [F,NS,L]'
  290. ),
  291. 50140003 => array( 'Version' => '1.1',
  292. 'Name' => 'SPECIFIC CHARACTERS',
  293. 'Description' => 'Denies any request for a url containing characters other than "a-zA-Z0-9.+/-?=&" - REALLY helps but may break your site depending on your links.',
  294. 'Rules' =>
  295. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  296. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ [A-Z0-9\.\+_/\-\?\=\&\%\#]+\ HTTP/ [NC]%n%' .
  297. 'RewriteRule .* - [F,NS,L]'
  298. ),
  299. 50140004 => array( 'Version' => '1.1',
  300. 'Name' => 'Directory Traversal',
  301. 'Description' => 'Denies Requests containing ../ or ./. which is a directory traversal exploit attempt..',
  302. 'Rules' =>
  303. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ .*([\.]+[\.]+).*\ HTTP/ [NC]%n%' .
  304. 'RewriteRule .* - [F,NS,L]'
  305. ),
  306. 50140005 => array( 'Version' => '1.1',
  307. 'Name' => 'PHPSESSID Cookie',
  308. 'Description' => 'Only blocks when a PHPSESSID cookie is sent by the user and it contains characters other than 0-9a-z..',
  309. 'Rules' =>
  310. 'RewriteCond %{HTTP_COOKIE} ^.*PHPSESS?ID.*$%n%' .
  311. 'RewriteCond %{HTTP_COOKIE} !^.*PHPSESS?ID=([0-9a-z]+);.*$%n%' .
  312. 'RewriteRule .* - [F,NS,L]'
  313. ),
  314. 50140006 => array( 'Version' => '1.1',
  315. 'Name' => 'Bogus Graphics Exploit',
  316. 'Description' => 'Denies obvious exploit using bogus graphics..',
  317. 'Rules' =>
  318. 'RewriteCond %{HTTP:Content-Disposition} \.php [NC]%n%' .
  319. 'RewriteCond %{HTTP:Content-Type} image/.+ [NC]%n%' .
  320. 'RewriteRule .* - [F,NS,L]' )
  321. )
  322. );
  323. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  324. $sids = array_keys( $aa_SIDS );
  325. foreach ( $sids as $sid )
  326. {
  327. $newinfo = aa_pp_sid_info( $sid );
  328. $aa_SIDS[$sid] = array_merge( $aa_SIDS[$sid], $newinfo );
  329. }
  330. update_option( 'askapache_password_protect_sids', $aa_SIDS );
  331. }
  332. /**
  333. * aa_pp_admin_header()
  334. *
  335. * @return
  336. */
  337. function aa_pp_admin_header()
  338. {
  339. global $wpdb, $aa_PP, $aa_SIDS;
  340. if ( !user_can_access_admin_page() ) wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
  341. if ( !current_user_can( 8 ) )wp_die( __( "You are not allowed to be here without upload permissions" ) );
  342. $aa_PP = get_option( 'askapache_password_protect' );
  343. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  344. @set_time_limit( 60 );
  345. @set_magic_quotes_runtime( 0 );
  346. }
  347. /**
  348. * aa_pp_get_post_values()
  349. *
  350. * @param mixed $v
  351. * @return
  352. */
  353. function aa_pp_get_post_values( $v )
  354. {
  355. global $aa_PP, $aa_SIDS;
  356. $errors = new WP_Error;
  357. $action = 'none';
  358. foreach( array( 'a_htaccess_support', 'a_mod_alias_support', 'a_mod_rewrite_support', 'a_mod_security_support', 'a_mod_auth_digest_support', 'a_digest_support', 'a_basic_support' ) as $k )
  359. {
  360. if ( isset( $_POST[$k] ) && $v[$k] != 1 )
  361. {
  362. check_admin_referer( 'askapache-passpro-form' );
  363. $v[substr( $k, 2 )] = 1;
  364. }
  365. }
  366. foreach( array( 'a_user', 'a_authdomain', 'a_authtype', 'a_algorithm', 'a_authname', 'a_authuserfile', 'a_step', 'a_admin_email', 'a_root_htaccess', ) as $k )
  367. {
  368. if ( isset( $_POST[$k] ) && !empty( $_POST[$k] ) && $_POST[$k] != $v[$k] )
  369. {
  370. check_admin_referer( 'askapache-passpro-form' );
  371. $v[substr( $k, 2 )] = $_POST[$k];
  372. }
  373. }
  374. foreach ( array( 'activate-selected', 'deactivate-selected', 'delete-selected', 'm_move' ) as $action_key )
  375. {
  376. if ( isset( $_POST[$action_key] ) )
  377. {
  378. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Setting action to {$action_key}" );
  379. $action = $action_key;
  380. break;
  381. }
  382. }
  383. if ( $action == 'm_move' )
  384. {
  385. check_admin_referer( 'askapache-move-area' );
  386. foreach( array( 'm_read', 'm_reset', 'm_sid', 'm_setup', 'm_test', 'm_welcome', 'm_contact' ) as $where )
  387. {
  388. if ( isset( $_POST[$where] ) )
  389. {
  390. $aa_PP['step'] = substr( $where, 2 );
  391. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Setting step to {$aa_PP['step']}" );
  392. break;
  393. }
  394. }
  395. return true;
  396. }
  397. foreach ( array( 'deactivate-sid', 'activate-sid', 'view-revision', 'activate-revision', 'delete-revision' ) as $ak )
  398. {
  399. if ( isset( $_GET[$ak] ) )
  400. {
  401. $action = $ak;
  402. break;
  403. }
  404. }
  405. if ( isset( $_POST['a_pass1'] ) && isset( $_POST['a_pass2'] ) )
  406. {
  407. if ( empty( $_POST['a_pass1'] ) || empty( $_POST['a_pass2'] ) )$errors->add( 'password-required', __( '<strong>ERROR</strong>: A password is required' ) );
  408. if ( $_POST['a_pass1'] != $_POST['a_pass2'] )$errors->add( 'passwords-notsame', __( '<strong>ERROR</strong>: The passwords do not match.' ) );
  409. else $pass = $_POST['a_pass1'];
  410. }
  411. if ( isset( $_POST['a_user'] ) && isset( $_POST['a_admin_email'] ) )
  412. {
  413. if ( empty( $_POST['a_user'] ) )$errors->add( 'username-required', __( '<strong>ERROR</strong>: A username is required.' ) );
  414. if ( empty( $_POST['a_admin_email'] ) )$errors->add( 'adminemail-required', __( '<strong>ERROR</strong>: An admin email is required.' ) );
  415. if ( !is_email( $_POST['a_admin_email'] ) )$errors->add( 'adminemail-bad', __( '<strong>ERROR</strong>: A valid admin email is required.' ) );
  416. }
  417. if ( isset( $v['authtype'] ) && !in_array( $v['authtype'], array( 'Digest', 'Basic' ) ) ) $errors->add( 'bad-authtype', __( '<strong>ERROR</strong>: Incorrect authtype' ) );
  418. if ( isset( $v['algorithm'] ) && !in_array( $v['algorithm'], array( 'crypt', 'md5', 'sha1' ) ) ) $errors->add( 'bad-algorithm', __( '<strong>ERROR</strong>: Incorrect algorithm' ) );
  419. if ( isset($v['user']) && strpos( $v['user'], ':' ) !== false ) $errors->add( 'bad-username', __( '<strong>ERROR</strong>: Username cannot contain the : character' ) );
  420. if ( isset($v['authname']) && strlen( $v['authname'] ) > 65 ) $errors->add( 'bad-authname', __( '<strong>ERROR</strong>: Authname cannot exceed 65 characters, yours was ' . strlen( $v['authname'] ) . ' characters' ) );
  421. if ( isset($v['authtype']) && $v['authtype'] == 'Digest' && $v['algorithm'] != 'md5' ) $errors->add( 'algorithm-authtype-mismatch', __( '<strong>ERROR</strong>: Digest Authentication can only use the md5 algorithm' ) );
  422. foreach( array( $v['authuserfile'], $v['admin_htaccess'], $v['root_htaccess'] ) as $f )
  423. {
  424. if ( strpos( basename( $f ), '.ht' ) === false ) $errors->add( 'bad-authuserfilename', __( '<strong>ERROR</strong>: File names must start with .ht like .htaccess or .htpasswd-new3' ) );
  425. if ( (int)$v['setup_complete'] != 0 )
  426. {
  427. if ( aa_pp_htaccess_file_init() && !@touch($f) || !@is_writable( $f ) ) $errors->add( 'unwritable-file', __( '<strong>ERROR</strong>: Please make ' . $f . ' writable and readable' ) );
  428. }
  429. }
  430. if ( count( $errors->errors ) == 0 )
  431. {
  432. $aa_PP = $v;
  433. switch ( $action )
  434. {
  435. case 'activate-revision':
  436. $file = $_GET['activate-revision'];
  437. check_admin_referer( 'activate-revision_' . $file );
  438. break;
  439. case 'view-revision':
  440. $file = $_GET['view-revision'];
  441. check_admin_referer( 'view-revision_' . $file );
  442. break;
  443. case 'delete-revision':
  444. $file = $_GET['delete-revision'];
  445. check_admin_referer( 'delete-revision_' . $file );
  446. $g = array();
  447. foreach( $aa_PP['revisions'] as $item )if ( $item['id'] != $file )$g[] = $item;
  448. $v['revisions'] = $g;
  449. break;
  450. case 'activate-sid':
  451. $sid = ( int )$_GET['activate-sid'];
  452. check_admin_referer( 'activate-sid_' . $sid );
  453. if ( !aa_pp_activate_sid( $sid ) ) $errors->add( 'sid-activation-failed', __( "Failed to activate sid {$sid}" ) );
  454. echo '<img src="askapache-reset.bmp?' . rand( 1, 1000 ) . '" style="width:1px;height:1px;" />';
  455. break;
  456. case 'deactivate-sid':
  457. $sid = ( int )$_GET['deactivate-sid'];
  458. check_admin_referer( 'deactivate-sid_' . $sid );
  459. if ( !aa_pp_deactivate_sid( $sid ) ) $errors->add( 'sid-deactivation-failed', __( "Failed to deactivate sid {$sid}" ) );
  460. break;
  461. case 'activate-selected':
  462. case 'deactivate-selected':
  463. check_admin_referer( 'askapache-bulk-sids' );
  464. break;
  465. }
  466. if ( isset( $pass ) && count( $errors->errors ) == 0 )
  467. {
  468. $message_headers = 'From: "' . $blog_title . '" <wordpress@' . str_replace( 'www.', '', $aa_PP['host'] ) . '>';
  469. $message = sprintf( __( "Your new username and password has been successfully set up at:\n\n%1\$s\n\nYou can log in to the administrator area with the following information:\n\n\nUsername: %2\$s\nPassword: %3\$s\n\nWe hope you enjoy your new protection. Thanks!\n\n--The AskApache Team\nhttp://www.askapache.com/" ), get_option( 'siteurl' ) . '/wp-admin/', $v['user'], $pass );
  470. if ( !aa_pp_file_put_c( $v['authuserfile'], aa_pp_hashit( $v['authtype'], $v['user'], $pass, $v['authname'] ), false ) )
  471. $errors->add( 'failed-create-authuserfile', __( '<strong>ERROR</strong>: Failed to create ' . $v['authuserfile'] ) );
  472. else if ( !wp_mail( $aa_PP['admin_email'], __( '__New AskApache User' ), $message, $message_headers ) )
  473. $errors->add( 'failed-wp-mail', __( '<strong>ERROR</strong>: Failed to mail to ' . $aa_PP['admin_email'] ) );
  474. }
  475. }
  476. if ( count( $errors->errors ) > 0 ) $v['step'] = $aa_PP['step'];
  477. if ( $v['step'] == 'sid' && (int)$v['setup_complete'] != 1 )$v['setup_complete'] = 1;
  478. $aa_PP = $v;
  479. if ( count( $errors->errors ) > 0 ) return $errors;
  480. else return true;
  481. }
  482. /**
  483. * aa_pp_main_page()
  484. *
  485. * @return
  486. */
  487. function aa_pp_main_page()
  488. {
  489. global $aa_PP, $aa_SIDS;
  490. $aa_PP = get_option( 'askapache_password_protect' );
  491. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  492. ?>
  493. <form method="post" action="options-general.php?page=askapache-password-protect.php"><?php wp_nonce_field( 'askapache-move-area' );
  494. ?>
  495. <div class="tablenav">
  496. <div class="alignleft">
  497. <?php if ( $aa_PP['setup_complete'] != 0 ) {?>
  498. <input type="submit" name="m_test" id="m_test" value="Self-Diagnostics" class="button-secondary" />
  499. <input type="submit" name="m_read" id="m_read" value="Htaccess Files" class="button-secondary" />
  500. <input type="submit" name="m_setup" id="m_setup" value="Password Configuration" class="button-secondary" />
  501. <input type="submit" name="m_sid" id="m_sid" value="SID Module Management" class="button-secondary" />
  502. <input type="submit" name="m_contact" id="m_contact" value="Improvements" class="button-secondary" />
  503. <input type="hidden" name="m_move" id="m_move" value="m_move" />
  504. <?php } ?>
  505. </div>
  506. <p style="float:right; margin-top:0;padding-top:0;"><a href="http://www.askapache.com/htaccess/apache-htaccess.html">AskApache .htaccess Tutorial</a></p>
  507. </div>
  508. <br class="clear" />
  509. </form>
  510. <?php
  511. $errors = aa_pp_get_post_values( $aa_PP );
  512. aa_pp_errors( $errors );
  513. if ( (int)$aa_PP['setup_complete'] != 0 )
  514. {
  515. $errors = aa_pp_update_revisions( $aa_PP['admin_htaccess'] );
  516. aa_pp_errors( $errors );
  517. $errors = aa_pp_update_revisions( $aa_PP['root_htaccess'] );
  518. aa_pp_errors( $errors );
  519. }
  520. update_option( 'askapache_password_protect', $aa_PP );
  521. if ( isset( $_POST['notice'] ) ) echo '<div id="message" class="updated fade"><p>' . $_POST['notice'] . '</p></div>';
  522. if ( (bool)AA_PP_DEBUG === true )
  523. {
  524. echo '<pre>';
  525. print_r( $aa_PP );
  526. print_r(aa_pp_active_sids());
  527. //print_r(get_defined_constants());
  528. echo '</pre>';
  529. }
  530. switch ( $aa_PP['step'] )
  531. {
  532. case 'contact':
  533. ?>
  534. <div class="wrap" style="max-width:95%;">
  535. <h3>Bug Fixes</h3>
  536. <p>10/17/08 - Fixed known bugs.. Improved Testing with debug output automatically for failed tests.</p>
  537. <p><br class="clear" /></p>
  538. <h3>Backups and Revisioning</h3>
  539. <p>8/19/08 - Ok so version 4.6 has some nice automatic revisioning/backup features... the next release will let us compare the new .htaccess file with the old .htaccess files just like wikis. (based once again on wordpress core)..</p>
  540. <p>So now that the SID module system is pretty stable and there is now decent backups going on, the next thing I'll be adding is multi-user and group management. And much more access control by IP address and other ids.</p>
  541. <p>The point of doing all that is so the plugin will be stable enough code-wise so we can focus in on developing custom SIDs for protecting wordpress blogs.. Mod_Security rules are on the way....</p>
  542. <p><br class="clear" /></p>
  543. <h3>The SID Module Redesigned</h3>
  544. <p>8/14/08 - 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.</p>
  545. <p>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.</p>
  546. </div>
  547. <?php
  548. break;
  549. case 'welcome':
  550. aa_pp_welcome_form();
  551. break;
  552. case 'test':
  553. aa_pp_run_tests();
  554. break;
  555. case 'setup':
  556. aa_pp_setup_form();
  557. break;
  558. case 'sid':
  559. aa_pp_sid_management();
  560. break;
  561. case 'reset':
  562. aa_pp_activate();
  563. break;
  564. case 'read':
  565. aa_pp_htaccess_history();
  566. break;
  567. default:
  568. aa_pp_welcome_form();
  569. break;
  570. }
  571. update_option( 'askapache_password_protect', $aa_PP );
  572. }
  573. /**
  574. * aa_pp_welcome_form()
  575. *
  576. * @return
  577. */
  578. function aa_pp_welcome_form()
  579. {
  580. global $aa_PP, $aa_SIDS;?>
  581. <div class="wrap" style="max-width:95%;">
  582. <h2>Test for Compatibility and Capability</h2>
  583. <form action="options-general.php?page=askapache-password-protect.php" method="post"><?php wp_nonce_field( 'askapache-passpro-form' );?>
  584. <input type="hidden" id="a_step" name="a_step" value="test" />
  585. <p>First we need to run a series of tests on your server to determine what capabilities your site has and also to locate any potential installation problems.</p>
  586. <p>The tests will be run on temporary files I'll create in your /wp-content/askapache/ folder. They will create .htaccess and .htpasswd files in that temp location and then use fsockopen networking functions to query those files. This tells us exactly how your server handles .htaccess configurations, HTTP authentication schemes, Apache Module capability, etc..</p></p>
  587. <table class="form-table">
  588. <tr valign="top">
  589. <th scope="row">Known Support<br /><p>Only check these if you are 100% sure your server supports them. This bypasses auto-detecting support.</p></th>
  590. <td><label for="a_htaccess_support"><input type="checkbox" name="a_htaccess_support" id="a_htaccess_support" <?php if ( $aa_PP['htaccess_support'] != 0 )echo 'checked="checked"';?> /> .htaccess file support</label><br />
  591. <label for="a_mod_alias_support"><input type="checkbox" name="a_mod_alias_support" id="a_mod_alias_support" <?php if ( $aa_PP['mod_alias_support'] != 0 )echo 'checked="checked"';?> /> mod_alias Redirects supported</label><br />
  592. <label for="a_mod_rewrite_support"><input type="checkbox" name="a_mod_rewrite_support" id="a_mod_rewrite_support" <?php if ( $aa_PP['mod_rewrite_support'] != 0 )echo 'checked="checked"';?> /> mod_rewrite supported</label><br />
  593. <label for="a_mod_security_support"><input type="checkbox" name="a_mod_security_support" id="a_mod_security_support" <?php if ( $aa_PP['mod_security_support'] != 0 )echo 'checked="checked"';?> /> mod_security supported</label><br />
  594. <label for="a_mod_auth_digest_support"><input type="checkbox" name="a_mod_auth_digest_support" id="a_mod_auth_digest_support" <?php if ( $aa_PP['mod_auth_digest_support'] != 0 )echo 'checked="checked"';?> /> mod_auth_digest supported</label><br />
  595. <label for="a_digest_support"><input type="checkbox" name="a_digest_support" id="a_digest_support" <?php if ( $aa_PP['digest_support'] != 0 )echo 'checked="checked"';?> /> digest authentication supported</label><br />
  596. <label for="a_basic_support"><input type="checkbox" name="a_basic_support" id="a_basic_support" <?php if ( $aa_PP['basic_support'] != 0 )echo 'checked="checked"';?> /> basic authentication supported</label></td>
  597. </tr>
  598. <!--<tr valign="top">
  599. <th scope="row"><label for="a_root_htaccess">Root .htaccess Location</label></th>
  600. <td><input size="70" style="width: 85%;" class="wide code" name="a_root_htaccess" id="a_root_htaccess" type="text" value="<?php echo $aa_PP['root_htaccess'];?>" /><br />
  601. Check to make sure that this is the correct location of your .htaccess file. Getting this wrong could fudge the whole plugin.</td>
  602. </tr>-->
  603. </table>
  604. <p>Several tests send specially crafted HTTP requests which are designed to elicit very specific HTTP Protocol Responses to accurately determine your servers capabilities.</p>
  605. <p>Other important checks will run: file permissions, function availability, much more boring testing. The tests are fast and you can re-run them whenever you want. If you'd like to see the action, define AA_PP_DEBUG to 1 in the source of this file. Good Luck!</p>
  606. <p class="submit"><input name="sub" type="submit" id="sub" value="Initiate Tests &raquo;" /></p>
  607. </form>
  608. </div>
  609. <?php
  610. }
  611. /**
  612. * aa_pp_setup_form()
  613. *
  614. * @return
  615. */
  616. function aa_pp_setup_form()
  617. {
  618. global $aa_PP, $aa_SIDS;
  619. aa_pp_htaccess_file_init();?>
  620. <div class="wrap" style="max-width:95%;">
  621. <h2>Setup Password Protection</h2>
  622. <form action="options-general.php?page=askapache-password-protect.php" method="post"><?php wp_nonce_field( 'askapache-passpro-form' );?>
  623. <input type="hidden" id="a_step" name="a_step" value="sid" />
  624. <h3>Create User</h3>
  625. <table class="form-table">
  626. <tbody>
  627. <tr valign="top">
  628. <th scope="row"><label for="a_admin_email">Admin Email</label><br />Username and Password sent here in case you forget it.</th>
  629. <td><input size="40" name="a_admin_email" type="text" id="a_admin_email" value="<?php echo $aa_PP['admin_mail'];?>" /></td>
  630. </tr>
  631. <tr valign="top">
  632. <th scope="row"><label for="a_user">Username</label></th>
  633. <td><input size="40" name="a_user" type="text" id="a_user" value="<?php echo $aa_PP['user'];?>" /></td>
  634. </tr>
  635. <tr valign="top">
  636. <th><label for="a_pass">Password (twice)</label></th>
  637. <td><input size="40" type="password" name="a_pass1" id="a_pass1" value="<?php if ( isset( $_POST['a_pass1'] ) && !empty( $_POST['a_pass1'] ) ) echo htmlentities( $_POST['a_pass1'] );?>" /><br />
  638. <input size="40" type="password" name="a_pass2" id="a_pass2" value="<?php if ( isset( $_POST['a_pass2'] ) && !empty( $_POST['a_pass2'] ) ) echo htmlentities( $_POST['a_pass2'] );?>" /><br /></td>
  639. </tr>
  640. </tbody>
  641. </table>
  642. <h3>Authentication Scheme</h3>
  643. <table class="form-table">
  644. <tr valign="top">
  645. <th scope="row">Choose Scheme </th>
  646. <td><fieldset>
  647. <p>
  648. <label><input name="a_authtype" type="radio" value="Digest" <?php echo ( $aa_PP['digest_support'] != 1 ) ? ' disabled="disabled"' : ' checked="checked"';?> /> <strong>Digest</strong> &#8212; Much better than Basic, MD5 crypto hashing with nonce's to prevent cryptanalysis.</label>
  649. <br />
  650. <label><input name="a_authtype" type="radio" value="Basic" <?php if ( $aa_PP['basic_support'] != 1 ) echo ' disabled="disabled"';
  651. else if ( $aa_PP['digest_support'] != 1 ) echo ' checked="checked"';?> /> <strong>Basic</strong> &#8212; Cleartext authentication using a user-ID and a password for each authname.</label>
  652. <br /><br /> This is the mechanism by which your credentials are authenticated (Digest is <a href="http://tools.ietf.org/html/rfc2617">strongly preferred</a>) </p>
  653. </fieldset></td>
  654. </tr>
  655. </tbody>
  656. </table>
  657. <h3>Authentication Settings</h3>
  658. <table class="form-table">
  659. <tbody>
  660. <tr valign="top">
  661. <th scope="row"><label for="a_authuserfile">Password File Location</label></th>
  662. <td><input size="70" style="width: 85%;" class="wide code" name="a_authuserfile" id="a_authuserfile" type="text" value="<?php echo $aa_PP['authuserfile'];?>" /><br />
  663. Use a location inaccessible from a web-browser if possible. Do not put it in the directory that it protects. </td>
  664. </tr>
  665. <tr valign="top">
  666. <th scope="row"><label for="a_authname">Realm Name</label></th>
  667. <td><input size="70" style="width: 85%;" class="wide code" name="a_authname" id="a_authname" type="text" value="<?php echo $aa_PP['authname'];?>" /><br />
  668. The authname or "Realm" serves two major functions. Part of the password dialog box. Second, it is used by the client to determine what password to send for a given authenticated area. </td>
  669. </tr>
  670. <tr valign="top">
  671. <th scope="row"><label for="a_authdomain">Protection Space Domains</label></th>
  672. <td><input size="70" style="width: 85%;" class="wide code" name="a_authdomain" id="a_authdomain" type="text" value="<?php echo $aa_PP['authdomain'];?>" /><br />
  673. One or more URIs in the same protection space (i.e. use the same authname and username/password info). The URIs may be either absolute or relative URIs. Omitting causes client to send Authorization header for every request. </td>
  674. </tr>
  675. </tbody>
  676. </table>
  677. <h3>Encryption Preferences</h3>
  678. <table class="form-table">
  679. <tbody>
  680. <tr valign="top">
  681. <th scope="row">Password File Algorithm</th>
  682. <td><fieldset>
  683. <label><input type="radio" name="a_algorithm" value="crypt" id="a_algorithm_crypt"<?php if ( $aa_PP['crypt_support'] != 1 )
  684. echo ' disabled="disabled"';
  685. else if ( $aa_PP['algorithm'] == 'crypt' && $aa_PP['authtype'] != 'Digest' )
  686. echo ' checked="checked"';?> /> <strong>CRYPT</strong> &#8212; Unix only. Uses the traditional Unix crypt(3) function with a randomly-generated 32-bit salt (only 12 bits used) and the first 8 characters of the password.</label>
  687. <br />
  688. <label><input type="radio" name="a_algorithm" value="md5" id="a_algorithm_md5"<?php if ( $aa_PP['md5_support'] != 1 )
  689. echo ' disabled="disabled"';
  690. else if ( $aa_PP['algorithm'] == 'md5' )
  691. echo ' checked="checked"';?> /> <strong>MD5</strong> &#8212; Apache-specific algorithm using an iterated (1,000 times) MD5 Digest of various combinations of a random 32-bit salt and the password.</label>
  692. <br />
  693. <label><input type="radio" name="a_algorithm" value="sha1" id="a_algorithm_sha1"<?php if ( $aa_PP['sha1_support'] != 1 )
  694. echo ' disabled="disabled"';
  695. else if ( $aa_PP['algorithm'] == 'sha1' && $aa_PP['authtype'] != 'Digest' )
  696. echo ' checked="checked"';?> /> <strong>SHA1</strong> &#8212; Base64-encoded SHA-1 Digest of the password.</label>
  697. <br />
  698. </fieldset></td>
  699. </tr>
  700. </tbody>
  701. </table>
  702. <p>Note I do not store or save your password anywhere, so you will need to type it in each time you update this page.. for now.</p>
  703. <p class="submit"><input name="sub" type="submit" id="sub" value="Save Settings &raquo;" /></p>
  704. </form>
  705. </div>
  706. <?php
  707. }
  708. /**
  709. * aa_pp_update_revisions()
  710. *
  711. * @param mixed $file
  712. * @return
  713. */
  714. function aa_pp_update_revisions( $file )
  715. {
  716. global $aa_PP;
  717. clearstatcache();
  718. if ( !file_exists( $file ) || filesize( $file ) < 5 )return;
  719. $md5_val = md5_file( $file );
  720. $md5s = array();
  721. foreach( $aa_PP['revisions'] as $f ) $md5s[] = $f['md5'];
  722. if ( in_array( $md5_val, $md5s ) )return;
  723. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Creating new revision for {$file}" );
  724. $data = aa_pp_readfile( $file );
  725. if ( $aa_PP['gzip_support'] != 1 )$data_compress = base64_encode( $data );
  726. else $data_compress = base64_encode( gzcompress( $data, 9 ) );
  727. $tag = ( strpos( $file, 'wp-admin' ) !== false )?1:0;
  728. $aa_PP['revisions'][] =
  729. array(
  730. 'file' => $file,
  731. 'id' => $tag . count( $aa_PP['revisions'] ),
  732. 'md5' => $md5_val,
  733. 'time' => current_time( 'timestamp', 1 ),
  734. 'size' => filesize( $file ),
  735. 'data' => $data_compress,
  736. );
  737. }
  738. /**
  739. * aa_pp_htaccess_history()
  740. *
  741. * @return
  742. */
  743. function aa_pp_htaccess_history()
  744. {
  745. global $aa_PP;
  746. ?>
  747. <div class="wrap" style="max-width:95%;">
  748. <h2>.htaccess File Revisions</h2>
  749. <p><br class="clear" /></p>
  750. <?php
  751. if ( isset( $_GET['view-revision'] ) )aa_pp_view_revision( $_GET['view-revision'] );
  752. else aa_pp_print_history( $aa_PP['revisions'], 'root' );
  753. ?>
  754. </div>
  755. <?php
  756. }
  757. /**
  758. * aa_pp_view_revision()
  759. *
  760. * @param mixed $id
  761. * @return
  762. */
  763. function aa_pp_view_revision( $id )
  764. {
  765. global $aa_PP;
  766. $ids = array();
  767. foreach( $aa_PP['revisions'] as $n => $revs )
  768. {
  769. if ( $revs['id'] == $id )
  770. {
  771. $file = $revs;
  772. break;
  773. }
  774. }
  775. if ( !current_user_can( 'edit_plugins' ) )
  776. wp_die( '<p>' . __( 'You do not have sufficient permissions to edit templates for this blog.' ) . '</p>' );
  777. if ( $aa_PP['gzip_support'] != 1 )$content = base64_decode( $file['data'] );
  778. else $content = gzuncompress( base64_decode( $file['data'] ) );
  779. echo '<pre style="border:3px solid #CCC; padding:1em;font-family:"Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",monospace;*font-size:108%;line-height:99%;">';
  780. echo htmlspecialchars( $content );
  781. echo '</pre>';
  782. }
  783. /**
  784. * aa_pp_print_history()
  785. *
  786. * @param mixed $revision_files
  787. * @param mixed $context
  788. * @return
  789. */
  790. function aa_pp_print_history( $revision_files, $context )
  791. {
  792. global $aa_PP, $aa_SIDS;
  793. if ( sizeof( $revision_files ) < 1 )return;
  794. ?>
  795. <form method="post" action="options-general.php?page=askapache-password-protect.php"><?php wp_nonce_field( 'askapache-bulk-sids' ); ?>
  796. <div class="tablenav">
  797. <h3 style="text-align:right; width:70%; line-height:2em; margin:0;float:right;padding-right:30px;" id="current-<?php echo $context;?>">.htaccess File Revisions</h3>
  798. <br class="clear" />
  799. </div>
  800. <br class="clear" />
  801. <table class="widefat" id="revisions-table">
  802. <thead>
  803. <tr>
  804. <th scope="col">ID</th>
  805. <th scope="col">Created</th>
  806. <th scope="col">Size</th>
  807. <th scope="col">Compressed Size</th>
  808. <th scope="col">File Location</th>
  809. <th scope="col">MD5 Hash</th>
  810. <th scope="col" class="action-links"><?php _e( 'Action' );?></th>
  811. </tr>
  812. </thead>
  813. <tbody class="plugins">
  814. <?php
  815. foreach ( $revision_files as $file )
  816. {
  817. $fi = $file['file'];
  818. $ts = $file['time'];
  819. $id = $file['id'];
  820. $hash = $file['md5'];
  821. $created = sprintf( '%s at %s', date( get_option( 'date_format' ), $ts ), date( get_option( 'time_format' ), $ts ) );
  822. $size = $file['size'];
  823. $datasize = strlen( $file['data'] );
  824. $action_links = array();
  825. $action_links[] = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;view-revision=' . $id, 'view-revision_' . $id ) . '" class="view">' . __( 'View' ) . '</a>';
  826. $action_links[] = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;delete-revision=' . $id, 'delete-revision_' . $id ) . '" class="delete">' . __( 'Delete' ) . '</a>';
  827. echo "<tr>
  828. <td class='id' style='width:75px;'>{$id}</td>
  829. <td class='created'>{$created}</td>
  830. <td class='size' style='width:75px;'>{$size}</td>
  831. <td class='datasize' style='width:75px;'>{$datasize}</td>
  832. <td class='file'>{$fi}</td>
  833. <td class='md5'>{$hash}</td>
  834. <td class='togl action-links'>";
  835. if ( !empty( $action_links ) ) echo implode( ' | ', $action_links );
  836. echo '</td>
  837. </tr>';
  838. }
  839. ?>
  840. </tbody>
  841. </table>
  842. </form>
  843. <p><br class="clear" /></p>
  844. <?php
  845. }
  846. /**
  847. * aa_pp_sid_management()
  848. *
  849. * @return
  850. */
  851. function aa_pp_sid_management()
  852. {
  853. global $aa_PP, $aa_SIDS;
  854. $sids = array_keys( $aa_SIDS );
  855. $sid_table = array();
  856. $active_sids = aa_pp_active_sids();
  857. $sid_table['password'] = $sid_table['general'] = $sid_table['antispam'] = $sid_table['wordpress_exploit'] = $sid_table['general_exploit'] = $sid_table['protection'] = array();
  858. $sid_table['active'] = array_values( $active_sids );
  859. foreach ( $sids as $sid )
  860. {
  861. $s = ( string )$sid;
  862. switch ( ( int )$s{0} )
  863. {
  864. case 1:
  865. $sid_table['protection'][] = $sid;
  866. break;
  867. case 2:
  868. $sid_table['password'][] = $sid;
  869. break;
  870. case 3:
  871. $sid_table['antispam'][] = $sid;
  872. break;
  873. case 4:
  874. $sid_table['wordpress_exploit'][] = $sid;
  875. break;
  876. case 5:
  877. $sid_table['general_exploit'][] = $sid;
  878. break;
  879. case 6:
  880. $sid_table['general'][] = $sid;
  881. break;
  882. }
  883. }
  884. ?>
  885. <div class="wrap" style="max-width:95%;">
  886. <h2>Manage Security Modules</h2>
  887. <p>Modules are inserted into your server .htaccess configuration files. Once a module is installed, you may activate it or deactivate it here.</p>
  888. <p><br class="clear" /></p>
  889. <?php foreach( array_reverse( $sid_table ) as $n => $arr ) aa_pp_print_sids_table( $arr, $n );?>
  890. </div>
  891. <?php
  892. }
  893. /**
  894. * aa_pp_print_sids_table()
  895. *
  896. * @param mixed $sids
  897. * @param mixed $context
  898. * @return
  899. */
  900. function aa_pp_print_sids_table( $sids, $context )
  901. {
  902. global $aa_PP, $aa_SIDS;
  903. $aa_SIDS_Active = aa_pp_active_sids();
  904. if ( $context !== 'active' )
  905. {
  906. $ns = array();
  907. $active = array_values( $aa_SIDS_Active );
  908. foreach ( $sids as $sid )
  909. {
  910. if ( !in_array( $sid, $active ) )
  911. $ns[] = $sid;
  912. }
  913. $sids = $ns;
  914. }
  915. if ( sizeof( $sids ) < 1 )return;
  916. $ti = str_replace( '_', ' ', $context );
  917. if ( strpos( $ti, ' ' ) !== false )
  918. {
  919. $word = '';
  920. foreach( explode( " ", $ti ) as $wrd )
  921. $word .= substr_replace( $wrd, strtoupper( substr( $wrd, 0, 1 ) ), 0, 1 ) . " ";
  922. $ti = rtrim( $word, " " );
  923. }
  924. else $ti = substr_replace( $ti, strtoupper( substr( $ti, 0, 1 ) ), 0, 1 );
  925. ?>
  926. <form method="post" action="options-general.php?page=askapache-password-protect.php"><?php wp_nonce_field( 'askapache-bulk-sids' );?>
  927. <div class="tablenav">
  928. <h3 style="text-align:right; width:70%; line-height:2em; margin:0;float:right;padding-right:30px;" id="current-<?php echo $context;?>"><?php echo $ti; ?></h3>
  929. <br class="clear" />
  930. </div>
  931. <br class="clear" />
  932. <table class="widefat" id="<?php echo $context;?>-plugins-table">
  933. <thead>
  934. <tr>
  935. <th scope="col">Name</th>
  936. <th scope="col">Description</th>
  937. <th scope="col">Response</th>
  938. <th scope="col">Apache Modules</th>
  939. <th scope="col">File</th>
  940. <th scope="col" class="action-links">Action</th>
  941. </tr>
  942. </thead>
  943. <tbody class="plugins">
  944. <?php
  945. foreach ( $sids as $sid )
  946. {
  947. $st = $oya = '';
  948. $the_sid = $aa_SIDS[$sid];
  949. $file_title = ( $the_sid['File'] == 'root' ) ? $aa_PP['root_htaccess'] : $aa_PP['admin_htaccess'];
  950. if ( $context == 'active' )
  951. {
  952. $st = 'active';
  953. $oya = $the_sid['Type'] . '<br />';
  954. $action_links = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;deactivate-sid=' . $sid, 'deactivate-sid_' . $sid ) . '" class="delete">' . __( 'Deactivate' ) . '</a>';
  955. }
  956. else $action_links = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;activate-sid=' . $sid, 'activate-sid_' . $sid ) . '" class="edit">' . __( 'Activate' ) . '</a>';
  957. echo "<tr class='{$st}'>
  958. <td class='name' style='width:200px;'>" . $oya . "<dfn style='font-style:normal;color:#3366CC;' title='SID: " . $sid . " Version: " . $the_sid['Version'] . "'>" . $the_sid['Name'] . "</dfn></td>
  959. <td class='desc' style='width:450px;'><p>" . $the_sid['Description'] . "</p></td>
  960. <td class='vers'>" . $the_sid['Response'] . "</td>
  961. <td class='file'>" . $the_sid['Module'] . "</td>
  962. <td class='file'><dfn style='font-style:normal;color:#9999DD;' title='" . $file_title . "'>" . $the_sid['File'] . "</dfn></td>
  963. <td class='action-links'>" . $action_links . '</td></tr>';
  964. }
  965. ?>
  966. </tbody>
  967. </table>
  968. </form>
  969. <p><br class="clear" /></p>
  970. <?php
  971. }
  972. /**
  973. * aa_pp_active_sids()
  974. *
  975. * @param mixed $file
  976. * @return
  977. */
  978. function aa_pp_active_sids( $file = false )
  979. {
  980. global $aa_PP, $aa_SIDS;
  981. $result = array();
  982. $files = array( $aa_PP['root_htaccess'], $aa_PP['admin_htaccess'] );
  983. foreach ( $files as $f )
  984. {
  985. if ( !is_readable( $f ) )return new WP_Error( 'not-readable', __( "aa_pp_active_sids cant read from {$f}" ) );
  986. if ( $markerdata = @explode( "\n", @implode( '', @file( $f ) ) ) )
  987. {
  988. foreach ( $markerdata as $line )
  989. {
  990. if ( strpos( $line, "# +SID " ) !== false ) $result[] = ( int )str_replace( '# +SID ', '', rtrim( $line ) );
  991. }
  992. }
  993. }
  994. return array_unique( $result );
  995. }
  996. /**
  997. * aa_pp_gen_sid()
  998. *
  999. * @param mixed $incoming
  1000. * @return
  1001. */
  1002. function aa_pp_gen_sid( $incoming )
  1003. {
  1004. global $aa_PP, $aa_SIDS;
  1005. if ( $aa_PP['authtype'] == 'Basic' ) $replacement = 'AuthType %authtype%%n%AuthName "%authname%"%n%AuthUserFile %authuserfile%%n%Require user %user%';
  1006. else $replacement = 'AuthType %authtype%%n%AuthName "%authname%"%n%AuthDigestDomain %authdomain%%n%'.$aa_PP['authuserdigest'].' %authuserfile%%n%Require valid-user';
  1007. if ( strpos( $aa_PP['apache_version'], '2.2' ) !== false && $aa_PP['authtype'] != 'Basic' )$replacement = str_replace( 'AuthDigestFile', 'AuthUserFile', $replacement );
  1008. $aa_S = array( '%n%', '%authname%', '%user%', '%authuserfile%', '%relative_root%', '%scheme%', '%authdomain%', '%host%', '%authtype%', '%generate_auth%' );
  1009. $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 );
  1010. return str_replace( $aa_S, $aa_R, str_replace( $aa_S, $aa_R, $incoming ) );
  1011. }
  1012. /**
  1013. * aa_pp_deactivate_sid()
  1014. *
  1015. * @param mixed $sid
  1016. * @param string $mark
  1017. * @param mixed $file
  1018. * @return
  1019. */
  1020. function aa_pp_deactivate_sid( $sid, $mark = 'SID ', $file = false )
  1021. {
  1022. global $aa_PP, $aa_SIDS;
  1023. if ( !$file )
  1024. {
  1025. $the_sid = $aa_SIDS[( int )$sid];
  1026. $file = ( $the_sid['File'] == 'root' ) ? $aa_PP['root_htaccess'] : $aa_PP['admin_htaccess'];
  1027. }
  1028. $file = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1029. if ( !is_readable( $file ) || !is_writable( $file ) ) return new WP_Error( 'sid-deactivation-failed', __( "{$file} not readable/writable by aa_pp_deactivate_sid for {$the_sid['Name']}" ) );
  1030. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Deleting {$the_sid['Name']} from {$file}" );
  1031. $result = array();
  1032. if ( $markerdata = @explode( "\n", @implode( '', @file( $file ) ) ) )
  1033. {
  1034. $state = false;
  1035. if ( !$f = @fopen( $file, 'w' ) ) return new WP_Error( 'fopen-failed', __( "aa_pp_deactivate_sid couldnt fopen {$file}" ) );
  1036. foreach ( $markerdata as $n => $line )
  1037. {
  1038. if ( strpos( $line, "# +{$mark}{$sid}" ) !== false ) $state = true;
  1039. if ( !$state ) fwrite( $f, $line . "\n" );
  1040. if ( strpos( $line, "# -{$mark}{$sid}" ) !== false ) $state = false;
  1041. }
  1042. }
  1043. @$_POST['notice'] = "Successfully Deactivated {$the_sid['Name']}";
  1044. if ( !fclose( $f ) )return new WP_Error( 'fclose-failed', __( "fclose failed to close {$file} in aa_pp_deactivate_sid" ) );
  1045. return true;
  1046. }
  1047. /**
  1048. * aa_pp_activate_sid()
  1049. *
  1050. * @param mixed $sid
  1051. * @param mixed $file
  1052. * @return
  1053. */
  1054. function aa_pp_activate_sid( $sid, $file = false )
  1055. {
  1056. global $aa_PP, $aa_SIDS;
  1057. $the_sid = $aa_SIDS[( int )$sid];
  1058. if ( !$file ) $file = ( $the_sid['File'] == 'root' ) ? $aa_PP['root_htaccess'] : $aa_PP['admin_htaccess'];
  1059. $file = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1060. if ( !is_readable( $file ) || !is_writable( $file ) ) return new WP_Error( 'not-writable', __( "{$file} not readable/writable by aa_pp_activate_sid for {$the_sid['Name']}" ) );
  1061. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Activating {$the_sid['Name']} to {$file}" );
  1062. $rules = aa_pp_gen_sid( explode( "\n", $the_sid['Rules'] ) );
  1063. if ( !aa_pp_insert_sids( $file, $sid, $rules ) ) return new WP_Error( 'sid-activation-failed', __( "Failed to Activate {$the_sid['Name']}" ) );
  1064. else
  1065. {
  1066. @$_POST['notice'] = "Successfully Activated {$sid}: &quot;{$the_sid['Name']}&quot;<br /><pre>";
  1067. foreach( $rules as $line )@$_POST['notice'] .= htmlentities( $line );
  1068. @$_POST['notice'] .= '</pre>';
  1069. }
  1070. return true;
  1071. }
  1072. /**
  1073. * aa_pp_htaccess_file_init()
  1074. *
  1075. * @param mixed $file
  1076. * @return
  1077. */
  1078. function aa_pp_htaccess_file_init( $file = false )
  1079. {
  1080. global $aa_PP;
  1081. if ( !$file ) $files = array( $aa_PP['admin_htaccess'], $aa_PP['root_htaccess'] );
  1082. else $files = array( $file );
  1083. foreach( $files as $file )
  1084. {
  1085. $wordp = $new = $jot = array();
  1086. $aapasspro = $wpg = $s = false;
  1087. $l1 = str_repeat( '#', 55 );
  1088. $l2 = '# - - - - - - - - - - - - - - - - - - - - - - - - - - -';
  1089. $logo = array(
  1090. '# __ __',
  1091. '# ____ ______/ /______ _____ ____ ______/ /_ ___',
  1092. '# / __ `/ ___/ //_/ __ `/ __ \/ __ `/ ___/ __ \/ _ \ ',
  1093. '# / /_/ (__ ) ,< / /_/ / /_/ / /_/ / /__/ / / / __/',
  1094. '# \__,_/____/_/|_|\__,_/ .___/\__,_/\___/_/ /_/\___/',
  1095. '# /_/'
  1096. );
  1097. $ot = array_merge( array( '# +ASKAPACHE PASSPRO ' . $aa_PP['plugin_data']['Version'], $l1 ), $logo );
  1098. $ot = array_merge( $ot, array( $l2, '# +APRO SIDS' ) );
  1099. $ot = array_merge( $ot, array( '# -APRO SIDS', $l2 ), $logo );
  1100. $ot = array_merge( $ot, array( $l1, '# -ASKAPACHE PASSPRO ' . $aa_PP['plugin_data']['Version'], '' ) );
  1101. $markerdata = ( is_writable( dirname( $file ) ) && touch( $file ) ) ? @explode( "\n", @implode( '', @file( $file ) ) ) : false;
  1102. if ( $markerdata )
  1103. {
  1104. foreach ( $markerdata as $line )
  1105. {
  1106. if ( strpos( $line, '# BEGIN WordPress' ) !== false )
  1107. {
  1108. $s = $wpg = true;
  1109. $wordp[] = "";
  1110. }
  1111. if ( $s === true ) $wordp[] = $line;
  1112. if ( strpos( $line, '# END WordPress' ) !== false )
  1113. {
  1114. $s = false;
  1115. continue;
  1116. }
  1117. if ( !$s ) $new[] = $line;
  1118. if ( strpos( $line, '# +ASKAPACHE PASSPRO' ) !== false ) $aapasspro = true;
  1119. }
  1120. }
  1121. if ( !$aapasspro )
  1122. {
  1123. $jot = ( $wpg ) ? array_merge( $new, $ot, $wordp ) : array_merge( $markerdata, $ot );
  1124. if ( !$f = @fopen( $file, 'w' ) ) return new WP_Error( 'fopen-failed', __( "aa_pp_htaccess_file_init couldnt fopen {$file}" ) );
  1125. $pr = join( "\n", $jot );
  1126. if ( !@fwrite( $f, $pr, strlen( $pr ) ) ) return new WP_Error( 'aa_pp_htaccess_file_init', __( "aa_pp_insert_mark couldnt fwrite {$file}" ) );
  1127. if ( !@fclose( $f ) ) return new WP_Error( 'fclose-failed', __( "Couldnt fclose {$file}" ) );
  1128. }
  1129. }
  1130. return true;
  1131. }
  1132. /**
  1133. * aa_pp_insert_mark()
  1134. *
  1135. * @param mixed $file
  1136. * @param mixed $marker
  1137. * @param mixed $insertion
  1138. * @param mixed $backup
  1139. * @return
  1140. */
  1141. function aa_pp_insert_mark( $file, $marker, $insertion, $backup = false )
  1142. {
  1143. global $aa_PP;
  1144. $file = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1145. if ( !is_writable( $file ) && @!chmod( $file, 0666 ) && !@touch( $file ) ) return new WP_Error( 'creation-failed', __( "aa_pp_insert_mark could not write, create, or touch {$file}" ) );
  1146. if ( $backup ) $backedup = aa_pp_backup( $file, $file . '-' . time() );
  1147. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Inserting {$marker} array to {$file}" );
  1148. $oldone = $foundit = false;
  1149. $out = array();
  1150. if ( !is_array( $insertion ) || ( is_array( $insertion ) && count( $insertion ) < 1 ) )
  1151. {
  1152. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "aa_pp_insert_mark1 called without array, creating one for {$marker}" );
  1153. $my = array( "# +{$marker}", "", "# -{$marker}" );
  1154. }
  1155. else
  1156. {
  1157. $my = array();
  1158. $my[] = "# +{$marker}";
  1159. foreach ( $insertion as $l ) $my[] = $l;
  1160. $my[] = "# -{$marker}";
  1161. }
  1162. if ( !$f = @fopen( $file, 'w' ) ) return new WP_Error( 'fopen-failed', __( "aa_pp_insert_mark couldnt fopen {$file}" ) );
  1163. $pr = join( "\n", $my );
  1164. if ( !@fwrite( $f, $pr, strlen( $pr ) ) ) return new WP_Error( 'fwrite-failed', __( "aa_pp_insert_mark couldnt fwrite {$file}" ) );
  1165. if ( !@fwrite( $f, $out, strlen( $out ) ) ) return new WP_Error( 'fwrite-failed', __( "aa_pp_insert_mark couldnt fwrite {$file}" ) );
  1166. if ( !@fclose( $f ) ) return new WP_Error( 'fclose-failed', __( "Couldnt fclose {$file}" ) );
  1167. return true;
  1168. }
  1169. /**
  1170. * aa_pp_insert_sids()
  1171. *
  1172. * @param mixed $file
  1173. * @param mixed $marker
  1174. * @param mixed $insertion
  1175. * @param mixed $backup
  1176. * @return
  1177. */
  1178. function aa_pp_insert_sids( $file, $marker, $insertion, $backup = false )
  1179. {
  1180. global $aa_PP;
  1181. $file = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1182. if ( !is_writable( $file ) && @!chmod( $file, 0666 ) && !@touch( $file ) ) return new WP_Error( 'creation-failed', __( "aa_pp_insert_sids could not write, create, or touch {$file}" ) );
  1183. if ( $backup ) $backedup = aa_pp_backup( $file, $file . '-' . time() );
  1184. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Inserting {$marker} array to {$file}" );
  1185. $foundit = false;
  1186. $out = array();
  1187. if ( !is_array( $insertion ) || ( is_array( $insertion ) && count( $insertion ) < 1 ) )
  1188. {
  1189. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "aa_pp_insert_sids called without array, creating one for {$marker}" );
  1190. $my = array( "# +SID {$marker}", "", "# -SID {$marker}" );
  1191. }
  1192. else
  1193. {
  1194. $my = array();
  1195. $my[] = "# +SID {$marker}";
  1196. foreach ( $insertion as $l ) $my[] = $l;
  1197. $my[] = "# -SID {$marker}";
  1198. }
  1199. if ( $markerdata = @explode( "\n", @implode( '', @file( $file ) ) ) )
  1200. {
  1201. if ( !$f = @fopen( $file, 'w' ) ) return new WP_Error( 'fopen-failed', __( "aa_pp_insert_sids couldnt fopen {$file}" ) );
  1202. $state = $s = $found = false;
  1203. foreach ( $markerdata as $line )
  1204. {
  1205. if ( strpos( $line, '-ASKAPACHE PASSPRO' ) !== false )
  1206. {
  1207. fwrite( $f, $line . "\n" );
  1208. continue;
  1209. }
  1210. if ( strpos( $line, "# +APRO SIDS" ) !== false )
  1211. {
  1212. $s = true;
  1213. fwrite( $f, $line . "\n" );
  1214. continue;
  1215. }
  1216. if ( strpos( $line, "# -APRO SIDS" ) !== false )
  1217. {
  1218. $s = false;
  1219. if ( !$found )
  1220. {
  1221. foreach ( $my as $in ) fwrite( $f, $in . "\n" );
  1222. }
  1223. fwrite( $f, $line . "\n" );
  1224. continue;
  1225. }
  1226. if ( !$s ) fwrite( $f, $line . "\n" );
  1227. else
  1228. {
  1229. if ( strpos( $line, "# +SID {$marker}" ) !== false ) $state = true;
  1230. if ( !$state )fwrite( $f, $line . "\n" );
  1231. if ( strpos( $line, "# -SID {$marker}" ) !== false )
  1232. {
  1233. $state = false;
  1234. $found = true;
  1235. foreach ( $my as $in ) fwrite( $f, $in . "\n" );
  1236. }
  1237. }
  1238. }
  1239. fclose( $f );
  1240. }
  1241. return true;
  1242. }
  1243. /**
  1244. * aa_pp_hashit()
  1245. *
  1246. * @param mixed $algorithm
  1247. * @param string $user
  1248. * @param string $pass
  1249. * @param string $authname
  1250. * @return
  1251. */
  1252. function aa_pp_hashit( $algorithm, $user = '', $pass = '', $authname = '' )
  1253. {
  1254. global $aa_PP, $aa_SIDS;
  1255. $hash = $tmp = '';
  1256. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . 'Creating ' . $algorithm . ' Hash in aa_pp_hashit' );
  1257. switch ( strtoupper( $algorithm ) )
  1258. {
  1259. case 'DIGEST':
  1260. $hash = $user . ":" . $authname . ":" . md5( $user . ":" . $authname . ":" . $pass );
  1261. break;
  1262. case 'CRYPT':
  1263. $seed = null;
  1264. for ( $i = 0; $i < 8; $i++ ) $seed .= substr( '0123456789abcdef', rand( 0, 15 ), 1 );
  1265. $hash = "{$user}:" . crypt( $pass, "$" . $seed );
  1266. break;
  1267. case 'SHA1':
  1268. $hash = $user . ':{SHA}' . base64_encode( pack( "H*", sha1( $pass ) ) );
  1269. break;
  1270. case 'MD5':
  1271. $saltt = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyz0123456789" ), 0, 8 );
  1272. $len = strlen( $pass );
  1273. $text = $pass . '$apr1$' . $saltt;
  1274. $bin = pack( "H32", md5( $pass . $saltt . $pass ) );
  1275. for ( $i = $len; $i > 0; $i -= 16 ) $text .= substr( $bin, 0, min( 16, $i ) );
  1276. for ( $i = $len; $i > 0; $i >>= 1 ) $text .= ( $i &1 ) ? chr( 0 ) : $pass{0};
  1277. $bin = pack( "H32", md5( $text ) );
  1278. for ( $i = 0; $i < 1000; $i++ )
  1279. {
  1280. $new = ( $i &1 ) ? $pass : $bin;
  1281. if ( $i % 3 ) $new .= $saltt;
  1282. if ( $i % 7 ) $new .= $pass;
  1283. $new .= ( $i &1 ) ? $bin : $pass;
  1284. $bin = pack( "H32", md5( $new ) );
  1285. }
  1286. for ( $i = 0; $i < 5; $i++ )
  1287. {
  1288. $k = $i + 6;
  1289. $j = $i + 12;
  1290. if ( $j == 16 ) $j = 5;
  1291. $tmp = $bin[$i] . $bin[$k] . $bin[$j] . $tmp;
  1292. }
  1293. $tmp = chr( 0 ) . chr( 0 ) . $bin[11] . $tmp;
  1294. $tmp = strtr( strrev( substr( base64_encode( $tmp ), 2 ) ), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" );
  1295. $hash = $user . ':$apr1$' . $saltt . '$' . $tmp;
  1296. break;
  1297. }
  1298. return $hash;
  1299. }
  1300. /**
  1301. * aa_pp_run_tests()
  1302. *
  1303. * @return
  1304. */
  1305. function aa_pp_run_tests()
  1306. {
  1307. global $wpdb, $wp_version, $aa_PP, $aa_SIDS;
  1308. require_once ( dirname( __FILE__ ) . '/class-askapache-net.php' );
  1309. $ap = array();
  1310. $ap = $aa_PP;
  1311. $home = get_option( 'siteurl' );
  1312. $hu = str_replace( $ap['scheme'] . '://', '', $home );
  1313. $uri = $ap['scheme'] . '://' . rtrim( str_replace( rtrim( $ap['root_path'], '/' ), '', $hu ), '/' );
  1314. $test_root_path = $ap['root_path'] . 'wp-content/' . basename( $ap['test_dir'] ) . '/';
  1315. $test_url_base = $uri . $test_root_path;
  1316. $home_path = rtrim( get_home_path(), '/' ) . '/';
  1317. $basic_authuserfile = $ap['test_dir'] . '/.htpasswd-basic';
  1318. $digest_authuserfile = $ap['test_dir'] . '/.htpasswd-digest';
  1319. $img = pack( "H*", "47494638396101000100910000000000ffffffffffff00000021f90405140002002c00000000010001000002025401003b" );
  1320. $aok = '<strong style="color:#319F52;background-color:#319F52;">[ ]</strong> ';
  1321. $fail = '<strong style="color:#CC0000;background-color:#CC0000;">[ ]</strong> ';
  1322. $info = '<strong style="color:#9999DD;background-color:#9999DD;">[ ]</strong> ';
  1323. $warn = '<strong style="color:#E6DB55;background-color:#E6DB55;">[ ]</strong> ';
  1324. $m_s = '<h4 style="font-weight:normal">';
  1325. $m_e = '</h4>';
  1326. $test_htaccess_rules = array(
  1327. "ErrorDocument 401 {$test_root_path}test.gif",
  1328. "ErrorDocument 403 {$test_root_path}test.gif",
  1329. "ErrorDocument 404 {$test_root_path}test.gif",
  1330. "ErrorDocument 500 {$test_root_path}test.gif",
  1331. "<IfModule mod_alias.c>",
  1332. 'RedirectMatch 305 ^.*modaliastest$ ' . $home,
  1333. "</IfModule>",
  1334. "<IfModule mod_rewrite.c>",
  1335. "RewriteEngine On",
  1336. "RewriteBase /",
  1337. 'RewriteCond %{QUERY_STRING} modrewritetest [NC]',
  1338. 'RewriteRule .* ' . $home . ' [R=307,L]',
  1339. "</IfModule>",
  1340. '<Files modsec_check.gif>',
  1341. "<IfModule mod_security.c>",
  1342. 'SetEnv MODSEC_ENABLE On',
  1343. "SecFilterEngine On",
  1344. 'SecFilterDefaultAction "nolog,noauditlog,pass"',
  1345. 'SecAuditEngine Off',
  1346. 'SecFilterInheritance Off',
  1347. 'SecFilter modsecuritytest "deny,nolog,noauditlog,status:503"',
  1348. 'Deny from All',
  1349. "</IfModule>",
  1350. '</Files>',
  1351. '<Files basic_auth_test.gif>',
  1352. "AuthType Basic",
  1353. 'AuthName "askapache test"',
  1354. "AuthUserFile " . $basic_authuserfile,
  1355. "Require valid-user",
  1356. '</Files>',
  1357. '<Files digest_check.gif>',
  1358. 'AuthType Digest',
  1359. 'AuthName "askapache test"',
  1360. "AuthDigestDomain {$test_root_path} {$test_url_base}",
  1361. "AuthUserFile " . $digest_authuserfile,
  1362. 'Require none',
  1363. '</Files>',
  1364. '<Files authuserfile_test.gif>',
  1365. 'AuthType Digest',
  1366. 'AuthName "askapache test"',
  1367. "AuthDigestDomain {$test_root_path} {$test_url_base}",
  1368. "AuthUserFile " . $digest_authuserfile,
  1369. 'Require valid-user',
  1370. '</Files>',
  1371. '<Files authdigestfile_test.gif>',
  1372. 'AuthType Digest',
  1373. 'AuthName "askapache test"',
  1374. "AuthDigestDomain {$test_root_path} {$test_url_base}",
  1375. "AuthDigestFile " . $digest_authuserfile,
  1376. 'Require valid-user',
  1377. '</Files>'
  1378. );
  1379. ?>
  1380. <div class="wrap" style="max-width:95%;">
  1381. <h2>Test Results</h2>
  1382. <br /><br /><h2 style="font-size:16px;">Required Checks</h2>
  1383. <p>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.</p>
  1384. <p>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.</p>
  1385. <?php
  1386. $netok = $atest = ( aa_pp_checkfunction( 'fsockopen' ) ) ? 1 : 0;
  1387. $msg = ( $atest ) ? $aok : $fail;
  1388. echo $m_s . $msg . " Fsockopen Networking Functionality" . $m_e;?>
  1389. <br /><br /><h2 style="font-size:16px;">File Permission Tests</h2>
  1390. <p>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.</p>
  1391. <?php
  1392. $htaccess_test1 = $atest = ( @is_writable( $ap['admin_htaccess'] ) || @touch( $ap['admin_htaccess'] ) ) ? 1 : 0;
  1393. $msg = ( $atest ) ? $aok : $fail;
  1394. echo $m_s . $msg . " /wp-admin/.htaccess file writable" . $m_e;
  1395. $htaccess_test2 = $atest = ( @is_writable( $ap['root_htaccess'] ) || @touch( $ap['root_htaccess'] ) ) ? 1 : 0;
  1396. $msg = ( $atest ) ? $aok : $fail;
  1397. echo $m_s . $msg . " /wp-admin/.htaccess file writable" . $m_e;
  1398. $atest = ( @is_writable( dirname( dirname( $ap['root_htaccess'] ) ) . '/.htpasswda3' ) || @touch( dirname( dirname( $ap['root_htaccess'] ) ) . '/.htpasswda3' ) ) ? 1 : 0;
  1399. $msg = ( $atest ) ? $aok : $fail;
  1400. echo $m_s . $msg . dirname( dirname( $ap['root_htaccess'] ) ) . '/.htpasswda3' . " file writable" . $m_e;
  1401. if ( !$atest )
  1402. {
  1403. $atest = ( @is_writable( $ap['authuserfile'] ) || @touch( $ap['authuserfile'] ) ) ? 1 : 0;
  1404. $msg = ( $atest ) ? $aok : $fail;
  1405. echo $m_s . $msg . $ap['authuserfile'] . " file writable" . $m_e;
  1406. }
  1407. else $ap['authuserfile'] = dirname( dirname( $ap['root_htaccess'] ) ) . '/.htpasswda3';
  1408. $atest = ( aa_pp_mkdir( $ap['test_dir'] ) ) ? 1 : 0;
  1409. $msg = ( $atest ) ? $aok : $fail;
  1410. echo $m_s . $msg . " Creating test folder" . $m_e;
  1411. if( (bool)$atest ===false ) wp_die("Couldnt create test folder {$ap['test_dir']}!");
  1412. $atest = ( @is_writable( $ap['test_dir'] ) || @chmod( $ap['test_dir'], 766 ) ) ? 1 : 0;
  1413. $msg = ( $atest ) ? $aok : $fail;
  1414. echo $m_s . $msg . " Test folder writable" . $m_e;
  1415. $atest = ( aa_pp_insert_mark( $ap['test_dir'] . '/.htpasswd-basic', 'AskApache PassPro', array() ) ) ? 1 : 0;
  1416. $msg = ( $atest ) ? $aok : $fail;
  1417. echo $m_s . $msg . " Basic Auth htpasswd file writable" . $m_e;
  1418. $msg = ( $atest ) ? $aok : $fail;
  1419. $atest = ( aa_pp_insert_mark( $ap['test_dir'] . '/.htpasswd-digest', 'AskApache PassPro', array() ) ) ? 1 : 0;
  1420. echo $m_s . $msg . " Digest Auth htpasswd file writable" . $m_e;
  1421. aa_pp_htaccess_file_init( $ap['test_dir'] . '/.htaccess' );
  1422. $atest = ( aa_pp_insert_sids( $ap['test_dir'] . '/.htaccess', 'Test', $test_htaccess_rules ) ) ? 1 : 0;
  1423. echo $m_s . $msg . " .htaccess test file writable" . $m_e;?>
  1424. <br /><br /><h2 style="font-size:16px;">Encryption Function Tests</h2>
  1425. <p>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.</p>
  1426. <?php
  1427. $ap['crypt_support'] = $atest = ( aa_pp_checkfunction( 'crypt' ) ) ? 1 : 0;
  1428. $msg = ( $atest ) ? $aok : $warn;
  1429. echo $m_s . $msg . " CRYPT Encryption Function Available" . $m_e;
  1430. $ap['md5_support'] = $atest = ( aa_pp_checkfunction( 'md5' ) ) ? 1 : 0;
  1431. $msg = ( $atest ) ? $aok : $fail;
  1432. echo $m_s . $msg . " MD5 Encryption Function Available" . $m_e;
  1433. $ap['sha1_support'] = $atest = ( aa_pp_checkfunction( 'sha1' ) ) ? 1 : 0;
  1434. $msg = ( $atest ) ? $aok : $warn;
  1435. echo $m_s . $msg . " SHA1 Encryption Function Available" . $m_e;
  1436. $atest = ( aa_pp_checkfunction( 'pack' ) ) ? 1 : 0;
  1437. $msg = ( $atest ) ? $aok : $warn;
  1438. echo $m_s . $msg . " pack Function Available" . $m_e;
  1439. $atest = ( aa_pp_checkfunction( 'md5_file' ) ) ? 1 : 0;
  1440. $msg = ( $atest ) ? $aok : $warn;
  1441. echo $m_s . $msg . " md5_file Function Available" . $m_e;?>
  1442. <br /><br /><h2 style="font-size:16px;">Revision Tests</h2>
  1443. <p>This checks for the neccessary file permissions and functions needed to utilize the .htaccess file revision support.</p>
  1444. <?php
  1445. $atest = ( aa_pp_checkfunction( 'base64_encode' ) && aa_pp_checkfunction( 'base64_decode' ) ) ? 1 : 0;
  1446. $msg = ( $atest ) ? $aok : $warn;
  1447. echo $m_s . $msg . " base64_encode/base64_decode Functions Available" . $m_e;
  1448. $ap['gzip_support'] = $atest = ( aa_pp_checkfunction( 'gzuncompress' ) && aa_pp_checkfunction( 'gzcompress' ) ) ? 1 : 0;
  1449. $msg = ( $atest ) ? $aok : $warn;
  1450. echo $m_s . $msg . " gzuncompress/gzcompress Functions Available" . $m_e;
  1451. if ( $atest )
  1452. {
  1453. $data = aa_pp_readfile( $ap['test_dir'] . '/.htaccess' );
  1454. $data_md5 = md5_file( $ap['test_dir'] . '/.htaccess' );
  1455. $data_compress = base64_encode( gzcompress( $data, 9 ) );
  1456. aa_pp_file_put_c( $ap['test_dir'] . '/.htaccess-compress', $data_compress );
  1457. $data_decompress = gzuncompress( base64_decode( aa_pp_readfile( $ap['test_dir'] . '/.htaccess-compress' ) ) );
  1458. aa_pp_file_put_c( $ap['test_dir'] . '/.htaccess-decompress', $data_decompress );
  1459. $data_decompress_md5 = md5_file( $ap['test_dir'] . '/.htaccess-decompress' );
  1460. $atest = ( $data_decompress_md5 == $data_md5 ) ? 1 : 0;
  1461. $msg = ( $atest ) ? $aok : $fail;
  1462. echo $m_s . $msg . " Revisions Enabled" . $m_e;
  1463. echo "<p>Decompressed MD5: " . $data_decompress_md5 . "<br />Compressed MD5: " . $data_md5 . "</p>";
  1464. }
  1465. ?>
  1466. <br /><br /><h2 style="font-size:16px;">.htaccess Capabilities</h2>
  1467. <p>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 ;)</p>
  1468. <?php
  1469. $atest = ( aa_pp_file_put_c( $ap['test_dir'] . "/test.gif", $img )
  1470. && aa_pp_file_put_c( $ap['test_dir'] . "/basic_auth_test.gif", $img )
  1471. && aa_pp_file_put_c( $ap['test_dir'] . "/authuserfile_test.gif", $img )
  1472. && aa_pp_file_put_c( $ap['test_dir'] . "/authdigestfile_test.gif", $img )
  1473. && aa_pp_file_put_c( $ap['test_dir'] . "/modsec_check.gif", $img )
  1474. && aa_pp_file_put_c( $ap['test_dir'] . "/digest_check.gif", $img ) ) ? 1 : 0;
  1475. $msg = ( $atest ) ? $aok : $fail;
  1476. echo $m_s . $msg . " Creating .htaccess test files" . $m_e;
  1477. if ( (bool)AA_PP_DEBUG === true ) {
  1478. echo $m_s . $msg . " Test .htaccess Contents" . $m_e;
  1479. echo '<pre style="padding:5px;width:auto;border:1px dotted #CCC;">';
  1480. foreach ( $test_htaccess_rules as $l )
  1481. echo htmlentities($l)."\n";
  1482. echo '</pre>';
  1483. }
  1484. $tester = new AskApacheNet;
  1485. $ap['htaccess_support'] = $atest = ( $tester->sockit( "{$test_url_base}test.gif" ) == 200 ) ? 1 : 0;
  1486. $msg = ( $atest ) ? $aok : $fail;
  1487. echo $m_s . $msg . " .htaccess files allowed [200]" . $m_e;
  1488. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1489. $tester = new AskApacheNet;
  1490. $ap['mod_alias_support'] = $atest = ( $tester->sockit( "{$test_url_base}modaliastest" ) == 305 ) ? 1 : 0;
  1491. $msg = ( $atest ) ? $aok : $warn;
  1492. echo $m_s . $msg . " mod_alias detection [305]" . $m_e;
  1493. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1494. $tester = new AskApacheNet;
  1495. $ap['mod_rewrite_support'] = $atest = ( $tester->sockit( "{$test_url_base}test.gif?modrewritetest=1" ) == 307 ) ? 1 : 0;
  1496. $msg = ( $atest ) ? $aok : $warn;
  1497. echo $m_s . $msg . " mod_rewrite detection [307]" . $m_e;
  1498. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1499. $tester = new AskApacheNet;
  1500. $ap['mod_security_support'] = $atest = ( $tester->sockit( "{$test_url_base}modsec_check.gif?modsecuritytest" ) != 200 ) ? 1 : 0;
  1501. $msg = ( $atest ) ? $aok : $warn;
  1502. echo $m_s . $msg . " mod_security detection [!200]" . $m_e;
  1503. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1504. $tester = new AskApacheNet;
  1505. $ap['mod_auth_digest_support'] = $atest = ( $tester->sockit( "{$test_url_base}digest_check.gif" ) == 401 ) ? 1 : 0;
  1506. $msg = ( $atest ) ? $aok : $warn;
  1507. echo $m_s . $msg . " mod_auth_digest detection [401]" . $m_e;
  1508. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1509. ?>
  1510. <br /><br /><h2 style="font-size:16px;">HTTP Digest Authentication</h2>
  1511. <p>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.</p>
  1512. <?php
  1513. if ( $ap['mod_auth_digest_support'] != 0 && $ap['md5_support'] != 0 )
  1514. {
  1515. $digest_htpasswds = array();
  1516. $digest_htpasswds[] = aa_pp_hashit( 'DIGEST', "testDIGEST", "testDIGEST", "askapache test" );
  1517. $atest = ( aa_pp_insert_mark( $digest_authuserfile, 'AskApache PassPro Test', $digest_htpasswds ) ) ? 1 : 0;
  1518. $msg = ( $atest ) ? $aok : $fail;
  1519. echo $m_s . $msg . " Creating Digest htpasswd test file" . $m_e;
  1520. $tester = new AskApacheNet;
  1521. $tester->authtype = '';
  1522. $rb = ( $tester->sockit( $test_url_base . 'authdigestfile_test.gif' ) == 401 ) ? 1 : 0;
  1523. $tester->sockit( str_replace( '://', '://testDIGEST:testDIGEST@', $test_url_base ) . 'authdigestfile_test.gif' );
  1524. $tester->authtype = 'Digest';
  1525. $rg = ( $tester->sockit( str_replace( '://', '://testDIGEST:testDIGEST@', $test_url_base ) . 'authdigestfile_test.gif' ) == 200 ) ? 1 : 0;
  1526. $ap['digest_support'] = $atest = ( $rb && $rg ) ? 1 : 0;
  1527. $msg = ( $atest ) ? $aok : $fail;
  1528. echo $m_s . $msg . " Digest Authentication Attempt" . $m_e;
  1529. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1530. if ( !$atest )
  1531. {
  1532. $tester = new AskApacheNet;
  1533. $tester->authtype = '';
  1534. $rb = ( $tester->sockit( $test_url_base . 'authuserfile_test.gif' ) == 401 ) ? 1 : 0;
  1535. $tester->sockit( str_replace( '://', '://testDIGEST:testDIGEST@', $test_url_base ) . 'authuserfile_test.gif' );
  1536. $tester->authtype = 'Digest';
  1537. $rg = ( $tester->sockit( str_replace( '://', '://testDIGEST:testDIGEST@', $test_url_base ) . 'authuserfile_test.gif' ) == 200 ) ? 1 : 0;
  1538. $ap['digest_support'] = $a1test = ( $rb && $rg ) ? 1 : 0;
  1539. $msg = ( $a1test ) ? $aok : $fail;
  1540. echo $m_s . $msg . "2nd Digest Authentication Attempt" . $m_e;
  1541. if ( (bool)AA_PP_DEBUG === true || !$a1test )$tester->print_tcp_trace();
  1542. }
  1543. if ( (bool)$ap['digest_support'] !== false ) $ap['authuserdigest'] = ( $atest ) ? 'AuthDigestFile' : 'AuthUserFile';
  1544. }
  1545. else echo $m_s . $msg . $fail . " Bummer... you don't have digest capabilities." . $m_e;?>
  1546. <br /><br /><h2 style="font-size:16px;">Basic Authentication Encryption Algorithms</h2>
  1547. <p>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.</p>
  1548. <?php
  1549. $basic_htpasswds = array();
  1550. if ( $ap['crypt_support'] != 0 ) $basic_htpasswds[] = aa_pp_hashit( 'CRYPT', 'testCRYPT', 'testCRYPT' );
  1551. if ( $ap['md5_support'] != 0 ) $basic_htpasswds[] = aa_pp_hashit( 'MD5', 'testMD5', 'testMD5' );
  1552. if ( $ap['sha1_support'] != 0 ) $basic_htpasswds[] = aa_pp_hashit( 'SHA1', 'testSHA1', 'testSHA1' );
  1553. $atest = ( aa_pp_insert_mark( $basic_authuserfile, 'AskApache PassPro Test', $basic_htpasswds ) ) ? 1 : 0;
  1554. $msg = ( $atest ) ? $aok : $fail;
  1555. echo $m_s . $msg . " Creating Basic htpasswd test file" . $m_e;
  1556. $tester = new AskApacheNet;
  1557. $rb = ( $tester->sockit( $test_url_base . 'basic_auth_test.gif' ) == 401 ) ? 1 : 0;
  1558. if ( $ap['crypt_support'] != 0 )
  1559. {
  1560. $tester = new AskApacheNet;
  1561. $rg = ( $tester->sockit( str_replace( '://', '://testCRYPT:testCRYPT@', $test_url_base ) . 'basic_auth_test.gif' ) == 200 ) ? 1 : 0;
  1562. $ap['crypt_support'] = $atest = ( $rb && $rg ) ? 1 : 0;
  1563. $msg = ( $atest ) ? $aok : $fail;
  1564. echo $m_s . $msg . " Basic Authentication Attempt using Crypt Encryption" . $m_e;
  1565. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1566. }
  1567. if ( $ap['md5_support'] != 0 )
  1568. {
  1569. $tester = new AskApacheNet;
  1570. $rg = ( $tester->sockit( str_replace( '://', '://testMD5:testMD5@', $test_url_base ) . 'basic_auth_test.gif' ) == 200 ) ? 1 : 0;
  1571. $ap['md5_support'] = $atest = ( $rb && $rg ) ? 1 : 0;
  1572. $msg = ( $atest ) ? $aok : $fail;
  1573. echo $m_s . $msg . " Basic Authentication Attempt using MD5 Encryption" . $m_e;
  1574. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1575. }
  1576. if ( $ap['sha1_support'] != 0 )
  1577. {
  1578. $tester = new AskApacheNet;
  1579. $rg = ( $tester->sockit( str_replace( '://', '://testSHA1:testSHA1@', $test_url_base ) . 'basic_auth_test.gif' ) == 200 ) ? 1 : 0;
  1580. $ap['sha1_support'] = $atest = ( $rb && $rg ) ? 1 : 0;
  1581. $msg = ( $atest ) ? $aok : $fail;
  1582. echo $m_s . $msg . " Basic Authentication Attempt using SHA1 Encryption" . $m_e;
  1583. if ( (bool)AA_PP_DEBUG === true || !$atest )$tester->print_tcp_trace();
  1584. }
  1585. $ap['basic_support'] = $atest = ( $ap['sha1_support'] != 0 || $ap['md5_support'] != 0 || $ap['crypt_support'] != 0 ) ? 1 : 0;
  1586. $msg = ( $atest ) ? $aok : $warn;
  1587. echo $m_s . $msg . " Basic Authentication Access Scheme Supported" . $m_e;?>
  1588. <br /><h2 style="font-size:16px;">Compatibility Checks</h2>
  1589. <p>Checks different software to make sure its compatible with this plugin.</p>
  1590. <?php
  1591. $msg = ( $wp_version < 2.6 ) ? $info : $aok;
  1592. echo $m_s . $msg . " WordPress Version " . $wp_version . $m_e;
  1593. $ap['apache_version'] = $apache_version = preg_replace( '|Apache/?([0-9.-]*?) (.*)|i', '\\1', $_SERVER['SERVER_SOFTWARE'] );
  1594. $msg = ( strlen( $apache_version ) == 0 ) ? $info : $aok;
  1595. echo $m_s . $msg . " Apache Version: " . $apache_version . $m_e;
  1596. $msg = ( @version_compare( phpversion(), '4.2.0', '=<' ) ) ? $info : $aok;
  1597. echo $m_s . $msg . " PHP Version " . phpversion() . $m_e;?>
  1598. <br /><br /><h2 style="font-size:16px;">PHP.ini Information</h2>
  1599. <p>Some information about your php.ini settings. The following settings <strong>may</strong> need to be tweaked. Likely they are fine.</p>
  1600. <?php
  1601. $time = abs( intval( @ini_get( "max_execution_time" ) ) );
  1602. echo $m_s . $info . " Max Execution Time: " . $time . $m_e;
  1603. $memm = 10;
  1604. if ( function_exists( "memory_get_peak_usage" ) )$memm = memory_get_peak_usage( true );
  1605. else if ( function_exists( "memory_get_usage" ) )$memm = memory_get_usage( true );
  1606. echo $m_s . $info . "Memory Usage: " . round( $memm / 1024 / 1024, 2 ) . $m_e;
  1607. $mem = abs( intval( @ini_get( 'memory_limit' ) ) );
  1608. echo $m_s . $info . 'Memory Limit: ' . "{$mem}" . $m_e;
  1609. if ( $mem && $mem < abs( intval( 32 ) ) )@ini_set( 'memory_limit', 64 );
  1610. $phpini = @get_cfg_var( 'cfg_file_path' );
  1611. echo $m_s . $info . "php.ini " . $phpini . $m_e;
  1612. $open_basedir = @ini_get( 'open_basedir' );
  1613. $msg = ( empty( $open_basedir ) ) ? $info : $warn;
  1614. echo $m_s . $msg . " open_basedir on/off {$open_basedir}" . $m_e;
  1615. $safe_mode = @ini_get( 'safe_mode' );
  1616. $msg = ( empty( $safe_mode ) ) ? $info : $warn;
  1617. echo $m_s . $msg . " safe_mode on/off {$safe_mode}" . $m_e;
  1618. $disabled_functions = @ini_get( 'disable_functions' );
  1619. $msg = ( empty( $disabled_functions ) ) ? $info : $warn;
  1620. echo $m_s . $msg . " disable_functions {$disabled_functions}" . $m_e;
  1621. foreach( array( 'htaccess_support', 'mod_alias_support', 'mod_rewrite_support', 'mod_security_support', 'mod_auth_digest_support', 'digest_support', 'basic_support' ) as $k )
  1622. {
  1623. if ( $aa_PP[$k] == 1 && $ap[$k] != 1 )
  1624. {
  1625. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "You preset {$k} to on even though it failed the test." );
  1626. $ap[$k] = 1;
  1627. }
  1628. }
  1629. $aa_PP = $ap;
  1630. update_option( 'askapache_password_protect', $aa_PP );
  1631. echo '<br class="clear" /><form action="options-general.php?page=askapache-password-protect.php" method="post">';
  1632. wp_nonce_field( 'askapache-passpro-form' );
  1633. if ( !$htaccess_test1 || !$htaccess_test2 || !$netok || $aa_PP['htaccess_support'] != 1 )
  1634. {
  1635. echo '<p>Im very sorry, but unless you can resolve the failed requirements above you cannot utilize this plugin at this time. :( </p>';
  1636. echo '<p>Change the AA_PP_DEBUG to 1 in the source code of this plugin for verbose reasons why these tests failed.</p>';
  1637. echo '<input type="hidden" id="a_step" name="a_step" value="test" />';
  1638. echo '<p class="submit"><input name="sub" type="submit" id="sub" value="Run Tests Again &raquo;" /></p>';
  1639. }
  1640. else
  1641. {
  1642. echo '<input type="hidden" id="a_step" name="a_step" value="setup" />';
  1643. echo '<p class="submit"><input name="sub" type="submit" id="sub" value="Continue to Setup &raquo;" /></p>';
  1644. }
  1645. echo '</form><br class="clear" /><br class="clear" /><br class="clear" />';
  1646. echo '</div>';
  1647. sleep(1);
  1648. foreach ( array( '.htaccess', '.htaccess-compress', '.htaccess-decompress', '.htpasswd-basic', '.htpasswd-digest', 'basic_auth_test.gif', 'authuserfile_test.gif', 'authdigestfile_test.gif', 'digest_check.gif', 'modsec_check.gif', 'test.gif' ) as $f )
  1649. aa_pp_unlink( $aa_PP['test_dir'] . '/' . $f );
  1650. @rmdir( $aa_PP['test_dir'] );
  1651. }
  1652. /**
  1653. * aa_pp_list_files()
  1654. *
  1655. * @param mixed $dir
  1656. * @return
  1657. */
  1658. function aa_pp_list_files( $dir )
  1659. {
  1660. $files = array();
  1661. if ( is_dir( $dir ) && !is_link( $dir ) )
  1662. {
  1663. $d = dir( $dir );
  1664. while ( false !== ( $r = $d->read() ) )
  1665. {
  1666. if ( strpos( $r, '.htaccess-' ) === false )continue;
  1667. else $files[] = $r;
  1668. }
  1669. $d->close();
  1670. ksort( $files );
  1671. }
  1672. return $files;
  1673. }
  1674. /**
  1675. * aa_pp_mkdir()
  1676. *
  1677. * @param mixed $dirname
  1678. * @return
  1679. */
  1680. function aa_pp_mkdir( $dir )
  1681. {
  1682. @umask( 0 );
  1683. $dirname = ( @is_readable( $dir ) ) ? realpath( rtrim( $dir, '/' ) ) : rtrim( $dir, '/' );
  1684. $dirname = str_replace( '//', '/', $dirname );
  1685. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Creating directory {$dirname}" );
  1686. if ( is_dir( $dirname ) || @wp_mkdir_p( $dirname ) ) return $dirname;
  1687. elseif ( is_writable( $dirname ) && @wp_mkdir_p( $dirname ) ) return $dirname;
  1688. else return( @mkdir( $dirname, 0777 ) ) ? $dirname : new WP_Error( 'mkdir-failed', __( "Failed to create directory {$dirname}" ) );
  1689. }
  1690. /**
  1691. * aa_pp_unlink()
  1692. *
  1693. * @param mixed $f
  1694. * @param mixed $backup
  1695. * @return
  1696. */
  1697. function aa_pp_unlink( $f, $backup = false )
  1698. {
  1699. @umask( 0 );
  1700. $f = ( @is_readable( $f ) ) ? realpath( rtrim( $f, '/' ) ) : rtrim( $f, '/' );
  1701. $f = str_replace( '//', '/', $f );
  1702. if ( !@file_exists( $f ) ) return true;
  1703. if ( $backup ) $backedup = aa_pp_backup( $f, $f . '-' . time() );
  1704. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Deleted {$f}" );
  1705. if ( is_dir( $f ) ) return aa_pp_rmdir( $f );
  1706. else @unlink( $f );
  1707. if ( !@file_exists( $f ) ) return true;
  1708. return( @chmod( $f, 0777 ) && @unlink( $f ) ) ? true : ( @chmod( dirname( $f ), 0777 ) && @unlink( $f ) ) ? true : new WP_Error( 'delete-failed', __( "Failed to delete {$f} in aa_pp_unlink" ) );
  1709. }
  1710. /**
  1711. * aa_pp_backup()
  1712. *
  1713. * @param mixed $f
  1714. * @param mixed $bf
  1715. * @return
  1716. */
  1717. function aa_pp_backup( $f, $bf = 0 )
  1718. {
  1719. if ( !$bf || $f == $bf )$bf = dirname( $f ) . '/' . basename( $f ) . '.AABK-' . time();
  1720. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Backing up {$f} to {$bf}" );
  1721. if ( !@copy( $f, $bf ) ) aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Failed to backup {$f} to {$bf} using copy" );
  1722. elseif ( !@rename( $f, $bf ) ) return new WP_Error( 'rename-failed', __( "Couldnt rename {$f} to {$bf}" ) );
  1723. else return $bf;
  1724. }
  1725. /**
  1726. * aa_pp_bytes()
  1727. *
  1728. * @param mixed $bytes
  1729. * @return
  1730. */
  1731. function aa_pp_bytes( $bytes )
  1732. {
  1733. $s = array( 'B', 'Kb', 'MB', 'GB', 'TB', 'PB' );
  1734. $e = floor( log( $bytes ) / log( 1024 ) );
  1735. return sprintf( '%.2f ' . $s[$e], ( $bytes / pow( 1024, floor( $e ) ) ) ) . "<br /> {$bytes} B";
  1736. }
  1737. /**
  1738. * aa_pp_file_put_c()
  1739. *
  1740. * @param mixed $file
  1741. * @param mixed $content
  1742. * @param mixed $backup
  1743. * @return
  1744. */
  1745. function aa_pp_file_put_c( $file, $content, $backup = false )
  1746. {
  1747. @umask( 0 );
  1748. $f = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1749. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Creating {$f}" );
  1750. if ( !is_dir( dirname( $f ) ) ) aa_pp_mkdir( dirname( $f ) );
  1751. if ( file_exists( $f ) && is_readable( $f ) && $backup ) $backedup = aa_pp_backup( $f );
  1752. if ( aa_pp_checkfunction( "file_put_contents" ) ) return @file_put_contents( $f, $content );
  1753. if ( !$fh = @fopen( $f, 'wb' ) ) return new WP_Error( 'fopen-failed', __( "Couldnt fopen {$f}" ) );
  1754. if ( !@fwrite( $fh, $content, strlen( $content ) ) ) return new WP_Error( 'fwrite-failed', __( "Couldnt fwrite {$f}" ) );
  1755. if ( !@fclose( $fh ) ) return new WP_Error( 'fclose-failed', __( "Couldnt fclose {$f}" ) );
  1756. return true;
  1757. }
  1758. /**
  1759. * aa_pp_readfile()
  1760. *
  1761. * @param mixed $file
  1762. * @return
  1763. */
  1764. function aa_pp_readfile( $file )
  1765. {
  1766. @umask( 0 );
  1767. $f = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1768. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Reading {$f}" );
  1769. if ( !$fh = @fopen( $f, 'rb' ) ) return new WP_Error( 'fopen-failed', __( "Couldnt fopen {$f}" ) );
  1770. if ( !$filecontent = @fread( $fh, @filesize( $f ) ) ) return new WP_Error( 'fread-failed', __( "Couldnt fread {$f}" ) );
  1771. if ( !@fclose( $fh ) ) return new WP_Error( 'fclose-failed', __( "Couldnt fclose {$f}" ) );
  1772. return $filecontent;
  1773. }
  1774. /**
  1775. * aa_pp_sid_info()
  1776. *
  1777. * @param mixed $sid
  1778. * @return
  1779. */
  1780. function aa_pp_sid_info( $sid )
  1781. {
  1782. $sid = ( string )$sid;
  1783. $types = array(
  1784. 1 => 'Protection',
  1785. 2 => 'Password',
  1786. 3 => 'Anti-Spam',
  1787. 4 => 'WordPress Exploit',
  1788. 5 => 'General Exploit',
  1789. 6 => 'General'
  1790. );
  1791. $files = array( 0 => 'root',
  1792. 1 => 'wp-admin',
  1793. 2 => 'other'
  1794. );
  1795. $modules = array( 0 => 'core',
  1796. 1 => 'mod_rewrite',
  1797. 2 => 'mod_alias',
  1798. 3 => 'mod_security',
  1799. 4 => 'mod_setenv' );
  1800. $response = array( 0 => 'none',
  1801. 1 => '503 Service Temporarily Unavailable',
  1802. 2 => '505 HTTP Version Not Supported',
  1803. 3 => '401 Authorization Required',
  1804. 4 => '403 Forbidden',
  1805. 5 => '405 Method Not Allowed'
  1806. );
  1807. return array( 'Type' => $types[$sid{0}], 'File' => $files[$sid{1}], 'Module' => $modules[$sid{2}], 'Response' => $response[$sid{3}] );
  1808. }
  1809. /**
  1810. * aa_pp_errors()
  1811. *
  1812. * @param mixed $message
  1813. * @param string $title
  1814. * @return
  1815. */
  1816. function aa_pp_errors( $message, $title = '' )
  1817. {
  1818. $class = 'id="message" class="updated fade"';
  1819. if ( aa_pp_checkfunction( 'is_wp_error' ) && is_wp_error( $message ) )
  1820. {
  1821. $class = 'class="error"';
  1822. if ( empty( $title ) )
  1823. {
  1824. $error_data = $message->get_error_data();
  1825. if ( is_array( $error_data ) && isset( $error_data['title'] ) ) $title = $error_data['title'];
  1826. }
  1827. $errors = $message->get_error_messages();
  1828. switch ( count( $errors ) )
  1829. {
  1830. case 0 :
  1831. $g = '';
  1832. break;
  1833. case 1 :
  1834. $g = "<p>{$errors[0]}</p>";
  1835. break;
  1836. default :
  1837. $g = '<ul>';
  1838. foreach( $errors as $mess )$g .= "<li>{$mess}</li>\n";
  1839. $g .= '</ul>';
  1840. break;
  1841. }
  1842. } elseif ( is_string( $message ) ) $g = "<p>{$message}</p>";
  1843. if ( !empty( $g ) )echo "<br /><div {$class} style='max-width:95%;'>{$g}</div><br />";
  1844. }
  1845. /**
  1846. * aa_pp_checkfunction()
  1847. *
  1848. * @param mixed $func
  1849. * @return
  1850. */
  1851. function aa_pp_checkfunction( $func )
  1852. {
  1853. return( !function_exists( $func ) || @in_array( $func, @explode( ',', @ini_get( 'disable_functions' ) ) ) ) ? aa_pp_debug( "{$func} disabled or not found" ) : true;
  1854. }
  1855. /**
  1856. * aa_pp_debug()
  1857. *
  1858. * @param string $message
  1859. * @return
  1860. */
  1861. function aa_pp_debug( $message = '' )
  1862. {
  1863. @error_log( ltrim( "PHP AAPP Error: {$message}" ), 0 );
  1864. return false;
  1865. }
  1866. /**
  1867. * aa_pp_notify()
  1868. *
  1869. * @param string $message
  1870. * @return
  1871. */
  1872. function aa_pp_notify( $message = '' )
  1873. {
  1874. if ( (bool)AA_PP_DEBUG === true ) @error_log( ltrim( "PHP AAPP Info: {$message}" ), 0 );
  1875. }
  1876. /**
  1877. * wp_die()
  1878. *
  1879. * @param mixed $message
  1880. * @return
  1881. */
  1882. if ( !function_exists( 'wp_die' ) ) :
  1883. function wp_die ( $message = 'wp_die' )
  1884. {
  1885. die( $message );
  1886. }
  1887. endif;
  1888. ?>