jtorctl.patch 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. diff --git a/README.md b/README.md
  2. index 902d727..359cc69 100644
  3. --- a/README.md
  4. +++ b/README.md
  5. @@ -1,7 +1,4 @@
  6. -
  7. A Java library for controlling a Tor instance via its control port. It is
  8. used in the Android app Orbot as well as others.
  9. -To add this library to a gradle project:
  10. -
  11. - compile 'net.freehaven.tor.control:jtorctl:0.2'
  12. +This fork includes patches for managing onion services.
  13. diff --git a/net/freehaven/tor/control/TorControlCommands.java b/net/freehaven/tor/control/TorControlCommands.java
  14. index 36482d5..14486e3 100644
  15. --- a/net/freehaven/tor/control/TorControlCommands.java
  16. +++ b/net/freehaven/tor/control/TorControlCommands.java
  17. @@ -144,5 +144,8 @@ public interface TorControlCommands {
  18. "No such OR",
  19. };
  20. + public static final String HS_ADDRESS = "onionAddress";
  21. + public static final String HS_PRIVKEY = "onionPrivKey";
  22. +
  23. }
  24. diff --git a/net/freehaven/tor/control/TorControlConnection.java b/net/freehaven/tor/control/TorControlConnection.java
  25. index 9524612..eacdd66 100644
  26. --- a/net/freehaven/tor/control/TorControlConnection.java
  27. +++ b/net/freehaven/tor/control/TorControlConnection.java
  28. @@ -40,10 +40,14 @@ public class TorControlConnection implements TorControlCommands {
  29. static class Waiter {
  30. List<ReplyLine> response; // Locking: this
  31. + boolean interrupted;
  32. synchronized List<ReplyLine> getResponse() throws InterruptedException {
  33. while (response == null) {
  34. wait();
  35. + if (interrupted) {
  36. + throw new InterruptedException();
  37. + }
  38. }
  39. return response;
  40. }
  41. @@ -52,6 +56,11 @@ public class TorControlConnection implements TorControlCommands {
  42. this.response = response;
  43. notifyAll();
  44. }
  45. +
  46. + synchronized void interrupt() {
  47. + interrupted = true;
  48. + notifyAll();
  49. + }
  50. }
  51. static class ReplyLine {
  52. @@ -171,7 +180,7 @@ public class TorControlConnection implements TorControlCommands {
  53. protected synchronized List<ReplyLine> sendAndWaitForResponse(String s,
  54. String rest) throws IOException {
  55. - if(parseThreadException != null) throw parseThreadException;
  56. + if (parseThreadException != null) throw parseThreadException;
  57. checkThread();
  58. Waiter w = new Waiter();
  59. if (debugOutput != null)
  60. @@ -305,8 +314,15 @@ public class TorControlConnection implements TorControlCommands {
  61. while (true) {
  62. ArrayList<ReplyLine> lst = readReply();
  63. if (lst.isEmpty()) {
  64. - // connection has been closed remotely! end the loop!
  65. - return;
  66. + // interrupted queued waiters, there won't be any response.
  67. + synchronized (waiters) {
  68. + if (!waiters.isEmpty()) {
  69. + for (Waiter w : waiters) {
  70. + w.interrupt();
  71. + }
  72. + }
  73. + }
  74. + throw new IOException("Tor is no longer running");
  75. }
  76. if ((lst.get(0)).status.startsWith("6"))
  77. handleEvent(lst);
  78. @@ -736,11 +752,111 @@ public class TorControlConnection implements TorControlCommands {
  79. sendAndWaitForResponse("TAKEOWNERSHIP\r\n", null);
  80. }
  81. + /**
  82. + * Tells Tor to generate and set up a new onion service using the best
  83. + * supported algorithm.
  84. + * <p/>
  85. + * ADD_ONION was added in Tor 0.2.7.1-alpha.
  86. + */
  87. + public Map<String,String> addOnion(Map<Integer,String> portLines)
  88. + throws IOException {
  89. + return addOnion("NEW:BEST", portLines, null);
  90. + }
  91. +
  92. + /**
  93. + * Tells Tor to generate and set up a new onion service using the best
  94. + * supported algorithm.
  95. + * <p/>
  96. + * ADD_ONION was added in Tor 0.2.7.1-alpha.
  97. + */
  98. + public Map<String,String> addOnion(Map<Integer,String> portLines,
  99. + boolean ephemeral, boolean detach)
  100. + throws IOException {
  101. + return addOnion("NEW:BEST", portLines, ephemeral, detach);
  102. + }
  103. +
  104. + /**
  105. + * Tells Tor to set up an onion service using the provided private key.
  106. + * <p/>
  107. + * ADD_ONION was added in Tor 0.2.7.1-alpha.
  108. + */
  109. + public Map<String,String> addOnion(String privKey,
  110. + Map<Integer,String> portLines)
  111. + throws IOException {
  112. + return addOnion(privKey, portLines, null);
  113. + }
  114. +
  115. + /**
  116. + * Tells Tor to set up an onion service using the provided private key.
  117. + * <p/>
  118. + * ADD_ONION was added in Tor 0.2.7.1-alpha.
  119. + */
  120. + public Map<String,String> addOnion(String privKey,
  121. + Map<Integer,String> portLines,
  122. + boolean ephemeral, boolean detach)
  123. + throws IOException {
  124. + List<String> flags = new ArrayList<String>();
  125. + if (ephemeral)
  126. + flags.add("DiscardPK");
  127. + if (detach)
  128. + flags.add("Detach");
  129. + return addOnion(privKey, portLines, flags);
  130. + }
  131. +
  132. + /**
  133. + * Tells Tor to set up an onion service.
  134. + * <p/>
  135. + * ADD_ONION was added in Tor 0.2.7.1-alpha.
  136. + */
  137. + public Map<String,String> addOnion(String privKey,
  138. + Map<Integer,String> portLines,
  139. + List<String> flags)
  140. + throws IOException {
  141. + if (privKey.indexOf(':') < 0)
  142. + throw new IllegalArgumentException("Invalid privKey");
  143. + if (portLines == null || portLines.size() < 1)
  144. + throw new IllegalArgumentException("Must provide at least one port line");
  145. + StringBuilder b = new StringBuilder();
  146. + b.append("ADD_ONION ").append(privKey);
  147. + if (flags != null && flags.size() > 0) {
  148. + b.append(" Flags=");
  149. + String separator = "";
  150. + for (String flag : flags) {
  151. + b.append(separator).append(flag);
  152. + separator = ",";
  153. + }
  154. + }
  155. + for (Map.Entry<Integer,String> portLine : portLines.entrySet()) {
  156. + int virtPort = portLine.getKey();
  157. + String target = portLine.getValue();
  158. + b.append(" Port=").append(virtPort);
  159. + if (target != null && target.length() > 0)
  160. + b.append(",").append(target);
  161. + }
  162. + b.append("\r\n");
  163. + List<ReplyLine> lst = sendAndWaitForResponse(b.toString(), null);
  164. + Map<String,String> ret = new HashMap<String,String>();
  165. + ret.put(HS_ADDRESS, (lst.get(0)).msg.split("=", 2)[1]);
  166. + if (lst.size() > 2)
  167. + ret.put(HS_PRIVKEY, (lst.get(1)).msg.split("=", 2)[1]);
  168. + return ret;
  169. + }
  170. +
  171. + /**
  172. + * Tells Tor to take down an onion service previously set up with
  173. + * addOnion(). The hostname excludes the .onion extension.
  174. + * <p/>
  175. + * DEL_ONION was added in Tor 0.2.7.1-alpha.
  176. + */
  177. + public void delOnion(String hostname) throws IOException {
  178. + sendAndWaitForResponse("DEL_ONION " + hostname + "\r\n", null);
  179. + }
  180. +
  181. /** Tells Tor to forget any cached client state relating to the hidden
  182. * service with the given hostname (excluding the .onion extension).
  183. */
  184. public void forgetHiddenService(String hostname) throws IOException {
  185. - sendAndWaitForResponse("FORGETHS " + hostname + "\r\n", null);
  186. + sendAndWaitForResponse("HSFORGET " + hostname + "\r\n", null);
  187. }
  188. }