X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmoonshot-local-flat-file-store.vala;h=d1d7127194c37b6e2b0ae6fffbcce5f223807579;hb=e2f8a250279d9a79a03d82995ef191d773627bfa;hp=1d2caa76bf5ea7853e4245bc47165184b8ffa761;hpb=616ca8ad559c77d15b07f341a6274b96c7febbf4;p=moonshot-ui.git diff --git a/src/moonshot-local-flat-file-store.vala b/src/moonshot-local-flat-file-store.vala index 1d2caa7..d1d7127 100644 --- a/src/moonshot-local-flat-file-store.vala +++ b/src/moonshot-local-flat-file-store.vala @@ -1,15 +1,229 @@ +/* + * Copyright (c) 2011-2014, JANET(UK) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of JANET(UK) nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +using Gee; public class LocalFlatFileStore : Object, IIdentityCardStore { - private SList id_card_list; + static MoonshotLogger logger = get_logger("LocalFlatFileStore"); - public void add_card(IdCard card) { - } + private LinkedList id_card_list; + private const string FILE_NAME = "identities.txt"; - public void remove_card(IdCard card) { - } + public void add_card(IdCard card) { + id_card_list.add(card); + store_id_cards(); + } - public SList get_card_list() { - return id_card_list.copy(); - } - } + public IdCard? update_card(IdCard card) { + id_card_list.remove(card); + id_card_list.add(card); + store_id_cards(); + foreach(IdCard idcard in id_card_list) { + if (idcard.display_name == card.display_name) { + return idcard; + } + } + logger.error(@"update_card: card '$(card.display_name)' was not found after re-loading!"); + return null; + } + + public bool remove_card(IdCard card) { + if (id_card_list.remove(card)) { + store_id_cards(); + return true; + } + return false; + } + + public LinkedList get_card_list() { + return id_card_list; + } + + public IIdentityCardStore.StoreType get_store_type() { + return IIdentityCardStore.StoreType.FLAT_FILE; + } + + private void load_id_cards() { + id_card_list.clear(); + var key_file = new KeyFile(); + var path = get_data_dir(); + var filename = Path.build_filename(path, FILE_NAME); + logger.trace("load_id_cards: attempting to load from " + filename); + + try { + key_file.load_from_file(filename, KeyFileFlags.NONE); + } + catch (Error e) { + stdout.printf("Error: %s\n", e.message); + return; + } + + var identities_uris = key_file.get_groups(); + foreach (string identity in identities_uris) { + try { + IdCard id_card = new IdCard(); + + id_card.issuer = key_file.get_string(identity, "Issuer"); + id_card.username = key_file.get_string(identity, "Username"); + id_card.password = key_file.get_string(identity, "Password"); + id_card.update_services(key_file.get_string_list(identity, "Services")); + id_card.display_name = key_file.get_string(identity, "DisplayName"); + if (key_file.has_key(identity, "StorePassword")) { + id_card.store_password = (key_file.get_string(identity, "StorePassword") == "yes"); + } else { + id_card.store_password = (id_card.password != null) && (id_card.password != ""); + } + + if (key_file.has_key(identity, "Rules-Patterns") && + key_file.has_key(identity, "Rules-AlwaysConfirm")) { + string [] rules_patterns = key_file.get_string_list(identity, "Rules-Patterns"); + string [] rules_always_conf = key_file.get_string_list(identity, "Rules-AlwaysConfirm"); + + if (rules_patterns.length == rules_always_conf.length) { + Rule[] rules = new Rule[rules_patterns.length]; + for (int i = 0; i < rules_patterns.length; i++) { + rules[i] = {rules_patterns[i], rules_always_conf[i]}; + } + id_card.rules = rules; + } + } + + // Trust anchor + string ca_cert = key_file.get_string(identity, "CA-Cert").strip(); + string server_cert = key_file.get_string(identity, "ServerCert"); + string subject = key_file.get_string(identity, "Subject"); + string subject_alt = key_file.get_string(identity, "SubjectAlt"); + bool user_verified = get_bool_setting(identity, "TA_User_Verified", false, key_file); + var ta = new TrustAnchor(ca_cert, server_cert, subject, subject_alt, user_verified); + string ta_datetime_added = get_string_setting(identity, "TA_DateTime_Added", "", key_file); + if (ta_datetime_added != "") { + ta.set_datetime_added(ta_datetime_added); + } + id_card.set_trust_anchor_from_store(ta); + id_card_list.add(id_card); + } + catch (Error e) { + logger.error("load_id_cards: Error while loading keyfile: %s\n".printf(e.message)); + stdout.printf("Error: %s\n", e.message); + } + } + } + + private string get_data_dir() { + string path; + path = Path.build_filename(Environment.get_user_data_dir(), + Config.PACKAGE_TARNAME); + + if (!FileUtils.test(path, FileTest.EXISTS)) { + DirUtils.create_with_parents(path, 0700); + } + return path; + } + + internal void store_id_cards() { + var key_file = new KeyFile(); + foreach (IdCard id_card in this.id_card_list) { + logger.trace(@"store_id_cards: Storing '$(id_card.display_name)'"); + + /* workaround for Centos vala array property bug: use temp arrays */ + var rules = id_card.rules; + string[] rules_patterns = new string[rules.length]; + string[] rules_always_conf = new string[rules.length]; + + for (int i = 0; i < rules.length; i++) { + rules_patterns[i] = rules[i].pattern; + rules_always_conf[i] = rules[i].always_confirm; + } + + key_file.set_string(id_card.display_name, "Issuer", id_card.issuer ?? ""); + key_file.set_string(id_card.display_name, "DisplayName", id_card.display_name ?? ""); + key_file.set_string(id_card.display_name, "Username", id_card.username ?? ""); + if (id_card.store_password && (id_card.password != null)) + key_file.set_string(id_card.display_name, "Password", id_card.password); + else + key_file.set_string(id_card.display_name, "Password", ""); + + // Using id_card.services.to_array() seems to cause a crash, possibly due to + // an unowned reference to the array. + string[] svcs = new string[id_card.services.size]; + for (int i = 0; i < id_card.services.size; i++) { + svcs[i] = id_card.services[i]; + } + + key_file.set_string_list(id_card.display_name, "Services", svcs); + + if (rules.length > 0) { + key_file.set_string_list(id_card.display_name, "Rules-Patterns", rules_patterns); + key_file.set_string_list(id_card.display_name, "Rules-AlwaysConfirm", rules_always_conf); + } + key_file.set_string(id_card.display_name, "StorePassword", id_card.store_password ? "yes" : "no"); + + // Trust anchor + key_file.set_string(id_card.display_name, "CA-Cert", id_card.trust_anchor.ca_cert); + key_file.set_string(id_card.display_name, "Subject", id_card.trust_anchor.subject); + key_file.set_string(id_card.display_name, "SubjectAlt", id_card.trust_anchor.subject_alt); + key_file.set_string(id_card.display_name, "ServerCert", id_card.trust_anchor.server_cert); + if (id_card.trust_anchor.datetime_added != "") { + key_file.set_string(id_card.display_name, "TA_DateTime_Added", id_card.trust_anchor.datetime_added); + } + key_file.set_boolean(id_card.display_name, "TA_User_Verified", id_card.trust_anchor.user_verified); + logger.trace(@"store_id_cards: Stored '$(id_card.display_name)'"); + } + + var text = key_file.to_data(null); + + try { + var path = get_data_dir(); + var filename = Path.build_filename(path, FILE_NAME); + logger.trace("store_id_cards: attempting to store to " + filename); + var file = File.new_for_path(filename); + var stream = file.replace(null, false, FileCreateFlags.PRIVATE); + #if GIO_VAPI_USES_ARRAYS + stream.write(text.data); + #else + var bits = text.data; + stream.write(&bits[0], bits.length); + #endif + } + catch (Error e) { + logger.error("store_id_cards: Error while saving keyfile: %s\n".printf(e.message)); + stdout.printf("Error: %s\n", e.message); + } + + load_id_cards(); + } + + public LocalFlatFileStore() { + id_card_list = new LinkedList(); + load_id_cards(); + } +}