xref: /dokuwiki/inc/auth.php (revision f3f0262c480d7e509b008d37c90aed884532bba8)
1<?
2require_once("inc/common.php");
3require_once("inc/io.php");
4# load the the auth functions
5require_once('inc/auth_'.$conf['authtype'].'.php');
6
7# some ACL level defines
8define('AUTH_NONE',0);
9define('AUTH_READ',1);
10define('AUTH_EDIT',2);
11define('AUTH_CREATE',4);
12define('AUTH_UPLOAD',8);
13define('AUTH_GRANT',255);
14
15if($conf['useacl']){
16  auth_login($_REQUEST['u'],$_REQUEST['p']);
17  # load ACL into a global array
18  $AUTH_ACL = file('conf/acl.auth');
19}
20
21/**
22 * This tries to login the user based on the sent auth credentials
23 *
24 * The authentication works like this: if a username was given
25 * a new login is assumed and user/password are checked - if they
26 * are correct a random authtoken is created which is stored in
27 * the session _and_ in a cookie.
28 * The user stays logged in as long as the session and the cookie
29 * match. This still isn't the securest method but requires an
30 * attacker to steal an existing session _and_ the authtoken
31 * cookie. The actual password is only transfered once per login.
32 *
33 * On a successful login $_SERVER[REMOTE_USER] and $USERINFO
34 * are set.
35*/
36function auth_login($user,$pass){
37  global $USERINFO;
38  global $conf;
39  global $lang;
40  $cookie  = $_COOKIE['AUTHTOKEN'];
41	$session = $_SESSION[$conf['title']]['authtoken'];
42
43  if(isset($user)){
44    if (auth_checkPass($user,$pass)){
45      //make username available as REMOTE_USER
46      $_SERVER['REMOTE_USER'] = $user;
47      //set global user info
48      $USERINFO = auth_getUserData($user);
49      //set authtoken
50      $token = md5(uniqid(rand(), true));
51      $_SESSION[$conf['title']]['user']      = $user;
52      $_SESSION[$conf['title']]['authtoken'] = $token;
53      setcookie('AUTHTOKEN', $token);
54    }else{
55      //invalid credentials - log off
56      msg($lang['badlogin'],-1);
57      auth_logoff();
58    }
59  }elseif(isset($cookie) && isset($session)){
60    if($cookie == $session){
61      //make username available as REMOTE_USER
62      $_SERVER['REMOTE_USER'] = $_SESSION[$conf['title']]['user'];
63      //set global user info
64      $USERINFO = auth_getUserData($_SERVER['REMOTE_USER']);
65    }else{
66      //bad token
67      auth_logoff();
68    }
69  }else{
70    //just to be sure
71    auth_logoff();
72  }
73}
74
75/**
76 * This clears all authenticationdata and thus log the user
77 * off
78 */
79function auth_logoff(){
80  global $conf;
81  global $USERINFO;
82  unset($_SESSION[$conf['title']]['authtoken']);
83  unset($_SESSION[$conf['title']]['user']);
84  unset($_SERVER['REMOTE_USER']);
85  $USERINFO=null;
86}
87
88/**
89 * Convinience function for auth_aclcheck
90 */
91function auth_quickaclcheck($id){
92  global $conf;
93  global $USERINFO;
94  # if no ACL is used always return upload rights
95  if(!$conf['useacl']) return AUTH_UPLOAD;
96  return auth_aclcheck($id,$_SERVER['REMOTE_USER'],$USERINFO['grps']);
97}
98
99/**
100 * Returns the maximum rights a user has for
101 * the given ID or its namespace
102 */
103function auth_aclcheck($id,$user,$groups){
104  global $conf;
105  global $AUTH_ACL;
106
107  # if no ACL is used always return upload rights
108  if(!$conf['useacl']) return AUTH_UPLOAD;
109
110  $ns    = getNS($id);
111  $perm  = -1;
112
113  if($user){
114    //prepend groups with @
115    for($i=0; $i<count($groups); $i++){
116      $groups[$i] = '@'.$groups[$i];
117    }
118    //add ALL group
119    $groups[] = '@ALL';
120    //add User
121    $groups[] = $user;
122    //build regexp
123    $regexp   = join('|',$groups);
124  }else{
125    $regexp = '@ALL';
126  }
127
128  //check exact match first
129  $matches = preg_grep('/^'.$id.'\s+('.$regexp.')\s+/',$AUTH_ACL);
130  if(count($matches)){
131    foreach($matches as $match){
132      $match = preg_replace('/#.*$/','',$match); //ignore comments
133      $acl   = preg_split('/\s+/',$match);
134      if($acl[2] > $perm){
135        $perm = $acl[2];
136      }
137    }
138    if($perm > -1){
139      //we had a match - return it
140      return $perm;
141    }
142  }
143
144  //still here? do the namespace checks
145  if($ns){
146    $path = $ns.':\*';
147  }else{
148    $path = '\*'; //root document
149  }
150
151  do{
152    $matches = preg_grep('/^'.$path.'\s+('.$regexp.')\s+/',$AUTH_ACL);
153    if(count($matches)){
154      foreach($matches as $match){
155        $match = preg_replace('/#.*$/','',$match); //ignore comments
156        $acl   = preg_split('/\s+/',$match);
157        if($acl[2] > $perm){
158          $perm = $acl[2];
159        }
160      }
161      //we had a match - return it
162      return $perm;
163    }
164
165    //get next higher namespace
166    $ns   = getNS($ns);
167
168    if($path != '\*'){
169      $path = $ns.':\*';
170      if($path == ':\*') $path = '\*';
171    }else{
172      //we did this already
173      //looks like there is something wrong with the ACL
174      //break here
175      return $perm;
176    }
177  }while(1); //this should never loop endless
178}
179
180/**
181 * Create a pronouncable password
182 *
183 * @see: http://www.phpbuilder.com/annotate/message.php3?id=1014451
184 */
185function auth_pwgen(){
186  $pw = '';
187  $c  = 'bcdfghjklmnprstvwz'; //consonants except hard to speak ones
188  $v  = 'aeiou';              //vowels
189  $a  = $c.$v;                //both
190
191  //use two syllables...
192  for($i=0;$i < 2; $i++){
193    $pw .= $c[rand(0, strlen($c)-1)];
194    $pw .= $v[rand(0, strlen($v)-1)];
195    $pw .= $a[rand(0, strlen($a)-1)];
196  }
197  //... and add a nice number
198  $pw .= rand(10,99);
199
200  return $pw;
201}
202
203/**
204 * Sends a password to the given user
205 *
206 * returns true on success
207 */
208function auth_sendPassword($user,$password){
209  global $conf;
210  global $lang;
211  $users = auth_loadUserData();
212  $hdrs  = '';
213
214  if(!$users[$user]['mail']) return false;
215
216  $text = rawLocale('password');
217  $text = str_replace('@DOKUWIKIURL@',getBaseURL(true),$text);
218  $text = str_replace('@FULLNAME@',$users[$user]['name'],$text);
219  $text = str_replace('@LOGIN@',$user,$text);
220  $text = str_replace('@PASSWORD@',$password,$text);
221  $text = str_replace('@TITLE@',$conf['title'],$text);
222
223  if (!empty($conf['mailfrom'])) {
224    $hdrs = 'From: '.$conf['mailfrom']."\n";
225  }
226  return @mail($users[$user]['mail'],$lang['regpwmail'],$text,$hdrs);
227}
228
229/**
230 * The new user registration - we get our info directly from
231 * $_POST
232 *
233 * It returns true on success and false on any error
234 */
235function register(){
236  global $lang;
237  global $conf;
238
239  if(!$_POST['save']) return false;
240  if(!$conf['openregister']) return false;
241
242  //clean username
243  $_POST['login'] = preg_replace('/.*:/','',$_POST['login']);
244  $_POST['login'] = cleanID($_POST['login']);
245  //clean fullname and email
246  $_POST['fullname'] = trim(str_replace(':','',$_POST['fullname']));
247  $_POST['email']    = trim(str_replace(':','',$_POST['email']));
248
249  if( empty($_POST['login']) ||
250      empty($_POST['fullname']) ||
251      empty($_POST['email']) ){
252    msg($lang['regmissing'],-1);
253    return false;
254  }
255
256  //check mail
257  if(!isvalidemail($_POST['email'])){
258    msg($lang['regbadmail'],-1);
259    return false;
260  }
261
262  //okay try to create the user
263  $pass = auth_createUser($_POST['login'],$_POST['fullname'],$_POST['email']);
264  if(empty($pass)){
265    msg($lang['reguexists'],-1);
266    return false;
267  }
268
269  //send him the password
270  if (auth_sendPassword($_POST['login'],$pass)){
271    msg($lang['regsuccess'],1);
272    return true;
273  }else{
274    msg($lang['regmailfail'],-1);
275    return false;
276  }
277}
278
279/**
280 * Uses a regular expresion to check if a given mail address is valid
281 *
282 * @see http://www.webmasterworld.com/forum88/135.htm
283 *
284 * May not be completly RFC conform!
285 */
286function isvalidemail($email){
287  return eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,4}$", $email);
288}
289
290?>
291