/** * This method is used to print the HTML output when the user was not authenticated. * * @param $client phpcas client * @param $failure the failure that occured * @param $cas_url the URL the CAS server was asked for * @param $no_response the response from the CAS server (other * parameters are ignored if TRUE) * @param $bad_response bad response from the CAS server ($err_code * and $err_msg ignored if TRUE) * @param $cas_response the response of the CAS server * @param $err_code the error code given by the CAS server * @param $err_msg the error message given by the CAS server */ public function __construct($client, $failure, $cas_url, $no_response, $bad_response = '', $cas_response = '', $err_code = '', $err_msg = '') { phpCAS::traceBegin(); $client->printHTMLHeader($client->getString(CAS_STR_AUTHENTICATION_FAILED)); printf($client->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED), htmlentities($client->getURL()), $_SERVER['SERVER_ADMIN']); phpCAS::trace('CAS URL: ' . $cas_url); phpCAS::trace('Authentication failure: ' . $failure); if ($no_response) { phpCAS::trace('Reason: no response from the CAS server'); } else { if ($bad_response) { phpCAS::trace('Reason: bad response from the CAS server'); } else { switch ($client->getServerVersion()) { case CAS_VERSION_1_0: phpCAS::trace('Reason: CAS error'); break; case CAS_VERSION_2_0: if (empty($err_code)) { phpCAS::trace('Reason: no CAS error'); } else { phpCAS::trace('Reason: [' . $err_code . '] CAS error: ' . $err_msg); } break; } } phpCAS::trace('CAS response: ' . $cas_response); } $client->printHTMLFooter(); phpCAS::traceExit(); }
/** * This method is called to force authentication if the user was not already * authenticated. If the user is not authenticated, halt by redirecting to * the CAS server. */ function forceAuthentication() { global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL; phpCAS::traceBegin(); if (!is_object($PHPCAS_CLIENT)) { phpCAS::error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()'); } $auth = $PHPCAS_CLIENT->forceAuthentication(); // store where the authentication has been checked and the result $dbg = phpCAS::backtrace(); $PHPCAS_AUTH_CHECK_CALL = array('done' => TRUE, 'file' => $dbg[0]['file'], 'line' => $dbg[0]['line'], 'method' => __CLASS__ . '::' . __FUNCTION__, 'result' => $auth); if (!$auth) { phpCAS::trace('user is not authenticated, redirecting to the CAS server'); $PHPCAS_CLIENT->forceAuthentication(); } else { phpCAS::trace('no need to authenticate (user `' . phpCAS::getUser() . '\' is already authenticated)'); } phpCAS::traceEnd(); return $auth; }
/** * Match a list of proxies. * * @param array $list The list of proxies in front of this service. * * @return bool */ public function matches(array $list) { $list = array_values($list); // Ensure that we have an indexed array if ($this->isSizeValid($list)) { $mismatch = false; foreach ($this->chain as $i => $search) { $proxy_url = $list[$i]; if (preg_match('/^\\/.*\\/[ixASUXu]*$/s', $search)) { if (preg_match($search, $proxy_url)) { phpCAS::trace("Found regexp " . $search . " matching " . $proxy_url); } else { phpCAS::trace("No regexp match " . $search . " != " . $proxy_url); $mismatch = true; break; } } else { if (strncasecmp($search, $proxy_url, strlen($search)) == 0) { phpCAS::trace("Found string " . $search . " matching " . $proxy_url); } else { phpCAS::trace("No match " . $search . " != " . $proxy_url); $mismatch = true; break; } } } if (!$mismatch) { phpCAS::trace("Proxy chain matches"); return true; } } else { phpCAS::trace("Proxy chain skipped: size mismatch"); } return false; }
/** * Match a list of proxies. * * @param array $list The list of proxies in front of this service. * * @return bool */ public function matches(array $list) { phpCAS::trace("Using CAS_ProxyChain_Any. No proxy validation is performed."); return true; }
/** * Set no SSL validation for the CAS server. * * @return void */ public static function setNoCasServerValidation() { phpCAS::traceBegin(); phpCAS::_validateClientExists(); phpCAS::trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.'); self::$_PHPCAS_CLIENT->setNoCasServerValidation(); phpCAS::traceEnd(); }
/** * This method reads a PGT corresponding to a PGT Iou and deletes the * corresponding file. * * @param $pgt_iou the PGT iou * * @return the corresponding PGT, or FALSE on error * * @public */ function read($pgt_iou) { phpCAS::traceBegin(); $pgt = FALSE; $fname = $this->getPGTIouFilename($pgt_iou); if (file_exists($fname)) { if (!($f = fopen($fname, "r"))) { phpCAS::trace('could not open `' . $fname . '\''); } else { if (($pgt = fgets($f)) === FALSE) { phpCAS::trace('could not read PGT from `' . $fname . '\''); } fclose($f); } // delete the PGT file @unlink($fname); } else { phpCAS::trace('No such file `' . $fname . '\''); } phpCAS::traceEnd($pgt); return $pgt; }
/** * Internal method to initialize our cURL handle and configure the request. * This method should NOT be used outside of the CurlRequest or the * CurlMultiRequest. * * @return resource The cURL handle on success, false on failure */ private function _initAndConfigure() { /********************************************************* * initialize the CURL session *********************************************************/ $ch = curl_init($this->url); if (version_compare(PHP_VERSION, '5.1.3', '>=')) { //only avaible in php5 curl_setopt_array($ch, $this->_curlOptions); } else { foreach ($this->_curlOptions as $key => $value) { curl_setopt($ch, $key, $value); } } /********************************************************* * Set SSL configuration *********************************************************/ if ($this->caCertPath) { if ($this->validateCN) { curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); } else { curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); } curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_CAINFO, $this->caCertPath); phpCAS::trace('CURL: Set CURLOPT_CAINFO ' . $this->caCertPath); } else { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); } /********************************************************* * Configure curl to capture our output. *********************************************************/ // return the CURL output into a variable curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // get the HTTP header with a callback curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curlReadHeaders')); /********************************************************* * Add cookie headers to our request. *********************************************************/ if (count($this->cookies)) { $cookieStrings = array(); foreach ($this->cookies as $name => $val) { $cookieStrings[] = $name . '=' . $val; } curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookieStrings)); } /********************************************************* * Add any additional headers *********************************************************/ if (count($this->headers)) { curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); } /********************************************************* * Flag and Body for POST requests *********************************************************/ if ($this->isPost) { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postBody); } return $ch; }
/** * Open the IMAP stream (similar to imap_open()). * * @return resource Returns an IMAP stream on success * @throws CAS_OutOfSequenceException If called multiple times. * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. * The code of the Exception will be one of: * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE * PHPCAS_SERVICE_PT_FAILURE * @throws CAS_ProxiedService_Exception If there is a failure sending the request to the target service. */ public function open() { if ($this->hasBeenOpened()) { throw new CAS_OutOfSequenceException('Stream already opened.'); } if (empty($this->_mailbox)) { throw new CAS_ProxiedService_Exception('You must specify a mailbox via ' . get_class($this) . '->setMailbox($mailbox)'); } phpCAS::traceBegin(); // Get our proxy ticket and append it to our URL. $this->initializeProxyTicket(); phpCAS::trace('opening IMAP mailbox `' . $this->_mailbox . '\'...'); $this->_stream = @imap_open($this->_mailbox, $this->_username, $this->getProxyTicket(), $this->_options); if ($this->_stream) { phpCAS::trace('ok'); } else { phpCAS::trace('could not open mailbox'); // @todo add localization integration. $message = 'IMAP Error: ' . $url . ' ' . var_export(imap_errors(), true); phpCAS::trace($message); throw new CAS_ProxiedService_Exception($message); } phpCAS::traceEnd(); return $this->_stream; }
/** * Build and perform a request, following redirects * * @param string $url url for the request * * @return void * @throws CAS_ProxyTicketException If there is a proxy-ticket failure. * The code of the Exception will be one of: * PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE * PHPCAS_SERVICE_PT_FAILURE * @throws CAS_ProxiedService_Exception If there is a failure sending the * request to the target service. */ protected function makeRequest($url) { // Verify that we are not in a redirect loop $this->_numRequests++; if ($this->_numRequests > 4) { $message = 'Exceeded the maximum number of redirects (3) in proxied service request.'; phpCAS::trace($message); throw new CAS_ProxiedService_Exception($message); } // Create a new request. $request = clone $this->requestHandler; $request->setUrl($url); // Add any cookies to the request. $request->addCookies($this->_cookieJar->getCookies($url)); // Add any other parts of the request needed by concrete classes $this->populateRequest($request); // Perform the request. phpCAS::trace('Performing proxied service request to \'' . $url . '\''); if (!$request->send()) { $message = 'Could not perform proxied service request to URL`' . $url . '\'. ' . $request->getErrorMessage(); phpCAS::trace($message); throw new CAS_ProxiedService_Exception($message); } // Store any cookies from the response; $this->_cookieJar->storeCookies($url, $request->getResponseHeaders()); // Follow any redirects if ($redirectUrl = $this->getRedirectUrl($request->getResponseHeaders())) { phpCAS::trace('Found redirect:' . $redirectUrl); $this->makeRequest($redirectUrl); } else { $this->_responseHeaders = $request->getResponseHeaders(); $this->_responseBody = $request->getResponseBody(); $this->_responseStatusCode = $request->getResponseStatusCode(); } }
/** * Set no SSL validation for the CAS server. * * @return void */ public static function setNoCasServerValidation() { phpCAS::traceBegin(); if (!is_object(self::$_PHPCAS_CLIENT)) { phpCAS::error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()'); } phpCAS::trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.'); self::$_PHPCAS_CLIENT->setNoCasServerValidation(); phpCAS::traceEnd(); }
/** * This method is used to print the HTML output when the user was not * authenticated. * * @param CAS_Client $client phpcas client * @param string $failure the failure that occured * @param string $cas_url the URL the CAS server was asked for * @param bool $no_response the response from the CAS server (other * parameters are ignored if TRUE) * @param bool $bad_response bad response from the CAS server ($err_code * and $err_msg ignored if TRUE) * @param string $cas_response the response of the CAS server * @param int $err_code the error code given by the CAS server * @param string $err_msg the error message given by the CAS server */ public function __construct($client, $failure, $cas_url, $no_response, $bad_response = '', $cas_response = '', $err_code = '', $err_msg = '') { phpCAS::traceBegin(); $lang = $client->getLangObj(); $client->printHTMLHeader($lang->getAuthenticationFailed()); printf($lang->getYouWereNotAuthenticated(), htmlentities($client->getURL()), isset($_SERVER['SERVER_ADMIN']) ? $_SERVER['SERVER_ADMIN'] : ''); phpCAS::trace('CAS URL: ' . $cas_url); phpCAS::trace('Authentication failure: ' . $failure); if ($no_response) { phpCAS::trace('Reason: no response from the CAS server'); } else { if ($bad_response) { phpCAS::trace('Reason: bad response from the CAS server'); } else { switch ($client->getServerVersion()) { case CAS_VERSION_1_0: phpCAS::trace('Reason: CAS error'); break; case CAS_VERSION_2_0: case CAS_VERSION_3_0: if (empty($err_code)) { phpCAS::trace('Reason: no CAS error'); } else { phpCAS::trace('Reason: [' . $err_code . '] CAS error: ' . $err_msg); } break; } } phpCAS::trace('CAS response: ' . $cas_response); } $client->printHTMLFooter(); phpCAS::traceExit(); }
/** * Validate the proxies from the proxy ticket validation against the * chains that were definded. * * @param array $list List of proxies from the proxy ticket validation. * * @return if any chain fully matches the supplied list */ public function contains(array $list) { phpCAS::traceBegin(); $count = 0; foreach ($this->_chains as $chain) { phpCAS::trace("Checking chain " . $count++); if ($chain->matches($list)) { phpCAS::traceEnd(true); return true; } } phpCAS::trace("No proxy chain matches."); phpCAS::traceEnd(false); return false; }
/** * This method reads a PGT corresponding to a PGT Iou and deletes the * corresponding db entry. * * @param string $pgt_iou the PGT iou * * @return the corresponding PGT, or FALSE on error */ public function read($pgt_iou) { phpCAS::traceBegin(); $pgt = false; // initialize the PDO object for this method $pdo = $this->_getPdo(); $this->_setErrorMode(); try { $pdo->beginTransaction(); // fetch the pgt for the specified pgt_iou $query = $pdo->prepare($this->retrievePgtSql()); $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); $query->execute(); $pgt = $query->fetchColumn(0); $query->closeCursor(); // delete the specified pgt_iou from the database $query = $pdo->prepare($this->deletePgtSql()); $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); $query->execute(); $query->closeCursor(); $pdo->commit(); } catch (PDOException $e) { // attempt rolling back the transaction before throwing a phpCAS error try { $pdo->rollBack(); } catch (PDOException $e) { } phpCAS::trace('error reading PGT from database: ' . $e->getMessage()); } // reset the PDO object $this->_resetErrorMode(); phpCAS::traceEnd(); return $pgt; }
/** * This method rebroadcasts logout/pgtIou requests. Can be LOGOUT,PGTIOU * * @param int $type type of rebroadcasting. * * @return void */ private function _rebroadcast($type) { phpCAS::traceBegin(); $rebroadcast_curl_options = array(CURLOPT_FAILONERROR => 1, CURLOPT_FOLLOWLOCATION => 1, CURLOPT_RETURNTRANSFER => 1, CURLOPT_CONNECTTIMEOUT => 1, CURLOPT_TIMEOUT => 4); // Try to determine the IP address of the server if (!empty($_SERVER['SERVER_ADDR'])) { $ip = $_SERVER['SERVER_ADDR']; } else { if (!empty($_SERVER['LOCAL_ADDR'])) { // IIS 7 $ip = $_SERVER['LOCAL_ADDR']; } } // Try to determine the DNS name of the server if (!empty($ip)) { $dns = gethostbyaddr($ip); } $multiClassName = 'CAS_Request_CurlMultiRequest'; $multiRequest = new $multiClassName(); for ($i = 0; $i < sizeof($this->_rebroadcast_nodes); $i++) { if ($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::HOSTNAME && !empty($dns) && stripos($this->_rebroadcast_nodes[$i], $dns) === false || $this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::IP && !empty($ip) && stripos($this->_rebroadcast_nodes[$i], $ip) === false) { phpCAS::trace('Rebroadcast target URL: ' . $this->_rebroadcast_nodes[$i] . $_SERVER['REQUEST_URI']); $className = $this->_requestImplementation; $request = new $className(); $url = $this->_rebroadcast_nodes[$i] . $_SERVER['REQUEST_URI']; $request->setUrl($url); if (count($this->_rebroadcast_headers)) { $request->addHeaders($this->_rebroadcast_headers); } $request->makePost(); if ($type == self::LOGOUT) { // Logout request $request->setPostBody('rebroadcast=false&logoutRequest=' . $_POST['logoutRequest']); } else { if ($type == self::PGTIOU) { // pgtIou/pgtId rebroadcast $request->setPostBody('rebroadcast=false'); } } $request->setCurlOptions($rebroadcast_curl_options); $multiRequest->addRequest($request); } else { phpCAS::trace('Rebroadcast not sent to self: ' . $this->_rebroadcast_nodes[$i] . ' == ' . (!empty($ip) ? $ip : '') . '/' . (!empty($dns) ? $dns : '')); } } // We need at least 1 request if ($multiRequest->getNumRequests() > 0) { $multiRequest->send(); } phpCAS::traceEnd(); }
/** * Send the request and store the results. * * @return boolean TRUE on success, FALSE on failure. */ protected function _sendRequest() { phpCAS::traceBegin(); /********************************************************* * initialize the CURL session *********************************************************/ $ch = curl_init($this->url); if (version_compare(PHP_VERSION, '5.1.3', '>=')) { //only avaible in php5 curl_setopt_array($ch, $this->curlOptions); } else { foreach ($this->curlOptions as $key => $value) { curl_setopt($ch, $key, $value); } } /********************************************************* * Set SSL configuration *********************************************************/ if ($this->caCertPath) { curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_CAINFO, $this->caCertPath); phpCAS::trace('CURL: Set CURLOPT_CAINFO'); } else { curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); } /********************************************************* * Configure curl to capture our output. *********************************************************/ // return the CURL output into a variable curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // get the HTTP header with a callback curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curlReadHeaders')); /********************************************************* * Add cookie headers to our request. *********************************************************/ if (count($this->cookies)) { $cookieStrings = array(); foreach ($this->cookies as $name => $val) { $cookieStrings[] = $name . '=' . $val; } curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookieStrings)); } /********************************************************* * Add any additional headers *********************************************************/ if (count($this->headers)) { curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); } /********************************************************* * Flag and Body for POST requests *********************************************************/ if ($this->isPost) { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postBody); } /********************************************************* * Perform the query *********************************************************/ $buf = curl_exec($ch); if ($buf === FALSE) { phpCAS::trace('curl_exec() failed'); $this->storeErrorMessage('CURL error #' . curl_errno($ch) . ': ' . curl_error($ch)); $res = FALSE; } else { $this->storeResponseBody($buf); phpCAS::trace("Response Body: \n" . $buf . "\n"); $res = TRUE; } // close the CURL session curl_close($ch); phpCAS::traceEnd($res); return $res; }
/** * Parse a single cookie header line. * * Based on RFC2965 http://www.ietf.org/rfc/rfc2965.txt * * @param string $line The header line. * @param string $defaultDomain The domain to use if none is specified in the cookie. * @return array */ protected function parseCookieHeader($line, $defaultDomain) { if (!$defaultDomain) { throw new CAS_InvalidArgumentException('$defaultDomain was not provided.'); } // Set our default values $cookie = array('domain' => $defaultDomain, 'path' => '/', 'secure' => false); $line = preg_replace('/^Set-Cookie2?: /i', '', trim($line)); // trim any trailing semicolons. $line = trim($line, ';'); phpCAS::trace("Cookie Line: {$line}"); // This implementation makes the assumption that semicolons will not // be present in quoted attribute values. While attribute values that // contain semicolons are allowed by RFC2965, they are hopefully rare // enough to ignore for our purposes. Most browsers make the same // assumption. $attributeStrings = explode(';', $line); foreach ($attributeStrings as $attributeString) { // split on the first equals sign and use the rest as value $attributeParts = explode('=', $attributeString, 2); $attributeName = trim($attributeParts[0]); $attributeNameLC = strtolower($attributeName); if (isset($attributeParts[1])) { $attributeValue = trim($attributeParts[1]); // Values may be quoted strings. if (strpos($attributeValue, '"') === 0) { $attributeValue = trim($attributeValue, '"'); // unescape any escaped quotes: $attributeValue = str_replace('\\"', '"', $attributeValue); } } else { $attributeValue = null; } switch ($attributeNameLC) { case 'expires': $cookie['expires'] = strtotime($attributeValue); break; case 'max-age': $cookie['max-age'] = (int) $attributeValue; // Set an expiry time based on the max-age if ($cookie['max-age']) { $cookie['expires'] = time() + $cookie['max-age']; } else { $cookie['expires'] = time() - 1; } break; case 'secure': $cookie['secure'] = true; break; case 'domain': case 'path': case 'port': case 'version': case 'comment': case 'commenturl': case 'discard': case 'httponly': $cookie[$attributeNameLC] = $attributeValue; break; default: $cookie['name'] = $attributeName; $cookie['value'] = $attributeValue; } } return $cookie; }
function authenticate() { global $wpcas_options, $cas_configured; phpCAS::setDebug('/tmp/phpCAS.log'); if (!$cas_configured) { die(__('wpCAS plugin not configured', 'wpcas')); } if (phpCAS::isAuthenticated()) { /** * @author dbalseiro * Me fijo en el atributo Tipo de Usuario para ver si accede o no a la app */ $tipoUsr = phpCAS::getAttributes(); $tipoUsr = $tipoUsr['personType']; phpCAS::trace($tipoUsr); if ($tipoUsr != 'INTERNA') { wp_die('No tiene permiso para acceder a esta aplicacion'); die; } // CAS was successful $user = get_user_by('login', phpCAS::getUser()); if (!$user) { $email = phpCAS::getAttributes(); $email = $email['email']; $user = get_user_by('email', $email); } if ($user) { // user already exists // the CAS user has a WP account wp_set_auth_cookie($user->ID); if (isset($_GET['redirect_to'])) { wp_redirect(preg_match('/^http/', $_GET['redirect_to']) ? $_GET['redirect_to'] : site_url($_GET['redirect_to'])); die; } wp_redirect(site_url('/')); die; } else { // the CAS user _does_not_have_ a WP account if (function_exists('wpcas_nowpuser')) { $email = phpCAS::getAttributes(); $email = $email['email']; wpcas_nowpuser(phpCAS::getUser(), $email); } else { die(__('you do not have permission here', 'wpcas')); } } } else { phpCAS::forceAuthentication(); die("NOT AUTHENTICATED"); } }