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