20 #include <boost/function.hpp>
21 #include <boost/bind.hpp>
22 #include <boost/signals2/signal.hpp>
23 #include <boost/algorithm/string/predicate.hpp>
24 #include <boost/algorithm/string/split.hpp>
25 #include <boost/algorithm/string/classification.hpp>
26 #include <boost/algorithm/string/replace.hpp>
28 #include <event2/bufferevent.h>
29 #include <event2/buffer.h>
30 #include <event2/util.h>
31 #include <event2/event.h>
32 #include <event2/thread.h>
37 static const int TOR_COOKIE_SIZE = 32;
39 static const int TOR_NONCE_SIZE = 32;
41 static const std::string TOR_SAFE_SERVERKEY =
"Tor safe cookie authentication server-to-controller hash";
43 static const std::string TOR_SAFE_CLIENTKEY =
"Tor safe cookie authentication controller-to-server hash";
45 static const float RECONNECT_TIMEOUT_START = 1.0;
47 static const float RECONNECT_TIMEOUT_EXP = 1.5;
52 static const int MAX_LINE_LENGTH = 100000;
123 static void readcb(
struct bufferevent *bev,
void *ctx);
124 static void eventcb(
struct bufferevent *bev,
short what,
void *ctx);
128 base(_base), b_conn(0)
141 struct evbuffer *input = bufferevent_get_input(bev);
142 size_t n_read_out = 0;
146 while((line = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF)) != NULL)
148 std::string s(line, n_read_out);
153 self->message.code =
atoi(s.substr(0,3));
154 self->message.lines.push_back(s.substr(4));
158 if (self->message.code >= 600) {
161 self->async_handler(*
self, self->message);
163 if (!self->reply_handlers.empty()) {
165 self->reply_handlers.front()(*
self,
self->message);
166 self->reply_handlers.pop_front();
171 self->message.Clear();
177 if (evbuffer_get_length(input) > MAX_LINE_LENGTH) {
178 LogPrintf(
"tor: Disconnecting because MAX_LINE_LENGTH exceeded\n");
186 if (what & BEV_EVENT_CONNECTED) {
188 self->connected(*
self);
189 }
else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
190 if (what & BEV_EVENT_ERROR) {
196 self->disconnected(*
self);
205 struct sockaddr_storage connect_to_addr;
206 int connect_to_addrlen =
sizeof(connect_to_addr);
207 if (evutil_parse_sockaddr_port(target.c_str(),
208 (
struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) {
209 LogPrintf(
"tor: Error parsing socket address %s\n", target);
214 b_conn = bufferevent_socket_new(
base, -1, BEV_OPT_CLOSE_ON_FREE);
218 bufferevent_enable(
b_conn, EV_READ|EV_WRITE);
223 if (bufferevent_socket_connect(
b_conn, (
struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) {
224 LogPrintf(
"tor: Error connecting to address %s\n", target);
242 struct evbuffer *buf = bufferevent_get_output(
b_conn);
245 evbuffer_add(buf, cmd.data(), cmd.size());
246 evbuffer_add(buf,
"\r\n", 2);
258 static std::pair<std::string,std::string> SplitTorReplyLine(
const std::string &s)
262 while (ptr < s.size() && s[ptr] !=
' ') {
263 type.push_back(s[ptr]);
268 return make_pair(type, s.substr(ptr));
277 static std::map<std::string,std::string> ParseTorReplyMapping(
const std::string &s)
279 std::map<std::string,std::string> mapping;
281 while (ptr < s.size()) {
282 std::string
key, value;
283 while (ptr < s.size() && s[ptr] !=
'=' && s[ptr] !=
' ') {
284 key.push_back(s[ptr]);
288 return std::map<std::string,std::string>();
292 if (ptr < s.size() && s[ptr] ==
'"') {
294 bool escape_next =
false;
295 while (ptr < s.size() && (escape_next || s[ptr] !=
'"')) {
297 escape_next = (s[ptr] ==
'\\' && !escape_next);
298 value.push_back(s[ptr]);
302 return std::map<std::string,std::string>();
314 std::string escaped_value;
315 for (
size_t i = 0; i < value.size(); ++i) {
316 if (value[i] ==
'\\') {
322 if (value[i] ==
'n') {
323 escaped_value.push_back(
'\n');
324 }
else if (value[i] ==
't') {
325 escaped_value.push_back(
'\t');
326 }
else if (value[i] ==
'r') {
327 escaped_value.push_back(
'\r');
328 }
else if (
'0' <= value[i] && value[i] <=
'7') {
333 for (j = 1; j < 3 && (i+j) < value.size() &&
'0' <= value[i+j] && value[i+j] <=
'7'; ++j) {}
337 if (j == 3 && value[i] >
'3') {
340 escaped_value.push_back(strtol(value.substr(i, j).c_str(), NULL, 8));
344 escaped_value.push_back(value[i]);
347 escaped_value.push_back(value[i]);
350 value = escaped_value;
352 while (ptr < s.size() && s[ptr] !=
' ') {
353 value.push_back(s[ptr]);
357 if (ptr < s.size() && s[ptr] ==
' ')
359 mapping[
key] = value;
371 static std::pair<bool,std::string> ReadBinaryFile(
const fs::path &filename,
size_t maxsize=std::numeric_limits<size_t>::max())
375 return std::make_pair(
false,
"");
379 while ((n=fread(buffer, 1,
sizeof(buffer), f)) > 0) {
384 return std::make_pair(
false,
"");
386 retval.append(buffer, buffer+n);
387 if (retval.size() > maxsize)
391 return std::make_pair(
true,retval);
397 static bool WriteBinaryFile(
const fs::path &filename,
const std::string &data)
402 if (fwrite(data.data(), 1, data.size(), f) != data.size()) {
455 static void reconnect_cb(evutil_socket_t fd,
short what,
void *arg);
460 target(_target), conn(base), reconnect(true), reconnect_ev(0),
461 reconnect_timeout(RECONNECT_TIMEOUT_START)
465 LogPrintf(
"tor: Failed to create event for reconnection: out of memory?\n");
469 LogPrintf(
"tor: Initiating connection to Tor control port %s failed\n", _target);
492 if (reply.
code == 250) {
494 for (
const std::string &s : reply.
lines) {
495 std::map<std::string,std::string> m = ParseTorReplyMapping(s);
496 std::map<std::string,std::string>::iterator i;
497 if ((i = m.find(
"ServiceID")) != m.end())
499 if ((i = m.find(
"PrivateKey")) != m.end())
503 LogPrintf(
"tor: Error parsing ADD_ONION parameters:\n");
504 for (
const std::string &s : reply.
lines) {
518 }
else if (reply.
code == 510) {
519 LogPrintf(
"tor: Add onion failed with unrecognized command (You probably need to upgrade Tor)\n");
521 LogPrintf(
"tor: Add onion failed; error code %d\n", reply.
code);
527 if (reply.
code == 250) {
532 if (
GetArg(
"-onion",
"") ==
"") {
547 LogPrintf(
"tor: Authentication failed\n");
567 static std::vector<uint8_t> ComputeResponse(
const std::string &
key,
const std::vector<uint8_t> &cookie,
const std::vector<uint8_t> &clientNonce,
const std::vector<uint8_t> &serverNonce)
571 computeHash.Write(cookie.data(), cookie.size());
572 computeHash.Write(clientNonce.data(), clientNonce.size());
573 computeHash.Write(serverNonce.data(), serverNonce.size());
574 computeHash.Finalize(computedHash.data());
580 if (reply.
code == 250) {
582 std::pair<std::string,std::string> l = SplitTorReplyLine(reply.
lines[0]);
583 if (l.first ==
"AUTHCHALLENGE") {
584 std::map<std::string,std::string> m = ParseTorReplyMapping(l.second);
589 std::vector<uint8_t> serverHash =
ParseHex(m[
"SERVERHASH"]);
590 std::vector<uint8_t> serverNonce =
ParseHex(m[
"SERVERNONCE"]);
592 if (serverNonce.size() != 32) {
593 LogPrintf(
"tor: ServerNonce is not 32 bytes, as required by spec\n");
597 std::vector<uint8_t> computedServerHash = ComputeResponse(TOR_SAFE_SERVERKEY,
cookie,
clientNonce, serverNonce);
598 if (computedServerHash != serverHash) {
599 LogPrintf(
"tor: ServerHash %s does not match expected ServerHash %s\n",
HexStr(serverHash),
HexStr(computedServerHash));
603 std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY,
cookie,
clientNonce, serverNonce);
606 LogPrintf(
"tor: Invalid reply to AUTHCHALLENGE\n");
609 LogPrintf(
"tor: SAFECOOKIE authentication challenge failed\n");
615 if (reply.
code == 250) {
616 std::set<std::string> methods;
617 std::string cookiefile;
623 for (
const std::string &s : reply.
lines) {
624 std::pair<std::string,std::string> l = SplitTorReplyLine(s);
625 if (l.first ==
"AUTH") {
626 std::map<std::string,std::string> m = ParseTorReplyMapping(l.second);
627 std::map<std::string,std::string>::iterator i;
628 if ((i = m.find(
"METHODS")) != m.end())
629 boost::split(methods, i->second, boost::is_any_of(
","));
630 if ((i = m.find(
"COOKIEFILE")) != m.end())
631 cookiefile = i->second;
632 }
else if (l.first ==
"VERSION") {
633 std::map<std::string,std::string> m = ParseTorReplyMapping(l.second);
634 std::map<std::string,std::string>::iterator i;
635 if ((i = m.find(
"Tor")) != m.end()) {
640 for (
const std::string &s : methods) {
648 std::string torpassword =
GetArg(
"-torpassword",
"");
649 if (!torpassword.empty()) {
650 if (methods.count(
"HASHEDPASSWORD")) {
652 boost::replace_all(torpassword,
"\"",
"\\\"");
655 LogPrintf(
"tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n");
657 }
else if (methods.count(
"NULL")) {
660 }
else if (methods.count(
"SAFECOOKIE")) {
662 LogPrint(
BCLog::TOR,
"tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile);
663 std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE);
664 if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) {
665 cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end());
666 clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
670 if (status_cookie.first) {
671 LogPrintf(
"tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE);
673 LogPrintf(
"tor: Authentication cookie %s could not be opened (check permissions)\n", cookiefile);
676 }
else if (methods.count(
"HASHEDPASSWORD")) {
677 LogPrintf(
"tor: The only supported authentication mechanism left is password, but no password provided with -torpassword\n");
679 LogPrintf(
"tor: No supported authentication method\n");
682 LogPrintf(
"tor: Requesting protocol info failed\n");
691 LogPrintf(
"tor: Error sending initial protocolinfo command\n");
719 LogPrintf(
"tor: Re-initiating connection to Tor control port %s failed\n",
target);
735 static struct event_base *gBase;
736 static boost::thread torControlThread;
738 static void TorControlThread()
742 event_base_dispatch(gBase);
749 evthread_use_windows_threads();
751 evthread_use_pthreads();
753 gBase = event_base_new();
755 LogPrintf(
"tor: Unable to create event_base\n");
759 torControlThread = boost::thread(boost::bind(&
TraceThread<
void (*)()>,
"torcontrol", &TorControlThread));
766 event_base_loopbreak(gBase);
774 torControlThread.try_join_for(boost::chrono::seconds(1));
775 event_base_free(gBase);