From a2ce62e1f360e9cdb2221cfa3b091c02bda857eb Mon Sep 17 00:00:00 2001
From: Laurens Vrijnsen <laurens.vrijnsen@sioux.eu>
Date: Fri, 22 Mar 2013 07:36:52 -0400
Subject: [PATCH] Added enforced HTTP Basic Authentication

---
 src/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties |    4 
 src/com/gitblit/wicket/AuthorizationStrategy.java     |   15 +++
 src/com/gitblit/wicket/GitBlitWebApp_nl.properties    |    2 
 src/com/gitblit/wicket/GitBlitWebApp_pl.properties    |    4 
 src/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties |    4 
 src/com/gitblit/wicket/pages/LogoutPage.java          |   23 ++++-
 src/com/gitblit/wicket/GitBlitWebApp_ko.properties    |    4 
 src/com/gitblit/wicket/GitBlitWebApp.properties       |    4 
 src/com/gitblit/wicket/GitBlitWebApp_ja.properties    |    2 
 src/com/gitblit/wicket/GitBlitWebApp_es.properties    |    4 
 src/WEB-INF/web.xml                                   |    9 ++
 src/com/gitblit/wicket/pages/LogoutPage.html          |   33 ++++++++
 src/com/gitblit/EnforceAuthenticationFilter.java      |   90 ++++++++++++++++++++++
 src/com/gitblit/wicket/GitBlitWebApp.java             |    2 
 14 files changed, 190 insertions(+), 10 deletions(-)

diff --git a/src/WEB-INF/web.xml b/src/WEB-INF/web.xml
index bdc882a..a943688 100644
--- a/src/WEB-INF/web.xml
+++ b/src/WEB-INF/web.xml
@@ -214,6 +214,15 @@
 		<filter-name>PagesFilter</filter-name>
 		<url-pattern>/pages/*</url-pattern>
 	</filter-mapping>
+	
+	<filter>
+		<filter-name>EnforceAuthenticationFilter</filter-name>
+		<filter-class>com.gitblit.EnforceAuthenticationFilter</filter-class>
+	</filter>
+	<filter-mapping>
+        <filter-name>EnforceAuthenticationFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
 
 
 	<!-- Wicket Filter -->
diff --git a/src/com/gitblit/EnforceAuthenticationFilter.java b/src/com/gitblit/EnforceAuthenticationFilter.java
new file mode 100644
index 0000000..6dc454c
--- /dev/null
+++ b/src/com/gitblit/EnforceAuthenticationFilter.java
@@ -0,0 +1,90 @@
+/**
+ * 
+ */
+package com.gitblit;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.models.UserModel;
+
+/**
+ * This filter enforces authentication via HTTP Basic Authentication, if the settings indicate so.
+ * It looks at the settings "web.authenticateViewPages" and "web.enforceHttpBasicAuthentication"; if
+ * both are true, any unauthorized access will be met with a HTTP Basic Authentication header.
+ *
+ * @author Laurens Vrijnsen
+ *
+ */
+public class EnforceAuthenticationFilter implements Filter {
+	
+	protected transient Logger logger = LoggerFactory.getLogger(getClass());
+
+	/* 
+	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+	 */
+	@Override
+	public void init(FilterConfig filterConfig) throws ServletException {
+		// nothing to be done
+
+	} //init
+	
+
+	/* 
+	 * This does the actual filtering: is the user authenticated? If not, enforce HTTP authentication (401)
+	 * 
+	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+	 */
+	@Override
+	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+		
+		/*
+		 * Determine whether to enforce the BASIC authentication:
+		 */
+		@SuppressWarnings("static-access")
+		Boolean mustForceAuth = GitBlit.self().getBoolean("web.authenticateViewPages", false)
+								&& GitBlit.self().getBoolean("web.enforceHttpBasicAuthentication", false);
+		
+		HttpServletRequest  HttpRequest  = (HttpServletRequest)request;
+		HttpServletResponse HttpResponse = (HttpServletResponse)response; 
+		UserModel user = GitBlit.self().authenticate(HttpRequest);
+		
+		if (mustForceAuth && (user == null)) {
+			// not authenticated, enforce now:
+			logger.info(MessageFormat.format("EnforceAuthFilter: user not authenticated for URL {0}!", request.toString()));
+			@SuppressWarnings("static-access")
+			String CHALLENGE = MessageFormat.format("Basic realm=\"{0}\"", GitBlit.self().getString("web.siteName",""));
+			HttpResponse.setHeader("WWW-Authenticate", CHALLENGE);
+			HttpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+			return;
+
+		} else {
+			// user is authenticated, or don't care, continue handling
+			chain.doFilter( request, response );
+			
+		} // authenticated
+	} // doFilter
+
+	
+	/* 
+	 * @see javax.servlet.Filter#destroy()
+	 */
+	@Override
+	public void destroy() {
+		// Nothing to be done
+
+	} // destroy
+
+}
diff --git a/src/com/gitblit/wicket/AuthorizationStrategy.java b/src/com/gitblit/wicket/AuthorizationStrategy.java
index 21bd1b7..51183a2 100644
--- a/src/com/gitblit/wicket/AuthorizationStrategy.java
+++ b/src/com/gitblit/wicket/AuthorizationStrategy.java
@@ -15,10 +15,16 @@
  */
 package com.gitblit.wicket;
 
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.wicket.Component;
 import org.apache.wicket.RestartResponseException;
 import org.apache.wicket.authorization.IUnauthorizedComponentInstantiationListener;
 import org.apache.wicket.authorization.strategies.page.AbstractPageAuthorizationStrategy;
+import org.apache.wicket.protocol.http.WebResponse;
+import org.apache.wicket.protocol.http.servlet.AbortWithWebErrorCodeException;
 
 import com.gitblit.GitBlit;
 import com.gitblit.Keys;
@@ -78,8 +84,17 @@
 
 	@Override
 	public void onUnauthorizedInstantiation(Component component) {
+		
 		if (component instanceof BasePage) {
 			throw new RestartResponseException(RepositoriesPage.class);
 		}
+		/*** DISABLED CODE ***
+		if (component instanceof BasePage) {
+			HttpServletResponse response = ((WebResponse)component.getResponse()).getHttpServletResponse();
+			response.setHeader("WWW-Authenticate", "Basic realm=test");
+			throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_UNAUTHORIZED);
+			
+		} 
+		*** END DISABLED ***/
 	}
 }
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.java b/src/com/gitblit/wicket/GitBlitWebApp.java
index 4e32daa..2300d0f 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.java
+++ b/src/com/gitblit/wicket/GitBlitWebApp.java
@@ -40,6 +40,7 @@
 import com.gitblit.wicket.pages.GravatarProfilePage;
 import com.gitblit.wicket.pages.HistoryPage;
 import com.gitblit.wicket.pages.LogPage;
+import com.gitblit.wicket.pages.LogoutPage;
 import com.gitblit.wicket.pages.LuceneSearchPage;
 import com.gitblit.wicket.pages.MarkdownPage;
 import com.gitblit.wicket.pages.MetricsPage;
@@ -101,6 +102,7 @@
 		mount("/metrics", MetricsPage.class, "r");
 		mount("/blame", BlamePage.class, "r", "h", "f");
 		mount("/users", UsersPage.class);
+		mount("/logout", LogoutPage.class);
 
 		// setup ticket urls
 		mount("/tickets", TicketsPage.class, "r");
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index a993f9f..7a2b1bb 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -442,4 +442,6 @@
 gb.siteNameDescription = short, descriptive name of your server 
 gb.excludeFromActivity = exclude from activity page
 gb.isSparkleshared = repository is Sparkleshared
-gb.owners = owners
\ No newline at end of file
+gb.owners = owners
+gb.sessionEnded = Session has been closed
+gb.closeBrowser = Please close the browser to properly end the session.
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_es.properties b/src/com/gitblit/wicket/GitBlitWebApp_es.properties
index 64c9ca1..210a75f 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp_es.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_es.properties
@@ -440,4 +440,6 @@
 gb.validity = Vigencia
 gb.siteName = Nombre del sitio
 gb.siteNameDescription = Nombre corto y descriptivo de tu servidor 
-gb.excludeFromActivity = Excluir de la p\u00E1gina de actividad
\ No newline at end of file
+gb.excludeFromActivity = Excluir de la p\u00E1gina de actividad
+gb.sessionEnded = La sesi\u00F3n ha sido cerrada
+gb.closeBrowser = Porfavor cierre el navegador para terminar correctamente la sesi\u00F3n.
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_ja.properties b/src/com/gitblit/wicket/GitBlitWebApp_ja.properties
index 086df7b..d0234f8 100755
--- a/src/com/gitblit/wicket/GitBlitWebApp_ja.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_ja.properties
@@ -314,3 +314,5 @@
 gb.allowAuthenticatedDescription = \u5168\u3066\u306e\u8a8d\u8a3c\u6e08\u307f\u30e6\u30fc\u30b6\u30fc\u3078\u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3059\u308b
 gb.allowNamedDescription = \u6307\u5b9a\u3057\u305f\u540d\u524d\u306e\u30e6\u30fc\u30b6\u30fc/\u30c1\u30fc\u30e0\u3078\u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3059\u308b
 gb.markdownFailure = Markdown \u306e\u30d1\u30fc\u30b9\u306b\u5931\u6557\u3057\u307e\u3057\u305f!
+gb.sessionEnded = Session has been closed
+gb.closeBrowser = Please close the browser to properly end the session.
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_ko.properties b/src/com/gitblit/wicket/GitBlitWebApp_ko.properties
index 18eda26..42915df 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp_ko.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_ko.properties
@@ -440,4 +440,6 @@
 gb.validity = \uC720\uD6A8\uC131
 gb.siteName = \uC0AC\uC774\uD2B8 \uC774\uB984
 gb.siteNameDescription = \uC11C\uBC84\uC758 \uC9E6\uC740 \uC124\uBA85\uC774 \uD3EC\uD568\uB41C \uC774\uB984
-gb.excludeFromActivity = \uC561\uD2F0\uBE44\uD2F0 \uD398\uC774\uC9C0\uC5D0\uC11C \uC81C\uC678
\ No newline at end of file
+gb.excludeFromActivity = \uC561\uD2F0\uBE44\uD2F0 \uD398\uC774\uC9C0\uC5D0\uC11C \uC81C\uC678
+gb.sessionEnded = Session has been closed
+gb.closeBrowser = Please close the browser to properly end the session.
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_nl.properties b/src/com/gitblit/wicket/GitBlitWebApp_nl.properties
index 5471ad8..f1281e1 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp_nl.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_nl.properties
@@ -441,3 +441,5 @@
 gb.siteName = site naam
 gb.siteNameDescription = korte, verduidelijkende naam van deze server
 gb.excludeFromActivity = sluit uit van activiteitspagina
+gb.sessionEnded = Sessie is afgesloten
+gb.closeBrowser = Sluit de browser af om de sessie helemaal te beeindigen.
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_pl.properties b/src/com/gitblit/wicket/GitBlitWebApp_pl.properties
index 82ffa63..b75e8f8 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp_pl.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_pl.properties
@@ -318,4 +318,6 @@
 gb.projects = Projekty
 gb.project = Projekt
 gb.allProjects = Wszystkie projekty
-gb.copyToClipboard = Kopiuj do schowka
\ No newline at end of file
+gb.copyToClipboard = Kopiuj do schowka
+gb.sessionEnded = Session has been closed
+gb.closeBrowser = Please close the browser to properly end the session.
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties b/src/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties
index efe286c..a02d2ff 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_pt_BR.properties
@@ -442,4 +442,6 @@
 gb.siteNameDescription = breve, mas ainda assim um nome descritivo para seu servidor
 gb.excludeFromActivity = excluir da p�gina de atividades
 gb.isSparkleshared = reposit�rio � Sparkleshared
-gb.owners = propriet�rios
\ No newline at end of file
+gb.owners = propriet�rios
+gb.sessionEnded = Session has been closed
+gb.closeBrowser = Please close the browser to properly end the session.
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties b/src/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties
index b571585..96e2067 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp_zh_CN.properties
@@ -441,4 +441,6 @@
 gb.siteName = \u7f51\u7ad9\u540d\u79f0
 gb.siteNameDescription = \u60a8\u7684\u670d\u52a1\u5668\u7684\u7b80\u8981\u63cf\u8ff0
 gb.excludeFromActivity = \u4ece\u6d3b\u52a8\u9875\u9762\u6392\u9664
-gb.isSparkleshared = repository is Sparkleshared
\ No newline at end of file
+gb.isSparkleshared = repository is Sparkleshared
+gb.sessionEnded = Session has been closed
+gb.closeBrowser = Please close the browser to properly end the session.
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/LogoutPage.html b/src/com/gitblit/wicket/pages/LogoutPage.html
new file mode 100644
index 0000000..d407783
--- /dev/null
+++ b/src/com/gitblit/wicket/pages/LogoutPage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  
+      xml:lang="en"  
+      lang="en"> 
+<body>
+<wicket:extend>
+	<div class="navbar navbar-fixed-top">
+		<div class="navbar-inner">
+			<div class="container">
+				<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            			<span class="icon-bar"></span>
+            			<span class="icon-bar"></span>
+            			<span class="icon-bar"></span>
+          		</a>
+				<a class="brand" wicket:id="rootLink">
+					<img src="gitblt_25_white.png" width="79" height="25" alt="gitblit" class="logo"/>
+				</a>
+				
+			</div>
+		</div>
+	</div>
+				
+	<!-- subclass content -->
+	<div class="container">
+		<div style="text-align:center" wicket:id="feedback">[Feedback Panel]</div>
+		
+		<h1><wicket:message key="gb.sessionEnded">[Session has ended]</wicket:message></h1>
+		<p><wicket:message key="gb.closeBrowser">[Please close the browser]</wicket:message></p>
+	</div>
+</wicket:extend>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/LogoutPage.java b/src/com/gitblit/wicket/pages/LogoutPage.java
index 4690ad1..982de0e 100644
--- a/src/com/gitblit/wicket/pages/LogoutPage.java
+++ b/src/com/gitblit/wicket/pages/LogoutPage.java
@@ -16,21 +16,36 @@
 package com.gitblit.wicket.pages;
 
 import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.WebRequest;
 import org.apache.wicket.protocol.http.WebResponse;
 
 import com.gitblit.GitBlit;
 import com.gitblit.models.UserModel;
 import com.gitblit.wicket.GitBlitWebSession;
 
-public class LogoutPage extends WebPage {
+public class LogoutPage extends BasePage {
 
 	public LogoutPage() {
+		super();
 		GitBlitWebSession session = GitBlitWebSession.get();
 		UserModel user = session.getUser();
 		GitBlit.self().setCookie((WebResponse) getResponse(), null);
 		GitBlit.self().logout(user);
 		session.invalidate();		
-		setRedirect(true);
-		setResponsePage(getApplication().getHomePage());
-	}
+		
+		/*
+		 * Now check whether the authentication was realized via the Authorization in the header.
+		 * If so, it is likely to be cached by the browser, and cannot be undone. Effectively, this means
+		 * that you cannot log out...
+		 */
+		if ( ((WebRequest)getRequest()).getHttpServletRequest().getHeader("Authorization") != null ) {
+			// authentication will be done via this route anyway, show a page to close the browser:
+			// this will be done by Wicket.
+			setupPage(null, getString("gb.logout"));
+			
+		} else {
+			setRedirect(true);
+			setResponsePage(getApplication().getHomePage());
+		} // not via WWW-Auth
+	} // LogoutPage
 }
\ No newline at end of file

--
Gitblit v1.9.1