Add wxSecretStore

Add a new class allowing to store passwords and other sensitive information
using the OS-provided facilities.

Add implementations for all the main platforms, documentation and a new sample
(which contains an ad hoc unit test as the real unit test for this class would
probably be a bad idea as it wouldn't run in non-interactive contexts and
could show OS level dialog boxes if it did).
This commit is contained in:
Vadim Zeitlin
2016-05-29 01:13:44 +02:00
parent 21d90d48ba
commit 675d9d779d
48 changed files with 5288 additions and 68 deletions

View File

@@ -433,6 +433,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//

View File

@@ -277,6 +277,14 @@
# endif
#endif /* !defined(wxUSE_REGEX) */
#ifndef wxUSE_SECRETSTORE
# ifdef wxABORT_ON_CONFIG_ERROR
# error "wxUSE_SECRETSTORE must be defined, please read comment near the top of this file."
# else
# define wxUSE_SECRETSTORE 1
# endif
#endif /* !defined(wxUSE_SECRETSTORE) */
#ifndef wxUSE_STDPATHS
# ifdef wxABORT_ON_CONFIG_ERROR
# error "wxUSE_STDPATHS must be defined, please read comment near the top of this file."

View File

@@ -31,6 +31,12 @@ public:
return &m_error;
}
// Check if any error actually occurred.
operator bool() const
{
return m_error != NULL;
}
wxString GetMessage() const
{
return wxString::FromUTF8(m_error->message);

View File

@@ -434,6 +434,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//

View File

@@ -434,6 +434,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//

View File

@@ -177,6 +177,12 @@
#endif /* __GNUWIN32__ */
/* MinGW32 doesn't provide wincred.h defining the API needed by this */
#ifdef __MINGW32_TOOLCHAIN__
#undef wxUSE_SECRETSTORE
#define wxUSE_SECRETSTORE 0
#endif
#if !wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
# undef wxUSE_CHECKLISTBOX
# define wxUSE_CHECKLISTBOX 0

View File

@@ -434,6 +434,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//

View File

@@ -435,6 +435,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//

View File

@@ -0,0 +1,93 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/private/secretstore.h
// Purpose: Classes used in wxSecretStore implementation only.
// Author: Vadim Zeitlin
// Created: 2016-05-27
// Copyright: (c) 2016 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PRIVATE_SECRETSTORE_H_
#define _WX_PRIVATE_SECRETSTORE_H_
#include "wx/object.h" // wxRefCounter
// Both of the implementation classes here are ref-counted so that the
// corresponding public objects could be copied cheaply and, in the case of
// wxSecretValue, also to avoid having the secret in more than one place in
// memory at a time.
// ----------------------------------------------------------------------------
// Class holding wxSecretValue data
// ----------------------------------------------------------------------------
// This is a common base class for our own and libsecret-based implementations.
class wxSecretValueImpl : public wxRefCounter
{
public:
wxSecretValueImpl()
{
}
virtual size_t GetSize() const = 0;
virtual const void *GetData() const = 0;
};
// Trivial common implementation of wxSecretValueImpl used under MSW and OS X.
#if defined(__WINDOWS__) || defined(__DARWIN__)
class wxSecretValueGenericImpl : public wxSecretValueImpl
{
public:
wxSecretValueGenericImpl(size_t size, const void *data)
: m_size(size),
m_data(new char[size])
{
memcpy(m_data, data, size);
}
virtual ~wxSecretValueGenericImpl()
{
if ( m_data )
{
wxSecretValue::Wipe(m_size, m_data);
delete [] m_data;
}
}
virtual size_t GetSize() const wxOVERRIDE { return m_size; }
virtual const void *GetData() const wxOVERRIDE { return m_data; }
private:
const size_t m_size;
char* const m_data;
};
#endif // MSW or OSX
// ----------------------------------------------------------------------------
// Base class for wxSecretStore implementations
// ----------------------------------------------------------------------------
// All its methods are similar to the methods of the public class except that
// they work with the implementation rather than public objects and they all
// take an extra "wxString&" output parameter which is filled with the low
// level error message in case of an error. This message will be logged by
// wxSecretStore itself, wxSecretStoreImpl methods shouldn't do any logging on
// their own.
class wxSecretStoreImpl : public wxRefCounter
{
public:
virtual bool Save(const wxString& service,
const wxString& user,
const wxSecretValueImpl& secret,
wxString& errmsg) = 0;
virtual wxSecretValueImpl* Load(const wxString& service,
const wxString& user,
wxString& errmsg) const = 0;
virtual bool Delete(const wxString& service,
const wxString& user,
wxString& errmsg) = 0;
};
#endif // _WX_PRIVATE_SECRETSTORE_H_

141
include/wx/secretstore.h Normal file
View File

@@ -0,0 +1,141 @@
///////////////////////////////////////////////////////////////////////////////
// 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"
#if wxUSE_SECRETSTORE
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);
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;
// Erase the given area of memory overwriting its presumably sensitive
// content.
static void Wipe(size_t size, void *data);
private:
// 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.
bool IsOk() const { return m_impl != NULL; }
// Store a secret.
//
// The service name should be user readable and unique.
//
// If a secret with the same service name and user 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& user,
const wxSecretValue& secret);
// Look up a secret.
//
// If no such secret is found, an empty value is returned, but no error is
// logged (however an error may still be logged if some other error occurs).
// If more than one secret matching the parameters exist, only one
// arbitrarily chosen of them is returned (notice that it's impossible to
// get into such situation using this API only).
wxSecretValue Load(const wxString& service, const wxString& user) const;
// Delete a previously stored secret.
//
// If there is more than one matching secret, all of them are deleted.
//
// If any secrets were deleted, returns true. Otherwise returns false and
// logs an error if any error other than not finding any matching secrets
// occurred.
bool Delete(const wxString& service, const wxString& user);
private:
// Ctor takes ownership of the passed pointer.
explicit wxSecretStore(wxSecretStoreImpl* impl) : m_impl(impl) { }
wxSecretStoreImpl* const m_impl;
};
#endif // wxUSE_SECRETSTORE
#endif // _WX_SECRETSTORE_H_

View File

@@ -430,6 +430,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//

View File

@@ -433,6 +433,13 @@
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_FSVOLUME 1
// Use wxSecretStore class for storing passwords using OS-specific facilities.
//
// Default is 1
//
// Recommended setting: 1 (but may be safely disabled if you don't use it)
#define wxUSE_SECRETSTORE 1
// Use wxStandardPaths class which allows to retrieve some standard locations
// in the file system
//