I2CP: New Blinding Info message (proposal 123)

client- and router-side support
new session lookupDest2() method
return new b33 failure codes from lookup
show b33 alternates in tools
stub out support in HTTP client
This commit is contained in:
zzz
2019-09-10 12:37:11 +00:00
parent c99a42f0b1
commit 479461ab3b
15 changed files with 679 additions and 22 deletions

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 5;
public final static long BUILD = 6;
/** for example "-test" */
public final static String EXTRA = "";

View File

@ -15,6 +15,7 @@ import net.i2p.CoreVersion;
import net.i2p.crypto.EncType;
import net.i2p.crypto.SigType;
import net.i2p.data.Base64;
import net.i2p.data.BlindData;
import net.i2p.data.DatabaseEntry;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
@ -25,7 +26,9 @@ import net.i2p.data.LeaseSet2;
import net.i2p.data.Payload;
import net.i2p.data.PrivateKey;
import net.i2p.data.PublicKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
import net.i2p.data.i2cp.BlindingInfoMessage;
import net.i2p.data.i2cp.CreateLeaseSetMessage;
import net.i2p.data.i2cp.CreateLeaseSet2Message;
import net.i2p.data.i2cp.CreateSessionMessage;
@ -152,6 +155,9 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
case GetBandwidthLimitsMessage.MESSAGE_TYPE:
handleGetBWLimits((GetBandwidthLimitsMessage)message);
break;
case BlindingInfoMessage.MESSAGE_TYPE:
handleBlindingInfo((BlindingInfoMessage)message);
break;
default:
if (_log.shouldLog(Log.ERROR))
_log.error("Unhandled I2CP type received: " + message.getType());
@ -774,6 +780,8 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
* Divide router limit by 1.75 for overhead.
* This could someday give a different answer to each client.
* But it's not enforced anywhere.
*
* protected for unit test override
*/
protected void handleGetBWLimits(GetBandwidthLimitsMessage message) {
if (_log.shouldLog(Log.INFO))
@ -789,4 +797,41 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
}
}
/**
*
* @since 0.9.43
*/
private void handleBlindingInfo(BlindingInfoMessage message) {
if (_log.shouldInfo())
_log.info("Got Blinding info");
BlindData bd = message.getBlindData();
SigningPublicKey spk = bd.getUnblindedPubKey();
if (spk == null || bd == null) {
// hash or hostname lookup? don't support for now
if (_log.shouldWarn())
_log.warn("Unsupported BlindingInfo type: " + message);
return;
}
BlindData obd = _context.netDb().getBlindData(spk);
if (obd == null) {
_context.netDb().setBlindData(bd);
if (_log.shouldWarn())
_log.warn("New: " + bd);
} else {
// update if changed
PrivateKey okey = obd.getAuthPrivKey();
PrivateKey nkey = bd.getAuthPrivKey();
String osec = obd.getSecret();
String nsec = bd.getSecret();
if ((nkey != null && !nkey.equals(okey)) ||
(nsec != null && !nsec.equals(osec))) {
_context.netDb().setBlindData(bd);
if (_log.shouldWarn())
_log.warn("Updated: " + bd);
} else {
if (_log.shouldWarn())
_log.warn("No change: " + obd);
}
}
}
}

View File

@ -93,6 +93,7 @@ class LookupDestJob extends JobImpl {
SigningPublicKey spk = bd.getUnblindedPubKey();
BlindData bd2 = getContext().netDb().getBlindData(spk);
if (bd2 != null) {
// BlindData from database may have privkey or secret
bd = bd2;
} else {
getContext().netDb().setBlindData(bd);
@ -132,6 +133,20 @@ class LookupDestJob extends JobImpl {
returnDest(d);
return;
}
boolean fail1 = _blindData.getAuthRequired() && _blindData.getAuthPrivKey() == null;
boolean fail2 = _blindData.getSecretRequired() && _blindData.getSecret() == null;
if (fail1 || fail2) {
int code;
if (fail1 && fail2)
code = HostReplyMessage.RESULT_SECRET_AND_KEY_REQUIRED;
else if (fail1)
code = HostReplyMessage.RESULT_KEY_REQUIRED;
else
code = HostReplyMessage.RESULT_SECRET_REQUIRED;
if (_log.shouldDebug())
_log.debug("Failed b33 lookup " + _name + " with code " + code);
returnFail(code);
}
}
if (_name != null) {
// inline, ignore timeout
@ -151,7 +166,7 @@ class LookupDestJob extends JobImpl {
getContext().netDb().lookupDestination(_hash, done, _timeout, _fromLocalDest);
} else {
// blinding decode fail
returnFail();
returnFail(HostReplyMessage.RESULT_DECRYPTION_FAILURE);
}
}
@ -198,13 +213,22 @@ class LookupDestJob extends JobImpl {
}
/**
* Return the failed hash so the client can correlate replies with requests
* Return the request ID or failed hash so the client can correlate replies with requests
* @since 0.8.3
*/
private void returnFail() {
returnFail(HostReplyMessage.RESULT_FAILURE);
}
/**
* Return the request ID or failed hash so the client can correlate replies with requests
* @param code failure code, greater than zero, only used for HostReplyMessage
* @since 0.9.43
*/
private void returnFail(int code) {
I2CPMessage msg;
if (_reqID >= 0)
msg = new HostReplyMessage(_sessID, HostReplyMessage.RESULT_FAILURE, _reqID);
msg = new HostReplyMessage(_sessID, code, _reqID);
else if (_hash != null)
msg = new DestReplyMessage(_hash);
else