From 9dc5e9ca9b6d6349fa1dc45b587e22da6c7a343b Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Mon, 3 Aug 2009 12:46:00 +0000
Subject: [PATCH] saml2: Add debug endpoint.

This patch introduces a debug-endpont, which can receive SAML2 messages
and show them to the user, before sending them to their real
destination.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1604 44740490-163a-0410-bde0-09ae8108e29a
---
 modules/saml2/www/debug.php | 83 +++++++++++++++++++++++++++++++++++++
 templates/post-debug.php    | 51 ++++++++++++++++++++++-
 2 files changed, 132 insertions(+), 2 deletions(-)
 create mode 100644 modules/saml2/www/debug.php

diff --git a/modules/saml2/www/debug.php b/modules/saml2/www/debug.php
new file mode 100644
index 000000000..7c6b44ced
--- /dev/null
+++ b/modules/saml2/www/debug.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * Endpoint for debugging sent SAML-messages.
+ *
+ * This endpoint will display the message to the user before passing it
+ * to its destination.
+ *
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+
+$globalConfig = SimpleSAML_Configuration::getInstance();
+
+if (array_key_exists('SAMLRequest', $_REQUEST)) {
+	$type = 'SAMLRequest';
+} elseif (array_key_exists('SAMLResponse', $_REQUEST)) {
+	$type = 'SAMLResponse';
+} else {
+	throw new SimpleSAML_Error_BadRequest('Unknown SAML2 message type.');
+}
+
+$message = $_REQUEST[$type];
+
+$message = @base64_decode($message);
+if ($message === FALSE) {
+	throw new SimpleSAML_Error_BadRequest('Unable to base64-decode message.');
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'GET') {
+	$message = @gzinflate($message);
+	if ($message === FALSE) {
+		throw new SimpleSAML_Error_BadRequest('Unable to gzinflate message.');
+	}
+}
+
+$document = new DOMDocument();
+if (!$document->loadXML($message)) {
+	throw new SimpleSAML_Error_BadRequest('Unable to parse XML.');
+}
+$root = $document->firstChild;
+
+if (!$root->hasAttribute('Destination')) {
+	throw new SimpleSAML_Error_BadRequest('Missing Destination-attribute on root element.');
+}
+$realDestination = $root->getAttribute('Destination');
+
+SimpleSAML_Utilities::formatDOMElement($root);
+$message = $document->saveXML($root);
+
+
+switch($_SERVER['REQUEST_METHOD']) {
+case 'GET':
+	$queryString = $_SERVER['QUERY_STRING'];
+
+	if (strpos($realDestination, '?') === FALSE) {
+		$url = $realDestination . '?' . $queryString;
+	} else {
+		$url = $realDestination . '&' . $queryString;
+	}
+
+	$t = new SimpleSAML_XHTML_Template($globalConfig, 'httpredirect-debug.php');
+	$t->data['url'] = $url;
+	$t->data['message'] = htmlspecialchars($message);
+	$t->show();
+	exit();
+
+case 'POST':
+	$post = $_POST;
+
+	$t = new SimpleSAML_XHTML_Template($globalConfig, 'post-debug.php');
+
+	$t->data['post'] = $post;
+	$t->data['destination'] = $realDestination;
+	$t->data['responseHTML'] = htmlspecialchars($message);
+	$t->show();
+	exit();
+
+default:
+	throw new SimpleSAML_Error_BadRequest('Unexpected request method: ' . var_export($_SERVER['REQUEST_METHOD'], TRUE));
+}
+
+?>
\ No newline at end of file
diff --git a/templates/post-debug.php b/templates/post-debug.php
index 2402f1afb..a1d4a9c21 100644
--- a/templates/post-debug.php
+++ b/templates/post-debug.php
@@ -2,6 +2,50 @@
 	$this->data['icon'] = 'debug.png';
 	$this->data['autofocus'] = 'sendbutton';
 	$this->includeAtTemplateBase('includes/header.php'); 
+
+if (array_key_exists('post', $this->data)) {
+	$post = $this->data['post'];
+} else {
+	/* For backwards compatibility. */
+	assert('array_key_exists("response", $this->data)');
+	assert('array_key_exists("RelayStateName", $this->data)');
+	assert('array_key_exists("RelayState", $this->data)');
+
+	$post = array(
+		'SAMLResponse' => $this->data['response'],
+		$this->data['RelayStateName'] => $this->data['RelayState'],
+	);
+}
+
+/**
+ * Write out one or more INPUT elements for the given name-value pair.
+ *
+ * If the value is a string, this function will write a single INPUT element.
+ * If the value is an array, it will write multiple INPUT elements to
+ * recreate the array.
+ *
+ * @param string $name  The name of the element.
+ * @param string|array $value  The value of the element.
+ */
+function printItem($name, $value) {
+	assert('is_string($name)');
+	assert('is_string($value) || is_array($value)');
+
+	if (is_string($value)) {
+		echo '<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />';
+		return;
+	}
+
+	/* This is an array... */
+	foreach ($value as $index => $item) {
+		printItem($name . '[' . var_export($index, TRUE) . ']', $item);
+	}
+}
+
+foreach ($post as $name => $value) {
+	printItem($name, $value);
+}
+
 ?>
 
 
@@ -11,8 +55,11 @@
 		<p><?php echo($this->t('{admin:debug_sending_message_text_button}')); ?></p>
 		
 		<form method="post" action="<?php echo htmlspecialchars($this->data['destination']); ?>">
-			<input type="hidden" name="SAMLResponse" value="<?php echo htmlspecialchars($this->data['response']); ?>" />
-			<input type="hidden" name="<?php echo htmlspecialchars($this->data['RelayStateName']); ?>" value="<?php echo htmlspecialchars($this->data['RelayState']); ?>" />
+<?php
+foreach ($post as $name => $value) {
+	printItem($name, $value);
+}
+?>
 			<input type="submit" value="<?php echo($this->t('{admin:debug_sending_message_send}')); ?>" id="sendbutton" />
 		</form>
 
-- 
GitLab