...
 
Commits (8)
......@@ -15,7 +15,6 @@ dependencies {
implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0'
implementation 'org.whispersystems:curve25519-java:0.5.0'
implementation 'org.briarproject:jtorctl:0.3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
......
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
import java.util.Arrays;
import java.util.List;
/**
* Static class to do bytewise structure manipulation in Java.
*/
/* XXXX There must be a better way to do most of this.
* XXXX The string logic here uses default encoding, which is stupid.
*/
final class Bytes {
/** Write the two-byte value in 's' into the byte array 'ba', starting at
* the index 'pos'. */
public static void setU16(byte[] ba, int pos, short s) {
ba[pos] = (byte)((s >> 8) & 0xff);
ba[pos+1] = (byte)((s ) & 0xff);
}
/** Write the four-byte value in 'i' into the byte array 'ba', starting at
* the index 'pos'. */
public static void setU32(byte[] ba, int pos, int i) {
ba[pos] = (byte)((i >> 24) & 0xff);
ba[pos+1] = (byte)((i >> 16) & 0xff);
ba[pos+2] = (byte)((i >> 8) & 0xff);
ba[pos+3] = (byte)((i ) & 0xff);
}
/** Return the four-byte value starting at index 'pos' within 'ba' */
public static int getU32(byte[] ba, int pos) {
return
((ba[pos ]&0xff)<<24) |
((ba[pos+1]&0xff)<<16) |
((ba[pos+2]&0xff)<< 8) |
((ba[pos+3]&0xff));
}
public static String getU32S(byte[] ba, int pos) {
return String.valueOf( (getU32(ba,pos))&0xffffffffL );
}
/** Return the two-byte value starting at index 'pos' within 'ba' */
public static int getU16(byte[] ba, int pos) {
return
((ba[pos ]&0xff)<<8) |
((ba[pos+1]&0xff));
}
/** Return the string starting at position 'pos' of ba and extending
* until a zero byte or the end of the string. */
public static String getNulTerminatedStr(byte[] ba, int pos) {
int len, maxlen = ba.length-pos;
for (len=0; len<maxlen; ++len) {
if (ba[pos+len] == 0)
break;
}
return new String(ba, pos, len);
}
/**
* Read bytes from 'ba' starting at 'pos', dividing them into strings
* along the character in 'split' and writing them into 'lst'
*/
public static void splitStr(List<String> lst, byte[] ba, int pos, byte split) {
while (pos < ba.length && ba[pos] != 0) {
int len;
for (len=0; pos+len < ba.length; ++len) {
if (ba[pos+len] == 0 || ba[pos+len] == split)
break;
}
if (len>0)
lst.add(new String(ba, pos, len));
pos += len;
if (ba[pos] == split)
++pos;
}
}
/**
* Read bytes from 'ba' starting at 'pos', dividing them into strings
* along the character in 'split' and writing them into 'lst'
*/
public static List<String> splitStr(List<String> lst, String str) {
// split string on spaces, include trailing/leading
String[] tokenArray = str.split(" ", -1);
if (lst == null) {
lst = Arrays.asList( tokenArray );
} else {
lst.addAll( Arrays.asList( tokenArray ) );
}
return lst;
}
private static final char[] NYBBLES = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
public static final String hex(byte[] ba) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < ba.length; ++i) {
int b = (ba[i]) & 0xff;
buf.append(NYBBLES[b >> 4]);
buf.append(NYBBLES[b&0x0f]);
}
return buf.toString();
}
private Bytes() {};
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
/** A single key-value pair from Tor's configuration. */
public class ConfigEntry {
public ConfigEntry(String k, String v) {
key = k;
value = v;
is_default = false;
}
public ConfigEntry(String k) {
key = k;
value = "";
is_default = true;
}
public final String key;
public final String value;
public final boolean is_default;
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
/**
* Abstract interface whose methods are invoked when Tor sends us an event.
*
* @see TorControlConnection#setEventHandler
* @see TorControlConnection#setEvents
*/
public interface EventHandler {
/**
* Invoked when a circuit's status has changed.
* Possible values for <b>status</b> are:
* <ul>
* <li>"LAUNCHED" : circuit ID assigned to new circuit</li>
* <li>"BUILT" : all hops finished, can now accept streams</li>
* <li>"EXTENDED" : one more hop has been completed</li>
* <li>"FAILED" : circuit closed (was not built)</li>
* <li>"CLOSED" : circuit closed (was built)</li>
* </ul>
*
* <b>circID</b> is the alphanumeric identifier of the affected circuit,
* and <b>path</b> is a comma-separated list of alphanumeric ServerIDs.
*/
public void circuitStatus(String status, String circID, String path);
/**
* Invoked when a stream's status has changed.
* Possible values for <b>status</b> are:
* <ul>
* <li>"NEW" : New request to connect</li>
* <li>"NEWRESOLVE" : New request to resolve an address</li>
* <li>"SENTCONNECT" : Sent a connect cell along a circuit</li>
* <li>"SENTRESOLVE" : Sent a resolve cell along a circuit</li>
* <li>"SUCCEEDED" : Received a reply; stream established</li>
* <li>"FAILED" : Stream failed and not retriable.</li>
* <li>"CLOSED" : Stream closed</li>
* <li>"DETACHED" : Detached from circuit; still retriable.</li>
* </ul>
*
* <b>streamID</b> is the alphanumeric identifier of the affected stream,
* and its <b>target</b> is specified as address:port.
*/
public void streamStatus(String status, String streamID, String target);
/**
* Invoked when the status of a connection to an OR has changed.
* Possible values for <b>status</b> are ["LAUNCHED" | "CONNECTED" | "FAILED" | "CLOSED"].
* <b>orName</b> is the alphanumeric identifier of the OR affected.
*/
public void orConnStatus(String status, String orName);
/**
* Invoked once per second. <b>read</b> and <b>written</b> are
* the number of bytes read and written, respectively, in
* the last second.
*/
public void bandwidthUsed(long read, long written);
/**
* Invoked whenever Tor learns about new ORs. The <b>orList</b> object
* contains the alphanumeric ServerIDs associated with the new ORs.
*/
public void newDescriptors(java.util.List<String> orList);
/**
* Invoked when Tor logs a message.
* <b>severity</b> is one of ["DEBUG" | "INFO" | "NOTICE" | "WARN" | "ERR"],
* and <b>msg</b> is the message string.
*/
public void message(String severity, String msg);
/**
* Invoked when an unspecified message is received.
* <type> is the message type, and <msg> is the message string.
*/
public void unrecognized(String type, String msg);
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
/**
* Implementation of EventHandler that ignores all events. Useful
* when you only want to override one method.
*/
public class NullEventHandler implements EventHandler {
public void circuitStatus(String status, String circID, String path) {}
public void streamStatus(String status, String streamID, String target) {}
public void orConnStatus(String status, String orName) {}
public void bandwidthUsed(long read, long written) {}
public void newDescriptors(java.util.List<String> orList) {}
public void message(String severity, String msg) {}
public void unrecognized(String type, String msg) {}
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* A hashed digest of a secret password (used to set control connection
* security.)
*
* For the actual hashing algorithm, see RFC2440's secret-to-key conversion.
*/
public class PasswordDigest {
private final byte[] secret;
private final String hashedKey;
/** Return a new password digest with a random secret and salt. */
public static PasswordDigest generateDigest() {
byte[] secret = new byte[20];
SecureRandom rng = new SecureRandom();
rng.nextBytes(secret);
return new PasswordDigest(secret);
}
/** Construct a new password digest with a given secret and random salt */
public PasswordDigest(byte[] secret) {
this(secret, null);
}
/** Construct a new password digest with a given secret and random salt.
* Note that the 9th byte of the specifier determines the number of hash
* iterations as in RFC2440.
*/
public PasswordDigest(byte[] secret, byte[] specifier) {
this.secret = secret.clone();
if (specifier == null) {
specifier = new byte[9];
SecureRandom rng = new SecureRandom();
rng.nextBytes(specifier);
specifier[8] = 96;
}
hashedKey = "16:"+encodeBytes(secretToKey(secret, specifier));
}
/** Return the secret used to generate this password hash.
*/
public byte[] getSecret() {
return secret.clone();
}
/** Return the hashed password in the format used by Tor. */
public String getHashedPassword() {
return hashedKey;
}
/** Parameter used by RFC2440's s2k algorithm. */
private static final int EXPBIAS = 6;
/** Implement rfc2440 s2k */
public static byte[] secretToKey(byte[] secret, byte[] specifier) {
MessageDigest d;
try {
d = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException("Can't run without sha-1.");
}
int c = (specifier[8])&0xff;
int count = (16 + (c&15)) << ((c>>4) + EXPBIAS);
byte[] tmp = new byte[8+secret.length];
System.arraycopy(specifier, 0, tmp, 0, 8);
System.arraycopy(secret, 0, tmp, 8, secret.length);
while (count > 0) {
if (count >= tmp.length) {
d.update(tmp);
count -= tmp.length;
} else {
d.update(tmp, 0, count);
count = 0;
}
}
byte[] key = new byte[20+9];
System.arraycopy(d.digest(), 0, key, 9, 20);
System.arraycopy(specifier, 0, key, 0, 9);
return key;
}
/** Return a hexadecimal encoding of a byte array. */
// XXX There must be a better way to do this in Java.
private static final String encodeBytes(byte[] ba) {
return Bytes.hex(ba);
}
}
We broke the version detection stuff in Tor 0.1.2.16 / 0.2.0.4-alpha.
Somebody should rip out the v0 control protocol stuff from here, and
it should start working again. -RD
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
/** Interface defining constants used by the Tor controller protocol.
*/
// XXXX Take documentation for these from control-spec.txt
public interface TorControlCommands {
public static final short CMD_ERROR = 0x0000;
public static final short CMD_DONE = 0x0001;
public static final short CMD_SETCONF = 0x0002;
public static final short CMD_GETCONF = 0x0003;
public static final short CMD_CONFVALUE = 0x0004;
public static final short CMD_SETEVENTS = 0x0005;
public static final short CMD_EVENT = 0x0006;
public static final short CMD_AUTH = 0x0007;
public static final short CMD_SAVECONF = 0x0008;
public static final short CMD_SIGNAL = 0x0009;
public static final short CMD_MAPADDRESS = 0x000A;
public static final short CMD_GETINFO = 0x000B;
public static final short CMD_INFOVALUE = 0x000C;
public static final short CMD_EXTENDCIRCUIT = 0x000D;
public static final short CMD_ATTACHSTREAM = 0x000E;
public static final short CMD_POSTDESCRIPTOR = 0x000F;
public static final short CMD_FRAGMENTHEADER = 0x0010;
public static final short CMD_FRAGMENT = 0x0011;
public static final short CMD_REDIRECTSTREAM = 0x0012;
public static final short CMD_CLOSESTREAM = 0x0013;
public static final short CMD_CLOSECIRCUIT = 0x0014;
public static final String[] CMD_NAMES = {
"ERROR",
"DONE",
"SETCONF",
"GETCONF",
"CONFVALUE",
"SETEVENTS",
"EVENT",
"AUTH",
"SAVECONF",
"SIGNAL",
"MAPADDRESS",
"GETINFO",
"INFOVALUE",
"EXTENDCIRCUIT",
"ATTACHSTREAM",
"POSTDESCRIPTOR",
"FRAGMENTHEADER",
"FRAGMENT",
"REDIRECTSTREAM",
"CLOSESTREAM",
"CLOSECIRCUIT",
};
public static final short EVENT_CIRCSTATUS = 0x0001;
public static final short EVENT_STREAMSTATUS = 0x0002;
public static final short EVENT_ORCONNSTATUS = 0x0003;
public static final short EVENT_BANDWIDTH = 0x0004;
public static final short EVENT_NEWDESCRIPTOR = 0x0006;
public static final short EVENT_MSG_DEBUG = 0x0007;
public static final short EVENT_MSG_INFO = 0x0008;
public static final short EVENT_MSG_NOTICE = 0x0009;
public static final short EVENT_MSG_WARN = 0x000A;
public static final short EVENT_MSG_ERROR = 0x000B;
public static final String[] EVENT_NAMES = {
"(0)",
"CIRC",
"STREAM",
"ORCONN",
"BW",
"OLDLOG",
"NEWDESC",
"DEBUG",
"INFO",
"NOTICE",
"WARN",
"ERR",
};
public static final byte CIRC_STATUS_LAUNCHED = 0x01;
public static final byte CIRC_STATUS_BUILT = 0x02;
public static final byte CIRC_STATUS_EXTENDED = 0x03;
public static final byte CIRC_STATUS_FAILED = 0x04;
public static final byte CIRC_STATUS_CLOSED = 0x05;
public static final String[] CIRC_STATUS_NAMES = {
"LAUNCHED",
"BUILT",
"EXTENDED",
"FAILED",
"CLOSED",
};
public static final byte STREAM_STATUS_SENT_CONNECT = 0x00;
public static final byte STREAM_STATUS_SENT_RESOLVE = 0x01;
public static final byte STREAM_STATUS_SUCCEEDED = 0x02;
public static final byte STREAM_STATUS_FAILED = 0x03;
public static final byte STREAM_STATUS_CLOSED = 0x04;
public static final byte STREAM_STATUS_NEW_CONNECT = 0x05;
public static final byte STREAM_STATUS_NEW_RESOLVE = 0x06;
public static final byte STREAM_STATUS_DETACHED = 0x07;
public static final String[] STREAM_STATUS_NAMES = {
"SENT_CONNECT",
"SENT_RESOLVE",
"SUCCEEDED",
"FAILED",
"CLOSED",
"NEW_CONNECT",
"NEW_RESOLVE",
"DETACHED"
};
public static final byte OR_CONN_STATUS_LAUNCHED = 0x00;
public static final byte OR_CONN_STATUS_CONNECTED = 0x01;
public static final byte OR_CONN_STATUS_FAILED = 0x02;
public static final byte OR_CONN_STATUS_CLOSED = 0x03;
public static final String[] OR_CONN_STATUS_NAMES = {
"LAUNCHED","CONNECTED","FAILED","CLOSED"
};
public static final byte SIGNAL_HUP = 0x01;
public static final byte SIGNAL_INT = 0x02;
public static final byte SIGNAL_USR1 = 0x0A;
public static final byte SIGNAL_USR2 = 0x0C;
public static final byte SIGNAL_TERM = 0x0F;
public static final String ERROR_MSGS[] = {
"Unspecified error",
"Internal error",
"Unrecognized message type",
"Syntax error",
"Unrecognized configuration key",
"Invalid configuration value",
"Unrecognized byte code",
"Unauthorized",
"Failed authentication attempt",
"Resource exhausted",
"No such stream",
"No such circuit",
"No such OR",
};
public static final String HS_ADDRESS = "onionAddress";
public static final String HS_PRIVKEY = "onionPrivKey";
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
import java.io.IOException;
/**
* An exception raised when Tor tells us about an error.
*/
public class TorControlError extends IOException {
static final long serialVersionUID = 3;
private final int errorType;
public TorControlError(int type, String s) {
super(s);
errorType = type;
}
public TorControlError(String s) {
this(-1, s);
}
public int getErrorType() {
return errorType;
}
public String getErrorMsg() {
try {
if (errorType == -1)
return null;
return TorControlCommands.ERROR_MSGS[errorType];
} catch (ArrayIndexOutOfBoundsException ex) {
return "Unrecongized error #"+errorType;
}
}
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control;
import java.io.IOException;
/**
* An exception raised when Tor behaves in an unexpected way.
*/
public class TorControlSyntaxError extends IOException {
static final long serialVersionUID = 3;
public TorControlSyntaxError(String s) { super(s); }
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control.examples;
import java.io.PrintWriter;
import java.util.Iterator;
import net.freehaven.tor.control.EventHandler;
public class DebuggingEventHandler implements EventHandler {
private final PrintWriter out;
public DebuggingEventHandler(PrintWriter p) {
out = p;
}
public void circuitStatus(String status, String circID, String path) {
out.println("Circuit "+circID+" is now "+status+" (path="+path+")");
}
public void streamStatus(String status, String streamID, String target) {
out.println("Stream "+streamID+" is now "+status+" (target="+target+")");
}
public void orConnStatus(String status, String orName) {
out.println("OR connection to "+orName+" is now "+status);
}
public void bandwidthUsed(long read, long written) {
out.println("Bandwidth usage: "+read+" bytes read; "+
written+" bytes written.");
}
public void newDescriptors(java.util.List<String> orList) {
out.println("New descriptors for routers:");
for (Iterator<String> i = orList.iterator(); i.hasNext(); )
out.println(" "+i.next());
}
public void message(String type, String msg) {
out.println("["+type+"] "+msg.trim());
}
public void unrecognized(String type, String msg) {
out.println("unrecognized event ["+type+"] "+msg.trim());
}
}
// Copyright 2005 Nick Mathewson, Roger Dingledine
// See LICENSE file for copying information
package net.freehaven.tor.control.examples;
import net.freehaven.tor.control.*;
import java.io.EOFException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.Iterator;
public class Main implements TorControlCommands {
public static void main(String args[]) {
if (args.length < 1) {
System.err.println("No command given.");
return;
}
try {
if (args[0].equals("set-config")) {
setConfig(args);
} else if (args[0].equals("get-config")) {
getConfig(args);
} else if (args[0].equals("get-info")) {
getInfo(args);
} else if (args[0].equals("listen")) {
listenForEvents(args);
} else if (args[0].equals("signal")) {
signal(args);
} else if (args[0].equals("auth")) {
authDemo(args);
} else {
System.err.println("Unrecognized command: "+args[0]);
}
} catch (EOFException ex) {
System.out.println("Control socket closed by Tor.");
} catch (TorControlError ex) {
System.err.println("Error from Tor process: "+
ex+" ["+ex.getErrorMsg()+"]");
} catch (IOException ex) {
System.err.println("IO exception when talking to Tor process: "+
ex);
ex.printStackTrace(System.err);
}
}
private static TorControlConnection getConnection(String[] args,
boolean daemon) throws IOException {
Socket s = new Socket("127.0.0.1", 9100);
TorControlConnection conn = new TorControlConnection(s);
conn.launchThread(daemon);
conn.authenticate(new byte[0]);
return conn;
}
private static TorControlConnection getConnection(String[] args)
throws IOException {
return getConnection(args, true);
}
public static void setConfig(String[] args) throws IOException {
// Usage: "set-config [-save] key value key value key value"
TorControlConnection conn = getConnection(args);
ArrayList<String> lst = new ArrayList<String>();
int i = 1;
boolean save = false;
if (args[i].equals("-save")) {
save = true;
++i;
}
for (; i < args.length; i +=2) {
lst.add(args[i]+" "+args[i+1]);
}
conn.setConf(lst);
if (save) {
conn.saveConf();
}
}
public static void getConfig(String[] args) throws IOException {
// Usage: get-config key key key
TorControlConnection conn = getConnection(args);
List<ConfigEntry> lst = conn.getConf(Arrays.asList(args).subList(1,args.length));
for (Iterator<ConfigEntry> i = lst.iterator(); i.hasNext(); ) {
ConfigEntry e = i.next();
System.out.println("KEY: "+e.key);
System.out.println("VAL: "+e.value);
}
}
public static void getInfo(String[] args) throws IOException {
TorControlConnection conn = getConnection(args);
Map<String,String> m = conn.getInfo(Arrays.asList(args).subList(1,args.length));
for (Iterator<Map.Entry<String, String>> i = m.entrySet().iterator(); i.hasNext(); ) {
Map.Entry<String,String> e = i.next();
System.out.println("KEY: "+e.getKey());
System.out.println("VAL: "+e.getValue());
}
}
public static void listenForEvents(String[] args) throws IOException {
// Usage: listen [circ|stream|orconn|bw|newdesc|info|notice|warn|error]*
TorControlConnection conn = getConnection(args, false);
ArrayList<String> lst = new ArrayList<String>();
for (int i = 1; i < args.length; ++i) {
lst.add(args[i]);
}
conn.setEventHandler(
new DebuggingEventHandler(new PrintWriter(System.out, true)));
conn.setEvents(lst);
}
public static void signal(String[] args) throws IOException {
// Usage signal [reload|shutdown|dump|debug|halt]
TorControlConnection conn = getConnection(args, false);
// distinguish shutdown signal from other signals
if ("SHUTDOWN".equalsIgnoreCase(args[1])
|| "HALT".equalsIgnoreCase(args[1])) {
conn.shutdownTor(args[1].toUpperCase());
} else {
conn.signal(args[1].toUpperCase());
}
}
public static void authDemo(String[] args) throws IOException {
PasswordDigest pwd = PasswordDigest.generateDigest();
Socket s = new Socket("127.0.0.1", 9100);
TorControlConnection conn = new TorControlConnection(s);
conn.launchThread(true);
conn.authenticate(new byte[0]);
conn.setConf("HashedControlPassword", pwd.getHashedPassword());
s = new Socket("127.0.0.1", 9100);
conn = new TorControlConnection(s);
conn.launchThread(true);
conn.authenticate(pwd.getSecret());
}
}
......@@ -38,6 +38,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
......@@ -106,7 +108,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final ResourceProvider resourceProvider;
private final int maxLatency, maxIdleTime, socketTimeout;
private final File torDirectory, torFile, geoIpFile, obfs4File, configFile;
private final File doneFile, cookieFile;
private final File doneFile, cookieFile, jtorCTLFile;
private final ConnectionStatus connectionStatus;
private final AtomicBoolean used = new AtomicBoolean(false);
......@@ -151,6 +153,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done");
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
jtorCTLFile = new File(torDirectory, "jtorctl.out");
connectionStatus = new ConnectionStatus();
// Don't execute more than one connection status check at a time
connectionStatusExecutor =
......@@ -205,6 +208,19 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} catch (SecurityException | IOException e) {
throw new PluginException(e);
}
// FIXME
long torPid = getPid(torProcess);
LOG.info("Tor PID: " + torPid);
/*
pb = new ProcessBuilder("/usr/bin/strace", "-ff", "-o", "strace.out",
"-p", String.valueOf(torPid));
try {
pb.start();
LOG.info("Started strace");
} catch (SecurityException | IOException e) {
logException(LOG, WARNING, e);
}
*/
// Log the process's standard output until it detaches
if (LOG.isLoggable(INFO)) {
Scanner stdout = new Scanner(torProcess.getInputStream());
......@@ -249,6 +265,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
controlConnection.setConf("LOG", "debug file torlog");
controlConnection.setDebugging(
new PrintWriter(new FileOutputStream(jtorCTLFile), true));
// FIXME Spam the control port with enable/disable network commands
spamControlPort();
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
......@@ -272,6 +293,38 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
bind();
}
// FIXME
private long getPid(Process p) {
long pid = -1;
try {
if (p.getClass().getName().equals("java.lang.UNIXProcess")) {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getLong(p);
f.setAccessible(false);
}
} catch (Exception e) {
logException(LOG, INFO, e);
}
return pid;
}
// FIXME
private void spamControlPort() {
ioExecutor.execute(() -> {
LOG.info("Spamming control port");
try {
//noinspection InfiniteLoopStatement
for (boolean bridges = true; ; bridges = !bridges) {
LOG.info("Enable bridges " + bridges);
enableBridges(bridges, false);
}
} catch (IOException e) {
logException(LOG, WARNING, e);
}
});
}
private boolean assetsAreUpToDate() {
return doneFile.lastModified() > getLastUpdateTime();
}
......
......@@ -22,7 +22,6 @@ dependencyVerification {
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
......