| 589 | } |
| 590 | |
| 591 | void LuxController::protocolinfo_cb(LuxControlConnection& _conn, const LuxControlReply& reply) |
| 592 | { |
| 593 | if (reply.code == 250) { |
| 594 | std::set<std::string> methods; |
| 595 | std::string cookiefile; |
| 596 | /* |
| 597 | * 250-AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE="/home/x/.lux/control_auth_cookie" |
| 598 | * 250-AUTH METHODS=NULL |
| 599 | * 250-AUTH METHODS=HASHEDPASSWORD |
| 600 | */ |
| 601 | for (const std::string &s : reply.lines) { |
| 602 | std::pair<std::string,std::string> l = SplitLuxReplyLine(s); |
| 603 | if (l.first == "AUTH") { |
| 604 | std::map<std::string,std::string> m = ParseLuxReplyMapping(l.second); |
| 605 | std::map<std::string,std::string>::iterator i; |
| 606 | if ((i = m.find("METHODS")) != m.end()) |
| 607 | boost::split(methods, i->second, boost::is_any_of(",")); |
| 608 | if ((i = m.find("COOKIEFILE")) != m.end()) |
| 609 | cookiefile = i->second; |
| 610 | } else if (l.first == "VERSION") { |
| 611 | std::map<std::string,std::string> m = ParseLuxReplyMapping(l.second); |
| 612 | std::map<std::string,std::string>::iterator i; |
| 613 | if ((i = m.find("Lux")) != m.end()) { |
| 614 | LogPrint("lux", "lux: Connected to Lux version %s\n", i->second); |
| 615 | } |
| 616 | } |
| 617 | } |
| 618 | for (const std::string &s : methods) { |
| 619 | LogPrint("lux", "lux: Supported authentication method: %s\n", s); |
| 620 | } |
| 621 | // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use HASHEDPASSWORD |
| 622 | /* Authentication: |
| 623 | * cookie: hex-encoded ~/.lux/control_auth_cookie |
| 624 | * password: "password" |
| 625 | */ |
| 626 | std::string luxpassword = GetArg("-luxpassword", ""); |
| 627 | if (!luxpassword.empty()) { |
| 628 | if (methods.count("HASHEDPASSWORD")) { |
| 629 | LogPrint("lux", "lux: Using HASHEDPASSWORD authentication\n"); |
| 630 | boost::replace_all(luxpassword, "\"", "\\\""); |
| 631 | _conn.Command("AUTHENTICATE \"" + luxpassword + "\"", boost::bind(&LuxController::auth_cb, this, _1, _2)); |
| 632 | } else { |
| 633 | LogPrintf("lux: Password provided with -luxpassword, but HASHEDPASSWORD authentication is not available\n"); |
| 634 | } |
| 635 | } else if (methods.count("NULL")) { |
| 636 | LogPrint("lux", "lux: Using NULL authentication\n"); |
| 637 | _conn.Command("AUTHENTICATE", boost::bind(&LuxController::auth_cb, this, _1, _2)); |
| 638 | } else if (methods.count("SAFECOOKIE")) { |
| 639 | // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.lux/control_auth_cookie |
| 640 | LogPrint("lux", "lux: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); |
| 641 | std::pair<bool,std::string> status_cookie = ReadBinaryFile(cookiefile, LUX_COOKIE_SIZE); |
| 642 | if (status_cookie.first && status_cookie.second.size() == LUX_COOKIE_SIZE) { |
| 643 | // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&LuxController::auth_cb, this, _1, _2)); |
| 644 | cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end()); |
| 645 | clientNonce = std::vector<uint8_t>(LUX_NONCE_SIZE, 0); |
| 646 | GetRandBytes(&clientNonce[0], LUX_NONCE_SIZE); |
| 647 | _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), boost::bind(&LuxController::authchallenge_cb, this, _1, _2)); |
| 648 | } else { |
nothing calls this directly
no test coverage detected