Some formatting changes
[moonshot-ui.git] / src / moonshot-keyring-store-secret.vala
1 /*
2 * Copyright (C) 2018   Sam Hartman
3 * Copyright (c) 2011-2016, JANET(UK)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
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.
16  *
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.
20  *
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
31  * SUCH DAMAGE.
32 */
33
34 #if LIBSECRET_KEYRING
35
36 using Secret;
37
38 private Collection? find_secret_collection()
39 {
40     Collection secret_collection = null;
41     try {
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);
47     }
48     return secret_collection;
49 }
50
51 public class KeyringStore : KeyringStoreBase {
52     /*
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.
57     */
58     private const SchemaAttributeType sstring = SchemaAttributeType.STRING;
59     private static Schema schema = new Schema("org.freedesktop.Secret.Generic", SchemaFlags.NONE,
60                                               "Moonshot", sstring,
61                                               "Issuer", sstring,
62                                               "Username", sstring,
63                                               "DisplayName", sstring,
64                                               "Services", sstring,
65                                               "Rules-Pattern", sstring,
66                                               "Rules-AlwaysConfirm", sstring,
67                                               "CA-Cert", sstring,
68                                               "Server-Cert", sstring,
69                                               "Subject", sstring,
70                                               "Subject-Alt", sstring,
71                                               "TA_DateTime_Added", sstring,
72                                               "StorePassword", sstring);
73     private static Collection? secret_collection = find_secret_collection();
74
75     /* clear all keyring-stored ids (in preparation to store current list) */
76     protected override void clear_keyring() {
77         GLib.List<Item> items;
78         try {
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);
82             return;
83         }
84         foreach(unowned Item entry in items) {
85             try {
86                 bool res = entry.delete_sync();
87                 if (!res) {
88                     stdout.printf("Failed to delete item: %s\n", entry.get_label());
89                 }
90             } catch (GLib.Error e) {
91                 stdout.printf("Error deleting item: %s\n", e.message);
92             }
93         }
94     }
95
96     protected override void load_id_cards()  throws GLib.Error {
97         id_card_list.clear();
98
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;
104             if (secret != null)
105                 secret_text = secret.get_text();
106             var id_card = deserialize(entry.attributes, secret_text);
107             id_card_list.add(id_card);
108         }
109     }
110
111     internal override void store_id_cards() {
112         logger.trace("store_id_cards");
113         clear_keyring();
114         foreach (IdCard id_card in this.id_card_list) {
115             try {
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");
121             }
122         }
123         try {
124             load_id_cards();
125         } catch (GLib.Error e) {
126             logger.error(@"Unable to load ID Cards: $(e.message)\n");
127         }
128
129     }
130
131     public static bool is_available()
132     {
133         if (secret_collection == null) {
134             secret_collection = find_secret_collection();
135         }
136
137         return secret_collection != null;
138     }
139
140 }
141
142 #endif