2016-10-06 15:57:01 +00:00
< ? php
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
/**
* Project :
* Contenido Content Management System
*
* Description :
* Contenido daabase , session and authentication classes
*
* Requirements :
* @ con_php_req 5
*
* @ package Contenido core
* @ version 1.7
* @ author Boris Erdmann , Kristian Koehntopp
* @ copyright four for business AG < www . 4 fb . de >
* @ license http :// www . contenido . org / license / LIZENZ . txt
* @ link http :// www . 4 fb . de
* @ link http :// www . contenido . org
*
*
* { @ internal
* created 2000 - 01 - 01
* modified 2008 - 07 - 04 , bilal arslan , added security fix
* modified 2010 - 02 - 02 , Ingo van Peeren , added local method connect () in order
* to allow only one database connection , see [ CON - 300 ]
* modified 2010 - 02 - 17 , Ingo van Peeren , only one connection for mysqli too
* modified 2011 - 03 - 03 , Murat Purc , some redesign / improvements ( partial adaption to PHP 5 )
* modified 2011 - 03 - 18 , Murat Purc , Fixed occuring " Duplicated entry " errors by using CT_Sql , see [ CON - 370 ]
* modified 2011 - 03 - 21 , Murat Purc , added Contenido_CT_Session to uses PHP ' s session implementation
*
2019-07-03 11:58:28 +00:00
* $Id $ :
2016-10-06 15:57:01 +00:00
* }}
*
*/
if ( ! defined ( 'CON_FRAMEWORK' )) {
die ( 'Illegal call' );
}
/**
* DB - class for all DB handling
*/
2017-03-09 17:20:28 +00:00
class DB_ConLite extends DB_Sql {
2016-10-06 15:57:01 +00:00
/**
* Constructor of database class .
*
* @ param array $options Optional assoziative options . The value depends
* on used DBMS , but is generally as follows :
* - $options [ 'connection' ][ 'host' ] ( string ) Hostname or ip
* - $options [ 'connection' ][ 'database' ] ( string ) Database name
* - $options [ 'connection' ][ 'user' ] ( string ) User name
* - $options [ 'connection' ][ 'password' ] ( string ) User password
* - $options [ 'nolock' ] ( bool ) Optional , not lock table
* - $options [ 'sequenceTable' ] ( string ) Optional , sequesnce table
* - $options [ 'haltBehavior' ] ( string ) Optional , halt behavior on occured errors
* - $options [ 'haltMsgPrefix' ] ( string ) Optional , Text to prepend to the halt message
* - $options [ 'enableProfiling' ] ( bool ) Optional , flag to enable profiling
* @ return void
*/
2017-03-09 17:20:28 +00:00
public function __construct ( array $options = array ()) {
2016-10-06 15:57:01 +00:00
global $cachemeta ;
parent :: __construct ( $options );
if ( ! is_array ( $cachemeta )) {
$cachemeta = array ();
}
// TODO check this out
// HerrB: Checked and disabled. Kills umlauts, if tables are latin1_general.
// try to use the new connection and get the needed encryption
//$this->query("SET NAMES 'utf8'");
2019-08-19 12:02:54 +00:00
// modify mysql strict mode
$this -> query ( 'SET SESSION sql_mode = "NO_ENGINE_SUBSTITUTION"' );
2016-10-06 15:57:01 +00:00
}
/**
* Fetches the next recordset from result set
*
* @ param bool
*/
2017-03-09 17:20:28 +00:00
public function next_record () {
2016-10-06 15:57:01 +00:00
global $cCurrentModule ;
// FIXME For what reason is NoRecord used???
$this -> NoRecord = false ;
if ( ! $this -> Query_ID ) {
$this -> NoRecord = true ;
if ( $cCurrentModule > 0 ) {
$this -> halt ( " next_record called with no query pending in Module ID $cCurrentModule . " );
} else {
$this -> halt ( " next_record called with no query pending. " );
}
return false ;
}
return parent :: next_record ();
}
/**
* Returns the metada of passed table
*
* @ param string $sTable The tablename of empty string to retrieve metadata of all tables !
* @ return array | bool Assoziative metadata array ( result depends on used db driver )
* or false in case of an error
* @ deprecated Use db drivers toArray () method instead
*/
2017-03-09 17:20:28 +00:00
public function copyResultToArray ( $sTable = '' ) {
2016-10-06 15:57:01 +00:00
$aValues = array ();
2017-03-09 17:20:28 +00:00
$aMetadata = $this -> metadata ( $sTable );
2016-10-06 15:57:01 +00:00
if ( ! is_array ( $aMetadata ) || count ( $aMetadata ) == 0 ) {
return false ;
}
foreach ( $aMetadata as $entry ) {
$aValues [ $entry [ 'name' ]] = $this -> f ( $entry [ 'name' ]);
}
return $aValues ;
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
/**
* Wrapper class for old contenido class
*
* @ deprecated since version 2.0 . 0 , use DB_ConLite instead
*/
class DB_Contenido extends DB_ConLite {
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
/**
*
* @ deprecated since version 2.0 . 0
* @ param array $options
*/
public function __construct ( array $options = array ()) {
parent :: __construct ( $options );
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_CT_Sql extends CT_Sql {
2016-10-06 15:57:01 +00:00
/**
* Database class name
* @ var string
*/
public $database_class = 'DB_Contenido' ;
/**
* And find our session data in this table .
* @ var string
*/
public $database_table = '' ;
2017-03-09 17:20:28 +00:00
public function __construct () {
2016-10-06 15:57:01 +00:00
global $cfg ;
$this -> database_table = $cfg [ 'tab' ][ 'phplib_active_sessions' ];
}
/**
* Stores the session data in database table .
*
* Overwrites parents and uses MySQLs REPLACE statement , to prevent race
* conditions while executing INSERT statements by multiple frames in backend .
*
* - Existing entry will be overwritten
* - Non existing entry will be added
*
* @ param string $id The session id ( hash )
* @ param string $name Name of the session
* @ param string $str The value to store
* @ return bool
*/
2017-03-09 17:20:28 +00:00
public function ac_store ( $id , $name , $str ) {
2016-10-06 15:57:01 +00:00
switch ( $this -> encoding_mode ) {
case 'slashes' :
$str = addslashes ( $name . ':' . $str );
2017-03-09 17:20:28 +00:00
break ;
2016-10-06 15:57:01 +00:00
case 'base64' :
default :
$str = base64_encode ( $name . ':' . $str );
}
$name = addslashes ( $name );
2017-03-09 17:20:28 +00:00
$now = date ( 'YmdHis' , time ());
2016-10-06 15:57:01 +00:00
$iquery = sprintf (
2017-03-09 17:20:28 +00:00
" REPLACE INTO %s (sid, name, val, changed) VALUES ('%s', '%s', '%s', '%s') " , $this -> database_table , $id , $name , $str , $now
2016-10-06 15:57:01 +00:00
);
return ( $this -> db -> query ( $iquery )) ? true : false ;
}
2017-03-09 17:20:28 +00:00
}
2016-10-06 15:57:01 +00:00
/**
* Implements the interface class for storing session data to disk using file
* session container of phplib .
*/
2017-03-09 17:20:28 +00:00
class Contenido_CT_File extends CT_File {
2016-10-06 15:57:01 +00:00
/**
* The maximum length for one line in session file .
* @ var int
*/
public $iLineLength = 999999 ;
/**
* Overrides standard constructor for setting up file path to the one which is
* configured in php . ini
*
* @ return Contenido_CT_File
*
* @ author Holger Librenz < holger . librenz @ 4 fb . de >
*/
2017-03-09 17:20:28 +00:00
public function __construct () {
2016-10-06 15:57:01 +00:00
global $cfg ;
if ( isset ( $cfg [ 'session_line_length' ]) && ! empty ( $cfg [ 'session_line_length' ])) {
$this -> iLineLength = ( int ) $cfg [ 'session_line_length' ];
}
// get php.ini value for session path
$this -> file_path = session_save_path () . '/' ;
}
/**
* Overrides get method , because standard byte count is not really senseful for
* contenido !
*
* @ param string $sId
* @ param string $sName
* @ return mixed
*/
2017-03-09 17:20:28 +00:00
public function ac_get_value ( $sId , $sName ) {
2016-10-06 15:57:01 +00:00
if ( file_exists ( $this -> file_path . " $sId $sName " )) {
$f = fopen ( $this -> file_path . " $sId $sName " , 'r' );
2017-03-09 17:20:28 +00:00
if ( $f < 0 ) {
2016-10-06 15:57:01 +00:00
return '' ;
}
$s = fgets ( $f , $this -> iLineLength );
fclose ( $f );
return urldecode ( $s );
} else {
return '' ;
}
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_CT_Shm extends CT_Shm {
public function __construct () {
2016-10-06 15:57:01 +00:00
$this -> ac_start ();
}
2017-03-09 17:20:28 +00:00
}
2016-10-06 15:57:01 +00:00
/**
* Contenido session container , uses PHP ' s session implementation .
*
* NOTE : Is experimental , so don ' t use this in a production environment .
*
* To use this , set session container in contenido / includes / config . misc . php to
* $cfg [ " session_container " ] = 'session' ;
*
* @ todo Make session container configurable
*
* @ author Murat Purc < murat @ purc . de >
*/
2017-03-09 17:20:28 +00:00
class Contenido_CT_Session extends CT_Session {
public function __construct () {
2016-10-06 15:57:01 +00:00
$this -> ac_start ( array (
2017-03-09 17:20:28 +00:00
'namespace' => 'contenido_ct_session_ns' ,
'session.hash_function' => '1' , // use sha-1 function
'session.hash_bits_per_character' => '5' , // and set 5 character to achieve 32 chars
2016-10-06 15:57:01 +00:00
# 'session.save_path' => 'your path',
# 'session.name' => 'your session name',
# 'session.gc_maxlifetime' => 'your lifetime in seconds',
));
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_Session extends Session {
public $classname = 'Contenido_Session' ;
public $cookiename = 'contenido' ; ## defaults to classname
public $magic = '934ComeOnEileen' ; ## ID seed
public $mode = 'get' ; ## We propagate session IDs with cookies
public $fallback_mode = 'cookie' ;
public $lifetime = 0 ; ## 0 = do session cookies, else minutes
public $that_class = 'Contenido_CT_Sql' ; ## name of data storage container
public $gc_probability = 5 ;
public function __construct () {
2016-10-06 15:57:01 +00:00
global $cfg ;
$sFallback = 'sql' ;
$sClassPrefix = 'Contenido_CT_' ;
$sStorageContainer = strtolower ( $cfg [ 'session_container' ]);
2017-03-09 17:20:28 +00:00
if ( class_exists ( $sClassPrefix . ucfirst ( $sStorageContainer ))) {
2016-10-06 15:57:01 +00:00
$sClass = $sClassPrefix . ucfirst ( $sStorageContainer );
} else {
$sClass = $sClassPrefix . ucfirst ( $sFallback );
}
$this -> that_class = $sClass ;
}
2017-03-09 17:20:28 +00:00
public function delete () {
2016-10-06 15:57:01 +00:00
$oCol = new InUseCollection ();
$oCol -> removeSessionMarks ( $this -> id );
parent :: delete ();
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_Frontend_Session extends Session {
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
public $classname = 'Contenido_Frontend_Session' ;
public $cookiename = 'sid' ; ## defaults to classname
public $magic = 'Phillipip' ; ## ID seed
public $mode = 'cookie' ; ## We propagate session IDs with cookies
public $fallback_mode = 'cookie' ;
public $lifetime = 0 ; ## 0 = do session cookies, else minutes
public $that_class = 'Contenido_CT_Sql' ; ## name of data storage container
2016-10-06 15:57:01 +00:00
public $gc_probability = 5 ;
2017-03-09 17:20:28 +00:00
public function __construct () {
2016-10-06 15:57:01 +00:00
global $load_lang , $load_client , $cfg ;
$this -> cookiename = 'sid_' . $load_client . '_' . $load_lang ;
2017-03-09 17:20:28 +00:00
$this -> setExpires ( time () + 3600 );
2016-10-06 15:57:01 +00:00
// added 2007-10-11, H. Librenz
// bugfix (found by dodger77): we need alternative session containers
// also in frontend
$sFallback = 'sql' ;
$sClassPrefix = 'Contenido_CT_' ;
$sStorageContainer = strtolower ( $cfg [ 'session_container' ]);
if ( class_exists ( $sClassPrefix . ucfirst ( $sStorageContainer ))) {
$sClass = $sClassPrefix . ucfirst ( $sStorageContainer );
} else {
$sClass = $sClassPrefix . ucfirst ( $sFallback );
}
$this -> that_class = $sClass ;
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_Auth extends Auth {
public $classname = 'Contenido_Auth' ;
public $lifetime = 15 ;
2016-10-06 15:57:01 +00:00
public $database_class = 'DB_Contenido' ;
public $database_table = 'con_phplib_auth_user' ;
2017-03-09 17:20:28 +00:00
public function auth_loginform () {
2016-10-06 15:57:01 +00:00
global $sess , $_PHPLIB ;
include ( $_PHPLIB [ 'libdir' ] . 'loginform.ihtml' );
}
2017-03-09 17:20:28 +00:00
public function auth_validatelogin () {
2016-10-06 15:57:01 +00:00
global $username , $password ;
if ( $password == '' ) {
return false ;
}
if ( isset ( $username )) {
$this -> auth [ 'uname' ] = $username ; ## This provides access for 'loginform.ihtml'
2017-03-09 17:20:28 +00:00
} elseif ( $this -> nobody ) { ## provides for 'default login cancel'
2016-10-06 15:57:01 +00:00
$uid = $this -> auth [ 'uname' ] = $this -> auth [ 'uid' ] = 'nobody' ;
return $uid ;
}
$uid = false ;
$this -> db -> query (
2017-03-09 17:20:28 +00:00
sprintf ( " SELECT user_id, perms FROM %s WHERE username = '%s' AND password = '%s' " , $this -> database_table , addslashes ( $username ), addslashes ( $password ))
2016-10-06 15:57:01 +00:00
);
while ( $this -> db -> next_record ()) {
$uid = $this -> db -> f ( 'user_id' );
$this -> auth [ 'perm' ] = $this -> db -> f ( 'perms' );
}
return $uid ;
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_Default_Auth extends Contenido_Auth {
2016-10-06 15:57:01 +00:00
public $classname = 'Contenido_Default_Auth' ;
2017-03-09 17:20:28 +00:00
public $lifetime = 1 ;
public $nobody = true ;
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
public function auth_loginform () {
2016-10-06 15:57:01 +00:00
global $sess , $_PHPLIB ;
include ( $_PHPLIB [ 'libdir' ] . 'defloginform.ihtml' );
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_Challenge_Auth extends Auth {
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
public $classname = 'Contenido_Challenge_Auth' ;
public $lifetime = 1 ;
public $magic = 'Simsalabim' ; ## Challenge seed
2016-10-06 15:57:01 +00:00
public $database_class = 'DB_Contenido' ;
public $database_table = 'con_phplib_auth_user' ;
2017-03-09 17:20:28 +00:00
public function auth_loginform () {
2016-10-06 15:57:01 +00:00
global $sess , $challenge , $_PHPLIB ;
$challenge = md5 ( uniqid ( $this -> magic ));
$sess -> register ( 'challenge' );
include ( $_PHPLIB [ 'libdir' ] . 'crloginform.ihtml' );
}
2017-03-09 17:20:28 +00:00
public function auth_validatelogin () {
2016-10-06 15:57:01 +00:00
global $username , $password , $challenge , $response , $timestamp ;
if ( $password == '' ) {
return false ;
}
if ( isset ( $username )) {
// This provides access for 'loginform.ihtml'
$this -> auth [ 'uname' ] = $username ;
}
// Sanity check: If the user presses 'reload', don't allow a login with the data
// again. Instead, prompt again.
if ( $timestamp < ( time () - 60 * 15 )) {
return false ;
}
$this -> db -> query (
2017-03-09 17:20:28 +00:00
sprintf ( " SELECT user_id, perms, password FROM %s WHERE username = '%s' " , $this -> database_table , addslashes ( $username ))
2016-10-06 15:57:01 +00:00
);
while ( $this -> db -> next_record ()) {
2017-03-09 17:20:28 +00:00
$uid = $this -> db -> f ( 'user_id' );
$perm = $this -> db -> f ( 'perms' );
$pass = $this -> db -> f ( 'password' );
2016-10-06 15:57:01 +00:00
}
$exspected_response = md5 ( " $username : $pass : $challenge " );
// True when JS is disabled
if ( $response == '' ) {
if ( $password != $pass ) {
return false ;
} else {
$this -> auth [ 'perm' ] = $perm ;
return $uid ;
}
}
// Response is set, JS is enabled
if ( $exspected_response != $response ) {
return false ;
} else {
$this -> auth [ 'perm' ] = $perm ;
return $uid ;
}
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
##
## Contenido_Challenge_Crypt_Auth: Keep passwords in md5 hashes rather
## than cleartext in database
## Author: Jim Zajkowski <jim@jimz.com>
2017-03-09 17:20:28 +00:00
class Contenido_Challenge_Crypt_Auth extends Auth {
public $classname = 'Contenido_Challenge_Crypt_Auth' ;
public $lifetime = 15 ;
public $magic = 'Frrobo123xxica' ; ## Challenge seed
2016-10-06 15:57:01 +00:00
public $database_class = 'DB_Contenido' ;
public $database_table = '' ;
2017-03-09 17:20:28 +00:00
public $group_table = '' ;
public $member_table = '' ;
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
public function __construct () {
2016-10-06 15:57:01 +00:00
global $cfg ;
$this -> database_table = $cfg [ 'tab' ][ 'phplib_auth_user_md5' ];
$this -> group_table = $cfg [ 'tab' ][ 'groups' ];
$this -> member_table = $cfg [ 'tab' ][ 'groupmembers' ];
$this -> lifetime = $cfg [ 'backend' ][ 'timeout' ];
if ( $this -> lifetime == 0 ) {
$this -> lifetime = 15 ;
}
}
2017-03-09 17:20:28 +00:00
public function auth_loginform () {
2016-10-06 15:57:01 +00:00
global $sess , $challenge , $_PHPLIB , $cfg ;
$challenge = md5 ( uniqid ( $this -> magic ));
$sess -> register ( 'challenge' );
include ( $cfg [ 'path' ][ 'contenido' ] . 'main.loginform.php' );
}
2017-03-09 17:20:28 +00:00
public function auth_loglogin ( $uid ) {
2016-10-06 15:57:01 +00:00
global $cfg , $client , $lang , $auth , $sess , $saveLoginTime ;
2017-03-09 17:20:28 +00:00
$perm = new Contenido_Perm ();
2016-10-06 15:57:01 +00:00
$timestamp = date ( 'Y-m-d H:i:s' );
2017-03-09 17:20:28 +00:00
$idcatart = '0' ;
2016-10-06 15:57:01 +00:00
/* Find the first accessible client and language for the user */
// All the needed information should be available in clients_lang - but the previous code was designed with a
// reference to the clients table. Maybe fail-safe technology, who knows...
$sql = 'SELECT tblClientsLang.idclient, tblClientsLang.idlang FROM ' .
2017-03-09 17:20:28 +00:00
$cfg [ 'tab' ][ 'clients' ] . ' AS tblClients, ' . $cfg [ 'tab' ][ 'clients_lang' ] . ' AS tblClientsLang ' .
'WHERE tblClients.idclient = tblClientsLang.idclient ORDER BY idclient ASC, idlang ASC' ;
2016-10-06 15:57:01 +00:00
$this -> db -> query ( $sql );
$bFound = false ;
while ( $this -> db -> next_record () && ! $bFound ) {
$iTmpClient = $this -> db -> f ( 'idclient' );
2017-03-09 17:20:28 +00:00
$iTmpLang = $this -> db -> f ( 'idlang' );
2016-10-06 15:57:01 +00:00
if ( $perm -> have_perm_client_lang ( $iTmpClient , $iTmpLang )) {
$client = $iTmpClient ;
2017-03-09 17:20:28 +00:00
$lang = $iTmpLang ;
2016-10-06 15:57:01 +00:00
$bFound = true ;
}
}
if ( isset ( $idcat ) && isset ( $idart )) {
// SECURITY FIX
$sql = " SELECT idcatart
FROM
2017-03-09 17:20:28 +00:00
" . $cfg['tab'] ['cat_art'] . "
2016-10-06 15:57:01 +00:00
WHERE
2017-03-09 17:20:28 +00:00
idcat = '" . Contenido_Security::toInteger($idcat) . "' AND
idart = '" . Contenido_Security::toInteger($idart) . "' " ;
2016-10-06 15:57:01 +00:00
$this -> db -> query ( $sql );
$this -> db -> next_record ();
$idcatart = $this -> db -> f ( 'idcatart' );
}
if ( ! is_numeric ( $client ) || ! is_numeric ( $lang )) {
return ;
}
2017-03-09 17:20:28 +00:00
$idaction = $perm -> getIDForAction ( 'login' );
$lastentry = $this -> db -> nextid ( $cfg [ 'tab' ][ 'actionlog' ]);
2016-10-06 15:57:01 +00:00
$sql = " INSERT INTO
2017-03-09 17:20:28 +00:00
" . $cfg['tab'] ['actionlog'] . "
2016-10-06 15:57:01 +00:00
SET
idlog = $lastentry ,
user_id = '" . $uid . "' ,
2017-03-09 17:20:28 +00:00
idclient = '" . Contenido_Security::toInteger($client) . "' ,
idlang = '" . Contenido_Security::toInteger($lang) . "' ,
2016-10-06 15:57:01 +00:00
idaction = $idaction ,
idcatart = $idcatart ,
logtimestamp = '$timestamp' " ;
$this -> db -> query ( $sql );
$sess -> register ( 'saveLoginTime' );
$saveLoginTime = true ;
}
2017-03-09 17:20:28 +00:00
public function auth_validatelogin () {
2016-10-06 15:57:01 +00:00
global $username , $password , $challenge , $response , $formtimestamp , $auth_handlers ;
$gperm = array ();
if ( $password == '' ) {
return false ;
}
2017-03-09 17:20:28 +00:00
if (( $formtimestamp + ( 60 * 15 )) < time ()) {
2016-10-06 15:57:01 +00:00
return false ;
}
if ( isset ( $username )) {
$this -> auth [ 'uname' ] = $username ; ## This provides access for 'loginform.ihtml'
} elseif ( $this -> nobody ) { ## provides for 'default login cancel'
$uid = $this -> auth [ 'uname' ] = $this -> auth [ 'uid' ] = 'nobody' ;
return $uid ;
}
2017-03-09 17:20:28 +00:00
$uid = false ;
2016-10-06 15:57:01 +00:00
$perm = false ;
$pass = false ;
$sDate = date ( 'Y-m-d' );
$this -> db -> query ( sprintf ( " SELECT user_id, perms, password FROM %s WHERE username = '%s' AND
2017-08-10 13:35:06 +00:00
( valid_from <= '" . $sDate . "' OR valid_from = '1000-01-01' OR valid_from = '0000-00-00' OR valid_from is NULL ) AND
( valid_to >= '" . $sDate . "' OR valid_to = '1000-01-01' OR valid_to = '0000-00-00' OR valid_to is NULL ) " , $this->database_table , Contenido_Security::escapeDB( $username , $this->db )
2016-10-06 15:57:01 +00:00
));
$sMaintenanceMode = getSystemProperty ( 'maintenance' , 'mode' );
2017-03-09 17:20:28 +00:00
while ( $this -> db -> next_record ()) {
$uid = $this -> db -> f ( 'user_id' );
$perm = $this -> db -> f ( 'perms' );
$pass = $this -> db -> f ( 'password' ); ## Password is stored as a md5 hash
2016-10-06 15:57:01 +00:00
$bInMaintenance = false ;
if ( $sMaintenanceMode == 'enabled' ) {
#sysadmins are allowed to login every time
if ( ! preg_match ( '/sysadmin/' , $perm )) {
$bInMaintenance = true ;
}
}
if ( $bInMaintenance ) {
unset ( $uid );
unset ( $perm );
unset ( $pass );
}
if ( is_array ( $auth_handlers ) && ! $bInMaintenance ) {
if ( array_key_exists ( $pass , $auth_handlers )) {
$success = call_user_func ( $auth_handlers [ $pass ], $username , $password );
if ( $success ) {
$uid = md5 ( $username );
$pass = md5 ( $password );
}
}
}
}
if ( $uid == false ) {
## No user found, sleep and exit
sleep ( 5 );
return false ;
} else {
2017-03-09 17:20:28 +00:00
$this -> db -> query ( sprintf ( " SELECT a.group_id AS group_id, a.perms AS perms " .
" FROM %s AS a, %s AS b WHERE a.group_id = b.group_id AND b.user_id = '%s' " , $this -> group_table , $this -> member_table , $uid
2016-10-06 15:57:01 +00:00
));
if ( $perm != '' ) {
$gperm [] = $perm ;
}
while ( $this -> db -> next_record ()) {
$gperm [] = $this -> db -> f ( 'perms' );
}
if ( is_array ( $gperm )) {
2017-03-09 17:20:28 +00:00
$perm = implode ( ',' , $gperm );
2016-10-06 15:57:01 +00:00
}
if ( $response == '' ) { ## True when JS is disabled
if ( md5 ( $password ) != $pass ) { ## md5 hash for non-JavaScript browsers
sleep ( 5 );
return false ;
} else {
$this -> auth [ 'perm' ] = $perm ;
$this -> auth_loglogin ( $uid );
return $uid ;
}
}
$expected_response = md5 ( " $username : $pass : $challenge " );
if ( $expected_response != $response ) { ## Response is set, JS is enabled
sleep ( 5 );
return false ;
} else {
$this -> auth [ 'perm' ] = $perm ;
$this -> auth_loglogin ( $uid );
return $uid ;
}
}
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
class Contenido_Frontend_Challenge_Crypt_Auth extends Auth {
public $classname = 'Contenido_Frontend_Challenge_Crypt_Auth' ;
public $lifetime = 15 ;
public $magic = 'Frrobo123xxica' ; ## Challenge seed
2016-10-06 15:57:01 +00:00
public $database_class = 'DB_Contenido' ;
public $database_table = '' ;
public $fe_database_table = '' ;
2017-03-09 17:20:28 +00:00
public $group_table = '' ;
public $member_table = '' ;
public $nobody = true ;
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
public function __construct () {
2016-10-06 15:57:01 +00:00
global $cfg ;
$this -> database_table = $cfg [ 'tab' ][ 'phplib_auth_user_md5' ];
$this -> fe_database_table = $cfg [ 'tab' ][ 'frontendusers' ];
$this -> group_table = $cfg [ 'tab' ][ 'groups' ];
$this -> member_table = $cfg [ 'tab' ][ 'groupmembers' ];
}
2017-03-09 17:20:28 +00:00
public function auth_preauth () {
2016-10-06 15:57:01 +00:00
global $password ;
if ( $password == '' ) {
/* Stay as nobody when an empty password is passed */
$uid = $this -> auth [ 'uname' ] = $this -> auth [ 'uid' ] = 'nobody' ;
return false ;
}
return $this -> auth_validatelogin ();
}
2017-03-09 17:20:28 +00:00
public function auth_loginform () {
2016-10-06 15:57:01 +00:00
global $sess , $challenge , $_PHPLIB , $client , $cfgClient ;
$challenge = md5 ( uniqid ( $this -> magic ));
$sess -> register ( 'challenge' );
2017-03-09 17:20:28 +00:00
include ( $cfgClient [ $client ][ 'path' ][ 'frontend' ] . 'front_crcloginform.inc.php' );
2016-10-06 15:57:01 +00:00
}
2017-03-09 17:20:28 +00:00
public function auth_validatelogin () {
2016-10-06 15:57:01 +00:00
global $username , $password , $challenge , $response , $auth_handlers , $client ;
2017-03-09 17:20:28 +00:00
$client = ( int ) $client ;
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
if ( isset ( $username )) {
2016-10-06 15:57:01 +00:00
$this -> auth [ 'uname' ] = $username ; ## This provides access for 'loginform.ihtml'
} else if ( $this -> nobody ) { ## provides for 'default login cancel'
$uid = $this -> auth [ 'uname' ] = $this -> auth [ 'uid' ] = 'nobody' ;
return $uid ;
}
$uid = false ;
/* Authentification via frontend users */
2017-03-09 17:20:28 +00:00
$this -> db -> query ( sprintf ( " SELECT idfrontenduser, password FROM %s WHERE username = '%s' AND idclient=' $client ' AND active='1' " , $this -> fe_database_table , Contenido_Security :: escapeDB ( urlencode ( $username ), $this -> db )
2016-10-06 15:57:01 +00:00
));
if ( $this -> db -> next_record ()) {
2017-03-09 17:20:28 +00:00
$uid = $this -> db -> f ( 'idfrontenduser' );
2016-10-06 15:57:01 +00:00
$perm = 'frontend' ;
$pass = $this -> db -> f ( 'password' );
}
if ( $uid == false ) {
/* Authentification via backend users */
2017-03-09 17:20:28 +00:00
$this -> db -> query ( sprintf ( " SELECT user_id, perms, password FROM %s WHERE username = '%s' " , $this -> database_table , Contenido_Security :: escapeDB ( $username , $this -> db )));
2016-10-06 15:57:01 +00:00
2017-03-09 17:20:28 +00:00
while ( $this -> db -> next_record ()) {
$uid = $this -> db -> f ( 'user_id' );
$perm = $this -> db -> f ( 'perms' );
$pass = $this -> db -> f ( 'password' ); ## Password is stored as a md5 hash
2016-10-06 15:57:01 +00:00
if ( is_array ( $auth_handlers )) {
if ( array_key_exists ( $pass , $auth_handlers )) {
$success = call_user_func ( $auth_handlers [ $pass ], $username , $password );
if ( $success ) {
2017-03-09 17:20:28 +00:00
$uid = md5 ( $username );
2016-10-06 15:57:01 +00:00
$pass = md5 ( $password );
}
}
}
}
if ( $uid !== false ) {
2017-03-09 17:20:28 +00:00
$this -> db -> query ( sprintf ( " SELECT a.group_id AS group_id, a.perms AS perms " .
" FROM %s AS a, %s AS b WHERE a.group_id = b.group_id AND " .
" b.user_id = '%s' " , $this -> group_table , $this -> member_table , $uid
2016-10-06 15:57:01 +00:00
));
/* Deactivated : Backend user would be sysadmin when logged on as frontend user
2017-03-09 17:20:28 +00:00
* ( and perms would be checked ), see http :// www . contenido . org / forum / viewtopic . php ? p = 85666 #85666
$perm = 'sysadmin' ; */
2016-10-06 15:57:01 +00:00
if ( $perm != '' ) {
$gperm [] = $perm ;
}
while ( $this -> db -> next_record ()) {
$gperm [] = $this -> db -> f ( 'perms' );
}
if ( is_array ( $gperm )) {
2017-03-09 17:20:28 +00:00
$perm = implode ( ',' , $gperm );
2016-10-06 15:57:01 +00:00
}
}
}
if ( $uid == false ) {
## User not found, sleep and exit
sleep ( 5 );
return false ;
} else {
if ( $response == '' ) { ## True when JS is disabled
if ( md5 ( $password ) != $pass ) { ## md5 hash for non-JavaScript browsers
sleep ( 5 );
return false ;
} else {
$this -> auth [ 'perm' ] = $perm ;
return $uid ;
}
}
$expected_response = md5 ( " $username : $pass : $challenge " );
if ( $expected_response != $response ) { ## Response is set, JS is enabled
sleep ( 5 );
return false ;
} else {
$this -> auth [ 'perm' ] = $perm ;
return $uid ;
}
}
}
2017-03-09 17:20:28 +00:00
2016-10-06 15:57:01 +00:00
}
/**
* Registers an external auth handler
*/
2017-03-09 17:20:28 +00:00
function register_auth_handler ( $aHandlers ) {
2016-10-06 15:57:01 +00:00
global $auth_handlers ;
if ( ! is_array ( $auth_handlers )) {
$auth_handlers = array ();
}
if ( ! is_array ( $aHandlers )) {
$aHandlers = Array ( $aHandlers );
}
foreach ( $aHandlers as $sHandler ) {
if ( ! in_array ( $sHandler , $auth_handlers )) {
$auth_handlers [ md5 ( $sHandler )] = $sHandler ;
}
}
}
?>