| 1 |
<?php |
<?php |
| 2 |
// $Id: singlesignon.module,v 1.21.2.11 2008/05/03 11:35:50 wayland76 Exp $ |
// $Id: singlesignon.module,v 1.28 2008/05/05 04:15:43 wayland76 Exp $ |
| 3 |
|
|
| 4 |
|
|
| 5 |
/** |
/** |
| 49 |
* |
* |
| 50 |
* @link http://drupal.org/project/singlesignon |
* @link http://drupal.org/project/singlesignon |
| 51 |
* @author Daniel Convissor <danielc@analysisandsolutions.com> |
* @author Daniel Convissor <danielc@analysisandsolutions.com> |
| 52 |
* @version $Revision: 1.21.2.11 $ (HEAD) |
* @version $Revision: 1.28 $ (HEAD) |
| 53 |
*/ |
*/ |
| 54 |
|
|
| 55 |
// {{{ core functions |
// {{{ core functions |
| 56 |
|
|
| 57 |
/** |
/** |
| 58 |
* Implementation of hook_init(). |
* Implementation of hook_boot(). |
| 59 |
* |
* |
| 60 |
* Automatically invoked for each hit to a Drupal website if the |
* Automatically invoked for each hit to a Drupal website if the |
| 61 |
* "singlesignon" module is enabled. |
* "singlesignon" module is enabled. |
| 62 |
*/ |
*/ |
| 63 |
function singlesignon_init() { |
function singlesignon_boot() { |
| 64 |
global $user, $_singlesignon_bot_matches; |
global $user, $_singlesignon_bot_matches; |
| 65 |
|
|
| 66 |
$variable_defaults = array( |
$variable_defaults = array( |
| 99 |
return; |
return; |
| 100 |
} |
} |
| 101 |
|
|
|
// url() only available if bootstrap has reached FULL. |
|
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); |
|
|
|
|
| 102 |
// This is the user's first hit to a slave site. Take note of their |
// This is the user's first hit to a slave site. Take note of their |
| 103 |
// session ID, since that's how we tell if they've been here or not. |
// session ID, since that's how we tell if they've been here or not. |
| 104 |
// Then go to the master site to see if they are logged in over there. |
// Then go to the master site to see if they are logged in over there. |
| 105 |
$_SESSION['singlesignon_prior_sid'] = session_id(); |
$_SESSION['singlesignon_prior_sid'] = session_id(); |
| 106 |
$query = 'slave_session='. session_id() .'&singlesignon_dest='. _singlesignon_get_dest(); |
|
| 107 |
_singlesignon_goto($master_url . url('singlesignon/initial_check', $query)); |
_singlesignon_goto_url('singlesignon/initial_check'); |
| 108 |
} |
} |
| 109 |
} |
} |
| 110 |
|
|
| 156 |
return; |
return; |
| 157 |
} |
} |
| 158 |
else if ($user->uid) { |
else if ($user->uid) { |
|
// url() only available if bootstrap has reached FULL. |
|
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); |
|
|
|
|
| 159 |
// Tell the master site the user just logged in. |
// Tell the master site the user just logged in. |
| 160 |
$query = 'slave_session='. session_id() .'&singlesignon_dest='. _singlesignon_get_dest(); |
_singlesignon_goto_url('singlesignon/login'); |
|
_singlesignon_goto($master_url . url('singlesignon/login', $query)); |
|
| 161 |
} |
} |
| 162 |
} |
} |
| 163 |
} |
} |
| 208 |
// }}} |
// }}} |
| 209 |
// {{{ helper functions |
// {{{ helper functions |
| 210 |
|
|
| 211 |
|
/** |
| 212 |
|
* Sets up the URL and goes to it |
| 213 |
|
*/ |
| 214 |
|
function _singlesignon_goto_url($url) { |
| 215 |
|
// url() only available if bootstrap has reached FULL. |
| 216 |
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); |
| 217 |
|
|
| 218 |
|
$query = 'slave_session='. session_id() .'&singlesignon_dest='. _singlesignon_get_dest(); |
| 219 |
|
_singlesignon_goto($master_url . url($url, array('query' => $query))); |
| 220 |
|
} |
| 221 |
|
|
| 222 |
|
/** |
| 223 |
|
* Gets the SQL to update the sessions a bit -- can equivalent code be found somewhere else? |
| 224 |
|
*/ |
| 225 |
function _singlesignon_get_sql($user) { |
function _singlesignon_get_sql($user) { |
| 226 |
$in = substr(str_repeat("'%s',", count($_SESSION['singlesignon_slave_sessions'])), 0, -1); |
$in = substr(str_repeat("'%s',", count($_SESSION['singlesignon_slave_sessions'])), 0, -1); |
| 227 |
$sql = "UPDATE {sessions} SET uid = %d WHERE sid IN ($in)"; // I know the coder module complains about this, but it appears to be necessary in this case |
$sql = "UPDATE {sessions} SET uid = %d WHERE sid IN ($in)"; // I know the coder module complains about this, but it appears to be necessary in this case |
| 294 |
return ( |
return ( |
| 295 |
preg_match($_singlesignon_bot_matches['useragents_nocase'], $_SERVER['HTTP_USER_AGENT']) |
preg_match($_singlesignon_bot_matches['useragents_nocase'], $_SERVER['HTTP_USER_AGENT']) |
| 296 |
|| preg_match($_singlesignon_bot_matches['useragents_case'], $_SERVER['HTTP_USER_AGENT']) |
|| preg_match($_singlesignon_bot_matches['useragents_case'], $_SERVER['HTTP_USER_AGENT']) |
| 297 |
|| preg_match($_singlesignon_bot_matches['client_IP'], $_SERVER['REMOTE_ADDR']) |
|| preg_match($_singlesignon_bot_matches['client_IP'], ip_address()) |
| 298 |
|| preg_match($_singlesignon_bot_matches['target_url'], request_uri()) |
|| preg_match($_singlesignon_bot_matches['target_url'], request_uri()) |
| 299 |
); |
); |
| 300 |
} |
} |
| 313 |
/** |
/** |
| 314 |
* Implementation of hook_menu(). |
* Implementation of hook_menu(). |
| 315 |
*/ |
*/ |
| 316 |
function singlesignon_menu($maycache) { |
function singlesignon_menu() { |
| 317 |
$items = array( |
$items['admin/settings/singlesignon'] = array( |
| 318 |
array( |
'title' => 'Shared Sign-on', |
| 319 |
'path' => 'admin/settings/singlesignon', |
'description' => 'Shares users and sign-ons between sites (previously called "Single Sign-on"', |
| 320 |
'title' => t('Shared Sign-on'), |
'page callback' => 'drupal_get_form', |
| 321 |
'description' => t('Shares users and sign-ons between sites (previously called "Single Sign-on"'), |
'page arguments' => array('singlesignon_admin_settings'), |
| 322 |
'callback' => 'drupal_get_form', |
'access arguments' => array('access administration pages'), |
| 323 |
'callback arguments' => array('singlesignon_admin_settings'), |
'type' => MENU_NORMAL_ITEM, |
|
'access' => user_access('access administration pages'), |
|
|
'type' => MENU_NORMAL_ITEM, |
|
|
), |
|
| 324 |
); |
); |
| 325 |
|
|
| 326 |
return $items; |
return $items; |
| 349 |
'#type' => 'textfield', |
'#type' => 'textfield', |
| 350 |
'#title' => t('Master URL'), |
'#title' => t('Master URL'), |
| 351 |
'#default_value' => $master_url, |
'#default_value' => $master_url, |
| 352 |
'#description' => t('Enter the URL of your master Shared Sign-On server, in the form of <b>http://www.example.com</b>. Leave the trailing slash off. Do NOT include any path information.'), |
'#description' => t('Enter the URL of your master Shared Sign-On server, in the form of <b>http://www.example.com</b>. Leave the trailing slash off. Do NOT include any path information except to the root of the drupal install.'), |
| 353 |
'#maxlength' => '300', |
'#maxlength' => '300', |
| 354 |
'#size' => '80', |
'#size' => '80', |
| 355 |
'#disabled' => $use_domain, |
'#disabled' => $use_domain, |
| 422 |
/** |
/** |
| 423 |
* Hook for validating a form; verifies the values for singlesignon bot recognition. |
* Hook for validating a form; verifies the values for singlesignon bot recognition. |
| 424 |
*/ |
*/ |
| 425 |
function singlesignon_admin_settings_validate($form_id, $form_values, $form) { |
function singlesignon_admin_settings_validate($form, &$form_state) { |
| 426 |
$s['useragents_case'] = _singlesignon_verify_value($form_values, 'useragents_case'); |
$s['useragents_case'] = _singlesignon_verify_value($form_state['values'], 'useragents_case'); |
| 427 |
$s['useragents_nocase'] = _singlesignon_verify_value($form_values, 'useragents_nocase', '', 'i'); |
$s['useragents_nocase'] = _singlesignon_verify_value($form_state['values'], 'useragents_nocase', '', 'i'); |
| 428 |
$s['client_IP'] = _singlesignon_verify_value($form_values, 'client_IP', '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'); |
$s['client_IP'] = _singlesignon_verify_value($form_state['values'], 'client_IP', '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'); |
| 429 |
$s['target_url'] = _singlesignon_verify_value($form_values, 'target_url', '\\\\\/[A-Za-z0-9_\.\*\/\\\\-]*\$$'); |
$s['target_url'] = _singlesignon_verify_value($form_state['values'], 'target_url', '\\\\\/[A-Za-z0-9_\.\*\/\\\\-]*\$$'); |
| 430 |
|
|
| 431 |
form_set_value($form['singlesignon_bot_matches'], $s); |
$form_state['values']['singlesignon_bot_matches'] = $s; |
| 432 |
} |
} |
| 433 |
|
|
| 434 |
/** |
/** |