From 9236ad2b2ddf76728e87f21c6486e66067526e2c Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:31:06 +0100 Subject: [PATCH] security enhancements and small formatting changes - wipe crypto password on all crypto folder unlock return paths - wipe passwords on logout/unlink - *pwd reference setup only after online check succeeds --- pclsync/putil.h | 8 ++++++++ pclsync_lib.cpp | 41 ++++++++++++++++++++++++++++++++++------- pclsync_lib.h | 13 ++++++++++--- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/pclsync/putil.h b/pclsync/putil.h index a956188..8d391e9 100644 --- a/pclsync/putil.h +++ b/pclsync/putil.h @@ -1,6 +1,10 @@ #ifndef __PUTIL_H #define __PUTIL_H +#ifdef __cplusplus +extern "C" { +#endif + #include #define NTO_STR(s) TO_STR(s) @@ -9,4 +13,8 @@ void putil_wipe(void *mem, size_t sz); +#ifdef __cplusplus +} +#endif + #endif diff --git a/pclsync_lib.cpp b/pclsync_lib.cpp index 609f2ee..77a1df0 100644 --- a/pclsync_lib.cpp +++ b/pclsync_lib.cpp @@ -43,6 +43,7 @@ #include "pshm.h" #include "pdevice.h" #include "pcommands.h" +#include "putil.h" #include "pclsync_lib.h" @@ -70,6 +71,18 @@ const std::string &clib::pclsync_lib::get_crypto_pass() { return crypto_pass_; }; +void clib::pclsync_lib::wipe_crypto_pass() { + this->wipe(crypto_pass_); +} + +void clib::pclsync_lib::wipe_password() { + this->wipe(password_); +} + +void clib::pclsync_lib::wipe_tfa_code() { + this->wipe(tfa_code_); +} + const std::string &clib::pclsync_lib::get_mount() { return mount_; } void clib::pclsync_lib::set_trusted_device(bool arg) { @@ -201,21 +214,22 @@ void event_handler(psync_eventtype_t event, psync_eventdata_t eventdata) { } static int lib_setup_cripto() { - const char *pwd = clib::pclsync_lib::get_lib().get_crypto_pass().c_str(); - if(pstatus_get(PSTATUS_TYPE_ONLINE) == PSTATUS_ONLINE_OFFLINE) { std::cout << "Cannot unlock crypto folder, pcloudcc is offline" << std::endl; return PSYNC_CRYPTO_CANT_CONNECT; } + const char *pwd = clib::pclsync_lib::get_lib().get_crypto_pass().c_str(); if(!pcryptofolder_issetup()) { std::cout << "crypto is not setup, setting it up now..." << std::endl; if(int ret = pcryptofolder_setup(pwd, "no hint") != PSYNC_CRYPTO_SETUP_SUCCESS) { std::cout << "crypto setup failed, error code was " << ret << std::endl; + clib::pclsync_lib::get_lib().wipe_crypto_pass(); return ret; } if(int ret = pcryptofolder_mkdir(0, "Crypto", NULL, NULL) != PSYNC_CRYPTO_SUCCESS) { std::cout << "failed to create crypto directory, error code was" << ret << std::endl; + clib::pclsync_lib::get_lib().wipe_crypto_pass(); return ret; } std::cout << "crypto folder was setup using the provided password, " @@ -225,9 +239,11 @@ static int lib_setup_cripto() { if(int ret = pcryptofolder_unlock(pwd) != PSYNC_CRYPTO_START_SUCCESS) { std::cout << "Failed to unlock crypto folder: error code was " << ret << std::endl; + clib::pclsync_lib::get_lib().wipe_crypto_pass(); return ret; } + clib::pclsync_lib::get_lib().wipe_crypto_pass(); clib::pclsync_lib::get_lib().crypto_on_ = true; return 0; } @@ -470,22 +486,33 @@ int clib::pclsync_lib::init() { } int clib::pclsync_lib::login(const char *user, const char *pass, int save) { - set_username(user); - set_password(pass); - set_savepass(bool(save)); + username_ = user; + password_ = pass; + save_pass_ = save; psync_set_user_pass(user, pass, save); return 0; } int clib::pclsync_lib::logout() { - set_password(""); + wipe_password(); psync_logout(); return 0; } int clib::pclsync_lib::unlink() { set_username(""); - set_password(""); + wipe_password(); psync_unlink(); return 0; } + +void clib::pclsync_lib::wipe(std::string& s) { + if (s.empty()) { + return; + } + + void* mem = &s[0]; + size_t sz = s.size(); + putil_wipe(mem, sz); + s.clear(); +} \ No newline at end of file diff --git a/pclsync_lib.h b/pclsync_lib.h index 6b3cb08..8c78716 100644 --- a/pclsync_lib.h +++ b/pclsync_lib.h @@ -77,6 +77,12 @@ public: void set_daemon(bool p); void set_status_callback(status_callback_t p); + // FIXME: not ideal, better if programmer does not have to remember to do + // this, but good enough for now... + void wipe_password(); + void wipe_crypto_pass(); + void wipe_tfa_code(); + // Singleton static pclsync_lib &get_lib(); @@ -103,9 +109,9 @@ public: private: std::string username_; - std::string password_; - std::string tfa_code_; - std::string crypto_pass_; + std::string password_; // SENSITIVE, use wipe function + std::string tfa_code_; // SENSITIVE, use wipe function + std::string crypto_pass_; // SENSITIVE, use wipe function std::string mount_; @@ -113,6 +119,7 @@ private: bool daemon_; void do_get_pass_from_console(std::string &password); + void wipe(std::string& str); }; } // namespace clibrary } // namespace console_client