| 646 | } |
| 647 | |
| 648 | void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorControlReply& reply) |
| 649 | { |
| 650 | if (reply.code == TOR_REPLY_OK) { |
| 651 | std::set<std::string> methods; |
| 652 | std::string cookiefile; |
| 653 | /* |
| 654 | * 250-AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE="/home/x/.tor/control_auth_cookie" |
| 655 | * 250-AUTH METHODS=NULL |
| 656 | * 250-AUTH METHODS=HASHEDPASSWORD |
| 657 | */ |
| 658 | for (const std::string &s : reply.lines) { |
| 659 | std::pair<std::string,std::string> l = SplitTorReplyLine(s); |
| 660 | if (l.first == "AUTH") { |
| 661 | std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); |
| 662 | std::map<std::string,std::string>::iterator i; |
| 663 | if ((i = m.find("METHODS")) != m.end()) { |
| 664 | std::vector<std::string> m_vec = SplitString(i->second, ','); |
| 665 | methods = std::set<std::string>(m_vec.begin(), m_vec.end()); |
| 666 | } |
| 667 | if ((i = m.find("COOKIEFILE")) != m.end()) |
| 668 | cookiefile = i->second; |
| 669 | } else if (l.first == "VERSION") { |
| 670 | std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); |
| 671 | std::map<std::string,std::string>::iterator i; |
| 672 | if ((i = m.find("Tor")) != m.end()) { |
| 673 | LogDebug(BCLog::TOR, "Connected to Tor version %s", i->second); |
| 674 | } |
| 675 | } |
| 676 | } |
| 677 | for (const std::string &s : methods) { |
| 678 | LogDebug(BCLog::TOR, "Supported authentication method: %s", s); |
| 679 | } |
| 680 | // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use HASHEDPASSWORD |
| 681 | /* Authentication: |
| 682 | * cookie: hex-encoded ~/.tor/control_auth_cookie |
| 683 | * password: "password" |
| 684 | */ |
| 685 | std::string torpassword = gArgs.GetArg("-torpassword", ""); |
| 686 | if (!torpassword.empty()) { |
| 687 | if (methods.contains("HASHEDPASSWORD")) { |
| 688 | LogDebug(BCLog::TOR, "Using HASHEDPASSWORD authentication"); |
| 689 | ReplaceAll(torpassword, "\"", "\\\""); |
| 690 | _conn.Command("AUTHENTICATE \"" + torpassword + "\"", std::bind_front(&TorController::auth_cb, this)); |
| 691 | } else { |
| 692 | LogWarning("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available"); |
| 693 | } |
| 694 | } else if (methods.contains("NULL")) { |
| 695 | LogDebug(BCLog::TOR, "Using NULL authentication"); |
| 696 | _conn.Command("AUTHENTICATE", std::bind_front(&TorController::auth_cb, this)); |
| 697 | } else if (methods.contains("SAFECOOKIE")) { |
| 698 | // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie |
| 699 | LogDebug(BCLog::TOR, "Using SAFECOOKIE authentication, reading cookie authentication from %s", cookiefile); |
| 700 | std::pair<bool,std::string> status_cookie = ReadBinaryFile(fs::PathFromString(cookiefile), TOR_COOKIE_SIZE); |
| 701 | if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { |
| 702 | // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind_front(&TorController::auth_cb, this)); |
| 703 | m_cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end()); |
| 704 | m_client_nonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0); |
| 705 | GetRandBytes(m_client_nonce); |
no test coverage detected