From f4476bd9b5badd36cd0617d76538e47d9649986b Mon Sep 17 00:00:00 2001 From: Jan Schumann Date: Mon, 20 Feb 2012 19:51:26 +0100 Subject: Refactored auth system: All auth methods are now introduced as plugins. --- lib/plugins/authpgsql/auth.php | 331 ++++++++++++++++++++++++++++++++++ lib/plugins/authpgsql/plugin.info.txt | 7 + 2 files changed, 338 insertions(+) create mode 100644 lib/plugins/authpgsql/auth.php create mode 100644 lib/plugins/authpgsql/plugin.info.txt (limited to 'lib/plugins/authpgsql') 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 @@ + + */ +// 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 + * @author Chris Smith + * @author Matthias Grimm + * @author Jan Schumann +*/ +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 + * @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 + */ + 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 + * @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 + */ + 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 -- cgit v1.2.3 From 94c0297d119ce52ad794c18f26220311e3c0ed8c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 6 Oct 2012 11:31:26 +0200 Subject: completed plugin.info.txt files --- lib/plugins/authpgsql/plugin.info.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/plugin.info.txt b/lib/plugins/authpgsql/plugin.info.txt index ad565b853..598eb848b 100644 --- a/lib/plugins/authpgsql/plugin.info.txt +++ b/lib/plugins/authpgsql/plugin.info.txt @@ -1,7 +1,7 @@ base authad -author -email -date +author Andreas Gohr +email andi@splitbrain.org +date 2012-10-06 name active directory auth plugin desc Provides authentication against a Microsoft Active Directory -url +url http://www.dokuwiki.org/plugin:authad -- cgit v1.2.3 From 454d868b911059adb8889a2d6afefa016d6a21f5 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Nov 2012 14:04:41 +0100 Subject: make all sub auth classes call the parent constructor This does nothing currently but allows us adding certain things to the base class later. --- lib/plugins/authpgsql/auth.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/auth.php b/lib/plugins/authpgsql/auth.php index 824a77882..46154b6ca 100644 --- a/lib/plugins/authpgsql/auth.php +++ b/lib/plugins/authpgsql/auth.php @@ -31,6 +31,8 @@ class auth_plugin_authpgsql extends auth_plugin_authmysql * Constructor */ function auth_plugin_authpgsql() { + parent::__construct(); + global $conf; $this->cnf = $conf['auth']['ad']; -- cgit v1.2.3 From 4476793e4f72ca2d73ff618d3eb009e8b430f7f2 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Nov 2012 17:11:10 +0100 Subject: authpgsql fixes * fixes merge messup (code was made up from parts of authad) * code and PHP5 cleanup --- lib/plugins/authpgsql/auth.php | 561 +++++++++++++++++++-------------- lib/plugins/authpgsql/conf/default.php | 3 + 2 files changed, 326 insertions(+), 238 deletions(-) create mode 100644 lib/plugins/authpgsql/conf/default.php (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/auth.php b/lib/plugins/authpgsql/auth.php index 46154b6ca..3f8ff3249 100644 --- a/lib/plugins/authpgsql/auth.php +++ b/lib/plugins/authpgsql/auth.php @@ -1,15 +1,9 @@ - */ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); /** - * PgSQL authentication backend + * PostgreSQL authentication backend * * This class inherits much functionality from the MySQL class * and just reimplements the Postgres specific parts. @@ -19,315 +13,406 @@ if(!defined('DOKU_INC')) die(); * @author Chris Smith * @author Matthias Grimm * @author Jan Schumann -*/ -class auth_plugin_authpgsql extends auth_plugin_authmysql -{ - var $cnf = null; - var $opts = null; - var $adldap = null; - var $users = null; + */ +class auth_plugin_authpgsql extends auth_plugin_authmysql { /** * Constructor + * + * checks if the pgsql interface is available, otherwise it will + * set the variable $success of the basis class to false + * + * @author Matthias Grimm + * @author Andreas Gohr */ - function auth_plugin_authpgsql() { - parent::__construct(); - - global $conf; - $this->cnf = $conf['auth']['ad']; + public function __construct() { + // we don't want the stuff the MySQL constructor does, but the grandparent might do something + DokuWiki_Auth_Plugin::__construct(); - - // 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); + if(!function_exists('pg_connect')) { + $this->_debug("PgSQL err: PHP Postgres extension not found.", -1, __LINE__, __FILE__); $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); + $this->loadConfig(); - $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'; - } + // set capabilities based upon config strings set + if(empty($this->conf['user']) || + empty($this->conf['password']) || empty($this->conf['database']) + ) { + $this->_debug("PgSQL err: insufficient configuration.", -1, __LINE__, __FILE__); + $this->success = false; + return; } - // prepare adLDAP standard configuration - $this->opts = $this->cnf; + $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')); + } - // add possible domain specific configuration - if($dom && is_array($this->cnf[$dom])) foreach($this->cnf[$dom] as $key => $val){ - $this->opts[$key] = $val; + /** + * Check if the given config strings are set + * + * @author Matthias Grimm + * + * @param array $keys + * @param bool $wop + * @return bool + */ + protected function _chkcnf($keys, $wop = false) { + foreach($keys as $key) { + if(empty($this->conf[$key])) return false; } + return true; + } - // 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']); + /** + * Counts users which meet certain $filter criteria. + * + * @author Matthias Grimm + * + * @param array $filter filter criteria in item/pattern pairs + * @return int count of found users. + */ + public function getUserCount($filter = array()) { + $rc = 0; - // we can change the password if SSL is set - if($this->opts['use_ssl'] || $this->opts['use_tls']){ - $this->cando['modPass'] = true; + if($this->_openDB()) { + $sql = $this->_createSQLFilter($this->conf['getUsers'], $filter); + + // no equivalent of SQL_CALC_FOUND_ROWS in pgsql? + if(($result = $this->_queryDB($sql))) { + $rc = count($result); + } + $this->_closeDB(); } - $this->cando['modName'] = true; - $this->cando['modMail'] = true; + return $rc; } /** - * Check user+password [required auth function] + * Bulk retrieval of user data * - * Checks if the given user exists and the given - * plaintext password is correct by trying to bind - * to the LDAP server + * @author Matthias Grimm * - * @author James Van Lommel - * @return bool + * @param int $first index of first user to be returned + * @param int $limit max number of users to be returned + * @param array $filter array of field/pattern pairs + * @return array userinfo (refer getUserData for internal userinfo details) */ - function checkPass($user, $pass){ - if($_SERVER['REMOTE_USER'] && - $_SERVER['REMOTE_USER'] == $user && - $this->cnf['sso']) return true; + public function retrieveUsers($first = 0, $limit = 10, $filter = array()) { + $out = array(); + + if($this->_openDB()) { + $this->_lockTables("READ"); + $sql = $this->_createSQLFilter($this->conf['getUsers'], $filter); + $sql .= " ".$this->conf['SortOrder']." LIMIT $limit OFFSET $first"; + $result = $this->_queryDB($sql); + + foreach($result as $user) + if(($info = $this->_getUserInfo($user['user']))) + $out[$user['user']] = $info; - if(!$this->_init()) return false; - return $this->adldap->authenticate($user, $pass); + $this->_unlockTables(); + $this->_closeDB(); + } + return $out; } + // @inherit function joinGroup($user, $group) + // @inherit function leaveGroup($user, $group) { + /** - * Return user info [required auth function] + * Adds a user to a group. * - * Returns info about the given user needs to contain - * at least these fields: + * If $force is set to true non existing groups would be created. * - * name string full name of the user - * mail string email address of the user - * grps array list of groups the user is in + * The database connection must already be established. Otherwise + * this function does nothing and returns 'false'. * - * This LDAP specific function returns the following - * addional fields: + * @author Matthias Grimm + * @author Andreas Gohr * - * dn string distinguished name (DN) - * uid string Posix User ID - * - * @author James Van Lommel + * @param string $user user to add to a group + * @param string $group name of the group + * @param bool $force create missing groups + * @return bool true on success, false on error */ - 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]; + protected function _addUserToGroup($user, $group, $force = false) { + $newgroup = 0; + + if(($this->dbcon) && ($user)) { + $gid = $this->_getGroupID($group); + if(!$gid) { + if($force) { // create missing groups + $sql = str_replace('%{group}', addslashes($group), $this->conf['addGroup']); + $this->_modifyDB($sql); + //group should now exists try again to fetch it + $gid = $this->_getGroupID($group); + $newgroup = 1; // group newly created + } } - } - - // handle ActiveDirectory memberOf - $info['grps'] = $this->adldap->user_groups($user,(bool) $this->opts['recursive_groups']); + if(!$gid) return false; // group didn't exist and can't be created - if (is_array($info['grps'])) { - foreach ($info['grps'] as $ndx => $group) { - $info['grps'][$ndx] = $this->cleanGroup($group); + $sql = $this->conf['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->conf['delGroup']); + $sql = str_replace('%{group}', addslashes($group), $sql); + $this->_modifyDB($sql); } } - - // 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; + return false; } + // @inherit function _delUserFromGroup($user $group) + // @inherit function _getGroups($user) + // @inherit function _getUserID($user) + /** - * Make AD group names usable by DokuWiki. + * Adds a new User to the database. * - * Removes backslashes ('\'), pound signs ('#'), and converts spaces to underscores. + * The database connection must already be established + * for this function to work. Otherwise it will return + * 'false'. * - * @author James Van Lommel (jamesvl@gmail.com) + * @param string $user login of the user + * @param string $pwd encrypted password + * @param string $name full name of the user + * @param string $mail email address + * @param array $grps array of groups the user should become member of + * @return bool + * + * @author Andreas Gohr + * @author Chris Smith + * @author Matthias Grimm */ - function cleanGroup($name) { - $sName = str_replace('\\', '', $name); - $sName = str_replace('#', '', $sName); - $sName = preg_replace('[\s]', '_', $sName); - return $sName; + protected function _addUser($user, $pwd, $name, $mail, $grps) { + if($this->dbcon && is_array($grps)) { + $sql = str_replace('%{user}', addslashes($user), $this->conf['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; + } + + $group = ''; + $gid = false; + + if($uid) { + foreach($grps as $group) { + $gid = $this->_addUserToGroup($user, $group, 1); + if($gid === false) break; + } + + if($gid !== false){ + 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); + $this->_debug("PgSQL err: Adding user '$user' to group '$group' failed.", -1, __LINE__, __FILE__); + } + } + } + return false; } /** - * Sanitize user names + * 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. + * + * @author Matthias Grimm + * + * @return bool */ - function cleanUser($name) { - return $this->cleanGroup($name); + protected function _openDB() { + if(!$this->dbcon) { + $dsn = $this->conf['server'] ? 'host='.$this->conf['server'] : ''; + $dsn .= ' port='.$this->conf['port']; + $dsn .= ' dbname='.$this->conf['database']; + $dsn .= ' user='.$this->conf['user']; + $dsn .= ' password='.$this->conf['password']; + + $con = @pg_connect($dsn); + if($con) { + $this->dbcon = $con; + return true; // connection and database successfully opened + } else { + $this->_debug( + "PgSQL err: Connection to {$this->conf['user']}@{$this->conf['server']} not possible.", + -1, __LINE__, __FILE__ + ); + } + return false; // connection failed + } + return true; // connection already open } /** - * Most values in LDAP are case-insensitive + * Closes a database connection. + * + * @author Matthias Grimm */ - function isCaseSensitive(){ - return false; + protected function _closeDB() { + if($this->dbcon) { + pg_close($this->dbcon); + $this->dbcon = 0; + } } /** - * Bulk retrieval of user data + * Sends a SQL query to the database and transforms the result into + * an associative array. * - * @author Dominik Eckelmann - * @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) + * This function is only able to handle queries that returns a + * table such as SELECT. + * + * @author Matthias Grimm + * + * @param string $query SQL string that contains the query + * @return array the result table */ - 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; + protected function _queryDB($query) { + $resultarray = array(); + 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; + } else{ + $this->_debug('PgSQL err: '.pg_last_error($this->dbcon), -1, __LINE__, __FILE__); } } - return $result; + return false; } /** - * Modify user data + * Executes an update or insert query. This differs from the + * MySQL one because it does NOT return the last insertID * - * @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; + * @author Andreas Gohr + */ + protected function _modifyDB($query) { + if($this->dbcon) { + $result = @pg_query($this->dbcon, $query); + if($result) { + pg_free_result($result); + return true; } + $this->_debug('PgSQL err: '.pg_last_error($this->dbcon), -1, __LINE__, __FILE__); } - - return $return; + return false; } /** - * Initialize the AdLDAP library and connect to the server + * Start a transaction + * + * @author Matthias Grimm + * + * @param string $mode could be 'READ' or 'WRITE' + * @return bool */ - 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; - } + protected function _lockTables($mode) { + if($this->dbcon) { + $this->_modifyDB('BEGIN'); 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 + * Commit a transaction * - * @author Chris Smith + * @author Matthias Grimm */ - 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; - } + protected function _unlockTables() { + if($this->dbcon) { + $this->_modifyDB('COMMIT'); + return true; } - return 1; + return false; } - 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 + /** + * Escape a string for insertion into the database + * + * @author Andreas Gohr + * + * @param string $string The string to escape + * @param bool $like Escape wildcard chars as well? + * @return string + */ + protected function _escape($string, $like = false) { + $string = pg_escape_string($string); + if($like) { + $string = addcslashes($string, '%_'); } + return $string; } } \ No newline at end of file diff --git a/lib/plugins/authpgsql/conf/default.php b/lib/plugins/authpgsql/conf/default.php new file mode 100644 index 000000000..401da80b7 --- /dev/null +++ b/lib/plugins/authpgsql/conf/default.php @@ -0,0 +1,3 @@ + Date: Sat, 2 Feb 2013 18:28:59 +0100 Subject: added config metadata for authpgsql plugin --- lib/plugins/authpgsql/conf/metadata.php | 33 ++++++++++++++++++++++++++++++ lib/plugins/authpgsql/lang/en/settings.php | 33 ++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 lib/plugins/authpgsql/conf/metadata.php create mode 100644 lib/plugins/authpgsql/lang/en/settings.php (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/conf/metadata.php b/lib/plugins/authpgsql/conf/metadata.php new file mode 100644 index 000000000..d52a17865 --- /dev/null +++ b/lib/plugins/authpgsql/conf/metadata.php @@ -0,0 +1,33 @@ + Date: Tue, 5 Feb 2013 13:55:30 +0100 Subject: fixed authpg plugin info --- lib/plugins/authpgsql/plugin.info.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/plugin.info.txt b/lib/plugins/authpgsql/plugin.info.txt index 598eb848b..9699d3365 100644 --- a/lib/plugins/authpgsql/plugin.info.txt +++ b/lib/plugins/authpgsql/plugin.info.txt @@ -1,7 +1,7 @@ -base authad +base authpg author Andreas Gohr email andi@splitbrain.org date 2012-10-06 -name active directory auth plugin -desc Provides authentication against a Microsoft Active Directory -url http://www.dokuwiki.org/plugin:authad +name PostgreSQL auth plugin +desc Provides authentication against a PostgreSQL database +url http://www.dokuwiki.org/plugin:authpg -- cgit v1.2.3 From ed2c6a71b7c05ed9ffb9031519900a6bd9e64d0a Mon Sep 17 00:00:00 2001 From: Klap-in Date: Tue, 5 Feb 2013 20:15:04 +0100 Subject: use consistent name for authpgsql --- lib/plugins/authpgsql/plugin.info.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/plugin.info.txt b/lib/plugins/authpgsql/plugin.info.txt index 9699d3365..ad71771b4 100644 --- a/lib/plugins/authpgsql/plugin.info.txt +++ b/lib/plugins/authpgsql/plugin.info.txt @@ -1,7 +1,7 @@ -base authpg +base authpgsql author Andreas Gohr email andi@splitbrain.org date 2012-10-06 name PostgreSQL auth plugin desc Provides authentication against a PostgreSQL database -url http://www.dokuwiki.org/plugin:authpg +url http://www.dokuwiki.org/plugin:authpgsql -- cgit v1.2.3 From 45970804e69e3d087fe19ad9cefaff0ef44be795 Mon Sep 17 00:00:00 2001 From: Klap-in Date: Sat, 16 Feb 2013 22:53:38 +0100 Subject: Complete metadata and defaults of auth plugin configs --- lib/plugins/authpgsql/conf/default.php | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/conf/default.php b/lib/plugins/authpgsql/conf/default.php index 401da80b7..7f78280f9 100644 --- a/lib/plugins/authpgsql/conf/default.php +++ b/lib/plugins/authpgsql/conf/default.php @@ -1,3 +1,33 @@ Date: Sun, 24 Feb 2013 10:36:18 +0100 Subject: Italian language update --- lib/plugins/authpgsql/lang/it/settings.php | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 lib/plugins/authpgsql/lang/it/settings.php (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/lang/it/settings.php b/lib/plugins/authpgsql/lang/it/settings.php new file mode 100644 index 000000000..10ae72f87 --- /dev/null +++ b/lib/plugins/authpgsql/lang/it/settings.php @@ -0,0 +1,5 @@ + Date: Sun, 24 Feb 2013 10:37:45 +0100 Subject: Simplified Chinese language update --- lib/plugins/authpgsql/lang/zh/settings.php | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 lib/plugins/authpgsql/lang/zh/settings.php (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/lang/zh/settings.php b/lib/plugins/authpgsql/lang/zh/settings.php new file mode 100644 index 000000000..dc7223d89 --- /dev/null +++ b/lib/plugins/authpgsql/lang/zh/settings.php @@ -0,0 +1,37 @@ + + */ +$lang['server'] = '您的 PostgreSQL 服务器'; +$lang['port'] = '您的 PostgreSQL 服务器端口'; +$lang['user'] = 'PostgreSQL 用户名'; +$lang['password'] = '上述用户的密码'; +$lang['database'] = '使用的数据库'; +$lang['debug'] = '显示额外调试信息'; +$lang['forwardClearPass'] = '将用户密码以明文形式传送给下面的 SQL 语句,而不使用 passcrypt 密码加密选项'; +$lang['checkPass'] = '检查密码的 SQL 语句'; +$lang['getUserInfo'] = '获取用户信息的 SQL 语句'; +$lang['getGroups'] = '获取用户的组成员身份的 SQL 语句'; +$lang['getUsers'] = '列出所有用户的 SQL 语句'; +$lang['FilterLogin'] = '根据登录名筛选用户的 SQL 子句'; +$lang['FilterName'] = '根据全名筛选用户的 SQL 子句'; +$lang['FilterEmail'] = '根据电子邮件地址筛选用户的 SQL 子句'; +$lang['FilterGroup'] = '根据组成员身份筛选用户的 SQL 子句'; +$lang['SortOrder'] = '对用户排序的 SQL 子句'; +$lang['addUser'] = '添加新用户的 SQL 语句'; +$lang['addGroup'] = '添加新组的 SQL 语句'; +$lang['addUserGroup'] = '将用户添加到现有组的 SQL 语句'; +$lang['delGroup'] = '删除组的 SQL 语句'; +$lang['getUserID'] = '获取用户主键的 SQL 语句'; +$lang['delUser'] = '删除用户的 SQL 语句'; +$lang['delUserRefs'] = '从所有组中删除一个用户的 SQL 语句'; +$lang['updateUser'] = '更新用户信息的 SQL 语句'; +$lang['UpdateLogin'] = '更新用户登录名的 Update 子句'; +$lang['UpdatePass'] = '更新用户密码的 Update 子句'; +$lang['UpdateEmail'] = '更新用户电子邮件地址的 Update 子句'; +$lang['UpdateName'] = '更新用户全名的 Update 子句'; +$lang['UpdateTarget'] = '更新时识别用户的 Limit 子句'; +$lang['delUserGroup'] = '从指定组删除用户的 SQL 语句'; +$lang['getGroupID'] = '获取指定组主键的 SQL 语句'; -- cgit v1.2.3 From 338ac38c748d94f32ca394dc604dda97ce6762e3 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 24 Feb 2013 10:39:52 +0100 Subject: fixed typos --- lib/plugins/authpgsql/lang/en/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/authpgsql') diff --git a/lib/plugins/authpgsql/lang/en/settings.php b/lib/plugins/authpgsql/lang/en/settings.php index 74a1c1cc9..8c048fa0f 100644 --- a/lib/plugins/authpgsql/lang/en/settings.php +++ b/lib/plugins/authpgsql/lang/en/settings.php @@ -20,7 +20,7 @@ $lang['addUser'] = 'SQL statement to add a new user'; $lang['addGroup'] = 'SQL statement to add a new group'; $lang['addUserGroup'] = 'SQL statment to add a user to an existing group'; $lang['delGroup'] = 'SQL statement to remove a group'; -$lang['getUserID'] = 'SQL statement to get the primary ey of a user'; +$lang['getUserID'] = 'SQL statement to get the primary key of a user'; $lang['delUser'] = 'SQL statement to delete a user'; $lang['delUserRefs'] = 'SQL statement to remove a user from all groups'; $lang['updateUser'] = 'SQL statement to update a user profile'; -- cgit v1.2.3