Don't create duplicate identities. LP 1180914.
authorKevin Wasserman <kevin.wasserman@painless-security.com>
Fri, 14 Mar 2014 15:49:01 +0000 (11:49 -0400)
committerKevin Wasserman <kevin.wasserman@painless-security.com>
Fri, 14 Mar 2014 18:29:26 +0000 (14:29 -0400)
When adding a new identity, replace any existing identity with the same nai.
Provide appropriate confirmation dialog if gui is available.

src/moonshot-id.vala
src/moonshot-idcard-store.vala
src/moonshot-identities-manager.vala
src/moonshot-identity-management-view.vala
src/moonshot-keyring-store.vala
src/moonshot-local-flat-file-store.vala

index 8f90e8d..9418911 100644 (file)
@@ -4,12 +4,31 @@ public class TrustAnchor : Object
   public string subject {get; set; default = "";}
   public string subject_alt  {get; set; default = "";}
   public string server_cert  {get; set; default = "";}
+  public int Compare(TrustAnchor other)
+  {
+    if (this.ca_cert != other.ca_cert)
+      return 1;
+    if (this.subject != other.subject)
+      return 1;
+    if (this.subject_alt != other.subject_alt)
+      return 1;
+    if (this.server_cert != other.server_cert)
+      return 1;
+    return 0;
+  }
 }
 
 public struct Rule
 {
   public string pattern;
   public string always_confirm;
+  public int Compare(Rule other) {
+    if (this.pattern != other.pattern)
+      return 1;
+    if (this.always_confirm != other.always_confirm)
+      return 1;
+    return 0;
+  }
 }
 
 public class IdCard : Object
@@ -57,6 +76,37 @@ public class IdCard : Object
     return (display_name == NO_IDENTITY);
   }
 
+  public enum DiffFlags {
+    DISPLAY_NAME,
+    USERNAME,
+    PASSWORD,
+    ISSUER,
+    RULES,
+    SERVICES,
+    TRUST_ANCHOR;
+  }
+
+  public int Compare(IdCard other)
+  {
+    int diff = 0;
+    if (this.display_name != other.display_name)
+      diff |= 1 << DiffFlags.DISPLAY_NAME;
+    if (this.username != other.username)
+      diff |= 1 << DiffFlags.USERNAME;
+    if (this.password != other.password)
+      diff |= 1 << DiffFlags.PASSWORD;
+    if (this.issuer != other.issuer)
+      diff |= 1 << DiffFlags.ISSUER;
+    if (CompareRules(this.rules, other.rules)!=0)
+      diff |= 1 << DiffFlags.RULES;
+    if (CompareStringArray(this.services, other.services)!=0)
+      diff |= 1 << DiffFlags.SERVICES;
+    if (this.trust_anchor.Compare(other.trust_anchor)!=0)
+      diff |= 1 << DiffFlags.TRUST_ANCHOR;
+    stdout.printf("Diff Flags: %x\n", diff);
+    return diff;
+  }
+
   public static IdCard NewNoIdentity() 
   { 
     IdCard card = new IdCard();
@@ -68,3 +118,25 @@ public class IdCard : Object
     password = null;
   }
 }
+
+public int CompareRules(Rule[] a, Rule[] b)
+{
+  if (a.length != b.length)
+    return 1;
+  for (int i=0; i<a.length; i++) {
+    if (a[i].Compare(b[i]) != 0)
+      return 1;
+  }
+  return 0;
+}
+
+public int CompareStringArray(string[] a, string [] b)
+{
+  if (a.length != b.length)
+    return 1;
+  for (int i=0; i<a.length; i++) {
+    if (a[i] != b[i])
+      return 1;
+  }
+  return 0;
+}
index 7fa060e..78033af 100644 (file)
@@ -7,7 +7,7 @@ public interface IIdentityCardStore : Object {
     }
 
     public abstract void add_card(IdCard card);
-    public abstract void remove_card(IdCard card);
+    public abstract bool remove_card(IdCard card);
     public abstract IdCard? update_card(IdCard card);
     public abstract StoreType get_store_type();
     public abstract LinkedList<IdCard> get_card_list(); 
index ceadb30..b8b2f5d 100644 (file)
@@ -109,6 +109,44 @@ public class IdentityManagerModel : Object {
         return true;
     }
 
+    private bool remove_duplicates(IdCard card)
+    {
+        bool duplicate_found = false;
+        bool found = false;
+        do {
+           var cards = get_card_list();
+           found = false;
+           foreach (IdCard id_card in cards) {
+               if ((card != id_card) && (id_card.nai == card.nai)) {
+                  stdout.printf("removing duplicate id for '%s'\n", card.nai);
+                  remove_card_internal(id_card);
+                  found = duplicate_found = true;
+                  break;
+               }
+           }
+        } while (found);
+        return duplicate_found;
+    }
+
+    public IdCard? find_id_card(string nai, bool force_flat_file_store) {
+        IdCard? retval = null;
+        IIdentityCardStore.StoreType saved_store_type = get_store_type();
+        if (force_flat_file_store)
+            set_store_type(IIdentityCardStore.StoreType.FLAT_FILE);
+
+        foreach (IdCard id in get_card_list()) {
+            if (id.nai == nai) {
+                retval = id;
+                break;
+            }
+        }
+        set_store_type(saved_store_type);
+        if (force_flat_file_store && 
+            (saved_store_type != IIdentityCardStore.StoreType.FLAT_FILE))
+            card_list_changed();
+        return retval;
+    }
+
     public void add_card(IdCard card, bool force_flat_file_store) {
         if (card.temporary)
             return;
@@ -119,6 +157,8 @@ public class IdentityManagerModel : Object {
         if (force_flat_file_store)
             set_store_type(IIdentityCardStore.StoreType.FLAT_FILE);
 
+        remove_duplicates(card);
+
         if (!display_name_is_valid (card.display_name, out candidate))
         {
           card.display_name = candidate;
@@ -147,10 +187,19 @@ public class IdentityManagerModel : Object {
         return retval;
      }
 
-     public void remove_card(IdCard card) {
-        password_table.RemovePassword(card, store);
-        store.remove_card(card);
-        card_list_changed();
+     private bool remove_card_internal(IdCard card) {
+         if (card.temporary)
+             return false;
+         password_table.RemovePassword(card, store);
+         return store.remove_card(card);
+     }
+
+     public bool remove_card(IdCard card) {
+         if (remove_card_internal(card)) {
+            card_list_changed();
+            return true;
+         }
+         return false;
      }
 
      public void set_store_type(IIdentityCardStore.StoreType type) {
index 515b8f9..77d8056 100644 (file)
@@ -329,14 +329,38 @@ public class IdentityManagerView : Window {
          */
         var ret = Gtk.ResponseType.YES;
 #else
-
-        var dialog = new Gtk.MessageDialog (this,
+        Gtk.MessageDialog dialog;
+        IdCard? prev_id = identities_manager.find_id_card(id_card.nai, force_flat_file_store);
+        if (prev_id!=null) {
+            int flags = prev_id.Compare(id_card);
+            if (flags == 0) {
+                return false; // no changes, no need to update
+            } else if ((flags & (1<<IdCard.DiffFlags.DISPLAY_NAME)) != 0) {
+                dialog = new Gtk.MessageDialog (this,
+                                            Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                            Gtk.MessageType.QUESTION,
+                                            Gtk.ButtonsType.YES_NO,
+                                            _("Would you like to replace ID Card '%s' using nai '%s' with the new ID Card '%s'?"),
+                                            prev_id.display_name,
+                                            prev_id.nai,
+                                            id_card.display_name);
+            } else {
+                dialog = new Gtk.MessageDialog (this,
+                                            Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                            Gtk.MessageType.QUESTION,
+                                            Gtk.ButtonsType.YES_NO,
+                                            _("Would you like to update ID Card '%s' using nai '%s'?"),
+                                            id_card.display_name,
+                                            id_card.nai);
+            }
+        } else {
+            dialog = new Gtk.MessageDialog (this,
                                             Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                             Gtk.MessageType.QUESTION,
                                             Gtk.ButtonsType.YES_NO,
                                             _("Would you like to add '%s' ID Card to the ID Card Organizer?"),
                                             id_card.display_name);
-
+        }
         var ret = dialog.run ();
         dialog.destroy ();
 #endif
index 00e09f5..e8daeb2 100644 (file)
@@ -22,9 +22,11 @@ public class KeyringStore : Object, IIdentityCardStore {
         return null;
     }
 
-    public void remove_card(IdCard card) {
-        id_card_list.remove(card);
-        store_id_cards ();
+    public bool remove_card(IdCard card) {
+        bool retval = id_card_list.remove(card);
+        if (retval)
+            store_id_cards ();
+        return retval;
     }
 
     public IIdentityCardStore.StoreType get_store_type() {
index 99874fc..de8b4b2 100644 (file)
@@ -19,9 +19,12 @@ public class LocalFlatFileStore : Object, IIdentityCardStore {
         return null;
     }
 
-    public void remove_card(IdCard card) {
-        id_card_list.remove(card);
-        store_id_cards ();
+    public bool remove_card(IdCard card) {
+        if (id_card_list.remove(card)) {
+            store_id_cards ();
+            return true;
+        }
+        return false;
     }
 
     public LinkedList<IdCard> get_card_list() {