diff --git a/htroot/ConfigBasic.java b/htroot/ConfigBasic.java index fcf4e5f35..3129eff97 100644 --- a/htroot/ConfigBasic.java +++ b/htroot/ConfigBasic.java @@ -53,6 +53,7 @@ import java.util.regex.Pattern; import de.anomic.data.translator; import de.anomic.http.httpHeader; +import de.anomic.http.httpd; import de.anomic.http.httpdFileHandler; import de.anomic.kelondro.kelondroBase64Order; import de.anomic.plasma.plasmaSwitchboard; @@ -142,7 +143,7 @@ public class ConfigBasic { // admin password if ((user.length() > 0) && (pw1.length() > 3) && (pw1.equals(pw2))) { // check passed. set account: - env.setConfig("adminAccountBase64MD5", serverCodings.encodeMD5Hex(kelondroBase64Order.standardCoder.encodeString(user + ":" + pw1))); + env.setConfig(httpd.ADMIN_ACCOUNT_B64MD5, serverCodings.encodeMD5Hex(kelondroBase64Order.standardCoder.encodeString(user + ":" + pw1))); env.setConfig("adminAccount", ""); // authenticate immediately //prop.put("AUTHENTICATE", "admin log-in"); @@ -191,7 +192,7 @@ public class ConfigBasic { } // check if values are proper - boolean properPW = (env.getConfig("adminAccount", "").length() == 0) && (env.getConfig("adminAccountBase64MD5", "").length() > 0); + boolean properPW = (env.getConfig("adminAccount", "").length() == 0) && (env.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, "").length() > 0); boolean properName = (env.getConfig("peerName","").length() >= 3) && (!(yacySeed.isDefaultPeerName(env.getConfig("peerName","")))); boolean properPort = (yacyCore.seedDB.mySeed.isSenior()) || (yacyCore.seedDB.mySeed.isPrincipal()); diff --git a/htroot/SettingsAck_p.java b/htroot/SettingsAck_p.java index 109640c2f..8c14c6be8 100644 --- a/htroot/SettingsAck_p.java +++ b/htroot/SettingsAck_p.java @@ -124,7 +124,7 @@ public class SettingsAck_p { return prop; } // check passed. set account: - env.setConfig("adminAccountBase64MD5", serverCodings.encodeMD5Hex(kelondroBase64Order.standardCoder.encodeString(user + ":" + pw1))); + env.setConfig(httpd.ADMIN_ACCOUNT_B64MD5, serverCodings.encodeMD5Hex(kelondroBase64Order.standardCoder.encodeString(user + ":" + pw1))); env.setConfig("adminAccount", ""); prop.put("info", 5);//admin account changed prop.put("info_user", user); diff --git a/htroot/Status.java b/htroot/Status.java index a53492239..28905e87c 100644 --- a/htroot/Status.java +++ b/htroot/Status.java @@ -50,6 +50,7 @@ import java.text.DecimalFormat; import java.util.Date; import de.anomic.http.httpHeader; +import de.anomic.http.httpd; import de.anomic.http.httpdByteCountInputStream; import de.anomic.http.httpdByteCountOutputStream; import de.anomic.plasma.plasmaSwitchboard; @@ -137,7 +138,7 @@ public class Status { } // password protection - if (env.getConfig("adminAccountBase64MD5", "").length() == 0) { + if (env.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, "").length() == 0) { prop.put("protection", 0); // not protected } else { prop.put("protection", 1); // protected diff --git a/htroot/User.java b/htroot/User.java index 2c4ed2524..eb9af874a 100644 --- a/htroot/User.java +++ b/htroot/User.java @@ -50,6 +50,7 @@ import java.io.IOException; import de.anomic.data.userDB; import de.anomic.http.httpHeader; +import de.anomic.http.httpd; import de.anomic.kelondro.kelondroBase64Order; import de.anomic.plasma.plasmaSwitchboard; import de.anomic.server.serverCodings; @@ -112,7 +113,7 @@ public class User{ String password=(String)post.get("password"); entry=sb.userDB.passwordAuth(username, password); - boolean staticAdmin = sb.getConfig("adminAccountBase64MD5", "").equals( + boolean staticAdmin = sb.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, "").equals( serverCodings.encodeMD5Hex( kelondroBase64Order.standardCoder.encodeString(username + ":" + password) ) diff --git a/htroot/htdocsdefault/dir.java b/htroot/htdocsdefault/dir.java index 38e98858f..abfc36726 100644 --- a/htroot/htdocsdefault/dir.java +++ b/htroot/htdocsdefault/dir.java @@ -58,6 +58,7 @@ import java.util.Iterator; import de.anomic.data.userDB; import de.anomic.http.httpHeader; +import de.anomic.http.httpd; import de.anomic.plasma.plasmaURL; import de.anomic.index.indexURLEntry; import de.anomic.kelondro.kelondroBase64Order; @@ -113,7 +114,7 @@ public class dir { prop.put("port", serverCore.getPortNr(env.getConfig("port","8080"))); // generate upload/download authorizations - final String adminAccountBase64MD5 = switchboard.getConfig("adminAccountBase64MD5", ""); + final String adminAccountBase64MD5 = switchboard.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, ""); final String uploadAccountBase64MD5 = switchboard.getConfig("uploadAccountBase64MD5", ""); final String downloadAccountBase64MD5 = switchboard.getConfig("downloadAccountBase64MD5", ""); diff --git a/htroot/yacysearch.java b/htroot/yacysearch.java index e99b6bdde..4dd5a2118 100644 --- a/htroot/yacysearch.java +++ b/htroot/yacysearch.java @@ -54,7 +54,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.TreeSet; -import de.anomic.data.wikiCode; import de.anomic.htmlFilter.htmlFilterImageEntry; import de.anomic.http.httpHeader; import de.anomic.index.indexURLEntry; diff --git a/source/de/anomic/http/httpd.java b/source/de/anomic/http/httpd.java index 23732cb4f..ea0df6d9f 100644 --- a/source/de/anomic/http/httpd.java +++ b/source/de/anomic/http/httpd.java @@ -56,7 +56,6 @@ import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URLDecoder; import java.net.URLEncoder; -import java.nio.charset.Charset; import java.util.Arrays; import java.util.Date; import java.util.HashMap; @@ -67,6 +66,7 @@ import java.util.StringTokenizer; import de.anomic.data.userDB; import de.anomic.data.wikiCode; +import de.anomic.kelondro.kelondroBase64Order; import de.anomic.net.URL; import de.anomic.plasma.plasmaSwitchboard; import de.anomic.server.serverByteBuffer; @@ -90,6 +90,13 @@ import de.anomic.yacy.yacySeed; */ public final class httpd implements serverHandler { + /** + *

public static final String ADMIN_ACCOUNT_B64MD5 = "adminAccountBase64MD5"

+ *

Name of the setting holding the authentification hash for the static admin-account. It is calculated + * by first encoding username:password as Base64 and hashing it using {@link serverCodings#encodeMD5Hex(String)}.

+ */ + public static final String ADMIN_ACCOUNT_B64MD5 = "adminAccountBase64MD5"; + public static final int ERRORCASE_MESSAGE = 4; public static final int ERRORCASE_FILE = 5; @@ -287,6 +294,16 @@ public final class httpd implements serverHandler { return persistent; } + public static int staticAdminAuthenticated(String authorization, serverSwitch sw){ + if(authorization==null) return 1; + //if (authorization.length() < 6) return 1; // no authentication information given + //authorization = authorization.trim().substring(6); + String adminAccountBase64MD5 = sw.getConfig(ADMIN_ACCOUNT_B64MD5, ""); + if (adminAccountBase64MD5.length() == 0) return 2; // no passwrd stored + if (adminAccountBase64MD5.equals(serverCodings.encodeMD5Hex(authorization))) return 4; // hard-authenticated, all ok + return 0; + } + private boolean handleServerAuthentication(httpHeader header) throws IOException { // getting the http version that is used by the client String httpVersion = this.prop.getProperty(httpHeader.CONNECTION_PROP_HTTP_VER, "HTTP/0.9"); @@ -319,6 +336,24 @@ public final class httpd implements serverHandler { return true; } + private boolean handleYaCyHopAuthentication(httpHeader header) throws IOException { + // proxy hops must identify with 3 criteria: + + // the access path must be into the yacy protocol path; it must start with 'yacy' + if (!(this.prop.getProperty(httpHeader.CONNECTION_PROP_PATH, "").startsWith("/yacy/"))) return false; + + // the accessing client must identify with user:password, where + // user = addressed peer name + // pw = addressed peer hash (b64-hash) + String auth = (String) header.get(httpHeader.PROXY_AUTHORIZATION,"xxxxxx"); + String test = kelondroBase64Order.standardCoder.encodeString(yacyCore.seedDB.mySeed.getName() + ":" + yacyCore.seedDB.mySeed.hash); + if (!test.equals(auth.trim().substring(6))) return false; + + // the accessing client must use a yacy user-agent + + return true; + } + private boolean handleProxyAuthentication(httpHeader header) throws IOException { // getting the http version that is used by the client String httpVersion = this.prop.getProperty("HTTP", "HTTP/0.9"); @@ -456,8 +491,8 @@ public final class httpd implements serverHandler { } } else { // pass to proxy - if (((this.allowYaCyHop) && (this.prop.getProperty(httpHeader.CONNECTION_PROP_PATH, "").startsWith("/yacy/"))) || - ((this.allowProxy) && (this.handleProxyAuthentication(header)))) { + if (((this.allowYaCyHop) && (handleYaCyHopAuthentication(header))) || + ((this.allowProxy) && (handleProxyAuthentication(header)))) { proxyHandler.doGet(this.prop, header, this.session.out); } else { // not authorized through firewall blocking (ip does not match filter) @@ -529,8 +564,8 @@ public final class httpd implements serverHandler { } } else { // pass to proxy - if (((this.allowYaCyHop) && (this.prop.getProperty(httpHeader.CONNECTION_PROP_PATH, "").startsWith("/yacy/"))) || - ((this.allowProxy) && (this.handleProxyAuthentication(header)))) { + if (((this.allowYaCyHop) && (handleYaCyHopAuthentication(header))) || + ((this.allowProxy) && (handleProxyAuthentication(header)))) { proxyHandler.doHead(prop, header, this.session.out); } else { // not authorized through firewall blocking (ip does not match filter) @@ -611,8 +646,8 @@ public final class httpd implements serverHandler { } } else { // pass to proxy - if (((this.allowYaCyHop) && (this.prop.getProperty(httpHeader.CONNECTION_PROP_PATH, "").startsWith("/yacy/"))) || - ((this.allowProxy) && (this.handleProxyAuthentication(header)))) { + if (((this.allowYaCyHop) && (handleYaCyHopAuthentication(header))) || + ((this.allowProxy) && (handleProxyAuthentication(header)))) { proxyHandler.doPost(prop, header, this.session.out, this.session.in); } else { // not authorized through firewall blocking (ip does not match filter) @@ -678,7 +713,7 @@ public final class httpd implements serverHandler { } // pass to proxy - if (((this.allowYaCyHop) && (this.prop.getProperty(httpHeader.CONNECTION_PROP_PATH, "").startsWith("/yacy/"))) || + if (((this.allowYaCyHop) && (handleYaCyHopAuthentication(header))) || ((this.allowProxy) && (this.handleProxyAuthentication(header)))) { proxyHandler.doConnect(prop, header, this.session.in, this.session.out); } else { diff --git a/source/de/anomic/http/httpdFileHandler.java b/source/de/anomic/http/httpdFileHandler.java index 28154b977..36b1a4a2d 100644 --- a/source/de/anomic/http/httpdFileHandler.java +++ b/source/de/anomic/http/httpdFileHandler.java @@ -137,12 +137,8 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http private MessageDigest md5Digest = null; - /** - * Template Cache - * @param switchboard - */ - private static final HashMap templateCache; - + + private static final HashMap templateCache; private static final HashMap templateMethodCache; public static boolean useTemplateCache = false; @@ -319,7 +315,7 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http // check permission/granted access String authorization = (String) requestHeader.get(httpHeader.AUTHORIZATION); - String adminAccountBase64MD5 = switchboard.getConfig("adminAccountBase64MD5", ""); + String adminAccountBase64MD5 = switchboard.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, ""); int pos = path.lastIndexOf("."); @@ -330,7 +326,7 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http //Authentication successful. remove brute-force flag serverCore.bfHost.remove(conProp.getProperty("CLIENTIP")); //static - }else if(authorization != null && sb.staticAdminAuthenticated(authorization.trim().substring(6))==4){ + }else if(authorization != null && httpd.staticAdminAuthenticated(authorization.trim().substring(6), switchboard)==4){ //Authentication successful. remove brute-force flag serverCore.bfHost.remove(conProp.getProperty("CLIENTIP")); //no auth diff --git a/source/de/anomic/plasma/plasmaSwitchboard.java b/source/de/anomic/plasma/plasmaSwitchboard.java index 2c131398e..c7771c3a8 100644 --- a/source/de/anomic/plasma/plasmaSwitchboard.java +++ b/source/de/anomic/plasma/plasmaSwitchboard.java @@ -131,6 +131,7 @@ import de.anomic.htmlFilter.htmlFilterContentScraper; import de.anomic.http.httpHeader; import de.anomic.http.httpRemoteProxyConfig; import de.anomic.http.httpc; +import de.anomic.http.httpd; import de.anomic.index.indexContainer; import de.anomic.index.indexRWIEntry; import de.anomic.index.indexRWIEntryNew; @@ -148,7 +149,6 @@ import de.anomic.plasma.parser.ParserException; import de.anomic.plasma.urlPattern.defaultURLPattern; import de.anomic.plasma.urlPattern.plasmaURLPattern; import de.anomic.server.serverAbstractSwitch; -import de.anomic.server.serverCodings; import de.anomic.server.serverDate; import de.anomic.server.serverFileUtils; import de.anomic.server.serverInstantThread; @@ -632,12 +632,6 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser */ public static final String CRAWLER_THREADS_ACTIVE_MAX = "crawler.MaxActiveThreads"; - /** - *

public static final String ADMIN_ACCOUNT_B64MD5 = "adminAccountBase64MD5"

- *

Name of the setting holding the authentification hash for the static admin-account. It is calculated - * by first encoding username:password as Base64 and hashing it using {@link serverCodings#encodeMD5Hex(String)}.

- */ - public static final String ADMIN_ACCOUNT_B64MD5 = "adminAccountBase64MD5"; public static final String OWN_SEED_FILE = "yacyOwnSeedFile"; /** *

public static final String STORAGE_PEER_HASH = "storagePeerHash"

@@ -2888,7 +2882,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser public int adminAuthenticated(httpHeader header) { - String adminAccountBase64MD5 = getConfig("adminAccountBase64MD5", ""); + String adminAccountBase64MD5 = getConfig(httpd.ADMIN_ACCOUNT_B64MD5, ""); String authorization = ((String) header.get(httpHeader.AUTHORIZATION, "xxxxxx")).trim().substring(6); // security check against too long authorization strings @@ -2901,17 +2895,7 @@ public final class plasmaSwitchboard extends serverAbstractSwitch implements ser if (userDB.hasAdminRight((String) header.get(httpHeader.AUTHORIZATION, "xxxxxx"), ((String) header.get("CLIENTIP", "")), header.getHeaderCookies())) return 4; //return, because 4=max // authorization with admin keyword in configuration - return staticAdminAuthenticated(authorization); - } - - public int staticAdminAuthenticated(String authorization){ - if(authorization==null) return 1; - //if (authorization.length() < 6) return 1; // no authentication information given - //authorization = authorization.trim().substring(6); - String adminAccountBase64MD5 = getConfig(ADMIN_ACCOUNT_B64MD5, ""); - if (adminAccountBase64MD5.length() == 0) return 2; // no passwrd stored - if (adminAccountBase64MD5.equals(serverCodings.encodeMD5Hex(authorization))) return 4; // hard-authenticated, all ok - return 0; + return httpd.staticAdminAuthenticated(authorization, this); } public boolean verifyAuthentication(httpHeader header, boolean strict) { diff --git a/source/de/anomic/soap/AbstractService.java b/source/de/anomic/soap/AbstractService.java index 614dc8643..df08ebb63 100644 --- a/source/de/anomic/soap/AbstractService.java +++ b/source/de/anomic/soap/AbstractService.java @@ -67,6 +67,7 @@ import org.w3c.dom.Element; import de.anomic.http.httpHeader; import de.anomic.http.httpTemplate; +import de.anomic.http.httpd; import de.anomic.server.serverClassLoader; import de.anomic.server.serverObjects; import de.anomic.server.serverSwitch; @@ -235,7 +236,7 @@ public abstract class AbstractService { // the base64 encoded and md5 hashed authentication string String authString = authElement.getValue(); - String adminAccountBase64MD5 = this.switchboard.getConfig("adminAccountBase64MD5",""); + String adminAccountBase64MD5 = this.switchboard.getConfig(httpd.ADMIN_ACCOUNT_B64MD5,""); if (authString.length() == 0) { throw new AxisFault("log-in required"); } else if (!(adminAccountBase64MD5.equals(authString))) { diff --git a/source/migration.java b/source/migration.java index 57beb09f4..aaedb5e67 100644 --- a/source/migration.java +++ b/source/migration.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import de.anomic.data.listManager; +import de.anomic.http.httpd; import de.anomic.kelondro.kelondroBase64Order; import de.anomic.plasma.plasmaSwitchboard; import de.anomic.server.serverFileUtils; @@ -187,7 +188,7 @@ public class migration { sb.setConfig("serverAccount", ""); } if ((acc = sb.getConfig("adminAccount", "")).length() > 0) { - sb.setConfig("adminAccountBase64MD5", de.anomic.server.serverCodings.encodeMD5Hex(kelondroBase64Order.standardCoder.encodeString(acc))); + sb.setConfig(httpd.ADMIN_ACCOUNT_B64MD5, de.anomic.server.serverCodings.encodeMD5Hex(kelondroBase64Order.standardCoder.encodeString(acc))); sb.setConfig("adminAccount", ""); } @@ -201,7 +202,7 @@ public class migration { sb.setConfig("serverAccountBase64", ""); } if ((acc = sb.getConfig("adminAccountBase64", "")).length() > 0) { - sb.setConfig("adminAccountBase64MD5", de.anomic.server.serverCodings.encodeMD5Hex(acc)); + sb.setConfig(httpd.ADMIN_ACCOUNT_B64MD5, de.anomic.server.serverCodings.encodeMD5Hex(acc)); sb.setConfig("adminAccountBase64", ""); } if ((acc = sb.getConfig("uploadAccountBase64", "")).length() > 0) { diff --git a/source/yacy.java b/source/yacy.java index d062542db..533800947 100644 --- a/source/yacy.java +++ b/source/yacy.java @@ -379,7 +379,7 @@ public final class yacy { final boolean browserPopUpTrigger = sb.getConfig("browserPopUpTrigger", "true").equals("true"); if (browserPopUpTrigger) { String browserPopUpPage = sb.getConfig("browserPopUpPage", "ConfigBasic.html"); - boolean properPW = (sb.getConfig("adminAccount", "").length() == 0) && (sb.getConfig("adminAccountBase64MD5", "").length() > 0); + boolean properPW = (sb.getConfig("adminAccount", "").length() == 0) && (sb.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, "").length() > 0); if (!properPW) browserPopUpPage = "ConfigBasic.html"; final String browserPopUpApplication = sb.getConfig("browserPopUpApplication", "netscape"); serverSystem.openBrowser((server.withSSL()?"https":"http") + "://localhost:" + serverCore.getPortNr(port) + "/" + browserPopUpPage, browserPopUpApplication); @@ -539,7 +539,7 @@ public final class yacy { int port = serverCore.getPortNr(config.getProperty("port", "8080")); // read password - String encodedPassword = (String) config.get("adminAccountBase64MD5"); + String encodedPassword = (String) config.get(httpd.ADMIN_ACCOUNT_B64MD5); if (encodedPassword == null) encodedPassword = ""; // not defined // send 'wget' to web interface diff --git a/test/de/anomic/soap/services/AbstractServiceTest.java b/test/de/anomic/soap/services/AbstractServiceTest.java index a2d9d7ce2..6bca3292a 100644 --- a/test/de/anomic/soap/services/AbstractServiceTest.java +++ b/test/de/anomic/soap/services/AbstractServiceTest.java @@ -15,6 +15,8 @@ import org.apache.axis.MessageContext; import org.apache.axis.client.Stub; import org.apache.axis.transport.http.HTTPConstants; +import de.anomic.http.httpd; + public abstract class AbstractServiceTest extends TestCase { protected static final String SOAP_HEADER_NAMESPACE = "http://http.anomic.de/header"; protected static final String SOAP_HEADER_AUTHORIZATION = "Authorization"; @@ -47,7 +49,7 @@ public abstract class AbstractServiceTest extends TestCase { fileInput.close(); // getting admin account auth string - authString = peerProperties.getProperty("adminAccountBase64MD5"); + authString = peerProperties.getProperty(httpd.ADMIN_ACCOUNT_B64MD5); if (authString == null) throw new Exception("Unable to find authentication information."); peerPort = peerProperties.getProperty("port");