I2CP: Set offline keys in generated LS2

(router side to follow)
Propagate error from disconnect message to session listener
Refactor RLSMH options
This commit is contained in:
zzz
2018-12-05 13:50:07 +00:00
parent 2876da2565
commit d054c6bc04
3 changed files with 55 additions and 10 deletions

View File

@ -148,6 +148,10 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
/** monitor for waiting until a lease set has been granted */
protected final Object _leaseSetWait = new Object();
/** set in propogateError(), sync with _stateLock */
private String _errorMessage;
private Throwable _errorCause;
/**
* @since 0.9.8
*/
@ -694,6 +698,8 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
try {
// protect w/ closeSocket()
synchronized(_stateLock) {
_errorMessage = null;
_errorCause = null;
// If we are in the router JVM, connect using the internal queue
if (_context.isRouterContext()) {
// _socket and _writer remain null
@ -780,8 +786,17 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
_leaseSetWait.wait(1000);
}
// if we got a disconnect message while waiting
if (isClosed())
throw new IOException("Disconnected from router while waiting for tunnels");
synchronized (_stateLock) {
if (isClosed()) {
String msg = "Disconnected from router while waiting for tunnels";
if (_errorMessage != null)
msg += ": " + _errorMessage;
IOException ioe = new IOException(msg);
if (_errorCause != null)
ioe.initCause(_errorCause);
throw ioe;
}
}
}
if (_log.shouldLog(Log.INFO)) {
long connected = _context.clock().now();
@ -1258,6 +1273,9 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
if (_log.shouldLog(level))
_log.log(level, getPrefix() + msgpfx + msg, error);
if (_sessionListener != null) _sessionListener.errorOccurred(this, msg, error);
// Save for throwing out of connect()
_errorMessage = msg;
_errorCause = error;
}
/**

View File

@ -49,6 +49,15 @@ import net.i2p.util.Log;
class RequestLeaseSetMessageHandler extends HandlerImpl {
private final Map<Destination, LeaseInfo> _existingLeaseSets;
// LS 1
private static final String PROP_LS_ENCRYPT = "i2cp.encryptLeaseSet";
private static final String PROP_LS_KEY = "i2cp.leaseSetKey";
private static final String PROP_LS_PK = "i2cp.leaseSetPrivateKey";
private static final String PROP_LS_SPK = "i2cp.leaseSetSigningPrivateKey";
// LS 2
private static final String PROP_LS_TYPE = "i2cp.leaseSetType";
private static final String PROP_LS_ENCTYPE = "i2cp.leaseSetEncType";
public RequestLeaseSetMessageHandler(I2PAppContext context) {
this(context, RequestLeaseSetMessage.MESSAGE_TYPE);
}
@ -70,13 +79,15 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
protected static boolean requiresLS2(I2PSessionImpl session) {
if (!session.supportsLS2())
return false;
String s = session.getOptions().getProperty("crypto.encType");
if (session.isOffline())
return true;
String s = session.getOptions().getProperty(PROP_LS_ENCTYPE);
if (s != null) {
EncType type = EncType.parseEncType(s);
if (type != null && type != EncType.ELGAMAL_2048 && type.isAvailable())
return true;
}
s = session.getOptions().getProperty("i2cp.leaseSetType");
s = session.getOptions().getProperty(PROP_LS_TYPE);
if (s != null) {
try {
int type = Integer.parseInt(s);
@ -117,9 +128,9 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
LeaseInfo li = _existingLeaseSets.get(dest);
if (li == null) {
// [enctype:]b64 of private key
String spk = session.getOptions().getProperty("i2cp.leaseSetPrivateKey");
String spk = session.getOptions().getProperty(PROP_LS_PK);
// [sigtype:]b64 of private key
String sspk = session.getOptions().getProperty("i2cp.leaseSetSigningPrivateKey");
String sspk = session.getOptions().getProperty(PROP_LS_SPK);
PrivateKey privKey = null;
SigningPrivateKey signingPrivKey = null;
if (spk != null && sspk != null) {
@ -178,7 +189,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
}
} else {
EncType type = EncType.ELGAMAL_2048;
String senc = session.getOptions().getProperty("crypto.encType");
String senc = session.getOptions().getProperty(PROP_LS_ENCTYPE);
if (senc != null) {
EncType newtype = EncType.parseEncType(senc);
if (newtype != null) {
@ -215,8 +226,8 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
opts = ((SubSession) session).getPrimaryOptions();
else
opts = session.getOptions();
boolean encrypt = Boolean.parseBoolean(opts.getProperty("i2cp.encryptLeaseSet"));
String sk = opts.getProperty("i2cp.leaseSetKey");
boolean encrypt = Boolean.parseBoolean(opts.getProperty(PROP_LS_ENCRYPT));
String sk = opts.getProperty(PROP_LS_KEY);
Hash h = dest.calculateHash();
if (encrypt && sk != null) {
SessionKey key = new SessionKey();
@ -231,6 +242,16 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
} else {
_context.keyRing().remove(h);
}
// offline keys
if (session.isOffline()) {
LeaseSet2 ls2 = (LeaseSet2) leaseSet;
boolean ok = ls2.setOfflineSignature(session.getOfflineExpiration(), session.getTransientSigningPublicKey(),
session.getOfflineSignature());
if (!ok) {
session.propogateError("Bad offline signature", new Exception());
// TODO just let the router handle it for now
}
}
try {
leaseSet.sign(session.getPrivateKey());
// Workaround for unparsable serialized signing private key for revocation

View File

@ -34,7 +34,13 @@ class SetDateMessageHandler extends HandlerImpl {
// we did was get the time from ourselves.
if (!_context.isRouterContext())
Clock.getInstance().setNow(msg.getDate().getTime());
// TODO - save router's version string for future reference
// This saves the various support capabilities based on
// the router's version string for future reference
session.dateUpdated(msg.getVersion());
if (session.isOffline() && !session.supportsLS2()) {
// TODO check other options also? see RLSMH.requiresLS2()
session.propogateError("Router does not support offline keys", new Exception());
session.destroySession(false);
}
}
}