Skip to content

Instantly share code, notes, and snippets.

@adamhotep
Last active March 5, 2019 03:58
Show Gist options
  • Save adamhotep/e5798989187b393789c1 to your computer and use it in GitHub Desktop.
Save adamhotep/e5798989187b393789c1 to your computer and use it in GitHub Desktop.
Simple command-line interface to GNOME keyring
/*
* gnome-keyring-query, for simple command-line interactions with gnome-keyring.
*
* To compile and install:
*
* sudo apt-get install libgnome-keyring-dev libglib2.0-dev
* gcc `pkg-config --cflags --libs gnome-keyring-1 glib-2.0` -o gnome-keyring-query gnome-keyring-query.c
* chmod +x gnome-keyring-query
* sudo cp -p gnome-keyring-query /usr/local/bin/
*
* Forked from public domain code by author(s) unknown, archived at
* https://web.archive.org/web/20160326164519/http://www.gentoo-wiki.info/Store_SSH_passphrases_in_gnome-keyring
*
* All changes from the original source are Copyright 2014+ Adam Katz
* and are released under the GNU LGPL.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* See <http://www.gnu.org/licenses/> for full license text.
*
* BEERWARE: IF YOU THINK THIS IS WORTH IT, YOU ARE WELCOME TO BUY ME A BEER.
*/
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
/*
* Workaround for deprecation of libgnome-keyring (won't work forever)
* TODO: migrate to libsecret (which looks nontrivial, likely WONTFIX).
* Notes for that:
* https://codereview.chromium.org/292573002
* https://bugs.chromium.org/p/chromium/issues/detail?id=355223
*/
#define GNOME_KEYRING_DEPRECATED
#define GNOME_KEYRING_DEPRECATED_FOR(x)
#include "gnome-keyring.h"
#define APPLICATION_NAME "gnome-keyring-query"
#define VERSION "1.2.20190212"
#define MAX_PASSWORD_LENGTH 100
char * get_password(const char * name);
int set_password(const char * name, const char * password);
void usage()
{
puts("Usage:\n"
" " APPLICATION_NAME " <mode> <name>\n"
"Parameters:\n"
" mode - either 'get' or 'set' (without quotes)\n"
" name - a name to identify the key\n"
"Notes:\n"
" If mode is 'get', then the password is dumped to stdout.\n"
" If mode is 'set', then the password is read from stdin.\n"
"\nVersion: " VERSION "\n"
"https://gist.github.com/adamhotep/e5798989187b393789c1"
);
exit(EXIT_FAILURE);
}
int main(int argc, char * argv[])
{
enum
{
MODE_GET, MODE_SET
} mode;
char * name;
char * password;
g_set_application_name(APPLICATION_NAME);
if (argc != 3)
usage();
if (g_ascii_strcasecmp(argv[1], "get") == 0)
mode = MODE_GET;
else if (g_ascii_strcasecmp(argv[1], "set") == 0)
mode = MODE_SET;
else
{
fprintf(stderr, "Invalid mode: %s\n", argv[1]);
exit(EXIT_FAILURE);
}
name = argv[2];
switch (mode)
{
case MODE_GET:
password = get_password(name);
if (!password)
{
fprintf(stderr, "Failed to get password: %s\n", name);
exit(EXIT_FAILURE);
}
puts(password);
g_free(password);
break;
case MODE_SET:
password = g_malloc(MAX_PASSWORD_LENGTH);
*password = '\0';
fgets(password, MAX_PASSWORD_LENGTH, stdin);
if (!set_password(name, password))
{
fprintf(stderr, "Failed to set password: %s\n", name);
exit(EXIT_FAILURE);
}
g_free(password);
break;
}
return 0;
}
char * get_password(const char * name)
{
GnomeKeyringAttributeList * attributes;
GnomeKeyringResult result;
GList * found_list;
GList * i;
GnomeKeyringFound * found;
char * password;
attributes = g_array_new(FALSE, FALSE, sizeof (GnomeKeyringAttribute));
gnome_keyring_attribute_list_append_string(attributes,
"name",
name);
gnome_keyring_attribute_list_append_string(attributes,
"magic",
APPLICATION_NAME);
result = gnome_keyring_find_items_sync(GNOME_KEYRING_ITEM_GENERIC_SECRET,
attributes,
&found_list);
gnome_keyring_attribute_list_free(attributes);
if (result != GNOME_KEYRING_RESULT_OK)
return NULL;
for (i = found_list; i != NULL; i = i->next)
{
found = i->data;
password = g_strdup(found->secret);
break;
}
gnome_keyring_found_list_free(found_list);
return password;
}
int set_password(const char * name, const char * password)
{
GnomeKeyringAttributeList * attributes;
GnomeKeyringResult result;
guint item_id;
attributes = g_array_new(FALSE, FALSE, sizeof (GnomeKeyringAttribute));
gnome_keyring_attribute_list_append_string(attributes,
"name",
name);
gnome_keyring_attribute_list_append_string(attributes,
"magic",
APPLICATION_NAME);
result = gnome_keyring_item_create_sync(NULL,
GNOME_KEYRING_ITEM_GENERIC_SECRET,
name,
attributes,
password,
TRUE,
&item_id);
gnome_keyring_attribute_list_free(attributes);
return (result == GNOME_KEYRING_RESULT_OK);
}
@adamhotep
Copy link
Author

adamhotep commented Aug 12, 2016

@qrkourier – Sorry, I must have missed the github notification for that comment.

Looks like the guts of GNOME keyring are slated for removal. This code depends on deprecated methods and GNOME 3.12+ didn't want to let it happen without an explicit workaround. Solved, at least until "deprecated" becomes "obsoleted."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment