Commit affc89eb authored by sm's avatar sm

Make stmm-input-plugins support sudo

parent c98ae694
......@@ -49,7 +49,8 @@ static constexpr int32_t s_nDlpCommentLineStartLen = 1;
const std::string DlpInfos::s_sDisabledDlpsFile = "disabled-dlps.txt";
DlpInfos::DlpInfos(bool bEnablePlugins, const std::vector<std::string>& aEnDisablePlugins, const std::vector<std::string>& aGroups
DlpInfos::DlpInfos(bool bEnablePlugins, const std::vector<std::string>& aEnDisablePlugins
, const std::vector<std::string>& aGroups
, const std::vector<std::string>& aPluginPaths, const std::vector<std::string>& aDisablePaths
, bool bVerbose)
: m_bVerbose(bVerbose)
......@@ -71,7 +72,7 @@ DlpInfos::DlpInfos(bool bEnablePlugins, const std::vector<std::string>& aEnDisab
for (auto& oDlp : aDlps) {
traverse(oDlp, aDlps, m_aOrderedDlpInfos);
}
// at this point all m_bVisited are true
// at this point all m_aOrderedDlpInfos[].m_bVisited are true
// disable dlps not in the restricting group
for (auto& oDlp : m_aOrderedDlpInfos) {
for (const auto& sMustGroup : aGroups) {
......@@ -89,10 +90,10 @@ DlpInfos::DlpInfos(bool bEnablePlugins, const std::vector<std::string>& aEnDisab
}
// disable dlps listed in the disable files
for (const auto& sDirPath : aPluginPaths) {
parseDisabledNamesFile(sDirPath + "/" + s_sDisabledDlpsFile, m_aOrderedDlpInfos);
parseDisabledNamesFile(sDirPath + "/" + s_sDisabledDlpsFile, m_aOrderedDlpInfos, true);
}
for (const auto& sDirPath : aDisablePaths) {
parseDisabledNamesFile(sDirPath + "/" + s_sDisabledDlpsFile, m_aOrderedDlpInfos);
parseDisabledNamesFile(sDirPath + "/" + s_sDisabledDlpsFile, m_aOrderedDlpInfos, false);
}
}
......@@ -213,7 +214,7 @@ bool DlpInfos::parseDlpInfo(DlpInfo& oInfo)
}
return true;
}
bool DlpInfos::parseDisabledNamesFile(const std::string& sFile, std::vector<DlpInfo>& aDlps)
bool DlpInfos::parseDisabledNamesFile(const std::string& sFile, std::vector<DlpInfo>& aDlps, bool bDisabledInSys)
{
//std::cout << "DlpInfo - parseDisabledNamesFile " << sFile << '\n';
std::ifstream oInFile(sFile);
......@@ -221,8 +222,9 @@ bool DlpInfos::parseDisabledNamesFile(const std::string& sFile, std::vector<DlpI
//std::cout << "DlpInfo - Couldn't open file '" << sFile << "'" << '\n';
return false; //--------------------------------------------------------
}
auto aNames = parseBlock(oInFile, true);
for (const auto& sPluginName : aNames) {
auto aLines = parseBlock(oInFile, true);
for (const auto& sPluginLine : aLines) {
const std::string sPluginName = trimString(sPluginLine);
auto itFind = std::find_if(aDlps.begin(), aDlps.end(), [&](const DlpInfo& oCur)
{
return oCur.m_sName == sPluginName;
......@@ -232,6 +234,7 @@ bool DlpInfos::parseDisabledNamesFile(const std::string& sFile, std::vector<DlpI
}
// mark as disabled
(*itFind).m_bVisited = false;
(*itFind).m_bDisabledInSys = bDisabledInSys;
}
return true;
}
......
......@@ -45,14 +45,24 @@ struct DlpInfo
std::vector<std::string> m_aDllDescriptionLines; // The description.
std::vector<std::string> m_aGroups; // The groups.
bool isEnabled() const { return m_bVisited; }
bool isDisabledInSysPath() const { return m_bDisabledInSys; }
private:
friend class DlpInfos;
bool m_bVisited = false;
bool m_bDisabledInSys = false;
};
class DlpInfos
{
public:
/** Constructor.
* @param bEnablePlugins Whether to enable only plugins in aEnDisablePlugins or enable all but those in aEnDisablePlugins.
* @param aEnDisablePlugins The plugin names enabled or disabled according to bEnablePlugins.
* @param aGroups If not empty, the groups the plugins must define to be enabled.
* @param aPluginPaths The paths where plugins can be installed and disable-dlps.txt files defined.
* @param aDisablePaths Additional paths where to find disable-dlps.txt files.
* @param bVerbose
*/
DlpInfos(bool bEnablePlugins, const std::vector<std::string>& aEnDisablePlugins, const std::vector<std::string>& aGroups
, const std::vector<std::string>& aPluginPaths, const std::vector<std::string>& aDisablePaths, bool bVerbose);
......@@ -88,7 +98,7 @@ private:
void getDir(bool bEnablePlugins, const std::vector<std::string>& aEnDisablePlugins
, std::vector<DlpInfo>& aNameFiles, const std::string& sDirPath);
static bool parseDlpInfo(DlpInfo& oInfo);
static bool parseDisabledNamesFile(const std::string& sFile, std::vector<DlpInfo>& aDlps);
static bool parseDisabledNamesFile(const std::string& sFile, std::vector<DlpInfo>& aDlps, bool bDisabledInSys);
static void traverse(DlpInfo& oInfo, std::vector<DlpInfo>& aDlps, std::vector<DlpInfo>& aOrderedDlps);
static bool dirExists(const std::string& sPath);
private:
......
......@@ -17,6 +17,8 @@ DefineCommonCompileOptions()
# Source files (and headers only used for building)
set(STMMI_PLUGINS_SOURCES
${PROJECT_SOURCE_DIR}/src/config.h
${PROJECT_SOURCE_DIR}/src/sysdata.h
${PROJECT_SOURCE_DIR}/src/sysdata.cc
${PROJECT_SOURCE_DIR}/src/main.cc
)
......
......@@ -55,19 +55,10 @@ std::vector<std::string> getDataDirs()
return aDataDirs;
}
std::string getUserDataDir()
const char* getUserDataDir()
{
static const char* const s_p0UserDataDir = "@STMMI_PKG_USER_DATA_DIR@";
const char* p0Home = ::secure_getenv("HOME");
std::string sHome{p0Home};
if (sHome.empty()) {
return sHome; //--------------------------------------------------------
}
std::string sUserDataDir{s_p0UserDataDir};
if (sUserDataDir.empty()) {
return sUserDataDir; //-------------------------------------------------
}
return sHome + "/" + sUserDataDir;
return s_p0UserDataDir;
}
} // namespace Config
......
......@@ -34,7 +34,7 @@ const std::string& getVersionString();
std::vector<std::string> getDataDirs();
std::string getUserDataDir();
const char* getUserDataDir();
} // namespace Config
......
This diff is collapsed.
/*
* Copyright © 2019 Stefano Marsili, <stemars@gmx.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>
*/
/*
* File: sysdata.cc
*/
#include "sysdata.h"
#include "config.h"
#include <cassert>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <unistd.h>
#include <pwd.h>
#include <string.h>
namespace stmi
{
SysData SysData::getSysData()
{
SysData oSysData{};
oSysData.m_aDataPaths = Config::getDataDirs();
const std::string sUserDataDir = Config::getUserDataDir();
const auto nEffectiveUID = ::geteuid();
oSysData.m_nUID = nEffectiveUID;
oSysData.m_nGID = ::getegid();
if (nEffectiveUID == 0) {
oSysData.m_bIsRoot = true;
char* p0SudoUserId = ::getenv("SUDO_USER");
errno = 0;
::passwd* p0PwdData = ::getpwnam((p0SudoUserId != nullptr) ? p0SudoUserId : "root");
if (p0PwdData == nullptr) {
oSysData.m_sError = ::strerror(errno);
} else {
oSysData.m_nUID = p0PwdData->pw_uid;
oSysData.m_nGID = p0PwdData->pw_gid;
const char* p0HomePath = p0PwdData->pw_dir;
oSysData.m_sLocalDataPath = std::string(p0HomePath) + "/" + sUserDataDir;
if (p0SudoUserId == nullptr) {
std::cerr << "Root user is not supposed to have a home directory." << '\n';
std::cerr << "If you really want to create or modify file" << '\n';
std::cerr << "\'" << oSysData.m_sLocalDataPath << "/" << DlpInfos::s_sDisabledDlpsFile << "'" << '\n';
std::cerr << "do it manually!" << '\n';
oSysData.m_sLocalDataPath.clear();
}
}
} else {
// normal user
errno = 0;
::passwd* p0PwdData = ::getpwuid(nEffectiveUID);
if (p0PwdData == nullptr) {
oSysData.m_sError = ::strerror(errno);
} else {
const char* p0HomePath = p0PwdData->pw_dir;
oSysData.m_sLocalDataPath = std::string(p0HomePath) + "/" + sUserDataDir;
}
}
oSysData.m_aDisablePaths = oSysData.m_aDataPaths;
std::vector<std::string> aExtraDisablePaths;
if (! oSysData.m_sLocalDataPath.empty()) {
oSysData.m_aDisablePaths.push_back(oSysData.m_sLocalDataPath);
aExtraDisablePaths.push_back(oSysData.m_sLocalDataPath);
}
oSysData.m_refDlpInfos = std::make_unique<DlpInfos>(false, std::vector<std::string>{}, std::vector<std::string>{}
, oSysData.m_aDataPaths, aExtraDisablePaths, false);
return oSysData;
}
const std::vector<std::string>& SysData::getDisablePaths() const
{
return m_aDisablePaths;
}
const DlpInfos& SysData::getDlpInfos() const
{
return *m_refDlpInfos;
}
const DlpInfo* SysData::findPlugin(const std::string& sPluginName) const
{
const std::vector<DlpInfo>& aDlps = getDlpInfos().getOrderedDlps();
const auto itFind = std::find_if(aDlps.begin(), aDlps.end(), [&](const DlpInfo& oDlpInfo)
{
return (oDlpInfo.m_sName == sPluginName);
});
const bool bFound = (itFind != aDlps.end());
return (bFound ? &(*itFind) : nullptr);
}
int SysData::dropPrivileges() const
{
// drop privileges, so that the ownership of the file isn't root
auto nRet = ::setgid(m_nGID);
if (nRet == -1) {
std::cerr << "Error: " << ::strerror(errno) << ". Couldn't set group id to " << m_nGID << "." << '\n';
return EXIT_FAILURE; //-------------------------------------
}
nRet = ::setuid(m_nUID);
if (nRet == -1) {
std::cerr << "Error: " << ::strerror(errno) << ". Couldn't set user id to " << m_nUID << "." << '\n';
return EXIT_FAILURE; //-------------------------------------
}
return EXIT_SUCCESS;
}
std::string SysData::getVersionString()
{
return Config::getVersionString();
}
} // namespace stmi
/*
* Copyright © 2019 Stefano Marsili, <stemars@gmx.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>
*/
/*
* File: sysdata.h
*/
#ifndef STMI_SYS_DATA_H
#define STMI_SYS_DATA_H
#include "dlpinfos.h"
#include <vector>
#include <string>
#include <memory>
namespace stmi
{
using std::unique_ptr;
class SysData
{
public:
static SysData getSysData();
const std::string& getError() const { return m_sError; }
static std::string getVersionString();
const DlpInfos& getDlpInfos() const;
const DlpInfo* findPlugin(const std::string& sPluginName) const;
/** The paths where disable-dlps.txt files can be found.
* If not empty the getLocalDataPath() is the last.
* @return The paths.
*/
const std::vector<std::string>& getDisablePaths() const;
/** The local path.
* Ex. /home/john/.local/share/etc/stmm-input-dl
* @return Can be empty (root).
*/
const std::string& getLocalDataPath() const { return m_sLocalDataPath; }
const std::vector<std::string>& getSysDataPaths() const { return m_aDataPaths; }
bool isRoot() const { return m_bIsRoot; }
int dropPrivileges() const;
private:
std::vector<std::string> m_aDataPaths; // need root access, usually: {/usr/local/etc/stmm-input-dl, /etc/stmm-input-dl}
std::string m_sLocalDataPath; // in user's $HOME, ex. /home/john/.local/etc/stmm-input-dl
std::string m_sError;
bool m_bIsRoot = false;
int32_t m_nUID = -1; // The user. If isRoot() is true, the user that called sudo.
int32_t m_nGID = -1; // The group. If isRoot() is true, the group that called sudo.
unique_ptr<DlpInfos> m_refDlpInfos;
std::vector<std::string> m_aDisablePaths; // m_aDataPaths + [m_sLocalDataPath]
};
#endif /* STMI_SYS_DATA_H */
} // namespace stmi
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment