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.
This commit is contained in:
luccioman 2018-04-18 08:10:51 +02:00
parent 02673379df
commit 8bc36506f2
4 changed files with 73 additions and 47 deletions

View File

@ -28,7 +28,8 @@
Your YaCy Peer needs some basic information to operate properly
</p>
<form action="ConfigBasic.html" method="get" accept-charset="UTF-8">
<form action="ConfigBasic.html" method="post" accept-charset="UTF-8">
<input type="hidden" name="transactionToken" value="#[transactionToken]#"/>
<ol>
<li>
<img src="env/grafics/ok.png" height="16" width="16" alt="ok" />&nbsp;Select a language for the interface:<br />
@ -46,7 +47,7 @@
</fieldset>
</li>
<!-- take care that no other items are changed, but also change the former if no js is enabled -->
<script type="text/javascript"> document.write('</form><form action="ConfigBasic.html" method="get">'); </script>
<script type="text/javascript"> document.write('</form><form action="ConfigBasic.html" method="post" accept-charset="UTF-8"><input type="hidden" name="transactionToken" value="#[transactionToken]#"/>');</script>
#(setUseCase)#::

View File

@ -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);
// 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();
}
}
}
if (ssl) {
prop.put("withsslenabled_sslport", env.getHttpServer().getSslPort());
}
if (peerName != null && peerName.length() > 0) {
peerName = peerName.replace(' ', '-');
}
// peer name settings
String peerName = (post == null) ? sb.peers.mySeed().getName() : post.get("peername", "");
if (peerName != null && peerName.length() > 0) peerName = peerName.replace(' ', '-');
// 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());
// 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)) {

View File

@ -49,6 +49,7 @@
#(commitDHTNoGlobalSearch)#::<div class="error">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.</div>#(/commitDHTNoGlobalSearch)#
#(commitRobinson)#::<div class="commit">For Robinson Mode, index distribution and receive is switched off.</div>#(/commitRobinson)#
<form id="NetworkForm" method="post" action="ConfigNetwork_p.html" enctype="multipart/form-data" accept-charset="UTF-8">
<input type="hidden" name="transactionToken" value="#[transactionToken]#"/>
<fieldset>
<legend>
<label>Network and Domain Specification</label>
@ -101,6 +102,7 @@
without any data exchange between your peer and other peers.
</p>
<form id="ConfigForm" method="post" action="ConfigNetwork_p.html" enctype="multipart/form-data" accept-charset="UTF-8">
<input type="hidden" name="transactionToken" value="#[transactionToken]#"/>
<fieldset>
<legend>
<input type="radio" name="network" id="p2p" onclick="EnableP2P()" value="p2p"#(p2p.checked)#:: checked="checked"#(/p2p.checked)# />

View File

@ -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", ""));