forked from I2P_Developers/i2p.i2p
auth and ssl support
This commit is contained in:
@ -6,8 +6,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
|
|
||||||
import gnu.getopt.Getopt;
|
import gnu.getopt.Getopt;
|
||||||
|
|
||||||
@ -15,6 +17,7 @@ import net.i2p.I2PAppContext;
|
|||||||
import net.i2p.data.Base32;
|
import net.i2p.data.Base32;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
|
import net.i2p.util.I2PSSLSocketFactory;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.VersionComparator;
|
import net.i2p.util.VersionComparator;
|
||||||
|
|
||||||
@ -38,19 +41,22 @@ public class SAMStreamSend {
|
|||||||
//private boolean _dead;
|
//private boolean _dead;
|
||||||
/** Connection id (Integer) to peer (Flooder) */
|
/** Connection id (Integer) to peer (Flooder) */
|
||||||
private final Map<String, Sender> _remotePeers;
|
private final Map<String, Sender> _remotePeers;
|
||||||
|
private static I2PSSLSocketFactory _sslSocketFactory;
|
||||||
|
|
||||||
private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4;
|
private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4;
|
||||||
private static final String USAGE = "Usage: SAMStreamSend [-s] [-m mode] [-v version] [-b samHost] [-p samPort] peerDestFile dataDir\n" +
|
private static final String USAGE = "Usage: SAMStreamSend [-s] [-m mode] [-v version] [-b samHost] [-p samPort] [-u user] [-w password] peerDestFile dataDir\n" +
|
||||||
" modes: stream: 0; datagram: 1; v1datagram: 2; raw: 3; v1raw: 4\n" +
|
" modes: stream: 0; datagram: 1; v1datagram: 2; raw: 3; v1raw: 4\n" +
|
||||||
" -s: use SSL";
|
" -s: use SSL";
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
Getopt g = new Getopt("SAM", args, "sb:m:p:v:");
|
Getopt g = new Getopt("SAM", args, "sb:m:p:u:v:w:");
|
||||||
boolean isSSL = false;
|
boolean isSSL = false;
|
||||||
int mode = STREAM;
|
int mode = STREAM;
|
||||||
String version = "1.0";
|
String version = "1.0";
|
||||||
String host = "127.0.0.1";
|
String host = "127.0.0.1";
|
||||||
String port = "7656";
|
String port = "7656";
|
||||||
|
String user = null;
|
||||||
|
String password = null;
|
||||||
int c;
|
int c;
|
||||||
while ((c = g.getopt()) != -1) {
|
while ((c = g.getopt()) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -78,6 +84,14 @@ public class SAMStreamSend {
|
|||||||
port = g.getOptarg();
|
port = g.getOptarg();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
user = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
password = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
case ':':
|
case ':':
|
||||||
@ -92,10 +106,19 @@ public class SAMStreamSend {
|
|||||||
System.err.println(USAGE);
|
System.err.println(USAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ((user == null && password != null) ||
|
||||||
|
(user != null && password == null)) {
|
||||||
|
System.err.println("both user and password or neither");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user != null && password != null && VersionComparator.comp(version, "3.2") < 0) {
|
||||||
|
System.err.println("user/password require 3.2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||||
SAMStreamSend sender = new SAMStreamSend(ctx, host, port,
|
SAMStreamSend sender = new SAMStreamSend(ctx, host, port,
|
||||||
args[startArgs], args[startArgs + 1]);
|
args[startArgs], args[startArgs + 1]);
|
||||||
sender.startup(version, isSSL, mode);
|
sender.startup(version, isSSL, mode, user, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SAMStreamSend(I2PAppContext ctx, String samHost, String samPort, String destFile, String dataFile) {
|
public SAMStreamSend(I2PAppContext ctx, String samHost, String samPort, String destFile, String dataFile) {
|
||||||
@ -110,7 +133,7 @@ public class SAMStreamSend {
|
|||||||
_remotePeers = new HashMap<String, Sender>();
|
_remotePeers = new HashMap<String, Sender>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startup(String version, boolean isSSL, int mode) {
|
public void startup(String version, boolean isSSL, int mode, String user, String password) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Starting up");
|
_log.debug("Starting up");
|
||||||
try {
|
try {
|
||||||
@ -121,7 +144,7 @@ public class SAMStreamSend {
|
|||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Reader created");
|
_log.debug("Reader created");
|
||||||
OutputStream out = sock.getOutputStream();
|
OutputStream out = sock.getOutputStream();
|
||||||
String ourDest = handshake(out, version, true, eventHandler, mode);
|
String ourDest = handshake(out, version, true, eventHandler, mode, user, password);
|
||||||
if (ourDest == null)
|
if (ourDest == null)
|
||||||
throw new IOException("handshake failed");
|
throw new IOException("handshake failed");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@ -134,7 +157,7 @@ public class SAMStreamSend {
|
|||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Reader2 created");
|
_log.debug("Reader2 created");
|
||||||
out = sock2.getOutputStream();
|
out = sock2.getOutputStream();
|
||||||
String ok = handshake(out, version, false, eventHandler, mode);
|
String ok = handshake(out, version, false, eventHandler, mode, user, password);
|
||||||
if (ok == null)
|
if (ok == null)
|
||||||
throw new IOException("2nd handshake failed");
|
throw new IOException("2nd handshake failed");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@ -172,13 +195,32 @@ public class SAMStreamSend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Socket connect(boolean isSSL) throws IOException {
|
private Socket connect(boolean isSSL) throws IOException {
|
||||||
return new Socket(_samHost, Integer.parseInt(_samPort));
|
int port = Integer.parseInt(_samPort);
|
||||||
|
if (!isSSL)
|
||||||
|
return new Socket(_samHost, port);
|
||||||
|
synchronized(SAMStreamSink.class) {
|
||||||
|
if (_sslSocketFactory == null) {
|
||||||
|
try {
|
||||||
|
_sslSocketFactory = new I2PSSLSocketFactory(
|
||||||
|
_context, true, "certificates/sam");
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
throw new IOException("SSL error", gse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SSLSocket sock = (SSLSocket) _sslSocketFactory.createSocket(_samHost, port);
|
||||||
|
I2PSSLSocketFactory.verifyHostname(_context, sock, _samHost);
|
||||||
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return our b64 dest or null */
|
/** @return our b64 dest or null */
|
||||||
private String handshake(OutputStream samOut, String version, boolean isMaster, SAMEventHandler eventHandler, int mode) {
|
private String handshake(OutputStream samOut, String version, boolean isMaster,
|
||||||
|
SAMEventHandler eventHandler, int mode, String user, String password) {
|
||||||
synchronized (samOut) {
|
synchronized (samOut) {
|
||||||
try {
|
try {
|
||||||
|
if (user != null && password != null)
|
||||||
|
samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + " USER=" + user + " PASSWORD=" + password + '\n').getBytes());
|
||||||
|
else
|
||||||
samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes());
|
samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes());
|
||||||
samOut.flush();
|
samOut.flush();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
@ -6,9 +6,11 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
|
|
||||||
import gnu.getopt.Getopt;
|
import gnu.getopt.Getopt;
|
||||||
|
|
||||||
@ -16,6 +18,7 @@ import net.i2p.I2PAppContext;
|
|||||||
import net.i2p.data.Base32;
|
import net.i2p.data.Base32;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
|
import net.i2p.util.I2PSSLSocketFactory;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.VersionComparator;
|
import net.i2p.util.VersionComparator;
|
||||||
|
|
||||||
@ -41,19 +44,22 @@ public class SAMStreamSink {
|
|||||||
//private boolean _dead;
|
//private boolean _dead;
|
||||||
/** Connection id (Integer) to peer (Flooder) */
|
/** Connection id (Integer) to peer (Flooder) */
|
||||||
private final Map<String, Sink> _remotePeers;
|
private final Map<String, Sink> _remotePeers;
|
||||||
|
private static I2PSSLSocketFactory _sslSocketFactory;
|
||||||
|
|
||||||
private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4;
|
private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4;
|
||||||
private static final String USAGE = "Usage: SAMStreamSink [-s] [-m mode] [-v version] [-b samHost] [-p samPort] myDestFile sinkDir\n" +
|
private static final String USAGE = "Usage: SAMStreamSink [-s] [-m mode] [-v version] [-b samHost] [-p samPort] [-u user] [-w password] myDestFile sinkDir\n" +
|
||||||
" modes: stream: 0; datagram: 1; v1datagram: 2; raw: 3; v1raw: 4\n" +
|
" modes: stream: 0; datagram: 1; v1datagram: 2; raw: 3; v1raw: 4\n" +
|
||||||
" -s: use SSL";
|
" -s: use SSL";
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
Getopt g = new Getopt("SAM", args, "sb:m:p:v:");
|
Getopt g = new Getopt("SAM", args, "sb:m:p:u:v:w:");
|
||||||
boolean isSSL = false;
|
boolean isSSL = false;
|
||||||
int mode = STREAM;
|
int mode = STREAM;
|
||||||
String version = "1.0";
|
String version = "1.0";
|
||||||
String host = "127.0.0.1";
|
String host = "127.0.0.1";
|
||||||
String port = "7656";
|
String port = "7656";
|
||||||
|
String user = null;
|
||||||
|
String password = null;
|
||||||
int c;
|
int c;
|
||||||
while ((c = g.getopt()) != -1) {
|
while ((c = g.getopt()) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -81,6 +87,14 @@ public class SAMStreamSink {
|
|||||||
port = g.getOptarg();
|
port = g.getOptarg();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
user = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
password = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
case ':':
|
case ':':
|
||||||
@ -95,10 +109,19 @@ public class SAMStreamSink {
|
|||||||
System.err.println(USAGE);
|
System.err.println(USAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ((user == null && password != null) ||
|
||||||
|
(user != null && password == null)) {
|
||||||
|
System.err.println("both user and password or neither");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user != null && password != null && VersionComparator.comp(version, "3.2") < 0) {
|
||||||
|
System.err.println("user/password require 3.2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||||
SAMStreamSink sink = new SAMStreamSink(ctx, host, port,
|
SAMStreamSink sink = new SAMStreamSink(ctx, host, port,
|
||||||
args[startArgs], args[startArgs + 1]);
|
args[startArgs], args[startArgs + 1]);
|
||||||
sink.startup(version, isSSL, mode);
|
sink.startup(version, isSSL, mode, user, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SAMStreamSink(I2PAppContext ctx, String samHost, String samPort, String destFile, String sinkDir) {
|
public SAMStreamSink(I2PAppContext ctx, String samHost, String samPort, String destFile, String sinkDir) {
|
||||||
@ -113,7 +136,7 @@ public class SAMStreamSink {
|
|||||||
_remotePeers = new HashMap<String, Sink>();
|
_remotePeers = new HashMap<String, Sink>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startup(String version, boolean isSSL, int mode) {
|
public void startup(String version, boolean isSSL, int mode, String user, String password) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Starting up");
|
_log.debug("Starting up");
|
||||||
try {
|
try {
|
||||||
@ -124,7 +147,7 @@ public class SAMStreamSink {
|
|||||||
_reader.startReading();
|
_reader.startReading();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Reader created");
|
_log.debug("Reader created");
|
||||||
String ourDest = handshake(out, version, true, eventHandler, mode);
|
String ourDest = handshake(out, version, true, eventHandler, mode, user, password);
|
||||||
if (ourDest == null)
|
if (ourDest == null)
|
||||||
throw new IOException("handshake failed");
|
throw new IOException("handshake failed");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@ -142,7 +165,7 @@ public class SAMStreamSink {
|
|||||||
_reader2.startReading();
|
_reader2.startReading();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Reader2 created");
|
_log.debug("Reader2 created");
|
||||||
String ok = handshake(out, version, false, eventHandler, mode);
|
String ok = handshake(out, version, false, eventHandler, mode, user, password);
|
||||||
if (ok == null)
|
if (ok == null)
|
||||||
throw new IOException("2nd handshake failed");
|
throw new IOException("2nd handshake failed");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@ -350,13 +373,32 @@ public class SAMStreamSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Socket connect(boolean isSSL) throws IOException {
|
private Socket connect(boolean isSSL) throws IOException {
|
||||||
return new Socket(_samHost, Integer.parseInt(_samPort));
|
int port = Integer.parseInt(_samPort);
|
||||||
|
if (!isSSL)
|
||||||
|
return new Socket(_samHost, port);
|
||||||
|
synchronized(SAMStreamSink.class) {
|
||||||
|
if (_sslSocketFactory == null) {
|
||||||
|
try {
|
||||||
|
_sslSocketFactory = new I2PSSLSocketFactory(
|
||||||
|
_context, true, "certificates/sam");
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
throw new IOException("SSL error", gse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SSLSocket sock = (SSLSocket) _sslSocketFactory.createSocket(_samHost, port);
|
||||||
|
I2PSSLSocketFactory.verifyHostname(_context, sock, _samHost);
|
||||||
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return our b64 dest or null */
|
/** @return our b64 dest or null */
|
||||||
private String handshake(OutputStream samOut, String version, boolean isMaster, SAMEventHandler eventHandler, int mode) {
|
private String handshake(OutputStream samOut, String version, boolean isMaster,
|
||||||
|
SAMEventHandler eventHandler, int mode, String user, String password) {
|
||||||
synchronized (samOut) {
|
synchronized (samOut) {
|
||||||
try {
|
try {
|
||||||
|
if (user != null && password != null)
|
||||||
|
samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + " USER=" + user + " PASSWORD=" + password + '\n').getBytes());
|
||||||
|
else
|
||||||
samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes());
|
samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes());
|
||||||
samOut.flush();
|
samOut.flush();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
Reference in New Issue
Block a user