Hi, I spent a couple of hours hacking on getting PHP sessions to work
in the Drupal SimpleSAMLphp module, this should make the module a lot
easier to use as it now does not require using memcache.
As Drupal hijacks PHP session handling, the way I have done it, is by
grabbing the session file SimpleSAMLphp made when doing the
authentication, and doing the decoding without the help of PHP's
session handling code.
The code still needs to check the PHP session defaults and the
SimpleSAMLphp config for the correct paths and and variable names.
Also I don't quite know if it's SimpleSAMLphp phpSession
implementation that is broken as it assumes nobody messes with the
session handling, so maybe a better place for this code is in
SimpleSAMLphp?
Btw. I also removed all the str_replace('http://', 'https://'.. as it
makes testing a cumbersome affair and it's an assumption that does not
always hold in some vhost setups. eg.
http://www.it-kartellet.dk =
https://secure.it-kartellet.dk. At least it should be optional?
But anyways, have a look at the patch and give some comments.
Regards
Troels.
diff --git a/sites/all/modules/simplesamlphp_auth/
simplesamlphp_auth.module b/sites/all/modules/simplesamlphp_auth/
simplesamlphp_auth.module
index 574f5f7..4da4c89 100644
--- a/sites/all/modules/simplesamlphp_auth/simplesamlphp_auth.module
+++ b/sites/all/modules/simplesamlphp_auth/simplesamlphp_auth.module
@@ -4,6 +4,7 @@
* simpleSAMLphp authentication module for Drupal.
*
* (c) UNINETT, Andreas Åkre Solberg, <
andreas...@uninett.no>.
http://rnd.feide.no
+ * (c) IT-Kartellet, Troels Liebe Bentsen <
tro...@it-kartellet.dk>.
http://www.it-kartellet.dk
*
* This authentication module is based on the shibboleth
authentication module, with changes
* to adopt to use simpleSAMLphp.
@@ -38,11 +39,26 @@ function simplesamlphp_auth_init() {
global $saml_config;
//get the simplesamlphp session
- $basedir = variable_get('simplesamlphp_auth_installdir', '/var/
simplesamlphp');
+ $basedir = variable_get('simplesamlphp_auth_installdir', '/home/tlb/
apps/simplesamlphp');
require_once($basedir . '/www/_include.php');
+
+ // TODO: use SimpleSAML configuration to find out how session is
stored, ie. cookie name etc.
+ // Drupal overrides the session handeling functions so we don't
have access
+ // to sesssion the SimpleSAML login got for us, so we have to fetch
the
+ // session directly from the directory where PHP stores them.
+
+ // Get current PHP session ID
+ $session_id = $_COOKIE['PHPSESSID'];
+ // Slurp session file into $data
+ $data = implode('', file("/var/lib/php5/sess_$session_id"));
+ // Decode that session data, we can't use sesssion_decode as this
closes the header.
+ $session_data = _session_real_decode($data);
+ // Inject session into $_SESSION so SimpleSAML_Session::getInstance
() can find it.
+ $_SESSION['SimpleSAMLphp_SESSION'] = $session_data
['SimpleSAMLphp_SESSION'];
+
/* Load simpleSAMLphp, configuration and metadata */
$saml_config = SimpleSAML_Configuration::getInstance();
- $saml_session = SimpleSAML_Session::getInstance(FALSE);
+ $saml_session = SimpleSAML_Session::getInstance();
if ($user->uid) {
//user is logged in - Drupal
@@ -97,8 +113,6 @@ function simplesamlphp_auth_init() {
}
-
-
/**
* Implementation of hook_user().
*/
@@ -191,7 +205,6 @@ function simplesamlphp_auth_settings() {
}
-
function simplesamlphp_auth_form_user_login_alter(&$form, &
$form_state) {
$form['simplesaml_login_link'] = array(
@@ -248,6 +261,7 @@ function _simplesamlphp_auth_get_authname() {
throw new Exception(t('error in
simplesamlphp_auth.module: no valid unique id attribute set'));
}
}
+
return $authname;
}
@@ -319,7 +333,7 @@ function _simplesamlphp_auth_get_logouturl() {
/* Check if valid local session exists.. */
if (isset($saml_session) && $saml_session->isValid() ) {
- $initSLOurl = str_replace('http://', 'https://',
SimpleSAML_Utilities::selfURLhost()) .
+ $initSLOurl = SimpleSAML_Utilities::selfURLhost().
'/' . $saml_config->getValue('baseurlpath') . 'saml2/sp/
initSLO.php?RelayState=' .
urlencode(variable_get('simplesamlphp_auth_logout_page','/'));
}
@@ -342,10 +356,9 @@ function _simplesamlphp_auth_generate_login_text
() {
require_once((isset($SIMPLESAML_INCPREFIX)?
$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/Session.php');
require_once((isset($SIMPLESAML_INCPREFIX)?
$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/XHTML/Template.php');
- $initSSOurl = str_replace('http://', 'https://',
SimpleSAML_Utilities::selfURLhost()) .
- '/' . $saml_config->getValue('baseurlpath') . 'saml2/sp/initSSO.php?
RelayState=' .
- urlencode(str_replace('http://', 'https://',
SimpleSAML_Utilities::selfURL()));
-
+ $initSSOurl =SimpleSAML_Utilities::selfURLhost(). '/'
+ . $saml_config->getBaseURL(). 'saml2/sp/initSSO.php?RelayState='
+ . urlencode(SimpleSAML_Utilities::selfURL());
/* Check if valid local session exists.. */
if (isset($saml_session) && $saml_session->isValid() ) {
@@ -368,9 +381,9 @@ function _simplesamlphp_auth_generate_block_text()
{
require_once((isset($SIMPLESAML_INCPREFIX)?
$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/Session.php');
require_once((isset($SIMPLESAML_INCPREFIX)?
$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/XHTML/Template.php');
- $initSSOurl = str_replace('http://', 'https://',
SimpleSAML_Utilities::selfURLhost()) .
- '/' . $saml_config->getValue('baseurlpath') . 'saml2/sp/initSSO.php?
RelayState=' .
- urlencode(str_replace('http://', 'https://',
SimpleSAML_Utilities::selfURL()));
+ $initSSOurl =SimpleSAML_Utilities::selfURLhost(). '/'
+ . $saml_config->getBaseURL(). 'saml2/sp/initSSO.php?
RelayState='
+ . urlencode(SimpleSAML_Utilities::selfURL());
/* Check if valid local session exists.. */
if (isset($saml_session) && $saml_session->isValid() ) {
@@ -402,7 +415,6 @@ function _simplesamlphp_auth_evaulaterolerule
($roleruleevaluation, $attributes)
return false;
}
-
function _simplesamlphp_auth_rolepopulation($rolemap) {
global $saml_session;
$roles = array();
@@ -448,7 +460,6 @@ function _simplesamlphp_auth_evaulaterolerule
($roleruleevaluation, $attributes)
}
-
/**
* This helper function is used by developers to debug the form API
workflow in this module.
* Uncomment the function body to activate.
@@ -456,3 +467,91 @@ function _simplesamlphp_auth_evaulaterolerule
($roleruleevaluation, $attributes)
function _simplesaml_auth_debug($message) {
watchdog('simplesamlphp_auth', $message, NULL, WATCHDOG_DEBUG);
}
+
+// Code from
http://dk.php.net/manual/en/function.session-decode.php#56106
+function _session_real_decode($str)
+{
+ define('PS_DELIMITER', '|');
+ define('PS_UNDEF_MARKER', '!');
+ $str = (string)$str;
+
+ $endptr = strlen($str);
+ $p = 0;
+
+ $serialized = '';
+ $items = 0;
+ $level = 0;
+
+ while ($p < $endptr) {
+ $q = $p;
+ while ($str[$q] != PS_DELIMITER)
+ if (++$q >= $endptr) break 2;
+
+ if ($str[$p] == PS_UNDEF_MARKER) {
+ $p++;
+ $has_value = false;
+ } else {
+ $has_value = true;
+ }
+
+ $name = substr($str, $p, $q - $p);
+ $q++;
+
+ $serialized .= 's:' . strlen($name) . ':"' . $name . '";';
+
+ if ($has_value) {
+ for (;;) {
+ $p = $q;
+ switch (strtolower($str[$q])) {
+ case 'n': /* null */
+ case 'b': /* boolean */
+ case 'i': /* integer */
+ case 'd': /* decimal */
+ do $q++;
+ while ( ($q < $endptr) && ($str[$q] !=
';') );
+ $q++;
+ $serialized .= substr($str, $p, $q - $p);
+ if ($level == 0) break 2;
+ break;
+ case 'r': /* reference */
+ $q+= 2;
+ for ($id = ''; ($q < $endptr) && ($str[$q] !=
';'); $q++) $id .= $str[$q];
+ $q++;
+ $serialized .= 'R:' . ($id + 1) . ';'; /*
increment pointer because of outer array */
+ if ($level == 0) break 2;
+ break;
+ case 's': /* string */
+ $q+=2;
+ for ($length=''; ($q < $endptr) && ($str[$q] !
= ':'); $q++) $length .= $str[$q];
+ $q+=2;
+ $q+= (int)$length + 2;
+ $serialized .= substr($str, $p, $q - $p);
+ if ($level == 0) break 2;
+ break;
+ case 'a': /* array */
+ case 'O': /* object */
+ do $q++;
+ while ( ($q < $endptr) && ($str[$q] !=
'{') );
+ $q++;
+ $level++;
+ $serialized .= substr($str, $p, $q - $p);
+ break;
+ case '}': /* end of array|object */
+ $q++;
+ $serialized .= substr($str, $p, $q - $p);
+ if (--$level == 0) break 2;
+ break;
+ default:
+ return false;
+ }
+ }
+ } else {
+ $serialized .= 'N;';
+ $q+= 2;
+ }
+ $items++;
+ $p = $q;
+ }
+ return @unserialize( 'a:' . $items . ':{' . $serialized . '}' );
+};
+