/[drupal]/contributions/modules/cas/cas.module
ViewVC logotype

Contents of /contributions/modules/cas/cas.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.58 - (show annotations) (download) (as text)
Tue Aug 11 14:52:24 2009 UTC (3 months, 2 weeks ago) by metzlerd
Branch: MAIN
Changes since 1.57: +3 -3 lines
File MIME type: text/x-php
#521564 lengthen url fields
1 <?php
2 // $Id: cas.module,v 1.57 2009/06/05 17:07:19 metzlerd Exp $
3
4 /**
5 * @file Enables users to authenticate via a Central Authentication Service (CAS)
6 * Cas will currently work if the auto registration is turned on and will
7 * create user accounts automatically.
8 */
9
10 require_once ('CAS/CAS.php');
11 define('CAS_NO_VERIFY', 'none');
12 define('CAS_VERIFY', 'verify');
13 define('CAS_CA_VERIFY', 'ca_verify');
14
15 /**
16 * Invokes hook_auth_transform() in every module.
17 *
18 * Other modules may need to transform the results of phpCAS::getUser() into a Drupal username
19 * (i.e. phpCAS::getUser() is not guaranteed to return the same username that the user typed in
20 * or the Drupal username might be username@cas or something and we need to know it before we filter)
21 *
22 * We cannot use hook_insert or any user hooks, because they fire way too late.
23 * We cannot use module_invoke_all(), because the argument needs to be passed by reference.
24 *
25 * @param $cas_user
26 * The cas reply string to transform into a drupal username
27 */
28 function cas_invoke_auth_transform(&$cas_name) {
29 foreach (module_list() as $module) {
30 $function = $module .'_auth_transform';
31 if (function_exists($function)) {
32 $function('cas', $cas_name);
33 }
34 }
35 }
36
37 /**
38 * Invokes hook_auth_filter() in every module.
39 *
40 * We cannot use module_invoke_all() for this,
41 * because we want to break out as soon as one fails.
42 *
43 * @param $cas_user
44 * The transformed $cas_name to filter
45 *
46 * @return
47 * TRUE if no module implementing this hook denied access
48 * FALSE if any module returned FALSE
49 */
50 function cas_invoke_auth_filter($cas_name) {
51 foreach (module_list() as $module) {
52 $function = $module .'_auth_filter';
53 if (function_exists($function)) {
54 if (($return = $function('cas', $cas_name)) === FALSE) {
55 return FALSE;
56 }
57 }
58 }
59 return TRUE;
60 }
61
62 /**
63 * Implementation of hook_init
64 * Traps a page load to see if authentication is required.
65 */
66 function cas_init() {
67 _cas_single_sign_out_check();
68 cas_login_check();
69 }
70
71 /**
72 * Access function used to make sure cas menu doesn't show up when
73 * Not needed.
74 *
75 * @return boolean
76 */
77 function cas_menu_check() {
78 global $user;
79 $access = FALSE;
80 if ($user->uid == 0) $access = TRUE;
81 if (strpos($_GET['q'], 'admin/build/menu') !== FALSE) {
82 $access = TRUE;
83 }
84 return $access;
85 }
86
87 /**
88 * Check to see if we need to display the logout menu.
89 *
90 * @return boolean
91 */
92 function cas_menu_logout_check() {
93 global $user;
94 $access = FALSE;
95 if ($user->uid) $access = TRUE;
96 return $access;
97 }
98
99 /**
100 * Checks to see if the user needs to be logged in
101 *
102 */
103 function cas_login_check() {
104 global $user, $account;
105
106
107 if ($user->uid) {
108 //Don't Login because we already are
109 return;
110 }
111
112 // Determine whether we should check for long
113 $cas_check_first = variable_get('cas_check_first',1);
114
115 if ($_COOKIE['cas_login_checked']) {
116 $cas_check_first = 0;
117 }
118
119 $cas_force_login = _cas_force_login();
120
121 if ($cas_force_login || $cas_check_first) {
122 // Variable set
123 $cas_user_register = variable_get('cas_user_register', 1);
124 $cas_authmap = variable_get('cas_authmap', 0);
125 $server_version = (string)variable_get('cas_version', '2.0');
126 $server_cas_server = (string)variable_get('cas_server', 'sso-cas.univ-rennes1.fr');
127 $server_port = (int)variable_get('cas_port', '443');
128 $server_uri = (string)variable_get('cas_uri', '');
129 $cas_domain = (string)variable_get('cas_domain', '');
130 $cas_cert_verify = (string)variable_get('cas_cert_verify', CAS_NO_VERIFY);
131 $cas_cert = (string)variable_get('cas_cert', '');
132 $all_roles = user_roles();
133 $cas_roles = array();
134 foreach ($all_roles as $key => $value) {
135 if (array_key_exists($key, variable_get('cas_auto_assigned_role', array(DRUPAL_AUTHENTICATED_RID)))) {
136 $cas_roles[$key] = $key;
137 }
138 }
139 if ( ($debugFile = variable_get("cas_debugfile","")) != "" ) {
140 phpCAS::setDebug($debugFile);
141 }
142 // Drupal takes care of its own session
143 $start_session = (boolean)FALSE;
144 cas_save_page();
145 $cas_service_ticket = $_GET['ticket']; // We use this later for CAS 3 logoutRequests
146 if ( variable_get("cas_proxy",0) ) {
147 phpCAS::proxy($server_version, $server_cas_server, $server_port, $server_uri, $start_session);
148 $casPGTStoragePath = variable_get("cas_pgtpath","");
149 if ( $casPGTStoragePath != "" ) {
150 $casPGTFormat = variable_get("cas_pgtformat", "plain");
151 phpCAS::setPGTStorageFile($casPGTFormat, $casPGTStoragePath);
152 }
153 }
154 else {
155 phpCAS::client($server_version, $server_cas_server, $server_port, $server_uri, $start_session);
156 }
157 // force CAS authentication
158 // Determine if CA option is set. This is only avialable in version 0.6 or greater, so we need to test
159 // to make sure its callable.
160 if (is_callable(array(phpCAS, 'setNoCasServerValidation'))) {
161 switch ($cas_cert_verify) {
162 case CAS_NO_VERIFY:
163 phpCAS::setNoCasServerValidation();
164 break;
165
166 case CAS_VERIFY:
167 phpCAS::setCasServerCert($cas_cert);
168 break;
169
170 case CAS_CA_VERIFY:
171 phpCAS::setCasServerCACert($cas_cert);
172 break;
173 }
174 }
175
176 // We're going to try phpCAS auth test
177 if (!$cas_force_login) {
178 $logged_in = phpCAS::checkAuthentication();
179 // Set the login tested cookie
180 setcookie('cas_login_checked','true');
181
182 // We're done cause we're not logged in.
183 if (!$logged_in) return;
184
185 } else {
186 // using function check for backward compatibility of the cas libraries.
187 // Newer versions of the cas client use authenticateIfNeeded,
188 // but older versions use forceAuthentication
189 if (is_callable(array(phpCAS, 'authenticateIfNeeded'))) {
190 phpCAS::authenticateIfNeeded();
191 }
192 else {
193 phpCAS::forceAuthentication();
194 }
195 }
196
197 $cas_name = phpCAS::getUser();
198
199 /*
200 * Invoke hook_auth_transform($op, &$username)
201 *
202 * Allow other modules to change the login name
203 * eg. if phpCAS::getUser() returns a string like it:johndoe:10.10.1.2:200805064255
204 * eg. if your cas users in Drupal need to be johndoe@cas
205 *
206 * Note: this transformation needs to happen before we check for blocked users.
207 */
208 cas_invoke_auth_transform($cas_name);
209
210 /*
211 * Invoke hook_auth_filter($op, &$username)
212 *
213 * Allow other modules to filter out some cas logins
214 * eg. if you want to use cas authentication but only allow SOME people in
215 * eg. if you want to filter out people without LDAP home directories
216 */
217 if (($allow = cas_invoke_auth_filter($cas_name)) === FALSE) {
218 drupal_set_message("The user account $cas_name is not available on this site.", "error");
219 return;
220 }
221
222 // blocked user check
223
224 if ($cas_authmap && user_is_blocked($cas_name)) {
225 // blocked in user administration
226 drupal_set_message("The username $cas_name has been blocked.", "error");
227 return;
228 }
229 // this is because users can change their name.
230 if (!$cas_authmap && _cas_external_user_is_blocked($cas_name)) {
231 // blocked in user administration
232 drupal_set_message("The username $cas_name has been blocked.", "error");
233 return;
234 }
235 if (drupal_is_denied('user', $cas_name)) {
236 // denied by access controls
237 drupal_set_message("The name $cas_name is a reserved username.", "error");
238 return;
239 }
240
241 // try to log into Drupal
242 if ($cas_authmap) {
243 // users are coming from Drupal; no need to use the external_load and the authmap
244 $user = user_load(array("name" => $cas_name));
245 }
246 else {
247 // users are external; use authmap table for associating external users
248 $user = user_external_load($cas_name);
249 if (!$user->uid && variable_get('cas_hijack_user', 0)) {
250 $user = user_load(array("name" => $cas_name));
251 if ($user->uid) user_set_authmaps($user, array('authname_cas' => $cas_name));
252 }
253 }
254
255 // If we don't have a user register them.
256 if (!$user->uid) {
257 if ($cas_user_register == 1) {
258 $user_default = array(
259 "name" => $cas_name,
260 "pass" => user_password(),
261 "init" => db_escape_string($cas_name),
262 "status" => 1,
263 "roles" => $cas_roles,
264 );
265 if (!$cas_authmap) $user_default['authname_cas'] = $cas_name;
266 if ($cas_domain) $user_default['mail'] = $cas_name .'@'. $cas_domain;
267
268 // Become user 1 to be able to save profile information
269 session_save_session(FALSE);
270 $admin = array('uid' => 1);
271 $user = user_load($admin);
272
273 // now save the user and become the new user.
274 $user = user_save("", $user_default);
275 session_save_session(TRUE);
276 watchdog("user", 'new user: %n (CAS)', array('%n' => $user->name), WATCHDOG_NOTICE, l(t("edit user"), "admin/user/edit/$user->uid"));
277 if (($user->uid) && ($user->uid > 0) && $cas_authmap) {
278 module_invoke_all('user', 'login', NULL, $user);
279 unset($_SESSION['cas_goto']);
280 watchdog('user', 'Session opened for %name.', array('%name' => $user->name));
281 drupal_goto("user/". $user->uid ."/edit");
282 }
283
284 // Set a session variable to denote this the initial login
285 $_SESSION['cas_first_login'] = TRUE;
286 }
287 }
288
289 // final check to make sure we have a good user
290 if ($user->uid && $user->uid > 0) {
291 /*
292 ** LDAPAuth interfacing - BEGIN
293 */
294
295 if (variable_get('cas_useldap_groups', '')) {
296 if ($ldap_config_name = _get_ldap_config_name($user->name)) {
297 _ldapauth_init($ldap_config_name);
298 include_once('modules/ldap_integration/ldapgroups.module');
299 $user->ldap_authentified = TRUE;
300 ldapgroups_user_login($user);
301 }
302 }
303
304 /*
305 ** LDAPAuth interfacing - END
306 */
307
308 /*
309 ** CAS Sigle Sign Out - BEGIN
310 */
311
312 if (variable_get('cas_signout', FALSE)) {
313 _cas_single_sign_out_save_token($user, $cas_service_ticket);
314 }
315
316 /*
317 * CAS Single Sign Out - END
318 */
319
320 // update the roles and reset the password
321 $roles = $user->roles;
322 foreach ($cas_roles as $role) {
323 $roles[$role] = $role;
324 }
325 /* Removing password cause it cases problems with phpcas. */
326 $user_up = array(
327 // "pass" => user_password(),
328 "roles" => $roles,
329 );
330 $user = user_save($user, $user_up);
331
332 $edit = array();
333 if (module_exists('persistent_login') && $_SESSION['cas_remember']) {
334 $edit['persistent_login'] = 1;
335 }
336 module_invoke_all('user', 'login', $edit, $user);
337 drupal_set_message(t(variable_get('cas_login_message', 'Logged in via CAS as %cas_username.'), array('%cas_username' => $user->name)));
338 if ($edit['persistent_login'] == 1) {
339 drupal_set_message(t('You will remain logged in on this computer even after you close your browser.'));
340 }
341 watchdog('user', 'Session opened for %name.', array('%name' => $user->name));
342 // We can't count on the menu because we're changing login states.
343 cas_login_page();
344 }
345 // if we have a good user
346 else {
347 session_destroy();
348 $user = drupal_anonymous_user();
349 }
350 }
351 // End if user is already logged in else
352 }
353
354 /**
355 * Implementation of hook_perm().
356 */
357 function cas_perm() {
358 return array('administer cas');
359 }
360
361 /**
362 * Implementation of hook_help().
363 */
364 function cas_help($section) {
365 switch ($section) {
366 case 'admin/modules#description':
367 return t("Allows users to authenticate via a Central Authentication Service.");
368 }
369 }
370
371 /**
372 * Implements hook_menu.
373 *
374 */
375 function cas_menu() {
376 global $user;
377 $items = array();
378 //cas_login_check();
379 $items['admin/user/cas'] = array(
380 'title' => t('CAS settings'),
381 'description' => 'Configure central authentication services',
382 'page callback' => 'drupal_get_form',
383 'page arguments' => array('cas_admin_settings'),
384 'access arguments' => array('administer cas'),
385 'type' => MENU_NORMAL_ITEM,
386 );
387
388 $items['cas'] = array(
389 'path' => 'cas',
390 'title' => t('CAS Login'),
391 'page callback' => 'cas_login_page',
392 'access callback' => 'cas_menu_check',
393 'type' => MENU_SUGGESTED_ITEM,
394 );
395
396
397 $items['caslogout'] = array(
398 'title' => t('CAS Logout'),
399 'page callback' => 'cas_logout',
400 'access callback' => 'cas_menu_logout_check',
401 'type' => MENU_SUGGESTED_ITEM,
402 );
403
404
405 return $items;
406 }
407
408 /**
409 * Provides settings pages.
410 */
411 function cas_admin_settings() {
412
413 $form['server'] = array(
414 '#type' => 'fieldset',
415 '#title' => t('CAS server settings'),
416 '#collapsible' => TRUE,
417 '#collapsed' => FALSE,
418 );
419
420 $form['server']['cas_version'] = array(
421 '#type' => 'radios',
422 '#title' => t('CAS version'),
423 '#default_value' => variable_get('cas_version', '2.0'),
424 '#options' => array('1.0' => '1.0', '2.0' => '2.0'),
425 );
426
427 $form['server']['cas_server'] = array(
428 '#type' => 'textfield',
429 '#title' => t('CAS server'),
430 '#default_value' => variable_get('cas_server', ''),
431 '#size' => 30,
432 '#maxlength' => 55,
433 '#description' => t('Location of CAS authentication service.'),
434 );
435
436 $form['server']['cas_port'] = array(
437 '#type' => 'textfield',
438 '#title' => t('CAS port'),
439 '#default_value' => variable_get('cas_port', '443'),
440 '#size' => 30,
441 '#maxlength' => 8,
442 '#description' => '443 is the standard ssl port. 8443 is the standard non-root port for Tomcat.',
443 );
444
445 $form['server']['cas_uri'] = array(
446 '#type' => 'textfield',
447 '#title' => t('CAS URI'),
448 '#default_value' => variable_get('cas_uri', ''),
449 '#size' => 30, '#description' => 'If CAS is not at the root of the host, include a URI (e.g., /cas).',
450 );
451
452 $form['server']['cas_check_first'] = array(
453 '#type' => 'checkbox',
454 '#title' => t('Check to see if a user is allready logged in?'),
455 '#default_value' => variable_get('cas_check_first', 0),
456 '#description' => t('This check is performed once the first time a user visits your site, so that the local drupal logout is still useful for site admins. ')
457 );
458
459 $form['server']['cas_verify'] = array(
460 '#type' => 'radios',
461 '#title' => t('CAS PEM certificate verification'),
462 '#default_value' => variable_get('cas_verify', CAS_NO_VERIFY),
463 '#options' => array(CAS_NO_VERIFY => 'Do not verify the certificate', CAS_VERIFY => 'Verify the server using PEM cerificate',
464 CAS_CA_VERIFY => 'Verify the Certificate Authority using PEM certificate'),
465 );
466
467
468 $form['server']['cas_cert'] = array(
469 '#type' => 'textfield',
470 '#title' => t('CAS PEM Certificate (phpCAS 0.6 or greater)'),
471 '#default_value' => variable_get('cas_cert', ''),
472 '#size' => 30, '#description' => 'With client version 0.6 or greater this is the certificate for validating cas or the cas CA as appropriate.',
473 );
474
475 $form['server']['cas_proxy'] = array(
476 '#type' => 'checkbox',
477 '#title' => t('Initialize CAS as proxy'),
478 '#default_value' => variable_get('cas_proxy', 0),
479 '#description' => t('When using a proxy it is required to set the option "Require CAS login for:" to "specific pages" with "node/*" as a specific page or "all pages except specific pages" on the "Redirection settings".')
480 );
481
482 $form['server']['cas_pgtformat'] = array(
483 '#type' => 'radios',
484 '#title' => t('CAS PGT storage file format'),
485 '#default_value' => variable_get('cas_pgtformat', 'plain'),
486 '#options' => array('plain' => 'Plain Text', 'xml' => 'XML'),
487 );
488
489 $form['server']['cas_pgtpath'] = array(
490 '#type' => 'textfield',
491 '#title' => t('CAS PGT storage path'),
492 '#default_value' => variable_get('cas_pgtpath', ''),
493 '#size' => 30,
494 '#description' => "Only needed if 'Use CAS proxy initializer' is configured. Leave empty for default.",
495 );
496
497 $form['server']['cas_signout'] = array(
498 '#type' => 'checkbox',
499 '#title' => t('Enable CAS Single Sign Out (CAS server 3.1 or greater)'),
500 '#default_value' => variable_get('cas_signout', FALSE),
501 '#description' => t('For more details see <a href="http://www.ja-sig.org/wiki/display/CASUM/Single+Sign+Out">http://www.ja-sig.org/wiki/display/CASUM/Single+Sign+Out</a>.'),
502 );
503
504 $form['server']['cas_debugfile'] = array(
505 '#type' => 'textfield',
506 '#title' => t('CAS debugging output filename'),
507 '#default_value' => variable_get('cas_debugfile', ''),
508 '#size' => 30,
509 '#description' => "Leave empty if you don't want debugging output.",
510 );
511
512
513 $form['account'] = array(
514 '#type' => 'fieldset',
515 '#title' => t('User account settings'),
516 '#collapsible' => TRUE,
517 '#collapsed' => TRUE,
518 );
519
520 $form['account']['cas_authmap'] = array(
521 '#type' => 'checkbox',
522 '#title' => t('Is Drupal also the CAS user repository?'),
523 '#default_value' => variable_get('cas_authmap', 0),
524 '#description' => t('In most cases, the answer will be no; an LDAP repository will be the source of CAS users. But in some cases, the Drupal user database could be used as the central user store for single sign-on. If this is the case, select this option.'),
525 );
526
527 $form['account']['cas_hijack_user'] = array(
528 '#type' => 'checkbox',
529 '#title' => t('If Drupal is not the user repository, should cas highjack users with the same name?'),
530 '#default_value' => variable_get('cas_hijack_user', 0),
531 '#description' => t('If you have pre-created regular accounts in cas that you want converted to mapped accounts, check this box. Otherwise CAS will likely throw duplicate key violation errors on new users.'),
532 );
533
534 $form['account']['cas_user_register'] = array(
535 '#type' => 'checkbox',
536 '#title' => t('Should Drupal user accounts be automatically created?'),
537 '#default_value' => variable_get('cas_user_register', 1),
538 '#description' => t('If a CAS user logs in, his Drupal account will automatically be created. If you don\'t check this option, you will have to pre-create accounts for the users you want to allow.'),
539 );
540
541 $form['account']['cas_domain'] = array(
542 '#type' => 'textfield',
543 '#title' => t('Email Domain'),
544 '#default_value' => variable_get('cas_domain', ''),
545 '#size' => 30,
546 '#maxlength' => 55,
547 '#description' => t('Append this domain name to each new user in order generate his email address.'),
548 );
549
550 $form['account']['cas_hide_email'] = array(
551 '#type' => 'checkbox',
552 '#title' => t('Users canot change email address'),
553 '#default_value' => variable_get('cas_hide_email', 0),
554 '#description' => t('Hide email address field on the edit user form.'),
555 );
556
557 $form['account']['cas_hide_password'] = array(
558 '#type' => 'checkbox',
559 '#title' => t('Users canot change password'),
560 '#default_value' => variable_get('cas_hide_password', 0),
561 '#description' => t('Hide password field on the edit user form.'),
562 );
563
564 if (module_exists('persistent_login')) {
565 $form['account']['cas_allow_rememberme'] = array(
566 '#type' => 'checkbox',
567 '#title' => t('Users can stay logged in between sessions'),
568 '#default_value' => variable_get('cas_allow_rememberme', 0),
569 '#description' => t('If Persistent Login is enabled, users can choose to stay logged in between browser sessions'),
570 );
571 }
572
573 $form['account']['cas_auto_assigned_role'] = array(
574 '#type' => 'select',
575 '#title' => t('Auto-assign users to the role(s)'),
576 '#default_value' => variable_get('cas_auto_assigned_role', array(DRUPAL_AUTHENTICATED_RID)),
577 '#options' => user_roles(TRUE),
578 '#multiple' => TRUE,
579 '#description' => t('This value can be used to establish a role automatically for all CAS users. As an example, if you are also using the simple_ldap module, you can use this role to establish a tie between CAS and LDAP-populated data. i.e. Users with the role of \'cas:user\' should have their LDAP data updated automatically.'),
580 );
581
582
583 $form['pages'] = array(
584 '#type' => 'fieldset',
585 '#title' => t('Redirection settings'),
586 '#collapsible' => TRUE,
587 '#collapsed' => TRUE,
588 );
589
590 $form['pages']['cas_access'] = array(
591 '#type' => 'radios',
592 '#title' => t('Require CAS login for'),
593 '#default_value' => variable_get('cas_access', 0),
594 '#options' => array(t('specific pages'), t('all pages except specific pages')),
595 );
596
597 $form['pages']['cas_pages'] = array(
598 '#type' => 'textarea',
599 '#title' => t('Specific pages'),
600 '#default_value' => variable_get('cas_pages', ''),
601 '#cols' => 40,
602 '#rows' => 5,
603 '#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are '<em>blog</em>' for the blog page and '<em>blog/*</em>' for every personal blog. '<em>&lt;front&gt;</em>' is the front page."),
604 );
605
606 // Settings for redirection upon first login
607 $form['pages']['cas_first_login'] = array(
608 '#type' => 'checkbox',
609 '#title' => t('Force redirection on initial login'),
610 '#default_value' => variable_get('cas_first_login', 0),
611 '#description' => t("Activate this option if you want a user to be directed to the following page after their first CAS login."),
612 );
613
614 $form['pages']['cas_first_login_destination'] = array(
615 '#type' => 'textfield',
616 '#title' => t('Initial login landing page'),
617 '#default_value' => variable_get('cas_first_login_destination', ''),
618 '#size' => 30,
619 '#maxlength' => 255,
620 '#description' => t("Drupal path or URL. An example path is '<em>blog</em>' for the blog page. '&lt;front&gt;' is the front page. An example URL is '<em>http://www.example.com</em>'."),
621 );
622
623 // Setting for message displayed to user upon successfull login
624 $form['pages']['cas_login_message'] = array(
625 '#type' => 'textfield',
626 '#title' => t('Successful login message'),
627 '#default_value' => variable_get('cas_login_message', 'Logged in via CAS as %cas_username.'),
628 '#description' => 'The message displayed to a user when he successfully logs in via CAS. You may specify \'%cas_username\', the username of the user.',
629 );
630
631 // Setting for page to return to after a CAS logout
632 $form['pages']['cas_logout_redirect'] = array(
633 '#type' => 'checkbox',
634 '#title' => t('Redirect user on logout'),
635 '#default_value' => variable_get('cas_logout_redirect', 0),
636 '#description' => t("Activate this option if you want a user to be directed to the following page after logging out of CAS. The logout destination must be specified below."),
637 );
638
639 $form['pages']['cas_logout_destination'] = array(
640 '#type' => 'textfield',
641 '#title' => t('Logout destination'),
642 '#default_value' => variable_get('cas_logout_destination', ''),
643 '#size' => 30,
644 '#maxlength' => 255,
645 '#description' => t("URL. An example URL is '<em>http://www.example.com</em>'. You can also use '&lt;front&gt;' for the front page."),
646 );
647
648
649 $form['misc'] = array(
650 '#type' => 'fieldset',
651 '#title' => t('Miscellaneous settings'),
652 '#collapsible' => TRUE,
653 '#collapsed' => TRUE,
654 );
655
656 $form['misc']['cas_changePasswordURL'] = array(
657 '#type' => 'textfield',
658 '#title' => t('Change password URL'),
659 '#default_value' => variable_get('cas_changePasswordURL', ''),
660 '#description' => t('The URL users should use for changing their password. Leave blank to use the standard Drupal page.'),
661 );
662
663 $form['misc']['cas_registerURL'] = array(
664 '#type' => 'textfield',
665 '#title' => t('Registration URL'),
666 '#default_value' => variable_get('cas_registerURL', ''),
667 '#description' => t('The URL users should use for changing registering. Leave blank to use the standard Drupal page.'),
668 );
669
670
671 $form['ldap'] = array(
672 '#type' => 'fieldset',
673 '#title' => t('LDAP settings'),
674 '#collapsible' => TRUE,
675 '#collapsed' => TRUE,
676 );
677
678 $form['ldap']['cas_useldap'] = array(
679 '#type' => 'checkbox',
680 '#title' => t('Should we extract the user email from an LDAP directory?'),
681 '#default_value' => variable_get('cas_useldap', 0),
682 '#description' => t('Activate this option if you want to extract the user email from an LDAP directory. <strong>Ldapauth module must be enabled and configured</strong>.'),
683 );
684
685 $form['ldap']['cas_ldap_email_attribute'] = array(
686 '#type' => 'textfield',
687 '#title' => t('Email attribute'),
688 '#default_value' => variable_get('cas_ldap_email_attribute', 'mail'),
689 '#size' => 30,
690 '#maxlength' => 55,
691 '#description' => t('LDAP entry attribute containing the email address.'),
692 );
693
694 $form['ldap']['cas_useldap_groups'] = array(
695 '#type' => 'checkbox',
696 '#title' => t('Should we extract user groups from an LDAP directory?'),
697 '#default_value' => variable_get('cas_useldap_groups', 0),
698 '#description' => t('Activate this option if you want to extract the user groups from an LDAP directory. <strong>Ldapgroups module must be enabled and configured</strong>.'),
699 );
700
701 return system_settings_form($form);
702 }
703
704 /**
705 * Saves the page that the user was on when login was requested or required
706 */
707 function cas_save_page() {
708 if (!$_SESSION['cas_goto']) {
709 if (arg(0) == 'cas') {
710 //we're were destined to the CAS login page, so set
711 //the page to the referrer.
712 $_SESSION['cas_goto'] = $_SERVER['HTTP_REFERER'];
713 }
714 else {
715 //We're destined for another page, so save the group.
716 $_SESSION['cas_goto'] = $_GET['q'];
717 }
718 }
719 }
720
721 /**
722 * Redirects to appropriate page based on user settings.
723 */
724 function cas_login_page() {
725 global $user;
726 $destination = variable_get('site_frontpage', 'node');
727 // If it is the user's first CAS login and initial login redirection is enabled, go to the set page
728 if ($_SESSION['cas_first_login'] && (variable_get('cas_first_login', 0) == 1)) {
729 $destination = variable_get('cas_first_login_destination', '');
730 unset($_SESSION['cas_first_login']);
731 }
732 elseif ($_REQUEST['destination']) {
733 $destination = $_REQUEST['destination'];
734 }
735 elseif ($_SESSION['cas_goto']) {
736 $destination = $_SESSION['cas_goto'];
737 }
738 unset($_SESSION['cas_goto']);
739 drupal_goto($destination);
740 // this should never happen.
741 $output .= t("Cas page... you should never get here");
742 return $output;
743 }
744
745 /**
746 * Logs a user out of drupal and then out of cas
747 */
748 function cas_logout() {
749 global $user;
750
751 watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
752
753
754 // Destroy the current session:
755 session_destroy();
756 module_invoke_all('user', 'logout', NULL, $user);
757
758 // We have to use $GLOBALS to unset a global variable:
759 $user = user_load(array('uid' => 0));
760
761 $port = variable_get('cas_port', '443');
762 $server = variable_get('cas_server', 'cas');
763 $uri = variable_get('cas_uri', '');
764
765 // Begin constructing logout destination
766 $logout_destination = 'https://'. $server;
767 // Add abnormal port
768 if ($port != '443') {
769 $logout_destination .= ':'. $port;
770 }
771 // Add logout
772 if ($uri) $logout_destination .= '/'. trim($uri, '/');
773 $logout_destination .= '/logout';
774
775 // Add destination override so that a destination can be specified on the logout link
776 // e.g. caslogout?desination=http://foo.bar.com/foobar
777 // do not accept caslogout as a valid destination, since that may cause a redirect loop
778 $destination = preg_replace("/(destination=|caslogout)/", "", drupal_get_destination());
779
780 //Make it an absolute url. This will also convert <front> to the front page.
781 $destination = url($destination, array('absolute' => TRUE));
782
783 // If there was no override and admin has set and enabled a logout destination, look for it
784 if (empty($destination) && variable_get('cas_logout_redirect', 0)) {
785 $destination = variable_get('cas_logout_destination', '');
786 // redirecti is enabled but no url is given - default to baseurl
787 if (empty($destination)) {
788 $destination = $base_url;
789 }
790 }
791
792 // Add the log out destination if we have one
793 // The three variables are a hack because cas server implementations don't seem to be consistent with
794 // its use.
795 if ($destination) {
796 $logout_destination .= '?destination='. $destination .'&service='. $destination .'&url='. $destination;
797 }
798
799 // Go to the constructed logout destination
800 drupal_goto($logout_destination);
801 }
802
803 /**
804 * Provides login blog that only shows up when the user logs in.
805 */
806 function cas_block($op = 'list', $delta = 0, $edit = array()) {
807 global $user;
808 if ($op == 'list') {
809 $blocks[0]['info'] = t('CAS User login');
810
811 return $blocks;
812 }
813 else if ($op == 'view') {
814 $block = array();
815
816 switch ($delta) {
817 case 0:
818 // For usability's sake, avoid showing two login forms on one page.
819 if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
820 $edit = $_POST['edit'];
821
822 $output = "<div class=\"user-login-block\">\n";
823 $output .= drupal_get_form('cas_login_form');
824 $output .= "</div>\n";
825 $block['subject'] = t('User Login');
826 $block['content'] = $output;
827 }
828 return $block;
829 }
830 }
831 }
832
833 function cas_login_form($form_state) {
834 $form['submit'] = array('#type' => 'submit', '#value' => t('Log in via CAS'));
835 if (module_exists('persistent_login') && variable_get('cas_allow_rememberme', 0)) {
836 $form['remember'] = array(
837 '#type' => 'checkbox',
838 '#title' => t('Remember me'),
839 '#default_value' => 0,
840 );
841 }
842 return $form;
843 }
844
845 function cas_login_form_submit($form, &$form_state) {
846 if ($form_state['values']['remember']) {
847 $_SESSION['cas_remember'] = 1;
848 }
849 $form_state['redirect'] = 'cas';
850 }
851
852 /**
853 * Determines whether cas login should be enforced for this page load.
854 * This is done based on the redirection settings for this module.
855 */
856 function _cas_force_login() {
857
858 list($arg0) = split('/', $_GET['q']);
859 // Don't even do the test if we're hitting the cas page
860 if ($arg0 == "cas") {
861 return TRUE;
862 }
863
864 // Don't even do the test if cron.php or xmlrpc.php is invoked. Don't require login.
865 if (base_path() .'cron.php' == $_SERVER['PHP_SELF'] || base_path() .'xmlrpc.php' == $_SERVER['PHP_SELF']) return FALSE;
866
867 // set the default behavior
868 if (variable_get('cas_access', 0) == 1) {
869 $force_login = TRUE;
870 }
871 else {
872 $force_login = FALSE;
873 }
874
875 $pages = variable_get('cas_pages', '');
876 // This common page matching logic used throughout drupal.
877 if ($pages) {
878 $path = drupal_get_path_alias($_GET['q']);
879 $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. variable_get('site_frontpage', 'node') .'\2'), preg_quote($pages, '/')) .')$/';
880 $path_match = preg_match($regexp, $path);
881
882 // Alter the default
883 if ($path_match) {
884 if ($force_login) $force_login = FALSE;
885 else $force_login = TRUE;
886 }
887 }
888
889 return $force_login;
890 }
891
892 /**
893 * implementation of hook_form_alter
894 * Overrides specific from settings based on user policy.
895 */
896 function cas_form_alter(&$form, $form_state, $form_id) {
897 //drupal_set_message($form_id.'<pre>'.print_r($form,1).'</pre>');
898 switch ($form_id) {
899 case 'user_profile_form':
900 //make the email field hidden and force the value to the default.
901 if (variable_get('cas_hide_email', 0)) {
902 if (variable_get('cas_domain', '')) {
903 $form['account']['mail']['#type'] = 'hidden';
904 $form['account']['mail']['#value'] = $form['account']['mail']['#default_value'];
905 if (!$form['account']['mail']['#default_value']) {
906 $form['account']['mail']['#value'] = $form['account']['name']['#default_value'] .'@'. variable_get('cas_domain', '');
907 }
908
909 }
910
911 /*
912 ** LDAPAuth interfacing - BEGIN
913 */
914 if (variable_get('cas_useldap', '')) {
915 global $ldapauth_ldap, $user;
916 if ($ldap_config_name = _get_ldap_config_name($user->name)) {
917 _ldapauth_init($ldap_config_name);
918 _ldapauth_user_lookup($user->name);
919 $cas_ldap_email_attribute = (string)variable_get('cas_ldap_email_attribute', 'mail');
920 $ldap_entries = $ldapauth_ldap->search($ldapauth_ldap->getOption('basedn'), $ldapauth_ldap->getOption('user_attr') .'='. $user->name, array($cas_ldap_email_attribute));
921 if ($ldap_entries['count'] == 1 && isset($ldap_entries[0][$cas_ldap_email_attribute][0])) if (trim($ldap_entries[0][$cas_ldap_email_attribute][0]) != '') {
922 $form['account']['mail']['#type'] = 'hidden';
923 $form['account']['mail']['#value'] = $ldap_entries[0][$cas_ldap_email_attribute][0];
924 }
925 }
926 }
927
928 /*
929 ** LDAPAuth interfacing - END
930 */
931 }
932
933 //Remove the password fields from the form.
934 if (variable_get('cas_hide_password', 0))unset($form['account']['pass']);
935 break;
936
937 case 'user_pass':
938 if (!user_access('administer users') && variable_get('cas_changePasswordURL', '') != '') {
939 drupal_goto(variable_get('cas_changePasswordURL', ''));
940 }
941 break;
942
943 case 'user_register':
944 if (!user_access('administer users') && variable_get('cas_registerURL', '') != '') {
945 drupal_goto(variable_get('cas_registerURL', ''));
946 }
947 break;
948 }
949 }
950 /*
951 ** LDAPAuth interfacing - BEGIN
952 */
953
954 /**
955 * LDAP Auxiliary functions
956 */
957 function _get_ldap_config_name($user_name) {
958 include_once('modules/ldap_integration/ldapauth.module');
959 $user_found = FALSE;
960 $result = db_query("SELECT name FROM {ldapauth} WHERE status = '%d' ORDER BY sid", 1);
961 while ($row = db_fetch_object($result)) {
962 // cycle thru the authentication schemes - first successful one wins
963 // instantiate ldap
964 _ldapauth_init($row->name);
965 $ldap_user_entry = _ldapauth_user_lookup($user_name);
966 if ($ldap_user_entry) {
967 $user_found = TRUE;
968 break;
969 }
970 }
971 if ($user_found) return $row->name;
972 else return FALSE;
973 }
974
975 /*
976 ** LDAPAuth interfacing - END
977 */
978
979 /*
980 * CAS Sigle Sign Out - BEGIN
981 */
982 function _cas_single_sign_out_check() {
983 if (variable_get('cas_signout', FALSE) && array_key_exists("logoutRequest", $_POST)) {
984 $cas_logout_request_xml_string = utf8_encode($_POST["logoutRequest"]); // it's important!
985 if ($cas_logout_request_xml = domxml_open_mem($cas_logout_request_xml_string)) {
986 $cas_session_indexes = $cas_logout_request_xml->get_elements_by_tagname( "SessionIndex" );
987 if ($cas_session_indexes[0] != NULL) {
988 $cas_session_index = $cas_session_indexes[0]->get_content();
989 // Log them out now.
990 // first lets find out who we want to log off
991 $result = db_query_range("SELECT cld.uid FROM {cas_login_data} cld WHERE cld.cas_session_id = '%s'", $cas_session_index, 0, 1);
992 if ($result !== FALSE) {
993 while ($cas_login_data = db_fetch_object($result)) {
994 $uid = $cas_login_data->uid;
995 // remove all entry for user id in cas_login_data
996 db_query("DELETE FROM {cas_login_data} WHERE uid = %d", $uid);
997 // remove their session
998 db_query("DELETE FROM {sessions} WHERE uid = %d", $uid);
999 }
1000 }
1001 }
1002 }
1003 }
1004 }
1005
1006 function _cas_single_sign_out_save_token($user, $cas_sign_out_token) {
1007 // Ok lets save the CAS service ticket to DB so
1008 // we can handle CAS logoutRequests when they come
1009 if ($user->uid && $user->uid > 0 && !empty($cas_sign_out_token)) {
1010 db_query("INSERT INTO {cas_login_data} (cas_session_id, uid) VALUES ('%s', %d)", $cas_sign_out_token, $user->uid);
1011 }
1012 }
1013
1014 /*
1015 ** CAS Sigle Sign Out - END
1016 */
1017
1018 function _cas_external_user_is_blocked($name) {
1019 $deny = db_fetch_object(db_query("SELECT u.name FROM {users} u JOIN {authmap} m ON u.uid=m.uid WHERE status = 0 AND m.authname = LOWER('%s')", $name));
1020 return $deny;
1021 }
1022

  ViewVC Help
Powered by ViewVC 1.1.2