void UPnP::processPacket(BaseLib::Http& http) { try { BaseLib::Http::Header& header = http.getHeader(); if(header.method != "M-SEARCH" || header.fields.find("st") == header.fields.end() || header.host.empty()) return; BaseLib::HelperFunctions::toLower(header.fields.at("st")); if(header.fields.at("st") == "urn:schemas-upnp-org:device:basic:1" || header.fields.at("st") == "urn:schemas-upnp-org:device:basic:1.0" || header.fields.at("st") == "ssdp:all" || header.fields.at("st") == "upnp:rootdevice" || header.fields.at("st") == _st) { if(GD::bl->debugLevel >= 5) _out.printDebug("Debug: Discovery packet received from " + header.host); std::pair<std::string, std::string> address = BaseLib::HelperFunctions::splitLast(header.host, ':'); int32_t port = BaseLib::Math::getNumber(address.second, false); if(!address.first.empty() && port > 0) { int32_t mx = 500; if(header.fields.find("mx") != header.fields.end()) mx = BaseLib::Math::getNumber(header.fields.at("mx"), false) * 1000; std::this_thread::sleep_for(std::chrono::milliseconds(20)); //Wait for 0 to mx seconds for load balancing if(mx > 500) { mx = BaseLib::HelperFunctions::getRandomNumber(0, mx - 500); GD::out.printDebug("Debug: Sleeping " + std::to_string(mx) + "ms before sending response."); std::this_thread::sleep_for(std::chrono::milliseconds(mx)); } sendOK(address.first, port, header.fields.at("st") == "upnp:rootdevice"); std::this_thread::sleep_for(std::chrono::milliseconds(100)); sendNotify(); } } } catch(const std::exception& ex) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what()); } catch(BaseLib::Exception& ex) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what()); } catch(...) { _out.printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__); } }
bool Auth::basicServer(BaseLib::Http& httpPacket) { if(!_initialized) throw AuthException("Not initialized."); _http.reset(); uint32_t bufferLength = 1024; char buffer[bufferLength + 1]; if(httpPacket.getHeader().authorization.empty()) { if(_basicAuthHTTPHeader.empty()) { _basicAuthHTTPHeader.append("HTTP/1.1 401 Authorization Required\r\n"); _basicAuthHTTPHeader.append("WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"); _basicAuthHTTPHeader.append("Connection: Keep-Alive\r\n"); std::string content("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"><title>Authorization Required</title></head><body>Authorization Required</body></html>"); _basicAuthHTTPHeader.append("Content-Length: " + std::to_string(content.size()) + "\r\n\r\n"); _basicAuthHTTPHeader.append(content); } std::shared_ptr<std::vector<char>> data(new std::vector<char>()); data->insert(data->begin(), _basicAuthHTTPHeader.begin(), _basicAuthHTTPHeader.end()); try { _socket->proofwrite(data); int32_t bytesRead = _socket->proofread(buffer, bufferLength); //Some clients send only one byte in the first packet if(bytesRead == 1) bytesRead += _socket->proofread(&buffer[1], bufferLength - 1); buffer[bytesRead] = '\0'; try { _http.process(buffer, bufferLength); } catch(BaseLib::HttpException& ex) { throw AuthException("Authorization failed because of HTTP exception: " + ex.what()); } } catch(const BaseLib::SocketOperationException& ex) { throw AuthException("Authorization failed because of socket exception: " + ex.what()); } } else _http = httpPacket; if(_http.getHeader().authorization.empty()) { sendBasicUnauthorized(false); throw AuthException("No header field \"Authorization\""); } std::pair<std::string, std::string> authData = BaseLib::HelperFunctions::splitLast(_http.getHeader().authorization, ' '); BaseLib::HelperFunctions::toLower(authData.first); if(authData.first != "basic") { sendBasicUnauthorized(false); throw AuthException("Authorization type is not basic but: " + authData.first); } std::string decodedData; BaseLib::Base64::decode(authData.second, decodedData); std::pair<std::string, std::string> credentials = BaseLib::HelperFunctions::splitLast(decodedData, ':'); BaseLib::HelperFunctions::toLower(credentials.first); if(std::find(_validUsers.begin(), _validUsers.end(), credentials.first) == _validUsers.end()) { sendBasicUnauthorized(false); throw AuthException("User name " + credentials.first + " is not in the list of valid users in /etc/homegear/rpcservers.conf."); } if(User::verify(credentials.first, credentials.second)) return true; sendBasicUnauthorized(false); return false; }