Perform proper checking for share availability
To check for shares, the code attempts to connect anonymously to the share. In most cases this will fail with NT_STATUS_ACCESS_DENIED, so the regex array used for parsing the output of smbclient in smb4php has been overridden to treat such output as success. The 'test' method for storage classes can now take a single parameter, $isPersonal, which allows the storage to adjust the tests performed based on if they are being configured as personal shares or as system shares.
This commit is contained in:
parent
cac4aaa8c4
commit
b077528087
|
@ -8,6 +8,8 @@
|
||||||
# Homepage: http://www.phpclasses.org/smb4php
|
# Homepage: http://www.phpclasses.org/smb4php
|
||||||
#
|
#
|
||||||
# Copyright (c) 2007 Victor M. Varela <vmvarela@gmail.com>
|
# Copyright (c) 2007 Victor M. Varela <vmvarela@gmail.com>
|
||||||
|
# Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
|
||||||
|
# Copyright (c) 2014 Robin McCorkell <rmccorkell@karoshi.org.uk>
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU General Public License
|
# modify it under the terms of the GNU General Public License
|
||||||
|
@ -19,8 +21,6 @@
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# Addition 17/12/2012 Frank Karlitschek (frank@owncloud.org)
|
|
||||||
# Addition 17/03/2014 Robin McCorkell (rmccorkell@karoshi.org.uk)
|
|
||||||
# On the official website http://www.phpclasses.org/smb4php the
|
# On the official website http://www.phpclasses.org/smb4php the
|
||||||
# license is listed as LGPL so we assume that this is
|
# license is listed as LGPL so we assume that this is
|
||||||
# dual-licensed GPL/LGPL
|
# dual-licensed GPL/LGPL
|
||||||
|
@ -44,6 +44,42 @@ $GLOBALS['__smb_cache'] = array ('stat' => array (), 'dir' => array ());
|
||||||
|
|
||||||
class smb {
|
class smb {
|
||||||
|
|
||||||
|
private static $regexp = array (
|
||||||
|
'^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip',
|
||||||
|
'Anonymous login successful' => 'skip',
|
||||||
|
'^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip',
|
||||||
|
'^\tSharename[ ]+Type[ ]+Comment$' => 'shares',
|
||||||
|
'^\t---------[ ]+----[ ]+-------$' => 'skip',
|
||||||
|
'^\tServer [ ]+Comment$' => 'servers',
|
||||||
|
'^\t---------[ ]+-------$' => 'skip',
|
||||||
|
'^\tWorkgroup[ ]+Master$' => 'workg',
|
||||||
|
'^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip',
|
||||||
|
'^\tIPC\\\$(.*)[ ]+IPC' => 'skip',
|
||||||
|
'^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share',
|
||||||
|
'^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip',
|
||||||
|
'([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip',
|
||||||
|
'Got a positive name query response from ' => 'skip',
|
||||||
|
'^(session setup failed): (.*)$' => 'error',
|
||||||
|
'^(.*): ERRSRV - ERRbadpw' => 'error',
|
||||||
|
'^Error returning browse list: (.*)$' => 'error',
|
||||||
|
'^tree connect failed: (.*)$' => 'error',
|
||||||
|
'^(Connection to .* failed)(.*)$' => 'error-connect',
|
||||||
|
'^NT_STATUS_(.*) ' => 'error',
|
||||||
|
'^NT_STATUS_(.*)\$' => 'error',
|
||||||
|
'ERRDOS - ERRbadpath \((.*).\)' => 'error',
|
||||||
|
'cd (.*): (.*)$' => 'error',
|
||||||
|
'^cd (.*): NT_STATUS_(.*)' => 'error',
|
||||||
|
'^\t(.*)$' => 'srvorwg',
|
||||||
|
'^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip',
|
||||||
|
'^Job ([0-9]+) cancelled' => 'skip',
|
||||||
|
'^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files',
|
||||||
|
'^message start: ERRSRV - (ERRmsgoff)' => 'error'
|
||||||
|
);
|
||||||
|
|
||||||
|
function getRegexp() {
|
||||||
|
return self::$regexp;
|
||||||
|
}
|
||||||
|
|
||||||
function parse_url ($url) {
|
function parse_url ($url) {
|
||||||
$pu = parse_url (trim($url));
|
$pu = parse_url (trim($url));
|
||||||
foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) {
|
foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) {
|
||||||
|
@ -75,46 +111,16 @@ class smb {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function execute ($command, $purl) {
|
function execute ($command, $purl, $regexp = NULL) {
|
||||||
return smb::client ('-d 0 '
|
return smb::client ('-d 0 '
|
||||||
. escapeshellarg ('//' . $purl['host'] . '/' . $purl['share'])
|
. escapeshellarg ('//' . $purl['host'] . '/' . $purl['share'])
|
||||||
. ' -c ' . escapeshellarg ($command), $purl
|
. ' -c ' . escapeshellarg ($command), $purl, $regexp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function client ($params, $purl) {
|
function client ($params, $purl, $regexp = NULL) {
|
||||||
|
|
||||||
static $regexp = array (
|
if ($regexp === NULL) $regexp = smb::$regexp;
|
||||||
'^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip',
|
|
||||||
'Anonymous login successful' => 'skip',
|
|
||||||
'^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip',
|
|
||||||
'^\tSharename[ ]+Type[ ]+Comment$' => 'shares',
|
|
||||||
'^\t---------[ ]+----[ ]+-------$' => 'skip',
|
|
||||||
'^\tServer [ ]+Comment$' => 'servers',
|
|
||||||
'^\t---------[ ]+-------$' => 'skip',
|
|
||||||
'^\tWorkgroup[ ]+Master$' => 'workg',
|
|
||||||
'^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip',
|
|
||||||
'^\tIPC\\\$(.*)[ ]+IPC' => 'skip',
|
|
||||||
'^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share',
|
|
||||||
'^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip',
|
|
||||||
'([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip',
|
|
||||||
'Got a positive name query response from ' => 'skip',
|
|
||||||
'^(session setup failed): (.*)$' => 'error',
|
|
||||||
'^(.*): ERRSRV - ERRbadpw' => 'error',
|
|
||||||
'^Error returning browse list: (.*)$' => 'error',
|
|
||||||
'^tree connect failed: (.*)$' => 'error',
|
|
||||||
'^(Connection to .* failed)(.*)$' => 'error-connect',
|
|
||||||
'^NT_STATUS_(.*) ' => 'error',
|
|
||||||
'^NT_STATUS_(.*)\$' => 'error',
|
|
||||||
'ERRDOS - ERRbadpath \((.*).\)' => 'error',
|
|
||||||
'cd (.*): (.*)$' => 'error',
|
|
||||||
'^cd (.*): NT_STATUS_(.*)' => 'error',
|
|
||||||
'^\t(.*)$' => 'srvorwg',
|
|
||||||
'^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip',
|
|
||||||
'^Job ([0-9]+) cancelled' => 'skip',
|
|
||||||
'^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files',
|
|
||||||
'^message start: ERRSRV - (ERRmsgoff)' => 'error'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (SMB4PHP_AUTHMODE == 'env') {
|
if (SMB4PHP_AUTHMODE == 'env') {
|
||||||
putenv("USER={$purl['user']}%{$purl['pass']}");
|
putenv("USER={$purl['user']}%{$purl['pass']}");
|
||||||
|
|
|
@ -319,7 +319,7 @@ class OC_Mount_Config {
|
||||||
'backend' => $backends[$mount['class']]['backend'],
|
'backend' => $backends[$mount['class']]['backend'],
|
||||||
'options' => $mount['options'],
|
'options' => $mount['options'],
|
||||||
'applicable' => array('groups' => array($group), 'users' => array()),
|
'applicable' => array('groups' => array($group), 'users' => array()),
|
||||||
'status' => self::getBackendStatus($mount['class'], $mount['options'])
|
'status' => self::getBackendStatus($mount['class'], $mount['options'], false)
|
||||||
);
|
);
|
||||||
$hash = self::makeConfigHash($config);
|
$hash = self::makeConfigHash($config);
|
||||||
// If an existing config exists (with same class, mountpoint and options)
|
// If an existing config exists (with same class, mountpoint and options)
|
||||||
|
@ -349,7 +349,7 @@ class OC_Mount_Config {
|
||||||
'backend' => $backends[$mount['class']]['backend'],
|
'backend' => $backends[$mount['class']]['backend'],
|
||||||
'options' => $mount['options'],
|
'options' => $mount['options'],
|
||||||
'applicable' => array('groups' => array(), 'users' => array($user)),
|
'applicable' => array('groups' => array(), 'users' => array($user)),
|
||||||
'status' => self::getBackendStatus($mount['class'], $mount['options'])
|
'status' => self::getBackendStatus($mount['class'], $mount['options'], true)
|
||||||
);
|
);
|
||||||
$hash = self::makeConfigHash($config);
|
$hash = self::makeConfigHash($config);
|
||||||
// If an existing config exists (with same class, mountpoint and options)
|
// If an existing config exists (with same class, mountpoint and options)
|
||||||
|
@ -389,7 +389,7 @@ class OC_Mount_Config {
|
||||||
'mountpoint' => substr($mountPoint, strlen($uid) + 8),
|
'mountpoint' => substr($mountPoint, strlen($uid) + 8),
|
||||||
'backend' => $backends[$mount['class']]['backend'],
|
'backend' => $backends[$mount['class']]['backend'],
|
||||||
'options' => $mount['options'],
|
'options' => $mount['options'],
|
||||||
'status' => self::getBackendStatus($mount['class'], $mount['options'])
|
'status' => self::getBackendStatus($mount['class'], $mount['options'], true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ class OC_Mount_Config {
|
||||||
* @param array $options backend configuration options
|
* @param array $options backend configuration options
|
||||||
* @return bool true if the connection succeeded, false otherwise
|
* @return bool true if the connection succeeded, false otherwise
|
||||||
*/
|
*/
|
||||||
private static function getBackendStatus($class, $options) {
|
private static function getBackendStatus($class, $options, $isPersonal) {
|
||||||
if (self::$skipTest) {
|
if (self::$skipTest) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +412,7 @@ class OC_Mount_Config {
|
||||||
if (class_exists($class)) {
|
if (class_exists($class)) {
|
||||||
try {
|
try {
|
||||||
$storage = new $class($options);
|
$storage = new $class($options);
|
||||||
return $storage->test();
|
return $storage->test($isPersonal);
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
\OCP\Util::logException('files_external', $exception);
|
\OCP\Util::logException('files_external', $exception);
|
||||||
return false;
|
return false;
|
||||||
|
@ -479,7 +479,7 @@ class OC_Mount_Config {
|
||||||
$mountPoints[$mountType] = $mount;
|
$mountPoints[$mountType] = $mount;
|
||||||
}
|
}
|
||||||
self::writeData($isPersonal, $mountPoints);
|
self::writeData($isPersonal, $mountPoints);
|
||||||
return self::getBackendStatus($class, $classOptions);
|
return self::getBackendStatus($class, $classOptions, $isPersonal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,11 +8,15 @@
|
||||||
|
|
||||||
namespace OC\Files\Storage;
|
namespace OC\Files\Storage;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../3rdparty/smb4php/smb.php';
|
||||||
|
|
||||||
class SMB_OC extends \OC\Files\Storage\SMB {
|
class SMB_OC extends \OC\Files\Storage\SMB {
|
||||||
|
private $username_as_share;
|
||||||
|
|
||||||
public function __construct($params) {
|
public function __construct($params) {
|
||||||
if (isset($params['host']) && \OC::$session->exists('smb-credentials')) {
|
if (isset($params['host']) && \OC::$session->exists('smb-credentials')) {
|
||||||
$host=$params['host'];
|
$host=$params['host'];
|
||||||
$username_as_share = ($params['username_as_share'] === 'true');
|
$this->username_as_share = ($params['username_as_share'] === 'true');
|
||||||
|
|
||||||
$params_auth = \OC::$session->get('smb-credentials');
|
$params_auth = \OC::$session->get('smb-credentials');
|
||||||
$user = \OC::$session->get('loginname');
|
$user = \OC::$session->get('loginname');
|
||||||
|
@ -21,7 +25,7 @@ class SMB_OC extends \OC\Files\Storage\SMB {
|
||||||
$root=isset($params['root'])?$params['root']:'/';
|
$root=isset($params['root'])?$params['root']:'/';
|
||||||
$share = '';
|
$share = '';
|
||||||
|
|
||||||
if ($username_as_share) {
|
if ($this->username_as_share) {
|
||||||
$share = '/'.$user;
|
$share = '/'.$user;
|
||||||
} elseif (isset($params['share'])) {
|
} elseif (isset($params['share'])) {
|
||||||
$share = $params['share'];
|
$share = $params['share'];
|
||||||
|
@ -47,4 +51,39 @@ class SMB_OC extends \OC\Files\Storage\SMB {
|
||||||
public function isSharable($path) {
|
public function isSharable($path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test($isPersonal = true) {
|
||||||
|
if ($isPersonal) {
|
||||||
|
if ($this->stat(''))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$smb = new \smb();
|
||||||
|
$pu = $smb->parse_url($this->constructUrl(''));
|
||||||
|
|
||||||
|
// Attempt to connect anonymously
|
||||||
|
$pu['user'] = '';
|
||||||
|
$pu['pass'] = '';
|
||||||
|
|
||||||
|
// Share cannot be checked if dynamic
|
||||||
|
if ($this->username_as_share) {
|
||||||
|
if ($smb->look($pu))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$pu['share'])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// The following error messages are expected due to anonymous login
|
||||||
|
$regexp = array(
|
||||||
|
'(NT_STATUS_ACCESS_DENIED)' => 'skip'
|
||||||
|
) + $smb->getRegexp();
|
||||||
|
|
||||||
|
if ($smb->client("-d 0 " . escapeshellarg('//' . $pu['host'] . '/' . $pu['share']) . " -c exit", $pu, $regexp))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue