Add AUTH commands: ENABLE, DISABLE, ADD, REMOVE

Store changes to config file
This commit is contained in:
zzz
2015-06-26 21:32:24 +00:00
parent 33672e6a86
commit b82c1ead72
2 changed files with 54 additions and 4 deletions

View File

@@ -58,6 +58,7 @@ public class SAMBridge implements Runnable, ClientApp {
private final int _listenPort;
private final Properties i2cpProps;
private final boolean _useSSL;
private final File _configFile;
private volatile Thread _runner;
/**
@@ -117,6 +118,7 @@ public class SAMBridge implements Runnable, ClientApp {
if (_useSSL && !SystemVersion.isJava7())
throw new IllegalArgumentException("SSL requires Java 7 or higher");
persistFilename = options.keyFile;
_configFile = options.configFile;
nameToPrivKeys = new HashMap<String,String>(8);
_handlers = new HashSet<Handler>(8);
this.i2cpProps = options.opts;
@@ -140,7 +142,8 @@ public class SAMBridge implements Runnable, ClientApp {
* @param persistFile location to store/load named keys to/from
* @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);
_mgr = null;
_listenHost = listenHost;
@@ -150,6 +153,7 @@ public class SAMBridge implements Runnable, ClientApp {
throw new IllegalArgumentException("SSL requires Java 7 or higher");
this.i2cpProps = i2cpProps;
persistFilename = persistFile;
_configFile = configFile;
nameToPrivKeys = new HashMap<String,String>(8);
_handlers = new HashSet<Handler>(8);
loadKeys();
@@ -451,7 +455,8 @@ public class SAMBridge implements Runnable, ClientApp {
public static void main(String args[]) {
try {
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();
} catch (RuntimeException e) {
e.printStackTrace();
@@ -490,10 +495,12 @@ public class SAMBridge implements Runnable, ClientApp {
private final int port;
private final Properties opts;
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.isSSL = isSSL;
this.configFile = configFile;
}
}
@@ -614,7 +621,7 @@ public class SAMBridge implements Runnable, ClientApp {
if (remaining > 0) {
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);
}
}
/** @since 0.9.22 */
public void saveConfig() throws IOException {
DataHelper.storeProps(i2cpProps, _configFile);
}
}

View File

@@ -36,6 +36,7 @@ import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.Log;
import net.i2p.util.I2PAppThread;
import net.i2p.util.PasswordManager;
/**
* Class able to handle a SAM version 3 client connection.
@@ -425,6 +426,8 @@ class SAMv3Handler extends SAMv1Handler
} else if (domain.equals("RAW")) {
// TODO not yet overridden, ID is ignored, most recent RAW session is used
canContinue = execRawMessage(opcode, props);
} else if (domain.equals("AUTH")) {
canContinue = execAuthMessage(opcode, props);
} else {
if (_log.shouldLog(Log.DEBUG))
_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");
}
}
}