propagate from branch 'i2p.i2p' (head e606c473eb1e461a477e45419f6295b6430a7353)

to branch 'i2p.i2p.zzz.test2' (head 6212892778308db10a86e58f9f275c838f604973)
This commit is contained in:
zzz
2014-09-09 19:27:10 +00:00
83 changed files with 1081 additions and 236 deletions

View File

@@ -314,6 +314,7 @@ public class Router implements RouterClock.ClockShiftListener {
if (f.exists())
SecureFileOutputStream.setPerms(f);
}
CryptoChecker.warnUnavailableCrypto(_context);
_routerInfo = null;
_higherVersionSeen = false;

View File

@@ -18,10 +18,10 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 9;
public final static long BUILD = 16;
/** for example "-test" */
public final static String EXTRA = "";
public final static String EXTRA = "-rc";
public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;
public static void main(String args[]) {
System.out.println("I2P Router version: " + FULL_VERSION);

View File

@@ -0,0 +1,249 @@
package net.i2p.router.networkdb.kademlia;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import gnu.getopt.Getopt;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.data.RouterAddress;
import net.i2p.data.RouterInfo;
import net.i2p.router.transport.BadCountries;
import net.i2p.router.transport.GeoIP;
import net.i2p.util.FileUtil;
/**
* Copy a random selection of 'count' router infos from configDir/netDb
* to 'toDir'. Skip your own router info, and old, hidden, unreachable, and
* introduced routers, and those from bad countries.
*
* Used in the build process.
*
* @since 0.9.15
*
*/
public class BundleRouterInfos {
/**
* Usage: PersistentDataStore -i configDir -o toDir -c count
*
* Copy a random selection of 'count' router infos from configDir/netDb
* to 'toDir'. Skip your own router info, and old, hidden, unreachable, and
* introduced routers, and those from bad countries.
*
* @since 0.9.15
*/
public static void main(String[] args) {
Getopt g = new Getopt("PersistentDataStore", args, "i:o:c:");
String in = System.getProperty("user.home") + "/.i2p";
String out = "netDb";
int count = 200;
boolean error = false;
int c;
while ((c = g.getopt()) != -1) {
switch (c) {
case 'i':
in = g.getOptarg();
break;
case 'o':
out = g.getOptarg();
break;
case 'c':
String scount = g.getOptarg();
try {
count = Integer.parseInt(scount);
} catch (NumberFormatException nfe) {
error = true;
}
break;
case '?':
case ':':
default:
error = true;
}
}
if (error) {
usage();
System.exit(1);
}
Properties props = new Properties();
props.setProperty(GeoIP.PROP_GEOIP_DIR, System.getProperty("user.dir") + "/installer/resources");
GeoIP geoIP = new GeoIP(new I2PAppContext(props));
File confDir = new File(in);
File dbDir = new File(confDir, "netDb");
if (!dbDir.exists()) {
System.out.println("NetDB directory " + dbDir + " does not exist");
System.exit(1);
}
File myFile = new File(confDir, "router.info");
File toDir = new File(out);
toDir.mkdirs();
InputStream fis = null;
Hash me = null;
try {
fis = new BufferedInputStream(new FileInputStream(myFile));
RouterInfo ri = new RouterInfo();
ri.readBytes(fis, true); // true = verify sig on read
me = ri.getIdentity().getHash();
} catch (Exception e) {
//System.out.println("Can't determine our identity");
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
int routerCount = 0;
List<File> toRead = new ArrayList<File>(2048);
for (int j = 0; j < PersistentDataStore.B64.length(); j++) {
File subdir = new File(dbDir, PersistentDataStore.DIR_PREFIX + PersistentDataStore.B64.charAt(j));
File[] files = subdir.listFiles(PersistentDataStore.RouterInfoFilter.getInstance());
if (files == null)
continue;
routerCount += files.length;
for (int i = 0; i < files.length; i++) {
toRead.add(files[i]);
}
}
if (toRead.isEmpty()) {
System.out.println("No files to copy in " + dbDir);
System.exit(1);
}
Collections.shuffle(toRead);
int copied = 0;
long tooOld = System.currentTimeMillis() - 7*24*60*60*1000L;
Map<String, String> ipMap = new HashMap<String, String>(count);
for (File file : toRead) {
if (copied >= count)
break;
Hash key = PersistentDataStore.getRouterInfoHash(file.getName());
if (key == null) {
System.out.println("Skipping bad " + file);
continue;
}
if (key.equals(me)) {
System.out.println("Skipping my RI");
continue;
}
fis = null;
try {
fis = new BufferedInputStream(new FileInputStream(file));
RouterInfo ri = new RouterInfo();
ri.readBytes(fis, true); // true = verify sig on read
try { fis.close(); } catch (IOException ioe) {}
fis = null;
if (ri.getPublished() < tooOld) {
System.out.println("Skipping too old " + key);
continue;
}
if (ri.getCapabilities().contains("U")) {
System.out.println("Skipping unreachable " + key);
continue;
}
if (ri.getCapabilities().contains("K")) {
System.out.println("Skipping slow " + key);
continue;
}
Collection<RouterAddress> addrs = ri.getAddresses();
if (addrs.isEmpty()) {
System.out.println("Skipping hidden " + key);
continue;
}
boolean hasIntro = false;
boolean hasIPv4 = false;
boolean dupIP = false;
for (RouterAddress addr : addrs) {
if ("SSU".equals(addr.getTransportStyle()) && addr.getOption("ihost0") != null) {
hasIntro = true;
break;
}
String host = addr.getHost();
if (host != null && host.contains(".")) {
hasIPv4 = true;
geoIP.add(host);
String old = ipMap.put(host, file.getName());
if (old != null && !old.equals(file.getName())) {
dupIP = true;
break;
}
}
}
if (dupIP) {
System.out.println("Skipping dup IP " + key);
continue;
}
if (hasIntro) {
System.out.println("Skipping introduced " + key);
continue;
}
if (!hasIPv4) {
System.out.println("Skipping IPv6-only " + key);
continue;
}
File toFile = new File(toDir, file.getName());
// We could call ri.write() to avoid simultaneous change by the router
boolean ok = FileUtil.copy(file, toFile, true, true);
if (ok)
copied++;
else
System.out.println("Failed copy of " + file + " to " + toDir);
} catch (Exception e) {
System.out.println("Skipping bad " + file);
} finally {
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
}
}
if (copied > 0) {
// now do all the geoip lookups, and delete any bad countries
geoIP.blockingLookup();
for (Map.Entry<String, String> e : ipMap.entrySet()) {
String co = geoIP.get(e.getKey());
if (co != null) {
if (BadCountries.contains(co)) {
String name = e.getValue();
File toFile = new File(toDir, name);
if (toFile.delete()) {
String full = geoIP.fullName(co);
if (full == null)
full = co;
System.out.println("Skipping " + full + ": " + name);
copied--;
}
}
}
}
}
if (copied > 0) {
System.out.println("Copied " + copied + " router info files to " + toDir);
} else {
System.out.println("Failed to copy any files to " + toDir);
System.exit(1);
}
}
private static void usage() {
System.err.println("Usage: PersistentDataStore [-i $HOME/.i2p] [-o netDb/] [-c 200]");
}
}

View File

@@ -54,8 +54,8 @@ class PersistentDataStore extends TransientDataStore {
private final static int READ_DELAY = 2*60*1000;
private static final String PROP_FLAT = "router.networkDatabase.flat";
private static final String DIR_PREFIX = "r";
private static final String B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~";
static final String DIR_PREFIX = "r";
static final String B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~";
/**
* @param dbDir relative path
@@ -614,7 +614,7 @@ class PersistentDataStore extends TransientDataStore {
return DIR_PREFIX + b64.charAt(0) + File.separatorChar + ROUTERINFO_PREFIX + b64 + ROUTERINFO_SUFFIX;
}
private static Hash getRouterInfoHash(String filename) {
static Hash getRouterInfoHash(String filename) {
return getHash(filename, ROUTERINFO_PREFIX, ROUTERINFO_SUFFIX);
}
@@ -651,7 +651,7 @@ class PersistentDataStore extends TransientDataStore {
}
}
private final static class RouterInfoFilter implements FilenameFilter {
static class RouterInfoFilter implements FilenameFilter {
private static final FilenameFilter _instance = new RouterInfoFilter();
public static final FilenameFilter getInstance() { return _instance; }
public boolean accept(File dir, String name) {

View File

@@ -74,8 +74,7 @@ public class Reseeder {
"http://reseed.i2p-projekt.de/" + "," +
//"http://euve5653.vserver.de/netDb/" + "," +
"http://cowpuncher.drollette.com/netdb/" + "," +
//Temp disabled (#1351)
//"http://i2p.mooo.com/netDb/" + "," +
"http://i2p.mooo.com/netDb/" + "," +
"http://193.150.121.66/netDb/" + "," +
"http://netdb.i2p2.no/" + "," +
"http://reseed.info/" + "," +
@@ -93,8 +92,7 @@ public class Reseeder {
"https://reseed.i2p-projekt.de/" + "," +
//"https://euve5653.vserver.de/netDb/" + "," +
"https://cowpuncher.drollette.com/netdb/" + "," +
//Temp disabled (#1351)
//"https://i2p.mooo.com/netDb/" + "," +
"https://i2p.mooo.com/netDb/" + "," +
"https://193.150.121.66/netDb/" + "," +
"https://netdb.i2p2.no/" + "," +
"https://reseed.info/" + "," +

View File

@@ -271,6 +271,8 @@ public class WorkingDir {
// We don't currently have a default addressbook/ in the base distribution,
// but distros might put one in
"addressbook,eepsite," +
// 0.9.15 support bundled router infos
"netDb," +
// base install - files
// We don't currently have a default router.config, logger.config, susimail.config, or webapps.config in the base distribution,
// but distros might put one in

View File

@@ -0,0 +1,101 @@
package net.i2p.router.tasks;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import net.i2p.crypto.SigType;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
/**
* Warn about unavailable crypto to router and wrapper logs
*
* @since 0.9.15
*/
public class CryptoChecker {
private static String JRE6 = "http://www.oracle.com/technetwork/java/javase/downloads/index.html";
// these two are US-only and can change?
//private static String JRE7 = "http://www.oracle.com/technetwork/java/javase/documentation/java-se-7-doc-download-435117.html";
//private static String JRE8 = "http://www.oracle.com/technetwork/java/javase/documentation/jdk8-doc-downloads-2133158.html";
/**
* @param ctx if null, logs only to System.out (called from main)
*/
public static void warnUnavailableCrypto(RouterContext ctx) {
if (SystemVersion.isAndroid())
return;
boolean unavail = false;
Log log = null;
for (SigType t : SigType.values()) {
if (!t.isAvailable()) {
if (!unavail) {
unavail = true;
if (ctx != null)
log = ctx.logManager().getLog(CryptoChecker.class);
}
String s = "Crypto " + t + " is not available";
if (log != null)
log.logAlways(log.WARN, s);
System.out.println("Warning: " + s);
}
}
if (unavail) {
if (!SystemVersion.isJava7()) {
String s = "Java version: " + System.getProperty("java.version") + " Please consider upgrading to Java 7";
if (log != null)
log.logAlways(log.WARN, s);
System.out.println(s);
}
if (!isUnlimited()) {
String s = "Please consider installing the Java Cryptography Unlimited Strength Jurisdiction Policy Files from ";
//if (SystemVersion.isJava8())
// s += JRE8;
//else if (SystemVersion.isJava7())
// s += JRE7;
//else
s += JRE6;
if (log != null)
log.logAlways(log.WARN, s);
System.out.println(s);
}
String s = "This crypto will be required in a future release";
if (log != null)
log.logAlways(log.WARN, s);
System.out.println("Warning: " + s);
} else if (ctx == null) {
// called from main()
System.out.println("All crypto available");
}
}
/**
* Copied from CryptixAESEngine
*/
private static boolean isUnlimited() {
try {
if (Cipher.getMaxAllowedKeyLength("AES") < 256)
return false;
} catch (NoSuchAlgorithmException e) {
return false;
} catch (NoSuchMethodError e) {
// JamVM, gij
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec key = new SecretKeySpec(new byte[32], "AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
} catch (GeneralSecurityException gse) {
return false;
}
}
return true;
}
public static void main(String[] args) {
warnUnavailableCrypto(null);
}
}

View File

@@ -9,7 +9,7 @@ import java.util.Set;
* Maintain a list of bad places.
* @since 0.8.13
*/
abstract class BadCountries {
public abstract class BadCountries {
private static final Set<String> _countries;

View File

@@ -16,6 +16,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
@@ -38,11 +39,9 @@ import net.i2p.util.Log;
*
* @author zzz
*/
class GeoIP {
public class GeoIP {
private final Log _log;
// change to test with main()
//private final I2PAppContext _context;
private final RouterContext _context;
private final I2PAppContext _context;
private final Map<String, String> _codeToName;
/** code to itself to prevent String proliferation */
private final Map<String, String> _codeCache;
@@ -56,8 +55,10 @@ class GeoIP {
private final AtomicBoolean _lock;
private int _lookupRunCount;
//public GeoIP(I2PAppContext context) {
public GeoIP(RouterContext context) {
/**
* @param context RouterContext in production, I2PAppContext for testing only
*/
public GeoIP(I2PAppContext context) {
_context = context;
_log = context.logManager().getLog(GeoIP.class);
_codeToName = new ConcurrentHashMap<String, String>(512);
@@ -71,6 +72,7 @@ class GeoIP {
}
static final String PROP_GEOIP_ENABLED = "routerconsole.geoip.enable";
public static final String PROP_GEOIP_DIR = "geoip.dir";
static final String GEOIP_DIR_DEFAULT = "geoip";
static final String GEOIP_FILE_DEFAULT = "geoip.txt";
static final String COUNTRY_FILE_DEFAULT = "countries.txt";
@@ -187,7 +189,10 @@ class GeoIP {
*
*/
private void readCountryFile() {
File geoFile = new File(_context.getBaseDir(), GEOIP_DIR_DEFAULT);
String geoDir = _context.getProperty(PROP_GEOIP_DIR, GEOIP_DIR_DEFAULT);
File geoFile = new File(geoDir);
if (!geoFile.isAbsolute())
geoFile = new File(_context.getBaseDir(), geoDir);
geoFile = new File(geoFile, COUNTRY_FILE_DEFAULT);
if (!geoFile.exists()) {
if (_log.shouldLog(Log.WARN))
@@ -246,7 +251,10 @@ class GeoIP {
*
*/
private String[] readGeoIPFile(Long[] search) {
File geoFile = new File(_context.getBaseDir(), GEOIP_DIR_DEFAULT);
String geoDir = _context.getProperty(PROP_GEOIP_DIR, GEOIP_DIR_DEFAULT);
File geoFile = new File(geoDir);
if (!geoFile.isAbsolute())
geoFile = new File(_context.getBaseDir(), geoDir);
geoFile = new File(geoFile, GEOIP_FILE_DEFAULT);
if (!geoFile.exists()) {
if (_log.shouldLog(Log.WARN))
@@ -300,24 +308,28 @@ class GeoIP {
/**
* Put our country code in the config, where others (such as Timestamper) can get it,
* and it will be there next time at startup.
*
* Does nothing in I2PAppContext
*/
private void updateOurCountry() {
/**** comment out to test with main() */
String oldCountry = _context.router().getConfigSetting(PROP_IP_COUNTRY);
Hash ourHash = _context.routerHash();
if (! (_context instanceof RouterContext))
return;
RouterContext ctx = (RouterContext) _context;
String oldCountry = ctx.router().getConfigSetting(PROP_IP_COUNTRY);
Hash ourHash = ctx.routerHash();
// we should always have a RouterInfo by now, but we had one report of an NPE here
if (ourHash == null)
return;
String country = _context.commSystem().getCountry(ourHash);
String country = ctx.commSystem().getCountry(ourHash);
if (country != null && !country.equals(oldCountry)) {
_context.router().saveConfig(PROP_IP_COUNTRY, country);
if (_context.commSystem().isInBadCountry() && _context.getProperty(Router.PROP_HIDDEN_HIDDEN) == null) {
ctx.router().saveConfig(PROP_IP_COUNTRY, country);
if (ctx.commSystem().isInBadCountry() && ctx.getProperty(Router.PROP_HIDDEN_HIDDEN) == null) {
String name = fullName(country);
if (name == null)
name = country;
_log.logAlways(Log.WARN, "Setting hidden mode to protect you in " + name +
", you may override on the network configuration page");
_context.router().rebuildRouterInfo();
ctx.router().rebuildRouterInfo();
}
}
/****/

View File

@@ -292,7 +292,14 @@ public class ControlPoint implements HTTPRequestListener
DeviceList devList = new DeviceList();
int nRoots = devNodeList.size();
for (int n=0; n<nRoots; n++) {
Node rootNode = devNodeList.getNode(n);
// AIOOB was thrown from here, maybe would be better to
// copy the list before traversal?
Node rootNode;
try {
rootNode = devNodeList.getNode(n);
} catch (ArrayIndexOutOfBoundsException aioob) {
break;
}
Device dev = getDevice(rootNode);
if (dev == null)
continue;