00001 <?php
00002 # This file is part of the Savane project
00003 # <http://gna.org/projects/savane/>
00004 #
00005 # $Id: session.php 5450 2006-02-19 18:00:27Z yeupou $
00006 #
00007 # Copyright 1999-2000 (c) The SourceForge Crew
00008 # Copyright 2000-2003 (c) Free Software Foundation
00009 #
00010 # Copyright 2003-2005 (c) Mathieu Roy <yeupou--at--gnu.org>
00011 # Derek Feichtinger <derek.feichtinger--cern.ch>
00012 #
00013 # The Savane project is free software; you can redistribute it and/or
00014 # modify it under the terms of the GNU General Public License
00015 # as published by the Free Software Foundation; either version 2
00016 # of the License, or (at your option) any later version.
00017 #
00018 # The Savane project is distributed in the hope that it will be useful,
00019 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00021 # GNU General Public License for more details.
00022 #
00023 # You should have received a copy of the GNU General Public License
00024 # along with the Savane project; if not, write to the Free Software
00025 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00026
00027
00028 $G_SESSION=array();
00029 $G_USER=array();
00030
00031 function session_login_valid($form_loginname,
00032 $form_pw,
00033 $allowpending=0,
00034 $cookie_for_a_year=0,
00035 $crypted_pw=0,
00036 $stay_in_ssl=1)
00037 {
00038
00039 # Password is crypted if we are coming from the brother site.
00040 # Normally, users should use this feature
00041 # if they never login at brother site.
00042 # FIXME: feel free to mess with PHP3 and crypt...
00043 global $session_hash;
00044
00045 if (!$form_loginname || !$form_pw)
00046 {
00047 fb(_('Missing Password Or User Name'), 1);
00048 return false;
00049 }
00050
00051 $resq = db_query("SELECT user_id,user_pw,status FROM user WHERE "
00052 . "user_name = '$form_loginname'");
00053 if (!$resq || db_numrows($resq) < 1)
00054 {
00055 fb(_('Invalid User Name'), 1);
00056 return false;
00057 }
00058
00059 $usr = db_fetch_array($resq);
00060
00061 # Check status first:
00062 # if allowpending (for verify.php) then allow
00063 if ($allowpending && ($usr['status'] == 'P'))
00064 {
00065 #1;
00066 }
00067 else
00068 {
00069 if ($usr['status'] == 'P')
00070 {
00071 #account pending
00072 fb(_('Account Pending'), 1);
00073 return false;
00074 }
00075 if ($usr['status'] == 'D' || $usr['status'] == 'S')
00076 {
00077 #account deleted
00078 fb(_('Account Deleted'), 1);
00079 return false;
00080 }
00081 if ($usr['status'] != 'A')
00082 {
00083 #unacceptable account flag
00084 fb(_('Account Not Active'),1);
00085 return false;
00086 }
00087 }
00088
00089
00090
00091 # TODO: Brother site login mechanism should be implemented later for
00092 # all authentication methods:
00093 #
00094
00095
00096 #
00097 # authentication method: PAM based
00098 # this requires the 'pam_auth' php extension from
00099 # http:#www.math.ohio-state.edu/~ccunning/pam_auth.html
00100 #
00101 if($usr['user_pw'] == 'PAM')
00102 {
00103 $pam_error='';
00104 if(! pam_auth($form_loginname, $form_pw, &$pam_error))
00105 {
00106 fb(_('Invalid Password (AFS)'), 1);
00107 return false;
00108 }
00109
00110 }
00111 else if ($usr['user_pw'] == '')
00112 {
00113 #
00114 # authentication method: Kerberos
00115 # If both user_pw and unix_pw are empty the user might
00116 # be able to login if she/he has a Kerberos account.
00117 # Update unix_pw and user_pw.
00118 # TODO: THE KERBEROS PASSWORD SHOULD NOT BE STORED LOCALLY!!!!
00119 #
00120 if ($GLOBALS[sys_use_krb5])
00121 { $ret = krb5_login($form_loginname, $form_pw); }
00122
00123 if($ret == KRB5_NOTOK)
00124 {
00125 fb("phpkrb5 module failure", 1);
00126 return false;
00127 }
00128 if($ret == KRB5_BAD_USER)
00129 {
00130 fb("user is not a kerberos principal", 1);
00131 return false;
00132 }
00133 if($ret == KRB5_BAD_PASSWORD)
00134 {
00135 fb("user is a kerberos principal but passwords do not match", 1);
00136 return false;
00137 }
00138 $md5_pw = md5($form_pw);
00139 db_query("UPDATE user SET user_pw = '$md5_pw' WHERE user_id = ".$usr['user_id']);
00140 }
00141 else if($usr['user_pw'] == 'SSH')
00142 {
00143 fb('This user is known but we have no way to authenticate her/him. Please ask for a password to site administrators', 1);
00144 return false;
00145
00146 }
00147 else
00148 {
00149 # Default authentication method:
00150 # MD5 encrypted password stored locally
00151
00152 # For this authentication method we enable a brother site
00153 # login mechanism:
00154 # Password is crypted (crypt()) if we are coming from the brother site.
00155 # Normally, users shouldn't use this feature
00156 # unless they login at brother site one time.
00157 # FIXME: feel free to mess with PHP3 and crypt...
00158 if ($crypted_pw)
00159 {
00160 if (crypt($usr['user_pw'],$form_pw) != $form_pw)
00161 {
00162 #invalid password or user_name
00163 fb(_('Invalid Password'),1);
00164 return false;
00165 }
00166 }
00167 else
00168 {
00169 if ($usr['user_pw'] != md5($form_pw))
00170 {
00171 #invalid password or user_name
00172 fb(_('Invalid Password'),1);
00173 return false;
00174 }
00175 }
00176
00177 }
00178
00179
00180
00181 #create a new session
00182 session_set_new($usr['user_id'], $cookie_for_a_year, $stay_in_ssl);
00183
00184 return true;
00185 }
00186
00187 function session_checkip($oldip,$newip)
00188 {
00189 $eoldip = explode(".",$oldip);
00190 $enewip = explode(".",$newip);
00191
00192 # ## require same class b subnet
00193 if (($eoldip[0]!=$enewip[0])||($eoldip[1]!=$enewip[1]))
00194 {
00195 return 0;
00196 }
00197 else
00198 {
00199 return 1;
00200 }
00201 }
00202
00203 function session_issecure()
00204 {
00205 return (getenv('HTTPS') == 'on');
00206 }
00207
00208
00209 function session_needsstayinssl()
00210 {
00211 return db_result(db_query("SELECT stay_in_ssl FROM session WHERE session_hash='$GLOBALS[session_hash]'"), 0, 'stay_in_ssl');
00212 }
00213
00214 function session_cookie($n,$v,$cookie_for_a_year=0)
00215 {
00216
00217 # yeupou--gnu.org 2004-09-21: this will pose problem on different servers
00218 # with the same domain; on the other hand, it's helpful for servers that
00219 # want multiple domains to be working.
00220 # In the meantime, shut it off.
00221 #
00222 # Define the domain name, only the last part of it like .domain.org
00223 # in order to permit any host of .domain.org to access it.
00224 #preg_match("/[^\.\/]+\.[^\.\/]+$/", $GLOBALS['sys_default_domain'], $domain);
00225 #$domain = ".".$domain[0];
00226 $domain = $GLOBALS['sys_default_domain'];
00227
00228 if ($cookie_for_a_year=="1")
00229 {
00230 # Set the cookie for a year.
00231 setcookie($n,$v, time() + 60*60*24*365 ,$GLOBALS['sys_home'],$domain,0);
00232 }
00233 else
00234 {
00235 setcookie($n,$v,0,$GLOBALS['sys_home'],$domain,0);
00236 }
00237 }
00238
00239 # Removes a cookie. This is an alternative to setting it to an empty
00240 # or irrelevant value, and will just prevent the browser from sending
00241 # it again.
00242 function session_delete_cookie($n)
00243 {
00244 setcookie($n, '', 0, $GLOBALS['sys_home'], $GLOBALS['sys_default_domain'], 0);
00245 }
00246
00247 function session_redirect($loc)
00248 {
00249 header('Location: http' . (session_issecure()?'s':'') . ':
00250 print("\n\n");
00251 exit;
00252 }
00253
00254 function session_require_test($req)
00255 {
00256
00257
00258
00259 if (user_is_super_user())
00260 {
00261 return true;
00262 }
00263 if ($req['group'])
00264 {
00265 $query = "SELECT user_id FROM user_group WHERE user_id=" . user_getid()
00266 . " AND group_id=$req[group]";
00267 if ($req['admin_flags'])
00268 {
00269 $query .= " AND admin_flags = '$req[admin_flags]'";
00270 }
00271 if ((db_numrows(db_query($query)) < 1) || !$req['group'])
00272 {
00273 return false;
00274 }
00275
00276 }
00277 elseif ($req['user'])
00278 {
00279 if (user_getid() != $req['user'])
00280 {
00281 return false;
00282 }
00283 }
00284 elseif ($req['isloggedin'])
00285 {
00286 if (!user_isloggedin())
00287 {
00288 return false;
00289 }
00290 }
00291 else
00292 {
00293 return false;
00294 }
00295
00296 }
00297
00298 function session_require($req)
00299 {
00300
00301
00302
00303 if (user_is_super_user())
00304 {
00305 return true;
00306 }
00307
00308 if ($req['group'])
00309 {
00310 $query = "SELECT user_id FROM user_group WHERE user_id=" . user_getid()
00311 . " AND group_id=$req[group]";
00312 if ($req['admin_flags'])
00313 {
00314 $query .= " AND admin_flags = '$req[admin_flags]'";
00315 }
00316
00317 if ((db_numrows(db_query($query)) < 1) || !$req['group'])
00318 {
00319 exit_error("Insufficient Group Access","You do not have permission to "
00320 . "view this page.");
00321 }
00322 }
00323 elseif ($req['user'])
00324 {
00325 if (user_getid() != $req['user'])
00326 {
00327 exit_error("Insufficient User Access","You do not have permission to "
00328 . "view this page.");
00329 }
00330 }
00331 elseif ($req['isloggedin'])
00332 {
00333 if (!user_isloggedin())
00334 {
00335 exit_error("Required Login","In order to view this page, you must "
00336 . "be logged in.");
00337 }
00338 }
00339 else
00340 {
00341 exit_error("Insufficient Access","Probably by mangling a URL, you have attempted "
00342 . "to reach a part of the site for which you do not have access. This can "
00343 . "probably be fixed by properly navigating through the site.");
00344 }
00345 }
00346
00347 function session_setglobals($user_id)
00348 {
00349 global $G_USER;
00350
00351 # unset($G_USER);
00352
00353 if ($user_id > 0)
00354 {
00355 $result=db_query("SELECT user_id,user_name FROM user WHERE user_id='$user_id'");
00356 if (!$result || db_numrows($result) < 1)
00357 {
00358 #echo db_error();
00359 $G_USER = array();
00360 }
00361 else
00362 {
00363 $G_USER = db_fetch_array($result);
00364 # echo $G_USER['user_name'].'<BR>';
00365 }
00366 }
00367 else
00368 {
00369 $G_USER = array();
00370 }
00371 }
00372
00373 function session_set_new($user_id, $cookie_for_a_year=0, $stay_in_ssl=1)
00374 {
00375 global $G_SESSION;
00376
00377 # unset($G_SESSION);
00378
00379 # concatinate current time, and random seed for MD5 hash
00380 # continue until unique hash is generated (SHOULD only be once)
00381 do {
00382 $pre_hash = time() . rand() . $GLOBALS['REMOTE_ADDR'] . microtime();
00383 $GLOBALS['session_hash'] = md5($pre_hash);
00384 }
00385 while (db_numrows(db_query("SELECT session_hash FROM session WHERE session_hash='$GLOBALS[session_hash]'")) > 0);
00386
00387 # set session cookies
00388 session_cookie("session_hash",$GLOBALS['session_hash'],$cookie_for_a_year);
00389 session_cookie("session_uid",$user_id,$cookie_for_a_year);
00390
00391 # make new session entries into db
00392 db_query("INSERT INTO session (session_hash, ip_addr, time, user_id, stay_in_ssl) VALUES ('".addslashes($GLOBALS[session_hash])."','".addslashes($GLOBALS[REMOTE_ADDR])."'," . time() . ",'$user_id','$stay_in_ssl')");
00393
00394 # set global
00395 $res=db_query("SELECT * FROM session WHERE session_hash='$GLOBALS[session_hash]'");
00396 if (db_numrows($res) > 1)
00397 {
00398 db_query("DELETE FROM session WHERE session_hash='$GLOBALS[session_hash]'");
00399 exit_error("ERROR","ERROR - two people had the same hash - backarrow and re-login. It should never happen again");
00400 }
00401 else
00402 {
00403 $G_SESSION = db_fetch_array($res);
00404 session_setglobals($G_SESSION['user_id']);
00405 }
00406
00407 # if the user specified he wants only one session to be opened at a time,
00408 # kill the others sessions
00409 if (user_get_preference("keep_only_one_session"))
00410 {
00411 db_query("DELETE FROM session WHERE session_hash<>'$GLOBALS[session_hash]' AND user_id='$user_id'");
00412 }
00413 }
00414
00415 function session_set()
00416 {
00417 global $G_SESSION,$G_USER;
00418
00419 # unset($G_SESSION);
00420
00421 # assume bad session_hash and session. If all checks work, then allow
00422 # otherwise make new session
00423 $id_is_good = 0;
00424
00425 # here also check for good hash, set if new session is needed
00426 $session_hash = sane_cookie("session_hash");
00427 $session_uid = sane_cookie("session_uid");
00428 if ($session_hash && $session_uid)
00429 {
00430 $result=db_query("SELECT * FROM session WHERE session_hash='".$session_hash."' AND user_id='".$session_uid."'");
00431 $G_SESSION = db_fetch_array($result);
00432
00433 # does hash exist?
00434 if ($G_SESSION['session_hash'])
00435 {
00436 if (session_checkip($G_SESSION['ip_addr'],$GLOBALS['REMOTE_ADDR']))
00437 {
00438 $id_is_good = 1;
00439 }
00440 } # else hash was not in database
00441 } # else (hash does not exist) or (session hash is bad)
00442
00443 if ($id_is_good)
00444 {
00445 session_setglobals($G_SESSION['user_id']);
00446 }
00447 else
00448 {
00449 unset($G_SESSION);
00450 unset($G_USER);
00451 }
00452 }
00453
00454 function session_count ($uid)
00455 {
00456 return db_numrows(db_query("SELECT ip_addr FROM session WHERE "
00457 . "user_id = '".$uid."'"));
00458
00459 }
00460
00461 ?>