From 4d83cb804e9a5371745a8c6a7f0069d2e86b7126 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Thu, 27 Mar 2008 15:33:34 +0000
Subject: [PATCH] Added support for Auth MemCookie.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@451 44740490-163a-0410-bde0-09ae8108e29a
---
 config-templates/authmemcookie.php |  69 ++++++++++++++
 config-templates/config.php        |   3 +-
 dictionaries/errors.php            |   7 ++
 extra/auth_memcookie.conf          |  38 ++++++++
 lib/SimpleSAML/AuthMemCookie.php   | 146 +++++++++++++++++++++++++++++
 www/authmemcookie.php              | 105 +++++++++++++++++++++
 6 files changed, 367 insertions(+), 1 deletion(-)
 create mode 100644 config-templates/authmemcookie.php
 create mode 100644 extra/auth_memcookie.conf
 create mode 100644 lib/SimpleSAML/AuthMemCookie.php
 create mode 100644 www/authmemcookie.php

diff --git a/config-templates/authmemcookie.php b/config-templates/authmemcookie.php
new file mode 100644
index 000000000..fa3e4a9de
--- /dev/null
+++ b/config-templates/authmemcookie.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * This is the configuration file for the Auth MemCookie example.
+ */
+
+$config = array(
+
+	/*
+	 * This is the name of the cookie we should save the session id in. The value of this option must match the
+	 * Auth_memCookie_CookieName option in the Auth MemCookie configuration. The default value is 'AuthMemCookie'.
+	 *
+	 * Default:
+	 *  'cookiename' => 'AuthMemCookie',
+	 */
+	'cookiename' => 'AuthMemCookie',
+
+	/*
+	 * This option specifies the name of the attribute which contains the username of the user. It must be set to
+	 * a valid attribute name.
+	 *
+	 * Examples:
+	 *  'username' => 'uid', // LDAP attribute for user id.
+	 *  'username' => 'mail', // LDAP attribute for email address.
+	 *
+	 * Default:
+	 *  No default value.
+	 */
+	'username' => NULL,
+
+	/*
+	 * This option specifies the name of the attribute which contains the groups of the user. Set this option to
+	 * NULL if you don't want to include any groups.
+	 *
+	 * Example:
+	 *  'groups' => 'edupersonaffiliation',
+	 *
+	 * Default:
+	 *  'groups' => NULL,
+	 */
+	'groups' => NULL,
+
+	/*
+	 * This option contains the hostname of IP address of the memcache server where we should store the
+	 * authentication information. Thos option should match the address part of the
+	 * Auth_memCookie_Memcached_AddrPort option in the Auth MemCookie configuration.
+	 *
+	 * Examples:
+	 *  'memcache.host' => '192.168.93.52',
+	 *  'memcache.host' => 'memcache.example.org',
+	 *
+	 * Default:
+	 *  'memcache.host' => '127.0.0.1',
+	 */
+	'memcache.host' => '127.0.0.1',
+
+	/*
+	 * This option contains the port number of the memcache server where we should store the
+	 * authentication information. Thos option should match the port part of the
+	 * Auth_memCookie_Memcached_AddrPort option in the Auth MemCookie configuration.
+	 *
+	 * Default:
+	 *  'memcache.port' => 11211,
+	 */
+	'memcache.port' => 11211,
+
+);
+
+?>
\ No newline at end of file
diff --git a/config-templates/config.php b/config-templates/config.php
index 6b67ad173..53901fba8 100644
--- a/config-templates/config.php
+++ b/config-templates/config.php
@@ -98,7 +98,8 @@ $config = array (
 	'enable.shib13-sp'		=> false,
 	'enable.shib13-idp'		=> false,
 	'enable.openid-provider'=> false,
-	
+	'enable.authmemcookie' => false,
+
 	/* 
 	 * This value is the duration of the session in seconds. Make sure that the time duration of
 	 * cookies both at the SP and the IdP exceeds this duration.
diff --git a/dictionaries/errors.php b/dictionaries/errors.php
index 18c61d9a6..eed068e44 100644
--- a/dictionaries/errors.php
+++ b/dictionaries/errors.php
@@ -337,4 +337,11 @@ $lang = array(
 		'de' => 'Fehler bei der Kommunikation mit dem CAS Server.',
 	),
 
+	'title_CONFIG' => array(
+		'en' => 'Configuration error',
+	),
+	'descr_CONFIG' => array(
+		'en' => 'simpleSAMLphp appears to be misconfigured.',
+	),
+
 );
\ No newline at end of file
diff --git a/extra/auth_memcookie.conf b/extra/auth_memcookie.conf
new file mode 100644
index 000000000..77e5e12a0
--- /dev/null
+++ b/extra/auth_memcookie.conf
@@ -0,0 +1,38 @@
+<Location />
+        # This is a list of memcache servers which Auth MemCookie
+        # should use. It is a ','-separated list of
+        # host:port-pairs.
+        # Note that this list must list the same servers as the
+        # 'authmemcookie.servers'-option in config.php in the
+        # configuration for simpleSAMLphp.
+        Auth_memCookie_Memcached_AddrPort "127.0.0.1:11211"
+
+        # This must be set to 'on' to enable Auth MemCookie for
+        # this directory.
+        Auth_memCookie_Authoritative on
+
+        # This adjusts the maximum number of data elements in the
+        # session data. The default is 10, which can be to low.
+        Auth_memCookie_SessionTableSize "40"
+
+        # These two commands are required to enable access control
+        # in Apache.
+        AuthType Cookie
+        AuthName "My Login"
+
+        # This command causes apache to redirect to the given
+        # URL when we receive a '401 Authorization Required'
+        # error. We redirect to "/openssophp/spSSOInit.php",
+        # which initializes a login to the IdP.
+        ErrorDocument 401 "/simplesaml/authmemcookie.php"
+
+</Location>
+
+<Location /secret>
+        # This allows all authenticated users to access the
+        # directory. To learn more about the 'Require' command,
+        # please look at:
+        # http://httpd.apache.org/docs/2.0/mod/core.html#require
+        Require valid-user
+</Location>
+
diff --git a/lib/SimpleSAML/AuthMemCookie.php b/lib/SimpleSAML/AuthMemCookie.php
new file mode 100644
index 000000000..a316041d9
--- /dev/null
+++ b/lib/SimpleSAML/AuthMemCookie.php
@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * This is a helper class for the Auth MemCookie module.
+ * It handles the configuration, and implements the logout handler.
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class SimpleSAML_AuthMemCookie {
+
+	/**
+	 * This is the singleton instance of this class.
+	 */
+	private static $instance = NULL;
+
+
+	/**
+	 * The configuration for Auth MemCookie.
+	 */
+	private $amcConfig;
+
+	/**
+	 * This function is used to retrieve the singleton instance of this class.
+	 *
+	 * @return The singleton instance of this class.
+	 */
+	public static function getInstance() {
+		if(self::$instance === NULL) {
+			self::$instance = new SimpleSAML_AuthMemCookie();
+		}
+
+		return self::$instance;
+	}
+
+
+	/**
+	 * This function implements the constructor for this class. It loads the Auth MemCookie configuration.
+	 */
+	private function __construct() {
+		/* Load Auth MemCookie configuration. */
+		$globalConfig = SimpleSAML_Configuration::getInstance();
+		SimpleSAML_Configuration::init($GLOBALS['configdir'], 'authmemcookie', 'authmemcookie.php');
+		$this->amcConfig = SimpleSAML_Configuration::getInstance('authmemcookie');
+	}
+
+
+	/**
+	 * This function retrieves the name of the cookie from the configuration.
+	 *
+	 * @return The name of the cookie.
+	 */
+	public function getCookieName() {
+		$cookieName = $this->amcConfig->getValue('cookiename', 'AuthMemCookie');
+		if(!is_string($cookieName) || strlen($cookieName) === 0) {
+			throw new Exception('Configuration option \'cookiename\' contains an invalid value. This option should be a string.');
+		}
+
+		return $cookieName;
+	}
+
+
+	/**
+	 * This function retrieves the name of the attribute which contains the username from the configuration.
+	 *
+	 * @return The name of the attribute which contains the username.
+	 */
+	public function getUsernameAttr() {
+		$usernameAttr = $this->amcConfig->getValue('username');
+		if($usernameAttr === NULL) {
+			throw new Exception('Missing required configuration option \'username\' in authmemcookie.php.');
+		}
+
+		return $usernameAttr;
+	}
+
+
+	/**
+	 * This function retrieves the name of the attribute which contains the groups from the configuration.
+	 *
+	 * @return The name of the attribute which contains the groups.
+	 */
+	public function getGroupsAttr() {
+		$groupsAttr = $this->amcConfig->getValue('groups');
+
+		return $groupsAttr;
+	}
+
+
+	/**
+	 * This function creates and initializes a Memcache object from our configuration.
+	 *
+	 * @return A Memcache object initialized from our configuration.
+	 */
+	public function getMemcache() {
+
+		$memcacheHost = $this->amcConfig->getValue('memcache.host', '127.0.0.1');
+		if(!is_string($memcacheHost)) {
+			throw new Exception('Invalid value of the \'memcache.host\' configuration option. This option' .
+					    ' should be a string with a hostname or a string with an IP address.');
+		}
+
+		$memcachePort = $this->amcConfig->getValue('memcache.port', 11211);
+		if(!is_int($memcachePort)) {
+			throw new Exception('Invalid value of the \'memcache.port\' configuration option. This option' .
+					    ' should be an integer.');
+		}
+
+		$memcache = new Memcache;
+		$memcache->connect($memcacheHost, $memcachePort);
+
+		return $memcache;
+	}
+
+
+	/**
+	 * This function logs the user out by deleting the session information from memcache.
+	 */
+	private function doLogout() {
+
+		$cookieName = $this->getCookieName();
+
+		/* Check if we have a valid cookie. */
+		if(!array_key_exists($cookieName, $_COOKIE)) {
+			return;
+		}
+
+		$sessionID = $_COOKIE[$cookieName];
+
+		/* Delete the session from memcache. */
+
+		$memcache = $this->getMemcache();
+		$memcache->delete($sessionID);
+	}
+
+
+	/**
+	 * This function implements the logout handler. It deletes the information from Memcache.
+	 */
+	public static function logoutHandler() {
+		self::getInstance()->doLogout();
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/www/authmemcookie.php b/www/authmemcookie.php
new file mode 100644
index 000000000..d76274b57
--- /dev/null
+++ b/www/authmemcookie.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * This file implements an script which can be used to authenticate users with Auth MemCookie.
+ * See: http://authmemcookie.sourceforge.net/
+ *
+ * The configuration for this script is stored in config/authmemcookie.php.
+ *
+ * The file extra/auth_memcookie.conf contains an example of how Auth Memcookie can be configured
+ * to use simpleSAMLphp.
+ */
+
+require_once('_include.php');
+
+require_once((isset($SIMPLESAML_INCPREFIX)?$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/Utilities.php');
+require_once((isset($SIMPLESAML_INCPREFIX)?$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/Session.php');
+require_once((isset($SIMPLESAML_INCPREFIX)?$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/AuthMemCookie.php');
+
+try {
+	/* Load simpleSAMLphp configuration. */
+	$globalConfig = SimpleSAML_Configuration::getInstance();
+	$session = SimpleSAML_Session::getInstance(TRUE);
+
+	/* Check if this module is enabled. */
+	if(!$globalConfig->getValue('enable.authmemcookie', FALSE)) {
+		SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS');
+	}
+
+	/* Load Auth MemCookie configuration. */
+	$amc = SimpleSAML_AuthMemCookie::getInstance();
+
+	/* Check if the user is authorized. We attempt to authenticate the user if not. */
+	if (!$session->isValid('saml2') ) {
+		SimpleSAML_Utilities::redirect(
+			'/' . $globalConfig->getBaseURL() . 'saml2/sp/initSSO.php',
+			array('RelayState' => SimpleSAML_Utilities::selfURL())
+			);
+	}
+
+
+	/* Generate session id and save it in a cookie. */
+	$sessionID = SimpleSAML_Utilities::generateID();
+
+	$cookieName = $amc->getCookieName();
+	setcookie($cookieName, $sessionID, 0, '/', NULL, SimpleSAML_Utilities::isHTTPS(), TRUE);
+
+
+	/* Generate the authentication information. */
+
+	$attributes = $session->getAttributes();
+
+	$authData = array();
+
+	/* Username. */
+	$usernameAttr = $amc->getUsernameAttr();
+	if(!array_key_exists($usernameAttr, $attributes)) {
+		throw new Exception('The user doesn\'t have an attribute named \'' . $usernameAttr .
+			'\'. This attribute is expected to contain the username.');
+	}
+	$authData['UserName'] = $attributes[$usernameAttr];
+
+	/* Groups. */
+	$groupsAttr = $amc->getGroupsAttr();
+	if($groupsAttr !== NULL) {
+		if(!array_key_exists($groupsAttr, $attributes)) {
+			throw new Exception('The user doesn\'t have an attribute named \'' . $groupsAttr .
+				'\'. This attribute is expected to contain the groups the user is a member of.');
+		}
+		$authData['Groups'] = $attributes[$groupsAttr];
+	} else {
+		$authData['Groups'] = array();
+	}
+
+	$authData['RemoteIP'] = $_SERVER['REMOTE_ADDR'];
+
+	foreach($attributes as $n => $v) {
+		$authData['ATTR_' . $n] = $v;
+	}
+
+
+	/* Store the authentication data in the memcache server. */
+
+	$data = '';
+	foreach($authData as $n => $v) {
+		if(is_array($v)) {
+			$v = implode(':', $v);
+		}
+
+		$data .= $n . '=' . $v . "\r\n";
+	}
+
+
+	$memcache = $amc->getMemcache();
+	$memcache->set($sessionID, $data);
+
+	/* Register logout handler. */
+	$session->registerLogoutHandler('SimpleSAML/AuthMemCookie.php', 'SimpleSAML_AuthMemCookie', 'logoutHandler');
+
+	/* Redirect the user back to this page to signal that the login is completed. */
+	SimpleSAML_Utilities::redirect(SimpleSAML_Utilities::selfURL());
+} catch(Exception $e) {
+	SimpleSAML_Utilities::fatalError($session->getTrackID(), 'CONFIG', $e);
+}
+
+?>
\ No newline at end of file
-- 
GitLab