From 4375074d3a3ef5257ec209a1b720eb8ffb9aeae3 Mon Sep 17 00:00:00 2001
From: Mads Freek Petersen <freek@wayf.dk>
Date: Tue, 22 Apr 2008 22:17:04 +0000
Subject: [PATCH] Added support for serviceValidate and getting attributes from
 cas response by specifying a list of attribute to XPath mappings

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@508 44740490-163a-0410-bde0-09ae8108e29a
---
 www/auth/login-cas-ldap.php | 88 +++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 39 deletions(-)

diff --git a/www/auth/login-cas-ldap.php b/www/auth/login-cas-ldap.php
index 62a76a23d..8e5f9a361 100755
--- a/www/auth/login-cas-ldap.php
+++ b/www/auth/login-cas-ldap.php
@@ -32,7 +32,9 @@ try {
 		throw new Exception('No CAS authentication configuration for this SAML 2.0 entity ID [' . $idpentityid . ']');
 	}
 
-	$idpconfig = $casldapconfig[$idpentityid];
+	$casconfig = $casldapconfig[$idpentityid]['cas'];
+	$ldapconfig = $casldapconfig[$idpentityid]['ldap'];
+	
 	
 } catch (Exception $exception) {
 	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
@@ -61,13 +63,44 @@ function casValidate($cas) {
 		$ticket = urlencode($_GET['ticket']);
 	
 		#ini_set('default_socket_timeout', 15);
-		$result = file_get_contents($cas['validate'] . '?ticket=' . $ticket . '&service=' . urlencode($service) );
-		$res = preg_split("/\n/",$result);
-		
-		if (strcmp($res[0], "yes") == 0) {
-			return $res[1];
+
+		if (isset($cas['validate'])) { # cas v1 yes|no\r<username> style
+			$paramPrefix = strpos($cas['validate'], '?') ? '&' : '?';
+			$result = file_get_contents($cas['validate'] . $paramPrefix . 'ticket=' . $ticket . '&service=' . urlencode($service) );
+			$res = preg_split("/\n/",$result);
+			
+			if (strcmp($res[0], "yes") == 0) {
+				return array($res[1], array());
+			} else {
+				throw new Exception("Failed to validate CAS service ticket: $ticket");
+			}
+		} elseif (isset($cas['serviceValidate'])) { # cas v2 xml style
+			$paramPrefix = strpos($cas['serviceValidate'], '?') ? '&' : '?';
+
+			$result = file_get_contents($cas['serviceValidate'] . $paramPrefix . 'ticket=' . $ticket . '&service=' . urlencode($service) );
+
+			$dom = DOMDocument::loadXML($result);
+			$xPath = new DOMXpath($dom);
+			$xPath->registerNamespace("cas", 'http://www.yale.edu/tp/cas');
+			$success = $xPath->query("/cas:serviceResponse/cas:authenticationSuccess/cas:user");
+			if ($success->length == 0) {
+				$failure = $xPath->evaluate("/cas:serviceResponse/cas:authenticationFailure");
+				throw new Exception("Error when validating CAS service ticket: " . $failure->item(0)->textContent);
+			} else {
+				
+				$attributes = array();
+				if ($casattributes = $cas['attributes']) { # some has attributes in the xml - attributes is a list of XPath expressions to get them
+					foreach ($casattributes as $name => $query) {
+						$attrs = $xPath->query($query);
+						foreach ($attrs as $attrvalue) $attributes[$name][] = $attrvalue->textContent;
+					}
+				}
+				$casusername = $success->item(0)->textContent;
+				
+				return array($casusername, $attributes);
+			}
 		} else {
-			throw new Exception("Failed to validate CAS service ticket: $ticket");
+			throw new Exception("validate or serviceValidate not specified");
 		}
 	
 	/**
@@ -76,7 +109,6 @@ function casValidate($cas) {
 	} else {
 		SimpleSAML_Logger::info("AUTH - cas-ldap: redirecting to {$cas['login']}");
 		SimpleSAML_Utilities::redirect($cas['login'], array(
-			'renew' => 'true',
 			'service' => $service
 		));		
 	}
@@ -85,41 +117,19 @@ function casValidate($cas) {
 
 
 try {
-
-
-
-
-
+	
 	$relaystate = $_REQUEST['RelayState'];
 
-	$username = casValidate($idpconfig['cas']);
-	SimpleSAML_Logger::info('AUTH - cas-ldap: '. $username . ' authenticated by ' . $idpconfig['cas']['validate']);
-	
+	list($username, $casattributes) = casValidate($casconfig);
 	
-	
-	/*
-	 * Connecting to LDAP.
-	 */
-	$ldap = new SimpleSAML_Auth_LDAP($idpconfig['ldap']['servers'], $idpconfig['ldap']['enable_tls']);
-	
-	if ($idpconfig['ldap']['priv_user_dn']) {
-	
-		if (!$ldap->bind($idpconfig['ldap']['priv_user_dn'], $idpconfig['ldap']['priv_user_pw']) ) {
-			throw new Exception('Could not bind with system user: ' . $idpconfig['ldap']['priv_user_dn']);
-		}
-	}
-	
-	/*
-	 * Search for user in LDAP.
-	 */
-	$dn = $ldap->searchfordn($idpconfig['ldap']['searchbase'], $idpconfig['ldap']['searchattributes'], $username);
-	
-	/*
-	 * Retrieve attributes from LDAP
-	 */
-	$attributes = $ldap->getAttributes($dn, $idpconfig['ldap']['attributes']);
+	SimpleSAML_Logger::info('AUTH - cas-ldap: '. $username . ' authenticated by ' . $casconfig['validate']);
 
-	
+	$ldapattributes = array();
+	if ($ldapconfig['servers']) {
+		$ldap = new SimpleSAML_Auth_LDAP($ldapconfig['servers'], $ldapconfig['enable_tls']);
+		$ldapattributes = $ldap->validate($ldapconfig, $username);
+	}
+	$attributes = array_merge_recursive($casattributes, $ldapattributes);
 	$session->setAuthenticated(true, 'login-cas-ldap');
 	$session->setAttributes($attributes);
 	
-- 
GitLab