forked from I2P_Developers/i2p.i2p
Add AUTH commands: ENABLE, DISABLE, ADD, REMOVE
Store changes to config file
This commit is contained in:
@@ -58,6 +58,7 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
private final int _listenPort;
|
private final int _listenPort;
|
||||||
private final Properties i2cpProps;
|
private final Properties i2cpProps;
|
||||||
private final boolean _useSSL;
|
private final boolean _useSSL;
|
||||||
|
private final File _configFile;
|
||||||
private volatile Thread _runner;
|
private volatile Thread _runner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,6 +118,7 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
if (_useSSL && !SystemVersion.isJava7())
|
if (_useSSL && !SystemVersion.isJava7())
|
||||||
throw new IllegalArgumentException("SSL requires Java 7 or higher");
|
throw new IllegalArgumentException("SSL requires Java 7 or higher");
|
||||||
persistFilename = options.keyFile;
|
persistFilename = options.keyFile;
|
||||||
|
_configFile = options.configFile;
|
||||||
nameToPrivKeys = new HashMap<String,String>(8);
|
nameToPrivKeys = new HashMap<String,String>(8);
|
||||||
_handlers = new HashSet<Handler>(8);
|
_handlers = new HashSet<Handler>(8);
|
||||||
this.i2cpProps = options.opts;
|
this.i2cpProps = options.opts;
|
||||||
@@ -140,7 +142,8 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
* @param persistFile location to store/load named keys to/from
|
* @param persistFile location to store/load named keys to/from
|
||||||
* @throws RuntimeException if a server socket can't be opened
|
* @throws RuntimeException if a server socket can't be opened
|
||||||
*/
|
*/
|
||||||
public SAMBridge(String listenHost, int listenPort, boolean isSSL, Properties i2cpProps, String persistFile) {
|
public SAMBridge(String listenHost, int listenPort, boolean isSSL, Properties i2cpProps,
|
||||||
|
String persistFile, File configFile) {
|
||||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(SAMBridge.class);
|
_log = I2PAppContext.getGlobalContext().logManager().getLog(SAMBridge.class);
|
||||||
_mgr = null;
|
_mgr = null;
|
||||||
_listenHost = listenHost;
|
_listenHost = listenHost;
|
||||||
@@ -150,6 +153,7 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
throw new IllegalArgumentException("SSL requires Java 7 or higher");
|
throw new IllegalArgumentException("SSL requires Java 7 or higher");
|
||||||
this.i2cpProps = i2cpProps;
|
this.i2cpProps = i2cpProps;
|
||||||
persistFilename = persistFile;
|
persistFilename = persistFile;
|
||||||
|
_configFile = configFile;
|
||||||
nameToPrivKeys = new HashMap<String,String>(8);
|
nameToPrivKeys = new HashMap<String,String>(8);
|
||||||
_handlers = new HashSet<Handler>(8);
|
_handlers = new HashSet<Handler>(8);
|
||||||
loadKeys();
|
loadKeys();
|
||||||
@@ -451,7 +455,8 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
try {
|
try {
|
||||||
Options options = getOptions(args);
|
Options options = getOptions(args);
|
||||||
SAMBridge bridge = new SAMBridge(options.host, options.port, options.isSSL, options.opts, options.keyFile);
|
SAMBridge bridge = new SAMBridge(options.host, options.port, options.isSSL, options.opts,
|
||||||
|
options.keyFile, options.configFile);
|
||||||
bridge.startThread();
|
bridge.startThread();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -490,10 +495,12 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
private final int port;
|
private final int port;
|
||||||
private final Properties opts;
|
private final Properties opts;
|
||||||
private final boolean isSSL;
|
private final boolean isSSL;
|
||||||
|
private final File configFile;
|
||||||
|
|
||||||
public Options(String host, int port, boolean isSSL, Properties opts, String keyFile) {
|
public Options(String host, int port, boolean isSSL, Properties opts, String keyFile, File configFile) {
|
||||||
this.host = host; this.port = port; this.opts = opts; this.keyFile = keyFile;
|
this.host = host; this.port = port; this.opts = opts; this.keyFile = keyFile;
|
||||||
this.isSSL = isSSL;
|
this.isSSL = isSSL;
|
||||||
|
this.configFile = configFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,7 +621,7 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
if (remaining > 0) {
|
if (remaining > 0) {
|
||||||
parseOptions(args, startOpts, opts);
|
parseOptions(args, startOpts, opts);
|
||||||
}
|
}
|
||||||
return new Options(host, port, isSSL, opts, keyfile);
|
return new Options(host, port, isSSL, opts, keyfile, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -742,4 +749,9 @@ public class SAMBridge implements Runnable, ClientApp {
|
|||||||
changeState(STOPPED);
|
changeState(STOPPED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9.22 */
|
||||||
|
public void saveConfig() throws IOException {
|
||||||
|
DataHelper.storeProps(i2cpProps, _configFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ import net.i2p.data.DataHelper;
|
|||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
|
import net.i2p.util.PasswordManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class able to handle a SAM version 3 client connection.
|
* Class able to handle a SAM version 3 client connection.
|
||||||
@@ -425,6 +426,8 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
} else if (domain.equals("RAW")) {
|
} else if (domain.equals("RAW")) {
|
||||||
// TODO not yet overridden, ID is ignored, most recent RAW session is used
|
// TODO not yet overridden, ID is ignored, most recent RAW session is used
|
||||||
canContinue = execRawMessage(opcode, props);
|
canContinue = execRawMessage(opcode, props);
|
||||||
|
} else if (domain.equals("AUTH")) {
|
||||||
|
canContinue = execAuthMessage(opcode, props);
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Unrecognized message domain: \""
|
_log.debug("Unrecognized message domain: \""
|
||||||
@@ -889,5 +892,40 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9.22 */
|
||||||
|
private boolean execAuthMessage(String opcode, Properties props) {
|
||||||
|
if (opcode.equals("ENABLE")) {
|
||||||
|
i2cpProps.setProperty(SAMBridge.PROP_AUTH, "true");
|
||||||
|
} else if (opcode.equals("DISABLE")) {
|
||||||
|
i2cpProps.setProperty(SAMBridge.PROP_AUTH, "false");
|
||||||
|
} else if (opcode.equals("ADD")) {
|
||||||
|
String user = props.getProperty("USER");
|
||||||
|
String pw = props.getProperty("PASSWORD");
|
||||||
|
if (user == null || pw == null)
|
||||||
|
return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"USER and PASSWORD required\"\n");
|
||||||
|
String prop = SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX;
|
||||||
|
if (i2cpProps.containsKey(prop))
|
||||||
|
return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"user " + user + " already exists\"\n");
|
||||||
|
PasswordManager pm = new PasswordManager(I2PAppContext.getGlobalContext());
|
||||||
|
String shash = pm.createHash(pw);
|
||||||
|
i2cpProps.setProperty(prop, shash);
|
||||||
|
} else if (opcode.equals("REMOVE")) {
|
||||||
|
String user = props.getProperty("USER");
|
||||||
|
if (user == null)
|
||||||
|
return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"USER required\"\n");
|
||||||
|
String prop = SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX;
|
||||||
|
if (!i2cpProps.containsKey(prop))
|
||||||
|
return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"user " + user + " not found\"\n");
|
||||||
|
i2cpProps.remove(prop);
|
||||||
|
} else {
|
||||||
|
return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown AUTH command\"\n");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
bridge.saveConfig();
|
||||||
|
return writeString("AUTH STATUS RESULT=OK\n");
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"Config save failed: " + ioe + "\"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user