xref: /plugin/authchained/auth.php (revision 32fe206a598f7f5dff3df603d41f8b6dbb41d4ba)
1<?php
2// must be run within Dokuwiki
3if(!defined('DOKU_INC')) die();
4
5/**
6* Chained authentication backend
7*
8* @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
9* @author     Philipp Nesuer <pneuser@physik.fu-berlin.de>
10*/
11class auth_plugin_authchained extends DokuWiki_Auth_Plugin {
12    public $success = true;
13    //array with authentication plugins
14    protected $chained_plugins = array();
15    protected $chained_auth = NULL;
16
17    /**
18    * Constructor.
19    *
20    * Loads all configured plugins or the authentication plugin of the
21    * logged in user.
22    *
23    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
24    */
25    public function __construct() {
26        global $conf;
27        // call parent
28        #      parent::__constructor();
29
30        //check if there is already an authentication plugin selected
31        if( isset($_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']) &&
32            !empty($_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']) ) {
33            //get previously selected authentication plugin
34            $tmp_plugin = $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'];
35            require_once(DOKU_INC."lib/plugins/".$tmp_plugin."/auth.php");
36            $tmp_classname = "auth_plugin_".$tmp_plugin;
37            $this->chained_auth = new $tmp_classname;
38
39        } else {
40            //get authentication plugins
41            if(isset($conf['plugin']['authchained']['authtypes'])){
42                foreach(explode(":",$conf['plugin']['authchained']['authtypes']) as $tmp_plugin){
43                    require_once(DOKU_INC."lib/plugins/".$tmp_plugin."/auth.php");
44                    $tmp_classname = "auth_plugin_".$tmp_plugin;
45                    $tmp_class = new $tmp_classname;
46                    $tmp_module = array($tmp_plugin,$tmp_class);
47                    array_push($this->chained_plugins, $tmp_module);
48                }
49            }else{
50                $success = false;
51            }
52        }
53        //debug
54        //      print_r($chained_plugins);
55    }
56
57    /**
58    * Forwards the authentication to configured authplugins.
59    * Returns true, if the usermanager authtype has the capability and no user
60    * is logged in.
61    *
62    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
63    * @param   string $cap the capability to check
64    * @return  bool
65    */
66    public function canDo($cap) {
67        global $conf;
68        #      print_r($cap);
69        if(is_null($this->chained_auth)) {
70            foreach($this->chained_plugins as $module) {
71                #echo "TEST AUTHMANAGER!!!";
72                if($module[0] == $conf['plugin']['authchained']['usermanager_authtype']) {
73                    $module[1]->canDo($cap);
74                }
75            }
76            return false;
77        } else {
78            #echo "canDo $cap ".$this->chained_auth->canDo($cap)."\n";
79            return $this->chained_auth->canDo($cap);
80        }
81    }
82
83    /**
84    * Forwards the result of the auth plugin of the logged in user or
85    * returns false
86    *
87    * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
88    * @param string $type   Modification type ('create', 'modify', 'delete')
89    * @param array  $params Parameters for the createUser, modifyUser or deleteUsers method. The content of this array depends on the modification type
90    * @return mixed Result from the modification function or false if an event handler has canceled the action
91    */
92    public function triggerUserMod($type, $params) {
93        if(is_null($this->chained_auth))
94            return false;
95        else
96            return $this->chained_auth->triggerUserMod($type, $params);
97    }
98
99    /**
100    * Forwards the result of the auth plugin of the logged in user and
101    * unsets our session variable.
102    * @see     auth_logoff()
103    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de
104    */
105    public function logOff() {
106        if(!is_null($this->chained_auth))
107            $this->chained_auth->logOff();
108        unset($_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']);
109    }
110
111    /**
112    * Do all authentication [ OPTIONAL ]
113    * If the current plugin is external, be external.
114    *
115    * @see     auth_login()
116    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
117    *
118    * @param   string  $user    Username
119    * @param   string  $pass    Cleartext Password
120    * @param   bool    $sticky  Cookie should not expire
121    * @return  bool             true on successful auth
122    */
123    public function trustExternal($user, $pass, $sticky = false) {
124        if(!is_null($this->chained_auth) && $this->chained_auth->canDo('external'))
125            $this->chained_auth->trustExternal($user, $pass, $sticky);
126    }
127
128    /**
129    * Check user+password [ MUST BE OVERRIDDEN ]
130    *
131    * Checks if the given user exists in one of the plugins and checks
132    * against the given password. The first plugin returning true becomes
133    * auth plugin of the user session.
134    *
135    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de
136    * @param   string $user the user name
137    * @param   string $pass the clear text password
138    * @return  bool
139    */
140    public function checkPass($user, $pass) {
141        //debug
142        //print_r($this->chained_plugins);
143        if(is_null($this->chained_auth)) {
144            foreach($this->chained_plugins as $module) {
145                if($module[1]->canDo('external')) {
146                    if($module[1]->trustExternal($user, $pass)) {
147                        $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = $module[0];
148                        $this->chained_auth = $module[1];
149                        return true;
150                    } else {
151                        if($module[1]->checkPass($user, $pass)) {
152                            $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = $module[0];
153                            $this->chained_auth = $module[1];
154                            return true;
155                        }
156                    }
157                } else {
158                    if($module[1]->checkPass($user, $pass)) {
159                        $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = $module[0];
160                        $this->this->chained_auth = $module[1];
161                        return true;
162                    }
163                }
164            }
165        } else {
166            return $this->chained_auth->checkPass($user, $pass);
167        }
168        return false;
169    }
170
171    /**
172    * Forwards the result of the auth plugin of the logged in user or
173    * checks all plugins if the users exists. The first plugin returning
174    * data is used.
175    *
176    * name string  full name of the user
177    * mail string  email addres of the user
178    * grps array   list of groups the user is in
179    *
180    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
181    * @param   string $user the user name
182    * @return  array containing user data or false
183    */
184    public function getUserData($user) {
185        //if(!$this->cando['external']) msg("no valid authorisation system in use", -1);
186        //       echo "TESTSETEST";
187        if(is_null($this->chained_auth)) {
188            foreach($this->chained_plugins as $module) {
189                $tmp_array = $module[1]->getUserData($user);
190                if(!is_bool($tmp_array))
191                    $tmp_chk_arr =array_filter($tmp_array);
192                if(!empty($tmp_chk_arr) && $tmp_array)
193                    return $tmp_array;
194            }
195            return false;
196        } else {
197            return $this->chained_auth->getUserData($user);
198        }
199    }
200
201    /**
202    * Forwards the result of the auth plugin of the logged in user or
203    * returns null.
204    *
205    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
206    * @param  string     $user
207    * @param  string     $pass
208    * @param  string     $name
209    * @param  string     $mail
210    * @param  null|array $grps
211    * @return bool|null
212    */
213    public function createUser($user, $pass, $name, $mail, $grps = null) {
214        if(is_null($this->chained_auth)) {
215            msg("authorisation method does not allow creation of new users", -1);
216            return null;
217        } else {
218            //please note: users will be added to the module, to which the
219            //current user is logged into
220            if($this->canDo('addUser')) {
221                return $this->chained_auth->createUser($user, $pass, $name, $mail, $grps);
222            } else {
223                msg("authorisation method does not allow creation of new users", -1);
224                return null;
225            }
226        }
227    }
228
229    /**
230    * Forwards the result of the auth plugin of the logged in user or
231    * returns false
232    *
233    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
234    * @param   string $user    nick of the user to be changed
235    * @param   array  $changes array of field/value pairs to be changed (password will be clear text)
236    * @return  bool
237    */
238    public function modifyUser($user, $changes) {
239        if(is_null($this->chained_auth)) {
240            msg("authorisation method does not allow modifying of user data", -1);
241            return false;
242        } else {
243            //please note: users will be modified in the module, to which the
244            //current user is logged into
245            if( $this->canDo('modLogin') && $this->canDo('modPass') &&
246                $this->canDo('modName') && $this->canDo('modMail') &&
247                $this->canDo('modGroups')){
248                    return $this->chained_auth->createUser($user, $changes);
249            } else {
250                msg("authorisation method does not allow modifying of user data", -1);
251                return false;
252            }
253        }
254
255    }
256
257    /**
258    * Forwards the result of the auth plugin of the logged in user or
259    * returns false
260    *
261    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
262    * @param   array  $users
263    * @return  int    number of users deleted
264    */
265    public function deleteUsers($users) {
266        if(is_null($this->chained_auth)){
267            msg("authorisation method does not allow deleting of users", -1);
268            return false;
269        } else {
270            //please note: users will be added to the module, to which the
271            //current user is logged into
272            if($this->canDo('delUser')){
273                return $this->chained_auth->createUser($users);
274            }else{
275                msg("authorisation method does not allow deleting of users", -1);
276                return false;
277            }
278        }
279    }
280
281    /**
282    * Forwards the result of the auth plugin of the logged in user or
283    * returns 0
284    *
285    * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
286    * @param  array $filter array of field/pattern pairs, empty array for no filter
287    * @return int
288    */
289    public function getUserCount($filter = array()) {
290        if(is_null($this->chained_auth)){
291            msg("authorisation method does not provide user counts", -1);
292            return 0;
293        } else {
294            //please note: users will be counted in the module, to which the
295            //current user is logged into
296            if($this->canDo('getUserCount')){
297                return $this->chained_auth->getUserCount($filter);
298            } else {
299                msg("authorisation method does not provide user counts", -1);
300                return 0;
301            }
302        }
303    }
304
305    /**
306    * Forwards the result of the auth plugin of the logged in user or
307    * returns empty array
308    *
309    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
310    * @param   int   $start     index of first user to be returned
311    * @param   int   $limit     max number of users to be returned
312    * @param   array $filter    array of field/pattern pairs, null for no filter
313    * @return  array list of userinfo (refer getUserData for internal userinfo details)
314    */
315    public function retrieveUsers($start = 0, $limit = -1, $filter = null) {
316        if(is_null($this->chained_auth)) {
317            msg("authorisation method does not support mass retrievals", -1);
318            return array();
319        } else {
320            //please note: users will be retrieved from the module, to which the
321            //current user is logged into
322            if($this->canDo('getUsers')){
323                return $this->chained_auth->retrieveUsers($start, $limit, $filter);
324            } else {
325                msg("authorisation method does not support mass retrievals", -1);
326                return array();
327            }
328        }
329    }
330
331    /**
332    * Forwards the result of the auth plugin of the logged in user or
333    * returns false
334    *
335    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
336    * @param   string $group
337    * @return  bool
338    */
339    public function addGroup($group) {
340        if(is_null($this->chained_auth)){
341            msg("authorisation method does not support independent group creation", -1);
342            return false;
343        } else {
344            //please note: users will be added to the module, to which the
345            //current user is logged into
346            if($this->canDo('addGroup')) {
347                return $this->chained_auth->addGroup($group);
348            } else {
349                msg("authorisation method does not support independent group creation", -1);
350                return false;
351            }
352        }
353    }
354
355    /**
356    * Forwards the result of the auth plugin of the logged in user or
357    * returns empty array
358    *
359    * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
360    * @param   int $start
361    * @param   int $limit
362    * @return  array
363    */
364    public function retrieveGroups($start = 0, $limit = 0) {
365        if(is_null($this->chained_auth)){
366            msg("authorisation method does not support group list retrieval", -1);
367            return array();
368        } else {
369            //please note: users will be retrieved from the module, to which the
370            //current user is logged into
371            if($this->canDo('getGroups')){
372                return $this->chained_auth->retrieveGroups($start,$limit);
373            }else{
374                msg("authorisation method does not support group list retrieval", -1);
375                return array();
376            }
377        }
378    }
379
380    /**
381    * Forwards the result of the auth plugin of the logged in user or
382    * returns true
383    *
384    * @return bool
385    */
386    public function isCaseSensitive() {
387        if(is_null($this->chained_auth))
388            return true;
389        else
390            return $this->chained_auth->isCaseSensitive();
391    }
392
393    /**
394    * Sanitize a given username [OPTIONAL]
395    * Forwards the result of the auth plugin of the logged in user or
396    * returns false
397    *
398    *
399    * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
400    * @param string $user username
401    * @return string the cleaned username
402    */
403    public function cleanUser($user) {
404        //print_r($this->chained_auth);
405        if(is_null($this->chained_auth))
406            return $user;
407        else
408            return $this->chained_auth->cleanUser($user);
409    }
410
411    /**
412    * Sanitize a given groupname [OPTIONAL]
413    * Forwards the result of the auth plugin of the logged in user or
414    * returns false
415    *
416    * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
417    * @param  string $group groupname
418    * @return string the cleaned groupname
419    */
420    public function cleanGroup($group) {
421        if(is_null($this->chained_auth)) {
422            return $group;
423        } else {
424            return $this->chained_auth->cleanGroup($group);
425        }
426    }
427
428
429    public function useSessionCache($user) {
430        global $conf;
431        if(is_null($this->chained_auth))
432            return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'].'/sessionpurge'));
433        else
434            return $this->chained_auth->useSessionCache($user);
435    }
436}
437