diff --git a/CASA/micasad/cache/SecretStore.cs b/CASA/micasad/cache/SecretStore.cs index 97269a17..9285f1be 100644 --- a/CASA/micasad/cache/SecretStore.cs +++ b/CASA/micasad/cache/SecretStore.cs @@ -89,7 +89,12 @@ namespace sscs.cache // start a MPFileWatcher if necessary if (mpWatcher == null) { - mpWatcher = new MPFileWatcher(GetUserHomeDirectory(), ConstStrings.MICASA_PASSCODE_BY_MASTERPASSWD_FILE); + // make sure HomeDirectory exists + String sHomeDir = GetUserHomeDirectory(); + if (sHomeDir != null && sHomeDir.Length > 0) + { + mpWatcher = new MPFileWatcher(GetUserHomeDirectory(), ConstStrings.MICASA_PASSCODE_BY_MASTERPASSWD_FILE); + } } } diff --git a/CASA/micasad/init/CredMgr.cs b/CASA/micasad/init/CredMgr.cs index f1312ff8..8dab9945 100644 --- a/CASA/micasad/init/CredMgr.cs +++ b/CASA/micasad/init/CredMgr.cs @@ -44,7 +44,7 @@ namespace sscs.init string sCredMgrPath = GetCredMgrPath(); if (sCredMgrPath != null) { - RunProcess(sExePath, "/i /n /s " + "\"" + sCredMgrPath + "\""); + RunProcess(sExePath, "/i /n /s " + "\"" + sCredMgrPath + "\""); } } } @@ -71,6 +71,7 @@ namespace sscs.init { try { + System.Diagnostics.Trace.WriteLine("Running: " + sProcess + " " + sArgs); Process myProcess = new Process(); ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(sProcess); diff --git a/CASA/micasad/lss/LocalStorage.cs b/CASA/micasad/lss/LocalStorage.cs index a2c290aa..b5c6dafd 100644 --- a/CASA/micasad/lss/LocalStorage.cs +++ b/CASA/micasad/lss/LocalStorage.cs @@ -38,77 +38,77 @@ using Novell.CASA.MiCasa.Common; namespace sscs.lss { - /// - /* - * This class is a service to store data persistently. - * How it does this is determined by implementation within the - * private methods (File system using file(s), database, etc) - * The MasterPasscode can be used to generate the key for - * encyption and decryption. - * If encrpytion is used, the private methods will also manage - * how the encyption key is to be stored and retrieved. - * Each piece of data is located by a DataID. - * This might be an individual credentail or - * a complete store. - */ + /// + /* + * This class is a service to store data persistently. + * How it does this is determined by implementation within the + * private methods (File system using file(s), database, etc) + * The MasterPasscode can be used to generate the key for + * encyption and decryption. + * If encrpytion is used, the private methods will also manage + * how the encyption key is to be stored and retrieved. + * Each piece of data is located by a DataID. + * This might be an individual credentail or + * a complete store. + */ - /* We might not need this as a separate class. - * Depending on the db changes, we can change this later. - */ + /* We might not need this as a separate class. + * Depending on the db changes, we can change this later. + */ - /// - public class LocalStorage - { + /// + public class LocalStorage + { private byte[] m_baGeneratedKey = null; private SecretStore userStore = null; - private int persistThreadSleepTime = 1000 * 60 * 5; //1000 * 30; - private Thread persistThread = null; + private int persistThreadSleepTime = 1000 * 60 * 5; //1000 * 30; + private Thread persistThread = null; #if LINUX Mono.Unix.UnixFileSystemInfo sockFileInfo; Mono.Unix.UnixUserInfo sockFileOwner; #endif - private static string LINUXID = "Unix"; + private static string LINUXID = "Unix"; internal LocalStorage(SecretStore store,byte[] baMasterPasscode) - { - userStore = store; + { + userStore = store; m_baGeneratedKey = baMasterPasscode; - LoadPersistentStore(); - userStore.DumpSecretstore(); - } - ~LocalStorage() - { - if(persistThread != null) - { - persistThread.Abort(); - persistThread.Join(); - } - } + LoadPersistentStore(); + userStore.DumpSecretstore(); + } + ~LocalStorage() + { + if(persistThread != null) + { + persistThread.Abort(); + persistThread.Join(); + } + } - // allowing a user to choose the storage location is not approved yet + // allowing a user to choose the storage location is not approved yet private LocalStorage(SecretStore store, byte[] baMasterPasscode, string sStorageDirectory) - { - userStore = store; + { + userStore = store; m_baGeneratedKey = baMasterPasscode; - LoadPersistentStore(); - userStore.DumpSecretstore(); - } + LoadPersistentStore(); + userStore.DumpSecretstore(); + } - private void StorePersistentData(string sDataID, byte[] baData) - { + private void StorePersistentData(string sDataID, byte[] baData) + { - } + } - private byte[] RetrievePersistentData(string sDataID) - { + private byte[] RetrievePersistentData(string sDataID) + { - return null; - } + return null; + } public void PersistStoreWithDelay() { @@ -144,10 +144,10 @@ namespace sscs.lss } - private string GetDecryptedXml() - { - try - { + private string GetDecryptedXml() + { + try + { string fileName = userStore.GetPersistenceFilePath(); string tempFile = fileName; int count = 0; @@ -192,145 +192,145 @@ namespace sscs.lss return null; byte[] key = CASACrypto.GetKeySetFromFile(baPasscode,userStore.GetKeyFilePath()); - if( null == key ) - return null; + if( null == key ) + return null; - byte[] decryptedBuffer = CASACrypto.ReadFileAndDecryptData(key,fileName); + byte[] decryptedBuffer = CASACrypto.ReadFileAndDecryptData(key,fileName); - if( null == decryptedBuffer ) - return null; + if( null == decryptedBuffer ) + return null; string temp = Encoding.UTF8.GetString(decryptedBuffer, 0, decryptedBuffer.Length); return temp; - } - catch(Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - CSSSLogger.DbgLog("Unable to get persistent store"); - } - return null; - } - /* This method, uses the key to decrypt the persistent store - * and populates userStore with the persistent data. - */ - private bool LoadPersistentStore() - { - try - { - string xpath = ""; - XmlDocument doc = new XmlDocument(); + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Unable to get persistent store"); + } + return null; + } + /* This method, uses the key to decrypt the persistent store + * and populates userStore with the persistent data. + */ + private bool LoadPersistentStore() + { + try + { + string xpath = ""; + XmlDocument doc = new XmlDocument(); - string xmlToLoad = GetDecryptedXml(); - if(xmlToLoad != null) - { - doc.LoadXml(xmlToLoad); + string xmlToLoad = GetDecryptedXml(); + if(xmlToLoad != null) + { + doc.LoadXml(xmlToLoad); #if false - XmlTextWriter writer = new XmlTextWriter("/home/poorna/.miCASA.xml",null); + XmlTextWriter writer = new XmlTextWriter("d:/persist.xml",null); writer.Formatting = Formatting.Indented; doc.Save(writer); writer.Close(); #endif - } - else - { - 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; + } + else + { + 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; + 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); + 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); + 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"; + // 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; + // 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); - } + LinkedKeyInfo lki = new LinkedKeyInfo(sSecretID, sKeyID, true); + KeyValue kv = secret.GetKeyValue(key); + kv.AddLink(lki); + } - } - }//if ends - } + } + }//if ends + } - }//end of traversing keyChainNodeList - } - } - catch(Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - } + }//end of traversing keyChainNodeList + } + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + } // collect now to remove old data from memory GC.Collect(); - return true; - } + return true; + } private void PersistStoreDelayThreadFn() { @@ -339,139 +339,26 @@ namespace sscs.lss persistThread = null; } - private void PersistStoreThreadFn() - { - while(true) - { + private void PersistStoreThreadFn() + { + while(true) + { Thread.Sleep(persistThreadSleepTime); PersistStore(); - } - } + } + } - /* Persists the store to an xml file. - * TBD : Would we require any form of encoding? - */ + /* Persists the store to an xml file. + * TBD : Would we require any form of encoding? + */ - internal void PersistStore() - { -// userStore.DumpSecretstore(); - try - { - - MemoryStream ms1 = new MemoryStream(); - XmlTextWriter writer = new XmlTextWriter(ms1,null); - writer.Formatting = Formatting.Indented; - - writer.WriteStartDocument(); - writer.WriteStartElement(XmlConsts.miCASANode); - writer.WriteAttributeString(XmlConsts.versionAttr,"1.5"); - - { - IDictionaryEnumerator iter = (IDictionaryEnumerator)userStore.GetKeyChainEnumerator(); - char [] tmpId; - string sTmpId; - while( iter.MoveNext() ) - { - KeyChain kc = (KeyChain)iter.Value; - writer.WriteStartElement(XmlConsts.keyChainNode); - string kcId = kc.GetKey(); - tmpId = new char[kcId.Length-1]; - for(int i = 0; i < kcId.Length-1; i++ ) - tmpId[i] = kcId[i]; - sTmpId = new string(tmpId); - - writer.WriteAttributeString(XmlConsts.idAttr,sTmpId); -/* If we need to store time - writer.WriteStartElement(XmlConsts.timeNode); - writer.WriteAttributeString(XmlConsts.createdTimeNode,kc.CreatedTime.ToString()); - writer.WriteAttributeString(XmlConsts.modifiedTimeNode,kc.ModifiedTime.ToString()); - writer.WriteEndElement(); -*/ - - IDictionaryEnumerator secIter = (IDictionaryEnumerator)(kc.GetAllSecrets()); - while(secIter.MoveNext()) - { - Secret secret = (Secret)secIter.Value; - writer.WriteStartElement(XmlConsts.secretNode); - string secretId = secret.GetKey(); - tmpId = new char[secretId.Length-1]; - for(int i = 0; i < secretId.Length-1; i++ ) - tmpId[i] = secretId[i]; - sTmpId = new string(tmpId); - - writer.WriteAttributeString(XmlConsts.idAttr,sTmpId); -/* If we need to store time - writer.WriteStartElement(XmlConsts.timeNode); - writer.WriteAttributeString(XmlConsts.createdTimeNode,secret.CreatedTime.ToString()); - writer.WriteAttributeString(XmlConsts.modifiedTimeNode,secret.ModifiedTime.ToString()); - writer.WriteEndElement(); -*/ - - writer.WriteStartElement(XmlConsts.valueNode); -// byte[] byteArr = secret.GetValue(); - - IDictionaryEnumerator etor = (IDictionaryEnumerator)secret.GetKeyValueEnumerator(); - while(etor.MoveNext()) - { - string sKey = (string)etor.Key; - string value = secret.GetKeyValue(sKey).GetValue(); - writer.WriteStartElement(XmlConsts.keyNode); - writer.WriteAttributeString(XmlConsts.idAttr, sKey); - writer.WriteStartElement(XmlConsts.keyValueNode); - writer.WriteString(value); - writer.WriteEndElement(); -/* If we need to store time - writer.WriteStartElement(XmlConsts.timeNode); - writer.WriteAttributeString(XmlConsts.createdTimeNode,(secret.GetKeyValueCreatedTime(sKey)).ToString()); - writer.WriteAttributeString(XmlConsts.modifiedTimeNode,(secret.GetKeyValueModifiedTime(sKey)).ToString()); - writer.WriteEndElement(); -*/ - // write all LinkKeys - Hashtable htLinkedKeys = secret.GetLinkedKeys(sKey); - if (htLinkedKeys != null) - { - IDictionaryEnumerator etorLinked = (IDictionaryEnumerator)htLinkedKeys.GetEnumerator(); - while(etorLinked.MoveNext()) - { - LinkedKeyInfo lki = (LinkedKeyInfo)etorLinked.Value; - writer.WriteStartElement(XmlConsts.linkedKeyNode); - - writer.WriteStartElement(XmlConsts.linkedTargetSecretNode); - writer.WriteString(lki.GetLinkedSecretID().Substring(0, lki.GetLinkedSecretID().Length-1)); - writer.WriteEndElement(); - - writer.WriteStartElement(XmlConsts.linkedTargetKeyNode); - writer.WriteString(lki.GetLinkedKeyID()); - writer.WriteEndElement(); - - writer.WriteEndElement(); - } - } - - writer.WriteEndElement(); - } - -/* - char[] chArr = new char[byteArr.Length]; - for(int z = 0; z < byteArr.Length; z++) - chArr[z] = (char)byteArr[z]; - - string stringToStore = new string(chArr); - writer.WriteString(stringToStore); -*/ - - writer.WriteEndElement(); //end of value node - writer.WriteEndElement(); - } - writer.WriteEndElement(); //keychain - } - } - writer.WriteEndElement(); //miCASA node - writer.WriteEndDocument(); - writer.Flush(); - writer.Close(); - - //byte[] key = CASACrypto.GetKeySetFromFile(CASACrypto.GetMasterPasscode(userStore.GetDesktopPasswd(),userStore.GetPasscodeByDesktopFilePath()),userStore.GetKeyFilePath()); + internal void PersistStore() + { + //userStore.DumpSecretstore(); + try + { + MemoryStream ms1 = GetSecretsAsXMLStream(); + //byte[] key = CASACrypto.GetKeySetFromFile(CASACrypto.GetMasterPasscode(userStore.GetDesktopPasswd(),userStore.GetPasscodeByDesktopFilePath()),userStore.GetKeyFilePath()); byte[] key = CASACrypto.GetKeySetFromFile(m_baGeneratedKey, userStore.GetKeyFilePath()); string fileName = userStore.GetPersistenceFilePath(); @@ -515,6 +402,129 @@ namespace sscs.lss { CSSSLogger.ExpLog(e.ToString()); } - } - } + } + + internal MemoryStream GetSecretsAsXMLStream() + { + try + { + MemoryStream ms1 = new MemoryStream(); + XmlTextWriter writer = new XmlTextWriter(ms1,null); + writer.Formatting = Formatting.Indented; + + writer.WriteStartDocument(); + writer.WriteStartElement(XmlConsts.miCASANode); + writer.WriteAttributeString(XmlConsts.versionAttr,"1.5"); + + IDictionaryEnumerator iter = (IDictionaryEnumerator)userStore.GetKeyChainEnumerator(); + char [] tmpId; + string sTmpId; + while( iter.MoveNext() ) + { + KeyChain kc = (KeyChain)iter.Value; + writer.WriteStartElement(XmlConsts.keyChainNode); + string kcId = kc.GetKey(); + tmpId = new char[kcId.Length-1]; + for(int i = 0; i < kcId.Length-1; i++ ) + tmpId[i] = kcId[i]; + sTmpId = new string(tmpId); + + writer.WriteAttributeString(XmlConsts.idAttr,sTmpId); + /* If we need to store time + writer.WriteStartElement(XmlConsts.timeNode); + writer.WriteAttributeString(XmlConsts.createdTimeNode,kc.CreatedTime.ToString()); + writer.WriteAttributeString(XmlConsts.modifiedTimeNode,kc.ModifiedTime.ToString()); + writer.WriteEndElement(); + */ + + IDictionaryEnumerator secIter = (IDictionaryEnumerator)(kc.GetAllSecrets()); + while(secIter.MoveNext()) + { + Secret secret = (Secret)secIter.Value; + writer.WriteStartElement(XmlConsts.secretNode); + string secretId = secret.GetKey(); + tmpId = new char[secretId.Length-1]; + for(int i = 0; i < secretId.Length-1; i++ ) + tmpId[i] = secretId[i]; + sTmpId = new string(tmpId); + + writer.WriteAttributeString(XmlConsts.idAttr,sTmpId); + /* If we need to store time + writer.WriteStartElement(XmlConsts.timeNode); + writer.WriteAttributeString(XmlConsts.createdTimeNode,secret.CreatedTime.ToString()); + writer.WriteAttributeString(XmlConsts.modifiedTimeNode,secret.ModifiedTime.ToString()); + writer.WriteEndElement(); + */ + + writer.WriteStartElement(XmlConsts.valueNode); + // byte[] byteArr = secret.GetValue(); + + IDictionaryEnumerator etor = (IDictionaryEnumerator)secret.GetKeyValueEnumerator(); + while(etor.MoveNext()) + { + string sKey = (string)etor.Key; + string value = secret.GetKeyValue(sKey).GetValue(); + writer.WriteStartElement(XmlConsts.keyNode); + writer.WriteAttributeString(XmlConsts.idAttr, sKey); + writer.WriteStartElement(XmlConsts.keyValueNode); + writer.WriteString(value); + writer.WriteEndElement(); + /* If we need to store time + writer.WriteStartElement(XmlConsts.timeNode); + writer.WriteAttributeString(XmlConsts.createdTimeNode,(secret.GetKeyValueCreatedTime(sKey)).ToString()); + writer.WriteAttributeString(XmlConsts.modifiedTimeNode,(secret.GetKeyValueModifiedTime(sKey)).ToString()); + writer.WriteEndElement(); + */ + // write all LinkKeys + Hashtable htLinkedKeys = secret.GetLinkedKeys(sKey); + if (htLinkedKeys != null) + { + IDictionaryEnumerator etorLinked = (IDictionaryEnumerator)htLinkedKeys.GetEnumerator(); + while(etorLinked.MoveNext()) + { + LinkedKeyInfo lki = (LinkedKeyInfo)etorLinked.Value; + writer.WriteStartElement(XmlConsts.linkedKeyNode); + + writer.WriteStartElement(XmlConsts.linkedTargetSecretNode); + writer.WriteString(lki.GetLinkedSecretID().Substring(0, lki.GetLinkedSecretID().Length-1)); + writer.WriteEndElement(); + + writer.WriteStartElement(XmlConsts.linkedTargetKeyNode); + writer.WriteString(lki.GetLinkedKeyID()); + writer.WriteEndElement(); + + writer.WriteEndElement(); + } + } + + writer.WriteEndElement(); + } + + /* + char[] chArr = new char[byteArr.Length]; + for(int z = 0; z < byteArr.Length; z++) + chArr[z] = (char)byteArr[z]; + + string stringToStore = new string(chArr); + writer.WriteString(stringToStore); + */ + + writer.WriteEndElement(); //end of value node + writer.WriteEndElement(); + } + writer.WriteEndElement(); //keychain + } + + writer.WriteEndElement(); //miCASA node + writer.WriteEndDocument(); + writer.Flush(); + writer.Close(); + return ms1; + } + catch (Exception e) + { + throw e; + } + } + } }