From 2d3518d9bd7727680d9e18222b72bd26b287a137 Mon Sep 17 00:00:00 2001 From: Jim Norman Date: Thu, 10 Aug 2006 16:21:47 +0000 Subject: [PATCH] Add Export/import feature --- CASA/gui/CASAManager.csproj | 15 +- CASA/gui/CasaMain.cs | 19 +- CASA/gui/CommonGUI.cs | 105 ++- CASA/gui/ExportSecrets.cs | 150 ++++ CASA/gui/ImportSecrets.cs | 119 +++ CASA/gui/images/casa.glade | 704 +++++++++++++++++- CASA/micasad/cache/SecretStore.cs | 44 ++ CASA/micasad/communication/win/PipeManager.cs | 2 +- CASA/micasad/lib/Novell.CASA.Common.csproj | 10 + CASA/micasad/lib/common/ExportXMLSecrets.cs | 34 + CASA/micasad/lib/common/ImportXMLSecrets.cs | 42 ++ .../lib/communication/MiCasaRequestReply.cs | 2 + CASA/micasad/lss/CASACrypto.cs | 270 ++++--- CASA/micasad/lss/LocalStorage.cs | 172 +++-- CASA/micasad/verbs/ObjectSerialization.cs | 64 ++ .../windows/vs_solutions/CASAInstall/CASA.ncb | Bin 642048 -> 642048 bytes .../windows/vs_solutions/CASAInstall/CASA.suo | Bin 43008 -> 52224 bytes .../vs_solutions/CASAInstall/CASA.vdproj | 118 +-- 18 files changed, 1591 insertions(+), 279 deletions(-) create mode 100644 CASA/gui/ExportSecrets.cs create mode 100644 CASA/gui/ImportSecrets.cs create mode 100644 CASA/micasad/lib/common/ExportXMLSecrets.cs create mode 100644 CASA/micasad/lib/common/ImportXMLSecrets.cs diff --git a/CASA/gui/CASAManager.csproj b/CASA/gui/CASAManager.csproj index cc37bdc4..6af1cf2a 100644 --- a/CASA/gui/CASAManager.csproj +++ b/CASA/gui/CASAManager.csproj @@ -185,6 +185,11 @@ SubType = "Code" BuildAction = "Compile" /> + + - /// ******************************************************************** /// private void HandleQuit() diff --git a/CASA/gui/CommonGUI.cs b/CASA/gui/CommonGUI.cs index 6f5cdd61..7ea8c990 100644 --- a/CASA/gui/CommonGUI.cs +++ b/CASA/gui/CommonGUI.cs @@ -39,6 +39,9 @@ namespace Novell.CASA.GUI public class CommonGUI { + public static string HINT_DIR = "Export Directory"; + public static string HINT_FILENAME = "Export Filename"; + [Glade.Widget] Gtk.Label label86, label88; @@ -155,7 +158,7 @@ namespace Novell.CASA.GUI { // prompt user MessageDialog md=new MessageDialog( - mainWindow,Gtk.DialogFlags.Modal, + mainWindow,Gtk.DialogFlags.Modal, Gtk.MessageType.Warning, Gtk.ButtonsType.Ok, "Master Password entered is incorrect"); @@ -212,6 +215,106 @@ namespace Novell.CASA.GUI mTrayInstance.UpdateTrayIcon(false); } } + + public static string FileChooser(FileChooserAction action, String sWindowTitle, String sCurrentFolder, String sHintFileName) + { + FileChooserDialog chooser = new FileChooserDialog (sWindowTitle, + null, + action); + + if (sCurrentFolder != null) + chooser.SetCurrentFolder(sCurrentFolder); + + if (sHintFileName != null) + chooser.SetFilename(sCurrentFolder+sHintFileName); + + + // set location + chooser.SetPosition(Gtk.WindowPosition.CenterAlways); + chooser.AddButton (Stock.Cancel, ResponseType.Cancel); + + if (action == FileChooserAction.Open) + chooser.AddButton (Stock.Open, ResponseType.Ok); + else + chooser.AddButton(Stock.Save, ResponseType.Ok); + + int response = chooser.Run (); + + string ret = null; + if ((ResponseType) response == ResponseType.Ok) + { + ret = chooser.Uri; + } + +/* + // if the action is SAVE, and the file that is choosen exists, prompt the user for overwrite + if (action == FileChooserAction.Save) + { + string sFilename = ret.Substring(8); + if (System.IO.File.Exists(sFilename)) + { + // prompt user for overwrite + + + + } + } +*/ + chooser.Destroy(); + return ret; + } + + /// + /// VerifyMasterPasswordWithUser dialog + /// + public void VerifyMasterPasswordWithUser() + { + + //Logger.DbgLog("GUI:CasaMain.Login() - IsMasterPasswordSet returned false"); +#if W32 + Glade.XML gxmlTemp = new Glade.XML ("../images/casa.glade", "dialogLogin", null); +#endif +#if LINUX + Glade.XML gxmlTemp = new Glade.XML (Common.GladeFile, "dialogLogin", null); +#endif + + gxmlTemp.Autoconnect (this); + dialogLogin.TransientFor = (Gtk.Window)CasaMain.gxmlMain.GetWidget("windowMain");; + + label86.Text = "Enter your Master Password to continue."; + entryMasterPassword3.Text=""; + label88.Hide(); + entryMasterPassword4.Hide(); + //dialogLogin.SetPosition(Gtk.WindowPosition.Center); + dialogLogin.Destroyed += new EventHandler(dialogLogin_Destroyed); + dialogLogin.Modal = true; + dialogLogin.Show(); + } + + public static void DisplayMessage(Gtk.MessageType messageType, String sMessage) + { + MessageDialog md = new MessageDialog(null, + Gtk.DialogFlags.Modal, + messageType, + Gtk.ButtonsType.Close, + sMessage); + + md.SetPosition(Gtk.WindowPosition.CenterAlways); + md.Response +=new ResponseHandler(md_Response3); + md.Show(); + + } + + private static void md_Response3(object o, ResponseArgs args) + { + MessageDialog md = (MessageDialog)o; + if (md != null) + { + md.Destroy(); + } + } + + #if W32 public static bool IsGTKSharpInstalled() diff --git a/CASA/gui/ExportSecrets.cs b/CASA/gui/ExportSecrets.cs new file mode 100644 index 00000000..5f46663a --- /dev/null +++ b/CASA/gui/ExportSecrets.cs @@ -0,0 +1,150 @@ +using System; +using System.IO; + +using Novell.CASA.MiCasa.Communication; +using Novell.CASA.MiCasa.Common; + +using Gtk; +using Glade; + +namespace Novell.CASA.GUI +{ + /// + /// Summary description for ExportSecrets. + /// + public class ExportSecrets + { + + private Config m_config = null; + + [Glade.Widget] + Gtk.Label label86, + label88; + + [Glade.Widget] + Gtk.Entry entryMasterPassword; + + [Glade.Widget] + Gtk.Dialog dialogExport; + + [Glade.Widget] + Gtk.CheckButton checkbuttonNoEncrypt; + + public ExportSecrets(Config config) + { + m_config = config; + } + + public void Run() + { + // prompt for master password, and optional passphrase to encrypt + //Logger.DbgLog("GUI:CasaMain.Login() - IsMasterPasswordSet returned false"); +#if W32 + Glade.XML gxmlTemp = new Glade.XML ("../images/casa.glade", "dialogExport", null); +#endif +#if LINUX + Glade.XML gxmlTemp = new Glade.XML (Common.GladeFile, "dialogLogin", null); +#endif + + gxmlTemp.Autoconnect (this); + dialogExport.TransientFor = (Gtk.Window)CasaMain.gxmlMain.GetWidget("windowMain");; + + + dialogExport.Destroyed += new EventHandler(dialogExport_Destroyed); + dialogExport.Modal = true; + dialogExport.Show(); + } + private void dialogExport_Destroyed(object sender, EventArgs e) + { + + } + + private void on_buttonCloseExportSecrets_clicked(object sender, EventArgs args) + { + if (dialogExport != null) + { + dialogExport.Destroy(); + } + } + + private void on_buttonOkExportSecrets_clicked(object sender, EventArgs args) + { + if( 0 == miCASA.SetMasterPassword(0, entryMasterPassword.Text) ) + { + string sMasterPWD = entryMasterPassword.Text; + string sEncryptString = entryMasterPassword.Text; + + if (checkbuttonNoEncrypt.Active) + sEncryptString = null; + + if (dialogExport != null) + { + dialogExport.Destroy(); + } + + string sHintDir = m_config.GetConfigSetting(CommonGUI.HINT_DIR, null); + string sHintFile = m_config.GetConfigSetting(CommonGUI.HINT_FILENAME, null); + + // prompt the user for storage location + string sFileName = GetStorageFileName(sHintDir, sHintFile); + + if (sFileName != null) + { + //Store off this location for next export + int iLastSlash = sFileName.LastIndexOf("/"); + if (iLastSlash > 0) + { + sHintFile = sFileName.Substring(iLastSlash + 1); + sHintDir = sFileName.Substring(8, sFileName.Length - sHintFile.Length - 8); + } + + // save for later use + m_config.SetConfigSetting(CommonGUI.HINT_DIR, sHintDir); + m_config.SetConfigSetting(CommonGUI.HINT_FILENAME, sHintFile); + m_config.WriteConfig(); + + // call our daemon to get the users secrets + ExportXMLSecrets exportSecrets = new ExportXMLSecrets(sMasterPWD, sEncryptString); + byte[] theSecrets = (byte[])Novell.CASA.MiCasa.Communication.MiCasaRequestReply.Send(MiCasaRequestReply.VERB_EXPORT_SECRETS, null, null, null, exportSecrets); + + // write em out. + FileStream fs = new FileStream(sFileName.Substring(8), FileMode.Create); + fs.Write(theSecrets, 0, theSecrets.Length); + fs.Flush(); + fs.Close(); + + CommonGUI.DisplayMessage(MessageType.Info, "Secrets saved to: \r\n" + sFileName.Substring(8)); + + } + } + else + { + // prompt user + MessageDialog md=new MessageDialog(dialogExport,Gtk.DialogFlags.Modal, + Gtk.MessageType.Warning, + Gtk.ButtonsType.Ok, + "Master Password incorrect"); + + md.Response +=new ResponseHandler(md_Response2); + md.SetPosition(Gtk.WindowPosition.CenterOnParent); + md.Modal = true; + md.Show(); + } + } + + private string GetStorageFileName(string sHintDir, string sHintFile) + { + String sFileName = CommonGUI.FileChooser(FileChooserAction.Save, "Select filename and location for secrets", sHintDir, sHintFile); + return sFileName; + } + + private void md_Response2(object o, ResponseArgs args) + { + MessageDialog md = (MessageDialog)o; + if (md != null) + { + md.Destroy(); + } + } + } +} diff --git a/CASA/gui/ImportSecrets.cs b/CASA/gui/ImportSecrets.cs new file mode 100644 index 00000000..cdea0b02 --- /dev/null +++ b/CASA/gui/ImportSecrets.cs @@ -0,0 +1,119 @@ +using System; +using System.IO; + +using Novell.CASA.MiCasa.Communication; +using Novell.CASA.MiCasa.Common; + +namespace Novell.CASA.GUI +{ + /// + /// Summary description for ImportSecrets. + /// + public class ImportSecrets + { + Config m_config = null; + public MiCasa m_objMiCasa = null; + byte[] buffer = null; + + [Glade.Widget] + Gtk.Entry entryMasterPassword; + + [Glade.Widget] + Gtk.Dialog dialogImport; + + public ImportSecrets(Config config, MiCasa objMiCasa) + { + m_config = config; + m_objMiCasa = objMiCasa; + } + + public void Run() + { + String sHintDir = m_config.GetConfigSetting(CommonGUI.HINT_DIR, null);; + String sHintFilename = m_config.GetConfigSetting(CommonGUI.HINT_FILENAME, null); + + // ask the user to locate the secret file to import + string sFile = CommonGUI.FileChooser(Gtk.FileChooserAction.Open, "Select import file", sHintDir, sHintFilename); + if (sFile != null) + { + // parse of the file:/// + sFile = sFile.Substring(8); + + if (File.Exists(sFile)) + { + + // let's read it + FileStream fs = new FileStream(sFile, FileMode.Open); + buffer = new byte[fs.Length]; + + int iBytes = fs.Read(buffer, 0, (int)fs.Length); + string data = System.Text.Encoding.ASCII.GetString(buffer); + + fs.Flush(); + fs.Close(); + + // check for clear text secrets + if (data.StartsWith("True - + True gtk-new 1 @@ -78,7 +78,7 @@ - + True gtk-new 1 @@ -99,7 +99,7 @@ - + True gtk-new 1 @@ -125,7 +125,7 @@ - + True gtk-refresh 1 @@ -152,7 +152,7 @@ - + True gtk-dialog-authentication 1 @@ -173,7 +173,7 @@ - + True gtk-open 1 @@ -194,7 +194,7 @@ - + True gtk-delete 1 @@ -213,6 +213,54 @@ + + + True + _Export Secrets + True + + + + + True + gtk-floppy + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Import Secrets + True + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + True @@ -222,7 +270,7 @@ - + True gtk-quit 1 @@ -258,7 +306,7 @@ - + True gtk-zoom-fit 1 @@ -279,7 +327,7 @@ - + True gtk-jump-to 1 @@ -300,7 +348,7 @@ - + True gtk-copy 1 @@ -328,7 +376,7 @@ - + True gtk-delete 1 @@ -362,7 +410,7 @@ True - + True gtk-execute 1 @@ -384,7 +432,7 @@ - + True gtk-execute 1 @@ -405,7 +453,7 @@ - + True gtk-execute 1 @@ -426,7 +474,7 @@ - + True gtk-execute 1 @@ -447,7 +495,7 @@ - + True gtk-execute 1 @@ -472,7 +520,7 @@ - + True gtk-revert-to-saved 1 @@ -499,7 +547,7 @@ - + True gtk-preferences 1 @@ -533,7 +581,7 @@ - + True gtk-add 1 @@ -554,7 +602,7 @@ - + True gtk-remove 1 @@ -605,7 +653,7 @@ - + True gtk-help 1 @@ -632,7 +680,7 @@ - + True gtk-dialog-info 1 @@ -11863,4 +11911,614 @@ the following characters + + True + CASA - Export Secrets + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ALWAYS + True + False + True + CASAicons.ico + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-help + True + GTK_RELIEF_NONE + True + -11 + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + True + -7 + + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + gtk-dialog-authentication + 6 + 0.5 + 0.5 + 0 + 0 + + + 4 + False + True + + + + + 4 + True + True + + + + + + True + False + 0 + + + + True + <b>Export miCASA Secrets</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + False + False + + + + + + True + Your Master Password is required to +export your secrets. Your secrets will +be encrypted using your Master Password. + +If you wish, you can export your secrets +in clear text. + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + 6 + True + 0 + 0.5 + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + 6 + True + 3 + 2 + False + 6 + 6 + + + + True + Master Password : + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + True + False + 512 + + True + * + False + + + 1 + 2 + 0 + 1 + + + + + + + True + True + Do not encrypt export file + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 1 + 2 + fill + + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + CASA - Import Secrets + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ALWAYS + True + False + True + CASAicons.ico + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-help + True + GTK_RELIEF_NONE + True + -11 + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_NORMAL + True + -7 + + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + gtk-dialog-authentication + 6 + 0.5 + 0.5 + 0 + 0 + + + 4 + False + True + + + + + 4 + True + True + + + + + + True + False + 0 + + + + True + <b>Export miCASA Secrets</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + False + False + + + + + + True + The file you selected appears +to be encypted. Please enter +the Master Password used +to encrypt this file + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + 6 + True + 0 + 0.5 + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + 6 + True + 3 + 2 + False + 6 + 6 + + + + True + Master Password : + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + True + False + 512 + + True + * + False + + + 1 + 2 + 0 + 1 + + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + diff --git a/CASA/micasad/cache/SecretStore.cs b/CASA/micasad/cache/SecretStore.cs index 9285f1be..0b35f64e 100644 --- a/CASA/micasad/cache/SecretStore.cs +++ b/CASA/micasad/cache/SecretStore.cs @@ -804,5 +804,49 @@ namespace sscs.cache string homeDir = GetUserHomeDirectory(); return homeDir + ConstStrings.MICASA_VALIDATION_FILE; } + internal byte[] GetSecrets(string sEncryptionString) + { + if (lss != null) + { + MemoryStream ms = lss.GetSecretsAsXMLStream(); + byte[] baSecrets = ms.ToArray(); + + // encrypt if an encryptionstring was passed + if ((sEncryptionString != null) && (sEncryptionString.Length > 0)) + { + byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false); + + // now encypt it. + baSecrets = sscs.crypto.CASACrypto.EncryptData(baSecrets, baKey); + } + return baSecrets; + } + else + { + return null; + } + } + + internal void MergeXMLSecrets(byte[] encryptedXmlSecrets, string sEncryptionString) + { + if (sEncryptionString != null) + { + // decrypt the buffer using the string passed in. + byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false); + byte[] baBuffer = sscs.crypto.CASACrypto.DecryptData(encryptedXmlSecrets, baKey); + MergeXMLSecrets(baBuffer); + } + } + + internal void MergeXMLSecrets(byte[] decryptedXmlSecrets) + { + XmlDocument doc = new XmlDocument(); + String sXMLData = Encoding.ASCII.GetString(decryptedXmlSecrets); + doc.LoadXml(sXMLData); + if (lss != null) + { + lss.AddXMLSecretsToStore(doc); + } + } } } diff --git a/CASA/micasad/communication/win/PipeManager.cs b/CASA/micasad/communication/win/PipeManager.cs index 4100ff96..90708d61 100644 --- a/CASA/micasad/communication/win/PipeManager.cs +++ b/CASA/micasad/communication/win/PipeManager.cs @@ -40,7 +40,7 @@ namespace sscs.communication.win { private uint NumberPipes = 16; private uint OutBuffer = 65536; //512; private uint InBuffer = 65536; //512; - private const int MAX_READ_BYTES = 5000; + private const int MAX_READ_BYTES = 15000; private bool _listen = true; public bool Listen { get { diff --git a/CASA/micasad/lib/Novell.CASA.Common.csproj b/CASA/micasad/lib/Novell.CASA.Common.csproj index 85092f55..c849869c 100644 --- a/CASA/micasad/lib/Novell.CASA.Common.csproj +++ b/CASA/micasad/lib/Novell.CASA.Common.csproj @@ -98,6 +98,16 @@ SubType = "Code" BuildAction = "Compile" /> + + + /// Summary description for ExportSecrets. + /// + /// + [Serializable] + public class ExportXMLSecrets + { + private string m_sMasterPassword = null; + private string m_sPassphrase = null; + + public ExportXMLSecrets(string sMasterPassword, string sPassphrase) + { + m_sMasterPassword = sMasterPassword; + if (sPassphrase != null) + { + m_sPassphrase = sPassphrase; + } + } + + public string GetMasterPassword() + { + return m_sMasterPassword; + } + + public string GetPassphrase() + { + return m_sPassphrase; + } + } +} diff --git a/CASA/micasad/lib/common/ImportXMLSecrets.cs b/CASA/micasad/lib/common/ImportXMLSecrets.cs new file mode 100644 index 00000000..36bea8da --- /dev/null +++ b/CASA/micasad/lib/common/ImportXMLSecrets.cs @@ -0,0 +1,42 @@ +using System; + +namespace Novell.CASA.MiCasa.Common +{ + /// + /// Summary description for AddXMLSecrets. + /// + /// + [Serializable] + public class ImportXMLSecrets + { + private string m_MasterPassword = null; + private byte[] m_XmlSecrets = null; + private string m_sStatus = ""; + + public ImportXMLSecrets(string sMasterPassword, byte[] XmlSecrets) + { + m_MasterPassword = sMasterPassword; + m_XmlSecrets = XmlSecrets; + } + + public string GetMasterPasssword() + { + return m_MasterPassword; + } + + public byte[] GetXmlSecrets() + { + return m_XmlSecrets; + } + + public void SetStatus(string s) + { + m_sStatus = s; + } + + public string GetStatus() + { + return m_sStatus; + } + } +} diff --git a/CASA/micasad/lib/communication/MiCasaRequestReply.cs b/CASA/micasad/lib/communication/MiCasaRequestReply.cs index 25c3f6db..4d5e1bd0 100644 --- a/CASA/micasad/lib/communication/MiCasaRequestReply.cs +++ b/CASA/micasad/lib/communication/MiCasaRequestReply.cs @@ -56,6 +56,8 @@ namespace Novell.CASA.MiCasa.Communication public const int VERB_RESET_MASTER_PASSWORD = 18; public const int VERB_GET_SECRETIDS = 19; public const int VERB_VALIDATE_DESKTOP_PWD = 20; + public const int VERB_EXPORT_SECRETS = 21; + public const int VERB_ADD_XML_SECRETS = 22; public const int VERB_DUMP_LINKED_KEYS = 96; public const int VERB_CREATE_TEST_SECRETS = 97; diff --git a/CASA/micasad/lss/CASACrypto.cs b/CASA/micasad/lss/CASACrypto.cs index a7ccad63..18672892 100644 --- a/CASA/micasad/lss/CASACrypto.cs +++ b/CASA/micasad/lss/CASACrypto.cs @@ -32,143 +32,199 @@ using sscs.constants; namespace sscs.crypto { - public class CASACrypto - { + public class CASACrypto + { - private const int SALTSIZE = 64; - private const int ITERATION_COUNT = 1000; - private const int HASH_SIZE = 32; + private const int SALTSIZE = 64; + private const int ITERATION_COUNT = 1000; + private const int HASH_SIZE = 32; - internal static byte[] Generate16ByteKeyFromString(string sTheString, string sFilepath, bool bUseOldMethod) - { - byte[] baKey = new byte[16]; //return value - try - { - Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes(sTheString, SALTSIZE, ITERATION_COUNT, bUseOldMethod); - baKey = pkcs5.GetBytes(16); - } - catch(Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - CSSSLogger.DbgLog("Key generation failed"); - baKey = null; - } - return baKey; - } + internal static byte[] Generate16ByteKeyFromString(string sTheString, string sFilepath, bool bUseOldMethod) + { + byte[] baKey = new byte[16]; //return value + try + { + Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes(sTheString, SALTSIZE, ITERATION_COUNT, bUseOldMethod); + baKey = pkcs5.GetBytes(16); + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Key generation failed"); + baKey = null; + } + return baKey; + } - internal static bool StoreKeySetUsingMasterPasscode(byte[] key, - byte[] IV, byte[] baMasterPasscode, string fileName) - { - bool bRet = false; - FileStream fsEncrypt = null; - CryptoStream csEncrypt = null; - try - { + internal static bool StoreKeySetUsingMasterPasscode(byte[] key, + byte[] IV, byte[] baMasterPasscode, string fileName) + { + bool bRet = false; + FileStream fsEncrypt = null; + CryptoStream csEncrypt = null; + try + { - //Get an encryptor. - RijndaelManaged myRijndael = new RijndaelManaged(); - ICryptoTransform encryptor; - encryptor = myRijndael.CreateEncryptor(baMasterPasscode, GenerateAndSaveIV(fileName, myRijndael)); + //Get an encryptor. + RijndaelManaged myRijndael = new RijndaelManaged(); + ICryptoTransform encryptor; + encryptor = myRijndael.CreateEncryptor(baMasterPasscode, GenerateAndSaveIV(fileName, myRijndael)); - //Encrypt the data to a file - fsEncrypt = new FileStream(fileName, FileMode.Create); + //Encrypt the data to a file + fsEncrypt = new FileStream(fileName, FileMode.Create); // make hidden File.SetAttributes(fileName, FileAttributes.Hidden); - SHA256 sha = new SHA256Managed(); - byte[] hash = sha.ComputeHash(key); + SHA256 sha = new SHA256Managed(); + byte[] hash = sha.ComputeHash(key); - fsEncrypt.Write(hash,0,hash.Length); - fsEncrypt.Flush(); + fsEncrypt.Write(hash,0,hash.Length); + fsEncrypt.Flush(); - csEncrypt = new CryptoStream(fsEncrypt, encryptor, CryptoStreamMode.Write); + csEncrypt = new CryptoStream(fsEncrypt, encryptor, CryptoStreamMode.Write); - //Write all data to the crypto stream and flush it. - csEncrypt.Write(key, 0, key.Length); - csEncrypt.FlushFinalBlock(); - bRet = true; - } - catch(Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - CSSSLogger.DbgLog("Unable to store the generated key"); - bRet = false; - } - if (csEncrypt != null) - csEncrypt.Close(); - if( fsEncrypt != null ) - fsEncrypt.Close(); - return bRet; - } + //Write all data to the crypto stream and flush it. + csEncrypt.Write(key, 0, key.Length); + csEncrypt.FlushFinalBlock(); + bRet = true; + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Unable to store the generated key"); + bRet = false; + } + if (csEncrypt != null) + csEncrypt.Close(); + if( fsEncrypt != null ) + fsEncrypt.Close(); + return bRet; + } - internal static byte[] GetKeySetFromFile(byte[] baMasterPasscode, - string fileName ) - { - byte[] baSavedKey = null; - FileStream fsDecrypt = null; - CryptoStream csDecrypt = null; + internal static byte[] GetKeySetFromFile(byte[] baMasterPasscode, + string fileName ) + { + byte[] baSavedKey = null; + FileStream fsDecrypt = null; + CryptoStream csDecrypt = null; - try - { + try + { #if LINUX UnixFileInfo fsTest = new UnixFileInfo (fileName); if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink) #else - if(!File.Exists(fileName)) + if(!File.Exists(fileName)) #endif - { - return null; - } + { + return null; + } - /* Get a decryptor that uses the same key and IV - * as the encryptor. - */ + /* Get a decryptor that uses the same key and IV + * as the encryptor. + */ - RijndaelManaged myRijndael = new RijndaelManaged(); - ICryptoTransform decryptor = myRijndael.CreateDecryptor(baMasterPasscode, RetrieveIV(fileName, baMasterPasscode)); - //Now decrypt - fsDecrypt = new FileStream(fileName, FileMode.Open); + RijndaelManaged myRijndael = new RijndaelManaged(); + ICryptoTransform decryptor = myRijndael.CreateDecryptor(baMasterPasscode, RetrieveIV(fileName, baMasterPasscode)); + //Now decrypt + fsDecrypt = new FileStream(fileName, FileMode.Open); - byte[] storedHash = new byte[32]; - fsDecrypt.Read(storedHash,0,storedHash.Length); + byte[] storedHash = new byte[32]; + fsDecrypt.Read(storedHash,0,storedHash.Length); - csDecrypt = new CryptoStream(fsDecrypt, decryptor, CryptoStreamMode.Read); - baSavedKey = new byte[32]; + csDecrypt = new CryptoStream(fsDecrypt, decryptor, CryptoStreamMode.Read); + baSavedKey = new byte[32]; - //Read the data out of the crypto stream. - csDecrypt.Read(baSavedKey, 0, baSavedKey.Length); + //Read the data out of the crypto stream. + csDecrypt.Read(baSavedKey, 0, baSavedKey.Length); - SHA256 sha = new SHA256Managed(); - byte[] newHash = sha.ComputeHash(baSavedKey); - for( int i = 0 ; i < 32; i++ ) - { - if(storedHash[i] != newHash[i]) - { - CSSSLogger.DbgLog("Hash doesnot match"); - csDecrypt.Close(); - fsDecrypt.Close(); - return null; - } - } - } - catch(Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - CSSSLogger.DbgLog("Unable to get the stored key"); - baSavedKey = null; - } + SHA256 sha = new SHA256Managed(); + byte[] newHash = sha.ComputeHash(baSavedKey); + for( int i = 0 ; i < 32; i++ ) + { + if(storedHash[i] != newHash[i]) + { + CSSSLogger.DbgLog("Hash doesnot match"); + csDecrypt.Close(); + fsDecrypt.Close(); + return null; + } + } + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Unable to get the stored key"); + baSavedKey = null; + } - if (csDecrypt != null) - csDecrypt.Close(); + if (csDecrypt != null) + csDecrypt.Close(); - if ( fsDecrypt != null ) - fsDecrypt.Close(); + if ( fsDecrypt != null ) + fsDecrypt.Close(); - return baSavedKey; - } + return baSavedKey; + } + + internal static byte[] DecryptData(byte[] encyptedXmlData, byte[] key) + { + CryptoStream csDecrypt = null; + byte[] buffer = new byte[encyptedXmlData.Length]; + MemoryStream ms = new MemoryStream(encyptedXmlData); + + try + { + //Get an decryptor. + RijndaelManaged myRijndael = new RijndaelManaged(); + ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, key); + csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); + + //Read all data to the crypto stream and flush it. + int iBytesRead = csDecrypt.Read(buffer,0,encyptedXmlData.Length); + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("decrypting failed."); + } + if (csDecrypt != null) + csDecrypt.Close(); + + return buffer; + } + + internal static byte[] EncryptData(byte[] xmlData, byte[] key) + { + CryptoStream csEncrypt = null; + MemoryStream encryptedData = new MemoryStream(); + try + { + //Get an encryptor. + RijndaelManaged myRijndael = new RijndaelManaged(); + ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, key); + + //csEncrypt = new CryptoStream(fsEncrypt, encryptor, CryptoStreamMode.Write); + csEncrypt = new CryptoStream(encryptedData, encryptor, CryptoStreamMode.Write); + + //Write all data to the crypto stream and flush it. + csEncrypt.Write(xmlData, 0, xmlData.Length); + csEncrypt.FlushFinalBlock(); + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Encrypting failed."); + } + if (csEncrypt != null) + csEncrypt.Close(); + + return encryptedData.ToArray(); + } + internal static void EncryptDataAndWriteToFile(byte[] xmlData, byte[] key, string fileName) diff --git a/CASA/micasad/lss/LocalStorage.cs b/CASA/micasad/lss/LocalStorage.cs index b5c6dafd..7df6a40b 100644 --- a/CASA/micasad/lss/LocalStorage.cs +++ b/CASA/micasad/lss/LocalStorage.cs @@ -237,89 +237,9 @@ namespace sscs.lss { return false; } - xpath = "//" + XmlConsts.miCASANode; - XmlNode miCASANode = doc.SelectSingleNode(xpath); - if(miCASANode != null) - { - xpath = "descendant::" + XmlConsts.keyChainNode; - XmlNodeList keyChainNodeList = miCASANode.SelectNodes(xpath); - foreach(XmlNode node in keyChainNodeList) - { - XmlAttributeCollection attrColl = node.Attributes; - string keyChainId = (attrColl[XmlConsts.idAttr]).Value + "\0"; - KeyChain keyChain = null; - - if( userStore.CheckIfKeyChainExists(keyChainId) == false ) - { - keyChain = new KeyChain(keyChainId); - userStore.AddKeyChain(keyChain); - } - else - { - keyChain = userStore.GetKeyChain(keyChainId); - } - xpath = "descendant::" + XmlConsts.secretNode; - XmlNodeList secretNodeList = node.SelectNodes(xpath); - foreach(XmlNode secretNode in secretNodeList) - { - attrColl = secretNode.Attributes; - string secretId = (attrColl[XmlConsts.idAttr]).Value + "\0"; - xpath = "descendant::" + XmlConsts.valueNode; - Secret secret = new Secret(secretId); - if( keyChain.CheckIfSecretExists(secretId) == false) - { - keyChain.AddSecret(secret); - XmlNode secretValNode = (secretNode.SelectSingleNode(xpath)); - xpath = "descendant::" + XmlConsts.keyNode; - XmlNodeList keyNodeList = secretValNode.SelectNodes(xpath); - - secret = keyChain.GetSecret(secretId); - foreach(XmlNode keyNode in keyNodeList) - { - attrColl = keyNode.Attributes; - string key; - try - { - key = (attrColl[XmlConsts.idAttr]).Value; - } - catch (Exception) - { - // LinkedKey node, continue - continue; - } - xpath = "descendant::" + XmlConsts.keyValueNode; - XmlNode keyValNode = keyNode.SelectSingleNode(xpath); - string keyValue = keyValNode.InnerText; - secret.SetKeyValue(key,keyValue); - - - // add linked keys - xpath = "descendant::" + XmlConsts.linkedKeyNode; - XmlNodeList linkNodeList = keyNode.SelectNodes(xpath); - foreach(XmlNode linkNode in linkNodeList) - { - // get TargetSecretID - xpath = "descendant::" + XmlConsts.linkedTargetSecretNode; - XmlNode targetSecretNode = linkNode.SelectSingleNode(xpath); - string sSecretID = targetSecretNode.InnerText + "\0"; - - // get TargetSecretKey - xpath = "descendant::" + XmlConsts.linkedTargetKeyNode; - XmlNode targetKeyNode = linkNode.SelectSingleNode(xpath); - string sKeyID = targetKeyNode.InnerText; - - LinkedKeyInfo lki = new LinkedKeyInfo(sSecretID, sKeyID, true); - KeyValue kv = secret.GetKeyValue(key); - kv.AddLink(lki); - } - - } - }//if ends - } - - }//end of traversing keyChainNodeList - } + // add these to the store + AddXMLSecretsToStore(doc); } catch(Exception e) { @@ -332,6 +252,94 @@ namespace sscs.lss return true; } + internal void AddXMLSecretsToStore(XmlDocument doc) + { + string xpath = ""; + xpath = "//" + XmlConsts.miCASANode; + XmlNode miCASANode = doc.SelectSingleNode(xpath); + if(miCASANode != null) + { + xpath = "descendant::" + XmlConsts.keyChainNode; + XmlNodeList keyChainNodeList = miCASANode.SelectNodes(xpath); + foreach(XmlNode node in keyChainNodeList) + { + XmlAttributeCollection attrColl = node.Attributes; + string keyChainId = (attrColl[XmlConsts.idAttr]).Value + "\0"; + KeyChain keyChain = null; + + if( userStore.CheckIfKeyChainExists(keyChainId) == false ) + { + keyChain = new KeyChain(keyChainId); + userStore.AddKeyChain(keyChain); + } + else + { + keyChain = userStore.GetKeyChain(keyChainId); + } + xpath = "descendant::" + XmlConsts.secretNode; + XmlNodeList secretNodeList = node.SelectNodes(xpath); + foreach(XmlNode secretNode in secretNodeList) + { + attrColl = secretNode.Attributes; + string secretId = (attrColl[XmlConsts.idAttr]).Value + "\0"; + xpath = "descendant::" + XmlConsts.valueNode; + Secret secret = new Secret(secretId); + if( keyChain.CheckIfSecretExists(secretId) == false) + { + keyChain.AddSecret(secret); + XmlNode secretValNode = (secretNode.SelectSingleNode(xpath)); + xpath = "descendant::" + XmlConsts.keyNode; + + XmlNodeList keyNodeList = secretValNode.SelectNodes(xpath); + + secret = keyChain.GetSecret(secretId); + foreach(XmlNode keyNode in keyNodeList) + { + attrColl = keyNode.Attributes; + string key; + try + { + key = (attrColl[XmlConsts.idAttr]).Value; + } + catch (Exception) + { + // LinkedKey node, continue + continue; + } + xpath = "descendant::" + XmlConsts.keyValueNode; + XmlNode keyValNode = keyNode.SelectSingleNode(xpath); + string keyValue = keyValNode.InnerText; + secret.SetKeyValue(key,keyValue); + + + // add linked keys + xpath = "descendant::" + XmlConsts.linkedKeyNode; + XmlNodeList linkNodeList = keyNode.SelectNodes(xpath); + foreach(XmlNode linkNode in linkNodeList) + { + // get TargetSecretID + xpath = "descendant::" + XmlConsts.linkedTargetSecretNode; + XmlNode targetSecretNode = linkNode.SelectSingleNode(xpath); + string sSecretID = targetSecretNode.InnerText + "\0"; + + // get TargetSecretKey + xpath = "descendant::" + XmlConsts.linkedTargetKeyNode; + XmlNode targetKeyNode = linkNode.SelectSingleNode(xpath); + string sKeyID = targetKeyNode.InnerText; + + LinkedKeyInfo lki = new LinkedKeyInfo(sSecretID, sKeyID, true); + KeyValue kv = secret.GetKeyValue(key); + kv.AddLink(lki); + } + + } + }//if ends + } + + }//end of traversing keyChainNodeList + } + } + private void PersistStoreDelayThreadFn() { Thread.Sleep(15000); diff --git a/CASA/micasad/verbs/ObjectSerialization.cs b/CASA/micasad/verbs/ObjectSerialization.cs index 5cbde52c..a10bb64d 100644 --- a/CASA/micasad/verbs/ObjectSerialization.cs +++ b/CASA/micasad/verbs/ObjectSerialization.cs @@ -33,6 +33,7 @@ using sscs.lss; using System.Runtime.Serialization.Formatters.Binary; using System.IO; +using System.Xml; using Novell.CASA.MiCasa.Common; using Novell.CASA.MiCasa.Communication; @@ -218,6 +219,14 @@ namespace sscs.verbs { return DoValidateDesktopPwd(ssStore, wo); } + case MiCasaRequestReply.VERB_EXPORT_SECRETS: + { + return DoExportSecrets(ssStore, wo); + } + case MiCasaRequestReply.VERB_ADD_XML_SECRETS: + { + return DoMergeXMLSecrets(ssStore, wo); + } default: { @@ -235,6 +244,61 @@ namespace sscs.verbs return wo; } + private WrappedObject DoMergeXMLSecrets(SecretStore ssStore, WrappedObject wo) + { + ImportXMLSecrets addSecrets = (ImportXMLSecrets)wo.GetObject(); + string sMasterPassword = addSecrets.GetMasterPasssword(); + byte[] baXMLSecrets = addSecrets.GetXmlSecrets(); + + try + { + if (sMasterPassword != null) + { + // decrypt secrets if possible + ssStore.MergeXMLSecrets(baXMLSecrets, sMasterPassword); + } + else + { + // do the merge now. + ssStore.MergeXMLSecrets(baXMLSecrets); + } + addSecrets.SetStatus("Success"); + wo.SetError(constants.RetCodes.SUCCESS, ""); + } + catch (Exception e) + { + addSecrets.SetStatus(e.ToString()); + wo.SetError(constants.RetCodes.FAILURE, e.ToString()); + } + + return wo; + } + + private WrappedObject DoExportSecrets(SecretStore ssStore, WrappedObject wo) + { + ExportXMLSecrets secrets = (ExportXMLSecrets)wo.GetObject(); + + // validate masterpassword + try + { + string sMasterPassword = secrets.GetMasterPassword(); + ssStore.UnlockStore(null, sMasterPassword); + } + catch (Exception e) + { + wo.SetError(constants.RetCodes.FAILURE, e.ToString()); + return wo; + } + + string sEncrpyptionPassphrase = secrets.GetPassphrase(); + + // get all secrets + wo.SetObject(ssStore.GetSecrets(sEncrpyptionPassphrase)); + wo.SetError(constants.RetCodes.SUCCESS, ""); + return wo; + + } + private WrappedObject DoValidateDesktopPwd(SecretStore ssStore, WrappedObject wo) { // let's validate the Desktop pwd diff --git a/CASA/package/windows/vs_solutions/CASAInstall/CASA.ncb b/CASA/package/windows/vs_solutions/CASAInstall/CASA.ncb index dac16bdfa538213d4ecef2b183b0f71e4643da54..a416619d002dcc4a4d8a77b18b7845e530e9531e 100644 GIT binary patch delta 9476 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 A6#xJL delta 2068 zcmbtVZA?>F7(VB=)PjQj;6nwWVbeiT(+a34aV;$Z6B(jg;>H|UK89j}wlFEEZActL z;-qhMMAWf5H>O)uu0NJ+ahQ;0Mz?8n%C^kt=HE?!Xfl_L?m4|+)a~Ey&2!IrKh8Pt z=edDFRp7F8`mn^EbVPb?{!+$R9#9Od0M-D@fmJ{O-Ig-u+A(tgi-9CyG7^ahl+b#W zk(bkARjN7{{DJjnL+WPDm}7YPZ^vbi`YW#MdrVy{kxMmaxjG1LNISl27RF@2#XPK@ z)d6niV@<4!9I~Bic?brE&7d`88{ydCwsK8Fxu4aIzL? zx3le2yLp)j`?;~ZDY}y{dV-rZV&`gR2Y);EbF(Ij#E-{E&56f$ur)$g)XyHfpTKwP zz?cDuCq@~p(IJIhQ!SO^g!(fQQz;_WyQ(O0xUeXZgN{`z%uL>e!>r6M)^j1jlLAcd z`_0Kb!`*YA-V_k>49G-k@CbVtn^vHJ&dd|&q%NPUXi~Q_`KmBaIN^e$UZ4*2=TxDe zCv7rQM3+KAeKPmbpnfTTn=b0pt;gm-qXL2IK#-d8E?O{<@>4S3Gu8IZ#`;;F{4Q= zo?}OCIzh_9vFT&hv06D`4#vd0;alU>f{T=6sp2`b%aW`fLhVu8h%sgxR_W=qB|Yh3 z0;Z40lCfXs(9VujK130VY4sT)_u_pcTADsk7ldmrI97{=tq5j4=pN677wp-CTi1@< z7!FoVes&_7aoJ{_km#C5M_GA^y8X}_078K14Jyz3E9okTYryxwb>IdtL02?Jx;JAM zUCuWR)MU}Ud>xJCFB)AoHuL%Ev?&2@M^r>Fi9S+#%L_`R_en`Qq{4|>irDSDmF|1G z&lr28HPxU0)-Yfnk<3cuxj9;bo#1GJI&fSVH9#4A8DF#s+kz-5l+f7*+n`Th7M)KO zcY%2ah#(Z%-&8_67-Ocgzu;a(}+EK#`S5~ zucbvh3Q6rhOSU!}g}PT$gWp0Qb{QyqAWcr|yQ3n{h(R`V{LV?;Sx7Z)2Ku(!EVp)_ z>rSS1H}xnMJML>Y4rM#g$OPeMAv|kSs%Lx^*;h%09!B zAs%ztsH!eY&I(P$g!f3{L20%q>3aNsa^dp|mP>8@x%AShQn_!igBMh@jSzYf5Jxn; z4XC=ts71{PjA%_O>Rm~Z5hjZJSB%R=ic-ok`;YZ>qbFPc+Eby`Aha8(?MyQDf9!)3 zrBvFmdUT(U^B<`Fo!$ILdVudw)V_ar%uR6;@c{=})LL>5d_jSxLb`KU$9F|Hq)$ diff --git a/CASA/package/windows/vs_solutions/CASAInstall/CASA.vdproj b/CASA/package/windows/vs_solutions/CASAInstall/CASA.vdproj index 75faa8e1..587ecd08 100644 --- a/CASA/package/windows/vs_solutions/CASAInstall/CASA.vdproj +++ b/CASA/package/windows/vs_solutions/CASAInstall/CASA.vdproj @@ -21,24 +21,6 @@ } "Entry" { - "MsmKey" = "8:_43A67B1DA6D34A6098E563CC902B950F" - "OwnerKey" = "8:_A6D188F9B5AF430C92D0B9606ADF4C63" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_43A67B1DA6D34A6098E563CC902B950F" - "OwnerKey" = "8:_98DCC664712A41B993FCD33026D06FFC" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { - "MsmKey" = "8:_43A67B1DA6D34A6098E563CC902B950F" - "OwnerKey" = "8:_BF2CE61978054B2DB482792974E390F0" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { "MsmKey" = "8:_6CE0B932302E4E3783AAD1EA468ABD34" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -75,6 +57,24 @@ } "Entry" { + "MsmKey" = "8:_EF3E9937AC8B4A898E7B80BCEA175E6A" + "OwnerKey" = "8:_98DCC664712A41B993FCD33026D06FFC" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EF3E9937AC8B4A898E7B80BCEA175E6A" + "OwnerKey" = "8:_BF2CE61978054B2DB482792974E390F0" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EF3E9937AC8B4A898E7B80BCEA175E6A" + "OwnerKey" = "8:_A6D188F9B5AF430C92D0B9606ADF4C63" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_EF467E7BEF8E4109BAD7E2FE47508D13" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -307,13 +307,13 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:CASA" - "ProductCode" = "8:{9763A76D-50C8-4D81-AAB2-0415D042E299}" - "PackageCode" = "8:{A775679E-BE18-4FCC-884B-B5A6626CD0A4}" + "ProductCode" = "8:{970A65D5-A969-4659-B2AF-F212B518F99A}" + "PackageCode" = "8:{1368B6D9-3ACA-446D-8E33-C207F44508D6}" "UpgradeCode" = "8:{DFD8B8A0-EA51-4202-831C-7CD2B90A63AE}" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" - "ProductVersion" = "8:1.7.732" + "ProductVersion" = "8:1.7.786" "Manufacturer" = "8:Novell" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" @@ -835,7 +835,7 @@ } "MergeModule" { - "{35A69C6E-5BA4-440D-803D-762B59A45393}:_43A67B1DA6D34A6098E563CC902B950F" + "{35A69C6E-5BA4-440D-803D-762B59A45393}:_EF3E9937AC8B4A898E7B80BCEA175E6A" { "UseDynamicProperties" = "11:TRUE" "IsDependency" = "11:TRUE" @@ -854,7 +854,7 @@ { "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_98DCC664712A41B993FCD33026D06FFC" { - "SourcePath" = "8:..\\CASA-gui-msm\\Debug\\CASA-gui.msm" + "SourcePath" = "8:..\\CASA-gui-msm\\Release\\CASA-gui.msm" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_E8900D5F0BD44DC0BB0BEFDF7C43B30C" @@ -907,7 +907,7 @@ } "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_A6D188F9B5AF430C92D0B9606ADF4C63" { - "SourcePath" = "8:..\\CASA-dev-msm\\Debug\\miCASA-Dev-msm.msm" + "SourcePath" = "8:..\\CASA-dev-msm\\Release\\miCASA-Dev-msm.msm" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_E8900D5F0BD44DC0BB0BEFDF7C43B30C" @@ -939,17 +939,31 @@ "SourcePath" = "8:..\\CASA-dev-msm\\Release\\miCASA-Dev-msm.msm" "Properties" { - "_62D43560615587AE3DB95A0BA428D5BE.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "_4610C2D660057AC39D7FDD4891590B10.4F1ACC03A482468C9BEBF6D83FA4F7FE" { - "Name" = "8:_62D43560615587AE3DB95A0BA428D5BE.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Name" = "8:_4610C2D660057AC39D7FDD4891590B10.4F1ACC03A482468C9BEBF6D83FA4F7FE" "DisplayName" = "8:" "Description" = "8:" "Type" = "3:2" - "ContextData" = "8:InstallToGAC=;IsolateToManifest=_A1ECD7DAF522A0E5D85BCDD9EAED3209.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "ContextData" = "8:InstallToGAC=;IsolateToManifest=_8FCF3A547028ECFD0B5049EFAB348182.4F1ACC03A482468C9BEBF6D83FA4F7FE" "Attributes" = "3:0" "Setting" = "3:2" - "Value" = "8:_A1ECD7DAF522A0E5D85BCDD9EAED3209.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "DefaultValue" = "8:_A1ECD7DAF522A0E5D85BCDD9EAED3209.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Value" = "8:_8FCF3A547028ECFD0B5049EFAB348182.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "DefaultValue" = "8:_8FCF3A547028ECFD0B5049EFAB348182.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "ParentName" = "8:_6418E7496A474EDDAC9A91150BBE4A26.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "UsePlugInResources" = "11:FALSE" + } + "_4F85CEF984A77868D0A929E54872824F.4F1ACC03A482468C9BEBF6D83FA4F7FE" + { + "Name" = "8:_4F85CEF984A77868D0A929E54872824F.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "DisplayName" = "8:" + "Description" = "8:" + "Type" = "3:2" + "ContextData" = "8:InstallToGAC=;IsolateToManifest=_0683B4C519DB3748EBD996E0ABA831C0.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Attributes" = "3:0" + "Setting" = "3:2" + "Value" = "8:_0683B4C519DB3748EBD996E0ABA831C0.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "DefaultValue" = "8:_0683B4C519DB3748EBD996E0ABA831C0.4F1ACC03A482468C9BEBF6D83FA4F7FE" "ParentName" = "8:_6418E7496A474EDDAC9A91150BBE4A26.4F1ACC03A482468C9BEBF6D83FA4F7FE" "UsePlugInResources" = "11:FALSE" } @@ -964,59 +978,45 @@ "Setting" = "3:1" "UsePlugInResources" = "11:FALSE" } - "_6E1C74B0F6DBAA22C571F4B02C1DB283.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "_B6F5734BF952F464EAB21BAD6E20F38A.4F1ACC03A482468C9BEBF6D83FA4F7FE" { - "Name" = "8:_6E1C74B0F6DBAA22C571F4B02C1DB283.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Name" = "8:_B6F5734BF952F464EAB21BAD6E20F38A.4F1ACC03A482468C9BEBF6D83FA4F7FE" "DisplayName" = "8:" "Description" = "8:" "Type" = "3:2" - "ContextData" = "8:InstallToGAC=;IsolateToManifest=_E33B56BF66EDE9E5F123E5CB7C4EEAB7.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "ContextData" = "8:InstallToGAC=;IsolateToManifest=_79BCEE497E2B712D20C7E4A2F4800E60.4F1ACC03A482468C9BEBF6D83FA4F7FE" "Attributes" = "3:0" "Setting" = "3:2" - "Value" = "8:_E33B56BF66EDE9E5F123E5CB7C4EEAB7.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "DefaultValue" = "8:_E33B56BF66EDE9E5F123E5CB7C4EEAB7.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Value" = "8:_79BCEE497E2B712D20C7E4A2F4800E60.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "DefaultValue" = "8:_79BCEE497E2B712D20C7E4A2F4800E60.4F1ACC03A482468C9BEBF6D83FA4F7FE" "ParentName" = "8:_6418E7496A474EDDAC9A91150BBE4A26.4F1ACC03A482468C9BEBF6D83FA4F7FE" "UsePlugInResources" = "11:FALSE" } - "_95C01A87787956AC69FC2E9C7FA507A7.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "_E7CF2B4A827BE173141CA1E1D0F82AFF.4F1ACC03A482468C9BEBF6D83FA4F7FE" { - "Name" = "8:_95C01A87787956AC69FC2E9C7FA507A7.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Name" = "8:_E7CF2B4A827BE173141CA1E1D0F82AFF.4F1ACC03A482468C9BEBF6D83FA4F7FE" "DisplayName" = "8:" "Description" = "8:" "Type" = "3:2" - "ContextData" = "8:InstallToGAC=;IsolateToManifest=_79C6F8F43FF4CB3AF63B925D0EA1C564.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "ContextData" = "8:InstallToGAC=;IsolateToManifest=_108CF762A5E732DB8AA6185773BCA705.4F1ACC03A482468C9BEBF6D83FA4F7FE" "Attributes" = "3:0" "Setting" = "3:2" - "Value" = "8:_79C6F8F43FF4CB3AF63B925D0EA1C564.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "DefaultValue" = "8:_79C6F8F43FF4CB3AF63B925D0EA1C564.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Value" = "8:_108CF762A5E732DB8AA6185773BCA705.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "DefaultValue" = "8:_108CF762A5E732DB8AA6185773BCA705.4F1ACC03A482468C9BEBF6D83FA4F7FE" "ParentName" = "8:_6418E7496A474EDDAC9A91150BBE4A26.4F1ACC03A482468C9BEBF6D83FA4F7FE" "UsePlugInResources" = "11:FALSE" } - "_E1A13CA07F77E5ABDB363BA4E14A8EED.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "_F0F8D6D23B097F7830C01E614D9034B9.4F1ACC03A482468C9BEBF6D83FA4F7FE" { - "Name" = "8:_E1A13CA07F77E5ABDB363BA4E14A8EED.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Name" = "8:_F0F8D6D23B097F7830C01E614D9034B9.4F1ACC03A482468C9BEBF6D83FA4F7FE" "DisplayName" = "8:" "Description" = "8:" "Type" = "3:2" - "ContextData" = "8:InstallToGAC=;IsolateToManifest=_793F49C101FDC71EA468B0F50F5E7FF8.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "ContextData" = "8:InstallToGAC=;IsolateToManifest=_290870C7D1693472634A9D8D875DA83B.4F1ACC03A482468C9BEBF6D83FA4F7FE" "Attributes" = "3:0" "Setting" = "3:2" - "Value" = "8:_793F49C101FDC71EA468B0F50F5E7FF8.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "DefaultValue" = "8:_793F49C101FDC71EA468B0F50F5E7FF8.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "ParentName" = "8:_6418E7496A474EDDAC9A91150BBE4A26.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "UsePlugInResources" = "11:FALSE" - } - "_ED516AEF413A6424C60E58C4FE881B58.4F1ACC03A482468C9BEBF6D83FA4F7FE" - { - "Name" = "8:_ED516AEF413A6424C60E58C4FE881B58.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "DisplayName" = "8:" - "Description" = "8:" - "Type" = "3:2" - "ContextData" = "8:InstallToGAC=;IsolateToManifest=_4CF0917F390ACC0AF5A1750516A3993E.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "Attributes" = "3:0" - "Setting" = "3:2" - "Value" = "8:_4CF0917F390ACC0AF5A1750516A3993E.4F1ACC03A482468C9BEBF6D83FA4F7FE" - "DefaultValue" = "8:_4CF0917F390ACC0AF5A1750516A3993E.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "Value" = "8:_290870C7D1693472634A9D8D875DA83B.4F1ACC03A482468C9BEBF6D83FA4F7FE" + "DefaultValue" = "8:_290870C7D1693472634A9D8D875DA83B.4F1ACC03A482468C9BEBF6D83FA4F7FE" "ParentName" = "8:_6418E7496A474EDDAC9A91150BBE4A26.4F1ACC03A482468C9BEBF6D83FA4F7FE" "UsePlugInResources" = "11:FALSE" } @@ -1030,7 +1030,7 @@ } "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_BF2CE61978054B2DB482792974E390F0" { - "SourcePath" = "8:..\\CASA-msm\\Debug\\CASA-msm.msm" + "SourcePath" = "8:..\\CASA-msm\\Release\\CASA-msm.msm" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_E8900D5F0BD44DC0BB0BEFDF7C43B30C"