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;
 | 
						|
}
 |