[SCM] Debian packaging for the Shibboleth Apache SP branch, lenny, updated. debian/1.3.1.dfsg1-3+lenny1-1-g2619ead

Russ Allbery rra at debian.org
Thu Nov 12 05:32:49 UTC 2009


The following commit has been merged in the lenny branch:
commit 2619ead7e2c797d09a514f55084852116b6172e1
Author: Russ Allbery <rra at debian.org>
Date:   Wed Nov 11 21:32:07 2009 -0800

    Security fix for URL handling (CVE-2009-3300)
    
    * SECURITY: Fix improper handling of URLs that could be abused for
      script injection and other cross-site scripting attacks.
      (CVE-2009-3300)

diff --git a/adfs/handlers.cpp b/adfs/handlers.cpp
index 382b67b..1eaeaad 100644
--- a/adfs/handlers.cpp
+++ b/adfs/handlers.cpp
@@ -429,8 +429,19 @@ pair<bool,void*> ADFSHandler::run(ShibTarget* st, const IPropertySet* handler, b
             ret=handler->getString("ResponseLocation").second;
         if (!ret)
             ret=st->getApplication()->getString("homeURL").second;
-        if (!ret)
-            ret="/";
+        if (!ret) {
+            // No homeURL, so compute a URL to the root of the site.
+            int port = st->getPort();
+            const char* scheme = st->getProtocol();
+            string dest = string(scheme) + "://" + st->getHostname();
+            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
+                ostringstream portstr;
+                portstr << port;
+                dest += ':' + portstr.str();
+            }
+            dest += '/';
+            return make_pair(true, st->sendRedirect(dest));
+        }
         return make_pair(true, st->sendRedirect(ret));
     }
     
@@ -469,7 +480,7 @@ pair<bool,void*> ADFSHandler::run(ShibTarget* st, const IPropertySet* handler, b
 
     if (target=="default") {
         pair<bool,const char*> homeURL=app->getString("homeURL");
-        target=homeURL.first ? homeURL.second : "/";
+        target=homeURL.first ? homeURL.second : "";
     }
     else if (target=="cookie" || target.empty()) {
         // Pull the target value from the "relay state" cookie.
@@ -478,7 +489,7 @@ pair<bool,void*> ADFSHandler::run(ShibTarget* st, const IPropertySet* handler, b
         if (!relay_state || !*relay_state) {
             // No apparent relay state value to use, so fall back on the default.
             pair<bool,const char*> homeURL=app->getString("homeURL");
-            target=homeURL.first ? homeURL.second : "/";
+            target=homeURL.first ? homeURL.second : "";
         }
         else {
             char* rscopy=strdup(relay_state);
@@ -519,6 +530,19 @@ pair<bool,void*> ADFSHandler::run(ShibTarget* st, const IPropertySet* handler, b
         }
     }
 
+    if (target == "") {
+        // No homeURL, so compute a URL to the root of the site.
+        int port = st->getPort();
+        const char* scheme = st->getProtocol();
+        target = string(scheme) + "://" + st->getHostname();
+        if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
+            ostringstream portstr;
+            portstr << port;
+            target += ':' + portstr.str();
+        }
+        target += '/';
+    }
+
     // Now redirect to the target.
     return make_pair(true, st->sendRedirect(target));
 }
diff --git a/apache/mod_apache.cpp b/apache/mod_apache.cpp
index 6c906d8..752cec9 100644
--- a/apache/mod_apache.cpp
+++ b/apache/mod_apache.cpp
@@ -69,6 +69,7 @@ namespace {
     char* g_szSHIBConfig = NULL;
     char* g_szSchemaDir = NULL;
     ShibTargetConfig* g_Config = NULL;
+    set<string> g_allowedSchemes;
     string g_unsetHeaderValue;
     bool g_checkSpoofing = true;
     bool g_catchAll = true;
@@ -443,9 +444,12 @@ public:
     const string& content_type="text/html",
 	const Iterator<header_t>& headers=EMPTY(header_t)
     ) {
+    checkString(content_type, "Detected control character in a response header.");
     m_req->content_type = ap_psprintf(m_req->pool, content_type.c_str());
     while (headers.hasNext()) {
         const header_t& h=headers.next();
+        checkString(h.first, "Detected control character in a response header.");
+        checkString(h.second, "Detected control character in a response header.");
         ap_table_set(m_req->headers_out, h.first.c_str(), h.second.c_str());
     }
     ap_send_http_header(m_req);
@@ -453,6 +457,9 @@ public:
     return (void*)((code==200) ? DONE : code);
   }
   virtual void* sendRedirect(const string& url) {
+    checkString(url, "Detected control character in an attempted redirect.");
+    if (g_allowedSchemes.find(url.substr(0, url.find(':'))) == g_allowedSchemes.end())
+        throw FatalProfileException("Invalid scheme in attempted redirect.");
     ap_table_set(m_req->headers_out, "Location", url.c_str());
     return (void*)REDIRECT;
   }
@@ -465,6 +472,15 @@ public:
   shib_server_config* m_sc;
   shib_request_config* m_rc;
   set<string> m_allhttp;
+
+private:
+  void checkString(const string& s, const char* msg) {
+    string::const_iterator e = s.end();
+    for (string::const_iterator i=s.begin(); i!=e; ++i) {
+        if (iscntrl(*i))
+            throw FatalProfileException(msg);
+    }
+  }
 };
 
 /********************************************************************************/
@@ -1122,14 +1138,30 @@ extern "C" void shib_child_init(apr_pool_t* p, server_rec* s)
         saml::Locker locker(conf);
         const IPropertySet* props=conf->getPropertySet("Local");
         if (props) {
-            pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
-            if (unsetValue.first)
-                g_unsetHeaderValue = unsetValue.second;
+            pair<bool,const char*> str=props->getString("unsetHeaderValue");
+            if (str.first)
+                g_unsetHeaderValue = str.second;
+            str=props->getString("allowedSchemes");
+            if (str.first) {
+                string schemes=str.second;
+                unsigned int j=0;
+                for (unsigned int i=0;  i < schemes.length();  i++) {
+                    if (schemes.at(i)==' ') {
+                        g_allowedSchemes.insert(schemes.substr(j, i-j));
+                        j = i+1;
+                    }
+                }
+                g_allowedSchemes.insert(schemes.substr(j, schemes.length()-j));
+            }
             pair<bool,bool> flag=props->getBool("checkSpoofing");
             g_checkSpoofing = !flag.first || flag.second;
             flag=props->getBool("catchAll");
             g_catchAll = !flag.first || flag.second;
         }
+        if (g_allowedSchemes.empty()) {
+            g_allowedSchemes.insert("https");
+            g_allowedSchemes.insert("http");
+        }
     }
     catch (exception&) {
         ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to initialize system");
diff --git a/debian/changelog b/debian/changelog
index 8883e75..277a7e3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+shibboleth-sp (1.3.1.dfsg1-3+lenny2) stable-security; urgency=high
+
+  * SECURITY: Fix improper handling of URLs that could be abused for
+    script injection and other cross-site scripting attacks.
+    (CVE-2009-3300)
+
+ -- Russ Allbery <rra at debian.org>  Wed, 11 Nov 2009 21:25:14 -0800
+
 shibboleth-sp (1.3.1.dfsg1-3+lenny1) stable-security; urgency=high
 
   * SECURITY: Correctly handle decoding of malformed URLs, closing a
diff --git a/schemas/shibboleth-targetconfig-1.0.xsd b/schemas/shibboleth-targetconfig-1.0.xsd
index f40ba61..e1b6e44 100644
--- a/schemas/shibboleth-targetconfig-1.0.xsd
+++ b/schemas/shibboleth-targetconfig-1.0.xsd
@@ -7,7 +7,7 @@
 	elementFormDefault="qualified"
 	attributeFormDefault="unqualified"
 	blockDefault="substitution"
-	version="1.3.1">
+	version="1.3.5">
 
 	<import namespace="urn:oasis:names:tc:SAML:1.0:assertion" schemaLocation="cs-sstc-schema-assertion-1.1.xsd"/>
 	<import namespace="urn:oasis:names:tc:SAML:2.0:metadata" schemaLocation="saml-schema-metadata-2.0.xsd"/>
@@ -38,7 +38,7 @@
 			<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
 		</sequence>
 		<attribute name="type" type="conf:string" use="required"/>
-		<attribute name="uri" type="anyURI" use="optional"/>
+		<attribute name="uri" type="anyURI"/>
 		<anyAttribute namespace="##any" processContents="lax"/>
 	</complexType>
 
@@ -62,8 +62,8 @@
 			<element name="CredentialsProvider" type="conf:PluggableType" minOccurs="0" maxOccurs="unbounded"/>
 			<element ref="conf:AttributeFactory" minOccurs="0" maxOccurs="unbounded"/>
 		</sequence>
-		<attribute name="logger" type="anyURI" use="optional"/>
-		<attribute name="clockSkew" type="unsignedInt" use="optional"/>
+		<attribute name="logger" type="anyURI"/>
+		<attribute name="clockSkew" type="unsignedInt"/>
 		<anyAttribute namespace="##other" processContents="lax"/>
 	</complexType>
 
@@ -79,7 +79,7 @@
 							<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
 						</sequence>
 						<attribute name="path" type="anyURI" use="required"/>
-						<attribute name="fatal" type="boolean" use="optional"/>
+						<attribute name="fatal" type="boolean"/>
 						<anyAttribute namespace="##other" processContents="lax"/>
 					</complexType>
 				</element>
@@ -123,8 +123,8 @@
 							<element name="Argument" type="conf:string" minOccurs="0" maxOccurs="unbounded"/>
 						</sequence>
 						<attributeGroup ref="conf:SessionCacheProperties"/>
-						<attribute name="mysqlTimeout" type="unsignedInt" use="optional" default="14400"/>
-						<attribute name="storeAttributes" type="boolean" use="optional" default="false"/>
+						<attribute name="mysqlTimeout" type="unsignedInt" default="14400"/>
+						<attribute name="storeAttributes" type="boolean" default="false"/>
 						<anyAttribute namespace="##other" processContents="lax"/>
 					</complexType>
 				</element>
@@ -151,19 +151,19 @@
 			</choice>
 			<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
 		</sequence>
-		<attribute name="logger" type="anyURI" use="optional"/>
+		<attribute name="logger" type="anyURI"/>
 		<anyAttribute namespace="##other" processContents="lax"/>
 	</complexType>
 
 	<attributeGroup name="SessionCacheProperties">
-    	<attribute name="cleanupInterval" type="unsignedInt" use="optional" default="300"/>
-    	<attribute name="cacheTimeout" type="unsignedInt" use="optional" default="28800"/>
-		<attribute name="AAConnectTimeout" type="unsignedInt" use="optional" default="15"/>
-		<attribute name="AATimeout" type="unsignedInt" use="optional" default="30"/>
-		<attribute name="defaultLifetime" type="unsignedInt" use="optional" default="1800"/>
-		<attribute name="retryInterval" type="unsignedInt" use="optional" default="300"/>
-		<attribute name="strictValidity" type="boolean" use="optional" default="true"/>
-		<attribute name="propagateErrors" type="boolean" use="optional" default="false"/>
+    	<attribute name="cleanupInterval" type="unsignedInt" default="300"/>
+    	<attribute name="cacheTimeout" type="unsignedInt" default="28800"/>
+		<attribute name="AAConnectTimeout" type="unsignedInt" default="15"/>
+		<attribute name="AATimeout" type="unsignedInt" default="30"/>
+		<attribute name="defaultLifetime" type="unsignedInt" default="1800"/>
+		<attribute name="retryInterval" type="unsignedInt" default="300"/>
+		<attribute name="strictValidity" type="boolean" default="true"/>
+		<attribute name="propagateErrors" type="boolean" default="false"/>
 	</attributeGroup>
 
 	<complexType name="LocalConfigurationType">
@@ -186,11 +186,13 @@
 			</element>
 			<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
 		</sequence>
-		<attribute name="logger" type="anyURI" use="optional"/>
-		<attribute name="localRelayState" type="boolean" use="optional" default="false"/>
-		<attribute name="unsetHeaderValue" type="conf:string" use="optional"/>
-		<attribute name="checkSpoofing" type="boolean" use="optional"/>
-		<attribute name="catchAll" type="boolean" use="optional"/>
+		<attribute name="logger" type="anyURI"/>
+		<attribute name="localRelayState" type="boolean" default="false"/>
+		<attribute name="unsetHeaderValue" type="conf:string"/>
+		<attribute name="checkSpoofing" type="boolean"/>
+        <attribute name="spoofKey" type="conf:string"/>
+		<attribute name="catchAll" type="boolean"/>
+        <attribute name="allowedSchemes" type="conf:listOfStrings"/>
 		<anyAttribute namespace="##other" processContents="lax"/>
 	</complexType>
 	
@@ -204,14 +206,15 @@
 						</sequence>
 						<attribute name="id" type="unsignedInt" use="required"/>
 						<attribute name="name" type="conf:string" use="required"/>
-						<attribute name="port" type="unsignedInt" use="optional"/>
-						<attribute name="sslport" type="unsignedInt" use="optional"/>
-						<attribute name="scheme" type="conf:string" use="optional"/>
+						<attribute name="port" type="unsignedInt"/>
+						<attribute name="sslport" type="unsignedInt"/>
+						<attribute name="scheme" type="conf:string"/>
 					</complexType>
 				</element>
 				<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
 			</sequence>
-			<attribute name="normalizeRequest" type="boolean" use="optional"/>
+			<attribute name="normalizeRequest" type="boolean"/>
+            <attribute name="safeHeaderNames" type="boolean"/>
 			<anyAttribute namespace="##other" processContents="lax"/>
 		</complexType>
 	</element>
@@ -255,11 +258,11 @@
 	</element>
 	
 	<attributeGroup name="ContentSettings">
-		<attribute name="authType" type="conf:string" use="optional"/>
-		<attribute name="requireSession" type="boolean" use="optional"/>
-		<attribute name="requireSessionWith" type="conf:string" use="optional"/>
-		<attribute name="exportAssertion" type="boolean" use="optional"/>
-		<attribute name="redirectToSSL" type="unsignedInt" use="optional"/>
+		<attribute name="authType" type="conf:string"/>
+		<attribute name="requireSession" type="boolean"/>
+		<attribute name="requireSessionWith" type="conf:string"/>
+		<attribute name="exportAssertion" type="boolean"/>
+		<attribute name="redirectToSSL" type="unsignedInt"/>
 		<anyAttribute namespace="##other" processContents="lax"/>
 	</attributeGroup>
 	<element name="AccessControlProvider" type="conf:PluggableType"/>
@@ -301,7 +304,7 @@
     				<element ref="conf:PathRegex"/>
     			</choice>
     		</sequence>
-    		<attribute name="scheme" use="optional">
+    		<attribute name="scheme">
 			    <simpleType>
 			        <restriction base="string">
 			            <enumeration value="http"/>
@@ -313,8 +316,8 @@
 			    </simpleType>
     		</attribute>
     		<attribute name="name" type="conf:string" use="required"/>
-    		<attribute name="port" type="unsignedInt" use="optional"/>
-    		<attribute name="applicationId" type="conf:string" use="optional"/>
+    		<attribute name="port" type="unsignedInt"/>
+    		<attribute name="applicationId" type="conf:string"/>
            	<attributeGroup ref="conf:ContentSettings"/>
     	</complexType>
     </element>
@@ -353,7 +356,7 @@
     			</choice>
     		</sequence>
     		<attribute name="name" type="conf:string" use="required"/>
-    		<attribute name="applicationId" type="conf:string" use="optional"/>
+    		<attribute name="applicationId" type="conf:string"/>
            	<attributeGroup ref="conf:ContentSettings"/>
         </complexType>
     </element>
@@ -395,7 +398,7 @@
 			</sequence>
 			<attribute name="id" type="conf:string" fixed="default"/>
 			<attribute name="providerId" type="anyURI" use="required"/>
-			<attribute name="homeURL" type="anyURI" use="optional"/>
+			<attribute name="homeURL" type="anyURI"/>
 	        <anyAttribute namespace="##other" processContents="lax"/>
 		</complexType>
 	</element>
@@ -419,8 +422,8 @@
 				</choice>
 			</sequence>
 			<attribute name="id" type="conf:string" use="required"/>
-			<attribute name="providerId" type="anyURI" use="optional"/>
-			<attribute name="homeURL" type="anyURI" use="optional"/>
+			<attribute name="providerId" type="anyURI"/>
+			<attribute name="homeURL" type="anyURI"/>
 	        <anyAttribute namespace="##other" processContents="lax"/>
 		</complexType>
 	</element>
@@ -445,20 +448,20 @@
 				<element ref="md:SingleLogoutService"/>
 				<element name="ExtensionService" type="conf:PluggableType"/>
 			</choice>
-			<!-- deprecated --> <attribute name="wayfURL" type="anyURI" use="optional"/>
-			<!-- deprecated --> <attribute name="shireURL" type="anyURI" use="optional"/>
-			<!-- deprecated --> <attribute name="shireSSL" type="boolean" use="optional"/>
-			<attribute name="handlerURL" type="anyURI" use="optional"/>
-			<attribute name="handlerSSL" type="boolean" use="optional" default="true"/>
-			<attribute name="cookieName" type="conf:string" use="optional"/>
-			<attribute name="cookieProps" type="conf:string" use="optional"/>
-			<attribute name="idpHistory" type="boolean" use="optional" default="true"/>
-			<attribute name="idpHistoryDays" type="unsignedInt" use="optional"/>
-			<attribute name="lifetime" type="unsignedInt" use="optional"/>
-			<attribute name="timeout" type="unsignedInt" use="optional"/>
-			<attribute name="checkAddress" type="boolean" use="optional"/>
-			<attribute name="consistentAddress" type="boolean" use="optional" default="true"/>
-			<attribute name="checkReplay" type="boolean" use="optional" default="true"/>
+			<!-- deprecated --> <attribute name="wayfURL" type="anyURI"/>
+			<!-- deprecated --> <attribute name="shireURL" type="anyURI"/>
+			<!-- deprecated --> <attribute name="shireSSL" type="boolean"/>
+			<attribute name="handlerURL" type="anyURI"/>
+			<attribute name="handlerSSL" type="boolean" default="true"/>
+			<attribute name="cookieName" type="conf:string"/>
+			<attribute name="cookieProps" type="conf:string"/>
+			<attribute name="idpHistory" type="boolean" default="true"/>
+			<attribute name="idpHistoryDays" type="unsignedInt"/>
+			<attribute name="lifetime" type="unsignedInt"/>
+			<attribute name="timeout" type="unsignedInt"/>
+			<attribute name="checkAddress" type="boolean"/>
+			<attribute name="consistentAddress" type="boolean" default="true"/>
+			<attribute name="checkReplay" type="boolean" default="true"/>
 			<anyAttribute namespace="##other" processContents="lax"/>
 		</complexType>
 	</element>
@@ -472,11 +475,11 @@
 			</sequence>
 			<attribute name="Location" type="anyURI" use="required"/>
 			<attribute name="Binding" type="anyURI" use="required"/>
-			<attribute name="wayfURL" type="anyURI" use="optional"/>
-			<attribute name="wayfBinding" type="anyURI" use="optional"/>
-			<attribute name="checkCDC" type="anyURI" use="optional"/>
-			<attribute name="isDefault" type="boolean" use="optional"/>
-			<attribute name="id" type="conf:string" use="optional"/>
+			<attribute name="wayfURL" type="anyURI"/>
+			<attribute name="wayfBinding" type="anyURI"/>
+			<attribute name="checkCDC" type="anyURI"/>
+			<attribute name="isDefault" type="boolean"/>
+			<attribute name="id" type="conf:string"/>
 			<anyAttribute namespace="##any" processContents="lax"/>
 		</complexType>
 	</element>
@@ -489,28 +492,28 @@
 			<sequence>
 				<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
 			</sequence>
-			<!-- deprecated --> <attribute name="shire" type="anyURI" use="optional"/>
-			<attribute name="session" type="anyURI" use="optional"/>
-			<attribute name="metadata" type="anyURI" use="optional"/>
+			<!-- deprecated --> <attribute name="shire" type="anyURI"/>
+			<attribute name="session" type="anyURI"/>
+			<attribute name="metadata" type="anyURI"/>
 			<attribute name="rm" type="anyURI" use="required"/>
-			<attribute name="access" type="anyURI" use="optional"/>
-			<attribute name="ssl" type="anyURI" use="optional"/>
-			<attribute name="supportContact" type="conf:string" use="optional"/>
-			<attribute name="logoLocation" type="anyURI" use="optional"/>
-			<attribute name="styleSheet" type="anyURI" use="optional"/>
+			<attribute name="access" type="anyURI"/>
+			<attribute name="ssl" type="anyURI"/>
+			<attribute name="supportContact" type="conf:string"/>
+			<attribute name="logoLocation" type="anyURI"/>
+			<attribute name="styleSheet" type="anyURI"/>
 			<anyAttribute namespace="##any" processContents="lax"/>
 		</complexType>
 	</element>
 
 	<attributeGroup name="CredentialUseGroup">
-		<attribute name="TLS" type="conf:string" use="optional"/>
-		<attribute name="Signing" type="conf:string" use="optional"/>
-		<attribute name="signRequest" type="boolean" use="optional" default="false"/>
-		<attribute name="signatureAlg" type="anyURI" use="optional"/>
-		<attribute name="digestAlg" type="anyURI" use="optional"/>
-		<attribute name="signedResponse" type="boolean" use="optional" default="false"/>
-		<attribute name="signedAssertions" type="boolean" use="optional" default="false"/>
-		<attribute name="authType" use="optional">
+		<attribute name="TLS" type="conf:string"/>
+		<attribute name="Signing" type="conf:string"/>
+		<attribute name="signRequest" type="boolean" default="false"/>
+		<attribute name="signatureAlg" type="anyURI"/>
+		<attribute name="digestAlg" type="anyURI"/>
+		<attribute name="signedResponse" type="boolean" default="false"/>
+		<attribute name="signedAssertions" type="boolean" default="false"/>
+		<attribute name="authType">
 			<simpleType>
 				<restriction base="string">
 					<enumeration value="basic"/>
@@ -520,8 +523,8 @@
 				</restriction>
 			</simpleType>
 		</attribute>
-		<attribute name="authUsername" use="optional"/>
-		<attribute name="authPassword" use="optional"/>
+		<attribute name="authUsername"/>
+		<attribute name="authPassword"/>
 	</attributeGroup>
 
 	<element name="CredentialUse">
diff --git a/shib-target/shib-handlers.cpp b/shib-target/shib-handlers.cpp
index abdf707..21e9cfa 100644
--- a/shib-target/shib-handlers.cpp
+++ b/shib-target/shib-handlers.cpp
@@ -316,7 +316,7 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, const IPropertySet* handler,
 
     if (target=="default") {
         pair<bool,const char*> homeURL=app->getString("homeURL");
-        target=homeURL.first ? homeURL.second : "/";
+        target=homeURL.first ? homeURL.second : "";
     }
     else if (target=="cookie" || target.empty()) {
         // Pull the target value from the "relay state" cookie.
@@ -325,7 +325,7 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, const IPropertySet* handler,
         if (!relay_state || !*relay_state) {
             // No apparent relay state value to use, so fall back on the default.
             pair<bool,const char*> homeURL=app->getString("homeURL");
-            target=homeURL.first ? homeURL.second : "/";
+            target=homeURL.first ? homeURL.second : "";
         }
         else {
             char* rscopy=strdup(relay_state);
@@ -366,6 +366,19 @@ pair<bool,void*> SAML1Consumer::run(ShibTarget* st, const IPropertySet* handler,
         }
     }
 
+    if (target == "") {
+        // No homeURL, so compute a URL to the root of the site.
+        int port = st->getPort();
+        const char* scheme = st->getProtocol();
+        target = string(scheme) + "://" + st->getHostname();
+        if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
+            ostringstream portstr;
+            portstr << port;
+            target += ':' + portstr.str();
+        }
+        target += '/';
+    }
+
     // Now redirect to the target.
     return make_pair(true, st->sendRedirect(target));
 }
@@ -401,8 +414,19 @@ pair<bool,void*> ShibLogout::run(ShibTarget* st, const IPropertySet* handler, bo
         ret=handler->getString("ResponseLocation").second;
     if (!ret)
         ret=st->getApplication()->getString("homeURL").second;
-    if (!ret)
-        ret="/";
+    if (!ret) {
+        // No homeURL, so compute a URL to the root of the site.
+        int port = st->getPort();
+        const char* scheme = st->getProtocol();
+        string dest = string(scheme) + "://" + st->getHostname();
+        if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
+            ostringstream portstr;
+            portstr << port;
+            dest += ':' + portstr.str();
+        }
+        dest += '/';
+        return make_pair(true, st->sendRedirect(dest));
+    }
     return make_pair(true, st->sendRedirect(ret));
 }
 

-- 
Debian packaging for the Shibboleth Apache SP



More information about the Pkg-shibboleth-devel mailing list