diff --git a/CASA/micasad/Makefile.am b/CASA/micasad/Makefile.am index 51b9b370..a1052e2f 100644 --- a/CASA/micasad/Makefile.am +++ b/CASA/micasad/Makefile.am @@ -70,6 +70,7 @@ CSFILES=$(srcdir)/AssemblyInfo.cs \ $(srcdir)/common/UnixUserIdentifier.cs \ $(srcdir)/common/Constants.cs \ $(srcdir)/common/CSSSLogger.cs \ + $(srcdir)/common/CSSSUtils.cs \ $(srcdir)/common/CSSSException.cs \ $(srcdir)/communication/IPCChannel.cs \ $(srcdir)/communication/CommunicationFactory.cs \ diff --git a/CASA/micasad/cache/MPFileWatcher.cs b/CASA/micasad/cache/MPFileWatcher.cs index 27573417..2fc04fa4 100644 --- a/CASA/micasad/cache/MPFileWatcher.cs +++ b/CASA/micasad/cache/MPFileWatcher.cs @@ -1,169 +1,174 @@ -using System; -using System.IO; - -using sscs.common; - -namespace sscs.cache -{ - /// - /// Summary description for MPFileWatcher. - /// - public class MPFileWatcher - { - FileSystemWatcher fwatcher; - private string m_dir = null; - private string m_filename = null; - private byte[] m_baMP = new byte[32]; - private byte[] m_baMPIV = new byte[32]; - private byte[] m_baMPSalt = null; - private bool m_bIgnoreFileDeletes = false; - - public MPFileWatcher(string MPFilePath, string MPFileName) - { - m_dir = MPFilePath; - m_filename = MPFileName; - - if ((MPFilePath != null) && (MPFileName != null)) - { - LogMessage("Starting MPFile watcher on " + MPFilePath + "/" + MPFileName.Substring(1)); - fwatcher = new FileSystemWatcher(MPFilePath); - fwatcher.Filter = MPFileName.Substring(1)+"*"; - fwatcher.Deleted += new FileSystemEventHandler(fwatcher_Deleted); - fwatcher.Renamed += new RenamedEventHandler(fwatcher_Renamed); - fwatcher.Changed += new FileSystemEventHandler(fwatcher_Changed); - fwatcher.EnableRaisingEvents = true; - } - - if (File.Exists(MPFilePath + MPFileName)) - { - LoadAndCacheMPFiles(); - } - } - - ~MPFileWatcher() - { - if (fwatcher != null) - fwatcher.EnableRaisingEvents = false; - fwatcher = null; - } - internal void pauseWatcher() - { - m_bIgnoreFileDeletes = true; - } - - internal void resumeWatcher() - { - m_bIgnoreFileDeletes = false; - } - - private void fwatcher_Deleted(object sender, FileSystemEventArgs e) - { - if (!m_bIgnoreFileDeletes) - { - LogMessage("MP file deleted"); - ReWriteFiles(); - } - } - - private void fwatcher_Changed(object sender, FileSystemEventArgs e) - { - LogMessage("MP file Changed"); - LoadAndCacheMPFiles(); - } - - private void fwatcher_Renamed(object sender, RenamedEventArgs e) - { - LogMessage("MP file renamed"); - fwatcher_Deleted(sender, e); - } - - private void LoadAndCacheMPFiles() - { - LogMessage("Loading and caching MP files"); - - try - { - FileStream fs = new FileStream(m_dir + m_filename, FileMode.Open, FileAccess.Read); - fs.Read(m_baMP, 0, m_baMP.Length); - fs.Flush(); - fs.Close(); - - fs = new FileStream(m_dir + m_filename + ".IV", FileMode.Open, FileAccess.Read); - fs.Read(m_baMPIV, 0, m_baMPIV.Length); - fs.Flush(); - fs.Close(); - - if (File.Exists(m_dir + m_filename + ".salt")) - { - m_baMPSalt = new byte[64]; - fs = new FileStream(m_dir + m_filename + ".salt", FileMode.Open, FileAccess.Read); - fs.Read(m_baMPSalt, 0, m_baMPSalt.Length); - fs.Flush(); - fs.Close(); - } - - } - - catch (Exception e) - { - LogMessage(e.ToString()); - } - } - - private void ReWriteFiles() - { - try - { - FileStream fs = new FileStream(m_dir + m_filename, FileMode.Create); - fs.Write(m_baMP, 0, m_baMP.Length); - fs.Flush(); - fs.Close(); - - File.SetAttributes(m_dir + m_filename, FileAttributes.Hidden); - } - catch (Exception e) - { - LogMessage(e.ToString()); - } - - try - { - FileStream fs = new FileStream(m_dir + m_filename + ".IV", FileMode.Create); - fs.Write(m_baMPIV, 0, m_baMPIV.Length); - fs.Flush(); - fs.Close(); - - File.SetAttributes(m_dir + m_filename + ".IV", FileAttributes.Hidden); - } - catch (Exception e) - { - LogMessage(e.ToString()); - } - - - if (m_baMPSalt != null) - { - try - { - FileStream fs = new FileStream(m_dir + m_filename + ".salt", FileMode.Create); - fs.Write(m_baMPSalt, 0, m_baMPSalt.Length); - fs.Flush(); - fs.Close(); - - File.SetAttributes(m_dir + m_filename + ".salt", FileAttributes.Hidden); - } - catch (Exception e) - { - LogMessage(e.ToString()); - } - } - - } - - private void LogMessage(string message) - { -// Console.WriteLine(message); - CSSSLogger.DbgLog("MPFileWatcher:" + message); - } - } -} +using System; +using System.IO; + +using sscs.common; + +namespace sscs.cache +{ + /// + /// Summary description for MPFileWatcher. + /// + class MPFileWatcher + { + FileSystemWatcher fwatcher; + private string m_dir = null; + private string m_filename = null; + private byte[] m_baMP = new byte[32]; + private byte[] m_baMPIV = new byte[32]; + private byte[] m_baMPSalt = null; + private bool m_bIgnoreFileDeletes = false; + private SecretStore m_store = null; + + public MPFileWatcher(SecretStore store, string MPFilePath, string MPFileName) + { + m_store = store; + m_dir = MPFilePath; + m_filename = MPFileName; + + if ((MPFilePath != null) && (MPFileName != null)) + { + LogMessage("Starting MPFile watcher on " + MPFilePath + "/" + MPFileName.Substring(1)); + fwatcher = new FileSystemWatcher(MPFilePath); + fwatcher.Filter = MPFileName.Substring(1)+"*"; + fwatcher.Deleted += new FileSystemEventHandler(fwatcher_Deleted); + fwatcher.Renamed += new RenamedEventHandler(fwatcher_Renamed); + fwatcher.Changed += new FileSystemEventHandler(fwatcher_Changed); + fwatcher.EnableRaisingEvents = true; + } + + if (File.Exists(MPFilePath + MPFileName)) + { + LoadAndCacheMPFiles(); + } + } + + ~MPFileWatcher() + { + if (fwatcher != null) + fwatcher.EnableRaisingEvents = false; + fwatcher = null; + } + internal void pauseWatcher() + { + m_bIgnoreFileDeletes = true; + } + + internal void resumeWatcher() + { + m_bIgnoreFileDeletes = false; + } + + private void fwatcher_Deleted(object sender, FileSystemEventArgs e) + { + if (!m_bIgnoreFileDeletes) + { + LogMessage("MP file deleted"); + ReWriteFiles(); + } + } + + private void fwatcher_Changed(object sender, FileSystemEventArgs e) + { + LogMessage("MP file Changed"); + LoadAndCacheMPFiles(); + } + + private void fwatcher_Renamed(object sender, RenamedEventArgs e) + { + LogMessage("MP file renamed"); + fwatcher_Deleted(sender, e); + } + + private void LoadAndCacheMPFiles() + { + LogMessage("Loading and caching MP files"); + + try + { + FileStream fs = new FileStream(m_dir + m_filename, FileMode.Open, FileAccess.Read); + fs.Read(m_baMP, 0, m_baMP.Length); + fs.Flush(); + fs.Close(); + + fs = new FileStream(m_dir + m_filename + ".IV", FileMode.Open, FileAccess.Read); + fs.Read(m_baMPIV, 0, m_baMPIV.Length); + fs.Flush(); + fs.Close(); + + if (File.Exists(m_dir + m_filename + ".salt")) + { + m_baMPSalt = new byte[64]; + fs = new FileStream(m_dir + m_filename + ".salt", FileMode.Open, FileAccess.Read); + fs.Read(m_baMPSalt, 0, m_baMPSalt.Length); + fs.Flush(); + fs.Close(); + } + + } + + catch (Exception e) + { + LogMessage(e.ToString()); + } + } + + private void ReWriteFiles() + { + try + { + FileStream fs = new FileStream(m_dir + m_filename, FileMode.Create); + fs.Write(m_baMP, 0, m_baMP.Length); + fs.Flush(); + fs.Close(); + + File.SetAttributes(m_dir + m_filename, FileAttributes.Hidden); + CSSSUtils.SetSocketUserAsOwner(m_dir + m_filename, m_store.user.UserIdentifier); + } + catch (Exception e) + { + LogMessage(e.ToString()); + } + + try + { + FileStream fs = new FileStream(m_dir + m_filename + ".IV", FileMode.Create); + fs.Write(m_baMPIV, 0, m_baMPIV.Length); + fs.Flush(); + fs.Close(); + + File.SetAttributes(m_dir + m_filename + ".IV", FileAttributes.Hidden); + CSSSUtils.SetSocketUserAsOwner(m_dir + m_filename + ".IV", m_store.user.UserIdentifier); + } + catch (Exception e) + { + LogMessage(e.ToString()); + } + + + if (m_baMPSalt != null) + { + try + { + FileStream fs = new FileStream(m_dir + m_filename + ".salt", FileMode.Create); + fs.Write(m_baMPSalt, 0, m_baMPSalt.Length); + fs.Flush(); + fs.Close(); + + File.SetAttributes(m_dir + m_filename + ".salt", FileAttributes.Hidden); + CSSSUtils.SetSocketUserAsOwner(m_dir + m_filename + ".salt", m_store.user.UserIdentifier); + } + catch (Exception e) + { + LogMessage(e.ToString()); + } + } + + } + + private void LogMessage(string message) + { +// Console.WriteLine(message); + CSSSLogger.DbgLog("MPFileWatcher:" + message); + } + } +} diff --git a/CASA/micasad/cache/SecretStore.cs b/CASA/micasad/cache/SecretStore.cs index 576dd549..b0b26057 100644 --- a/CASA/micasad/cache/SecretStore.cs +++ b/CASA/micasad/cache/SecretStore.cs @@ -116,7 +116,7 @@ namespace sscs.cache String sPersistentDir = GetPersistenceDirectory(); if (sPersistentDir != null && sPersistentDir.Length > 0) { - mpWatcher = new MPFileWatcher(GetPersistenceDirectory(), ConstStrings.MICASA_PASSCODE_BY_MASTERPASSWD_FILE); + mpWatcher = new MPFileWatcher(this, GetPersistenceDirectory(), ConstStrings.MICASA_PASSCODE_BY_MASTERPASSWD_FILE); } } } @@ -176,16 +176,16 @@ namespace sscs.cache { try { - byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), false); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) - { + byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), false, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) + { ReEncryptPasscodeUsingRandomSalt(baPasscode, sDesktopPassword, GetPasscodeByDesktopFilePath()); return true; } // try old salt - baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), true); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) - { + baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), true, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) + { ReEncryptPasscodeUsingRandomSalt(baPasscode, sDesktopPassword, GetPasscodeByDesktopFilePath()); return true; } @@ -230,7 +230,8 @@ namespace sscs.cache */ baPasscode = CASACrypto.GenerateServerMasterPasscode( GetServerPasscodeBySystemKeyFilePath(), - GetServerValidationFilePath()); + GetServerValidationFilePath(), + user.UserIdentifier); if (null == baPasscode) { @@ -246,8 +247,8 @@ namespace sscs.cache } } - baPasscode = CASACrypto.GetServerMasterPasscodeUsingSystemKey(GetServerPasscodeBySystemKeyFilePath()); - if (CASACrypto.ValidatePasscode(baPasscode, GetServerValidationFilePath())) + baPasscode = CASACrypto.GetServerMasterPasscodeUsingSystemKey(GetServerPasscodeBySystemKeyFilePath(), user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetServerValidationFilePath(), user.UserIdentifier)) { slss = new LocalStorage(this, baPasscode, true); bIsServerStorePersistent = true; @@ -335,23 +336,23 @@ namespace sscs.cache } } - baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { lss = new LocalStorage(this, baPasscode); - bIsStorePersistent = true; + bIsStorePersistent = true; ReEncryptPasscodeUsingRandomSalt(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath()); return true; } else { // try old encryption method - baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), true); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), true, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { - // rewrite file using new encryption + // rewrite file using new encryption ReEncryptPasscodeUsingRandomSalt(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath()); - //CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath()); + //CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath(), user.UserIdentifier); lss = new LocalStorage(this, baPasscode); bIsStorePersistent = true; return true; @@ -381,7 +382,7 @@ namespace sscs.cache myRijndael.GenerateKey(); key = myRijndael.Key; - CASACrypto.StoreKeySetUsingMasterPasscode(key, IV, baPasscode, fileName); + CASACrypto.StoreKeySetUsingMasterPasscode(key, IV, baPasscode, fileName, user.UserIdentifier); } catch (Exception) { @@ -410,10 +411,10 @@ namespace sscs.cache */ if (desktopPasswd != null) { - baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath(), user.UserIdentifier); return true; } else @@ -422,20 +423,23 @@ namespace sscs.cache baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd( desktopPasswd, GetPasscodeByDesktopFilePath(), - true); + true, + user.UserIdentifier); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { // rewrite file using new method CASACrypto.EncryptAndStoreMasterPasscodeUsingString( baPasscode, desktopPasswd, - GetPasscodeByDesktopFilePath()); + GetPasscodeByDesktopFilePath(), + user.UserIdentifier); CASACrypto.EncryptAndStoreMasterPasscodeUsingString( baPasscode, mPasswd, - GetPasscodeByMasterPasswdFilePath()); + GetPasscodeByMasterPasswdFilePath(), + user.UserIdentifier); return true; } else @@ -447,8 +451,8 @@ namespace sscs.cache baPasscode = CASACrypto.GenerateMasterPasscodeUsingString(mPasswd, GetPasscodeByMasterPasswdFilePath(), GetValidationFilePath(), user.UserIdentifier); if (baPasscode != null) { - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath(), user.UserIdentifier); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath(), user.UserIdentifier); if (File.Exists(GetPersistenceFilePath())) { File.Delete(GetPersistenceFilePath()); @@ -493,7 +497,7 @@ namespace sscs.cache GenerateAndStoreEncryptionKey(baPasscode, GetKeyFilePath()); } - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath(), user.UserIdentifier); if (bIsStorePersistent == false) { lss = new LocalStorage(this, baPasscode); @@ -514,12 +518,12 @@ namespace sscs.cache //If validation succeeds,start persistence. if (desktopPasswd == null) { - baPasscode = CASACrypto.DecryptMasterPasscodeUsingString(mPasswd, GetPasscodeByMasterPasswdFilePath(), false); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.DecryptMasterPasscodeUsingString(mPasswd, GetPasscodeByMasterPasswdFilePath(), false, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { if (bIsStorePersistent == false) { - lss = new LocalStorage(this, baPasscode); + lss = new LocalStorage(this, baPasscode); ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); bIsStorePersistent = true; } @@ -528,11 +532,11 @@ namespace sscs.cache else { // try validation, if it fails, try decryption using the old method - baPasscode = CASACrypto.DecryptMasterPasscodeUsingString(mPasswd, GetPasscodeByMasterPasswdFilePath(), true); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.DecryptMasterPasscodeUsingString(mPasswd, GetPasscodeByMasterPasswdFilePath(), true, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { // rewrite file - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath(), user.UserIdentifier); if (bIsStorePersistent == false) { lss = new LocalStorage(this, baPasscode); @@ -549,13 +553,13 @@ namespace sscs.cache else { //There are 2 cases - either desktop passwd has changed //or it hasnt. - baPasscode = CASACrypto.GetMasterPasscodeUsingMasterPasswd(mPasswd, GetPasscodeByMasterPasswdFilePath(), false); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.GetMasterPasscodeUsingMasterPasswd(mPasswd, GetPasscodeByMasterPasswdFilePath(), false, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { RewriteDesktopPasswdFile(baPasscode, desktopPasswd); if (bIsStorePersistent == false) { - lss = new LocalStorage(this, baPasscode); + lss = new LocalStorage(this, baPasscode); ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); bIsStorePersistent = true; } @@ -563,13 +567,13 @@ namespace sscs.cache } else { - baPasscode = CASACrypto.GetMasterPasscodeUsingMasterPasswd(mPasswd, GetPasscodeByMasterPasswdFilePath(), true); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.GetMasterPasscodeUsingMasterPasswd(mPasswd, GetPasscodeByMasterPasswdFilePath(), true, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { RewriteDesktopPasswdFile(baPasscode, desktopPasswd); if (bIsStorePersistent == false) { - lss = new LocalStorage(this, baPasscode); + lss = new LocalStorage(this, baPasscode); ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath()); bIsStorePersistent = true; } @@ -592,7 +596,7 @@ namespace sscs.cache { try { - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath(), user.UserIdentifier); CSSSLogger.DbgLog("Re-encryted passcode with desktop passwd"); } catch (Exception e) @@ -606,20 +610,20 @@ namespace sscs.cache { try { - byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), false); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) - { + byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), false, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) + { ReEncryptPasscodeUsingRandomSalt(baPasscode, oldDesktopPasswd, GetPasscodeByDesktopFilePath()); return baPasscode; } else { // try old method - baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), true); - if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath())) + baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), true, user.UserIdentifier); + if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath(), user.UserIdentifier)) { // rewrite file now - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, oldDesktopPasswd, GetPasscodeByDesktopFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, oldDesktopPasswd, GetPasscodeByDesktopFilePath(), user.UserIdentifier); return baPasscode; } @@ -652,9 +656,9 @@ namespace sscs.cache //Create a new key and initialization vector. myRijndael.GenerateKey(); key = myRijndael.Key; - CASACrypto.StoreKeySetUsingMasterPasscode(key,IV,sMasterPasscode,GetKeyFilePath()); + CASACrypto.StoreKeySetUsingMasterPasscode(key,IV,sMasterPasscode,GetKeyFilePath(), user.UserIdentifier); //Store the master passcode encrypted with the desktopPasswd - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(sMasterPasscode, desktopPasswd, GetPasswdFilePath()); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(sMasterPasscode, desktopPasswd, GetPasswdFilePath(), user.UserIdentifier); lss = new LocalStorage(this,sMasterPasscode); bIsStorePersistent = true; bRet = true; @@ -857,11 +861,11 @@ namespace sscs.cache internal bool ChangeMasterPassword(string sCurrentPWD, string sNewPWD) { string sMasterFilePath = GetPasscodeByMasterPasswdFilePath(); - byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingMasterPasswd(sCurrentPWD, sMasterFilePath, false); + byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingMasterPasswd(sCurrentPWD, sMasterFilePath, false, user.UserIdentifier); if (baPasscode != null) { PauseFileWatcher(); - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, sNewPWD, sMasterFilePath); + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, sNewPWD, sMasterFilePath, user.UserIdentifier); ResumeFileWatcher(); return true; } @@ -907,6 +911,11 @@ namespace sscs.cache return user.GetUserName(); } + internal UserIdentifier GetUserIdentifier() + { + return user.UserIdentifier; + } + internal string GetPersistenceDirectory() { if (m_persistenceDirectory != null) @@ -917,53 +926,62 @@ namespace sscs.cache return null; } else - { - - string sUserHomeDir = GetUserHomeDirectory(); - if (sUserHomeDir != null) - { - - // the user might have set a different one - // load the policy file and check. - UIPol uiPolicy = (UIPol)ICASAPol.GetPolicy(CASAPolType.UI_POL, sUserHomeDir, GetUserName()); - if (uiPolicy != null) - { - string sDir = uiPolicy.GetConfigSetting(ConstStrings.CONFIG_PERSISTENT_DIRECTORY); - if ((sDir != null) && (sDir.Length > 0)) - { - m_persistenceDirectory = sDir; - return m_persistenceDirectory; - } - } - } - else - { - // user not logged in yet - return null; + { + + string sUserHomeDir = GetUserHomeDirectory(); + if (sUserHomeDir != null) + { + // the user might have set a different one + // load the policy file and check. + UIPol uiPolicy = (UIPol)ICASAPol.GetPolicy(CASAPolType.UI_POL, sUserHomeDir, GetUserName()); + if (uiPolicy != null) + { + string sDir = uiPolicy.GetConfigSetting(ConstStrings.CONFIG_PERSISTENT_DIRECTORY); + if ((sDir != null) && (sDir.Length > 0)) + { + m_persistenceDirectory = sDir; + if (IsDirectoryOwnedByUser(sDir)) + { + ChangeFileOwnershipForMiCasaFiles(sDir); + return m_persistenceDirectory; + } + else + { + CSSSLogger.log(true, "CASA Warning: " + GetUserName() + " has persistent directory set to " + sDir); + return null; + } + } + } + } + else + { + // user not logged in yet + return null; } } - m_persistenceDirectory = MigrateMiCasaFiles(); - return m_persistenceDirectory; + m_persistenceDirectory = MigrateMiCasaFiles(); + ChangeFileOwnershipForMiCasaFiles(null); + return m_persistenceDirectory; } internal string MigrateMiCasaFiles() - { + { string sSeperator = "/"; #if LINUX // for v1.7, we are storing MiCasa files in /home/.casa/[username] // let's migrate the files if needed string sNewPath = POLICY_DIRECTORY + "/" + user.GetUserName(); -#else - string sNewPath = GetUserHomeDirectory() + "\\CASA"; - - System.Diagnostics.Trace.WriteLine("Migrate files to " + sNewPath); - - if (!Directory.Exists(sNewPath)) - { - Directory.CreateDirectory(sNewPath); - } - +#else + string sNewPath = GetUserHomeDirectory() + "\\CASA"; + + System.Diagnostics.Trace.WriteLine("Migrate files to " + sNewPath); + + if (!Directory.Exists(sNewPath)) + { + Directory.CreateDirectory(sNewPath); + } + sSeperator = "\\"; #endif try @@ -991,6 +1009,48 @@ namespace sscs.cache return (sNewPath); } + internal void ChangeFileOwnershipForMiCasaFiles(string sDir) + { +#if LINUX + string sSeperator = "/"; + string sNewPath; + if (sDir != null) + { + sNewPath = sDir; + } + else + { + sNewPath = POLICY_DIRECTORY + "/" + user.GetUserName(); + } + + try + { + if (CSSSUtils.IsFileOwnedByRoot(sNewPath + sSeperator + ".miCASA")) + { + if(CSSSUtils.CompareSocketAndFileUserIds(sNewPath + sSeperator + ".miCASA", user.UserIdentifier)) + return; + else + { + String[] miCASAFiles = Directory.GetFiles(sNewPath, ".miCASA*"); + + if ((miCASAFiles != null) && (miCASAFiles.Length > 0)) + { + for (int i = 0; i < miCASAFiles.Length; i++) + { + string sFileName = miCASAFiles[i].Substring(miCASAFiles[i].LastIndexOf(sSeperator)); + CSSSUtils.SetSocketUserAsOwner(sNewPath + sFileName, user.UserIdentifier); + } + } + } + } + } + catch (Exception e) + { + CSSSLogger.DbgLog(e.ToString()); + } +#endif + } + internal bool SetPeristenceDirectory(string sNewDirectory) { if (Directory.Exists(sNewDirectory)) @@ -999,11 +1059,12 @@ namespace sscs.cache if (mpWatcher != null) { mpWatcher.pauseWatcher(); - mpWatcher = new MPFileWatcher(sNewDirectory, ConstStrings.MICASA_PASSCODE_BY_MASTERPASSWD_FILE); + mpWatcher = new MPFileWatcher(this, sNewDirectory, ConstStrings.MICASA_PASSCODE_BY_MASTERPASSWD_FILE); mpWatcher.resumeWatcher(); } m_persistenceDirectory = sNewDirectory; + ChangeFileOwnershipForMiCasaFiles(m_persistenceDirectory); return true; } @@ -1097,7 +1158,7 @@ namespace sscs.cache // encrypt if an encryptionstring was passed if ((sEncryptionString != null) && (sEncryptionString.Length > 0)) { - byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false, false); + byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false, false, user.UserIdentifier); // now encypt it. baSecrets = sscs.crypto.CASACrypto.EncryptData(baSecrets, baKey, ref baIV); @@ -1115,7 +1176,7 @@ namespace sscs.cache if (sEncryptionString != null) { // decrypt the buffer using the string passed in. - byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false, false); + byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false, false, user.UserIdentifier); byte[] baBuffer = sscs.crypto.CASACrypto.DecryptData(encryptedXmlSecrets, baKey, baIV); MergeXMLSecrets(baBuffer); } @@ -1127,14 +1188,14 @@ namespace sscs.cache String sXMLData = Encoding.ASCII.GetString(decryptedXmlSecrets); doc.LoadXml(sXMLData); LocalStorage.AddXMLSecretsToStore(this, doc); - } - - private void ReEncryptPasscodeUsingRandomSalt(byte[] baPasscode, string sPassword, string sFilepath) - { - if (!File.Exists(sFilepath + ".salt")) - { - CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, sPassword, sFilepath); - } + } + + private void ReEncryptPasscodeUsingRandomSalt(byte[] baPasscode, string sPassword, string sFilepath) + { + if (!File.Exists(sFilepath + ".salt")) + { + CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, sPassword, sFilepath, user.UserIdentifier); + } } internal void CreatePolicyDirectory() diff --git a/CASA/micasad/common/CSSSUtils.cs b/CASA/micasad/common/CSSSUtils.cs new file mode 100644 index 00000000..768dacf1 --- /dev/null +++ b/CASA/micasad/common/CSSSUtils.cs @@ -0,0 +1,162 @@ +/*********************************************************************** + * + * Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + ***********************************************************************/ + +using System; +using System.IO; +using System.Text; +#if LINUX +using Mono.Unix; +using Mono.Unix.Native; +#endif +using sscs.common; +using sscs.constants; + +namespace sscs.common +{ + class CSSSUtils + { + public static bool IsFileOwnedByRoot(string filePath) + { +#if LINUX + try + { + int retVal = -1; + int fd = -1; + Stat fStatus; + + fd = Syscall.open(filePath, OpenFlags.O_NOFOLLOW); + + retVal = Syscall.fstat(fd, out fStatus); + if ( retVal < 0 ) + { + CSSSLogger.DbgLog("fstat() failed..."); + return false; + } + + if(fStatus.st_uid != 0) + { + CSSSLogger.DbgLog("File not owned by root: {0}"); + return false; + } + + retVal = Syscall.close(fd); + if ( retVal < 0 ) + { + CSSSLogger.DbgLog("close() failed..."); + return false; + } + return true; + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Failed while checking whether the file is owned by root or not"); + } + return false; +#else + return true; +#endif + } + + + public static bool SetSocketUserAsOwner(string filePath, UserIdentifier userID) + { +#if LINUX + try + { + int retVal = -1; + int fd = -1; + + fd = Syscall.open(filePath, OpenFlags.O_NOFOLLOW); + + UnixUserInfo uui = new UnixUserInfo(userID.GetUID()); + + retVal = Syscall.fchown(fd, (uint) uui.UserId, (uint) uui.GroupId); + if ( retVal < 0 ) + { + CSSSLogger.DbgLog("fchown() failed..."); + return false; + } + + retVal = Syscall.close(fd); + if ( retVal < 0 ) + { + CSSSLogger.DbgLog("close() failed..."); + return false; + } + return true; + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Unable to set the owner of the file to the socket user"); + } + return false; +#else + return true; +#endif + } + + + public static bool CompareSocketAndFileUserIds(string filePath, UserIdentifier userID) + { +#if LINUX + try + { + int retVal = -1; + int fd = -1; + Stat fStatus; + + fd = Syscall.open(filePath, OpenFlags.O_NOFOLLOW); + + retVal = Syscall.fstat(fd, out fStatus); + if ( retVal < 0 ) + { + CSSSLogger.DbgLog("fstat() failed..."); + return false; + } + + if(fStatus.st_uid != userID.GetUID()) + { + return false; + } + + retVal = Syscall.close(fd); + if ( retVal < 0 ) + { + CSSSLogger.DbgLog("close() failed..."); + return false; + } + return true; + } + catch(Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Failed during the comparision of the user ids on the file and socket"); + } + return false; +#else + return true; +#endif + } + } +} diff --git a/CASA/micasad/lss/CASACrypto.cs b/CASA/micasad/lss/CASACrypto.cs index efa243d1..605188dd 100644 --- a/CASA/micasad/lss/CASACrypto.cs +++ b/CASA/micasad/lss/CASACrypto.cs @@ -26,6 +26,7 @@ using System.Text; using System.Security.Cryptography; #if LINUX using Mono.Unix; +using Mono.Unix.Native; #endif using sscs.common; using sscs.constants; @@ -40,12 +41,12 @@ namespace sscs.crypto private const int HASH_SIZE = 32; private const uint MAX_FILE_SIZE = 16 * 1024 * 1024; //16 MB - internal static byte[] Generate16ByteKeyFromString(string sTheString, string sFilepath, bool bUseOldMethod, bool bGenerateRandomSalt) + internal static byte[] Generate16ByteKeyFromString(string sTheString, string sFilepath, bool bUseOldMethod, bool bGenerateRandomSalt, UserIdentifier userID) { byte[] baKey = new byte[16]; //return value try { - Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes(sTheString, SALTSIZE, ITERATION_COUNT, bUseOldMethod, sFilepath, bGenerateRandomSalt); + Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes(sTheString, SALTSIZE, ITERATION_COUNT, bUseOldMethod, sFilepath, bGenerateRandomSalt, userID); baKey = pkcs5.GetBytes(16); } catch(Exception e) @@ -58,7 +59,7 @@ namespace sscs.crypto } internal static bool StoreKeySetUsingMasterPasscode(byte[] key, - byte[] IV, byte[] baMasterPasscode, string fileName) + byte[] IV, byte[] baMasterPasscode, string fileName, UserIdentifier userID) { bool bRet = false; FileStream fsEncrypt = null; @@ -69,7 +70,7 @@ namespace sscs.crypto //Get an encryptor. RijndaelManaged myRijndael = new RijndaelManaged(); ICryptoTransform encryptor; - encryptor = myRijndael.CreateEncryptor(baMasterPasscode, GenerateAndSaveIV(fileName, myRijndael)); + encryptor = myRijndael.CreateEncryptor(baMasterPasscode, GenerateAndSaveIV(fileName, myRijndael, userID)); //Encrypt the data to a file fsEncrypt = new FileStream(fileName, FileMode.Create); @@ -88,6 +89,15 @@ namespace sscs.crypto //Write all data to the crypto stream and flush it. csEncrypt.Write(key, 0, key.Length); csEncrypt.FlushFinalBlock(); + + csEncrypt.Close(); + fsEncrypt.Close(); + + if (!CSSSUtils.SetSocketUserAsOwner(fileName, userID)) + { + CSSSLogger.DbgLog("Unable to set the owner of the key file to the socket user"); + } + bRet = true; } catch(Exception e) @@ -100,11 +110,12 @@ namespace sscs.crypto csEncrypt.Close(); if( fsEncrypt != null ) fsEncrypt.Close(); + return bRet; } internal static byte[] GetKeySetFromFile(byte[] baMasterPasscode, - string fileName ) + string fileName, UserIdentifier userID ) { byte[] baSavedKey = null; FileStream fsDecrypt = null; @@ -114,7 +125,7 @@ namespace sscs.crypto { #if LINUX UnixFileInfo fsTest = new UnixFileInfo (fileName); - if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink) + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(fileName, userID)) #else if(!File.Exists(fileName)) #endif @@ -127,7 +138,7 @@ namespace sscs.crypto */ RijndaelManaged myRijndael = new RijndaelManaged(); - ICryptoTransform decryptor = myRijndael.CreateDecryptor(baMasterPasscode, RetrieveIV(fileName, baMasterPasscode)); + ICryptoTransform decryptor = myRijndael.CreateDecryptor(baMasterPasscode, RetrieveIV(fileName, baMasterPasscode, userID)); //Now decrypt fsDecrypt = new FileStream(fileName, FileMode.Open); @@ -181,7 +192,7 @@ namespace sscs.crypto { //Get an decryptor. RijndaelManaged myRijndael = new RijndaelManaged(); - ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, baIV); + ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, baIV); csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); //Read all data to the crypto stream and flush it. @@ -233,7 +244,7 @@ namespace sscs.crypto internal static void EncryptDataAndWriteToFile(byte[] xmlData, - byte[] key, string fileName) + byte[] key, string fileName, UserIdentifier userID) { FileStream fsEncrypt = null; CryptoStream csEncrypt = null; @@ -241,7 +252,7 @@ namespace sscs.crypto { //Get an encryptor. RijndaelManaged myRijndael = new RijndaelManaged(); - byte[] baIV = GenerateAndSaveIV(fileName, myRijndael); + byte[] baIV = GenerateAndSaveIV(fileName, myRijndael, userID); ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, baIV); @@ -249,8 +260,8 @@ namespace sscs.crypto //Encrypt the data to a file fsEncrypt = new FileStream(fileName, FileMode.Create); - // make hidden - File.SetAttributes(fileName, FileAttributes.Hidden); + // make hidden + File.SetAttributes(fileName, FileAttributes.Hidden); SHA256 sha = new SHA256Managed(); @@ -266,15 +277,21 @@ namespace sscs.crypto fsClear.Write(dup, 0, dup.Length); fsClear.Flush(); fsClear.Close(); + CSSSUtils.SetSocketUserAsOwner(fileName + ".xml", userID); #endif - csEncrypt = new CryptoStream(fsEncrypt, encryptor, CryptoStreamMode.Write); //Write all data to the crypto stream and flush it. csEncrypt.Write(xmlData, 0, xmlData.Length); csEncrypt.FlushFinalBlock(); + csEncrypt.Close(); + fsEncrypt.Close(); + + if (!CSSSUtils.SetSocketUserAsOwner(fileName, userID)) { + CSSSLogger.DbgLog("Unable to set the owner of the encrypted file to the socket user"); + } } catch(Exception e) { @@ -287,7 +304,7 @@ namespace sscs.crypto fsEncrypt.Close(); } - internal static void ComputeHashAndWriteToFile(byte[] baPasscode, string fileName) + internal static void ComputeHashAndWriteToFile(byte[] baPasscode, string fileName, UserIdentifier userID) { FileStream fsHash = null; @@ -295,14 +312,21 @@ namespace sscs.crypto try { - SHA256 shaM = new SHA256Managed(); - hash = shaM.ComputeHash(baPasscode); + SHA256 shaM = new SHA256Managed(); + hash = shaM.ComputeHash(baPasscode); - fsHash = new FileStream(fileName, FileMode.Create); - File.SetAttributes(fileName, FileAttributes.Hidden); + fsHash = new FileStream(fileName, FileMode.Create); + File.SetAttributes(fileName, FileAttributes.Hidden); - fsHash.Write(hash, 0, hash.Length); - fsHash.Flush(); + fsHash.Write(hash, 0, hash.Length); + fsHash.Flush(); + + fsHash.Close(); + + if (!CSSSUtils.SetSocketUserAsOwner(fileName, userID)) + { + CSSSLogger.DbgLog("Unable to set the owner of the hash file to the socket user"); + } } catch(Exception e) { @@ -315,7 +339,7 @@ namespace sscs.crypto } internal static byte[] ReadFileAndDecryptData(byte[] key, - string fileName) + string fileName, UserIdentifier userID) { FileStream fsDecrypt = null; CryptoStream csDecrypt = null; @@ -328,16 +352,16 @@ namespace sscs.crypto //Get a decryptor that uses the same key and IV as the encryptor. RijndaelManaged myRijndael = new RijndaelManaged(); - byte[] baIV = RetrieveIV(fileName, IV); + byte[] baIV = RetrieveIV(fileName, IV, userID); ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, baIV); #if LINUX - UnixFileInfo fsTest = new UnixFileInfo (fileName); - if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink) + UnixFileInfo fsTest = new UnixFileInfo (fileName); + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(fileName, userID)) #else - if(!File.Exists(fileName)) + if(!File.Exists(fileName)) #endif - { + { return null; } @@ -347,23 +371,23 @@ namespace sscs.crypto fsDecrypt.Read(storedHash,0,storedHash.Length); csDecrypt = new CryptoStream(fsDecrypt, decryptor, CryptoStreamMode.Read); - if(fsDecrypt.Length < HASH_SIZE ) - { - csDecrypt.Close(); - fsDecrypt.Close(); - return null; - } + if(fsDecrypt.Length < HASH_SIZE ) + { + csDecrypt.Close(); + fsDecrypt.Close(); + return null; + } - if(fsDecrypt.Length > MAX_FILE_SIZE ) - { - CSSSLogger.DbgLog("Size of the secret file exceeded the maximum allowed."); - csDecrypt.Close(); - fsDecrypt.Close(); - return null; - } + if(fsDecrypt.Length > MAX_FILE_SIZE ) + { + CSSSLogger.DbgLog("Size of the secret file exceeded the maximum allowed."); + csDecrypt.Close(); + fsDecrypt.Close(); + return null; + } - ulong fileLen = (ulong)(fsDecrypt.Length - HASH_SIZE); - byte[] fromEncrypt = new byte[fileLen]; + ulong fileLen = (ulong)(fsDecrypt.Length - HASH_SIZE); + byte[] fromEncrypt = new byte[fileLen]; //Read the data out of the crypto stream. int bytesRead = csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length); @@ -407,24 +431,24 @@ namespace sscs.crypto if (csDecrypt != null) { - try - { - csDecrypt.Close(); - } - catch - { - } + try + { + csDecrypt.Close(); + } + catch + { + } } if( fsDecrypt != null ) { - try - { - fsDecrypt.Close(); - } - catch - { - } + try + { + fsDecrypt.Close(); + } + catch + { + } } return null; } @@ -508,9 +532,9 @@ namespace sscs.crypto return (File.Exists(fileName)); } - internal static byte[] GetMasterPasscode(string desktopPasswd, string fileName) + internal static byte[] GetMasterPasscode(string desktopPasswd, string fileName, UserIdentifier userID) { - byte[] mp = DecryptMasterPasscodeUsingString(desktopPasswd, fileName, false); + byte[] mp = DecryptMasterPasscodeUsingString(desktopPasswd, fileName, false, userID); return mp; } @@ -523,24 +547,25 @@ namespace sscs.crypto internal static void EncryptAndStoreMasterPasscodeUsingString( byte[] baMasterPasscode, string passwd, - string fileName) + string fileName, + UserIdentifier userID) { FileStream fsEncrypt = null; CryptoStream csEncrypt = null; try { if(File.Exists(fileName)) - File.Delete(fileName); - - byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, false, true); + File.Delete(fileName); + + byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, false, true, userID); //Get an encryptor. RijndaelManaged myRijndael = new RijndaelManaged(); - ICryptoTransform encryptor; - - encryptor = myRijndael.CreateEncryptor(baKey, GenerateAndSaveIV(fileName, myRijndael)); + ICryptoTransform encryptor; + + encryptor = myRijndael.CreateEncryptor(baKey, GenerateAndSaveIV(fileName, myRijndael, userID)); - //Encrypt the data to a file + //Encrypt the data to a file fsEncrypt = new FileStream(fileName,FileMode.Create); csEncrypt = new CryptoStream(fsEncrypt, encryptor, @@ -552,9 +577,13 @@ namespace sscs.crypto csEncrypt.Close(); fsEncrypt.Close(); - // make hidden - File.SetAttributes(fileName, FileAttributes.Hidden); + // make hidden + File.SetAttributes(fileName, FileAttributes.Hidden); + if (!CSSSUtils.SetSocketUserAsOwner(fileName, userID)) + { + CSSSLogger.DbgLog("Unable to set the owner of the MPC file to the socket user"); + } } catch(Exception e) { @@ -568,11 +597,10 @@ namespace sscs.crypto { fsEncrypt.Close(); } - } public static byte[] DecryptMasterPasscodeUsingString(string passwd, - string fileName, bool bTryOldMethod) + string fileName, bool bTryOldMethod, UserIdentifier userID) { FileStream fsDecrypt = null; CryptoStream csDecrypt = null; @@ -580,27 +608,26 @@ namespace sscs.crypto try { - byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, bTryOldMethod, false); + byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, bTryOldMethod, false, userID); /* Get a decryptor that uses the same key and * IV as the encryptor. */ RijndaelManaged myRijndael = new RijndaelManaged(); - ICryptoTransform decryptor = myRijndael.CreateDecryptor(baKey, RetrieveIV(fileName, baKey)); + ICryptoTransform decryptor = myRijndael.CreateDecryptor(baKey, RetrieveIV(fileName, baKey, userID)); //Now decrypt #if LINUX - UnixFileInfo fsTest = new UnixFileInfo (fileName); - if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink) + UnixFileInfo fsTest = new UnixFileInfo (fileName); + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(fileName, userID)) #else - if (!File.Exists(fileName)) + if (!File.Exists(fileName)) #endif { return null; } fsDecrypt = new FileStream(fileName, FileMode.Open); - csDecrypt = new CryptoStream(fsDecrypt, decryptor, - CryptoStreamMode.Read); + csDecrypt = new CryptoStream(fsDecrypt, decryptor, CryptoStreamMode.Read); baSavedMasterPasscode = new byte[16]; //Read the data out of the crypto stream. @@ -633,7 +660,8 @@ namespace sscs.crypto internal static byte[] GetMasterPasscodeUsingMasterPasswd( string mPasswd, string fileName, - bool bUseOldMethod) + bool bUseOldMethod, + UserIdentifier userID) { byte[] baMasterPasscode; try @@ -643,7 +671,7 @@ namespace sscs.crypto /* Decrypt the passcode from the file using master passwd. * and return the decrypted passcode. */ - baMasterPasscode = DecryptMasterPasscodeUsingString(mPasswd, fileName, bUseOldMethod); + baMasterPasscode = DecryptMasterPasscodeUsingString(mPasswd, fileName, bUseOldMethod, userID); return baMasterPasscode; } else @@ -660,7 +688,8 @@ namespace sscs.crypto internal static byte[] GetMasterPasscodeUsingDesktopPasswd( string desktopPasswd, string fileName, - bool bUseOldMethod) + bool bUseOldMethod, + UserIdentifier userID) { byte[] passcode; try @@ -671,7 +700,7 @@ namespace sscs.crypto * and return the decrypted passcode. */ passcode = DecryptMasterPasscodeUsingString(desktopPasswd, - fileName, bUseOldMethod); + fileName, bUseOldMethod, userID); return passcode; } @@ -689,12 +718,13 @@ namespace sscs.crypto internal static byte[] GetServerMasterPasscodeUsingMasterPasswd( string mPasswd, string fileName, - bool bUseOldMethod) + bool bUseOldMethod, + UserIdentifier userID) { - return GetMasterPasscodeUsingMasterPasswd ( mPasswd, fileName, bUseOldMethod); + return GetMasterPasscodeUsingMasterPasswd ( mPasswd, fileName, bUseOldMethod, userID); } - internal static byte[] GetServerMasterPasscodeUsingSystemKey(string fileName) + internal static byte[] GetServerMasterPasscodeUsingSystemKey(string fileName, UserIdentifier userID) { byte[] baSavedMasterPasscode = null; @@ -702,7 +732,7 @@ namespace sscs.crypto { #if LINUX UnixFileInfo fsTest = new UnixFileInfo (fileName); - if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink) + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(fileName, userID)) #else if (!File.Exists(fileName)) #endif @@ -716,7 +746,7 @@ namespace sscs.crypto fs.Close(); baSavedMasterPasscode = new byte[16]; - baSavedMasterPasscode = ProtectedData.Unprotect( encryptedMasterPasscode, RetrieveIV(fileName, new byte[16]), DataProtectionScope.CurrentUser ); + baSavedMasterPasscode = ProtectedData.Unprotect( encryptedMasterPasscode, RetrieveIV(fileName, new byte[16], userID), DataProtectionScope.CurrentUser ); } catch (CryptographicException e) { @@ -732,7 +762,7 @@ namespace sscs.crypto string desktopPasswd, string fileName, string validationFile, - UserIdentifier userId + UserIdentifier userID ) { try @@ -747,9 +777,9 @@ namespace sscs.crypto EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, - fileName); - - ComputeHashAndWriteToFile(baPasscode, validationFile + "Hash"); //Hash of MPC is written to ".miCASAValidateHash" file + fileName, + userID); + ComputeHashAndWriteToFile(baPasscode, validationFile + "Hash", userID); //Hash of MPC is written to ".miCASAValidateHash" file return baPasscode; } catch(Exception e) @@ -762,7 +792,8 @@ namespace sscs.crypto internal static byte[] GenerateServerMasterPasscode( string fileName, - string validationFile + string validationFile, + UserIdentifier userID ) { byte[] baPasscode = null; @@ -775,14 +806,18 @@ namespace sscs.crypto myRijndael.GenerateKey(); baPasscode = myRijndael.Key; - byte [] encryptedMasterPasscode = ProtectedData.Protect( baPasscode, GenerateAndSaveIV(fileName, null), DataProtectionScope.CurrentUser ); + byte [] encryptedMasterPasscode = ProtectedData.Protect( baPasscode, GenerateAndSaveIV(fileName, null, userID), DataProtectionScope.CurrentUser ); FileStream fs = new FileStream(fileName, FileMode.Create); File.SetAttributes(fileName, FileAttributes.Hidden); fs.Write(encryptedMasterPasscode, 0, encryptedMasterPasscode.Length); fs.Flush(); fs.Close(); - ComputeHashAndWriteToFile(baPasscode, validationFile + "Hash"); //Hash of MPC is written to ".miCASASrvValidateHash" file + if (!CSSSUtils.SetSocketUserAsOwner(fileName, userID)) + { + CSSSLogger.DbgLog("Unable to set the owner of the server MPC file to the socket user"); + } + ComputeHashAndWriteToFile(baPasscode, validationFile + "Hash", userID); //Hash of MPC is written to ".miCASASrvValidateHash" file } catch(Exception e) @@ -794,14 +829,14 @@ namespace sscs.crypto return baPasscode; } - public static bool CompareHashes(byte[] baPasscode, string fileName) + public static bool CompareHashes(byte[] baPasscode, string fileName, UserIdentifier userID) { FileStream fsHash = null; try { #if LINUX UnixFileInfo fsTest = new UnixFileInfo (fileName); - if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink) + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(fileName, userID)) #else if (!File.Exists(fileName)) #endif @@ -840,7 +875,7 @@ namespace sscs.crypto return false; } - public static bool ValidatePasscode(byte[] baPasscode, string fileName) + public static bool ValidatePasscode(byte[] baPasscode, string fileName, UserIdentifier userID) { /* Here we decrpyt a well known string, throw exception * if not successful @@ -854,7 +889,7 @@ namespace sscs.crypto try { - if(CompareHashes(baPasscode, fileName + "Hash")) + if(CompareHashes(baPasscode, fileName + "Hash", userID)) { CSSSLogger.DbgLog("Using the hash of MPC for validating the MPC"); return true; @@ -862,7 +897,7 @@ namespace sscs.crypto else { CSSSLogger.DbgLog("Using the validation string encrypted with MPC for validating the MPC"); - byte[] baString = ReadFileAndDecryptData(baPasscode, fileName); + byte[] baString = ReadFileAndDecryptData(baPasscode, fileName, userID); string sString = Encoding.Default.GetString(baString); char[] trimChars = {'\0'}; sString = sString.TrimEnd(trimChars); @@ -880,27 +915,27 @@ namespace sscs.crypto } catch(Exception e) { - CSSSLogger.ExpLog(e.ToString()); - CSSSLogger.DbgLog("Validation of passcode failed."); - } - return false; - } + CSSSLogger.ExpLog(e.ToString()); + CSSSLogger.DbgLog("Validation of passcode failed."); + } + return false; + } - private static byte[] GenerateAndSaveIV(string sFileName, RijndaelManaged theRiManaged) + private static byte[] GenerateAndSaveIV(string sFileName, RijndaelManaged theRiManaged, UserIdentifier userID) { byte[] baIV = null; - if ( theRiManaged != null ) - { - theRiManaged.GenerateIV(); - baIV = theRiManaged.IV; - } - else - { - RandomNumberGenerator rng = RandomNumberGenerator.Create (); - baIV = new byte [16]; - rng.GetBytes (baIV); - } + if ( theRiManaged != null ) + { + theRiManaged.GenerateIV(); + baIV = theRiManaged.IV; + } + else + { + RandomNumberGenerator rng = RandomNumberGenerator.Create (); + baIV = new byte [16]; + rng.GetBytes (baIV); + } try { @@ -911,6 +946,11 @@ namespace sscs.crypto fs.Close(); File.SetAttributes(sFileName + ".IV", FileAttributes.Hidden); + + if (!CSSSUtils.SetSocketUserAsOwner(sFileName + ".IV", userID)) + { + CSSSLogger.DbgLog("Unable to set the owner of the IV file to the socket user"); + } } catch (Exception e) { @@ -920,13 +960,23 @@ namespace sscs.crypto return baIV; } - private static byte[] RetrieveIV(string sFileName, byte[] baOrigValue) + private static byte[] RetrieveIV(string sFileName, byte[] baOrigValue, UserIdentifier userID) { byte[] IV = new byte[16]; // check for file existence try { +#if LINUX + UnixFileInfo fsTest = new UnixFileInfo (sFileName + ".IV"); + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(sFileName + ".IV", userID)) +#else + if (!File.Exists(sFileName + ".IV")) +#endif + { + return null; + } + FileStream fs = new FileStream(sFileName + ".IV", FileMode.Open); fs.Read(IV, 0, 16); fs.Close(); diff --git a/CASA/micasad/lss/LocalStorage.cs b/CASA/micasad/lss/LocalStorage.cs index 40387dc1..a7b14ac3 100644 --- a/CASA/micasad/lss/LocalStorage.cs +++ b/CASA/micasad/lss/LocalStorage.cs @@ -18,28 +18,28 @@ * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * - ***********************************************************************/ - -using System; -using System.IO; -using System.Text; -using System.Collections; -using System.Threading; -using System.Security.Cryptography; -using System.Xml; + ***********************************************************************/ + +using System; +using System.IO; +using System.Text; +using System.Collections; +using System.Threading; +using System.Security.Cryptography; +using System.Xml; #if LINUX using Mono.Unix.Native; -#endif -using sscs.cache; -using sscs.crypto; -using sscs.common; -using sscs.constants; -using Novell.CASA.MiCasa.Common; -using Novell.CASA.CASAPolicy; - -namespace sscs.lss -{ - /// +#endif +using sscs.cache; +using sscs.crypto; +using sscs.common; +using sscs.constants; +using Novell.CASA.MiCasa.Common; +using Novell.CASA.CASAPolicy; + +namespace sscs.lss +{ + /// /* * This class is a service to store data persistently. * How it does this is determined by implementation within the @@ -51,809 +51,738 @@ namespace sscs.lss * 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. - */ - - /// - 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 Thread sPersistThread = null; - + */ + + /// + 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 Thread sPersistThread = null; + #if LINUX Mono.Unix.UnixFileSystemInfo sockFileInfo; Mono.Unix.UnixUserInfo sockFileOwner; -#endif - - private static string LINUXID = "Unix"; - - internal LocalStorage(SecretStore store, byte[] baMasterPasscode, bool dummy) - { - userStore = store; - m_baGeneratedKey = baMasterPasscode; - LoadPersistentStore(ConstStrings.SSCS_SERVER_KEY_CHAIN_ID); - //userStore.DumpSecretstore(); - } - - internal LocalStorage(SecretStore store, byte[] baMasterPasscode) - { - userStore = store; - m_baGeneratedKey = baMasterPasscode; - LoadPersistentStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); - userStore.DumpSecretstore(); - } - - ~LocalStorage() - { - if (persistThread != null) - { - persistThread.Abort(); - persistThread.Join(); - } - - if (sPersistThread != null) - { - sPersistThread.Abort(); - sPersistThread.Join(); - } - } - - // allowing a user to choose the storage location is not approved yet - private LocalStorage(SecretStore store, - byte[] baMasterPasscode, string sStorageDirectory) - { - userStore = store; - m_baGeneratedKey = baMasterPasscode; - LoadPersistentStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); - userStore.DumpSecretstore(); - } - - private void StorePersistentData(string sDataID, byte[] baData) - { - - } - - private byte[] RetrievePersistentData(string sDataID) - { - - - return null; - } - - public void PersistStoreWithDelay() - { - if (persistThread == null) - { - persistThread = new Thread(new ThreadStart(PersistStoreDelayThreadFn)); - persistThread.Start(); - } - } - - public void PersistServerStoreWithDelay() - { - if (sPersistThread == null) - { - sPersistThread = new Thread(new ThreadStart(PersistServerStoreDelayThreadFn)); - sPersistThread.Start(); - } - } - - public bool StopPersistence() - { - if (persistThread != null) - { - persistThread.Abort(); - persistThread.Join(); - } - return true; - } - - public bool StopServerPersistence() - { - if (sPersistThread != null) - { - sPersistThread.Abort(); - sPersistThread.Join(); - } - return true; - } - - public bool IsOwnedByRoot(string fileName) - { -#if LINUX - sockFileInfo = new Mono.Unix.UnixFileInfo(fileName); - sockFileOwner = sockFileInfo.OwnerUser; - if(0==sockFileOwner.UserId) - return true; +#endif + + private static string LINUXID = "Unix"; + + internal LocalStorage(SecretStore store, byte[] baMasterPasscode, bool dummy) + { + userStore = store; + m_baGeneratedKey = baMasterPasscode; + LoadPersistentStore(ConstStrings.SSCS_SERVER_KEY_CHAIN_ID); + //userStore.DumpSecretstore(); + } + + internal LocalStorage(SecretStore store, byte[] baMasterPasscode) + { + userStore = store; + m_baGeneratedKey = baMasterPasscode; + LoadPersistentStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); + userStore.DumpSecretstore(); + } + + ~LocalStorage() + { + if (persistThread != null) + { + persistThread.Abort(); + persistThread.Join(); + } + + if (sPersistThread != null) + { + sPersistThread.Abort(); + sPersistThread.Join(); + } + } + + // allowing a user to choose the storage location is not approved yet + private LocalStorage(SecretStore store, + byte[] baMasterPasscode, string sStorageDirectory) + { + userStore = store; + m_baGeneratedKey = baMasterPasscode; + LoadPersistentStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); + userStore.DumpSecretstore(); + } + + private void StorePersistentData(string sDataID, byte[] baData) + { + + } + + private byte[] RetrievePersistentData(string sDataID) + { + + + return null; + } + + public void PersistStoreWithDelay() + { + if (persistThread == null) + { + persistThread = new Thread(new ThreadStart(PersistStoreDelayThreadFn)); + persistThread.Start(); + } + } + + public void PersistServerStoreWithDelay() + { + if (sPersistThread == null) + { + sPersistThread = new Thread(new ThreadStart(PersistServerStoreDelayThreadFn)); + sPersistThread.Start(); + } + } + + public bool StopPersistence() + { + if (persistThread != null) + { + persistThread.Abort(); + persistThread.Join(); + } + return true; + } + + public bool StopServerPersistence() + { + if (sPersistThread != null) + { + sPersistThread.Abort(); + sPersistThread.Join(); + } + return true; + } + + private string GetDecryptedServerSecretsXml() + { + try + { + string fileName = userStore.GetServerSecretsPersistenceFilePath(); + string tempFile = fileName; + if (!File.Exists(fileName)) + { + // check for tmp file + if (File.Exists(tempFile + ".tmp")) + { + File.Move(tempFile + ".tmp", fileName); + File.Delete(tempFile + ".tmp"); + } else - return false; -#else - return true; -#endif - } - - private string GetDecryptedServerSecretsXml() - { - try - { - string fileName = userStore.GetServerSecretsPersistenceFilePath(); - string tempFile = fileName; - int count = 0; - if (!File.Exists(fileName)) - { - while (true) - { - // check for tmp file - if (File.Exists(tempFile + ".tmp")) - { - if (IsOwnedByRoot(tempFile + ".tmp")) - { - File.Move(tempFile + ".tmp", fileName); - break; - } - else - { - count++; - tempFile = fileName + count.ToString(); - } - } - else - return null; - - } - - // delete tmp file if there - if (File.Exists(tempFile + ".tmp")) - { - if (IsOwnedByRoot(tempFile + ".tmp")) - File.Delete(tempFile + ".tmp"); - } - } - - byte[] baPasscode = null; - if (null != m_baGeneratedKey) - baPasscode = m_baGeneratedKey; - else - baPasscode = CASACrypto.GetServerMasterPasscodeUsingSystemKey(userStore.GetServerPasscodeBySystemKeyFilePath()); - - if (null == baPasscode) - return null; - - byte[] key = CASACrypto.GetKeySetFromFile(baPasscode, userStore.GetServerKeyFilePath()); - if (null == key) - return null; - - byte[] decryptedBuffer = CASACrypto.ReadFileAndDecryptData(key, fileName); - - 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; - } - - private string GetDecryptedXml() - { - try - { - string fileName = userStore.GetPersistenceFilePath(); - string tempFile = fileName; - int count = 0; - if (!File.Exists(fileName)) - { - while (true) - { - // check for tmp file - if (File.Exists(tempFile + ".tmp")) - { - if (IsOwnedByRoot(tempFile + ".tmp")) - { - File.Move(tempFile + ".tmp", fileName); - break; - } - else - { - count++; - tempFile = fileName + count.ToString(); - } - } - else - return null; - - } - - // delete tmp file if there - if (File.Exists(tempFile + ".tmp")) - { - if (IsOwnedByRoot(tempFile + ".tmp")) - File.Delete(tempFile + ".tmp"); - } - } - - byte[] baPasscode = null; - if (null != m_baGeneratedKey) - baPasscode = m_baGeneratedKey; - else - baPasscode = CASACrypto.GetMasterPasscode(userStore.GetDesktopPasswd(), userStore.GetPasscodeByDesktopFilePath()); - - if (null == baPasscode) - return null; - - byte[] key = CASACrypto.GetKeySetFromFile(baPasscode, userStore.GetKeyFilePath()); - if (null == key) - return null; - - byte[] decryptedBuffer = CASACrypto.ReadFileAndDecryptData(key, fileName); - - 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; - } - + return null; + } + + byte[] baPasscode = null; + if (null != m_baGeneratedKey) + baPasscode = m_baGeneratedKey; + else + baPasscode = CASACrypto.GetServerMasterPasscodeUsingSystemKey(userStore.GetServerPasscodeBySystemKeyFilePath(), userStore.GetUserIdentifier()); + + if (null == baPasscode) + return null; + + byte[] key = CASACrypto.GetKeySetFromFile(baPasscode, userStore.GetServerKeyFilePath(), userStore.GetUserIdentifier()); + if (null == key) + return null; + + byte[] decryptedBuffer = CASACrypto.ReadFileAndDecryptData(key, fileName, userStore.GetUserIdentifier()); + + 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; + } + + private string GetDecryptedXml() + { + try + { + string fileName = userStore.GetPersistenceFilePath(); + string tempFile = fileName; + if (!File.Exists(fileName)) + { + // check for tmp file + if (File.Exists(tempFile + ".tmp")) + { + File.Move(tempFile + ".tmp", fileName); + File.Delete(tempFile + ".tmp"); + } + else + return null; + } + + byte[] baPasscode = null; + if (null != m_baGeneratedKey) + baPasscode = m_baGeneratedKey; + else + baPasscode = CASACrypto.GetMasterPasscode(userStore.GetDesktopPasswd(), userStore.GetPasscodeByDesktopFilePath(), userStore.GetUserIdentifier()); + + if (null == baPasscode) + return null; + + byte[] key = CASACrypto.GetKeySetFromFile(baPasscode, userStore.GetKeyFilePath(), userStore.GetUserIdentifier()); + if (null == key) + return null; + + byte[] decryptedBuffer = CASACrypto.ReadFileAndDecryptData(key, fileName, userStore.GetUserIdentifier()); + + 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(string keyChainId) - { - try - { - //string xpath = ""; - XmlDocument doc = new XmlDocument(); - - string xmlToLoad = null; - if (keyChainId == ConstStrings.SSCS_SESSION_KEY_CHAIN_ID) - xmlToLoad = GetDecryptedXml(); - else if (keyChainId == ConstStrings.SSCS_SERVER_KEY_CHAIN_ID) - xmlToLoad = GetDecryptedServerSecretsXml(); - - if (xmlToLoad != null) - { - doc.LoadXml(xmlToLoad); - + */ + private bool LoadPersistentStore(string keyChainId) + { + try + { + //string xpath = ""; + XmlDocument doc = new XmlDocument(); + + string xmlToLoad = null; + if (keyChainId == ConstStrings.SSCS_SESSION_KEY_CHAIN_ID) + xmlToLoad = GetDecryptedXml(); + else if (keyChainId == ConstStrings.SSCS_SERVER_KEY_CHAIN_ID) + xmlToLoad = GetDecryptedServerSecretsXml(); + + if (xmlToLoad != null) + { + doc.LoadXml(xmlToLoad); + #if false XmlTextWriter writer = new XmlTextWriter("d:/persist.xml",null); writer.Formatting = Formatting.Indented; doc.Save(writer); writer.Close(); -#endif - } - else - { - return false; - } - - // add these to the store - AddXMLSecretsToStore(userStore, doc); - } - catch (Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - } - - // collect now to remove old data from memory - GC.Collect(); - - return true; - } - - internal static void AddXMLSecretsToStore(SecretStore userStore, XmlDocument doc) - { - // get the conflict keychain - KeyChain kcConflict; - if (!userStore.CheckIfKeyChainExists(ConstStrings.SSCS_CONFLICT_KEYCHAIN + '\0')) - { - kcConflict = new KeyChain(ConstStrings.SSCS_CONFLICT_KEYCHAIN + '\0'); - userStore.AddKeyChain(kcConflict); - } - else - { - kcConflict = userStore.GetKeyChain(ConstStrings.SSCS_CONFLICT_KEYCHAIN + '\0'); - } - - 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); - - // set the created time if possible - XmlNode timeNode = node.SelectSingleNode("descendant::" + XmlConsts.timeNode); - if (timeNode != null) - { - XmlAttributeCollection timeAttribCol = timeNode.Attributes; - if (timeAttribCol != null) - { - XmlNode createdTimeNode = timeAttribCol.GetNamedItem(XmlConsts.createdTimeNode); - if (createdTimeNode != null) - { - //Console.WriteLine("KeyChain create time:" + new DateTime(long.Parse(createdTimeNode.Value))); - } - else - { - //Console.WriteLine("Create time not found"); - } - XmlNode modifiedTimeNode = timeAttribCol.GetNamedItem(XmlConsts.modifiedTimeNode); - if (modifiedTimeNode != null) - { - //Console.WriteLine("KeyChain mod time:" + new DateTime(long.Parse(modifiedTimeNode.Value))); - } - } - } - } - - 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); - - - // get time stamps for this secret - XmlNode timeNode = secretNode.SelectSingleNode("descendant::" + XmlConsts.timeNode); - if (timeNode != null) - { - //Console.WriteLine("Secret: " + secretId); - XmlAttributeCollection timeAttribCol = timeNode.Attributes; - if (timeAttribCol != null) - { - XmlNode createdTimeNode = timeAttribCol.GetNamedItem(XmlConsts.createdTimeNode); - if (createdTimeNode != null) - { - //Console.WriteLine("Secret create time:" + new DateTime(long.Parse(createdTimeNode.Value))); - secret.CreatedTime = new DateTime(long.Parse(createdTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); - } - else - { - //Console.WriteLine("Create time not found"); - } - - XmlNode modifiedTimeNode = timeAttribCol.GetNamedItem(XmlConsts.modifiedTimeNode); - if (modifiedTimeNode != null) - { - //Console.WriteLine("Secret mod time:" + new DateTime(long.Parse(modifiedTimeNode.Value))); - secret.ModifiedTime = new DateTime(long.Parse(modifiedTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); - } - else - { - //Console.WriteLine("mod time not found"); - } - } - } - - - //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; - string sIsBinary = ""; - try - { - key = (attrColl[XmlConsts.idAttr]).Value; - - } - catch (Exception) - { - // LinkedKey node, continue - continue; - } - - // get binary attribute, if set - try - { - sIsBinary = attrColl.GetNamedItem(XmlConsts.binaryAttr).Value; - } - catch - { - sIsBinary = "false"; - } - - xpath = "descendant::" + XmlConsts.keyValueNode; - XmlNode keyValNode = keyNode.SelectSingleNode(xpath); - string keyValue = keyValNode.InnerText; - - // set binary type if set - if ((sIsBinary != null) && (sIsBinary.Equals("true"))) - { - byte[] baDec = Convert.FromBase64String(keyValue); - secret.SetKeyValue(key, baDec, false); - - KeyValue kv = secret.GetKeyValue(key); - kv.SetValueType(KeyValue.VALUE_TYPE_BINARY); - } - else - { - secret.SetKeyValue(key, keyValue, false); - } - - // get time attributes on this key/value - XmlNode timeNodeKey = keyNode.SelectSingleNode("descendant::" + XmlConsts.timeNode); - if (timeNodeKey != null) - { - // get the key value we just set - KeyValue kv = secret.GetKeyValue(key); - - XmlAttributeCollection timeAttribCol = timeNodeKey.Attributes; - if (timeAttribCol != null) - { - XmlNode createdTimeNode = timeAttribCol.GetNamedItem(XmlConsts.createdTimeNode); - if (createdTimeNode != null) - { - kv.CreatedTime = new DateTime(long.Parse(createdTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); - } - else - { - //Console.WriteLine("Create time not found"); - } - - XmlNode modifiedTimeNode = timeAttribCol.GetNamedItem(XmlConsts.modifiedTimeNode); - if (modifiedTimeNode != null) - { - kv.ModifiedTime = new DateTime(long.Parse(modifiedTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); - } - else - { - //Console.WriteLine("mod time not found"); - } - } - } - - - // 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 - - // if SecretID already exists, add to the conflict keychain - if (keyChain.CheckIfSecretExists(secretId) == false) - { - keyChain.AddSecret(secret); - } - else - { - if (kcConflict.CheckIfSecretExists(secretId)) - { - kcConflict.RemoveSecret(secretId); - } - kcConflict.AddSecret(secret); - } - - } - - }//end of traversing keyChainNodeList - } - } - - private void PersistStoreDelayThreadFn() - { - Thread.Sleep(15000); - PersistStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); - persistThread = null; - } - - private void PersistServerStoreDelayThreadFn() - { - Thread.Sleep(15000); - PersistStore(ConstStrings.SSCS_SERVER_KEY_CHAIN_ID); - sPersistThread = null; - } - - private void PersistStoreThreadFn() - { - while (true) - { - Thread.Sleep(persistThreadSleepTime); - PersistStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); - } - } - - private void PersistServerStoreThreadFn() - { - while (true) - { - Thread.Sleep(persistThreadSleepTime); - PersistStore(ConstStrings.SSCS_SERVER_KEY_CHAIN_ID); - } - } - +#endif + } + else + { + return false; + } + + // add these to the store + AddXMLSecretsToStore(userStore, doc); + } + catch (Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + } + + // collect now to remove old data from memory + GC.Collect(); + + return true; + } + + internal static void AddXMLSecretsToStore(SecretStore userStore, XmlDocument doc) + { + // get the conflict keychain + KeyChain kcConflict; + if (!userStore.CheckIfKeyChainExists(ConstStrings.SSCS_CONFLICT_KEYCHAIN + '\0')) + { + kcConflict = new KeyChain(ConstStrings.SSCS_CONFLICT_KEYCHAIN + '\0'); + userStore.AddKeyChain(kcConflict); + } + else + { + kcConflict = userStore.GetKeyChain(ConstStrings.SSCS_CONFLICT_KEYCHAIN + '\0'); + } + + 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); + + // set the created time if possible + XmlNode timeNode = node.SelectSingleNode("descendant::" + XmlConsts.timeNode); + if (timeNode != null) + { + XmlAttributeCollection timeAttribCol = timeNode.Attributes; + if (timeAttribCol != null) + { + XmlNode createdTimeNode = timeAttribCol.GetNamedItem(XmlConsts.createdTimeNode); + if (createdTimeNode != null) + { + //Console.WriteLine("KeyChain create time:" + new DateTime(long.Parse(createdTimeNode.Value))); + } + else + { + //Console.WriteLine("Create time not found"); + } + XmlNode modifiedTimeNode = timeAttribCol.GetNamedItem(XmlConsts.modifiedTimeNode); + if (modifiedTimeNode != null) + { + //Console.WriteLine("KeyChain mod time:" + new DateTime(long.Parse(modifiedTimeNode.Value))); + } + } + } + } + + 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); + + + // get time stamps for this secret + XmlNode timeNode = secretNode.SelectSingleNode("descendant::" + XmlConsts.timeNode); + if (timeNode != null) + { + //Console.WriteLine("Secret: " + secretId); + XmlAttributeCollection timeAttribCol = timeNode.Attributes; + if (timeAttribCol != null) + { + XmlNode createdTimeNode = timeAttribCol.GetNamedItem(XmlConsts.createdTimeNode); + if (createdTimeNode != null) + { + //Console.WriteLine("Secret create time:" + new DateTime(long.Parse(createdTimeNode.Value))); + secret.CreatedTime = new DateTime(long.Parse(createdTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); + } + else + { + //Console.WriteLine("Create time not found"); + } + + XmlNode modifiedTimeNode = timeAttribCol.GetNamedItem(XmlConsts.modifiedTimeNode); + if (modifiedTimeNode != null) + { + //Console.WriteLine("Secret mod time:" + new DateTime(long.Parse(modifiedTimeNode.Value))); + secret.ModifiedTime = new DateTime(long.Parse(modifiedTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); + } + else + { + //Console.WriteLine("mod time not found"); + } + } + } + + + //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; + string sIsBinary = ""; + try + { + key = (attrColl[XmlConsts.idAttr]).Value; + + } + catch (Exception) + { + // LinkedKey node, continue + continue; + } + + // get binary attribute, if set + try + { + sIsBinary = attrColl.GetNamedItem(XmlConsts.binaryAttr).Value; + } + catch + { + sIsBinary = "false"; + } + + xpath = "descendant::" + XmlConsts.keyValueNode; + XmlNode keyValNode = keyNode.SelectSingleNode(xpath); + string keyValue = keyValNode.InnerText; + + // set binary type if set + if ((sIsBinary != null) && (sIsBinary.Equals("true"))) + { + byte[] baDec = Convert.FromBase64String(keyValue); + secret.SetKeyValue(key, baDec, false); + + KeyValue kv = secret.GetKeyValue(key); + kv.SetValueType(KeyValue.VALUE_TYPE_BINARY); + } + else + { + secret.SetKeyValue(key, keyValue, false); + } + + // get time attributes on this key/value + XmlNode timeNodeKey = keyNode.SelectSingleNode("descendant::" + XmlConsts.timeNode); + if (timeNodeKey != null) + { + // get the key value we just set + KeyValue kv = secret.GetKeyValue(key); + + XmlAttributeCollection timeAttribCol = timeNodeKey.Attributes; + if (timeAttribCol != null) + { + XmlNode createdTimeNode = timeAttribCol.GetNamedItem(XmlConsts.createdTimeNode); + if (createdTimeNode != null) + { + kv.CreatedTime = new DateTime(long.Parse(createdTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); + } + else + { + //Console.WriteLine("Create time not found"); + } + + XmlNode modifiedTimeNode = timeAttribCol.GetNamedItem(XmlConsts.modifiedTimeNode); + if (modifiedTimeNode != null) + { + kv.ModifiedTime = new DateTime(long.Parse(modifiedTimeNode.Value), DateTimeKind.Utc).ToLocalTime(); + } + else + { + //Console.WriteLine("mod time not found"); + } + } + } + + + // 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 + + // if SecretID already exists, add to the conflict keychain + if (keyChain.CheckIfSecretExists(secretId) == false) + { + keyChain.AddSecret(secret); + } + else + { + if (kcConflict.CheckIfSecretExists(secretId)) + { + kcConflict.RemoveSecret(secretId); + } + kcConflict.AddSecret(secret); + } + + } + + }//end of traversing keyChainNodeList + } + } + + private void PersistStoreDelayThreadFn() + { + Thread.Sleep(15000); + PersistStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); + persistThread = null; + } + + private void PersistServerStoreDelayThreadFn() + { + Thread.Sleep(15000); + PersistStore(ConstStrings.SSCS_SERVER_KEY_CHAIN_ID); + sPersistThread = null; + } + + private void PersistStoreThreadFn() + { + while (true) + { + Thread.Sleep(persistThreadSleepTime); + PersistStore(ConstStrings.SSCS_SESSION_KEY_CHAIN_ID); + } + } + + private void PersistServerStoreThreadFn() + { + while (true) + { + Thread.Sleep(persistThreadSleepTime); + PersistStore(ConstStrings.SSCS_SERVER_KEY_CHAIN_ID); + } + } + /* Persists the store to an xml file. * TBD : Would we require any form of encoding? - */ - - internal void PersistStore(string keyChainId) - { - string sPeristSecrets = null; - - // is policy set to persist secrets - UIPol uiPolicy = (UIPol)ICASAPol.GetPolicy(CASAPolType.UI_POL, userStore.GetUserHomeDirectory(), userStore.GetUserName()); - if (uiPolicy != null) - { - sPeristSecrets = uiPolicy.GetConfigSetting(ConstStrings.CONFIG_PERSIST_SECRETS); - } - - if ((sPeristSecrets != null) && (sPeristSecrets.Equals("0"))) - { - // delete .miCASA file and .IV file - if (keyChainId == ConstStrings.SSCS_SESSION_KEY_CHAIN_ID) - File.Delete(userStore.GetPersistenceFilePath()); - else if (keyChainId == ConstStrings.SSCS_SERVER_KEY_CHAIN_ID) - File.Delete(userStore.GetServerSecretsPersistenceFilePath()); - return; - } - - //userStore.DumpSecretstore(); - try - { - MemoryStream ms1 = GetSecretsAsXMLStream(this.userStore, keyChainId); - byte[] key = null; - string fileName = null; - - if (keyChainId == ConstStrings.SSCS_SESSION_KEY_CHAIN_ID) - { - key = CASACrypto.GetKeySetFromFile(m_baGeneratedKey, userStore.GetKeyFilePath()); - fileName = userStore.GetPersistenceFilePath(); - } - else if (keyChainId == ConstStrings.SSCS_SERVER_KEY_CHAIN_ID) - { - key = CASACrypto.GetKeySetFromFile(m_baGeneratedKey, userStore.GetServerKeyFilePath()); - fileName = userStore.GetServerSecretsPersistenceFilePath(); - } - - string tempFile = fileName; - int count = 0; - - // rename existing file - if (File.Exists(fileName)) - { - while (true) - { - if (File.Exists(tempFile + ".tmp")) - { - if (IsOwnedByRoot(tempFile + ".tmp")) - { - File.Delete(tempFile + ".tmp"); - break; - } - else - { - count++; - tempFile = fileName + count.ToString(); - } - } - else - break; - } - File.Move(fileName, tempFile + ".tmp"); - } - - CASACrypto.EncryptDataAndWriteToFile(ms1.ToArray(), key, fileName); - - //remove temp - if (File.Exists(tempFile + ".tmp")) - { - if (IsOwnedByRoot(tempFile + ".tmp")) - File.Delete(tempFile + ".tmp"); - } - } - catch (Exception e) - { - CSSSLogger.ExpLog(e.ToString()); - } - } - - internal static MemoryStream GetSecretsAsXMLStream(SecretStore userStore, string keyChainId) - { - 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; - 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); - - if ((keyChainId != null) && (keyChainId != sTmpId)) - continue; - - writer.WriteStartElement(XmlConsts.keyChainNode); - writer.WriteAttributeString(XmlConsts.idAttr, sTmpId); - // If we need to store time - writer.WriteStartElement(XmlConsts.timeNode); - writer.WriteAttributeString(XmlConsts.createdTimeNode, kc.CreatedTime.ToUniversalTime().Ticks.ToString()); - writer.WriteAttributeString(XmlConsts.modifiedTimeNode, kc.ModifiedTime.ToUniversalTime().Ticks.ToString()); - writer.WriteEndElement(); - - PersistencePol policy = null; - - 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); - - // TODO: Does Policy allow persisting this secret. - if (policy == null) - { - policy = (PersistencePol)ICASAPol.GetPolicy(CASAPolType.PERSISTENCE_POL, userStore.GetUserHomeDirectory(), userStore.GetUserName()); - } - - bool bSaveValues = true; - if (policy != null) - { - if (policy.GetSecretPolicy(sTmpId, "Persistent", "True").Equals("False")) - { - //continue; - bSaveValues = false; - } - } - - writer.WriteAttributeString(XmlConsts.idAttr, sTmpId); - // If we need to store time - writer.WriteStartElement(XmlConsts.timeNode); - writer.WriteAttributeString(XmlConsts.createdTimeNode, secret.CreatedTime.ToUniversalTime().Ticks.ToString()); - writer.WriteAttributeString(XmlConsts.modifiedTimeNode, secret.ModifiedTime.ToUniversalTime().Ticks.ToString()); - writer.WriteEndElement(); - - writer.WriteStartElement(XmlConsts.valueNode); - // byte[] byteArr = secret.GetValue(); - - IDictionaryEnumerator etor = (IDictionaryEnumerator)secret.GetKeyValueEnumerator(); - while (etor.MoveNext()) - { - string sKey = (string)etor.Key; - KeyValue kv = secret.GetKeyValue(sKey); - if (!kv.IsPersistent) - { - continue; - } - - string value = kv.GetValue(); - writer.WriteStartElement(XmlConsts.keyNode); - writer.WriteAttributeString(XmlConsts.idAttr, sKey); - if (kv.GetValueType() == KeyValue.VALUE_TYPE_BINARY) - { - writer.WriteAttributeString(XmlConsts.binaryAttr, "true"); - } - - writer.WriteStartElement(XmlConsts.keyValueNode); - - if (bSaveValues) - { - if (kv.GetValueType() == KeyValue.VALUE_TYPE_BINARY) - { - writer.WriteString(Convert.ToBase64String(kv.GetValueAsBytes())); - } - else - { - writer.WriteString(value); - } - } - else - writer.WriteString(""); - - writer.WriteEndElement(); - // If we need to store time - writer.WriteStartElement(XmlConsts.timeNode); - writer.WriteAttributeString(XmlConsts.createdTimeNode, (secret.GetKeyValueCreatedTime(sKey)).ToUniversalTime().Ticks.ToString()); - writer.WriteAttributeString(XmlConsts.modifiedTimeNode, (secret.GetKeyValueModifiedTime(sKey)).ToUniversalTime().Ticks.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(); - } - + */ + + internal void PersistStore(string keyChainId) + { + string sPeristSecrets = null; + + // is policy set to persist secrets + UIPol uiPolicy = (UIPol)ICASAPol.GetPolicy(CASAPolType.UI_POL, userStore.GetUserHomeDirectory(), userStore.GetUserName()); + if (uiPolicy != null) + { + sPeristSecrets = uiPolicy.GetConfigSetting(ConstStrings.CONFIG_PERSIST_SECRETS); + } + + if ((sPeristSecrets != null) && (sPeristSecrets.Equals("0"))) + { + // delete .miCASA file and .IV file + if (keyChainId == ConstStrings.SSCS_SESSION_KEY_CHAIN_ID) + File.Delete(userStore.GetPersistenceFilePath()); + else if (keyChainId == ConstStrings.SSCS_SERVER_KEY_CHAIN_ID) + File.Delete(userStore.GetServerSecretsPersistenceFilePath()); + return; + } + + //userStore.DumpSecretstore(); + try + { + MemoryStream ms1 = GetSecretsAsXMLStream(this.userStore, keyChainId); + byte[] key = null; + string fileName = null; + + if (keyChainId == ConstStrings.SSCS_SESSION_KEY_CHAIN_ID) + { + key = CASACrypto.GetKeySetFromFile(m_baGeneratedKey, userStore.GetKeyFilePath(), userStore.GetUserIdentifier()); + fileName = userStore.GetPersistenceFilePath(); + } + else if (keyChainId == ConstStrings.SSCS_SERVER_KEY_CHAIN_ID) + { + key = CASACrypto.GetKeySetFromFile(m_baGeneratedKey, userStore.GetServerKeyFilePath(), userStore.GetUserIdentifier()); + fileName = userStore.GetServerSecretsPersistenceFilePath(); + } + + string tempFile = fileName; + // rename existing file + if (File.Exists(fileName)) + { + if (File.Exists(tempFile + ".tmp")) + { + File.Delete(tempFile + ".tmp"); + } + File.Move(fileName, tempFile + ".tmp"); + } + + CASACrypto.EncryptDataAndWriteToFile(ms1.ToArray(), key, fileName, userStore.GetUserIdentifier()); + + //remove temp + if (File.Exists(tempFile + ".tmp")) + { + File.Delete(tempFile + ".tmp"); + } + } + catch (Exception e) + { + CSSSLogger.ExpLog(e.ToString()); + } + } + + internal static MemoryStream GetSecretsAsXMLStream(SecretStore userStore, string keyChainId) + { + 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; + 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); + + if ((keyChainId != null) && (keyChainId != sTmpId)) + continue; + + writer.WriteStartElement(XmlConsts.keyChainNode); + writer.WriteAttributeString(XmlConsts.idAttr, sTmpId); + // If we need to store time + writer.WriteStartElement(XmlConsts.timeNode); + writer.WriteAttributeString(XmlConsts.createdTimeNode, kc.CreatedTime.ToUniversalTime().Ticks.ToString()); + writer.WriteAttributeString(XmlConsts.modifiedTimeNode, kc.ModifiedTime.ToUniversalTime().Ticks.ToString()); + writer.WriteEndElement(); + + PersistencePol policy = null; + + 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); + + // TODO: Does Policy allow persisting this secret. + if (policy == null) + { + policy = (PersistencePol)ICASAPol.GetPolicy(CASAPolType.PERSISTENCE_POL, userStore.GetUserHomeDirectory(), userStore.GetUserName()); + } + + bool bSaveValues = true; + if (policy != null) + { + if (policy.GetSecretPolicy(sTmpId, "Persistent", "True").Equals("False")) + { + //continue; + bSaveValues = false; + } + } + + writer.WriteAttributeString(XmlConsts.idAttr, sTmpId); + // If we need to store time + writer.WriteStartElement(XmlConsts.timeNode); + writer.WriteAttributeString(XmlConsts.createdTimeNode, secret.CreatedTime.ToUniversalTime().Ticks.ToString()); + writer.WriteAttributeString(XmlConsts.modifiedTimeNode, secret.ModifiedTime.ToUniversalTime().Ticks.ToString()); + writer.WriteEndElement(); + + writer.WriteStartElement(XmlConsts.valueNode); + // byte[] byteArr = secret.GetValue(); + + IDictionaryEnumerator etor = (IDictionaryEnumerator)secret.GetKeyValueEnumerator(); + while (etor.MoveNext()) + { + string sKey = (string)etor.Key; + KeyValue kv = secret.GetKeyValue(sKey); + if (!kv.IsPersistent) + { + continue; + } + + string value = kv.GetValue(); + writer.WriteStartElement(XmlConsts.keyNode); + writer.WriteAttributeString(XmlConsts.idAttr, sKey); + if (kv.GetValueType() == KeyValue.VALUE_TYPE_BINARY) + { + writer.WriteAttributeString(XmlConsts.binaryAttr, "true"); + } + + writer.WriteStartElement(XmlConsts.keyValueNode); + + if (bSaveValues) + { + if (kv.GetValueType() == KeyValue.VALUE_TYPE_BINARY) + { + writer.WriteString(Convert.ToBase64String(kv.GetValueAsBytes())); + } + else + { + writer.WriteString(value); + } + } + else + writer.WriteString(""); + + writer.WriteEndElement(); + // If we need to store time + writer.WriteStartElement(XmlConsts.timeNode); + writer.WriteAttributeString(XmlConsts.createdTimeNode, (secret.GetKeyValueCreatedTime(sKey)).ToUniversalTime().Ticks.ToString()); + writer.WriteAttributeString(XmlConsts.modifiedTimeNode, (secret.GetKeyValueModifiedTime(sKey)).ToUniversalTime().Ticks.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++) @@ -861,24 +790,24 @@ namespace sscs.lss 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; - } - } - } -} + */ + + 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; + } + } + } +} diff --git a/CASA/micasad/lss/Rfc2898DeriveBytes.cs b/CASA/micasad/lss/Rfc2898DeriveBytes.cs index 7e62f996..9566dfaf 100644 --- a/CASA/micasad/lss/Rfc2898DeriveBytes.cs +++ b/CASA/micasad/lss/Rfc2898DeriveBytes.cs @@ -20,312 +20,326 @@ * ***********************************************************************/ -// -// Rfc2898DeriveBytes.cs: RFC2898 (PKCS#5 v2) Key derivation for Password Based Encryption -// -// Author: -// Sebastien Pouliot (sebastien@ximian.com) -// -// (C) 2003 Motus Technologies Inc. (http://www.motus.com) -// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - - - -//using System.Runtime.InteropServices; -using System; -using System.Text; -using System.IO; -using System.Security.Cryptography; - -using sscs.lss; -using sscs.common; - -namespace sscs.crypto { - - //[ComVisible (true)] - public class Rfc2898DeriveBytes : DeriveBytes { - - private const int defaultIterations = 1000; - - private int _iteration; - private byte[] _salt; - private HMACSHA1 _hmac; - private byte[] _buffer; - private int _pos; - private int _f; - - // constructors - - public Rfc2898DeriveBytes (string password, byte[] salt) - : this (password, salt, defaultIterations) - { - } - - public Rfc2898DeriveBytes (string password, byte[] salt, int iterations) - { - if (password == null) - throw new ArgumentNullException ("password"); - - Salt = salt; - IterationCount = iterations; - _hmac = new HMACSHA1 (Encoding.UTF8.GetBytes (password)); - } - - public Rfc2898DeriveBytes (byte[] password, byte[] salt, int iterations) - { - if (password == null) - throw new ArgumentNullException ("password"); - - Salt = salt; - IterationCount = iterations; - _hmac = new HMACSHA1 (password); - } - - public Rfc2898DeriveBytes (string password, int saltSize) - : this (password, saltSize, defaultIterations) - { - } - - public Rfc2898DeriveBytes(string password, int saltSize, int iterations) - : this (password, saltSize, iterations, false, null, false) - { - } - - public Rfc2898DeriveBytes (string password, int saltSize, int iterations, bool bUseOldMethod, string sFilepath, bool bGenerateAndSaveRandomSalt) - { - if (password == null) - throw new ArgumentNullException ("password"); - if (saltSize < 0) - throw new ArgumentOutOfRangeException ("invalid salt length"); - - if (bUseOldMethod) - { - Salt = GenerateOldSalt(password, saltSize); - } - else - { - if (bGenerateAndSaveRandomSalt) - { - Salt = GenerateAndSaveRandomSalt(saltSize, sFilepath); - } - else - { - // load saved salt if one was saved - if ((sFilepath != null) && (File.Exists(sFilepath + ".salt"))) - { - Salt = LoadSavedSalt(sFilepath); - } - else - { - Salt = GenerateNewSalt(password, saltSize); - } - } - } - - IterationCount = iterations; - _hmac = new HMACSHA1 (Encoding.UTF8.GetBytes (password)); - } - - private byte[] GenerateAndSaveRandomSalt(int saltSize, string sFilepath) - { - byte[] randomSalt = new byte[saltSize]; - FastRandom fr = new FastRandom(); - fr.NextBytes(randomSalt); - - // save salt - try - { - - FileStream fs = new FileStream(sFilepath + ".salt", FileMode.OpenOrCreate); - fs.Write(randomSalt, 0, randomSalt.Length); - fs.Flush(); - fs.Close(); - - File.SetAttributes(sFilepath + ".salt", FileAttributes.Hidden); - - } - catch (Exception e) - { - CSSSLogger.DbgLog(e.ToString()); - } - - return randomSalt; - } - - private byte[] LoadSavedSalt(string sFilePath) - { - byte[] baSalt = null; - - try - { - FileStream fs = new FileStream(sFilePath + ".salt", FileMode.Open); - baSalt = new byte[fs.Length]; - fs.Read(baSalt, 0, (int)fs.Length); - fs.Close(); - } - catch (Exception e) - { - CSSSLogger.DbgLog(e.ToString()); - } - return baSalt; - } - - private static byte[] GenerateOldSalt(string password, int saltSize) - { - byte[] buffer = new byte[saltSize]; - Random rand = new Random(password.GetHashCode()); - rand.NextBytes(buffer); - return buffer; - } - - private static byte[] GenerateNewSalt(string password, int saltSize) - { - int j = 0; - byte[] buffer = new byte[saltSize]; - - // iterate thru each character, creating a new Random, - // getting 2 bytes from each, until our salt buffer is full. - for (int i = 0; i < password.Length;) - { - char letter = password[i]; - int iLetter = (int)letter; - - FastRandom ranNum = new FastRandom(iLetter * (j+1)); - byte[] temp = new byte[2]; - ranNum.NextBytes(temp); - - for (int k = 0; k < temp.Length; k++) - { - buffer[j++] = temp[k]; - // get out if buffer is full - if (j >= saltSize) - { - return buffer; - } - } - - i++; - - // reset i if at end of password - if ((i + 1) > password.Length) - { - i = 0; - } - - - } - - return buffer; - } - - // properties - public int IterationCount - { - get { return _iteration; } - set { - if (value < 1) - throw new ArgumentOutOfRangeException ("IterationCount < 1"); - - _iteration = value; - } - } - - public byte[] Salt { - get { return (byte[]) _salt.Clone (); } - set { - if (value == null) - throw new ArgumentNullException ("Salt"); - if (value.Length < 8) - throw new ArgumentException ("Salt < 8 bytes"); - - _salt = (byte[])value.Clone (); - } - } - - // methods - - private byte[] F (byte[] s, int c, int i) - { - byte[] data = new byte [s.Length + 4]; - Buffer.BlockCopy (s, 0, data, 0, s.Length); - byte[] int4 = BitConverter.GetBytes (i); - Array.Reverse (int4, 0, 4); - Buffer.BlockCopy (int4, 0, data, s.Length, 4); - - // this is like j=0 - byte[] u1 = _hmac.ComputeHash (data); - data = u1; - // so we start at j=1 - for (int j=1; j < c; j++) { - byte[] un = _hmac.ComputeHash (data); - // xor - for (int k=0; k < 20; k++) - u1 [k] = (byte)(u1 [k] ^ un [k]); - data = un; - } - return u1; - } - - public override byte[] GetBytes (int cb) - { - if (cb < 1) - throw new ArgumentOutOfRangeException ("cb"); - - int l = cb / 20; // HMACSHA1 == 160 bits == 20 bytes - int r = cb % 20; // remainder - if (r != 0) - l++; // rounding up - - byte[] result = new byte [cb]; - int rpos = 0; - if (_pos > 0) { - int count = Math.Min (20 - _pos, cb); - Buffer.BlockCopy (_buffer, _pos, result, 0, count); - if (count >= cb) - return result; - _pos = 0; - rpos = 20 - cb; - r = cb - rpos; - } - - for (int i=1; i <= l; i++) { - _buffer = F (_salt, _iteration, ++_f); - int count = ((i == l) ? r : 20); - Buffer.BlockCopy (_buffer, _pos, result, rpos, count); - rpos += _pos + count; - _pos = ((count == 20) ? 0 : count); - } - - return result; - } - - public override void Reset () - { - _buffer = null; - _pos = 0; - _f = 0; - } - } -} - - +// +// Rfc2898DeriveBytes.cs: RFC2898 (PKCS#5 v2) Key derivation for Password Based Encryption +// +// Author: +// Sebastien Pouliot (sebastien@ximian.com) +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + + +//using System.Runtime.InteropServices; +using System; +using System.Text; +using System.IO; +using System.Security.Cryptography; + +using sscs.lss; +using sscs.common; + +namespace sscs.crypto { + + //[ComVisible (true)] + public class Rfc2898DeriveBytes : DeriveBytes { + + private const int defaultIterations = 1000; + + private int _iteration; + private byte[] _salt; + private HMACSHA1 _hmac; + private byte[] _buffer; + private int _pos; + private int _f; + + // constructors + + public Rfc2898DeriveBytes (string password, byte[] salt) + : this (password, salt, defaultIterations) + { + } + + public Rfc2898DeriveBytes (string password, byte[] salt, int iterations) + { + if (password == null) + throw new ArgumentNullException ("password"); + + Salt = salt; + IterationCount = iterations; + _hmac = new HMACSHA1 (Encoding.UTF8.GetBytes (password)); + } + + public Rfc2898DeriveBytes (byte[] password, byte[] salt, int iterations) + { + if (password == null) + throw new ArgumentNullException ("password"); + + Salt = salt; + IterationCount = iterations; + _hmac = new HMACSHA1 (password); + } + + public Rfc2898DeriveBytes (string password, int saltSize) + : this (password, saltSize, defaultIterations) + { + } + + public Rfc2898DeriveBytes(string password, int saltSize, int iterations) + : this (password, saltSize, iterations, false, null, false, null) + { + } + + public Rfc2898DeriveBytes (string password, int saltSize, int iterations, bool bUseOldMethod, string sFilepath, bool bGenerateAndSaveRandomSalt, UserIdentifier userID) + { + if (password == null) + throw new ArgumentNullException ("password"); + if (saltSize < 0) + throw new ArgumentOutOfRangeException ("invalid salt length"); + + if (bUseOldMethod) + { + Salt = GenerateOldSalt(password, saltSize); + } + else + { + if (bGenerateAndSaveRandomSalt) + { + Salt = GenerateAndSaveRandomSalt(saltSize, sFilepath, userID); + } + else + { + // load saved salt if one was saved + if ((sFilepath != null) && (File.Exists(sFilepath + ".salt"))) + { + Salt = LoadSavedSalt(sFilepath, userID); + } + else + { + Salt = GenerateNewSalt(password, saltSize); + } + } + } + + IterationCount = iterations; + _hmac = new HMACSHA1 (Encoding.UTF8.GetBytes (password)); + } + + private byte[] GenerateAndSaveRandomSalt(int saltSize, string sFilepath, UserIdentifier userID) + { + byte[] randomSalt = new byte[saltSize]; + FastRandom fr = new FastRandom(); + fr.NextBytes(randomSalt); + + // save salt + try + { + + FileStream fs = new FileStream(sFilepath + ".salt", FileMode.OpenOrCreate); + fs.Write(randomSalt, 0, randomSalt.Length); + fs.Flush(); + fs.Close(); + + File.SetAttributes(sFilepath + ".salt", FileAttributes.Hidden); + + if (!CSSSUtils.SetSocketUserAsOwner(sFilepath + ".salt", userID)) + { + CSSSLogger.DbgLog("Unable to set the owner of the file to the socket user"); + } + } + catch (Exception e) + { + CSSSLogger.DbgLog(e.ToString()); + } + + return randomSalt; + } + + private byte[] LoadSavedSalt(string sFilePath, UserIdentifier userID) + { + byte[] baSalt = null; + + try + { +#if LINUX + Mono.Unix.UnixFileInfo fsTest = new Mono.Unix.UnixFileInfo (sFilePath + ".salt"); + if((fsTest == null) || !(fsTest.Exists) || fsTest.IsSymbolicLink || !CSSSUtils.CompareSocketAndFileUserIds(sFilePath + ".salt", userID)) +#else + if (!File.Exists(sFilePath + ".salt")) +#endif + { + return null; + } + + FileStream fs = new FileStream(sFilePath + ".salt", FileMode.Open); + baSalt = new byte[fs.Length]; + fs.Read(baSalt, 0, (int)fs.Length); + fs.Close(); + } + catch (Exception e) + { + CSSSLogger.DbgLog(e.ToString()); + } + return baSalt; + } + + private static byte[] GenerateOldSalt(string password, int saltSize) + { + byte[] buffer = new byte[saltSize]; + Random rand = new Random(password.GetHashCode()); + rand.NextBytes(buffer); + return buffer; + } + + private static byte[] GenerateNewSalt(string password, int saltSize) + { + int j = 0; + byte[] buffer = new byte[saltSize]; + + // iterate thru each character, creating a new Random, + // getting 2 bytes from each, until our salt buffer is full. + for (int i = 0; i < password.Length;) + { + char letter = password[i]; + int iLetter = (int)letter; + + FastRandom ranNum = new FastRandom(iLetter * (j+1)); + byte[] temp = new byte[2]; + ranNum.NextBytes(temp); + + for (int k = 0; k < temp.Length; k++) + { + buffer[j++] = temp[k]; + // get out if buffer is full + if (j >= saltSize) + { + return buffer; + } + } + + i++; + + // reset i if at end of password + if ((i + 1) > password.Length) + { + i = 0; + } + + + } + + return buffer; + } + + // properties + public int IterationCount + { + get { return _iteration; } + set { + if (value < 1) + throw new ArgumentOutOfRangeException ("IterationCount < 1"); + + _iteration = value; + } + } + + public byte[] Salt { + get { return (byte[]) _salt.Clone (); } + set { + if (value == null) + throw new ArgumentNullException ("Salt"); + if (value.Length < 8) + throw new ArgumentException ("Salt < 8 bytes"); + + _salt = (byte[])value.Clone (); + } + } + + // methods + + private byte[] F (byte[] s, int c, int i) + { + byte[] data = new byte [s.Length + 4]; + Buffer.BlockCopy (s, 0, data, 0, s.Length); + byte[] int4 = BitConverter.GetBytes (i); + Array.Reverse (int4, 0, 4); + Buffer.BlockCopy (int4, 0, data, s.Length, 4); + + // this is like j=0 + byte[] u1 = _hmac.ComputeHash (data); + data = u1; + // so we start at j=1 + for (int j=1; j < c; j++) { + byte[] un = _hmac.ComputeHash (data); + // xor + for (int k=0; k < 20; k++) + u1 [k] = (byte)(u1 [k] ^ un [k]); + data = un; + } + return u1; + } + + public override byte[] GetBytes (int cb) + { + if (cb < 1) + throw new ArgumentOutOfRangeException ("cb"); + + int l = cb / 20; // HMACSHA1 == 160 bits == 20 bytes + int r = cb % 20; // remainder + if (r != 0) + l++; // rounding up + + byte[] result = new byte [cb]; + int rpos = 0; + if (_pos > 0) { + int count = Math.Min (20 - _pos, cb); + Buffer.BlockCopy (_buffer, _pos, result, 0, count); + if (count >= cb) + return result; + _pos = 0; + rpos = 20 - cb; + r = cb - rpos; + } + + for (int i=1; i <= l; i++) { + _buffer = F (_salt, _iteration, ++_f); + int count = ((i == l) ? r : 20); + Buffer.BlockCopy (_buffer, _pos, result, rpos, count); + rpos += _pos + count; + _pos = ((count == 20) ? 0 : count); + } + + return result; + } + + public override void Reset () + { + _buffer = null; + _pos = 0; + _f = 0; + } + } +} + +