From 9a012b3efb0908fb6f7afabfcbd027765bd339b1 Mon Sep 17 00:00:00 2001
From: Carl Denis <c.denis@mrduck.fr>
Date: Fri, 10 Feb 2012 19:44:42 +0100
Subject: [PATCH] first version of the dual auth module

---
 framework/Auth/lib/Horde/Auth/Dual.php         |   69 ++++++++++++++++++++++++
 framework/Core/lib/Horde/Core/Auth/Dual.php    |   48 ++++++++++++++++
 framework/Core/lib/Horde/Core/Factory/Auth.php |    9 +++
 3 files changed, 126 insertions(+), 0 deletions(-)
 create mode 100644 framework/Auth/lib/Horde/Auth/Dual.php
 create mode 100644 framework/Core/lib/Horde/Core/Auth/Dual.php

diff --git a/framework/Auth/lib/Horde/Auth/Dual.php b/framework/Auth/lib/Horde/Auth/Dual.php
new file mode 100644
index 0000000..ec9c502
--- /dev/null
+++ b/framework/Auth/lib/Horde/Auth/Dual.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * The Horde_Auth_Dual class provides a way to combine two separate
+ * authentication modules by having one or both validate the login.
+ *
+ * Copyright 2002-2011 Horde LLC (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did
+ * not receive this file, http://www.horde.org/licenses/lgpl21
+ *
+ * @author   Carl Denis <c.denis@mrduck.fr>
+ * @category Horde
+ * @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
+ * @package  Auth
+ */
+class Horde_Auth_Dual extends Horde_Auth_Base
+{
+    /**
+     * Constructor.
+     *
+     * @param array $params  Required parameters:
+     * <pre>
+     * 'auth1_driver' - (Horde_Auth_Base) The admin driver.
+     * 'auth2_driver' - (Horde_Auth_Base) The auth driver.
+     * 'single_validation' - (Boolean) Whether one positive auth is sufficient
+     *                      DEFAULT: true
+     * </pre>
+     *
+     * @throws InvalidArgumentException
+     */
+    public function __construct(array $params = array())
+    {
+        foreach (array('auth1_driver', 'auth2_driver') as $val) {
+            if (!isset($params[$val])) {
+                throw new InvalidArgumentException('Missing ' . $val . ' parameter.');
+            }
+        }
+
+        if( !isset($params['single_validation']) ||
+            !(($params['single_validation'] !== true || $params['single_validation'] !== false))) {
+            $params = array_merge( array('single_validation' => true), $params);
+        }
+
+        parent::__construct($params);
+    }
+
+    /**
+     * Find out if a set of login credentials are valid.
+     *
+     * @param string $userId      The userId to check.
+     * @param array $credentials  The credentials to use.
+     *
+     * @throws Horde_Auth_Exception
+     */
+    protected function _authenticate($userId, $credentials)
+    {
+        if( !$this->_params['single_validation'] && (
+            !$this->_params['auth1_driver']->authenticate($userId, $credentials) ||
+            !$this->_params['auth2_driver']->authenticate($userId, $credentials))) {
+                throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
+            }
+
+        if(  $this->_params['single_validation'] && (
+            !$this->_params['auth1_driver']->authenticate($userId, $credentials) &&
+            !$this->_params['auth2_driver']->authenticate($userId, $credentials))) {
+                throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN);
+            }
+    }
+}
diff --git a/framework/Core/lib/Horde/Core/Auth/Dual.php b/framework/Core/lib/Horde/Core/Auth/Dual.php
new file mode 100644
index 0000000..17ed657
--- /dev/null
+++ b/framework/Core/lib/Horde/Core/Auth/Dual.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * The Horde_Core_Auth_Dual class provides Horde-specific functions
+ * on top of the base dual driver.
+ *
+ * Copyright 2011 Horde LLC (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did
+ * not receive this file, see http://opensource.org/licenses/lgpl-2.1.php
+ *
+ * @author   Carl Denis <c.denis@mrduck.fr>
+ * @category Horde
+ * @license  http://opensource.org/licenses/lgpl-2.1.php LGPL
+ * @package  Core
+ */
+class Horde_Core_Auth_Dual extends Horde_Auth_Dual
+{
+    /**
+     * Returns information on what login parameters to display on the login
+     * screen.
+     *
+     * @see Horde_Core_Auth_Application::getLoginParams()
+     *
+     * @throws Horde_Exception
+     */
+    public function getLoginParams()
+    {
+        $params = array();
+
+        if (method_exists($this->_params['auth1_driver'], 'getLoginParams')) {
+            $params = array_merge($this->_params['auth1_driver']->getLoginParams(),$params);
+        }
+        if (method_exists($this->_params['auth2_driver'], 'getLoginParams')) {
+            $params = array_merge($this->_params['auth2_driver']->getLoginParams(),$params);
+        }
+
+        if(!empty($params)) {
+            return $params;
+        }
+
+        return array(
+            'js_code' => array(),
+            'js_files' => array(),
+            'params' => array()
+        );
+    }
+
+}
diff --git a/framework/Core/lib/Horde/Core/Factory/Auth.php b/framework/Core/lib/Horde/Core/Factory/Auth.php
index 7ff45b9..bc30267 100644
--- a/framework/Core/lib/Horde/Core/Factory/Auth.php
+++ b/framework/Core/lib/Horde/Core/Factory/Auth.php
@@ -88,6 +88,8 @@ class Horde_Core_Factory_Auth extends Horde_Core_Factory_Base
             $driver = 'Http_Remote';
         } elseif (strcasecmp($driver, 'composite') === 0) {
             $driver = 'Horde_Core_Auth_Composite';
+        } elseif (strcasecmp($driver, 'dual') === 0) {
+            $driver = 'Horde_Core_Auth_Dual';
         } elseif (strcasecmp($driver, 'ldap') === 0) {
             $driver = 'Horde_Core_Auth_Ldap';
         } elseif (strcasecmp($driver, 'msad') === 0) {
@@ -111,6 +113,13 @@ class Horde_Core_Factory_Auth extends Horde_Core_Factory_Base
             $params['auth_driver'] = $this->_create($params['auth_driver']['driver'], $params['auth_driver']['params']);
             break;
 
+        case 'horde_core_auth_dual':
+            if(!empty($params['auth1_driver']['driver']))
+                $params['auth1_driver'] = $this->_create($params['auth1_driver']['driver'], $params['auth1_driver']['params']);
+            if(!empty($params['auth2_driver']['driver']))
+                $params['auth2_driver'] = $this->_create($params['auth2_driver']['driver'], $params['auth2_driver']['params']);
+            break;
+
         case 'cyrsql':
             $imap_config = array(
                 'hostspec' => empty($params['cyrhost']) ? null : $params['cyrhost'],
-- 
1.7.8.3