summaryrefslogtreecommitdiffstats
path: root/xbmc/PasswordManager.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /xbmc/PasswordManager.cpp
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/PasswordManager.cpp')
-rw-r--r--xbmc/PasswordManager.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/xbmc/PasswordManager.cpp b/xbmc/PasswordManager.cpp
new file mode 100644
index 0000000..fdbb902
--- /dev/null
+++ b/xbmc/PasswordManager.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "PasswordManager.h"
+
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "profiles/ProfileManager.h"
+#include "profiles/dialogs/GUIDialogLockSettings.h"
+#include "settings/SettingsComponent.h"
+#include "utils/FileUtils.h"
+#include "utils/StringUtils.h"
+#include "utils/XMLUtils.h"
+#include "utils/log.h"
+
+#include <mutex>
+
+CPasswordManager &CPasswordManager::GetInstance()
+{
+ static CPasswordManager sPasswordManager;
+ return sPasswordManager;
+}
+
+CPasswordManager::CPasswordManager()
+{
+ m_loaded = false;
+}
+
+bool CPasswordManager::AuthenticateURL(CURL &url)
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ if (!m_loaded)
+ Load();
+ std::string lookup(GetLookupPath(url));
+ std::map<std::string, std::string>::const_iterator it = m_temporaryCache.find(lookup);
+ if (it == m_temporaryCache.end())
+ { // second step, try something that doesn't quite match
+ it = m_temporaryCache.find(GetServerLookup(lookup));
+ }
+ if (it != m_temporaryCache.end())
+ {
+ CURL auth(it->second);
+ url.SetDomain(auth.GetDomain());
+ url.SetPassword(auth.GetPassWord());
+ url.SetUserName(auth.GetUserName());
+ return true;
+ }
+ return false;
+}
+
+bool CPasswordManager::PromptToAuthenticateURL(CURL &url)
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ std::string passcode;
+ std::string username = url.GetUserName();
+ std::string domain = url.GetDomain();
+ if (!domain.empty())
+ username = domain + '\\' + username;
+
+ bool saveDetails = false;
+ if (!CGUIDialogLockSettings::ShowAndGetUserAndPassword(username, passcode, url.GetWithoutUserDetails(), &saveDetails))
+ return false;
+
+ // domain/name to domain\name
+ std::string name = username;
+ std::replace(name.begin(), name.end(), '/', '\\');
+
+ if (url.IsProtocol("smb") && name.find('\\') != std::string::npos)
+ {
+ auto pair = StringUtils::Split(name, '\\', 2);
+ url.SetDomain(pair[0]);
+ url.SetUserName(pair[1]);
+ }
+ else
+ {
+ url.SetDomain("");
+ url.SetUserName(username);
+ }
+
+ url.SetPassword(passcode);
+
+ // save the information for later
+ SaveAuthenticatedURL(url, saveDetails);
+ return true;
+}
+
+void CPasswordManager::SaveAuthenticatedURL(const CURL &url, bool saveToProfile)
+{
+ // don't store/save authenticated url if it doesn't contain username
+ if (url.GetUserName().empty())
+ return;
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ std::string path = GetLookupPath(url);
+ std::string authenticatedPath = url.Get();
+
+ if (!m_loaded)
+ Load();
+
+ if (saveToProfile)
+ { // write to some random XML file...
+ m_permanentCache[path] = authenticatedPath;
+ Save();
+ }
+
+ // save for both this path and more generally the server as a whole.
+ m_temporaryCache[path] = authenticatedPath;
+ m_temporaryCache[GetServerLookup(path)] = authenticatedPath;
+}
+
+bool CPasswordManager::IsURLSupported(const CURL &url)
+{
+ return url.IsProtocol("smb")
+ || url.IsProtocol("nfs")
+ || url.IsProtocol("ftp")
+ || url.IsProtocol("ftps")
+ || url.IsProtocol("sftp")
+ || url.IsProtocol("http")
+ || url.IsProtocol("https")
+ || url.IsProtocol("dav")
+ || url.IsProtocol("davs");
+}
+
+void CPasswordManager::Clear()
+{
+ m_temporaryCache.clear();
+ m_permanentCache.clear();
+ m_loaded = false;
+}
+
+void CPasswordManager::Load()
+{
+ Clear();
+
+ const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
+
+ std::string passwordsFile = profileManager->GetUserDataItem("passwords.xml");
+ if (CFileUtils::Exists(passwordsFile))
+ {
+ CXBMCTinyXML doc;
+ if (!doc.LoadFile(passwordsFile))
+ {
+ CLog::Log(LOGERROR, "{} - Unable to load: {}, Line {}\n{}", __FUNCTION__, passwordsFile,
+ doc.ErrorRow(), doc.ErrorDesc());
+ return;
+ }
+ const TiXmlElement *root = doc.RootElement();
+ if (root->ValueStr() != "passwords")
+ return;
+ // read in our passwords
+ const TiXmlElement *path = root->FirstChildElement("path");
+ while (path)
+ {
+ std::string from, to;
+ if (XMLUtils::GetPath(path, "from", from) && XMLUtils::GetPath(path, "to", to))
+ {
+ m_permanentCache[from] = to;
+ m_temporaryCache[from] = to;
+ m_temporaryCache[GetServerLookup(from)] = to;
+ }
+ path = path->NextSiblingElement("path");
+ }
+ }
+ m_loaded = true;
+}
+
+void CPasswordManager::Save() const
+{
+ if (m_permanentCache.empty())
+ return;
+
+ CXBMCTinyXML doc;
+ TiXmlElement rootElement("passwords");
+ TiXmlNode *root = doc.InsertEndChild(rootElement);
+ if (!root)
+ return;
+
+ for (std::map<std::string, std::string>::const_iterator i = m_permanentCache.begin(); i != m_permanentCache.end(); ++i)
+ {
+ TiXmlElement pathElement("path");
+ TiXmlNode *path = root->InsertEndChild(pathElement);
+ XMLUtils::SetPath(path, "from", i->first);
+ XMLUtils::SetPath(path, "to", i->second);
+ }
+
+ const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
+
+ doc.SaveFile(profileManager->GetUserDataItem("passwords.xml"));
+}
+
+std::string CPasswordManager::GetLookupPath(const CURL &url) const
+{
+ if (url.IsProtocol("sftp"))
+ return GetServerLookup(url.Get());
+
+ return url.GetProtocol() + "://" + url.GetHostName() + "/" + url.GetShareName();
+}
+
+std::string CPasswordManager::GetServerLookup(const std::string &path) const
+{
+ CURL url(path);
+ return url.GetProtocol() + "://" + url.GetHostName() + "/";
+}