forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.update' (head 267311f29e501fcc8b3d674a93e78b5520ac985e)
to branch 'i2p.i2p' (head edeca2ab47e734c2314ff394609292d8bd3d5293)
This commit is contained in:
@ -16,7 +16,7 @@ package net.i2p;
|
||||
public class CoreVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = "0.9.2";
|
||||
public final static String VERSION = "0.9.3";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Core version: " + VERSION);
|
||||
|
58
core/java/src/net/i2p/app/ClientApp.java
Normal file
58
core/java/src/net/i2p/app/ClientApp.java
Normal file
@ -0,0 +1,58 @@
|
||||
package net.i2p.app;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* If a class started via clients.config implements this interface,
|
||||
* it will be used to manage the client, instead of starting with main()
|
||||
*
|
||||
* Clients implementing this interface MUST provide the following constructor:
|
||||
*
|
||||
* public MyClientApp(I2PAppContext context, ClientAppManager listener, String[] args) {...}
|
||||
*
|
||||
* All parameters are non-null.
|
||||
* This constructor is for instantiation only.
|
||||
* Do not take a long time. Do not block. Never start threads or processes in it.
|
||||
* The ClientAppState of the returned object must be INITIALIZED,
|
||||
* or else throw something.
|
||||
* The startup() method will be called next.
|
||||
*
|
||||
* Never ever hold a static reference to the context or anything derived from it.
|
||||
*
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public interface ClientApp {
|
||||
|
||||
/**
|
||||
* Do not take a long time. Do not block. Start threads here if necessary.
|
||||
* Client must call ClientAppManager.notify() at least once within this
|
||||
* method to change the state from INITIALIZED to something else.
|
||||
* Will not be called multiple times on the same object.
|
||||
*/
|
||||
public void startup() throws Throwable;
|
||||
|
||||
/**
|
||||
* Do not take a long time. Do not block. Use a thread if necessary.
|
||||
* If previously running, client must call ClientAppManager.notify() at least once within this
|
||||
* method to change the state to STOPPING or STOPPED.
|
||||
* May be called multiple times on the same object, in any state.
|
||||
*/
|
||||
public void shutdown(String[] args) throws Throwable;
|
||||
|
||||
/**
|
||||
* The current state of the ClientApp.
|
||||
*/
|
||||
public ClientAppState getState();
|
||||
|
||||
/**
|
||||
* The generic name of the ClientApp, used for registration,
|
||||
* e.g. "console". Do not translate.
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* The dislplay name of the ClientApp, used in user interfaces.
|
||||
* The app must translate.
|
||||
*/
|
||||
public String getDisplayName();
|
||||
}
|
51
core/java/src/net/i2p/app/ClientAppManager.java
Normal file
51
core/java/src/net/i2p/app/ClientAppManager.java
Normal file
@ -0,0 +1,51 @@
|
||||
package net.i2p.app;
|
||||
|
||||
/**
|
||||
* Notify the router of events, and provide methods for
|
||||
* client apps to find each other.
|
||||
*
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public interface ClientAppManager {
|
||||
|
||||
/**
|
||||
* Must be called on all state transitions except
|
||||
* from UNINITIALIZED to INITIALIZED.
|
||||
*
|
||||
* @param app non-null
|
||||
* @param state non-null
|
||||
* @param message may be null
|
||||
* @param e may be null
|
||||
*/
|
||||
public void notify(ClientApp app, ClientAppState state, String message, Exception e);
|
||||
|
||||
/**
|
||||
* Register with the manager under the given name,
|
||||
* so that other clients may find it.
|
||||
* Only required for apps used by other apps.
|
||||
*
|
||||
* @param app non-null
|
||||
* @param name non-null
|
||||
* @return true if successful, false if duplicate name
|
||||
*/
|
||||
public boolean register(ClientApp app);
|
||||
|
||||
/**
|
||||
* Unregister with the manager. Name must be the same as that from register().
|
||||
* Only required for apps used by other apps.
|
||||
*
|
||||
* @param app non-null
|
||||
* @param name non-null
|
||||
*/
|
||||
public void unregister(ClientApp app);
|
||||
|
||||
/**
|
||||
* Get a registered app.
|
||||
* Only used for apps finding other apps.
|
||||
*
|
||||
* @param app non-null
|
||||
* @param name non-null
|
||||
* @return client app or null
|
||||
*/
|
||||
public ClientApp getRegisteredApp(String name);
|
||||
}
|
25
core/java/src/net/i2p/app/ClientAppState.java
Normal file
25
core/java/src/net/i2p/app/ClientAppState.java
Normal file
@ -0,0 +1,25 @@
|
||||
package net.i2p.app;
|
||||
|
||||
/**
|
||||
* Status of a client application.
|
||||
* ClientAppManager.notify() must be called on all state transitions except
|
||||
* from UNINITIALIZED to INITIALIZED.
|
||||
*
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public enum ClientAppState {
|
||||
/** initial value */
|
||||
UNINITIALIZED,
|
||||
/** after constructor is complete */
|
||||
INITIALIZED,
|
||||
STARTING,
|
||||
START_FAILED,
|
||||
RUNNING,
|
||||
STOPPING,
|
||||
/** stopped normally */
|
||||
STOPPED,
|
||||
/** stopped abnormally */
|
||||
CRASHED,
|
||||
/** forked as a new process, status unknown from now on */
|
||||
FORKED
|
||||
}
|
18
core/java/src/net/i2p/app/package.html
Normal file
18
core/java/src/net/i2p/app/package.html
Normal file
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Interfaces for classes to be started and stopped via clients.config.
|
||||
Classes implementing the ClientApp interface will be controlled with
|
||||
the that interface instead of being started with main().
|
||||
</p>
|
||||
<p>
|
||||
The benefits for clients using this interface:
|
||||
<ul>
|
||||
<li>Get the current context via the constructor
|
||||
<li>Complete life cycle management by the router
|
||||
<li>Avoid the need for static references
|
||||
<li>Ability to find other clients without using static references
|
||||
</ul>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
@ -361,12 +361,21 @@ public class DataHelper {
|
||||
throw new RuntimeException("IO error writing to memory?! " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pretty print the mapping, unsorted
|
||||
* (unless the options param is an OrderedProperties)
|
||||
*/
|
||||
public static String toString(Properties options) {
|
||||
return toString((Map) options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretty print the mapping, unsorted
|
||||
* (unless the options param is an OrderedProperties)
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public static String toString(Map<?, ?> options) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (options != null) {
|
||||
for (Map.Entry entry : options.entrySet()) {
|
||||
@ -502,7 +511,7 @@ public class DataHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex with leading zeros.
|
||||
* Lower-case hex with leading zeros.
|
||||
* Use toHexString(byte[]) to not get leading zeros
|
||||
* @param buf may be null (returns "")
|
||||
* @return String of length 2*buf.length
|
||||
@ -516,7 +525,7 @@ public class DataHelper {
|
||||
private static final byte[] EMPTY_BUFFER = "".getBytes();
|
||||
|
||||
/**
|
||||
* Hex with leading zeros.
|
||||
* Lower-case hex with leading zeros.
|
||||
* Use toHexString(byte[]) to not get leading zeros
|
||||
* @param buf may be null
|
||||
* @param len number of bytes. If greater than buf.length, additional zeros will be prepended
|
||||
@ -546,7 +555,7 @@ public class DataHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex without leading zeros.
|
||||
* Lower-case hex without leading zeros.
|
||||
* Use toString(byte[] to get leading zeros
|
||||
* @param data may be null (returns "00")
|
||||
*/
|
||||
|
@ -25,6 +25,15 @@ import net.i2p.I2PAppContext;
|
||||
*/
|
||||
public abstract class Addresses {
|
||||
|
||||
/**
|
||||
* Do we have any non-loop, non-wildcard IPv4 address at all?
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public static boolean isConnected() {
|
||||
// not as good as using a Java DBus implementation to talk to NetworkManager...
|
||||
return !getAddresses(true, false, false).isEmpty();
|
||||
}
|
||||
|
||||
/** @return the first non-local address it finds, or null */
|
||||
public static String getAnyAddress() {
|
||||
SortedSet<String> a = getAddresses();
|
||||
@ -51,13 +60,28 @@ public abstract class Addresses {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a sorted array of all addresses
|
||||
* @return a sorted set of all addresses including wildcard
|
||||
* @param includeLocal whether to include local
|
||||
* @param includeIPv6 whether to include IPV6
|
||||
* @return an array of all addresses
|
||||
* @since 0.8.3
|
||||
*/
|
||||
public static SortedSet<String> getAddresses(boolean includeLocal, boolean includeIPv6) {
|
||||
return getAddresses(includeLocal, includeLocal, includeIPv6);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a sorted set of all addresses
|
||||
* @param includeSiteLocal whether to include private like 192.168.x.x
|
||||
* @param includeLoopAndWildcard whether to include 127.x.x.x and 0.0.0.0
|
||||
* @param includeIPv6 whether to include IPV6
|
||||
* @param includeWildCard whether to include 0.0.0.0 and/or 0:0:0:0:0:0 (includeLocal must be true)
|
||||
* @return an array of all addresses
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public static SortedSet<String> getAddresses(boolean includeSiteLocal,
|
||||
boolean includeLoopbackAndWildcard,
|
||||
boolean includeIPv6) {
|
||||
boolean haveIPv4 = false;
|
||||
boolean haveIPv6 = false;
|
||||
SortedSet<String> rv = new TreeSet();
|
||||
@ -70,7 +94,8 @@ public abstract class Addresses {
|
||||
haveIPv4 = true;
|
||||
else
|
||||
haveIPv6 = true;
|
||||
if (shouldInclude(allMyIps[i], includeLocal, includeIPv6))
|
||||
if (shouldInclude(allMyIps[i], includeSiteLocal,
|
||||
includeLoopbackAndWildcard, includeIPv6))
|
||||
rv.add(allMyIps[i].getHostAddress());
|
||||
}
|
||||
}
|
||||
@ -87,34 +112,39 @@ public abstract class Addresses {
|
||||
haveIPv4 = true;
|
||||
else
|
||||
haveIPv6 = true;
|
||||
if (shouldInclude(addr, includeLocal, includeIPv6))
|
||||
if (shouldInclude(addr, includeSiteLocal,
|
||||
includeLoopbackAndWildcard, includeIPv6))
|
||||
rv.add(addr.getHostAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {}
|
||||
|
||||
if (includeLocal && haveIPv4)
|
||||
rv.add("0.0.0.0");
|
||||
if (includeLocal && includeIPv6 && haveIPv6)
|
||||
rv.add("0:0:0:0:0:0:0:0"); // we could do "::" but all the other ones are probably in long form
|
||||
if (includeLoopbackAndWildcard) {
|
||||
if (haveIPv4)
|
||||
rv.add("0.0.0.0");
|
||||
if (includeIPv6 && haveIPv6)
|
||||
rv.add("0:0:0:0:0:0:0:0"); // we could do "::" but all the other ones are probably in long form
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
private static boolean shouldInclude(InetAddress ia, boolean includeLocal, boolean includeIPv6) {
|
||||
private static boolean shouldInclude(InetAddress ia, boolean includeSiteLocal,
|
||||
boolean includeLoopbackAndWildcard, boolean includeIPv6) {
|
||||
return
|
||||
(!ia.isLinkLocalAddress()) &&
|
||||
(!ia.isLinkLocalAddress()) && // 169.254.x.x
|
||||
(!ia.isMulticastAddress()) &&
|
||||
(includeLocal ||
|
||||
(includeLoopbackAndWildcard ||
|
||||
((!ia.isAnyLocalAddress()) &&
|
||||
(!ia.isLoopbackAddress()) &&
|
||||
(!ia.isSiteLocalAddress()))) &&
|
||||
(!ia.isLoopbackAddress()))) &&
|
||||
(includeSiteLocal ||
|
||||
!ia.isSiteLocalAddress()) &&
|
||||
// Hamachi 5/8 allocated to RIPE (30 November 2010)
|
||||
// Removed from TransportImpl.isPubliclyRoutable()
|
||||
// Check moved to here, for now, but will eventually need to
|
||||
// remove it from here also.
|
||||
(includeLocal ||
|
||||
(!ia.getHostAddress().startsWith("5."))) &&
|
||||
//(includeLocal ||
|
||||
//(!ia.getHostAddress().startsWith("5."))) &&
|
||||
(includeIPv6 ||
|
||||
(ia instanceof Inet4Address));
|
||||
}
|
||||
@ -247,13 +277,18 @@ public abstract class Addresses {
|
||||
* Print out the local addresses
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
System.err.println("External Addresses:");
|
||||
Set<String> a = getAddresses(false, false);
|
||||
System.err.println("External IPv4 Addresses:");
|
||||
Set<String> a = getAddresses(false, false, false);
|
||||
for (String s : a)
|
||||
System.err.println(s);
|
||||
System.err.println("All addresses:");
|
||||
a = getAddresses(true, true);
|
||||
System.err.println("\nExternal and Local IPv4 Addresses:");
|
||||
a = getAddresses(true, false, false);
|
||||
for (String s : a)
|
||||
System.err.println(s);
|
||||
System.err.println("\nAll addresses:");
|
||||
a = getAddresses(true, true, true);
|
||||
for (String s : a)
|
||||
System.err.println(s);
|
||||
System.err.println("\nIs connected? " + isConnected());
|
||||
}
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ public class NativeBigInteger extends BigInteger {
|
||||
/**
|
||||
* <p>Compare the BigInteger.modPow vs the NativeBigInteger.modPow of some
|
||||
* really big (2Kbit) numbers 100 different times and benchmark the
|
||||
* performance (or shit a brick if they don't match). </p>
|
||||
* performance.</p>
|
||||
*
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
|
200
core/java/src/net/i2p/util/PasswordManager.java
Normal file
200
core/java/src/net/i2p/util/PasswordManager.java
Normal file
@ -0,0 +1,200 @@
|
||||
package net.i2p.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.SessionKey;
|
||||
|
||||
/**
|
||||
* Manage both plaintext and salted/hashed password storage in
|
||||
* router.config.
|
||||
*
|
||||
* There's no state here, so instantiate at will.
|
||||
*
|
||||
* @since 0.9.4
|
||||
*/
|
||||
public class PasswordManager {
|
||||
private final I2PAppContext _context;
|
||||
|
||||
protected static final int SALT_LENGTH = 16;
|
||||
/** 48 */
|
||||
protected static final int SHASH_LENGTH = SALT_LENGTH + SessionKey.KEYSIZE_BYTES;
|
||||
|
||||
/** stored as plain text */
|
||||
protected static final String PROP_PW = ".password";
|
||||
/** stored obfuscated as b64 of the UTF-8 bytes */
|
||||
protected static final String PROP_B64 = ".b64";
|
||||
/** stored as the hex of the MD5 hash of the ISO-8859-1 bytes. Compatible with Jetty. */
|
||||
protected static final String PROP_MD5 = ".md5";
|
||||
/** stored as a Unix crypt string */
|
||||
protected static final String PROP_CRYPT = ".crypt";
|
||||
/** stored as the b64 of the 16 byte salt + the 32 byte hash of the UTF-8 bytes */
|
||||
protected static final String PROP_SHASH = ".shash";
|
||||
|
||||
public PasswordManager(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks both plaintext and hash
|
||||
*
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @param pw plain text, already trimmed
|
||||
* @return if pw verified
|
||||
*/
|
||||
public boolean check(String realm, String user, String pw) {
|
||||
return checkPlain(realm, user, pw) ||
|
||||
checkB64(realm, user, pw) ||
|
||||
checkHash(realm, user, pw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @param pw plain text, already trimmed
|
||||
* @return if pw verified
|
||||
*/
|
||||
public boolean checkPlain(String realm, String user, String pw) {
|
||||
String pfx = realm;
|
||||
if (user != null && user.length() > 0)
|
||||
pfx += '.' + user;
|
||||
return pw.equals(_context.getProperty(pfx + PROP_PW));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @param pw plain text, already trimmed
|
||||
* @return if pw verified
|
||||
*/
|
||||
public boolean checkB64(String realm, String user, String pw) {
|
||||
String pfx = realm;
|
||||
if (user != null && user.length() > 0)
|
||||
pfx += '.' + user;
|
||||
String b64 = _context.getProperty(pfx + PROP_B64);
|
||||
if (b64 == null)
|
||||
return false;
|
||||
return b64.equals(Base64.encode(DataHelper.getUTF8(pw)));
|
||||
}
|
||||
|
||||
/**
|
||||
* With random salt
|
||||
*
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @param pw plain text, already trimmed
|
||||
* @return if pw verified
|
||||
*/
|
||||
public boolean checkHash(String realm, String user, String pw) {
|
||||
String pfx = realm;
|
||||
if (user != null && user.length() > 0)
|
||||
pfx += '.' + user;
|
||||
String shash = _context.getProperty(pfx + PROP_SHASH);
|
||||
if (shash == null)
|
||||
return false;
|
||||
byte[] shashBytes = Base64.decode(shash);
|
||||
if (shashBytes == null || shashBytes.length != SHASH_LENGTH)
|
||||
return false;
|
||||
byte[] salt = new byte[SALT_LENGTH];
|
||||
byte[] hash = new byte[SessionKey.KEYSIZE_BYTES];
|
||||
System.arraycopy(shashBytes, 0, salt, 0, SALT_LENGTH);
|
||||
System.arraycopy(shashBytes, SALT_LENGTH, hash, 0, SessionKey.KEYSIZE_BYTES);
|
||||
byte[] pwHash = _context.keyGenerator().generateSessionKey(salt, DataHelper.getUTF8(pw)).getData();
|
||||
return DataHelper.eq(hash, pwHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Either plain or b64
|
||||
*
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @return the pw or null
|
||||
*/
|
||||
public String get(String realm, String user) {
|
||||
String rv = getPlain(realm, user);
|
||||
if (rv != null)
|
||||
return rv;
|
||||
return getB64(realm, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @return the pw or null
|
||||
*/
|
||||
public String getPlain(String realm, String user) {
|
||||
String pfx = realm;
|
||||
if (user != null && user.length() > 0)
|
||||
pfx += '.' + user;
|
||||
return _context.getProperty(pfx + PROP_PW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param realm e.g. i2cp, routerconsole, etc.
|
||||
* @param user null or "" for no user, already trimmed
|
||||
* @return the decoded pw or null
|
||||
*/
|
||||
public String getB64(String realm, String user) {
|
||||
String pfx = realm;
|
||||
if (user != null && user.length() > 0)
|
||||
pfx += '.' + user;
|
||||
String b64 = _context.getProperty(pfx + PROP_B64);
|
||||
if (b64 == null)
|
||||
return null;
|
||||
return Base64.decodeToString(b64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Straight MD5, no salt
|
||||
* Will return the MD5 sum of "user:subrealm:pw", compatible with Jetty
|
||||
* and RFC 2617.
|
||||
*
|
||||
* @param subrealm to be used in creating the checksum
|
||||
* @param user non-null, non-empty, already trimmed
|
||||
* @param pw non-null, plain text, already trimmed
|
||||
* @return lower-case hex with leading zeros, 32 chars, or null on error
|
||||
*/
|
||||
public static String md5Hex(String subrealm, String user, String pw) {
|
||||
String fullpw = user + ':' + subrealm + ':' + pw;
|
||||
return md5Hex(fullpw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Straight MD5, no salt
|
||||
* Will return the MD5 sum of the data, compatible with Jetty
|
||||
* and RFC 2617.
|
||||
*
|
||||
* @param fullpw non-null, plain text, already trimmed
|
||||
* @return lower-case hex with leading zeros, 32 chars, or null on error
|
||||
*/
|
||||
public static String md5Hex(String fullpw) {
|
||||
try {
|
||||
byte[] data = fullpw.getBytes("ISO-8859-1");
|
||||
byte[] sum = md5Sum(data);
|
||||
if (sum != null)
|
||||
// adds leading zeros if necessary
|
||||
return DataHelper.toString(sum);
|
||||
} catch (UnsupportedEncodingException uee) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard MD5 checksum
|
||||
*
|
||||
* @param data non-null
|
||||
* @return 16 bytes, or null on error
|
||||
*/
|
||||
public static byte[] md5Sum(byte[] data) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(data);
|
||||
return md.digest();
|
||||
} catch (NoSuchAlgorithmException nsae) {}
|
||||
return null;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user