Skip to content

Commit

Permalink
Merge pull request #3377 from katzyn/web
Browse files Browse the repository at this point in the history
Add -webExternalNames setting and fix WebServer.getConnection()
  • Loading branch information
katzyn committed Jan 15, 2022
2 parents cbb5d4e + eb75633 commit ccaadc0
Show file tree
Hide file tree
Showing 38 changed files with 263 additions and 137 deletions.
5 changes: 3 additions & 2 deletions h2/src/docsrc/html/advanced.html
Expand Up @@ -1370,9 +1370,10 @@ <h2 id="remote_access">Protection against Remote Access</h2>
<p>
If you enable remote access using <code>-webAllowOthers</code>,
please ensure the web server can only be accessed from trusted networks.
If this option is specified, <code>-webExternalNames</code> should be also specified with
comma-separated list of external names or addresses of this server.
The options <code>-baseDir</code> don't protect
access to the tools section, prevent remote shutdown of the web server,
changes to the preferences, the saved connection settings,
access to the saved connection settings,
or access to other databases accessible from the system.
</p>

Expand Down
2 changes: 1 addition & 1 deletion h2/src/main/org/h2/Driver.java
Expand Up @@ -56,7 +56,7 @@ public Connection connect(String url, Properties info) throws SQLException {
if (url == null) {
throw DbException.getJdbcSQLException(ErrorCode.URL_FORMAT_ERROR_2, null, Constants.URL_FORMAT, null);
} else if (url.startsWith(Constants.START_URL)) {
return new JdbcConnection(url, info, null, null);
return new JdbcConnection(url, info, null, null, false);
} else if (url.equals(DEFAULT_URL)) {
return DEFAULT_CONNECTION.get();
} else {
Expand Down
7 changes: 6 additions & 1 deletion h2/src/main/org/h2/jdbc/JdbcConnection.java
Expand Up @@ -103,12 +103,17 @@ public class JdbcConnection extends TraceObject implements Connection, JdbcConne
* @param info of this connection
* @param user of this connection
* @param password for the user
* @param forbidCreation whether database creation is forbidden
* @throws SQLException on failure
*/
@SuppressWarnings("resource")
public JdbcConnection(String url, Properties info, String user, Object password) throws SQLException {
public JdbcConnection(String url, Properties info, String user, Object password, boolean forbidCreation)
throws SQLException {
try {
ConnectionInfo ci = new ConnectionInfo(url, info, user, password);
if (forbidCreation) {
ci.setProperty("FORBID_CREATION", "TRUE");
}
String baseDir = SysProperties.getBaseDir();
if (baseDir != null) {
ci.setBaseDir(baseDir);
Expand Down
9 changes: 5 additions & 4 deletions h2/src/main/org/h2/jdbcx/JdbcDataSource.java
Expand Up @@ -152,7 +152,7 @@ public void setLogWriter(PrintWriter out) {
@Override
public Connection getConnection() throws SQLException {
debugCodeCall("getConnection");
return new JdbcConnection(url, null, userName, StringUtils.cloneCharArray(passwordChars));
return new JdbcConnection(url, null, userName, StringUtils.cloneCharArray(passwordChars), false);
}

/**
Expand All @@ -169,7 +169,7 @@ public Connection getConnection(String user, String password)
if (isDebugEnabled()) {
debugCode("getConnection(" + quote(user) + ", \"\")");
}
return new JdbcConnection(url, null, user, password);
return new JdbcConnection(url, null, user, password, false);
}

/**
Expand Down Expand Up @@ -319,7 +319,7 @@ public Reference getReference() {
public XAConnection getXAConnection() throws SQLException {
debugCodeCall("getXAConnection");
return new JdbcXAConnection(factory, getNextId(XA_DATA_SOURCE),
new JdbcConnection(url, null, userName, StringUtils.cloneCharArray(passwordChars)));
new JdbcConnection(url, null, userName, StringUtils.cloneCharArray(passwordChars), false));
}

/**
Expand All @@ -336,7 +336,8 @@ public XAConnection getXAConnection(String user, String password)
if (isDebugEnabled()) {
debugCode("getXAConnection(" + quote(user) + ", \"\")");
}
return new JdbcXAConnection(factory, getNextId(XA_DATA_SOURCE), new JdbcConnection(url, null, user, password));
return new JdbcXAConnection(factory, getNextId(XA_DATA_SOURCE),
new JdbcConnection(url, null, user, password, false));
}

/**
Expand Down
5 changes: 3 additions & 2 deletions h2/src/main/org/h2/server/TcpServer.java
Expand Up @@ -86,7 +86,8 @@ private void initManagementDb() throws SQLException {
managementPassword = StringUtils.convertBytesToHex(MathUtils.secureRandomBytes(32));
}
// avoid using the driver manager
JdbcConnection conn = new JdbcConnection("jdbc:h2:" + getManagementDbName(port), null, "", managementPassword);
JdbcConnection conn = new JdbcConnection("jdbc:h2:" + getManagementDbName(port), null, "", managementPassword,
false);
managementDb = conn;

try (Statement stat = conn.createStatement()) {
Expand Down Expand Up @@ -446,7 +447,7 @@ public static synchronized void shutdown(String url, String password,
}
String db = getManagementDbName(port);
for (int i = 0; i < 2; i++) {
try (JdbcConnection conn = new JdbcConnection("jdbc:h2:" + url + '/' + db, null, "", password)) {
try (JdbcConnection conn = new JdbcConnection("jdbc:h2:" + url + '/' + db, null, "", password, true)) {
PreparedStatement prep = conn.prepareStatement("CALL STOP_SERVER(?, ?, ?)");
prep.setInt(1, all ? 0 : port);
prep.setString(2, password);
Expand Down
4 changes: 4 additions & 0 deletions h2/src/main/org/h2/server/web/WebApp.java
Expand Up @@ -394,6 +394,7 @@ private String autoCompleteList() {
private String admin() {
session.put("port", Integer.toString(server.getPort()));
session.put("allowOthers", Boolean.toString(server.getAllowOthers()));
session.put("webExternalNames", server.getExternalNames());
session.put("ssl", String.valueOf(server.getSSL()));
session.put("sessions", server.getSessions());
return "admin.jsp";
Expand All @@ -408,6 +409,9 @@ private String adminSave() {
boolean allowOthers = Utils.parseBoolean((String) attributes.get("allowOthers"), false, false);
prop.setProperty("webAllowOthers", String.valueOf(allowOthers));
server.setAllowOthers(allowOthers);
String externalNames = (String) attributes.get("webExternalNames");
prop.setProperty("webExternalNames", externalNames);
server.setExternalNames(externalNames);
boolean ssl = Utils.parseBoolean((String) attributes.get("ssl"), false, false);
prop.setProperty("webSSL", String.valueOf(ssl));
server.setSSL(ssl);
Expand Down
39 changes: 30 additions & 9 deletions h2/src/main/org/h2/server/web/WebServer.java
Expand Up @@ -159,6 +159,7 @@ public class WebServer implements Service {
// private URLClassLoader urlClassLoader;
private int port;
private boolean allowOthers;
private String externalNames;
private boolean isDaemon;
private final Set<WebThread> running =
Collections.synchronizedSet(new HashSet<WebThread>());
Expand All @@ -171,6 +172,7 @@ public class WebServer implements Service {
private final HashSet<String> languages = new HashSet<>();
private String startDateTime;
private ServerSocket serverSocket;
private String host;
private String url;
private ShutdownHandler shutdownHandler;
private Thread listenerThread;
Expand Down Expand Up @@ -319,6 +321,7 @@ public void init(String... args) {
"webSSL", false);
allowOthers = SortedProperties.getBooleanProperty(prop,
"webAllowOthers", false);
externalNames = SortedProperties.getStringProperty(prop, "webExternalNames", null);
setAdminPassword(SortedProperties.getStringProperty(prop, "webAdminPassword", null));
commandHistoryString = prop.getProperty(COMMAND_HISTORY);
for (int i = 0; args != null && i < args.length; i++) {
Expand All @@ -329,6 +332,8 @@ public void init(String... args) {
ssl = true;
} else if (Tool.isOption(a, "-webAllowOthers")) {
allowOthers = true;
} else if (Tool.isOption(a, "-webExternalNames")) {
externalNames = args[++i];
} else if (Tool.isOption(a, "-webDaemon")) {
isDaemon = true;
} else if (Tool.isOption(a, "-baseDir")) {
Expand Down Expand Up @@ -375,10 +380,21 @@ public String getURL() {
return url;
}

/**
* @return host name
*/
public String getHost() {
if (host == null) {
updateURL();
}
return host;
}

private void updateURL() {
try {
host = NetUtils.getLocalAddress();
StringBuilder builder = new StringBuilder(ssl ? "https" : "http").append("://")
.append(NetUtils.getLocalAddress()).append(':').append(port);
.append(host).append(':').append(port);
if (key != null && serverSocket != null) {
builder.append("?key=").append(key);
}
Expand Down Expand Up @@ -551,6 +567,14 @@ public boolean getAllowOthers() {
return allowOthers;
}

void setExternalNames(String externalNames) {
this.externalNames = externalNames;
}

String getExternalNames() {
return externalNames;
}

void setSSL(boolean b) {
ssl = b;
}
Expand Down Expand Up @@ -731,6 +755,9 @@ synchronized void saveProperties(Properties prop) {
Integer.toString(SortedProperties.getIntProperty(old, "webPort", port)));
prop.setProperty("webAllowOthers",
Boolean.toString(SortedProperties.getBooleanProperty(old, "webAllowOthers", allowOthers)));
if (externalNames != null) {
prop.setProperty("webExternalNames", externalNames);
}
prop.setProperty("webSSL",
Boolean.toString(SortedProperties.getBooleanProperty(old, "webSSL", ssl)));
if (adminPassword != null) {
Expand Down Expand Up @@ -774,16 +801,10 @@ Connection getConnection(String driver, String databaseUrl, String user,
String password, String userKey, NetworkConnectionInfo networkConnectionInfo) throws SQLException {
driver = driver.trim();
databaseUrl = databaseUrl.trim();
if (databaseUrl.startsWith("jdbc:h2:")) {
if (!allowSecureCreation || key == null || !key.equals(userKey)) {
if (ifExists) {
databaseUrl += ";FORBID_CREATION=TRUE";
}
}
}
// do not trim the password, otherwise an
// encrypted H2 database with empty user password doesn't work
return JdbcUtils.getConnection(driver, databaseUrl, user.trim(), password, networkConnectionInfo);
return JdbcUtils.getConnection(driver, databaseUrl, user.trim(), password, networkConnectionInfo,
ifExists && (!allowSecureCreation || key == null || !key.equals(userKey)));
}

/**
Expand Down

0 comments on commit ccaadc0

Please sign in to comment.