diff -rbup mantis/config_defaults_inc.php mantis-cas/config_defaults_inc.php
--- mantis/config_defaults_inc.php	2007-10-24 07:35:38.000000000 +0200
+++ mantis-cas/config_defaults_inc.php	2007-11-28 15:05:05.000000000 +0100
@@ -873,6 +873,22 @@
 	$g_hr_width				= 50;
 
 	#############################
+	# Mantis CAS Settings
+	#############################
+
+	# --- using phpCAS -------------
+	$g_cas_server = 'example.com.au';
+	$g_cas_port = 443;
+	$g_cas_uri = '';             # e.g. '/cas'
+	$g_cas_version = '2.0';
+	# --- CAS + LDAP -------------
+	$g_cas_use_ldap     = OFF;   # translate CAS username through LDAP
+	$g_ldap_mantis_uid  = 'uid'; # The LDAP field matching the Mantis username
+	$g_cas_ldap_update  = OFF;   # Should we update user details from LDAP?
+	$g_cas_ldap_update_fields = ''; # e.g. 'cn,userpassword'
+	$g_cas_ldap_update_map    = ''; # e.g. 'realname,password'
+
+	#############################
 	# Mantis LDAP Settings
 	#############################
 
@@ -1147,7 +1163,7 @@
 	$g_set_status_threshold = array();
 
 	# --- login method ----------------
-	# CRYPT or PLAIN or MD5 or LDAP or BASIC_AUTH
+	# CRYPT or PLAIN or MD5 or LDAP or BASIC_AUTH or CAS_AUTH
 	# You can simply change this at will. Mantis will try to figure out how the passwords were encrypted.
 	$g_login_method				= MD5;
 
diff -rbup mantis/core/authentication_api.php mantis-cas/core/authentication_api.php
--- mantis/core/authentication_api.php	2007-11-21 16:19:41.000000000 +0100
+++ mantis-cas/core/authentication_api.php	2007-11-28 15:15:03.000000000 +0100
@@ -23,6 +23,171 @@
 
 	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'gpc_api.php' );
 
+	# --------------------
+	# PHP4 hack
+	# --------------------
+	if(!function_exists('array_combine')) {
+		function array_combine($keys, $values) {
+			if(count($keys) < 1 || count($keys) != count($values) || !is_array($keys) || !is_array($values)) {
+				return false;
+			}
+
+			$keys = array_values($keys);
+			$values = array_values($values);
+			for($x=0; $x < count($keys); $x++) {
+				$return_array[$keys[$x]] = $values[$x];
+			}
+
+			return $return_array;
+		}
+	}
+
+    ## CAS functions and settings
+    
+    # --------------------
+    # Initializes phpCAS
+    #
+    function auth_cas_init() {
+        # phpCAS must be installed
+        require_once('CAS/CAS.php');
+    
+        static $s_initialized=false;
+        
+        if (! $s_initialized ) {
+            phpCAS::setDebug();
+            ## These should be set in config_inc.php
+            ## $g_login_method = CAS_AUTH;
+            $t_server_version = config_get( 'cas_version' );
+            $t_server_cas_server = config_get( 'cas_server' );
+            $t_server_port = config_get( 'cas_port' );
+            $t_server_uri = config_get( 'cas_uri' );
+            $t_start_session = (boolean)FALSE; # Mantis takes care of its own session
+            
+            phpCAS::client($t_server_version, $t_server_cas_server, $t_server_port, $t_server_uri, $t_start_session);
+            
+            $s_initialized = true;
+        }
+    
+    }
+
+
+    # --------------------
+    # Fetches the user's CAS name, authenticating if needed
+    # Can translate name through LDAP
+    #
+    function auth_cas_get_name()
+    {
+        # Get CAS username from phpCAS
+        auth_cas_init();
+        phpCAS::forceAuthentication();
+        $t_cas_id =  phpCAS::getUser();
+
+        # If needed, translate the CAS username through LDAP        
+        $t_username = $t_cas_id;
+        if (config_get( 'cas_use_ldap', false )) {
+            $t_username = auth_cas_ldap_translate( $t_cas_id );
+        }        
+        return $t_username;
+    }
+
+
+    # --------------------
+    # Takes an ID string, and looks up the LDAP directory to find
+    # the matching username for Mantis.
+    #
+    # Optionally, also update the user information in the Mantis user
+    # table.
+    #
+    # @param $p_cas_id [STRING] Typically, the username given by phpCAS
+    # @param $p_update_user [BOOLEAN] Whether or not to update user details from LDAP
+    #
+    function auth_cas_ldap_translate( $p_cas_id, $p_update_user='' )
+    {
+        # Please make sure the Mantis CAS and LDAP settings are set in config_inc.php
+        
+	$t_ldap_organization = config_get( 'ldap_organization' );
+	$t_ldap_root_dn	= config_get( 'ldap_root_dn' );
+		
+        # Required fields in LDAP for CAS
+	$t_ldap_uid_field = config_get( 'cas_ldap_uid_field', 'uid' ) ;
+	$t_ldap_mantis_uid = config_get( 'ldap_mantis_uid', 'uid' );
+        $t_ldap_required = array( $t_ldap_uid_field, $t_ldap_mantis_uid, 'dn' );
+        $t_ldap_required = array_combine( $t_ldap_required, $t_ldap_required );
+
+	# User-defined fields to fetch from LDAP...
+        $t_ldap_fields = explode( ',', config_get( 'cas_ldap_update_fields' ) );
+        $t_ldap_fields = array_combine( $t_ldap_fields, $t_ldap_fields );
+        # ...which are mapped to Mantis user fields
+        $t_ldap_map = explode( ',', config_get( 'cas_ldap_update_map' ) );
+        $t_ldap_map = array_combine( $t_ldap_map, $t_ldap_map );
+
+        # Build LDAP search filter, attribute list from CAS ID
+	$t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$p_cas_id))";
+	$t_search_attrs = array_values($t_ldap_required + $t_ldap_fields);  # array union
+
+        # Use Mantis ldap_api to connect to LDAP
+        $t_ds = ldap_connect_bind();
+	$t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs );
+	$t_info	= ldap_get_entries( $t_ds, $t_sr );
+	# Parse the LDAP entry to find the Mantis username
+        if ( $t_info ) {
+            # Get Mantis username
+            $t_username = $t_info[0][$t_ldap_mantis_uid][0];
+            
+            # @@@ The fact that we got here means the user is authenticated
+            # @@@ by CAS, and has an LDAP entry.
+            # @@@ We might as well update other user details since we are here.
+
+            # If no argument given, check settings
+            if ( '' == $p_update_user ) {
+                $p_update_user = config_get( 'cas_ldap_update', FALSE );
+            }
+            # If there's a user record, then update it
+            if ( $p_update_user ) {
+                # Only proceed if the field map arrays are the same length
+                $t_field_map = array_combine( $t_ldap_fields, $t_ldap_map );
+                if ($t_field_map) {
+                    # If user is new, then we must create their account before updating it
+                    # @@@ ( make sure $g_allow_blank_email == ON )
+                    $t_userid = user_get_id_by_name($t_username);
+                    if ( false == $t_userid ) {
+                        user_create( $t_username, '' );
+                        # @@@ Wow, this is pretty lame
+                        $t_userid = user_get_id_by_name($t_username);                        
+                    }
+                    # @@@ maybe we can optimize this to write all fields at once?
+                    foreach ( $t_field_map as $key=>$t_userfield ) {
+                        if (isset($t_info[0][$key][0])) {
+                            user_set_field( $t_userid, $t_userfield, $t_info[0][$key][0] );
+                        }
+                    }
+                }
+            }
+            
+        }
+        ldap_free_result( $t_sr );
+        ldap_unbind( $t_ds );
+        
+        return $t_username;
+    }
+
+    
+    # --------------------
+    # Logs out of CAS, redirecting to Mantis on re-login
+    # User should already be logged out of Mantis by the time this is called
+    # (see auth_logout)
+    #
+    function auth_cas_logout()
+    {
+        $t_path = config_get('path');
+        
+        auth_cas_init();
+        phpCAS::logout($t_path);
+    }
+
+
+
+
 	### Authentication API ###
 
 	$g_script_login_cookie = null;
@@ -81,9 +246,11 @@
 
 		$t_login_method = config_get( 'login_method' );
 
+        # @@@ added by Joshua: CAS_AUTH
 		if ( false === $t_user_id ) {
-			if ( BASIC_AUTH == $t_login_method ) {
-				# attempt to create the user if using BASIC_AUTH
+			if ( in_array( $t_login_method, array( BASIC_AUTH, CAS_AUTH ) ) ) {
+				# attempt to create the user if using BASIC_AUTH or CAS_AUTH
+                # ( make sure $g_allow_blank_email == ON )
 				$t_cookie_string = user_create( $p_username, $p_password );
 
 				if ( false === $t_cookie_string ) {
@@ -194,6 +361,13 @@
         if (auth_clear_cookies()) {
             helper_clear_pref_cookies();
         }
+
+    	# @@@ added by Joshua
+    	if ( CAS_AUTH == config_get( 'login_method' ) ) {
+            # Redirect to CAS page to logout
+            auth_cas_logout();
+    	}
+
 		return true;
 	}
 
@@ -207,11 +381,24 @@
 	function auth_does_password_match( $p_user_id, $p_test_password ) {
 		$t_configured_login_method = config_get( 'login_method' );
 
+        # @@@ added by Joshua
+        if ( CAS_AUTH == $t_configured_login_method ) {
+            # CAS takes care of password verification for us
+            return true;
+        }
+
 		if ( LDAP == $t_configured_login_method ) {
 			return ldap_authenticate( $p_user_id, $p_test_password );
 		}
 
 		$t_password			= user_get_field( $p_user_id, 'password' );
+		# @@@ added by Joshua
+		# Allow for packed MD5 passwords
+        if (substr($t_password, 0, 5) == '{MD5}') {
+            # Unpack the stored password into MD5 for comparison
+            $temp = unpack('H*', base64_decode( substr( $t_password, 5 ) ));
+            $t_password = $temp[1];
+        }
 		$t_login_methods	= Array(MD5, CRYPT, PLAIN);
 		foreach ( $t_login_methods as $t_login_method ) {
 
diff -rbup mantis/core/constant_inc.php mantis-cas/core/constant_inc.php
--- mantis/core/constant_inc.php	2007-10-14 00:35:18.000000000 +0200
+++ mantis-cas/core/constant_inc.php	2007-11-27 16:45:49.000000000 +0100
@@ -116,6 +116,7 @@
 	define( 'LDAP',				4 );
 	define( 'BASIC_AUTH',		5 );
 	define( 'HTTP_AUTH',		6 );
+	define( 'CAS_AUTH',         7 );
 
 	# file upload methods
 	define( 'DISK',			1 );
diff -rbup mantis/core/ldap_api.php mantis-cas/core/ldap_api.php
--- mantis/core/ldap_api.php	2007-11-21 16:08:26.000000000 +0100
+++ mantis-cas/core/ldap_api.php	2007-11-27 16:51:30.000000000 +0100
@@ -28,8 +28,10 @@
  	# --------------------
 	# Connect and bind to the LDAP directory
 	function ldap_connect_bind( $p_binddn = '', $p_password = '' ) {
+		# @@@ added by Joshua: ldap_ver
 		$t_ldap_server	= config_get( 'ldap_server' );
 		$t_ldap_port	= config_get( 'ldap_port' );
+		$t_ldap_ver	= config_get( 'ldap_ver', 3 );
 
 		if (!extension_loaded('ldap')) {
 			trigger_error(ERROR_LDAP_EXTENSION_NOT_LOADED,ERROR);
@@ -37,6 +39,7 @@
 		
 		$t_ds = @ldap_connect ( $t_ldap_server, $t_ldap_port );
 		if ( $t_ds > 0 ) {
+			ldap_set_option($t_ds, LDAP_OPT_PROTOCOL_VERSION, $t_ldap_ver);
 			$t_protocol_version = config_get( 'ldap_protocol_version' );
 
 			if ( $t_protocol_version > 0 ) {
diff -rbup mantis/login_page.php mantis-cas/login_page.php
--- mantis/login_page.php	2007-11-21 16:21:09.000000000 +0100
+++ mantis-cas/login_page.php	2007-11-27 16:45:49.000000000 +0100
@@ -35,8 +35,9 @@
 	$f_return		= gpc_get_string( 'return', '' );
 
 	# Check for HTTP_AUTH. HTTP_AUTH is handled in login.php
-
-	if ( HTTP_AUTH == config_get( 'login_method' ) ) {
+	# And now CAS_AUTH too -- Joshua
+	if ( in_array(config_get( 'login_method' ), array( HTTP_AUTH, CAS_AUTH )) )
+	{
 		$t_uri = "login.php";
 
 		if ( !$f_return && ON == config_get( 'allow_anonymous_login' ) ) {
diff -rbup mantis/login.php mantis-cas/login.php
--- mantis/login.php	2007-10-14 00:33:18.000000000 +0200
+++ mantis-cas/login.php	2007-11-27 16:45:49.000000000 +0100
@@ -33,12 +33,19 @@
 	$f_return		= gpc_get_string( 'return', config_get( 'default_home_page' ) );
 	$f_from			= gpc_get_string( 'from', '' );
 
-	if ( BASIC_AUTH == config_get( 'login_method' ) ) {
+    // Added by Joshua (17 October 2006)
+    if ( CAS_AUTH == config_get( 'login_method' ) ) {
+        // This will detour to the CAS login page if needed
+        $f_username = auth_cas_get_name();
+        $f_password = '';
+    }
+
+	else if ( BASIC_AUTH == config_get( 'login_method' ) ) {
 		$f_username = $_SERVER['REMOTE_USER'];
 		$f_password = $_SERVER['PHP_AUTH_PW'];
  	}
 
-	if ( HTTP_AUTH == config_get( 'login_method' ) ) {
+	else if ( HTTP_AUTH == config_get( 'login_method' ) ) {
 		if ( !auth_http_is_logout_pending() )
 		{
 			if ( isset( $_SERVER['PHP_AUTH_USER'] ) )
