summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2012-10-06 10:46:10 +0200
committerAndreas Gohr <andi@splitbrain.org>2012-10-06 10:46:10 +0200
commit93a7873eb0646b5712d75b031cd8b8b143968ba2 (patch)
treea97bf3309c75947475a42a73f23727f7d2642677
parent2ca4ac4d5e2214a945489b6aa66c9542b3ee2e4a (diff)
parentf4476bd9b5badd36cd0617d76538e47d9649986b (diff)
downloadrpg-93a7873eb0646b5712d75b031cd8b8b143968ba2.tar.gz
rpg-93a7873eb0646b5712d75b031cd8b8b143968ba2.tar.bz2
Merge remote-tracking branch 'janschumann/master' into future
This merge fixes all conflicts but is otherwise untested and might break funktionality in the auth system somewhere. It NEEDS MAJOR TESTING! Some refactoring of the auth plugins is still needed: * move to PHP5 style * fix comments * add plugin.info.txt * janschumann/master: Refactored auth system: All auth methods are now introduced as plugins. Bugfix: auth types are now correcty added Setup auth system from plugins Added Auth-Plugin-Prototype to autoload Load auth types from plugins in settings_authtype class Added prototype for Auth-Plugins added plugin type 'auth' Conflicts: inc/auth.php inc/auth/pgsql.class.php inc/init.php inc/load.php lib/plugins/auth.php lib/plugins/authad/auth.php lib/plugins/authldap/auth.php lib/plugins/authmysql/auth.php lib/plugins/authplain/auth.php
-rw-r--r--inc/auth.php42
-rw-r--r--inc/auth/pgsql.class.php419
-rw-r--r--inc/init.php2
-rw-r--r--inc/load.php3
-rw-r--r--lib/plugins/auth.php (renamed from inc/auth/basic.class.php)28
-rw-r--r--lib/plugins/authad/auth.php (renamed from inc/auth/ad.class.php)14
-rw-r--r--lib/plugins/authad/plugin.info.txt7
-rw-r--r--lib/plugins/authldap/auth.php (renamed from inc/auth/ldap.class.php)9
-rw-r--r--lib/plugins/authldap/plugin.info.txt7
-rw-r--r--lib/plugins/authmysql/auth.php (renamed from inc/auth/mysql.class.php)10
-rw-r--r--lib/plugins/authmysql/plugin.info.txt7
-rw-r--r--lib/plugins/authpgsql/auth.php331
-rw-r--r--lib/plugins/authpgsql/plugin.info.txt7
-rw-r--r--lib/plugins/authplain/auth.php (renamed from inc/auth/plain.class.php)12
-rw-r--r--lib/plugins/authplain/plugin.info.txt7
-rw-r--r--lib/plugins/config/settings/extra.class.php51
16 files changed, 483 insertions, 473 deletions
diff --git a/inc/auth.php b/inc/auth.php
index 99adfa791..25b9e4632 100644
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -34,38 +34,34 @@ define('AUTH_ADMIN', 255);
*/
function auth_setup() {
global $conf;
- /* @var auth_basic $auth */
+ /* @var DokuWiki_Auth_Plugin $auth */
global $auth;
/* @var Input $INPUT */
global $INPUT;
global $AUTH_ACL;
global $lang;
+ global $config_cascade;
+ global $plugin_controller;
$AUTH_ACL = array();
if(!$conf['useacl']) return false;
- // load the the backend auth functions and instantiate the auth object XXX
- if(@file_exists(DOKU_INC.'inc/auth/'.$conf['authtype'].'.class.php')) {
- require_once(DOKU_INC.'inc/auth/basic.class.php');
- require_once(DOKU_INC.'inc/auth/'.$conf['authtype'].'.class.php');
-
- $auth_class = "auth_".$conf['authtype'];
- if(class_exists($auth_class)) {
- $auth = new $auth_class();
- if($auth->success == false) {
- // degrade to unauthenticated user
- unset($auth);
- auth_logoff();
- msg($lang['authtempfail'], -1);
- }
- } else {
- nice_die($lang['authmodfailed']);
- }
- } else {
- nice_die($lang['authmodfailed']);
+ // try to load auth backend from plugins
+ foreach ($plugin_controller->getList('auth') as $plugin) {
+ if ($conf['authtype'] === $plugin) {
+ $auth = $plugin_controller->load('auth', $plugin);
+ break;
+ }
}
- if(!isset($auth) || !$auth) return false;
+ if(!$auth) return false;
+
+ if ($auth && $auth->success == false) {
+ // degrade to unauthenticated user
+ unset($auth);
+ auth_logoff();
+ msg($lang['authtempfail'], -1);
+ }
// do the login either by cookie or provided credentials XXX
$INPUT->set('http_credentials', false);
@@ -91,7 +87,9 @@ function auth_setup() {
}
// apply cleaning
- $INPUT->set('u', $auth->cleanUser($INPUT->str('u')));
+ if (true === $auth->success) {
+ $_REQUEST['u'] = $auth->cleanUser($_REQUEST['u']);
+ }
if($INPUT->str('authtok')) {
// when an authentication token is given, trust the session
diff --git a/inc/auth/pgsql.class.php b/inc/auth/pgsql.class.php
deleted file mode 100644
index b422b100d..000000000
--- a/inc/auth/pgsql.class.php
+++ /dev/null
@@ -1,419 +0,0 @@
-<?php
-/**
- * PgSQL authentication backend
- *
- * This class inherits much functionality from the MySQL class
- * and just reimplements the Postgres specific parts.
- *
- * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Chris Smith <chris@jalakai.co.uk>
- * @author Matthias Grimm <matthias.grimmm@sourceforge.net>
- */
-
-require_once(DOKU_INC.'inc/auth/mysql.class.php');
-
-class auth_pgsql extends auth_mysql {
-
- /**
- * Constructor
- *
- * checks if the pgsql interface is available, otherwise it will
- * set the variable $success of the basis class to false
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- * @author Andreas Gohr <andi@splitbrain.org>
- */
- function __construct() {
- global $conf;
- $this->cnf = $conf['auth']['pgsql'];
- if(!$this->cnf['port']){
- $this->cnf['port'] = 5432;
- }
-
- if (method_exists($this, 'auth_basic')){
- parent::auth_basic();
- }
-
- if(!function_exists('pg_connect')) {
- if ($this->cnf['debug'])
- msg("PgSQL err: PHP Postgres extension not found.",-1);
- $this->success = false;
- return;
- }
-
- $this->defaultgroup = $conf['defaultgroup'];
-
- // set capabilities based upon config strings set
- if (empty($this->cnf['user']) ||
- empty($this->cnf['password']) || empty($this->cnf['database'])){
- if ($this->cnf['debug']){
- msg("PgSQL err: insufficient configuration.",-1,__LINE__,__FILE__);
- }
- $this->success = false;
- return;
- }
-
- $this->cando['addUser'] = $this->_chkcnf(array(
- 'getUserInfo',
- 'getGroups',
- 'addUser',
- 'getUserID',
- 'getGroupID',
- 'addGroup',
- 'addUserGroup'));
- $this->cando['delUser'] = $this->_chkcnf(array(
- 'getUserID',
- 'delUser',
- 'delUserRefs'));
- $this->cando['modLogin'] = $this->_chkcnf(array(
- 'getUserID',
- 'updateUser',
- 'UpdateTarget'));
- $this->cando['modPass'] = $this->cando['modLogin'];
- $this->cando['modName'] = $this->cando['modLogin'];
- $this->cando['modMail'] = $this->cando['modLogin'];
- $this->cando['modGroups'] = $this->_chkcnf(array(
- 'getUserID',
- 'getGroups',
- 'getGroupID',
- 'addGroup',
- 'addUserGroup',
- 'delGroup',
- 'getGroupID',
- 'delUserGroup'));
- /* getGroups is not yet supported
- $this->cando['getGroups'] = $this->_chkcnf(array('getGroups',
- 'getGroupID')); */
- $this->cando['getUsers'] = $this->_chkcnf(array(
- 'getUsers',
- 'getUserInfo',
- 'getGroups'));
- $this->cando['getUserCount'] = $this->_chkcnf(array('getUsers'));
- }
-
- /**
- * Check if the given config strings are set
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- * @return bool
- */
- function _chkcnf($keys, $wop=false){
- foreach ($keys as $key){
- if (empty($this->cnf[$key])) return false;
- }
- return true;
- }
-
- // @inherit function checkPass($user,$pass)
- // @inherit function getUserData($user)
- // @inherit function createUser($user,$pwd,$name,$mail,$grps=null)
- // @inherit function modifyUser($user, $changes)
- // @inherit function deleteUsers($users)
-
-
- /**
- * [public function]
- *
- * Counts users which meet certain $filter criteria.
- *
- * @param array $filter filter criteria in item/pattern pairs
- * @return count of found users.
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function getUserCount($filter=array()) {
- $rc = 0;
-
- if($this->_openDB()) {
- $sql = $this->_createSQLFilter($this->cnf['getUsers'], $filter);
-
- // no equivalent of SQL_CALC_FOUND_ROWS in pgsql?
- if (($result = $this->_queryDB($sql))){
- $rc = count($result);
- }
- $this->_closeDB();
- }
- return $rc;
- }
-
- /**
- * Bulk retrieval of user data. [public function]
- *
- * @param first index of first user to be returned
- * @param limit max number of users to be returned
- * @param filter array of field/pattern pairs
- * @return array of userinfo (refer getUserData for internal userinfo details)
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function retrieveUsers($first=0,$limit=10,$filter=array()) {
- $out = array();
-
- if($this->_openDB()) {
- $this->_lockTables("READ");
- $sql = $this->_createSQLFilter($this->cnf['getUsers'], $filter);
- $sql .= " ".$this->cnf['SortOrder']." LIMIT $limit OFFSET $first";
- $result = $this->_queryDB($sql);
-
- foreach ($result as $user)
- if (($info = $this->_getUserInfo($user['user'])))
- $out[$user['user']] = $info;
-
- $this->_unlockTables();
- $this->_closeDB();
- }
- return $out;
- }
-
- // @inherit function joinGroup($user, $group)
- // @inherit function leaveGroup($user, $group) {
-
- /**
- * Adds a user to a group.
- *
- * If $force is set to '1' non existing groups would be created.
- *
- * The database connection must already be established. Otherwise
- * this function does nothing and returns 'false'.
- *
- * @param $user user to add to a group
- * @param $group name of the group
- * @param $force '1' create missing groups
- * @return bool 'true' on success, 'false' on error
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- * @author Andreas Gohr <andi@splitbrain.org>
- */
- function _addUserToGroup($user, $group, $force=0) {
- $newgroup = 0;
-
- if (($this->dbcon) && ($user)) {
- $gid = $this->_getGroupID($group);
- if (!$gid) {
- if ($force) { // create missing groups
- $sql = str_replace('%{group}',addslashes($group),$this->cnf['addGroup']);
- $this->_modifyDB($sql);
- //group should now exists try again to fetch it
- $gid = $this->_getGroupID($group);
- $newgroup = 1; // group newly created
- }
- }
- if (!$gid) return false; // group didn't exist and can't be created
-
- $sql = $this->cnf['addUserGroup'];
- if(strpos($sql,'%{uid}') !== false){
- $uid = $this->_getUserID($user);
- $sql = str_replace('%{uid}', addslashes($uid), $sql);
- }
- $sql = str_replace('%{user}', addslashes($user),$sql);
- $sql = str_replace('%{gid}', addslashes($gid),$sql);
- $sql = str_replace('%{group}',addslashes($group),$sql);
- if ($this->_modifyDB($sql) !== false) return true;
-
- if ($newgroup) { // remove previously created group on error
- $sql = str_replace('%{gid}', addslashes($gid),$this->cnf['delGroup']);
- $sql = str_replace('%{group}',addslashes($group),$sql);
- $this->_modifyDB($sql);
- }
- }
- return false;
- }
-
- // @inherit function _delUserFromGroup($user $group)
- // @inherit function _getGroups($user)
- // @inherit function _getUserID($user)
-
- /**
- * Adds a new User to the database.
- *
- * The database connection must already be established
- * for this function to work. Otherwise it will return
- * 'false'.
- *
- * @param $user login of the user
- * @param $pwd encrypted password
- * @param $name full name of the user
- * @param $mail email address
- * @param $grps array of groups the user should become member of
- * @return bool
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Chris Smith <chris@jalakai.co.uk>
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function _addUser($user,$pwd,$name,$mail,$grps){
- if($this->dbcon && is_array($grps)) {
- $sql = str_replace('%{user}', addslashes($user),$this->cnf['addUser']);
- $sql = str_replace('%{pass}', addslashes($pwd),$sql);
- $sql = str_replace('%{name}', addslashes($name),$sql);
- $sql = str_replace('%{email}',addslashes($mail),$sql);
- if($this->_modifyDB($sql)){
- $uid = $this->_getUserID($user);
- }else{
- return false;
- }
-
- if ($uid) {
- foreach($grps as $group) {
- $gid = $this->_addUserToGroup($user, $group, 1);
- if ($gid === false) break;
- }
-
- if ($gid) return true;
- else {
- /* remove the new user and all group relations if a group can't
- * be assigned. Newly created groups will remain in the database
- * and won't be removed. This might create orphaned groups but
- * is not a big issue so we ignore this problem here.
- */
- $this->_delUser($user);
- if ($this->cnf['debug'])
- msg("PgSQL err: Adding user '$user' to group '$group' failed.",-1,__LINE__,__FILE__);
- }
- }
- }
- return false;
- }
-
- // @inherit function _delUser($user)
- // @inherit function _getUserInfo($user)
- // @inherit function _updateUserInfo($changes, $uid)
- // @inherit function _getGroupID($group)
-
- /**
- * Opens a connection to a database and saves the handle for further
- * usage in the object. The successful call to this functions is
- * essential for most functions in this object.
- *
- * @return bool
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function _openDB() {
- if (!$this->dbcon) {
- $dsn = $this->cnf['server'] ? 'host='.$this->cnf['server'] : '';
- $dsn .= ' port='.$this->cnf['port'];
- $dsn .= ' dbname='.$this->cnf['database'];
- $dsn .= ' user='.$this->cnf['user'];
- $dsn .= ' password='.$this->cnf['password'];
-
- $con = @pg_connect($dsn);
- if ($con) {
- $this->dbcon = $con;
- return true; // connection and database successfully opened
- } else if ($this->cnf['debug']){
- msg ("PgSQL err: Connection to {$this->cnf['user']}@{$this->cnf['server']} not possible.",
- -1,__LINE__,__FILE__);
- }
- return false; // connection failed
- }
- return true; // connection already open
- }
-
- /**
- * Closes a database connection.
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function _closeDB() {
- if ($this->dbcon) {
- pg_close ($this->dbcon);
- $this->dbcon = 0;
- }
- }
-
- /**
- * Sends a SQL query to the database and transforms the result into
- * an associative array.
- *
- * This function is only able to handle queries that returns a
- * table such as SELECT.
- *
- * @param $query SQL string that contains the query
- * @return array with the result table
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function _queryDB($query) {
- if ($this->dbcon) {
- $result = @pg_query($this->dbcon,$query);
- if ($result) {
- while (($t = pg_fetch_assoc($result)) !== false)
- $resultarray[]=$t;
- pg_free_result ($result);
- return $resultarray;
- }elseif ($this->cnf['debug'])
- msg('PgSQL err: '.pg_last_error($this->dbcon),-1,__LINE__,__FILE__);
- }
- return false;
- }
-
- /**
- * Executes an update or insert query. This differs from the
- * MySQL one because it does NOT return the last insertID
- *
- * @author Andreas Gohr
- */
- function _modifyDB($query) {
- if ($this->dbcon) {
- $result = @pg_query($this->dbcon,$query);
- if ($result) {
- pg_free_result ($result);
- return true;
- }
- if ($this->cnf['debug']){
- msg('PgSQL err: '.pg_last_error($this->dbcon),-1,__LINE__,__FILE__);
- }
- }
- return false;
- }
-
- /**
- * Start a transaction
- *
- * @param $mode could be 'READ' or 'WRITE'
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function _lockTables($mode) {
- if ($this->dbcon) {
- $this->_modifyDB('BEGIN');
- return true;
- }
- return false;
- }
-
- /**
- * Commit a transaction
- *
- * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
- */
- function _unlockTables() {
- if ($this->dbcon) {
- $this->_modifyDB('COMMIT');
- return true;
- }
- return false;
- }
-
- // @inherit function _createSQLFilter($sql, $filter)
-
-
- /**
- * Escape a string for insertion into the database
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @param string $string The string to escape
- * @param boolean $like Escape wildcard chars as well?
- */
- function _escape($string,$like=false){
- $string = pg_escape_string($string);
- if($like){
- $string = addcslashes($string,'%_');
- }
- return $string;
- }
-
-}
-
-//Setup VIM: ex: et ts=2 :
diff --git a/inc/init.php b/inc/init.php
index 9568d9b93..30eb1b251 100644
--- a/inc/init.php
+++ b/inc/init.php
@@ -196,7 +196,7 @@ init_paths();
init_files();
// setup plugin controller class (can be overwritten in preload.php)
-$plugin_types = array('admin','syntax','action','renderer', 'helper','remote');
+$plugin_types = array('auth', 'admin','syntax','action','renderer', 'helper','remote');
global $plugin_controller_class, $plugin_controller;
if (empty($plugin_controller_class)) $plugin_controller_class = 'Doku_Plugin_Controller';
diff --git a/inc/load.php b/inc/load.php
index b8a279523..fbbf020fd 100644
--- a/inc/load.php
+++ b/inc/load.php
@@ -86,6 +86,7 @@ function load_autoload($name){
'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php',
'DokuWiki_Syntax_Plugin' => DOKU_PLUGIN.'syntax.php',
'DokuWiki_Remote_Plugin' => DOKU_PLUGIN.'remote.php',
+ 'DokuWiki_Auth_Plugin' => DOKU_PLUGIN.'auth.php',
);
@@ -95,7 +96,7 @@ function load_autoload($name){
}
// Plugin loading
- if(preg_match('/^(helper|syntax|action|admin|renderer|remote)_plugin_('.DOKU_PLUGIN_NAME_REGEX.')(?:_([^_]+))?$/',
+ if(preg_match('/^(auth|helper|syntax|action|admin|renderer|remote)_plugin_('.DOKU_PLUGIN_NAME_REGEX.')(?:_([^_]+))?$/',
$name, $m)) {
// try to load the wanted plugin file
$c = ((count($m) === 4) ? "/{$m[3]}" : '');
diff --git a/inc/auth/basic.class.php b/lib/plugins/auth.php
index 7c0a5f2c9..637435252 100644
--- a/inc/auth/basic.class.php
+++ b/lib/plugins/auth.php
@@ -1,14 +1,19 @@
<?php
/**
- * auth/basic.class.php
+ * Auth Plugin Prototype
*
* foundation authorisation class
* all auth classes should inherit from this class
*
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Chris Smith <chris@jalakai.co.uk>
+ * @author Jan Schumann <js@jschumann-it.com>
+
*/
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
-class auth_basic {
+class DokuWiki_Auth_Plugin extends DokuWiki_Plugin {
var $success = true;
/**
@@ -397,5 +402,22 @@ class auth_basic {
return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'].'/sessionpurge'));
}
+
+ /**
+ * loadConfig()
+ * merges the plugin's default settings with any local settings
+ * this function is automatically called through getConf()
+ */
+ function loadConfig(){
+ global $conf;
+
+ parent::loadConfig();
+
+ $this->conf['debug'] = $conf['debug'];
+ $this->conf['useacl'] = $conf['useacl'];
+ $this->conf['disableactions'] = $conf['disableactions'];
+ $this->conf['autopasswd'] = $conf['autopasswd'];
+ $this->conf['passcrypt'] = $conf['ssha'];
+ }
+
}
-//Setup VIM: ex: et ts=2 :
diff --git a/inc/auth/ad.class.php b/lib/plugins/authad/auth.php
index a6f3b0513..35c19f471 100644
--- a/inc/auth/ad.class.php
+++ b/lib/plugins/authad/auth.php
@@ -1,4 +1,9 @@
<?php
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+require_once(DOKU_INC.'inc/adLDAP.php');
+
/**
* Active Directory authentication backend for DokuWiki
*
@@ -11,7 +16,7 @@
* $conf['useacl'] = 1;
* $conf['disableactions'] = 'register';
* $conf['autopasswd'] = 0;
- * $conf['authtype'] = 'ad';
+ * $conf['authtype'] = 'authad';
* $conf['passcrypt'] = 'ssha';
*
* $conf['auth']['ad']['account_suffix'] = '
@@ -33,17 +38,18 @@
*
* // get additional information to the userinfo array
* // add a list of comma separated ldap contact fields.
- * $conf['auth']['ad']['additional'] = 'field1,field2';
+ * $conf['plugin']['authad']['additional'] = 'field1,field2';
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author James Van Lommel <jamesvl@gmail.com>
* @link http://www.nosq.com/blog/2005/08/ldap-activedirectory-and-dokuwiki/
* @author Andreas Gohr <andi@splitbrain.org>
+ * @author Jan Schumann <js@schumann-it.com>
*/
require_once(DOKU_INC.'inc/adLDAP/adLDAP.php');
-class auth_ad extends auth_basic {
+class auth_plugin_authad extends DokuWiki_Auth_Plugin {
/**
* @var array copy of the auth backend configuration
*/
@@ -516,5 +522,3 @@ class auth_ad extends auth_basic {
}
}
}
-
-//Setup VIM: ex: et ts=4 :
diff --git a/lib/plugins/authad/plugin.info.txt b/lib/plugins/authad/plugin.info.txt
new file mode 100644
index 000000000..ad565b853
--- /dev/null
+++ b/lib/plugins/authad/plugin.info.txt
@@ -0,0 +1,7 @@
+base authad
+author
+email
+date
+name active directory auth plugin
+desc Provides authentication against a Microsoft Active Directory
+url
diff --git a/inc/auth/ldap.class.php b/lib/plugins/authldap/auth.php
index 23c2c281c..721abb48e 100644
--- a/inc/auth/ldap.class.php
+++ b/lib/plugins/authldap/auth.php
@@ -1,13 +1,16 @@
<?php
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
/**
* LDAP authentication backend
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
* @author Chris Smith <chris@jalakaic.co.uk>
+ * @author Jan Schumann <js@schumann-it.com>
*/
-
-class auth_ldap extends auth_basic {
+class auth_plugin_authldap extends DokuWiki_Auth_Plugin {
var $cnf = null;
var $con = null;
var $bound = 0; // 0: anonymous, 1: user, 2: superuser
@@ -482,5 +485,3 @@ class auth_ldap extends auth_basic {
}
}
}
-
-//Setup VIM: ex: et ts=4 :
diff --git a/lib/plugins/authldap/plugin.info.txt b/lib/plugins/authldap/plugin.info.txt
new file mode 100644
index 000000000..c36385224
--- /dev/null
+++ b/lib/plugins/authldap/plugin.info.txt
@@ -0,0 +1,7 @@
+base authldap
+author
+email
+date
+name ldap auth plugin
+desc Provides authentication against am LDAP server
+url
diff --git a/inc/auth/mysql.class.php b/lib/plugins/authmysql/auth.php
index 9dcf82a87..8a8f9a488 100644
--- a/inc/auth/mysql.class.php
+++ b/lib/plugins/authmysql/auth.php
@@ -1,4 +1,7 @@
<?php
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
/**
* MySQLP authentication backend
*
@@ -6,10 +9,9 @@
* @author Andreas Gohr <andi@splitbrain.org>
* @author Chris Smith <chris@jalakai.co.uk>
* @author Matthias Grimm <matthias.grimmm@sourceforge.net>
+ * @author Jan Schumann <js@schumann-it.com>
*/
-
-class auth_mysql extends auth_basic {
-
+class auth_plugin_authmysql extends DokuWiki_Auth_Plugin {
var $dbcon = 0;
var $dbver = 0; // database version
var $dbrev = 0; // database revision
@@ -943,5 +945,3 @@ class auth_mysql extends auth_basic {
return $string;
}
}
-
-//Setup VIM: ex: et ts=2 :
diff --git a/lib/plugins/authmysql/plugin.info.txt b/lib/plugins/authmysql/plugin.info.txt
new file mode 100644
index 000000000..d08d4a7ef
--- /dev/null
+++ b/lib/plugins/authmysql/plugin.info.txt
@@ -0,0 +1,7 @@
+base authmysql
+author
+email
+date
+name mysql auth plugin
+desc Provides authentication against a MySQL Server
+url
diff --git a/lib/plugins/authpgsql/auth.php b/lib/plugins/authpgsql/auth.php
new file mode 100644
index 000000000..824a77882
--- /dev/null
+++ b/lib/plugins/authpgsql/auth.php
@@ -0,0 +1,331 @@
+<?php
+/**
+ * Plugin auth provider
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Jan Schumann <js@schumann-it.com>
+ */
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+/**
+ * PgSQL authentication backend
+ *
+ * This class inherits much functionality from the MySQL class
+ * and just reimplements the Postgres specific parts.
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Chris Smith <chris@jalakai.co.uk>
+ * @author Matthias Grimm <matthias.grimmm@sourceforge.net>
+ * @author Jan Schumann <js@schumann-it.com>
+*/
+class auth_plugin_authpgsql extends auth_plugin_authmysql
+{
+ var $cnf = null;
+ var $opts = null;
+ var $adldap = null;
+ var $users = null;
+
+ /**
+ * Constructor
+ */
+ function auth_plugin_authpgsql() {
+ global $conf;
+ $this->cnf = $conf['auth']['ad'];
+
+
+ // additional information fields
+ if (isset($this->cnf['additional'])) {
+ $this->cnf['additional'] = str_replace(' ', '', $this->cnf['additional']);
+ $this->cnf['additional'] = explode(',', $this->cnf['additional']);
+ } else $this->cnf['additional'] = array();
+
+ // ldap extension is needed
+ if (!function_exists('ldap_connect')) {
+ if ($this->cnf['debug'])
+ msg("AD Auth: PHP LDAP extension not found.",-1);
+ $this->success = false;
+ return;
+ }
+
+ // Prepare SSO
+ if($_SERVER['REMOTE_USER'] && $this->cnf['sso']){
+ // remove possible NTLM domain
+ list($dom,$usr) = explode('\\',$_SERVER['REMOTE_USER'],2);
+ if(!$usr) $usr = $dom;
+
+ // remove possible Kerberos domain
+ list($usr,$dom) = explode('@',$usr);
+
+ $dom = strtolower($dom);
+ $_SERVER['REMOTE_USER'] = $usr;
+
+ // we need to simulate a login
+ if(empty($_COOKIE[DOKU_COOKIE])){
+ $_REQUEST['u'] = $_SERVER['REMOTE_USER'];
+ $_REQUEST['p'] = 'sso_only';
+ }
+ }
+
+ // prepare adLDAP standard configuration
+ $this->opts = $this->cnf;
+
+ // add possible domain specific configuration
+ if($dom && is_array($this->cnf[$dom])) foreach($this->cnf[$dom] as $key => $val){
+ $this->opts[$key] = $val;
+ }
+
+ // handle multiple AD servers
+ $this->opts['domain_controllers'] = explode(',',$this->opts['domain_controllers']);
+ $this->opts['domain_controllers'] = array_map('trim',$this->opts['domain_controllers']);
+ $this->opts['domain_controllers'] = array_filter($this->opts['domain_controllers']);
+
+ // we can change the password if SSL is set
+ if($this->opts['use_ssl'] || $this->opts['use_tls']){
+ $this->cando['modPass'] = true;
+ }
+ $this->cando['modName'] = true;
+ $this->cando['modMail'] = true;
+ }
+
+ /**
+ * Check user+password [required auth function]
+ *
+ * Checks if the given user exists and the given
+ * plaintext password is correct by trying to bind
+ * to the LDAP server
+ *
+ * @author James Van Lommel <james@nosq.com>
+ * @return bool
+ */
+ function checkPass($user, $pass){
+ if($_SERVER['REMOTE_USER'] &&
+ $_SERVER['REMOTE_USER'] == $user &&
+ $this->cnf['sso']) return true;
+
+ if(!$this->_init()) return false;
+ return $this->adldap->authenticate($user, $pass);
+ }
+
+ /**
+ * Return user info [required auth function]
+ *
+ * Returns info about the given user needs to contain
+ * at least these fields:
+ *
+ * name string full name of the user
+ * mail string email address of the user
+ * grps array list of groups the user is in
+ *
+ * This LDAP specific function returns the following
+ * addional fields:
+ *
+ * dn string distinguished name (DN)
+ * uid string Posix User ID
+ *
+ * @author James Van Lommel <james@nosq.com>
+ */
+ function getUserData($user){
+ global $conf;
+ if(!$this->_init()) return false;
+
+ $fields = array('mail','displayname','samaccountname');
+
+ // add additional fields to read
+ $fields = array_merge($fields, $this->cnf['additional']);
+ $fields = array_unique($fields);
+
+ //get info for given user
+ $result = $this->adldap->user_info($user, $fields);
+ //general user info
+ $info['name'] = $result[0]['displayname'][0];
+ $info['mail'] = $result[0]['mail'][0];
+ $info['uid'] = $result[0]['samaccountname'][0];
+ $info['dn'] = $result[0]['dn'];
+
+ // additional information
+ foreach ($this->cnf['additional'] as $field) {
+ if (isset($result[0][strtolower($field)])) {
+ $info[$field] = $result[0][strtolower($field)][0];
+ }
+ }
+
+ // handle ActiveDirectory memberOf
+ $info['grps'] = $this->adldap->user_groups($user,(bool) $this->opts['recursive_groups']);
+
+ if (is_array($info['grps'])) {
+ foreach ($info['grps'] as $ndx => $group) {
+ $info['grps'][$ndx] = $this->cleanGroup($group);
+ }
+ }
+
+ // always add the default group to the list of groups
+ if(!is_array($info['grps']) || !in_array($conf['defaultgroup'],$info['grps'])){
+ $info['grps'][] = $conf['defaultgroup'];
+ }
+
+ return $info;
+ }
+
+ /**
+ * Make AD group names usable by DokuWiki.
+ *
+ * Removes backslashes ('\'), pound signs ('#'), and converts spaces to underscores.
+ *
+ * @author James Van Lommel (jamesvl@gmail.com)
+ */
+ function cleanGroup($name) {
+ $sName = str_replace('\\', '', $name);
+ $sName = str_replace('#', '', $sName);
+ $sName = preg_replace('[\s]', '_', $sName);
+ return $sName;
+ }
+
+ /**
+ * Sanitize user names
+ */
+ function cleanUser($name) {
+ return $this->cleanGroup($name);
+ }
+
+ /**
+ * Most values in LDAP are case-insensitive
+ */
+ function isCaseSensitive(){
+ return false;
+ }
+
+ /**
+ * Bulk retrieval of user data
+ *
+ * @author Dominik Eckelmann <dokuwiki@cosmocode.de>
+ * @param start index of first user to be returned
+ * @param limit max number of users to be returned
+ * @param filter array of field/pattern pairs, null for no filter
+ * @return array of userinfo (refer getUserData for internal userinfo details)
+ */
+ function retrieveUsers($start=0,$limit=-1,$filter=array()) {
+ if(!$this->_init()) return false;
+
+ if ($this->users === null) {
+ //get info for given user
+ $result = $this->adldap->all_users();
+ if (!$result) return array();
+ $this->users = array_fill_keys($result, false);
+ }
+
+ $i = 0;
+ $count = 0;
+ $this->_constructPattern($filter);
+ $result = array();
+
+ foreach ($this->users as $user => &$info) {
+ if ($i++ < $start) {
+ continue;
+ }
+ if ($info === false) {
+ $info = $this->getUserData($user);
+ }
+ if ($this->_filter($user, $info)) {
+ $result[$user] = $info;
+ if (($limit >= 0) && (++$count >= $limit)) break;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Modify user data
+ *
+ * @param $user nick of the user to be changed
+ * @param $changes array of field/value pairs to be changed
+ * @return bool
+ */
+ function modifyUser($user, $changes) {
+ $return = true;
+
+ // password changing
+ if(isset($changes['pass'])){
+ try {
+ $return = $this->adldap->user_password($user,$changes['pass']);
+ } catch (adLDAPException $e) {
+ if ($this->cnf['debug']) msg('AD Auth: '.$e->getMessage(), -1);
+ $return = false;
+ }
+ if(!$return) msg('AD Auth: failed to change the password. Maybe the password policy was not met?',-1);
+ }
+
+ // changing user data
+ $adchanges = array();
+ if(isset($changes['name'])){
+ // get first and last name
+ $parts = explode(' ',$changes['name']);
+ $adchanges['surname'] = array_pop($parts);
+ $adchanges['firstname'] = join(' ',$parts);
+ $adchanges['display_name'] = $changes['name'];
+ }
+ if(isset($changes['mail'])){
+ $adchanges['email'] = $changes['mail'];
+ }
+ if(count($adchanges)){
+ try {
+ $return = $return & $this->adldap->user_modify($user,$adchanges);
+ } catch (adLDAPException $e) {
+ if ($this->cnf['debug']) msg('AD Auth: '.$e->getMessage(), -1);
+ $return = false;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Initialize the AdLDAP library and connect to the server
+ */
+ function _init(){
+ if(!is_null($this->adldap)) return true;
+
+ // connect
+ try {
+ $this->adldap = new adLDAP($this->opts);
+ if (isset($this->opts['ad_username']) && isset($this->opts['ad_password'])) {
+ $this->canDo['getUsers'] = true;
+ }
+ return true;
+ } catch (adLDAPException $e) {
+ if ($this->cnf['debug']) {
+ msg('AD Auth: '.$e->getMessage(), -1);
+ }
+ $this->success = false;
+ $this->adldap = null;
+ }
+ return false;
+ }
+
+ /**
+ * return 1 if $user + $info match $filter criteria, 0 otherwise
+ *
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+ function _filter($user, $info) {
+ foreach ($this->_pattern as $item => $pattern) {
+ if ($item == 'user') {
+ if (!preg_match($pattern, $user)) return 0;
+ } else if ($item == 'grps') {
+ if (!count(preg_grep($pattern, $info['grps']))) return 0;
+ } else {
+ if (!preg_match($pattern, $info[$item])) return 0;
+ }
+ }
+ return 1;
+ }
+
+ function _constructPattern($filter) {
+ $this->_pattern = array();
+ foreach ($filter as $item => $pattern) {
+// $this->_pattern[$item] = '/'.preg_quote($pattern,"/").'/i'; // don't allow regex characters
+ $this->_pattern[$item] = '/'.str_replace('/','\/',$pattern).'/i'; // allow regex characters
+ }
+ }
+} \ No newline at end of file
diff --git a/lib/plugins/authpgsql/plugin.info.txt b/lib/plugins/authpgsql/plugin.info.txt
new file mode 100644
index 000000000..ad565b853
--- /dev/null
+++ b/lib/plugins/authpgsql/plugin.info.txt
@@ -0,0 +1,7 @@
+base authad
+author
+email
+date
+name active directory auth plugin
+desc Provides authentication against a Microsoft Active Directory
+url
diff --git a/inc/auth/plain.class.php b/lib/plugins/authplain/auth.php
index e682d2522..570d029ff 100644
--- a/inc/auth/plain.class.php
+++ b/lib/plugins/authplain/auth.php
@@ -1,14 +1,16 @@
<?php
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
/**
* Plaintext authentication backend
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
* @author Chris Smith <chris@jalakai.co.uk>
+ * @author Jan Schumann <js@schumann-it.com>
*/
-
-class auth_plain extends auth_basic {
-
+class auth_plugin_authplain extends DokuWiki_Auth_Plugin {
var $users = null;
var $_pattern = array();
@@ -323,6 +325,4 @@ class auth_plain extends auth_basic {
$this->_pattern[$item] = '/'.str_replace('/','\/',$pattern).'/i'; // allow regex characters
}
}
-}
-
-//Setup VIM: ex: et ts=2 :
+} \ No newline at end of file
diff --git a/lib/plugins/authplain/plugin.info.txt b/lib/plugins/authplain/plugin.info.txt
new file mode 100644
index 000000000..3273e21d7
--- /dev/null
+++ b/lib/plugins/authplain/plugin.info.txt
@@ -0,0 +1,7 @@
+base authplain
+author
+email
+date
+name auth plugin
+desc Provides authentication against local password storage
+url
diff --git a/lib/plugins/config/settings/extra.class.php b/lib/plugins/config/settings/extra.class.php
index b4e35b1cc..f6adf1c18 100644
--- a/lib/plugins/config/settings/extra.class.php
+++ b/lib/plugins/config/settings/extra.class.php
@@ -43,17 +43,54 @@ if (!class_exists('setting_authtype')) {
class setting_authtype extends setting_multichoice {
function initialize($default,$local,$protected) {
+ global $plugin_controller;
- // populate $this->_choices with a list of available auth mechanisms
- $authtypes = glob(DOKU_INC.'inc/auth/*.class.php');
- $authtypes = preg_replace('#^.*/([^/]*)\.class\.php$#i','$1', $authtypes);
- $authtypes = array_diff($authtypes, array('basic'));
- sort($authtypes);
-
- $this->_choices = $authtypes;
+ // retrive auth types provided by plugins
+ foreach ($plugin_controller->getList('auth') as $plugin) {
+ $this->_choices[] = $plugin;
+ }
parent::initialize($default,$local,$protected);
}
+
+ function update($input) {
+ global $plugin_controller;
+
+ // is an update posible?
+ $mayUpdate = parent::update($input);
+
+ // is it an auth plugin?
+ if (in_array($input, $plugin_controller->getList('auth'))) {
+ // reject disabled plugins
+ if ($plugin_controller->isdisabled($input)) {
+ $this->_error = true;
+ msg('Auth type ' . $input . ' is disabled.');
+ return false;
+ }
+
+ // load the plugin
+ $auth_plugin = $plugin_controller->load('auth', $input);
+
+ // @TODO: throw an error in plugin controller instead of returning null
+ if (is_null($auth_plugin)) {
+ $this->_error = true;
+ msg('Cannot load Auth Plugin "' . $input . '"');
+ return false;
+ }
+
+ // verify proper instanciation (is this really a plugin?) @TODO use instanceof? impement interface?
+ if (is_object($auth_plugin) && !method_exists($auth_plugin, 'getPluginName')) {
+ $this->_error = true;
+ msg('Cannot create Auth Plugin "' . $input . '"');
+ return false;
+ }
+ }
+
+ msg('Successfully changed auth system. Please re-login.');
+ auth_logoff();
+
+ return true;
+ }
}
}