From f5aa2687f59479952439a0b9ae2e4a43bb021a59 Mon Sep 17 00:00:00 2001
From: Andy Summers <andrew.summers@wisc.edu>
Date: Wed, 27 Jul 2016 10:31:11 -0500
Subject: [PATCH] Fix bug with non-HTTP Shib sessions being valid for HTTP
 sessions

Previously, the `PreauthUserDetailsProvider` was only checking that a
valid Shib session existed by looking for the regular or HTTP Shib
session header. This check is now strengthened by validating the
correct header exists for the correct instance.
---
 composer.json                                 |   2 +-
 .../FederatedPreauthUserDetailsProvider.php   |   4 +-
 ...ederatedPreauthUserDetailsProviderTest.php | 102 ------------------
 ...ederatedPreauthUserDetailsProviderTest.php |  79 ++++++++++++++
 .../doit/LocalUserDetailsProviderTest.php     |   2 +-
 .../{testuser.json => localuser.json}         |   3 +-
 src/test/resources/testuser_http.json         |  16 +++
 7 files changed, 100 insertions(+), 108 deletions(-)
 delete mode 100644 src/test/edu/wisc/doit/FederatedPreauthUserDetailsProviderTest.php
 create mode 100644 src/test/edu/wisc/doit/HTTPFederatedPreauthUserDetailsProviderTest.php
 rename src/test/resources/{testuser.json => localuser.json} (84%)
 create mode 100644 src/test/resources/testuser_http.json

diff --git a/composer.json b/composer.json
index 0e153b2..c60f3b3 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,7 @@
   "type": "library",
   "homepage": "https://git.doit.wisc.edu/adi-ia/uw-php-security",
   "license": "Apache-2.0",
-  "version": "1.0.2",
+  "version": "1.0.3",
   "authors": [{
     "name": "UW-Madison DoIT ADI Integrated Applications",
     "email": "adi-ia@lists.wisc.edu",
diff --git a/src/main/edu/wisc/doit/FederatedPreauthUserDetailsProvider.php b/src/main/edu/wisc/doit/FederatedPreauthUserDetailsProvider.php
index 94ea410..a0c17d4 100644
--- a/src/main/edu/wisc/doit/FederatedPreauthUserDetailsProvider.php
+++ b/src/main/edu/wisc/doit/FederatedPreauthUserDetailsProvider.php
@@ -28,8 +28,8 @@ class FederatedPreauthUserDetailsProvider implements UserDetailsProvider
     public function loadUser()
     {
         // Return null if no Shib session is found
-        if (empty(getenv(FederatedPreauthUserDetailsProvider::SHIB_SESSION_ID)) &&
-            empty(getenv(FederatedPreauthUserDetailsProvider::SHIB_SESSION_ID_HTTP))) {
+        if ($this->httpHeaders && !getenv(FederatedPreauthUserDetailsProvider::SHIB_SESSION_ID_HTTP) ||
+            !$this->httpHeaders && !getenv(FederatedPreauthUserDetailsProvider::SHIB_SESSION_ID)) {
             return null;
         }
 
diff --git a/src/test/edu/wisc/doit/FederatedPreauthUserDetailsProviderTest.php b/src/test/edu/wisc/doit/FederatedPreauthUserDetailsProviderTest.php
deleted file mode 100644
index 4accd8e..0000000
--- a/src/test/edu/wisc/doit/FederatedPreauthUserDetailsProviderTest.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-use edu\wisc\doit\UserDetailsProvider;
-use edu\wisc\doit\FederatedPreauthUserDetailsProvider;
-
-/**
- * Tests for {@link FederatedPreauthUserDetailsProvider}.
- */
-class FederatedPreauthUserDetailsProviderTest extends \PHPUnit_Framework_TestCase
-{
-
-    /** @var array */
-    private $attributes;
-
-    /** @var UserDetailsProvider */
-    private $userProvider;
-
-    /**
-     * Populate putenv with Shib attributes to simulate a logged in user
-     */
-    protected function setUp()
-    {
-        parent::setUp();
-        $jsonString = file_get_contents(__DIR__ . "/../../../resources/testuser.json");
-        if ($jsonString === false) {
-            return null;
-        }
-
-        $this->attributes = json_decode($jsonString, true);
-    }
-
-    public function testLoadUser()
-    {
-        $this->setupHttpPreauthEnvironment();
-        $this->userProvider = new FederatedPreauthUserDetailsProvider(true);
-        $user = $this->userProvider->loadUser();
-        $this->assertNotNull($user);
-        $this->assertEquals("bbadger@wisc.edu", $user->getEppn());
-        $this->assertEquals("UW123A456", $user->getPvi());
-        $this->assertEquals("BUCKINGHAM BADGER", $user->getFullName());
-        $this->assertEquals("bucky.badger@wisc.edu", $user->getEmailAddress());
-        $this->assertEquals("a_source", $user->getSource());
-        $this->assertEquals("123456789", $user->getIsisEmplid());
-        $this->assertEquals("BUCKINGHAM", $user->getFirstName());
-        $this->assertEquals("BADGER", $user->getLastName());
-    }
-
-    public function testLoadUserWithNoEPPN()
-    {
-        $this->setupHttpPreauthEnvironment();
-        $this->userProvider = new FederatedPreauthUserDetailsProvider(true);
-        // Clear Shib session ID to simulate no session
-        putenv(UserDetailsProvider::SHIB_SESSION_ID);
-        $user = $this->userProvider->loadUser();
-        $this->assertNull($user);
-    }
-
-    public function testLoadUserWithNoEmail()
-    {
-        $this->setupHttpPreauthEnvironment();
-        $this->userProvider = new FederatedPreauthUserDetailsProvider(true);
-        // Clear email to simulate no email
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_EMAIL));
-        $user = $this->userProvider->loadUser();
-        $this->assertFalse($user->getEmailAddress());
-    }
-
-    /**
-     * Setup environment to simulate a Preauth (Shib) environment.
-     */
-    private function setupPreauthEnvironment()
-    {
-        putenv(UserDetailsProvider::FED_EPPN . '=' . $this->attributes[UserDetailsProvider::FED_EPPN]);
-        putenv(UserDetailsProvider::FED_SPVI . '=' . $this->attributes[UserDetailsProvider::FED_SPVI]);
-        putenv(UserDetailsProvider::FED_FULLNAME . '=' . $this->attributes[UserDetailsProvider::FED_FULLNAME]);
-        putenv(UserDetailsProvider::FED_FIRST_NAME . '=' . $this->attributes[UserDetailsProvider::FED_FIRST_NAME]);
-        putenv(UserDetailsProvider::FED_LAST_NAME . '=' . $this->attributes[UserDetailsProvider::FED_LAST_NAME]);
-        putenv(UserDetailsProvider::UDDS . '=' . implode(",", $this->attributes[UserDetailsProvider::UDDS]));
-        putenv(UserDetailsProvider::FED_EMAIL . '=' . $this->attributes[UserDetailsProvider::FED_EMAIL]);
-        putenv(UserDetailsProvider::SOURCE . '=' . $this->attributes[UserDetailsProvider::SOURCE]);
-        putenv(UserDetailsProvider::ISIS_EMPLID . '=' . $this->attributes[UserDetailsProvider::ISIS_EMPLID]);
-        putenv(UserDetailsProvider::SHIB_SESSION_ID  . '=' . $this->attributes[UserDetailsProvider::SHIB_SESSION_ID]);
-    }
-
-    /**
-     * Setup environment to simulate HTTP Preauth.
-     */
-    private function setupHttpPreauthEnvironment()
-    {
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_EPPN) . '=' . $this->attributes[UserDetailsProvider::FED_EPPN]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_SPVI) . '=' . $this->attributes[UserDetailsProvider::FED_SPVI]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_FULLNAME) . '=' . $this->attributes[UserDetailsProvider::FED_FULLNAME]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_FIRST_NAME) . '=' . $this->attributes[UserDetailsProvider::FED_FIRST_NAME]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_LAST_NAME) . '=' . $this->attributes[UserDetailsProvider::FED_LAST_NAME]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::UDDS) . '=' . implode(",", $this->attributes[UserDetailsProvider::UDDS]));
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_EMAIL) . '=' . $this->attributes[UserDetailsProvider::FED_EMAIL]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::SOURCE) . '=' . $this->attributes[UserDetailsProvider::SOURCE]);
-        putenv('HTTP_' . strtoupper(UserDetailsProvider::ISIS_EMPLID) . '=' . $this->attributes[UserDetailsProvider::ISIS_EMPLID]);
-        putenv(UserDetailsProvider::SHIB_SESSION_ID  . '=' . $this->attributes[UserDetailsProvider::SHIB_SESSION_ID]);
-    }
-
-}
diff --git a/src/test/edu/wisc/doit/HTTPFederatedPreauthUserDetailsProviderTest.php b/src/test/edu/wisc/doit/HTTPFederatedPreauthUserDetailsProviderTest.php
new file mode 100644
index 0000000..683915a
--- /dev/null
+++ b/src/test/edu/wisc/doit/HTTPFederatedPreauthUserDetailsProviderTest.php
@@ -0,0 +1,79 @@
+<?php
+
+use edu\wisc\doit\UserDetailsProvider;
+use edu\wisc\doit\FederatedPreauthUserDetailsProvider;
+
+/**
+ * Tests for {@link FederatedPreauthUserDetailsProvider}.
+ */
+class HTTPFederatedPreauthUserDetailsProviderTest extends \PHPUnit_Framework_TestCase
+{
+
+    /** @var array */
+    private $attributes;
+
+    /** @var UserDetailsProvider */
+    private $userProvider;
+
+    /**
+     * Populate putenv with Shib attributes to simulate a logged in user
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $jsonString = file_get_contents(__DIR__ . "/../../../resources/testuser_http.json");
+        if ($jsonString === false) {
+            return null;
+        }
+
+        $this->attributes = json_decode($jsonString, true);
+        $this->userProvider = new FederatedPreauthUserDetailsProvider(true);
+
+        putenv($this->mapAttribute(UserDetailsProvider::FED_EPPN) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::FED_EPPN)]);
+        putenv($this->mapAttribute(UserDetailsProvider::FED_SPVI) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::FED_SPVI)]);
+        putenv($this->mapAttribute(UserDetailsProvider::FED_FULLNAME) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::FED_FULLNAME)]);
+        putenv($this->mapAttribute(UserDetailsProvider::FED_FIRST_NAME) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::FED_FIRST_NAME)]);
+        putenv($this->mapAttribute(UserDetailsProvider::FED_LAST_NAME) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::FED_LAST_NAME)]);
+        putenv($this->mapAttribute(UserDetailsProvider::UDDS) . '=' . implode(",", $this->attributes[$this->mapAttribute(UserDetailsProvider::UDDS)]));
+        putenv($this->mapAttribute(UserDetailsProvider::FED_EMAIL) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::FED_EMAIL)]);
+        putenv($this->mapAttribute(UserDetailsProvider::SOURCE) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::SOURCE)]);
+        putenv($this->mapAttribute(UserDetailsProvider::ISIS_EMPLID) . '=' . $this->attributes[$this->mapAttribute(UserDetailsProvider::ISIS_EMPLID)]);
+        putenv(UserDetailsProvider::SHIB_SESSION_ID_HTTP  . '=' . $this->attributes[UserDetailsProvider::SHIB_SESSION_ID_HTTP]);
+    }
+
+    public function testLoadUser()
+    {
+        $user = $this->userProvider->loadUser();
+        $this->assertNotNull($user);
+        $this->assertEquals("bbadger@wisc.edu", $user->getEppn());
+        $this->assertEquals("UW123A456", $user->getPvi());
+        $this->assertEquals("BUCKINGHAM BADGER", $user->getFullName());
+        $this->assertEquals("bucky.badger@wisc.edu", $user->getEmailAddress());
+        $this->assertEquals("a_source", $user->getSource());
+        $this->assertEquals("123456789", $user->getIsisEmplid());
+        $this->assertEquals("BUCKINGHAM", $user->getFirstName());
+        $this->assertEquals("BADGER", $user->getLastName());
+    }
+
+    public function testLoadUserWithNoEPPN()
+    {
+        // Clear Shib session ID to simulate no session
+        putenv(UserDetailsProvider::SHIB_SESSION_ID_HTTP);
+        $user = $this->userProvider->loadUser();
+        $this->assertNull($user);
+    }
+
+    public function testLoadUserWithNoEmail()
+    {
+        // Clear email to simulate no email
+        putenv('HTTP_' . strtoupper(UserDetailsProvider::FED_EMAIL));
+        $user = $this->userProvider->loadUser();
+        $this->assertFalse($user->getEmailAddress());
+    }
+
+    private function mapAttribute($attribute)
+    {
+        return 'HTTP_' . strtoupper($attribute);
+    }
+
+}
diff --git a/src/test/edu/wisc/doit/LocalUserDetailsProviderTest.php b/src/test/edu/wisc/doit/LocalUserDetailsProviderTest.php
index 175219a..52b4bb8 100644
--- a/src/test/edu/wisc/doit/LocalUserDetailsProviderTest.php
+++ b/src/test/edu/wisc/doit/LocalUserDetailsProviderTest.php
@@ -10,7 +10,7 @@ class LocalUserDetailsProviderTest extends \PHPUnit_Framework_TestCase
 
     public function testLoadUser()
     {
-        $userDetailsService = new LocalUserDetailsProvider(__DIR__ . "/../../../resources/testuser.json");
+        $userDetailsService = new LocalUserDetailsProvider(__DIR__ . "/../../../resources/localuser.json");
         $user = $userDetailsService->loadUser();
         $this->assertEquals("bbadger@wisc.edu", $user->getEppn());
         $this->assertEquals("UW123A456", $user->getPvi());
diff --git a/src/test/resources/testuser.json b/src/test/resources/localuser.json
similarity index 84%
rename from src/test/resources/testuser.json
rename to src/test/resources/localuser.json
index 57b252d..a3a5344 100644
--- a/src/test/resources/testuser.json
+++ b/src/test/resources/localuser.json
@@ -11,6 +11,5 @@
   ],
   "eduWisconsinEmailAddress": "bucky.badger@wisc.edu",
   "source": "a_source",
-  "isisEmplid": "123456789",
-  "Shib-Session-Id": "1234567890"
+  "isisEmplid": "123456789"
 }
\ No newline at end of file
diff --git a/src/test/resources/testuser_http.json b/src/test/resources/testuser_http.json
new file mode 100644
index 0000000..7de908f
--- /dev/null
+++ b/src/test/resources/testuser_http.json
@@ -0,0 +1,16 @@
+{
+  "HTTP_EPPN": "bbadger@wisc.edu",
+  "HTTP_EDUWISCONSINSPVI": "UW123A456",
+  "HTTP_CN": "BUCKINGHAM BADGER",
+  "HTTP_EDUWISCONSINCOMMONNAME": "BUCKINGHAM BADGER",
+  "HTTP_EDUWISCONSINGIVENNAME": "BUCKINGHAM",
+  "HTTP_EDUWISCONSINSURNAME": "BADGER",
+  "HTTP_UDDS": [
+    "UW123A456",
+    "UW234A567"
+  ],
+  "HTTP_EDUWISCONSINEMAILADDRESS": "bucky.badger@wisc.edu",
+  "HTTP_SOURCE": "a_source",
+  "HTTP_ISISEMPLID": "123456789",
+  "HTTP_SHIB_SESSION_ID": "1234567890"
+}
\ No newline at end of file
-- 
GitLab