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:
zzz
2019-05-24 17:42:11 +00:00
parent 47c64c2eef
commit 2abd59e6d4
8 changed files with 331 additions and 20 deletions

View File

@@ -569,11 +569,13 @@ public class GeneralHelper {
int rv;
String authType = getProperty(tunnel, "i2cp.leaseSetAuthType", "0");
if (authType.equals("2")) {
// shared PSK key
rv = 4;
// per-client PSK key
// TODO
//rv = 6;
if (getProperty(tunnel, "i2cp.leaseSetClient.psk.0", null) != null) {
// per-client PSK key
rv = 6;
} else {
// shared PSK key
rv = 4;
}
} else if (authType.equals("1")) {
rv = 8;
} else {
@@ -596,6 +598,25 @@ public class GeneralHelper {
public String getBlindedPassword(int tunnel) {
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 &lt; 0
@@ -868,6 +889,8 @@ public class GeneralHelper {
if ((!isMD5Proxy) &&
TunnelConfig._nonProxyNoShowSet.contains(key))
continue;
if (key.startsWith("i2cp.leaseSetClient."))
continue;
sorted.put(key, (String)e.getValue());
}
if (sorted.isEmpty())

View File

@@ -2,7 +2,10 @@ package net.i2p.i2ptunnel.ui;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@@ -14,6 +17,7 @@ import net.i2p.client.I2PClient;
import net.i2p.crypto.KeyGenerator;
import net.i2p.crypto.SigType;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.SimpleDataStructure;
import net.i2p.i2ptunnel.I2PTunnelClientBase;
@@ -77,6 +81,13 @@ public class TunnelConfig {
private Destination _dest;
private String _filterDefinition;
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() {
_context = I2PAppContext.getGlobalContext();
@@ -271,6 +282,59 @@ public class TunnelConfig {
_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) {
if (val)
_booleanOptions.add(I2PTunnelIRCClient.PROP_DCC);
@@ -858,6 +922,74 @@ public class TunnelConfig {
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,
"inbound.randomKey", "outbound.randomKey", "i2cp.leaseSetSigningPrivateKey", "i2cp.leaseSetPrivateKey",
I2PTunnelServer.PROP_ALT_PKF,
"i2cp.leaseSetSecret", "i2cp.leaseSetType", "i2cp.leaseSetAuthType"
"i2cp.leaseSetSecret", "i2cp.leaseSetType", "i2cp.leaseSetAuthType", "i2cp.leaseSetPrivKey"
};
private static final String _httpServerOpts[] = {
I2PTunnelHTTPServer.OPT_POST_WINDOW,

View File

@@ -226,6 +226,17 @@ public class EditBean extends IndexBean {
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 &lt; 0
* @since 0.9.12

View File

@@ -872,6 +872,63 @@ public class IndexBean {
_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 */
public void setDCC(String moo) {
_config.setDCC(true);