wxWidgets/include/wx/secretstore.h
Lauri Nurmi 83c6edcc32 Always call wxSecureZeroMemory() to wipe memory in wxSecretValue
Replaces a call to MSW native ::SecureZeroMemory(), and calls to plain
memset().
2022-06-04 15:14:09 +03:00

262 lines
7.8 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: wx/secretstore.h
// Purpose: Storing and retrieving secrets using OS-provided facilities.
// Author: Vadim Zeitlin
// Created: 2016-05-27
// Copyright: (c) 2016 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_SECRETSTORE_H_
#define _WX_SECRETSTORE_H_
#include "wx/defs.h"
#include "wx/string.h"
#if wxUSE_SECRETSTORE
// Initial version of wxSecretStore required passing user name to Load(), which
// didn't make much sense without support for multiple usernames per service,
// so the API was changed to load the username too. Test for this symbol to
// distinguish between the old and the new API, it wasn't defined before the
// API change.
#define wxHAS_SECRETSTORE_LOAD_USERNAME
class wxSecretStoreImpl;
class wxSecretValueImpl;
// ----------------------------------------------------------------------------
// Represents a secret value, e.g. a password string.
// ----------------------------------------------------------------------------
// This is an immutable value-like class which tries to ensure that the secret
// value will be wiped out from memory once it's not needed any more.
class WXDLLIMPEXP_BASE wxSecretValue
{
public:
// Creates an empty secret value (not the same as an empty password).
wxSecretValue() : m_impl(NULL) { }
// Creates a secret value from the given data.
wxSecretValue(size_t size, const void *data)
: m_impl(NewImpl(size, data))
{
}
// Creates a secret value from string.
explicit wxSecretValue(const wxString& secret)
{
const wxScopedCharBuffer buf(secret.utf8_str());
m_impl = NewImpl(buf.length(), buf.data());
}
wxSecretValue(const wxSecretValue& other);
wxSecretValue& operator=(const wxSecretValue& other);
~wxSecretValue();
// Check if a secret is not empty.
bool IsOk() const { return m_impl != NULL; }
// Compare with another secret.
bool operator==(const wxSecretValue& other) const;
bool operator!=(const wxSecretValue& other) const
{
return !(*this == other);
}
// Get the size, in bytes, of the secret data.
size_t GetSize() const;
// Get read-only access to the secret data.
//
// Don't assume it is NUL-terminated, use GetSize() instead.
const void *GetData() const;
// Get the secret data as a string.
//
// Notice that you may want to overwrite the string contents after using it
// by calling WipeString().
wxString GetAsString(const wxMBConv& conv = wxConvWhateverWorks) const;
// Erase the given area of memory overwriting its presumably sensitive
// content.
static void Wipe(size_t size, void *data);
// Overwrite the contents of the given wxString.
static void WipeString(wxString& str);
private:
// This method is implemented in platform-specific code and must return a
// new heap-allocated object initialized with the given data.
static wxSecretValueImpl* NewImpl(size_t size, const void *data);
// This ctor is only used by wxSecretStore and takes ownership of the
// provided existing impl pointer.
explicit wxSecretValue(wxSecretValueImpl* impl) : m_impl(impl) { }
wxSecretValueImpl* m_impl;
friend class wxSecretStore;
};
// ----------------------------------------------------------------------------
// A collection of secrets, sometimes called a key chain.
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_BASE wxSecretStore
{
public:
// Returns the default secrets collection to use.
//
// Currently this is the only way to create a secret store object. In the
// future we could add more factory functions to e.g. create non-persistent
// stores or allow creating stores corresponding to the native facilities
// being used (e.g. specify schema name under Linux or a SecKeychainRef
// under OS X).
static wxSecretStore GetDefault();
// This class has no default ctor, use GetDefault() instead.
// But it can be copied, a copy refers to the same store as the original.
wxSecretStore(const wxSecretStore& store);
// Dtor is not virtual, this class is not supposed to be derived from.
~wxSecretStore();
// Check if this object is valid, i.e. can be used, and optionally fill in
// the provided error message string if it isn't.
bool IsOk(wxString* errmsg = NULL) const;
// Store a username/password combination.
//
// The service name should be user readable and unique.
//
// If a secret with the same service name already exists, it will be
// overwritten with the new value.
//
// Returns false after logging an error message if an error occurs,
// otherwise returns true indicating that the secret has been stored.
bool Save(const wxString& service,
const wxString& username,
const wxSecretValue& password);
// Look up the username/password for the given service.
//
// If no username/password is found for the given service, false is
// returned.
//
// Otherwise the function returns true and updates the provided user name
// and password arguments.
bool Load(const wxString& service,
wxString& username,
wxSecretValue& password) const;
// Delete a previously stored username/password combination.
//
// If anything was deleted, returns true. Otherwise returns false and
// logs an error if any error other than not finding any matches occurred.
bool Delete(const wxString& service);
private:
// Ctor takes ownership of the passed pointer.
explicit wxSecretStore(wxSecretStoreImpl* impl) : m_impl(impl) { }
wxSecretStoreImpl* const m_impl;
};
#else // !wxUSE_SECRETSTORE
#include "wx/utils.h"
// Provide stand in for wxSecretValue allowing to use it without having #if
// wxUSE_SECRETSTORE checks everywhere. Unlike the real version, this class
// doesn't provide any added security.
class wxSecretValue
{
public:
wxSecretValue() { m_valid = false; }
wxSecretValue(size_t size, const void *data)
{
Init(size, data);
}
explicit wxSecretValue(const wxString& secret)
{
const wxScopedCharBuffer buf(secret.utf8_str());
Init(buf.length(), buf.data());
}
bool IsOk() const { return m_valid; }
bool operator==(const wxSecretValue& other) const
{
return m_valid == other.m_valid && m_data == other.m_data;
}
bool operator!=(const wxSecretValue& other) const
{
return !(*this == other);
}
size_t GetSize() const { return m_data.utf8_str().length(); }
const void *GetData() const { return m_data.utf8_str().data(); }
wxString GetAsString(const wxMBConv& conv = wxConvWhateverWorks) const
{
wxUnusedVar(conv);
return m_data;
}
static void Wipe(size_t size, void *data) { wxSecureZeroMemory(data, size); }
static void WipeString(wxString& str)
{
str.assign(str.length(), '*');
str.clear();
}
private:
void Init(size_t size, const void *data)
{
m_data = wxString::From8BitData(static_cast<const char*>(data), size);
}
wxString m_data;
bool m_valid;
};
#endif // wxUSE_SECRETSTORE/!wxUSE_SECRETSTORE
// Helper class ensuring WipeString() is called.
//
// It should only be used as a local variable and never polymorphically.
class wxSecretString : public wxString
{
public:
wxSecretString()
{
}
wxSecretString(const wxString& value)
: wxString(value)
{
}
explicit wxSecretString(const wxSecretValue& value)
: wxString(value.GetAsString())
{
}
~wxSecretString()
{
wxSecretValue::WipeString(*this);
}
};
#endif // _WX_SECRETSTORE_H_