premier commit

This commit is contained in:
<bdauvergne@entrouvert.com> 1206618689 +0100 0001-01-01 00:00:00 +00:00
commit 4cebb47113
42 changed files with 2430 additions and 0 deletions

47
INSTALL Normal file
View File

@ -0,0 +1,47 @@
= Installation =
The Makefile is minimal and support two targets for installation: install and
zip.
== The zip target ==
The zip target create a standalone zipfile containing useful files for a
mono-application usage of the spkit. In this case you will have to modify
include/lassospkit_datadir.inc.php to return the correct path Vto the directory
where the spkit will save its datas.
== The install target ==
It supports three parameters $(DOCPREFIX), $(DATAPREFIX) and $(DESTDIR).
DESTDIR will be prefixed to any install path destination, it is there to help
packaging using a staging area before install.
DATAPREFIX is the directory where non-platform dependant datas are stored.
example: /usr/share.
DOCPREFIX is the directory where documentation is stored
xample: /usr/share/doc
= Usage =
== Shared ==
In the shared install case you just have to add
"require_once('lassospkit/lassospkit_public_api.inc.php')" to your code and to
map the $(DATAPREFIX)/spkitlasso/endpoints/ to somewhere inside your
application URL space. For example via a symbolic link if your HTTP server is
permitted to follow them or via an "Alias" if you are using apache. By default
configuration and datas for the spkit will be saved inside
/var/lib/spkitlasso/$(DOMAIN), so if you application appear on multiple domains
do not forget to create appropriate symbolic or otherwise you will have
competing configuration and data directories.
== Monousage ==
You will have to create or find a protected directory where to store
configuration and data from the spkit. The absolute path to this directory must
be returned by the function lasso_datadir() inside
"include/lassospkit_datadir.inc.php". After you just have to add
require_once('path_to_include/lassospkit_public_api.inc.php'); inside you
application.

42
Makefile Normal file
View File

@ -0,0 +1,42 @@
VERSION=0.1
NAME=spkitlasso
DIR:=$(shell basename `pwd`)
FULL=$(NAME)-$(VERSION)
ZIP=$(FULL).zip
TGZ=$(FULL).tar.gz
DATAPREFIX=/usr/share/
DATADIR=$(DATAPREFIX)/$(NAME)
PHPINCLUDEDIR=/usr/share/php/
DOCPREFIX=/usr/share/doc/
DOCDIR=$(DOCPREFIX)/$(NAME)
.PHONY: zip distclean dist install all clean
all:
zip:
cd .. && rm -f $(ZIP) && zip -r $(ZIP) $(DIR) -x \*Makefile -x \*.bzr\* -x .\* -x \*.swp -x \*/debian\* -x \*{TODO,Makefile}
dist: distclean
mkdir $(FULL)
cp -R debian doc exemples endpoints include README Makefile INSTALL TODO $(FULL)
rm -f ../$(TGZ)
tar cvzf ../$(TGZ) $(FULL)
install:
install -d $(DESTDIR)$(DATADIR) $(DESTDIR)$(DATADIR)/include $(DESTDIR)$(DATADIR)/endpoints $(DESTDIR)$(PHPINCLUDEDIR) $(DESTDIR)$(DOCDIR)/exemples
install -d $(DESTDIR)$(DOCDIR)/html
install -m 644 -t $(DESTDIR)$(DATADIR)/include include/*
install -m 644 -t $(DESTDIR)$(DATADIR)/endpoints endpoints/*
install -m 644 -t $(DESTDIR)$(DOCDIR)/exemples exemples/*
install -d $(DESTDIR)$(DOCDIR)
ln -sf $(DATADIR)/include $(DESTDIR)$(PHPINCLUDEDIR)/$(NAME)
install -m 644 -t $(DESTDIR)$(DOCDIR)/html doc/*.html
install -m 644 -t $(DESTDIR)$(DOCDIR) README INSTALL
distclean:
rm -rf $(FULL)
clean:

66
README Normal file
View File

@ -0,0 +1,66 @@
Lasso SPKit PHP v0.1
This library contains code to ease the usage of the PHP bindings of the lasso
library inside a service provider, usually an existing web application where
you wish to handle some of the profile of the Liberty Alliance or SAML 2.0
protocols.
The API is procedural, minimal and easy to comprehend. Depending
upon the configuration
= Description of the API =
General idea: Initiation of SAML request is done via redirection to a local
page and transmission of parameters to this pages are done via PHP sessions.
The $relay parameters are the url where user should be redirected at the end of
the SAML request whatever the result is.
function lassospkit_nameid()
* return the nameid found during the last SSO request in the current session.
If it is non-null, it usually means that we are logged to an SAML IdP.
function lassospkit_set_nameid($nameid)
* Set the nameid that the next SAML profile should use. Use it before
presenting link for defederation or single logout. It has no effect if redirecting toward SSO.
function lassospkit_userid()
* When automated storage of the federation is activated this parameter will
contain the last userID associated with the current nameID. The association
is done by calling setUserID then making a successul SSO request (via a
redirection to lassospki_websso_redirect).
When automated storage is inactivated, it always returns null and set_userid
is ignored by the backend code.
function lassospkit_error()
* When non-null gives a human readable explaination of the last unsucessful
SAML request. Can be an error or a normal event like the user refusing to
federate is identity in the context of an SSO request.
function lassospkit_federation()
* Return an opaque blob containing informations on the federation created with an IdP
afer a succesful request. If you intend to handle yourself storage of the federation,
you must save this together with local user account/sessions informations and restores
it before any future redirection to a logout/defederation request. If you user automated
persistence you can ignore it.
function lassospkit_set_federation($federation)
* Restore the opaque blob needed to initalize SAML requests. See previous function.
function lassospkit_websso_redirect($relay)
* URL to the local page intiating SSO exchanges with the IdP. Use the baseUrl
configuration option to construct this URL.
function lassospkit_set_userid()
* Set the userID (can be any string) to persist together
with the nameId when using automatized persistence of federations.
function lassospkit_defederation_redirect($relay)
* Return the URL to the local page initiating defederation exchanges with the
IdP. It appends the endpoint suffix to the baseUrl configuration option to
build this URL.
function lassospkit_logout_redirect($relay)
* Return the URL to the local page initiating logout exchanges with the
IdP. It appends the endpoint suffix to the baseUrl configuration option to
build this URL.

7
TODO Normal file
View File

@ -0,0 +1,7 @@
- simplify LassoSPKitUtilsSession using generic getters/setters.
- implements id-ff 1.2 version of all functionalities.
- support full nameidmanagement protocol.
- move metadata support into LassoSPKitMetatada class.
- endpoints to retrieve metadatas.
- use LassoSPKitUtilsSession in findFederation, saveFederation et changeFederation.
- create LassoSPKitEndpoint to share implementation between liberty and SAML 2

6
debian/changelog vendored Normal file
View File

@ -0,0 +1,6 @@
spkitlasso (0.1-1) unstable; urgency=low
* Initial release
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Thu, 20 Mar 2008 14:23:09 +0100

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
5

15
debian/control vendored Normal file
View File

@ -0,0 +1,15 @@
Source: spkitlasso
Section: unknown
Priority: extra
Maintainer: Benjamin Dauvergne <bdauvergne@entrouvert.com>
Build-Depends: cdbs, debhelper (>= 5)
Standards-Version: 3.7.2
Package: spkitlasso
Architecture: any
Depends: lasso-php
Description: Simple library to use Lasso PHP bindings inside service providers
This package provides PHP 5 classes and a procedural API to use Lasso basic
protocols like SSO, Identity Federation, Identity Defederation and SLO,
without having to handle transport and persistence of SAML 2.0 or
ID-FF 1.2 assertions.

22
debian/copyright vendored Normal file
View File

@ -0,0 +1,22 @@
This package was debianized by Benjamin Dauvergne <bdauvergne@entrouvert.com> on
Thu, 20 Mar 2008 14:23:09 +0100.
It was downloaded from <url://example.com>
Upstream Author(s):
Benjamin Dauvergne <bdauvergne@entrouvert.com>
Copyright:
Copyright (C) 2008 Entr'Ouvert
License:
This software is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
The Debian packaging is (C) 2008, Benjamin Dauvergne <bdauvergne@entrouvert.com> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.

4
debian/dirs vendored Normal file
View File

@ -0,0 +1,4 @@
usr/share/spkitlasso
usr/share/doc
usr/share/php
usr/share/

3
debian/docs vendored Normal file
View File

@ -0,0 +1,3 @@
INSTALL
README
TODO

10
debian/rules vendored Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/make -f
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/makefile.mk
# Add here any variable or target overrides you need.
DEB_MAKE_INSTALL_TARGET := install DESTDIR=$(CURDIR)/debian/tmp/
DEB_MAKE_CHECK_TARGET :=
DEB_DH_INSTALL_ARGS:=--autodest

13
debian/spkitlasso.doc-base vendored Normal file
View File

@ -0,0 +1,13 @@
Document: spkitlasso
Title: Debian spkitlasso Manual
Author: Benjamin Dauvergne <bdauvergne@entrouvert.com>
Abstract: This manual describes what spkitlasso is
and how it can be used to
manage online manuals on Debian systems.
Section: unknown
Format: HTML
Index: /usr/share/doc/spkitlasso/html/index.html
Files: /usr/share/doc/spkitlasso/html/*.html

1
debian/spkitlasso.install vendored Normal file
View File

@ -0,0 +1 @@
debian/tmp/usr/*

5
debian/spkitlasso.postinst vendored Normal file
View File

@ -0,0 +1,5 @@
# Automatically added by dh_installdocs
if [ "$1" = configure ] && which install-docs >/dev/null 2>&1; then
install-docs -i /usr/share/doc-base/spkitlasso
fi
# End automatically added section

6
debian/spkitlasso.prerm vendored Normal file
View File

@ -0,0 +1,6 @@
# Automatically added by dh_installdocs
if [ "$1" = remove ] || [ "$1" = upgrade ] && \
which install-docs >/dev/null 2>&1; then
install-docs -r spkitlasso
fi
# End automatically added section

5
doc/index.html Normal file
View File

@ -0,0 +1,5 @@
<html>
<body>
To do!
</body>
</html>

53
endpoints/configure.php Normal file
View File

@ -0,0 +1,53 @@
<?php
require_once('../include/lassospkit_configgen.inc.php');
require_once('../include/lassospkit_config.inc.php');
require_once('../include/lassospkit_debug.inc.php');
require_once('../include/lassospkit_metadata.inc.php');
require_once('../include/lassospkit_utils.inc.php');
$configgen = new LassoSPKitConfigUIGen();
$error = null;
if (isset($_POST)) {
if (isset($_POST['clean'])) {
unlink(SP_METADATA);
unlink(PRIVATE_KEY);
unlink(IDP_METADATA);
}
if (isset($_POST['organization'])
&& (isset($_POST['idp_metadata'])
|| isset($_POST['idp_metadata_url'])))
{
$ret = $configgen->makeConfig(
$_POST['organization'],
$_POST['idp_metadata'],
$_POST['idp_metadata_url'],
isset($_POST['clear_pkey']),
$error);
if ($ret) {
try {
$configgen->importConfigFromPost($_POST);
} catch (Exception $e) {
lassospkit_showCode($e);
}
}
}
}
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
?>
<html>
<head>
<link type="text/css" rel="stylesheet" href="style.css">
</head>
<body>
<?
if ($error) {
?><span class="error"> <em>Error:</em> <? echo $error?></span><?
}
$configgen->render_form();
?>
</body>
</html>

63
endpoints/liberty.php Normal file
View File

@ -0,0 +1,63 @@
<?php
require_once("../include/lassospkit_helper.inc.php");
require_once("../include/lassospkit_dispatcher.inc.php");
require_once("../include/lassospkit_metadata.inc.php");
require_once("../include/lassospkit_utils.inc.php");
session_start()
dispatch(array('/login' => login,
'/federate' => federate,
'/ssoAssertionConsumer' => ssoAssertionConsumer,
'/sloInit' => sloInit,
'/sloSoap' => sloSoap,
'/sloRedirect' => sloRedirect,
'/sloResponse' => sloResponse,
'/defederate' => defederate,
'/defederateReturn' => defederateReturn,
'/defederateNotification' => defederateNotification,
'/metadata' => metadata));
// TODO fill implementation
function login() {
$saml2 = new LassoSPKitLiberty(new LassoSPKitDummySession());
$params = LassoSPKitUtilsSession::getParams('login');
$federate = TRUE;
if (isset($params['federate'])) {
$federate = $params['federate'];
}
$saml2->sso(TRUE, $federate);
}
function federate() {
$saml2 = new LassoSPKitLiberty(new LassoSPKitDummySession());
$saml2->sso(TRUE, TRUE);
}
function ssoAssertionConsumer() {
}
function sloInit() {
}
function sloSoap() {
}
function sloRedirect() {
}
function sloResponse() {
}
function defederate() {
}
function defederateReturn() {
}
function defederateNotification() {
}
function metadata() {
header('Content-type: text/xml');
$datadir = LassoSPKitHelper::getMetadataDir(LASSO_PROTOCOL_LIBERTY_1_2);
$pkey = $datadir . "/" . PRIVATE_KEY;
LassoSPKitUtils::extractPublicKey($pkey, $publickey, $error);
try {
$content = LassoSPKitMetadataLiberty::generateMetadata(dirname(LassoSPKitUtils::mydir()), LassoSPKitConfig::get('organization'), $publickey);
if ($content) {
header('Content-type: text/xml');
echo $content;
}
} catch (Exception $e) {
throw $e;
}
}

165
endpoints/saml2.php Normal file
View File

@ -0,0 +1,165 @@
<?php
require_once("../include/lassospkit_helper.inc.php");
require_once("../include/lassospkit_dispatcher.inc.php");
require_once("../include/lassospkit_saml2.inc.php");
require_once("../include/lassospkit_metadata.inc.php");
require_once("../include/lassospkit_utils.inc.php");
require_once("../include/lassospkit_utils_session.inc.php");
require_once("../include/lassospkit_dummysession.inc.php");
require_once("../include/lassospkit_autopersistentsession.inc.php");
session_start();
function verifyReferer() {
if (isset($_SERVER['HTTP_REFERER'])) {
$host = $_SERVER['HTTP_REFERER'];
$host = strstr('//', $host);
$pos = strpos($host, '/');
if ($pos !== FALSE) {
$host = substr($host, 0, $pos);
}
if ($host && isset($_SERVER['HTTP_HOST']) && $host != $_SERVER['HTTP_HOST']) {
echo "Bad referer '$host' != '" . $_SERVER['HTTP_HOST'] . "'";
exit(1);
}
}
}
try {
dispatch(array('/login' => 'login',
'/federate' => 'federate',
'/ssoAssertionConsumer' => 'ssoAssertionConsumer',
'/slo' => 'slo',
'/sloSoap' => 'sloSoap',
'/sloRedirect' => 'sloRedirect',
'/sloResponse' => 'sloResponse',
'/defederate' => 'defederate',
'/nidManagementInit' => 'nidManagementInit',
'/nidManagementSoap' => 'nidManagementSoap',
'/nidManagementRedirect' => 'nidManagementRedirect',
'/nidManagementResponse' => 'nidManagementResponse',
'/metadata' => 'metadata'));
} catch (Exception $e) {
lassospkit_showCode($e);
lassospkit_showCode(var_export($_SESSION,1));
}
// TODO fill implementation
function finishRequest($method, $profileStr, $session, $ret) {
if ($method == LASSO_HTTP_METHOD_SOAP) {
if (! $ret) {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState($profileStr));
} else {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState('error'));
}
} else {
if (! $ret) {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState('error'));
}
}
}
function finishResponse($profileSTR, $session, $ret) {
if (! $ret) {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState($profileSTR));
} else {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState('error'));
}
}
function getSession() {
$session_class = "LassoSPKit" . LassoSPKitConfig::get('session');
return new $session_class();
}
function detectMethodAssertionConsumer() {
}
function login() {
verifyReferer();
$saml2 = new LassoSPKitSAML2(new LassoSPKitDummySession());
$params = LassoSPKitUtilsSession::getParams('login');
$federate = TRUE;
if (isset($params['federate'])) {
$federate = $params['federate'];
}
$saml2->sso(FALSE, $federate);
LassoSPKitUtilsSession::setRelayState('sso',LassoSPKitUtilsSession::getRelayState('login'));
}
function federate() {
verifyReferer();
$saml2 = new LassoSPKitSAML2(new LassoSPKitDummySession());
$saml2->sso(TRUE, TRUE);
LassoSPKitUtilsSession::setRelayState('sso',LassoSPKitUtilsSession::getRelayState('federate'));
}
function ssoAssertionConsumer() {
$session = getSession();
$saml2 = new LassoSPKitSAML2($session);
if (isset($_GET)) {
$ok = $saml2->ssoConsumer(LASSO_HTTP_METHOD_ARTIFACT_GET, $_SERVER['QUERY_STRING']);
} elseif (isset($_POST)) {
$ok = $saml2->ssoConsumer(LASSO_HTTP_METHOD_ARTIFACT_POST, $_SERVER['QUERY_STRING']);
}
if ($ok) {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState('sso'));
} else {
$session->doRedirect(LassoSPKitUtilsSession::getRelayState('error'));
}
}
function slo() {
$session = getSession();
$saml2 = new LassoSPKitSAML2($session);
$method = LASSO_HTTP_METHOD_REDIRECT;
$ret = $saml2->initiateSLO($method);
$headers = headers_list();
finishRequest($method, 'slo', $session, $ret);
}
function sloSoap() {
$session = getSession();
$saml2 = new LassoSPKitSAML2($session);
if ($saml2->processSOAPRequestSLO() == 0) {
lassospkit_debuglog("SLO SOAP Request handler: fatal error");
}
}
function sloRedirect() {
}
function sloResponse() {
$session = getSession();
$saml2 = new LassoSPKitSAML2($session);
$ret = $saml2->processRedirectResponseSLO();
finishResponse('slo', $session, $ret);
}
function defederate() {
$session = getSession();
$saml2 = new LassoSPKitSAML2($session);
$method = LASSO_HTTP_METHOD_REDIRECT;
$ret = $saml2->initiateFTNotification($method);
finishRequest($method, 'defederation', $session, $ret);
LassoSPKitUtilsSession::setRelayState('nidmanagement',LassoSPKitUtilsSession::getRelayState('defederation'));
}
function nidManagementInit() {
}
function nidManagementSoap() {
}
function nidManagementRedirect() {
}
// NidManagement Redirect Response
function nidManagementResponse() {
$session = getSession();
$saml2 = new LassoSPKitSAML2($session);
$method = LASSO_HTTP_METHOD_REDIRECT;
$ret = $saml2->processRedirectResponseNameIdManagement();
finishResponse('defederation', $session, $ret);
}
function metadata() {
$datadir = LassoSPKitHelper::getMetadataDir(LASSO_PROTOCOL_SAML_2_0);
$pkey = $datadir . "/" . PRIVATE_KEY;
LassoSPKitUtils::extractPublicKey($pkey, $publickey, $error);
try {
$content = LassoSPKitMetadataSAML2::generateMetadata(dirname(LassoSPKitUtils::mydir()), LassoSPKitConfig::get('organization'), $publickey);
if ($content) {
header('Content-type: text/xml');
echo $content;
}
} catch (Exception $e) {
throw $e;
}
}

2
endpoints/style.css Normal file
View File

@ -0,0 +1,2 @@
.error { width: auto; color: red; border: 1px solid red; padding: 2px; }
pre,.code { background: #BBB; border: 1px solid black; padding: 1ex;white-space: pre; overflow: scroll }

44
exemples/index.php Executable file
View File

@ -0,0 +1,44 @@
<?php
session_start();
echo '<?xml version="1.0" encoding="UTF-8"?>';
require_once('spkitlasso/include/lassospkit_public_api.inc.php');
require_once('spkitlasso/include/lassospkit_debug.inc.php');
require_once('spkitlasso/include/lassospkit_utils.inc.php');
function show($a) {
echo "<li><a href='$a'>";
echo $a;
echo "</a></li>";
}
?>
<html>
<head>
<link type="text/css" rel="stylesheet" href="endpoints/style.css">
</head>
<h1>Points d'accés</h1>
<ul>
<?
$myself = LassoSPKitUtils::myself();
show(lassospkit_login_redirect($myself));
show(lassospkit_federate_redirect($myself));
show(lassospkit_logout_redirect($myself));
show(lassospkit_defederation_redirect($myself));
show('endpoints/configure');
$nameid = lassospkit_nameid();
$userid = lassospkit_userid();
$error = lassospkit_error();
$federation = lassospkit_federation();
if ($federation) {
lassospkit_set_federation($federation);
}
?>
<li>NameId: <? echo lassospkit_showCode(var_export($nameid,1)) ?></li>
<li>UserId: <? echo lassospkit_showCode($userid) ?></li>
<li>Error: <? echo lassospkit_showCode($error) ?></li>
<li>Federation: <? echo lassospkit_showCode($federation) ?></li>
</ul>
</html>

View File

@ -0,0 +1,48 @@
<?php
require_once('lassospkit_generic_session.inc.php');
require_once('lassospkit_utils_session.inc.php');
require_once('lassospkit_debug.inc.php');
require_once('lassospkit_file.inc.php');
require_once('lassospkit_config.inc.php');
require_once('lassospkit_generic_session.inc.php');
class LassoSPKitAutoPersistentSession extends LassoSPKitGenericSession {
private $storage;
function __construct() {
$storage_class = "LassoSPKit" . LassoSPKitConfig::get('storage') . "Store";
$this->storage = @new $storage_class();
if ($this->storage == null) {
throw new Exception("Config error: storage class $storage_class does not exist");
}
}
function findFederation($nameID) {
if (! $nameID) {
return 0;
}
$blob = $this->storage->get($nameID);
if ($blob == null) {
return 0;
}
return $this->explodeFederationBlob($blob);
}
function saveFederation() {
$nameIDs = $this->getNameIDs();
$firstID = array_pop($nameIDs);
if ($firstID == null) {
throw new Exception("save federation has no nameIDs to create keys");
}
$blob = $this->getFederationBlob();
$this->storage->set($firstID, $blob);
foreach ($nameIDs as $otherID) {
$this->storage->alias($firstID, $otherID);
}
parent::saveFederation();
}
function changeFederation($oldID, $newID) {
if ($newID) {
$this->storage->rename($oldID, $newID);
} else {
$this->storage->delete($oldID);
}
}
}

View File

@ -0,0 +1,91 @@
<?
require_once('lassospkit_datadir.inc.php');
/** This class represents the non-SAML-metadata part
* of the config of the spkit. */
class LassoSPKitConfig {
static $default_values = array(
'federate' => 'file', /* Does the backend persist federation ? no, file or mysql. */
'mysql_host'=> 'localhost', /* Configuration of the MySql connection if federate = mysql */
'mysql_user' => '',
'mysql_password' => '',
'mysql_database' => '',
'mysql_table' => '_lassospkit_userid2nameid',
'lasso_lib' => 'lasso.php', /* Where is lasso PHP binding ? */
'debug' => '0', /* Activate extra debugging */
'organization' => "", /* Nom de l'organisation */
'conformance' => "",
'idp_metadata_url' => "",
'baseUrl' => "",
'session' => "DummySession",
'storage' => "File"
);
private static $instance = null;
private static $file;
function __construct() {
}
static function init() {
self::$file = lassospkit_datadir() . '/lassospkit_config.ini';
if (! self::$instance) {
self::$instance = array();
$ph = @dba_open(self::$file, 'rl', 'inifile');
if ($ph) {
try {
foreach (self::$default_values as $k => $v) {
if (dba_exists($k, $ph)) {
self::$instance[$k] = dba_fetch($k, $ph);
}
}
} catch (Exception $e) {
dba_close($ph);
throw $e;
}
dba_close($ph);
}
}
}
static function commit() {
$ph = dba_open(self::$file, 'nl', 'inifile');
if (! $ph) {
throw Exception('Cannot open the config file for writing');
}
try {
foreach (self::$instance as $k => $v) {
if (isset(self::$default_values[$k])) {
dba_replace($k, $v, $ph);
}
}
} catch (Exception $e) {
dba_close($ph);
throw $e;
}
dba_close($ph);
}
function setDefault($name) {
self::init();
unset(self::$instance[$name]);
}
static function get($name) {
self::init();
if (! isset(self::$default_values[$name])) {
throw new Exception('Try to read an unknown config field');
}
if (isset(self::$instance[$name])) {
return self::$instance[$name];
}
return self::$default_values[$name];
}
static function set($name, $value) {
self::init();
if (! isset(self::$default_values[$name])) {
throw new Exception('Try to write an unknown config field');
}
self::$instance[$name] = $value;
}
public function keys() {
return array_keys(self::$default_values);
}
}
?>

View File

@ -0,0 +1,267 @@
<?php
require_once('lassospkit_datadir.inc.php');
require_once('lassospkit_helper.inc.php');
/** This class generate the WebUI for configuring the SP kit. */
class LassoSPKitConfigUIGen
{
private $special_input;
private $default_input;
private $base;
function __construct() {
$this->special_input = array(
'organization' =>
array('Nom du service',
'text'),
'baseUrl' =>
array('Base des URLS des points d\'accés', 'text'),
'gruik' =>
array('URL des métadatas SAML 2.0 du SP',
'url',
LassoSPKitUtils::relativePathToURL("saml2/metadata")),
'gruik2' =>
array('URL des métadatas Liberty 1.2 du SP',
'url',
LassoSPKitUtils::relativePathToURL("liberty/metadata")),
'idp_metadata_url' =>
array('URL des métadatas du service d\'authentification',
'text'),
'idp_metadata' =>
array('Métadatas de l\'IdP',
'textarea'),
'clear_pkey' =>
array('Génère une clé privée, même si une existe déjà',
'checkbox'),
'federate' =>
array('Stockage de la fédération',
'select',
array('no' => 'Non',
'MySql' => 'Via MySql',
'File' => 'Via le filesystem')),
'mysql_host' => array('Host de la base MySql'),
'mysql_user' => array('Identifiant sur la base'),
'mysql_password' => array('Mot de passe sur la base', 'password'),
'mysql_database' => array('Nom de la base'),
'mysql_table' => array('Nom de la table'),
'lasso_lib' => array('Emplacement de la bibliothèque Lasso PHP'));
}
function itype($name) {
if (isset($this->special_input[$name][1])) {
return $this->special_input[$name][1];
}
return 'text';
}
function icaption($name) {
if (isset($this->special_input[$name][0])) {
return $this->special_input[$name][0];
}
return $name;
}
function value($name) {
switch ($name) {
case 'idp_metadata':
return @file_get_contents(LassoSPKitHelper::getIdpMetadataFile());
case 'baseUrl':
return LassoSPKitUtils::mydir();
}
if (isset(LassoSPKitConfig::$default_values[$name])) {
return LassoSPKitConfig::get($name);
}
return '';
}
function msg($mess) {
echo htmlspecialchars(gettext($mess));
}
function render_form() {
echo '<head>', "\n";
echo '<title>';
$this->msg('Configuration du SP-Kit LassoSPKit');
echo '</title>', "\n";
echo '<body>', "\n";
echo '<h1>', "\n";
$this->msg('Configuration du SP-kit LassoSPKit');
echo '</h1>', "\n";
echo '<form action="' . htmlspecialchars(LassoSPKitUtils::myself()) . '" method="post">', "\n";
echo ' <table>', "\n";
foreach ($this->special_input as $k => $v) {
echo '<tr><td>';
$this->msg($this->icaption($k));
echo '</td><td>';
$actual = $this->value($k);
$type = $this->itype($k);
switch ($type) {
case 'textarea':
echo '<textarea name="' . $k . '" cols="80" row="20">';
$this->msg($actual);
echo '</textarea>';
break;
case 'select':
echo '<select name="' . $k . '" size="1">';
foreach ($v[2] as $x => $y) {
echo '<option value="' . $x . '"';
if ($actual == $x) {
echo ' selected ';
}
echo '>';
$this->msg($y);
echo '</option>';
}
echo '</select>';
break;
case 'text':
echo '<input name="' . $k . '"';
echo 'type="text" size="80" value="' . $actual . '"/>';
break;
case 'url':
echo '<a href="';
$this->msg($v[2]);
echo '">';
$this->msg($v[2]);
echo '</a>';
break;
default:
echo '<input name="' . $k . '"';
echo 'type="' . $type . '" ';
if ($actual) {
echo 'value="' . $actual . '" ';
}
echo '/>';
break;
}
echo '</td></tr>', "\n";
}
echo '<tr><td/><td><input type="submit" value="Modifier"/></td></tr>', "\n";
echo '</table>', "\n";
echo '</body>', "\n";
}
function importConfigFromPost($post) {
foreach (LassoSPKitConfig::keys() as $k) {
if (isset($post[$k]))
{
LassoSPKitConfig::set($k, $post[$k]);
}
}
LassoSPKitConfig::commit();
}
function validateMetadata($file) {
return LassoSPKitHelper::getConformance($file);
}
function getIdpMeta($idpMeta, $idpMetaUrl, &$conformance, &$error) {
if (! $idpMeta && ! $idpMetaUrl) {
throw new Exception("illegal argument");
}
$file = tempnam(TEMPDIR, "idp-metadata-temp");
$ok = 0;
if ($idpMetaUrl) {
$idpMeta = @file_get_contents($idpMetaUrl);
$ok = ($idpMeta != null);
if ($ok) {
$ok = @file_put_contents($file, $idpMeta);
if ($ok) {
$conformance = $this->validateMetadata($file);
$ok = ($conformance != -1);
if (! $ok) {
$error = "GetIDPMeta: Retrieved metadatas non conformant";
}
} else {
$error = "GetIDPMeta: Cannot store retrieved IdP metadatas";
}
} else {
$error = "GetIDPMeta: Cannot retrieve metadatas from the given URL: $idpMetaUrl";
}
}
if (! $ok && $idpMeta) {
$ok = @file_put_contents($file, $idpMeta);
if ($ok) {
$conformance = $this->validateMetadata($file);
$ok = ($conformance != -1);
if (! $ok) {
$error = "GetIDPMeta: Metadatas non conformant";
}
} else {
$error = "GetIDPMeta: Cannot store given IdP metadatas";
}
}
if ($ok) {
return $file;
} else {
@unlink($file);
return FALSE;
}
}
function generateSPMetadata($conformance, $organization, $publickey, &$error) {
$spmeta = LassoSPKitHelper::getMetadataDir($conformance) . "/" . SP_METADATA;
$base = LassoSPKitConfig::get('baseUrl');
switch ($conformance) {
case LASSO_PROTOCOL_SAML_2_0:
$meta = LassoSPKitMetadataSAML2::generateMetadata($base, $organization, $publickey);
LassoSPKitConfig::set('conformance', 'saml2');
break;
case LASSO_PROTOCOL_LIBERTY_1_0:
case LASSO_PROTOCOL_LIBERTY_1_1:
case LASSO_PROTOCOL_LIBERTY_1_2:
$meta = LassoSPKitMetadataLiberty::generateMetadata($base, $organization, $publickey);
LassoSPKitConfig::set('conformance', 'liberty');
break;
default:
throw new Exception("illegal argument");
}
$ok = file_put_contents($spmeta, $meta);
if (! $ok) {
$error = "GenerateSPMetadata: Cannot save generated sp metadatas in $spmeta ";
return 0;
}
return 1;
}
function makeConfig($organization, $idpMeta, $idpMetaUrl, $removePrivateKey, &$error) {
$base = lassospkit_datadir();
// Get idp metadatas
$file = $this->getIdpMeta($idpMeta, $idpMetaUrl, $conformance, $error);
if (! $file) {
return 0;
}
$metabase = LassoSPKitHelper::getMetadataDir($conformance);
if (! is_dir($metabase)) {
if (! @mkdir($metabase)) {
$error = "MakeConfig: Cannot create directory $metabase";
return 0;
}
}
if (! LassoSPKitUtils::checkCanWrite($metabase, $error)) {
return 0;
}
if (! LassoSPKitUtils::checkCanWrite($base, $error)) {
return 0;
}
$idpmeta = LassoSPKitHelper::getIdpMetadataFile();
if (! ($contents = @file_get_contents($file)) || ! @file_put_contents($idpmeta, $contents)) {
$error = "MakeConfig: Cannot move idp temporary files to final place";
return 0;
}
@unlink($file);
// Create local metadatas
$pkey = $metabase . "/" . PRIVATE_KEY;
if (! is_file($pkey) || $removePrivateKey) {
@unlink($pkey);
if (! LassoSPKitUtils::generatePrivateKey($pkey, $error)) {
return 0;
}
}
$publickey = null; // Will contain the publickey
if (! LassoSPKitUtils::extractPublicKey($pkey, $publickey, $error)) {
return 0;
}
if (! $this->generateSPMetadata($conformance,
LassoSPKitConfig::get('organization'),
$publickey,
$error)) {
return 0;
}
return 1;
}
}

View File

@ -0,0 +1,11 @@
<?php
/** Function for getting the place of the config file, the federation files when autofederation is activated.
* Change this function to change way of find kit position. When using lassospkit
* in an unique directory with you application, you can just make it return "../data".
*/
function lassospkit_datadir() {
// return '/var/lib/lassospkit/' . $_SERVER['HTTP_HOST'];
return "/home/bdauvergne/public_html/data";
// return $_SERVER['DOCUMENT_ROOT'] . '/data';
}

View File

@ -0,0 +1,57 @@
<?php
require_once('lassospkit_config.inc.php');
libxml_use_internal_errors(true);
error_reporting(E_ALL);
function lassospkit_debuglog($msg, $level = 0) {
$lassospkit_debug_level = LassoSPKitConfig::get('debug');
if ($level <= $lassospkit_debug_level) {
openlog("LassoPHP.SP.Kit", LOG_PID, LOG_AUTHPRIV);
syslog(LOG_DEBUG, $msg);
closelog();
}
}
function lassospkit_showCode($code) {
echo '<pre class="code">';
echo htmlspecialchars($code);
echo '</pre>';
}
// function lassospkit_errorhandler($errno, $errstr, $errfile, $errline)
//{
// if (error_reporting()==0) {
// return false;
// }
// switch ($errno) {
// case E_USER_ERROR:
// bigdebug("Mon ERREUR [$errno] $errstr\n".
// "\n" . var_export(debug_backtrace(),1) .
// " Erreur fatale sur la ligne $errline dans le fichier $errfile".
// ", PHP " . PHP_VERSION . " (" . PHP_OS . ")\n".
// "Arrêt...");
// exit(1);
// break;
//
// case E_USER_WARNING:
// bigdebug("Mon ALERTE [$errno] $errstr"
// . "\n" . var_export(debug_backtrace(),1)
// . " Erreur fatale sur la ligne $errline dans le fichier $errfile");
// break;
//
// case E_USER_NOTICE:
// bigdebug("Mon AVERTISSEMENT [$errno] $errstr"
// . "\n" . var_export(debug_backtrace(),1)
// . " Erreur fatale sur la ligne $errline dans le fichier $errfile");
// break;
//
// default:
// bigdebug("Type d'erreur inconnu : [$errno] $errstr"
// . "\n" . var_export(debug_backtrace(),1)
// . " Erreur fatale sur la ligne $errline dans le fichier $errfile");
// break;
// }
//
// /* Ne pas exécuter le gestionnaire interne de PHP */
// return true;
//}

View File

@ -0,0 +1,9 @@
<?
/** Magic constants... */
define("SP_METADATA", "sp_metadata.xml");
define("IDP_METADATA","idp_metadata.xml");
define("PRIVATE_KEY", "private.key");
define("OPENSSL_BIN", "/usr/bin/openssl");
define("TEMPDIR","/tmp");
define("_CHECK_FILENAME", ".654564XDSFSTEST");
?>

View File

@ -0,0 +1,13 @@
<?
function dispatch ($urls) {
$path_info = $_SERVER['PATH_INFO'];
$fname = $urls[$path_info];
if ($fname) {
$fname();
exit(0);
} else {
header("HTTP/1.0 404 Not Found");
exit(0);
}
}
?>

View File

@ -0,0 +1,29 @@
<?php
require_once('lassospkit_generic_session.inc.php');
require_once('lassospkit_utils_session.inc.php');
require_once('lassospkit_debug.inc.php');
class LassoSPKitDummySession extends LassoSPKitGenericSession {
/** Save the federation into the SESSION object */
function saveFederation() {
LassoSPKitUtilsSession::setFederation(
serialize($this->getFederationBlob()));
parent::saveFederation();
}
/** Use the nameID as a hint to validate the stored dumps.
It not present use them directly. */
function findFederation($nameID) {
$federation = LassoSPKitUtilsSession::getFederation();
$ret = explodeFederationBlob($federation);
if ($ret == 1 && $nameID) {
$nameIDs = $this->getNameIDs();
if (! @in_array($nameID, $nameIDs)) {
$this->setSessionDump(null);
$this->setIdentityDump(null);
LassoSPKitUtilsSession::setUserId(null);
return 0;
}
}
return $ret;
}
}

View File

@ -0,0 +1,56 @@
<?
require_once('lassospkit_storage.inc.php');
require_once('lassospkit_datadir.inc.php');
/** Hard links needs to be supported on the filesystem. */
class LassoSPKitFileStore implements LassoSPKitStore {
public $base = '';
function __construct() {
$this->base = lassospkit_datadir();
}
private function filepath($key) {
return $this->base . '/' . $this->filename($key);
}
private function filename($key) {
return 'lib_session_' . $key;
}
function get($key) {
$content = @file_get_contents($this->filepath($key));
if ($content === FALSE) {
return null;
}
return @unserialize($content);
}
function set($key, $value) {
if ($key && $key != "") {
$ret = @file_put_contents($this->filepath($key), @serialize($value));
$this->debug($ret, "cannot set contents of file " . $this->filepath($key));
} else {
throw new Exception("Bad usage of FileStore::set, key is null");
}
}
function delete($key) {
@unlink($this->filepath($key));
}
function alias($key,$alias) {
$target = $this->filename($key);
$sym = $this->filepath($alias);
@unlink($sym);
$ret = @link($target,$sym);
$this->debug($ret, "could not alias key $key => $alias");
return $ret;
}
function rename($old,$new) {
$old_path = $this->filename($old);
$new_path = $this->filename($new);
$ret = @rename($old_path, $new_path);
$this->debug($ret, "could not rename key $old => $new");
return $ret;
}
function debug($ret, $mesg) {
if ($ret === FALSE) {
lassospkit_debuglog("SPKit File Storage: " . $mesg);
}
}
}
?>

View File

@ -0,0 +1,71 @@
<?php
/** This class implements dummy methods for
generic handling of SSO session i.e storage
of federation data (identity_dump and
session_dump), retrieval of attributes,
etc.. */
class LassoSPKitGenericSession {
public $exception;
private $session_dump;
private $identity_dump;
function processAttributes(array $attributes) {
}
function doRedirect($url) {
header("Location: $url");
}
function doResponse($mimeType, $content) {
header("Content-type: $mimeType");
echo $content;
}
function logout() {
}
/** Save session_dump and identity_dump,
use any mean to link them to a local session.
The default implementation just report the list of nameIDs
in the nameIDs session variable.
*/
function saveFederation() {
$identity_dump = $this->getIdentityDump();
$nameIDs = LassoSPKitHelper::getNameIDsFromDump($identity_dump);
LassoSPKitUtilsSession::setNameID($nameIDs);
}
function findFederation($nameID) {
}
function changeFederation($nameID, $NewID) {
}
function setSessionDump($dump) {
$this->session_dump = $dump;
}
function setIdentityDump($dump) {
$this->identity_dump = $dump;
}
function getSessionDump() {
return $this->session_dump;
}
function getIdentityDump() {
return $this->identity_dump;
}
function getNameIDs() {
$identity_dump = $this->getIdentityDump();
return LassoSPKitHelper::getNameIDsFromDump($identity_dump);
}
function getFederationBlob() {
$userid = LassoSPKitUtilsSession::getUserID();
return array(
'identity'=> $this->getIdentityDump(),
'session' => $this->getSessionDump(),
'userid'=>$userid);
}
function explodeFederationBlob($blob) {
$federation = @unserialize($blob);
if ($federation === FALSE) {
$this->debug(FALSE, "Could not unserialize content of key file for key $nameID");
return 0;
}
$this->setSessionDump($federation['session']);
$this->setIdentityDump($federation['identity']);
LassoSPKitUtilsSession::setUserID($federation['userid']);
}
}

View File

@ -0,0 +1,204 @@
<?
require_once('lassospkit_datadir.inc.php');
require_once('lassospkit_config.inc.php');
require_once('lassospkit_lib.inc.php');
require_once('lassospkit_debug.inc.php');
class LassoSPKitHelper {
/** If session_dump and identity_dump are present in the
session object, use then to initialize the profile */
static function restoreDumps(LassoProfile $profile,
LassoSPKitGenericSession $session) {
$sessionDump = $session->getSessionDump();
$identityDump = $session->getIdentityDump();
if ($sessionDump) {
$profile->setSessionFromDump($sessionDump);
}
if ($identityDump) {
$profile->setIdentityFromDump($identityDump);
}
}
/** If identity or session is dirty save them in the session
object using setIdentyDump and setSessionDump.
Returns the dirtiness statute ('or' of the two dirty flag).
*/
static function saveDumps(LassoProfile $profile,
LassoSPKitGenericSession $session) {
$ok = 0;
if ($profile->hasDirtyIdentity()) {
if ($profile->identity) {
$session->setIdentityDump($profile->identity->dump());
} else {
$session->setIdentityDump(null);
}
$ok = 1;
}
if ($profile->hasDirtySession()) {
if ($profile->session) {
$session->setSessionDump($profile->session->dump());
} else {
$session->setSessionDump(null);
}
$ok = 1;
}
return $ok;
}
/** Extract attributes values and keys from an assertion,
and copy them into array $arr. */
static function assertionExtractAttributes(LassoAssertion $assertion, &$attributes) {
foreach ($assertion->attributeStatement[0]->attribute
as $attribute) {
if ($attribute->name == LASSO_SAML2_ATTRIBUTE_NAME_EPR) {
continue;
}
$arr = array();
foreach ($attribute->attributeValue as $value) {
array_push($arr, $value->any[0]->content);
}
$attributes[$attribute->name] = $arr;
}
}
/** Return the NameID found in profile->nameIdentifier. If throw is TRUE
* and we cannot find a nameIdentifier then throws IDENTIFIER_NOT_FOUND. */
static function profileGetNameID(LassoProfile $profile) {
$nameIdentifier = $profile->nameIdentifier;
if (! $nameIdentifier || ! $content = $nameIdentifier->content) {
return null;
}
return $content;
}
/** This should handle removing of federation, identity == null, ask
for federation termination on the session. */
static function saveFederation(LassoProfile $profile,
LassoSPKitGenericSession $session) {
$nameID = self::profileGetNameID($profile);
if (self::saveDumps($profile,$session)) {
$session->saveFederation($nameID);
}
}
/** Contract is that if NewID is null, session should forget about
the current federation, if it is not then the link between local id
and nameID should be changed to point to NewID. */
static function changeFederation(LassoProfile $profile,
LassoSPKitGenericSession $session,
$NewID) {
$nameID = self::profileGetNameID($profile);
$session->changeFederation($nameID, $NewID);
}
/** Try to restore the federation informations from the profile.
* The contract with the session object is that after findFederation
* if it returned TRUE, then $session->identity_dump et
* $session->session_dump contains valid dumps.
*/
static function findFederation(LassoProfile $profile,
LassoSPKitGenericSession $session) {
$nameID = self::profileGetNameID($profile);
if ($session->findFederation($nameID) == 0) {
if ($nameID) {
throw new LassoProfileFederationNotFoundError();
} else {
throw new LassoProfileNameIdentifierNotFoundError($profile->dump());
}
}
self::restoreDumps($profile,$session);
return 1;
}
static function postToHost($host, $path, $data_to_send, $ssl = false) {
if ($ssl) {
$fp = fsockopen('tls://' . $host, 443);
} else {
$fp = fsockopen($host, 80);
}
fputs($fp, "POST $path HTTP/1.1\n");
fputs($fp, "Host: $host\n");
fputs($fp, "Content-type: text/xml\n");
fputs($fp, "Content-length: ".strlen($data_to_send)."\n");
fputs($fp, "Connection: close\n\n");
fputs($fp, "$data_to_send\n");
$res = '';
while(!feof($fp)) {
$res .= fgets($fp, 128);
}
fclose($fp);
$res = substr(strstr($res, "\r\n\r\n"), 4);
return $res;
}
static public function soapCall($url, $msg) {
if (strstr($url, 'http://') != $url)
return "";
$short_url = substr($url, 7);
$url_tokens = explode("/", $short_url);
$host = $url_tokens[0];
unset($url_tokens[0]);
$query = implode("/", $url_tokens);
$query = "/" . $query;
$response = self::postToHost($host, $query, $msg);
return $response;
}
/** Make a SOAP call using parameters found in profile. */
static public function SoapCallWithProfile(LassoProfile $profile) {
return self::soapCall($profile->msgUrl, $profile->msgBody);
}
static public function notImplemented() {
LassoError::throw_on_rc(LASSO_PROFILE_ERROR_UNSUPPORTED_PROFILE);
}
/** Return the directory where metadatas are stored */
static public function getMetadataDir($conformance) {
$base = lassospkit_datadir();
switch ($conformance) {
case LASSO_PROTOCOL_SAML_2_0:
$base .= "/saml2";
break;
case LASSO_PROTOCOL_LIBERTY_1_0:
case LASSO_PROTOCOL_LIBERTY_1_1:
case LASSO_PROTOCOL_LIBERTY_1_2:
$base .= "/liberty";
break;
default:
throw new Exception("illegal argument");
}
return $base;
}
static function getConformance($file) {
try {
$server = new LassoProvider(LASSO_PROVIDER_ROLE_IDP
, $file, null, null);
if ($server) {
return $server->protocolConformance;
} else {
return -1;
}
} catch (Exception $e) {
return -1;
}
}
static function getIdpMetadataFile() {
return lassospkit_datadir() . "/" . IDP_METADATA;
}
static function getNameIDsFromDump($dump) {
$identity = LassoIdentity::newFromDump($dump);
if (! $identity) {
return array();
}
$nameIDs = self::getNameIDs($identity);
return $nameIDs;
}
static function getNameIDs(LassoIdentity $identity) {
$nameIDs = array();
foreach ($identity->federations as $rid => $federation) {
$nameIDs[$rid] = $federation->remoteNameIdentifier->content;
}
return $nameIDs;
}
}
?>

View File

@ -0,0 +1,5 @@
<?php
require_once('lassospkit_config.inc.php');
$lasso_lib = LassoSPKitConfig::get('lasso_lib');
require_once($lasso_lib);
lasso_init();

View File

@ -0,0 +1,17 @@
<?
require_once('lassospkit_config.inc.php');
require_once('lassospkit_debug.inc.php');
require_once('lassospkit_saml_common.inc.php');
require_once('lassospkit_lib.inc.php');
class LassoSPKitLiberty extends LassoSPKitSAMLCommon {
public function __construct(LassoSPKitGenericSession $session) {
parent::__construct($session);
$this->initServer(lassospkit_datadir() . "/liberty");
}
/** Overloaded method to serve as callback to common SSO method. */
protected ssoNameIdPolicyConfig(LassoLogin $login, $blob) {
$request = $login->request;
$request->NameIDPolicy = $blob;
}
}

View File

@ -0,0 +1,76 @@
<?php
class LassoSPKitMetadataSAML2 {
static function generateMetadata($baseUrl, $orgname, $publickey) {
$meta = '<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
entityID="' . $baseUrl . '/saml2/metadata">
<SPSSODescriptor
AuthnRequestsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyValue>' . $publickey . '</ds:KeyValue>
</ds:KeyInfo>
</KeyDescriptor>
<AssertionConsumerService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="' . $baseUrl . '/saml2/ssoAssertionConsumer" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="' . $baseUrl . '/saml2/sloSoap"/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="' . $baseUrl . '/saml2/sloRedirect" ResponseLocation="' . $baseUrl . '/saml2/sloResponse"/>
<ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="' . $baseUrl . '/saml2/nidManagementSoap"/>
<ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="'. $baseUrl .'/saml2/nidManagementRedirect" ResponseLocation="'. $baseUrl .'/saml2/nidManagementResponse"/>
</SPSSODescriptor>
<Organization>
<OrganizationName xml:lang="en">' . $orgname . '</OrganizationName>
</Organization>
</EntityDescriptor>';
return $meta;
}
}
class LassoSPKitMetadataLiberty {
static function generateMetadata($baseUrl, $orgname, $publickey) {
$meta = "";
$meta .=
'<?xml version="1.0"?>
<EntityDescriptor
providerID="' . $baseUrl . '/liberty/metadata" xmlns="urn:liberty:metadata:2003-08" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<SPDescriptor>';
// Public key
$meta .=
'<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:KeyValue>' . htmlspecialchars($publickey) . '</ds:KeyValue>
</ds:KeyInfo>
</KeyDescriptor>';
// Endpoints
$meta .=
'<SOAPEndpoint>' . $baseUrl .'/liberty/soap</SOAPEndpoint>
<SingleLogoutServiceURL>' . $baseUrl . '/liberty/sloRedirect</SingleLogoutServiceURL>
<SingleLogoutServiceReturnURL>'. $baseUrl .'/liberty/sloResponse</SingleLogoutServiceReturnURL>
<FederationTerminationServiceURL>'. $baseUrl.'/liberty/defederateNotification</FederationTerminationServiceURL>
<FederationTerminationServiceReturnURL>'. $baseUrl.'/liberty/defederateReturn</FederationTerminationServiceReturnURL>
<AssertionConsumerServiceURL>' . $baseUrl . '/liberty/ssoAssertionConsumer</AssertionConsumerServiceURL>
';
// TODO select supported profiles by config
$meta .= "<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-sp-http</SingleLogoutProtocolProfile>\n";
$meta .= "<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-sp-soap</SingleLogoutProtocolProfile>\n";
$meta .= "<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-idp-http</SingleLogoutProtocolProfile>\n";
$meta .= "<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-idp-soap</SingleLogoutProtocolProfile>\n";
$meta .= "<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-sp-http</FederationTerminationNotificationProtocolProfile>\n";
$meta .= "<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-sp-soap</FederationTerminationNotificationProtocolProfile>\n";
$meta .= "<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-idp-http</FederationTerminationNotificationProtocolProfile>\n";
$meta .= "<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-idp-soap</FederationTerminationNotificationProtocolProfile>\n";
$meta .= "<AuthnRequestsSigned>true</AuthnRequestsSigned>
</SPDescriptor>
</EntityDescriptor>";
return $meta;
}
}

View File

@ -0,0 +1,44 @@
<?php
require_once('lassospkit_storage.inc.php');
class LassoSPKitMySqlStore implements LassoSPKitStore {
private $db;
private $table;
function __construct() {
$host = LassoSPKitConfig::get('mysql_host');
$user = LassoSPKitConfig::get('mysql_user');
$password = LassoSPKitConfig::get('mysql_password');
$database = LassoSPKitConfig::get('mysql_database');
$this->table = $table = LassoSPKitConfig::get('mysql_table');
$this->db = mysql_connect($host, $user, $password);
mysql_select_db($database);
mysql_query('CREATE TABLE IF NOT EXISTS ' . $table . '(nameid varchar(50), record varchar(2000), PRIMARY KEY (nameid))', $this->db);
}
function get($key) {
$result = mysql_query('SELECT record FROM ' . $this->table, $this->db);
if ($result) {
return @unserialize(mysql_result($result, 0));
} else {
return null;
}
}
function __destruct() {
mysql_close($this->db);
}
function set($key,$value) {
$sql = sprintf("REPLACE %s VALUES ('%s','%s')",
$this->table,
mysql_real_escape_string($key),
mysql_real_escape_string(serialize($record)));
$result = mysql_query($sql, $this->db);
}
function delete($key) {
$sql = sprintf("DELETE FROM %s WHERE nameid = '%s'",
$this->table,
mysql_real_escape_string($key));
mysql_query($sql, $this->db);
}
function alias($key,$alias) {
}
}

View File

@ -0,0 +1,90 @@
<?php
require_once('lassospkit_utils_session.inc.php');
require_once('lassospkit_config.inc.php');
/** This file contains the public front-end API
to the LassoSPKit for PHP.
The idea is to limit interaction at the minimum.
If lassospkit_nameid() is null the you are not logged
to an IdP.
To obtain the nameID associated with login to an IdP,
just redirect the user's browser using
lassospkit_websso_redirect($allowCreate). The allowCreate
defines if you want a new federation created or only accept
previously defined federation (the case if you wan to retrieve
a previously established federation).
*/
/** If this session contains the result of a recent WebSSO return
the retrieved nameID. */
function lassospkit_nameid() {
return LassoSPKitUtilsSession::getNameID();
}
function lassospkit_set_nameid($nameid) {
LassoSPKitUtilsSession::setNameID($nameid);
}
/** Returns the userid associated to the current, if any. */
function lassospkit_userid() {
return LassoSPKitUtilsSession::getUserID();
}
/** If last interaction resulted in an error,
* return a human readable description. */
function lassospkit_error() {
return LassoSPKitUtilsSession::getLastError();
}
/** Return an opaque string representing
federation informations as result of the last
liberty exchange.
*/
function lassospkit_federation() {
return LassoSPKitUtilsSession::getFederation();
}
/** Set the opaque string representing
federation informations as result of the last
liberty exchange.
*/
function lassospkit_set_federation($federation) {
LassoSPKitUtilsSession::setFederation($federation);
}
/* Return the URL where to redirect a user when liberty authentification
* is required for existing federation or to get a transient one.
*/
function lassospkit_login_redirect($relay, $federate = TRUE) {
LassoSPKitUtilsSession::setRelayState('login',$relay);
LassoSPKitUtilsSession::setParams('login',array('federate'=>$federate));
return LassoSPKitConfig::get('baseUrl') . "/" . LassoSPKitConfig::get('conformance') . '/login';
}
/* Return the URL where to redirect a user to create a new federation, or
* get an existing one.
* Eventually pass a username to auto-store the new federation.
*/
function lassospkit_federate_redirect($relay) {
LassoSPKitUtilsSession::setRelayState('federate',$relay);
return LassoSPKitConfig::get('baseUrl') . "/" . LassoSPKitConfig::get('conformance') . '/federate';
}
/** Sets the userid to associate to this nameID, during
the next WebSSO interaction.
Only useful if you activated autofederation. */
function lassospkit_set_userid() {
LassoSPKitUtilsSession::setUserID($nameid);
}
/* Return the URL where to redirect a user to initiated defederation of the current nameid. */
function lassospkit_defederation_redirect($relay) {
LassoSPKitUtilsSession::setRelayState('defederation',$relay);
return LassoSPKitConfig::get('baseUrl') . "/" . LassoSPKitConfig::get('conformance') . '/defederate';
}
function lassospkit_logout_redirect($relay) {
LassoSPKitUtilsSession::setRelayState('slo',$relay);
return LassoSPKitConfig::get('baseUrl') . "/" . LassoSPKitConfig::get('conformance') . '/slo';
}
LassoSPKitUtilsSession::setRelayState('error', '../..');

View File

@ -0,0 +1,158 @@
<?php
require_once('lassospkit_datadir.inc.php');
require_once('lassospkit_config.inc.php');
require_once('lassospkit_debug.inc.php');
require_once('lassospkit_saml_common.inc.php');
require_once('lassospkit_lib.inc.php');
class LassoSPKitSaml2 extends LassoSPKitSAMLCommon {
public function __construct(LassoSPKitGenericSession $session) {
parent::__construct($session);
if (!$this->initServer(lassospkit_datadir() . "/saml2")) {
throw new Exception("Construction de l'objet SAML2 impossible");
}
}
/** Overloaded method to serve as callback to common SSO method. */
protected function ssoNameIdPolicyConfig(LassoLogin $login, $blob) {
$request = $login->request;
$nameidpolicy = $request->NameIDPolicy;
$nameidpolicy->format = $blob['nameIDFormat'];
$nameidpolicy->allowCreate = $blob['allowCreate'];
}
public function sso($create = TRUE, $federate = TRUE) {
if ($federate) {
$format = LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT;
} else {
$format = LASSO_SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT;
}
return $this->ssoInit($create,$format);
}
public function ssoInit(
$allowCreate = TRUE,
$nameIDFormat = LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
$remoteID = null,
$method = LASSO_HTTP_METHOD_REDIRECT,
$isConsentObtained = FALSE,
$forceAuthn = FALSE,
$isPassive = FALSE)
{
$login = null;
return parent::ssoCommon($login, $remoteID, $method, $isConsentObtained, $forceAuthn, $isPassive, array('nameIDFormat'=>$nameIDFormat, 'allowCreate' => $allowCreate));
}
/** Defederation, convert to NameIdManagement protocol **/
public function initiateFTNotification($method = LASSO_HTTP_METHOD_SOAP,$remoteID = null)
{
$ok = $this->initiateNameIdManagement(null, $method, $remoteID);
parent::initiateFTNotification($method,$remoteID);
return $ok;
}
/** Name Id Management, SP inititated */
/* Request */
public function initiateNameIdManagement($newNameID, $method = LASSO_HTTP_METHOD_SOAP, $remoteID = null) {
$ret = 0;
lassospkit_debuglog("initiateNIDManagement NNID: $newNameID Meth: $method RID: $remoteID ");
$ok = 1 && $nidmanagement = new LassoNameIdManagement($this->server);
$this->findFederation($nidmanagement);
$ok = $ok && ! $ret = $nidmanagement->initRequest($remoteID, $newNameID, $method);
$ok = $ok && ! $ret = $nidmanagement->buildRequestMsg();
switch ($method) {
case LASSO_HTTP_METHOD_REDIRECT:
$this->keepProfile($nidmanagement);
$this->finishRedirectRequest($nidmanagement, $ret, $ok);
break;
case LASSO_HTTP_METHOD_SOAP:
$this->finishSOAPRequest($nidmanagement, $ret, $ok, $response);
$ok = $ok && $this->processResponseNameIdManagement($response, $nidmanagement);
break;
case LASSO_HTTP_METHOD_ARTIFACT_GET:
case LASSO_HTTP_METHOD_ARTIFACT_POST:
case LASSO_HTTP_METHOD_POST:
default:
LassoSPKitHelper::notImplemented();
}
if (! $ok) {
lassospkit_debuglog("NID failed Ret: $ret Exp: " . $this->exception);
$this->status = gettext('La défédération a échoué');
}
return $ok;
}
function processRedirectResponseNameIdManagement() {
$ret = 0;
$nidmanagement = null;
$ok = $this->processResponseNameIdManagement($_SERVER['QUERY_STRING'], $nidmanagement);
return $ok;
}
/** Response **/
public function processResponseNameIdManagement($message, &$nidmanagement)
{
$ret = 0;
$ok = 1;
lassospkit_debuglog("NameIdManagement SP initiated Response");
if ($nidmanagement == null) {
$ok = $ok && $nidmanagement = LassoNameIdManagement::newFromDump($this->server, $this->restoreProfile());
if ($ok) {
$this->findFederation($nidmanagement);
}
}
$ok = $ok && ! $ret = $nidmanagement->processResponseMsg($message);
if ($ok || $ret > 0) {
$this->saveFederation($nidmanagement);
}
if ($ret != 0) {
$this->setRet($ret);
}
return $ok;
}
/** Name Id Management request IdP iniated */
public function processRedirectRequestNameIdManagement() {
return processRequestNameIdManagement(LASSO_HTTP_METHOD_REDIRECT,
$_SERVER['QUERY_STRING']);
}
public function processSOAPRequestSLO() {
$contents = $this->receiveSoapMessage();
return processRequestSLO(LASSO_HTTP_METHOD_SOAP,
$contents);
}
private function processRequestNameIdManagement($method, $message)
{
lassospkit_debuglog("NameIdManagement request handling");
$ret = 0;
$ok = 1;
$ok = $ok && $nidmanagement = new LassoNameIdManagement($this->server);
$ok = $ok && ! $ret = $nidmanagement->processRequestMsg($message);
$this->findFederation($nidmanagement);
$ok = $ok && ! $ret = $nidmanagement->validateRequest();
if ($ok) {
LassoSPKitHelper::changeFederation($nidmanagement, $this->session, $nidmanagement->request->NewID);
}
$this->finishResponse($method, $nidmanagement, $ret, $ok);
if (! $ok) {
$this->status = gettext('La requête de défédération a échoué');
}
return $ok;
}
function keepProfile(LassoProfile $profile) {
$fed = @unserialize(LassoSPKitUtilsSession::getFederation());
if ($fed == null) {
$fed = array();
}
$fed['profile'] = $profile->dump();
LassoSPKitUtilsSession::setFederation(serialize($fed));
}
function restoreProfile() {
$fed = LassoSPKitUtilsSession::getFederation();
if ($fed == null)
return null;
$fed = @unserialize($fed);
if ($fed == null)
return null;
if (isset($fed['profile'])) {
$profile = @$fed['profile'];
unset($fed['profile']);
} else {
return null;
}
LassoSPKitUtilsSession::setFederation(serialize($fed));
return $profile;
}
}

View File

@ -0,0 +1,354 @@
<?
require_once('lassospkit_config.inc.php');
require_once('lassospkit_debug.inc.php');
require_once('lassospkit_lib.inc.php');
require_once('lassospkit_generic_session.inc.php');
/**
* TODO: initServer();
*/
class LassoSPKitSAMLCommon {
protected $session;
protected $server;
/** Error handling */
protected $reset_status = 0;
protected $human_status = "";
protected $ret = 0;
public $ret_str = "";
protected $exception = null;
public function __construct(LassoSPKitGenericSession $session) {
$this->session = $session;
}
/* Accessors */
/* Status is a human readable and translatable string. */
protected function setStatus($str) {
$this->human_status = gettext($str);
}
protected function getStatus() {
return $this->human_status;
}
/* Ret is the return code from the last error returning
lasso function. */
protected function setRet($ret, $prefix = "") {
$this->ret = $ret;
if ($ret != 0) {
$this->ret_str = strError($ret);
LassoSPKitUtilsSession::setLastError($prefix . $this->ret_str);
} else {
$this->ret_str = "";
}
}
protected function getRet() {
return $this->ret . ":" . $this->ret_str;
}
/** Create the server object by retrieving the configuration from
the data object. */
function initServer($base) {
if ($this->server) {
return 1;
}
$spmeta = $base . "/" . SP_METADATA;
$idpmeta = $base . "/../" . IDP_METADATA;
$pkey = $base . "/" . PRIVATE_KEY;
$ok = $this->checkFile($spmeta);
$ok = $ok && $this->checkFile($idpmeta);
$ok = $ok && $this->checkFile($pkey);
$ok = $ok
&& $server = new LassoServer($spmeta, $pkey, NULL, NULL);
$ok = $ok
&& ! $ret = $server->addProvider(LASSO_PROVIDER_ROLE_IDP
,$idpmeta,null, null);
if (! $ok) {
lassospkit_debuglog("Erreur création serveur: Ret=$ret Msg=" . strError($ret));
return 0;
} else {
$this->server = $server;
return $server;
}
}
protected static function checkFile($file) {
if (! file_exists($file)) {
lassospkit_debuglog("File " . $file . " is absent, can't construct server object");
return 0;
}
return 1;
}
/*** Helper functions ***/
protected function ssoNameIdPolicyConfig($blob) {
throw new Exception("Must be overloaded!!");
}
/** Helper function to do redirects. */
protected function doRedirect(LassoProfile $profile) {
$this->session->doRedirect($profile->msgUrl);
}
/** Return a normal HTTP response, for SOAP Response binding */
protected function doResponse(LassoProfile $profile) {
$this->session->doResponse('text/xml', $profile->msgBody);
}
/** Read a soap message from stdin */
protected function receiveSOAPMessage() {
$contents = file_get_contents("php://input");
return $contents;
}
/** Retrieve the response message associated to an artifact string,
method is the method used to transmit the artifact.
This method makes a soap call to resolve the artifact, it is synchronous
so can potentially take times.
*/
protected function artifactResolve(LassoProfile $profile, $query, $method, &$ok, &$ret) {
$ok = $ok && ! $ret = $profile->initRequest($query, $method);
$ok = $ok && ! $ret = $profile->buildRequestMsg();
$ok = $ok && $content = LassoSPKitHelper::SoapCallWithProfile($profile);
$ok = $ok && ! $ret = $profile->processResponseMsg($content);
if (! $ok) {
$this->setRet($ret);
}
return $ok;
}
/** Finish a request with a redirect transport */
protected function finishRedirectRequest(LassoProfile $profile, &$ret, &$ok) {
if ($ok) {
$this->doRedirect($profile);
}
}
/** Finish a request with a SOAP transport */
protected function finishSOAPRequest(LassoProfile $profile, &$ret, &$ok, &$response) {
if ($ok) {
$response = LassoSPKitHelper::SoapCallWithProfile($profile);
}
}
protected function finishResponse(LassoProfile $profile, $method, &$ret, &$ok) {
$ok = $ok && ! $ret = $profile->buildResponse();
switch ($method) {
case LASSO_HTTP_METHOD_REDIRECT:
$this->doRedirect($profile);
break;
case LASSO_HTTP_METHOD_SOAP:
$this->doResponse($profile);
break;
default:
LassoSPKitHelper::notImplemented();
}
}
/** Web SSO protocol */
/** Start a WebSSO interaction. Initiate the redirect using
the doRedirect method of the session object.
Calls ssoNameIdPolicyConfig on the session object to initialize.
*/
protected function ssoCommon(&$login,
$remoteID,
$method,
$isConsentObtained,
$forceAuthn,
$isPassive,
$blob) {
lassospkit_debuglog("SSO request initiated RID: $remoteID Meth: $method Consent: $isConsentObtained ForceAuthn: $forceAuthn Passive: $isPassive " . var_export($blob,1) );
$ok = 1 && $login = new LassoLogin($this->server);
$ok = $ok && ! $ret = $login->initAuthnRequest($remoteID,$method);
$ok = $ok && $request = $login->request;
$ok = $ok && $nameidpolicy = $request->NameIDPolicy;
if ($ok) {
$this->ssoNameIdPolicyConfig($login, $blob);
$request->consent = $isConsentObtained;
$request->ForceAuthn = $forceAuthn;
$request->IsPassive = $isPassive;
}
$ok = $ok && ! $ret = $login->buildAuthnRequestMsg();
if (! $ok) {
lassospkit_debuglog("SSO request failed ErrCode: $ret");
$this->setStatus("Erreur durant l'authentification");
$this->setRet($ret);
} else {
switch($method) {
case LASSO_HTTP_METHOD_REDIRECT:
$this->doRedirect($login);
break;
default:
LassoSPKitHelper::notImplemented();
}
}
return $ok;
}
/** Method to consume response to auth requests. */
function ssoConsumer($method, $message) {
$ret = 0;
lassospkit_debuglog("Consuming SSO assertion");
$ok = 1 && $login = new LassoLogin($this->server);
switch ($method) {
case LASSO_HTTP_METHOD_ARTIFACT_GET:
case LASSO_HTTP_METHOD_ARTIFACT_POST:
$ok = $ok && $this->artifactResolve($login,
$message,
$method, $ok, $ret);
break;
case LASSO_HTTP_METHOD_POST:
$ok = $ok && ! $ret = $this->processResponseMsg($message);
break;
}
if ($ok) {
try {
$this->findFederation($login);
} catch (LassoProfileFederationNotFoundError $error) {
} catch (LassoProfileNameIdentifierNotFoundError $error) {
$ok = 0;
$ret = LASSO_PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND;
}
}
$ok = $ok && ! $ret = $login->acceptSso();
if ($login->assertion) {
LassoSPKitHelper::assertionExtractAttributes($login->assertion, $attributes);
$this->session->processAttributes($attributes);
}
if ($ok) {
$this->saveFederation($login);
}
if (! $ok) {
$this->setStatus("Le SSO a échoué");
$this->setRet($ret);
}
return $ok;
}
/** Web SLO methods */
/* SP initiated */
public function initiateSLO($method = LASSO_HTTP_METHOD_SOAP, $remoteID = null)
{
$ret = 0;
lassospkit_debuglog("SLO SP initiated request");
$ok = 1 && $logout = new LassoLogout($this->server);
$this->findFederation($logout);
$ok = $ok && ! $ret = $logout->initRequest($remoteID, $method);
$ok = $ok && ! $ret = $logout->buildRequestMsg();
if ($ok) {
switch ($method) {
case LASSO_HTTP_METHOD_REDIRECT:
$this->finishRedirectRequest($logout, $ret, $ok);
break;
case LASSO_HTTP_METHOD_SOAP:
$this->finishSOAPRequest($logout, $ret, $ok, $response);
$ok = $ok && $this->processResponseSLO($logout, $response);
break;
case LASSO_HTTP_METHOD_ARTIFACT_GET:
case LASSO_HTTP_METHOD_ARTIFACT_POST:
case LASSO_HTTP_METHOD_POST:
default:
LassoSPKitHelper::notImplemented();
}
}
if (! $ok) {
lassospkit_debuglog("SLO SP initiated request failed ErrCode: $ret");
$this->setStatus("Le SSO a échoué");
$this->setRet($ret);
}
return $ok;
}
public function processRedirectResponseSLO() {
$ret = 0;
$logout = null;
$ok = $this->processResponseSLO($logout, $_SERVER['QUERY_STRING']);
if (! $ok) {
lassospkit_debuglog("SLO SP initiated response failed ErrCode: $ret");
$this->setStatus("Le SLO a échoué");
$this->setRet($ret);
}
return $ok;
}
protected function processResponseSLO(&$logout, $message) {
$ret = 0;
$ok = 1;
lassospkit_debuglog("SLO SP initiated Response");
if (! $logout) {
$ok = $ok && $logout = new LassoLogout($this->server);
$this->findFederation($logout);
}
$ok = $ok && ! $ret = $logout->processResponseMsg($message);
$prefix = "";
switch ($ret) {
case 0:
break;
case LASSO_DS_ERROR_INVALID_SIGNATURE:
lassospkit_debuglog("Logout warn: invalid signature");
$prefix = "Warning: ";
$ok = 1;
break;
case LASSO_LOGOUT_ERROR_REQUEST_DENIED:
lassospkit_debuglog("Logout warn: request denied");
$prefix = "Warning: ";
$ok = 1;
break;
case LASSO_LOGOUT_ERROR_UNKNOWN_PRINCIPAL:
lassospkit_debuglog("Unknown principal on logout, probably session stopped already on IdP");
$prefix = "Warning: ";
$ok = 1;
break;
case LASSO_PROFILE_ERROR_INVALID_QUERY:
lassospkit_debuglog("Invalid response");
$prefix = "Error: ";
$ok = 0;
break;
default:
lassospkit_debuglog("SLO Response ErrCode: $ret");
$prefix = "Error: ";
$ok = 0;
break;
}
if ($ok == 1) {
$this->saveFederation($logout);
$this->session->logout();
}
if ($ret != 0) {
$this->setRet($ret, $prefix);
lassospkit_debuglog("SLO Res Code: $ret");
}
return $ok;
}
/** IDP initiated SLO **/
public function processRedirectRequestSLO() {
return processRequestSLO(LASSO_HTTP_METHOD_REDIRECT,
$_SERVER['QUERY_STRING']);
}
public function processSOAPRequestSLO() {
$contents = $this->receiveSoapMessage();
return processRequestSLO(LASSO_HTTP_METHOD_SOAP,
$contents);
}
protected function processRequestSLO(&$method, $message) {
lassospkit_debuglog("SLO Request handling");
$ret = 0;
$ok = $ok && $logout = new LassoLogout($this->server);
$ok = $ok && ! $ret = $logout->processRequestMsg($content);
$this->findFederation($logout);
$ok = $ok && ! $ret = $logout->validateRequest();
if ($ok) {
if ($method == LASSO_HTTP_METHOD_ANY) {
$method = $logout->http_request_method;
} else {
$ok = ($method == $logout->http_request_method);
}
}
$this->finishResponse($method, $logout, $ret, $ok);
if (! $ok) {
lassospkit_debuglog("SLO Request handling failed ErrCode: $ret");
$this->setStatus("Le SLO a échoué");
$this->setRet($ret);
} else {
$this->session->logout();
}
return $ok;
}
protected function saveFederation(LassoProfile $profile) {
LassoSPKitHelper::saveFederation($profile, $this->session);
}
protected function findFederation(LassoProfile $profile) {
LassoSPKitHelper::findFederation($profile, $this->session);
}
/** Federation termination **/
public function initiateFTNotification($method = LASSO_HTTP_METHOD_SOAP, $remoteID = null) {
$this->session->changeFederation(null, null);
}
}

View File

@ -0,0 +1,10 @@
<?
interface LassoSPKitStore {
public function get($key);
public function set($key, $value);
public function delete($key);
public function alias($key1,$key2);
public function rename($key1, $key2);
}
?>

View File

@ -0,0 +1,65 @@
<?php
require_once('lassospkit_defines.inc.php');
class LassoSPKitUtils {
static public function myself() {
return 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
}
static public function mydir() {
return 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']);
}
static public function relativePathToURL($rel) {
$abs = "";
if (isset($_SERVER['HTTPS'])) {
$abs = "https://";
} else {
$abs = "http://";
}
$abs = $abs . $_SERVER['HTTP_HOST'];
$abs = $abs . dirname($_SERVER['PHP_SELF']) . "/";
$abs = $abs . $rel;
return $abs;
}
static function checkCanWrite($dir, &$error) {
$path = $dir . "/" . _CHECK_FILENAME;
$ok = ! file_exists($path) || unlink($path);
$ok = $ok && $file = fopen($path,"w");
$ok = $ok && fclose($file);
unlink($path);
if (! $ok) {
$error = "Cannot write into " . $dir;
}
return $ok;
}
static function generatePrivateKey($file,&$error) {
if (! is_file(OPENSSL_BIN)) {
$error = "SSL Generate: Can't find OpenSSL at " . OPENSSL_BIN;
return 0;
}
exec('/usr/bin/openssl genrsa -out ' . $file . ' 2048', $foo, $ret);
if ($ret != 0) {
$error = "SSL Generate: OpenSSL returned non-0 while computing the private key, check your ssl installation.";
return 0;
}
return 1;
}
public static function extractPublicKey($file,&$public,&$error) {
if (! is_file(OPENSSL_BIN)) {
$error = "SSL Generate: Can't find OpenSSL at " . OPENSSL_BIN;
return 0;
}
$tempfname = tempnam(TEMPDIR, "lassospkit-public-key");
$cmdline = '/usr/bin/openssl rsa -in ' . $file . ' -pubout -out ' . $tempfname;
exec($cmdline, $foo, $ret);
if ($ret != 0) {
$error = "SSL Generate: OpenSSL return non-0 while extracting the public key from the private key file, check your ssl installation. $cmdline";
return 0;
}
if (! $public = file_get_contents($tempfname)) {
$error = "SSL Generate: Extracted public key is empty. See $tempfname.";
return 0;
}
@unlink($tempfname);
return 1;
}
}

View File

@ -0,0 +1,175 @@
<?php
/** This object encapsulate the communication between the frontend and the
backend of the LassoSPkit.
If you use autofederation, i.e if you let the backend store relations between
NameID and your local userId, you would only use get/setUserID().
If not you must store Federation,NameID and UserID together in the application
code.
*/
class LassoSPKitUtilsSession {
private static $key = "__LassoSPKitSessionObject";
private static $THIS;
private $vars;
/** If we getted the last error, clear it. */
private $clears = array();
/** The supported keys */
static $keys = array(
'NameID'=>0,
'UserID'=>0,
'Federation'=>0,
'LastError'=>0,
'loginRelayState'=>0,
'federateRelayState'=>0,
'ssoRelayState'=>0,
'sloRelayState'=>0,
'defederationRelayState'=>0,
'nidmanagementRelayState'=>0,
'errorRelayState'=>0,
'loginParams'=>0,
'federateParams'=>0,
'sloParams'=>0,
'defederationParams'=>0);
/** The keys that must not survive one communication (one set followed by one get). */
static $keysToClearAfterGet = array(
'LastError'=>0,
'loginRelayState'=>0,
'federateRelayState'=>0,
'ssoRelayState'=>0,
'sloRelayState'=>0,
'defederationRelayState'=>0,
'nidmanagementRelayState'=>0,
'errorRelayState'=>0,
'loginParams'=>0,
'federateParams'=>0,
'sloParams'=>0,
'defederationParams'=>0);
private function __construct() {
if (! isset($_SESSION)) {
throw new Exception("LassoSPKit cannot work without sessions.");
}
if (isset($_SESSION[self::$key])) {
$t = @unserialize($_SESSION[self::$key]);
if ($t && is_array($t)) {
$this->vars = $t;
} else {
// Malformed session object, reset
$this->vars = array();
self::clear();
}
} else {
$this->vars = array();
}
}
/** In the finalizer, reset one-shot keys, then
store the rest in the PHP session */
function __destruct() {
foreach ($this->clears as $k => $v) {
unset($this->vars[$k]);
}
$_SESSION[self::$key] = serialize($this->vars);
}
/** Get the singleton object to communicate
with the backend/fronted of the LassoSPKit. */
public static function getSingleton() {
if (! self::$THIS) {
self::$THIS = new LassoSPKitUtilsSession();
}
return self::$THIS;
}
function get($key) {
if (! isset(self::$keys[$key])) {
throw new Exception("The key $key is not supported by LassoSPKitUtilsSession");
}
if (isset(self::$keysToClearAfterGet[$key])) {
$this->clearAtShutdown($key);
}
if (isset($this->vars[$key])) {
return $this->vars[$key];
}
return null;
}
function set($key, $value) {
if (! isset(self::$keys[$key])) {
throw new Exception("The key $key is not supported by LassoSPKitUtilsSession");
}
if (isset(self::$keysToClearAfterGet[$key])) {
$this->doNotClearAtShutdown($key);
}
$this->vars[$key] = $value;
}
function clearAtShutdown($key) {
$this->clears[$key] = 1;
}
function doNotClearAtShutdown($key) {
unset($this->clears[$key]);
}
/** Return the NameID resulting
* of the last WebSSO or passed from the
* application to other profiles thant SSO,
* like SLO, FederationTermination or
* NameIdManagement. */
static function getNameID() {
$athis = self::getSingleton();
return $athis->get('NameID');
}
/* Helper static functions */
/** Clear the session object of all communication
from the LassoSPKit. */
static function clear() {
unset($_SESSION[self::$key]);
}
/** Set the NameID to transmit. */
static function setNameID($NameID) {
$athis = self::getSingleton();
$athis->set('NameID',$NameID);
}
static function getUserID() {
$athis = self::getSingleton();
return $athis->get('UserID');
}
static function setUserID($UserID) {
$athis = self::getSingleton();
$athis->set('UserID',$UserID);
}
static function getLastError() {
$athis = self::getSingleton();
return $athis->get('LastError');
}
static function setLastError($LastError) {
$athis = self::getSingleton();
$athis->set('LastError',$LastError);
}
static function getFederation() {
$athis = self::getSingleton();
return $athis->get('Federation');
}
static function setFederation($Federation) {
$athis = self::getSingleton();
$athis->set('Federation',$Federation);
}
static function getRelayState($profile) {
$athis = self::getSingleton();
return $athis->get($profile . "RelayState");
}
static function setRelayState($profile, $RelayState) {
$athis = self::getSingleton();
$athis->set($profile."RelayState", $RelayState);
}
static function getParams($profile) {
$athis = self::getSingleton();
return $athis->get($profile . "Params");
}
static function setParams($profile, $Params) {
$athis = self::getSingleton();
$athis->set($profile ."Params", $Params);
}
}