Don't create duplicate identities. LP 1180914.
[moonshot-ui.git] / src / moonshot-keyring-store.vala
1 using Gee;
2
3 #if GNOME_KEYRING
4 public class KeyringStore : Object, IIdentityCardStore {
5     private LinkedList<IdCard> id_card_list;
6     private const string keyring_store_attribute = "Moonshot";
7     private const string keyring_store_version = "1.0";
8     private const GnomeKeyring.ItemType item_type = GnomeKeyring.ItemType.GENERIC_SECRET;
9
10     public void add_card(IdCard card) {
11         id_card_list.add(card);
12         store_id_cards ();
13     }
14
15     public IdCard? update_card(IdCard card) {
16         id_card_list.remove(card);
17         id_card_list.add(card);
18         store_id_cards ();
19         foreach (IdCard idcard in id_card_list)
20             if (idcard.display_name == card.display_name)
21                 return idcard;
22         return null;
23     }
24
25     public bool remove_card(IdCard card) {
26         bool retval = id_card_list.remove(card);
27         if (retval)
28             store_id_cards ();
29         return retval;
30     }
31
32     public IIdentityCardStore.StoreType get_store_type() {
33         return IIdentityCardStore.StoreType.KEYRING;
34     }
35
36     public LinkedList<IdCard> get_card_list() {
37         return id_card_list;
38     }
39
40     /* clear all keyring-stored ids (in preparation to store current list) */
41     private void clear_keyring() {
42         GnomeKeyring.AttributeList match = new GnomeKeyring.AttributeList();
43         match.append_string(keyring_store_attribute, keyring_store_version);
44         GLib.List<GnomeKeyring.Found> items;
45         GnomeKeyring.find_items_sync(item_type, match, out items);
46         foreach(unowned GnomeKeyring.Found entry in items) {
47             GnomeKeyring.Result result = GnomeKeyring.item_delete_sync(null, entry.item_id);
48             if (result != GnomeKeyring.Result.OK) {
49                 stdout.printf("GnomeKeyring.item_delete_sync() failed. result: %d", result);
50             }
51         }
52     }
53      
54     private void load_id_cards() {
55         id_card_list.clear();
56
57         GnomeKeyring.AttributeList match = new GnomeKeyring.AttributeList();
58         match.append_string(keyring_store_attribute, keyring_store_version);
59         GLib.List<GnomeKeyring.Found> items;
60         GnomeKeyring.find_items_sync(item_type, match, out items);
61         foreach(unowned GnomeKeyring.Found entry in items) {
62             IdCard id_card = new IdCard ();
63             int i;
64             int rules_patterns_index = -1;
65             int rules_always_confirm_index = -1;
66             string store_password = null;
67             for (i=0; i<entry.attributes.len; i++) {
68                 var attribute = ((GnomeKeyring.Attribute *) entry.attributes.data)[i];
69                 string value = attribute.string_value;
70                 if (attribute.name == "Issuer") {
71                     id_card.issuer = value;
72                 } else if (attribute.name == "Username") {
73                     id_card.username = value;
74                 } else if (attribute.name == "DisplayName") {
75                     id_card.display_name = value;
76                 } else if (attribute.name == "Services") {
77                     id_card.services = value.split(";");
78                 } else if (attribute.name == "Rules-Pattern") {
79                     rules_patterns_index = i;
80                 } else if (attribute.name == "Rules-AlwaysConfirm") {
81                     rules_always_confirm_index = i;
82                 } else if (attribute.name == "CA-Cert") {
83                     id_card.trust_anchor.ca_cert = value;
84                 } else if (attribute.name == "Server-Cert") {
85                     id_card.trust_anchor.server_cert = value;
86                 } else if (attribute.name == "Subject") {
87                     id_card.trust_anchor.subject = value;
88                 } else if (attribute.name == "Subject-Alt") {
89                     id_card.trust_anchor.subject_alt = value;
90                 } else if (attribute.name == "StorePassword") {
91                     store_password = value;
92                 }
93             }
94             if ((rules_always_confirm_index != -1) && (rules_patterns_index != -1)) {
95                 string rules_patterns_all = ((GnomeKeyring.Attribute *) entry.attributes.data)[rules_patterns_index].string_value;
96                 string rules_always_confirm_all = ((GnomeKeyring.Attribute *) entry.attributes.data)[rules_always_confirm_index].string_value;
97                 string [] rules_always_confirm = rules_always_confirm_all.split(";");
98                 string [] rules_patterns = rules_patterns_all.split(";");
99                 if (rules_patterns.length == rules_always_confirm.length) {
100                    Rule[] rules = new Rule[rules_patterns.length];
101                    for (int j=0; j<rules_patterns.length; j++) {
102                        rules[j].pattern = rules_patterns[j];
103                        rules[j].always_confirm = rules_always_confirm[j];
104                    }
105                    id_card.rules = rules;
106                 }
107             }
108
109             if (store_password != null)
110                 id_card.store_password = (store_password == "yes");
111             else
112                 id_card.store_password = ((entry.secret != null) && (entry.secret != ""));
113
114             if (id_card.store_password)
115                 id_card.password = entry.secret;
116             else
117                 id_card.password = null;
118             id_card_list.add(id_card);
119         }
120     }
121
122     public void store_id_cards () {
123         clear_keyring();
124         foreach (IdCard id_card in this.id_card_list) {
125             string[] rules_patterns = new string[id_card.rules.length];
126             string[] rules_always_conf = new string[id_card.rules.length];
127             
128             for (int i=0; i<id_card.rules.length; i++) {
129                 rules_patterns[i] = id_card.rules[i].pattern;
130                 rules_always_conf[i] = id_card.rules[i].always_confirm;
131             }
132             string patterns = string.joinv(";", rules_patterns);
133             string always_conf = string.joinv(";", rules_always_conf);
134             string services = string.joinv(";", id_card.services);
135             GnomeKeyring.AttributeList attributes = new GnomeKeyring.AttributeList();
136             uint32 item_id;
137             attributes.append_string(keyring_store_attribute, keyring_store_version);
138             attributes.append_string("Issuer", id_card.issuer);
139             attributes.append_string("Username", id_card.username);
140             attributes.append_string("DisplayName", id_card.display_name);
141             attributes.append_string("Services", services);
142             attributes.append_string("Rules-Pattern", patterns);
143             attributes.append_string("Rules-AlwaysConfirm", always_conf);
144             attributes.append_string("CA-Cert", id_card.trust_anchor.ca_cert);
145             attributes.append_string("Server-Cert", id_card.trust_anchor.server_cert);
146             attributes.append_string("Subject", id_card.trust_anchor.subject);
147             attributes.append_string("Subject-Alt", id_card.trust_anchor.subject_alt);
148             attributes.append_string("StorePassword", id_card.store_password ? "yes" : "no");
149
150             GnomeKeyring.Result result = GnomeKeyring.item_create_sync(null,
151                 item_type, id_card.display_name, attributes,
152                 id_card.store_password ? id_card.password : "",
153                 true, out item_id);
154             if (result != GnomeKeyring.Result.OK) {
155                 stdout.printf("GnomeKeyring.item_create_sync() failed. result: %d", result);
156             }
157         }
158         load_id_cards();
159     }
160
161     public KeyringStore () {
162         id_card_list = new LinkedList<IdCard>();
163         load_id_cards();
164     }
165 }
166
167 #endif