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