use of net.i2p.util.PasswordManager in project i2p.i2p by i2p.
the class SAMHandlerFactory method createSAMHandler.
/**
* Return the right SAM handler depending on the protocol version
* required by the client.
*
* @param s Socket attached to SAM client
* @param i2cpProps config options for our i2cp connection
* @throws SAMException if the connection handshake (HELLO message) was malformed
* @return A SAM protocol handler, or null if the client closed before the handshake
*/
public static SAMHandler createSAMHandler(SocketChannel s, Properties i2cpProps, SAMBridge parent) throws SAMException {
String line;
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMHandlerFactory.class);
try {
Socket sock = s.socket();
sock.setKeepAlive(true);
StringBuilder buf = new StringBuilder(128);
ReadLine.readLine(sock, buf, HELLO_TIMEOUT);
sock.setSoTimeout(0);
line = buf.toString();
} catch (SocketTimeoutException e) {
throw new SAMException("Timeout waiting for HELLO VERSION", e);
} catch (IOException e) {
throw new SAMException("Error reading from socket", e);
} catch (RuntimeException e) {
throw new SAMException("Unexpected error", e);
}
if (log.shouldDebug())
log.debug("New message received: [" + line + ']');
// Message format: HELLO VERSION [MIN=v1] [MAX=v2]
Properties props = SAMUtils.parseParams(line);
if (!"HELLO".equals(props.remove(SAMUtils.COMMAND)) || !"VERSION".equals(props.remove(SAMUtils.OPCODE))) {
throw new SAMException("Must start with HELLO VERSION");
}
String minVer = props.getProperty("MIN");
if (minVer == null) {
// throw new SAMException("Missing MIN parameter in HELLO VERSION message");
// MIN optional as of 0.9.14
minVer = "1";
}
String maxVer = props.getProperty("MAX");
if (maxVer == null) {
// throw new SAMException("Missing MAX parameter in HELLO VERSION message");
// MAX optional as of 0.9.14
maxVer = "99.99";
}
String ver = chooseBestVersion(minVer, maxVer);
if (ver == null) {
SAMHandler.writeString("HELLO REPLY RESULT=NOVERSION\n", s);
return null;
}
if (Boolean.parseBoolean(i2cpProps.getProperty(SAMBridge.PROP_AUTH))) {
String user = props.getProperty("USER");
String pw = props.getProperty("PASSWORD");
if (user == null || pw == null) {
if (user == null)
log.logAlways(Log.WARN, "SAM authentication failed");
else
log.logAlways(Log.WARN, "SAM authentication failed, user: " + user);
throw new SAMException("USER and PASSWORD required");
}
String savedPW = i2cpProps.getProperty(SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX);
if (savedPW == null) {
log.logAlways(Log.WARN, "SAM authentication failed, user: " + user);
throw new SAMException("Authorization failed");
}
PasswordManager pm = new PasswordManager(I2PAppContext.getGlobalContext());
if (!pm.checkHash(savedPW, pw)) {
log.logAlways(Log.WARN, "SAM authentication failed, user: " + user);
throw new SAMException("Authorization failed");
}
}
// Let's answer positively
if (!SAMHandler.writeString("HELLO REPLY RESULT=OK VERSION=" + ver + "\n", s))
throw new SAMException("Error writing to socket");
// ...and instantiate the right SAM handler
int verMajor = getMajor(ver);
int verMinor = getMinor(ver);
SAMHandler handler;
try {
switch(verMajor) {
case 1:
handler = new SAMv1Handler(s, verMajor, verMinor, i2cpProps, parent);
break;
case 2:
handler = new SAMv2Handler(s, verMajor, verMinor, i2cpProps, parent);
break;
case 3:
handler = new SAMv3Handler(s, verMajor, verMinor, i2cpProps, parent);
break;
default:
log.error("BUG! Trying to initialize the wrong SAM version!");
throw new SAMException("BUG! (in handler instantiation)");
}
} catch (IOException e) {
log.error("Error creating the handler for version " + verMajor, e);
throw new SAMException("IOException caught during SAM handler instantiation");
}
return handler;
}
use of net.i2p.util.PasswordManager in project i2p.i2p by i2p.
the class SAMv3Handler method execAuthMessage.
/**
* @since 0.9.24
*/
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_ERROR, "USER and PASSWORD required");
String prop = SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX;
if (i2cpProps.containsKey(prop))
return writeString(AUTH_ERROR, "user " + user + " already exists");
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_ERROR, "USER required");
String prop = SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX;
if (!i2cpProps.containsKey(prop))
return writeString(AUTH_ERROR, "user " + user + " not found");
i2cpProps.remove(prop);
} else {
return writeString(AUTH_ERROR, "Unknown AUTH command");
}
try {
bridge.saveConfig();
return writeString("AUTH STATUS RESULT=OK\n");
} catch (IOException ioe) {
return writeString(AUTH_ERROR, "Config save failed: " + ioe);
}
}
use of net.i2p.util.PasswordManager in project i2p.i2p by i2p.
the class ClientMessageEventListener method checkAuth.
/**
* Side effect - sets _authorized.
* Side effect - disconnects session if not authorized.
*
* @param props contains i2cp.username and i2cp.password, may be null
* @return success
* @since 0.9.11
*/
private boolean checkAuth(Properties props) {
if (_authorized)
return true;
if (_enforceAuth && _context.getBooleanProperty(PROP_AUTH)) {
String user = null;
String pw = null;
if (props != null) {
user = props.getProperty("i2cp.username");
pw = props.getProperty("i2cp.password");
}
if (user == null || user.length() == 0 || pw == null || pw.length() == 0) {
_log.logAlways(Log.WARN, "I2CP authentication failed");
_runner.disconnectClient("Authorization required, specify i2cp.username and i2cp.password in options");
_authorized = false;
return false;
}
PasswordManager mgr = new PasswordManager(_context);
if (!mgr.checkHash(PROP_AUTH, user, pw)) {
_log.logAlways(Log.WARN, "I2CP authentication failed, user: " + user);
_runner.disconnectClient("Authorization failed, user = " + user);
_authorized = false;
return false;
}
if (_log.shouldLog(Log.INFO))
_log.info("I2CP auth success user: " + user);
}
_authorized = true;
return true;
}
Aggregations