/* * * Copyright (c) 2020-2023, David Xanatos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser 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 . */ #pragma once #include #include #include "qsbieapi_global.h" #include "SbieStatus.h" #include "SbieTrace.h" #include "./Sandboxie/SandBox.h" #include "./Sandboxie/BoxedProcess.h" class QSBIEAPI_EXPORT CSbieAPI : public QThread { Q_OBJECT public: CSbieAPI(QObject* parent = 0); virtual ~CSbieAPI(); static bool IsSbieCtrlRunning(); static bool TerminateSbieCtrl(); virtual SB_STATUS Connect(bool takeOver, bool withQueue); virtual SB_STATUS Disconnect(); virtual bool IsConnected() const; static bool IsWow64(); virtual QString GetVersion(); virtual SB_STATUS TakeOver(); virtual SB_STATUS WatchIni(bool bEnable = true, bool bReLoad = true); virtual QString GetSbiePath() const { return m_SbiePath; } virtual QString GetIniPath() const { return m_IniPath; } virtual QString ResolveAbsolutePath(const QString& Path); virtual void UpdateDriveLetters(); virtual QString Nt2DosPath(QString NtPath, bool* pOk = NULL) const; static quint32 GetVolumeSN(const wchar_t* path, std::wstring* pLabel = NULL); virtual SB_STATUS ReloadBoxes(bool bForceUpdate = false); static SB_STATUS ValidateName(const QString& BoxName); virtual QString MkNewName(QString Name); virtual SB_STATUS CreateBox(const QString& BoxName, bool bReLoad = true); virtual SB_STATUS UpdateProcesses(int iKeep, bool bAllSessions); virtual QMap GetAllBoxes() { return m_SandBoxes; } virtual QMap GetAllProcesses() { return m_BoxedProxesses; } virtual CSandBoxPtr GetBoxByProcessId(quint32 ProcessId) const; virtual CSandBoxPtr GetBoxByName(const QString &BoxName) const { return m_SandBoxes.value(BoxName.toLower()); } virtual CBoxedProcessPtr GetProcessById(quint32 ProcessId) const; virtual SB_STATUS TerminateAll(bool bNoExceptions = false); virtual SB_STATUS SetProcessExemption(quint32 process_id, quint32 action_id, bool NewState); virtual bool GetProcessExemption(quint32 process_id, quint32 action_id); virtual QString GetBoxedPath(const QString& BoxName, const QString& Path); virtual QString GetBoxedPath(CSandBox* pBox, const QString& Path, const QString& Snapshot = QString()); virtual QString GetRealPath(CSandBox* pBox, const QString& Path); enum ESetMode { eIniUpdate = 0, eIniAppend, eIniInsert, eIniDelete }; // Config virtual SB_STATUS ReloadConfig(bool ReconfigureDrv = false); virtual SB_STATUS ReloadCert(); virtual void CommitIniChanges(); virtual QString SbieIniGet(const QString& Section, const QString& Setting, quint32 Index = 0, qint32* ErrCode = NULL); virtual QString SbieIniGet2(const QString& Section, const QString& Setting, quint32 Index = 0, bool bWithGlobal = false, bool bNoExpand = true, bool withTemplates = false); virtual QString SbieIniGetEx(const QString& Section, const QString& Setting); virtual SB_STATUS SbieIniSet(const QString& Section, const QString& Setting, const QString& Value, ESetMode Mode = eIniUpdate, bool bRefresh = true); virtual bool IsBox(const QString& BoxName, bool& bIsEnabled); virtual QSharedPointer GetGlobalSettings() const { return m_pGlobalSection; } virtual QSharedPointer GetUserSettings() const { return m_pUserSection; } virtual QString GetCurrentUserName() const { return m_UserName; } virtual QString GetCurrentUserSid() const { return m_UserSid; } virtual bool IsConfigLocked(); virtual SB_STATUS UnlockConfig(const QString& Password); virtual SB_STATUS LockConfig(const QString& NewPassword); virtual void ClearPassword(); virtual SB_RESULT(QByteArray) RC4Crypt(const QByteArray& Data); virtual bool GetDriverInfo(quint32 InfoClass, void* pBuffer, size_t Size); enum EFeatureFlags { eSbieFeatureWFP = 0x00000001, eSbieFeatureObCB = 0x00000002, eSbieFeaturePMod = 0x00000004, eSbieFeatureAppC = 0x00000008, eSbieFeatureSbiL = 0x00000010, eSbieFeatureARM64 = 0x40000000, eSbieFeatureCert = 0x80000000 }; virtual quint32 GetFeatureFlags(); virtual QString GetFeatureStr(); virtual int IsDyndataActive(); // Forced Processes virtual SB_STATUS DisableForceProcess(bool Set, int Seconds = 0); virtual bool AreForceProcessDisabled(); // Mount Manager virtual SB_STATUS ImBoxCreate(CSandBox* pBox, quint64 uSizeKb, const QString& Password = QString()); virtual SB_STATUS ImBoxMount(CSandBox* pBox, const QString& Password = QString(), bool bProtect = false, bool bAutoUnmount = false); virtual SB_STATUS ImBoxUnmount(CSandBox* pBox); virtual SB_RESULT(QStringList) ImBoxEnum(); virtual SB_RESULT(QVariantMap) ImBoxQuery(const QString& Root = QString()); //virtual SB_STATUS ImBoxUpdate( // todo // Monitor virtual SB_STATUS EnableMonitor(bool Enable); virtual bool IsMonitoring(); virtual const QVector& GetTrace(); virtual int GetTraceCount() const { return m_TraceList.count(); } virtual void ClearTrace() { m_TraceList.clear(); QMutexLocker Lock(&m_TraceMutex); m_TraceCache.clear(); } // Other virtual quint64 QueryProcessInfo(quint32 ProcessId, quint32 InfoClass = 0); virtual QString GetSbieMsgStr(quint32 code, quint32 Lang = 1033); enum EStartFlags { eStartDefault = 0, eStartElevated = 1, eStartFCP = 2 }; virtual SB_RESULT(quint32) RunStart(const QString& BoxName, const QString& Command, EStartFlags Flags = eStartDefault, const QString& WorkingDir = QString(), QProcess* pProcess = NULL); virtual QString GetStartPath() const; virtual quint32 GetSessionID() const; virtual SB_STATUS SetSecureParam(const QString& Name, const void* data, size_t size); virtual SB_STATUS GetSecureParam(const QString& Name, void* data, size_t size, quint32* size_out = NULL, bool bVerify = false); enum ESbieQueuedRequests { ePrintSpooler = -1, eInvalidQueuedRequests = 0, eFileMigration = 1, eInetBlockade = 2, }; void LoadEventLog(); virtual SB_RESULT(int) RunUpdateUtility(const QStringList& Params, quint32 Elevate = 0, bool Wait = false); public slots: virtual void SendReplyData(quint32 RequestId, const QVariantMap& Result); signals: void StatusChanged(); void ConfigReloaded(); //void LogMessage(const QString& Message, bool bNotify = true); void LogSbieMessage(quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId); void ProcessBoxed(quint32 ProcessId, const QString& Path, const QString& Box, quint32 ParentId, const QString& CmdLine); void FileToRecover(const QString& BoxName, const QString& FilePath, const QString& BoxPath, quint32 ProcessId); void BoxAdded(const CSandBoxPtr& pBox); void BoxOpened(const CSandBoxPtr& pBox); void BoxClosed(const CSandBoxPtr& pBox); void BoxRemoved(const CSandBoxPtr& pBox); void NotAuthorized(bool bLoginRequired, bool &bRetry); void QueuedRequest(quint32 ClientPid, quint32 ClientTid, quint32 RequestId, const QVariantMap& Data); protected slots: virtual void OnIniChanged(const QString &path); virtual void OnReloadConfig(); virtual CBoxedProcessPtr OnProcessBoxed(quint32 ProcessId, const QString& Path, const QString& Box, quint32 ParentId, const QString& CmdLine); protected: friend class CSandBox; friend class CBoxedProcess; virtual SB_STATUS ReloadConf(quint32 flags, quint32 SessionId = -1); virtual CSandBox* NewSandBox(const QString& BoxName, class CSbieAPI* pAPI); virtual CBoxedProcess* NewBoxedProcess(quint32 ProcessId, class CSandBox* pBox); virtual QString GetSbieHome() const; virtual QString GetIniPath(bool* IsHome) const; virtual QString GetUserSection(QString* pUserName = NULL, bool* pIsAdmin = NULL) const; virtual bool HasProcesses(const QString& BoxName); virtual bool GetQueue(); virtual bool GetLog(); virtual bool GetMonitor(); virtual SB_STATUS TerminateAll(const QString& BoxName); virtual SB_STATUS Terminate(quint32 ProcessId); virtual SB_STATUS SetSuspendedAll(const QString& BoxName, bool bSuspended); virtual SB_STATUS SetSuspended(quint32 ProcessId, bool bSuspended); virtual SB_STATUS RunSandboxed(const QString& BoxName, const QString& Command, QString WrkDir = QString(), quint32 Flags = 0); virtual SB_STATUS UpdateBoxPaths(CSandBox* pSandBox); virtual SB_STATUS UpdateProcessInfo(const CBoxedProcessPtr& pProcess); virtual SB_STATUS GetProcessInfo(quint32 ProcessId, quint32* pParentId = NULL, quint32* pInfo = NULL, bool* pSuspended = NULL, QString* pImagePath = NULL, QString* pCommandLine = NULL, QString* pWorkingDir = NULL); virtual void GetUserPaths(); virtual QString GetDeviceMap(); virtual QByteArray MakeEnvironment(bool AddDeviceMap); virtual void run(); QMap m_SandBoxes; QMap m_BoxedProxesses; mutable QMutex m_TraceMutex; QVector m_TraceCache; QVector m_TraceList; mutable QReadWriteLock m_DriveLettersMutex; struct SDrive { QString Letter; QString NtPath; enum EType { EVolume = 0, EShare } Type; QString Aux; }; QMap m_DriveLetters; QString m_SbiePath; QString m_IniPath; QFileSystemWatcher m_IniWatcher; bool m_IniReLoad; bool m_bReloadPending; bool m_bBoxesDirty; bool m_bWithQueue; bool m_bTerminate; QSharedPointerm_pGlobalSection; QSharedPointerm_pUserSection; QString m_UserName; QString m_UserSid; QString m_ProgramDataDir; QString m_PublicDir; QString m_UserDir; public: struct SScopedVoid { ~SScopedVoid() { if (ptr) free(ptr); } inline void Assign(void* p) {Q_ASSERT(!ptr); ptr = p;} protected: SScopedVoid(void* p) : ptr(p) {} void* ptr; }; template struct SScoped : public SScopedVoid { SScoped(void* p = NULL) : SScopedVoid(p) {} inline T* Detache() {T* p = ptr; ptr = NULL; return p;} inline T* Value() {return (T*)ptr;} inline T* operator->() const {return (T*)ptr;} inline T& operator*() const {return *((T*)ptr);} inline operator T*() const {return (T*)ptr;} private: SScoped(const SScoped& other) {} // copying is explicitly forbidden SScoped& operator=(T* p) {return *this;} SScoped& operator=(const SScoped& other) {return *this;} }; private: mutable QMutex m_ThreadMutex; mutable QWaitCondition m_ThreadWait; SB_STATUS CallServer(void* req, SScopedVoid* prpl) const; SB_STATUS SbieIniSet(void *RequestBuf, void *pPasswordWithinRequestBuf, const QString& SectionName, const QString& SettingName); struct SSbieAPI* m; };