Merge branch 'master' into routing
This commit is contained in:
commit
d579defc66
|
@ -21,15 +21,17 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once('apps/user_ldap/lib_ldap.php');
|
OCP\App::registerAdmin('user_ldap', 'settings');
|
||||||
require_once('apps/user_ldap/user_ldap.php');
|
|
||||||
require_once('apps/user_ldap/group_ldap.php');
|
|
||||||
|
|
||||||
OCP\App::registerAdmin('user_ldap','settings');
|
$connector = new OCA\user_ldap\lib\Connection('user_ldap');
|
||||||
|
$userBackend = new OCA\user_ldap\USER_LDAP();
|
||||||
|
$userBackend->setConnector($connector);
|
||||||
|
$groupBackend = new OCA\user_ldap\GROUP_LDAP();
|
||||||
|
$groupBackend->setConnector($connector);
|
||||||
|
|
||||||
// register user backend
|
// register user backend
|
||||||
OC_User::useBackend( 'LDAP' );
|
OC_User::useBackend($userBackend);
|
||||||
OC_Group::useBackend( new OC_GROUP_LDAP() );
|
OC_Group::useBackend($groupBackend);
|
||||||
|
|
||||||
// add settings page to navigation
|
// add settings page to navigation
|
||||||
$entry = array(
|
$entry = array(
|
||||||
|
|
|
@ -21,24 +21,22 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class OC_GROUP_LDAP extends OC_Group_Backend {
|
namespace OCA\user_ldap;
|
||||||
// //group specific settings
|
|
||||||
protected $ldapGroupFilter;
|
class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface {
|
||||||
protected $ldapGroupMemberAssocAttr;
|
protected $enabled = false;
|
||||||
protected $configured = false;
|
|
||||||
|
|
||||||
protected $_group_user = array();
|
protected $_group_user = array();
|
||||||
protected $_user_groups = array();
|
protected $_user_groups = array();
|
||||||
protected $_group_users = array();
|
protected $_group_users = array();
|
||||||
protected $_groups = array();
|
protected $_groups = array();
|
||||||
|
|
||||||
public function __construct() {
|
public function setConnector(lib\Connection &$connection) {
|
||||||
$this->ldapGroupFilter = OCP\Config::getAppValue('user_ldap', 'ldap_group_filter', '(objectClass=posixGroup)');
|
parent::setConnector($connection);
|
||||||
$this->ldapGroupMemberAssocAttr = OCP\Config::getAppValue('user_ldap', 'ldap_group_member_assoc_attribute', 'uniqueMember');
|
if(empty($this->connection->ldapGroupFilter) || empty($this->connection->ldapGroupMemberAssocAttr)) {
|
||||||
|
$this->enabled = false;
|
||||||
if(!empty($this->ldapGroupFilter) && !empty($this->ldapGroupMemberAssocAttr)) {
|
|
||||||
$this->configured = true;
|
|
||||||
}
|
}
|
||||||
|
$this->enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,31 +48,31 @@ class OC_GROUP_LDAP extends OC_Group_Backend {
|
||||||
* Checks whether the user is member of a group or not.
|
* Checks whether the user is member of a group or not.
|
||||||
*/
|
*/
|
||||||
public function inGroup($uid, $gid) {
|
public function inGroup($uid, $gid) {
|
||||||
if(!$this->configured) {
|
if(!$this->enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(isset($this->_group_user[$gid][$uid])) {
|
if(isset($this->_group_user[$gid][$uid])) {
|
||||||
return $this->_group_user[$gid][$uid];
|
return $this->_group_user[$gid][$uid];
|
||||||
}
|
}
|
||||||
$dn_user = OC_LDAP::username2dn($uid);
|
$dn_user = $this->username2dn($uid);
|
||||||
$dn_group = OC_LDAP::groupname2dn($gid);
|
$dn_group = $this->groupname2dn($gid);
|
||||||
// just in case
|
// just in case
|
||||||
if(!$dn_group || !$dn_user) {
|
if(!$dn_group || !$dn_user) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//usually, LDAP attributes are said to be case insensitive. But there are exceptions of course.
|
//usually, LDAP attributes are said to be case insensitive. But there are exceptions of course.
|
||||||
$members = OC_LDAP::readAttribute($dn_group, $this->ldapGroupMemberAssocAttr);
|
$members = $this->readAttribute($dn_group, $this->connection->ldapGroupMemberAssocAttr);
|
||||||
if(!$members) {
|
if(!$members) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//extra work if we don't get back user DNs
|
//extra work if we don't get back user DNs
|
||||||
//TODO: this can be done with one LDAP query
|
//TODO: this can be done with one LDAP query
|
||||||
if(strtolower($this->ldapGroupMemberAssocAttr) == 'memberuid') {
|
if(strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid') {
|
||||||
$dns = array();
|
$dns = array();
|
||||||
foreach($members as $mid) {
|
foreach($members as $mid) {
|
||||||
$filter = str_replace('%uid', $mid, OC_LDAP::conf('ldapLoginFilter'));
|
$filter = str_replace('%uid', $mid, $this->connection->ldapLoginFilter);
|
||||||
$ldap_users = OC_LDAP::fetchListOfUsers($filter, 'dn');
|
$ldap_users = $this->fetchListOfUsers($filter, 'dn');
|
||||||
if(count($ldap_users) < 1) {
|
if(count($ldap_users) < 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -96,36 +94,37 @@ class OC_GROUP_LDAP extends OC_Group_Backend {
|
||||||
* if the user exists at all.
|
* if the user exists at all.
|
||||||
*/
|
*/
|
||||||
public function getUserGroups($uid) {
|
public function getUserGroups($uid) {
|
||||||
if(!$this->configured) {
|
if(!$this->enabled) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
if(isset($this->_user_groups[$uid])) {
|
if(isset($this->_user_groups[$uid])) {
|
||||||
return $this->_user_groups[$uid];
|
return $this->_user_groups[$uid];
|
||||||
}
|
}
|
||||||
$userDN = OC_LDAP::username2dn($uid);
|
$userDN = $this->username2dn($uid);
|
||||||
if(!$userDN) {
|
if(!$userDN) {
|
||||||
$this->_user_groups[$uid] = array();
|
$this->_user_groups[$uid] = array();
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
//uniqueMember takes DN, memberuid the uid, so we need to distinguish
|
//uniqueMember takes DN, memberuid the uid, so we need to distinguish
|
||||||
if((strtolower($this->ldapGroupMemberAssocAttr) == 'uniquemember')
|
if((strtolower($this->connection->ldapGroupMemberAssocAttr) == 'uniquemember')
|
||||||
|| (strtolower($this->ldapGroupMemberAssocAttr) == 'member')) {
|
|| (strtolower($this->connection->ldapGroupMemberAssocAttr) == 'member')
|
||||||
|
) {
|
||||||
$uid = $userDN;
|
$uid = $userDN;
|
||||||
} else if(strtolower($this->ldapGroupMemberAssocAttr) == 'memberuid') {
|
} else if(strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid') {
|
||||||
$result = OC_LDAP::readAttribute($userDN, 'uid');
|
$result = $this->readAttribute($userDN, 'uid');
|
||||||
$uid = $result[0];
|
$uid = $result[0];
|
||||||
} else {
|
} else {
|
||||||
// just in case
|
// just in case
|
||||||
$uid = $userDN;
|
$uid = $userDN;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filter = OC_LDAP::combineFilterWithAnd(array(
|
$filter = $this->combineFilterWithAnd(array(
|
||||||
$this->ldapGroupFilter,
|
$this->connection->ldapGroupFilter,
|
||||||
$this->ldapGroupMemberAssocAttr.'='.$uid
|
$this->connection->ldapGroupMemberAssocAttr.'='.$uid
|
||||||
));
|
));
|
||||||
$groups = OC_LDAP::fetchListOfGroups($filter, array(OC_LDAP::conf('ldapGroupDisplayName'),'dn'));
|
$groups = $this->fetchListOfGroups($filter, array($this->connection->ldapGroupDisplayName,'dn'));
|
||||||
$this->_user_groups[$uid] = array_unique(OC_LDAP::ownCloudGroupNames($groups), SORT_LOCALE_STRING);
|
$this->_user_groups[$uid] = array_unique($this->ownCloudGroupNames($groups), SORT_LOCALE_STRING);
|
||||||
|
|
||||||
return $this->_user_groups[$uid];
|
return $this->_user_groups[$uid];
|
||||||
}
|
}
|
||||||
|
@ -135,44 +134,44 @@ class OC_GROUP_LDAP extends OC_Group_Backend {
|
||||||
* @returns array with user ids
|
* @returns array with user ids
|
||||||
*/
|
*/
|
||||||
public function usersInGroup($gid) {
|
public function usersInGroup($gid) {
|
||||||
if(!$this->configured) {
|
if(!$this->enabled) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
if(isset($this->_group_users[$gid])) {
|
if(isset($this->_group_users[$gid])) {
|
||||||
return $this->_group_users[$gid];
|
return $this->_group_users[$gid];
|
||||||
}
|
}
|
||||||
|
|
||||||
$groupDN = OC_LDAP::groupname2dn($gid);
|
$groupDN = $this->groupname2dn($gid);
|
||||||
if(!$groupDN) {
|
if(!$groupDN) {
|
||||||
$this->_group_users[$gid] = array();
|
$this->_group_users[$gid] = array();
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$members = OC_LDAP::readAttribute($groupDN, $this->ldapGroupMemberAssocAttr);
|
$members = $this->readAttribute($groupDN, $this->connection->ldapGroupMemberAssocAttr);
|
||||||
if(!$members) {
|
if(!$members) {
|
||||||
$this->_group_users[$gid] = array();
|
$this->_group_users[$gid] = array();
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
$isMemberUid = (strtolower($this->ldapGroupMemberAssocAttr) == 'memberuid');
|
$isMemberUid = (strtolower($this->connection->ldapGroupMemberAssocAttr) == 'memberuid');
|
||||||
foreach($members as $member) {
|
foreach($members as $member) {
|
||||||
if($isMemberUid) {
|
if($isMemberUid) {
|
||||||
$filter = OCP\Util::mb_str_replace('%uid', $member, OC_LDAP::conf('ldapLoginFilter'), 'UTF-8');
|
$filter = \OCP\Util::mb_str_replace('%uid', $member, $this->connection->ldapLoginFilter, 'UTF-8');
|
||||||
$ldap_users = OC_LDAP::fetchListOfUsers($filter, 'dn');
|
$ldap_users = $this->fetchListOfUsers($filter, 'dn');
|
||||||
if(count($ldap_users) < 1) {
|
if(count($ldap_users) < 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$result[] = OC_LDAP::dn2username($ldap_users[0]);
|
$result[] = $this->dn2username($ldap_users[0]);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if($ocname = OC_LDAP::dn2username($member)){
|
if($ocname = $this->dn2username($member)) {
|
||||||
$result[] = $ocname;
|
$result[] = $ocname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!$isMemberUid) {
|
if(!$isMemberUid) {
|
||||||
$result = array_intersect($result, OCP\User::getUsers());
|
$result = array_intersect($result, \OCP\User::getUsers());
|
||||||
}
|
}
|
||||||
$this->_group_users[$gid] = array_unique($result, SORT_LOCALE_STRING);
|
$this->_group_users[$gid] = array_unique($result, SORT_LOCALE_STRING);
|
||||||
return $this->_group_users[$gid];
|
return $this->_group_users[$gid];
|
||||||
|
@ -185,12 +184,12 @@ class OC_GROUP_LDAP extends OC_Group_Backend {
|
||||||
* Returns a list with all groups
|
* Returns a list with all groups
|
||||||
*/
|
*/
|
||||||
public function getGroups() {
|
public function getGroups() {
|
||||||
if(!$this->configured) {
|
if(!$this->enabled) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
if(empty($this->_groups)) {
|
if(empty($this->_groups)) {
|
||||||
$ldap_groups = OC_LDAP::fetchListOfGroups($this->ldapGroupFilter, array(OC_LDAP::conf('ldapGroupDisplayName'), 'dn'));
|
$ldap_groups = $this->fetchListOfGroups($this->connection->ldapGroupFilter, array($this->connection->ldapGroupDisplayName, 'dn'));
|
||||||
$this->_groups = OC_LDAP::ownCloudGroupNames($ldap_groups);
|
$this->_groups = $this->ownCloudGroupNames($ldap_groups);
|
||||||
}
|
}
|
||||||
return $this->_groups;
|
return $this->_groups;
|
||||||
}
|
}
|
||||||
|
@ -203,4 +202,17 @@ class OC_GROUP_LDAP extends OC_Group_Backend {
|
||||||
public function groupExists($gid){
|
public function groupExists($gid){
|
||||||
return in_array($gid, $this->getGroups());
|
return in_array($gid, $this->getGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if backend implements actions
|
||||||
|
* @param $actions bitwise-or'ed actions
|
||||||
|
* @returns boolean
|
||||||
|
*
|
||||||
|
* Returns the supported actions as int to be
|
||||||
|
* compared with OC_USER_BACKEND_CREATE_USER etc.
|
||||||
|
*/
|
||||||
|
public function implementsActions($actions) {
|
||||||
|
//always returns false, because possible actions are modifying actions. We do not write to LDAP, at least for now.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,593 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud – LDAP Access
|
||||||
|
*
|
||||||
|
* @author Arthur Schiwon
|
||||||
|
* @copyright 2012 Arthur Schiwon blizzz@owncloud.com
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\user_ldap\lib;
|
||||||
|
|
||||||
|
abstract class Access {
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
public function setConnector(Connection &$connection) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkConnection() {
|
||||||
|
return ($this->connection instanceof Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief reads a given attribute for an LDAP record identified by a DN
|
||||||
|
* @param $dn the record in question
|
||||||
|
* @param $attr the attribute that shall be retrieved
|
||||||
|
* @returns the values in an array on success, false otherwise
|
||||||
|
*
|
||||||
|
* Reads an attribute from an LDAP entry
|
||||||
|
*/
|
||||||
|
public function readAttribute($dn, $attr) {
|
||||||
|
if(!$this->checkConnection()) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No LDAP Connector assigned, access impossible for readAttribute.', \OCP\Util::WARN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$cr = $this->connection->getConnectionResource();
|
||||||
|
$rr = @ldap_read($cr, $dn, 'objectClass=*', array($attr));
|
||||||
|
if(!is_resource($rr)) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'readAttribute failed for DN '.$dn, \OCP\Util::DEBUG);
|
||||||
|
//in case an error occurs , e.g. object does not exist
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$er = ldap_first_entry($cr, $rr);
|
||||||
|
//LDAP attributes are not case sensitive
|
||||||
|
$result = \OCP\Util::mb_array_change_key_case(ldap_get_attributes($cr, $er), MB_CASE_LOWER, 'UTF-8');
|
||||||
|
$attr = mb_strtolower($attr, 'UTF-8');
|
||||||
|
|
||||||
|
if(isset($result[$attr]) && $result[$attr]['count'] > 0) {
|
||||||
|
$values = array();
|
||||||
|
for($i=0;$i<$result[$attr]['count'];$i++) {
|
||||||
|
$values[] = $this->resemblesDN($attr) ? $this->sanitizeDN($result[$attr][$i]) : $result[$attr][$i];
|
||||||
|
}
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief checks wether the given attribute`s valua is probably a DN
|
||||||
|
* @param $attr the attribute in question
|
||||||
|
* @return if so true, otherwise false
|
||||||
|
*/
|
||||||
|
private function resemblesDN($attr) {
|
||||||
|
$resemblingAttributes = array(
|
||||||
|
'dn',
|
||||||
|
'uniquemember',
|
||||||
|
'member'
|
||||||
|
);
|
||||||
|
return in_array($attr, $resemblingAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sanitizes a DN received from the LDAP server
|
||||||
|
* @param $dn the DN in question
|
||||||
|
* @return the sanitized DN
|
||||||
|
*/
|
||||||
|
private function sanitizeDN($dn) {
|
||||||
|
//OID sometimes gives back DNs with whitespace after the comma a la "uid=foo, cn=bar, dn=..." We need to tackle this!
|
||||||
|
$dn = preg_replace('/([^\\\]),(\s+)/u', '\1,', $dn);
|
||||||
|
|
||||||
|
//make comparisons and everything work
|
||||||
|
$dn = mb_strtolower($dn, 'UTF-8');
|
||||||
|
|
||||||
|
return $dn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gives back the database table for the query
|
||||||
|
*/
|
||||||
|
private function getMapTable($isUser) {
|
||||||
|
if($isUser) {
|
||||||
|
return '*PREFIX*ldap_user_mapping';
|
||||||
|
} else {
|
||||||
|
return '*PREFIX*ldap_group_mapping';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the LDAP DN for the given internal ownCloud name of the group
|
||||||
|
* @param $name the ownCloud name in question
|
||||||
|
* @returns string with the LDAP DN on success, otherwise false
|
||||||
|
*
|
||||||
|
* returns the LDAP DN for the given internal ownCloud name of the group
|
||||||
|
*/
|
||||||
|
public function groupname2dn($name) {
|
||||||
|
return $this->ocname2dn($name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the LDAP DN for the given internal ownCloud name of the user
|
||||||
|
* @param $name the ownCloud name in question
|
||||||
|
* @returns string with the LDAP DN on success, otherwise false
|
||||||
|
*
|
||||||
|
* returns the LDAP DN for the given internal ownCloud name of the user
|
||||||
|
*/
|
||||||
|
public function username2dn($name) {
|
||||||
|
$dn = $this->ocname2dn($name, true);
|
||||||
|
if($dn) {
|
||||||
|
return $dn;
|
||||||
|
} else {
|
||||||
|
//fallback: user is not mapped
|
||||||
|
$filter = $this->combineFilterWithAnd(array(
|
||||||
|
$this->connection->ldapUserFilter,
|
||||||
|
$this->connection->ldapUserDisplayName . '=' . $name,
|
||||||
|
));
|
||||||
|
$result = $this->searchUsers($filter, 'dn');
|
||||||
|
if(isset($result[0]['dn'])) {
|
||||||
|
$this->mapComponent($result[0], $name, true);
|
||||||
|
return $result[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the LDAP DN for the given internal ownCloud name
|
||||||
|
* @param $name the ownCloud name in question
|
||||||
|
* @param $isUser is it a user? otherwise group
|
||||||
|
* @returns string with the LDAP DN on success, otherwise false
|
||||||
|
*
|
||||||
|
* returns the LDAP DN for the given internal ownCloud name
|
||||||
|
*/
|
||||||
|
private function ocname2dn($name, $isUser) {
|
||||||
|
$table = $this->getMapTable($isUser);
|
||||||
|
|
||||||
|
$query = \OCP\DB::prepare('
|
||||||
|
SELECT ldap_dn
|
||||||
|
FROM '.$table.'
|
||||||
|
WHERE owncloud_name = ?
|
||||||
|
');
|
||||||
|
|
||||||
|
$record = $query->execute(array($name))->fetchOne();
|
||||||
|
return $record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the internal ownCloud name for the given LDAP DN of the group
|
||||||
|
* @param $dn the dn of the group object
|
||||||
|
* @param $ldapname optional, the display name of the object
|
||||||
|
* @returns string with with the name to use in ownCloud, false on DN outside of search DN
|
||||||
|
*
|
||||||
|
* returns the internal ownCloud name for the given LDAP DN of the group
|
||||||
|
*/
|
||||||
|
public function dn2groupname($dn, $ldapname = null) {
|
||||||
|
if(mb_strripos($dn, $this->connection->ldapBaseGroups, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen($this->connection->ldapBaseGroups, 'UTF-8'))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->dn2ocname($dn, $ldapname, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the internal ownCloud name for the given LDAP DN of the user
|
||||||
|
* @param $dn the dn of the user object
|
||||||
|
* @param $ldapname optional, the display name of the object
|
||||||
|
* @returns string with with the name to use in ownCloud
|
||||||
|
*
|
||||||
|
* returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN
|
||||||
|
*/
|
||||||
|
public function dn2username($dn, $ldapname = null) {
|
||||||
|
if(mb_strripos($dn, $this->connection->ldapBaseUsers, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen($this->connection->ldapBaseUsers, 'UTF-8'))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->dn2ocname($dn, $ldapname, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns an internal ownCloud name for the given LDAP DN
|
||||||
|
* @param $dn the dn of the user object
|
||||||
|
* @param $ldapname optional, the display name of the object
|
||||||
|
* @param $isUser optional, wether it is a user object (otherwise group assumed)
|
||||||
|
* @returns string with with the name to use in ownCloud
|
||||||
|
*
|
||||||
|
* returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN
|
||||||
|
*/
|
||||||
|
public function dn2ocname($dn, $ldapname = null, $isUser = true) {
|
||||||
|
$dn = $this->sanitizeDN($dn);
|
||||||
|
$table = $this->getMapTable($isUser);
|
||||||
|
if($isUser) {
|
||||||
|
$nameAttribute = $this->connection->ldapUserDisplayName;
|
||||||
|
} else {
|
||||||
|
$nameAttribute = $this->connection->ldapGroupDisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = \OCP\DB::prepare('
|
||||||
|
SELECT owncloud_name
|
||||||
|
FROM '.$table.'
|
||||||
|
WHERE ldap_dn = ?
|
||||||
|
');
|
||||||
|
|
||||||
|
$component = $query->execute(array($dn))->fetchOne();
|
||||||
|
if($component) {
|
||||||
|
return $component;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_null($ldapname)) {
|
||||||
|
$ldapname = $this->readAttribute($dn, $nameAttribute);
|
||||||
|
$ldapname = $ldapname[0];
|
||||||
|
}
|
||||||
|
$ldapname = $this->sanitizeUsername($ldapname);
|
||||||
|
|
||||||
|
//a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot.
|
||||||
|
if($this->mapComponent($dn, $ldapname, $isUser)) {
|
||||||
|
return $ldapname;
|
||||||
|
}
|
||||||
|
|
||||||
|
//doh! There is a conflict. We need to distinguish between users/groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this object is located.
|
||||||
|
$oc_name = $this->alternateOwnCloudName($ldapname, $dn);
|
||||||
|
if($this->mapComponent($dn, $oc_name, $isUser)) {
|
||||||
|
return $oc_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: do not simple die away!
|
||||||
|
//and this of course should never been thrown :)
|
||||||
|
throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief gives back the user names as they are used ownClod internally
|
||||||
|
* @param $ldapGroups an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... )
|
||||||
|
* @returns an array with the user names to use in ownCloud
|
||||||
|
*
|
||||||
|
* gives back the user names as they are used ownClod internally
|
||||||
|
*/
|
||||||
|
public function ownCloudUserNames($ldapUsers) {
|
||||||
|
return $this->ldap2ownCloudNames($ldapUsers, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief gives back the group names as they are used ownClod internally
|
||||||
|
* @param $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... )
|
||||||
|
* @returns an array with the group names to use in ownCloud
|
||||||
|
*
|
||||||
|
* gives back the group names as they are used ownClod internally
|
||||||
|
*/
|
||||||
|
public function ownCloudGroupNames($ldapGroups) {
|
||||||
|
return $this->ldap2ownCloudNames($ldapGroups, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function ldap2ownCloudNames($ldapObjects, $isUsers) {
|
||||||
|
if($isUsers) {
|
||||||
|
$knownObjects = $this->mappedUsers();
|
||||||
|
$nameAttribute = $this->connection->ldapUserDisplayName;
|
||||||
|
} else {
|
||||||
|
$knownObjects = $this->mappedGroups();
|
||||||
|
$nameAttribute = $this->connection->ldapGroupDisplayName;
|
||||||
|
}
|
||||||
|
$ownCloudNames = array();
|
||||||
|
|
||||||
|
foreach($ldapObjects as $ldapObject) {
|
||||||
|
$key = \OCP\Util::recursiveArraySearch($knownObjects, $ldapObject['dn']);
|
||||||
|
|
||||||
|
//everything is fine when we know the group
|
||||||
|
if($key !== false) {
|
||||||
|
$ownCloudNames[] = $knownObjects[$key]['owncloud_name'];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//a new group! Then let's try to add it. We're shooting into the blue with the group name, assuming that in most cases there will not be a conflict. But first make sure, that the display name contains only allowed characters.
|
||||||
|
$ocname = $this->sanitizeUsername($ldapObject[$nameAttribute]);
|
||||||
|
if($this->mapComponent($ldapObject['dn'], $ocname, $isUsers)) {
|
||||||
|
$ownCloudNames[] = $ocname;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//doh! There is a conflict. We need to distinguish between groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this entry is located.
|
||||||
|
$ocname = $this->alternateOwnCloudName($ocname, $ldapObject['dn']);
|
||||||
|
if($this->mapComponent($ldapObject['dn'], $ocname, $isUsers)) {
|
||||||
|
$ownCloudNames[] = $ocname;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: do not simple die away
|
||||||
|
//and this of course should never been thrown :)
|
||||||
|
throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.');
|
||||||
|
}
|
||||||
|
return $ownCloudNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object
|
||||||
|
* @param $name the display name of the object
|
||||||
|
* @param $dn the dn of the object
|
||||||
|
* @returns string with with the name to use in ownCloud
|
||||||
|
*
|
||||||
|
* creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object
|
||||||
|
*/
|
||||||
|
private function alternateOwnCloudName($name, $dn) {
|
||||||
|
$ufn = ldap_dn2ufn($dn);
|
||||||
|
$name = $name . '@' . trim(\OCP\Util::mb_substr_replace($ufn, '', 0, mb_strpos($ufn, ',', 0, 'UTF-8'), 'UTF-8'));
|
||||||
|
$name = $this->sanitizeUsername($name);
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief retrieves all known groups from the mappings table
|
||||||
|
* @returns array with the results
|
||||||
|
*
|
||||||
|
* retrieves all known groups from the mappings table
|
||||||
|
*/
|
||||||
|
private function mappedGroups() {
|
||||||
|
return $this->mappedComponents(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief retrieves all known users from the mappings table
|
||||||
|
* @returns array with the results
|
||||||
|
*
|
||||||
|
* retrieves all known users from the mappings table
|
||||||
|
*/
|
||||||
|
private function mappedUsers() {
|
||||||
|
return $this->mappedComponents(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mappedComponents($isUsers) {
|
||||||
|
$table = $this->getMapTable($isUsers);
|
||||||
|
|
||||||
|
$query = \OCP\DB::prepare('
|
||||||
|
SELECT ldap_dn, owncloud_name
|
||||||
|
FROM '. $table
|
||||||
|
);
|
||||||
|
|
||||||
|
return $query->execute()->fetchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief inserts a new user or group into the mappings table
|
||||||
|
* @param $dn the record in question
|
||||||
|
* @param $ocname the name to use in ownCloud
|
||||||
|
* @param $isUser is it a user or a group?
|
||||||
|
* @returns true on success, false otherwise
|
||||||
|
*
|
||||||
|
* inserts a new user or group into the mappings table
|
||||||
|
*/
|
||||||
|
private function mapComponent($dn, $ocname, $isUser = true) {
|
||||||
|
$table = $this->getMapTable($isUser);
|
||||||
|
$dn = $this->sanitizeDN($dn);
|
||||||
|
|
||||||
|
$sqlAdjustment = '';
|
||||||
|
$dbtype = \OCP\Config::getSystemValue('dbtype');
|
||||||
|
if($dbtype == 'mysql') {
|
||||||
|
$sqlAdjustment = 'FROM dual';
|
||||||
|
}
|
||||||
|
|
||||||
|
$insert = \OCP\DB::prepare('
|
||||||
|
INSERT INTO '.$table.' (ldap_dn, owncloud_name)
|
||||||
|
SELECT ?,?
|
||||||
|
'.$sqlAdjustment.'
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM '.$table.'
|
||||||
|
WHERE ldap_dn = ?
|
||||||
|
OR owncloud_name = ? )
|
||||||
|
');
|
||||||
|
|
||||||
|
$res = $insert->execute(array($dn, $ocname, $dn, $ocname));
|
||||||
|
|
||||||
|
if(\OCP\DB::isError($res)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$insRows = $res->numRows();
|
||||||
|
|
||||||
|
if($insRows == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchListOfUsers($filter, $attr) {
|
||||||
|
return $this->fetchList($this->searchUsers($filter, $attr), (count($attr) > 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchListOfGroups($filter, $attr) {
|
||||||
|
return $this->fetchList($this->searchGroups($filter, $attr), (count($attr) > 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchList($list, $manyAttributes) {
|
||||||
|
if(is_array($list)) {
|
||||||
|
if($manyAttributes) {
|
||||||
|
return $list;
|
||||||
|
} else {
|
||||||
|
return array_unique($list, SORT_LOCALE_STRING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//error cause actually, maybe throw an exception in future.
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief executes an LDAP search, optimized for Users
|
||||||
|
* @param $filter the LDAP filter for the search
|
||||||
|
* @param $attr optional, when a certain attribute shall be filtered out
|
||||||
|
* @returns array with the search result
|
||||||
|
*
|
||||||
|
* Executes an LDAP search
|
||||||
|
*/
|
||||||
|
public function searchUsers($filter, $attr = null) {
|
||||||
|
return $this->search($filter, $this->connection->ldapBaseUsers, $attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief executes an LDAP search, optimized for Groups
|
||||||
|
* @param $filter the LDAP filter for the search
|
||||||
|
* @param $attr optional, when a certain attribute shall be filtered out
|
||||||
|
* @returns array with the search result
|
||||||
|
*
|
||||||
|
* Executes an LDAP search
|
||||||
|
*/
|
||||||
|
public function searchGroups($filter, $attr = null) {
|
||||||
|
return $this->search($filter, $this->connection->ldapBaseGroups, $attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief executes an LDAP search
|
||||||
|
* @param $filter the LDAP filter for the search
|
||||||
|
* @param $base the LDAP subtree that shall be searched
|
||||||
|
* @param $attr optional, when a certain attribute shall be filtered out
|
||||||
|
* @returns array with the search result
|
||||||
|
*
|
||||||
|
* Executes an LDAP search
|
||||||
|
*/
|
||||||
|
private function search($filter, $base, $attr = null) {
|
||||||
|
if(!is_null($attr) && !is_array($attr)) {
|
||||||
|
$attr = array(mb_strtolower($attr, 'UTF-8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we have a resource
|
||||||
|
$link_resource = $this->connection->getConnectionResource();
|
||||||
|
if(is_resource($link_resource)) {
|
||||||
|
$sr = ldap_search($link_resource, $base, $filter, $attr);
|
||||||
|
$findings = ldap_get_entries($link_resource, $sr );
|
||||||
|
|
||||||
|
// if we're here, probably no connection resource is returned.
|
||||||
|
// to make ownCloud behave nicely, we simply give back an empty array.
|
||||||
|
if(is_null($findings)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Seems like we didn't find any resource.
|
||||||
|
// Return an empty array just like before.
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Could not search, because resource is missing.', \OCP\Util::DEBUG);
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_null($attr)) {
|
||||||
|
$selection = array();
|
||||||
|
$multiarray = false;
|
||||||
|
if(count($attr) > 1) {
|
||||||
|
$multiarray = true;
|
||||||
|
$i = 0;
|
||||||
|
}
|
||||||
|
foreach($findings as $item) {
|
||||||
|
if(!is_array($item)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$item = \OCP\Util::mb_array_change_key_case($item, MB_CASE_LOWER, 'UTF-8');
|
||||||
|
|
||||||
|
if($multiarray) {
|
||||||
|
foreach($attr as $key) {
|
||||||
|
$key = mb_strtolower($key, 'UTF-8');
|
||||||
|
if(isset($item[$key])) {
|
||||||
|
if($key != 'dn') {
|
||||||
|
$selection[$i][$key] = $this->resemblesDN($key) ? $this->sanitizeDN($item[$key][0]) : $item[$key][0];
|
||||||
|
} else {
|
||||||
|
$selection[$i][$key] = $this->sanitizeDN($item[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
} else {
|
||||||
|
//tribute to case insensitivity
|
||||||
|
$key = mb_strtolower($attr[0], 'UTF-8');
|
||||||
|
|
||||||
|
if(isset($item[$key])) {
|
||||||
|
if($this->resemblesDN($key)) {
|
||||||
|
$selection[] = $this->sanitizeDN($item[$key]);
|
||||||
|
} else {
|
||||||
|
$selection[] = $item[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $selection;
|
||||||
|
}
|
||||||
|
return $findings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sanitizeUsername($name) {
|
||||||
|
if($this->connection->ldapIgnoreNamingRules) {
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//REPLACEMENTS
|
||||||
|
$name = \OCP\Util::mb_str_replace(' ', '_', $name, 'UTF-8');
|
||||||
|
|
||||||
|
//every remaining unallowed characters will be removed
|
||||||
|
$name = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $name);
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief combines the input filters with AND
|
||||||
|
* @param $filters array, the filters to connect
|
||||||
|
* @returns the combined filter
|
||||||
|
*
|
||||||
|
* Combines Filter arguments with AND
|
||||||
|
*/
|
||||||
|
public function combineFilterWithAnd($filters) {
|
||||||
|
return $this->combineFilter($filters, '&');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief combines the input filters with AND
|
||||||
|
* @param $filters array, the filters to connect
|
||||||
|
* @returns the combined filter
|
||||||
|
*
|
||||||
|
* Combines Filter arguments with AND
|
||||||
|
*/
|
||||||
|
public function combineFilterWithOr($filters) {
|
||||||
|
return $this->combineFilter($filters, '|');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief combines the input filters with given operator
|
||||||
|
* @param $filters array, the filters to connect
|
||||||
|
* @param $operator either & or |
|
||||||
|
* @returns the combined filter
|
||||||
|
*
|
||||||
|
* Combines Filter arguments with AND
|
||||||
|
*/
|
||||||
|
private function combineFilter($filters, $operator) {
|
||||||
|
$combinedFilter = '('.$operator;
|
||||||
|
foreach($filters as $filter) {
|
||||||
|
if($filter[0] != '(') {
|
||||||
|
$filter = '('.$filter.')';
|
||||||
|
}
|
||||||
|
$combinedFilter.=$filter;
|
||||||
|
}
|
||||||
|
$combinedFilter.=')';
|
||||||
|
return $combinedFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function areCredentialsValid($name, $password) {
|
||||||
|
$testConnection = clone $this->connection;
|
||||||
|
$credentials = array(
|
||||||
|
'ldapAgentName' => $name,
|
||||||
|
'ldapAgentPassword' => $password
|
||||||
|
);
|
||||||
|
if(!$testConnection->setConfiguration($credentials)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $testConnection->bind();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,245 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud – LDAP Access
|
||||||
|
*
|
||||||
|
* @author Arthur Schiwon
|
||||||
|
* @copyright 2012 Arthur Schiwon blizzz@owncloud.com
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\user_ldap\lib;
|
||||||
|
|
||||||
|
class Connection {
|
||||||
|
private $ldapConnectionRes = null;
|
||||||
|
private $configID;
|
||||||
|
private $configured = false;
|
||||||
|
|
||||||
|
//cached settings
|
||||||
|
protected $config = array(
|
||||||
|
'ldapHost' => null,
|
||||||
|
'ldapPort' => null,
|
||||||
|
'ldapBase' => null,
|
||||||
|
'ldapBaseUsers' => null,
|
||||||
|
'ldapBaseGroups' => null,
|
||||||
|
'ldapAgentName' => null,
|
||||||
|
'ldapAgentPassword' => null,
|
||||||
|
'ldapTLS' => null,
|
||||||
|
'ldapNoCase' => null,
|
||||||
|
'ldapIgnoreNamingRules' => null,
|
||||||
|
'ldapUserDisplayName' => null,
|
||||||
|
'ldapUserFilter' => null,
|
||||||
|
'ldapGroupFilter' => null,
|
||||||
|
'ldapGroupDisplayName' => null,
|
||||||
|
'ldapLoginFilter' => null,
|
||||||
|
'ldapQuotaAttribute' => null,
|
||||||
|
'ldapQuotaDefault' => null,
|
||||||
|
'ldapEmailAttribute' => null,
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct($configID = 'user_ldap') {
|
||||||
|
$this->configID = $configID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
@ldap_unbind($this->ldapConnectionRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __get($name) {
|
||||||
|
if(!$this->configured) {
|
||||||
|
$this->readConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($this->config[$name])) {
|
||||||
|
return $this->config[$name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief initializes the LDAP backend
|
||||||
|
* @param $force read the config settings no matter what
|
||||||
|
*
|
||||||
|
* initializes the LDAP backend
|
||||||
|
*/
|
||||||
|
public function init($force = false) {
|
||||||
|
$this->readConfiguration($force);
|
||||||
|
$this->establishConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the LDAP handler
|
||||||
|
*/
|
||||||
|
public function getConnectionResource() {
|
||||||
|
if(!$this->ldapConnectionRes) {
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
|
if(is_null($this->ldapConnectionRes)) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Connection could not be established', \OCP\Util::ERROR);
|
||||||
|
}
|
||||||
|
return $this->ldapConnectionRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches the general LDAP configuration.
|
||||||
|
*/
|
||||||
|
private function readConfiguration($force = false) {
|
||||||
|
\OCP\Util::writeLog('user_ldap','Checking conf state: isConfigured? '.print_r($this->configured, true).' isForce? '.print_r($force, true).' configID? '.print_r($this->configID, true), \OCP\Util::DEBUG);
|
||||||
|
if((!$this->configured || $force) && !is_null($this->configID)) {
|
||||||
|
\OCP\Util::writeLog('user_ldap','Reading the configuration', \OCP\Util::DEBUG);
|
||||||
|
$this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, 'ldap_host', '');
|
||||||
|
$this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, 'ldap_port', 389);
|
||||||
|
$this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, 'ldap_dn','');
|
||||||
|
$this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, 'ldap_agent_password',''));
|
||||||
|
$this->config['ldapBase'] = \OCP\Config::getAppValue($this->configID, 'ldap_base', '');
|
||||||
|
$this->config['ldapBaseUsers'] = \OCP\Config::getAppValue($this->configID, 'ldap_base_users',$this->config['ldapBase']);
|
||||||
|
$this->config['ldapBaseGroups'] = \OCP\Config::getAppValue($this->configID, 'ldap_base_groups', $this->config['ldapBase']);
|
||||||
|
$this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, 'ldap_tls',0);
|
||||||
|
$this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, 'ldap_nocase', 0);
|
||||||
|
$this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_display_name', 'uid'), 'UTF-8');
|
||||||
|
$this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_userlist_filter','objectClass=person');
|
||||||
|
$this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_filter','(objectClass=posixGroup)');
|
||||||
|
$this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_login_filter', '(uid=%uid)');
|
||||||
|
$this->config['ldapGroupDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_group_display_name', 'uid'), 'UTF-8');
|
||||||
|
$this->config['ldapQuotaAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_attr', '');
|
||||||
|
$this->config['ldapQuotaDefault'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_def', '');
|
||||||
|
$this->config['ldapEmailAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_email_attr', '');
|
||||||
|
$this->config['ldapGroupMemberAssocAttr'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_member_assoc_attribute', 'uniqueMember');
|
||||||
|
$this->config['ldapIgnoreNamingRules'] = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false);
|
||||||
|
|
||||||
|
$this->configured = $this->validateConfiguration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set LDAP configuration with values delivered by an array, not read from configuration
|
||||||
|
* @param $config array that holds the config parameters in an associated array
|
||||||
|
* @param &$setParameters optional; array where the set fields will be given to
|
||||||
|
* @return true if config validates, false otherwise. Check with $setParameters for detailed success on single parameters
|
||||||
|
*/
|
||||||
|
public function setConfiguration($config, &$setParameters = null) {
|
||||||
|
if(!is_array($config)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($config as $parameter => $value) {
|
||||||
|
if(isset($this->config[$parameter])) {
|
||||||
|
$this->config[$parameter] = $value;
|
||||||
|
if(is_array($setParameters)) {
|
||||||
|
$setParameters[] = $parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->configured = $this->validateConfiguration();
|
||||||
|
|
||||||
|
return $this->configured;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validates the user specified configuration
|
||||||
|
* @returns true if configuration seems OK, false otherwise
|
||||||
|
*/
|
||||||
|
private function validateConfiguration() {
|
||||||
|
//first step: "soft" checks: settings that are not really necessary, but advisable. If left empty, give an info message
|
||||||
|
if(empty($this->config['ldapBaseUsers'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Base tree for Users is empty, using Base DN', \OCP\Util::INFO);
|
||||||
|
$this->config['ldapBaseUsers'] = $this->config['ldapBase'];
|
||||||
|
}
|
||||||
|
if(empty($this->config['ldapBaseGroups'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Base tree for Groups is empty, using Base DN', \OCP\Util::INFO);
|
||||||
|
$this->config['ldapBaseGroups'] = $this->config['ldapBase'];
|
||||||
|
}
|
||||||
|
if(empty($this->config['ldapGroupFilter']) && empty($this->config['ldapGroupMemberAssocAttr'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No group filter is specified, LDAP group feature will not be used.', \OCP\Util::INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
//second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning.
|
||||||
|
$configurationOK = true;
|
||||||
|
if(empty($this->config['ldapHost'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No LDAP host given, won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
if(empty($this->config['ldapPort'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No LDAP Port given, won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
if((empty($this->config['ldapAgentName']) && !empty($this->config['ldapAgentPassword']))
|
||||||
|
|| (!empty($this->config['ldapAgentName']) && empty($this->config['ldapAgentPassword']))) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Either no password given for the user agent or a password is given, but no LDAP agent; won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
//TODO: check if ldapAgentName is in DN form
|
||||||
|
if(empty($this->config['ldapBase']) && (empty($this->config['ldapBaseUsers']) && empty($this->config['ldapBaseGroups']))) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No Base DN given, won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
if(empty($this->config['ldapUserDisplayName'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No user display name attribute specified, won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
if(empty($this->config['ldapGroupDisplayName'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No group display name attribute specified, won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
if(empty($this->config['ldapLoginFilter'])) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'No login filter specified, won`t connect.', \OCP\Util::WARN);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
if(mb_strpos($this->config['ldapLoginFilter'], '%uid', 0, 'UTF-8') === false) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Login filter does not contain %uid place holder, won`t connect.', \OCP\Util::WARN);
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Login filter was ' . $this->config['ldapLoginFilter'], \OCP\Util::DEBUG);
|
||||||
|
$configurationOK = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $configurationOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects and Binds to LDAP
|
||||||
|
*/
|
||||||
|
private function establishConnection() {
|
||||||
|
if(!$this->configured) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Configuration is invalid, cannot connect', \OCP\Util::WARN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!$this->ldapConnectionRes) {
|
||||||
|
$this->ldapConnectionRes = ldap_connect($this->config['ldapHost'], $this->config['ldapPort']);
|
||||||
|
if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
|
||||||
|
if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
|
||||||
|
if($this->config['ldapTLS']) {
|
||||||
|
ldap_start_tls($this->ldapConnectionRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds to LDAP
|
||||||
|
*/
|
||||||
|
public function bind() {
|
||||||
|
$ldapLogin = @ldap_bind($this->getConnectionResource(), $this->config['ldapAgentName'], $this->config['ldapAgentPassword']);
|
||||||
|
if(!$ldapLogin) {
|
||||||
|
\OCP\Util::writeLog('user_ldap', 'Bind failed: ' . ldap_errno($this->ldapConnectionRes) . ': ' . ldap_error($this->ldapConnectionRes), \OCP\Util::ERROR);
|
||||||
|
$this->ldapConnectionRes = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,721 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ownCloud – LDAP lib
|
|
||||||
*
|
|
||||||
* @author Arthur Schiwon
|
|
||||||
* @copyright 2012 Arthur Schiwon blizzz@owncloud.com
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public
|
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
define('LDAP_GROUP_MEMBER_ASSOC_ATTR','uniqueMember');
|
|
||||||
define('LDAP_GROUP_DISPLAY_NAME_ATTR','cn');
|
|
||||||
|
|
||||||
//needed to unbind, because we use OC_LDAP only statically
|
|
||||||
class OC_LDAP_DESTRUCTOR {
|
|
||||||
public function __destruct() {
|
|
||||||
OC_LDAP::destruct();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OC_LDAP {
|
|
||||||
static protected $ldapConnectionRes = false;
|
|
||||||
static protected $configured = false;
|
|
||||||
|
|
||||||
//cached settings
|
|
||||||
static protected $ldapHost;
|
|
||||||
static protected $ldapPort;
|
|
||||||
static protected $ldapBase;
|
|
||||||
static protected $ldapBaseUsers;
|
|
||||||
static protected $ldapBaseGroups;
|
|
||||||
static protected $ldapAgentName;
|
|
||||||
static protected $ldapAgentPassword;
|
|
||||||
static protected $ldapTLS;
|
|
||||||
static protected $ldapNoCase;
|
|
||||||
static protected $ldapIgnoreNamingRules;
|
|
||||||
// user and group settings, that are needed in both backends
|
|
||||||
static protected $ldapUserDisplayName;
|
|
||||||
static protected $ldapUserFilter;
|
|
||||||
static protected $ldapGroupDisplayName;
|
|
||||||
static protected $ldapLoginFilter;
|
|
||||||
|
|
||||||
static protected $__d;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief initializes the LDAP backend
|
|
||||||
* @param $force read the config settings no matter what
|
|
||||||
*
|
|
||||||
* initializes the LDAP backend
|
|
||||||
*/
|
|
||||||
static public function init($force = false) {
|
|
||||||
if(is_null(self::$__d)) {
|
|
||||||
self::$__d = new OC_LDAP_DESTRUCTOR();
|
|
||||||
}
|
|
||||||
self::readConfiguration($force);
|
|
||||||
self::establishConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function destruct() {
|
|
||||||
@ldap_unbind(self::$ldapConnectionRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns a read-only configuration value
|
|
||||||
* @param $key the name of the configuration value
|
|
||||||
* @returns the value on success, otherwise null
|
|
||||||
*
|
|
||||||
* returns a read-only configuration values
|
|
||||||
*
|
|
||||||
* we cannot work with getters, because it is a static class
|
|
||||||
*/
|
|
||||||
static public function conf($key) {
|
|
||||||
if(!self::$configured) {
|
|
||||||
self::init();
|
|
||||||
}
|
|
||||||
|
|
||||||
$availableProperties = array(
|
|
||||||
'ldapUserDisplayName',
|
|
||||||
'ldapGroupDisplayName',
|
|
||||||
'ldapLoginFilter'
|
|
||||||
);
|
|
||||||
|
|
||||||
if(in_array($key, $availableProperties)) {
|
|
||||||
return self::$$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gives back the database table for the query
|
|
||||||
*/
|
|
||||||
static private function getMapTable($isUser) {
|
|
||||||
if($isUser) {
|
|
||||||
return '*PREFIX*ldap_user_mapping';
|
|
||||||
} else {
|
|
||||||
return '*PREFIX*ldap_group_mapping';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns the LDAP DN for the given internal ownCloud name of the group
|
|
||||||
* @param $name the ownCloud name in question
|
|
||||||
* @returns string with the LDAP DN on success, otherwise false
|
|
||||||
*
|
|
||||||
* returns the LDAP DN for the given internal ownCloud name of the group
|
|
||||||
*/
|
|
||||||
static public function groupname2dn($name) {
|
|
||||||
return self::ocname2dn($name, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns the LDAP DN for the given internal ownCloud name of the user
|
|
||||||
* @param $name the ownCloud name in question
|
|
||||||
* @returns string with the LDAP DN on success, otherwise false
|
|
||||||
*
|
|
||||||
* returns the LDAP DN for the given internal ownCloud name of the user
|
|
||||||
*/
|
|
||||||
static public function username2dn($name) {
|
|
||||||
$dn = self::ocname2dn($name, true);
|
|
||||||
if($dn) {
|
|
||||||
return $dn;
|
|
||||||
} else {
|
|
||||||
//fallback: user is not mapped
|
|
||||||
self::init();
|
|
||||||
$filter = self::combineFilterWithAnd(array(
|
|
||||||
self::$ldapUserFilter,
|
|
||||||
self::$ldapUserDisplayName . '=' . $name,
|
|
||||||
));
|
|
||||||
$result = self::searchUsers($filter, 'dn');
|
|
||||||
if(isset($result[0]['dn'])) {
|
|
||||||
self::mapUser($result[0], $name);
|
|
||||||
return $result[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function ocname2dn($name, $isUser) {
|
|
||||||
$table = self::getMapTable($isUser);
|
|
||||||
|
|
||||||
$query = OCP\DB::prepare('
|
|
||||||
SELECT ldap_dn
|
|
||||||
FROM '.$table.'
|
|
||||||
WHERE owncloud_name = ?
|
|
||||||
');
|
|
||||||
|
|
||||||
$record = $query->execute(array($name))->fetchOne();
|
|
||||||
return $record;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns the internal ownCloud name for the given LDAP DN of the group
|
|
||||||
* @param $dn the dn of the group object
|
|
||||||
* @param $ldapname optional, the display name of the object
|
|
||||||
* @returns string with with the name to use in ownCloud, false on DN outside of search DN
|
|
||||||
*
|
|
||||||
* returns the internal ownCloud name for the given LDAP DN of the group
|
|
||||||
*/
|
|
||||||
static public function dn2groupname($dn, $ldapname = null) {
|
|
||||||
if(mb_strripos($dn, self::$ldapBaseGroups, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen(self::$ldapBaseGroups, 'UTF-8'))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return self::dn2ocname($dn, $ldapname, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns the internal ownCloud name for the given LDAP DN of the user
|
|
||||||
* @param $dn the dn of the user object
|
|
||||||
* @param $ldapname optional, the display name of the object
|
|
||||||
* @returns string with with the name to use in ownCloud
|
|
||||||
*
|
|
||||||
* returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN
|
|
||||||
*/
|
|
||||||
static public function dn2username($dn, $ldapname = null) {
|
|
||||||
if(mb_strripos($dn, self::$ldapBaseUsers, 0, 'UTF-8') !== (mb_strlen($dn, 'UTF-8')-mb_strlen(self::$ldapBaseUsers, 'UTF-8'))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return self::dn2ocname($dn, $ldapname, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function dn2ocname($dn, $ldapname = null, $isUser = true) {
|
|
||||||
$dn = self::sanitizeDN($dn);
|
|
||||||
$table = self::getMapTable($isUser);
|
|
||||||
if($isUser) {
|
|
||||||
$nameAttribute = self::conf('ldapUserDisplayName');
|
|
||||||
} else {
|
|
||||||
$nameAttribute = self::conf('ldapGroupDisplayName');
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = OCP\DB::prepare('
|
|
||||||
SELECT owncloud_name
|
|
||||||
FROM '.$table.'
|
|
||||||
WHERE ldap_dn = ?
|
|
||||||
');
|
|
||||||
|
|
||||||
$component = $query->execute(array($dn))->fetchOne();
|
|
||||||
if($component) {
|
|
||||||
return $component;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_null($ldapname)) {
|
|
||||||
$ldapname = self::readAttribute($dn, $nameAttribute);
|
|
||||||
$ldapname = $ldapname[0];
|
|
||||||
}
|
|
||||||
$ldapname = self::sanitizeUsername($ldapname);
|
|
||||||
|
|
||||||
//a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot.
|
|
||||||
if(self::mapComponent($dn, $ldapname, $isUser)) {
|
|
||||||
return $ldapname;
|
|
||||||
}
|
|
||||||
|
|
||||||
//doh! There is a conflict. We need to distinguish between users/groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this object is located.
|
|
||||||
$oc_name = self::alternateOwnCloudName($ldapname, $dn);
|
|
||||||
if(self::mapComponent($dn, $oc_name, $isUser)) {
|
|
||||||
return $oc_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
//and this of course should never been thrown :)
|
|
||||||
throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief gives back the user names as they are used ownClod internally
|
|
||||||
* @param $ldapGroups an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... )
|
|
||||||
* @returns an array with the user names to use in ownCloud
|
|
||||||
*
|
|
||||||
* gives back the user names as they are used ownClod internally
|
|
||||||
*/
|
|
||||||
static public function ownCloudUserNames($ldapUsers) {
|
|
||||||
return self::ldap2ownCloudNames($ldapUsers, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief gives back the group names as they are used ownClod internally
|
|
||||||
* @param $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... )
|
|
||||||
* @returns an array with the group names to use in ownCloud
|
|
||||||
*
|
|
||||||
* gives back the group names as they are used ownClod internally
|
|
||||||
*/
|
|
||||||
static public function ownCloudGroupNames($ldapGroups) {
|
|
||||||
return self::ldap2ownCloudNames($ldapGroups, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function ldap2ownCloudNames($ldapObjects, $isUsers) {
|
|
||||||
if($isUsers) {
|
|
||||||
$knownObjects = self::mappedUsers();
|
|
||||||
$nameAttribute = self::conf('ldapUserDisplayName');
|
|
||||||
} else {
|
|
||||||
$knownObjects = self::mappedGroups();
|
|
||||||
$nameAttribute = self::conf('ldapGroupDisplayName');
|
|
||||||
}
|
|
||||||
$ownCloudNames = array();
|
|
||||||
|
|
||||||
foreach($ldapObjects as $ldapObject) {
|
|
||||||
$key = self::recursiveArraySearch($knownObjects, $ldapObject['dn']);
|
|
||||||
|
|
||||||
//everything is fine when we know the group
|
|
||||||
if($key !== false) {
|
|
||||||
$ownCloudNames[] = $knownObjects[$key]['owncloud_name'];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//a new group! Then let's try to add it. We're shooting into the blue with the group name, assuming that in most cases there will not be a conflict. But first make sure, that the display name contains only allowed characters.
|
|
||||||
$ocname = self::sanitizeUsername($ldapObject[$nameAttribute]);
|
|
||||||
if(self::mapComponent($ldapObject['dn'], $ocname, $isUsers)) {
|
|
||||||
$ownCloudNames[] = $ocname;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//doh! There is a conflict. We need to distinguish between groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this entry is located.
|
|
||||||
$ocname = self::alternateOwnCloudName($ocname, $ldapObject['dn']);
|
|
||||||
if(self::mapComponent($ldapObject['dn'], $ocname, $isUsers)) {
|
|
||||||
$ownCloudNames[] = $ocname;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//and this of course should never been thrown :)
|
|
||||||
throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.');
|
|
||||||
}
|
|
||||||
return $ownCloudNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object
|
|
||||||
* @param $name the display name of the object
|
|
||||||
* @param $dn the dn of the object
|
|
||||||
* @returns string with with the name to use in ownCloud
|
|
||||||
*
|
|
||||||
* creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object
|
|
||||||
*/
|
|
||||||
static private function alternateOwnCloudName($name, $dn) {
|
|
||||||
$ufn = ldap_dn2ufn($dn);
|
|
||||||
$name = $name . '@' . trim(OCP\Util::mb_substr_replace($ufn, '', 0, mb_strpos($ufn, ',', 0, 'UTF-8'), 'UTF-8'));
|
|
||||||
$name = self::sanitizeUsername($name);
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief retrieves all known groups from the mappings table
|
|
||||||
* @returns array with the results
|
|
||||||
*
|
|
||||||
* retrieves all known groups from the mappings table
|
|
||||||
*/
|
|
||||||
static private function mappedGroups() {
|
|
||||||
return self::mappedComponents(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief retrieves all known users from the mappings table
|
|
||||||
* @returns array with the results
|
|
||||||
*
|
|
||||||
* retrieves all known users from the mappings table
|
|
||||||
*/
|
|
||||||
static private function mappedUsers() {
|
|
||||||
return self::mappedComponents(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function mappedComponents($isUsers) {
|
|
||||||
$table = self::getMapTable($isUsers);
|
|
||||||
|
|
||||||
$query = OCP\DB::prepare('
|
|
||||||
SELECT ldap_dn, owncloud_name
|
|
||||||
FROM '. $table
|
|
||||||
);
|
|
||||||
|
|
||||||
return $query->execute()->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief inserts a new user or group into the mappings table
|
|
||||||
* @param $dn the record in question
|
|
||||||
* @param $ocname the name to use in ownCloud
|
|
||||||
* @param $isUser is it a user or a group?
|
|
||||||
* @returns true on success, false otherwise
|
|
||||||
*
|
|
||||||
* inserts a new user or group into the mappings table
|
|
||||||
*/
|
|
||||||
static private function mapComponent($dn, $ocname, $isUser = true) {
|
|
||||||
$table = self::getMapTable($isUser);
|
|
||||||
$dn = self::sanitizeDN($dn);
|
|
||||||
|
|
||||||
$sqlAdjustment = '';
|
|
||||||
$dbtype = OCP\Config::getSystemValue('dbtype');
|
|
||||||
if($dbtype == 'mysql') {
|
|
||||||
$sqlAdjustment = 'FROM dual';
|
|
||||||
}
|
|
||||||
|
|
||||||
$insert = OCP\DB::prepare('
|
|
||||||
INSERT INTO '.$table.' (ldap_dn, owncloud_name)
|
|
||||||
SELECT ?,?
|
|
||||||
'.$sqlAdjustment.'
|
|
||||||
WHERE NOT EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM '.$table.'
|
|
||||||
WHERE ldap_dn = ?
|
|
||||||
OR owncloud_name = ? )
|
|
||||||
');
|
|
||||||
|
|
||||||
$res = $insert->execute(array($dn, $ocname, $dn, $ocname));
|
|
||||||
|
|
||||||
if(OCP\DB::isError($res)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$insRows = $res->numRows();
|
|
||||||
|
|
||||||
if($insRows == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function fetchListOfUsers($filter, $attr) {
|
|
||||||
return self::fetchList(OC_LDAP::searchUsers($filter, $attr), (count($attr) > 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function fetchListOfGroups($filter, $attr) {
|
|
||||||
return self::fetchList(OC_LDAP::searchGroups($filter, $attr), (count($attr) > 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function fetchList($list, $manyAttributes) {
|
|
||||||
if(is_array($list)) {
|
|
||||||
if($manyAttributes) {
|
|
||||||
return $list;
|
|
||||||
} else {
|
|
||||||
return array_unique($list, SORT_LOCALE_STRING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//error cause actually, maybe throw an exception in future.
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief reads a given attribute for an LDAP record identified by a DN
|
|
||||||
* @param $dn the record in question
|
|
||||||
* @param $attr the attribute that shall be retrieved
|
|
||||||
* @returns the values in an array on success, false otherwise
|
|
||||||
*
|
|
||||||
* Reads an attribute from an LDAP entry
|
|
||||||
*/
|
|
||||||
static public function readAttribute($dn, $attr) {
|
|
||||||
$cr = self::getConnectionResource();
|
|
||||||
$rr = ldap_read($cr, $dn, 'objectClass=*', array($attr));
|
|
||||||
$er = ldap_first_entry($cr, $rr);
|
|
||||||
//LDAP attributes are not case sensitive
|
|
||||||
$result = OCP\Util::mb_array_change_key_case(ldap_get_attributes($cr, $er), MB_CASE_LOWER, 'UTF-8');
|
|
||||||
$attr = mb_strtolower($attr, 'UTF-8');
|
|
||||||
|
|
||||||
if(isset($result[$attr]) && $result[$attr]['count'] > 0){
|
|
||||||
$values = array();
|
|
||||||
for($i=0;$i<$result[$attr]['count'];$i++) {
|
|
||||||
$values[] = self::resemblesDN($attr) ? self::sanitizeDN($result[$attr][$i]) : $result[$attr][$i];
|
|
||||||
}
|
|
||||||
return $values;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief executes an LDAP search, optimized for Users
|
|
||||||
* @param $filter the LDAP filter for the search
|
|
||||||
* @param $attr optional, when a certain attribute shall be filtered out
|
|
||||||
* @returns array with the search result
|
|
||||||
*
|
|
||||||
* Executes an LDAP search
|
|
||||||
*/
|
|
||||||
static public function searchUsers($filter, $attr = null) {
|
|
||||||
self::init();
|
|
||||||
return self::search($filter, self::$ldapBaseUsers, $attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief executes an LDAP search, optimized for Groups
|
|
||||||
* @param $filter the LDAP filter for the search
|
|
||||||
* @param $attr optional, when a certain attribute shall be filtered out
|
|
||||||
* @returns array with the search result
|
|
||||||
*
|
|
||||||
* Executes an LDAP search
|
|
||||||
*/
|
|
||||||
static public function searchGroups($filter, $attr = null) {
|
|
||||||
self::init();
|
|
||||||
return self::search($filter, self::$ldapBaseGroups, $attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief executes an LDAP search
|
|
||||||
* @param $filter the LDAP filter for the search
|
|
||||||
* @param $base the LDAP subtree that shall be searched
|
|
||||||
* @param $attr optional, when a certain attribute shall be filtered out
|
|
||||||
* @returns array with the search result
|
|
||||||
*
|
|
||||||
* Executes an LDAP search
|
|
||||||
*/
|
|
||||||
static private function search($filter, $base, $attr = null) {
|
|
||||||
if(!is_null($attr) && !is_array($attr)) {
|
|
||||||
$attr = array(mb_strtolower($attr, 'UTF-8'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if we have a resource
|
|
||||||
$link_resource = self::getConnectionResource();
|
|
||||||
if(is_resource($link_resource)) {
|
|
||||||
$sr = ldap_search($link_resource, $base, $filter, $attr);
|
|
||||||
$findings = ldap_get_entries($link_resource, $sr );
|
|
||||||
|
|
||||||
// if we're here, probably no connection resource is returned.
|
|
||||||
// to make ownCloud behave nicely, we simply give back an empty array.
|
|
||||||
if(is_null($findings)) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Seems like we didn't find any resource.
|
|
||||||
// Return an empty array just like before.
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_null($attr)) {
|
|
||||||
$selection = array();
|
|
||||||
$multiarray = false;
|
|
||||||
if(count($attr) > 1) {
|
|
||||||
$multiarray = true;
|
|
||||||
$i = 0;
|
|
||||||
}
|
|
||||||
foreach($findings as $item) {
|
|
||||||
if(!is_array($item)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$item = OCP\Util::mb_array_change_key_case($item, MB_CASE_LOWER, 'UTF-8');
|
|
||||||
|
|
||||||
if($multiarray) {
|
|
||||||
foreach($attr as $key) {
|
|
||||||
$key = mb_strtolower($key, 'UTF-8');
|
|
||||||
if(isset($item[$key])) {
|
|
||||||
if($key != 'dn'){
|
|
||||||
$selection[$i][$key] = self::resemblesDN($key) ? self::sanitizeDN($item[$key][0]) : $item[$key][0];
|
|
||||||
} else {
|
|
||||||
$selection[$i][$key] = self::sanitizeDN($item[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
$i++;
|
|
||||||
} else {
|
|
||||||
//tribute to case insensitivity
|
|
||||||
$key = mb_strtolower($attr[0], 'UTF-8');
|
|
||||||
|
|
||||||
if(isset($item[$key])) {
|
|
||||||
if(self::resemblesDN($key)) {
|
|
||||||
$selection[] = self::sanitizeDN($item[$key]);
|
|
||||||
} else {
|
|
||||||
$selection[] = $item[$key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return $selection;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $findings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function resemblesDN($attr) {
|
|
||||||
$resemblingAttributes = array(
|
|
||||||
'dn',
|
|
||||||
'uniquemember',
|
|
||||||
'member'
|
|
||||||
);
|
|
||||||
return in_array($attr, $resemblingAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function sanitizeDN($dn) {
|
|
||||||
//OID sometimes gives back DNs with whitespace after the comma a la "uid=foo, cn=bar, dn=..." We need to tackle this!
|
|
||||||
$dn = preg_replace('/([^\\\]),(\s+)/u','\1,',$dn);
|
|
||||||
|
|
||||||
//make comparisons and everything work
|
|
||||||
$dn = mb_strtolower($dn, 'UTF-8');
|
|
||||||
|
|
||||||
return $dn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static private function sanitizeUsername($name) {
|
|
||||||
if(self::$ldapIgnoreNamingRules) {
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
//REPLACEMENTS
|
|
||||||
$name = OCP\Util::mb_str_replace(' ', '_', $name, 'UTF-8');
|
|
||||||
|
|
||||||
//every remaining unallowed characters will be removed
|
|
||||||
$name = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $name);
|
|
||||||
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief combines the input filters with AND
|
|
||||||
* @param $filters array, the filters to connect
|
|
||||||
* @returns the combined filter
|
|
||||||
*
|
|
||||||
* Combines Filter arguments with AND
|
|
||||||
*/
|
|
||||||
static public function combineFilterWithAnd($filters) {
|
|
||||||
return self::combineFilter($filters,'&');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief combines the input filters with AND
|
|
||||||
* @param $filters array, the filters to connect
|
|
||||||
* @returns the combined filter
|
|
||||||
*
|
|
||||||
* Combines Filter arguments with AND
|
|
||||||
*/
|
|
||||||
static public function combineFilterWithOr($filters) {
|
|
||||||
return self::combineFilter($filters,'|');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief combines the input filters with given operator
|
|
||||||
* @param $filters array, the filters to connect
|
|
||||||
* @param $operator either & or |
|
|
||||||
* @returns the combined filter
|
|
||||||
*
|
|
||||||
* Combines Filter arguments with AND
|
|
||||||
*/
|
|
||||||
static private function combineFilter($filters, $operator) {
|
|
||||||
$combinedFilter = '('.$operator;
|
|
||||||
foreach($filters as $filter) {
|
|
||||||
if($filter[0] != '(') {
|
|
||||||
$filter = '('.$filter.')';
|
|
||||||
}
|
|
||||||
$combinedFilter.=$filter;
|
|
||||||
}
|
|
||||||
$combinedFilter.=')';
|
|
||||||
return $combinedFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the LDAP handler
|
|
||||||
*/
|
|
||||||
static private function getConnectionResource() {
|
|
||||||
if(!self::$ldapConnectionRes) {
|
|
||||||
self::init();
|
|
||||||
}
|
|
||||||
if(is_null(self::$ldapConnectionRes)) {
|
|
||||||
OCP\Util::writeLog('ldap', 'Connection could not be established', OCP\Util::INFO);
|
|
||||||
}
|
|
||||||
return self::$ldapConnectionRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Caches the general LDAP configuration.
|
|
||||||
*/
|
|
||||||
static private function readConfiguration($force = false) {
|
|
||||||
if(!self::$configured || $force) {
|
|
||||||
self::$ldapHost = OCP\Config::getAppValue('user_ldap', 'ldap_host', '');
|
|
||||||
self::$ldapPort = OCP\Config::getAppValue('user_ldap', 'ldap_port', 389);
|
|
||||||
self::$ldapAgentName = OCP\Config::getAppValue('user_ldap', 'ldap_dn','');
|
|
||||||
self::$ldapAgentPassword = base64_decode(OCP\Config::getAppValue('user_ldap', 'ldap_agent_password',''));
|
|
||||||
self::$ldapBase = OCP\Config::getAppValue('user_ldap', 'ldap_base', '');
|
|
||||||
self::$ldapBaseUsers = OCP\Config::getAppValue('user_ldap', 'ldap_base_users',self::$ldapBase);
|
|
||||||
self::$ldapBaseGroups = OCP\Config::getAppValue('user_ldap', 'ldap_base_groups', self::$ldapBase);
|
|
||||||
self::$ldapTLS = OCP\Config::getAppValue('user_ldap', 'ldap_tls',0);
|
|
||||||
self::$ldapNoCase = OCP\Config::getAppValue('user_ldap', 'ldap_nocase', 0);
|
|
||||||
self::$ldapUserDisplayName = mb_strtolower(OCP\Config::getAppValue('user_ldap', 'ldap_display_name', 'uid'), 'UTF-8');
|
|
||||||
self::$ldapUserFilter = OCP\Config::getAppValue('user_ldap', 'ldap_userlist_filter','objectClass=person');
|
|
||||||
self::$ldapLoginFilter = OCP\Config::getAppValue('user_ldap', 'ldap_login_filter', '(uid=%uid)');
|
|
||||||
self::$ldapGroupDisplayName = mb_strtolower(OCP\Config::getAppValue('user_ldap', 'ldap_group_display_name', LDAP_GROUP_DISPLAY_NAME_ATTR), 'UTF-8');
|
|
||||||
self::$ldapIgnoreNamingRules = OCP\Config::getSystemValue('ldapIgnoreNamingRules', false);
|
|
||||||
|
|
||||||
if(empty(self::$ldapBaseUsers)) {
|
|
||||||
OCP\Util::writeLog('ldap', 'Base for Users is empty, using Base DN', OCP\Util::INFO);
|
|
||||||
self::$ldapBaseUsers = self::$ldapBase;
|
|
||||||
}
|
|
||||||
if(empty(self::$ldapBaseGroups)) {
|
|
||||||
OCP\Util::writeLog('ldap', 'Base for Groups is empty, using Base DN', OCP\Util::INFO);
|
|
||||||
self::$ldapBaseGroups = self::$ldapBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(
|
|
||||||
!empty(self::$ldapHost)
|
|
||||||
&& !empty(self::$ldapPort)
|
|
||||||
&& (
|
|
||||||
(!empty(self::$ldapAgentName) && !empty(self::$ldapAgentPassword))
|
|
||||||
|| ( empty(self::$ldapAgentName) && empty(self::$ldapAgentPassword))
|
|
||||||
)
|
|
||||||
&& !empty(self::$ldapBase)
|
|
||||||
&& !empty(self::$ldapUserDisplayName)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
self::$configured = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects and Binds to LDAP
|
|
||||||
*/
|
|
||||||
static private function establishConnection() {
|
|
||||||
if(!self::$configured) {
|
|
||||||
OCP\Util::writeLog('ldap', 'Configuration is invalid, cannot connect', OCP\Util::INFO);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!self::$ldapConnectionRes) {
|
|
||||||
self::$ldapConnectionRes = ldap_connect(self::$ldapHost, self::$ldapPort);
|
|
||||||
if(ldap_set_option(self::$ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
|
|
||||||
if(ldap_set_option(self::$ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
|
|
||||||
if(self::$ldapTLS) {
|
|
||||||
ldap_start_tls(self::$ldapConnectionRes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$ldapLogin = @ldap_bind(self::$ldapConnectionRes, self::$ldapAgentName, self::$ldapAgentPassword );
|
|
||||||
if(!$ldapLogin) {
|
|
||||||
OCP\Util::writeLog('ldap', 'Bind failed: ' . ldap_errno(self::$ldapConnectionRes) . ': ' . ldap_error(self::$ldapConnectionRes), OCP\Util::ERROR);
|
|
||||||
self::$ldapConnectionRes = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function areCredentialsValid($name, $password) {
|
|
||||||
return @ldap_bind(self::getConnectionResource(), $name, $password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* taken from http://www.php.net/manual/en/function.array-search.php#97645
|
|
||||||
* TODO: move somewhere, where its better placed since it is not LDAP specific. OC_Helper maybe?
|
|
||||||
*/
|
|
||||||
static public function recursiveArraySearch($haystack, $needle, $index = null) {
|
|
||||||
$aIt = new RecursiveArrayIterator($haystack);
|
|
||||||
$it = new RecursiveIteratorIterator($aIt);
|
|
||||||
|
|
||||||
while($it->valid()) {
|
|
||||||
if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
|
|
||||||
return $aIt->key();
|
|
||||||
}
|
|
||||||
|
|
||||||
$it->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -26,8 +26,8 @@ class Test_Group_Ldap extends UnitTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
function testSingleBackend(){
|
function testSingleBackend(){
|
||||||
OC_Group::useBackend(new OC_GROUP_LDAP());
|
OC_Group::useBackend(new OCA\user_ldap\GROUP_LDAP());
|
||||||
$group_ldap = new OC_GROUP_LDAP();
|
$group_ldap = new OCA\user_ldap\GROUP_LDAP();
|
||||||
|
|
||||||
$this->assertIsA(OC_Group::getGroups(),gettype(array()));
|
$this->assertIsA(OC_Group::getGroups(),gettype(array()));
|
||||||
$this->assertIsA($group_ldap->getGroups(),gettype(array()));
|
$this->assertIsA($group_ldap->getGroups(),gettype(array()));
|
||||||
|
|
|
@ -23,13 +23,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class OC_USER_LDAP extends OC_User_Backend {
|
namespace OCA\user_ldap;
|
||||||
|
|
||||||
// cached settings
|
class USER_LDAP extends lib\Access implements \OCP\UserInterface {
|
||||||
protected $ldapUserFilter;
|
|
||||||
protected $ldapQuotaAttribute;
|
|
||||||
protected $ldapQuotaDefault;
|
|
||||||
protected $ldapEmailAttribute;
|
|
||||||
|
|
||||||
// will be retrieved from LDAP server
|
// will be retrieved from LDAP server
|
||||||
protected $ldap_dc = false;
|
protected $ldap_dc = false;
|
||||||
|
@ -37,39 +33,32 @@ class OC_USER_LDAP extends OC_User_Backend {
|
||||||
// cache getUsers()
|
// cache getUsers()
|
||||||
protected $_users = null;
|
protected $_users = null;
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
$this->ldapUserFilter = OCP\Config::getAppValue('user_ldap', 'ldap_userlist_filter', '(objectClass=posixAccount)');
|
|
||||||
$this->ldapQuotaAttribute = OCP\Config::getAppValue('user_ldap', 'ldap_quota_attr', '');
|
|
||||||
$this->ldapQuotaDefault = OCP\Config::getAppValue('user_ldap', 'ldap_quota_def', '');
|
|
||||||
$this->ldapEmailAttribute = OCP\Config::getAppValue('user_ldap', 'ldap_email_attr', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function updateQuota($dn) {
|
private function updateQuota($dn) {
|
||||||
$quota = null;
|
$quota = null;
|
||||||
if(!empty($this->ldapQuotaDefault)) {
|
if(!empty($this->connection->ldapQuotaDefault)) {
|
||||||
$quota = $this->ldapQuotaDefault;
|
$quota = $this->connection->ldapQuotaDefault;
|
||||||
}
|
}
|
||||||
if(!empty($this->ldapQuotaAttribute)) {
|
if(!empty($this->connection->ldapQuotaAttribute)) {
|
||||||
$aQuota = OC_LDAP::readAttribute($dn, $this->ldapQuotaAttribute);
|
$aQuota = $this->readAttribute($dn, $this->connection->ldapQuotaAttribute);
|
||||||
|
|
||||||
if($aQuota && (count($aQuota) > 0)) {
|
if($aQuota && (count($aQuota) > 0)) {
|
||||||
$quota = $aQuota[0];
|
$quota = $aQuota[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!is_null($quota)) {
|
if(!is_null($quota)) {
|
||||||
OCP\Config::setUserValue(OC_LDAP::dn2username($dn), 'files', 'quota', OCP\Util::computerFileSize($quota));
|
\OCP\Config::setUserValue($this->dn2username($dn), 'files', 'quota', \OCP\Util::computerFileSize($quota));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateEmail($dn) {
|
private function updateEmail($dn) {
|
||||||
$email = null;
|
$email = null;
|
||||||
if(!empty($this->ldapEmailAttribute)) {
|
if(!empty($this->connection->ldapEmailAttribute)) {
|
||||||
$aEmail = OC_LDAP::readAttribute($dn, $this->ldapEmailAttribute);
|
$aEmail = $this->readAttribute($dn, $this->connection->ldapEmailAttribute);
|
||||||
if($aEmail && (count($aEmail) > 0)) {
|
if($aEmail && (count($aEmail) > 0)) {
|
||||||
$email = $aEmail[0];
|
$email = $aEmail[0];
|
||||||
}
|
}
|
||||||
if(!is_null($email)){
|
if(!is_null($email)) {
|
||||||
OCP\Config::setUserValue(OC_LDAP::dn2username($dn), 'settings', 'email', $email);
|
\OCP\Config::setUserValue($this->dn2username($dn), 'settings', 'email', $email);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,15 +73,15 @@ class OC_USER_LDAP extends OC_User_Backend {
|
||||||
*/
|
*/
|
||||||
public function checkPassword($uid, $password){
|
public function checkPassword($uid, $password){
|
||||||
//find out dn of the user name
|
//find out dn of the user name
|
||||||
$filter = OCP\Util::mb_str_replace('%uid', $uid, OC_LDAP::conf('ldapLoginFilter'), 'UTF-8');
|
$filter = \OCP\Util::mb_str_replace('%uid', $uid, $this->connection->ldapLoginFilter, 'UTF-8');
|
||||||
$ldap_users = OC_LDAP::fetchListOfUsers($filter, 'dn');
|
$ldap_users = $this->fetchListOfUsers($filter, 'dn');
|
||||||
if(count($ldap_users) < 1) {
|
if(count($ldap_users) < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$dn = $ldap_users[0];
|
$dn = $ldap_users[0];
|
||||||
|
|
||||||
//are the credentials OK?
|
//are the credentials OK?
|
||||||
if(!OC_LDAP::areCredentialsValid($dn, $password)) {
|
if(!$this->areCredentialsValid($dn, $password)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +90,7 @@ class OC_USER_LDAP extends OC_User_Backend {
|
||||||
$this->updateEmail($dn);
|
$this->updateEmail($dn);
|
||||||
|
|
||||||
//give back the display name
|
//give back the display name
|
||||||
return OC_LDAP::dn2username($dn);
|
return $this->dn2username($dn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,8 +101,8 @@ class OC_USER_LDAP extends OC_User_Backend {
|
||||||
*/
|
*/
|
||||||
public function getUsers(){
|
public function getUsers(){
|
||||||
if(is_null($this->_users)) {
|
if(is_null($this->_users)) {
|
||||||
$ldap_users = OC_LDAP::fetchListOfUsers($this->ldapUserFilter, array(OC_LDAP::conf('ldapUserDisplayName'), 'dn'));
|
$ldap_users = $this->fetchListOfUsers($this->connection->ldapUserFilter, array($this->connection->ldapUserDisplayName, 'dn'));
|
||||||
$this->_users = OC_LDAP::ownCloudUserNames($ldap_users);
|
$this->_users = $this->ownCloudUserNames($ldap_users);
|
||||||
}
|
}
|
||||||
return $this->_users;
|
return $this->_users;
|
||||||
}
|
}
|
||||||
|
@ -125,13 +114,13 @@ class OC_USER_LDAP extends OC_User_Backend {
|
||||||
*/
|
*/
|
||||||
public function userExists($uid){
|
public function userExists($uid){
|
||||||
//getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
|
//getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
|
||||||
$dn = OC_LDAP::username2dn($uid);
|
$dn = $this->username2dn($uid);
|
||||||
if(!$dn) {
|
if(!$dn) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if user really still exists, we will be able to read his cn
|
//if user really still exists, we will be able to read his cn
|
||||||
$cn = OC_LDAP::readAttribute($dn, 'cn');
|
$cn = $this->readAttribute($dn, 'cn');
|
||||||
if(!$cn || empty($cn)) {
|
if(!$cn || empty($cn)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -139,4 +128,27 @@ class OC_USER_LDAP extends OC_User_Backend {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief delete a user
|
||||||
|
* @param $uid The username of the user to delete
|
||||||
|
* @returns true/false
|
||||||
|
*
|
||||||
|
* Deletes a user
|
||||||
|
*/
|
||||||
|
public function deleteUser($uid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if backend implements actions
|
||||||
|
* @param $actions bitwise-or'ed actions
|
||||||
|
* @returns boolean
|
||||||
|
*
|
||||||
|
* Returns the supported actions as int to be
|
||||||
|
* compared with OC_USER_BACKEND_CREATE_USER etc.
|
||||||
|
*/
|
||||||
|
public function implementsActions($actions) {
|
||||||
|
return (bool)(OC_USER_BACKEND_CHECK_PASSWORD & $actions);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ OCP\Util::addHeader('link',array('rel'=>'openid.delegate', 'href'=>OCP\Util::lin
|
||||||
|
|
||||||
OCP\App::registerPersonal('user_openid','settings');
|
OCP\App::registerPersonal('user_openid','settings');
|
||||||
|
|
||||||
require_once 'openid/user_openid.php';
|
require_once 'apps/user_openid/user_openid.php';
|
||||||
|
|
||||||
//active the openid backend
|
//active the openid backend
|
||||||
OC_User::useBackend('openid');
|
OC_User::useBackend('openid');
|
||||||
|
|
|
@ -83,6 +83,9 @@ class OC{
|
||||||
elseif(strpos($className,'OCP\\')===0){
|
elseif(strpos($className,'OCP\\')===0){
|
||||||
require_once 'public/'.strtolower(str_replace('\\','/',substr($className,3)) . '.php');
|
require_once 'public/'.strtolower(str_replace('\\','/',substr($className,3)) . '.php');
|
||||||
}
|
}
|
||||||
|
elseif(strpos($className,'OCA\\')===0){
|
||||||
|
require_once 'apps/'.strtolower(str_replace('\\','/',substr($className,3)) . '.php');
|
||||||
|
}
|
||||||
elseif(strpos($className,'Sabre_')===0) {
|
elseif(strpos($className,'Sabre_')===0) {
|
||||||
require_once str_replace('_','/',$className) . '.php';
|
require_once str_replace('_','/',$className) . '.php';
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class OC_Group {
|
||||||
* @returns true/false
|
* @returns true/false
|
||||||
*/
|
*/
|
||||||
public static function useBackend( $backend ){
|
public static function useBackend( $backend ){
|
||||||
if($backend instanceof OC_Group_Backend){
|
if($backend instanceof OC_Group_Interface){
|
||||||
self::$_usedBackends[]=$backend;
|
self::$_usedBackends[]=$backend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000);
|
||||||
/**
|
/**
|
||||||
* Abstract base class for user management
|
* Abstract base class for user management
|
||||||
*/
|
*/
|
||||||
abstract class OC_Group_Backend {
|
abstract class OC_Group_Backend implements OC_Group_Interface {
|
||||||
protected $possibleActions = array(
|
protected $possibleActions = array(
|
||||||
OC_GROUP_BACKEND_CREATE_GROUP => 'createGroup',
|
OC_GROUP_BACKEND_CREATE_GROUP => 'createGroup',
|
||||||
OC_GROUP_BACKEND_DELETE_GROUP => 'deleteGroup',
|
OC_GROUP_BACKEND_DELETE_GROUP => 'deleteGroup',
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - group interface
|
||||||
|
*
|
||||||
|
* @author Arthur Schiwon
|
||||||
|
* @copyright 2012 Arthur Schiwon blizzz@owncloud.org
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface OC_Group_Interface {
|
||||||
|
/**
|
||||||
|
* @brief Check if backend implements actions
|
||||||
|
* @param $actions bitwise-or'ed actions
|
||||||
|
* @returns boolean
|
||||||
|
*
|
||||||
|
* Returns the supported actions as int to be
|
||||||
|
* compared with OC_GROUP_BACKEND_CREATE_GROUP etc.
|
||||||
|
*/
|
||||||
|
public function implementsActions($actions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief is user in group?
|
||||||
|
* @param $uid uid of the user
|
||||||
|
* @param $gid gid of the group
|
||||||
|
* @returns true/false
|
||||||
|
*
|
||||||
|
* Checks whether the user is member of a group or not.
|
||||||
|
*/
|
||||||
|
public function inGroup($uid, $gid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get all groups a user belongs to
|
||||||
|
* @param $uid Name of the user
|
||||||
|
* @returns array with group names
|
||||||
|
*
|
||||||
|
* This function fetches all groups a user belongs to. It does not check
|
||||||
|
* if the user exists at all.
|
||||||
|
*/
|
||||||
|
public function getUserGroups($uid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get a list of all groups
|
||||||
|
* @returns array with group names
|
||||||
|
*
|
||||||
|
* Returns a list with all groups
|
||||||
|
*/
|
||||||
|
public function getGroups();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if a group exists
|
||||||
|
* @param string $gid
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function groupExists($gid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get a list of all users in a group
|
||||||
|
* @returns array with user ids
|
||||||
|
*/
|
||||||
|
public function usersInGroup($gid);
|
||||||
|
|
||||||
|
}
|
|
@ -679,4 +679,30 @@ class OC_Helper {
|
||||||
}
|
}
|
||||||
return $subject;
|
return $subject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief performs a search in a nested array
|
||||||
|
* @param haystack the array to be searched
|
||||||
|
* @param needle the search string
|
||||||
|
* @param $index optional, only search this key name
|
||||||
|
* @return the key of the matching field, otherwise false
|
||||||
|
*
|
||||||
|
* performs a search in a nested array
|
||||||
|
*
|
||||||
|
* taken from http://www.php.net/manual/en/function.array-search.php#97645
|
||||||
|
*/
|
||||||
|
public static function recursiveArraySearch($haystack, $needle, $index = null) {
|
||||||
|
$aIt = new RecursiveArrayIterator($haystack);
|
||||||
|
$it = new RecursiveIteratorIterator($aIt);
|
||||||
|
|
||||||
|
while($it->valid()) {
|
||||||
|
if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
|
||||||
|
return $aIt->key();
|
||||||
|
}
|
||||||
|
|
||||||
|
$it->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
83
lib/ocs.php
83
lib/ocs.php
|
@ -176,6 +176,10 @@ class OC_OCS {
|
||||||
->requirements(array('format'=>'xml|json'));
|
->requirements(array('format'=>'xml|json'));
|
||||||
|
|
||||||
// CLOUD
|
// CLOUD
|
||||||
|
// systemWebApps
|
||||||
|
}elseif(($method=='get') and ($ex[$paracount-5] == 'v1.php') and ($ex[$paracount-4]=='cloud') and ($ex[$paracount-3] == 'system') and ($ex[$paracount-2] == 'webapps')){
|
||||||
|
OC_OCS::systemwebapps($format);
|
||||||
|
|
||||||
// quotaget
|
// quotaget
|
||||||
$router->create('quota_get',
|
$router->create('quota_get',
|
||||||
'/cloud/user/{user}.{format}')
|
'/cloud/user/{user}.{format}')
|
||||||
|
@ -199,6 +203,16 @@ class OC_OCS {
|
||||||
})
|
})
|
||||||
->requirements(array('format'=>'xml|json'));
|
->requirements(array('format'=>'xml|json'));
|
||||||
|
|
||||||
|
// keygetpublic
|
||||||
|
}elseif(($method=='get') and ($ex[$paracount-6] == 'v1.php') and ($ex[$paracount-5]=='cloud') and ($ex[$paracount-4] == 'user') and ($ex[$paracount-2] == 'publickey')){
|
||||||
|
$user=$ex[$paracount-3];
|
||||||
|
OC_OCS::publicKeyGet($format,$user);
|
||||||
|
|
||||||
|
// keygetprivate
|
||||||
|
}elseif(($method=='get') and ($ex[$paracount-6] == 'v1.php') and ($ex[$paracount-5]=='cloud') and ($ex[$paracount-4] == 'user') and ($ex[$paracount-2] == 'privatekey')){
|
||||||
|
$user=$ex[$paracount-3];
|
||||||
|
OC_OCS::privateKeyGet($format,$user);
|
||||||
|
|
||||||
|
|
||||||
// add more calls here
|
// add more calls here
|
||||||
// please document all the call in the draft spec
|
// please document all the call in the draft spec
|
||||||
|
@ -580,6 +594,29 @@ class OC_OCS {
|
||||||
|
|
||||||
// CLOUD API #############################################
|
// CLOUD API #############################################
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a list of installed web apps
|
||||||
|
* @param string $format
|
||||||
|
* @return string xml/json
|
||||||
|
*/
|
||||||
|
private static function systemWebApps($format) {
|
||||||
|
$login=OC_OCS::checkpassword();
|
||||||
|
$apps=OC_App::getEnabledApps();
|
||||||
|
$values=array();
|
||||||
|
foreach($apps as $app) {
|
||||||
|
$info=OC_App::getAppInfo($app);
|
||||||
|
if(isset($info['standalone'])) {
|
||||||
|
$newvalue=array('name'=>$info['name'],'url'=>OC_Helper::linkToAbsolute($app,''),'icon'=>'');
|
||||||
|
$values[]=$newvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
$txt=OC_OCS::generatexml($format, 'ok', 100, '', $values, 'cloud', '', 2, 0, 0);
|
||||||
|
echo($txt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the quota of a user
|
* get the quota of a user
|
||||||
* @param string $format
|
* @param string $format
|
||||||
|
@ -608,7 +645,7 @@ class OC_OCS {
|
||||||
$xml['used']=$used;
|
$xml['used']=$used;
|
||||||
$xml['relative']=$relative;
|
$xml['relative']=$relative;
|
||||||
|
|
||||||
$txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', 'full', 1, count($xml), 0);
|
$txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', '', 1, 0, 0);
|
||||||
echo($txt);
|
echo($txt);
|
||||||
}else{
|
}else{
|
||||||
echo self::generateXml('', 'fail', 300, 'User does not exist');
|
echo self::generateXml('', 'fail', 300, 'User does not exist');
|
||||||
|
@ -631,16 +668,56 @@ class OC_OCS {
|
||||||
|
|
||||||
// todo
|
// todo
|
||||||
// not yet implemented
|
// not yet implemented
|
||||||
// edit logic here
|
// add logic here
|
||||||
error_log('OCS call: user:'.$user.' quota:'.$quota);
|
error_log('OCS call: user:'.$user.' quota:'.$quota);
|
||||||
|
|
||||||
$xml=array();
|
$xml=array();
|
||||||
$txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', 'full', 1, count($xml), 0);
|
$txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', '', 1, 0, 0);
|
||||||
echo($txt);
|
echo($txt);
|
||||||
}else{
|
}else{
|
||||||
echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.');
|
echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the public key of a user
|
||||||
|
* @param string $format
|
||||||
|
* @param string $user
|
||||||
|
* @return string xml/json
|
||||||
|
*/
|
||||||
|
private static function publicKeyGet($format,$user) {
|
||||||
|
$login=OC_OCS::checkpassword();
|
||||||
|
|
||||||
|
if(OC_User::userExists($user)){
|
||||||
|
// calculate the disc space
|
||||||
|
$txt='this is the public key of '.$user;
|
||||||
|
echo($txt);
|
||||||
|
}else{
|
||||||
|
echo self::generateXml('', 'fail', 300, 'User does not exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the private key of a user
|
||||||
|
* @param string $format
|
||||||
|
* @param string $user
|
||||||
|
* @return string xml/json
|
||||||
|
*/
|
||||||
|
private static function privateKeyGet($format,$user) {
|
||||||
|
$login=OC_OCS::checkpassword();
|
||||||
|
if(OC_Group::inGroup($login, 'admin') or ($login==$user)) {
|
||||||
|
|
||||||
|
if(OC_User::userExists($user)){
|
||||||
|
// calculate the disc space
|
||||||
|
$txt='this is the private key of '.$user;
|
||||||
|
echo($txt);
|
||||||
|
}else{
|
||||||
|
echo self::generateXml('', 'fail', 300, 'User does not exist');
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ownCloud
|
||||||
|
*
|
||||||
|
* @author Arthur Schiwon
|
||||||
|
* @copyright 2012 Arthur Schiwon blizzz@owncloud.org
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface of ownCloud for apps to use.
|
||||||
|
* Group Class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCP;
|
||||||
|
|
||||||
|
interface GroupInterface extends \OC_Group_Interface {}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ownCloud
|
||||||
|
*
|
||||||
|
* @author Arthur Schiwon
|
||||||
|
* @copyright 2012 Arthur Schiwon blizzz@owncloud.org
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface of ownCloud for apps to use.
|
||||||
|
* User Class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCP;
|
||||||
|
|
||||||
|
interface UserInterface extends \OC_User_Interface {}
|
|
@ -320,4 +320,15 @@ class Util {
|
||||||
public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
|
public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) {
|
||||||
return(\OC_Helper::mb_str_replace($search, $replace, $subject, $encoding, $count));
|
return(\OC_Helper::mb_str_replace($search, $replace, $subject, $encoding, $count));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief performs a search in a nested array
|
||||||
|
* @param haystack the array to be searched
|
||||||
|
* @param needle the search string
|
||||||
|
* @param $index optional, only search this key name
|
||||||
|
* @return the key of the matching field, otherwise false
|
||||||
|
*/
|
||||||
|
public static function recursiveArraySearch($haystack, $needle, $index = null) {
|
||||||
|
return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ class OC_User {
|
||||||
* Set the User Authentication Module
|
* Set the User Authentication Module
|
||||||
*/
|
*/
|
||||||
public static function useBackend( $backend = 'database' ){
|
public static function useBackend( $backend = 'database' ){
|
||||||
if($backend instanceof OC_User_Backend){
|
if($backend instanceof OC_User_Interface){
|
||||||
self::$_usedBackends[get_class($backend)]=$backend;
|
self::$_usedBackends[get_class($backend)]=$backend;
|
||||||
}else{
|
}else{
|
||||||
// You'll never know what happens
|
// You'll never know what happens
|
||||||
|
|
|
@ -42,7 +42,7 @@ define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100);
|
||||||
*
|
*
|
||||||
* Subclass this for your own backends, and see OC_User_Example for descriptions
|
* Subclass this for your own backends, and see OC_User_Example for descriptions
|
||||||
*/
|
*/
|
||||||
abstract class OC_User_Backend {
|
abstract class OC_User_Backend implements OC_User_Interface {
|
||||||
|
|
||||||
protected $possibleActions = array(
|
protected $possibleActions = array(
|
||||||
OC_USER_BACKEND_CREATE_USER => 'createUser',
|
OC_USER_BACKEND_CREATE_USER => 'createUser',
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - user interface
|
||||||
|
*
|
||||||
|
* @author Arthur Schiwon
|
||||||
|
* @copyright 2012 Arthur Schiwon blizzz@owncloud.org
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface OC_User_Interface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if backend implements actions
|
||||||
|
* @param $actions bitwise-or'ed actions
|
||||||
|
* @returns boolean
|
||||||
|
*
|
||||||
|
* Returns the supported actions as int to be
|
||||||
|
* compared with OC_USER_BACKEND_CREATE_USER etc.
|
||||||
|
*/
|
||||||
|
public function implementsActions($actions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief delete a user
|
||||||
|
* @param $uid The username of the user to delete
|
||||||
|
* @returns true/false
|
||||||
|
*
|
||||||
|
* Deletes a user
|
||||||
|
*/
|
||||||
|
public function deleteUser($uid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a list of all users
|
||||||
|
* @returns array with all uids
|
||||||
|
*
|
||||||
|
* Get a list of all users.
|
||||||
|
*/
|
||||||
|
public function getUsers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief check if a user exists
|
||||||
|
* @param string $uid the username
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function userExists($uid);
|
||||||
|
|
||||||
|
}
|
54
webapps.php
54
webapps.php
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ownCloud status page. usefull if you want to check from the outside if an owncloud installation exists
|
|
||||||
*
|
|
||||||
* @author Frank Karlitschek
|
|
||||||
* @copyright 2012 Frank Karlitschek frank@owncloud.org
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public
|
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
$RUNTIME_NOAPPS = TRUE; //no apps, yet
|
|
||||||
|
|
||||||
require_once('lib/base.php');
|
|
||||||
|
|
||||||
|
|
||||||
//valid user account
|
|
||||||
if(isset($_SERVER['PHP_AUTH_USER'])) $authuser=$_SERVER['PHP_AUTH_USER']; else $authuser='';
|
|
||||||
if(isset($_SERVER['PHP_AUTH_PW'])) $authpw=$_SERVER['PHP_AUTH_PW']; else $authpw='';
|
|
||||||
|
|
||||||
if(!OC_User::login($authuser,$authpw)){
|
|
||||||
header('WWW-Authenticate: Basic realm="your valid user account"');
|
|
||||||
header('HTTP/1.0 401 Unauthorized');
|
|
||||||
exit;
|
|
||||||
}else{
|
|
||||||
|
|
||||||
$apps=OC_App::getEnabledApps();
|
|
||||||
$values=array();
|
|
||||||
foreach($apps as $app) {
|
|
||||||
$info=OC_App::getAppInfo($app);
|
|
||||||
if(isset($info['standalone'])) {
|
|
||||||
$newvalue=array('name'=>$info['name'],'url'=>OC_Helper::linkToAbsolute($app,''),'icon'=>'');
|
|
||||||
$values[]=$newvalue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
echo(json_encode($values));
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue