Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SMB/CIFS mounts using ownCloud login, fixes #7843 #7875

Merged
merged 7 commits into from
Mar 27, 2014
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 43 additions & 37 deletions apps/files_external/3rdparty/smb4php/smb.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
# Homepage: http://www.phpclasses.org/smb4php
#
# 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
# modify it under the terms of the GNU General Public License
Expand All @@ -19,8 +21,6 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# 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
# license is listed as LGPL so we assume that this is
# dual-licensed GPL/LGPL
Expand All @@ -44,6 +44,42 @@

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) {
$pu = parse_url (trim($url));
foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) {
Expand Down Expand Up @@ -75,46 +111,16 @@ function look ($purl) {
}


function execute ($command, $purl) {
function execute ($command, $purl, $regexp = NULL) {
return smb::client ('-d 0 '
. escapeshellarg ('//' . $purl['host'] . '/' . $purl['share'])
. ' -c ' . escapeshellarg ($command), $purl
. ' -c ' . escapeshellarg ($command), $purl, $regexp
);
}

function client ($params, $purl) {

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 client ($params, $purl, $regexp = NULL) {

if ($regexp === NULL) $regexp = smb::$regexp;

if (SMB4PHP_AUTHMODE == 'env') {
putenv("USER={$purl['user']}%{$purl['pass']}");
Expand Down
3 changes: 3 additions & 0 deletions apps/files_external/appinfo/app.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
* Copyright (c) 2014 Robin McCorkell <rmccorkell@karoshi.org.uk>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
Expand All @@ -13,6 +14,7 @@
OC::$CLASSPATH['OC\Files\Storage\Google'] = 'files_external/lib/google.php';
OC::$CLASSPATH['OC\Files\Storage\Swift'] = 'files_external/lib/swift.php';
OC::$CLASSPATH['OC\Files\Storage\SMB'] = 'files_external/lib/smb.php';
OC::$CLASSPATH['OC\Files\Storage\SMB_OC'] = 'files_external/lib/smb_oc.php';
OC::$CLASSPATH['OC\Files\Storage\AmazonS3'] = 'files_external/lib/amazons3.php';
OC::$CLASSPATH['OC\Files\Storage\Dropbox'] = 'files_external/lib/dropbox.php';
OC::$CLASSPATH['OC\Files\Storage\SFTP'] = 'files_external/lib/sftp.php';
Expand All @@ -27,4 +29,5 @@
// connecting hooks
OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OC_Mount_Config', 'initMountPointsHook');
OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\iRODS', 'login');
OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\SMB_OC', 'login');

26 changes: 17 additions & 9 deletions apps/files_external/lib/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* @author Michael Gapczynski
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
* @copyright 2014 Robin McCorkell <rmccorkell@karoshi.org.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
Expand Down Expand Up @@ -122,19 +123,26 @@ public static function getBackends() {
'password' => '*Password',
'share' => 'Share',
'root' => '&Root'));
$backends['\OC\Files\Storage\SMB_OC'] = array(
'backend' => 'SMB / CIFS using OC login',
'configuration' => array(
'host' => 'URL',
'username_as_share' => '!Username as share',
'share' => '&Share',
'root' => '&Root'));
}
}

if(OC_Mount_Config::checkcurl()){
$backends['\OC\Files\Storage\DAV']=array(
$backends['\OC\Files\Storage\DAV']=array(
'backend' => 'WebDAV',
'configuration' => array(
'host' => 'URL',
'user' => 'Username',
'password' => '*Password',
'root' => '&Root',
'secure' => '!Secure https://'));
$backends['\OC\Files\Storage\OwnCloud']=array(
$backends['\OC\Files\Storage\OwnCloud']=array(
'backend' => 'ownCloud',
'configuration' => array(
'host' => 'URL',
Expand Down Expand Up @@ -185,7 +193,7 @@ public static function initMountPointsHook($data) {
* @return array of mount point string as key, mountpoint config as value
*/
public static function getAbsoluteMountPoints($user) {
$mountPoints = array();
$mountPoints = array();

$datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
$mount_file = \OC_Config::getValue("mount_file", $datadir . "/mount.json");
Expand Down Expand Up @@ -311,7 +319,7 @@ public static function getSystemMountPoints() {
'backend' => $backends[$mount['class']]['backend'],
'options' => $mount['options'],
'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);
// If an existing config exists (with same class, mountpoint and options)
Expand Down Expand Up @@ -341,7 +349,7 @@ public static function getSystemMountPoints() {
'backend' => $backends[$mount['class']]['backend'],
'options' => $mount['options'],
'applicable' => array('groups' => array(), 'users' => array($user)),
'status' => self::getBackendStatus($mount['class'], $mount['options'])
'status' => self::getBackendStatus($mount['class'], $mount['options'], false)
);
$hash = self::makeConfigHash($config);
// If an existing config exists (with same class, mountpoint and options)
Expand Down Expand Up @@ -381,7 +389,7 @@ public static function getPersonalMountPoints() {
'mountpoint' => substr($mountPoint, strlen($uid) + 8),
'backend' => $backends[$mount['class']]['backend'],
'options' => $mount['options'],
'status' => self::getBackendStatus($mount['class'], $mount['options'])
'status' => self::getBackendStatus($mount['class'], $mount['options'], true)
);
}
}
Expand All @@ -394,7 +402,7 @@ public static function getPersonalMountPoints() {
* @param array $options backend configuration options
* @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) {
return true;
}
Expand All @@ -404,7 +412,7 @@ private static function getBackendStatus($class, $options) {
if (class_exists($class)) {
try {
$storage = new $class($options);
return $storage->test();
return $storage->test($isPersonal);
} catch (Exception $exception) {
\OCP\Util::logException('files_external', $exception);
return false;
Expand Down Expand Up @@ -471,7 +479,7 @@ public static function addMountPoint($mountPoint,
$mountPoints[$mountType] = $mount;
}
self::writeData($isPersonal, $mountPoints);
return self::getBackendStatus($class, $classOptions);
return self::getBackendStatus($class, $classOptions, $isPersonal);
}

/**
Expand Down
89 changes: 89 additions & 0 deletions apps/files_external/lib/smb_oc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* Copyright (c) 2014 Robin McCorkell <rmccorkell@karoshi.org.uk>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace OC\Files\Storage;

require_once __DIR__ . '/../3rdparty/smb4php/smb.php';

class SMB_OC extends \OC\Files\Storage\SMB {
private $username_as_share;

public function __construct($params) {
if (isset($params['host']) && \OC::$session->exists('smb-credentials')) {
$host=$params['host'];
$this->username_as_share = ($params['username_as_share'] === 'true');

$params_auth = \OC::$session->get('smb-credentials');
$user = \OC::$session->get('loginname');
$password = $params_auth['password'];

$root=isset($params['root'])?$params['root']:'/';
$share = '';

if ($this->username_as_share) {
$share = '/'.$user;
} elseif (isset($params['share'])) {
$share = $params['share'];
} else {
throw new \Exception();
}
parent::__construct(array(
"user" => $user,
"password" => $password,
"host" => $host,
"share" => $share,
"root" => $root
));
} else {
throw new \Exception();
}
}

public static function login( $params ) {
\OC::$session->set('smb-credentials', $params);
}

public function isSharable($path) {
return false;
}

public function test($isPersonal = true) {
if ($isPersonal) {
if ($this->stat(''))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please always use {}

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;
}
}
}