View source
<?php
define('CAS_LOGIN_COOKIE', 'cas_server_login');
function cas_server_menu() {
$items = array();
$items['cas/login'] = array(
'page callback' => 'cas_server_login',
'title' => 'CAS Login',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['cas/validate'] = array(
'page callback' => 'cas_server_validate',
'title' => 'CAS Validate',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['cas/serviceValidate'] = array(
'page callback' => 'cas_server_service_validate',
'title' => 'CAS Service Validate',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['cas/proxyValidate'] = array(
'page callback' => 'cas_server_service_validate',
'title' => 'CAS Proxy Ticket Validate',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['cas/logout'] = array(
'page callback' => 'cas_server_logout',
'title' => 'CAS Logout',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['admin/config/people/cas_server'] = array(
'title' => 'CAS Server',
'description' => 'Configure central authentication services server',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'cas_server_admin_settings',
),
'access arguments' => array(
'administer cas server',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'cas_server.admin.inc',
);
$items['admin/config/people/cas_server/settings'] = array(
'title' => 'Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
return $items;
}
function cas_server_permission() {
return array(
'administer cas server' => array(
'title' => t('Administer CAS Server'),
'description' => t('Configure CAS server settings.'),
'restrict access' => TRUE,
),
);
}
function cas_server_theme() {
return array(
'cas_service_validate_success' => array(
'variables' => array(
'name' => NULL,
'attributes' => NULL,
),
'file' => 'cas_server.response.inc',
),
'cas_service_validate_attributes' => array(
'variables' => array(
'attributes' => NULL,
'style' => 'jasig',
),
'file' => 'cas_server.response.inc',
),
'cas_service_validate_failure' => array(
'variables' => array(
'ticket' => NULL,
'error_code' => NULL,
),
'file' => 'cas_server.response.inc',
),
'cas_service_logout_request' => array(
'variables' => array(
'ticket' => NULL,
'date' => NULL,
'id' => NULL,
),
'file' => 'cas_server.response.inc',
),
'cas_service_validate_whitelist_failure' => array(
'variables' => array(
'service' => NULL,
'error_code' => NULL,
),
'file' => 'cas_server.response.inc',
),
);
}
function cas_server_cas_server_user_attributes($account, $service) {
return array(
'uid' => $account->uid,
'mail' => $account->mail,
'created' => $account->created,
'timezone' => $account->timezone,
'language' => $account->language,
'drupal_roles' => $account->roles,
);
}
function cas_server_service_return() {
global $user;
$service = isset($_COOKIE[CAS_LOGIN_COOKIE]) ? $_COOKIE[CAS_LOGIN_COOKIE] : '';
if ($service && $user->uid) {
$ticket = _cas_server_save_ticket($user->uid, $service);
setcookie(CAS_LOGIN_COOKIE, "", -3600);
drupal_goto($service, array(
'query' => array(
'ticket' => $ticket,
),
));
}
}
function cas_server_login() {
global $user;
$output = '';
$whitelist_error_msg = variable_get('cas_server_whitelist_failure', t('You do not have permission to login to CAS from this service.'));
$service = isset($_REQUEST['service']) ? $_REQUEST['service'] : '';
$gateway = isset($_REQUEST['gateway']);
if ($user->uid) {
if ($service) {
if (!_cas_server_check_service_whitelist($service)) {
return $whitelist_error_msg;
}
else {
$_COOKIE[CAS_LOGIN_COOKIE] = $service;
}
}
$output = t('You have successfully logged into CAS');
cas_server_service_return();
}
else {
if ($gateway && $service) {
drupal_goto($service);
}
else {
if ($service) {
if (!_cas_server_check_service_whitelist($service)) {
return $whitelist_error_msg;
}
else {
setcookie(CAS_LOGIN_COOKIE, $service);
}
}
$output .= l(t('Login'), 'user', array(
'query' => array(
'destination' => 'cas/login',
),
));
drupal_goto('user/login', array(
'query' => array(
'destination' => 'cas/login',
),
));
}
}
return $output;
}
function cas_server_validate() {
drupal_page_is_cacheable(FALSE);
drupal_add_http_header('Content-Type', 'text/plain; charset=utf-8');
$ticket = isset($_REQUEST['ticket']) ? $_REQUEST['ticket'] : '';
$service = isset($_REQUEST['service']) ? $_REQUEST['service'] : '';
if (!_cas_server_check_service_whitelist($service)) {
print "no\n";
print "\n";
return;
}
$user_name = _cas_server_validate($service, $ticket);
if ($user_name) {
print "yes\n";
print "{$user_name}\n";
}
else {
print "no\n";
print "\n";
}
}
function cas_server_service_validate() {
drupal_page_is_cacheable(FALSE);
drupal_add_http_header('Content-Type', 'text/xml; charset=utf-8');
$ticket = isset($_REQUEST['ticket']) ? $_REQUEST['ticket'] : '';
$service = isset($_REQUEST['service']) ? $_REQUEST['service'] : '';
if (!_cas_server_check_service_whitelist($service)) {
$cas_error = 'INVALID_REQUEST';
print theme('cas_server_validate_whitelist_failure', array(
'service' => $service,
'error_code' => $cas_error,
));
watchdog('cas', 'Service %service validation failed!', array(
'%service' => $service,
));
return;
}
$user_name = _cas_server_validate($service, $ticket);
if (!$user_name) {
$cas_error = 'INVALID_TICKET';
}
if (!$ticket || !$service) {
$cas_error = 'INVALID_REQUEST';
}
if ($user_name) {
$account = user_load_by_name($user_name);
$attributes = module_invoke_all('cas_server_user_attributes', $account, $service, $ticket);
$context = array(
'service' => $service,
'ticket' => $ticket,
);
drupal_alter('cas_server_user_attributes', $attributes, $account, $context);
print theme('cas_service_validate_success', array(
'name' => $user_name,
'attributes' => $attributes,
));
watchdog('cas', 'User %name CAS successfully authenticated.', array(
'%name' => $user_name,
));
}
else {
print theme('cas_service_validate_failure', array(
'ticket' => $ticket,
'error_code' => $cas_error,
));
watchdog('cas', 'Ticket %ticket for service %service not recognized.', array(
'%ticket' => $ticket,
'%service' => $service,
));
}
}
function _cas_server_check_service_whitelist($service) {
$mapping_raw = variable_get('cas_server_service_whitelist', '');
if (trim($mapping_raw) != '') {
if (!drupal_match_path($service, $mapping_raw)) {
return FALSE;
}
}
return TRUE;
}
function _cas_server_validate($service, $ticket) {
$user_name = '';
$ticket_info = array(
':service' => $service,
':ticket' => $ticket,
);
$result = db_query_range("SELECT u.name FROM {cas_server_tickets} t JOIN {users} u ON t.uid=u.uid WHERE t.service = :service and t.ticket = :ticket AND valid=1", 0, 1, $ticket_info);
if ($result !== FALSE) {
foreach ($result as $ticket_data) {
$user_name = $ticket_data->name;
}
}
db_update('cas_server_tickets')
->fields(array(
'valid' => 0,
))
->condition('ticket', $ticket)
->execute();
return $user_name;
}
function _cas_server_save_ticket($uid, $service) {
$time = REQUEST_TIME;
$ticket = 'ST-' . user_password();
$ticket_data = array(
'uid' => $uid,
'service' => $service,
'ticket' => $ticket,
'timestamp' => $time,
'valid' => 1,
);
if ($uid && $service) {
db_insert('cas_server_tickets')
->fields($ticket_data)
->execute();
}
return $ticket;
}
function cas_server_logout() {
if (isset($_GET['service']) && !_cas_server_check_service_whitelist($_GET['service'])) {
return variable_get('cas_server_whitelist_failure', t('You do not have permission to login to CAS from this service.'));
}
global $user;
if (user_is_logged_in()) {
watchdog('user', 'Session closed for %name.', array(
'%name' => format_username($user),
));
module_invoke_all('user_logout', $user);
}
session_destroy();
$output = '<p>' . t('You have been logged out successfully.') . '</p>';
if (isset($_REQUEST['url'])) {
$output .= '<p>' . l(t('Continue'), $_REQUEST['url']) . '</p>';
}
return $output;
}
function cas_server_logout_clients($account) {
$result = db_query("SELECT service, ticket, valid FROM {cas_server_tickets} WHERE uid= :uid", array(
':uid' => $account->uid,
));
if ($result !== FALSE) {
$expired_tickets = array();
$timelimit = time() + (int) variable_get('cas_server_slo_group_timeout', 15);
foreach ($result as $client) {
if (time() > $timelimit) {
break;
}
$expired_tickets[] = $client->ticket;
if (!$client->valid) {
$id = 'LR-' . user_password();
$date = date('c');
$logout_request = theme('cas_service_logout_request', array(
'id' => $id,
'date' => $date,
'ticket' => $client->ticket,
));
$response = drupal_http_request($client->service, array(
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded',
),
'method' => 'POST',
'data' => 'logoutRequest=' . urlencode($logout_request),
'timeout' => (int) variable_get('cas_server_slo_individual_timeout', 5),
));
if (@$response->error) {
watchdog('error', 'Error in CAS logout Request - %code : %message', array(
'%code' => $response->code,
'%error' => $response->error,
));
}
}
}
if ($expired_tickets) {
db_delete('cas_server_tickets')
->condition('ticket', $expired_tickets, 'IN')
->execute();
}
}
}
function cas_server_user_logout($account) {
cas_server_logout_clients($account);
}