summaryrefslogtreecommitdiff
path: root/inc/auth
diff options
context:
space:
mode:
Diffstat (limited to 'inc/auth')
-rw-r--r--inc/auth/ldap.php281
-rw-r--r--inc/auth/mysql.php182
-rw-r--r--inc/auth/pgsql.php135
-rw-r--r--inc/auth/plain.php113
4 files changed, 711 insertions, 0 deletions
diff --git a/inc/auth/ldap.php b/inc/auth/ldap.php
new file mode 100644
index 000000000..2f0f4f1ff
--- /dev/null
+++ b/inc/auth/ldap.php
@@ -0,0 +1,281 @@
+<?php
+/**
+ * LDAP authentication backend
+ *
+ * tested with openldap 2.x on Debian only
+ *
+ * PHPs LDAP extension is needed
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+//check for LDAP extension on load
+if(!function_exists('ldap_connect'))
+ msg("LDAP extension not found",-1);
+
+/**
+ * Connect to the LDAP server
+ *
+ * Holds the connection in global scope for multiple use
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_ldap_connect(){
+ global $LDAP_CONNECTION;
+ global $conf;
+ $cnf = $conf['auth']['ldap'];
+
+ if(!$LDAP_CONNECTION){
+ $LDAP_CONNECTION = @ldap_connect($cnf['server']);
+ if(!$LDAP_CONNECTION){
+ msg("LDAP: couldn't connect to LDAP server",-1);
+ return false;
+ }
+ //set protocol version
+ if($cnf['version']){
+ if(!@ldap_set_option($LDAP_CONNECTION,
+ LDAP_OPT_PROTOCOL_VERSION,
+ $cnf['version'])){
+ msg('Setting LDAP Protocol version '.$cnf['version'].' failed',-1);
+ if($cnf['debug'])
+ msg('LDAP errstr: '.htmlspecialchars(ldap_error($LDAP_CONNECTION)),0);
+
+ } else {
+ //use TLS (needs version 3)
+ if($cnf['starttls']) {
+ if (!@ldap_start_tls($LDAP_CONNECTION)){
+ msg('Starting TLS failed',-1);
+ if($cnf['debug'])
+ msg('LDAP errstr: '.htmlspecialchars(ldap_error($LDAP_CONNECTION)),0);
+ }
+ }
+ // needs version 3
+ if(isset($cnf['referrals'])) {
+ if(!@ldap_set_option($LDAP_CONNECTION,
+ LDAP_OPT_REFERRALS,
+ $cnf['referrals'])){
+ msg('Setting LDAP referrals to off failed',-1);
+ if($cnf['debug'])
+ msg('LDAP errstr: '.htmlspecialchars(ldap_error($LDAP_CONNECTION)),0);
+ }
+ }
+ }
+ }
+ }
+ return $LDAP_CONNECTION;
+}
+
+/**
+ * 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 Andreas Gohr <andi@splitbrain.org>
+ * @return bool
+ */
+function auth_checkPass($user,$pass){
+ global $conf;
+ $cnf = $conf['auth']['ldap'];
+
+ //reject empty password
+ if(empty($pass)) return false;
+
+ //connect to LDAP Server
+ $conn = auth_ldap_connect();
+ if(!$conn) return false;
+
+ // indirect user bind
+ if(!empty($cnf['binddn']) and !empty($cnf['bindpw'])) {
+ //use superuser credentials
+ if(!@ldap_bind($conn,$cnf['binddn'],$cnf['bindpw'])){
+ if($cnf['debug']) msg('LDAP errstr: '.htmlspecialchars(ldap_error($conn)),0);
+ return false;
+ }
+
+ // special bind string
+ } else if(!empty($cnf['binddn']) and !empty($cnf['usertree']) and !empty($cnf['userfilter'])) {
+ $dn = auth_ldap_makeFilter($cnf['binddn'], array('user'=>$user,'server'=>$cnf['server']));
+
+ // direct user bind
+ } else if(strpos($cnf['usertree'], '%{user}')) {
+ $dn = auth_ldap_makeFilter($cnf['usertree'], array('user'=>$user,'server'=>$cnf['server']));
+
+ // Anonymous bind
+ } else {
+ if(!@ldap_bind($conn)){
+ msg("LDAP: can not bind anonymously",-1);
+ if($cnf['debug']) msg('LDAP errstr: '.htmlspecialchars(ldap_error($conn)),0);
+ return false;
+ }
+ }
+
+ // Try to bind to with the dn if we have one.
+ if(!empty($dn)) {
+ // User/Password bind
+ if(!@ldap_bind($conn,$dn,$pass)){
+ if($cnf['debug']) msg('LDAP errstr: '.htmlspecialchars(ldap_error($conn)),0);
+ return false;
+ }
+ return true;
+ } else {
+ // See if we can find the user
+ $info = auth_getUserData($user);
+ if(empty($info['dn'])) {
+ return false;
+ } else {
+ $dn = $info['dn'];
+ }
+ // Try to bind with the dn provided
+ if(!@ldap_bind($conn,$dn,$pass)){
+ if($cnf['debug']) msg('LDAP errstr: '.htmlspecialchars(ldap_error($conn)),0);
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * 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 addres 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 Andreas Gohr <andi@splitbrain.org>
+ * @author Trouble
+ * @author Dan Allen <dan.j.allen@gmail.com>
+ * @auhtor <evaldas.auryla@pheur.org>
+ */
+function auth_getUserData($user){
+ global $conf;
+ $cnf = $conf['auth']['ldap'];
+
+ //connect to LDAP Server
+ $conn = auth_ldap_connect();
+ if(!$conn) return false;
+
+ $info['user']= $user;
+ $info['server']= $cnf['server'];
+
+ //get info for given user
+ $base = auth_ldap_makeFilter($cnf['usertree'], $info);
+ if(!empty($cnf['userfilter'])) {
+ $filter = auth_ldap_makeFilter($cnf['userfilter'], $info);
+ } else {
+ $filter = "(ObjectClass=*)";
+ }
+
+ $sr = @ldap_search($conn, $base, $filter);
+ $result = @ldap_get_entries($conn, $sr);
+ if($cnf['debug']) msg('LDAP errstr: '.htmlspecialchars(ldap_error($conn)),0);
+
+ // Don't accept more or less than one response
+ if($result['count'] != 1){
+ return false; //user not found
+ }
+
+ $user_result = $result[0];
+
+ //general user info
+ $info['dn']= $user_result['dn'];
+ $info['mail']= $user_result['mail'][0];
+ $info['name']= $user_result['cn'][0];
+
+ #overwrite if other attribs are specified.
+ foreach($cnf['mapping'] as $localkey => $key) {
+ if(is_array($key)) {
+ //use regexp to clean up user_result
+ list($key, $regexp) = each($key);
+ foreach($user_result[$key] as $grp){
+ if (preg_match($regexp,$grp,$match)) {
+ if($localkey == 'grps') {
+ $info[$localkey][] = $match[1];
+ } else {
+ $info[$localkey] = $match[1];
+ }
+ }
+ }
+ } else {
+ $info[$localkey] = $user_result[$key][0];
+ }
+ }
+
+ //get groups for given user if grouptree is given
+ if (!empty($cnf['grouptree'])) {
+ $base = auth_ldap_makeFilter($cnf['grouptree'], $user_result);
+ $filter = auth_ldap_makeFilter($cnf['groupfilter'], $user_result);
+
+ $sr = @ldap_search($conn, $base, $filter);
+ if(!$sr){
+ msg("LDAP: Reading group memberships failed",-1);
+ if($cnf['debug']) msg('LDAP errstr: '.htmlspecialchars(ldap_error($conn)),0);
+ return false;
+ }
+ $result = ldap_get_entries($conn, $sr);
+ foreach($result as $grp){
+ if(!empty($grp['cn'][0]))
+ $info['grps'][] = $grp['cn'][0];
+ }
+ }
+
+ //if no groups were found always return the default group
+ if(!count($info['grps'])) $info['grps'][] = $conf['defaultgroup'];
+
+ return $info;
+}
+
+/**
+ * Create a new User [required auth function]
+ *
+ * Not implemented
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_createUser($user,$pass,$name,$mail){
+ msg("Sorry. Creating users is not supported by the LDAP backend",-1);
+ return null;
+}
+
+
+/**
+ * Make ldap filter strings.
+ *
+ * Used by auth_getUserData to make the filter
+ * strings for grouptree and groupfilter
+ *
+ * filter string ldap search filter with placeholders
+ * placeholders array array with the placeholders
+ *
+ * @author Troels Liebe Bentsen <tlb@rapanden.dk>
+ * @return string
+ */
+function auth_ldap_makeFilter($filter, $placeholders) {
+ preg_match_all("/%{([^}]+)/", $filter, $matches, PREG_PATTERN_ORDER);
+ //replace each match
+ foreach ($matches[1] as $match) {
+ //take first element if array
+ if(is_array($placeholders[$match])) {
+ $value = $placeholders[$match][0];
+ } else {
+ $value = $placeholders[$match];
+ }
+ $filter = str_replace('%{'.$match.'}', $value, $filter);
+ }
+ return $filter;
+}
+
+//Setup VIM: ex: et ts=2 enc=utf-8 :
diff --git a/inc/auth/mysql.php b/inc/auth/mysql.php
new file mode 100644
index 000000000..758fe3b77
--- /dev/null
+++ b/inc/auth/mysql.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * MySQL authentication backend
+ *
+ * PHP's MySQL extension is needed
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+//check for MySQL extension on load
+if(!function_exists('mysql_connect'))
+ msg("MySQL extension not found",-1);
+
+/**
+ * Execute SQL
+ *
+ * Executes SQL statements and returns the results as list
+ * of hashes. Returns false on error. Returns auto_increment
+ * IDs on INSERT statements.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_mysql_runsql($sql_string) {
+ global $conf;
+ $cnf = $conf['auth']['mysql'];
+
+ $link = @mysql_connect ($cnf['server'], $cnf['user'], $cnf['password']);
+ if(!$link){
+ msg('MySQL: Connection to database failed!',-1);
+ return false;
+ }
+ $result = @mysql_db_query($cnf['database'],$sql_string,$link);
+ if(!$result){
+ msg('MySQL: '.mysql_error($link));
+ return false;
+ }
+
+ //mysql_db_query returns 1 on a insert statement -> no need to ask for results
+ if ($result != 1) {
+ for($i=0; $i< mysql_num_rows($result); $i++) {
+ $temparray = mysql_fetch_assoc($result);
+ $resultarray[]=$temparray;
+ }
+ mysql_free_result ($result);
+ } elseif (mysql_insert_id($link)) {
+ $resultarray = mysql_insert_id($link); //give back ID on insert
+ } else
+ $resultarray = 0; // asure that the return value is valid
+
+ mysql_close ($link);
+ return $resultarray;
+}
+
+/**
+ * Check user+password [required auth function]
+ *
+ * Checks if the given user exists and the given
+ * plaintext password is correct. Furtheron it
+ * might be checked wether the user is member of
+ * the right group
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+ * @return bool
+ */
+function auth_checkPass($user,$pass){
+ global $conf;
+ $cnf = $conf['auth']['mysql'];
+
+ $sql = str_replace('%u',addslashes($user),$cnf['passcheck']);
+ $sql = str_replace('%g',addslashes($conf['defaultgroup']),$sql);
+ $result = auth_mysql_runsql($sql);
+
+ if(count($result)){
+ return(auth_verifyPassword($pass,$result[0]['pass']));
+ }else{
+ return(false);
+ }
+}
+
+/**
+ * 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 addres of the user
+ * grps array list of groups the user is in
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_getUserData($user){
+ global $conf;
+ $cnf = $conf['auth']['mysql'];
+
+ $sql = str_replace('%u',addslashes($user),$cnf['userinfo']);
+ $result = auth_mysql_runsql($sql);
+ if(!count($result)) return false;
+ $info = $result[0];
+
+ $sql = str_replace('%u',addslashes($user),$cnf['groups']);
+ $result = auth_mysql_runsql($sql);
+ if(!count($result)){
+ $info['grps'][] = $conf['defaultgroup'];
+ }else{
+ foreach($result as $row){
+ $info['grps'][] = $row['group'];
+ }
+ }
+
+ return $info;
+}
+
+/**
+ * Create a new User [required auth function]
+ *
+ * user string username
+ * pass string password
+ * name string full name of the user
+ * mail string email address
+ *
+ * Returns false if the user already exists, null when an error
+ * occoured and the cleartext password of the new user if
+ * everything went well.
+ *
+ * The user HAS TO be added to the default group by this
+ * function
+ *
+ * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+ */
+function auth_createUser($user,$pass,$name,$mail){
+ global $conf;
+ $cnf = $conf['auth']['mysql'];
+
+ //check if user exists
+ $info = auth_getUserData($user);
+ if ($info != false) return false;
+
+ //get groupid of default group
+ if($cnf['getgroupid']){
+ $sql = str_replace('%g',addslashes($conf['defaultgroup']),$cnf['getgroupid']);
+ $result = auth_mysql_runsql($sql);
+ if($result === false) return null;
+ if (count($result) == 1){
+ $gid = $result[0]['gid'];
+ }else{
+ msg("MySQL: Couldn't find the default group",-1);
+ return null;
+ }
+ }
+
+ //prepare the insert
+ $sql = str_replace('%u' ,addslashes($user),$cnf['adduser']);
+ $sql = str_replace('%p' ,addslashes(auth_cryptPassword($pass)),$sql);
+ $sql = str_replace('%n' ,addslashes($name),$sql);
+ $sql = str_replace('%e' ,addslashes($mail),$sql);
+ $sql = str_replace('%gid',addslashes($gid),$sql);
+ $sql = str_replace('%g' ,addslashes($conf['defaultgroup']),$sql);
+
+ //do the insert
+ $uid = auth_mysql_runsql($sql);
+ if($uid == 0){
+ msg("Registering of the new user '$user' failed!", -1);
+ return null;
+ }
+
+ //add to default group
+ if ($cnf['addusergroup']) {
+ $sql = str_replace('%uid',addslashes($uid),$cnf['addusergroup']);
+ $sql = str_replace('%u' ,addslashes($user),$sql);
+ $sql = str_replace('%gid',addslashes($gid),$sql);
+ $sql = str_replace('%g' ,addslashes($conf['defaultgroup']),$sql);
+ $result = auth_mysql_runsql($sql);
+ if($result === false) msg("MySQL: couldn't add user to the default group");
+ }
+
+ return $pass;
+}
+
+//Setup VIM: ex: et ts=2 enc=utf-8 :
diff --git a/inc/auth/pgsql.php b/inc/auth/pgsql.php
new file mode 100644
index 000000000..b063f405e
--- /dev/null
+++ b/inc/auth/pgsql.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * PgSQL authentication backend
+ * (shamelessly based on the original auth_mysql.php ;-)
+ *
+ * PHP's PgSQL extension is needed
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Alexander Marx < mad-ml [at] madness [dot] at >
+ */
+
+//check for Postgresql extension on load
+if(!function_exists('pg_connect'))
+ msg("PgSQL extension not found",-1);
+
+/**
+ * Execute SQL
+ *
+ * Executes SQL statements and returns the results as list
+ * of hashes. Returns false on error.
+ *
+ */
+function auth_pgsql_runsql($sql_string) {
+ global $conf;
+ $cnf = $conf['auth']['pgsql'];
+
+ if($cnf['port']) {
+ $port=" port=".$cnf['port'];
+ }
+
+ $dsn="host=".$cnf['server']." dbname=".$cnf['database'].$port." user=".$cnf['user']." password=".$cnf['password'];
+ $link = pg_connect($dsn);
+ if(!$link){
+ msg('PgSQL: Connection to database failed!',-1);
+ return false;
+ }
+
+ $result = pg_query($link, $sql_string);
+ if(!$result){
+ msg('PgSQL: '.pg_last_error($link));
+ return false;
+ }
+
+ for($i=0; $i< pg_num_rows($result); $i++) {
+ $temparray = pg_fetch_assoc($result);
+ $resultarray[]=$temparray;
+ }
+ pg_free_result($result);
+ pg_close($link);
+ return $resultarray;
+}
+
+/**
+ * Check user+password [required auth function]
+ *
+ * Checks if the given user exists and the given
+ * plaintext password is correct
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @return bool
+ */
+function auth_checkPass($user,$pass){
+ global $conf;
+ $cnf = $conf['auth']['pgsql'];
+
+ $sql = str_replace('%u',addslashes($user),$cnf['userinfo']);
+ $result = auth_pgsql_runsql($sql);
+ if(count($result)>0) {
+ $info=$result[0];
+ return auth_verifyPassword($pass, $info['pass']);
+ } else {
+ return false;
+ }
+}
+
+/**
+ * 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 addres of the user
+ * grps array list of groups the user is in
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_getUserData($user){
+ global $conf;
+ $cnf = $conf['auth']['pgsql'];
+
+ $sql = str_replace('%u',addslashes($user),$cnf['userinfo']);
+ $result = auth_pgsql_runsql($sql);
+ if(!count($result)) return false;
+ $info = $result[0];
+
+ $sql = str_replace('%u',addslashes($user),$cnf['groups']);
+ $result = auth_pgsql_runsql($sql);
+ if(!count($result)) return false;
+ foreach($result as $row){
+ $info['grps'][] = $row['group'];
+ }
+
+ return $info;
+}
+
+/**
+ * Create a new User [required auth function]
+ */
+function auth_createUser($user,$pass,$name,$mail) {
+ global $conf;
+ $cnf = $conf['auth']['pgsql'];
+
+ if($cnf['createuser']) {
+ $sql = str_replace('%u',addslashes($user),$cnf['userinfo']);
+ $result = auth_pgsql_runsql($sql);
+ if(count($result)>0) return false;
+
+ $sql = str_replace('%u',addslashes($user),$cnf['createuser']);
+ $sql = str_replace('%p',auth_cryptPassword($pass),$sql);
+ $sql = str_replace('%f',addslashes($name),$sql);
+ $sql = str_replace('%e',addslashes($mail),$sql);
+ $sql = str_replace('%g',addslashes($conf['defaultgroup']),$sql);
+
+ $result=auth_pgsql_runsql($sql);
+ if(count($result))
+ return $pass;
+ } else {
+ msg("Sorry. Your PgSQL backend is not configured to create new users.",-1);
+ }
+ return null;
+}
+
+//Setup VIM: ex: et ts=2 enc=utf-8 :
+
diff --git a/inc/auth/plain.php b/inc/auth/plain.php
new file mode 100644
index 000000000..eaa01b79d
--- /dev/null
+++ b/inc/auth/plain.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Plaintext authentication backend
+ *
+ * If you want to authenticate against something
+ * else then the builtin flatfile auth system
+ * you have to reimplement the "required auth
+ * functions"
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+// we only accept page ids for auth_plain
+if(isset($_REQUEST['u']))
+ $_REQUEST['u'] = cleanID($_REQUEST['u']);
+
+/**
+ * Check user+password [required auth function]
+ *
+ * Checks if the given user exists and the given
+ * plaintext password is correct
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @return bool
+ */
+function auth_checkPass($user,$pass){
+ $users = auth_plain_loadUserData();
+
+ if(!isset($users[$user])) return false;
+
+ return auth_verifyPassword($pass,$users[$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 addres of the user
+ * grps array list of groups the user is in
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_getUserData($user){
+ $users = auth_plain_loadUserData();
+ return $users[$user];
+}
+
+/**
+ * Create a new User [required auth function]
+ *
+ * Returns false if the user already exists, null when an error
+ * occured and the cleartext password of the new user if
+ * everything went well.
+ *
+ * The new user HAS TO be added to the default group by this
+ * function!
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_createUser($user,$pass,$name,$mail){
+ global $conf;
+
+ $users = auth_plain_loadUserData();
+ if(isset($users[$user])) return false;
+
+ $userline = join(':',array($user,
+ auth_cryptPassword($pass),
+ $name,
+ $mail,
+ $conf['defaultgroup']));
+ $userline .= "\n";
+ $fh = fopen(DOKU_INC.'conf/users.auth.php','a');
+ if($fh){
+ fwrite($fh,$userline);
+ fclose($fh);
+ return $pass;
+ }
+ msg('The users.auth.php file is not writable. Please inform the Wiki-Admin',-1);
+ return null;
+}
+
+/**
+ * Load all user data
+ *
+ * Used by the plaintext auth functions
+ * loads the user file into a datastructure
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function auth_plain_loadUserData(){
+ $data = array();
+ $lines = file(DOKU_INC.'conf/users.auth.php');
+ foreach($lines as $line){
+ $line = preg_replace('/#.*$/','',$line); //ignore comments
+ $line = trim($line);
+ if(empty($line)) continue;
+
+ $row = split(":",$line,5);
+ $groups = split(",",$row[4]);
+ $data[$row[0]]['pass'] = $row[1];
+ $data[$row[0]]['name'] = urldecode($row[2]);
+ $data[$row[0]]['mail'] = $row[3];
+ $data[$row[0]]['grps'] = $groups;
+ }
+ return $data;
+}
+
+
+//Setup VIM: ex: et ts=2 enc=utf-8 :