Handling of secrets in memory
The password of the logged-in user has to survive for the whole life of the domain because it is needed for relogin (reconnect after a lost connection, domain switch, repository clean). It must never be present in the process memory in a readable form (9984).
lcbase::Secret
TahitiBase/lcsecret.h provides the container used for every long-living
secret:
lcbase::Secretholds the value obfuscated
lcbase::Secret::Clearscoped access to the plaintext, wipes it in the destructor
lcbase::Secret::WipeGuardwipes a foreign
std::stringon scope exitlcbase::wipeString()overwrite and release a std string
lcbase::wipeBuffer()overwrite a raw buffer
Typical usage:
lcbase::Secret::Clear pass(pDomainCfg->getLoginPassword());
pDomainImpl->activate(user, pass.get(), mode, msg, tahitiException);
Never copy the value out of the Clear scope.
Obfuscation is done by CryptProtectMemory / CryptUnprotectMemory with
the CRYPTPROTECTMEMORY_SAME_PROCESS flag, so the key is managed by the
operating system and is not part of the process image. Other platforms use a
key generated once per process. The value is padded to 16 bytes (PKCS#7), so
the length of the password is hidden as well.
The level of protection is obfuscation. It prevents finding the password by
scanning a memory dump, a crash dump or the page file. It is not a defence
against code running inside the process; a debugger attached to the process
can call CryptUnprotectMemory as well.
Where the password is stored
TahitiDomainConfiguration::m_loginPasswordThe one long-living copy. It is intentionally not a configuration item, so it cannot be read by a generic
getValue()call and can never be written into a configuration file. Set byDomainImpl::activate(), wiped byDomainImpl::deactivate().TciolDep2::passCopy inside the DEP2 module. Needed because reconnect authorizes again without asking Tahiti for the configuration.
Everything else is short-living and has to be wiped:
Connection.Optionsexpanded by%TAHITI_PASSWORD%(TahitiComm::initialize),the
ParseOptionsmap in the communication module (ParseOptions::wipe),CStringof the password controls (TahitiCommon::WipeString),m_PasswordofTahitiCommandLineInfo.
Rules
Never add the password as a configuration item.
Never log the password, not even on the debug level, and never log an expanded
Connection.Optionsstring.Keep every
Secret::Clearscope as short as possible.Wipe every
std::stringorCStringwhich held a secret;clear()andEmpty()only change the length, they do not overwrite the buffer.The
/pcommand line switch puts the password into the command line of the process, where any local process can read it. It is kept for compatibility only; do not use it in new deployments.