Permalink
Browse files

Enable HTTP Digest authentication for non admin users.

Also ensure authentication is not lost by Digest timeout when navigating
between index.html and search results page.

This way, running searches with extended features on a remote peer or a
password protected peer works with a regular user (with "Extended
search" rights). 
When authenticating on the search page with a user without "Extended
search" rights, it appears as authenticated, but has just its usual
access to the public search features.
  • Loading branch information...
luccioman committed Oct 26, 2017
1 parent 5161451 commit 8e732d437c9909ebde32d26549731e766e6ef427
@@ -93,7 +93,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
final int num = post.getInt("num",10); //indicates how many entries should be shown
if (!hasRights) {
final UserDB.Entry userentry = sb.userDB.proxyAuth(header.get(RequestHeader.AUTHORIZATION));
final UserDB.Entry userentry = sb.userDB.proxyAuth(header);
if (userentry != null && userentry.hasRight(UserDB.AccessRight.BLOG_RIGHT)) {
hasRights=true;
} else if (post.containsKey("login")) {
@@ -77,7 +77,7 @@ public static serverObjects respond(final RequestHeader header, serverObjects po
}
if (!hasRights) {
final UserDB.Entry userentry = sb.userDB.proxyAuth(header.get(RequestHeader.AUTHORIZATION));
final UserDB.Entry userentry = sb.userDB.proxyAuth(header);
if (userentry != null && userentry.hasRight(UserDB.AccessRight.BLOG_RIGHT)) {
hasRights = true;
} else if (post.containsKey("login")) {
@@ -54,7 +54,7 @@ public static servletProperties respond(final RequestHeader requestHeader, final
prop.put("logged-in_username", "");
prop.put("logged-in_returnto", "");
//identified via HTTPPassword
entry=sb.userDB.proxyAuth(requestHeader.get(RequestHeader.AUTHORIZATION));
entry=sb.userDB.proxyAuth(requestHeader);
if(entry != null){
prop.put("logged-in_identified-by", "1");
//try via cookie
@@ -119,6 +119,9 @@
</li>
<li id="header_administration">
<form action="index.html" method="get">
#(authorized)#::
<input type="hidden" name="auth" id="auth" value=""/>
#(/authorized)#
<button accesskey="s" type="submit" class="btn btn-inverse navbar-btn label-primary" title="Search Interface">
<span class="glyphicon glyphicon-search"></span>
<span class="hidden-sm hidden-md"> Search Interface &raquo;</span>
@@ -37,7 +37,7 @@
<span class="visible-sm glyphicon glyphicon-search"><b class="caret"></b></span>
</a>
<ul class="dropdown-menu" role="menu">
<li id="header_websearch"><a href="index.html#(authorized)#::?auth#(/authorized)#" onclick="this.href='index.html?#(authorized)#::auth&#(/authorized)#former='+document.searchform.search.value">Web Search</a></li>
<li id="header_websearch"><a href="index.html#(authSearch)#::?auth#(/authSearch)#" onclick="this.href='index.html?#(authSearch)#::auth&#(/authSearch)#former='+document.searchform.search.value">Web Search</a></li>
<li id="header_filesearch"><a href="yacyinteractive.html" onclick="this.href='yacyinteractive.html?handover='+document.searchform.search.value">File Search</a></li>
<li id="header_comparesearch"><a href="compare_yacy.html?display=0">Compare Search</a></li>
<li id="header_hostbrowser"><a href="HostBrowser.html?hosts=">Index Browser</a></li>
@@ -61,9 +61,9 @@ <h2 class="yacy">#[promoteSearchPageGreeting]#</h2>
<button id="Enter" name="Enter" class="btn btn-primary" type="submit">Search</button>
</div>
</div>
#(authorized)#::
#(authSearch)#::
<input type="hidden" name="auth" id="auth" value=""/>
#(/authorized)#
#(/authSearch)#
<input type="hidden" name="verify" value="#[search.verify]#" />
#(searchdomswitches)#::
<div class="yacysearch">
@@ -72,7 +72,7 @@ <h2 class="yacy">#[promoteSearchPageGreeting]#</h2>
#(searchaudio)#::<input type="radio" id="audio" name="contentdom" value="audio" #(check)#::checked="checked"#(/check)# />&nbsp;Audio&nbsp;&nbsp;#(/searchaudio)#
#(searchvideo)#::<input type="radio" id="video" name="contentdom" value="video" #(check)#::checked="checked"#(/check)# />&nbsp;Video&nbsp;&nbsp;#(/searchvideo)#
#(searchapp)#::<input type="radio" id="app" name="contentdom" value="app" #(check)#::checked="checked"#(/check)# />&nbsp;Applications#(/searchapp)#
#(searchoptions)#&nbsp;&nbsp;<a href="index.html?searchoptions=1" onclick="this.href='index.html?searchoptions=1&amp;former='+document.getElementById('search').value+'&amp;contentdom='+radioValue(document.getElementById('searchform').contentdom);">more options...</a>::#(/searchoptions)#
#(searchoptions)#&nbsp;&nbsp;<a href="index.html?searchoptions=1#(authSearch)#::&auth#(/authSearch)#" onclick="this.href='index.html?searchoptions=1#(authSearch)#::&auth#(/authSearch)#&amp;former='+document.getElementById('search').value+'&amp;contentdom='+radioValue(document.getElementById('searchform').contentdom);">more options...</a>::#(/searchoptions)#
</div>
#(/searchdomswitches)#
<input type="hidden" name="nav" value="#[search.navigation]#" />
@@ -31,6 +31,7 @@
import net.yacy.cora.document.analysis.Classification;
import net.yacy.cora.document.analysis.Classification.ContentDomain;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.data.UserDB;
import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants;
import net.yacy.search.schema.CollectionSchema;
@@ -57,14 +58,25 @@ public static serverObjects respond(final RequestHeader header, final serverObje
if(adminAuthenticated) {
authenticatedUserName = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin");
} else {
final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null;
if(user != null) {
authenticatedUserName = user.getUserName();
}
}
if ((post != null) && (post.containsKey("auth") || post.containsKey("publicPage"))) {
if (!adminAuthenticated) {
prop.authenticationRequired();
return prop;
}
}
boolean authenticated = adminAuthenticated || authenticatedUserName != null;
if (post != null) {
if (post.containsKey("publicPage") && !adminAuthenticated) { // Old style parameter : still in use ?
prop.authenticationRequired();
return prop;
}
if (post.containsKey("auth") && !authenticated) { // search with authentication required
prop.authenticationRequired();
return prop;
}
}
prop.put("authSearch", authenticated);
boolean global = (post == null) ? true : post.get("resource", "global").equals("global");
final boolean focus = (post == null) ? true : post.get("focus", "1").equals("1");
@@ -130,6 +142,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
prop.putHTML("constraint", constraint);
prop.put("searchdomswitches", sb.getConfigBool("search.text", true) || sb.getConfigBool("search.audio", true) || sb.getConfigBool("search.video", true) || sb.getConfigBool("search.image", true) || sb.getConfigBool("search.app", true) ? 1 : 0);
prop.put("searchdomswitches_searchoptions", searchoptions);
prop.put("searchdomswitches_searchoptions_authSearch", authenticated);
prop.put("searchdomswitches_searchtext", sb.getConfigBool("search.text", true) ? 1 : 0);
prop.put("searchdomswitches_searchaudio", sb.getConfigBool("search.audio", true) ? 1 : 0);
prop.put("searchdomswitches_searchvideo", sb.getConfigBool("search.video", true) ? 1 : 0);
@@ -159,7 +172,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
* @param authenticatedUserName the name of the currently authenticated user or null
*/
private static void handleTopNavBarLoginSection(final RequestHeader header, final Switchboard sb,
final serverObjects prop, String authenticatedUserName) {
final serverObjects prop, final String authenticatedUserName) {
final boolean showLogin = sb.getConfigBool(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT);
if(showLogin) {
@@ -109,9 +109,9 @@
#(/resortEnabled)#
</div>
</div>
#(authorized)#::
#(authSearch)#::
<input type="hidden" name="auth" id="auth" value=""/>
#(/authorized)#
#(/authSearch)#
<input type="hidden" name="contentdom" id="contentdom" value="#[contentdom]#" />
<input type="hidden" name="former" value="#[former]#" />
<input type="hidden" name="maximumRecords" value="#[count]#" />
@@ -137,6 +137,7 @@ public static serverObjects respond(
final servletProperties prop = new servletProperties();
prop.put("topmenu", sb.getConfigBool("publicTopmenu", true) ? 1 : 0);
prop.put("authSearch", authenticatedUserName != null);
// produce vocabulary navigation sidebars
Collection<Tagging> vocabularies = LibraryProvider.autotagging.getVocabularies();
@@ -206,7 +207,7 @@ public static serverObjects respond(
return prop;
}
if (post.containsKey("auth") && !extendedSearchRights) {
if (post.containsKey("auth") && authenticatedUserName == null) {
/*
* Access to authentication protected features is explicitely requested here
* but no authentication is provided : ask now for authentication.
@@ -784,7 +785,7 @@ public static serverObjects respond(
RequestHeader.FileType.HTML,
0,
theQuery,
suggestion, true, extendedSearchRights).toString());
suggestion, true, authenticatedUserName != null).toString());
prop.put("didYouMean_suggestions_" + meanCount + "_sep", "|");
meanCount++;
} catch (final ConcurrentModificationException e) {
@@ -862,7 +863,7 @@ public static serverObjects respond(
* eventually including fetched results with higher ranks from the Solr and RWI stacks */
prop.put("resortEnabled", !jsResort && global && !stealthmode && theSearch.resortCacheAllowed.availablePermits() > 0 ? 1 : 0);
prop.put("resortEnabled_url",
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, extendedSearchRights)
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, authenticatedUserName != null)
.append("&startRecord=").append(startRecord).append("&resortCachedResults=true")
.toString());
@@ -44,7 +44,7 @@ <h4 class="linktitle">
#(showMetadata)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="solr/select?q=id:%22#[urlhash]#%22&defType=edismax&start=0&rows=1&core=collection1&wt=html" target="_blank">Metadata</a>#(/showMetadata)#
#(showParser)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="ViewFile.html?urlHash=#[urlhash]#&amp;words=#[words]#" target="_blank">Parser</a>#(/showParser)#
#(showCitation)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="api/citation.html?hash=#[urlhash]#&filter=true" target="_blank">Citations</a>#(/showCitation)#
#(showPictures)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="yacysearch.html?contentdom=image#(authorized)#::&auth#(/authorized)#&url=#[link]#&query=#[former]#+inurl:#[link]#" target="_blank">Pictures</a>#(/showPictures)#
#(showPictures)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="yacysearch.html?contentdom=image#(authSearch)#::&auth#(/authSearch)#&url=#[link]#&query=#[former]#+inurl:#[link]#" target="_blank">Pictures</a>#(/showPictures)#
#(showCache)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="CacheResource_p.html?url=#[link]#" target="_blank">Cache</a>#(/showCache)#
#(showProxy)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="proxy.html?url=#[link]#" target="_blank">View via proxy</a>#(/showProxy)#
#(showHostBrowser)#::<span role="separator" aria-orientation="vertical">&nbsp;|&nbsp;</span><a href="HostBrowser.html?path=#[link]#"><img src="env/grafics/minitree.png" width="15" height="8" title="Browse index" alt="Browse index"/></a>#(/showHostBrowser)#
@@ -103,13 +103,12 @@ public static serverObjects respond(final RequestHeader header, final serverObje
final boolean adminAuthenticated = sb.verifyAuthentication(header);
final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null;
final boolean userAuthenticated = (user != null && user.hasRight(UserDB.AccessRight.EXTENDED_SEARCH_RIGHT));
final boolean authenticated = adminAuthenticated || userAuthenticated;
final boolean authenticated = adminAuthenticated || user != null;
final int item = post.getInt("item", -1);
final RequestHeader.FileType fileType = header.fileType();
if (post.containsKey("auth") && !authenticated) {
if (post.containsKey("auth") && !adminAuthenticated && user == null) {
/*
* Access to authentication protected features is explicitely requested here
* but no authentication is provided : ask now for authentication.
@@ -120,7 +119,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
prop.authenticationRequired();
return prop;
}
// default settings for blank item
prop.put("content", "0");
prop.put("rss", "0");
@@ -178,6 +177,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
prop.putXML("content_title-xml", result.title());
prop.putJSON("content_title-json", result.title());
prop.putHTML("content_showPictures_link", resultUrlstring);
prop.put("content_showPictures_authSearch", authenticated);
/* Add information about the current search navigators to let browser refresh yacysearchtrailer only if needed */
prop.put("content_nav-generation", theSearch.getNavGeneration());
@@ -72,12 +72,11 @@ public static serverObjects respond(final RequestHeader header, final serverObje
final boolean adminAuthenticated = sb.verifyAuthentication(header);
final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null;
final boolean userAuthenticated = (user != null && user.hasRight(UserDB.AccessRight.EXTENDED_SEARCH_RIGHT));
final boolean authenticated = adminAuthenticated || userAuthenticated;
final boolean authenticated = adminAuthenticated || user != null;
if (post.containsKey("auth") && !authenticated) {
/*
* Access to authentication protected features is explicitely requested here
* Authenticated search is explicitely requested here
* but no authentication is provided : ask now for authentication.
* Wihout this, after timeout of HTTP Digest authentication nonce, browsers no more send authentication information
* and as this page is not private, protected features would simply be hidden without asking browser again for authentication.
Oops, something went wrong.

0 comments on commit 8e732d4

Please sign in to comment.