Skip to content

Commit

Permalink
Finish 1.10.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean-Luc Picard committed Aug 28, 2016
2 parents 85a30d7 + 36b4f79 commit fe064dc
Show file tree
Hide file tree
Showing 22 changed files with 140 additions and 62 deletions.
31 changes: 31 additions & 0 deletions changelogs/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
nxt-client-1.10.1:

This release adds transaction replay protection, to be enabled at the hard fork
scheduled for block 1,000,000. Upgrading to 1.10.1 or later before that block
is mandatory for all.

The ecBlockId and ecBlockHeight transaction fields, previously populated but
not used, will begin to be used for enforcing that a transaction submitted on
one blockchain or fork will not be accepted on another blockchain or fork that
shares the same code. These fields by default will be set to a block 720 blocks
behind the last block at the time the transaction is created, and transactions
will only be accepted if their ecBlockId and ecBlockHeight values point to an
existing block when they are included in the blockchain. This default setting
provides protection against replaying the transaction on a hard fork that has
diverged more than 720 blocks from the one where the transaction was created.

Light clients that have no way of verifying the ecBlock values returned by a
remote node will use hardcoded values, to be updated manually at some releases.
Transactions from legacy light clients that leave eBlockId and height set to 0
will still be accepted, but cannot benefit from such replay protection.

All CreateTransaction APIs now accept additional ecBlockId and ecBlockHeight
parameters, allowing the default values to be overridden by the client.

Minor bugfixes and UI improvements.

Updated Jetty to version 9.3.11, delete the old lib folder before unpacking on
top.


--------------------------------------------------------------------------------
nxt-client-1.10.0e:

This is an experimental release introducing the new light client and roaming
Expand Down
27 changes: 0 additions & 27 deletions changelogs/nxt-client-1.10.1.changelog.txt

This file was deleted.

12 changes: 12 additions & 0 deletions changelogs/nxt-client-1.10.2.changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Changed default setting of nxt.apiServerCORS to true in nxt-default.properties,
to enable cross origin filter on the API server by default.

Added CORS peer service field, showing whether CORS is enabled for open API
nodes.

Recalculate NRS.isLocalhost when api proxy is enabled and blockchain download
has finished. Fixed starting funding monitor when running on remote host.

To protect against brute force attacks on the admin password of public nodes,
after 3 unsuccessful login attempts the remote host is blacklisted for 1 h.

2 changes: 1 addition & 1 deletion compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ rm -f sources.tmp
find addons/src/ -name "*.java" > addons.tmp
if [ -s addons.tmp ]; then
echo "compiling add-ons..."
javac -encoding utf8 -sourcepath "${SP}:addons/src" -classpath "${CP}:addons/classes" -d addons/classes @addons.tmp || exit 1
javac -encoding utf8 -sourcepath "${SP}:addons/src" -classpath "${CP}:addons/classes:addons/lib/*" -d addons/classes @addons.tmp || exit 1
echo "add-ons compiled successfully"
rm -f addons.tmp
else
Expand Down
4 changes: 2 additions & 2 deletions conf/nxt-default.properties
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ nxt.apiWelcomeFile=index.html
nxt.javadocResourceBase=./html/doc

# Enable Cross Origin Filter for the API server.
nxt.apiServerCORS=false
nxt.apiServerCORS=true

# Add X-Frame-Options SAMEORIGIN header to every response as a protection
# against clickjacking.
Expand Down Expand Up @@ -686,5 +686,5 @@ nxt.forceScan=false
#nxt.beforeShutdownScript=../bin/beforeShutdown.sh

# NRS version.
nxt.version=1.10.1
nxt.version=1.10.2

3 changes: 2 additions & 1 deletion html/ui/js/nrs.constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ var NRS = (function (NRS, $) {
requestType == "stopForging" ||
requestType == "startShuffler" ||
requestType == "getForging" ||
requestType == "markHost";
requestType == "markHost" ||
requestType == "startFundingMonitor";
};

NRS.getFileUploadConfig = function (requestType, data) {
Expand Down
2 changes: 2 additions & 0 deletions html/ui/js/nrs.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ var NRS = (function(NRS, $, undefined) {
}
}, false);
} else {
var hostName = window.location.hostname.toLowerCase();
NRS.isLocalHost = hostName == "localhost" || hostName == "127.0.0.1" || NRS.isPrivateIP(hostName);
NRS.handleBlockchainStatus(response, callback);
NRS.updateDashboardMessage();
}
Expand Down
2 changes: 1 addition & 1 deletion html/ui/js/nrs.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ var NRS = (function (NRS, $, undefined) {
return false;
}
var parts = ip.split('.');
return parts[0] === '10' || parts[0] == '127' || parts[0] === '172' && (parseInt(parts[1], 10) >= 16 && parseInt(parts[1], 10) <= 31) || parts[0] === '192' && parts[1] === '168';
return parts[0] === '10' || parts[0] == '127' || parts[0] === '172' && (parseInt(parts[1], 10) >= 16 && parseInt(parts[1], 10) <= 31) || parts[0] === '192' && parts[1] === '168';
};

NRS.convertToHex16 = function (str) {
Expand Down
3 changes: 1 addition & 2 deletions nxt.policy
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
grant {
permission java.util.PropertyPermission "*", "read, write";
permission java.lang.management.ManagementPermission "monitor";
permission java.io.FilePermission "<<ALL FILES>>", "read, execute";
permission java.io.FilePermission "-", "read, write, delete, execute";
permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete, execute";
permission java.util.logging.LoggingPermission "control";
permission java.lang.RuntimePermission "modifyThread";
permission java.security.SecurityPermission "getProperty.ssl.*";
Expand Down
3 changes: 3 additions & 0 deletions nxt.pro
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
-keep class * extends nxt.env.DirProvider
-keep class * extends nxt.addons.AddOn
-keep class nxt.addons.AddOn
-keep,includedescriptorclasses class nxtdesktop.JavaScriptBridge, nxtdesktop.DesktopApplication, nxtdesktop.WalletContextMenu {
<methods>;
}
-keepclassmembers class nxt.env.RuntimeEnvironment {
static boolean isHeadless();
}
Expand Down
2 changes: 1 addition & 1 deletion run-desktop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ if [ -x jre/bin/java ]; then
else
JAVA=java
fi
${JAVA} -cp classes:lib/*:conf:addons/classes -Dnxt.runtime.mode=desktop -Dnxt.runtime.dirProvider=nxt.env.DefaultDirProvider nxt.Nxt
${JAVA} -cp classes:lib/*:conf:addons/classes:addons/lib/* -Dnxt.runtime.mode=desktop -Dnxt.runtime.dirProvider=nxt.env.DefaultDirProvider nxt.Nxt
2 changes: 1 addition & 1 deletion run-tor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ if [ -x jre/bin/java ]; then
else
JAVA=java
fi
${JAVA} -DsocksProxyHost=localhost -DsocksProxyPort=9050 -cp classes:lib/*:conf:addons/classes nxt.Nxt
${JAVA} -DsocksProxyHost=localhost -DsocksProxyPort=9050 -cp classes:lib/*:conf:addons/classes:addons/lib/* nxt.Nxt

2 changes: 1 addition & 1 deletion run.bat
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
)

:startJava
start "NXT NRS from %~dp0" "%javaDir%"\bin\java.exe -cp classes;lib\*;conf;addons\classes -Dnxt.runtime.mode=desktop nxt.Nxt
start "NXT NRS from %~dp0" "%javaDir%"\bin\java.exe -cp classes;lib\*;conf;addons\classes;addons\lib\* -Dnxt.runtime.mode=desktop nxt.Nxt

:endProcess
endlocal
2 changes: 1 addition & 1 deletion run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ if [ -x jre/bin/java ]; then
else
JAVA=java
fi
${JAVA} -cp classes:lib/*:conf:addons/classes nxt.Nxt
${JAVA} -cp classes:lib/*:conf:addons/classes:addons/lib/* nxt.Nxt
2 changes: 1 addition & 1 deletion src/java/nxt/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public final class Constants {
public static final int LAST_CHECKSUM_BLOCK = CHECKSUM_BLOCK_19;
public static final int LAST_KNOWN_BLOCK = isTestnet ? 847000 : 907000;

public static final int[] MIN_VERSION = Constants.isTestnet ? new int[] {1, 9} : new int[] {1, 7};
public static final int[] MIN_VERSION = Constants.isTestnet ? new int[] {1, 10} : new int[] {1, 7};
public static final int[] MIN_PROXY_VERSION = new int[] {1, 10, 1};

static final long UNCONFIRMED_POOL_DEPOSIT_NQT = (isTestnet ? 50 : 100) * ONE_NXT;
Expand Down
2 changes: 1 addition & 1 deletion src/java/nxt/Nxt.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

public final class Nxt {

public static final String VERSION = "1.10.1";
public static final String VERSION = "1.10.2";
public static final String APPLICATION = "NRS";

private static volatile Time time = new Time.EpochTime();
Expand Down
59 changes: 54 additions & 5 deletions src/java/nxt/http/API.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import nxt.Constants;
import nxt.Nxt;
import nxt.util.Convert;
import nxt.util.Logger;
import nxt.util.ThreadPool;
import nxt.util.UPnP;
Expand Down Expand Up @@ -60,12 +61,15 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static nxt.http.JSONResponses.INCORRECT_ADMIN_PASSWORD;
import static nxt.http.JSONResponses.NO_PASSWORD_IN_CONFIG;
import static nxt.http.JSONResponses.LOCKED_ADMIN_PASSWORD;

public final class API {

Expand All @@ -80,11 +84,13 @@ public final class API {

private static final Set<String> allowedBotHosts;
private static final List<NetworkAddress> allowedBotNets;
private static final Map<String, PasswordCount> incorrectPasswords = new HashMap<>();
public static final String adminPassword = Nxt.getStringProperty("nxt.adminPassword", "", true);
static final boolean disableAdminPassword;
static final int maxRecords = Nxt.getIntProperty("nxt.maxAPIRecords");
static final boolean enableAPIUPnP = Nxt.getBooleanProperty("nxt.enableAPIUPnP");
public static final int apiServerIdleTimeout = Nxt.getIntProperty("nxt.apiServerIdleTimeout");
public static final boolean apiServerCORS = Nxt.getBooleanProperty("nxt.apiServerCORS");

private static final Server apiServer;
private static URI welcomePageUri;
Expand Down Expand Up @@ -243,7 +249,7 @@ public final class API {

apiHandler.addServlet(DbShellServlet.class, "/dbshell");

if (Nxt.getBooleanProperty("nxt.apiServerCORS")) {
if (apiServerCORS) {
FilterHolder filterHolder = apiHandler.addFilter(CrossOriginFilter.class, "/*", null);
filterHolder.setInitParameter("allowedHeaders", "*");
filterHolder.setAsyncSupported(true);
Expand Down Expand Up @@ -320,14 +326,57 @@ public static void verifyPassword(HttpServletRequest req) throws ParameterExcept
}
if (API.adminPassword.isEmpty()) {
throw new ParameterException(NO_PASSWORD_IN_CONFIG);
} else if (!API.adminPassword.equals(req.getParameter("adminPassword"))) {
Logger.logWarningMessage("Incorrect adminPassword");
throw new ParameterException(INCORRECT_ADMIN_PASSWORD);
}
checkOrLockPassword(req);
}

public static boolean checkPassword(HttpServletRequest req) {
return (API.disableAdminPassword || (!API.adminPassword.isEmpty() && API.adminPassword.equals(req.getParameter("adminPassword"))));
if (API.disableAdminPassword) {
return true;
}
if (API.adminPassword.isEmpty()) {
return false;
}
if (Convert.emptyToNull(req.getParameter("adminPassword")) == null) {
return false;
}
try {
checkOrLockPassword(req);
return true;
} catch (ParameterException e) {
return false;
}
}


private static class PasswordCount {
private int count;
private int time;
}

private static void checkOrLockPassword(HttpServletRequest req) throws ParameterException {
int now = Nxt.getEpochTime();
String remoteHost = req.getRemoteHost();
synchronized(incorrectPasswords) {
PasswordCount passwordCount = incorrectPasswords.get(remoteHost);
if (passwordCount != null && passwordCount.count >= 3 && now - passwordCount.time < 60*60) {
Logger.logWarningMessage("Too many incorrect admin password attempts from " + remoteHost);
throw new ParameterException(LOCKED_ADMIN_PASSWORD);
}
if (!API.adminPassword.equals(req.getParameter("adminPassword"))) {
if (passwordCount == null) {
passwordCount = new PasswordCount();
incorrectPasswords.put(remoteHost, passwordCount);
}
passwordCount.count++;
passwordCount.time = now;
Logger.logWarningMessage("Incorrect adminPassword from " + remoteHost);
throw new ParameterException(INCORRECT_ADMIN_PASSWORD);
}
if (passwordCount != null) {
incorrectPasswords.remove(remoteHost);
}
}
}

static boolean isAllowed(String remoteHost) {
Expand Down
31 changes: 16 additions & 15 deletions src/java/nxt/http/DbShellServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

import nxt.Db;
import nxt.util.Convert;
import nxt.util.JSON;
import org.h2.tools.Shell;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
Expand Down Expand Up @@ -71,7 +74,7 @@ public final class DbShellServlet extends HttpServlet {
"</html>\n";

private static final String form =
"<form action=\"/dbshell\" method=\"POST\" onsubmit=\"return submitForm(this" +
"<form action=\"/dbshell\" method=\"POST\" onsubmit=\"return submitForm(this" +
(API.disableAdminPassword ? "" : ", '{adminPassword}'") + ");\">" +
"<table class=\"table\" style=\"width:90%;\">" +
"<tr><td><pre class=\"result\" style=\"float:top;width:90%;\">" +
Expand All @@ -88,8 +91,8 @@ public final class DbShellServlet extends HttpServlet {
private static final String passwordFormTemplate =
"<form action=\"/dbshell\" method=\"POST\">" +
"<table class=\"table\">" +
"<tr><td colspan=\"3\">%s</td></tr>" +
"<tr>" +
"<tr><td colspan=\"3\">%s</td></tr>" +
"<tr>" +
"<td>Password:</td>" +
"<td><input type=\"password\" name=\"adminPassword\"/>" +
"<input type=\"submit\" value=\"Go!\"/></td>" +
Expand All @@ -98,13 +101,10 @@ public final class DbShellServlet extends HttpServlet {
"<input type=\"hidden\" name=\"showShell\" value=\"true\"/>" +
"</form>";

private static final String passwordForm = String.format(passwordFormTemplate,
private static final String passwordForm = String.format(passwordFormTemplate,
"<p>This page is password-protected. Please enter the administrator's password</p>");

private static final String passwordFormWrongPassword = String.format(passwordFormTemplate,
"<p style=\"color:red\">The provided password does not match the value of nxt.adminPassword. Please try again!</p>");


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
Expand All @@ -125,7 +125,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
body = passwordForm;
}
}

try (PrintStream out = new PrintStream(resp.getOutputStream())) {
out.print(header);
out.print(body);
Expand All @@ -148,17 +148,18 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S
if (API.adminPassword.isEmpty()) {
body = errorNoPasswordIsConfigured;
} else {
String adminPassword = req.getParameter("adminPassword");
if (API.adminPassword.equals(adminPassword)) {
try {
API.verifyPassword(req);
if ("true".equals(req.getParameter("showShell"))) {
body = form.replace("{adminPassword}", URLEncoder.encode(adminPassword, "UTF-8") );
body = form.replace("{adminPassword}", URLEncoder.encode(req.getParameter("adminPassword"), "UTF-8") );
}
} else {
body = passwordFormWrongPassword;
} catch (ParameterException exc) {
String desc = (String)((JSONObject)JSONValue.parse(JSON.toString(exc.getErrorResponse()))).get("errorDescription");
body = String.format(passwordFormTemplate, "<p style=\"color:red\">" + desc + "</p>");
}
}
}

if (body != null) {
try (PrintStream out = new PrintStream(resp.getOutputStream())) {
out.print(header);
Expand All @@ -167,7 +168,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S
}
return;
}

String line = Convert.nullToEmpty(req.getParameter("line"));
try (PrintStream out = new PrintStream(resp.getOutputStream())) {
out.println("\n> " + line);
Expand Down
Loading

0 comments on commit fe064dc

Please sign in to comment.