2 * Copyright (C) 2018 Sam Hartman
3 * Copyright (c) 2011-2016, JANET(UK)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of JANET(UK) nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 private Collection? find_secret_collection()
40 Collection secret_collection = null;
42 Service service = Service.get_sync(ServiceFlags.OPEN_SESSION);
43 secret_collection = Collection.for_alias_sync(service, COLLECTION_DEFAULT,
44 CollectionFlags.NONE);
45 } catch(GLib.Error e) {
46 stdout.printf("Unable to load secret service: %s\n", e.message);
48 return secret_collection;
51 public class KeyringStore : KeyringStoreBase {
53 * We choose to remain compatible with the way we stored secrets
54 * using libgnomekeyring. As a result, we cannot use our own schema
55 * identifier. Using our own schema might get us a nice icon in
56 * seahorse, but would not save much code.
58 private const SchemaAttributeType sstring = SchemaAttributeType.STRING;
59 private static Schema schema = new Schema("org.freedesktop.Secret.Generic", SchemaFlags.NONE,
63 "DisplayName", sstring,
65 "Rules-Pattern", sstring,
66 "Rules-AlwaysConfirm", sstring,
68 "Server-Cert", sstring,
70 "Subject-Alt", sstring,
71 "TA_DateTime_Added", sstring,
72 "StorePassword", sstring);
73 private static Collection? secret_collection = find_secret_collection();
75 /* clear all keyring-stored ids (in preparation to store current list) */
76 protected override void clear_keyring() {
77 GLib.List<Item> items;
79 items = secret_collection.search_sync(schema, match_attributes, SearchFlags.ALL);
80 } catch (GLib.Error e) {
81 stdout.printf("Failed to find items to delete: %s\n", e.message);
84 foreach(unowned Item entry in items) {
86 bool res = entry.delete_sync();
88 stdout.printf("Failed to delete item: %s\n", entry.get_label());
90 } catch (GLib.Error e) {
91 stdout.printf("Error deleting item: %s\n", e.message);
96 protected override void load_id_cards() throws GLib.Error {
99 GLib.List<Item> items = secret_collection.search_sync(schema, match_attributes,
100 SearchFlags.UNLOCK|SearchFlags.LOAD_SECRETS|SearchFlags.ALL);
101 foreach(unowned Item entry in items) {
102 var secret = entry.get_secret();
103 string secret_text = null;
105 secret_text = secret.get_text();
106 var id_card = deserialize(entry.attributes, secret_text);
107 id_card_list.add(id_card);
111 internal override void store_id_cards() {
112 logger.trace("store_id_cards");
114 foreach (IdCard id_card in this.id_card_list) {
116 var attributes = serialize(id_card);
117 password_storev_sync(schema, attributes, null, id_card.display_name,
118 id_card.store_password?id_card.password: "");
119 } catch(GLib.Error e) {
120 logger.error(@"Unable to store $(id_card.display_name): $(e.message)\n");
125 } catch (GLib.Error e) {
126 logger.error(@"Unable to load ID Cards: $(e.message)\n");
131 public static bool is_available()
133 if (secret_collection == null) {
134 secret_collection = find_secret_collection();
137 return secret_collection != null;