mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-07 16:44:20 +01:00
moved access checks into the class with a default implementation, so commands can override it, to be eg. anonymous or under other restrictions available
This commit is contained in:
parent
40a68b6cfd
commit
e195efadeb
@ -19,18 +19,21 @@ abstract class admin_cmd
|
||||
const scheduled = 1;
|
||||
const successful = 2;
|
||||
const failed = 3;
|
||||
const pending = 4;
|
||||
|
||||
/**
|
||||
* The status of the command, one of either scheduled, successful, failed or deleted
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $status;
|
||||
protected $status;
|
||||
|
||||
static $stati = array(
|
||||
admin_cmd::scheduled => 'scheduled',
|
||||
admin_cmd::successful => 'successful',
|
||||
admin_cmd::failed => 'failed',
|
||||
admin_cmd::deleted => 'deleted',
|
||||
admin_cmd::pending => 'pending',
|
||||
);
|
||||
|
||||
protected $created;
|
||||
@ -40,8 +43,8 @@ abstract class admin_cmd
|
||||
private $modified;
|
||||
private $modifier;
|
||||
private $modifier_email;
|
||||
private $error;
|
||||
private $errno;
|
||||
protected $error;
|
||||
protected $errno;
|
||||
public $requested;
|
||||
public $requested_email;
|
||||
public $comment;
|
||||
@ -167,7 +170,7 @@ abstract class admin_cmd
|
||||
{
|
||||
$ret = $this->remote_exec();
|
||||
}
|
||||
$this->status = admin_cmd::successful;
|
||||
if (is_null($this->status)) $this->status = admin_cmd::successful;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->error = $e->getMessage();
|
||||
@ -229,7 +232,10 @@ abstract class admin_cmd
|
||||
);
|
||||
$url = $remote['remote_url'].'/admin/remote.php?domain='.urlencode($remote['remote_domain']).'&secret='.urlencode($secret);
|
||||
//echo "sending command to $url\n"; _debug_array($opts);
|
||||
$message = file_get_contents($url, false, stream_context_create($opts));
|
||||
if (!($message = @file_get_contents($url, false, stream_context_create($opts))))
|
||||
{
|
||||
throw new egw_exception(lang('Could not remote execute the command').': '.$http_response_header[0]);
|
||||
}
|
||||
//echo "got: $message\n";
|
||||
|
||||
if (($value = unserialize($message)) !== false && $message !== serialize(false))
|
||||
@ -283,7 +289,7 @@ abstract class admin_cmd
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (is_null($this->id))
|
||||
if (!$this->id)
|
||||
{
|
||||
$this->id = admin_cmd::$sql->data['id'];
|
||||
// if the cmd has no uid yet, we create one from our id and the install-id of this eGW instance
|
||||
@ -429,6 +435,12 @@ abstract class admin_cmd
|
||||
{
|
||||
return $this->$property; // making all (non static) class vars readonly available
|
||||
}
|
||||
switch($property)
|
||||
{
|
||||
case 'accounts':
|
||||
self::_instanciate_accounts();
|
||||
return self::$accounts;
|
||||
}
|
||||
return $this->data[$property];
|
||||
}
|
||||
|
||||
@ -658,7 +670,7 @@ abstract class admin_cmd
|
||||
* @todo accounts class instanciation for setup
|
||||
* @throws egw_exception_assertion_failed(lang('%1 class not instanciated','accounts'),999);
|
||||
*/
|
||||
protected function _instanciate_accounts()
|
||||
static function _instanciate_accounts()
|
||||
{
|
||||
if (!is_object(admin_cmd::$accounts))
|
||||
{
|
||||
@ -857,7 +869,7 @@ abstract class admin_cmd
|
||||
{
|
||||
$data['remote_hash'] = self::remote_hash($data['install_id'],$data['config_passwd']);
|
||||
}
|
||||
elseif ($data['install_id'] || $data['config_passwd'] || !$data['remote_hash'])
|
||||
elseif (!$data['remote_hash'] && !($data['install_id'] && $data['config_passwd']))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('Either Install ID AND config password needed OR the remote hash!'));
|
||||
}
|
||||
@ -914,4 +926,41 @@ abstract class admin_cmd
|
||||
{
|
||||
return preg_match('/^[0-9a-f]{32}$/',$str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current command has the right crediential to be excuted remotely
|
||||
*
|
||||
* Command can reimplement that method, to allow eg. anonymous execution.
|
||||
*
|
||||
* This default implementation use a secret to authenticate with the installation,
|
||||
* which is a md5 hash build from the uid of the command (to not allow to send new
|
||||
* commands with an earsdroped secret) and the md5 hash of the md5 hash of the
|
||||
* config password and the install_id (egw_admin_remote.remote_hash)
|
||||
*
|
||||
* @param string $secret hash used to authenticate the command (
|
||||
* @param string $config_passwd of the current domain
|
||||
* @throws egw_exception_no_permission
|
||||
*/
|
||||
function check_remote_access($secret,$config_passwd)
|
||||
{
|
||||
// as a security measure remote administration need to be enabled under Admin > Site configuration
|
||||
list(,$remote_admin_install_id) = explode('-',$this->uid);
|
||||
$allowed_remote_admin_ids = $GLOBALS['egw_info']['server']['allow_remote_admin'] ? explode(',',$GLOBALS['egw_info']['server']['allow_remote_admin']) : array();
|
||||
|
||||
// to authenticate with the installation we use a secret, which is a md5 hash build from the uid
|
||||
// of the command (to not allow to send new commands with an earsdroped secret) and the md5 hash
|
||||
// of the md5 hash of the config password and the install_id (egw_admin_remote.remote_hash)
|
||||
if (is_null($config_passwd) || is_numeric($this->uid) || !in_array($remote_admin_install_id,$allowed_remote_admin_ids) ||
|
||||
$secret != ($md5=md5($this->uid.$this->remote_hash($GLOBALS['egw_info']['server']['install_id'],$config_passwd))))
|
||||
{
|
||||
//die("secret='$secret' != '$md5', is_null($config_passwd)=".is_null($config_passwd).", uid=$this->uid, remote_install_id=$remote_admin_install_id, allowed: ".implode(', ',$allowed_remote_admin_ids));
|
||||
$msg = lang('Permission denied!');
|
||||
if (!in_array($remote_admin_install_id,$allowed_remote_admin_ids))
|
||||
{
|
||||
$msg .= "\n".lang('Remote administration need to be enabled in the remote instance under Admin > Site configuration!');
|
||||
}
|
||||
throw new egw_exception_no_permission($msg,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
admin_cmd::_instanciate_accounts();
|
||||
|
@ -22,6 +22,20 @@ $GLOBALS['egw_info'] = array(
|
||||
|
||||
include('../header.inc.php');
|
||||
|
||||
// install an own exception handler to forward exceptions back to the remote side
|
||||
function remote_exception_handler(Exception $e)
|
||||
{
|
||||
$msg = $e->getMessage();
|
||||
if (is_object($GLOBALS['egw']->translation))
|
||||
{
|
||||
$msg = $GLOBALS['egw']->translation->convert($msg,$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
}
|
||||
header('HTTP/1.1 200 '.$msg);
|
||||
echo $e->getCode().' '.$msg;
|
||||
$GLOBALS['egw']->common->egw_exit();
|
||||
}
|
||||
set_exception_handler('remote_exception_handler');
|
||||
|
||||
$GLOBALS['egw']->applications->read_installed_apps(); // set $GLOBALS['egw_info']['apps'] (not set for login)
|
||||
|
||||
$instance = isset($_GET['domain']) ? $_GET['domain'] : $_REQUEST['domain']; // use GET before the rest
|
||||
@ -29,27 +43,8 @@ if (!isset($GLOBALS['egw_domain'][$instance]))
|
||||
{
|
||||
$instance = $GLOBALS['egw_info']['server']['default_domain'];
|
||||
}
|
||||
$domain_data = $GLOBALS['egw_domain'][$instance];
|
||||
//echo $instance; _debug_array($domain_data);
|
||||
|
||||
// as a security measure remote administration need to be enabled under Admin > Site configuration
|
||||
list(,$remote_admin_install_id) = explode('-',$_REQUEST['uid']);
|
||||
$allowed_remote_admin_ids = $GLOBALS['egw_info']['server']['allow_remote_admin'] ? explode(',',$GLOBALS['egw_info']['server']['allow_remote_admin']) : array();
|
||||
// to authenticate with the installation we use a secret, which is a md5 hash build from the uid
|
||||
// of the command (to not allow to send new commands with an earsdroped secret) and the md5 hash
|
||||
// of the md5 hash of the config password and the install_id (egw_admin_remote.remote_hash)
|
||||
if (!$domain_data || is_numeric($_REQUEST['uid']) || !in_array($remote_admin_install_id,$allowed_remote_admin_ids) ||
|
||||
$_REQUEST['secret'] != ($md5=md5($_REQUEST['uid'].admin_cmd::remote_hash($GLOBALS['egw_info']['server']['install_id'],$domain_data['config_passwd']))))
|
||||
{
|
||||
header("HTTP/1.1 200 Unauthorized");
|
||||
//die("0 secret != '$md5'");
|
||||
echo lang('0 Permission denied!');
|
||||
if (!in_array($remote_admin_install_id,$allowed_remote_admin_ids))
|
||||
{
|
||||
echo "\n".lang('Remote administration need to be enabled in the remote instance under Admin > Site configuration!');
|
||||
}
|
||||
$GLOBALS['egw']->common->egw_exit();
|
||||
}
|
||||
$config_passwd = $GLOBALS['egw_domain'][$instance]['config_passwd'];
|
||||
unset($GLOBALS['egw_domain']);
|
||||
|
||||
require_once(EGW_INCLUDE_ROOT.'/admin/inc/class.admin_cmd.inc.php');
|
||||
|
||||
@ -58,7 +53,15 @@ require_once(EGW_INCLUDE_ROOT.'/admin/inc/class.admin_cmd.inc.php');
|
||||
$cmd = admin_cmd::read($_REQUEST['uid']);
|
||||
if (is_object($cmd))
|
||||
{
|
||||
exit_with_status($cmd);
|
||||
$cmd->check_remote_access($_REQUEST['secret'],$config_passwd);
|
||||
|
||||
$success_msg = 'Successful';
|
||||
// if the comand object has a rerun method, call it
|
||||
if (method_exists($cmd,'rerun'))
|
||||
{
|
||||
$success_msg = $cmd->rerun();
|
||||
}
|
||||
exit_with_status($cmd,$success_msg);
|
||||
}
|
||||
|
||||
// check if requests contains a reasonable looking admin command to be queued
|
||||
@ -67,7 +70,7 @@ if (!$_REQUEST['uid'] || // no uid
|
||||
!$_REQUEST['creator_email']) // no creator email
|
||||
{
|
||||
header("HTTP/1.1 200 Bad format!");
|
||||
echo lang('0 Bad format!');
|
||||
echo '0 Bad format!';
|
||||
$GLOBALS['egw']->common->egw_exit();
|
||||
}
|
||||
|
||||
@ -81,22 +84,18 @@ if (isset($data['modifier'])) $data['modifier'] = 0;
|
||||
if (isset($data['requested'])) $data['requested'] = 0;
|
||||
|
||||
// instanciate comand and run it
|
||||
try {
|
||||
$cmd = admin_cmd::instanciate($data);
|
||||
//_debug_array($cmd); exit;
|
||||
$success_msg = $cmd->run();
|
||||
|
||||
$GLOBALS['egw']->translation->convert($success_msg,$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
$cmd = admin_cmd::instanciate($data);
|
||||
|
||||
if (!is_string($success_msg))
|
||||
{
|
||||
$success_msg = serialize($success_msg);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
header('HTTP/1.1 200 '.$e->getMessage());
|
||||
echo $e->getCode().' '.$e->getMessage();
|
||||
$GLOBALS['egw']->common->egw_exit();
|
||||
$cmd->check_remote_access($_REQUEST['secret'],$config_passwd);
|
||||
|
||||
//_debug_array($cmd); exit;
|
||||
$success_msg = $cmd->run();
|
||||
|
||||
$GLOBALS['egw']->translation->convert($success_msg,$GLOBALS['egw']->translation->charset(),'utf-8');
|
||||
|
||||
if (!is_string($success_msg))
|
||||
{
|
||||
$success_msg = serialize($success_msg);
|
||||
}
|
||||
exit_with_status($cmd,$success_msg);
|
||||
|
||||
@ -112,6 +111,7 @@ function exit_with_status($cmd,$success_msg='Successful')
|
||||
default: // everything else is returned as 200 HTTP status
|
||||
$success_msg = $cmd->stati[$cmd->status];
|
||||
// fall through
|
||||
case admin_cmd::pending:
|
||||
case admin_cmd::successful:
|
||||
header('HTTP/1.1 200 '.$cmd->stati[$cmd->status]);
|
||||
header('Content-type: text/plain; charset=utf-8');
|
||||
|
Loading…
Reference in New Issue
Block a user