I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 635535aa authored by jrandom's avatar jrandom Committed by zzz
Browse files

implement keyfile persistence (storing name=privKeyDataBase64\n for each name)

filename specified on the command line: SAMBridge [keyfile [listenHost] listenPortNum [ name=val]*]
parent 25314fd9
No related branches found
No related tags found
No related merge requests found
...@@ -9,6 +9,11 @@ package net.i2p.sam; ...@@ -9,6 +9,11 @@ package net.i2p.sam;
*/ */
import java.io.IOException; import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
...@@ -16,6 +21,7 @@ import java.util.Properties; ...@@ -16,6 +21,7 @@ import java.util.Properties;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
...@@ -24,6 +30,7 @@ import net.i2p.data.SigningPrivateKey; ...@@ -24,6 +30,7 @@ import net.i2p.data.SigningPrivateKey;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.I2PAppContext;
/** /**
* SAM bridge implementation. * SAM bridge implementation.
...@@ -31,10 +38,14 @@ import net.i2p.util.Log; ...@@ -31,10 +38,14 @@ import net.i2p.util.Log;
* @author human * @author human
*/ */
public class SAMBridge implements Runnable { public class SAMBridge implements Runnable {
private final static Log _log = new Log(SAMBridge.class); private final static Log _log = new Log(SAMBridge.class);
private ServerSocket serverSocket; private ServerSocket serverSocket;
private Properties i2cpProps; private Properties i2cpProps;
/**
* filename in which the name to private key mapping should
* be stored (and loaded from)
*/
private String persistFilename;
/** /**
* app designated destination name to the base64 of the I2P formatted * app designated destination name to the base64 of the I2P formatted
* destination keys (Destination+PrivateKey+SigningPrivateKey) * destination keys (Destination+PrivateKey+SigningPrivateKey)
...@@ -43,7 +54,8 @@ public class SAMBridge implements Runnable { ...@@ -43,7 +54,8 @@ public class SAMBridge implements Runnable {
private boolean acceptConnections = true; private boolean acceptConnections = true;
private final static int SAM_LISTENPORT = 7656; private static final int SAM_LISTENPORT = 7656;
public static final String DEFAULT_SAM_KEYFILE = "sam.keys";
private SAMBridge() {} private SAMBridge() {}
...@@ -53,8 +65,11 @@ public class SAMBridge implements Runnable { ...@@ -53,8 +65,11 @@ public class SAMBridge implements Runnable {
* @param listenHost hostname to listen for SAM connections on ("0.0.0.0" for all) * @param listenHost hostname to listen for SAM connections on ("0.0.0.0" for all)
* @param listenPort port number to listen for SAM connections on * @param listenPort port number to listen for SAM connections on
* @param i2cpProps set of I2CP properties for finding and communicating with the router * @param i2cpProps set of I2CP properties for finding and communicating with the router
* @param persistFile location to store/load named keys to/from
*/ */
public SAMBridge(String listenHost, int listenPort, Properties i2cpProps) { public SAMBridge(String listenHost, int listenPort, Properties i2cpProps, String persistFile) {
persistFilename = persistFile;
loadKeys();
try { try {
if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) { if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) {
serverSocket = new ServerSocket(listenPort, 0, InetAddress.getByName(listenHost)); serverSocket = new ServerSocket(listenPort, 0, InetAddress.getByName(listenHost));
...@@ -114,6 +129,57 @@ public class SAMBridge implements Runnable { ...@@ -114,6 +129,57 @@ public class SAMBridge implements Runnable {
*/ */
public void addKeystream(String name, String stream) { public void addKeystream(String name, String stream) {
nameToPrivKeys.put(name, stream); nameToPrivKeys.put(name, stream);
storeKeys();
}
/**
* Load up the keys from the persistFilename
*
*/
private synchronized void loadKeys() {
Map keys = new HashMap(16);
FileInputStream in = null;
try {
in = new FileInputStream(persistFilename);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ( (line = reader.readLine()) != null) {
int eq = line.indexOf('=');
String name = line.substring(0, eq);
String privKeys = line.substring(eq+1);
keys.put(name, privKeys);
}
} catch (FileNotFoundException fnfe) {
_log.warn("Key file does not exist at " + persistFilename);
} catch (IOException ioe) {
_log.error("Unable to read the keys from " + persistFilename, ioe);
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
}
nameToPrivKeys = Collections.synchronizedMap(keys);
}
/**
* Store the current keys to disk in the location specified on creation
*
*/
private synchronized void storeKeys() {
FileOutputStream out = null;
try {
out = new FileOutputStream(persistFilename);
for (Iterator iter = nameToPrivKeys.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String privKeys = (String)nameToPrivKeys.get(name);
out.write(name.getBytes());
out.write('=');
out.write(privKeys.getBytes());
out.write('\n');
}
} catch (IOException ioe) {
_log.error("Error writing out the SAM keys to " + persistFilename, ioe);
} finally {
if (out != null) try { out.close(); } catch (IOException ioe) {}
}
} }
/** /**
...@@ -125,15 +191,17 @@ public class SAMBridge implements Runnable { ...@@ -125,15 +191,17 @@ public class SAMBridge implements Runnable {
* depth, etc. * depth, etc.
*/ */
public static void main(String args[]) { public static void main(String args[]) {
String keyfile = DEFAULT_SAM_KEYFILE;
int port = SAM_LISTENPORT; int port = SAM_LISTENPORT;
String host = "0.0.0.0"; String host = "0.0.0.0";
Properties opts = null; Properties opts = null;
if (args.length > 0) { if (args.length > 0) {
int portIndex = 0; keyfile = args[0];
int portIndex = 1;
try { try {
port = Integer.parseInt(args[portIndex]); port = Integer.parseInt(args[portIndex]);
} catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
host = args[0]; host = args[1];
portIndex++; portIndex++;
try { try {
port = Integer.parseInt(args[portIndex]); port = Integer.parseInt(args[portIndex]);
...@@ -144,7 +212,7 @@ public class SAMBridge implements Runnable { ...@@ -144,7 +212,7 @@ public class SAMBridge implements Runnable {
} }
opts = parseOptions(args, portIndex+1); opts = parseOptions(args, portIndex+1);
} }
SAMBridge bridge = new SAMBridge(host, port, opts); SAMBridge bridge = new SAMBridge(host, port, opts, keyfile);
I2PThread t = new I2PThread(bridge, "SAMListener"); I2PThread t = new I2PThread(bridge, "SAMListener");
t.start(); t.start();
} }
...@@ -167,7 +235,8 @@ public class SAMBridge implements Runnable { ...@@ -167,7 +235,8 @@ public class SAMBridge implements Runnable {
} }
private static void usage() { private static void usage() {
System.err.println("Usage: SAMBridge [listenHost listenPortNum[ name=val]*]"); System.err.println("Usage: SAMBridge [keyfile [listenHost] listenPortNum[ name=val]*]");
System.err.println(" keyfile: location to persist private keys (default sam.keys)");
System.err.println(" listenHost: interface to listen on (0.0.0.0 for all interfaces)"); System.err.println(" listenHost: interface to listen on (0.0.0.0 for all interfaces)");
System.err.println(" listenPort: port to listen for SAM connections on (default 7656)"); System.err.println(" listenPort: port to listen for SAM connections on (default 7656)");
System.err.println(" name=val: options to pass when connecting via I2CP, such as "); System.err.println(" name=val: options to pass when connecting via I2CP, such as ");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment