includes/sessions.php
changeset 326 ab66d6d1f1f4
parent 313 854eecfada20
parent 322 5f1cd51bf1be
child 335 67bd3121a12e
equal deleted inserted replaced
314:474f8be55943 326:ab66d6d1f1f4
     1 <?php
     1 <?php
     2 
     2 
     3 /*
     3 /*
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
     5  * Version 1.0.2 (Coblynau)
     5  * Version 1.0.3 (Dyrad)
     6  * Copyright (C) 2006-2007 Dan Fuhry
     6  * Copyright (C) 2006-2007 Dan Fuhry
     7  * sessions.php - everything related to security and user management
     7  * sessions.php - everything related to security and user management
     8  *
     8  *
     9  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
     9  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
    10  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
    10  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
   661     $username = str_replace('_', ' ', $username);
   661     $username = str_replace('_', ' ', $username);
   662     $db_username_lower = $this->prepare_text(strtolower($username));
   662     $db_username_lower = $this->prepare_text(strtolower($username));
   663     $db_username       = $this->prepare_text($username);
   663     $db_username       = $this->prepare_text($username);
   664     
   664     
   665     // Select the user data from the table, and decrypt that so we can verify the password
   665     // Select the user data from the table, and decrypt that so we can verify the password
   666     $this->sql('SELECT password,old_encryption,user_id,user_level,theme,style,temp_password,temp_password_time FROM '.table_prefix.'users WHERE lcase(username)=\''.$db_username_lower.'\' OR username=\'' . $db_username . '\';');
   666     $this->sql('SELECT password,old_encryption,user_id,user_level,theme,style,temp_password,temp_password_time FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.$db_username_lower.'\' OR username=\'' . $db_username . '\';');
   667     if($db->numrows() < 1)
   667     if($db->numrows() < 1)
   668     {
   668     {
   669       // This wasn't logged in <1.0.2, dunno how it slipped through
   669       // This wasn't logged in <1.0.2, dunno how it slipped through
   670       if($level > USER_LEVEL_MEMBER)
   670       if($level > USER_LEVEL_MEMBER)
   671         $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
   671         $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
   879     
   879     
   880     // Initialize our success switch
   880     // Initialize our success switch
   881     $success = false;
   881     $success = false;
   882     
   882     
   883     // Retrieve the real password from the database
   883     // Retrieve the real password from the database
   884     $this->sql('SELECT password,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix.'users WHERE lcase(username)=\''.$this->prepare_text(strtolower($username)).'\';');
   884     $this->sql('SELECT password,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.$this->prepare_text(strtolower($username)).'\';');
   885     if($db->numrows() < 1)
   885     if($db->numrows() < 1)
   886     {
   886     {
   887       // This wasn't logged in <1.0.2, dunno how it slipped through
   887       // This wasn't logged in <1.0.2, dunno how it slipped through
   888       if($level > USER_LEVEL_MEMBER)
   888       if($level > USER_LEVEL_MEMBER)
   889         $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
   889         $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
  1207                              . '    ON ( u.user_id=x.user_id OR x.user_id IS NULL )' . "\n"
  1207                              . '    ON ( u.user_id=x.user_id OR x.user_id IS NULL )' . "\n"
  1208                              . '  LEFT JOIN '.table_prefix.'privmsgs AS p' . "\n"
  1208                              . '  LEFT JOIN '.table_prefix.'privmsgs AS p' . "\n"
  1209                              . '    ON ( p.message_to=u.username AND p.message_read=0 )' . "\n"
  1209                              . '    ON ( p.message_to=u.username AND p.message_read=0 )' . "\n"
  1210                              . '  WHERE k.session_key=\''.$keyhash.'\'' . "\n"
  1210                              . '  WHERE k.session_key=\''.$keyhash.'\'' . "\n"
  1211                              . '    AND k.salt=\''.$salt.'\'' . "\n"
  1211                              . '    AND k.salt=\''.$salt.'\'' . "\n"
  1212                              . '  GROUP BY u.user_id;');
  1212                              . '  GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;');
       
  1213     
  1213     if ( !$query )
  1214     if ( !$query )
  1214     {
  1215     {
  1215       $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms FROM '.table_prefix.'session_keys AS k
  1216       $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms FROM '.table_prefix.'session_keys AS k
  1216                              LEFT JOIN '.table_prefix.'users AS u
  1217                              LEFT JOIN '.table_prefix.'users AS u
  1217                                ON ( u.user_id=k.user_id )
  1218                                ON ( u.user_id=k.user_id )
  1218                              LEFT JOIN '.table_prefix.'privmsgs AS p
  1219                              LEFT JOIN '.table_prefix.'privmsgs AS p
  1219                                ON ( p.message_to=u.username AND p.message_read=0 )
  1220                                ON ( p.message_to=u.username AND p.message_read=0 )
  1220                              WHERE k.session_key=\''.$keyhash.'\'
  1221                              WHERE k.session_key=\''.$keyhash.'\'
  1221                                AND k.salt=\''.$salt.'\'
  1222                                AND k.salt=\''.$salt.'\'
  1222                              GROUP BY u.user_id;');
  1223                              GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level;');
  1223     }
  1224     }
  1224     if($db->numrows() < 1)
  1225     if($db->numrows() < 1)
  1225     {
  1226     {
  1226       // echo '(debug) $session->validate_session: Key was not found in database<br />';
  1227       // echo '(debug) $session->validate_session: Key was not found in database<br />';
  1227       return false;
  1228       return false;
  1570     $col_reason = ( $this->compat ) ? '"No reason entered (session manager is in compatibility mode)" AS reason' : 'reason';
  1571     $col_reason = ( $this->compat ) ? '"No reason entered (session manager is in compatibility mode)" AS reason' : 'reason';
  1571     $banned = false;
  1572     $banned = false;
  1572     if ( $this->user_logged_in )
  1573     if ( $this->user_logged_in )
  1573     {
  1574     {
  1574       // check by IP, email, and username
  1575       // check by IP, email, and username
  1575       $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n"
  1576       if ( ENANO_DBLAYER == 'MYSQL' )
  1576             . "    ( ban_type = " . BAN_IP    . " AND is_regex = 0 ) OR \n"
  1577       {
  1577             . "    ( ban_type = " . BAN_IP    . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) OR \n"
  1578         $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n"
  1578             . "    ( ban_type = " . BAN_USER  . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n"
  1579               . "    ( ban_type = " . BAN_IP    . " AND is_regex = 0 ) OR \n"
  1579             . "    ( ban_type = " . BAN_USER  . " AND is_regex = 1 AND '{$this->username}' REGEXP ban_value ) OR \n"
  1580               . "    ( ban_type = " . BAN_IP    . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) OR \n"
  1580             . "    ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n"
  1581               . "    ( ban_type = " . BAN_USER  . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n"
  1581             . "    ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' REGEXP ban_value ) \n"
  1582               . "    ( ban_type = " . BAN_USER  . " AND is_regex = 1 AND '{$this->username}' REGEXP ban_value ) OR \n"
  1582             . "  ORDER BY ban_type ASC;";
  1583               . "    ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n"
       
  1584               . "    ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' REGEXP ban_value ) \n"
       
  1585               . "  ORDER BY ban_type ASC;";
       
  1586       }
       
  1587       else if ( ENANO_DBLAYER == 'PGSQL' )
       
  1588       {
       
  1589         $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n"
       
  1590               . "    ( ban_type = " . BAN_IP    . " AND is_regex = 0 ) OR \n"
       
  1591               . "    ( ban_type = " . BAN_IP    . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' ~ ban_value ) OR \n"
       
  1592               . "    ( ban_type = " . BAN_USER  . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n"
       
  1593               . "    ( ban_type = " . BAN_USER  . " AND is_regex = 1 AND '{$this->username}' ~ ban_value ) OR \n"
       
  1594               . "    ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n"
       
  1595               . "    ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' ~ ban_value ) \n"
       
  1596               . "  ORDER BY ban_type ASC;";
       
  1597       }
  1583       $q = $this->sql($sql);
  1598       $q = $this->sql($sql);
  1584       if ( $db->numrows() > 0 )
  1599       if ( $db->numrows() > 0 )
  1585       {
  1600       {
  1586         while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
  1601         while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
  1587         {
  1602         {
  1608       $db->free_result();
  1623       $db->free_result();
  1609     }
  1624     }
  1610     else
  1625     else
  1611     {
  1626     {
  1612       // check by IP only
  1627       // check by IP only
  1613       $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE
  1628       if ( ENANO_DBLAYER == 'MYSQL' )
  1614                 ( ban_type = " . BAN_IP    . " AND is_regex = 0 ) OR
  1629       {
  1615                 ( ban_type = " . BAN_IP    . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value )
  1630         $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE
  1616               ORDER BY ban_type ASC;";
  1631                   ( ban_type = " . BAN_IP    . " AND is_regex = 0 ) OR
       
  1632                   ( ban_type = " . BAN_IP    . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value )
       
  1633                 ORDER BY ban_type ASC;";
       
  1634       }
       
  1635       else if ( ENANO_DBLAYER == 'PGSQL' )
       
  1636       {
       
  1637         $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE
       
  1638                   ( ban_type = " . BAN_IP    . " AND is_regex = 0 ) OR
       
  1639                   ( ban_type = " . BAN_IP    . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' ~ ban_value )
       
  1640                 ORDER BY ban_type ASC;";
       
  1641       }
  1617       $q = $this->sql($sql);
  1642       $q = $this->sql($sql);
  1618       if ( $db->numrows() > 0 )
  1643       if ( $db->numrows() > 0 )
  1619       {
  1644       {
  1620         while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
  1645         while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
  1621         {
  1646         {
  1671     $username = $this->prepare_text($username);
  1696     $username = $this->prepare_text($username);
  1672     $email = $this->prepare_text($email);
  1697     $email = $this->prepare_text($email);
  1673     $real_name = $this->prepare_text($real_name);
  1698     $real_name = $this->prepare_text($real_name);
  1674     
  1699     
  1675     $nameclause = ( $real_name != '' ) ? ' OR real_name=\''.$real_name.'\'' : '';
  1700     $nameclause = ( $real_name != '' ) ? ' OR real_name=\''.$real_name.'\'' : '';
  1676     $q = $this->sql('SELECT * FROM '.table_prefix.'users WHERE lcase(username)=\''.strtolower($username).'\' OR email=\''.$email.'\''.$nameclause.';');
  1701     $q = $this->sql('SELECT * FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.strtolower($username).'\' OR email=\''.$email.'\''.$nameclause.';');
  1677     if($db->numrows() > 0)
  1702     if($db->numrows() > 0)
  1678     {
  1703     {
  1679       $r = 'The ';
  1704       $r = 'The ';
  1680       $i=0;
  1705       $i=0;
  1681       $row = $db->fetchrow();
  1706       $row = $db->fetchrow();
  1956     {
  1981     {
  1957       $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE user_id='.$user.';'); // This is SAFE! This is only called if $user is an integer
  1982       $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE user_id='.$user.';'); // This is SAFE! This is only called if $user is an integer
  1958     }
  1983     }
  1959     elseif(is_string($user))
  1984     elseif(is_string($user))
  1960     {
  1985     {
  1961       $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE lcase(username)=lcase(\''.$db->escape($user).'\');');
  1986       $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=' . ENANO_SQLFUNC_LOWERCASE . '(\''.$db->escape($user).'\');');
  1962     }
  1987     }
  1963     else
  1988     else
  1964     {
  1989     {
  1965       return false;
  1990       return false;
  1966     }
  1991     }
  2457         unset($this->perms[$i]);
  2482         unset($this->perms[$i]);
  2458       }
  2483       }
  2459     }
  2484     }
  2460     
  2485     
  2461     // PAGE group info
  2486     // PAGE group info
  2462     $pg_list = $paths->get_page_groups($paths->cpage['urlname_nons'], $paths->namespace);
  2487     $pg_list = $paths->get_page_groups($paths->page_id, $paths->namespace);
  2463     $pg_info = '';
  2488     $pg_info = '';
  2464     foreach ( $pg_list as $g_id )
  2489     foreach ( $pg_list as $g_id )
  2465     {
  2490     {
  2466       $pg_info .= ' ( page_id=\'' . $g_id . '\' AND namespace=\'__PageGroup\' ) OR';
  2491       $pg_info .= ' ( page_id=\'' . $g_id . '\' AND namespace=\'__PageGroup\' ) OR';
  2467     }
  2492     }
  2477         $q[] = '( target_type='.ACL_TYPE_GROUP.' AND target_id='.intval($g_id).' )';
  2502         $q[] = '( target_type='.ACL_TYPE_GROUP.' AND target_id='.intval($g_id).' )';
  2478       }
  2503       }
  2479     }
  2504     }
  2480     // The reason we're using an ORDER BY statement here is because ACL_TYPE_GROUP is less than ACL_TYPE_USER, causing the user's individual
  2505     // The reason we're using an ORDER BY statement here is because ACL_TYPE_GROUP is less than ACL_TYPE_USER, causing the user's individual
  2481     // permissions to override group permissions.
  2506     // permissions to override group permissions.
  2482     $bs .= implode(" OR\n    ", $q) . " )\n  AND (" . $pg_info . ' ( page_id=\''.$db->escape($paths->cpage['urlname_nons']).'\' AND namespace=\''.$db->escape($paths->namespace).'\' ) )     
  2507     $bs .= implode(" OR\n    ", $q) . " )\n  AND (" . $pg_info . ' ( page_id=\''.$db->escape($paths->page_id).'\' AND namespace=\''.$db->escape($paths->namespace).'\' ) )     
  2483       ORDER BY target_type ASC, page_id ASC, namespace ASC;';
  2508       ORDER BY target_type ASC, page_id ASC, namespace ASC;';
  2484     $q = $this->sql($bs);
  2509     $q = $this->sql($bs);
  2485     if ( $row = $db->fetchrow() )
  2510     if ( $row = $db->fetchrow() )
  2486     {
  2511     {
  2487       do {
  2512       do {
  2684   
  2709   
  2685   function make_captcha($len = 7)
  2710   function make_captcha($len = 7)
  2686   {
  2711   {
  2687     $code = $this->generate_captcha_code($len);
  2712     $code = $this->generate_captcha_code($len);
  2688     $hash = md5(microtime() . mt_rand());
  2713     $hash = md5(microtime() . mt_rand());
  2689     $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key,salt,auth_level,source_ip,user_id) VALUES(\''.$hash.'\', \''.$s.'\', -1, \''.ip2hex($_SERVER['REMOTE_ADDR']).'\', -2);');
  2714     $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key,salt,auth_level,source_ip,user_id) VALUES(\''.$hash.'\', \'\', -1, \''.ip2hex($_SERVER['REMOTE_ADDR']).'\', -2);');
  2690     return $hash;
  2715     return $hash;
  2691   }
  2716   }
  2692   
  2717   
  2693   /**
  2718   /**
  2694    * Generates the actual confirmation code text.
  2719    * Generates the actual confirmation code text.
  2919     {
  2944     {
  2920       $pg_info .= ' ( page_id=\'' . $g_id . '\' AND namespace=\'__PageGroup\' ) OR';
  2945       $pg_info .= ' ( page_id=\'' . $g_id . '\' AND namespace=\'__PageGroup\' ) OR';
  2921     }
  2946     }
  2922     
  2947     
  2923     // Build a query to grab ACL info
  2948     // Build a query to grab ACL info
  2924     $bs = 'SELECT rules FROM '.table_prefix.'acl WHERE ' . "\n"
  2949     $bs = 'SELECT rules,target_type,target_id FROM '.table_prefix.'acl WHERE ' . "\n"
  2925           . '  ( ';
  2950           . '  ( ';
  2926     $q = Array();
  2951     $q = Array();
  2927     $q[] = '( target_type='.ACL_TYPE_USER.' AND target_id='.$session->user_id.' )';
  2952     $q[] = '( target_type='.ACL_TYPE_USER.' AND target_id='.$session->user_id.' )';
  2928     if(count($session->groups) > 0)
  2953     if(count($session->groups) > 0)
  2929     {
  2954     {