diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7b8b26907e8559f01f508d6de8b89115db105d12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ + +*.out +*.gi +bin/unlock_keyrings + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..e1e0a82086172e85ef0bf84f80a235c006649ed0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/lib/rlib"] + path = src/lib/rlib + url = https://github.com/recolic/rlib.git diff --git a/create_secret_file.sh b/create_secret_file.sh new file mode 100755 index 0000000000000000000000000000000000000000..ca22cb44a4956a538f6f18fcec439a55dd0be5b4 --- /dev/null +++ b/create_secret_file.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +filename="$1" +gpg_pubkey_id="$2" # leave empty to use default receipt. + +echo '>>> Please type keyring_name and password in the following format: + +keyring1:password1 +keyring2:password2 + +# Comment: This is a comment +login:12345678 + +>>> When you are done, use Ctrl-D to end.' + +gpg --encrypt -o "$filename" -a -r "$gpg_pubkey_id" +exit $? diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a0b203b5e9621b72520b78e88eb75a67420b2dcd --- /dev/null +++ b/src/Makefile @@ -0,0 +1,11 @@ + +CXX ?= g++ +CXXFLAGS := $(shell pkg-config --cflags --libs gnome-keyring-1) -I ./lib -I . +EXTRA_FLAGS ?= + +secret: rlib + $(CXX) $(CXXFLAGS) $(EXTRA_FLAGS) unlock_keyrings.cc ./lib/rlib/libr.a -o ../bin/unlock_keyrings + +rlib: + cd ./lib/rlib && make + diff --git a/src/keyring_op.hpp b/src/keyring_op.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de9d1da0c84e68c7fe2baab98a5f5a9d0efda442 --- /dev/null +++ b/src/keyring_op.hpp @@ -0,0 +1,27 @@ +#include <gnome-keyring-1/gnome-keyring.h> +#include <string> +#include <rlib/macro.hpp> + +inline GnomeKeyringResult do_unlock(std::string keyring, std::string password) { + return gnome_keyring_unlock_sync(keyring.c_str(), password.c_str()); +} + +inline std::string keyringResultToString(GnomeKeyringResult res) { + switch(res) { +#define RLIB_IMPL_GEN_RESULT(value) RLIB_IMPL_GEN_RESULT_1(value, RLIB_MACRO_TO_CSTR(value)) +#define RLIB_IMPL_GEN_RESULT_1(value, cstr) case (value): return (cstr) + + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_OK); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_DENIED); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_ALREADY_UNLOCKED); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_NO_SUCH_KEYRING); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_BAD_ARGUMENTS); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_IO_ERROR); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_CANCELLED); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_KEYRING_ALREADY_EXISTS); + RLIB_IMPL_GEN_RESULT(GNOME_KEYRING_RESULT_NO_MATCH); + default: + return std::string("Unknown Result Code: ") + std::to_string(res); + } +} diff --git a/src/lib/rlib b/src/lib/rlib new file mode 160000 index 0000000000000000000000000000000000000000..3a442c6dd8661d45cfe7528112b93c42ffa5d591 --- /dev/null +++ b/src/lib/rlib @@ -0,0 +1 @@ +Subproject commit 3a442c6dd8661d45cfe7528112b93c42ffa5d591 diff --git a/src/unlock_keyrings.cc b/src/unlock_keyrings.cc new file mode 100644 index 0000000000000000000000000000000000000000..3425f6c8ef313b3deec29274e634efe9cac52ee8 --- /dev/null +++ b/src/unlock_keyrings.cc @@ -0,0 +1,57 @@ +#include <rlib/log.hpp> +#include <rlib/opt.hpp> +#include <rlib/stream.hpp> +#include "keyring_op.hpp" + + +int main(int argc, char **argv) { + rlib::opt_parser args(argc, argv); + rlib::logger rlog(std::cout); + + if(args.getBoolArg("-h", "--help")) { + rlog.info("Usage: {} [-h/--help] [-q/--quiet] --secret-file <filename> # use `-` as stdin."); + return 0; + } + if(args.getBoolArg("-q", "--quiet")) { + rlog = rlib::logger(rlib::null_stream); + } + + auto secret_file_name = args.getValueArg("--secret-file"); + if(secret_file_name == "-") + secret_file_name = "/dev/fd/0"; + + std::ifstream secret_input (secret_file_name); + if(not secret_input) { + rlog.error("Unable to open file {}. Exiting...", secret_file_name); + return 2; + } + size_t line_num = 0; + bool no_error = true; + while(not secret_input.eof()) { + auto line = rlib::scanln(secret_input).strip("\t\n\r"); + auto line_removed_space = line; + line_removed_space.strip(' '); // Remove space may break keyring_name or password. + if(line_removed_space.empty() or line_removed_space[0] == '#') + continue; // Skip comments. + + auto keyring_and_pswd = line.split(':'); + if(keyring_and_pswd.size() != 2) { + rlog.error("Secret file line {} has wrong format. Expecting `${keyring}:${password}`", line_num); + return 3; + } + + auto res = do_unlock(keyring_and_pswd.at(0), keyring_and_pswd.at(1)); + auto msg = keyringResultToString(res); + if(res == GNOME_KEYRING_RESULT_OK) + rlog.verbose("line {}: {}.", line_num, msg); + else { + rlog.error("line {}: {}.", line_num, msg); + no_error = false; + } + + ++line_num; + } + + return no_error ? 0 : 4; +} +