forked from I2P_Developers/i2p.i2p
i2ptunnel: New b32 error page
Do basic b32 checks before looking up with session Util: Fix AIOOBE on bad input to base 32 decode log tweaks b33 decode error message tweaks
This commit is contained in:
@ -1215,12 +1215,39 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
}
|
}
|
||||||
} else if("i2p".equals(host)) {
|
} else if("i2p".equals(host)) {
|
||||||
clientDest = null;
|
clientDest = null;
|
||||||
} else if (destination.length() >= 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
} else if (destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
||||||
|
int len = destination.length();
|
||||||
|
if (len < 60 || (len >= 61 && len <= 63)) {
|
||||||
|
// 8-59 or 61-63 chars, this won't work
|
||||||
|
String header = getErrorPage("b32", ERR_DESTINATION_UNKNOWN);
|
||||||
|
try {
|
||||||
|
writeErrorMessage(header, _t("Corrupt b32 address"), out, targetRequest, false, destination);
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (len >= 64) {
|
||||||
|
// catch b33 errors before session lookup
|
||||||
|
try {
|
||||||
|
BlindData bd = Blinding.decode(_context, destination);
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Resolved b33 " + bd);
|
||||||
|
// TESTING
|
||||||
|
//sess.sendBlindingInfo(bd, 24*60*60*1000);
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
if (_log.shouldWarn())
|
||||||
|
_log.warn("Unable to resolve b33 " + destination, iae);
|
||||||
|
// b33 error page
|
||||||
|
String header = getErrorPage("b32", ERR_DESTINATION_UNKNOWN);
|
||||||
|
try {
|
||||||
|
writeErrorMessage(header, iae.getMessage(), out, targetRequest, false, destination);
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// use existing session to look up for efficiency
|
// use existing session to look up for efficiency
|
||||||
verifySocketManager();
|
verifySocketManager();
|
||||||
I2PSession sess = sockMgr.getSession();
|
I2PSession sess = sockMgr.getSession();
|
||||||
if (!sess.isClosed()) {
|
if (!sess.isClosed()) {
|
||||||
int len = destination.length();
|
|
||||||
if (len == 60) {
|
if (len == 60) {
|
||||||
byte[] hData = Base32.decode(destination.substring(0, 52));
|
byte[] hData = Base32.decode(destination.substring(0, 52));
|
||||||
if (hData != null) {
|
if (hData != null) {
|
||||||
@ -1234,33 +1261,43 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
} else if (len >= 64) {
|
} else if (len >= 64) {
|
||||||
if (_log.shouldInfo())
|
if (_log.shouldInfo())
|
||||||
_log.info("lookup b33 in-session " + destination);
|
_log.info("lookup b33 in-session " + destination);
|
||||||
try {
|
|
||||||
BlindData bd = Blinding.decode(_context, destination);
|
|
||||||
if (_log.shouldWarn())
|
|
||||||
_log.warn("Resolved b33 " + bd);
|
|
||||||
// TESTING
|
|
||||||
//sess.sendBlindingInfo(bd, 24*60*60*1000);
|
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
if (_log.shouldWarn())
|
|
||||||
_log.warn("Unable to resolve b33 " + destination, iae);
|
|
||||||
// TODO new error page
|
|
||||||
}
|
|
||||||
LookupResult lresult = sess.lookupDest2(destination, 20*1000);
|
LookupResult lresult = sess.lookupDest2(destination, 20*1000);
|
||||||
clientDest = lresult.getDestination();
|
clientDest = lresult.getDestination();
|
||||||
int code = lresult.getResultCode();
|
int code = lresult.getResultCode();
|
||||||
if (code != 0) {
|
if (code != LookupResult.RESULT_SUCCESS) {
|
||||||
if (_log.shouldWarn())
|
if (_log.shouldWarn())
|
||||||
_log.warn("Unable to resolve b33 " + destination + " error code " + code);
|
_log.warn("Unable to resolve b33 " + destination + " error code " + code);
|
||||||
// TODO new form
|
// TODO new form to supply missing data
|
||||||
|
if (code != LookupResult.RESULT_FAILURE) {
|
||||||
|
String header = getErrorPage("b32", ERR_DESTINATION_UNKNOWN);
|
||||||
|
String msg;
|
||||||
|
if (code == LookupResult.RESULT_SECRET_REQUIRED)
|
||||||
|
msg = "b32 address requires lookup password";
|
||||||
|
else if (code == LookupResult.RESULT_KEY_REQUIRED)
|
||||||
|
msg = "b32 address requires encryption key";
|
||||||
|
else if (code == LookupResult.RESULT_SECRET_AND_KEY_REQUIRED)
|
||||||
|
msg = "b32 address requires encryption key and lookup password";
|
||||||
|
else if (code == LookupResult.RESULT_DECRYPTION_FAILURE)
|
||||||
|
msg = "b32 address decryption failure, check encryption key";
|
||||||
|
else
|
||||||
|
msg = "lookup failure code " + code;
|
||||||
|
try {
|
||||||
|
writeErrorMessage(header, msg, out, targetRequest, false, destination);
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// 61-63 chars, this won't work
|
|
||||||
clientDest = _context.namingService().lookup(destination);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info("lookup b32 out of session " + destination);
|
||||||
|
// TODO can't get result code from here
|
||||||
clientDest = _context.namingService().lookup(destination);
|
clientDest = _context.namingService().lookup(destination);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info("lookup hostname " + destination);
|
||||||
clientDest = _context.namingService().lookup(destination);
|
clientDest = _context.namingService().lookup(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1518,7 +1555,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if(host == null) {
|
if(host == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(host.length() == 60 && host.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
if (host.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
Destination dest = _context.namingService().lookup(host);
|
Destination dest = _context.namingService().lookup(host);
|
||||||
|
@ -209,7 +209,7 @@ public final class Blinding {
|
|||||||
throw new IllegalArgumentException("Not a .b32.i2p address");
|
throw new IllegalArgumentException("Not a .b32.i2p address");
|
||||||
byte[] b = Base32.decode(address.substring(0, address.length() - 8));
|
byte[] b = Base32.decode(address.substring(0, address.length() - 8));
|
||||||
if (b == null)
|
if (b == null)
|
||||||
throw new IllegalArgumentException("Bad base32 encoding");
|
throw new IllegalArgumentException("Corrupt b32 address");
|
||||||
if (b.length < 35)
|
if (b.length < 35)
|
||||||
throw new IllegalArgumentException("Not a new-format address");
|
throw new IllegalArgumentException("Not a new-format address");
|
||||||
return decode(ctx, b);
|
return decode(ctx, b);
|
||||||
@ -234,22 +234,22 @@ public final class Blinding {
|
|||||||
b[2] ^= (byte) (check >> 16);
|
b[2] ^= (byte) (check >> 16);
|
||||||
int flag = b[0] & 0xff;
|
int flag = b[0] & 0xff;
|
||||||
if ((flag & 0xf8) != 0)
|
if ((flag & 0xf8) != 0)
|
||||||
throw new IllegalArgumentException("Corrupt b32 or unsupported options");
|
throw new IllegalArgumentException("Corrupt b32 address (or unsupported options)");
|
||||||
if ((flag & FLAG_TWOBYTE) != 0)
|
if ((flag & FLAG_TWOBYTE) != 0)
|
||||||
throw new IllegalArgumentException("Two byte sig types unsupported");
|
throw new IllegalArgumentException("Two byte signature types unsupported");
|
||||||
// TODO two-byte sigtypes
|
// TODO two-byte sigtypes
|
||||||
int st1 = b[1] & 0xff;
|
int st1 = b[1] & 0xff;
|
||||||
int st2 = b[2] & 0xff;
|
int st2 = b[2] & 0xff;
|
||||||
SigType sigt1 = SigType.getByCode(st1);
|
SigType sigt1 = SigType.getByCode(st1);
|
||||||
SigType sigt2 = SigType.getByCode(st2);
|
SigType sigt2 = SigType.getByCode(st2);
|
||||||
if (sigt1 == null)
|
if (sigt1 == null)
|
||||||
throw new IllegalArgumentException("Unknown sig type " + st1);
|
throw new IllegalArgumentException("Unsupported signature type " + st1);
|
||||||
if (!sigt1.isAvailable())
|
if (!sigt1.isAvailable())
|
||||||
throw new IllegalArgumentException("Unavailable sig type " + sigt1);
|
throw new IllegalArgumentException("Unavailable signature type " + sigt1);
|
||||||
if (sigt2 == null)
|
if (sigt2 == null)
|
||||||
throw new IllegalArgumentException("Unknown blinded sig type " + st2);
|
throw new IllegalArgumentException("Unsupported blinded signature type " + st2);
|
||||||
if (!sigt2.isAvailable())
|
if (!sigt2.isAvailable())
|
||||||
throw new IllegalArgumentException("Unavailable blinded sig type " + sigt2);
|
throw new IllegalArgumentException("Unavailable blinded signature type " + sigt2);
|
||||||
// todo secret/privkey
|
// todo secret/privkey
|
||||||
int spkLen = sigt1.getPubkeyLen();
|
int spkLen = sigt1.getPubkeyLen();
|
||||||
if (3 + spkLen > b.length)
|
if (3 + spkLen > b.length)
|
||||||
|
@ -235,6 +235,8 @@ public class Base32 {
|
|||||||
fivebits = DECODABET[source[i] - '2'];
|
fivebits = DECODABET[source[i] - '2'];
|
||||||
|
|
||||||
if (fivebits >= 0) {
|
if (fivebits >= 0) {
|
||||||
|
if (outBuffPosn >= len58)
|
||||||
|
return null;
|
||||||
if (usedbits == 0) {
|
if (usedbits == 0) {
|
||||||
outBuff[outBuffPosn] = (byte) ((fivebits << 3) & 0xf8);
|
outBuff[outBuffPosn] = (byte) ((fivebits << 3) & 0xf8);
|
||||||
usedbits = 5;
|
usedbits = 5;
|
||||||
|
25
installer/resources/proxy/b32-header.ht
Normal file
25
installer/resources/proxy/b32-header.ht
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
HTTP/1.1 400 Destination Not Found
|
||||||
|
Content-Type: text/html; charset=UTF-8
|
||||||
|
Cache-Control: no-cache
|
||||||
|
Connection: close
|
||||||
|
Proxy-Connection: close
|
||||||
|
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html><head>
|
||||||
|
<title>_("Website Unreachable")</title>
|
||||||
|
<noscript><style type="text/css">.script {display: none;}</style></noscript>
|
||||||
|
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico">
|
||||||
|
<link href="http://proxy.i2p/themes/console/default/console.css" rel="stylesheet" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="logo">
|
||||||
|
<a href="http://127.0.0.1:7657/" title="_("Router Console")"><img src="http://proxy.i2p/themes/console/images/i2plogo.png" alt="_("I2P Router Console")" border="0"></a><hr>
|
||||||
|
<a href="http://127.0.0.1:7657/config.jsp">_("Configuration")</a> <a href="http://127.0.0.1:7657/help.jsp">_("Help")</a> <a href="http://127.0.0.1:7657/susidns/index">_("Addressbook")</a>
|
||||||
|
</div>
|
||||||
|
<div class="warning" id="warning">
|
||||||
|
<h3>_("Warning: Invalid Destination")</h3>
|
||||||
|
<p>
|
||||||
|
_("The b32 address is invalid.")
|
||||||
|
<hr>
|
||||||
|
<p><b>_("Could not find the following destination:")</b>
|
||||||
|
</p>
|
@ -129,7 +129,7 @@ class LookupDestJob extends JobImpl {
|
|||||||
Destination d = _blindData.getDestination();
|
Destination d = _blindData.getDestination();
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Found cached b33 lookup " + _name + " to " + d);
|
_log.debug("Found cached b33 lookup " + _blindData.getUnblindedPubKey() + " to " + d);
|
||||||
returnDest(d);
|
returnDest(d);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ class LookupDestJob extends JobImpl {
|
|||||||
else
|
else
|
||||||
code = HostReplyMessage.RESULT_SECRET_REQUIRED;
|
code = HostReplyMessage.RESULT_SECRET_REQUIRED;
|
||||||
if (_log.shouldDebug())
|
if (_log.shouldDebug())
|
||||||
_log.debug("Failed b33 lookup " + _name + " with code " + code);
|
_log.debug("Failed b33 lookup " + _blindData.getUnblindedPubKey() + " with code " + code);
|
||||||
returnFail(code);
|
returnFail(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user