private string _subject = "";
private string _subject_alt = "";
private string _server_cert = "";
-
+ private string _datetime_added = "";
public bool user_verified = false;
+ private static string fixup (string s) {
+ return (s == null ? "" : s.strip());
+ }
+
public TrustAnchor(string ca_cert, string server_cert, string subject, string subject_alt, bool user_verified) {
- _ca_cert = ca_cert;
- _server_cert = server_cert;
- _subject = subject;
- _subject_alt = subject_alt;
+ _ca_cert = fixup(ca_cert);
+ _server_cert = fixup(server_cert);
+ _subject = fixup(subject);
+ _subject_alt = fixup(subject_alt);
this.user_verified = user_verified;
+
+ // If we're reading from store, this will be overridden (see set_datetime_added)
+ _datetime_added = "";
}
public TrustAnchor.empty() {
- _ca_cert = "";
- _server_cert = "";
- _subject = "";
- _subject_alt = "";
- this.user_verified = false;
}
}
}
+ public string datetime_added {
+ get {
+ return _datetime_added;
+ }
+ }
+
public bool is_empty() {
return ca_cert == "" && subject == "" && subject_alt == "" && server_cert == "";
}
return server_cert == "" ? TrustAnchorType.CA_CERT : TrustAnchorType.SERVER_CERT;
}
+ internal void set_datetime_added(string datetime) {
+ _datetime_added = fixup(datetime);
+ }
+
+ internal static string format_datetime_now() {
+ DateTime now = new DateTime.now_utc();
+ string dt = now.format("%b %d %T %Y %Z");
+ return dt;
+ }
+
public int Compare(TrustAnchor other)
{
- if (this.ca_cert != other.ca_cert)
+ if (this.ca_cert != other.ca_cert) {
return 1;
- if (this.subject != other.subject)
+ }
+ if (this.subject != other.subject) {
return 1;
- if (this.subject_alt != other.subject_alt)
+ }
+ if (this.subject_alt != other.subject_alt) {
return 1;
- if (this.server_cert != other.server_cert)
+ }
+ if (this.server_cert != other.server_cert) {
return 1;
- if (this.user_verified != other.user_verified)
+ }
+ if (this.user_verified != other.user_verified) {
return 1;
+ }
+ // if (!is_empty() && this.datetime_added != other.datetime_added) {
+ // return 1;
+ // }
return 0;
}
/*
- * Copyright (c) 2011-2014, JANET(UK)
+ * Copyright (c) 2011-2016, JANET(UK)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
public abstract IdCard? update_card(IdCard card);
public abstract StoreType get_store_type();
public abstract LinkedList<IdCard> get_card_list();
+
+ // Note that (at least right now) store_id_cards() will re-load the cards after saving them.
+ internal abstract void store_id_cards();
}
return false;
}
+ // The name is misleading: This not only sets the store type,
+ // it also creates a new store instance, which loads the card data.
public void set_store_type(IIdentityCardStore.StoreType type) {
if ((store != null) && (store.get_store_type() == type))
return;
store = new LocalFlatFileStore();
break;
}
+
+ // Loop through the loaded IDs. If any trust anchors are old enough that we didn't record
+ // the datetime_added, add it now.
+ string before_now = _("Before ") + TrustAnchor.format_datetime_now();
+ bool save_needed = false;
+ foreach (IdCard id in this.store.get_card_list()) {
+ if (!id.trust_anchor.is_empty() && id.trust_anchor.datetime_added == "") {
+ logger.trace("set_store_type : Set ta_datetime_added for old trust anchor on '%s' to '%s'".printf(id.display_name, before_now));
+ id.trust_anchor.set_datetime_added(before_now);
+ save_needed = true;
+ }
+ }
+ if (save_needed) {
+ this.store.store_id_cards();
+ }
}
public IIdentityCardStore.StoreType get_store_type() {
ta_table.attach(ta_clear_button, 1, 2, row, row + 1, fill, fill, 0, 0);
row++;
- //!!TODO
- Label added_label = new Label(_("Added on: N/A"));
+ Label added_label = new Label(_("Added : " + id.trust_anchor.datetime_added));
added_label.set_alignment(0, 0.5f);
ta_table.attach(added_label, 0, 1, row, row + 1, opts, opts, 20, 5);
row++;
Gtk.MessageDialog dialog;
IdCard? prev_id = identities_manager.find_id_card(id_card.nai, force_flat_file_store);
logger.trace("add_identity(flat=%s, card='%s'): find_id_card returned %s"
- .printf(force_flat_file_store.to_string(), id_card.display_name, (prev_id != null ? "non-null" : "null")));
+ .printf(force_flat_file_store.to_string(), id_card.display_name, (prev_id != null ? prev_id.display_name : "null")));
if (prev_id!=null) {
int flags = prev_id.Compare(id_card);
logger.trace("add_identity: compare returned " + flags.to_string());
return idcard;
}
}
+
+ logger.error(@"update_card: card '$(card.display_name)' was not found after re-loading!");
return null;
}
string subject = "";
string subject_alt = "";
bool user_verified = false;
+ string ta_datetime_added = "";
for (i = 0; i < entry.attributes.len; i++) {
var attribute = ((GnomeKeyring.Attribute *) entry.attributes.data)[i];
string value = "";
store_password = value;
} else if (attribute.name == "CACert_User_Verified") {
user_verified = (value == "true");
+ } else if (attribute.name == "TA_DateTime_Added") {
+ ta_datetime_added = value;
}
}
var ta = new TrustAnchor(ca_cert, server_cert, subject, subject_alt, user_verified);
+ if (ta_datetime_added != "") {
+ ta.set_datetime_added(ta_datetime_added);
+ }
id_card.set_trust_anchor_from_store(ta);
if ((rules_always_confirm_index != -1) && (rules_patterns_index != -1)) {
}
}
- public void store_id_cards() {
+ internal void store_id_cards() {
logger.trace("store_id_cards");
clear_keyring();
foreach (IdCard id_card in this.id_card_list) {
attributes.append_string("Subject", id_card.trust_anchor.subject);
attributes.append_string("Subject-Alt", id_card.trust_anchor.subject_alt);
attributes.append_string("CACert_User_Verified", id_card.trust_anchor.user_verified ? "true" : "false");
+ attributes.append_string("TA_DateTime_Added", id_card.trust_anchor.datetime_added);
attributes.append_string("StorePassword", id_card.store_password ? "yes" : "no");
GnomeKeyring.Result result = GnomeKeyring.item_create_sync(null,
using Gee;
public class LocalFlatFileStore : Object, IIdentityCardStore {
+ static MoonshotLogger logger = get_logger("LocalFlatFileStore");
+
private LinkedList<IdCard> id_card_list;
private const string FILE_NAME = "identities.txt";
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;
+ 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;
}
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);
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 = key_file.get_boolean(identity, "CACert_User_Verified");
+ bool user_verified = get_bool_setting(identity, "TA_DateTime_Added", 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);
}
return path;
}
- public void store_id_cards() {
+ 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[] empty = {};
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 ?? "");
+ 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);
+ 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, "CACert_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
#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);
}
/*
- * Copyright (c) 2011-2014, JANET(UK)
+ * Copyright (c) 2011-2016, JANET(UK)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
{
if (element_name == "identity")
{
- logger.trace("start_element_func (%p): Adding an identity".printf(this));
card = new IdCard();
_cards += card;
+
+ ta_ca_cert = "";
+ ta_server_cert = "";
+ ta_subject = "";
+ ta_subject_alt = "";
}
else if (element_name == "rule")
{
}
}
+ private void end_element_func(MarkupParseContext context,
+ string element_name) throws MarkupError
+ {
+ if (element_name == "identity")
+ {
+ if (ta_ca_cert != "" || ta_server_cert != "") {
+ var ta = new TrustAnchor(ta_ca_cert,
+ ta_server_cert,
+ ta_subject,
+ ta_subject_alt,
+ false);
+ card.set_trust_anchor_from_store(ta);
+ }
+ }
+ }
+
private void
text_element_func(MarkupParseContext context,
string text,
if (text_len < 1)
return;
- logger.trace("text_element_func (%p): text='%s'".printf(this, stack.nth_data(0)));
-
if (stack.nth_data(0) == "display-name" && display_name_handler(stack))
{
card.display_name = text;
card.rules[temp.length - 1].always_confirm = text;
}
}
- // This is ugly, but... we use the TrustAnchor field in the IdCard as a placeholder,
- // replacing it with a new one every time we read a new element.
- // "user_verified" is always false, since we're reading the TrustAnchor from XML.
else if (stack.nth_data(0) == "ca-cert" && ca_cert_handler(stack))
{
- string ca_cert = text;
- var ta = new TrustAnchor(ca_cert,
- card.trust_anchor.server_cert,
- card.trust_anchor.subject,
- card.trust_anchor.subject_alt,
- false);
- card.set_trust_anchor_from_store(ta);
+ ta_ca_cert = text ?? "";
}
else if (stack.nth_data(0) == "server-cert" && server_cert_handler(stack))
{
- string server_cert = text;
- var ta = new TrustAnchor(card.trust_anchor.ca_cert,
- server_cert,
- card.trust_anchor.subject,
- card.trust_anchor.subject_alt,
- false);
- card.set_trust_anchor_from_store(ta);
-
+ ta_server_cert = text ?? "";
}
else if (stack.nth_data(0) == "subject" && subject_handler(stack))
{
- string subject = text;
- var ta = new TrustAnchor(card.trust_anchor.ca_cert,
- card.trust_anchor.server_cert,
- subject,
- card.trust_anchor.subject_alt,
- false);
- card.set_trust_anchor_from_store(ta);
+ ta_subject = text;
}
else if (stack.nth_data(0) == "subject-alt" && subject_alt_handler(stack))
{
- string subject_alt = text;
- var ta = new TrustAnchor(card.trust_anchor.ca_cert,
- card.trust_anchor.server_cert,
- card.trust_anchor.subject,
- subject_alt,
- false);
- card.set_trust_anchor_from_store(ta);
+ ta_subject_alt = text;
}
}
-
-
private const MarkupParser parser = {
- start_element_func, null, text_element_func, null, null
+ start_element_func, end_element_func, text_element_func, null, null
};
private MarkupParseContext ctx;
private string text;
private string path;
+ private string ta_ca_cert;
+ private string ta_server_cert;
+ private string ta_subject;
+ private string ta_subject_alt;
+
private IdCard card;
private IdCard[] _cards = {};
while ((line = dis.read_line(null)) != null) {
text += line;
- // Preserve newlines -- important for certificate import.
- // (X509 certs can't be parsed without the newlines.)
+ // Preserve newlines.
//
// This may add an extra newline at EOF. Maybe use
// dis.read_upto("\n", ...) followed by dis.read_byte() instead?
{
error("Could not retreive file size");
}
-
- logger.trace(@"Parser(): read text to parse; length=$(text.length)");
}
public void parse() {
/*
- * Copyright (c) 2011-2014, JANET(UK)
+ * Copyright (c) 2011-2016, JANET(UK)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
idcard.issuer = realm;
idcard.update_services(services);
var ta = new TrustAnchor(ca_cert, server_cert, subject, subject_alt, false);
- idcard.set_trust_anchor_from_store(ta);
+ if (!ta.is_empty()) {
+ string ta_datetime_added = TrustAnchor.format_datetime_now();
+ ta.set_datetime_added(ta_datetime_added);
+ logger.trace("install_id_card : Set ta_datetime_added for '%s' to '%s'".printf(idcard.display_name, ta_datetime_added));
+ idcard.set_trust_anchor_from_store(ta);
+ }
logger.trace("install_id_card: Card '%s' has services: '%s'"
.printf(idcard.display_name, idcard.get_services_string("; ")));
// streams close automatically
}
-internal void set_bool_setting(string group_name, string key_name, bool value)
+internal void set_bool_setting(string group_name, string key_name, bool value, KeyFile? key_file=null)
{
- KeyFile key_file = get_keyfile();
+ KeyFile tmp_key_file = null;
+ if (key_file == null) {
+ // Use tmp_key_file to hold an owned reference (since key_file is unowned)
+ tmp_key_file = get_keyfile();
+ key_file = tmp_key_file;
+ }
key_file.set_boolean(group_name, key_name, value);
- save_keyfile(key_file);
+
+ if (tmp_key_file != null) {
+ // This is a "one-shot" settings update; save it now.
+ save_keyfile(key_file);
+ }
}
-internal bool get_bool_setting(string group_name, string key_name, bool default=false)
+internal bool get_bool_setting(string group_name, string key_name, bool default=false, KeyFile? key_file=null)
{
- KeyFile key_file = get_keyfile();
+ KeyFile tmp_key_file = null;
+ if (key_file == null) {
+ // Use tmp_key_file to hold an owned reference (since key_file is unowned)
+ tmp_key_file = get_keyfile();
+ key_file = tmp_key_file;
+ }
if (key_file == null)
return default;
}
-internal void set_string_setting(string group_name, string key_name, string value)
+internal void set_string_setting(string group_name, string key_name, string value, KeyFile? key_file=null)
{
- KeyFile key_file = get_keyfile();
+ KeyFile tmp_key_file = null;
+ if (key_file == null) {
+ // Use tmp_key_file to hold an owned reference (since key_file is unowned)
+ tmp_key_file = get_keyfile();
+ key_file = tmp_key_file;
+ }
key_file.set_string(group_name, key_name, value);
- save_keyfile(key_file);
+ if (tmp_key_file != null) {
+ // This is a "one-shot" settings update; save it now.
+ save_keyfile(key_file);
+ }
}
-internal string get_string_setting(string group_name, string key_name, string default="")
+internal string get_string_setting(string group_name, string key_name, string default="", KeyFile? key_file=null)
{
- KeyFile key_file = get_keyfile();
+ KeyFile tmp_key_file = null;
+ if (key_file == null) {
+ // Use tmp_key_file to hold an owned reference (since key_file is unowned)
+ tmp_key_file = get_keyfile();
+ key_file = tmp_key_file;
+ }
if (key_file == null)
return default;