diff --git a/bin/apicall.sh b/bin/apicall.sh index bfdcbc680..9f9ad70b5 100755 --- a/bin/apicall.sh +++ b/bin/apicall.sh @@ -21,10 +21,11 @@ port=$(grep ^port= "$YACY_DATA_PATH/SETTINGS/yacy.conf" |cut -d= -f2) admin=$(grep ^adminAccountUserName= "$YACY_DATA_PATH/SETTINGS/yacy.conf" |cut -d= -f2) adminAccountForLocalhost=$(grep ^adminAccountForLocalhost= "$YACY_DATA_PATH/SETTINGS/yacy.conf" | cut -d= -f2) -if grep "BASIC" "$YACY_APP_PATH/defaults/web.xml" > /dev/null; then - # When authentication method is in basic mode, use directly the password hash from the configuration file - YACY_ADMIN_PASSWORD=$(grep ^adminAccountBase64MD5= "$YACY_DATA_PATH/SETTINGS/yacy.conf" |cut -d= -f2) -fi +# Use directly the password hash from the configuration file. This is accepted as PW when the call comes from localhost. +# This exception in authorization handling makes it possible that users with access to the YaCy configuration files can administrate +# a peer without manual authentication input. This works only with Basic auth method. +# This is not a huge security problem because the target address is always localhost. +YACY_ADMIN_PASSWORD=$(grep ^adminAccountBase64MD5= "$YACY_DATA_PATH/SETTINGS/yacy.conf" |cut -d= -f2) if which curl > /dev/null; then if [ "$adminAccountForLocalhost" = "true" ]; then @@ -32,21 +33,21 @@ if which curl > /dev/null; then curl -sSf "http://127.0.0.1:$port/$1" elif [ -n "$YACY_ADMIN_PASSWORD" ]; then # admin password is provided as environment variable : let's use it - curl -sSf --anyauth -u "$admin:$YACY_ADMIN_PASSWORD" "http://127.0.0.1:$port/$1" + curl -sSf --basic -u "$admin:$YACY_ADMIN_PASSWORD" "http://127.0.0.1:$port/$1" else # no password environment variable : it will be asked interactively - curl -sSf --anyauth -u "$admin" "http://127.0.0.1:$port/$1" + curl -sSf --basic -u "$admin" "http://127.0.0.1:$port/$1" fi elif which wget > /dev/null; then if [ "$adminAccountForLocalhost" = "true" ]; then # localhost access as administrator without authentication is enabled - wget -nv -t 1 --timeout=120 "http://127.0.0.1:$port/$1" -O - + wget -nv --auth-no-challenge -t 1 --timeout=120 "http://127.0.0.1:$port/$1" -O - elif [ -n "$YACY_ADMIN_PASSWORD" ]; then # admin password is provided as environment variable : let's use it - wget -nv -t 1 --timeout=120 --http-user "$admin" --http-password "$YACY_ADMIN_PASSWORD" "http://127.0.0.1:$port/$1" -O - + wget -nv --auth-no-challenge -t 1 --timeout=120 --http-user "$admin" --http-password "$YACY_ADMIN_PASSWORD" "http://127.0.0.1:$port/$1" -O - else # no password environment variable : it will be asked interactively - wget -nv -t 1 --timeout=120 --http-user "$admin" --ask-password "http://127.0.0.1:$port/$1" -O - + wget -nv --auth-no-challenge -t 1 --timeout=120 --http-user "$admin" --ask-password "http://127.0.0.1:$port/$1" -O - fi else echo "Please install curl or wget" > /dev/stderr diff --git a/bin/clearall.sh b/bin/clearall.sh index 885379c9c..2f157f6a9 100755 --- a/bin/clearall.sh +++ b/bin/clearall.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh cd "`dirname $0`" -./protectedPostApiCall.sh "IndexControlURLs_p.html" "deletecomplete=&deleteIndex=on&deleteSolr=on&deleteCrawlQueues=on&deleteRobots=on&deleteSearchFl=on&deleteCache=on" \ No newline at end of file +./apicall.sh "IndexControlURLs_p.html" "deletecomplete=&deleteIndex=on&deleteSolr=on&deleteCrawlQueues=on&deleteRobots=on&deleteSearchFl=on&deleteCache=on" > /dev/null diff --git a/bin/clearcache.sh b/bin/clearcache.sh index 926d70e78..97de5f40e 100755 --- a/bin/clearcache.sh +++ b/bin/clearcache.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh cd "`dirname $0`" -./protectedPostApiCall.sh "IndexControlURLs_p.html" "deleteIndex=off&deleteSolr=off&deleteCache=on&deleteCrawlQueues=off&deleteRobots=on&deleteSearchFl=on&deletecomplete=" +./apicall.sh "IndexControlURLs_p.html" "deleteIndex=off&deleteSolr=off&deleteCache=on&deleteCrawlQueues=off&deleteRobots=on&deleteSearchFl=on&deletecomplete=" > /dev/null diff --git a/bin/clearindex.sh b/bin/clearindex.sh index 9c78bb997..773bb824b 100755 --- a/bin/clearindex.sh +++ b/bin/clearindex.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh cd "`dirname $0`" -./protectedPostApiCall.sh "IndexControlURLs_p.html" "deletecomplete=&deleteIndex=on&deleteSolr=on&deleteCrawlQueues=on&deleteRobots=on&deleteSearchFl=on&deleteCache=off" +./apicall.sh "IndexControlURLs_p.html" "deletecomplete=&deleteIndex=on&deleteSolr=on&deleteCrawlQueues=on&deleteRobots=on&deleteSearchFl=on&deleteCache=off" > /dev/null diff --git a/bin/deleteurl.sh b/bin/deleteurl.sh index 94aefcfb3..e5cb00da3 100755 --- a/bin/deleteurl.sh +++ b/bin/deleteurl.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh cd "`dirname $0`" -./protectedPostApiCall.sh "IndexControlURLs_p.html" "urlhashdeleteall=&urlstring=$1" +./apicall.sh "IndexControlURLs_p.html" "urlhashdeleteall=&urlstring=$1" > /dev/null diff --git a/bin/importmediawiki.sh b/bin/importmediawiki.sh index df1b4c7ae..7f5e829f8 100755 --- a/bin/importmediawiki.sh +++ b/bin/importmediawiki.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh cd "`dirname $0`" -./protectedPostApiCall.sh "IndexImportMediawiki_p.html" "file=$1" +./apicall.sh "IndexImportMediawiki_p.html" "file=$1" > /dev/null diff --git a/bin/passwd.sh b/bin/passwd.sh index b858929a1..770429b18 100755 --- a/bin/passwd.sh +++ b/bin/passwd.sh @@ -38,7 +38,7 @@ if [ -f "$YACY_DATA_PATH/yacy.running" ]; then echo "YaCy server appears to be running. Calling the ConfigAccounts_p API..." # When the server is running we can not directly modify the yacy.conf file so we use the ConfigAccounts_p API. # Otherwise the new password provided here could be overwritten by the server when it saves its in-memory configuration to the yacy.conf file - (./protectedPostApiCall.sh "ConfigAccounts_p.html" "setAdmin=&adminuser=$YACY_ADMIN_USER_NAME&adminpw1=$YACY_ADMIN_PASSWORD&adminpw2=$YACY_ADMIN_PASSWORD&access=" && \ + (./apicall.sh "ConfigAccounts_p.html" "setAdmin=&adminuser=$YACY_ADMIN_USER_NAME&adminpw1=$YACY_ADMIN_PASSWORD&adminpw2=$YACY_ADMIN_PASSWORD&access=" && \ echo "Password successfully changed for User Name '$YACY_ADMIN_USER_NAME'.") || \ (echo "Password setting failed." && exit 1) else @@ -54,4 +54,4 @@ else mv "$YACY_CONF_FILE".tmp "$YACY_CONF_FILE" && \ echo "Password successfully changed for User Name '$YACY_ADMIN_USER_NAME'.") || \ (echo "Password setting failed." && exit 1) -fi \ No newline at end of file +fi diff --git a/source/net/yacy/http/Jetty9YaCySecurityHandler.java b/source/net/yacy/http/Jetty9YaCySecurityHandler.java index 204418c60..cb58ef7ff 100644 --- a/source/net/yacy/http/Jetty9YaCySecurityHandler.java +++ b/source/net/yacy/http/Jetty9YaCySecurityHandler.java @@ -45,7 +45,7 @@ import org.eclipse.jetty.server.Request; * and updates AccessTracker */ public class Jetty9YaCySecurityHandler extends ConstraintSecurityHandler { - + /** * create the constraint for the given path * for urls containing *_p. (like info_p.html) admin access is required, @@ -66,40 +66,40 @@ public class Jetty9YaCySecurityHandler extends ConstraintSecurityHandler { // update AccessTracker final String remoteip = RequestHeader.client(request); serverAccessTracker.track(remoteip, pathInContext); - + try { refererHost = new MultiProtocolURL(request.getHeader(RequestHeader.REFERER)).getHost(); } catch (MalformedURLException e) { refererHost = null; - } + } final boolean accessFromLocalhost = Domains.isLocalhost(remoteip) && (refererHost == null || refererHost.length() == 0 || Domains.isLocalhost(refererHost)); // ! note : accessFromLocalhost compares localhost ip pattern final boolean grantedForLocalhost = adminAccountGrantedForLocalhost && accessFromLocalhost; - - /* Even when all pages are protected, we don't want to block those used for peer-to-peer or cluster communication (except in private robinson mode) - * (examples : /yacy/hello.html is required for p2p and cluster network presence and /solr/select for remote Solr search requests) */ - boolean protectedPage = (adminAccountNeededForAllPages && ((sb.isRobinsonMode() && !sb.isPublicRobinson()) || - !(pathInContext.startsWith("/yacy/") || pathInContext.startsWith("/solr/")))); - - /* Pages suffixed with "_p" are by the way always considered protected */ - protectedPage = protectedPage || (pathInContext.indexOf("_p.") > 0); - + + /* Even when all pages are protected, we don't want to block those used for peer-to-peer or cluster communication (except in private robinson mode) + * (examples : /yacy/hello.html is required for p2p and cluster network presence and /solr/select for remote Solr search requests) */ + boolean protectedPage = (adminAccountNeededForAllPages && ((sb.isRobinsonMode() && !sb.isPublicRobinson()) || + !(pathInContext.startsWith("/yacy/") || pathInContext.startsWith("/solr/")))); + + /* Pages suffixed with "_p" are by the way always considered protected */ + protectedPage = protectedPage || (pathInContext.indexOf("_p.") > 0); + // check "/gsa" and "/solr" if not publicSearchpage if (!protectedPage && !sb.getConfigBool(SwitchboardConstants.PUBLIC_SEARCHPAGE, true)) { - protectedPage = pathInContext.startsWith("/solr/") || pathInContext.startsWith("/gsa/"); + protectedPage = pathInContext.startsWith("/solr/") || pathInContext.startsWith("/gsa/"); } if (protectedPage) { if (grantedForLocalhost) { - return null; // quick return for local admin + return null; } else if (accessFromLocalhost) { - // last chance to authentify using the admin from localhost + // last chance to authorize using the admin from localhost final String credentials = request.getHeader(RequestHeader.AUTHORIZATION); - if (credentials != null && credentials.length() < 60 && credentials.startsWith("Basic ")) { // Basic credentials are short "Basic " + b64(user:pwd) + if (credentials != null && credentials.length() < 120 && credentials.startsWith("Basic ")) { // Basic credentials are short "Basic " + b64(user:pwd) final String foruser = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"); final String adminAccountBase64MD5 = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""); final String b64 = Base64Order.standardCoder.encodeString(foruser + ":" + adminAccountBase64MD5); // TODO: is this valid? ; consider "MD5:" prefixed config - if ((credentials.substring(6)).equals(b64)) return null; // lazy authentification for local access with credential from config (only a user with read access to DATA can do that) + if ((credentials.substring(6)).equals(b64)) return null; // lazy authentication for local access with credential from config (only a user with read access to DATA can do that) } } RoleInfo roleinfo = new RoleInfo(); diff --git a/stopYACY.sh b/stopYACY.sh index 557db43b7..4818819f3 100755 --- a/stopYACY.sh +++ b/stopYACY.sh @@ -20,7 +20,7 @@ if [ ! -f "$YACY_DATA_PATH/yacy.running" ]; then exit 1 fi -(bin/protectedPostApiCall.sh "Steering.html" "shutdown=true" && \ +(bin/apicall.sh "Steering.html" "shutdown=true" && \ echo "Please wait until the YaCy daemon process terminates [wget]" && \ echo "You can monitor this with 'tail -f $YACY_DATA_PATH/LOG/yacy00.log' and 'fuser $YACY_DATA_PATH/LOG/yacy00.log'") || \ exit $?