xref: /plugin/authchained/auth.php (revision c368b833883846bbcbbfe81b14cfbe8b8c8901a0)
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       foreach($this->chained_plugins as $module)
150       {
151	  if($module[1]->canDo('external'))
152	  {
153	     if($module[1]->trustExternal($user, $pass))
154	     {
155		$_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] =
156		   $module[0];
157		$this->chained_auth = $module[1];
158		return true;
159	     }else{
160		 if($module[1]->checkPass($user, $pass))
161		 {
162		    $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] =
163		                          $module[0];
164		    $this->chained_auth = $module[1];
165		    return true;
166		 }
167	     }
168	  }else{
169	     if($module[1]->checkPass($user, $pass))
170	     {
171		$_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] =
172		   $module[0];
173		$this->this->chained_auth = $module[1];
174		return true;
175	     }
176	  }
177       }
178        return false;
179    }
180
181    /**
182     * Forwards the result of the auth plugin of the logged in user or
183     * checks all plugins if the users exists. The first plugin returning
184     * data is used.
185     *
186     * name string  full name of the user
187     * mail string  email addres of the user
188     * grps array   list of groups the user is in
189     *
190     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
191     * @param   string $user the user name
192     * @return  array containing user data or false
193     */
194    public function getUserData($user) {
195       //if(!$this->cando['external']) msg("no valid authorisation system in use", -1);
196//       echo "TESTSETEST";
197       if(is_null($this->chained_auth))
198       {
199	  foreach($this->chained_plugins as $module)
200	  {
201	     $tmp_array = $module[1]->getUserData($user);
202	     if(!is_bool($tmp_array))
203	       $tmp_chk_arr =array_filter($tmp_array);
204	     if(!empty($tmp_chk_arr) && $tmp_array)
205		return $tmp_array;
206	  }
207	  return false;
208       }
209	else
210	{
211	   return $this->chained_auth->getUserData($user);
212	}
213    }
214
215    /**
216     * Forwards the result of the auth plugin of the logged in user or
217     * returns null.
218     *
219     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
220     * @param  string     $user
221     * @param  string     $pass
222     * @param  string     $name
223     * @param  string     $mail
224     * @param  null|array $grps
225     * @return bool|null
226     */
227    public function createUser($user, $pass, $name, $mail, $grps = null) {
228       if(is_null($this->chained_auth)){
229	  msg("authorisation method does not allow creation of new users",
230	     -1);
231	  return null;
232       }
233	else{
234	   //please note: users will be added to the module, to which the
235	   //current user is logged into
236	   if($this->canDo('addUser')){
237	      return $this->chained_auth->createUser($user, $pass, $name, $mail,
238		  $grps);
239	   }else{
240	      msg("authorisation method does not allow creation of new
241		 users", -1);
242	      return null;
243	   }
244	}
245     }
246
247    /**
248     * Forwards the result of the auth plugin of the logged in user or
249     * returns false
250     *
251     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
252     * @param   string $user    nick of the user to be changed
253     * @param   array  $changes array of field/value pairs to be changed (password will be clear text)
254     * @return  bool
255     */
256    public function modifyUser($user, $changes) {
257       if(is_null($this->chained_auth)){
258	  msg("authorisation method does not allow modifying of user data",
259	     -1);
260	  return false;
261       }
262	else{
263	   //please note: users will be modified in the module, to which the
264	   //current user is logged into
265	   if($this->canDo('modLogin') && $this->canDo('modPass') &&
266	      $this->canDo('modName') && $this->canDo('modMail') &&
267	      $this->canDo('modGroups')){
268	      return $this->chained_auth->createUser($user, $changes);
269	   }else{
270	      msg("authorisation method does not allow modifying of user
271		 data", -1);
272	      return false;
273	   }
274	}
275
276    }
277
278    /**
279     * Forwards the result of the auth plugin of the logged in user or
280     * returns false
281     *
282     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
283     * @param   array  $users
284     * @return  int    number of users deleted
285     */
286    public function deleteUsers($users) {
287       if(is_null($this->chained_auth)){
288	  msg("authorisation method does not allow deleting of users",
289	     -1);
290	  return false;
291       }
292	else{
293	   //please note: users will be added to the module, to which the
294	   //current user is logged into
295	   if($this->canDo('delUser')){
296	      return $this->chained_auth->createUser($users);
297	   }else{
298	      msg("authorisation method does not allow deleting of users", -1);
299	      return false;
300	   }
301	}
302    }
303
304    /**
305     * Forwards the result of the auth plugin of the logged in user or
306     * returns 0
307     *
308     * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
309     * @param  array $filter array of field/pattern pairs, empty array for no filter
310     * @return int
311     */
312    public function getUserCount($filter = array()) {
313       if(is_null($this->chained_auth)){
314	  msg("authorisation method does not provide user counts",
315	     -1);
316	  return 0;
317       }
318	else{
319	   //please note: users will be counted in the module, to which the
320	   //current user is logged into
321	   if($this->canDo('getUserCount')){
322	      return $this->chained_auth->getUserCount($filter);
323	   }else{
324	      msg("authorisation method does not provide user counts", -1);
325	      return 0;
326	   }
327	}
328
329    }
330
331    /**
332     * Forwards the result of the auth plugin of the logged in user or
333     * returns empty array
334     *
335     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
336     * @param   int   $start     index of first user to be returned
337     * @param   int   $limit     max number of users to be returned
338     * @param   array $filter    array of field/pattern pairs, null for no filter
339     * @return  array list of userinfo (refer getUserData for internal userinfo details)
340     */
341    public function retrieveUsers($start = 0, $limit = -1, $filter = null) {
342       if(is_null($this->chained_auth)){
343	  msg("authorisation method does not support mass retrievals",
344	     -1);
345	  return array();
346       }
347	else{
348	   //please note: users will be retrieved from the module, to which the
349	   //current user is logged into
350	   if($this->canDo('getUsers')){
351	      return $this->chained_auth->retrieveUsers($start, $limit, $filter);
352	   }else{
353	      msg("authorisation method does not support mass retrievals", -1);
354	      return array();
355	   }
356	}
357    }
358
359    /**
360     * Forwards the result of the auth plugin of the logged in user or
361     * returns false
362     *
363     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
364     * @param   string $group
365     * @return  bool
366     */
367    public function addGroup($group) {
368       if(is_null($this->chained_auth)){
369	  msg("authorisation method does not support independent group
370	     creation",
371	     -1);
372	  return false;
373       }
374	else{
375	   //please note: users will be added to the module, to which the
376	   //current user is logged into
377	   if($this->canDo('addGroup')){
378	      return $this->chained_auth->addGroup($group);
379	   }else{
380	      msg("authorisation method does not support independent group
381		 creation", -1);
382	      return false;
383	   }
384	}
385    }
386
387    /**
388     * Forwards the result of the auth plugin of the logged in user or
389     * returns empty array
390     *
391     * @author  Philipp Neuser <pneuser@physik.fu-berlin.de>
392     * @param   int $start
393     * @param   int $limit
394     * @return  array
395     */
396    public function retrieveGroups($start = 0, $limit = 0) {
397       if(is_null($this->chained_auth)){
398	  msg("authorisation method does not support group list retrieval",
399	     -1);
400	  return array();
401       }
402	else{
403	   //please note: users will be retrieved from the module, to which the
404	   //current user is logged into
405	   if($this->canDo('getGroups')){
406	      return $this->chained_auth->retrieveGroups($start,$limit);
407	   }else{
408	      msg("authorisation method does not support group list
409		 retrieval", -1);
410	      return array();
411	   }
412	}
413    }
414
415    /**
416     * Forwards the result of the auth plugin of the logged in user or
417     * returns true
418     *
419     * @return bool
420     */
421    public function isCaseSensitive() {
422       if(is_null($this->chained_auth))
423	  return true;
424       else
425	  return $this->chained_auth->isCaseSensitive();
426    }
427
428    /**
429     * Sanitize a given username [OPTIONAL]
430     * Forwards the result of the auth plugin of the logged in user or
431     * returns false
432     *
433     *
434     * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
435     * @param string $user username
436     * @return string the cleaned username
437     */
438    public function cleanUser($user) {
439       //print_r($this->chained_auth);
440        if(is_null($this->chained_auth))
441	  return $user;
442       else
443	  return $this->chained_auth->cleanUser($user);
444    }
445
446    /**
447     * Sanitize a given groupname [OPTIONAL]
448     * Forwards the result of the auth plugin of the logged in user or
449     * returns false
450     *
451     * @author Philipp Neuser <pneuser@physik.fu-berlin.de>
452     * @param  string $group groupname
453     * @return string the cleaned groupname
454     */
455    public function cleanGroup($group) {
456       if(is_null($this->chained_auth))
457       {
458	  return $group;
459       }
460       else
461	  return $this->chained_auth->cleanGroup($group);
462    }
463
464
465    public function useSessionCache($user) {
466       global $conf;
467       if(is_null($this->chained_auth))
468	  return ($_SESSION[DOKU_COOKIE]['auth']['time'] >=
469	  @filemtime($conf['cachedir'].'/sessionpurge'));
470       else
471	  return $this->chained_auth->useSessionCache($user);
472    }
473}
474