forked from I2P_Developers/i2p.i2p
i2ptunnel: Per-client auth config
Hide encryption key for per-client auth User-select: all for dest and reg fields
This commit is contained in:
@@ -569,11 +569,13 @@ public class GeneralHelper {
|
|||||||
int rv;
|
int rv;
|
||||||
String authType = getProperty(tunnel, "i2cp.leaseSetAuthType", "0");
|
String authType = getProperty(tunnel, "i2cp.leaseSetAuthType", "0");
|
||||||
if (authType.equals("2")) {
|
if (authType.equals("2")) {
|
||||||
// shared PSK key
|
if (getProperty(tunnel, "i2cp.leaseSetClient.psk.0", null) != null) {
|
||||||
rv = 4;
|
// per-client PSK key
|
||||||
// per-client PSK key
|
rv = 6;
|
||||||
// TODO
|
} else {
|
||||||
//rv = 6;
|
// shared PSK key
|
||||||
|
rv = 4;
|
||||||
|
}
|
||||||
} else if (authType.equals("1")) {
|
} else if (authType.equals("1")) {
|
||||||
rv = 8;
|
rv = 8;
|
||||||
} else {
|
} else {
|
||||||
@@ -596,6 +598,25 @@ public class GeneralHelper {
|
|||||||
public String getBlindedPassword(int tunnel) {
|
public String getBlindedPassword(int tunnel) {
|
||||||
return getProperty(tunnel, "i2cp.leaseSetSecret", "");
|
return getProperty(tunnel, "i2cp.leaseSetSecret", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of b64 name : b64key
|
||||||
|
* Pubkeys for DH, privkeys for PSK
|
||||||
|
* @param isDH true for DH, false for PSK
|
||||||
|
* @return non-null
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public List<String> getClientAuths(int tunnel, boolean isDH) {
|
||||||
|
List<String> rv = new ArrayList<String>(4);
|
||||||
|
String pfx = isDH ? "i2cp.leaseSetClient.dh." : "i2cp.leaseSetClient.psk.";
|
||||||
|
int i = 0;
|
||||||
|
String p;
|
||||||
|
while ((p = getProperty(tunnel, pfx + i, null)) != null) {
|
||||||
|
rv.add(p);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newTunnelType used if tunnel < 0
|
* @param newTunnelType used if tunnel < 0
|
||||||
@@ -868,6 +889,8 @@ public class GeneralHelper {
|
|||||||
if ((!isMD5Proxy) &&
|
if ((!isMD5Proxy) &&
|
||||||
TunnelConfig._nonProxyNoShowSet.contains(key))
|
TunnelConfig._nonProxyNoShowSet.contains(key))
|
||||||
continue;
|
continue;
|
||||||
|
if (key.startsWith("i2cp.leaseSetClient."))
|
||||||
|
continue;
|
||||||
sorted.put(key, (String)e.getValue());
|
sorted.put(key, (String)e.getValue());
|
||||||
}
|
}
|
||||||
if (sorted.isEmpty())
|
if (sorted.isEmpty())
|
||||||
|
@@ -2,7 +2,10 @@ package net.i2p.i2ptunnel.ui;
|
|||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -14,6 +17,7 @@ import net.i2p.client.I2PClient;
|
|||||||
import net.i2p.crypto.KeyGenerator;
|
import net.i2p.crypto.KeyGenerator;
|
||||||
import net.i2p.crypto.SigType;
|
import net.i2p.crypto.SigType;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.SimpleDataStructure;
|
import net.i2p.data.SimpleDataStructure;
|
||||||
import net.i2p.i2ptunnel.I2PTunnelClientBase;
|
import net.i2p.i2ptunnel.I2PTunnelClientBase;
|
||||||
@@ -77,6 +81,13 @@ public class TunnelConfig {
|
|||||||
private Destination _dest;
|
private Destination _dest;
|
||||||
private String _filterDefinition;
|
private String _filterDefinition;
|
||||||
private int _encryptMode;
|
private int _encryptMode;
|
||||||
|
private String[] _clientNames;
|
||||||
|
private String[] _clientKeys;
|
||||||
|
private Set<Integer> _clientRevocations;
|
||||||
|
// b64name : b64key
|
||||||
|
private String _newClientName;
|
||||||
|
private String _newClientKey;
|
||||||
|
private boolean _addClientAuth;
|
||||||
|
|
||||||
public TunnelConfig() {
|
public TunnelConfig() {
|
||||||
_context = I2PAppContext.getGlobalContext();
|
_context = I2PAppContext.getGlobalContext();
|
||||||
@@ -271,6 +282,59 @@ public class TunnelConfig {
|
|||||||
_otherOptions.remove("i2cp.leaseSetSecret");
|
_otherOptions.remove("i2cp.leaseSetSecret");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple entries in form
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void addClientNames(String[] s) {
|
||||||
|
_clientNames = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple entries in form
|
||||||
|
* Handles either order addClientName/addClientKey
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void addClientKeys(String[] s) {
|
||||||
|
_clientKeys = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple entries in form
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void revokeClients(String[] s) {
|
||||||
|
_clientRevocations = new HashSet<Integer>(4);
|
||||||
|
for (String k : s) {
|
||||||
|
try {
|
||||||
|
_clientRevocations.add(Integer.valueOf(Integer.parseInt(k)));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles either order newClientName/newClientKey
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void newClientName(String s) {
|
||||||
|
_newClientName = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles either order newClientName/newClientKey
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void newClientKey(String s) {
|
||||||
|
_newClientKey = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setAddClient(boolean val) {
|
||||||
|
_addClientAuth = val;
|
||||||
|
}
|
||||||
|
|
||||||
public void setDCC(boolean val) {
|
public void setDCC(boolean val) {
|
||||||
if (val)
|
if (val)
|
||||||
_booleanOptions.add(I2PTunnelIRCClient.PROP_DCC);
|
_booleanOptions.add(I2PTunnelIRCClient.PROP_DCC);
|
||||||
@@ -858,6 +922,74 @@ public class TunnelConfig {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// per-client keys
|
||||||
|
String pfx;
|
||||||
|
if (_encryptMode == 6 || _encryptMode == 7) {
|
||||||
|
pfx = OPT + "i2cp.leaseSetClient.psk.";
|
||||||
|
} else if (_encryptMode == 8 || _encryptMode == 9) {
|
||||||
|
pfx = OPT + "i2cp.leaseSetClient.dh.";
|
||||||
|
} else {
|
||||||
|
pfx = null;
|
||||||
|
}
|
||||||
|
List<String> clientAuth = null;
|
||||||
|
if (pfx != null) {
|
||||||
|
if (_clientNames != null && _clientKeys != null && _clientNames.length == _clientKeys.length) {
|
||||||
|
clientAuth = new ArrayList<String>(4);
|
||||||
|
} else if (_addClientAuth || _encryptMode == 6 || _encryptMode == 7) {
|
||||||
|
// force one client for per-client PSK
|
||||||
|
clientAuth = new ArrayList<String>(1);
|
||||||
|
if (!_addClientAuth) {
|
||||||
|
_addClientAuth = true;
|
||||||
|
if (_newClientName == null || _newClientName.length() == 0)
|
||||||
|
_newClientName = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + " 1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pfx != null && clientAuth != null) {
|
||||||
|
if (_clientNames != null && _clientKeys != null && _clientNames.length == _clientKeys.length) {
|
||||||
|
for (int i = 0; i < _clientNames.length; i++) {
|
||||||
|
if (_clientRevocations != null && _clientRevocations.contains(Integer.valueOf(i)))
|
||||||
|
continue;
|
||||||
|
String name = _clientNames[i];
|
||||||
|
String key = _clientKeys[i];
|
||||||
|
byte[] b = Base64.decode(key);
|
||||||
|
if (b == null || b.length != 32)
|
||||||
|
continue;
|
||||||
|
if (name.length() > 0)
|
||||||
|
name = Base64.encode(DataHelper.getUTF8(name));
|
||||||
|
else
|
||||||
|
name = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + ' ' + (i + 1)));
|
||||||
|
clientAuth.add(name + ':' + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_addClientAuth && _newClientName != null) {
|
||||||
|
String name = _newClientName;
|
||||||
|
if (name.length() > 0)
|
||||||
|
name = Base64.encode(DataHelper.getUTF8(name));
|
||||||
|
else
|
||||||
|
name = Base64.encode(DataHelper.getUTF8(GeneralHelper._t("Client", _context) + ' ' + (clientAuth.size() + 1)));
|
||||||
|
String key;
|
||||||
|
if (_encryptMode == 6 || _encryptMode == 7) {
|
||||||
|
byte[] b = new byte[32];
|
||||||
|
_context.random().nextBytes(b);
|
||||||
|
key = Base64.encode(b);
|
||||||
|
clientAuth.add(name + ':' + key);
|
||||||
|
} else if (_encryptMode == 8 || _encryptMode == 9) {
|
||||||
|
key = _newClientKey;
|
||||||
|
byte[] b = Base64.decode(key);
|
||||||
|
if (b != null && b.length == 32) {
|
||||||
|
// key required for DH
|
||||||
|
clientAuth.add(name + ':' + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
for (String auth : clientAuth) {
|
||||||
|
config.put(pfx + i, auth);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -933,7 +1065,7 @@ public class TunnelConfig {
|
|||||||
PROP_MAX_STREAMS, I2PClient.PROP_SIGTYPE,
|
PROP_MAX_STREAMS, I2PClient.PROP_SIGTYPE,
|
||||||
"inbound.randomKey", "outbound.randomKey", "i2cp.leaseSetSigningPrivateKey", "i2cp.leaseSetPrivateKey",
|
"inbound.randomKey", "outbound.randomKey", "i2cp.leaseSetSigningPrivateKey", "i2cp.leaseSetPrivateKey",
|
||||||
I2PTunnelServer.PROP_ALT_PKF,
|
I2PTunnelServer.PROP_ALT_PKF,
|
||||||
"i2cp.leaseSetSecret", "i2cp.leaseSetType", "i2cp.leaseSetAuthType"
|
"i2cp.leaseSetSecret", "i2cp.leaseSetType", "i2cp.leaseSetAuthType", "i2cp.leaseSetPrivKey"
|
||||||
};
|
};
|
||||||
private static final String _httpServerOpts[] = {
|
private static final String _httpServerOpts[] = {
|
||||||
I2PTunnelHTTPServer.OPT_POST_WINDOW,
|
I2PTunnelHTTPServer.OPT_POST_WINDOW,
|
||||||
|
@@ -226,6 +226,17 @@ public class EditBean extends IndexBean {
|
|||||||
return _helper.getBlindedPassword(tunnel);
|
return _helper.getBlindedPassword(tunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of b64 name : b64key
|
||||||
|
* Pubkeys for DH, privkeys for PSK
|
||||||
|
* @param isDH true for DH, false for PSK
|
||||||
|
* @return non-null
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public List<String> getClientAuths(int tunnel, boolean isDH) {
|
||||||
|
return _helper.getClientAuths(tunnel, isDH);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param newTunnelType used if tunnel < 0
|
* @param newTunnelType used if tunnel < 0
|
||||||
* @since 0.9.12
|
* @since 0.9.12
|
||||||
|
@@ -872,6 +872,63 @@ public class IndexBean {
|
|||||||
_config.setBlindedPassword(s);
|
_config.setBlindedPassword(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple entries in form
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setNofilter_clientName(String[] s) {
|
||||||
|
if (s != null) {
|
||||||
|
_config.addClientNames(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple entries in form
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setclientKey(String[] s) {
|
||||||
|
if (s != null) {
|
||||||
|
_config.addClientKeys(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiple entries in form
|
||||||
|
* Values are integers
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setRevokeClient(String[] s) {
|
||||||
|
if (s != null) {
|
||||||
|
_config.revokeClients(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setNofilter_newClientName(String s) {
|
||||||
|
if (s != null) {
|
||||||
|
_config.newClientName(s.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setNewClientKey(String s) {
|
||||||
|
if (s != null) {
|
||||||
|
_config.newClientKey(s.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.41
|
||||||
|
*/
|
||||||
|
public void setAddClient(String moo) {
|
||||||
|
_config.setAddClient(true);
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 0.8.9 */
|
/** @since 0.8.9 */
|
||||||
public void setDCC(String moo) {
|
public void setDCC(String moo) {
|
||||||
_config.setDCC(true);
|
_config.setDCC(true);
|
||||||
|
@@ -155,7 +155,7 @@
|
|||||||
</th>
|
</th>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" title="<%=intl._t("Read Only: Local Destination (if known)")%>" tabindex="0" onblur="resetScrollLeft(this)"><%=editBean.getDestinationBase64(curTunnel)%></div>
|
<div class="displayText" style="user-select: all;" title="<%=intl._t("Read Only: Local Destination (if known)")%>" tabindex="0" onblur="resetScrollLeft(this)"><%=editBean.getDestinationBase64(curTunnel)%></div>
|
||||||
</td><td>
|
</td><td>
|
||||||
<% String value3 = editBean.getPrivateKeyFile(curTunnel);
|
<% String value3 = editBean.getPrivateKeyFile(curTunnel);
|
||||||
if (value3 == null || "".equals(value3.trim())) {
|
if (value3 == null || "".equals(value3.trim())) {
|
||||||
@@ -485,20 +485,27 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td>
|
<td>
|
||||||
<b><%=intl._t("Encryption Key")%></b>
|
|
||||||
</td><td>
|
|
||||||
<%
|
<%
|
||||||
if (allowBlinding && editBean.isAdvanced()) {
|
if (allowBlinding && editBean.isAdvanced()) {
|
||||||
%>
|
%>
|
||||||
<b><%=intl._t("Optional lookup password")%>:</b>
|
<b><%=intl._t("Optional lookup password")%>:</b>
|
||||||
<%
|
<%
|
||||||
} // allowBlinding
|
} // allowBlinding
|
||||||
|
%>
|
||||||
|
</td><td>
|
||||||
|
<%
|
||||||
|
// even if not shown, we need to preserve the param as a hidden input below
|
||||||
|
// as it's the key we use to decrypt the PSK/DH LS on the router side
|
||||||
|
boolean showSharedKey = curEncryptMode.equals("1") || curEncryptMode.equals("4") || curEncryptMode.equals("5");
|
||||||
|
if (showSharedKey) {
|
||||||
|
%>
|
||||||
|
<b><%=intl._t("Encryption Key")%></b>
|
||||||
|
<%
|
||||||
|
} // showSharedKey
|
||||||
%>
|
%>
|
||||||
</td>
|
</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td>
|
<td>
|
||||||
<textarea rows="1" style="height: 3em;" cols="44" id="leasesetKey" name="encryptKey" title="<%=intl._t("Encryption key required to access this service")%>" wrap="off" readonly="readonly"><%=editBean.getEncryptKey(curTunnel)%></textarea>
|
|
||||||
</td><td>
|
|
||||||
<%
|
<%
|
||||||
if (allowBlinding && editBean.isAdvanced()) {
|
if (allowBlinding && editBean.isAdvanced()) {
|
||||||
%>
|
%>
|
||||||
@@ -506,9 +513,71 @@
|
|||||||
<%
|
<%
|
||||||
} // allowBlinding
|
} // allowBlinding
|
||||||
%>
|
%>
|
||||||
|
</td><td>
|
||||||
|
<input type="<%=showSharedKey ? "text" : "hidden"%>" style="user-select: all;" size="44" id="leasesetKey" name="encryptKey" title="<%=intl._t("Encryption key required to access this service")%>" readonly="readonly" value="<%=editBean.getEncryptKey(curTunnel)%>" class="freetext"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<%
|
<%
|
||||||
|
if (allowBlinding && editBean.isAdvanced()) {
|
||||||
|
boolean pskClient = curEncryptMode.equals("6") || curEncryptMode.equals("7");
|
||||||
|
boolean dhClient = curEncryptMode.equals("8") || curEncryptMode.equals("9");
|
||||||
|
if (pskClient || dhClient) {
|
||||||
|
// b64Name:b64Key
|
||||||
|
java.util.List<String> clientAuths = editBean.getClientAuths(curTunnel, dhClient);
|
||||||
|
if (!clientAuths.isEmpty()) {
|
||||||
|
%>
|
||||||
|
<tr><td><b><%=intl._t("Revoke?")%> <%=intl._t("Client Name")%></b></td><td><b><%=intl._t("Client Key")%></b></td></tr>
|
||||||
|
<%
|
||||||
|
int i = 0;
|
||||||
|
for (String clientAuth : clientAuths) {
|
||||||
|
String[] split = net.i2p.data.DataHelper.split(clientAuth, ":", 2);
|
||||||
|
String cname, ckey;
|
||||||
|
if (split.length == 2) {
|
||||||
|
cname = split[0];
|
||||||
|
ckey = split[1];
|
||||||
|
} else {
|
||||||
|
cname = "";
|
||||||
|
ckey = split[0];
|
||||||
|
}
|
||||||
|
if (cname.length() > 0) {
|
||||||
|
cname = net.i2p.data.DataHelper.escapeHTML(net.i2p.data.DataHelper.getUTF8(net.i2p.data.Base64.decode(cname)));
|
||||||
|
} else {
|
||||||
|
cname = intl._t("Client") + ' ' + (i + 1);
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
<tr>
|
||||||
|
<td><input value="<%=i%>" type="checkbox" name="revokeClient" class="tickbox" />
|
||||||
|
<input type="text" value="<%=cname%>" size="44" name="nofilter_clientName" class="freetext" /></td>
|
||||||
|
<td><input type="text" id="leasesetKey" style="user-select: all;" value="<%=ckey%>" size="44" name="clientKey" readonly="readonly" class="freetext" />
|
||||||
|
</tr>
|
||||||
|
<%
|
||||||
|
i++;
|
||||||
|
} // for
|
||||||
|
} // isEmpty
|
||||||
|
%>
|
||||||
|
<tr><td><b><%=intl._t("Add?")%> <%=intl._t("Client Name")%></b></td><td>
|
||||||
|
<%
|
||||||
|
if (dhClient) {
|
||||||
|
%>
|
||||||
|
<b><%=intl._t("Client Key")%></b>
|
||||||
|
<%
|
||||||
|
} // dhClient
|
||||||
|
%>
|
||||||
|
</td></tr><tr>
|
||||||
|
<td><input value="1" type="checkbox" name="addClient" class="tickbox" />
|
||||||
|
<input type="text" value="<%=intl._t("Client") + ' ' + (clientAuths.size() + 1)%>" size="44" name="nofilter_newClientName" class="freetext" /></td>
|
||||||
|
<td>
|
||||||
|
<%
|
||||||
|
if (dhClient) {
|
||||||
|
%>
|
||||||
|
<input type="text" id="leasesetKey" value="" size="44" maxlength="44" name="newClientKey" class="freetext" />
|
||||||
|
<%
|
||||||
|
} // dhClient
|
||||||
|
%>
|
||||||
|
</td></tr>
|
||||||
|
<%
|
||||||
|
} // pskClient || dhClient
|
||||||
|
} // allowBlinding
|
||||||
} // !isOffline
|
} // !isOffline
|
||||||
%>
|
%>
|
||||||
<tr>
|
<tr>
|
||||||
|
@@ -150,7 +150,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all; "title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -171,7 +171,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.writeRemove(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.writeRemove(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
%>
|
%>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -244,7 +244,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
%>
|
%>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -281,7 +281,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -318,7 +318,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
%>
|
%>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -351,7 +351,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
props2.setProperty(HostTxtEntry.PROP_OLDDEST, b64);
|
props2.setProperty(HostTxtEntry.PROP_OLDDEST, b64);
|
||||||
he2.signInner(spk);
|
he2.signInner(spk);
|
||||||
he2.sign(spk3);
|
he2.sign(spk3);
|
||||||
%><tr><td><div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he2.write(out); %></div></td></tr>
|
%><tr><td><div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he2.write(out); %></div></td></tr>
|
||||||
<tr><td class="infohelp"><%=intl._t("This will add an alternate destination for {0}", name)%></td></tr>
|
<tr><td class="infohelp"><%=intl._t("This will add an alternate destination for {0}", name)%></td></tr>
|
||||||
<%
|
<%
|
||||||
} else {
|
} else {
|
||||||
@@ -385,7 +385,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="displayText" tabindex="0" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
<div class="displayText" tabindex="0" style="user-select: all;" title="<%=intl._t("Copy and paste this to the registration site")%>"><% he.write(out); %></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
19
history.txt
19
history.txt
@@ -1,3 +1,22 @@
|
|||||||
|
2019-05-24 zzz
|
||||||
|
* i2ptunnel:
|
||||||
|
- Per-client auth config
|
||||||
|
- Hide encryption key for per-client auth
|
||||||
|
- User-select: all for key fields
|
||||||
|
|
||||||
|
2019-05-23 zzz
|
||||||
|
* i2ptunnel:
|
||||||
|
- Rework server encryption key UI in prep for blinded keys
|
||||||
|
- Remove generate button, automatically generate when required
|
||||||
|
- Refactor auto configuration
|
||||||
|
- Add LS2 option, change to select box
|
||||||
|
- Select box for sig type
|
||||||
|
|
||||||
|
2019-05-22 zzz
|
||||||
|
* Crypto: Add X25519 DH class
|
||||||
|
* Data: Per-client auth for enc. LS2 (proposal 123)
|
||||||
|
* Transport: Use KeyGenerator for X25519 keys
|
||||||
|
|
||||||
2019-05-21 zzz
|
2019-05-21 zzz
|
||||||
* Profiles: Omit comments from stored profiles
|
* Profiles: Omit comments from stored profiles
|
||||||
|
|
||||||
|
@@ -18,7 +18,7 @@ public class RouterVersion {
|
|||||||
/** deprecated */
|
/** deprecated */
|
||||||
public final static String ID = "Monotone";
|
public final static String ID = "Monotone";
|
||||||
public final static String VERSION = CoreVersion.VERSION;
|
public final static String VERSION = CoreVersion.VERSION;
|
||||||
public final static long BUILD = 5;
|
public final static long BUILD = 6;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
Reference in New Issue
Block a user