I have a working Session management on my platform which I programmed in PHP.
For security reasons I want to regenerate the Session ID at least when a user logs in successfully and if possible with each request to prevent session fixation.
The login part looks like this if the login credentials are correct. If they are not correct or the user has not entered anything yet I do not start a session and as far as I know one old value for the session id is used
session_set_cookie_params(1800, "/", $domain, true, true);
session_start();
session_regenerate_id(true);
Each time I make another request to the server and it checks wether my session is valid I call
session_regenerate_id(true);
I check for a valid session with this code:
$domain = $_SERVER["HTTP_HOST"];
if(session_status() != PHP_SESSION_ACTIVE)
{
session_set_cookie_params(0, "/", $domain, true, true);
session_start();
}
//Check if session has expired
$now = time();
if(isset($_SESSION["discard_after"]) && $now > $_SESSION["discard_after"])
{
session_unset();
session_destroy();
header("Location: https://".$domain."/login.php");
die();
}
session_regenerate_id(true);
$_SESSION["discard_after"] = $now + 120;
if ((!isset($_SESSION["loggedin"]) || !$_SESSION["loggedin"]) &&
basename($_SERVER["PHP_SELF"]) != "login.php")
{
header("Location: https://".$domain."/login.php");
die();
}
I monitored this with Burp and confirmed, that the session id changes when I log in successfully. The session ID also changes when I navigate through the site without any problem and just the way I want to.
However this behaviour is not consitent. I have some user who enter the correct credentials (I know this because of the logs) but have no valid session and can not cross the login page to the home page.
I also have the strange case that one has to log in twice (both times correct credentials) befor a valid session is set. This happens to me unpredictable as well as to other users. I could not see yet when this happens and when not, only that the login should have worked.
Some information about the setup. I have a Ubuntu 14.04 vServer with Apache2 and PHP 5.X. On the client side I use the latest version of Firefox and Chrome on Windows 7 64x. One user who can not login at all even though the credentials are correct and the code above is definitly executed is using Chrome on Windows 7 64x as well (I have no more information regarding this).
I know for sure that the problem is the session_regenerate_id(true); function because if I comment this line out everything works fine but this solution is not satisfactory to me. I also tried a PC from which I certainly never entered the website befor and there everything also works.
I can not see what causes this and the PHP man page did not really help me there. Especially the not determinstic behaviour confuses me.
I might not answer until tomorrow but I will value all useful answers and comments.
EDIT
This is the entire login sequence without unneccessary stuff that is not executed in my scenario or definitly unimportant. I never output anything befor.
if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["inputEmail"],
$_POST["inputPassword"]) && $_POST["inputEmail"] !== "" &&
$_POST["inputPassword"] !== "")
{
$domain = $_SERVER["HTTP_HOST"];
$passwordHash = hash("sha256", $_POST["inputPassword"]."somesecretsalt");
//Own function which definitly works
$connection = connectToDB("standard");
//Get usernames and passwordhashes for checking
$query_getUser = "SELECT id, firstname, lastname, email,
passwordhash FROM user WHERE email = ?;";
if($stmt = mysqli_prepare($connection, $query_getUser))
{
mysqli_stmt_bind_param($stmt, "s", $_POST["inputEmail"]);
mysqli_stmt_execute($stmt);
$userRAW = mysqli_stmt_get_result($stmt);
mysqli_stmt_close($stmt);
}
if(mysqli_num_rows($userRAW) == 1)
{
//State: User exists
$dataset = mysqli_fetch_array($userRAW, MYSQLI_ASSOC);
$now = time();
//This is the crucial part which is definitly executed because the
// log entry in the following if clause is executed
session_set_cookie_params(1800, "/", $domain, true, true);
session_start();
session_regenerate_id(true);
if($dataset["passwordhash"] === $passwordHash)
{
//State: User exists, correct password
$_SESSION["loggedin"] = true;
$_SESSION["id"] = $dataset["id"];
$_SESSION["email"] = $dataset["email"];
$_SESSION["name"] = $dataset["firstname"]." ".$dataset["lastname"];
$comment = $_SESSION["name"]." (ID:".$dataset["id"].") has logged in";
writeToLog("Login success ", $comment, __LINE__);
if ($_SERVER["SERVER_PROTOCOL"] == "HTTP/1.1")
{
if(php_sapi_name() == "cgi")
{
header("Status: 303 See Other");
}
else
{
header("HTTP/1.1 303 See Other");
}
}
header("Location: https://".$domain."/index.php");
mysqli_close($connection);
die();
}
}
mysqli_close($connection);
}
Related
I built a PHP/MySql login system for a website I am working on and all was working fine. I took a month off from working on it, pulled it up last night, and all of a sudden it doesn't work. It recognizes if a wrong username or password was entered, but if you enter the correct information it redirects you to the login page again. Was there some update somewhere that I am unaware of? I did not change anything in any of my files. It was working perfectly a month ago, and with no change at all it doesn't work now. Any ideas?
UPDATE
It is working if I check the remember me box, but not if I don't I will paste my code below:
Login Script:
<?php
define('INCLUDE_CHECK',true);
require 'connect.php';
require 'functions.php';
session_name('TheLoginSession');
session_start();
// ---------- LOGIN ----------
if($_POST['submit']=='Login')
{
// Checking whether the Login form has been submitted
$err = array();
// Will hold our errors
if(!$_POST['username'] || !$_POST['password'])
$err[] = 'All the fields must be filled in!';
if(!count($err))
{
$_POST['username'] = mysql_real_escape_string($_POST['username']);
$_POST['password'] = mysql_real_escape_string($_POST['password']);
$_POST['remembercheck'] = (int)$_POST['remembercheck'];
$storedsaltquery = mysql_fetch_assoc(mysql_query("SELECT rand FROM members WHERE usr = '".$_POST['username']."'"));
$storedsalt = $storedsaltquery['rand'];
// Escaping all input data
$row = mysql_fetch_assoc(mysql_query("SELECT id,compid,usr,firstName,level,yn FROM members WHERE usr='{$_POST['usernamelog']}' AND pass='".hash("sha256",$_POST['passwordlog'].$storedsalt)."'"));
if($row['id'])
{
// If everything is OK login
$_SESSION['usr']=$row['usr'];
$_SESSION['comp']=$row['compid'];
$_SESSION['id'] = $row['id'];
$_SESSION['name'] = $row['firstName'];
$_SESSION['usrlevel'] = $row['level'];
$_SESSION['new'] = $row['yn'];
$_SESSION['remembercheck'] = $_POST['remembercheck'];
// Store some data in the session
setcookie('Remember','remembercheck',time()+1209600,'/','.domain.com');
}
else $err[]='Wrong username and/or password!';
}
if($err)
$_SESSION['msg']['login-err'] = implode('<br />',$err);
// Save the error messages in the session
echo header("Location: ../index.php");
exit;
}
Index Page:
<?php
define('INCLUDE_CHECK',true);
require 'includes/connect.php';
require 'includes/functions.php';
// Those two files can be included only if INCLUDE_CHECK is defined
session_name('TheLoginSession');
// Starting the session
session_start();
if($_SESSION['id'] && !isset($_COOKIE['Remember']) && !$_SESSION['remembercheck'])
{
// If you are logged in, but you don't have the Remember cookie (browser restart)
// and you have not checked the remembercheck checkbox:
$_SESSION = array();
session_destroy();
// Destroy the session
}
if(isset($_GET['logoff']))
{
$_SESSION = array();
session_destroy();
header("Location: index.php");
exit;
}
if($_SESSION['id'] && $_SESSION['new'] != 1){
header("Location: home.php");
exit;
}
?>
How can there be an update if nothing's changed?
Are you using a CMS or framework?
If it's all your own code, and you haven't changed anything, then nothing would have updated.
I've had an issue like this before but without more information, hard to know if it is the same issue. Mine had the symptom you describe (login with bad creds and get the authentication error, login with good creds and redirect back to login).
Mine was due to failing to include code to remove old session cookies. The login attempt 'works' but an old cookie also read and attempts to authenticate, fails (because it is too old), and kicks the user back to login.
If this is your issue, clear your site cookies and see if you can then log in.
If that works, you'll want to add some cleanup code to your logout and stale session handling. For instance, for logging out:
// per http://www.php.net/manual/en/function.session-destroy.php
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
session_destroy();
Again, just guessing at your issue here.
this is my first question asked on SO so please excuse me if I go against some of the post etiquette - I'll do my best to explain my problem clearly, and I have searched for previous questions but none match my issue as far as I'm aware.
Background: Running on WAMP server 2.4 with Apache 2.4.4 and PHP 5.4.12 - Please let me know if you need any specifics.
I've been working on a new webapp project and seem to have run into a problem while trying to get PHP sessions working. My login process works as follows;
Once a user submits details and they are crosschecked with those stored in a Mysql database, a session is created and they are redirected to a temporary protected page.
The temporary page checks that the user has a valid session and if so displays a welcome message.
If the user does not have a valid session then they receive an error.
PROBLEM: Whenever I login (successfully might I add) I'm redirected and receive the error message "You are not authorized to access this page."
Here is the code for the login process (process_login.php):
<?php
include_once 'db_connect.php';
include_once 'functions.php';
sec_session_start(); // Our custom secure way of starting a PHP session.
if (isset($_POST['email'], $_POST['p'])) {
$email = $_POST['email'];
$password = $_POST['p']; // The hashed password.
//Form data error handling.
if ($email == "" || $password == ""){
echo "login failed";
exit();
} else {
//DB stuff.
$stmt = $mysqli->prepare("SELECT id, username, password, salt
FROM members
WHERE email = ?
LIMIT 1");
$stmt->bind_param('s', $email); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
// get variables from result.
$stmt->bind_result($user_id, $username, $db_password, $salt);
$stmt->fetch();
// hash the password with the unique salt.
$password = hash('sha512', $password . $salt);
if ($stmt->num_rows == 1) {
// If the user exists we check if the account is locked
// from too many login attempts
if (checkbrute($user_id, $mysqli) == true) {
// Account is locked
// Send an email to user saying their account is locked
return false;
} else {
// Check if the password in the database matches
// the password the user submitted.
if ($db_password == $password) {
// Password is correct!
// Get the user-agent string of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT'];
// XSS protection as we might print this value
$user_id = preg_replace("/[^0-9]+/", "", $user_id);
$_SESSION['user_id'] = $user_id;
// XSS protection as we might print this value
$username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username);
$_SESSION['username'] = $username;
$_SESSION['login_string'] = hash('sha512', $password . $user_browser);
header('Location: ../protected_page.php');
} else {
// Login failed
// Password is not correct
// We record this attempt in the database
$now = time();
$mysqli->query("INSERT INTO login_attempts(user_id, time)
VALUES ('$user_id', '$now')");
header('Location: ../index.php?error=1');
}
}
}
Here is the code for my session_start function (sec_session_start() )
function sec_session_start() {
$session_name = 'sec_session_id'; // Set a custom session name
$secure = true;
// This stops JavaScript being able to access the session id.
$httponly = true;
// Forces sessions to only use cookies.
if (ini_set('session.use_only_cookies', 1) === FALSE) {
header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
exit();
}
// Gets current cookies params.
$cookieParams = session_get_cookie_params();
session_set_cookie_params($cookieParams["lifetime"],
$cookieParams["path"],
$cookieParams["domain"],
$secure,
$httponly);
// Sets the session name to the one set above.
session_name($session_name);
session_start(); // Start the PHP session
session_regenerate_id(); // regenerated the session, delete the old one.
Here is my temporary test code (protected_page.php);
-note I'm new to this and seem to be having trouble posting my html.
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';
sec_session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Secure Login: Protected Page</title>
<link rel="stylesheet" href="styles/main.css" />
</head>
<body>
<?php if (login_check($mysqli) == true) {?>
<p>Welcome <?php echo htmlentities($_SESSION['username']); ?>!</p>
<p>
This is an example protected page. To access this page, users
must be logged in. At some stage, we'll also check the role of
the user, so pages will be able to determine the type of user
authorised to access the page.
</p>
<p>Return to login page</p>
<?php } else {?>
<p>
<span class="error">You are not authorized to access this page.</span> Please login.
</p>
<?php }?>
</body>
</html>
As far as any other specifics that might make a difference - the login form is loaded through a sidebar and sends
Any help is much appreciated! I'm semi new to this stuff and I've spent 5+ hours fiddling and can't seem to figure it out. Login works, the session code (as far as I'm aware) makes sense and SHOULD be working - ugh halp me.
ADDED NOTE: I've checked my C:/wamp/etc/ file and cleared the sessions, just by logging in apparently 4 session files are created? I think this must have something to do with it.
http://puu.sh/71Lhm.png
Okay I ended up solving my own problem, but I'm going to leave the answer here incase anybody has a similar issue with WAMP. (I think it's because I was using WAMP)
In my custom session function (sec_session_start) I had the option for $secure enabled. Though I believe this is only functional when you have it live on a production server using HTTPS. (Not on my local machine.) My reasoning could be wrong, but I changed the value of
$secure = true;
to
$secure = false;
And it worked! Great success.
I'm going through the pain of upgrading PHP on my server from 5.2 to 5.3. Having migrated my old php.ini to the new and upgraded my mysql passwords, my PHP sessions no longer work.
This is my login code below, it executes correctly and even logs my login correctly in the activity log. (updatelog function) I have also posted my session valid check code.
Is there anything obvious in my login code that is no longer valid in PHP 5.3, having previously worked under 5.2?
// Login User///
if(#$_POST["dologin"] == 1)
{
//record login attempt
updatelog("",$_SERVER['REMOTE_ADDR'],"Login Attempt By: ".$_POST['username']);
$user_name = escape($_POST["username"]);
$password = escape(md5(SALT.$_POST["password"]));
$login = $query->GetSingleQuery("--SINGLE","SELECT user_name, id, user_email FROM url_users WHERE user_name='".$user_name."' and user_password='".$password."';",array("user_name","id","user_email"));
if(!isset($login['user_name'])) //failed login
{
$_SESSION['loggedin'] = 0;
//record failure
updatelog("",$_SERVER['REMOTE_ADDR'],"Login Failure By: ".$_POST['username']);
header("Location: index.php?failed=1&user=$user_name");
}else
{
//login valid
//get country details
$getcountry = $query->GetSingleQuery("--SINGLE","SELECT geo_ip.ctry FROM admin_adfly.geo_ip geo_ip WHERE INET_ATON ('".$_SERVER['REMOTE_ADDR']."') BETWEEN geo_ip.ipfrom AND geo_ip.ipto;",array("ctry"));
//set session items
$_SESSION['country'] = $getcountry['ctry'];
$_SESSION['username'] = $login['user_name'];
$_SESSION['userid'] = $login['id'];
$_SESSION['loggedin'] = 1;
$_SESSION['email'] = $login['user_email'];
//session salt
$hsh = md5($_SERVER['HTTP_USER_AGENT'].SALT);
$_SESSION['_XXX(*##!_D#R*&$%(){*#)_D_296']['user_agent'] = $hsh;
//update the ui transaction log
updatelog($login['id'],$_SERVER['REMOTE_ADDR'],"Login Success For: ".$_POST['username']);
// run function to check if any adverts have completed
adcomplete($_SESSION['userid']);
//redirect
header("Location: index.php");
}
}
// Check users login session is valid, this is called on each page I want to restrict by login. ////
if(isset($_SESSION['_XXX(*##!_D#R*&$%(){*#)_D_296']['user_agent']) == $_SERVER['HTTP_USER_AGENT'].SALT)
{
return 1; //session success
}else
{
return 0; //session failure
}
The check for login is not checking the hash of user agent and salt, should be :
if (isset($_SESSION['_XXX(*##!_D#R*&$%(){*#)_D_296']['user_agent']) == md5($_SERVER['HTTP_USER_AGENT'].SALT))
{
return 1; //session success
} else {
return 0; //session failure
}
Edit:
Since the problem persists and it seems to be a php configuration issue I would try to make the simplest php page that uses sessions and try it out in the 5.3 environment to confirm that it is a php configuration problem and use that simple page to test the configuration while trying to fix the issue.
A simple php page:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
session_start();
if (isset($_SESSION['views']))
$_SESSION['views'] = $_SESSION['views'] + 1;
else
$_SESSION['views'] = 0;
echo '<pre>';
var_dump(session_id()); // I should stay the same
var_dump($_SESSION); // I should start at 0 and increase
echo '</pre>';
Simple solution:
Go to /var/lib/php and set attributes 777 to "session" directory.
EDIT:
Yes, I know it is not recommended solution, but it works. For do it right, you should set owner to php, httpd or nginx - I don't have time to check which it should be
After much messing about, it turns out that the problem was related to the last session name, it was somehow invalidating the entire browser session, removing all data from the session.
After removing "(*##!_D#R*&$%(){*#)_D_296" from the $_SESSION array, my login session started working again.
I have posted a question for this a long time ago, but i still can't find a answer. Basically, when a user has logged into the account and has been inactive for a while and when they return they would click something and then the system would log them out and they would have to re-login. It works 90% of the time, but sometimes it gives an error like: This page is redirecting in a way it will never complete.
But when a user clears the cookies it works fine and sometimes closing the tab and opening up a new one works too.
Here's the code:
<?php
$SUBDOMAIN = mysql_real_escape_string($_GET['p_name']);
$pname = mysql_real_escape_string($_GET['p_name']);
echo "$p_name";
include("db.php");
?>
<?php
session_start();
// Process the POST variables
$username = $_SESSION["user_name"];
//$password = $_POST["password"];
// Set up the session variables
$_SESSION["user_name"] = $username;
$ugData = $_REQUEST['p_name'];
if($_POST)
{
$_SESSION['user_name']=$_POST["user_name"];
$_SESSION['password']=$_POST["password"];
}
$secret = $info['password'];
//Checks if there is a login cookie
if(isset($_COOKIE['ID_my_site']))
//if there is, it logs you in and directes you to the members page
{
$username = $_COOKIE['ID_my_site'];
$pass = $_COOKIE['Key_my_site'];
$check = mysql_query("SELECT user_name, password FROM accounts WHERE user_name = '$username' and p_name='$ugData'")or die(mysql_error());
while($info = mysql_fetch_array( $check ))
{
if (# $info['password'] != $pass)
{
}
else
{
header("Location: home.php");
}
}
}
//if the login form is submitted
if (isset($_POST['submit']))
{
// if form has been submitted
// makes sure they filled it in
if(!$_POST['user_name'] | !$_POST['password'])
{
die('You did not fill in a required field.');
}
//checks it against the database
if (!get_magic_quotes_gpc())
{
$_POST['user_name'] = addslashes($_POST['user_name']);
}
$check = mysql_query("SELECT user_name,password FROM accounts WHERE user_name = '".$_POST['user_name']."' and p_name='".$ugData."'")or die(mysql_error());
//Gives error if user dosen't exist
$check2 = mysql_num_rows($check);
if ($check2 == 0)
{
die('That user does not exist in our database. <a href=add.php>Click Here to Register</a>');
}
while($info = mysql_fetch_array( $check ))
{
$_POST['password'] = md5($_POST['password']);
$_POST['password'] = $_POST['password'];
//gives error if the password is wrong
if (# $_POST['password'] != $info['password'])
{
die('Incorrect password, please try again');
}
else
{
// if login is ok then we add a cookie
$_POST['user_name'] = stripslashes($_POST['user_name']);
$hour = time() + 3600;
setcookie(ID_my_site, $_POST['user_name'], $hour);
setcookie(Key_my_site, $_POST['password'], $hour);
//then redirect them to the members area
header("Location: home.php");
}
}
}
else
{
// if they are not logged in
?>
</table>
</form>
<?php
}
?>
Hey, your code formatting is really bad no fun to read you might want to fix that. :)
I just had a quick look at it, erros occurring only 90% or sometimes hard to catch.
I saw you are using header("Location: home.php"); without any exit; at the end, which is generally a bad idea unless you intent to do so.
The function call header("Location: home.php"); will not stop the script from processing. The user might get the header and redirects and stops code from processing (depending on some php settings) but maybe some cookies get set before the user gets redirected. So try adding a exit; after your redirect header calls.
format you code
I would wager a guess that this has to due with the differing expire times of your session cookie, and the expire times you set for your ID_my_site and Key_my_site cookies. If not overridden, the default session timeout is 30 minutes (expressed as seconds in the settings - so 1,800). Your cookies are set to expire after an hour. So you could find yourself in a situation where the session has expired, but the other cookies are still present. Depending on the order / way you are checking things and then redirecting, you will encounter this situation if the user was idle for more than 30 minutes but less than 1 hour.
Since the only redirect you are performing in this code sample is the one to home.php, there is some sort of check occurring in that file, that is sending them on the never ending redirect spiral.
As an aside, that code sample really is very messy. You are assigning and reassigning the $username variable so often for example (and to seemingly different types of things - though I wouldn't know without seeing actual input), that it is no wonder you are having mystery issues. These few lines for example are redundant:
// Process the POST variables
$username = $_SESSION["user_name"];
//$password = $_POST["password"];
// Set up the session variables
$_SESSION["user_name"] = $username;
You're assigning $username from the session and immediately assigning it back.
From the beginning of the file:
$SUBDOMAIN = mysql_real_escape_string($_GET['p_name']);
$pname = mysql_real_escape_string($_GET['p_name']);
These two variables are assigned the same $_GET value, but it doesn't appear that $SUBDOMAIN is ever used.
And from the end of the file you are assigning the same value twice:
$_POST['password'] = md5($_POST['password']);
$_POST['password'] = $_POST['password'];
I really would encourage you to step back from your code, look at your inputs and figure out what you need to accomplish and refactor or rewrite this code entirely. With stuff like this floating around it is no wonder you have mystery bugs in your system.
Additionally, a HTTP Location header requires the URL to be absolute. You should use something like this:
$currentServerHost = $_SERVER['HTTP_HOST'];
$currentBaseURI = $currentServerHost . rtrim(dirname($_SERVER['PHP_SELF']), '/\');
header( 'Location: ' . 'http://' . $finalURI . '/home.php' );
exit;
Greetings,
I am working on a login system and getting stuck with Blackberry browsers authenticating. It seems they have an issue with PHP's session_regenerate_id(), can someone suggest an alternative? Here are the auth and login scripts:
UPDATE
It would appear that sessions in general are not working. Took out session_regenerate_id() just to see if it would work and it just redirects me every time, as though the $_SESSION['MD_SESS_ID']were blank. Really stuck here, any ideas would be appreciated. Cookies on the device are enabled, using a Blackberry Bold 9650. It works on my iPod Touch and every browser on my PC.
Login
<?php
session_start();
include $_SERVER['DOCUMENT_ROOT'] . '/includes/pdo_conn.inc.php';
//Function to sanitize values received from the form. Prevents SQL injection
function clean($str) {
$str = #trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return $str;
}
$username = clean($_POST['username']);
$password = clean($_POST['password']);
if ($username != "" && $password != "") {
$getUser = $db->prepare("SELECT id, username, password, salt FROM uc_dev WHERE username = ? LIMIT 1");
$getUser->execute(array($username));
$userDetails = $getUser->fetch();
$dbPW = $userDetails['password'];
$dbSalt = $userDetails['salt'];
$hashedPassword = hash('sha512', $dbSalt . $password);
if ($hashedPassword == $dbPW) {
//Login Successful
session_regenerate_id();
$_SESSION['MD_SESS_ID'] = $userDetails['id'];
header('Location: http://somewhere.com');
session_write_close();
} else {
header('Location: http://www.somewhere.com');
exit();
}
} else {
header('Location: http://somewhere.com');
exit();
}
?>
Auth
<?php
//Start the session
session_start();
//Verify that MEMBER ID session is present
if(!isset($_SESSION['MD_SESS_ID']) || (trim($_SESSION['MD_SESS_ID']) == '')) {
$_SESSION = array();
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
header("Location: http://somewhere.com");
exit();
}
?>
A while ago, I was doing some Blackberry development, and found out that the browser couldn't handle multiple cookies with the same name. Not sure if they've fixed this yet.
So if you're sending out the Set-Cookie header more than once (using setcookie, session_start, or session_regenerate_id), using the same name each time, this could be causing your problem.
You might want to keep track of the cookies you need to output, in an object or array, and only send them to the browser at the very end of the request. This way, if you need to change their values in the middle of the request, you can just overwrite the array's value, rather than sending out another cookie header.
This page may also help -- someone linked to it from PHP's session_regenerate_id page.