4154fbb8a3
This is less secure, but more convenient, than using raw pointers and in most cases the password will already be stored in a wxString anyhow.
238 lines
6.4 KiB
C++
238 lines
6.4 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: secretstore.cpp
|
|
// Purpose: wxWidgets sample showing the use of wxSecretStore class
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2016-05-27
|
|
// Copyright: (c) 2016 Vadim Zeitlin <vadim@wxwidgets.org>
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx/wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#include "wx/secretstore.h"
|
|
|
|
#include "wx/init.h"
|
|
#include "wx/crt.h"
|
|
#include "wx/log.h"
|
|
|
|
bool Save(wxSecretStore& store, const wxString& service, const wxString& user)
|
|
{
|
|
char password[4096];
|
|
wxPrintf("Enter the password for %s/%s (echoing NOT disabled): ",
|
|
service, user);
|
|
|
|
if ( !wxFgets(password, WXSIZEOF(password), stdin) )
|
|
{
|
|
wxFprintf(stderr, "Password not stored.\n");
|
|
return false;
|
|
}
|
|
|
|
size_t size = wxStrlen(password);
|
|
if ( size )
|
|
{
|
|
// Strip trailing new line.
|
|
--size;
|
|
password[size] = 0;
|
|
}
|
|
|
|
wxSecretValue secret(size, password);
|
|
|
|
// The password data was copied into wxSecretValue, don't leave it lying
|
|
// around in the stack unnecessarily.
|
|
wxSecretValue::Wipe(size, password);
|
|
|
|
if ( !store.Save(service, user, secret) )
|
|
{
|
|
wxFprintf(stderr,
|
|
"Failed to save the password for %s/%s.\n",
|
|
service, user);
|
|
return false;
|
|
}
|
|
|
|
wxPrintf("Password for %s/%s saved.\n",
|
|
service, user);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Load(wxSecretStore& store, const wxString& service, const wxString& user)
|
|
{
|
|
wxSecretValue secret = store.Load(service, user);
|
|
if ( !secret.IsOk() )
|
|
{
|
|
wxFprintf(stderr,
|
|
"Failed to load the password for %s/%s.\n",
|
|
service, user);
|
|
return false;
|
|
}
|
|
|
|
// Create a temporary variable just to make it possible to wipe it after
|
|
// using it.
|
|
wxString str(secret.GetAsString());
|
|
|
|
const size_t size = secret.GetSize();
|
|
wxPrintf("Password for %s/%s is %zu bytes long: \"%s\"\n",
|
|
service, user, size, str);
|
|
|
|
wxSecretValue::WipeString(str);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Delete(wxSecretStore& store, const wxString& service, const wxString& user)
|
|
{
|
|
if ( !store.Delete(service, user) )
|
|
{
|
|
wxFprintf(stderr,
|
|
"Password for %s/%s not deleted.\n",
|
|
service, user);
|
|
return false;
|
|
}
|
|
|
|
wxPrintf("Stored password for %s/%s deleted.\n",
|
|
service, user);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool PrintResult(bool ok)
|
|
{
|
|
wxPuts(ok ? "ok" : "ERROR");
|
|
return ok;
|
|
}
|
|
|
|
bool SelfTest(wxSecretStore& store, const wxString& service, const wxString& user)
|
|
{
|
|
wxPrintf("Running the tests...\n");
|
|
|
|
const wxSecretValue secret1(6, "secret");
|
|
|
|
wxPrintf("Storing the password:\t");
|
|
bool ok = store.Save(service, user, secret1);
|
|
if ( !PrintResult(ok) )
|
|
{
|
|
// The rest of the tests will probably fail too, no need to continue.
|
|
wxPrintf("Bailing out.\n");
|
|
return false;
|
|
}
|
|
|
|
wxPrintf("Loading the password:\t");
|
|
wxSecretValue secret = store.Load(service, user);
|
|
ok = secret.IsOk() &&
|
|
secret.GetSize() == secret1.GetSize() &&
|
|
memcmp(secret.GetData(), secret1.GetData(), secret1.GetSize()) == 0;
|
|
if ( !PrintResult(secret == secret1) )
|
|
ok = false;
|
|
|
|
// Overwriting the password should work.
|
|
const wxSecretValue secret2(6, "privet");
|
|
|
|
wxPrintf("Changing the password:\t");
|
|
if ( PrintResult(store.Save(service, user, secret2)) )
|
|
{
|
|
wxPrintf("Reloading the password:\t");
|
|
secret = store.Load(service, user);
|
|
if ( !PrintResult(secret == secret2) )
|
|
ok = false;
|
|
}
|
|
else
|
|
ok = false;
|
|
|
|
wxPrintf("Deleting the password:\t");
|
|
if ( !PrintResult(store.Delete(service, user)) )
|
|
ok = false;
|
|
|
|
// This is supposed to fail now.
|
|
wxPrintf("Deleting it again:\t");
|
|
if ( !PrintResult(!store.Delete(service, user)) )
|
|
ok = false;
|
|
|
|
// And loading should fail too.
|
|
wxPrintf("Loading after deleting:\t");
|
|
if ( !PrintResult(!store.Load(service, user).IsOk()) )
|
|
ok = false;
|
|
|
|
if ( ok )
|
|
wxPrintf("All tests passed!\n");
|
|
|
|
return ok;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
// To complement the standard EXIT_{SUCCESS,FAILURE}.
|
|
const int EXIT_SYNTAX = 2;
|
|
|
|
wxInitializer initializer;
|
|
if ( !initializer )
|
|
{
|
|
fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if ( argc != 4 )
|
|
{
|
|
wxFprintf(stderr,
|
|
"Usage: %s {save|load|delete|selftest} <service> <user>\n"
|
|
"\n"
|
|
"Sample showing wxSecretStore class functionality.\n"
|
|
"Specify one of the commands to perform the corresponding\n"
|
|
"function call. The \"service\" and \"user\" arguments are\n"
|
|
"mandatory, \"save\" will also prompt for password.\n",
|
|
argv[0]);
|
|
return EXIT_SYNTAX;
|
|
}
|
|
|
|
wxSecretStore store = wxSecretStore::GetDefault();
|
|
if ( !store.IsOk() )
|
|
{
|
|
wxFprintf(stderr, "Failed to create default secret store.\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
const wxString operation = argv[1];
|
|
const wxString service = argv[2];
|
|
const wxString user = argv[3];
|
|
|
|
bool ok;
|
|
if ( operation == "save" )
|
|
{
|
|
ok = Save(store, service, user);
|
|
}
|
|
else if ( operation == "load" )
|
|
{
|
|
ok = Load(store, service, user);
|
|
}
|
|
else if ( operation == "delete" )
|
|
{
|
|
ok = Delete(store, service, user);
|
|
}
|
|
else if ( operation == "selftest" )
|
|
{
|
|
ok = SelfTest(store, service, user);
|
|
}
|
|
else
|
|
{
|
|
wxFprintf(stderr,
|
|
"Unknown operation \"%s\", expected \"save\", \"load\" or "
|
|
"\"delete\".\n",
|
|
operation);
|
|
return EXIT_SYNTAX;
|
|
}
|
|
|
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
}
|