Plugin Directory

Changeset 913083

Timestamp:
05/13/2014 04:19:10 AM (10 years ago)
Author:
sean212
Message:

2.2 work

Location:
lockdown-wp-admin/trunk
Files:
16 added
4 edited

Legend:

Unmodified
Added
Removed
  • lockdown-wp-admin/trunk/README.md

    r770426 r913083  
    11Lockdown WP Admin
    22=============
     3
     4
     5
    36
    47Lockdown WP Admin conceals the administration and login screen from intruders. It can hide WordPress Admin (/wp-admin/) and and login (/wp-login.php) as well as add HTTP authentication to the login system. We can also change the login URL from wp-login.php to whatever you'd like: /login, /log-in-here, etc.
     
    100103* Support for WordPress 3.6
    101104* General Cleaning
     105
     106
     107
     108
     109
  • lockdown-wp-admin/trunk/lockdown-wp-admin.php

    r770426 r913083  
    55Donate link: http://seanfisher.co/donate/
    66Description: Securing the WordPress Administration interface by concealing the administration dashboard and changing the login page URL.
    7 Version: 2.1
     7Version: 2.
    88Author: Sean Fisher
    99Author URI: http://seanfisher.co/
     
    1313// This file name
    1414define('LD_FILE_NAME', __FILE__ );
     15
    1516
    1617/**
     
    2930     * @access private
    3031    **/
    31     public $ld_admin_version = '2.1';
     32    public ';
    3233   
    3334    /**
     
    3637     *
    3738     * @access  public
    38      * @global  string
     39     * @    string
    3940    **/
    4041    public $relm = 'Secure Area';
     
    4849   
    4950    /**
    50      * The base to get the login url
    51      *
    52      * @access  private
    53     **/
    54     protected $login_base = FALSE;
    55    
    56     /**
    5751     * Check if the Auth passed
    58      *
    5952     * See {@link WP_LockAuth::getAuthPassed()}
    6053     *
    61      * @var boolean
     54     * @ boolean
    6255     */
    6356    protected $passed = FALSE;
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
    6471
    6572    /**
     
    7380        if (! class_exists('Disable_WPMS_Plugin_LD'))
    7481            require_once( dirname( __FILE__ ) .'/no-wpmu.php' );
    75        
    76         // Add the action to setup the menu.
    77         add_action('admin_menu', array( $this, 'add_admin_menu'));
    78        
    79         // Setup the plugin.
    80         $this->setup_hide_admin();
    81        
    82         // Hide the login form
    83         $this->redo_login_form();
    84     }
    85    
    86     /**
    87      * Get a username and password from the HTTP auth
    88      *
    89      * @return array|bool
    90     **/
    91     public function get_http_auth_creds()
    92     {
    93         // Since PHP saves the HTTP Password in a bunch of places, we have to be able to test for all of them
    94         $username = $password = NULL;
    95        
    96         // mod_php
    97         if (isset($_SERVER['PHP_AUTH_USER']))
    98         {
    99             $username = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : NULL;
    100             $password = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : NULL;
    101         }
     82           
     83        require_once(LD_PLUGIN_DIR.'/src/Lockdown/Application.php');
     84        require_once(LD_PLUGIN_DIR.'/src/Lockdown/Admin.php');
    10285
    103         // most other servers
    104         elseif ($_SERVER['HTTP_AUTHENTICATION'])
    105         {
    106             if (strpos(strtolower($_SERVER['HTTP_AUTHENTICATION']),'basic') === 0)
    107             {
    108                 list($username,$password) = explode(':',base64_decode(substr($_SERVER['HTTP_AUTHENTICATION'], 6)));
    109             }
    110         }
    111        
    112         // Check them - if they're null a/o empty, they're invalid.
    113         if ( is_null($username) OR is_null($password) OR empty($username) OR empty($password))
    114             return FALSE;
    115         else
    116             return array('username' => $username, 'password' => $password);
    117     }
    118    
    119     /**
    120      * Update the users
    121      *
    122      * @access private
    123     **/
    124     public function update_users()
    125     {
    126         if ( ! isset( $_GET['page'] ) )
    127             return;
    128        
    129         if ( $_GET['page'] !== 'lockdown-private-users' )
    130             return;
    131        
    132         // Nonce
    133         if ( ! isset( $_REQUEST['_wpnonce'] ) )
    134             return;
    135        
    136         $nonce = $_REQUEST['_wpnonce'];
    137         if ( !wp_verify_nonce( $nonce, 'lockdown-wp-admin' ) )
    138             wp_die('Security error, please try again.');
    139        
    140         // Add a user
    141         if ( isset( $_POST['private_username'] ) && isset( $_POST['private_password'] ) )
    142         {
    143             if ( $_POST['private_username'] !== '' && $_POST['private_password'] !== '' )
    144             {
    145                 // Adding a user
    146                 $users = $this->get_private_users();
    147                 $add['user'] = sanitize_user( $_POST['private_username'] );
    148                 $add['pass'] = trim( md5( $_POST['private_password'] ) );
    149                
    150                 // See if it exists
    151                 if ($this->user_exists($users, $add['user'])) :
    152                     define('LD_ERROR', 'username-exists');
    153                     return;
    154                 endif;
    155 
    156                 $users[] = $add;
    157                
    158                 update_option('ld_private_users', $users);
    159                
    160                 define('LD_WP_ADMIN', TRUE);
    161                 return;
    162             }
    163         }
    164        
    165         // Deleting a user.
    166         if ( isset( $_GET['delete'] ) )
    167         {
    168             // Delete the user.
    169             unset( $users );
    170             $users = $this->get_private_users();
    171             $to_delete = (int) $_GET['delete'];
    172            
    173             if ( count( $users ) > 0 )
    174             {
    175                 foreach( $users as $key => $val )
    176                 {
    177                     if ( $key === $to_delete ) :
    178                         if( $this->current_user !== '' && $to_delete === $this->current_user )
    179                         {
    180                             // They can't delete themselves!
    181                             define('LD_ERROR', 'delete-self');
    182                             return;
    183                         }
    184                        
    185                         unset( $users[$key] );
    186                     endif;
    187                 }           
    188             }
    189            
    190             update_option('ld_private_users', $users);
    191            
    192             define('LD_WP_ADMIN', TRUE);
    193             return;
    194         }
    195     }
    196    
    197     /**
    198      * Update the options
    199      *
    200      * @access private
    201     **/
    202     public function update_options()
    203     {
    204         if ( !isset( $_GET['page'] ) )
    205             return;
    206        
    207         if ( $_GET['page'] !== 'lockdown-wp-admin' )
    208             return;
    209        
    210         if ( !isset( $_POST['did_update'] ) )
    211             return;
    212        
    213         // Nonce
    214         $nonce = $_POST['_wpnonce'];
    215         if ( ! wp_verify_nonce($nonce, 'lockdown-wp-admin') )
    216             wp_die('Security error, please try again.');
    217        
    218         // ---------------------------------------------------
    219         // They're updating.
    220         // ---------------------------------------------------
    221         if ( isset( $_POST['http_auth'] ) )
    222             update_option('ld_http_auth', trim( strtolower( $_POST['http_auth'] ) ) );
    223         else
    224             update_option('ld_http_auth', 'none' );
    225        
    226         if ( ! isset( $_POST['hide_wp_admin'] ) )
    227         {
    228             update_option('ld_hide_wp_admin', 'nope');
    229         }
    230         else
    231         {
    232             if ( $_POST['hide_wp_admin'] === 'yep' )
    233                 update_option('ld_hide_wp_admin', 'yep');
    234             else
    235                 update_option('ld_hide_wp_admin', 'nope');
    236         }
    237        
    238         if ( isset( $_POST['login_base'] ) )
    239         {
    240             $base = sanitize_title_with_dashes( $_POST['login_base']);
    241             $base = str_replace('/', '', $base);
    242            
    243             $disallowed = array(
    244                 'user', 'wp-admin', 'wp-content', 'wp-includes', 'wp-feed.php', 'index', 'feed', 'rss', 'robots', 'robots.txt', 'wp-login.php',
    245                 'wp-login', 'wp-config', 'blog', 'sitemap', 'sitemap.xml',
    246             );
    247             if ( in_array( $base, $disallowed ) )
    248             {
    249                 return define('LD_DIS_BASE', TRUE);
    250             }
    251             else
    252             {
    253                
    254                 update_option('ld_login_base', $base);
    255                 $this->login_base = sanitize_title_with_dashes ( $base );
    256             }
    257         }
    258        
    259         // Redirect
    260         define('LD_WP_ADMIN', TRUE);
    261         return;
    262     }
    263    
    264     /**
    265      * Send headers to the browser that are going to ask for a username/pass
    266      * from the browser.
    267      *
    268      * @access private
    269      * @return void
    270     **/
    271     private function inauth_headers()
    272     {
    273         // Disable if there is a text file there.
    274         if ( file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'disable_auth.txt'))
    275             return;
    276        
    277         header('WWW-Authenticate: Basic realm="'.$this->relm.'"');
    278         header('HTTP/1.0 401 Unauthorized');
    279         echo '<h1>Authorization Required.</h1>';
    280         exit;
     86        // Instantiate objects
     87        $this->admin = new Lockdown_Admin($this);
     88        $this->application = new Lockdown_Application($this);
    28189    }
    28290   
     
    28492     * Get the users for the private creds
    28593     *
    286      * @access private
     94     * @
    28795    **/
    28896    public function get_private_users()
    28997    {
    290         $opt = get_option('ld_private_users');
    291         if ( !is_array( $opt ) )
    292             return array();
    293        
    294         return $opt;
    295     }
    296    
    297     /**
    298      * Setup hiding wp-admin
    299     **/
    300     protected function setup_hide_admin()
    301     {
    302         $opt = get_option('ld_hide_wp_admin');
    303 
    304         // Nope, they didn't enable it.
    305         if ( $opt !== 'yep' ) return;
    306        
    307         // We're gonna hide it.
    308         $no_check_files = array('async-upload.php', 'admin-ajax.php', 'wp-app.php');
    309         $no_check_files = apply_filters('no_check_files', $no_check_files);
    310        
    311         $script_filename = empty($_SERVER['SCRIPT_FILENAME'])
    312             ? $_SERVER['PATH_TRANSLATED']
    313             : $_SERVER['SCRIPT_FILENAME'];
    314         $explode = explode('/', $script_filename);
    315         $file = end( $explode );
    316            
    317             // Disable for WP-CLI
    318         if ( defined('WP_CLI') AND WP_CLI )
    319             return $this->passed(true);
    320 
    321             if ( in_array( $file, $no_check_files ) )
    322             return $this->passed(true);
    323        
    324         // We only will hide it if we are in admin (/wp-admin/)
    325         if ( is_admin() )
    326         {
    327             // Non logged in users.
    328             if ( ! is_user_logged_in() )
    329                 $this->throw_404();
    330                        
    331             // Setup HTTP auth.
    332             $this->setup_http_area();
    333         }
    334     }
    335    
    336     /**
    337      * Get the current file name
    338      *
    339      * @return string JUST the file name
    340     **/
    341     public function get_file()
    342     {
    343         // We're gonna hide it.
    344         $no_check_files = array('async-upload.php');
    345         $no_check_files = apply_filters('no_check_files', $no_check_files);
    346        
    347         $script_filename = empty($_SERVER['SCRIPT_FILENAME'])
    348             ? $_SERVER['PATH_TRANSLATED']
    349             : $_SERVER['SCRIPT_FILENAME'];
    350         $explode = explode('/', $script_filename );
    351         return end( $explode );
    352     }
    353    
    354     /**
    355      * Setting up the HTTP Auth
    356      * Here, we only check if it's enabled
    357      *
    358      * @access protected
    359     **/
    360     protected function setup_http_area()
    361     {
    362         // We save what type of auth we're doing here.
    363         $opt = get_option('ld_http_auth');
    364        
    365         // What type of auth are we doing?
    366         switch( $opt )
    367         {
    368             // HTTP auth is going to ask for their WordPress creds.
    369             case 'wp_creds' :
    370                 $creds = $this->get_http_auth_creds();
    371                 if (! $creds )
    372                     $this->inauth_headers(); // Invalid credentials
    373                
    374                 // Are they already logged in as this?
    375                 $current_uid = get_current_user_id();
    376                
    377                 // We fixed this for use with non WP-MS sites
    378                 $requested_user = get_user_by('login', $creds['username']);
    379                
    380                 // Not a valid user.
    381                 if (! $requested_user )
    382                     $this->inauth_headers();
    383                
    384                 // The correct User ID.
    385                 $requested_uid = (int) $requested_user->ID;
    386                
    387                 // Already logged in?
    388                 if ( $current_uid === $requested_uid )
    389                     return $this->passed(true);
    390                
    391                 // Attempt to sign them in if they aren't already
    392                 if (! is_user_logged_in() ) :
    393                     // Try it via wp_signon
    394                     $creds = array();
    395                     $creds['user_login'] = $creds['username'];
    396                     $creds['user_password'] = $creds['password'];
    397                     $creds['remember'] = true;
    398                     $user = wp_signon( $creds, false );
    399                    
    400                     // In error
    401                     if ( is_wp_error($user) )
    402                         $this->inauth_headers();
    403                 endif;
    404                
    405                 // They passed!
    406                 $this->passed(true);
    407             break;
    408            
    409             // Private list of users to check
    410             case 'private' :
    411                 $users = $this->get_private_users();
    412                
    413                 // We want a user to exist.
    414                 // If nobody is found, we won't lock them out!
    415                 if ( ! $users || ! is_array( $users ) )
    416                     return;
    417                
    418                 // Let's NOT lock everybody out
    419                 if ( count( $users ) < 1 )
    420                     return;
    421                
    422                 // Get the HTTP auth creds
    423                 $creds = $this->get_http_auth_creds();
    424                
    425                 // Invalid creds
    426                 if (! $creds )
    427                     $this->inauth_headers();
    428                
    429                 // Did they enter a valid user?
    430                 if ( $this->user_array_check( $users, $creds['username'], $creds['password'] ) )
    431                 {
    432                     $this->passed(true);
    433                     $this->set_current_user( $users, $creds['username'] );
    434                     return;
    435                 }
    436                 else
    437                 {
    438                     return $this->inauth_headers();
    439                 }
    440                
    441             break;
    442            
    443             // Unknown type of auth
    444             default :
    445                 return FALSE;
    446         }
    447        
    448     }
    449     /**
    450      * Check an internal array of users against a passed user and pass
    451      *
    452      * @access protected
    453      * @return bool
    454      *
    455      * @param array $array The array of users
    456      * @param string $user The username to check for
    457      * @param string $pass The password to check for (plain text)
    458     **/
    459     protected function user_array_check( $array, $user, $pass )
    460     {
    461         foreach( $array as $key => $val )
    462         {
    463             if ( $val['user'] === $user && md5( $pass ) === $val['pass'] )
    464                 return TRUE;
    465         }
    466        
    467         return FALSE;
    468     }
    469 
    470     /**
    471      * See if a user exists in the array
    472      *
    473      * @access protected
    474      * @return boolean
    475      * @param array Array of users
    476      * @param string
    477      */
    478     protected function user_exists($array, $user)
    479     {
    480         if (count($array) == 0) return FALSE;
    481 
    482         foreach ($array as $k => $v) :
    483             if ($v['user'] == $user)
    484                 return TRUE;
    485         endforeach;
    486 
    487         return FALSE;
     98        return $this->application->getPrivateUsers();
    48899    }
    489100   
     
    491102     * Set the current user
    492103     *
    493      * @access private
    494      * @param array
    495      * @param integer
     104     * @deprecated Moved to {@see Lockdown_Application::setUser()}
    496105    **/
    497106    protected function set_current_user( $array, $user )
    498107    {
    499         foreach( $array as $key => $val )
    500         {
    501             if ( $val['user'] === $user )
    502                 $this->current_user = $key;
    503         }
    504     }
    505    
    506     /**
    507      * Adds the admin menu
    508      *
    509      * @acces private
    510     **/
    511     public function add_admin_menu()
    512     {
    513         add_menu_page('Lockdown WP', 'Lockdown WP', 'manage_options', 'lockdown-wp-admin', array( $this, 'admin_callback'));
    514         add_submenu_page( 'lockdown-wp-admin', 'Private Users', 'Private Users', 'manage_options', 'lockdown-private-users',  array( $this, 'sub_admin_callback'));
    515     }
    516    
    517     /**
    518      * The callback for the admin area
    519      *
    520      * You need the 'manage_options' capability to get here.
    521     **/
    522     public function admin_callback()
    523     {
    524         // Update the options
    525         $this->update_options();
    526        
    527         // The UI
    528         require_once( dirname( __FILE__ ) . '/admin.php' );
    529     }   
    530    
    531     /**
    532      * The callback for ther private users management.
    533      *
    534      * You need the 'manage_options' capability to get here.
    535     **/
    536     public function sub_admin_callback()
    537     {
    538         // Update the users options
    539         $this->update_users();
    540        
    541         // The UI
    542         $private_users = $this->get_private_users();
    543         require_once( dirname( __FILE__ ) . '/admin-private-users.php' );
    544     }
    545    
    546     /**
    547      * Rename the login URL
    548      *
    549      * @access public
    550     **/
    551     public function redo_login_form()
    552     {
    553         $login_base = get_option('ld_login_base');
    554 
    555         // It's not enabled.
    556         if ( $login_base == NULL || ! $login_base || $login_base == '' )
    557             return;
    558        
    559         $this->login_base = $login_base;
    560         unset( $login_base );
    561        
    562         // Setup the filters for the new login form
    563         add_filter('wp_redirect', array( &$this, 'filter_wp_login'));
    564         add_filter('network_site_url', array( &$this, 'filter_wp_login'));
    565         add_filter('site_url', array( &$this, 'filter_wp_login'));
    566        
    567         // We need to get the URL
    568         // This means we need to take the current URL,
    569         // strip it of an WordPress path (if the blog is located @ /blog/)
    570         // And then remove the query string
    571         // We also need to remove the index.php from the URL if it exists
    572        
    573         // The blog's URL
    574         $blog_url = trailingslashit( get_bloginfo('url') );
    575        
    576         // The Current URL
    577         $schema = is_ssl() ? 'https://' : 'http://';
    578         $current_url = $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    579        
    580         $request_url = str_replace( $blog_url, '', $current_url );
    581         $request_url = str_replace('index.php/', '', $request_url);
    582        
    583         $url_parts = explode( '?', $request_url, 2 );
    584         $base = $url_parts[0];
    585 
    586         // Remove trailing slash
    587         $base = rtrim($base,"/");
    588         $exp = explode( '/', $base, 2 );
    589         $super_base = end( $exp );
    590 
    591         // Are they visiting wp-login.php?
    592         if ( $super_base == 'wp-login.php')
    593             $this->throw_404();
    594        
    595         // Is this the "login" url?
    596         if ( $base !== $this->login_base )
    597             return FALSE;
    598        
    599         // We dont' want a WP plugin caching this page
    600         @define('NO_CACHE', TRUE);
    601         @define('WTC_IN_MINIFY', TRUE);
    602         @define('WP_CACHE', FALSE);
    603        
    604         // Hook onto this
    605         do_action('ld_login_page');
    606        
    607         include ABSPATH . '/wp-login.php';
    608         exit;
    609     }
    610    
    611     /**
    612      * Filters out wp-login to whatever they named it
    613      *
    614      * @access public
    615     **/
    616     public function filter_wp_login( $str )
    617     {
    618         return str_replace('wp-login.php', $this->login_base, $str);
    619     }
    620    
    621     /**
    622      * Launch and display the 404 page depending upon the template
    623      *
    624      * @param   void
    625      * @return  void
    626     **/
    627     public function throw_404()
    628     {
    629         // Change WP Query
    630         global $wp_query;
    631         $wp_query->set_404();
    632         status_header(404);
    633 
    634         // Disable that pesky Admin Bar
    635         add_filter('show_admin_bar', '__return_false', 900); 
    636         remove_action( 'admin_footer', 'wp_admin_bar_render', 10); 
    637         remove_action('wp_head', 'wp_admin_bar_header', 10);
    638         remove_action('wp_head', '_admin_bar_bump_cb', 10);
    639         wp_dequeue_script( 'admin-bar' );
    640         wp_dequeue_style( 'admin-bar' );
    641 
    642         // Template
    643         $four_tpl = apply_filters('LD_404', get_404_template());
    644 
    645         // Handle the admin bar
    646         @define('APP_REQUEST', TRUE);
    647         @define('DOING_AJAX', TRUE);
    648        
    649         if ( empty($four_tpl) OR ! file_exists($four_tpl) )
    650         {
    651             // We're gonna try and get TwentyTen's one
    652             $twenty_ten_tpl = apply_filters('LD_404_FALLBACK', WP_CONTENT_DIR . '/themes/twentythirteen/404.php');
    653            
    654             if (file_exists($twenty_ten_tpl))
    655                 require($twenty_ten_tpl);
    656             else
    657                 wp_die('404 - File not found!', '', array('response' => 404));
    658         }
    659         else
    660         {
    661             // Their theme has a template!
    662             require( $four_tpl );
    663         }
    664        
    665         // Either way, it's gonna stop right here.
    666         exit;
    667     }
    668 
    669     /**
    670      * See if a login base is suggested against
    671      *
    672      * @return boolean
    673      */
    674     public function isSuggestedAgainst()
    675     {
    676         return (in_array($this->login_base, array(
    677             'login',
    678             'admin',
    679             'user-login',
    680         )));
     108        return $this->application->setUser($array, $user);
    681109    }
    682110
    683111    /**
    684112     * Retrieve the Login Base
    685      *
    686113     * @return string
    687114     */
    688115    public function getLoginBase()
    689116    {
    690         return $this->login_base;
     117        return $this->;
    691118    }
    692119
     
    696123     * @return boolean
    697124     */
    698     public function getAuthPassed() { return $this->passed; }
     125    public function getAuthPassed()
     126    {
     127        return (bool) $this->passed;
     128    }
    699129
    700130    /**
     
    702132     * See {@link WP_LockAuth::getAuthPassed()}
    703133     *
    704      * @access protected
     134     * @access p
    705135     * @param boolean
    706136     */
    707     protected function passed($value)
     137    p function passed($value)
    708138    {
    709139        $this->passed = (bool) $value;
     
    729159}
    730160
    731 add_action('init', 'ld_setup_auth');
     161add_action('init', 'ld_setup_auth');
    732162
    733163/* End of file: lockdown-wp-admin.php */
  • lockdown-wp-admin/trunk/no-wpmu.php

    r770426 r913083  
    1 <?php if (! defined('ABSPATH')) exit;
     1<?php
    22/**
    33 * We don't want to allow for this plugin to be used in WP-MS or network wide.
     
    8585
    8686// The object.
    87 $setup_no_wpmu = new Disable_WPMS_Plugin_LD;
     87new Disable_WPMS_Plugin_LD;
    8888
    8989/* End of file: no-wpmu.php */
  • lockdown-wp-admin/trunk/readme.txt

    r770426 r913083  
    44Link: http://seanfisher.co/lockdown-wp-admin/
    55Tags: security, secure, lockdown, vulnerability, website security, wp-admin, login, hide login, rename login, http auth, 404, lockdown, srtfisher, secure
    6 Requires at least: 3.3
    7 Tested up to: 3.6
    8 Stable tag: 2.1
     6Requires at least: 3.
     7Tested up to: 3.
     8Stable tag: 2.
    99
    1010Lockdown WP Admin conceals the administration and login screen from intruders. It can hide WordPress Admin (/wp-admin/) and and login (/wp-login.php) as well as add HTTP authentication to the login system. We can also change the login URL from wp-login.php to whatever you'd like: /login, /log-in-here, etc.
     
    103103* Support for WordPress 3.6
    104104* General Cleaning
     105
     106
     107
     108
     109
Note: See TracChangeset for help on using the changeset viewer.