From 8bc36506f238f18a57969336a1c66d3b56ce91c9 Mon Sep 17 00:00:00 2001 From: luccioman Date: Wed, 18 Apr 2018 08:10:51 +0200 Subject: [PATCH] Enforced access controls on basic administration settings pages. Ensuring http post method is used for operations with server-side effects (in respect of http semantics), and a valid transaction token is provided by the user-agent. --- htroot/ConfigBasic.html | 5 +- htroot/ConfigBasic.java | 97 +++++++++++++++++++++---------------- htroot/ConfigNetwork_p.html | 2 + htroot/ConfigNetwork_p.java | 12 ++++- 4 files changed, 71 insertions(+), 45 deletions(-) diff --git a/htroot/ConfigBasic.html b/htroot/ConfigBasic.html index bef5b4775..60f7f7abc 100644 --- a/htroot/ConfigBasic.html +++ b/htroot/ConfigBasic.html @@ -28,7 +28,8 @@ Your YaCy Peer needs some basic information to operate properly

-
+ +
  1. ok Select a language for the interface:
    @@ -46,7 +47,7 @@
  2. - + #(setUseCase)#:: diff --git a/htroot/ConfigBasic.java b/htroot/ConfigBasic.java index 2eb239c32..3345f7aec 100644 --- a/htroot/ConfigBasic.java +++ b/htroot/ConfigBasic.java @@ -36,6 +36,7 @@ import java.util.regex.Pattern; import net.yacy.cora.protocol.Domains; import net.yacy.cora.protocol.RequestHeader; +import net.yacy.data.TransactionManager; import net.yacy.data.Translator; import net.yacy.data.WorkTables; import net.yacy.http.YaCyHttpServer; @@ -65,47 +66,71 @@ public class ConfigBasic { final serverObjects prop = new serverObjects(); final File langPath = new File(sb.getAppPath("locale.source", "locales").getAbsolutePath()); String lang = env.getConfig("locale.language", "browser"); - + final int authentication = sb.adminAuthenticated(header); if (authentication < 2) { // must authenticate prop.authenticationRequired(); return prop; } - - // store this call as api call - if (post != null && post.containsKey("set")) { - sb.tables.recordAPICall(post, "ConfigBasic.html", WorkTables.TABLE_API_TYPE_CONFIGURATION, "basic settings"); - } - - //boolean doPeerPing = false; + + /* For authenticated users only : acquire a transaction token for the next POST form submission */ + prop.put(TransactionManager.TRANSACTION_TOKEN_PARAM, TransactionManager.getTransactionToken(header)); + if ((sb.peers.mySeed().isVirgin()) || (sb.peers.mySeed().isJunior())) { new OnePeerPingBusyThread(sb.yc).start(); - //doPeerPing = true; } - // language settings - if (post != null && post.containsKey("language") && !lang.equals(post.get("language", "default")) && - (new TranslatorXliff().changeLang(env, langPath, post.get("language", "default") + ".lng"))) { - prop.put("changedLanguage", "1"); - } + String peerName = sb.peers.mySeed().getName(); + long port = env.getLocalPort(); //this allows a low port, but it will only get one, if the user edits the config himself. + boolean ssl = env.getConfigBool("server.https", false); + boolean upnp = false; + if (post != null) { + /* Settings will be modified : check this is a valid transaction using HTTP POST method */ + TransactionManager.checkPostTransaction(header, post); - // peer name settings - String peerName = (post == null) ? sb.peers.mySeed().getName() : post.get("peername", ""); - if (peerName != null && peerName.length() > 0) peerName = peerName.replace(' ', '-'); + // store this call as api call + if(post.containsKey("set")) { + sb.tables.recordAPICall(post, "ConfigBasic.html", WorkTables.TABLE_API_TYPE_CONFIGURATION, "basic settings"); + } + + // language settings + if(post.containsKey("language") && !lang.equals(post.get("language", "default"))) { + if(new TranslatorXliff().changeLang(env, langPath, post.get("language", "default") + ".lng")) { + prop.put("changedLanguage", "1"); + } + } + + // port settings + if(post.getInt("port", 0) > 1023) { + port = post.getLong("port", 8090); + ssl = post.getBoolean("withssl"); + } + + // peer name settings + peerName = post.get("peername", ""); + + // UPnP config + if(post.containsKey("port")) { // hack to allow checkbox + upnp = post.containsKey("enableUpnp"); + if (upnp && !sb.getConfigBool(SwitchboardConstants.UPNP_ENABLED, false)) { + UPnP.addPortMappings(); + } + sb.setConfig(SwitchboardConstants.UPNP_ENABLED, upnp); + if (!upnp) { + UPnP.deletePortMappings(); + } + } + } - // port settings - final long port; - boolean ssl; - if (post != null && post.getInt("port", 0) > 1023) { - port = post.getLong("port", 8090); - ssl = post.getBoolean("withssl"); - } else { - port = env.getLocalPort(); //this allows a low port, but it will only get one, if the user edits the config himself. - ssl = env.getConfigBool("server.https", false); + if (ssl) { + prop.put("withsslenabled_sslport", env.getHttpServer().getSslPort()); } - if (ssl) prop.put("withsslenabled_sslport",env.getHttpServer().getSslPort()); + if (peerName != null && peerName.length() > 0) { + peerName = peerName.replace(' ', '-'); + } + // check if peer name already exists final Seed oldSeed = sb.peers.lookupByName(peerName); if (oldSeed == null && @@ -115,21 +140,6 @@ public class ConfigBasic { sb.peers.saveMySeed(); } - // UPnP config - final boolean upnp; - if (post != null && post.containsKey("port")) { // hack to allow checkbox - upnp = post.containsKey("enableUpnp"); - if (upnp && !sb.getConfigBool(SwitchboardConstants.UPNP_ENABLED, false)) { - UPnP.addPortMappings(); - } - sb.setConfig(SwitchboardConstants.UPNP_ENABLED, upnp); - if (!upnp) { - UPnP.deletePortMappings(); - } - } else { - upnp = false; - } - // check port and ssl connection final boolean reconnect; if (!(env.getLocalPort() == port) || env.getConfigBool("server.https", false) != ssl) { @@ -175,6 +185,9 @@ public class ConfigBasic { prop.put("setUseCase_switchWarning", 0); String networkName = sb.getConfig(SwitchboardConstants.NETWORK_NAME, ""); if (post != null && post.containsKey("usecase")) { + /* Settings will be modified : check this is a valid transaction using HTTP POST method */ + TransactionManager.checkPostTransaction(header, post); + boolean hasNonEmptyRemoteSolr = sb.index.fulltext().connectedRemoteSolr() && (sb.index.fulltext().collectionSize() > 0 || sb.index.fulltext().webgraphSize() > 0); if ("freeworld".equals(post.get("usecase", "")) && !"freeworld".equals(networkName)) { diff --git a/htroot/ConfigNetwork_p.html b/htroot/ConfigNetwork_p.html index 3870d28d0..d55ed6928 100644 --- a/htroot/ConfigNetwork_p.html +++ b/htroot/ConfigNetwork_p.html @@ -49,6 +49,7 @@ #(commitDHTNoGlobalSearch)#::
    Global Search in P2P configuration is only allowed, if index receive is switched on. You have a P2P configuration, but are not allowed to search other peers.
    #(/commitDHTNoGlobalSearch)# #(commitRobinson)#::
    For Robinson Mode, index distribution and receive is switched off.
    #(/commitRobinson)# +
    @@ -101,6 +102,7 @@ without any data exchange between your peer and other peers.

    +
    diff --git a/htroot/ConfigNetwork_p.java b/htroot/ConfigNetwork_p.java index 554878943..91484c891 100644 --- a/htroot/ConfigNetwork_p.java +++ b/htroot/ConfigNetwork_p.java @@ -33,6 +33,7 @@ import java.util.Set; import net.yacy.cora.document.encoding.ASCII; import net.yacy.cora.protocol.RequestHeader; import net.yacy.cora.util.CommonPattern; +import net.yacy.data.TransactionManager; import net.yacy.data.WorkTables; import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.MapTools; @@ -45,12 +46,16 @@ public class ConfigNetwork_p { public static serverObjects respond( - @SuppressWarnings("unused") final RequestHeader header, + final RequestHeader header, final serverObjects post, final serverSwitch env) throws FileNotFoundException, IOException { final Switchboard sb = (Switchboard) env; final serverObjects prop = new serverObjects(); + + /* Acquire a transaction token for the next POST form submission */ + prop.put(TransactionManager.TRANSACTION_TOKEN_PARAM, TransactionManager.getTransactionToken(header)); + int commit = 0; // load all options for network definitions @@ -68,6 +73,9 @@ public class ConfigNetwork_p "network settings"); if ( post.containsKey("changeNetwork") ) { + /* Settings will be modified : check this is a valid transaction using HTTP POST method */ + TransactionManager.checkPostTransaction(header, post); + String networkDefinition = post.get("networkDefinition", "defaults/yacy.network.freeworld.unit"); final String networkDefinitionURL = post.get("networkDefinitionURL", ""); if ( !networkDefinitionURL.equals("")) { @@ -85,6 +93,8 @@ public class ConfigNetwork_p } if ( post.containsKey("save") ) { + /* Settings will be modified : check this is a valid transaction using HTTP POST method */ + TransactionManager.checkPostTransaction(header, post); // DHT control boolean indexDistribute = "on".equals(post.get("indexDistribute", ""));