* Sharing: fixed not accessible share, if user already logged into same EGroupware instance, also fixed WebDAV problems using a share URL

This commit is contained in:
Ralf Becker 2015-02-28 22:19:24 +00:00
parent 35fc079c7f
commit 1ea193ef14
3 changed files with 72 additions and 41 deletions

View File

@ -126,10 +126,22 @@ class egw_sharing
/** /**
* Create sharing session * Create sharing session
* *
* @param boolean $keep_session =false false: create a new session, true: try mounting it into existing (already verified) session * Certain cases:
* a) there is not session $keep_session === null
* --> create new anon session with just filemanager rights and share as fstab
* b) there is a session $keep_session === true
* b1) current user is share owner (eg. checking the link)
* --> mount share under token additionally
* b2) current user not share owner
* b2a) need/use filemanager UI (eg. directory)
* --> destroy current session and continue with a)
* b2b) single file or WebDAV
* --> modify EGroupware enviroment for that request only, no change in session
*
* @param boolean $keep_session =null null: create a new session, true: try mounting it into existing (already verified) session
* @return string with sessionid, does NOT return if no session created * @return string with sessionid, does NOT return if no session created
*/ */
public static function create_session($keep_session=false) public static function create_session($keep_session=null)
{ {
self::$db = $GLOBALS['egw']->db; self::$db = $GLOBALS['egw']->db;
@ -191,39 +203,14 @@ class egw_sharing
{ {
$share['share_root'] = '/'.$share['share_token']; $share['share_root'] = '/'.$share['share_token'];
// if current user is not the share owner, we need to give him access to mounted share // if current user is not the share owner, we cant just mount share
if (egw_vfs::$user != $share['share_owner']) if (egw_vfs::$user != $share['share_owner'])
{
// check if sharing user has owner rights for shared path
egw_vfs::$user = $share['share_owner'];
egw_vfs::clearstatcache();
if (egw_vfs::has_owner_rights($share['share_path']))
{
$rights = $share['share_writable'] && egw_vfs::is_writable($share['share_path']) ? 7 : 5;
egw_vfs::$user = $GLOBALS['egw']->session->account_id;
egw_vfs::eacl($share['share_root'], $rights, egw_vfs::$user, true); // true = session-only, not permanent
}
// if not, we must not use an eacl, as it grants recursive rights!
// (one could eg. create a writable share for / and use it to escalate his own rights)
// --> create a new session with propper rights (loosing current session)
else
{ {
$keep_session = false; $keep_session = false;
} }
} }
}
if (!$keep_session) // do NOT change to else, as we might have set $keep_session=false! if (!$keep_session) // do NOT change to else, as we might have set $keep_session=false!
{ {
// create session without checking auth: create(..., false, false)
if (!($sessionid = $GLOBALS['egw']->session->create('anonymous', '', 'text', false, false)))
{
sleep(1);
$status = '500 Internal Server Error';
header("HTTP/1.1 $status");
header("X-WebDAV-Status: $status", true);
echo "Failed to create session: ".$GLOBALS['egw']->session->reason."\n";
common::egw_exit();
}
// only allow filemanager app // only allow filemanager app
$GLOBALS['egw_info']['user']['apps'] = array( $GLOBALS['egw_info']['user']['apps'] = array(
'filemanager' => $GLOBALS['egw_info']['apps']['filemanager'] 'filemanager' => $GLOBALS['egw_info']['apps']['filemanager']
@ -260,8 +247,34 @@ class egw_sharing
// store sharing object in egw object and therefore in session // store sharing object in egw object and therefore in session
$GLOBALS['egw']->sharing = new egw_sharing($share); $GLOBALS['egw']->sharing = new egw_sharing($share);
// for an existing session we need to store modified egw and egw_info again in session // we have a session we want to keep, but share owner is different from current user and we need filemanager UI, or no session
if ($keep_session) // --> create a new anon session
if ($keep_session === false && $GLOBALS['egw']->sharing->use_filemanager() || is_null($keep_session))
{
// create session without checking auth: create(..., false, false)
if (!($sessionid = $GLOBALS['egw']->session->create('anonymous', '', 'text', false, false)))
{
sleep(1);
$status = '500 Internal Server Error';
header("HTTP/1.1 $status");
header("X-WebDAV-Status: $status", true);
echo "Failed to create session: ".$GLOBALS['egw']->session->reason."\n";
common::egw_exit();
}
// only allow filemanager app (gets overwritten by session::create)
$GLOBALS['egw_info']['user']['apps'] = array(
'filemanager' => $GLOBALS['egw_info']['apps']['filemanager']
);
}
// we have a session we want to keep, but share owner is different from current user and we dont need filemanager UI
// --> we dont need session and close it, to not modifiy it
elseif ($keep_session === false)
{
$GLOBALS['egw']->session->commit_session();
}
// update modified egw and egw_info again in session, if neccessary
if ($keep_session || $sessionid)
{ {
$_SESSION[egw_session::EGW_INFO_CACHE] = $GLOBALS['egw_info']; $_SESSION[egw_session::EGW_INFO_CACHE] = $GLOBALS['egw_info'];
unset($_SESSION[egw_session::EGW_INFO_CACHE]['flags']); // dont save the flags, they change on each request unset($_SESSION[egw_session::EGW_INFO_CACHE]['flags']); // dont save the flags, they change on each request
@ -272,6 +285,22 @@ class egw_sharing
return $sessionid; return $sessionid;
} }
/**
* Check if we use filemanager UI
*
* Only for directories, if browser supports it and filemanager is installed
*
* @return boolean
*/
public function use_filemanager()
{
return !(!egw_vfs::is_dir($this->share['share_root']) || $_SERVER['REQUEST_METHOD'] != 'GET' ||
// or unsupported browsers like ie < 10
html::$user_agent == 'msie' && html::$ua_version < 10.0 ||
// or if no filemanager installed (WebDAV has own autoindex)
!file_exists(__DIR__.'/../../filemanager/inc/class.filemanager_ui.inc.php'));
}
/** /**
* Server a request on a share specified in REQUEST_URI * Server a request on a share specified in REQUEST_URI
*/ */
@ -285,11 +314,7 @@ class egw_sharing
return $GLOBALS['egw']->sharing->ServeRequest(); return $GLOBALS['egw']->sharing->ServeRequest();
} }
// use pure WebDAV for everything but GET requests to directories // use pure WebDAV for everything but GET requests to directories
if (!egw_vfs::is_dir($this->share['share_root']) || $_SERVER['REQUEST_METHOD'] != 'GET' || if (!$this->use_filemanager())
// or unsupported browsers like ie < 10
html::$user_agent == 'msie' && html::$ua_version < 10.0 ||
// or if no filemanager installed (WebDAV has own autoindex)
!file_exists(__DIR__.'/../../filemanager/inc/class.filemanager_ui.inc.php'))
{ {
// send a content-disposition header, so browser knows how to name downloaded file // send a content-disposition header, so browser knows how to name downloaded file
if (!egw_vfs::is_dir($this->share['share_root'])) if (!egw_vfs::is_dir($this->share['share_root']))

View File

@ -548,7 +548,11 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
$path = egw_vfs::parse_url($url,PHP_URL_PATH); $path = egw_vfs::parse_url($url,PHP_URL_PATH);
if (!($stat = self::url_stat($path,STREAM_URL_STAT_LINK)) || !egw_vfs::check_access(egw_vfs::dirname($path),egw_vfs::WRITABLE, $parent_stat)) // need to get parent stat from Sqlfs, not Vfs
if (!isset($parent_stat)) $parent_stat = static::url_stat(egw_vfs::dirname($path), STREAM_URL_STAT_LINK);
if (!$parent_stat || !($stat = self::url_stat($path,STREAM_URL_STAT_LINK)) ||
!egw_vfs::check_access(egw_vfs::dirname($path), egw_vfs::WRITABLE, $parent_stat))
{ {
self::_remove_password($url); self::_remove_password($url);
if (self::LOG_LEVEL) error_log(__METHOD__."($url) permission denied!"); if (self::LOG_LEVEL) error_log(__METHOD__."($url) permission denied!");
@ -779,7 +783,7 @@ class sqlfs_stream_wrapper implements iface_stream_wrapper
$parent = egw_vfs::dirname($path); $parent = egw_vfs::dirname($path);
if (!($stat = self::url_stat($path,0)) || $stat['mime'] != self::DIR_MIME_TYPE || if (!($stat = self::url_stat($path,0)) || $stat['mime'] != self::DIR_MIME_TYPE ||
!egw_vfs::check_access($parent,egw_vfs::WRITABLE)) !egw_vfs::check_access($parent, egw_vfs::WRITABLE, static::url_stat($parent,0)))
{ {
self::_remove_password($url); self::_remove_password($url);
$err_msg = __METHOD__."($url,$options) ".(!$stat ? 'not found!' : $err_msg = __METHOD__."($url,$options) ".(!$stat ? 'not found!' :

View File

@ -90,7 +90,9 @@ class vfs_webdav_server extends HTTP_WebDAV_Server_Filesystem
{ {
// recursive delete the directory // recursive delete the directory
try { try {
$ret = egw_vfs::remove($options['path']) && !file_exists($path); $deleted = egw_vfs::remove($options['path']);
$ret = !empty($deleted[$options['path']]);
//error_log(__METHOD__."() egw_vfs::remove($options[path]) returned ".array2string($deleted)." --> ".array2string($ret));
} }
catch (Exception $e) { catch (Exception $e) {
return '403 Forbidden: '.$e->getMessage(); return '403 Forbidden: '.$e->getMessage();
@ -129,7 +131,7 @@ class vfs_webdav_server extends HTTP_WebDAV_Server_Filesystem
return "403 Forbidden"; return "403 Forbidden";
} }
if ( file_exists($parent."/".$name) ) { if ( file_exists($path) ) {
return "405 Method not allowed"; return "405 Method not allowed";
} }
@ -137,7 +139,7 @@ class vfs_webdav_server extends HTTP_WebDAV_Server_Filesystem
return "415 Unsupported media type"; return "415 Unsupported media type";
} }
$stat = mkdir($parent."/".$name, 0777); $stat = mkdir($path, 0777);
if (!$stat) { if (!$stat) {
return "403 Forbidden"; return "403 Forbidden";
} }