00001 <?php
00002
00008
00009 include_once(dirname(__FILE__).'/languages/languages.php');
00010
00011
00012 include_once(dirname(__FILE__).'/
PGTStorage/pgt-main.php');
00013
00022 class CASClient
00023 {
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00052 function
HTMLFilterOutput($str)
00053 {
00054 $str = str_replace('__CAS_VERSION__',$this->getServerVersion(),$str);
00055 $str = str_replace('__PHPCAS_VERSION__',phpCAS::getVersion(),$str);
00056 $str = str_replace('__SERVER_BASE_URL__',$this->getServerBaseURL(),$str);
00057 echo $str;
00058 }
00059
00068 var
$_output_header = '';
00069
00079 function
printHTMLHeader($title)
00080 {
00081 $this->HTMLFilterOutput(str_replace('__TITLE__',
00082 $title,
00083 (empty($this->_output_header)
00084 ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
00085 : $this->output_header)
00086 )
00087 );
00088 }
00089
00098 var
$_output_footer = '';
00099
00107 function
printHTMLFooter()
00108 {
00109 $this->HTMLFilterOutput(empty($this->_output_footer)
00110 ?('<hr><address>
phpCAS __PHPCAS_VERSION__ '.$this->getString(
CAS_STR_USING_SERVER).' <a href=
"__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
00111 :$this->_output_footer);
00112 }
00113
00121 function
setHTMLHeader($header)
00122 {
00123 $this->_output_header = $header;
00124 }
00125
00133 function
setHTMLFooter($footer)
00134 {
00135 $this->_output_footer = $footer;
00136 }
00137
00139
00140
00141
00156 var
$_lang = '';
00157
00165 function
getLang()
00166 {
00167
if ( empty($this->_lang) )
00168 $this->
setLang(
PHPCAS_LANG_DEFAULT);
00169
return $this->_lang;
00170 }
00171
00181 var
$_strings;
00182
00192 function
getString($str)
00193 {
00194
00195 $this->
getLang();
00196
00197
if ( !isset($this->_strings[$str]) ) {
00198 trigger_error('string `'.$str.
'\' not defined
for language `'.$this->getLang().
'\'',E_USER_ERROR);
00199 }
00200
return $this->
_strings[$str];
00201 }
00202
00212 function
setLang($lang)
00213 {
00214
00215 include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
00216
00217
if ( !is_array($this->_strings) ) {
00218 trigger_error('language `'.$lang.
'\' is not implemented',E_USER_ERROR);
00219 }
00220 $this->_lang = $lang;
00221 }
00222
00224
00225
00226
00256 var
$_server = array(
00257 'version' => -1,
00258 'hostname' => 'none',
00259 'port' => -1,
00260 'uri' => 'none'
00261 );
00262
00268 function
getServerVersion()
00269 {
00270
return $this->_server['version'];
00271 }
00272
00278 function
getServerHostname()
00279 {
return $this->_server['hostname']; }
00280
00286 function
getServerPort()
00287 {
return $this->_server['port']; }
00288
00294 function
getServerURI()
00295 {
return $this->_server['uri']; }
00296
00302 function
getServerBaseURL()
00303 {
00304
00305
if ( empty($this->_server['base_url']) ) {
00306 $this->_server['base_url'] = 'https:
00307 .$this->getServerHostname()
00308 .
':'
00309 .$this->getServerPort()
00310 .$this->getServerURI();
00311 }
00312
return $this->_server['base_url'];
00313 }
00314
00321 function
getServerLoginURL($gateway=
false)
00322 {
00323
phpCAS::traceBegin();
00324
00325
if ( empty($this->_server['login_url']) ) {
00326 $this->_server['login_url'] = $this->
getServerBaseURL();
00327 $this->_server['login_url'] .= 'login?service=';
00328 $this->_server['login_url'] .= preg_replace('/&/
','%26',$this->getURL());
00329
if ($gateway) {
00330 $this->_server['login_url'] .= '&gateway=
true';
00331 }
00332 }
00333 phpCAS::traceEnd($this->_server['login_url']);
00334
return $this->_server['login_url'];
00335 }
00336
00343 function
setServerLoginURL($url)
00344 {
00345
return $this->_server['login_url'] = $url;
00346 }
00347
00353 function
getServerServiceValidateURL()
00354 {
00355
00356
if ( empty($this->_server['service_validate_url']) ) {
00357
switch ($this->
getServerVersion()) {
00358
case CAS_VERSION_1_0:
00359 $this->_server['service_validate_url'] = $this->
getServerBaseURL().'validate';
00360
break;
00361
case CAS_VERSION_2_0:
00362 $this->_server['service_validate_url'] = $this->
getServerBaseURL().'serviceValidate';
00363
break;
00364 }
00365 }
00366
return $this->_server['service_validate_url'].'?service='.preg_replace('/&/
','%26',$this->getURL());
00367 }
00368
00374 function
getServerProxyValidateURL()
00375 {
00376
00377
if ( empty($this->_server['proxy_validate_url']) ) {
00378
switch ($this->
getServerVersion()) {
00379
case CAS_VERSION_1_0:
00380 $this->_server['proxy_validate_url'] = '';
00381
break;
00382
case CAS_VERSION_2_0:
00383 $this->_server['proxy_validate_url'] = $this->
getServerBaseURL().'proxyValidate';
00384
break;
00385 }
00386 }
00387
return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/
','%26',$this->getURL());
00388 }
00389
00395 function
getServerProxyURL()
00396 {
00397
00398
if ( empty($this->_server['proxy_url']) ) {
00399
switch ($this->
getServerVersion()) {
00400
case CAS_VERSION_1_0:
00401 $this->_server['proxy_url'] = '';
00402
break;
00403
case CAS_VERSION_2_0:
00404 $this->_server['proxy_url'] = $this->
getServerBaseURL().'proxy';
00405
break;
00406 }
00407 }
00408
return $this->_server['proxy_url'];
00409 }
00410
00416 function
getServerLogoutURL()
00417 {
00418
00419
if ( empty($this->_server['logout_url']) ) {
00420 $this->_server['logout_url'] = $this->
getServerBaseURL().'
logout';
00421 }
00422
return $this->_server['logout_url'];
00423 }
00424
00431 function
setServerLogoutURL($url)
00432 {
00433
return $this->_server['logout_url'] = $url;
00434 }
00435
00441 function
isHttps()
00442 {
00443
if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ) {
00444
return true;
00445 }
else {
00446
return false;
00447 }
00448 }
00449
00450
00451
00452
00467 function
CASClient($server_version,
00468 $proxy,
00469 $server_hostname,
00470 $server_port,
00471 $server_uri,
00472 $start_session =
true)
00473 {
00474
phpCAS::traceBegin();
00475
00476
00477
if ($start_session) {
00478 if (!isset($_SESSION)) session_start();
00479 }
00480
00481 $this->_proxy = $proxy;
00482
00483
00484
switch ($server_version) {
00485
case CAS_VERSION_1_0:
00486
if ( $this->
isProxy() )
00487 phpCAS::error('CAS proxies are not supported in CAS '
00488 .$server_version);
00489
break;
00490
case CAS_VERSION_2_0:
00491
break;
00492
default:
00493 phpCAS::error('
this version of CAS (`'
00494 .$server_version
00495 .
'\') is not supported by
phpCAS '
00496 .phpCAS::getVersion());
00497 }
00498 $this->_server['version'] = $server_version;
00499
00500
00501
if ( empty($server_hostname)
00502 || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
00503 phpCAS::error('bad CAS server hostname (`'.$server_hostname.
'\')');
00504 }
00505 $this->_server['hostname'] = $server_hostname;
00506
00507
00508
if ( $server_port == 0
00509 || !is_int($server_port) ) {
00510 phpCAS::error('bad CAS server port (`'.$server_hostname.
'\')');
00511 }
00512 $this->_server['port'] = $server_port;
00513
00514
00515
if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
00516 phpCAS::error('bad CAS server URI (`'.$server_uri.
'\')');
00517 }
00518
00519 $server_uri = preg_replace('/\/\
00520 $this->_server['uri'] = $server_uri;
00521
00522
00523 if ( $this->isProxy() ) {
00524 $this->
setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
00525 }
00526
00527
if ( $this->
isCallbackMode() ) {
00528
00529
if ( !$this->
isHttps() ) {
00530 phpCAS::error('CAS proxies must be secured to use
phpCAS; PGT\'s will not be received from the CAS server');
00531 }
00532 }
else {
00533
00534 $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
00535
00536
if( preg_match('/^ST-/',$ticket)) {
00537 phpCAS::trace('ST \''.$ticket.
'\' found');
00538
00539 $this->
setST($ticket);
00540 }
00541
00542
else if( ($this->
getServerVersion()!=
CAS_VERSION_1_0) && preg_match('/^PT-/',$ticket) ) {
00543 phpCAS::trace('PT \''.$ticket.
'\' found');
00544 $this->
setPT($ticket);
00545 }
00546
00547
else if ( !empty($ticket) ) {
00548 phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket,ENT_QUOTES,'ISO-8859-1').
'\')');
00549 }
00550
00551 unset($_GET['ticket']);
00552 }
00553 phpCAS::traceEnd();
00554 }
00555
00558
00559
00560
00561
00562
00563
00576 var
$_user = '';
00577
00585 function
setUser($user)
00586 {
00587 $this->_user = $user;
00588 }
00589
00597 function
getUser()
00598 {
00599
if ( empty($this->_user) ) {
00600 phpCAS::error('
this method should be used only after '.__CLASS__.'::
forceAuthentication() or '.__CLASS__.'::
isAuthenticated()');
00601 }
00602
return $this->_user;
00603 }
00604
00611 function
forceAuthentication()
00612 {
00613
phpCAS::traceBegin();
00614
00615
if ( $this->
isAuthenticated() ) {
00616
00617 phpCAS::trace('no need to authenticate');
00618 $res = TRUE;
00619 }
else {
00620
00621 unset($_SESSION['
phpCAS']['auth_checked']);
00622 $this->
redirectToCas(FALSE);
00623
00624 $res = FALSE;
00625 }
00626 phpCAS::traceEnd($res);
00627
return $res;
00628 }
00629
00635 function
checkAuthentication()
00636 {
00637
phpCAS::traceBegin();
00638
00639
if ( $this->
isAuthenticated() ) {
00640 phpCAS::trace('user is authenticated');
00641 $res = TRUE;
00642 }
else if (isset($_SESSION['
phpCAS']['auth_checked'])) {
00643
00644 unset($_SESSION['
phpCAS']['auth_checked']);
00645 $res = FALSE;
00646 }
else {
00647 $_SESSION['
phpCAS']['auth_checked'] =
true;
00648 $this->
redirectToCas(TRUE);
00649
00650 $res = FALSE;
00651 }
00652 phpCAS::traceEnd($res);
00653
return $res;
00654 }
00655
00664 function
isAuthenticated()
00665 {
00666
phpCAS::traceBegin();
00667 $res = FALSE;
00668 $validate_url = '';
00669
00670
if ( $this->
wasPreviouslyAuthenticated() ) {
00671
00672
00673 phpCAS::trace('user was already authenticated, no need to look
for tickets');
00674 $res = TRUE;
00675 } elseif ( $this->hasST() ) {
00676
00677 phpCAS::trace('ST `'.$this->getST().
'\' is present');
00678 $this->
validateST($validate_url,$text_response,$tree_response);
00679 phpCAS::trace('ST `'.$this->getST().
'\' was validated');
00680
if ( $this->
isProxy() ) {
00681 $this->
validatePGT($validate_url,$text_response,$tree_response);
00682 phpCAS::trace('PGT `'.$this->getPGT().
'\' was validated');
00683 $_SESSION['
phpCAS']['pgt'] = $this->
getPGT();
00684 }
00685 $_SESSION['
phpCAS']['user'] = $this->
getUser();
00686 $res = TRUE;
00687 } elseif ( $this->hasPT() ) {
00688
00689 phpCAS::trace('PT `'.$this->getPT().
'\' is present');
00690 $this->
validatePT($validate_url,$text_response,$tree_response);
00691 phpCAS::trace('PT `'.$this->getPT().
'\' was validated');
00692
if ( $this->
isProxy() ) {
00693 $this->
validatePGT($validate_url,$text_response,$tree_response);
00694 phpCAS::trace('PGT `'.$this->getPGT().
'\' was validated');
00695 $_SESSION['
phpCAS']['pgt'] = $this->
getPGT();
00696 }
00697 $_SESSION['
phpCAS']['user'] = $this->
getUser();
00698 $res = TRUE;
00699 }
else {
00700
00701 phpCAS::trace('no ticket found');
00702 }
00703
00704 phpCAS::traceEnd($res);
00705
return $res;
00706 }
00707
00713 function
isSessionAuthenticated ()
00714 {
00715
return !empty($_SESSION['
phpCAS']['user']);
00716 }
00717
00728 function
wasPreviouslyAuthenticated()
00729 {
00730
phpCAS::traceBegin();
00731
00732
if ( $this->
isCallbackMode() ) {
00733 $this->
callback();
00734 }
00735
00736 $auth = FALSE;
00737
00738
if ( $this->
isProxy() ) {
00739
00740
if ( $this->
isSessionAuthenticated() && !empty($_SESSION['
phpCAS']['pgt']) ) {
00741
00742 $this->setUser($_SESSION['
phpCAS']['user']);
00743 $this->
setPGT($_SESSION['
phpCAS']['pgt']);
00744 phpCAS::trace('user = `'.$_SESSION['
phpCAS']['user'].
'\', PGT = `'.$_SESSION['
phpCAS']['pgt'].
'\'');
00745 $auth = TRUE;
00746 } elseif ( $this->isSessionAuthenticated() && empty($_SESSION['
phpCAS']['pgt']) ) {
00747
00748 phpCAS::trace('username found (`'.$_SESSION['
phpCAS']['user'].
'\') but PGT is empty');
00749
00750 unset($_SESSION['
phpCAS']);
00751 $this->
setST('');
00752 $this->
setPT('');
00753 } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['
phpCAS']['pgt']) ) {
00754
00755 phpCAS::trace('PGT found (`'.$_SESSION['
phpCAS']['pgt'].
'\') but username is empty');
00756
00757 unset($_SESSION['
phpCAS']);
00758 $this->
setST('');
00759 $this->
setPT('');
00760 }
else {
00761 phpCAS::trace('neither user not PGT found');
00762 }
00763 }
else {
00764
00765
if ( $this->
isSessionAuthenticated() ) {
00766
00767 $this->setUser($_SESSION['
phpCAS']['user']);
00768 phpCAS::trace('user = `'.$_SESSION['
phpCAS']['user'].
'\'');
00769 $auth = TRUE;
00770 }
else {
00771 phpCAS::trace('no user found');
00772 }
00773 }
00774
00775 phpCAS::traceEnd($auth);
00776
return $auth;
00777 }
00778
00785 function
redirectToCas($gateway=
false)
00786 {
00787
phpCAS::traceBegin();
00788 $cas_url = $this->getServerLoginURL($gateway);
00789 header('Location: '.$cas_url);
00790 $this->printHTMLHeader($this->getString(
CAS_STR_AUTHENTICATION_WANTED));
00791 printf('<p>'.$this->getString(
CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
00792 $this->
printHTMLFooter();
00793
phpCAS::traceExit();
00794 exit();
00795 }
00796
00802 function
logout($url =
"")
00803 {
00804
phpCAS::traceBegin();
00805 $cas_url = $this->
getServerLogoutURL();
00806
00807
00808
if ( $url !=
"" ) {
00809 $url = '?service=' . $url;
00810 }
00811 header('Location: '.$cas_url . $url);
00812 session_unset();
00813 session_destroy();
00814 $this->printHTMLHeader($this->getString(
CAS_STR_LOGOUT));
00815 printf('<p>'.$this->getString(
CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
00816 $this->
printHTMLFooter();
00817
phpCAS::traceExit();
00818 exit();
00819 }
00820
00823
00824
00825
00826
00827
00828
00829
00830
00831
00845 var
$_st = '';
00846
00852 function
getST()
00853 {
return $this->_st; }
00854
00860 function
setST($st)
00861 { $this->_st = $st; }
00862
00868 function
hasST()
00869 {
return !empty($this->_st); }
00870
00873
00874
00875
00894 function
validateST($validate_url,&$text_response,&$tree_response)
00895 {
00896
phpCAS::traceBegin();
00897
00898 $validate_url = $this->
getServerServiceValidateURL().'&ticket='.$this->getST();
00899
if ( $this->
isProxy() ) {
00900
00901 $validate_url .= '&pgtUrl='.$this->getCallbackURL();
00902 }
00903
00904
00905
if ( !$this->
readURL($validate_url,'',$headers,$text_response,$err_msg) ) {
00906 phpCAS::trace('could not open URL \''.$validate_url.
'\' to validate ('.$err_msg.
')');
00907 $this->authError('ST not validated',
00908 $validate_url,
00909 TRUE);
00910 }
00911
00912
00913
switch ($this->
getServerVersion()) {
00914
case CAS_VERSION_1_0:
00915
if (preg_match('/^no\n/',$text_response)) {
00916 phpCAS::trace('ST has not been validated');
00917 $this->
authError('ST not validated',
00918 $validate_url,
00919 FALSE,
00920 FALSE,
00921 $text_response);
00922 }
00923
if (!preg_match('/^yes\n/',$text_response)) {
00924 phpCAS::trace('ill-formed response');
00925 $this->
authError('ST not validated',
00926 $validate_url,
00927 FALSE,
00928 TRUE,
00929 $text_response);
00930 }
00931
00932 $arr = preg_split('/\n/',$text_response);
00933 $this->setUser(trim($arr[1]));
00934
break;
00935
case CAS_VERSION_2_0:
00936
00937
if ( !($dom =
domxml_open_mem($text_response))) {
00938 phpCAS::trace('
domxml_open_mem() failed');
00939 $this->
authError('ST not validated',
00940 $validate_url,
00941 FALSE,
00942 TRUE,
00943 $text_response);
00944 }
00945
00946
if ( !($tree_response = $dom->document_element()) ) {
00947 phpCAS::trace('document_element() failed');
00948 $this->
authError('ST not validated',
00949 $validate_url,
00950 FALSE,
00951 TRUE,
00952 $text_response);
00953 }
00954
00955
if ( $tree_response->node_name() != 'serviceResponse' ) {
00956 phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().
'\'');
00957 $this->
authError('ST not validated',
00958 $validate_url,
00959 FALSE,
00960 TRUE,
00961 $text_response);
00962 }
00963
if (
sizeof($success_elements = $tree_response->get_elements_by_tagname(
"authenticationSuccess")) != 0) {
00964
00965
if (
sizeof($user_elements = $success_elements[0]->get_elements_by_tagname(
"user")) == 0) {
00966 phpCAS::trace('<authenticationSuccess> found, but no <user>');
00967 $this->
authError('ST not validated',
00968 $validate_url,
00969 FALSE,
00970 TRUE,
00971 $text_response);
00972 }
00973 $user = trim($user_elements[0]->get_content());
00974 phpCAS::trace('user = `'.$user);
00975 $this->setUser($user);
00976
00977 }
else if (
sizeof($failure_elements = $tree_response->get_elements_by_tagname(
"authenticationFailure")) != 0) {
00978 phpCAS::trace('<authenticationFailure> found');
00979
00980 $this->
authError('ST not validated',
00981 $validate_url,
00982 FALSE,
00983 FALSE,
00984 $text_response,
00985 $failure_elements[0]->get_attribute('code'),
00986 trim($failure_elements[0]->get_content()));
00987 }
else {
00988 phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
00989 $this->
authError('ST not validated',
00990 $validate_url,
00991 FALSE,
00992 TRUE,
00993 $text_response);
00994 }
00995
break;
00996 }
00997
00998
00999 phpCAS::traceEnd(TRUE);
01000
return TRUE;
01001 }
01002
01005
01006
01007
01008
01009
01010
01011
01012
01013
01025 var
$_proxy;
01026
01034 function
isProxy()
01035 {
01036
return $this->_proxy;
01037 }
01038
01040
01041
01042
01055 var
$_pgt = '';
01056
01062 function
getPGT()
01063 {
return $this->_pgt; }
01064
01070 function
setPGT($pgt)
01071 { $this->_pgt = $pgt; }
01072
01078 function
hasPGT()
01079 {
return !empty($this->_pgt); }
01080
01083
01084
01085
01103 var
$_callback_mode = FALSE;
01104
01112 function
setCallbackMode($callback_mode)
01113 {
01114 $this->_callback_mode = $callback_mode;
01115 }
01116
01125 function
isCallbackMode()
01126 {
01127
return $this->_callback_mode;
01128 }
01129
01138 var
$_callback_url = '';
01139
01149 function
getCallbackURL()
01150 {
01151
01152
if ( empty($this->_callback_url) ) {
01153 $final_uri = '';
01154
01155 $final_uri = 'https:
01156
01157
01158
01159
if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
01160
01161
01162
01163
if (empty($_SERVER['SERVER_NAME'])) {
01164 $final_uri .= $_SERVER['HTTP_HOST'];
01165 }
else {
01166 $final_uri .= $_SERVER['SERVER_NAME'];
01167 }
01168 }
else {
01169 $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
01170 }
01171
if ( ($this->
isHttps() && $_SERVER['SERVER_PORT']!=443)
01172 || (!$this->
isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
01173 $final_uri .=
':';
01174 $final_uri .= $_SERVER['SERVER_PORT'];
01175 }
01176 $request_uri = $_SERVER['REQUEST_URI'];
01177 $request_uri = preg_replace('/\?.*$/
','',$request_uri);
01178 $final_uri .= $request_uri;
01179 $this->
setCallbackURL($final_uri);
01180 }
01181
return $this->_callback_url;
01182 }
01183
01191 function
setCallbackURL($url)
01192 {
01193
return $this->_callback_url = $url;
01194 }
01195
01202 function
callback()
01203 {
01204
phpCAS::traceBegin();
01205 $this->printHTMLHeader('
phpCAS callback');
01206 $pgt_iou = $_GET['pgtIou'];
01207 $pgt = $_GET['pgtId'];
01208 phpCAS::trace('Storing PGT `'.$pgt.
'\' (
id=`'.$pgt_iou.
'\')');
01209 echo '<p>Storing PGT `'.$pgt.
'\' (
id=`'.$pgt_iou.
'\').</p>';
01210 $this->storePGT($pgt,$pgt_iou);
01211 $this->
printHTMLFooter();
01212
phpCAS::traceExit();
01213 }
01214
01217
01218
01219
01233 var
$_pgt_storage = null;
01234
01241 function
initPGTStorage()
01242 {
01243
01244
if ( !is_object($this->_pgt_storage) ) {
01245 $this->
setPGTStorageFile();
01246 }
01247
01248
01249 $this->_pgt_storage->init();
01250 }
01251
01260 function
storePGT($pgt,$pgt_iou)
01261 {
01262
01263 $this->
initPGTStorage();
01264
01265 $this->_pgt_storage->write($pgt,$pgt_iou);
01266 }
01267
01277 function
loadPGT($pgt_iou)
01278 {
01279
01280 $this->
initPGTStorage();
01281
01282
return $this->_pgt_storage->read($pgt_iou);
01283 }
01284
01294 function
setPGTStorageFile($format='',
01295 $path='')
01296 {
01297
01298
if ( is_object($this->_pgt_storage) ) {
01299 phpCAS::error('PGT storage already defined');
01300 }
01301
01302
01303 $this->_pgt_storage = &
new PGTStorageFile($
this,$format,$path);
01304 }
01305
01323 function
setPGTStorageDB($user,
01324 $password,
01325 $database_type,
01326 $hostname,
01327 $port,
01328 $database,
01329 $table)
01330 {
01331
01332
if ( is_object($this->_pgt_storage) ) {
01333 phpCAS::error('PGT storage already defined');
01334 }
01335
01336
01337 trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
01338
01339
01340 $this->_pgt_storage = &
new PGTStorageDB($
this,$user,$password,$database_type,$hostname,$port,$database,$table);
01341 }
01342
01343
01344
01345
01359 function
validatePGT(&$validate_url,$text_response,$tree_response)
01360 {
01361
phpCAS::traceBegin();
01362
if (
sizeof($arr = $tree_response->get_elements_by_tagname(
"proxyGrantingTicket")) == 0) {
01363 phpCAS::trace('<proxyGrantingTicket> not found');
01364
01365 $this->
authError('Ticket validated but no PGT Iou transmitted',
01366 $validate_url,
01367 FALSE,
01368 FALSE,
01369 $text_response);
01370 }
else {
01371
01372 $pgt_iou = trim($arr[0]->get_content());
01373 $pgt = $this->loadPGT($pgt_iou);
01374
if ( $pgt == FALSE ) {
01375 phpCAS::trace('could not load PGT');
01376 $this->
authError('PGT Iou was transmitted but PGT could not be retrieved',
01377 $validate_url,
01378 FALSE,
01379 FALSE,
01380 $text_response);
01381 }
01382 $this->setPGT($pgt);
01383 }
01384 phpCAS::traceEnd(TRUE);
01385
return TRUE;
01386 }
01387
01388
01389
01390
01391
01403 function
retrievePT($target_service,&$err_code,&$err_msg)
01404 {
01405
phpCAS::traceBegin();
01406
01407
01408
01409
01410
01411 $err_msg = '';
01412
01413
01414 $cas_url = $this->
getServerProxyURL().'?targetService='.preg_replace('/&/
','%26',$target_service).'&pgt='.$this->getPGT();
01415
01416
01417
if ( !$this->
readURL($cas_url,'',$headers,$cas_response,$err_msg) ) {
01418 phpCAS::trace('could not open URL \''.$cas_url.
'\' to validate ('.$err_msg.
')');
01419 $err_code =
PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
01420 $err_msg = 'could not retrieve PT (no response from the CAS server)';
01421 phpCAS::traceEnd(FALSE);
01422
return FALSE;
01423 }
01424
01425 $bad_response = FALSE;
01426
01427
if ( !$bad_response ) {
01428
01429
if ( !($dom = @
domxml_open_mem($cas_response))) {
01430 phpCAS::trace('
domxml_open_mem() failed');
01431
01432 $bad_response = TRUE;
01433 }
01434 }
01435
01436
if ( !$bad_response ) {
01437
01438
if ( !($root = $dom->document_element()) ) {
01439 phpCAS::trace('document_element() failed');
01440
01441 $bad_response = TRUE;
01442 }
01443 }
01444
01445
if ( !$bad_response ) {
01446
01447
if ( $root->node_name() != 'serviceResponse' ) {
01448 phpCAS::trace('node_name() failed');
01449
01450 $bad_response = TRUE;
01451 }
01452 }
01453
01454
if ( !$bad_response ) {
01455
01456
if (
sizeof($arr = $root->get_elements_by_tagname(
"proxySuccess")) != 0) {
01457
01458
if (
sizeof($arr = $root->get_elements_by_tagname(
"proxyTicket")) != 0) {
01459 $err_code =
PHPCAS_SERVICE_OK;
01460 $err_msg = '';
01461 $pt = trim($arr[0]->get_content());
01462 phpCAS::traceEnd($pt);
01463
return $pt;
01464 }
else {
01465 phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
01466 }
01467 }
01468
01469
else if (
sizeof($arr = $root->get_elements_by_tagname(
"proxyFailure")) != 0) {
01470
01471 $err_code =
PHPCAS_SERVICE_PT_FAILURE;
01472 $err_msg = 'PT retrieving failed (code=`'
01473 .$arr[0]->get_attribute('code')
01474 .
'\', message=`'
01475 .trim($arr[0]->get_content())
01476 .
'\')';
01477 phpCAS::traceEnd(FALSE);
01478
return FALSE;
01479 }
else {
01480 phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
01481 }
01482 }
01483
01484
01485 $err_code =
PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
01486 $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.
'\')';
01487
01488 phpCAS::traceEnd(FALSE);
01489
return FALSE;
01490 }
01491
01492
01493
01494
01495
01511 function
readURL($url,$cookies,&$headers,&$body,&$err_msg)
01512 {
01513
phpCAS::traceBegin();
01514 $headers = '';
01515 $body = '';
01516 $err_msg = '';
01517
01518 $res = TRUE;
01519
01520
01521 $ch = curl_init($url);
01522
01523
01524 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
01525
01526 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
01527
01528
01529 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
01530
01531 curl_setopt($ch, CURLOPT_HEADER, 1);
01532
01533
if ( is_array($cookies) ) {
01534 curl_setopt($ch,CURLOPT_COOKIE,implode(
';',$cookies));
01535 }
01536
01537 $buf = curl_exec ($ch);
01538
if ( $buf === FALSE ) {
01539 phpCAS::trace('cur_exec() failed');
01540 $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
01541
01542 curl_close ($ch);
01543 $res = FALSE;
01544 }
else {
01545
01546 curl_close ($ch);
01547
01548
01549
01550 $pos = FALSE;
01551
for ($i=0; $i<strlen($buf); $i++) {
01552
if ( $buf[$i] == chr(13) )
01553
if ( $buf[$i+1] == chr(10) )
01554
if ( $buf[$i+2] == chr(13) )
01555
if ( $buf[$i+3] == chr(10) ) {
01556
01557 $pos = $i;
01558
break;
01559 }
01560 }
01561
01562
if ( $pos === FALSE ) {
01563
01564 $err_msg = 'no header found';
01565 phpCAS::trace($err_msg);
01566 $res = FALSE;
01567 }
else {
01568
01569 $headers = preg_split (
"/[\n\r]+/",substr($buf,0,$pos));
01570
01571 $body = substr($buf,$pos+4);
01572 }
01573 }
01574
01575 phpCAS::traceEnd($res);
01576
return $res;
01577 }
01578
01594 function
serviceWeb($url,&$err_code,&$output)
01595 {
01596
phpCAS::traceBegin();
01597
01598 $pt = $this->retrievePT($url,$err_code,$output);
01599
01600 $res = TRUE;
01601
01602
01603
if ( !$pt ) {
01604
01605 phpCAS::trace('PT was not retrieved correctly');
01606 $res = FALSE;
01607 }
else {
01608
01609
if ( is_array($_SESSION['
phpCAS']['services'][$url]['cookies']) ) {
01610 foreach ( $_SESSION['
phpCAS']['services'][$url]['cookies'] as $name => $val ) {
01611 $cookies[] = $name.
'='.$val;
01612 }
01613 }
01614
01615
01616
if ( strstr($url,
'?') === FALSE ) {
01617 $service_url = $url.'?ticket='.$pt;
01618 }
else {
01619 $service_url = $url.'&ticket='.$pt;
01620 }
01621
01622 phpCAS::trace('reading URL`'.$service_url.
'\'');
01623 if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
01624 phpCAS::trace('could not read URL`'.$service_url.
'\'');
01625 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
01626
01627 $output = sprintf($this->getString(
CAS_STR_SERVICE_UNAVAILABLE),
01628 $service_url,
01629 $err_msg);
01630 $res = FALSE;
01631 }
else {
01632
01633 phpCAS::trace('URL`'.$service_url.
'\' has been read, storing cookies:');
01634 foreach ( $headers as $header ) {
01635
01636
if ( preg_match('/^Set-Cookie:/',$header) ) {
01637
01638 $header_val = preg_replace('/^Set-Cookie: */
','',$header);
01639
01640 $name_val = strtok($header_val,'; ');
01641
01642 $cookie_name = strtok($name_val,
'=');
01643 $cookie_val = strtok(
'=');
01644
01645 $_SESSION['
phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
01646 phpCAS::trace($cookie_name.' -> '.$cookie_val);
01647 }
01648 }
01649 }
01650 }
01651
01652 phpCAS::traceEnd($res);
01653
return $res;
01654 }
01655
01674 function
serviceMail($url,$flags,&$err_code,&$err_msg,&$pt)
01675 {
01676
phpCAS::traceBegin();
01677
01678 $pt = $this->retrievePT($target_service,$err_code,$output);
01679
01680 $stream = FALSE;
01681
01682
01683
if ( !$pt ) {
01684
01685 phpCAS::trace('PT was not retrieved correctly');
01686 }
else {
01687 phpCAS::trace('opening IMAP URL `'.$url.
'\'...');
01688 $stream = @imap_open($url,$this->getUser(),$pt,$flags);
01689
if ( !$stream ) {
01690 phpCAS::trace('could not open URL');
01691 $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
01692
01693 $err_msg = sprintf($this->getString(
CAS_STR_SERVICE_UNAVAILABLE),
01694 $service_url,
01695 var_export(imap_errors(),TRUE));
01696 $pt = FALSE;
01697 $stream = FALSE;
01698 }
else {
01699 phpCAS::trace('ok');
01700 }
01701 }
01702
01703 phpCAS::traceEnd($stream);
01704
return $stream;
01705 }
01706
01709
01710
01711
01712
01713
01714
01715
01716
01717
01731 var
$_pt = '';
01732
01738 function
getPT()
01739 {
return $this->_pt; }
01740
01746 function
setPT($pt)
01747 { $this->_pt = $pt; }
01748
01754 function
hasPT()
01755 {
return !empty($this->_pt); }
01756
01758
01759
01760
01773 function
validatePT(&$validate_url,&$text_response,&$tree_response)
01774 {
01775
phpCAS::traceBegin();
01776
01777 $validate_url = $this->
getServerProxyValidateURL().'&ticket='.$this->getPT();
01778
01779
if ( $this->
isProxy() ) {
01780
01781 $validate_url .= '&pgtUrl='.$this->getCallbackURL();
01782 }
01783
01784
01785
if ( !$this->readURL($validate_url,'',$headers,$text_response,$err_msg) ) {
01786 phpCAS::trace('could not open URL \''.$validate_url.
'\' to validate ('.$err_msg.
')');
01787 $this->authError('PT not validated',
01788 $validate_url,
01789 TRUE);
01790 }
01791
01792
01793
if ( !($dom =
domxml_open_mem($text_response))) {
01794
01795 $this->
authError('PT not validated',
01796 $alidate_url,
01797 FALSE,
01798 TRUE,
01799 $text_response);
01800 }
01801
01802
if ( !($tree_response = $dom->document_element()) ) {
01803
01804 $this->
authError('PT not validated',
01805 $validate_url,
01806 FALSE,
01807 TRUE,
01808 $text_response);
01809 }
01810
01811
if ( $tree_response->node_name() != 'serviceResponse' ) {
01812
01813 $this->
authError('PT not validated',
01814 $validate_url,
01815 FALSE,
01816 TRUE,
01817 $text_response);
01818 }
01819
if (
sizeof($arr = $tree_response->get_elements_by_tagname(
"authenticationSuccess")) != 0) {
01820
01821
if (
sizeof($arr = $tree_response->get_elements_by_tagname(
"user")) == 0) {
01822
01823 $this->
authError('PT not validated',
01824 $validate_url,
01825 FALSE,
01826 TRUE,
01827 $text_response);
01828 }
01829 $this->setUser(trim($arr[0]->get_content()));
01830
01831 }
else if (
sizeof($arr = $tree_response->get_elements_by_tagname(
"authenticationFailure")) != 0) {
01832
01833 $this->
authError('PT not validated',
01834 $validate_url,
01835 FALSE,
01836 FALSE,
01837 $text_response,
01838 $arr[0]->get_attribute('code'),
01839 trim($arr[0]->get_content()));
01840 }
else {
01841 $this->
authError('PT not validated',
01842 $validate_url,
01843 FALSE,
01844 TRUE,
01845 $text_response);
01846 }
01847
01848
01849
01850 phpCAS::traceEnd(TRUE);
01851
return TRUE;
01852 }
01853
01856
01857
01858
01859
01860
01861
01867
01868
01869
01877 var
$_url = '';
01878
01887 function
getURL()
01888 {
01889
phpCAS::traceBegin();
01890
01891
if ( empty($this->_url) ) {
01892 $final_uri = '';
01893
01894 $final_uri = ($this->
isHttps()) ? 'https' : 'http';
01895 $final_uri .= ':
01896
01897
01898
01899
if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
01900
01901
01902
01903
if (empty($_SERVER['SERVER_NAME'])) {
01904 $final_uri .= $_SERVER['HTTP_HOST'];
01905 }
else {
01906 $final_uri .= $_SERVER['SERVER_NAME'];
01907 }
01908 }
else {
01909 $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
01910 }
01911
if ( ($this->
isHttps() && $_SERVER['SERVER_PORT']!=443)
01912 || (!$this->
isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
01913 $final_uri .=
':';
01914 $final_uri .= $_SERVER['SERVER_PORT'];
01915 }
01916
01917 $final_uri .= strtok($_SERVER['REQUEST_URI'],
"?");
01918 $cgi_params =
'?'.strtok(
"?");
01919
01920 $cgi_params = preg_replace('/&ticket=[^&]*/
','',$cgi_params);
01921 $cgi_params = preg_replace('/\?ticket=[^&;]*/
','?',$cgi_params);
01922 $cgi_params = preg_replace('/\?%26/
','?',$cgi_params);
01923 $cgi_params = preg_replace('/\?&/
','?',$cgi_params);
01924 $cgi_params = preg_replace('/\?$/
','',$cgi_params);
01925 $final_uri .= $cgi_params;
01926 $this->
setURL($final_uri);
01927 }
01928 phpCAS::traceEnd($this->_url);
01929
return $this->_url;
01930 }
01931
01939 function
setURL($url)
01940 {
01941 $this->_url = $url;
01942 }
01943
01944
01945
01946
01962 function
authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
01963 {
01964
phpCAS::traceBegin();
01965
01966 $this->printHTMLHeader($this->getString(
CAS_STR_AUTHENTICATION_FAILED));
01967 printf($this->getString(
CAS_STR_YOU_WERE_NOT_AUTHENTICATED),$this->
getURL(),$_SERVER['SERVER_ADMIN']);
01968 phpCAS::trace('CAS URL: '.$cas_url);
01969 phpCAS::trace('Authentication failure: '.$failure);
01970
if ( $no_response ) {
01971 phpCAS::trace('Reason: no response from the CAS server');
01972 }
else {
01973
if ( $bad_response ) {
01974 phpCAS::trace('Reason: bad response from the CAS server');
01975 }
else {
01976
switch ($this->
getServerVersion()) {
01977
case CAS_VERSION_1_0:
01978 phpCAS::trace('Reason: CAS error');
01979
break;
01980
case CAS_VERSION_2_0:
01981
if ( empty($err_code) )
01982 phpCAS::trace('Reason: no CAS error');
01983
else
01984 phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
01985
break;
01986 }
01987 }
01988 phpCAS::trace('CAS response: '.$cas_response);
01989 }
01990 $this->
printHTMLFooter();
01991
phpCAS::traceExit();
01992 exit();
01993 }
01994
01996 }
01997
01998 ?>