first version of a setup command that can run via admins remote command execution

This commit is contained in:
Ralf Becker 2007-12-05 02:27:49 +00:00
parent e74c6debaa
commit 4f77162f64
6 changed files with 198 additions and 19 deletions

View File

@ -78,6 +78,9 @@ switch($action)
case '--check-acl';
return do_check_acl();
case '--show-header';
return run_command(new setup_cmd_showheader());
case '--exit-codes':
return list_exit_codes();
@ -123,6 +126,14 @@ function run_command(admin_cmd $cmd)
case '--skip-checks': //do not yet run the checks for scheduled local commands
$skip_checks = true;
break;
case '--header-access':
if ($cmd instanceof setup_cmd)
{
list($user,$pw) = explode(',',array_shift($arguments),2);
$cmd->set_header_secret($user,$pw);
}
break;
default:
//fail(99,lang('Unknown option %1',$extra);
@ -138,7 +149,15 @@ function run_command(admin_cmd $cmd)
{
fail($cmd->errno,$cmd->error);
}
echo $msg."\n\n";
if (($value = unserialize($msg)) !== false && $msg !== serialize(false))
{
print_r($value);
echo "\n";
}
else
{
echo $msg."\n\n";
}
exit(0);
}
@ -441,4 +460,4 @@ function do_subscribe_other($account_lid,$pw=null)
//$icServer->subscribeMailbox($mailbox);
//exit;
}
}
}

View File

@ -15,8 +15,6 @@
*/
abstract class admin_cmd
{
const edit_user = 16;
const deleted = 0;
const scheduled = 1;
const successful = 2;
@ -29,7 +27,7 @@ abstract class admin_cmd
private $status;
static $stati = array(
admin_cmd::scheduled => 'scheduled',
admin_cmd::scheduled => 'scheduled',
admin_cmd::successful => 'successful',
admin_cmd::failed => 'failed',
admin_cmd::deleted => 'deleted',
@ -48,7 +46,7 @@ abstract class admin_cmd
public $requested_email;
public $comment;
private $id;
private $uid;
protected $uid;
private $type = __CLASS__;
public $remote_id;
@ -394,8 +392,6 @@ abstract class admin_cmd
{
if (is_null(admin_cmd::$sql))
{
include_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.so_sql.inc.php');
admin_cmd::$sql = new so_sql('admin','egw_admin_queue',null,'cmd_');
}
}
@ -409,8 +405,6 @@ abstract class admin_cmd
{
if (is_null(admin_cmd::$remote))
{
include_once(EGW_INCLUDE_ROOT.'/etemplate/inc/class.so_sql.inc.php');
admin_cmd::$remote = new so_sql('admin','egw_admin_remote');
}
}
@ -815,7 +809,7 @@ abstract class admin_cmd
* Save / adds a remote instance
*
* @param array $data
* @return array/boolean data including remote_id or false on failure
* @return int remote_id
*/
static function save_remote(array $data)
{
@ -823,17 +817,21 @@ abstract class admin_cmd
if ($data['install_id'] && $data['config_passwd']) // calculate hash
{
$pw = preg_match('/^[a-f0-9]{32}$/',$data['config_passwd']) ? $data['config_passwd'] : md5($data['config_passwd']);
$pw = self::is_md5($data['config_passwd']) ? $data['config_passwd'] : md5($data['config_passwd']);
$data['remote_hash'] = md5($pw.$data['install_id']);
}
elseif ($data['install_id'] || $data['config_passwd'] || !$data['remote_hash'])
{
return false; // we need either install_id AND config_passwd OR the remote_hash
throw new Exception(lang('Either Install ID AND config password needed OR the remote hash!'));
}
//_debug_array($data);
admin_cmd::$remote->init($data);
return admin_cmd::$remote->save() == 0 ? admin_cmd::$remote->data : false;
if (admin_cmd::$remote->save() != 0)
{
throw new Exception (lang('Error saving to db:').' '.$this->sql->db->Error.' ('.$this->sql->db->Errno.')',$this->sql->db->Errno);
}
return admin_cmd::$remote->data['remote_id'];
}
/**
@ -850,4 +848,15 @@ abstract class admin_cmd
return $account.' ('.$GLOBALS['egw']->common->grab_owner_name($id).')';
}
/**
* Check if string is a md5 hash (32 chars of 0-9 or a-f)
*
* @param string $str
* @return boolean
*/
static function is_md5($str)
{
return preg_match('/^[0-9a-f]{32}$/',$str);
}
}

View File

@ -157,9 +157,12 @@ class admin_cmds
$content['msg'] = lang('You need to enter Install ID AND Password!');
break;
}
if (($content['remote'] = admin_cmd::save_remote($content['remote'])))
{
try {
$content['remote']['remote_id'] = admin_cmd::save_remote($content['remote']);
$content['msg'] = lang('Remote instance saved');
} catch (Exception $e) {
$content['msg'] = lang('Error saving').': '.$e->getMessage().' ('.$e->getCode().')';
break;
}
if ($button == 'apply') break;
// fall through for save

View File

@ -1,6 +1,6 @@
<?php
/**
* eGgroupWare admin - remote admin comand execution
* eGgroupWare admin - remote admin command execution
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
@ -10,6 +10,9 @@
* @version $Id$
*/
/**
* @var array
*/
$GLOBALS['egw_info'] = array(
'flags' => array(
'currentapp' => 'login',
@ -21,7 +24,7 @@ include('../header.inc.php');
$GLOBALS['egw']->applications->read_installed_apps(); // set $GLOBALS['egw_info']['apps'] (not set for login)
$instance = $_REQUEST['domain'];
$instance = isset($_GET['domain']) ? $_GET['domain'] : $_REQUEST['domain']; // use GET before the rest
if (!isset($GLOBALS['egw_domain'][$instance]))
{
$instance = $GLOBALS['egw_info']['server']['default_domain'];
@ -39,7 +42,7 @@ if (!$domain_data || is_numeric($_REQUEST['uid']) || !in_array($remote_admin_ins
$_REQUEST['secret'] != ($md5=md5($_REQUEST['uid'].md5($domain_data['config_passwd'].$GLOBALS['egw_info']['server']['install_id']))))
{
header("HTTP/1.1 200 Unauthorized");
//die("0 secret != '$md5'");
die("0 secret != '$md5'");
echo lang('0 Permission denied!');
if (!in_array($remote_admin_install_id,$allowed_remote_admin_ids))
{

View File

@ -0,0 +1,68 @@
<?php
/**
* eGgroupWare setup - abstract baseclass for all setup commands, extending admin_cmd
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package setup
* @copyright (c) 2007 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id: class.admin_cmd_check_acl.inc.php 24709 2007-11-27 03:20:28Z ralfbecker $
*/
/**
* setup command: abstract baseclass for all setup commands, extending admin_cmd
*/
abstract class setup_cmd extends admin_cmd
{
/**
* Should be called by every command usually requiring header admin rights
*
* @throws Exception(lang('Wrong credentials to access the header.inc.php file!'),2);
*/
protected function _check_header_access()
{
if ($this->header_secret != ($secret = $this->_calc_header_secret($GLOBALS['egw_info']['server']['header_admin_user'],
$GLOBALS['egw_info']['server']['header_admin_password'])))
{
//echo "header_secret='$this->header_secret' != '$secret'=_calc_header_secret({$GLOBALS['egw_info']['server']['header_admin_user']},{$GLOBALS['egw_info']['server']['header_admin_password']})\n";
throw new Exception (lang('Wrong credentials to access the header.inc.php file!'),2);
}
}
/**
* Set the user and pw required for any operation on the header file
*
* @param string $user
* @param string $pw password or md5 hash of it
*/
public function set_header_secret($user,$pw)
{
if ($this->uid || parent::save(false)) // we need to save first, to get the uid
{
$this->header_secret = $this->_calc_header_secret($user,$pw);
}
else
{
throw new Exception ('failed to set header_secret!');
}
}
/**
* Calculate the header_secret used to access the header from this command
*
* It's an md5 over the uid, header-admin-user and -password.
*
* @param string $header_admin_user
* @param string $header_admin_password
* @return string
*/
private function _calc_header_secret($header_admin_user=null,$header_admin_password=null)
{
if (!self::is_md5($header_admin_password)) $header_admin_password = md5($header_admin_password);
$secret = md5($this->uid.$header_admin_user.$header_admin_password);
//echo "header_secret='$secret' = md5('$this->uid'.'$header_admin_user'.'$header_admin_password')\n";
return $secret;
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* eGgroupWare setup - show/return the header.inc.php
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @package setup
* @copyright (c) 2007 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id: class.admin_cmd_check_acl.inc.php 24709 2007-11-27 03:20:28Z ralfbecker $
*/
/**
* setup command: show/return the header.inc.php
*
* Has no constructor, as we have no arguments beside the header admin user and password,
* which get set via setup_cmd::set_header_secret($user,$pw)
*/
class setup_cmd_showheader extends setup_cmd
{
/**
* Constructor
*
* @param array $data=array() default parm from parent class, no real parameters
*/
function __construct($data=array())
{
//echo __CLASS__.'::__construct()'; _debug_array($data);
admin_cmd::__construct($data);
}
/**
* show/return the header.inc.php
*
* @param boolean $check_only=false only run the checks (and throw the exceptions), but not the command itself
* @return string serialized $GLOBALS defined in the header.inc.php
* @throws Exception(lang('Wrong credentials to access the header.inc.php file!'),2);
* @throws Exception('header.inc.php not found!');
*/
function exec($check_only=false)
{
if ($this->remote_id && $check_only) return true; // cant check for the remote site locally!
$this->_check_header_access();
if ($check_only) return true;
$egw_info_backup = $GLOBALS['egw_info'];
$GLOBALS['egw_info'] = array (
'flags' => array(
'noapi' => true,
),
);
if (!($header = file_get_contents(EGW_SERVER_ROOT.'/header.inc.php')))
{
throw new Exception('header.inc.php not found!');
}
eval(str_replace(array('<?php','perfgetmicrotime'),array('','perfgetmicrotime2'),$header));
// unset the flags, they are not part of the header
unset($GLOBALS['egw_info']['flags']);
// include the api version of this instance
$GLOBALS['egw_info']['server']['versions']['phpgwapi'] = $egw_info_backup['server']['versions']['phpgwapi'];
$ret = serialize(array(
'egw_info' => $GLOBALS['egw_info'],
'egw_domain' => $GLOBALS['egw_domain'],
'EGW_SERVER_ROOT' => EGW_SERVER_ROOT,
'EGW_INCLUDE_ROOT' => EGW_INCLUDE_ROOT,
));
$GLOBALS['egw_info'] = $egw_info_backup;
return $ret;
}
}