From b82c1ead723ca6086699c7babeb111efa8ead090 Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 26 Jun 2015 21:32:24 +0000 Subject: [PATCH] Add AUTH commands: ENABLE, DISABLE, ADD, REMOVE Store changes to config file --- apps/sam/java/src/net/i2p/sam/SAMBridge.java | 20 ++++++++-- .../java/src/net/i2p/sam/SAMv3Handler.java | 38 +++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/apps/sam/java/src/net/i2p/sam/SAMBridge.java b/apps/sam/java/src/net/i2p/sam/SAMBridge.java index 4c67d1412..4b9a3293c 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMBridge.java +++ b/apps/sam/java/src/net/i2p/sam/SAMBridge.java @@ -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(8); _handlers = new HashSet(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(8); _handlers = new HashSet(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); + } } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index 445f8d10a..f623798dc 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -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"); + } + } }