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.
pull/137/head
luccioman 7 years ago
parent 02673379df
commit 8bc36506f2

@ -28,7 +28,8 @@
Your YaCy Peer needs some basic information to operate properly Your YaCy Peer needs some basic information to operate properly
</p> </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> <ol>
<li> <li>
<img src="env/grafics/ok.png" height="16" width="16" alt="ok" />&nbsp;Select a language for the interface:<br /> <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> </fieldset>
</li> </li>
<!-- take care that no other items are changed, but also change the former if no js is enabled --> <!-- 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)#:: #(setUseCase)#::

@ -36,6 +36,7 @@ import java.util.regex.Pattern;
import net.yacy.cora.protocol.Domains; import net.yacy.cora.protocol.Domains;
import net.yacy.cora.protocol.RequestHeader; import net.yacy.cora.protocol.RequestHeader;
import net.yacy.data.TransactionManager;
import net.yacy.data.Translator; import net.yacy.data.Translator;
import net.yacy.data.WorkTables; import net.yacy.data.WorkTables;
import net.yacy.http.YaCyHttpServer; import net.yacy.http.YaCyHttpServer;
@ -73,38 +74,62 @@ public class ConfigBasic {
return prop; return prop;
} }
// store this call as api call /* For authenticated users only : acquire a transaction token for the next POST form submission */
if (post != null && post.containsKey("set")) { prop.put(TransactionManager.TRANSACTION_TOKEN_PARAM, TransactionManager.getTransactionToken(header));
sb.tables.recordAPICall(post, "ConfigBasic.html", WorkTables.TABLE_API_TYPE_CONFIGURATION, "basic settings");
}
//boolean doPeerPing = false;
if ((sb.peers.mySeed().isVirgin()) || (sb.peers.mySeed().isJunior())) { if ((sb.peers.mySeed().isVirgin()) || (sb.peers.mySeed().isJunior())) {
new OnePeerPingBusyThread(sb.yc).start(); new OnePeerPingBusyThread(sb.yc).start();
//doPeerPing = true;
} }
// language settings String peerName = sb.peers.mySeed().getName();
if (post != null && post.containsKey("language") && !lang.equals(post.get("language", "default")) && long port = env.getLocalPort(); //this allows a low port, but it will only get one, if the user edits the config himself.
(new TranslatorXliff().changeLang(env, langPath, post.get("language", "default") + ".lng"))) { boolean ssl = env.getConfigBool("server.https", false);
prop.put("changedLanguage", "1"); 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();
}
}
} }
// peer name settings if (ssl) {
String peerName = (post == null) ? sb.peers.mySeed().getName() : post.get("peername", ""); prop.put("withsslenabled_sslport", env.getHttpServer().getSslPort());
if (peerName != null && peerName.length() > 0) peerName = peerName.replace(' ', '-'); }
// port settings if (peerName != null && peerName.length() > 0) {
final long port; peerName = peerName.replace(' ', '-');
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 // check if peer name already exists
final Seed oldSeed = sb.peers.lookupByName(peerName); final Seed oldSeed = sb.peers.lookupByName(peerName);
@ -115,21 +140,6 @@ public class ConfigBasic {
sb.peers.saveMySeed(); 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 // check port and ssl connection
final boolean reconnect; final boolean reconnect;
if (!(env.getLocalPort() == port) || env.getConfigBool("server.https", false) != ssl) { if (!(env.getLocalPort() == port) || env.getConfigBool("server.https", false) != ssl) {
@ -175,6 +185,9 @@ public class ConfigBasic {
prop.put("setUseCase_switchWarning", 0); prop.put("setUseCase_switchWarning", 0);
String networkName = sb.getConfig(SwitchboardConstants.NETWORK_NAME, ""); String networkName = sb.getConfig(SwitchboardConstants.NETWORK_NAME, "");
if (post != null && post.containsKey("usecase")) { 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() boolean hasNonEmptyRemoteSolr = sb.index.fulltext().connectedRemoteSolr()
&& (sb.index.fulltext().collectionSize() > 0 || sb.index.fulltext().webgraphSize() > 0); && (sb.index.fulltext().collectionSize() > 0 || sb.index.fulltext().webgraphSize() > 0);
if ("freeworld".equals(post.get("usecase", "")) && !"freeworld".equals(networkName)) { if ("freeworld".equals(post.get("usecase", "")) && !"freeworld".equals(networkName)) {

@ -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)# #(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)# #(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"> <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> <fieldset>
<legend> <legend>
<label>Network and Domain Specification</label> <label>Network and Domain Specification</label>
@ -101,6 +102,7 @@
without any data exchange between your peer and other peers. without any data exchange between your peer and other peers.
</p> </p>
<form id="ConfigForm" method="post" action="ConfigNetwork_p.html" enctype="multipart/form-data" accept-charset="UTF-8"> <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> <fieldset>
<legend> <legend>
<input type="radio" name="network" id="p2p" onclick="EnableP2P()" value="p2p"#(p2p.checked)#:: checked="checked"#(/p2p.checked)# /> <input type="radio" name="network" id="p2p" onclick="EnableP2P()" value="p2p"#(p2p.checked)#:: checked="checked"#(/p2p.checked)# />

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

Loading…
Cancel
Save