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;
|
||||
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 < 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())
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 < 0
|
||||
* @since 0.9.12
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user