diff --git a/CMakeLists.txt b/CMakeLists.txt index df55d288d..d6f989f01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ if(NOT HOST_OS) endif(NOT HOST_OS) set (CMAKE_CXX_STANDARD 11) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # Default CLFAGS and CXXFLAGS: set(CMAKE_C_FLAGS_RELEASE "-Wall -D__STDC_CONSTANT_MACROS -O2") set(CMAKE_CXX_FLAGS_RELEASE "-Wall -D__STDC_CONSTANT_MACROS -O2") diff --git a/src/zm_time.h b/src/zm_time.h index de9d2a22f..a9af32777 100644 --- a/src/zm_time.h +++ b/src/zm_time.h @@ -77,8 +77,6 @@ struct DeltaTimeval #define MSEC_PER_SEC 1000 extern struct timeval tv; -typedef typeof(tv.tv_sec) ast_time_t; -typedef typeof(tv.tv_usec) ast_suseconds_t; inline int tvDiffUsec( struct timeval first, struct timeval last ) { diff --git a/web/api/app/Config/bootstrap.php.in b/web/api/app/Config/bootstrap.php.in index f1c6d85d4..a94b58fc1 100644 --- a/web/api/app/Config/bootstrap.php.in +++ b/web/api/app/Config/bootstrap.php.in @@ -120,29 +120,17 @@ Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@'); Configure::write('ZM_VERSION', '@VERSION@'); Configure::write('ZM_API_VERSION', '@API_VERSION@'); -# Process name, value pairs from the main config file first -$configvals = api_process_configfile(Configure::read('ZM_CONFIG')); +require_once("../../../includes/config.php"); +global $configvals; -# Search for user created config files. If one or more are found then -# update our config value array with those values -$configSubFolder = Configure::read('ZM_CONFIG_SUBDIR'); -if ( is_dir($configSubFolder) ) { - if ( is_readable($configSubFolder) ) { - foreach ( glob("$configSubFolder/*.conf") as $filename ) { - $configvals = array_replace($configvals, api_process_configfile($filename) ); - } - } else { - error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." ); - } -} - -# Now that our array our finalized, define each key => value -# pair in the array as a constant +# Now that our array our finalized, and the config has been defined. +# Add them to the cakephp Config foreach( $configvals as $key => $value) { - define( $key, $value ); - Configure::write( $key, $value ); + Configure::write($key, $value); } - +if ( 0 ) { + // No longer needed, but I want to keep the code for reference + // // For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID if ( ! defined('ZM_SERVER_ID') ) { App::uses('ClassRegistry', 'Utility'); @@ -163,26 +151,4 @@ if ( ! defined('ZM_SERVER_ID') ) { } } } - -function api_process_configfile($configFile) { - if ( is_readable( $configFile ) ) { - $configvals = array(); - - $cfg = fopen( $configFile, 'r') or die('Could not open config file.'); - while ( !feof($cfg) ) { - $str = fgets( $cfg, 256 ); - if ( preg_match( '/^\s*$/', $str )) - continue; - elseif ( preg_match( '/^\s*#/', $str )) - continue; - elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches )) - $configvals[$matches[1]] = $matches[2]; - } - fclose( $cfg ); - return( $configvals ); - } else { - error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." ); - return( false ); - } } - diff --git a/web/api/app/Config/routes.php b/web/api/app/Config/routes.php index f58c7b9ba..a684f241e 100644 --- a/web/api/app/Config/routes.php +++ b/web/api/app/Config/routes.php @@ -36,7 +36,7 @@ /* Add new API to retrieve camera controls - for PTZ */ /* refer to https://github.com/ZoneMinder/ZoneMinder/issues/799#issuecomment-105233112 */ Router::mapResources('controls'); - Router::mapResources('groups'); + Router::mapResources('groups'); Router::parseExtensions(); /** diff --git a/web/api/app/Controller/AppController.php b/web/api/app/Controller/AppController.php index 1c0458c41..7be1cd72a 100644 --- a/web/api/app/Controller/AppController.php +++ b/web/api/app/Controller/AppController.php @@ -76,6 +76,8 @@ class AppController extends Controller { $zmOptAuth = $config['Config']['Value']; if ( $zmOptAuth == '1' ) { + require_once "../../../includes/auth.php"; + $this->loadModel('User'); if ( isset($_REQUEST['user']) and isset($_REQUEST['pass']) ) { $user = $this->User->find('first', array ('conditions' => array ( @@ -92,19 +94,6 @@ class AppController extends Controller { } if ( isset($_REQUEST['auth']) ) { - require_once "../../../includes/functions.php"; - - // Define some defines required by getAuthUser in functions.php - $defines = array('ZM_AUTH_HASH_IPS', 'ZM_AUTH_HASH_SECRET', 'ZM_AUTH_RELAY', 'ZM_OPT_USE_AUTH'); - $configQuery = array( - 'conditions' => array('OR' => array('Name' => $defines)), - 'fields' => array('Name', 'Value') - ); - $config = $this->Config->find('list', $configQuery); - - foreach ($defines as $define) { - define($define, $config[$define]); - } $user = getAuthUser($_REQUEST['auth']); if ( ! $user ) { @@ -134,9 +123,8 @@ class AppController extends Controller { $this->Session->Write('controlPermission',$userMonitors['User']['Control']); $this->Session->Write('systemPermission',$userMonitors['User']['System']); $this->Session->Write('monitorPermission',$userMonitors['User']['Monitors']); - } - else // if auth is not on, you can do everything - { + } else { + // if auth is not on, you can do everything //$userMonitors = $this->User->find('first', $options); $this->Session->Write('allowedMonitors',''); $this->Session->Write('streamPermission','View'); diff --git a/web/api/app/Controller/HostController.php b/web/api/app/Controller/HostController.php index 4fdb48cba..ff6410e15 100644 --- a/web/api/app/Controller/HostController.php +++ b/web/api/app/Controller/HostController.php @@ -7,8 +7,7 @@ class HostController extends AppController { public function daemonCheck($daemon=false, $args=false) { $string = Configure::read('ZM_PATH_BIN')."/zmdc.pl check"; - if ( $daemon ) - { + if ( $daemon ) { $string .= " $daemon"; if ( $args ) $string .= " $args"; @@ -31,6 +30,13 @@ class HostController extends AppController { )); } + function getAuthHash() { + $this->set(array( + 'auth_hash'=> generateAuthHash( ZM_AUTH_HASH_IPS ), + '_serialize' => array('auth_hash') + ) ); + } + // If $mid is set, only return disk usage for that monitor // Else, return an array of total disk usage, and per-monitor // usage. @@ -99,15 +105,14 @@ class HostController extends AppController { )); } - function getTimeZone() - { - //http://php.net/manual/en/function.date-default-timezone-get.php - $tz = date_default_timezone_get(); - $this->set(array( - 'tz' => $tz, - '_serialize' => array('tz') - )); - } + function getTimeZone() { + //http://php.net/manual/en/function.date-default-timezone-get.php + $tz = date_default_timezone_get(); + $this->set(array( + 'tz' => $tz, + '_serialize' => array('tz') + )); + } function getVersion() { //throw new UnauthorizedException(__('API Disabled')); diff --git a/web/includes/Event.php b/web/includes/Event.php index 6cc440664..7b15671d8 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -158,7 +158,7 @@ class Event { } # ! ZM_OPT_FAST_DELETE } # end Event->delete - public function getStreamSrc( $args=array(), $querySep='&' ) { + public function getStreamSrc( $args=array(), $querySep='&' ) { if ( $this->{'DefaultVideo'} and $args['mode'] != 'jpeg' ) { $streamSrc = ZM_BASE_PROTOCOL.'://'; $Monitor = $this->Monitor(); diff --git a/web/includes/auth.php b/web/includes/auth.php new file mode 100644 index 000000000..7850d29dd --- /dev/null +++ b/web/includes/auth.php @@ -0,0 +1,160 @@ + diff --git a/web/includes/config.php.in b/web/includes/config.php.in index 0ff558dbc..c9bd55dd7 100644 --- a/web/includes/config.php.in +++ b/web/includes/config.php.in @@ -26,6 +26,7 @@ define( 'ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@' ); // Path to config subfolder // Define, and override any given in config file define( 'ZM_VERSION', '@VERSION@' ); // Version define( 'ZM_DIR_TEMP', '@ZM_TMPDIR@' ); +global $configvals; $configFile = ZM_CONFIG; $localConfigFile = basename($configFile); diff --git a/web/includes/functions.php b/web/includes/functions.php index 285f1ada3..10cdda31d 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -27,59 +27,6 @@ if ( version_compare( phpversion(), '4.3.0', '<') ) { } } -# We are requiring these because this file is getting included from the api, which hasn't already included them. -require_once('logger.php'); -require_once('database.php'); - -function userLogin( $username, $password='', $passwordHashed=false ) { - global $user, $cookies; - - $sql = 'SELECT * FROM Users WHERE Enabled=1'; - $sql_values = NULL; - if ( ZM_AUTH_TYPE == 'builtin' ) { - if ( $passwordHashed ) { - $sql .= ' AND Username=? AND Password=?'; - } else { - $sql .= ' AND Username=? AND Password=password(?)'; - } - $sql_values = array( $username, $password ); - } else { - $sql .= ' AND Username=?'; - $sql_values = array( $username ); - } - session_start(); - $_SESSION['username'] = $username; - if ( ZM_AUTH_RELAY == 'plain' ) { - // Need to save this in session - $_SESSION['password'] = $password; - } - $_SESSION['remoteAddr'] = $_SERVER['REMOTE_ADDR']; // To help prevent session hijacking - if ( $dbUser = dbFetchOne( $sql, NULL, $sql_values ) ) { - Info( "Login successful for user \"$username\"" ); - $_SESSION['user'] = $user = $dbUser; - unset($_SESSION['loginFailed']); - if ( ZM_AUTH_TYPE == 'builtin' ) { - $_SESSION['passwordHash'] = $user['Password']; - } - session_regenerate_id(); - } else { - Warning( "Login denied for user \"$username\"" ); - $_SESSION['loginFailed'] = true; - unset( $user ); - } - session_write_close(); -} - -function userLogout() { - global $user; - Info( 'User "'.$user['Username'].'" logged out' ); - session_start(); - unset( $_SESSION['user'] ); - unset( $user ); - - session_destroy(); -} - function noCacheHeaders() { header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: '.gmdate( 'D, d M Y H:i:s' ).' GMT'); // always modified @@ -112,78 +59,6 @@ function CORSHeaders() { } } -function getAuthUser( $auth ) { - if ( ZM_OPT_USE_AUTH && ZM_AUTH_RELAY == 'hashed' && !empty($auth) ) { - $remoteAddr = ''; - if ( ZM_AUTH_HASH_IPS ) { - $remoteAddr = $_SERVER['REMOTE_ADDR']; - if ( !$remoteAddr ) { - Error( "Can't determine remote address for authentication, using empty string" ); - $remoteAddr = ''; - } - } - - if ( isset( $_SESSION['username'] ) ) { - # Most of the time we will be logged in already and the session will have our username, so we can significantly speed up our hash testing by only looking at our user. - # Only really important if you have a lot of users. - $sql = "SELECT * FROM Users WHERE Enabled = 1 AND Username='".$_SESSION['username']."'"; - } else { - $sql = 'SELECT * FROM Users WHERE Enabled = 1'; - } - - foreach ( dbFetchAll( $sql ) as $user ) { - $now = time(); - for ( $i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= (3600) ) { // Try for last two hours - $time = localtime( $now ); - $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; - $authHash = md5( $authKey ); - - if ( $auth == $authHash ) { - return $user; - } - } // end foreach hour - } // end foreach user - } // end if using auth hash - Error( "Unable to authenticate user from auth hash '$auth'" ); - return( false ); -} // end getAuthUser($auth) - -function generateAuthHash( $useRemoteAddr ) { - if ( ZM_OPT_USE_AUTH and ZM_AUTH_RELAY == 'hashed' and isset($_SESSION['username']) and $_SESSION['passwordHash'] ) { - # regenerate a hash at half the liftetime of a hash, an hour is 3600 so half is 1800 - $time = time(); - $mintime = $time - ( ZM_AUTH_HASH_TTL * 1800 ); - - if ( ( !isset($_SESSION['AuthHash']) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime ) ) { - # Don't both regenerating Auth Hash if an hour hasn't gone by yet - $local_time = localtime(); - $authKey = ''; - if ( $useRemoteAddr ) { - $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$_SESSION['remoteAddr'].$local_time[2].$local_time[3].$local_time[4].$local_time[5]; - } else { - $authKey = ZM_AUTH_HASH_SECRET.$_SESSION['username'].$_SESSION['passwordHash'].$local_time[2].$local_time[3].$local_time[4].$local_time[5]; - } - #Logger::Debug("Generated using hour:".$local_time[2] . ' mday:' . $local_time[3] . ' month:'.$local_time[4] . ' year: ' . $local_time[5] ); - $auth = md5( $authKey ); - if ( session_status() == PHP_SESSION_NONE ) { - $backTrace = debug_backtrace(); - $file = $backTrace[1]['file']; - $line = $backTrace[1]['line']; - Warning("Session is not active. AuthHash will not be cached. called from $file:$line. OldHash:" . $_SESSION['AuthHash'] . ' generated at ' . $_SESSION['AuthHashGeneratedAt'] . ' < ' . $time . ' - ( ' . ZM_AUTH_HASH_TTL . '* 1800 = ' . ZM_AUTH_HASH_TTL * 1800 ); - } - $_SESSION['AuthHash'] = $auth; - $_SESSION['AuthHashGeneratedAt'] = $time; - #Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" ); - #} else { - #Logger::Debug("Using cached auth " . $_SESSION['AuthHash'] ." beacuse generatedat:" . $_SESSION['AuthHashGeneratedAt'] . ' < now:'. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '. $mintime); - } # end if AuthHash is not cached - return $_SESSION['AuthHash']; - } else { - $auth = ''; - } - return( $auth ); -} - function getStreamSrc( $args, $querySep='&' ) { $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; @@ -451,24 +326,6 @@ function getZmuCommand( $args ) { return( $zmuCommand ); } -function visibleMonitor( $mid ) { - global $user; - - return( empty($user['MonitorIds']) || in_array( $mid, explode( ',', $user['MonitorIds'] ) ) ); -} - -function canView( $area, $mid=false ) { - global $user; - - return( ($user[$area] == 'View' || $user[$area] == 'Edit') && ( !$mid || visibleMonitor( $mid ) ) ); -} - -function canEdit( $area, $mid=false ) { - global $user; - - return( $user[$area] == 'Edit' && ( !$mid || visibleMonitor( $mid ) ) ); -} - function getEventDefaultVideoPath( $event ) { $Event = new Event( $event ); return $Event->getStreamSrc( array( 'mode'=>'mpeg', 'format'=>'h264' ) ); diff --git a/web/index.php b/web/index.php index c44037d76..f3fa91449 100644 --- a/web/index.php +++ b/web/index.php @@ -148,6 +148,7 @@ if ( ZM_OPT_USE_AUTH ) { require_once( 'includes/lang.php' ); require_once( 'includes/functions.php' ); +require_once( 'includes/auth.php' ); # Running is global but only do the daemonCheck if it is actually needed $running = null; diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index f61920c73..3d38a680b 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -110,16 +110,16 @@ echo output_link_if_exists( array( } ?> - - - - - - - - + + + + + + + + - - + @@ -152,7 +152,7 @@ echo output_link_if_exists( array( } if ( $skinJsPhpFile ) { ?> -