Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 5.5 (Session is lost) #583

Closed
splitbrain opened this issue Mar 4, 2014 · 17 comments
Closed

PHP 5.5 (Session is lost) #583

splitbrain opened this issue Mar 4, 2014 · 17 comments

Comments

@splitbrain
Copy link
Collaborator

just got this via email:

Recently switching our servers to PHP 5.5 we noticed that a login to the Dokuwiki instance does not work anymore, the session is lost after the redirect.

We debugged your the code and this is what needs to be changed to make Dokuwiki work on PHP 5.5:

When starting a session always check if the session is already active, otherwise PHP 5.5 will renew the session and that leads to loosing the previously opened session. That's why a login is lost:

Use this code to start a session:

            /*--PHP 5.5--*/
            if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
                if (session_status()==PHP_SESSION_NONE) { session_start(); }
            } else {
                if(session_id()=='') { session_start(); }
            }
@Chris--S
Copy link
Collaborator

Chris--S commented Mar 4, 2014

This is an odd report. I've been using PHP5.5 for my test wiki for a long time without any noticeable session issues. PHP 5.5.7 / CGI/FastCGI sapi.

@Chris--S
Copy link
Collaborator

Chris--S commented Mar 4, 2014

Can we ask for some more information to narrow down the actual cause.

  • Server OS, Webserver & PHP version & Sapi
  • dokuwiki auth module
  • any non-bundled plugins
  • is a non-default php session handler being used
  • the value of session settings, in particular, session.use_strict_mode & session.auto_start

@pisc-software
Copy link

We have 2 Servers where we have the same effect that did lead us to debugging and finding the above solution that works for us:

ServerOS: CentOS 5, CentOS 6 with Apache 2.2
PHP: Zend Server 6.3 with PHP 5.5.7 with default file based session handler on both server instances. Login Session handling did work with Zend Server 6.0.3 on PHP 5.4, the effect started after upgrading the Zend Server to PHP 5.5 (we where able to confirm that by comparing Dokuwiki on both servers with one still on Zend/PHP 5.4)
Dokuwiki: Authentication Module MySQL (and Plain also)
PHP.ini (values in brackets are different on one server):

[Session]
session.save_handler = files
session.save_path = "/usr/local/zend/tmp/sessions"
session.use_cookies = 1
session.use_only_cookies = 1
session.strict_mode = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.bug_compat_42 = Off
session.bug_compat_warn = Off
session.referer_check =
session.entropy_length = 0
session.entropy_file =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 1 (0)
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"

List of Plugins installed (although our debug did reveal that the plugins where not the cause):

acl
authad
authldap
authmysql
authpgsql
authplain
box
captcha
code
config
dirlisting
discussion
ditaa
emphasis
externallink
feed
folded
gallery
googleanalytics
graphviz
highlight
importoldchangelog
importoldindex
include
indexmenu
info
inserted
keyboard
nbsp
note
outdent
outliner
pagelist
pagemove
plugin
popularity
recent
revert
safefnrecode
source
styler
testing
tmp
translation
userhistory
usermanager
vshare
wrap
xterm

@Chris--S
Copy link
Collaborator

Chris--S commented Mar 7, 2014

Thanks for that information.

I've found a problem, but possibly not the one you're seeing. Running zend server 6.0.3 and its bundled apache 2.2, mod_php & php 5.5.7, I get a login problem when a msg() is being output. However, the code above (replacing line 151 in inc/init.php) didn't fix the issue.

The same problem doesn't show up for me running under my own php 5.5.7 (mac ports install), apache 2.2 using cgi/fast cgi.

If there is no msg() being generated during the login processing, then the zend setup logs you in ok.

[ initially the message was part of my debugging process to view the session_status() value. however, the testing plugin's "The testing plugin is enabled and should be disabled." message also does the job. ]

I've also done some tracking of session_status.

  • before session_start() is called, it has a value of PHP_SESSION_NONE
  • after session_start() is called, its value becomes PHP_SESSION_ACTIVE
  • calling session_start() again has no affect. The value stays as PHP_SESSION_ACTIVE and the current session remains (and the dokuwiki user stays logged in).

@Chris--S
Copy link
Collaborator

Chris--S commented Mar 7, 2014

Ok. Some wierdness. Its the session_start() call in send_redirect() which is causing the issue with the msg(). My earlier second session_start(), for some reason, didn't cause an issue - possibly (guess) because the session data hadn't changed.

@Chris--S
Copy link
Collaborator

Chris--S commented Mar 7, 2014

It seems to be...

Working login. Post response sends a DOKU_COOKIE. Session cookie is not altered.
Problem login. Post response re-sends unchanged session cookie. DOKU_COOKIE is not sent.

The session seems to be correctly saved with DOKU_COOKIE data. But without the cookie, DokuWiki won't trust it and so the user is considered not logged in.

@Chris--S
Copy link
Collaborator

This seems to be an issue with the PHP included with Zend server. The following short script is sufficient to highlight the problem. In "standard" PHP, the TEST cookie is present in both $h1 and $h2. In ZendServer 6.0.3 / PHP5.5.7, the TEST cookie is not present in $h2.

<?php
session_start();
session_write_close();

setcookie('TEST', '1', time()+3600);
$h1 = headers_list();

session_start();
$h2 = headers_list();
?>
<pre>
<?php 
print_r($h1);
print_r($h2);
?>
</pre>

@Chris--S
Copy link
Collaborator

I've raised the issue with Zend, case #00047966 (ref:_00D20FyX._50070ac40y:ref). I don't know how to link to the case or if its publicly available.

@pisc-software
Copy link

Thanks for the efforts, we are now using DokuWiki with the changes we posted, and runs nicely. Maybe its not even necessary to wait for Zend identify something, if by changing the code a solution is at hand.

If you need anything else from us, let me know.

@Chris--S
Copy link
Collaborator

Unfortunately the change you posted doesn't fix the issue I discovered.

With no access to the PHP source code used by ZendServer, I can only check the PHP source released at php.net, which shows session_start() including a session status check, which, if the session is active, results in session_start() doing nothing except triggering an E_NOTICE. https://github.com/php/php-src/blob/PHP-5.5.7/ext/session/session.c#L1430

@ghost
Copy link

ghost commented Apr 11, 2014

+1 I also have that problem since I using Ubuntu 14.04.

Any "how to" to solve this problem?

@Chris--S
Copy link
Collaborator

Apart from don't use Zend's PHP, none at this stage. I've not had any further response from Zend on case #00047966. I chased them on that today, response could be slow, due to no SLA, so no support priority. If you have an SLA with Zend, pls raise the issue and mention the above case#.

@ghost ghost mentioned this issue Apr 11, 2014
@pisc-software
Copy link

After some hours of debugging this we found out:
There is a cookie being set at login which stores the authentication credentials. And that cookie is not saved on the browser side in our environment of Zend Server 6 with PHP 5.5.

To overcome this we changed the "setcookie" directives to full specification including host-name in "inc/auth.php" and ensure that the current session is active before setting the cookie:

/* File: inc/auth.php */
function auth_logoff($keepbc = false) {
    global $conf;
    global $USERINFO;
    /* @var DokuWiki_Auth_Plugin $auth */
    global $auth;
    /* @var Input $INPUT */
    global $INPUT;

    // make sure the session is writable (it usually is)
    //@session_start();

    /*--PHP 5.5--*/
    if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
        if (session_status()==PHP_SESSION_NONE) { session_start(); }
    } else {
        if(session_id()=='') { session_start(); }
    }       

    if(isset($_SESSION[DOKU_COOKIE]['auth']['user']))
        unset($_SESSION[DOKU_COOKIE]['auth']['user']);
    if(isset($_SESSION[DOKU_COOKIE]['auth']['pass']))
        unset($_SESSION[DOKU_COOKIE]['auth']['pass']);
    if(isset($_SESSION[DOKU_COOKIE]['auth']['info']))
        unset($_SESSION[DOKU_COOKIE]['auth']['info']);
    if(!$keepbc && isset($_SESSION[DOKU_COOKIE]['bc']))
        unset($_SESSION[DOKU_COOKIE]['bc']);
    $INPUT->server->remove('REMOTE_USER');
    $USERINFO = null; //FIXME

    $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
    /*-- PHP 5.5 --*/
    setcookie(DOKU_COOKIE, '', time() - 600000, $cookieDir, $_SERVER['SERVER_NAME'], ($conf['securecookie'] && is_ssl()), true);

    if($auth) $auth->logOff();
}

function auth_setCookie($user, $pass, $sticky) {
    global $conf;
    /* @var DokuWiki_Auth_Plugin $auth */
    global $auth;
    global $USERINFO;

    if(!$auth) return false;
    $USERINFO = $auth->getUserData($user);

    if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
        if (session_status()==PHP_SESSION_NONE) { session_start(); }
    } else {
        if(session_id()=='') { session_start(); }
    }

    // set cookie
    $cookie    = base64_encode($user).'|'.((int) $sticky).'|'.base64_encode($pass);
    $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
    $time      = $sticky ? (time() + 60 * 60 * 24 * 365) : 0; //one year

    /*-- PHP 5.5 --*/
    setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, $_SERVER['SERVER_NAME'], ($conf['securecookie'] && is_ssl()), true);

    // set session
    $_SESSION[DOKU_COOKIE]['auth']['user'] = $user;
    $_SESSION[DOKU_COOKIE]['auth']['pass'] = sha1($pass);
    $_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid();
    $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
    $_SESSION[DOKU_COOKIE]['auth']['time'] = time();

    return true;
}

/* For our installation we also make a fall-back to use the user credentials that are stored in the session (as they actually are saved there also) */

function auth_getCookie() {
    if(!isset($_COOKIE[DOKU_COOKIE])) {
        if (isset($_SESSION[DOKU_COOKIE])) {
            return array($_SESSION[DOKU_COOKIE]['auth']['user'], false, $_SESSION[DOKU_COOKIE]['auth']['pass']);
        }
        return array(null, null, null);
    }
    list($user, $sticky, $pass) = explode('|', $_COOKIE[DOKU_COOKIE], 3);
    $sticky = (bool) $sticky;
    $pass   = base64_decode($pass);
    $user   = base64_decode($user);
    return array($user, $sticky, $pass);
}

We also changed the unhandy long Cookie Name to something shorter, as maybe that might also influence the browser not saving a cookie with very long names:

/* File: inc/init.php */

// define cookie and session id, append server port when securecookie is configured FS#1664
//if (!defined('DOKU_COOKIE')) define('DOKU_COOKIE', 'DW'.md5(DOKU_REL.(($conf['securecookie'])?$_SERVER['SERVER_PORT']:'')));
if (!defined('DOKU_COOKIE')) define('DOKU_COOKIE', 'DokuWikiSession');

With these changes the DokuWiki release 2014-05-05a "Ponder Stibbons" works in our Zend-Server environment. Without having to fix PHP, we simply applied good coding practice we fixed the code that did not reliably work on our PHP Enterprise environment.

@splitbrain
Copy link
Collaborator Author

just some thoughts

the rather longish session subkey was introduced a long way back to mitigate some problems in a old php version. it's probably no longer needed.

session handling could be improved by introducing a new helper class similar to $INPUT or maybe it could be integrated with it.

@multiscan
Copy link

I encountered a (probably unrelated) issue with the same effect: login lost after redirect.

In my case it was on a freshly installed dokuwiki, default template and no added plugins (something I have used in tens of cases before).

Being a small wiki for internal use and only accessible from the local LAN, I did not bother setting up ssl/https on the web server. This turned out to be the problem. The session cookie was never sent back to the server because the securecookie option is set to 1 by default.

Of course, had I checked the dokuwiki.php configuration file for defaults, I would have immediately figured out what was the problem but for some reason I was thinking that the problem was on my server's php-related configuration.

May be it would be a good idea to explicitly set the option in the initial local.php configuration file or add an https-enabled web server among the requirements

@splitbrain
Copy link
Collaborator Author

@multiscan as you say, your problem is unrelated. Also not true. The secure cookie option is only used when a site is served via SSL. DokuWiki runs fine on http with the option enabled. If you feel you encountered a bug please open a new ticket.

@phy25
Copy link
Collaborator

phy25 commented Feb 27, 2020

Closing since we no longer support PHP 5.5 and I don't see any newly posted issues about this.

@phy25 phy25 closed this as completed Feb 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants