From ea4ddc4cee44d4ce8853dcd0272dffb520668c8d Mon Sep 17 00:00:00 2001 From: Anatolii Sakhnik Date: Thu, 1 Aug 2013 09:17:09 +0300 Subject: [PATCH] Use tabs for indentation, spaces for alignment. Use anonymous namespace instead of static Open-webOS-DCO-1.0-Signed-off-by: Anatolii Sakhnik Change-Id: Iaea6e3863b31b34eccb627d4dc68d96ca3b2566f --- .gitignore | 1 + configure.ac | 68 ++-- doc/Makefile.am | 4 +- src/App.cc | 868 +++++++++++++++++++++-------------------- src/App.hh | 74 ++-- src/Database.cc | 264 ++++++------- src/Database.hh | 82 ++-- src/Debug.cc | 50 +-- src/Debug.hh | 2 +- src/Defs.hh | 2 +- src/Entry.cc | 192 ++++----- src/Entry.hh | 116 +++--- src/Field.cc | 26 +- src/Field.hh | 26 +- src/File3.cc | 450 ++++++++++----------- src/File3.hh | 68 ++-- src/Gcrypt.cc | 52 +-- src/Gcrypt.hh | 4 +- src/GtkEmitter.cc | 104 ++--- src/GtkEmitter.hh | 10 +- src/Hmac.cc | 46 +-- src/Hmac.hh | 18 +- src/IEmitter.hh | 8 +- src/KeyStretch.cc | 24 +- src/KeyStretch.hh | 22 +- src/Makefile.am | 13 +- src/Memory.cc | 26 +- src/Memory.hh | 42 +- src/Random.cc | 8 +- src/Random.hh | 36 +- src/Sha256.cc | 48 +-- src/Sha256.hh | 20 +- src/StdoutEmitter.cc | 6 +- src/StdoutEmitter.hh | 8 +- src/Terminal.cc | 614 ++++++++++++++--------------- src/Terminal.hh | 64 +-- src/Twofish.cc | 98 ++--- src/Twofish.hh | 72 ++-- src/main.cc | 54 +-- test/EntryTest.cc | 38 +- test/File3Test.cc | 96 ++--- test/KeyStretchTest.cc | 42 +- test/Makefile.am | 16 +- 43 files changed, 1951 insertions(+), 1931 deletions(-) diff --git a/.gitignore b/.gitignore index adf3e0a..8ac6366 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ missing /nbproject/private/ /nbproject test-driver +compile diff --git a/configure.ac b/configure.ac index 80aab63..64e28f8 100644 --- a/configure.ac +++ b/configure.ac @@ -29,55 +29,55 @@ BOOST_CPPFLAGS=$BOOST_CPPFLAGS" -DBOOST_DISABLE_THREADS" dnl -------------------------------------------------------------------------- dnl X clipboard support AC_ARG_ENABLE( - [xclip], - AS_HELP_STRING([--enable-xclip=[yes]], - [Enable copying to the X clipboard (yes,no,gtk2,gtk3)]) + [xclip], + AS_HELP_STRING([--enable-xclip=[yes]], + [Enable copying to the X clipboard (yes,no,gtk2,gtk3)]) ) AC_MSG_CHECKING(--enable-xclip argument) AS_CASE([$enable_xclip], - [no], [AC_MSG_RESULT(no X clipboard support)], - [yes|""],[AC_MSG_RESULT(yes - automatic X clipboard support) - enable_xclip=yes], - [gtk*], [AC_MSG_RESULT([yes - using $enable_xclip])], - [AC_MSG_RESULT([Sorry, $enable_xclip X clipboard is not supported])] + [no], [AC_MSG_RESULT(no X clipboard support)], + [yes|""],[AC_MSG_RESULT(yes - automatic X clipboard support) + enable_xclip=yes], + [gtk*], [AC_MSG_RESULT([yes - using $enable_xclip])], + [AC_MSG_RESULT([Sorry, $enable_xclip X clipboard is not supported])] ) AS_IF([test "x$enable_xclip" = "xgtk3"],[ - PKG_CHECK_MODULES([GTK], - [gtk+-3.0], - [gtk_found=yes]) + PKG_CHECK_MODULES([GTK], + [gtk+-3.0], + [gtk_found=yes]) ]) AS_IF([test "x$enable_xclip" = "xgtk2"],[ - PKG_CHECK_MODULES([GTK], - [gtk+-2.0], - [gtk_found=yes]) + PKG_CHECK_MODULES([GTK], + [gtk+-2.0], + [gtk_found=yes]) ]) AS_IF([test "x$enable_xclip" = "xyes"],[ - PKG_CHECK_MODULES([GTK], - [gtk+-3.0], - [gtk_found=yes enable_xclip=gtk3], - [gtk_found=no]) + PKG_CHECK_MODULES([GTK], + [gtk+-3.0], + [gtk_found=yes enable_xclip=gtk3], + [gtk_found=no]) ]) AS_IF([test "x$enable_xclip" = "xyes"],[ - PKG_CHECK_MODULES([GTK], - [gtk+-2.0], - [gtk_found=yes enable_xclip=gtk2], - [gtk_found=no]) + PKG_CHECK_MODULES([GTK], + [gtk+-2.0], + [gtk_found=yes enable_xclip=gtk2], + [gtk_found=no]) ]) AS_IF([test "x$gtk_found" = "xyes"],[ - AC_DEFINE([ENABLE_GTK],[1],[Define to compile with GTK+ support]) - AC_DEFINE([ENABLE_XCLIP],[1],[Define to compile with X clipboard support]) + AC_DEFINE([ENABLE_GTK],[1],[Define to compile with GTK+ support]) + AC_DEFINE([ENABLE_XCLIP],[1],[Define to compile with X clipboard support]) ]) AM_CONDITIONAL([ENABLE_GTK],[test "x$gtk_found" = "xyes"]) AS_IF([test "x$enable_xclip" = "xyes"],[ - AC_MSG_ERROR([No suitable X clipboard support library found]) + AC_MSG_ERROR([No suitable X clipboard support library found]) ]) AM_CONDITIONAL([ENABLE_XCLIP],[test "x$enable_xclip" != "xno"]) @@ -86,19 +86,19 @@ dnl -------------------------------------------------------------------------- dnl Documentation support AC_ARG_ENABLE(doc, - AS_HELP_STRING([--enable-doc=yes], [Build man pages (yes by default)]), - [wantdoc=$enableval], [wantdoc=yes]) + AS_HELP_STRING([--enable-doc=yes], [Build man pages (yes by default)]), + [wantdoc=$enableval], [wantdoc=yes]) AC_MSG_CHECKING([for building documentation]) AS_IF([test "x$wantdoc" = "xyes"], [ - AC_MSG_RESULT([yes]) - AC_CHECK_PROGS([ASCIIDOC], [asciidoc]) - AS_IF([test $ASCIIDOC], [ - ], [ - AC_MSG_ERROR([asciidoc is required to build man pages]) - ])], + AC_MSG_RESULT([yes]) + AC_CHECK_PROGS([ASCIIDOC], [asciidoc]) + AS_IF([test $ASCIIDOC], [ + ], [ + AC_MSG_ERROR([asciidoc is required to build man pages]) + ])], [ - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) ]) AM_CONDITIONAL(WANT_DOC, [test "x$wantdoc" = "xyes"]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 89222c7..f233f7c 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -19,8 +19,8 @@ man_MANS = gpwsafe.1 gpwsafe.1: gpwsafe.1.txt Makefile.am $(AM_V_GEN)a2x $(A2X_OPTS) \ - --asciidoc-opts="$(ASCIIDOC_OPTS) --out-file=./$@.xml" \ - $(srcdir)/$@.txt + --asciidoc-opts="$(ASCIIDOC_OPTS) --out-file=./$@.xml" \ + $(srcdir)/$@.txt # Files that should be removed MOSTLYCLEANFILES = gpwsafe.1 diff --git a/src/App.cc b/src/App.cc index 456ad5d..d6905f1 100644 --- a/src/App.cc +++ b/src/App.cc @@ -41,499 +41,507 @@ using namespace std; char const *const DEFAULT_FILE = ".gpwsafe.psafe3"; cApp::cApp(char const *program_name) - : _program_name(program_name) - , _command(_C_NOP) - , _emitter( + : _program_name(program_name) + , _command(_C_NOP) + , _emitter( #ifdef ENABLE_XCLIP - _E_XCLIP + _E_XCLIP #else - _E_STDOUT + _E_STDOUT #endif //ENABLE_XCLIP ) - , _user(false) - , _pass(false) - , _argument(0) + , _user(false) + , _pass(false) + , _argument(0) { - char const *home = getenv("HOME"); - if (home) - { - _file_name = home; - _file_name += "/"; - } - _file_name += DEFAULT_FILE; + char const *home = getenv("HOME"); + if (home) + { + _file_name = home; + _file_name += "/"; + } + _file_name += DEFAULT_FILE; } void cApp::_Usage(bool fail) { - ostream &os = fail ? cerr : cout; - if (!fail) - { - os << _program_name - << " - command line tool compatible with" - " Conterpane's PasswordSafe\n"; - } - os << "Usage: " << _program_name << " [OPTION] command [ARG]\n"; - os << "Options:\n" - " -f, --file=DATABASE_FILE specify the database file (~/" - << DEFAULT_FILE << " by default)\n" - " -u, --user emit username of listed account\n" - " -p, --pass emit password of listed account\n" - " -E, --echo force echoing of entry to stdout\n" + ostream &os = fail ? cerr : cout; + if (!fail) + { + os << _program_name + << " - command line tool compatible with" + " Conterpane's PasswordSafe\n"; + } + os << "Usage: " << _program_name << " [OPTION] command [ARG]\n"; + os << "Options:\n" + " -f, --file=DATABASE_FILE specify the database file (~/" + << DEFAULT_FILE << " by default)\n" + " -u, --user emit username of listed account\n" + " -p, --pass emit password of listed account\n" + " -E, --echo force echoing of entry to stdout\n" #ifdef ENABLE_XCLIP - " -x, --xclip force copying of entry to X selection\n" + " -x, --xclip force copying of entry to X selection\n" #endif //ENABLE_XCLIP - " -h, --help display this help and exit\n" - " -V, --version output version information and exit\n" - "Commands:\n" - " --create create an empty database\n" - " [--list] [REGEX] list all [matching] entries." - " If either -u or -p\n" - " are given, only one entry may match\n" - " -a, --add [NAME] add an entry\n" - " -e, --edit REGEX edit an entry\n" - ; - os << flush; - throw ExitEx(fail ? 1 : 0); + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n" + "Commands:\n" + " --create create an empty database\n" + " [--list] [REGEX] list all [matching] entries." + " If either -u or -p\n" + " are given, only one entry may match\n" + " -a, --add [NAME] add an entry\n" + " -e, --edit REGEX edit an entry\n" + ; + os << flush; + throw ExitEx(fail ? 1 : 0); } void cApp::Init(int argc, char *argv[]) { - while (true) - { - static struct option long_options[] = - { - { "help", no_argument, 0, 'h' }, - { "file", required_argument, 0, 'f' }, - { "list", no_argument, 0, 'L' }, - { "create", no_argument, 0, 'C' }, - { "add", no_argument, 0, 'a' }, - { "edit", no_argument, 0, 'e' }, - { "user", no_argument, 0, 'u' }, - { "pass", no_argument, 0, 'p' }, - { "echo", no_argument, 0, 'E' }, + while (true) + { + static struct option long_options[] = + { + { "help", no_argument, 0, 'h' }, + { "file", required_argument, 0, 'f' }, + { "list", no_argument, 0, 'L' }, + { "create", no_argument, 0, 'C' }, + { "add", no_argument, 0, 'a' }, + { "edit", no_argument, 0, 'e' }, + { "user", no_argument, 0, 'u' }, + { "pass", no_argument, 0, 'p' }, + { "echo", no_argument, 0, 'E' }, #ifdef ENABLE_XCLIP - { "xclip", no_argument, 0, 'x' }, + { "xclip", no_argument, 0, 'x' }, #endif //ENABLE_XCLIP - { 0, 0, 0, 0 } - }; - char const *const short_options = - "h" // help - "V" // version - "a" // add - "e" // edit - "f:" // file - "u" // user - "p" // pass - "E" // force echo to stdout + { 0, 0, 0, 0 } + }; + char const *const short_options = + "h" // help + "V" // version + "a" // add + "e" // edit + "f:" // file + "u" // user + "p" // pass + "E" // force echo to stdout #ifdef ENABLE_XCLIP - "x" // force copying to xclip + "x" // force copying to xclip #endif //ENABLE_XCLIP - ""; - int option_index = 0; - int c = getopt_long(argc, argv, - short_options, - long_options, &option_index); - if (-1 == c) - break; - switch (c) - { - case 'h': - return _Usage(false); - case 'V': - cout << _program_name << " " << VERSION << endl; - throw ExitEx(0); - case 'f': - _file_name = optarg; - break; - case 'L': - if (_command != _C_NOP) - return _Usage(false); - _command = _C_LIST; - break; - case 'a': - if (_command != _C_NOP) - return _Usage(false); - _command = _C_ADD; - break; - case 'e': - if (_command != _C_NOP) - return _Usage(false); - _command = _C_EDIT; - break; - case 'C': - if (_command != _C_NOP) - return _Usage(false); - _command = _C_CREATE; - break; - case 'u': - _user = true; - break; - case 'p': - _pass = true; - break; - case 'E': - _emitter = _E_STDOUT; - break; + ""; + int option_index = 0; + int c = getopt_long(argc, argv, + short_options, + long_options, &option_index); + if (-1 == c) + break; + switch (c) + { + case 'h': + return _Usage(false); + case 'V': + cout << _program_name << " " << VERSION << endl; + throw ExitEx(0); + case 'f': + _file_name = optarg; + break; + case 'L': + if (_command != _C_NOP) + return _Usage(false); + _command = _C_LIST; + break; + case 'a': + if (_command != _C_NOP) + return _Usage(false); + _command = _C_ADD; + break; + case 'e': + if (_command != _C_NOP) + return _Usage(false); + _command = _C_EDIT; + break; + case 'C': + if (_command != _C_NOP) + return _Usage(false); + _command = _C_CREATE; + break; + case 'u': + _user = true; + break; + case 'p': + _pass = true; + break; + case 'E': + _emitter = _E_STDOUT; + break; #ifdef ENABLE_XCLIP - case 'x': - _emitter = _E_XCLIP; - break; + case 'x': + _emitter = _E_XCLIP; + break; #endif //ENABLE_XCLIP - default: - return _Usage(true); - }; - } - - if (_command == _C_NOP) - _command = _C_LIST; - - if ((_command == _C_LIST || _command == _C_ADD || _command == _C_EDIT) - && optind != argc) - { - _argument = argv[optind++]; - } - - if (optind != argc) - { - cerr << "Too many arguments" << endl; - throw ExitEx(1); - } + default: + return _Usage(true); + }; + } + + if (_command == _C_NOP) + _command = _C_LIST; + + if ((_command == _C_LIST || _command == _C_ADD || _command == _C_EDIT) + && optind != argc) + { + _argument = argv[optind++]; + } + + if (optind != argc) + { + cerr << "Too many arguments" << endl; + throw ExitEx(1); + } } void cApp::Run() { - try - { - _Run(); - } - catch (std::exception const &e) - { - cerr << "Exception: " << e.what() << endl; - throw ExitEx(1); - } + try + { + _Run(); + } + catch (std::exception const &e) + { + cerr << "Exception: " << e.what() << endl; + throw ExitEx(1); + } } void cApp::_Run() { - switch (_command) - { - case _C_LIST: - return _DoList(); - case _C_CREATE: - return _DoCreate(); - case _C_ADD: - return _DoAdd(); - case _C_EDIT: - return _DoEdit(); - default: - cerr << "Command " << _command << " isn't implemented" << endl; - throw ExitEx(1); - } + switch (_command) + { + case _C_LIST: + return _DoList(); + case _C_CREATE: + return _DoCreate(); + case _C_ADD: + return _DoAdd(); + case _C_EDIT: + return _DoEdit(); + default: + cerr << "Command " << _command << " isn't implemented" << endl; + throw ExitEx(1); + } } -static cDatabase::PtrT _OpenDatabase(string const &file_name) +namespace { + +cDatabase::PtrT _OpenDatabase(string const &file_name) { - cDatabase::PtrT database(new cDatabase); - string prompt = "Enter password for " + file_name + ": "; - StringX password = cTerminal::GetPassword(prompt); - database->Read(file_name, password); - return database; + cDatabase::PtrT database(new cDatabase); + string prompt = "Enter password for " + file_name + ": "; + StringX password = cTerminal::GetPassword(prompt); + database->Read(file_name, password); + return database; } +} //namespace + void cApp::_PrintIntention(iEmitter const *emitter) { - if (!_user && !_pass) - return; - string subject; - if (_user) - subject += "login"; - if (_pass) - { - if (_user) - subject += " and "; - subject += "password"; - } - emitter->PrintIntention(subject); + if (!_user && !_pass) + return; + string subject; + if (_user) + subject += "login"; + if (_pass) + { + if (_user) + subject += " and "; + subject += "password"; + } + emitter->PrintIntention(subject); } +namespace { + template -static bool _CheckSingleEntry(EntriesT const &entries) +bool _CheckSingleEntry(EntriesT const &entries) { - assert(!entries.empty() && "Must be analyzed separately"); - - int count = std::distance(entries.begin(), entries.end()); - if (1 == count) - return true; - - cerr << "More than one matching entry: "; - int j = 0; - for (auto it = entries.begin(); - it != entries.end() && j != 3; ++it, ++j) - { - if (j) - cerr << ", "; - cerr << it->first; - } - int rest = count - j; - if (rest) - cerr << ", ... (" << rest << " more)"; - cerr << " ." << endl; - return false; + assert(!entries.empty() && "Must be analyzed separately"); + + int count = std::distance(entries.begin(), entries.end()); + if (1 == count) + return true; + + cerr << "More than one matching entry: "; + int j = 0; + for (auto it = entries.begin(); + it != entries.end() && j != 3; ++it, ++j) + { + if (j) + cerr << ", "; + cerr << it->first; + } + int rest = count - j; + if (rest) + cerr << ", ... (" << rest << " more)"; + cerr << " ." << endl; + return false; } +} //namespace; + void cApp::_DoList() { - unique_ptr emitter; - switch (_emitter) - { - case _E_STDOUT: - emitter.reset(new cStdoutEmitter); - break; + unique_ptr emitter; + switch (_emitter) + { + case _E_STDOUT: + emitter.reset(new cStdoutEmitter); + break; #ifdef ENABLE_XCLIP - case _E_XCLIP: + case _E_XCLIP: #ifdef ENABLE_GTK - emitter.reset(new cGtkEmitter); + emitter.reset(new cGtkEmitter); #endif //ENABLE_GTK - break; + break; #endif //ENABLE_XCLIP - } - - assert(emitter.get() && "Not implemented _emitter"); - - _PrintIntention(emitter.get()); - - cDatabase::PtrT database = _OpenDatabase(_file_name); - - auto match = database->Find(_argument); - if (match.empty()) - { - cerr << "No matching entries found" << endl; - throw ExitEx(1); - } - - if (!_user && !_pass) - { - for (auto const &title_entry : match) - cout << title_entry.first << endl; - return; - } - - if (!_CheckSingleEntry(match)) - throw ExitEx(1); - - auto const &title_entry = match.front(); - if (_user) - { - emitter->Emit("username for " + title_entry.first, - title_entry.second->GetUser()); - } - if (_pass) - { - emitter->Emit("password for " + title_entry.first, - title_entry.second->GetPass()); - } + } + + assert(emitter.get() && "Not implemented _emitter"); + + _PrintIntention(emitter.get()); + + cDatabase::PtrT database = _OpenDatabase(_file_name); + + auto match = database->Find(_argument); + if (match.empty()) + { + cerr << "No matching entries found" << endl; + throw ExitEx(1); + } + + if (!_user && !_pass) + { + for (auto const &title_entry : match) + cout << title_entry.first << endl; + return; + } + + if (!_CheckSingleEntry(match)) + throw ExitEx(1); + + auto const &title_entry = match.front(); + if (_user) + { + emitter->Emit("username for " + title_entry.first, + title_entry.second->GetUser()); + } + if (_pass) + { + emitter->Emit("password for " + title_entry.first, + title_entry.second->GetPass()); + } } void cApp::_DoCreate() { - if (!::access(_file_name.c_str(), F_OK)) - { - cerr << _file_name << " already exists" << endl; - throw ExitEx(1); - } - - string prompt1 = "Enter passphrase for " + _file_name + ": "; - StringX pass1 = cTerminal::GetPassword(prompt1); - string prompt2 = "Reenter passphrase for " + _file_name + ": "; - StringX pass2 = cTerminal::GetPassword(prompt2); - if (pass1 != pass2) - { - cerr << "Passphrases do not match" << endl; - throw ExitEx(1); - } - - cDatabase::PtrT database(new cDatabase); - database->Create(); - database->Write(_file_name, pass1); + if (!::access(_file_name.c_str(), F_OK)) + { + cerr << _file_name << " already exists" << endl; + throw ExitEx(1); + } + + string prompt1 = "Enter passphrase for " + _file_name + ": "; + StringX pass1 = cTerminal::GetPassword(prompt1); + string prompt2 = "Reenter passphrase for " + _file_name + ": "; + StringX pass2 = cTerminal::GetPassword(prompt2); + if (pass1 != pass2) + { + cerr << "Passphrases do not match" << endl; + throw ExitEx(1); + } + + cDatabase::PtrT database(new cDatabase); + database->Create(); + database->Write(_file_name, pass1); } void cApp::_DoAdd() { - // Copied from pwsafe - char const *name = _argument; - - cDatabase::PtrT database = _OpenDatabase(_file_name); - cEntry::PtrT entry(cEntry::Create()); - - if (name) - { - // group.title may be given via command line - char const *dot = strchr(name, '.'); - if (dot && - dot != name && - dot[1] && - strrchr(name, '.') == dot) - { - entry->SetTitle(dot + 1); - entry->SetGroup(StringX(name, dot - name)); - } - else - { - entry->SetTitle(name); - } - } + // Copied from pwsafe + char const *name = _argument; + + cDatabase::PtrT database = _OpenDatabase(_file_name); + cEntry::PtrT entry(cEntry::Create()); + + if (name) + { + // group.title may be given via command line + char const *dot = strchr(name, '.'); + if (dot && + dot != name && + dot[1] && + strrchr(name, '.') == dot) + { + entry->SetTitle(dot + 1); + entry->SetGroup(StringX(name, dot - name)); + } + else + { + entry->SetTitle(name); + } + } // FIXME: Limit count of retries. - while (true) - { - if (entry->GetTitle().empty()) - entry->SetTitle(cTerminal::GetText("name: ")); - if (entry->GetGroup().empty()) - entry->SetGroup(cTerminal::GetText("group []: ")); - - if (database->HasEntry(entry->GetFullTitle())) - { - cerr << entry->GetFullTitle() << " already exists" << endl; - if (name) - throw ExitEx(1); - entry->SetTitle(""); - entry->SetGroup(""); - } - else if (!entry->GetTitle().empty()) - break; - } - - entry->SetUser(cTerminal::GetText("username: ")); - if (entry->GetUser().empty()) - { - // FIXME!!! - throw ExitEx(1); - //e.default_login = getyn("use default username ("+e.the_default_login+") ? [n] ", false); - } - - StringX pass = - cTerminal::EnterPassword("password [return for random]: ", - "password again: "); - entry->SetPass(pass); - - entry->SetNotes(cTerminal::GetText("notes: ")); - - database->AddEntry(entry); - database->Write(); + while (true) + { + if (entry->GetTitle().empty()) + entry->SetTitle(cTerminal::GetText("name: ")); + if (entry->GetGroup().empty()) + entry->SetGroup(cTerminal::GetText("group []: ")); + + if (database->HasEntry(entry->GetFullTitle())) + { + cerr << entry->GetFullTitle() << " already exists" << endl; + if (name) + throw ExitEx(1); + entry->SetTitle(""); + entry->SetGroup(""); + } + else if (!entry->GetTitle().empty()) + break; + } + + entry->SetUser(cTerminal::GetText("username: ")); + if (entry->GetUser().empty()) + { + // FIXME!!! + throw ExitEx(1); + //e.default_login = getyn("use default username ("+e.the_default_login+") ? [n] ", false); + } + + StringX pass = + cTerminal::EnterPassword("password [return for random]: ", + "password again: "); + entry->SetPass(pass); + + entry->SetNotes(cTerminal::GetText("notes: ")); + + database->AddEntry(entry); + database->Write(); } void cApp::_DoEdit() { - char const *query = _argument; - if (!query) - { - cerr << "An entry must be specified" << endl; - throw ExitEx(1); - } - - cDatabase::PtrT database = _OpenDatabase(_file_name); - auto entries = database->Find(query); - if (entries.empty()) - { - cerr << "No matching entries found" << endl; - throw ExitEx(1); - } - if (!_CheckSingleEntry(entries)) - throw ExitEx(1); - - // Original entry - cEntry::PtrT e_orig = entries.front().second; - - // Copied from pwsafe - cEntry::PtrT e = e_orig->Copy(); // make a local copy to edit - - while (true) - { - e->SetTitle(cTerminal::GetText("name: [" + e_orig->GetTitle() + "] ", - e_orig->GetTitle())); - e->SetGroup(cTerminal::GetText("group: [" + e_orig->GetGroup() + "] ", - e_orig->GetGroup())); - if ((e->GetTitle() == e_orig->GetTitle() && - e->GetGroup() == e_orig->GetGroup()) || - !database->HasEntry(e->GetFullTitle())) - // e.name cannot be empty b/c if the user entered an empty string - // they got the old name - break; - cout << e->GetFullTitle() << " already exists" << endl; - } - - // FIXME!!!: What's the default login? - //if (e.default_login) - // e.default_login = getyn("keep default username ("+e_orig.the_default_login+") ? [y]", true); - //if (!e.default_login) { - // e.login = gettxt("username: ["+e_orig.login+"] ", e_orig.login); - // if (e.login.empty() && !e_orig.default_login) // no point in asking if they just disabled default login - // e.default_login = getyn("use default username ("+e_orig.the_default_login+") ? [n]", false); - //} - - while (true) - { - if (!cTerminal::GetYN("change password ? [n] ", false)) - break; - - StringX new_pw = - cTerminal::EnterPassword("new password: [return for random] ", - "new password again: "); - if (new_pw.empty() && !e->GetPass().empty()) - { - if (!cTerminal::GetYN("Confirm changing to an empty password?" - " [n] ")) - continue; - } - e->SetPass(new_pw); - break; - } - - e->SetNotes(cTerminal::GetText("notes: [] ", - e_orig->GetNotes())); - - cEntry::DiffT diff = e->Diff(e_orig); - if (diff.empty()) - { - cout << "No change" << endl; - return; - } - - std::string prompt = "Confirm changing "; - for (auto i = diff.begin(); i != diff.end(); ++i) - { - if (i != diff.begin()) - prompt += ", "; - switch (i->type) - { - case cEntry::FT_GROUP: - prompt += "group"; - break; - case cEntry::FT_TITLE: - prompt += "name"; - break; - case cEntry::FT_PASS: - prompt += "password"; - break; - case cEntry::FT_NOTES: - prompt += "notes"; - break; - default: - assert(!"Implement this"); - } - } - prompt += "? [y] "; - if (!cTerminal::GetYN(prompt, true)) - { - cout << "Changes abandoned" << endl; - return; - } - - database->RemoveEntry(e_orig); - database->AddEntry(e); - database->Write(); + char const *query = _argument; + if (!query) + { + cerr << "An entry must be specified" << endl; + throw ExitEx(1); + } + + cDatabase::PtrT database = _OpenDatabase(_file_name); + auto entries = database->Find(query); + if (entries.empty()) + { + cerr << "No matching entries found" << endl; + throw ExitEx(1); + } + if (!_CheckSingleEntry(entries)) + throw ExitEx(1); + + // Original entry + cEntry::PtrT e_orig = entries.front().second; + + // Copied from pwsafe + cEntry::PtrT e = e_orig->Copy(); // make a local copy to edit + + while (true) + { + e->SetTitle(cTerminal::GetText("name: [" + e_orig->GetTitle() + "] ", + e_orig->GetTitle())); + e->SetGroup(cTerminal::GetText("group: [" + e_orig->GetGroup() + "] ", + e_orig->GetGroup())); + if ((e->GetTitle() == e_orig->GetTitle() && + e->GetGroup() == e_orig->GetGroup()) || + !database->HasEntry(e->GetFullTitle())) + // e.name cannot be empty b/c if the user entered an empty string + // they got the old name + break; + cout << e->GetFullTitle() << " already exists" << endl; + } + + // FIXME!!!: What's the default login? + //if (e.default_login) + // e.default_login = getyn("keep default username ("+e_orig.the_default_login+") ? [y]", true); + //if (!e.default_login) { + // e.login = gettxt("username: ["+e_orig.login+"] ", e_orig.login); + // if (e.login.empty() && !e_orig.default_login) // no point in asking if they just disabled default login + // e.default_login = getyn("use default username ("+e_orig.the_default_login+") ? [n]", false); + //} + + while (true) + { + if (!cTerminal::GetYN("change password ? [n] ", false)) + break; + + StringX new_pw = + cTerminal::EnterPassword("new password: [return for random] ", + "new password again: "); + if (new_pw.empty() && !e->GetPass().empty()) + { + if (!cTerminal::GetYN("Confirm changing to an empty password?" + " [n] ")) + continue; + } + e->SetPass(new_pw); + break; + } + + e->SetNotes(cTerminal::GetText("notes: [] ", + e_orig->GetNotes())); + + cEntry::DiffT diff = e->Diff(e_orig); + if (diff.empty()) + { + cout << "No change" << endl; + return; + } + + std::string prompt = "Confirm changing "; + for (auto i = diff.begin(); i != diff.end(); ++i) + { + if (i != diff.begin()) + prompt += ", "; + switch (i->type) + { + case cEntry::FT_GROUP: + prompt += "group"; + break; + case cEntry::FT_TITLE: + prompt += "name"; + break; + case cEntry::FT_PASS: + prompt += "password"; + break; + case cEntry::FT_NOTES: + prompt += "notes"; + break; + default: + assert(!"Implement this"); + } + } + prompt += "? [y] "; + if (!cTerminal::GetYN(prompt, true)) + { + cout << "Changes abandoned" << endl; + return; + } + + database->RemoveEntry(e_orig); + database->AddEntry(e); + database->Write(); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/App.hh b/src/App.hh index 7b9ee17..9bf536d 100644 --- a/src/App.hh +++ b/src/App.hh @@ -31,56 +31,56 @@ namespace gPWS { struct iEmitter; class cApp - : boost::noncopyable + : boost::noncopyable { public: - cApp(char const *program_name); + cApp(char const *program_name); - void Init(int argc, char *argv[]); + void Init(int argc, char *argv[]); - void Run(); + void Run(); - struct ExitEx - { - int retcode; - ExitEx(int retcode_) : retcode(retcode_) { } - }; + struct ExitEx + { + int retcode; + ExitEx(int retcode_) : retcode(retcode_) { } + }; private: - char const *_program_name; - std::string _file_name; - - enum eCommand - { - _C_NOP = 0, - _C_LIST, - _C_CREATE, - _C_ADD, - _C_EDIT - } _command; - - enum eEmitter - { + char const *_program_name; + std::string _file_name; + + enum eCommand + { + _C_NOP = 0, + _C_LIST, + _C_CREATE, + _C_ADD, + _C_EDIT + } _command; + + enum eEmitter + { #ifdef ENABLE_XCLIP - _E_XCLIP, + _E_XCLIP, #endif //ENABLE_XCLIP - _E_STDOUT - } _emitter; + _E_STDOUT + } _emitter; - bool _user; - bool _pass; + bool _user; + bool _pass; - char const *_argument; + char const *_argument; - void _Run(); - void _Usage(bool fail); - void _DoList(); - void _PrintIntention(iEmitter const *emitter); - void _DoCreate(); - void _DoAdd(); - void _DoEdit(); + void _Run(); + void _Usage(bool fail); + void _DoList(); + void _PrintIntention(iEmitter const *emitter); + void _DoCreate(); + void _DoAdd(); + void _DoEdit(); }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Database.cc b/src/Database.cc index 32caf9c..5aaf38e 100644 --- a/src/Database.cc +++ b/src/Database.cc @@ -35,194 +35,194 @@ using namespace std; void *cDatabase::operator new(size_t n) { - return SecureAllocator::allocate(n); + return SecureAllocator::allocate(n); } void cDatabase::operator delete(void *p, size_t n) { - cDatabase *q = reinterpret_cast(p); - return SecureAllocator::deallocate(q, n); + cDatabase *q = reinterpret_cast(p); + return SecureAllocator::deallocate(q, n); } cDatabase::cDatabase() - : _changed(false) + : _changed(false) { - _fields.reserve(0x0F); + _fields.reserve(0x0F); } void cDatabase::Create() { - _fields.clear(); - _changed = false; - - sField::PtrT field(sField::Create()); - - // Insert default version (mock 3.10) - field->type = FT_VERSION; - field->value.clear(); - field->value.push_back(0x0A); - field->value.push_back(0x03); - _AddField(field); - - // Insert new UUID - field->type = FT_UUID; - field->value.resize(16); - boost::uuids::uuid new_uuid = boost::uuids::random_generator()(); - assert(new_uuid.size() == 16); - copy(new_uuid.begin(), new_uuid.end(), field->value.begin()); - _AddField(field); + _fields.clear(); + _changed = false; + + sField::PtrT field(sField::Create()); + + // Insert default version (mock 3.10) + field->type = FT_VERSION; + field->value.clear(); + field->value.push_back(0x0A); + field->value.push_back(0x03); + _AddField(field); + + // Insert new UUID + field->type = FT_UUID; + field->value.resize(16); + boost::uuids::uuid new_uuid = boost::uuids::random_generator()(); + assert(new_uuid.size() == 16); + copy(new_uuid.begin(), new_uuid.end(), field->value.begin()); + _AddField(field); } void cDatabase::Read(string const &fname, StringX const &pass) { - // The database must be clear. - assert(!_changed && "The changes must be written beforehand"); - - _changed = false; - _fname = fname; - _pass = pass; - _file.OpenRead(fname.c_str(), pass); - - // Read header fields first - sField::PtrT field; - while ((field = _file.ReadField())) - { - if (!_AddField(field)) - break; - } - - if (!field) - return; - - cEntry::PtrT entry(cEntry::Create()); - while ((field = _file.ReadField())) - { - if (!entry->AddField(field)) - { - // FIXME: Check if such key already exists. - // Avoid loosing information. - _entries[entry->GetFullTitle()] = entry; - entry = cEntry::Create(); - } - } + // The database must be clear. + assert(!_changed && "The changes must be written beforehand"); + + _changed = false; + _fname = fname; + _pass = pass; + _file.OpenRead(fname.c_str(), pass); + + // Read header fields first + sField::PtrT field; + while ((field = _file.ReadField())) + { + if (!_AddField(field)) + break; + } + + if (!field) + return; + + cEntry::PtrT entry(cEntry::Create()); + while ((field = _file.ReadField())) + { + if (!entry->AddField(field)) + { + // FIXME: Check if such key already exists. + // Avoid loosing information. + _entries[entry->GetFullTitle()] = entry; + entry = cEntry::Create(); + } + } } void cDatabase::Write(string const &fname, StringX const &pass) { - _changed = false; - _file.OpenWrite(fname.c_str(), pass, true); - - for (auto &field : _fields) - { - if (field) - _file.WriteField(field); - } - - // Field terminator - sField::PtrT terminator(sField::Create()); - terminator->type = 0xFF; - terminator->value.clear(); - _file.WriteField(terminator); - - for (auto &title_entry : _entries) - { - auto &entry = title_entry.second; - entry->ForEachField([this](sField::PtrT const &field) { - _file.WriteField(field); - }); - _file.WriteField(terminator); - } - - _file.CloseWrite(); + _changed = false; + _file.OpenWrite(fname.c_str(), pass, true); + + for (auto &field : _fields) + { + if (field) + _file.WriteField(field); + } + + // Field terminator + sField::PtrT terminator(sField::Create()); + terminator->type = 0xFF; + terminator->value.clear(); + _file.WriteField(terminator); + + for (auto &title_entry : _entries) + { + auto &entry = title_entry.second; + entry->ForEachField([this](sField::PtrT const &field) { + _file.WriteField(field); + }); + _file.WriteField(terminator); + } + + _file.CloseWrite(); } void cDatabase::Write() { - assert(!_fname.empty() && !_pass.empty()); + assert(!_fname.empty() && !_pass.empty()); - string new_fname = _fname + ".new"; - string backup = _fname + "~"; + string new_fname = _fname + ".new"; + string backup = _fname + "~"; - ::unlink(new_fname.c_str()); - Write(new_fname, _pass); + ::unlink(new_fname.c_str()); + Write(new_fname, _pass); - // The followin calls will fail unlikely. - ::unlink(backup.c_str()); + // The followin calls will fail unlikely. + ::unlink(backup.c_str()); - if (-1 == ::rename(_fname.c_str(), backup.c_str())) - { - cerr << "Failed to create backup: " << strerror(errno) << endl; - throw runtime_error("File system"); - } + if (-1 == ::rename(_fname.c_str(), backup.c_str())) + { + cerr << "Failed to create backup: " << strerror(errno) << endl; + throw runtime_error("File system"); + } - if (-1 == ::rename(new_fname.c_str(), _fname.c_str())) - { - cerr << "Failed to move new file: " << strerror(errno) << endl; - throw runtime_error("File system"); - } + if (-1 == ::rename(new_fname.c_str(), _fname.c_str())) + { + cerr << "Failed to move new file: " << strerror(errno) << endl; + throw runtime_error("File system"); + } } bool cDatabase::_AddField(sField::PtrT const &field) { - if (field->type == 0xFF) - return false; - if (_fields.size() <= field->type) - _fields.resize(static_cast(field->type) + 1); - _fields[field->type] = field; - return true; + if (field->type == 0xFF) + return false; + if (_fields.size() <= field->type) + _fields.resize(static_cast(field->type) + 1); + _fields[field->type] = field; + return true; } void cDatabase::Dump() const { - for (auto const &field : _fields) - { - if (!field) - continue; - cout << "{0x" - << boost::format("%02X") % unsigned(field->type) - << ", '" - << gPWS::Quote(&field->value[0], field->value.size()) - << "'}" - << endl; - } - cout << "==========" << endl; - - for (auto const &keyval : _entries) - { - auto const &entry = keyval.second; - entry->Dump(); - } + for (auto const &field : _fields) + { + if (!field) + continue; + cout << "{0x" + << boost::format("%02X") % unsigned(field->type) + << ", '" + << gPWS::Quote(&field->value[0], field->value.size()) + << "'}" + << endl; + } + cout << "==========" << endl; + + for (auto const &keyval : _entries) + { + auto const &entry = keyval.second; + entry->Dump(); + } } void cDatabase::AddEntry(cEntry::PtrT const &entry) { - // FIXME: Check if such key already exists. Avoid loosing information. - _entries[entry->GetFullTitle()] = entry; - _changed = true; + // FIXME: Check if such key already exists. Avoid loosing information. + _entries[entry->GetFullTitle()] = entry; + _changed = true; } void cDatabase::RemoveEntry(cEntry::PtrT const &entry) { - _entries.erase(entry->GetFullTitle()); - _changed = true; + _entries.erase(entry->GetFullTitle()); + _changed = true; } bool cDatabase::HasEntry(StringX const &full_title) const { - return _entries.find(full_title) != _entries.end(); + return _entries.find(full_title) != _entries.end(); } cDatabase::FilterRangeT cDatabase::Find(char const *query) const { - auto filter = [query](_TitleEntryT::value_type const &v) - { return !query || v.first.find(query) != v.first.npos; }; - FilterIterT begin(filter, _entries.begin(), _entries.end()); - FilterIterT end(filter, _entries.end(), _entries.end()); - return boost::make_iterator_range(begin, end); + auto filter = [query](_TitleEntryT::value_type const &v) + { return !query || v.first.find(query) != v.first.npos; }; + FilterIterT begin(filter, _entries.begin(), _entries.end()); + FilterIterT end(filter, _entries.end(), _entries.end()); + return boost::make_iterator_range(begin, end); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Database.hh b/src/Database.hh index 2ec4405..f70350d 100644 --- a/src/Database.hh +++ b/src/Database.hh @@ -34,68 +34,68 @@ namespace gPWS { class cDatabase - : boost::noncopyable + : boost::noncopyable { public: - typedef std::shared_ptr PtrT; + typedef std::shared_ptr PtrT; - void *operator new(size_t n); - void operator delete(void *p, size_t n); + void *operator new(size_t n); + void operator delete(void *p, size_t n); - cDatabase(); + cDatabase(); - void Create(); + void Create(); - void Read(std::string const &fname, - StringX const &pass); + void Read(std::string const &fname, + StringX const &pass); - void Write(std::string const &fname, - StringX const &pass); + void Write(std::string const &fname, + StringX const &pass); - // Use the cached file name and password - void Write(); + // Use the cached file name and password + void Write(); - void Dump() const; + void Dump() const; - void AddEntry(cEntry::PtrT const &entry); - void RemoveEntry(cEntry::PtrT const &entry); - bool HasEntry(StringX const &full_title) const; + void AddEntry(cEntry::PtrT const &entry); + void RemoveEntry(cEntry::PtrT const &entry); + bool HasEntry(StringX const &full_title) const; private: - cFile3 _file; - bool _changed; - std::string _fname; // Cached file name - StringX _pass; // Cached password + cFile3 _file; + bool _changed; + std::string _fname; // Cached file name + StringX _pass; // Cached password - enum _eFieldType - { - FT_VERSION = 0x00, - FT_UUID = 0x01, + enum _eFieldType + { + FT_VERSION = 0x00, + FT_UUID = 0x01, - FT_END = 0xFF - }; + FT_END = 0xFF + }; - // Associative vector of fields - typedef std::vector _FieldsT; - // Database header - _FieldsT _fields; + // Associative vector of fields + typedef std::vector _FieldsT; + // Database header + _FieldsT _fields; - // FullTitle -> EntryT - typedef std::map _TitleEntryT; - _TitleEntryT _entries; + // FullTitle -> EntryT + typedef std::map _TitleEntryT; + _TitleEntryT _entries; - bool _AddField(sField::PtrT const &field); + bool _AddField(sField::PtrT const &field); public: - typedef boost::filter_iterator - , - _TitleEntryT::const_iterator> - FilterIterT; - typedef boost::iterator_range FilterRangeT; + typedef boost::filter_iterator + , + _TitleEntryT::const_iterator> + FilterIterT; + typedef boost::iterator_range FilterRangeT; - FilterRangeT Find(char const *query) const; + FilterRangeT Find(char const *query) const; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Debug.cc b/src/Debug.cc index 7e0c189..e9cdc16 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -31,44 +31,44 @@ using namespace std; void PrintBuf(unsigned char const *buf, unsigned len) { - for (unsigned i = 0; i != len; ++i) - cout << boost::format("%02X") % buf[i]; - cout << endl; + for (unsigned i = 0; i != len; ++i) + cout << boost::format("%02X") % buf[i]; + cout << endl; } void PrintBuf(char const *buf, unsigned len) { - PrintBuf(reinterpret_cast(buf), len); + PrintBuf(reinterpret_cast(buf), len); } string Quote(unsigned char const *buf, unsigned len) { - string result; - for (unsigned i = 0; i != len; ++i) - { - unsigned char c = buf[i]; - if (isprint(c)) - { - result.push_back(c); - continue; - } - if (c == '\\') - { - result.push_back('\\'); - result.push_back('\\'); - continue; - } - boost::format fmt("\\x%02X"); - result += (fmt % static_cast(c)).str(); - } - return result; + string result; + for (unsigned i = 0; i != len; ++i) + { + unsigned char c = buf[i]; + if (isprint(c)) + { + result.push_back(c); + continue; + } + if (c == '\\') + { + result.push_back('\\'); + result.push_back('\\'); + continue; + } + boost::format fmt("\\x%02X"); + result += (fmt % static_cast(c)).str(); + } + return result; } string Quote(char const *buf, unsigned len) { - return Quote(reinterpret_cast(buf), len); + return Quote(reinterpret_cast(buf), len); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Debug.hh b/src/Debug.hh index c0298fc..b308953 100644 --- a/src/Debug.hh +++ b/src/Debug.hh @@ -35,4 +35,4 @@ std::string Quote(char const *buf, unsigned len); } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Defs.hh b/src/Defs.hh index e396a1b..8a6b9c2 100644 --- a/src/Defs.hh +++ b/src/Defs.hh @@ -43,4 +43,4 @@ typedef std::basic_ostringstream(); + return make_shared(); } void *cEntry::operator new(size_t n) { - return SecureAllocator::allocate(n); + return SecureAllocator::allocate(n); } void cEntry::operator delete(void *p, size_t n) { - cEntry *q = reinterpret_cast(p); - return SecureAllocator::deallocate(q, n); + cEntry *q = reinterpret_cast(p); + return SecureAllocator::deallocate(q, n); } cEntry::cEntry() - : _fields(0x0F, sField::PtrT()) + : _fields(0x0F, sField::PtrT()) { } cEntry::PtrT cEntry::Copy() const { - cEntry::PtrT entry(new cEntry); - entry->_fields.resize(_fields.size()); - for (unsigned i = 0; i != _fields.size(); ++i) - { - if (_fields[i]) - entry->_fields[i] = _fields[i]->Copy(); - } - return entry; + cEntry::PtrT entry(new cEntry); + entry->_fields.resize(_fields.size()); + for (unsigned i = 0; i != _fields.size(); ++i) + { + if (_fields[i]) + entry->_fields[i] = _fields[i]->Copy(); + } + return entry; } bool cEntry::AddField(sField::PtrT const &field) { - if (field->type == FT_END) - return false; - if (_fields.size() <= field->type) - _fields.resize(static_cast(field->type) + 1); - _fields[field->type] = field; - return true; + if (field->type == FT_END) + return false; + if (_fields.size() <= field->type) + _fields.resize(static_cast(field->type) + 1); + _fields[field->type] = field; + return true; } void cEntry::ForEachField(OnFieldT on_field) { - for (_FieldsT::const_iterator i = _fields.begin(); - i != _fields.end(); ++i) - { - sField::PtrT const &field(*i); - if (!field) - continue; - on_field(field); - } + for (_FieldsT::const_iterator i = _fields.begin(); + i != _fields.end(); ++i) + { + sField::PtrT const &field(*i); + if (!field) + continue; + on_field(field); + } } void cEntry::Dump() const { - for (_FieldsT::const_iterator i = _fields.begin(); - i != _fields.end(); ++i) - { - sField::PtrT const& field = *i; - if (!field) - continue; - cout << "{0x" - << boost::format("%02X") % unsigned(field->type) - << ", '" - << gPWS::Quote(&field->value[0], field->value.size()) - << "'}" - << endl; - } - cout << "----------" << endl; + for (_FieldsT::const_iterator i = _fields.begin(); + i != _fields.end(); ++i) + { + sField::PtrT const& field = *i; + if (!field) + continue; + cout << "{0x" + << boost::format("%02X") % unsigned(field->type) + << ", '" + << gPWS::Quote(&field->value[0], field->value.size()) + << "'}" + << endl; + } + cout << "----------" << endl; } StringX const &cEntry::GetValue(eFieldType field_type) const { - if (static_cast(field_type) >= _fields.size()) - return _empty; - sField::PtrT const &field = _fields[field_type]; - if (!field) - return _empty; - assert(field_type == field->type); - return field->value; + if (static_cast(field_type) >= _fields.size()) + return _empty; + sField::PtrT const &field = _fields[field_type]; + if (!field) + return _empty; + assert(field_type == field->type); + return field->value; } StringX cEntry::GetFullTitle() const { - if (GetGroup().empty()) - return GetTitle(); - return GetGroup() + "." + GetTitle(); + if (GetGroup().empty()) + return GetTitle(); + return GetGroup() + "." + GetTitle(); } void cEntry::SetValue(eFieldType field_type, StringX const &value) { - if (static_cast(field_type) >= _fields.size()) - _fields.resize(static_cast(field_type) + 1); - sField::PtrT &field = _fields[field_type]; - if (!field) - field = sField::Create(); - field->type = field_type; - field->value = value; + if (static_cast(field_type) >= _fields.size()) + _fields.resize(static_cast(field_type) + 1); + sField::PtrT &field = _fields[field_type]; + if (!field) + field = sField::Create(); + field->type = field_type; + field->value = value; } cEntry::DiffT cEntry::Diff(cEntry::PtrT const &other) const { - DiffT diff; - for (unsigned i = 0, n = (std::max)(_fields.size(), other->_fields.size()); - i != n; ++i) - { - sField::PtrT field; - if (i < _fields.size()) - field = _fields[i]; - sField::PtrT field_o; - if (i < other->_fields.size()) - field_o = other->_fields[i]; - - if (field) - { - if (!field_o) - { - sChange change = { field->type, sChange::C_ADDED }; - diff.push_back(change); - } - else - { - if (field->value != field_o->value) - { - sChange change = { field->type, sChange::C_MODIFIED }; - diff.push_back(change); - } - } - } - else // !field - { - if (field_o) - { - sChange change = { field_o->type, sChange::C_DELETED }; - diff.push_back(change); - } - } - } - return diff; + DiffT diff; + for (unsigned i = 0, n = (std::max)(_fields.size(), other->_fields.size()); + i != n; ++i) + { + sField::PtrT field; + if (i < _fields.size()) + field = _fields[i]; + sField::PtrT field_o; + if (i < other->_fields.size()) + field_o = other->_fields[i]; + + if (field) + { + if (!field_o) + { + sChange change = { field->type, sChange::C_ADDED }; + diff.push_back(change); + } + else + { + if (field->value != field_o->value) + { + sChange change = { field->type, sChange::C_MODIFIED }; + diff.push_back(change); + } + } + } + else // !field + { + if (field_o) + { + sChange change = { field_o->type, sChange::C_DELETED }; + diff.push_back(change); + } + } + } + return diff; } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Entry.hh b/src/Entry.hh index 1e30330..9a27fb8 100644 --- a/src/Entry.hh +++ b/src/Entry.hh @@ -30,88 +30,88 @@ namespace gPWS { class cEntry - : boost::noncopyable + : boost::noncopyable { public: - typedef std::shared_ptr PtrT; + typedef std::shared_ptr PtrT; - static PtrT Create(); + static PtrT Create(); - void operator delete(void *p, size_t n); + void operator delete(void *p, size_t n); - cEntry(); + cEntry(); - // Deep copy - cEntry::PtrT Copy() const; + // Deep copy + cEntry::PtrT Copy() const; - bool AddField(sField::PtrT const &field); + bool AddField(sField::PtrT const &field); - typedef std::function OnFieldT; + typedef std::function OnFieldT; - void ForEachField(OnFieldT on_field); + void ForEachField(OnFieldT on_field); - void Dump() const; + void Dump() const; - enum eFieldType - { - FT_GROUP = 0x02, - FT_TITLE = 0x03, - FT_USER = 0x04, - FT_NOTES = 0x05, - FT_PASS = 0x06, - FT_URL = 0x0D, + enum eFieldType + { + FT_GROUP = 0x02, + FT_TITLE = 0x03, + FT_USER = 0x04, + FT_NOTES = 0x05, + FT_PASS = 0x06, + FT_URL = 0x0D, - FT_END = 0xFF - }; + FT_END = 0xFF + }; - StringX const &GetValue(eFieldType field_type) const; + StringX const &GetValue(eFieldType field_type) const; - StringX const &GetGroup() const { return GetValue(FT_GROUP); } - StringX const &GetTitle() const { return GetValue(FT_TITLE); } - StringX const &GetUser() const { return GetValue(FT_USER); } - StringX const &GetNotes() const { return GetValue(FT_NOTES); } - StringX const &GetPass() const { return GetValue(FT_PASS); } - StringX const &GetUrl() const { return GetValue(FT_URL); } + StringX const &GetGroup() const { return GetValue(FT_GROUP); } + StringX const &GetTitle() const { return GetValue(FT_TITLE); } + StringX const &GetUser() const { return GetValue(FT_USER); } + StringX const &GetNotes() const { return GetValue(FT_NOTES); } + StringX const &GetPass() const { return GetValue(FT_PASS); } + StringX const &GetUrl() const { return GetValue(FT_URL); } - void SetValue(eFieldType field_type, StringX const &value); + void SetValue(eFieldType field_type, StringX const &value); - void SetGroup(StringX const &value) { SetValue(FT_GROUP, value); } - void SetTitle(StringX const &value) { SetValue(FT_TITLE, value); } - void SetUser(StringX const &value) { SetValue(FT_USER, value); } - void SetNotes(StringX const &value) { SetValue(FT_NOTES, value); } - void SetPass(StringX const &value) { SetValue(FT_PASS, value); } - void SetUrl(StringX const &value) { SetValue(FT_URL, value); } + void SetGroup(StringX const &value) { SetValue(FT_GROUP, value); } + void SetTitle(StringX const &value) { SetValue(FT_TITLE, value); } + void SetUser(StringX const &value) { SetValue(FT_USER, value); } + void SetNotes(StringX const &value) { SetValue(FT_NOTES, value); } + void SetPass(StringX const &value) { SetValue(FT_PASS, value); } + void SetUrl(StringX const &value) { SetValue(FT_URL, value); } - // group.title - StringX GetFullTitle() const; + // group.title + StringX GetFullTitle() const; - // Difference from another entry - struct sChange - { - uint8_t type; - enum eChange - { - C_ADDED = 0, - C_DELETED, - C_MODIFIED - } change; - }; + // Difference from another entry + struct sChange + { + uint8_t type; + enum eChange + { + C_ADDED = 0, + C_DELETED, + C_MODIFIED + } change; + }; - typedef std::vector DiffT; - DiffT Diff(cEntry::PtrT const &other) const; + typedef std::vector DiffT; + DiffT Diff(cEntry::PtrT const &other) const; private: - // Associative container. Type is used as index in the vector. - // Null means the field wasn't defined. - typedef std::vector _FieldsT; - _FieldsT _fields; + // Associative container. Type is used as index in the vector. + // Null means the field wasn't defined. + typedef std::vector _FieldsT; + _FieldsT _fields; - // Empty string to refer to if a specific field is missing. - StringX _empty; + // Empty string to refer to if a specific field is missing. + StringX _empty; - void *operator new(size_t n); + void *operator new(size_t n); }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Field.cc b/src/Field.cc index eae941c..a6f2637 100644 --- a/src/Field.cc +++ b/src/Field.cc @@ -31,36 +31,36 @@ using namespace std; sField::PtrT sField::Create() { - return make_shared(); + return make_shared(); } sField::PtrT sField::Copy() const { - sField::PtrT field(new sField); - field->type = type; - field->value = value; - return field; + sField::PtrT field(new sField); + field->type = type; + field->value = value; + return field; } void *sField::operator new(size_t n) { - return SecureAllocator::allocate(n); + return SecureAllocator::allocate(n); } void sField::operator delete(void *p, size_t n) { - sField *q(reinterpret_cast(p)); - return SecureAllocator::deallocate(q, n); + sField *q(reinterpret_cast(p)); + return SecureAllocator::deallocate(q, n); } ostream &operator<<(ostream &os, sField const &field) { - boost::format fmt("{0x%02X,%s}"); - fmt % static_cast(field.type); - fmt % Quote(&field.value[0], field.value.size()); - return os << fmt; + boost::format fmt("{0x%02X,%s}"); + fmt % static_cast(field.type); + fmt % Quote(&field.value[0], field.value.size()); + return os << fmt; } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Field.hh b/src/Field.hh index 9e9bedc..d1749bc 100644 --- a/src/Field.hh +++ b/src/Field.hh @@ -31,30 +31,30 @@ namespace gPWS { struct sField - : boost::noncopyable + : boost::noncopyable { - typedef std::shared_ptr PtrT; + typedef std::shared_ptr PtrT; - static PtrT Create(); + static PtrT Create(); - uint8_t type; - StringX value; + uint8_t type; + StringX value; - sField::PtrT Copy() const; + sField::PtrT Copy() const; - void operator delete(void *p, size_t n); + void operator delete(void *p, size_t n); - bool operator!=(sField const &o) - { - return type != o.type || value != o.value; - } + bool operator!=(sField const &o) + { + return type != o.type || value != o.value; + } private: - void *operator new(size_t n); + void *operator new(size_t n); }; std::ostream &operator<<(std::ostream &os, sField const &field); } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/File3.cc b/src/File3.cc index 87b3b72..96b7ea3 100644 --- a/src/File3.cc +++ b/src/File3.cc @@ -42,12 +42,12 @@ const unsigned SALT_LEN = 32; const string EOF_TAG("PWS3-EOFPWS3-EOF"); cFile3::cFile3() - : _state(S_CLOSED) - , _initial_state(_fs.exceptions()) - , _iterations(2048) + : _state(S_CLOSED) + , _initial_state(_fs.exceptions()) + , _iterations(2048) { - assert(gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P) && - "libgcrypt must be initialized beforehand"); + assert(gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P) && + "libgcrypt must be initialized beforehand"); } cFile3::~cFile3() @@ -56,122 +56,122 @@ cFile3::~cFile3() void cFile3::Close() { - _state = S_CLOSED; - _fs.close(); + _state = S_CLOSED; + _fs.close(); } void cFile3::OpenRead(char const *fname, StringX const &pass) { - assert(_state == S_CLOSED); - _state = S_READING; - - _fs.exceptions(_initial_state); - _fs.open(fname, ios::in|ios::binary); - if (!_fs) - throw runtime_error("Can't open file for reading"); - _fs.exceptions(ios::failbit|ios::badbit); - - char tag[MAGIC_TAG.size()]; - _fs.read(tag, MAGIC_TAG.size()); - if (!std::equal(MAGIC_TAG.begin(), MAGIC_TAG.end(), tag)) - throw runtime_error("Invalid tag"); - - char salt[SALT_LEN]; - _fs.read(salt, SALT_LEN); - - uint8_t iter_buf[4]; - _fs.read(reinterpret_cast(iter_buf), 4); - _iterations = uint32_t(iter_buf[0]) - + (uint32_t(iter_buf[1]) << 8) - + (uint32_t(iter_buf[2]) << 16) - + (uint32_t(iter_buf[3]) << 24); - - cKeyStretch key_stretch(pass.c_str(), pass.size(), - salt, SALT_LEN, - _iterations); - - cSha256 key_md(key_stretch.Get(), key_stretch.LENGTH); - - string key(cSha256::LENGTH, '\0'); - _fs.read(&key[0], key.size()); - - if (memcmp(&key[0], key_md.Get(), key.size())) - throw runtime_error("Key mismatch"); - - cTwofish twofish(cTwofish::M_ECB, key_stretch.Get(), key_stretch.LENGTH); - - if (_main_key.empty()) - _main_key.resize(cTwofish::KEY_LENGTH); - _fs.read(&_main_key[0], _main_key.size()); - twofish.Decrypt(&_main_key[0], _main_key.size(), - &_main_key[0], _main_key.size()); - - if (_hmac_key.empty()) - _hmac_key.resize(cHmac::KEY_LENGTH); - _fs.read(&_hmac_key[0], _hmac_key.size()); - twofish.Decrypt(&_hmac_key[0], _hmac_key.size(), - &_hmac_key[0], _hmac_key.size()); - _hmac_calculator.reset(new cHmac(&_hmac_key[0], _hmac_key.size())); - - BytesT iv(cTwofish::BLOCK_LENGTH); - _fs.read(reinterpret_cast(&iv[0]), iv.size()); - - _twofish.reset(new cTwofish(cTwofish::M_CBC, - &_main_key[0], - _main_key.size())); - _twofish->SetIV(&iv[0], iv.size()); + assert(_state == S_CLOSED); + _state = S_READING; + + _fs.exceptions(_initial_state); + _fs.open(fname, ios::in|ios::binary); + if (!_fs) + throw runtime_error("Can't open file for reading"); + _fs.exceptions(ios::failbit|ios::badbit); + + char tag[MAGIC_TAG.size()]; + _fs.read(tag, MAGIC_TAG.size()); + if (!std::equal(MAGIC_TAG.begin(), MAGIC_TAG.end(), tag)) + throw runtime_error("Invalid tag"); + + char salt[SALT_LEN]; + _fs.read(salt, SALT_LEN); + + uint8_t iter_buf[4]; + _fs.read(reinterpret_cast(iter_buf), 4); + _iterations = uint32_t(iter_buf[0]) + + (uint32_t(iter_buf[1]) << 8) + + (uint32_t(iter_buf[2]) << 16) + + (uint32_t(iter_buf[3]) << 24); + + cKeyStretch key_stretch(pass.c_str(), pass.size(), + salt, SALT_LEN, + _iterations); + + cSha256 key_md(key_stretch.Get(), key_stretch.LENGTH); + + string key(cSha256::LENGTH, '\0'); + _fs.read(&key[0], key.size()); + + if (memcmp(&key[0], key_md.Get(), key.size())) + throw runtime_error("Key mismatch"); + + cTwofish twofish(cTwofish::M_ECB, key_stretch.Get(), key_stretch.LENGTH); + + if (_main_key.empty()) + _main_key.resize(cTwofish::KEY_LENGTH); + _fs.read(&_main_key[0], _main_key.size()); + twofish.Decrypt(&_main_key[0], _main_key.size(), + &_main_key[0], _main_key.size()); + + if (_hmac_key.empty()) + _hmac_key.resize(cHmac::KEY_LENGTH); + _fs.read(&_hmac_key[0], _hmac_key.size()); + twofish.Decrypt(&_hmac_key[0], _hmac_key.size(), + &_hmac_key[0], _hmac_key.size()); + _hmac_calculator.reset(new cHmac(&_hmac_key[0], _hmac_key.size())); + + BytesT iv(cTwofish::BLOCK_LENGTH); + _fs.read(reinterpret_cast(&iv[0]), iv.size()); + + _twofish.reset(new cTwofish(cTwofish::M_CBC, + &_main_key[0], + _main_key.size())); + _twofish->SetIV(&iv[0], iv.size()); } sField::PtrT cFile3::ReadField() { - assert(_state == S_READING); - - _data.resize(cTwofish::BLOCK_LENGTH); - _fs.read(&_data[0], _data.size()); - - assert(EOF_TAG.size() == _data.size()); - if (!memcmp(&_data[0], EOF_TAG.data(), _data.size())) - { - BytesT hmac(cHmac::LENGTH); - _fs.read(reinterpret_cast(&hmac[0]), hmac.size()); - _state = S_CLOSED; - _fs.close(); - if (memcmp(_hmac_calculator->Get(), &hmac[0], hmac.size())) - throw runtime_error("HMAC check failed"); - return sField::PtrT(); - } - - _twofish->Decrypt(&_data[0], _data.size(), &_data[0], _data.size()); - uint8_t const *udata = reinterpret_cast(&_data[0]); - uint32_t length = uint32_t(udata[0]) - | (uint32_t(udata[1]) << 8) - | (uint32_t(udata[2]) << 16) - | (uint32_t(udata[3]) << 24); - - sField::PtrT field(sField::Create()); - field->type = _data[4]; - field->value.reserve(length); - StringX &value (field->value); - - for (unsigned i = 5; length > 0; ) - { - if (i == _data.size()) - { - _fs.read(&_data[0], _data.size()); - _twofish->Decrypt(&_data[0], _data.size(), - &_data[0], _data.size()); - i = 0; - } - int available = (std::min)(_data.size() - i, size_t(length)); - value.insert(value.end(), - _data.begin() + i, - _data.begin() + i + available); - length -= available; - i += available; - } - _hmac_calculator->Update(&value[0], value.size()); - return field; + assert(_state == S_READING); + + _data.resize(cTwofish::BLOCK_LENGTH); + _fs.read(&_data[0], _data.size()); + + assert(EOF_TAG.size() == _data.size()); + if (!memcmp(&_data[0], EOF_TAG.data(), _data.size())) + { + BytesT hmac(cHmac::LENGTH); + _fs.read(reinterpret_cast(&hmac[0]), hmac.size()); + _state = S_CLOSED; + _fs.close(); + if (memcmp(_hmac_calculator->Get(), &hmac[0], hmac.size())) + throw runtime_error("HMAC check failed"); + return sField::PtrT(); + } + + _twofish->Decrypt(&_data[0], _data.size(), &_data[0], _data.size()); + uint8_t const *udata = reinterpret_cast(&_data[0]); + uint32_t length = uint32_t(udata[0]) + | (uint32_t(udata[1]) << 8) + | (uint32_t(udata[2]) << 16) + | (uint32_t(udata[3]) << 24); + + sField::PtrT field(sField::Create()); + field->type = _data[4]; + field->value.reserve(length); + StringX &value (field->value); + + for (unsigned i = 5; length > 0; ) + { + if (i == _data.size()) + { + _fs.read(&_data[0], _data.size()); + _twofish->Decrypt(&_data[0], _data.size(), + &_data[0], _data.size()); + i = 0; + } + int available = (std::min)(_data.size() - i, size_t(length)); + value.insert(value.end(), + _data.begin() + i, + _data.begin() + i + available); + length -= available; + i += available; + } + _hmac_calculator->Update(&value[0], value.size()); + return field; } void cFile3::OpenWrite(char const *fname, @@ -179,128 +179,128 @@ void cFile3::OpenWrite(char const *fname, bool new_keys, bool very_strong) { - assert(_state == S_CLOSED); - _state = S_WRITING; - - _fs.exceptions(_initial_state); - _fs.open(fname, ios::out|ios::binary|ios::trunc); - if (!_fs) - throw runtime_error("Can't open file for writing"); - _fs.exceptions(ios::failbit|ios::badbit); - - _fs.write(&MAGIC_TAG[0], MAGIC_TAG.size()); - - char salt[SALT_LEN]; - cRandom::CreateNonce(salt, SALT_LEN); - _fs.write(salt, SALT_LEN); - - uint8_t iter_buf[4]; - iter_buf[0] = _iterations & 0xFF; - iter_buf[1] = (_iterations >> 8) & 0xFF; - iter_buf[2] = (_iterations >> 16) & 0xFF; - iter_buf[3] = (_iterations >> 24) & 0xFF; - - _fs.write(reinterpret_cast(iter_buf), 4); - - cKeyStretch key_stretch(pass.c_str(), pass.size(), - salt, SALT_LEN, - _iterations); - - cSha256 key_md(key_stretch.Get(), key_stretch.LENGTH); - - _fs.write(reinterpret_cast(key_md.Get()), key_md.LENGTH); - - cTwofish twofish(cTwofish::M_ECB, key_stretch.Get(), key_stretch.LENGTH); - - if (_main_key.empty() || new_keys) - { - _main_key.resize(cTwofish::KEY_LENGTH); - cRandom::Randomize(&_main_key[0], _main_key.size(), very_strong); - } - // Encrypt the main key before writing - StringX main_key_enc(_main_key); - twofish.Encrypt(&main_key_enc[0], main_key_enc.size(), - &_main_key[0], _main_key.size()); - _fs.write(&main_key_enc[0], main_key_enc.size()); - - if (_hmac_key.empty() || new_keys) - { - _hmac_key.resize(cHmac::KEY_LENGTH); - cRandom::Randomize(&_hmac_key[0], _hmac_key.size(), very_strong); - } - StringX hmac_key_enc(_hmac_key); - twofish.Encrypt(&hmac_key_enc[0], hmac_key_enc.size(), - &_hmac_key[0], _hmac_key.size()); - _fs.write(&hmac_key_enc[0], hmac_key_enc.size()); - - _hmac_calculator.reset(new cHmac(&_hmac_key[0], _hmac_key.size())); - - BytesT iv(cTwofish::BLOCK_LENGTH); - cRandom::CreateNonce(&iv[0], iv.size()); - _fs.write(reinterpret_cast(&iv[0]), iv.size()); - - _twofish.reset(new cTwofish(cTwofish::M_CBC, - &_main_key[0], - _main_key.size())); - _twofish->SetIV(&iv[0], iv.size()); + assert(_state == S_CLOSED); + _state = S_WRITING; + + _fs.exceptions(_initial_state); + _fs.open(fname, ios::out|ios::binary|ios::trunc); + if (!_fs) + throw runtime_error("Can't open file for writing"); + _fs.exceptions(ios::failbit|ios::badbit); + + _fs.write(&MAGIC_TAG[0], MAGIC_TAG.size()); + + char salt[SALT_LEN]; + cRandom::CreateNonce(salt, SALT_LEN); + _fs.write(salt, SALT_LEN); + + uint8_t iter_buf[4]; + iter_buf[0] = _iterations & 0xFF; + iter_buf[1] = (_iterations >> 8) & 0xFF; + iter_buf[2] = (_iterations >> 16) & 0xFF; + iter_buf[3] = (_iterations >> 24) & 0xFF; + + _fs.write(reinterpret_cast(iter_buf), 4); + + cKeyStretch key_stretch(pass.c_str(), pass.size(), + salt, SALT_LEN, + _iterations); + + cSha256 key_md(key_stretch.Get(), key_stretch.LENGTH); + + _fs.write(reinterpret_cast(key_md.Get()), key_md.LENGTH); + + cTwofish twofish(cTwofish::M_ECB, key_stretch.Get(), key_stretch.LENGTH); + + if (_main_key.empty() || new_keys) + { + _main_key.resize(cTwofish::KEY_LENGTH); + cRandom::Randomize(&_main_key[0], _main_key.size(), very_strong); + } + // Encrypt the main key before writing + StringX main_key_enc(_main_key); + twofish.Encrypt(&main_key_enc[0], main_key_enc.size(), + &_main_key[0], _main_key.size()); + _fs.write(&main_key_enc[0], main_key_enc.size()); + + if (_hmac_key.empty() || new_keys) + { + _hmac_key.resize(cHmac::KEY_LENGTH); + cRandom::Randomize(&_hmac_key[0], _hmac_key.size(), very_strong); + } + StringX hmac_key_enc(_hmac_key); + twofish.Encrypt(&hmac_key_enc[0], hmac_key_enc.size(), + &_hmac_key[0], _hmac_key.size()); + _fs.write(&hmac_key_enc[0], hmac_key_enc.size()); + + _hmac_calculator.reset(new cHmac(&_hmac_key[0], _hmac_key.size())); + + BytesT iv(cTwofish::BLOCK_LENGTH); + cRandom::CreateNonce(&iv[0], iv.size()); + _fs.write(reinterpret_cast(&iv[0]), iv.size()); + + _twofish.reset(new cTwofish(cTwofish::M_CBC, + &_main_key[0], + _main_key.size())); + _twofish->SetIV(&iv[0], iv.size()); } void cFile3::WriteField(sField::PtrT const &field) { - assert(_state == S_WRITING); - assert(field); - - _data.resize(cTwofish::BLOCK_LENGTH); - - StringX &value(field->value); - uint32_t length(value.size()); - _hmac_calculator->Update(&value[0], value.size()); - - _data[0] = length & 0xFF; - _data[1] = (length >> 8) & 0xFF; - _data[2] = (length >> 16) & 0xFF; - _data[3] = (length >> 24) & 0xFF; - _data[4] = field->type; - - for (unsigned val_idx = 0, data_idx = 5; ; ) - { - int data_rest = _data.size() - data_idx; - int value_rest = value.size() - val_idx; - int block_rest = (std::min)(data_rest, value_rest); - if (!value_rest && data_rest) - { - // Fill up the rest of the block with random data - cRandom::CreateNonce(&_data[0] + data_idx, data_rest); - } - if (!block_rest) - { - assert(_twofish.get()); - _twofish->Encrypt(&_data[0], _data.size(), - &_data[0], _data.size()); - _fs.write(&_data[0], _data.size()); - data_idx = 0; - if (!value_rest) - break; - continue; - } - copy(value.begin() + val_idx, value.begin() + val_idx + block_rest, - _data.begin() + data_idx); - data_idx += block_rest; - val_idx += block_rest; - } + assert(_state == S_WRITING); + assert(field); + + _data.resize(cTwofish::BLOCK_LENGTH); + + StringX &value(field->value); + uint32_t length(value.size()); + _hmac_calculator->Update(&value[0], value.size()); + + _data[0] = length & 0xFF; + _data[1] = (length >> 8) & 0xFF; + _data[2] = (length >> 16) & 0xFF; + _data[3] = (length >> 24) & 0xFF; + _data[4] = field->type; + + for (unsigned val_idx = 0, data_idx = 5; ; ) + { + int data_rest = _data.size() - data_idx; + int value_rest = value.size() - val_idx; + int block_rest = (std::min)(data_rest, value_rest); + if (!value_rest && data_rest) + { + // Fill up the rest of the block with random data + cRandom::CreateNonce(&_data[0] + data_idx, data_rest); + } + if (!block_rest) + { + assert(_twofish.get()); + _twofish->Encrypt(&_data[0], _data.size(), + &_data[0], _data.size()); + _fs.write(&_data[0], _data.size()); + data_idx = 0; + if (!value_rest) + break; + continue; + } + copy(value.begin() + val_idx, value.begin() + val_idx + block_rest, + _data.begin() + data_idx); + data_idx += block_rest; + val_idx += block_rest; + } } void cFile3::CloseWrite() { - assert(_state == S_WRITING); - _fs.write(EOF_TAG.data(), EOF_TAG.size()); - assert(_hmac_calculator.get()); - _fs.write(reinterpret_cast(_hmac_calculator->Get()), - cHmac::LENGTH); - _fs.close(); - _state = S_CLOSED; + assert(_state == S_WRITING); + _fs.write(EOF_TAG.data(), EOF_TAG.size()); + assert(_hmac_calculator.get()); + _fs.write(reinterpret_cast(_hmac_calculator->Get()), + cHmac::LENGTH); + _fs.close(); + _state = S_CLOSED; } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/File3.hh b/src/File3.hh index 60505be..1b8907f 100644 --- a/src/File3.hh +++ b/src/File3.hh @@ -32,51 +32,51 @@ namespace gPWS { class cFile3 - : boost::noncopyable + : boost::noncopyable { public: - cFile3(); - ~cFile3(); + cFile3(); + ~cFile3(); - void Close(); + void Close(); - void OpenRead(char const *fname, - StringX const &pass); + void OpenRead(char const *fname, + StringX const &pass); - sField::PtrT ReadField(); + sField::PtrT ReadField(); - void OpenWrite(char const *fname, - StringX const &pass, - bool new_keys = false, - bool very_strong = true); + void OpenWrite(char const *fname, + StringX const &pass, + bool new_keys = false, + bool very_strong = true); - void WriteField(sField::PtrT const &field); + void WriteField(sField::PtrT const &field); - void CloseWrite(); + void CloseWrite(); private: - enum _eState - { - S_CLOSED = 0, - S_READING, - S_WRITING - } _state; - - std::fstream _fs; - std::ios_base::iostate _initial_state; - - // Count of iterations for the key stretching - uint32_t _iterations; - - // Main encryption key for TwoFish - StringX _main_key; - StringX _hmac_key; - - std::unique_ptr _twofish; - std::unique_ptr _hmac_calculator; - StringX _data; + enum _eState + { + S_CLOSED = 0, + S_READING, + S_WRITING + } _state; + + std::fstream _fs; + std::ios_base::iostate _initial_state; + + // Count of iterations for the key stretching + uint32_t _iterations; + + // Main encryption key for TwoFish + StringX _main_key; + StringX _hmac_key; + + std::unique_ptr _twofish; + std::unique_ptr _hmac_calculator; + StringX _data; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Gcrypt.cc b/src/Gcrypt.cc index 54cd053..971304a 100644 --- a/src/Gcrypt.cc +++ b/src/Gcrypt.cc @@ -14,38 +14,42 @@ namespace gPWS { using namespace std; -static void +namespace { + +void _GcryProgressHandler(void *cb_data, const char *what, int printchar, int current, int total) { - if (!strcmp(what, "need_entropy")) - { - cerr << "\rEntropy pool: " << current << " of " << total - << " bytes are available."; - if (current == total) - cerr << " Done. " << endl; - else - cerr << " Waiting for more..." << flush; - } + if (!strcmp(what, "need_entropy")) + { + cerr << "\rEntropy pool: " << current << " of " << total + << " bytes are available."; + if (current == total) + cerr << " Done. " << endl; + else + cerr << " Waiting for more..." << flush; + } } +} //namespace; + int cGcrypt::Init() { - char const *const REQ_GCRYPT_VERSION = "1.2.0"; - if (!gcry_check_version(REQ_GCRYPT_VERSION)) - { - cerr << "libgcrypt version mismatch\n" << endl; - return 1; - } - - // Allocate secure memory for sensitive information (won't be swapped) - gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0); - gcry_set_progress_handler(_GcryProgressHandler, NULL); - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); - - return 0; + char const *const REQ_GCRYPT_VERSION = "1.2.0"; + if (!gcry_check_version(REQ_GCRYPT_VERSION)) + { + cerr << "libgcrypt version mismatch\n" << endl; + return 1; + } + + // Allocate secure memory for sensitive information (won't be swapped) + gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0); + gcry_set_progress_handler(_GcryProgressHandler, NULL); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + + return 0; } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Gcrypt.hh b/src/Gcrypt.hh index b133ccc..2b2681c 100644 --- a/src/Gcrypt.hh +++ b/src/Gcrypt.hh @@ -12,9 +12,9 @@ namespace gPWS { class cGcrypt { public: - static int Init(); + static int Init(); }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/GtkEmitter.cc b/src/GtkEmitter.cc index df77045..1cd1178 100644 --- a/src/GtkEmitter.cc +++ b/src/GtkEmitter.cc @@ -39,89 +39,93 @@ cGtkEmitter::~cGtkEmitter() void cGtkEmitter::PrintIntention(string const &subject) const { - cout << "Going to copy " << subject << " to X selection" << endl; + cout << "Going to copy " << subject << " to X selection" << endl; } -static void +namespace { + +void _TextGetFunc(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { - StringX const *val = reinterpret_cast(data); - gtk_selection_data_set_text (selection_data, val->c_str(), val->size()); - //gtk_clipboard_clear(clipboard); - gtk_main_quit(); + StringX const *val = reinterpret_cast(data); + gtk_selection_data_set_text (selection_data, val->c_str(), val->size()); + //gtk_clipboard_clear(clipboard); + gtk_main_quit(); } -static void +void _TextClearFunc(GtkClipboard *clipboard, gpointer data) { } -static gboolean +gboolean _OnStdin(GIOChannel *source, GIOCondition condition, gpointer data) { - // Read the ready byte from the stdin - char ch; - int res = ::read(g_io_channel_unix_get_fd(source), &ch, 1); - if (-1 == res) - { - } - // Quit the clipboard waiting - gtk_main_quit(); - return FALSE; + // Read the ready byte from the stdin + char ch; + int res = ::read(g_io_channel_unix_get_fd(source), &ch, 1); + if (-1 == res) + { + } + // Quit the clipboard waiting + gtk_main_quit(); + return FALSE; } +} //namespace; + void cGtkEmitter::Emit(StringX const &name, StringX const &val) { - int argc(0); - char **argv = { NULL }; - gtk_init(&argc, &argv); + int argc(0); + char **argv = { NULL }; + gtk_init(&argc, &argv); - GdkAtom primary = gdk_atom_intern("PRIMARY", TRUE); - GtkClipboard *clipboard = gtk_clipboard_get(primary); - if (!clipboard) - { - cerr << "Failed to get clipboard" << endl; - return; - } + GdkAtom primary = gdk_atom_intern("PRIMARY", TRUE); + GtkClipboard *clipboard = gtk_clipboard_get(primary); + if (!clipboard) + { + cerr << "Failed to get clipboard" << endl; + return; + } - GtkTargetList *list = gtk_target_list_new(NULL, 0); - gtk_target_list_add_text_targets (list, 0); + GtkTargetList *list = gtk_target_list_new(NULL, 0); + gtk_target_list_add_text_targets (list, 0); - gint n_targets; - GtkTargetEntry *targets = - gtk_target_table_new_from_list (list, &n_targets); + gint n_targets; + GtkTargetEntry *targets = + gtk_target_table_new_from_list (list, &n_targets); - gtk_clipboard_set_with_data (clipboard, - targets, n_targets, - _TextGetFunc, _TextClearFunc, - const_cast(&val)); - gtk_clipboard_set_can_store (clipboard, NULL, 0); + gtk_clipboard_set_with_data (clipboard, + targets, n_targets, + _TextGetFunc, _TextClearFunc, + const_cast(&val)); + gtk_clipboard_set_can_store (clipboard, NULL, 0); - gtk_target_table_free (targets, n_targets); - gtk_target_list_unref (list); + gtk_target_table_free (targets, n_targets); + gtk_target_list_unref (list); - cout << "You are ready to paste the " << name << " from PRIMARY" << endl; - cout << "Press any key when done" << endl; + cout << "You are ready to paste the " << name << " from PRIMARY" << endl; + cout << "Press any key when done" << endl; - // Switch off the canonical mode - cRawTerminal raw_terminal; + // Switch off the canonical mode + cRawTerminal raw_terminal; - // Poll the stdin for any events to react on key press - GIOChannel *channel = g_io_channel_unix_new(STDIN_FILENO); - /*gint evt_id =*/ g_io_add_watch(channel, G_IO_IN, _OnStdin, NULL); + // Poll the stdin for any events to react on key press + GIOChannel *channel = g_io_channel_unix_new(STDIN_FILENO); + /*gint evt_id =*/ g_io_add_watch(channel, G_IO_IN, _OnStdin, NULL); - gtk_main(); + gtk_main(); - gtk_clipboard_clear(clipboard); - g_io_channel_unref(channel); + gtk_clipboard_clear(clipboard); + g_io_channel_unref(channel); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/GtkEmitter.hh b/src/GtkEmitter.hh index 609fd7f..7c58ae2 100644 --- a/src/GtkEmitter.hh +++ b/src/GtkEmitter.hh @@ -29,14 +29,14 @@ class cGtkEmitter : public iEmitter { public: - cGtkEmitter(); - ~cGtkEmitter(); + cGtkEmitter(); + ~cGtkEmitter(); private: - virtual void PrintIntention(std::string const &subject) const; - virtual void Emit(StringX const &name, StringX const &val); + virtual void PrintIntention(std::string const &subject) const; + virtual void Emit(StringX const &name, StringX const &val); }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Hmac.cc b/src/Hmac.cc index 80dae96..c15c518 100644 --- a/src/Hmac.cc +++ b/src/Hmac.cc @@ -30,43 +30,43 @@ using namespace std; cHmac::cHmac(void const *key, size_t key_len) { - gcry_error_t error = - gcry_md_open(&_h, - GCRY_MD_SHA256, - GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC); - if (error) - { - cerr << "gcry_md_open failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("md error"); - } + gcry_error_t error = + gcry_md_open(&_h, + GCRY_MD_SHA256, + GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC); + if (error) + { + cerr << "gcry_md_open failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("md error"); + } - error = gcry_md_setkey(_h, key, key_len); - if (error) - { - cerr << "gcry_md_setkey failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("md error"); - } + error = gcry_md_setkey(_h, key, key_len); + if (error) + { + cerr << "gcry_md_setkey failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("md error"); + } } cHmac::~cHmac() { - gcry_md_close(_h); + gcry_md_close(_h); } void cHmac::Update(void const *data, size_t len) { - gcry_md_write(_h, data, len); + gcry_md_write(_h, data, len); } uint8_t const *cHmac::Get() const { - return gcry_md_read(_h, 0); + return gcry_md_read(_h, 0); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Hmac.hh b/src/Hmac.hh index 7c28e10..2efb3a1 100644 --- a/src/Hmac.hh +++ b/src/Hmac.hh @@ -28,23 +28,23 @@ namespace gPWS { class cHmac - : boost::noncopyable + : boost::noncopyable { public: - static const unsigned KEY_LENGTH = 32; - static const unsigned LENGTH = 32; + static const unsigned KEY_LENGTH = 32; + static const unsigned LENGTH = 32; - cHmac(void const *key, size_t key_len); + cHmac(void const *key, size_t key_len); - ~cHmac(); + ~cHmac(); - void Update(void const *data, size_t len); - uint8_t const *Get() const; + void Update(void const *data, size_t len); + uint8_t const *Get() const; private: - gcry_md_hd_t _h; + gcry_md_hd_t _h; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/IEmitter.hh b/src/IEmitter.hh index 237c08e..6b3cf8f 100644 --- a/src/IEmitter.hh +++ b/src/IEmitter.hh @@ -31,13 +31,13 @@ namespace gPWS { struct iEmitter : boost::noncopyable { - virtual ~iEmitter() { } + virtual ~iEmitter() { } - virtual void PrintIntention(std::string const &subject) const = 0; + virtual void PrintIntention(std::string const &subject) const = 0; - virtual void Emit(StringX const &name, StringX const &val) = 0; + virtual void Emit(StringX const &name, StringX const &val) = 0; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/KeyStretch.cc b/src/KeyStretch.cc index 6f54dd1..1546aee 100644 --- a/src/KeyStretch.cc +++ b/src/KeyStretch.cc @@ -31,16 +31,16 @@ cKeyStretch::cKeyStretch(void const* pass, unsigned salt_size, unsigned iterations) { - _sha256.Update(pass, pass_size); - _sha256.Update(salt, salt_size); - - for (unsigned i = 0; i != iterations; ++i) - { - uint8_t X[cSha256::LENGTH]; - memcpy(X, _sha256.Get(), cSha256::LENGTH); - _sha256.Reset(); - _sha256.Update(X, cSha256::LENGTH); - } + _sha256.Update(pass, pass_size); + _sha256.Update(salt, salt_size); + + for (unsigned i = 0; i != iterations; ++i) + { + uint8_t X[cSha256::LENGTH]; + memcpy(X, _sha256.Get(), cSha256::LENGTH); + _sha256.Reset(); + _sha256.Update(X, cSha256::LENGTH); + } } cKeyStretch::~cKeyStretch() @@ -49,9 +49,9 @@ cKeyStretch::~cKeyStretch() uint8_t const* cKeyStretch::Get() const { - return _sha256.Get(); + return _sha256.Get(); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/KeyStretch.hh b/src/KeyStretch.hh index ec9710c..01af0d3 100644 --- a/src/KeyStretch.hh +++ b/src/KeyStretch.hh @@ -28,25 +28,25 @@ namespace gPWS { class cKeyStretch - : boost::noncopyable + : boost::noncopyable { public: - cKeyStretch(void const* pass, - unsigned pass_size, - void const* salt, - unsigned salt_size, - unsigned iterations); + cKeyStretch(void const* pass, + unsigned pass_size, + void const* salt, + unsigned salt_size, + unsigned iterations); - ~cKeyStretch(); + ~cKeyStretch(); - static const unsigned LENGTH = cSha256::LENGTH; + static const unsigned LENGTH = cSha256::LENGTH; - uint8_t const *Get() const; + uint8_t const *Get() const; private: - cSha256 _sha256; + cSha256 _sha256; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Makefile.am b/src/Makefile.am index ca0004d..7ac5113 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ AM_CXXFLAGS = -Wall \ - $(LIBGCRYPT_CFLAGS) -DGCRYPT_NO_DEPRECATED \ - $(BOOST_CPPFLAGS) + $(LIBGCRYPT_CFLAGS) -DGCRYPT_NO_DEPRECATED \ + $(BOOST_CPPFLAGS) noinst_LIBRARIES = libgpwsafe.a @@ -23,10 +23,10 @@ libgpwsafe_a_SOURCES = \ bin_PROGRAMS = gpwsafe gpwsafe_SOURCES = main.cc \ - App.cc App.hh \ - IEmitter.hh \ - Terminal.cc Terminal.hh \ - StdoutEmitter.cc StdoutEmitter.hh + App.cc App.hh \ + IEmitter.hh \ + Terminal.cc Terminal.hh \ + StdoutEmitter.cc StdoutEmitter.hh gpwsafe_LDADD = libgpwsafe.a \ $(LIBGCRYPT_LIBS) @@ -38,4 +38,3 @@ gpwsafe_SOURCES += GtkEmitter.cc GtkEmitter.hh gpwsafe_LDADD += $(GTK_LIBS) gpwsafe_CXXFLAGS += $(GTK_CFLAGS) endif # Enable_GTK - diff --git a/src/Memory.cc b/src/Memory.cc index 0da4436..8730373 100644 --- a/src/Memory.cc +++ b/src/Memory.cc @@ -30,24 +30,24 @@ using namespace std; char *cLockedBlockAllocator::malloc(const size_type bytes) { - char *block = reinterpret_cast(std::malloc(bytes)); - int ret = mlock(block, bytes); - if (ret) - { - cerr << "WARNING: unable to use secure ram (need to have CAP_IPC_LOCK)" - << endl; - } - return block; + char *block = reinterpret_cast(std::malloc(bytes)); + int ret = mlock(block, bytes); + if (ret) + { + cerr << "WARNING: unable to use secure ram (need to have CAP_IPC_LOCK)" + << endl; + } + return block; } void cLockedBlockAllocator::free(char *const block) { - // We can't do munlock(), because the pool doesn't let us know the size - // of the block. Let's not bother, because any way the memory locks - // will be removed when the process exits. - std::free(block); + // We can't do munlock(), because the pool doesn't let us know the size + // of the block. Let's not bother, because any way the memory locks + // will be removed when the process exits. + std::free(block); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Memory.hh b/src/Memory.hh index 4f0b556..acf114c 100644 --- a/src/Memory.hh +++ b/src/Memory.hh @@ -30,38 +30,38 @@ namespace gPWS { class cLockedBlockAllocator { public: - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; - static char *malloc(const size_type bytes); - static void free(char *const block); + static char *malloc(const size_type bytes); + static void free(char *const block); }; template class SecureAllocator - : public boost::pool_allocator + : public boost::pool_allocator { public: - typedef boost::pool_allocator BaseT; + typedef boost::pool_allocator BaseT; - typedef T value_type; - typedef value_type * pointer; - typedef typename boost::pool::size_type size_type; + typedef T value_type; + typedef value_type * pointer; + typedef typename boost::pool::size_type size_type; - template - struct rebind - { - typedef SecureAllocator other; - }; + template + struct rebind + { + typedef SecureAllocator other; + }; - static void deallocate(const pointer ptr, const size_type n) - { - // Clear memory before returning it to the system. - memset(ptr, 0, n*sizeof(T)); - BaseT::deallocate (ptr, n); - } + static void deallocate(const pointer ptr, const size_type n) + { + // Clear memory before returning it to the system. + memset(ptr, 0, n*sizeof(T)); + BaseT::deallocate (ptr, n); + } }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Random.cc b/src/Random.cc index 446c1c4..c430fee 100644 --- a/src/Random.cc +++ b/src/Random.cc @@ -27,16 +27,16 @@ namespace gPWS { void cRandom::CreateNonce(uint8_t *buffer, unsigned len) { - gcry_create_nonce(buffer, len); + gcry_create_nonce(buffer, len); } void cRandom::Randomize(uint8_t *buffer, unsigned length, bool very_strong) { - gcry_randomize(buffer, length, - very_strong ? GCRY_VERY_STRONG_RANDOM : GCRY_STRONG_RANDOM); + gcry_randomize(buffer, length, + very_strong ? GCRY_VERY_STRONG_RANDOM : GCRY_STRONG_RANDOM); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Random.hh b/src/Random.hh index d2d9c43..acbb6cc 100644 --- a/src/Random.hh +++ b/src/Random.hh @@ -27,27 +27,27 @@ namespace gPWS { class cRandom - : boost::noncopyable + : boost::noncopyable { public: - static void CreateNonce(uint8_t *buffer, unsigned length); - - static void CreateNonce(char *buffer, unsigned length) - { - CreateNonce(reinterpret_cast(buffer), length); - } - - static void Randomize(uint8_t *buffer, unsigned length, - bool very_strong); - - static void Randomize(char *buffer, unsigned length, - bool very_strong) - { - Randomize(reinterpret_cast(buffer), length, - very_strong); - } + static void CreateNonce(uint8_t *buffer, unsigned length); + + static void CreateNonce(char *buffer, unsigned length) + { + CreateNonce(reinterpret_cast(buffer), length); + } + + static void Randomize(uint8_t *buffer, unsigned length, + bool very_strong); + + static void Randomize(char *buffer, unsigned length, + bool very_strong) + { + Randomize(reinterpret_cast(buffer), length, + very_strong); + } }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Sha256.cc b/src/Sha256.cc index 0fb9078..ae94937 100644 --- a/src/Sha256.cc +++ b/src/Sha256.cc @@ -30,52 +30,52 @@ using namespace std; cSha256::cSha256() { - gcry_error_t error = - gcry_md_open(&_h, GCRY_MD_SHA256, GCRY_MD_FLAG_SECURE); - if (error) - { - cerr << "gcry_md_open failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("md error"); - } + gcry_error_t error = + gcry_md_open(&_h, GCRY_MD_SHA256, GCRY_MD_FLAG_SECURE); + if (error) + { + cerr << "gcry_md_open failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("md error"); + } } cSha256::cSha256(void const *data, size_t len) { - gcry_error_t error = - gcry_md_open(&_h, GCRY_MD_SHA256, GCRY_MD_FLAG_SECURE); - if (error) - { - cerr << "gcry_md_open failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("md error"); - } + gcry_error_t error = + gcry_md_open(&_h, GCRY_MD_SHA256, GCRY_MD_FLAG_SECURE); + if (error) + { + cerr << "gcry_md_open failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("md error"); + } - gcry_md_write(_h, data, len); + gcry_md_write(_h, data, len); } cSha256::~cSha256() { - gcry_md_close(_h); + gcry_md_close(_h); } uint8_t const *cSha256::Get() const { - return gcry_md_read(_h, 0); + return gcry_md_read(_h, 0); } void cSha256::Update(void const *data, size_t len) { - gcry_md_write(_h, data, len); + gcry_md_write(_h, data, len); } void cSha256::Reset() { - gcry_md_reset(_h); + gcry_md_reset(_h); } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Sha256.hh b/src/Sha256.hh index ad191ec..051a760 100644 --- a/src/Sha256.hh +++ b/src/Sha256.hh @@ -28,24 +28,24 @@ namespace gPWS { class cSha256 - : boost::noncopyable + : boost::noncopyable { public: - static const unsigned LENGTH = 32; + static const unsigned LENGTH = 32; - cSha256(); - cSha256(void const *data, size_t len); + cSha256(); + cSha256(void const *data, size_t len); - ~cSha256(); + ~cSha256(); - void Update(void const *data, size_t len); - uint8_t const *Get() const; - void Reset(); + void Update(void const *data, size_t len); + uint8_t const *Get() const; + void Reset(); private: - gcry_md_hd_t _h; + gcry_md_hd_t _h; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/StdoutEmitter.cc b/src/StdoutEmitter.cc index 13ebe10..fa58b0a 100644 --- a/src/StdoutEmitter.cc +++ b/src/StdoutEmitter.cc @@ -29,14 +29,14 @@ using namespace std; void cStdoutEmitter::PrintIntention(string const &subject) const { - cout << "Going to print " << subject << " to stdout" << endl; + cout << "Going to print " << subject << " to stdout" << endl; } void cStdoutEmitter::Emit(StringX const &name, StringX const &val) { - cout << name << ": " << val << endl; + cout << name << ": " << val << endl; } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/StdoutEmitter.hh b/src/StdoutEmitter.hh index 60246c6..ceb489f 100644 --- a/src/StdoutEmitter.hh +++ b/src/StdoutEmitter.hh @@ -26,14 +26,14 @@ namespace gPWS { class cStdoutEmitter - : public iEmitter + : public iEmitter { private: - virtual void PrintIntention(std::string const &subject) const; + virtual void PrintIntention(std::string const &subject) const; - virtual void Emit(StringX const &name, StringX const &val); + virtual void Emit(StringX const &name, StringX const &val); }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Terminal.cc b/src/Terminal.cc index aa38492..fc0e43b 100644 --- a/src/Terminal.cc +++ b/src/Terminal.cc @@ -34,346 +34,346 @@ namespace gPWS { using namespace std; cRawTerminal::cRawTerminal(bool new_line) - : _new_line(new_line) + : _new_line(new_line) { - tcgetattr(STDIN_FILENO, &_tio); - - struct termios new_tio = _tio; - new_tio.c_lflag &= ~(ICANON); - // A hack for sparc (from pwsafe) - new_tio.c_cc[VMIN] = 1; - new_tio.c_cc[VTIME] = 0; - // Turn off echo too; no need to show them the char they pressed - new_tio.c_lflag &= ~(ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); + tcgetattr(STDIN_FILENO, &_tio); + + struct termios new_tio = _tio; + new_tio.c_lflag &= ~(ICANON); + // A hack for sparc (from pwsafe) + new_tio.c_cc[VMIN] = 1; + new_tio.c_cc[VTIME] = 0; + // Turn off echo too; no need to show them the char they pressed + new_tio.c_lflag &= ~(ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); } cRawTerminal::~cRawTerminal() { - tcsetattr(STDIN_FILENO, TCSANOW, &_tio); - if (_new_line) - cout << endl; + tcsetattr(STDIN_FILENO, TCSANOW, &_tio); + if (_new_line) + cout << endl; } ////////////////////////////////////////////////////////////////////////////// StringX cTerminal::GetPassword(char const *prompt) { - cRawTerminal raw_terminal(true); - - rl_completion_entry_function = NULL; - char *input = readline(prompt); - if (!input) - throw runtime_error("Can't get password"); - BOOST_SCOPE_EXIT((&input)) { - memset(input, 0, strlen(input)); - delete input; - } BOOST_SCOPE_EXIT_END - - return StringX(input); + cRawTerminal raw_terminal(true); + + rl_completion_entry_function = NULL; + char *input = readline(prompt); + if (!input) + throw runtime_error("Can't get password"); + BOOST_SCOPE_EXIT((&input)) { + memset(input, 0, strlen(input)); + delete input; + } BOOST_SCOPE_EXIT_END + + return StringX(input); } StringX cTerminal::GetText(char const *prompt, StringX const &def) { - rl_completion_entry_function = NULL; - char *input = readline(prompt); - if (!input) - throw runtime_error("Can't get text"); - BOOST_SCOPE_EXIT((&input)) { - memset(input, 0, strlen(input)); - delete input; - } BOOST_SCOPE_EXIT_END - - StringX res(input); - if (res.empty()) - return def; - return res; + rl_completion_entry_function = NULL; + char *input = readline(prompt); + if (!input) + throw runtime_error("Can't get text"); + BOOST_SCOPE_EXIT((&input)) { + memset(input, 0, strlen(input)); + delete input; + } BOOST_SCOPE_EXIT_END + + StringX res(input); + if (res.empty()) + return def; + return res; } StringX cTerminal::EnterPassword(char const *prompt1, char const *prompt2) { - // Copied from pwsafe - while (true) - { - StringX pw1 = GetPassword(prompt1); - if (pw1.empty()) - { - if (GetYN("Generate random password? [y] ", true)) - { - pw1 = RandomPassword(); - if (!pw1.empty()) - return pw1; - else - continue; // back to entering by hand for them - // (perhaps they want to copy only a subset - // of the original pw) - } // else let them have an empty password, though they'll have - // to enter it twice - } - StringX pw2 = GetPassword(prompt2); - if (pw1 == pw2) - { - return pw1; - } - cerr << "Passwords do not match" << endl; - } + // Copied from pwsafe + while (true) + { + StringX pw1 = GetPassword(prompt1); + if (pw1.empty()) + { + if (GetYN("Generate random password? [y] ", true)) + { + pw1 = RandomPassword(); + if (!pw1.empty()) + return pw1; + else + continue; // back to entering by hand for them + // (perhaps they want to copy only a subset + // of the original pw) + } // else let them have an empty password, though they'll have + // to enter it twice + } + StringX pw2 = GetPassword(prompt2); + if (pw1 == pw2) + { + return pw1; + } + cerr << "Passwords do not match" << endl; + } } bool cTerminal::GetYN(char const *prompt, int def_val) { - // Copied from pwsafe - while (true) - { - char c = GetChar(prompt, def_val > 0 ? 'y' : def_val == 0 ? 'n' : -1); - switch (tolower(c)) - { - case 'y': - return true; - case 'n': - return false; - // default: prompt again until we get a good answer - } - } + // Copied from pwsafe + while (true) + { + char c = GetChar(prompt, def_val > 0 ? 'y' : def_val == 0 ? 'n' : -1); + switch (tolower(c)) + { + case 'y': + return true; + case 'n': + return false; + // default: prompt again until we get a good answer + } + } } char cTerminal::GetChar(char const *prompt, const int def_val) { - // Copied from pwsafe - struct termios tio; - tcgetattr(STDIN_FILENO, &tio); - { - termios new_tio = tio; - new_tio.c_lflag &= ~(ICANON); - // now that we turn ICANON off we *must* set VMIN=1 - // or on sparc the read() buffers 4 at a time - new_tio.c_cc[VMIN] = 1; - new_tio.c_cc[VTIME] = 0; - tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); - } - BOOST_SCOPE_EXIT((&tio)){ - tcsetattr(STDIN_FILENO, TCSANOW, &tio); - } BOOST_SCOPE_EXIT_END - - while (true) - { - cout << prompt << flush; - char x; - ssize_t rc = read(STDIN_FILENO, &x, 1); - - if (rc != 1) - throw runtime_error("Read error"); - switch (x) - { - case '\r': - cout << endl; - // fall through to '\n' - case '\n': - if (def_val >= 0) - return def_val; - // else there is no default and the user must hit a proper char - break; - default: - cout << endl; - return x; - } - // if we get this far the user didn't answer, and we loop - // and reprompt them - } + // Copied from pwsafe + struct termios tio; + tcgetattr(STDIN_FILENO, &tio); + { + termios new_tio = tio; + new_tio.c_lflag &= ~(ICANON); + // now that we turn ICANON off we *must* set VMIN=1 + // or on sparc the read() buffers 4 at a time + new_tio.c_cc[VMIN] = 1; + new_tio.c_cc[VTIME] = 0; + tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); + } + BOOST_SCOPE_EXIT((&tio)){ + tcsetattr(STDIN_FILENO, TCSANOW, &tio); + } BOOST_SCOPE_EXIT_END + + while (true) + { + cout << prompt << flush; + char x; + ssize_t rc = read(STDIN_FILENO, &x, 1); + + if (rc != 1) + throw runtime_error("Read error"); + switch (x) + { + case '\r': + cout << endl; + // fall through to '\n' + case '\n': + if (def_val >= 0) + return def_val; + // else there is no default and the user must hit a proper char + break; + default: + cout << endl; + return x; + } + // if we get this far the user didn't answer, and we loop + // and reprompt them + } } StringX cTerminal::RandomPassword() { - // Copied from pwsafe - - // here I implement the 'easyvision' mode of pwsafe 1.9.x - // where the resulting ascii has nice legibility properties - // for those who copy these by hand - const static char all_alphanum[] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - const static char easyvision_alphanum[] = "abcdefghijkmnopqrstuvwxyz" - "ABCDEFGHJKLMNPQRTUVWXY" - "346789"; - const static char easyvision_symbol[] = "+-=_@#$%^&<>/~\\?"; - const static char hex_only[] = "0123456789abcdef"; - const static char digits_only[] = "0123456789"; - - - int entropy_needed = 20*8; // enough for proper initialization - // of a SHA1 hash, and enough for proper direct - // keying of 128-bit block ciphers - int type = 0; - while (true) - { - const char* type_name = ""; - const char* sets[2] = { "", "" }; - int entropy_per_char; - bool one_char_from_each_type = true; - switch (type) - { - case 0: - type_name = "alpha/digit/symbol"; - sets[0] = all_alphanum; - sets[1] = easyvision_symbol; - entropy_per_char = 628; - // 100 * log2(26+26+10+16) = log2(78); best case - break; - case 1: - type_name = "alpha/digit"; - sets[0] = all_alphanum; - entropy_per_char = 595; - break; - case 2: - type_name = "easy-to-read alpha/digit"; - sets[0] = easyvision_alphanum; - entropy_per_char = 555; - // 100 * log2(25+22+10) = log2(57); worse case - break; - case 3: - type_name = "easy-to-read alpha/digit/symbol"; - sets[0] = easyvision_alphanum; - sets[1] = easyvision_symbol; - entropy_per_char = 597; - break; - case 4: - type_name = "digits only"; - sets[0] = digits_only; - entropy_per_char = 332; // 100 * log2(10) - one_char_from_each_type = false; - break; - case 5: - type_name = "hex digits only"; - sets[0] = hex_only; - entropy_per_char = 400; // 100 * log2(16) - one_char_from_each_type = false; - break; - default: - // wrap around back to type 0 - type = 0; - continue; - } - - const int set0_chars = strlen(sets[0]); - const int total_chars = set0_chars + strlen(sets[1]); - - // But we are not going to generate all possible passwords - // because we are going to exclude those that don't have at least - // one char from each type, so that reduces the entropy_per_char - // if originally we had 2^(num_chars * entropy_per_char) possible - // passwords, and we exclude (in the worst case) (and double-counting - // those passwords that have two types of char missing) - // (57-25)/57 ^ num_chars + (57-22)/57 ^ num_chars + - // + (57-10)/57 ^ num_chars of these, we reduce the bits of entropy - // per char by - // log2(57)-log2(57-25) + log2(57)-log2(57-22) + log2(57)-log2(57-10) = - // = 1.82 pessimist bits/char - if (one_char_from_each_type) - entropy_per_char -= 182; - - const int num_chars = 1+100*entropy_needed/entropy_per_char; - // we want 20*8 bits of entropy in our password (thus good enough - // to create good SHA1 hashes/to key 128-bit key secret key algo's); - // +1 is in lou of rounding the division properly - - StringX pw; - bool got_upper, got_lower, got_num, got_sym; - do - { - pw.erase(); - - got_upper = false; - got_lower = false; - got_num = false; - got_sym = false; - - for (int i=0; i= total_chars); - - char c; - if (idx < set0_chars) - c = sets[0][idx]; - else - c = sets[1][idx-set0_chars]; - - pw += c; - - if (islower(c)) got_lower = true; - else if (isupper(c)) got_upper = true; - else if (isdigit(c)) got_num = true; - else got_sym = true; - } - } while (one_char_from_each_type && - (!got_lower || - !got_upper || - !got_num || - (sets[1][0] && !got_sym))); - // some systems want one of each type of char in the password, - // so might as well do it all the time, even though it is a tiny bit - // less random this way (but we already took that into account - // in entropy_per_char) - - // see what the user thinks of this one - OStringStreamX prompt_oss; - prompt_oss << "Use " << pw << "\n" - "type " << type_name << ", " - "length " << pw.length() << ", " - << entropy_needed - << " bits of entropy [y/N/ /+/-/q/?] ? "; - StringX prompt = prompt_oss.str(); - switch (tolower(GetChar(prompt, 'n'))) - { - case 'y': - return pw; - case 'q': - return ""; - case ' ': - type++; - break; - case '-': - if (entropy_needed > 128) - entropy_needed -= 32; - else if (entropy_needed > 64) - entropy_needed -= 16; - else if (entropy_needed > 32) - entropy_needed -= 8; - // else you can't go any lower - break; - case '+': case '=': - if (entropy_needed < 64) - entropy_needed += 8; - else if (entropy_needed < 128) - entropy_needed += 16; - // so we can hit 112, the magic number for WEP keys - else - entropy_needed += 32; - break; - case '?': case 'h': - cout << - "Commands:\n" - " Y Yes, accept this password\n" - " N No, generate another password of same type\n" - " Cycle through password types\n" - " - Lower the entropy & password length\n" - " + Raise the entropy & password length\n" - " Q Quit\n" - " ? Help\n" - << endl; - continue; - // default: show another password - } - } + // Copied from pwsafe + + // here I implement the 'easyvision' mode of pwsafe 1.9.x + // where the resulting ascii has nice legibility properties + // for those who copy these by hand + const static char all_alphanum[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + const static char easyvision_alphanum[] = "abcdefghijkmnopqrstuvwxyz" + "ABCDEFGHJKLMNPQRTUVWXY" + "346789"; + const static char easyvision_symbol[] = "+-=_@#$%^&<>/~\\?"; + const static char hex_only[] = "0123456789abcdef"; + const static char digits_only[] = "0123456789"; + + + int entropy_needed = 20*8; // enough for proper initialization + // of a SHA1 hash, and enough for proper direct + // keying of 128-bit block ciphers + int type = 0; + while (true) + { + const char* type_name = ""; + const char* sets[2] = { "", "" }; + int entropy_per_char; + bool one_char_from_each_type = true; + switch (type) + { + case 0: + type_name = "alpha/digit/symbol"; + sets[0] = all_alphanum; + sets[1] = easyvision_symbol; + entropy_per_char = 628; + // 100 * log2(26+26+10+16) = log2(78); best case + break; + case 1: + type_name = "alpha/digit"; + sets[0] = all_alphanum; + entropy_per_char = 595; + break; + case 2: + type_name = "easy-to-read alpha/digit"; + sets[0] = easyvision_alphanum; + entropy_per_char = 555; + // 100 * log2(25+22+10) = log2(57); worse case + break; + case 3: + type_name = "easy-to-read alpha/digit/symbol"; + sets[0] = easyvision_alphanum; + sets[1] = easyvision_symbol; + entropy_per_char = 597; + break; + case 4: + type_name = "digits only"; + sets[0] = digits_only; + entropy_per_char = 332; // 100 * log2(10) + one_char_from_each_type = false; + break; + case 5: + type_name = "hex digits only"; + sets[0] = hex_only; + entropy_per_char = 400; // 100 * log2(16) + one_char_from_each_type = false; + break; + default: + // wrap around back to type 0 + type = 0; + continue; + } + + const int set0_chars = strlen(sets[0]); + const int total_chars = set0_chars + strlen(sets[1]); + + // But we are not going to generate all possible passwords + // because we are going to exclude those that don't have at least + // one char from each type, so that reduces the entropy_per_char + // if originally we had 2^(num_chars * entropy_per_char) possible + // passwords, and we exclude (in the worst case) (and double-counting + // those passwords that have two types of char missing) + // (57-25)/57 ^ num_chars + (57-22)/57 ^ num_chars + + // + (57-10)/57 ^ num_chars of these, we reduce the bits of entropy + // per char by + // log2(57)-log2(57-25) + log2(57)-log2(57-22) + log2(57)-log2(57-10) = + // = 1.82 pessimist bits/char + if (one_char_from_each_type) + entropy_per_char -= 182; + + const int num_chars = 1+100*entropy_needed/entropy_per_char; + // we want 20*8 bits of entropy in our password (thus good enough + // to create good SHA1 hashes/to key 128-bit key secret key algo's); + // +1 is in lou of rounding the division properly + + StringX pw; + bool got_upper, got_lower, got_num, got_sym; + do + { + pw.erase(); + + got_upper = false; + got_lower = false; + got_num = false; + got_sym = false; + + for (int i=0; i= total_chars); + + char c; + if (idx < set0_chars) + c = sets[0][idx]; + else + c = sets[1][idx-set0_chars]; + + pw += c; + + if (islower(c)) got_lower = true; + else if (isupper(c)) got_upper = true; + else if (isdigit(c)) got_num = true; + else got_sym = true; + } + } while (one_char_from_each_type && + (!got_lower || + !got_upper || + !got_num || + (sets[1][0] && !got_sym))); + // some systems want one of each type of char in the password, + // so might as well do it all the time, even though it is a tiny bit + // less random this way (but we already took that into account + // in entropy_per_char) + + // see what the user thinks of this one + OStringStreamX prompt_oss; + prompt_oss << "Use " << pw << "\n" + "type " << type_name << ", " + "length " << pw.length() << ", " + << entropy_needed + << " bits of entropy [y/N/ /+/-/q/?] ? "; + StringX prompt = prompt_oss.str(); + switch (tolower(GetChar(prompt, 'n'))) + { + case 'y': + return pw; + case 'q': + return ""; + case ' ': + type++; + break; + case '-': + if (entropy_needed > 128) + entropy_needed -= 32; + else if (entropy_needed > 64) + entropy_needed -= 16; + else if (entropy_needed > 32) + entropy_needed -= 8; + // else you can't go any lower + break; + case '+': case '=': + if (entropy_needed < 64) + entropy_needed += 8; + else if (entropy_needed < 128) + entropy_needed += 16; + // so we can hit 112, the magic number for WEP keys + else + entropy_needed += 32; + break; + case '?': case 'h': + cout << + "Commands:\n" + " Y Yes, accept this password\n" + " N No, generate another password of same type\n" + " Cycle through password types\n" + " - Lower the entropy & password length\n" + " + Raise the entropy & password length\n" + " Q Quit\n" + " ? Help\n" + << endl; + continue; + // default: show another password + } + } } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Terminal.hh b/src/Terminal.hh index 89e4afa..59c5ebf 100644 --- a/src/Terminal.hh +++ b/src/Terminal.hh @@ -29,57 +29,57 @@ namespace gPWS { class cRawTerminal - : boost::noncopyable + : boost::noncopyable { public: - cRawTerminal(bool new_line = false); - ~cRawTerminal(); + cRawTerminal(bool new_line = false); + ~cRawTerminal(); private: - bool _new_line; - struct termios _tio; + bool _new_line; + struct termios _tio; }; class cTerminal - : boost::noncopyable + : boost::noncopyable { public: - static StringX GetPassword(char const *prompt); + static StringX GetPassword(char const *prompt); - static StringX GetPassword(std::string const &prompt) - { - return GetPassword(prompt.c_str()); - } + static StringX GetPassword(std::string const &prompt) + { + return GetPassword(prompt.c_str()); + } - static StringX GetText(char const *prompt, - StringX const &def = ""); + static StringX GetText(char const *prompt, + StringX const &def = ""); - static StringX GetText(StringX const &prompt, - StringX const &def = "") - { - return GetText(prompt.c_str(), def); - } + static StringX GetText(StringX const &prompt, + StringX const &def = "") + { + return GetText(prompt.c_str(), def); + } - static StringX EnterPassword(char const *prompt1, char const *prompt2); + static StringX EnterPassword(char const *prompt1, char const *prompt2); - static bool GetYN(char const *prompt, int def_val = -1); + static bool GetYN(char const *prompt, int def_val = -1); - static bool GetYN(std::string const &prompt, int def_val = -1) - { - return GetYN(prompt.c_str(), def_val); - } + static bool GetYN(std::string const &prompt, int def_val = -1) + { + return GetYN(prompt.c_str(), def_val); + } - static char GetChar(char const *prompt, const int def_val); + static char GetChar(char const *prompt, const int def_val); - template - static char GetChar(StringT const &prompt, const int def_val) - { - return GetChar(prompt.c_str(), def_val); - } + template + static char GetChar(StringT const &prompt, const int def_val) + { + return GetChar(prompt.c_str(), def_val); + } - static StringX RandomPassword(); + static StringX RandomPassword(); }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Twofish.cc b/src/Twofish.cc index d4c5537..47fa590 100644 --- a/src/Twofish.cc +++ b/src/Twofish.cc @@ -31,75 +31,75 @@ using namespace std; cTwofish::cTwofish(eMode mode, void const *key, size_t key_len) { - gcry_error_t error = gcry_cipher_open(&_h, - GCRY_CIPHER_TWOFISH, - mode, - // FIXME!!! - 0);//GCRY_CIPHER_SECURE); - if (error) - { - cerr << "gcry_cipher_open failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("cipher error"); - } + gcry_error_t error = gcry_cipher_open(&_h, + GCRY_CIPHER_TWOFISH, + mode, + // FIXME!!! + 0);//GCRY_CIPHER_SECURE); + if (error) + { + cerr << "gcry_cipher_open failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("cipher error"); + } - error = gcry_cipher_setkey(_h, key, key_len); - if (error) - { - cerr << "gcry_cipher_setkey failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("cipher error"); - } + error = gcry_cipher_setkey(_h, key, key_len); + if (error) + { + cerr << "gcry_cipher_setkey failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("cipher error"); + } } cTwofish::~cTwofish() { - gcry_cipher_close(_h); + gcry_cipher_close(_h); } void cTwofish::SetIV(void const *iv, size_t iv_len) { - gcry_error_t error = - gcry_cipher_setiv(_h, iv, iv_len); - if (error) - { - cerr << "gcry_cipher_setiv failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("cipher error"); - } + gcry_error_t error = + gcry_cipher_setiv(_h, iv, iv_len); + if (error) + { + cerr << "gcry_cipher_setiv failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("cipher error"); + } } void cTwofish::Decrypt(uint8_t *out, size_t out_len, uint8_t const *in, size_t in_len) { - gcry_error_t error = - gcry_cipher_decrypt(_h, out, out_len, in, in_len); - if (error) - { - cerr << "gcry_cipher_decrypt failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("cipher error"); - } + gcry_error_t error = + gcry_cipher_decrypt(_h, out, out_len, in, in_len); + if (error) + { + cerr << "gcry_cipher_decrypt failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("cipher error"); + } } void cTwofish::Encrypt(uint8_t *out, size_t out_len, uint8_t const *in, size_t in_len) { - gcry_error_t error = - gcry_cipher_encrypt(_h, out, out_len, in, in_len); - if (error) - { - cerr << "gcry_cipher_encrypt failed: " - << gcry_strsource(error) << "/" - << gcry_strerror(error) << endl; - throw runtime_error("cipher error"); - } + gcry_error_t error = + gcry_cipher_encrypt(_h, out, out_len, in, in_len); + if (error) + { + cerr << "gcry_cipher_encrypt failed: " + << gcry_strsource(error) << "/" + << gcry_strerror(error) << endl; + throw runtime_error("cipher error"); + } } } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/Twofish.hh b/src/Twofish.hh index 0874ab6..bd77ef0 100644 --- a/src/Twofish.hh +++ b/src/Twofish.hh @@ -29,57 +29,57 @@ namespace gPWS { class cTwofish - : boost::noncopyable + : boost::noncopyable { public: - enum eMode - { - M_ECB = GCRY_CIPHER_MODE_ECB, - M_CBC = GCRY_CIPHER_MODE_CBC - }; + enum eMode + { + M_ECB = GCRY_CIPHER_MODE_ECB, + M_CBC = GCRY_CIPHER_MODE_CBC + }; - static const unsigned KEY_LENGTH = 32; - static const unsigned BLOCK_LENGTH = 16; + static const unsigned KEY_LENGTH = 32; + static const unsigned BLOCK_LENGTH = 16; - cTwofish(eMode mode, - void const *key, size_t key_len); + cTwofish(eMode mode, + void const *key, size_t key_len); - ~cTwofish(); + ~cTwofish(); - void SetIV(void const *iv, size_t iv_len); + void SetIV(void const *iv, size_t iv_len); - void Decrypt(uint8_t *out, size_t out_len, - uint8_t const *in, size_t in_len); + void Decrypt(uint8_t *out, size_t out_len, + uint8_t const *in, size_t in_len); - template - void Decrypt(A *out, size_t out_len, - B const *in, size_t in_len) - { - BOOST_STATIC_ASSERT(sizeof(A) == sizeof(uint8_t)); - BOOST_STATIC_ASSERT(sizeof(B) == sizeof(uint8_t)); + template + void Decrypt(A *out, size_t out_len, + B const *in, size_t in_len) + { + BOOST_STATIC_ASSERT(sizeof(A) == sizeof(uint8_t)); + BOOST_STATIC_ASSERT(sizeof(B) == sizeof(uint8_t)); - Decrypt(reinterpret_cast(out), out_len, - reinterpret_cast(in), in_len); - } + Decrypt(reinterpret_cast(out), out_len, + reinterpret_cast(in), in_len); + } - void Encrypt(uint8_t *out, size_t out_len, - uint8_t const *in, size_t in_len); + void Encrypt(uint8_t *out, size_t out_len, + uint8_t const *in, size_t in_len); - template - void Encrypt(A *out, size_t out_len, - B const *in, size_t in_len) - { - BOOST_STATIC_ASSERT(sizeof(A) == sizeof(uint8_t)); - BOOST_STATIC_ASSERT(sizeof(B) == sizeof(uint8_t)); + template + void Encrypt(A *out, size_t out_len, + B const *in, size_t in_len) + { + BOOST_STATIC_ASSERT(sizeof(A) == sizeof(uint8_t)); + BOOST_STATIC_ASSERT(sizeof(B) == sizeof(uint8_t)); - Encrypt(reinterpret_cast(out), out_len, - reinterpret_cast(in), in_len); - } + Encrypt(reinterpret_cast(out), out_len, + reinterpret_cast(in), in_len); + } private: - gcry_cipher_hd_t _h; + gcry_cipher_hd_t _h; }; } //namespace gPWS; -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/src/main.cc b/src/main.cc index 87c2079..70cf6be 100644 --- a/src/main.cc +++ b/src/main.cc @@ -30,39 +30,43 @@ using namespace std; using namespace gPWS; -static char const *_Basename(char const *path) +namespace { + +char const *_Basename(char const *path) { - char const *res = strrchr(path, '/'); - if (!res) - return path; - return res + 1; + char const *res = strrchr(path, '/'); + if (!res) + return path; + return res + 1; } +} //namespace; + int main(int argc, char* argv[]) { - char const *program_name = _Basename(argv[0]); + char const *program_name = _Basename(argv[0]); - // Be nice and paranoid - umask(0077); + // Be nice and paranoid + umask(0077); - if (int res = cGcrypt::Init()) - { - cerr << "Can't initialize libgcrypt" << endl; - return res; - } + if (int res = cGcrypt::Init()) + { + cerr << "Can't initialize libgcrypt" << endl; + return res; + } - try - { - cApp app(program_name); - app.Init(argc, argv); + try + { + cApp app(program_name); + app.Init(argc, argv); - app.Run(); - } - catch (cApp::ExitEx const &e) - { - return e.retcode; - } - return 0; + app.Run(); + } + catch (cApp::ExitEx const &e) + { + return e.retcode; + } + return 0; } -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/test/EntryTest.cc b/test/EntryTest.cc index fdc0ef3..93f2e43 100644 --- a/test/EntryTest.cc +++ b/test/EntryTest.cc @@ -16,26 +16,26 @@ BOOST_AUTO_TEST_SUITE(EntryTest) BOOST_AUTO_TEST_CASE(TestDiff) { - using namespace gPWS; - cEntry::PtrT entry0(cEntry::Create()); - entry0->SetGroup("arch"); - entry0->SetTitle("aur"); - - cEntry::PtrT entry1(cEntry::Create()); - entry1->SetTitle("aur2"); - entry1->SetUser("sakhnik"); - - cEntry::DiffT diff = entry1->Diff(entry0); - - BOOST_CHECK_EQUAL(diff.size(), 3); - BOOST_CHECK_EQUAL(diff[0].type, cEntry::FT_GROUP); - BOOST_CHECK_EQUAL(diff[0].change, cEntry::sChange::C_DELETED); - BOOST_CHECK_EQUAL(diff[1].type, cEntry::FT_TITLE); - BOOST_CHECK_EQUAL(diff[1].change, cEntry::sChange::C_MODIFIED); - BOOST_CHECK_EQUAL(diff[2].type, cEntry::FT_USER); - BOOST_CHECK_EQUAL(diff[2].change, cEntry::sChange::C_ADDED); + using namespace gPWS; + cEntry::PtrT entry0(cEntry::Create()); + entry0->SetGroup("arch"); + entry0->SetTitle("aur"); + + cEntry::PtrT entry1(cEntry::Create()); + entry1->SetTitle("aur2"); + entry1->SetUser("sakhnik"); + + cEntry::DiffT diff = entry1->Diff(entry0); + + BOOST_CHECK_EQUAL(diff.size(), 3); + BOOST_CHECK_EQUAL(diff[0].type, cEntry::FT_GROUP); + BOOST_CHECK_EQUAL(diff[0].change, cEntry::sChange::C_DELETED); + BOOST_CHECK_EQUAL(diff[1].type, cEntry::FT_TITLE); + BOOST_CHECK_EQUAL(diff[1].change, cEntry::sChange::C_MODIFIED); + BOOST_CHECK_EQUAL(diff[2].type, cEntry::FT_USER); + BOOST_CHECK_EQUAL(diff[2].change, cEntry::sChange::C_ADDED); } BOOST_AUTO_TEST_SUITE_END() -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/test/File3Test.cc b/test/File3Test.cc index 981da7f..a9d12f6 100644 --- a/test/File3Test.cc +++ b/test/File3Test.cc @@ -19,10 +19,10 @@ using namespace std; struct sGlobalFixture { - sGlobalFixture() - { - gPWS::cGcrypt::Init(); - } + sGlobalFixture() + { + gPWS::cGcrypt::Init(); + } } global_fixture; @@ -30,51 +30,51 @@ BOOST_AUTO_TEST_SUITE(File3Test) BOOST_AUTO_TEST_CASE(TestWriteRead) { - srand(static_cast(time(NULL))); - - using namespace gPWS; - - typedef vector FieldsT; - FieldsT fields1; - for (unsigned i = 0, n = rand() % 999; i != n; ++i) - { - sField::PtrT field(sField::Create()); - field->type = rand() % 256; - field->value.resize(rand() % 256); - generate(field->value.begin(), field->value.end(), &rand); - fields1.push_back(field); - } - - char const *const fname = "/tmp/file3_test.psafe3"; - char const *const pass = "!23$QweR"; - - cFile3 file1; - file1.OpenWrite(fname, pass, true, false); - - for (FieldsT::const_iterator i = fields1.begin(); i != fields1.end(); ++i) - file1.WriteField(*i); - - file1.CloseWrite(); - - cFile3 file2; - file2.OpenRead(fname, pass); - FieldsT fields2; - sField::PtrT field; - while ((field = file2.ReadField())) - { - fields2.push_back(field); - } - - BOOST_CHECK_EQUAL_COLLECTIONS( - boost::make_indirect_iterator(fields1.begin()), - boost::make_indirect_iterator(fields1.end()), - boost::make_indirect_iterator(fields2.begin()), - boost::make_indirect_iterator(fields2.end()) - ); - - ::unlink(fname); + srand(static_cast(time(NULL))); + + using namespace gPWS; + + typedef vector FieldsT; + FieldsT fields1; + for (unsigned i = 0, n = rand() % 999; i != n; ++i) + { + sField::PtrT field(sField::Create()); + field->type = rand() % 256; + field->value.resize(rand() % 256); + generate(field->value.begin(), field->value.end(), &rand); + fields1.push_back(field); + } + + char const *const fname = "/tmp/file3_test.psafe3"; + char const *const pass = "!23$QweR"; + + cFile3 file1; + file1.OpenWrite(fname, pass, true, false); + + for (FieldsT::const_iterator i = fields1.begin(); i != fields1.end(); ++i) + file1.WriteField(*i); + + file1.CloseWrite(); + + cFile3 file2; + file2.OpenRead(fname, pass); + FieldsT fields2; + sField::PtrT field; + while ((field = file2.ReadField())) + { + fields2.push_back(field); + } + + BOOST_CHECK_EQUAL_COLLECTIONS( + boost::make_indirect_iterator(fields1.begin()), + boost::make_indirect_iterator(fields1.end()), + boost::make_indirect_iterator(fields2.begin()), + boost::make_indirect_iterator(fields2.end()) + ); + + ::unlink(fname); } BOOST_AUTO_TEST_SUITE_END() -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/test/KeyStretchTest.cc b/test/KeyStretchTest.cc index 993c84f..3cbd582 100644 --- a/test/KeyStretchTest.cc +++ b/test/KeyStretchTest.cc @@ -19,28 +19,28 @@ BOOST_AUTO_TEST_SUITE(KeyStretchTest) BOOST_AUTO_TEST_CASE(First) { - using namespace gPWS; - StringX pass("first123"); - string salt("\x12\xE8\xA7\x6F\x0B\x20\x84\x7A" - "\x51\x49\xC3\x9D\xD3\xA5\xB1\xD5" - "\x44\x46\x3A\xE6\x2D\x89\x99\x10" - "\x44\x44\x85\x59\x7A\x89\xE3\x87"); - cKeyStretch key_stretch(pass.c_str(), pass.size(), - salt.c_str(), salt.size(), - 2048); - const uint8_t ref[] = - { - 0x97, 0xE3, 0xD3, 0x0F, 0x55, 0x86, 0x76, 0xC1, - 0x1C, 0x2A, 0xA6, 0xFE, 0xD1, 0xEC, 0xA4, 0x04, - 0xD9, 0xF4, 0xB2, 0x88, 0xB4, 0x73, 0x14, 0x07, - 0xDC, 0x76, 0xD0, 0x1B, 0xEC, 0x2A, 0x02, 0x65 - }; - BOOST_CHECK_EQUAL_COLLECTIONS(boost::begin(ref), - boost::end(ref), - key_stretch.Get(), - key_stretch.Get() + key_stretch.LENGTH); + using namespace gPWS; + StringX pass("first123"); + string salt("\x12\xE8\xA7\x6F\x0B\x20\x84\x7A" + "\x51\x49\xC3\x9D\xD3\xA5\xB1\xD5" + "\x44\x46\x3A\xE6\x2D\x89\x99\x10" + "\x44\x44\x85\x59\x7A\x89\xE3\x87"); + cKeyStretch key_stretch(pass.c_str(), pass.size(), + salt.c_str(), salt.size(), + 2048); + const uint8_t ref[] = + { + 0x97, 0xE3, 0xD3, 0x0F, 0x55, 0x86, 0x76, 0xC1, + 0x1C, 0x2A, 0xA6, 0xFE, 0xD1, 0xEC, 0xA4, 0x04, + 0xD9, 0xF4, 0xB2, 0x88, 0xB4, 0x73, 0x14, 0x07, + 0xDC, 0x76, 0xD0, 0x1B, 0xEC, 0x2A, 0x02, 0x65 + }; + BOOST_CHECK_EQUAL_COLLECTIONS(boost::begin(ref), + boost::end(ref), + key_stretch.Get(), + key_stretch.Get() + key_stretch.LENGTH); } BOOST_AUTO_TEST_SUITE_END() -// vim: set et ts=4 sw=4 tw=80: +// vim: set noet ts=4 sw=4 tw=80: diff --git a/test/Makefile.am b/test/Makefile.am index 4146615..30e45ef 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -4,22 +4,22 @@ TESTS = KeyStretchTest \ EntryTest check_PROGRAMS = KeyStretchTest \ - File3Test \ - EntryTest + File3Test \ + EntryTest KeyStretchTest_SOURCES = KeyStretchTest.cc KeyStretchTest_LDADD = $(top_builddir)/src/libgpwsafe.a \ - $(LIBGCRYPT_LIBS) \ - $(BOOST_UNIT_TEST_FRAMEWORK_LIB) + $(LIBGCRYPT_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIB) File3Test_SOURCES = File3Test.cc File3Test_LDADD = $(top_builddir)/src/libgpwsafe.a \ - $(LIBGCRYPT_LIBS) \ - $(BOOST_UNIT_TEST_FRAMEWORK_LIB) + $(LIBGCRYPT_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIB) EntryTest_SOURCES = EntryTest.cc EntryTest_LDADD = $(top_builddir)/src/libgpwsafe.a \ - $(LIBGCRYPT_LIBS) \ - $(BOOST_UNIT_TEST_FRAMEWORK_LIB) + $(LIBGCRYPT_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIB) AM_CPPFLAGS = $(BOOST_CPPFLAGS) -DBOOST_TEST_DYN_LINK