diff --git a/contrib/openldap/core-fd-conf.schema b/contrib/openldap/core-fd-conf.schema
index 0db3f0fdba060ea5bee1d18c10db851329b048c6..cff504d0596a1f59a0e7ac3073a803c7f3f1c1be 100644
--- a/contrib/openldap/core-fd-conf.schema
+++ b/contrib/openldap/core-fd-conf.schema
@@ -429,6 +429,41 @@ attributetype ( 1.3.6.1.4.1.38414.8.20.3 NAME 'fdSslCertPath'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
   SINGLE-VALUE)
 
+# CAS
+
+attributetype ( 1.3.6.1.4.1.38414.8.21.1 NAME 'fdCasActivated'
+  DESC 'FusionDirectory - CAS activation'
+  EQUALITY booleanMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+  SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.38414.8.21.2 NAME 'fdCasServerCaCertPath'
+  DESC 'FusionDirectory - CAS server CA certificate path'
+  EQUALITY caseExactIA5Match
+  SUBSTR caseExactIA5SubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE)
+
+attributetype ( 1.3.6.1.4.1.38414.8.21.3 NAME 'fdCasHost'
+  DESC 'FusionDirectory - CAS host'
+  EQUALITY caseExactIA5Match
+  SUBSTR caseExactIA5SubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE)
+
+attributetype ( 1.3.6.1.4.1.38414.8.21.4 NAME 'fdCasPort'
+  DESC 'FusionDirectory - CAS port'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE)
+
+attributetype ( 1.3.6.1.4.1.38414.8.21.5 NAME 'fdCasContext'
+  DESC 'FusionDirectory - CAS context'
+  EQUALITY caseExactIA5Match
+  SUBSTR caseExactIA5SubstringsMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE)
+
 # merged from dashboard-fd.schema - Needed by Fusion Directory for dashboard options
 
 attributetype ( 1.3.6.1.4.1.38414.27.1.1 NAME 'fdDashboardPrefix'
@@ -533,7 +568,8 @@ objectclass ( 1.3.6.1.4.1.38414.8.2.1 NAME 'fusionDirectoryConf'
     fdAclTabOnObjects $
     fdRfc2307bis $ fdCopyPaste $ fdSnapshotURI $
     fdSnapshotAdminDn $ fdSnapshotAdminPassword $ fdPersonalTitleInDN $ fdAccountRDN $
-    fdSslCaCertPath $ fdSslKeyPath $ fdSslCertPath
+    fdSslCaCertPath $ fdSslKeyPath $ fdSslCertPath $
+    fdCasActivated $ fdCasServerCaCertPath $ fdCasHost $ fdCasPort $ fdCasContext
   ) )
 
 objectclass ( 1.3.6.1.4.1.38414.8.2.2 NAME 'fusionDirectoryPluginsConf'
diff --git a/html/index.php b/html/index.php
index 4f2f6957cc255aaf343284d8fb4a4a3d128fb059..284e526ac7c828814836854824362b6b9e12b7fe 100644
--- a/html/index.php
+++ b/html/index.php
@@ -34,8 +34,8 @@ function displayLogin()
 
   error_reporting(E_ALL | E_STRICT);
   /* Fill template with required values */
-  $username = "";
-  if (isset($_POST["username"])) {
+  $username = '';
+  if (isset($_POST['username'])) {
     $username = trim($_POST['username']);
   }
   $smarty->assign ('date', gmdate("D, d M Y H:i:s"));
@@ -223,43 +223,22 @@ class Index {
     self::$password = NULL;
   }
 
-  /* Check LDAP connection */
-  static function checkLdapConnection()
-  {
-    global $config, $ldap;
-    $ldap = $config->get_ldap_link();
-    /* FIXME - The following line is needed to put objectClass list in cache otherwise schemaCheck fails but I don’t get why */
-    $ldap->get_objectclasses();
-    if (is_null($ldap) || (is_int($ldap) && $ldap == 0)) {
-      return msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class());
-    }
-    return TRUE;
-  }
-
   /* Runs schemaCheck if activated in configuration */
   static function runSchemaCheck()
   {
-    global $config, $ldap;
+    global $config;
     if ($config->get_cfg_value('schemaCheck') != 'TRUE') {
       return TRUE;
     }
-    $recursive  = ($config->get_cfg_value('ldapFollowReferrals') == 'TRUE');
-    $tls        = ($config->get_cfg_value('ldapTLS') == 'TRUE');
-    if (!count($ldap->get_objectclasses())) {
-      return _('Cannot detect information about the installed LDAP schema!');
-    } else {
-      $cfg = array();
-      $cfg['admin']       = $config->current['ADMINDN'];
-      $cfg['password']    = $config->current['ADMINPASSWORD'];
-      $cfg['connection']  = $config->current['SERVER'];
-      $cfg['tls']         = $tls;
-      $str = check_schema($cfg);
-      $checkarr = array();
-      foreach ($str as $tr) {
-        if (isset($tr['IS_MUST_HAVE']) && !$tr['STATUS']) {
-          // FIXME - Is that the correct error message?
-          return _('Your LDAP setup contains old schema definitions:').'<br/><br/><i>'.$tr['MSG'].'</i>';
-        }
+    $cfg = array();
+    $cfg['admin']       = $config->current['ADMINDN'];
+    $cfg['password']    = $config->current['ADMINPASSWORD'];
+    $cfg['connection']  = $config->current['SERVER'];
+    $cfg['tls']         = ($config->get_cfg_value('ldapTLS') == 'TRUE');
+    $str = check_schema($cfg);
+    foreach ($str as $tr) {
+      if (isset($tr['IS_MUST_HAVE']) && !$tr['STATUS']) {
+        return _('LDAP schema check reported errors:').'<br/><br/><i>'.$tr['MSG'].'</i>';
       }
     }
     return TRUE;
@@ -268,7 +247,8 @@ class Index {
   /* Check locking LDAP branch is here or create it */
   static function checkForLockingBranch()
   {
-    global $config,$ldap;
+    global $config;
+    $ldap = $config->get_ldap_link();
     $ldap->cat(get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE'], array('dn'));
     $attrs = $ldap->fetch();
     if (!count($attrs)) {
@@ -389,7 +369,6 @@ class Index {
 
     $success = self::runSteps(array(
       'validateUserInput',
-      'checkLdapConnection',
       'ldapLoginUser',
       'loginAndCheckExpired',
       'runSchemaCheck',
@@ -401,10 +380,66 @@ class Index {
       self::redirect();
     }
   }
+
+  /* All login steps in the right order for CAS login */
+  static function casLoginProcess()
+  {
+    global $config, $message;
+
+    self::init();
+
+    /* Reset error messages */
+    $message = '';
+
+    //~ phpCAS::setDebug();
+
+    // Initialize phpCAS
+    phpCAS::client(
+      CAS_VERSION_2_0,
+      $config->get_cfg_value('casHost', 'localhost'),
+      (int)($config->get_cfg_value('casPort', 443)),
+      $config->get_cfg_value('casContext', '/cas')
+    );
+
+    // Set the CA certificate that is the issuer of the cert
+    phpCAS::setCasServerCACert($config->get_cfg_value('casServerCaCertPath'));
+    //~ phpCAS::setNoCasServerValidation();
+
+    // force CAS authentication
+    phpCAS::forceAuthentication();
+    self::$username = phpCAS::getUser();
+    $ldap = $config->get_ldap_link();
+    $ldap->cd($config->current['BASE']);
+    $verify_attr = explode(',', $config->get_cfg_value('loginAttribute', 'uid'));
+    $filter = '';
+    foreach ($verify_attr as $attr) {
+      $filter .= '('.$attr.'='.self::$username.')';
+    }
+    $ldap->search('(&(|'.$filter.')(objectClass=inetOrgPerson))');
+    $ldap->fetch();
+    $ui = new userinfo($config, $ldap->getDn());
+
+    $success = self::runSteps(array(
+      'loginAndCheckExpired',
+      'runSchemaCheck',
+      'checkForLockingBranch',
+    ));
+
+    if ($success) {
+      /* Everything went well, redirect to main.php */
+      self::redirect();
+    }
+  }
 }
 
-/* Got a formular answer, validate and try to log in */
-if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['login'])) {
+if ($config->get_cfg_value('casActivated') == 'TRUE') {
+  require_once('CAS.php');
+  /* Move CAS autoload before FD autoload */
+  spl_autoload_unregister('CAS_autoload');
+  spl_autoload_register('CAS_autoload', TRUE, TRUE);
+  Index::casLoginProcess();
+} elseif ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['login'])) {
+  /* Got a formular answer, validate and try to log in */
   Index::fullLoginProcess();
 }
 
diff --git a/html/main.php b/html/main.php
index bcb65607127ee723eef2d8fc3a5134b396aaf9b1..88a6c53f5ad71a26fff8c320dbea5ce9f981614d 100644
--- a/html/main.php
+++ b/html/main.php
@@ -132,11 +132,11 @@ $plist->gen_menu();
 $smarty->assign("hideMenus", FALSE);
 if ($config->get_cfg_value("handleExpiredAccounts") == "TRUE") {
   $expired = $ui->expired_status();
-  if ($expired == POSIX_WARN_ABOUT_EXPIRATION && !session::is_set('POSIX_WARN_ABOUT_EXPIRATION__DONE')) {
-    @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $expired, "This user account (".$ui->username.") is about to expire");
+  if (($expired == POSIX_WARN_ABOUT_EXPIRATION) && !session::is_set('POSIX_WARN_ABOUT_EXPIRATION__DONE')) {
+    @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $expired, "This user account (".$ui->uid.") is about to expire");
 
     // The users password is about to xpire soon, display a warning message.
-    new log("security", "fusiondirectory", "", array(), "password for user '".$ui->username."' is about to expire");
+    new log("security", "fusiondirectory", "", array(), "password for user '".$ui->uid."' is about to expire");
     msg_dialog::display(_("Password change"), _("Your password is about to expire, please change your password!"), INFO_DIALOG);
     session::set('POSIX_WARN_ABOUT_EXPIRATION__DONE', TRUE);
   } elseif ($expired == POSIX_FORCE_PASSWORD_CHANGE) {
@@ -245,9 +245,9 @@ if (isset($plug)) {
 }
 
 if ($ui->ignore_acl_for_current_user()) {
-  $smarty->assign ("username", "<div style='color:#FF0000;'>"._("User ACL checks disabled")."</div>&nbsp;".$ui->username);
+  $smarty->assign ('username', '<div style="color:#FF0000;">'._('User ACL checks disabled').'</div>&nbsp;'.$ui->uid);
 } else {
-  $smarty->assign ("username", $ui->username);
+  $smarty->assign ('username', $ui->uid);
 }
 $smarty->assign ("menu", $plist->menu);
 $smarty->assign ("plug", "$plug");
diff --git a/include/class_userinfo.inc b/include/class_userinfo.inc
index 0572936de14e3a5d0bb4c85a4c5c5bd5993a212b..d98634da09ee1b9a771c771ca3e325ac597401c7 100644
--- a/include/class_userinfo.inc
+++ b/include/class_userinfo.inc
@@ -34,7 +34,6 @@ class userinfo
 {
   var $dn;
   var $ip;
-  var $username;
   var $cn;
   var $uid;
   var $gidNumber    = -1;
@@ -56,11 +55,13 @@ class userinfo
   {
     $this->config = &$config;
     $ldap = $this->config->get_ldap_link();
-    $ldap->cat($userdn, array('sn', 'givenName', 'uid', 'gidNumber', 'preferredLanguage'));
+    $ldap->cat($userdn, array('cn', 'sn', 'givenName', 'uid', 'gidNumber', 'preferredLanguage'));
     $attrs = $ldap->fetch();
 
-    if (isset($attrs['givenName'][0]) && isset($attrs['sn'][0])) {
-      $this->cn = $attrs['givenName'][0]." ".$attrs['sn'][0];
+    if (isset($attrs['cn'][0])) {
+      $this->cn = $attrs['cn'][0];
+    } elseif (isset($attrs['givenName'][0]) && isset($attrs['sn'][0])) {
+      $this->cn = $attrs['givenName'][0].' '.$attrs['sn'][0];
     } else {
       $this->cn = $attrs['uid'][0];
     }
diff --git a/include/functions.inc b/include/functions.inc
index 5b47912cc289d9f8c6cdcb50eba4ae626dd1d35e..99d550f16b769e5ba38a6275196ec488cfe76c4f 100644
--- a/include/functions.inc
+++ b/include/functions.inc
@@ -450,14 +450,14 @@ function fusiondirectory_log ($message)
   global $ui;
 
   /* Preset to something reasonable */
-  $username = "[unauthenticated]";
+  $username = '[unauthenticated]';
 
   /* Replace username if object is present */
   if (isset($ui)) {
-    if ($ui->username != "") {
-      $username = "[$ui->username]";
+    if ($ui->uid != '') {
+      $username = '['.$ui->uid.']';
     } else {
-      $username = "[unknown]";
+      $username = '[unknown]';
     }
   }
 
@@ -527,10 +527,10 @@ function ldap_login_user ($username, $password)
   }
 
   $ldap->cd($config->current['BASE']);
-  $allowed_attributes = array("uid","mail");
+  $allowed_attributes = array('uid','mail');
   $verify_attr = array();
-  if ($config->get_cfg_value("loginAttribute") != "") {
-    $tmp = explode(",", $config->get_cfg_value("loginAttribute"));
+  if ($config->get_cfg_value('loginAttribute') != '') {
+    $tmp = explode(',', $config->get_cfg_value('loginAttribute'));
     foreach ($tmp as $attr) {
       if (in_array($attr, $allowed_attributes)) {
         $verify_attr[] = $attr;
@@ -539,15 +539,15 @@ function ldap_login_user ($username, $password)
   }
 
   if (count($verify_attr) == 0) {
-    $verify_attr = array("uid");
+    $verify_attr = array('uid');
   }
   $tmp    = $verify_attr;
-  $tmp[]  = "uid";
-  $filter = "";
+  $tmp[]  = 'uid';
+  $filter = '';
   foreach ($verify_attr as $attr) {
-    $filter .= "(".$attr."=".$username.")";
+    $filter .= '('.$attr.'='.$username.')';
   }
-  $filter = "(&(|".$filter.")(objectClass=inetOrgPerson))";
+  $filter = '(&(|'.$filter.')(objectClass=inetOrgPerson))';
   $ldap->search($filter, $tmp);
 
   /* get results, only a count of 1 is valid */
@@ -580,7 +580,6 @@ function ldap_login_user ($username, $password)
 
   /* got user dn, fill acl's */
   $ui = new userinfo($config, $ldap->getDN());
-  $ui->username = $attrs['uid'][0];
 
   /* password check, bind as user with supplied password  */
   $ldap->disconnect();
diff --git a/plugins/config/class_configInLdap.inc b/plugins/config/class_configInLdap.inc
index ee81dae3bfd620ab69437b28d17113d5308b1585..9b343f224f946fc2b15f4686e7c9ff0254dbb552 100644
--- a/plugins/config/class_configInLdap.inc
+++ b/plugins/config/class_configInLdap.inc
@@ -250,6 +250,36 @@ class configInLdap extends simplePlugin
           ),
         )
       ),
+      'cas' => array(
+        'name'  => _('CAS'),
+        'attrs' => array(
+          new BooleanAttribute (
+            _('Enable CAS'), _('CAS login will be used instead of LDAP bind'),
+            'fdCasActivated', FALSE,
+            FALSE
+          ),
+          new StringAttribute (
+            _('CA certificate path'), _('Path to the CA certificate of the CAS server'),
+            'fdCasServerCaCertPath', FALSE,
+            '/etc/ssl/certs/ca.cert'
+          ),
+          new StringAttribute (
+            _('Host'), _('Host of the CAS server'),
+            'fdCasHost', FALSE,
+            'localhost'
+          ),
+          new IntAttribute (
+            _('Port'), _('Port the CAS server is listening on'),
+            'fdCasPort', FALSE,
+            0 /*min*/, FALSE /*no max*/, 443
+          ),
+          new StringAttribute (
+            _('CAS context'), _('CAS context to be used'),
+            'fdCasContext', FALSE,
+            '/cas'
+          ),
+        )
+      ),
       'people_and_group' => array(
         'name'  => _('People and group storage'),
         'class' => array('critical'),
@@ -471,6 +501,18 @@ class configInLdap extends simplePlugin
         )
       )
     );
+    $this->attributesAccess['fdCasActivated']->setManagedAttributes(
+      array(
+        'disable' => array (
+          FALSE => array (
+            'fdCasServerCaCertPath',
+            'fdCasHost',
+            'fdCasPort',
+            'fdCasContext',
+          )
+        )
+      )
+    );
   }
 
   function compute_dn()
diff --git a/setup/class_setupStep_Finish.inc b/setup/class_setupStep_Finish.inc
index 3c3b0252760bd03d76c8fe5a97a0418b6d5a0a18..4e7b06dba5bf22ce8081e23484bb0ac5e23dd3c5 100644
--- a/setup/class_setupStep_Finish.inc
+++ b/setup/class_setupStep_Finish.inc
@@ -66,8 +66,7 @@ class Step_Finish extends setupStep
     /* Create ui object */
 
     /* got user dn, fill acl's */
-    $ui           = new userinfo($config, $cv['valid_admin']);
-    $ui->username = 'fd-admin';
+    $ui = new userinfo($config, $cv['valid_admin']);
     /* Username is set, load subtreeACL's now */
     $ui->loadACL();