diff --git a/KeePass/Forms/DatabaseSettingsForm.cs b/KeePass/Forms/DatabaseSettingsForm.cs index 1216792..1a24456 100644 --- a/KeePass/Forms/DatabaseSettingsForm.cs +++ b/KeePass/Forms/DatabaseSettingsForm.cs @@ -24,6 +24,7 @@ You should have received a copy of the GNU General Public License using System.Drawing; using System.Text; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; using KeePass.App; @@ -43,885 +44,884 @@ You should have received a copy of the GNU General Public License namespace KeePass.Forms { - public partial class DatabaseSettingsForm : Form - { - private bool m_bCreatingNew = false; - private PwDatabase m_pwDatabase = null; + public partial class DatabaseSettingsForm : Form + { + private bool m_bCreatingNew = false; + private PwDatabase m_pwDatabase = null; - private Color m_clr = Color.Empty; + private Color m_clr = Color.Empty; - private CustomContextMenuEx m_ctxColor = null; - private List m_vColorItems = new List(); - private Image m_imgColor = null; + private CustomContextMenuEx m_ctxColor = null; + private readonly List m_vColorItems = new(); + private Image m_imgColor = null; - private string m_strAutoCreateNew = "(" + KPRes.AutoCreateNew + ")"; - private Dictionary m_dictRecycleBinGroups = new Dictionary(); + private readonly string m_strAutoCreateNew = "(" + KPRes.AutoCreateNew + ")"; + private readonly Dictionary m_dictRecycleBinGroups = new(); - private Dictionary m_dictEntryTemplateGroups = new Dictionary(); + private readonly Dictionary m_dictEntryTemplateGroups = new(); - private bool m_bInitializing = true; - private volatile Thread m_thKdf = null; + private bool m_bInitializing = true; + private volatile Task m_thKdf = null; - public PwDatabase DatabaseEx - { - get { return m_pwDatabase; } - } + public PwDatabase DatabaseEx + { + get { return m_pwDatabase; } + } - public DatabaseSettingsForm() - { - InitializeComponent(); - Program.Translation.ApplyTo(this); - } + public DatabaseSettingsForm() + { + InitializeComponent(); + Program.Translation.ApplyTo(this); + } - public void InitEx(bool bCreatingNew, PwDatabase pwDatabase) - { - m_bCreatingNew = bCreatingNew; + public void InitEx(bool bCreatingNew, PwDatabase pwDatabase) + { + m_bCreatingNew = bCreatingNew; - Debug.Assert(pwDatabase != null); if(pwDatabase == null) throw new ArgumentNullException("pwDatabase"); - m_pwDatabase = pwDatabase; - } + Debug.Assert(pwDatabase != null); if (pwDatabase == null) throw new ArgumentNullException("pwDatabase"); + m_pwDatabase = pwDatabase; + } - private void OnFormLoad(object sender, EventArgs e) - { - Debug.Assert(m_pwDatabase != null); if(m_pwDatabase == null) throw new InvalidOperationException(); + private void OnFormLoad(object sender, EventArgs e) + { + Debug.Assert(m_pwDatabase != null); if (m_pwDatabase == null) throw new InvalidOperationException(); - m_bInitializing = true; + m_bInitializing = true; - GlobalWindowManager.AddWindow(this); + GlobalWindowManager.AddWindow(this); - IOConnectionInfo ioc = m_pwDatabase.IOConnectionInfo; - string strDisp = ioc.GetDisplayName(); + IOConnectionInfo ioc = m_pwDatabase.IOConnectionInfo; + string strDisp = ioc.GetDisplayName(); - string strDesc = KPRes.DatabaseSettingsDesc; - if(!string.IsNullOrEmpty(strDisp)) strDesc = strDisp; + string strDesc = KPRes.DatabaseSettingsDesc; + if (!string.IsNullOrEmpty(strDisp)) strDesc = strDisp; - BannerFactory.CreateBannerEx(this, m_bannerImage, - Properties.Resources.B48x48_Ark, KPRes.DatabaseSettings, strDesc); - this.Icon = AppIcons.Default; + BannerFactory.CreateBannerEx(this, m_bannerImage, + Properties.Resources.B48x48_Ark, KPRes.DatabaseSettings, strDesc); + this.Icon = AppIcons.Default; - FontUtil.AssignDefaultItalic(m_lblHeaderCpAlgo); - FontUtil.AssignDefaultItalic(m_lblHeaderCp); - FontUtil.AssignDefaultItalic(m_lblHeaderPerf); + FontUtil.AssignDefaultItalic(m_lblHeaderCpAlgo); + FontUtil.AssignDefaultItalic(m_lblHeaderCp); + FontUtil.AssignDefaultItalic(m_lblHeaderPerf); - FontUtil.AssignDefaultBold(m_rbNone); - FontUtil.AssignDefaultBold(m_rbGZip); + FontUtil.AssignDefaultBold(m_rbNone); + FontUtil.AssignDefaultBold(m_rbGZip); - UIUtil.ConfigureToolTip(m_ttRect); - m_ttRect.SetToolTip(m_btnKdf1Sec, KPRes.KdfParams1Sec); + UIUtil.ConfigureToolTip(m_ttRect); + m_ttRect.SetToolTip(m_btnKdf1Sec, KPRes.KdfParams1Sec); - m_tbDbName.PromptText = KPRes.DatabaseNamePrompt; - m_tbDbDesc.PromptText = KPRes.DatabaseDescPrompt; + m_tbDbName.PromptText = KPRes.DatabaseNamePrompt; + m_tbDbDesc.PromptText = KPRes.DatabaseDescPrompt; - if(m_bCreatingNew) this.Text = KPRes.ConfigureOnNewDatabase3; - else this.Text = KPRes.DatabaseSettings; + if (m_bCreatingNew) this.Text = KPRes.ConfigureOnNewDatabase3; + else this.Text = KPRes.DatabaseSettings; - m_tbDbName.Text = m_pwDatabase.Name; - UIUtil.SetMultilineText(m_tbDbDesc, m_pwDatabase.Description); - m_tbDefaultUser.Text = m_pwDatabase.DefaultUserName; + m_tbDbName.Text = m_pwDatabase.Name; + UIUtil.SetMultilineText(m_tbDbDesc, m_pwDatabase.Description); + m_tbDefaultUser.Text = m_pwDatabase.DefaultUserName; - m_clr = m_pwDatabase.Color; - bool bClr = !UIUtil.ColorsEqual(m_clr, Color.Empty); - if(bClr) - { - m_clr = AppIcons.RoundColor(m_clr); - UIUtil.OverwriteButtonImage(m_btnColor, ref m_imgColor, - UIUtil.CreateColorBitmap24(m_btnColor, m_clr)); - } - m_cbColor.Checked = bClr; - - for(int inx = 0; inx < CipherPool.GlobalPool.EngineCount; ++inx) - m_cmbEncAlgo.Items.Add(CipherPool.GlobalPool[inx].DisplayName); - - if(m_cmbEncAlgo.Items.Count > 0) - { - int nIndex = CipherPool.GlobalPool.GetCipherIndex(m_pwDatabase.DataCipherUuid); - m_cmbEncAlgo.SelectedIndex = ((nIndex >= 0) ? nIndex : 0); - } - - Debug.Assert(m_cmbKdf.Items.Count == 0); - foreach(KdfEngine kdf in KdfPool.Engines) - { - m_cmbKdf.Items.Add(kdf.Name); - } - - m_numKdfIt.Minimum = ulong.MinValue; - m_numKdfIt.Maximum = ulong.MaxValue; + m_clr = m_pwDatabase.Color; + bool bClr = !UIUtil.ColorsEqual(m_clr, Color.Empty); + if (bClr) + { + m_clr = AppIcons.RoundColor(m_clr); + UIUtil.OverwriteButtonImage(m_btnColor, ref m_imgColor, + UIUtil.CreateColorBitmap24(m_btnColor, m_clr)); + } + m_cbColor.Checked = bClr; + + for (int inx = 0; inx < CipherPool.GlobalPool.EngineCount; ++inx) + m_cmbEncAlgo.Items.Add(CipherPool.GlobalPool[inx].DisplayName); + + if (m_cmbEncAlgo.Items.Count > 0) + { + int nIndex = CipherPool.GlobalPool.GetCipherIndex(m_pwDatabase.DataCipherUuid); + m_cmbEncAlgo.SelectedIndex = ((nIndex >= 0) ? nIndex : 0); + } + + Debug.Assert(m_cmbKdf.Items.Count == 0); + foreach (KdfEngine kdf in KdfPool.Engines) + { + m_cmbKdf.Items.Add(kdf.Name); + } + + m_numKdfIt.Minimum = ulong.MinValue; + m_numKdfIt.Maximum = ulong.MaxValue; - m_numKdfMem.Minimum = ulong.MinValue; - m_numKdfMem.Maximum = ulong.MaxValue; - - Debug.Assert(m_cmbKdfMem.Items.Count == 0); - Debug.Assert(!m_cmbKdfMem.Sorted); - m_cmbKdfMem.Items.Add("B"); - m_cmbKdfMem.Items.Add("KB"); - m_cmbKdfMem.Items.Add("MB"); - m_cmbKdfMem.Items.Add("GB"); - - m_numKdfPar.Minimum = uint.MinValue; - m_numKdfPar.Maximum = uint.MaxValue; - - SetKdfParameters(m_pwDatabase.KdfParameters); - - // m_lbMemProt.Items.Add(KPRes.Title, m_pwDatabase.MemoryProtection.ProtectTitle); - // m_lbMemProt.Items.Add(KPRes.UserName, m_pwDatabase.MemoryProtection.ProtectUserName); - // m_lbMemProt.Items.Add(KPRes.Password, m_pwDatabase.MemoryProtection.ProtectPassword); - // m_lbMemProt.Items.Add(KPRes.Url, m_pwDatabase.MemoryProtection.ProtectUrl); - // m_lbMemProt.Items.Add(KPRes.Notes, m_pwDatabase.MemoryProtection.ProtectNotes); - - // m_cbAutoEnableHiding.Checked = m_pwDatabase.MemoryProtection.AutoEnableVisualHiding; - // m_cbAutoEnableHiding.Checked = false; - - if(m_pwDatabase.Compression == PwCompressionAlgorithm.None) - m_rbNone.Checked = true; - else if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip) - m_rbGZip.Checked = true; - else { Debug.Assert(false); } - - InitRecycleBinTab(); - InitAdvancedTab(); - - m_bInitializing = false; - EnableControlsEx(); - UIUtil.SetFocus(m_tbDbName, this); - } - - private void InitRecycleBinTab() - { - m_cbRecycleBin.Checked = m_pwDatabase.RecycleBinEnabled; - - m_cmbRecycleBin.Items.Add(m_strAutoCreateNew); - m_dictRecycleBinGroups[0] = PwUuid.Zero; - - int iSelect; - UIUtil.CreateGroupList(m_pwDatabase.RootGroup, m_cmbRecycleBin, - m_dictRecycleBinGroups, m_pwDatabase.RecycleBinUuid, out iSelect); - - m_cmbRecycleBin.SelectedIndex = Math.Max(0, iSelect); - } - - private void InitAdvancedTab() - { - m_cmbEntryTemplates.Items.Add("(" + KPRes.None + ")"); - m_dictEntryTemplateGroups[0] = PwUuid.Zero; - - int iSelect; - UIUtil.CreateGroupList(m_pwDatabase.RootGroup, m_cmbEntryTemplates, - m_dictEntryTemplateGroups, m_pwDatabase.EntryTemplatesGroup, out iSelect); - - m_cmbEntryTemplates.SelectedIndex = Math.Max(0, iSelect); - - m_numHistoryMaxItems.Minimum = 0; - m_numHistoryMaxItems.Maximum = int.MaxValue; - bool bHistMaxItems = (m_pwDatabase.HistoryMaxItems >= 0); - m_numHistoryMaxItems.Value = (bHistMaxItems ? m_pwDatabase.HistoryMaxItems : - PwDatabase.DefaultHistoryMaxItems); - m_cbHistoryMaxItems.Checked = bHistMaxItems; - - m_numHistoryMaxSize.Minimum = 0; - m_numHistoryMaxSize.Maximum = long.MaxValue / (1024 * 1024); - bool bHistMaxSize = (m_pwDatabase.HistoryMaxSize >= 0); - m_numHistoryMaxSize.Value = (bHistMaxSize ? m_pwDatabase.HistoryMaxSize : - PwDatabase.DefaultHistoryMaxSize) / (1024 * 1024); - m_cbHistoryMaxSize.Checked = bHistMaxSize; - - m_numKeyRecDays.Minimum = 0; - m_numKeyRecDays.Maximum = long.MaxValue; - bool bChangeRec = (m_pwDatabase.MasterKeyChangeRec >= 0); - m_numKeyRecDays.Value = (bChangeRec ? m_pwDatabase.MasterKeyChangeRec : 182); - m_cbKeyRec.Checked = bChangeRec; - - m_numKeyForceDays.Minimum = 0; - m_numKeyForceDays.Maximum = long.MaxValue; - bool bChangeForce = (m_pwDatabase.MasterKeyChangeForce >= 0); - m_numKeyForceDays.Value = (bChangeForce ? m_pwDatabase.MasterKeyChangeForce : 365); - m_cbKeyForce.Checked = bChangeForce; - - m_cbKeyForceOnce.Checked = m_pwDatabase.MasterKeyChangeForceOnce; - } - - private void EnableControlsEx() - { - if(m_bInitializing) return; - - m_btnColor.Enabled = m_cbColor.Checked; - - KdfEngine kdf = GetKdf(); - if(kdf != null) - { - if(kdf is AesKdf) - { - m_lblKdfMem.Visible = false; - m_numKdfMem.Visible = false; - m_cmbKdfMem.Visible = false; - - m_lblKdfPar.Visible = false; - m_numKdfPar.Visible = false; - } - else if(kdf is Argon2Kdf) - { - m_lblKdfMem.Visible = true; - m_numKdfMem.Visible = true; - m_cmbKdfMem.Visible = true; - - m_lblKdfPar.Visible = true; - m_numKdfPar.Visible = true; - } - // else { Debug.Assert(false); } // Plugins may provide controls - } - else { Debug.Assert(false); } - - m_numHistoryMaxItems.Enabled = m_cbHistoryMaxItems.Checked; - m_numHistoryMaxSize.Enabled = m_cbHistoryMaxSize.Checked; - - bool bEnableDays = ((Program.Config.UI.UIFlags & - (ulong)AceUIFlags.DisableKeyChangeDays) == 0); - m_numKeyRecDays.Enabled = (bEnableDays && m_cbKeyRec.Checked); - m_numKeyForceDays.Enabled = (bEnableDays && m_cbKeyForce.Checked); - m_cbKeyRec.Enabled = bEnableDays; - m_cbKeyForce.Enabled = bEnableDays; - m_cbKeyForceOnce.Enabled = bEnableDays; - - bool bKdfTh = (m_thKdf != null); - m_tabMain.Enabled = !bKdfTh; - - m_pbKdf.Visible = bKdfTh; - - m_btnHelp.Enabled = !bKdfTh; - m_btnCancelOp.Enabled = bKdfTh; - m_btnCancelOp.Visible = bKdfTh; - m_btnOK.Enabled = !bKdfTh; - m_btnCancel.Enabled = !bKdfTh; - } - - private void OnBtnOK(object sender, EventArgs e) - { - m_pwDatabase.SettingsChanged = DateTime.UtcNow; - - if(m_tbDbName.Text != m_pwDatabase.Name) - { - m_pwDatabase.Name = m_tbDbName.Text; - m_pwDatabase.NameChanged = DateTime.UtcNow; - } - - string strNew = m_tbDbDesc.Text; - string strOrgFlt = StrUtil.NormalizeNewLines(m_pwDatabase.Description, false); - string strNewFlt = StrUtil.NormalizeNewLines(strNew, false); - if(strNewFlt != strOrgFlt) - { - m_pwDatabase.Description = strNew; - m_pwDatabase.DescriptionChanged = DateTime.UtcNow; - } - - if(m_tbDefaultUser.Text != m_pwDatabase.DefaultUserName) - { - m_pwDatabase.DefaultUserName = m_tbDefaultUser.Text; - m_pwDatabase.DefaultUserNameChanged = DateTime.UtcNow; - } - - if(!m_cbColor.Checked) m_pwDatabase.Color = Color.Empty; - else m_pwDatabase.Color = m_clr; - - int nCipher = CipherPool.GlobalPool.GetCipherIndex(m_cmbEncAlgo.Text); - Debug.Assert(nCipher >= 0); - if(nCipher >= 0) - m_pwDatabase.DataCipherUuid = CipherPool.GlobalPool[nCipher].CipherUuid; - else - m_pwDatabase.DataCipherUuid = StandardAesEngine.AesUuid; - - // m_pwDatabase.KeyEncryptionRounds = (ulong)m_numKdfIt.Value; - KdfParameters pKdf = GetKdfParameters(true); - if(pKdf != null) m_pwDatabase.KdfParameters = pKdf; - // No assert, plugins may assign KDF parameters - - if(m_rbNone.Checked) m_pwDatabase.Compression = PwCompressionAlgorithm.None; - else if(m_rbGZip.Checked) m_pwDatabase.Compression = PwCompressionAlgorithm.GZip; - else { Debug.Assert(false); } - - // m_pwDatabase.MemoryProtection.ProtectTitle = UpdateMemoryProtection(0, - // m_pwDatabase.MemoryProtection.ProtectTitle, PwDefs.TitleField); - // m_pwDatabase.MemoryProtection.ProtectUserName = UpdateMemoryProtection(1, - // m_pwDatabase.MemoryProtection.ProtectUserName, PwDefs.UserNameField); - // m_pwDatabase.MemoryProtection.ProtectPassword = UpdateMemoryProtection(2, - // m_pwDatabase.MemoryProtection.ProtectPassword, PwDefs.PasswordField); - // m_pwDatabase.MemoryProtection.ProtectUrl = UpdateMemoryProtection(3, - // m_pwDatabase.MemoryProtection.ProtectUrl, PwDefs.UrlField); - // m_pwDatabase.MemoryProtection.ProtectNotes = UpdateMemoryProtection(4, - // m_pwDatabase.MemoryProtection.ProtectNotes, PwDefs.NotesField); - - // m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = m_cbAutoEnableHiding.Checked; - - if(m_cbRecycleBin.Checked != m_pwDatabase.RecycleBinEnabled) - { - m_pwDatabase.RecycleBinEnabled = m_cbRecycleBin.Checked; - m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; - } - int iRecBinSel = m_cmbRecycleBin.SelectedIndex; - if(m_dictRecycleBinGroups.ContainsKey(iRecBinSel)) - { - if(!m_dictRecycleBinGroups[iRecBinSel].Equals(m_pwDatabase.RecycleBinUuid)) - { - m_pwDatabase.RecycleBinUuid = m_dictRecycleBinGroups[iRecBinSel]; - m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; - } - } - else - { - Debug.Assert(false); - if(!PwUuid.Zero.Equals(m_pwDatabase.RecycleBinUuid)) - { - m_pwDatabase.RecycleBinUuid = PwUuid.Zero; - m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; - } - } - - int iTemplSel = m_cmbEntryTemplates.SelectedIndex; - if(m_dictEntryTemplateGroups.ContainsKey(iTemplSel)) - { - if(!m_dictEntryTemplateGroups[iTemplSel].Equals(m_pwDatabase.EntryTemplatesGroup)) - { - m_pwDatabase.EntryTemplatesGroup = m_dictEntryTemplateGroups[iTemplSel]; - m_pwDatabase.EntryTemplatesGroupChanged = DateTime.UtcNow; - } - } - else - { - Debug.Assert(false); - if(!PwUuid.Zero.Equals(m_pwDatabase.EntryTemplatesGroup)) - { - m_pwDatabase.EntryTemplatesGroup = PwUuid.Zero; - m_pwDatabase.EntryTemplatesGroupChanged = DateTime.UtcNow; - } - } - - if(!m_cbHistoryMaxItems.Checked) m_pwDatabase.HistoryMaxItems = -1; - else m_pwDatabase.HistoryMaxItems = (int)m_numHistoryMaxItems.Value; - - if(!m_cbHistoryMaxSize.Checked) m_pwDatabase.HistoryMaxSize = -1; - else m_pwDatabase.HistoryMaxSize = (long)m_numHistoryMaxSize.Value * 1024 * 1024; - - m_pwDatabase.MaintainBackups(); // Apply new history settings - - if(!m_cbKeyRec.Checked) m_pwDatabase.MasterKeyChangeRec = -1; - else m_pwDatabase.MasterKeyChangeRec = (long)m_numKeyRecDays.Value; - - if(!m_cbKeyForce.Checked) m_pwDatabase.MasterKeyChangeForce = -1; - else m_pwDatabase.MasterKeyChangeForce = (long)m_numKeyForceDays.Value; - - m_pwDatabase.MasterKeyChangeForceOnce = m_cbKeyForceOnce.Checked; - } - - // private bool UpdateMemoryProtection(int nIndex, bool bOldSetting, - // string strFieldID) - // { - // bool bNewProt = m_lbMemProt.GetItemChecked(nIndex); - // if(bNewProt != bOldSetting) - // m_pwDatabase.RootGroup.EnableStringFieldProtection(strFieldID, bNewProt); - // #if DEBUG - // EntryHandler eh = delegate(PwEntry pe) - // { - // ProtectedString ps = pe.Strings.Get(strFieldID); - // if(ps != null) { Debug.Assert(ps.IsProtected == bNewProt); } - // return true; - // }; - // Debug.Assert(m_pwDatabase.RootGroup.TraverseTree( - // TraversalMethod.PreOrder, null, eh)); - // #endif - // return bNewProt; - // } - - private void OnBtnCancel(object sender, EventArgs e) - { - } - - private void OnBtnHelp(object sender, EventArgs e) - { - string strSubTopic = null; - if(m_tabMain.SelectedTab == m_tabGeneral) - strSubTopic = AppDefs.HelpTopics.DbSettingsGeneral; - else if(m_tabMain.SelectedTab == m_tabSecurity) - strSubTopic = AppDefs.HelpTopics.DbSettingsSecurity; - // else if(m_tabMain.SelectedTab == m_tabProtection) - // strSubTopic = AppDefs.HelpTopics.DbSettingsProtection; - else if(m_tabMain.SelectedTab == m_tabCompression) - strSubTopic = AppDefs.HelpTopics.DbSettingsCompression; - - AppHelp.ShowHelp(AppDefs.HelpTopics.DatabaseSettings, strSubTopic); - } - - private bool AbortKdfThread() - { - if(m_thKdf == null) return false; - - try { m_thKdf.Abort(); } - catch(Exception) { Debug.Assert(false); } - m_thKdf = null; - - return true; - } - - private void OnFormClosed(object sender, FormClosedEventArgs e) - { - if(AbortKdfThread()) { Debug.Assert(false); } - - GlobalWindowManager.RemoveWindow(this); - - foreach(ColorMenuItem mi in m_vColorItems) - mi.Click -= this.HandleColorButtonClicked; - m_vColorItems.Clear(); - - UIUtil.DisposeButtonImage(m_btnColor, ref m_imgColor); - } - - private void OnKeyRecCheckedChanged(object sender, EventArgs e) - { - EnableControlsEx(); - } - - private void OnKeyForceCheckedChanged(object sender, EventArgs e) - { - EnableControlsEx(); - } - - // private void OnLinkClickedMemProtHelp(object sender, LinkLabelLinkClickedEventArgs e) - // { - // AppHelp.ShowHelp(AppDefs.HelpTopics.FaqTech, AppDefs.HelpTopics.FaqTechMemProt); - // } - - private void OnHistoryMaxItemsCheckedChanged(object sender, EventArgs e) - { - EnableControlsEx(); - } - - private void OnHistoryMaxSizeCheckedChanged(object sender, EventArgs e) - { - EnableControlsEx(); - } - - private void HandleColorButtonClicked(object sender, EventArgs e) - { - if(sender == null) { Debug.Assert(false); return; } - ColorMenuItem mi = (sender as ColorMenuItem); - if(mi == null) { Debug.Assert(false); return; } - - m_clr = mi.Color; - UIUtil.OverwriteButtonImage(m_btnColor, ref m_imgColor, - UIUtil.CreateColorBitmap24(m_btnColor, m_clr)); - } - - private void OnBtnColor(object sender, EventArgs e) - { - // Color? clr = UIUtil.ShowColorDialog(m_clr); - // if(clr.HasValue) - // { - // float h, s, v; - // UIUtil.ColorToHsv(clr.Value, out h, out s, out v); - // m_clr = UIUtil.ColorFromHsv(h, 1.0f, 1.0f); - // UIUtil.OverwriteButtonImage(m_btnColor, ref m_imgColor, - // UIUtil.CreateColorBitmap24(m_btnColor, m_clr)); - // } - - if(m_ctxColor == null) - { - m_ctxColor = new CustomContextMenuEx(); - - int qSize = (int)((20.0f * m_btnColor.Height) / 23.0f + 0.01f); - - // const int nMaxColors = 64; - int nMaxColors = AppIcons.Colors.Length; - int nBreakAt = (int)Math.Sqrt(0.1 + nMaxColors); - - // m_ctxColor.LayoutStyle = ToolStripLayoutStyle.Flow; - // FlowLayoutSettings fls = (m_ctxColor.LayoutSettings as FlowLayoutSettings); - // if(fls == null) { Debug.Assert(false); return; } - // fls.FlowDirection = FlowDirection.LeftToRight; - - // m_ctxColor.LayoutStyle = ToolStripLayoutStyle.Table; - // TableLayoutSettings tls = (m_ctxColor.LayoutSettings as TableLayoutSettings); - // if(tls == null) { Debug.Assert(false); return; } - // tls.ColumnCount = nBreakAt; - // tls.RowCount = nBreakAt; - - // m_ctxColor.SuspendLayout(); - - for(int i = 0; i < nMaxColors; ++i) - { - // float fHue = ((float)i * 360.0f) / (float)nMaxColors; - // Color clr = UIUtil.ColorFromHsv(fHue, 1.0f, 1.0f); - Color clr = AppIcons.Colors[i]; - - // Image img = UIUtil.CreateColorBitmap24(16, 16, clr); - // ToolStripButton btn = new ToolStripButton(string.Empty, img); - // btn.DisplayStyle = ToolStripItemDisplayStyle.Image; - // btn.ImageAlign = ContentAlignment.MiddleCenter; - // btn.AutoSize = true; - - ColorMenuItem mi = new ColorMenuItem(clr, qSize); - - if((i > 0) && ((i % nBreakAt) == 0)) - mi.Break = true; - // fls.SetFlowBreak(btn, true); - - mi.Click += this.HandleColorButtonClicked; - - // m_ctxColor.Items.Add(btn); - m_vColorItems.Add(mi); - } - - m_ctxColor.MenuItems.AddRange(m_vColorItems.ToArray()); - - // m_ctxColor.ResumeLayout(true); - // this.Controls.Add(m_ctxColor); - // m_ctxColor.BringToFront(); - } - - // m_ctxColor.Show(m_btnColor, new Point(0, m_btnColor.Height)); - // m_ctxColor.Location = new Point(m_btnColor.Location.X, - // m_btnColor.Location.Y - m_btnColor.Height - m_ctxColor.Height); - // m_ctxColor.Visible = true; - // m_ctxColor.Show(); - - m_ctxColor.ShowEx(m_btnColor); - } - - private void OnColorCheckedChanged(object sender, EventArgs e) - { - EnableControlsEx(); - } - - private KdfEngine GetKdf() - { - return KdfPool.Get(m_cmbKdf.Text); - } - - private KdfParameters GetKdfParameters(bool bShowAdjustments) - { - KdfEngine kdf = GetKdf(); - if(kdf == null) { Debug.Assert(false); return null; } - - string strAdj = string.Empty; - - KdfParameters pKdf = kdf.GetDefaultParameters(); - if(kdf is AesKdf) - pKdf.SetUInt64(AesKdf.ParamRounds, (ulong)m_numKdfIt.Value); - else if(kdf is Argon2Kdf) - { - ulong uIt = (ulong)m_numKdfIt.Value; - AdjustKdfParam(ref uIt, ">=", Argon2Kdf.MinIterations, - KPRes.Iterations, ref strAdj); - AdjustKdfParam(ref uIt, "<=", Argon2Kdf.MaxIterations, - KPRes.Iterations, ref strAdj); - pKdf.SetUInt64(Argon2Kdf.ParamIterations, uIt); - - // Adjust parallelism first, as memory depends on it - uint uPar = (uint)m_numKdfPar.Value; - AdjustKdfParam(ref uPar, ">=", Argon2Kdf.MinParallelism, - KPRes.Parallelism, ref strAdj); - uint uParMax = Argon2Kdf.MaxParallelism; - int cp = Environment.ProcessorCount; - if((cp > 0) && (cp <= (int.MaxValue / 2))) - uParMax = Math.Min(uParMax, (uint)(cp * 2)); - AdjustKdfParam(ref uPar, "<=", uParMax, - KPRes.Parallelism, ref strAdj); - pKdf.SetUInt32(Argon2Kdf.ParamParallelism, uPar); - - ulong uMem = (ulong)m_numKdfMem.Value; - int iMemUnit = m_cmbKdfMem.SelectedIndex; - while(iMemUnit > 0) - { - if(uMem > (ulong.MaxValue / 1024UL)) - { - uMem = ulong.MaxValue; - break; - } - - uMem *= 1024UL; - --iMemUnit; - } - - // 8*p blocks = 1024*8*p bytes minimum memory, see spec - Debug.Assert(Argon2Kdf.MinMemory == (1024UL * 8UL)); - ulong uMemMin = Argon2Kdf.MinMemory * uPar; - AdjustKdfParam(ref uMem, ">=", uMemMin, - KPRes.Memory, ref strAdj); - AdjustKdfParam(ref uMem, "<=", Argon2Kdf.MaxMemory, - KPRes.Memory, ref strAdj); - pKdf.SetUInt64(Argon2Kdf.ParamMemory, uMem); - } - else return null; // Plugins may handle it - - if(bShowAdjustments && (strAdj.Length > 0)) - { - strAdj = KPRes.KdfAdjust + MessageService.NewParagraph + strAdj; - MessageService.ShowInfo(strAdj); - } - - return pKdf; - } - - private static void AdjustKdfParam(ref T tValue, string strReq, - T tCmp, string strName, ref string strAdj) - where T : struct, IComparable - { - if(strReq == ">=") - { - if(tValue.CompareTo(tCmp) >= 0) return; - } - else if(strReq == "<=") - { - if(tValue.CompareTo(tCmp) <= 0) return; - } - else { Debug.Assert(false); return; } - - if(strAdj.Length > 0) - strAdj += MessageService.NewLine; - strAdj += "* " + strName + ": " + tValue.ToString() + - " -> " + tCmp.ToString() + "."; - - tValue = tCmp; - } - - private void SetKdfParameters(KdfParameters p) - { - if(p == null) { Debug.Assert(false); return; } - - KdfEngine kdf = KdfPool.Get(p.KdfUuid); - if(kdf == null) { Debug.Assert(false); return; } - - for(int i = 0; i < m_cmbKdf.Items.Count; ++i) - { - string strKdf = (m_cmbKdf.Items[i] as string); - if(string.IsNullOrEmpty(strKdf)) { Debug.Assert(false); continue; } - - if(strKdf.Equals(kdf.Name, StrUtil.CaseIgnoreCmp)) - { - bool bPrevInit = m_bInitializing; - m_bInitializing = true; // Prevent selection handler - - m_cmbKdf.SelectedIndex = i; - - m_bInitializing = bPrevInit; - break; - } - } - - if(kdf is AesKdf) - { - ulong uIt = p.GetUInt64(AesKdf.ParamRounds, - PwDefs.DefaultKeyEncryptionRounds); - SetKdfParameters(uIt, 1024, 2); - } - else if(kdf is Argon2Kdf) - { - ulong uIt = p.GetUInt64(Argon2Kdf.ParamIterations, - Argon2Kdf.DefaultIterations); - ulong uMem = p.GetUInt64(Argon2Kdf.ParamMemory, - Argon2Kdf.DefaultMemory); - uint uPar = p.GetUInt32(Argon2Kdf.ParamParallelism, - Argon2Kdf.DefaultParallelism); - SetKdfParameters(uIt, uMem, uPar); - } - // else { Debug.Assert(false); } // Plugins may provide other KDFs - } - - private void SetKdfParameters(ulong uIt, ulong uMem, uint uPar) - { - m_numKdfIt.Value = uIt; - - int nUnits = m_cmbKdfMem.Items.Count; - if((nUnits == 0) || (uMem == 0)) - { - m_numKdfMem.Value = uMem; - if(nUnits > 0) m_cmbKdfMem.SelectedIndex = 0; - else { Debug.Assert(false); } - return; - } - - ulong uMemWrtUnit = uMem; - int iUnit = 0; - while(iUnit < (nUnits - 1)) - { - if((uMemWrtUnit % 1024UL) != 0UL) break; - - uMemWrtUnit /= 1024UL; - ++iUnit; - } - - m_numKdfMem.Value = uMemWrtUnit; - m_cmbKdfMem.SelectedIndex = iUnit; - - m_numKdfPar.Value = uPar; - } - - private void OnKdfSelectedIndexChanged(object sender, EventArgs e) - { - if(m_bInitializing) return; - - KdfEngine kdf = GetKdf(); - if(kdf == null) { Debug.Assert(false); return; } - - SetKdfParameters(kdf.GetDefaultParameters()); - EnableControlsEx(); - } - - private void OnBtnKdf1Sec(object sender, EventArgs e) - { - KdfEngine kdf = GetKdf(); - if(kdf == null) { Debug.Assert(false); return; } - - if(!(kdf is AesKdf) && !(kdf is Argon2Kdf)) return; // No assert, plugins - if(m_thKdf != null) { Debug.Assert(false); return; } - - try - { - m_thKdf = new Thread(new ParameterizedThreadStart(this.Kdf1SecTh)); - EnableControlsEx(); // Disable controls (m_thKdf is not null) - - m_thKdf.Start(kdf); - } - catch(Exception) - { - Debug.Assert(false); - m_thKdf = null; - EnableControlsEx(); - } - } - - private void Kdf1SecTh(object o) - { - KdfParameters p = null; - string strMsg = null; - - try - { - KdfEngine kdf = (o as KdfEngine); - if(kdf != null) p = kdf.GetBestParameters(1000); - else { Debug.Assert(false); } - } - catch(ThreadAbortException) - { - try { Thread.ResetAbort(); } - catch(Exception) { Debug.Assert(false); } - return; - } - catch(Exception ex) - { - if((ex != null) && !string.IsNullOrEmpty(ex.Message)) - strMsg = ex.Message; - } - finally { m_thKdf = null; } // Before continuation, to enable controls - - try { m_btnOK.Invoke(new KdfpDelegate(this.Kdf1SecPost), p, strMsg); } - catch(Exception) { Debug.Assert(false); } - } - - private delegate void KdfpDelegate(KdfParameters p, string strMsg); - - private void Kdf1SecPost(KdfParameters p, string strMsg) - { - try - { - Debug.Assert(!m_btnOK.InvokeRequired); - - if(!string.IsNullOrEmpty(strMsg)) - MessageService.ShowInfo(strMsg); - else SetKdfParameters(p); - - EnableControlsEx(); - } - catch(Exception) { Debug.Assert(false); } - } - - private void OnBtnKdfTest(object sender, EventArgs e) - { - KdfParameters p = GetKdfParameters(true); - if(p == null) return; // No assert, plugins - - if(m_thKdf != null) { Debug.Assert(false); return; } - - try - { - SetKdfParameters(p); // Show auto-adjusted parameters - - m_thKdf = new Thread(new ParameterizedThreadStart(this.KdfTestTh)); - EnableControlsEx(); // Disable controls (m_thKdf is not null) - - m_thKdf.Start(p); - } - catch(Exception) - { - Debug.Assert(false); - m_thKdf = null; - EnableControlsEx(); - } - } - - private void KdfTestTh(object o) - { - string strMsg = KLRes.UnknownError; - - try - { - KdfParameters p = (o as KdfParameters); - if(p == null) { Debug.Assert(false); return; } - - KdfEngine kdf = KdfPool.Get(p.KdfUuid); - if(kdf == null) { Debug.Assert(false); return; } - - byte[] pbMsg = new byte[32]; - Program.GlobalRandom.NextBytes(pbMsg); - - kdf.Randomize(p); - - Stopwatch sw = Stopwatch.StartNew(); - kdf.Transform(pbMsg, p); - sw.Stop(); - - long lMS = sw.ElapsedMilliseconds; - lMS = Math.Max(lMS, 1L); - double dS = (double)lMS / 1000.0; - - strMsg = KPRes.TestSuccess + MessageService.NewParagraph + - KPRes.TransformTime.Replace(@"{PARAM}", dS.ToString()); - } - catch(ThreadAbortException) - { - try { Thread.ResetAbort(); } - catch(Exception) { Debug.Assert(false); } - return; - } - catch(Exception ex) - { - Debug.Assert(false); - if((ex != null) && !string.IsNullOrEmpty(ex.Message)) - strMsg = ex.Message; - } - finally { m_thKdf = null; } // Before continuation, to enable controls - - try { m_btnOK.Invoke(new KdfsDelegate(this.KdfTestPost), strMsg); } - catch(Exception) { Debug.Assert(false); } - } - - private delegate void KdfsDelegate(string strMsg); - - private void KdfTestPost(string strMsg) - { - try - { - Debug.Assert(!m_btnOK.InvokeRequired); - - EnableControlsEx(); - - if(!string.IsNullOrEmpty(strMsg)) - MessageService.ShowInfo(strMsg); - else { Debug.Assert(false); } - } - catch(Exception) { Debug.Assert(false); } - } - - private void OnBtnCancelOp(object sender, EventArgs e) - { - AbortKdfThread(); - EnableControlsEx(); - } - } + m_numKdfMem.Minimum = ulong.MinValue; + m_numKdfMem.Maximum = ulong.MaxValue; + + Debug.Assert(m_cmbKdfMem.Items.Count == 0); + Debug.Assert(!m_cmbKdfMem.Sorted); + m_cmbKdfMem.Items.Add("B"); + m_cmbKdfMem.Items.Add("KB"); + m_cmbKdfMem.Items.Add("MB"); + m_cmbKdfMem.Items.Add("GB"); + + m_numKdfPar.Minimum = uint.MinValue; + m_numKdfPar.Maximum = uint.MaxValue; + + SetKdfParameters(m_pwDatabase.KdfParameters); + + // m_lbMemProt.Items.Add(KPRes.Title, m_pwDatabase.MemoryProtection.ProtectTitle); + // m_lbMemProt.Items.Add(KPRes.UserName, m_pwDatabase.MemoryProtection.ProtectUserName); + // m_lbMemProt.Items.Add(KPRes.Password, m_pwDatabase.MemoryProtection.ProtectPassword); + // m_lbMemProt.Items.Add(KPRes.Url, m_pwDatabase.MemoryProtection.ProtectUrl); + // m_lbMemProt.Items.Add(KPRes.Notes, m_pwDatabase.MemoryProtection.ProtectNotes); + + // m_cbAutoEnableHiding.Checked = m_pwDatabase.MemoryProtection.AutoEnableVisualHiding; + // m_cbAutoEnableHiding.Checked = false; + + if (m_pwDatabase.Compression == PwCompressionAlgorithm.None) + m_rbNone.Checked = true; + else if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip) + m_rbGZip.Checked = true; + else { Debug.Assert(false); } + + InitRecycleBinTab(); + InitAdvancedTab(); + + m_bInitializing = false; + EnableControlsEx(); + UIUtil.SetFocus(m_tbDbName, this); + } + + private void InitRecycleBinTab() + { + m_cbRecycleBin.Checked = m_pwDatabase.RecycleBinEnabled; + + m_cmbRecycleBin.Items.Add(m_strAutoCreateNew); + m_dictRecycleBinGroups[0] = PwUuid.Zero; + + int iSelect; + UIUtil.CreateGroupList(m_pwDatabase.RootGroup, m_cmbRecycleBin, + m_dictRecycleBinGroups, m_pwDatabase.RecycleBinUuid, out iSelect); + + m_cmbRecycleBin.SelectedIndex = Math.Max(0, iSelect); + } + + private void InitAdvancedTab() + { + m_cmbEntryTemplates.Items.Add("(" + KPRes.None + ")"); + m_dictEntryTemplateGroups[0] = PwUuid.Zero; + + int iSelect; + UIUtil.CreateGroupList(m_pwDatabase.RootGroup, m_cmbEntryTemplates, + m_dictEntryTemplateGroups, m_pwDatabase.EntryTemplatesGroup, out iSelect); + + m_cmbEntryTemplates.SelectedIndex = Math.Max(0, iSelect); + + m_numHistoryMaxItems.Minimum = 0; + m_numHistoryMaxItems.Maximum = int.MaxValue; + bool bHistMaxItems = (m_pwDatabase.HistoryMaxItems >= 0); + m_numHistoryMaxItems.Value = (bHistMaxItems ? m_pwDatabase.HistoryMaxItems : + PwDatabase.DefaultHistoryMaxItems); + m_cbHistoryMaxItems.Checked = bHistMaxItems; + + m_numHistoryMaxSize.Minimum = 0; + m_numHistoryMaxSize.Maximum = long.MaxValue / (1024 * 1024); + bool bHistMaxSize = (m_pwDatabase.HistoryMaxSize >= 0); + m_numHistoryMaxSize.Value = (bHistMaxSize ? m_pwDatabase.HistoryMaxSize : + PwDatabase.DefaultHistoryMaxSize) / (1024 * 1024); + m_cbHistoryMaxSize.Checked = bHistMaxSize; + + m_numKeyRecDays.Minimum = 0; + m_numKeyRecDays.Maximum = long.MaxValue; + bool bChangeRec = (m_pwDatabase.MasterKeyChangeRec >= 0); + m_numKeyRecDays.Value = (bChangeRec ? m_pwDatabase.MasterKeyChangeRec : 182); + m_cbKeyRec.Checked = bChangeRec; + + m_numKeyForceDays.Minimum = 0; + m_numKeyForceDays.Maximum = long.MaxValue; + bool bChangeForce = (m_pwDatabase.MasterKeyChangeForce >= 0); + m_numKeyForceDays.Value = (bChangeForce ? m_pwDatabase.MasterKeyChangeForce : 365); + m_cbKeyForce.Checked = bChangeForce; + + m_cbKeyForceOnce.Checked = m_pwDatabase.MasterKeyChangeForceOnce; + } + + private void EnableControlsEx() + { + if (m_bInitializing) return; + + m_btnColor.Enabled = m_cbColor.Checked; + + KdfEngine kdf = GetKdf(); + if (kdf != null) + { + if (kdf is AesKdf) + { + m_lblKdfMem.Visible = false; + m_numKdfMem.Visible = false; + m_cmbKdfMem.Visible = false; + + m_lblKdfPar.Visible = false; + m_numKdfPar.Visible = false; + } + else if (kdf is Argon2Kdf) + { + m_lblKdfMem.Visible = true; + m_numKdfMem.Visible = true; + m_cmbKdfMem.Visible = true; + + m_lblKdfPar.Visible = true; + m_numKdfPar.Visible = true; + } + // else { Debug.Assert(false); } // Plugins may provide controls + } + else { Debug.Assert(false); } + + m_numHistoryMaxItems.Enabled = m_cbHistoryMaxItems.Checked; + m_numHistoryMaxSize.Enabled = m_cbHistoryMaxSize.Checked; + + bool bEnableDays = ((Program.Config.UI.UIFlags & + (ulong)AceUIFlags.DisableKeyChangeDays) == 0); + m_numKeyRecDays.Enabled = (bEnableDays && m_cbKeyRec.Checked); + m_numKeyForceDays.Enabled = (bEnableDays && m_cbKeyForce.Checked); + m_cbKeyRec.Enabled = bEnableDays; + m_cbKeyForce.Enabled = bEnableDays; + m_cbKeyForceOnce.Enabled = bEnableDays; + + bool bKdfTh = (m_thKdf != null); + m_tabMain.Enabled = !bKdfTh; + + m_pbKdf.Visible = bKdfTh; + + m_btnHelp.Enabled = !bKdfTh; + m_btnCancelOp.Enabled = bKdfTh; + m_btnCancelOp.Visible = bKdfTh; + m_btnOK.Enabled = !bKdfTh; + m_btnCancel.Enabled = !bKdfTh; + } + + private void OnBtnOK(object sender, EventArgs e) + { + m_pwDatabase.SettingsChanged = DateTime.UtcNow; + + if (m_tbDbName.Text != m_pwDatabase.Name) + { + m_pwDatabase.Name = m_tbDbName.Text; + m_pwDatabase.NameChanged = DateTime.UtcNow; + } + + string strNew = m_tbDbDesc.Text; + string strOrgFlt = StrUtil.NormalizeNewLines(m_pwDatabase.Description, false); + string strNewFlt = StrUtil.NormalizeNewLines(strNew, false); + if (strNewFlt != strOrgFlt) + { + m_pwDatabase.Description = strNew; + m_pwDatabase.DescriptionChanged = DateTime.UtcNow; + } + + if (m_tbDefaultUser.Text != m_pwDatabase.DefaultUserName) + { + m_pwDatabase.DefaultUserName = m_tbDefaultUser.Text; + m_pwDatabase.DefaultUserNameChanged = DateTime.UtcNow; + } + + if (!m_cbColor.Checked) m_pwDatabase.Color = Color.Empty; + else m_pwDatabase.Color = m_clr; + + int nCipher = CipherPool.GlobalPool.GetCipherIndex(m_cmbEncAlgo.Text); + Debug.Assert(nCipher >= 0); + if (nCipher >= 0) + m_pwDatabase.DataCipherUuid = CipherPool.GlobalPool[nCipher].CipherUuid; + else + m_pwDatabase.DataCipherUuid = StandardAesEngine.AesUuid; + + // m_pwDatabase.KeyEncryptionRounds = (ulong)m_numKdfIt.Value; + KdfParameters pKdf = GetKdfParameters(true); + if (pKdf != null) m_pwDatabase.KdfParameters = pKdf; + // No assert, plugins may assign KDF parameters + + if (m_rbNone.Checked) m_pwDatabase.Compression = PwCompressionAlgorithm.None; + else if (m_rbGZip.Checked) m_pwDatabase.Compression = PwCompressionAlgorithm.GZip; + else { Debug.Assert(false); } + + // m_pwDatabase.MemoryProtection.ProtectTitle = UpdateMemoryProtection(0, + // m_pwDatabase.MemoryProtection.ProtectTitle, PwDefs.TitleField); + // m_pwDatabase.MemoryProtection.ProtectUserName = UpdateMemoryProtection(1, + // m_pwDatabase.MemoryProtection.ProtectUserName, PwDefs.UserNameField); + // m_pwDatabase.MemoryProtection.ProtectPassword = UpdateMemoryProtection(2, + // m_pwDatabase.MemoryProtection.ProtectPassword, PwDefs.PasswordField); + // m_pwDatabase.MemoryProtection.ProtectUrl = UpdateMemoryProtection(3, + // m_pwDatabase.MemoryProtection.ProtectUrl, PwDefs.UrlField); + // m_pwDatabase.MemoryProtection.ProtectNotes = UpdateMemoryProtection(4, + // m_pwDatabase.MemoryProtection.ProtectNotes, PwDefs.NotesField); + + // m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = m_cbAutoEnableHiding.Checked; + + if (m_cbRecycleBin.Checked != m_pwDatabase.RecycleBinEnabled) + { + m_pwDatabase.RecycleBinEnabled = m_cbRecycleBin.Checked; + m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; + } + int iRecBinSel = m_cmbRecycleBin.SelectedIndex; + if (m_dictRecycleBinGroups.ContainsKey(iRecBinSel)) + { + if (!m_dictRecycleBinGroups[iRecBinSel].Equals(m_pwDatabase.RecycleBinUuid)) + { + m_pwDatabase.RecycleBinUuid = m_dictRecycleBinGroups[iRecBinSel]; + m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; + } + } + else + { + Debug.Assert(false); + if (!PwUuid.Zero.Equals(m_pwDatabase.RecycleBinUuid)) + { + m_pwDatabase.RecycleBinUuid = PwUuid.Zero; + m_pwDatabase.RecycleBinChanged = DateTime.UtcNow; + } + } + + int iTemplSel = m_cmbEntryTemplates.SelectedIndex; + if (m_dictEntryTemplateGroups.ContainsKey(iTemplSel)) + { + if (!m_dictEntryTemplateGroups[iTemplSel].Equals(m_pwDatabase.EntryTemplatesGroup)) + { + m_pwDatabase.EntryTemplatesGroup = m_dictEntryTemplateGroups[iTemplSel]; + m_pwDatabase.EntryTemplatesGroupChanged = DateTime.UtcNow; + } + } + else + { + Debug.Assert(false); + if (!PwUuid.Zero.Equals(m_pwDatabase.EntryTemplatesGroup)) + { + m_pwDatabase.EntryTemplatesGroup = PwUuid.Zero; + m_pwDatabase.EntryTemplatesGroupChanged = DateTime.UtcNow; + } + } + + if (!m_cbHistoryMaxItems.Checked) m_pwDatabase.HistoryMaxItems = -1; + else m_pwDatabase.HistoryMaxItems = (int)m_numHistoryMaxItems.Value; + + if (!m_cbHistoryMaxSize.Checked) m_pwDatabase.HistoryMaxSize = -1; + else m_pwDatabase.HistoryMaxSize = (long)m_numHistoryMaxSize.Value * 1024 * 1024; + + m_pwDatabase.MaintainBackups(); // Apply new history settings + + if (!m_cbKeyRec.Checked) m_pwDatabase.MasterKeyChangeRec = -1; + else m_pwDatabase.MasterKeyChangeRec = (long)m_numKeyRecDays.Value; + + if (!m_cbKeyForce.Checked) m_pwDatabase.MasterKeyChangeForce = -1; + else m_pwDatabase.MasterKeyChangeForce = (long)m_numKeyForceDays.Value; + + m_pwDatabase.MasterKeyChangeForceOnce = m_cbKeyForceOnce.Checked; + } + + // private bool UpdateMemoryProtection(int nIndex, bool bOldSetting, + // string strFieldID) + // { + // bool bNewProt = m_lbMemProt.GetItemChecked(nIndex); + // if(bNewProt != bOldSetting) + // m_pwDatabase.RootGroup.EnableStringFieldProtection(strFieldID, bNewProt); + // #if DEBUG + // EntryHandler eh = delegate(PwEntry pe) + // { + // ProtectedString ps = pe.Strings.Get(strFieldID); + // if(ps != null) { Debug.Assert(ps.IsProtected == bNewProt); } + // return true; + // }; + // Debug.Assert(m_pwDatabase.RootGroup.TraverseTree( + // TraversalMethod.PreOrder, null, eh)); + // #endif + // return bNewProt; + // } + + private void OnBtnCancel(object sender, EventArgs e) + { + } + + private void OnBtnHelp(object sender, EventArgs e) + { + string strSubTopic = null; + if (m_tabMain.SelectedTab == m_tabGeneral) + strSubTopic = AppDefs.HelpTopics.DbSettingsGeneral; + else if (m_tabMain.SelectedTab == m_tabSecurity) + strSubTopic = AppDefs.HelpTopics.DbSettingsSecurity; + // else if(m_tabMain.SelectedTab == m_tabProtection) + // strSubTopic = AppDefs.HelpTopics.DbSettingsProtection; + else if (m_tabMain.SelectedTab == m_tabCompression) + strSubTopic = AppDefs.HelpTopics.DbSettingsCompression; + + AppHelp.ShowHelp(AppDefs.HelpTopics.DatabaseSettings, strSubTopic); + } + + private bool AbortKdfThread() + { + if (m_thKdf == null) return false; + + try { m_thKdf.Dispose(); } + catch (Exception) { Debug.Assert(false); } + m_thKdf = null; + + return true; + } + + private void OnFormClosed(object sender, FormClosedEventArgs e) + { + if (AbortKdfThread()) { Debug.Assert(false); } + + GlobalWindowManager.RemoveWindow(this); + + foreach (ColorMenuItem mi in m_vColorItems) + mi.Click -= this.HandleColorButtonClicked; + m_vColorItems.Clear(); + + UIUtil.DisposeButtonImage(m_btnColor, ref m_imgColor); + } + + private void OnKeyRecCheckedChanged(object sender, EventArgs e) + { + EnableControlsEx(); + } + + private void OnKeyForceCheckedChanged(object sender, EventArgs e) + { + EnableControlsEx(); + } + + // private void OnLinkClickedMemProtHelp(object sender, LinkLabelLinkClickedEventArgs e) + // { + // AppHelp.ShowHelp(AppDefs.HelpTopics.FaqTech, AppDefs.HelpTopics.FaqTechMemProt); + // } + + private void OnHistoryMaxItemsCheckedChanged(object sender, EventArgs e) + { + EnableControlsEx(); + } + + private void OnHistoryMaxSizeCheckedChanged(object sender, EventArgs e) + { + EnableControlsEx(); + } + + private void HandleColorButtonClicked(object sender, EventArgs e) + { + if (sender == null) { Debug.Assert(false); return; } + ColorMenuItem mi = (sender as ColorMenuItem); + if (mi == null) { Debug.Assert(false); return; } + + m_clr = mi.Color; + UIUtil.OverwriteButtonImage(m_btnColor, ref m_imgColor, + UIUtil.CreateColorBitmap24(m_btnColor, m_clr)); + } + + private void OnBtnColor(object sender, EventArgs e) + { + // Color? clr = UIUtil.ShowColorDialog(m_clr); + // if(clr.HasValue) + // { + // float h, s, v; + // UIUtil.ColorToHsv(clr.Value, out h, out s, out v); + // m_clr = UIUtil.ColorFromHsv(h, 1.0f, 1.0f); + // UIUtil.OverwriteButtonImage(m_btnColor, ref m_imgColor, + // UIUtil.CreateColorBitmap24(m_btnColor, m_clr)); + // } + + if (m_ctxColor == null) + { + m_ctxColor = new CustomContextMenuEx(); + + int qSize = (int)((20.0f * m_btnColor.Height) / 23.0f + 0.01f); + + // const int nMaxColors = 64; + int nMaxColors = AppIcons.Colors.Length; + int nBreakAt = (int)Math.Sqrt(0.1 + nMaxColors); + + // m_ctxColor.LayoutStyle = ToolStripLayoutStyle.Flow; + // FlowLayoutSettings fls = (m_ctxColor.LayoutSettings as FlowLayoutSettings); + // if(fls == null) { Debug.Assert(false); return; } + // fls.FlowDirection = FlowDirection.LeftToRight; + + // m_ctxColor.LayoutStyle = ToolStripLayoutStyle.Table; + // TableLayoutSettings tls = (m_ctxColor.LayoutSettings as TableLayoutSettings); + // if(tls == null) { Debug.Assert(false); return; } + // tls.ColumnCount = nBreakAt; + // tls.RowCount = nBreakAt; + + // m_ctxColor.SuspendLayout(); + + for (int i = 0; i < nMaxColors; ++i) + { + // float fHue = ((float)i * 360.0f) / (float)nMaxColors; + // Color clr = UIUtil.ColorFromHsv(fHue, 1.0f, 1.0f); + Color clr = AppIcons.Colors[i]; + + // Image img = UIUtil.CreateColorBitmap24(16, 16, clr); + // ToolStripButton btn = new ToolStripButton(string.Empty, img); + // btn.DisplayStyle = ToolStripItemDisplayStyle.Image; + // btn.ImageAlign = ContentAlignment.MiddleCenter; + // btn.AutoSize = true; + + ColorMenuItem mi = new ColorMenuItem(clr, qSize); + + //if((i > 0) && ((i % nBreakAt) == 0)) + // mi.Break = true; + // fls.SetFlowBreak(btn, true); + + mi.Click += this.HandleColorButtonClicked; + + // m_ctxColor.Items.Add(btn); + m_vColorItems.Add(mi); + } + + m_ctxColor.Items.AddRange(m_vColorItems.ToArray()); + + // m_ctxColor.ResumeLayout(true); + // this.Controls.Add(m_ctxColor); + // m_ctxColor.BringToFront(); + } + + // m_ctxColor.Show(m_btnColor, new Point(0, m_btnColor.Height)); + // m_ctxColor.Location = new Point(m_btnColor.Location.X, + // m_btnColor.Location.Y - m_btnColor.Height - m_ctxColor.Height); + // m_ctxColor.Visible = true; + // m_ctxColor.Show(); + + m_ctxColor.ShowEx(m_btnColor); + } + + private void OnColorCheckedChanged(object sender, EventArgs e) + { + EnableControlsEx(); + } + + private KdfEngine GetKdf() + { + return KdfPool.Get(m_cmbKdf.Text); + } + + private KdfParameters GetKdfParameters(bool bShowAdjustments) + { + KdfEngine kdf = GetKdf(); + if (kdf == null) { Debug.Assert(false); return null; } + + string strAdj = string.Empty; + + KdfParameters pKdf = kdf.GetDefaultParameters(); + if (kdf is AesKdf) + pKdf.SetUInt64(AesKdf.ParamRounds, (ulong)m_numKdfIt.Value); + else if (kdf is Argon2Kdf) + { + ulong uIt = (ulong)m_numKdfIt.Value; + AdjustKdfParam(ref uIt, ">=", Argon2Kdf.MinIterations, + KPRes.Iterations, ref strAdj); + AdjustKdfParam(ref uIt, "<=", Argon2Kdf.MaxIterations, + KPRes.Iterations, ref strAdj); + pKdf.SetUInt64(Argon2Kdf.ParamIterations, uIt); + + // Adjust parallelism first, as memory depends on it + uint uPar = (uint)m_numKdfPar.Value; + AdjustKdfParam(ref uPar, ">=", Argon2Kdf.MinParallelism, + KPRes.Parallelism, ref strAdj); + uint uParMax = Argon2Kdf.MaxParallelism; + int cp = Environment.ProcessorCount; + if ((cp > 0) && (cp <= (int.MaxValue / 2))) + uParMax = Math.Min(uParMax, (uint)(cp * 2)); + AdjustKdfParam(ref uPar, "<=", uParMax, + KPRes.Parallelism, ref strAdj); + pKdf.SetUInt32(Argon2Kdf.ParamParallelism, uPar); + + ulong uMem = (ulong)m_numKdfMem.Value; + int iMemUnit = m_cmbKdfMem.SelectedIndex; + while (iMemUnit > 0) + { + if (uMem > (ulong.MaxValue / 1024UL)) + { + uMem = ulong.MaxValue; + break; + } + + uMem *= 1024UL; + --iMemUnit; + } + + // 8*p blocks = 1024*8*p bytes minimum memory, see spec + Debug.Assert(Argon2Kdf.MinMemory == (1024UL * 8UL)); + ulong uMemMin = Argon2Kdf.MinMemory * uPar; + AdjustKdfParam(ref uMem, ">=", uMemMin, + KPRes.Memory, ref strAdj); + AdjustKdfParam(ref uMem, "<=", Argon2Kdf.MaxMemory, + KPRes.Memory, ref strAdj); + pKdf.SetUInt64(Argon2Kdf.ParamMemory, uMem); + } + else return null; // Plugins may handle it + + if (bShowAdjustments && (strAdj.Length > 0)) + { + strAdj = KPRes.KdfAdjust + MessageService.NewParagraph + strAdj; + MessageService.ShowInfo(strAdj); + } + + return pKdf; + } + + private static void AdjustKdfParam(ref T tValue, string strReq, + T tCmp, string strName, ref string strAdj) + where T : struct, IComparable + { + if (strReq == ">=") + { + if (tValue.CompareTo(tCmp) >= 0) return; + } + else if (strReq == "<=") + { + if (tValue.CompareTo(tCmp) <= 0) return; + } + else { Debug.Assert(false); return; } + + if (strAdj.Length > 0) + strAdj += MessageService.NewLine; + strAdj += "* " + strName + ": " + tValue.ToString() + + " -> " + tCmp.ToString() + "."; + + tValue = tCmp; + } + + private void SetKdfParameters(KdfParameters p) + { + if (p == null) { Debug.Assert(false); return; } + + KdfEngine kdf = KdfPool.Get(p.KdfUuid); + if (kdf == null) { Debug.Assert(false); return; } + + for (int i = 0; i < m_cmbKdf.Items.Count; ++i) + { + string strKdf = (m_cmbKdf.Items[i] as string); + if (string.IsNullOrEmpty(strKdf)) { Debug.Assert(false); continue; } + + if (strKdf.Equals(kdf.Name, StrUtil.CaseIgnoreCmp)) + { + bool bPrevInit = m_bInitializing; + m_bInitializing = true; // Prevent selection handler + + m_cmbKdf.SelectedIndex = i; + + m_bInitializing = bPrevInit; + break; + } + } + + if (kdf is AesKdf) + { + ulong uIt = p.GetUInt64(AesKdf.ParamRounds, + PwDefs.DefaultKeyEncryptionRounds); + SetKdfParameters(uIt, 1024, 2); + } + else if (kdf is Argon2Kdf) + { + ulong uIt = p.GetUInt64(Argon2Kdf.ParamIterations, + Argon2Kdf.DefaultIterations); + ulong uMem = p.GetUInt64(Argon2Kdf.ParamMemory, + Argon2Kdf.DefaultMemory); + uint uPar = p.GetUInt32(Argon2Kdf.ParamParallelism, + Argon2Kdf.DefaultParallelism); + SetKdfParameters(uIt, uMem, uPar); + } + // else { Debug.Assert(false); } // Plugins may provide other KDFs + } + + private void SetKdfParameters(ulong uIt, ulong uMem, uint uPar) + { + m_numKdfIt.Value = uIt; + + int nUnits = m_cmbKdfMem.Items.Count; + if ((nUnits == 0) || (uMem == 0)) + { + m_numKdfMem.Value = uMem; + if (nUnits > 0) m_cmbKdfMem.SelectedIndex = 0; + else { Debug.Assert(false); } + return; + } + + ulong uMemWrtUnit = uMem; + int iUnit = 0; + while (iUnit < (nUnits - 1)) + { + if ((uMemWrtUnit % 1024UL) != 0UL) break; + + uMemWrtUnit /= 1024UL; + ++iUnit; + } + + m_numKdfMem.Value = uMemWrtUnit; + m_cmbKdfMem.SelectedIndex = iUnit; + + m_numKdfPar.Value = uPar; + } + + private void OnKdfSelectedIndexChanged(object sender, EventArgs e) + { + if (m_bInitializing) return; + + KdfEngine kdf = GetKdf(); + if (kdf == null) { Debug.Assert(false); return; } + + SetKdfParameters(kdf.GetDefaultParameters()); + EnableControlsEx(); + } + + private void OnBtnKdf1Sec(object sender, EventArgs e) + { + KdfEngine kdf = GetKdf(); + if (kdf == null) { Debug.Assert(false); return; } + + if (!(kdf is AesKdf) && !(kdf is Argon2Kdf)) return; // No assert, plugins + if (m_thKdf != null) { Debug.Assert(false); return; } + + try + { + m_thKdf = new Task(() => Kdf1SecTh(null)); + EnableControlsEx(); // Disable controls (m_thKdf is not null) + + } + catch (Exception) + { + Debug.Assert(false); + m_thKdf = null; + EnableControlsEx(); + } + } + + private void Kdf1SecTh(object o) + { + KdfParameters p = null; + string strMsg = null; + + try + { + KdfEngine kdf = (o as KdfEngine); + if (kdf != null) p = kdf.GetBestParameters(1000); + else { Debug.Assert(false); } + } + catch (ThreadAbortException) + { + try { Thread.ResetAbort(); } + catch (Exception) { Debug.Assert(false); } + return; + } + catch (Exception ex) + { + if ((ex != null) && !string.IsNullOrEmpty(ex.Message)) + strMsg = ex.Message; + } + finally { m_thKdf = null; } // Before continuation, to enable controls + + try { m_btnOK.Invoke(new KdfpDelegate(this.Kdf1SecPost), p, strMsg); } + catch (Exception) { Debug.Assert(false); } + } + + private delegate void KdfpDelegate(KdfParameters p, string strMsg); + + private void Kdf1SecPost(KdfParameters p, string strMsg) + { + try + { + Debug.Assert(!m_btnOK.InvokeRequired); + + if (!string.IsNullOrEmpty(strMsg)) + MessageService.ShowInfo(strMsg); + else SetKdfParameters(p); + + EnableControlsEx(); + } + catch (Exception) { Debug.Assert(false); } + } + + private void OnBtnKdfTest(object sender, EventArgs e) + { + KdfParameters p = GetKdfParameters(true); + if (p == null) return; // No assert, plugins + + if (m_thKdf != null) { Debug.Assert(false); return; } + + try + { + SetKdfParameters(p); // Show auto-adjusted parameters + + m_thKdf = new Task(() => Kdf1SecTh(null)); + EnableControlsEx(); // Disable controls (m_thKdf is not null) + + m_thKdf.Start(); + } + catch (Exception) + { + Debug.Assert(false); + m_thKdf = null; + EnableControlsEx(); + } + } + + private void KdfTestTh(object o) + { + string strMsg = KLRes.UnknownError; + + try + { + KdfParameters p = (o as KdfParameters); + if (p == null) { Debug.Assert(false); return; } + + KdfEngine kdf = KdfPool.Get(p.KdfUuid); + if (kdf == null) { Debug.Assert(false); return; } + + byte[] pbMsg = new byte[32]; + Program.GlobalRandom.NextBytes(pbMsg); + + kdf.Randomize(p); + + Stopwatch sw = Stopwatch.StartNew(); + kdf.Transform(pbMsg, p); + sw.Stop(); + + long lMS = sw.ElapsedMilliseconds; + lMS = Math.Max(lMS, 1L); + double dS = (double)lMS / 1000.0; + + strMsg = KPRes.TestSuccess + MessageService.NewParagraph + + KPRes.TransformTime.Replace(@"{PARAM}", dS.ToString()); + } + catch (ThreadAbortException) + { + try { Thread.ResetAbort(); } + catch (Exception) { Debug.Assert(false); } + return; + } + catch (Exception ex) + { + Debug.Assert(false); + if ((ex != null) && !string.IsNullOrEmpty(ex.Message)) + strMsg = ex.Message; + } + finally { m_thKdf = null; } // Before continuation, to enable controls + + try { m_btnOK.Invoke(new KdfsDelegate(this.KdfTestPost), strMsg); } + catch (Exception) { Debug.Assert(false); } + } + + private delegate void KdfsDelegate(string strMsg); + + private void KdfTestPost(string strMsg) + { + try + { + Debug.Assert(!m_btnOK.InvokeRequired); + + EnableControlsEx(); + + if (!string.IsNullOrEmpty(strMsg)) + MessageService.ShowInfo(strMsg); + else { Debug.Assert(false); } + } + catch (Exception) { Debug.Assert(false); } + } + + private void OnBtnCancelOp(object sender, EventArgs e) + { + AbortKdfThread(); + EnableControlsEx(); + } + } } diff --git a/KeePass/KeePass.csproj b/KeePass/KeePass.csproj index 30d6ea1..64e4d88 100644 --- a/KeePass/KeePass.csproj +++ b/KeePass/KeePass.csproj @@ -2,7 +2,7 @@ WinExe - net40 + net5.0-windows true KeePass.ico KeePass.pfx @@ -10,8 +10,4 @@ - - - - \ No newline at end of file diff --git a/KeePass/Program.cs b/KeePass/Program.cs index a6c24f8..0220b3b 100644 --- a/KeePass/Program.cs +++ b/KeePass/Program.cs @@ -752,7 +752,7 @@ internal static Mutex TryGlobalInstanceNotify(string strBaseName) ms.AddAccessRule(mar); bool bCreatedNew; - return new Mutex(false, strName, out bCreatedNew, ms); + return new Mutex(false, strName, out bCreatedNew); } catch(Exception) { } // Windows 9x and Mono 2.0+ (AddAccessRule) throw diff --git a/KeePass/UI/ColorMenuItem.cs b/KeePass/UI/ColorMenuItem.cs index b3af530..7714c17 100644 --- a/KeePass/UI/ColorMenuItem.cs +++ b/KeePass/UI/ColorMenuItem.cs @@ -26,7 +26,7 @@ You should have received a copy of the GNU General Public License namespace KeePass.UI { - public sealed class ColorMenuItem : MenuItem + public sealed class ColorMenuItem : ToolStripMenuItem { private Color m_clr; private int m_qSize; @@ -41,27 +41,27 @@ public ColorMenuItem(Color clr, int qSize) : base() m_clr = clr; m_qSize = qSize; - Debug.Assert(this.CanRaiseEvents); - this.ShowShortcut = false; - this.OwnerDraw = true; + Debug.Assert(CanRaiseEvents); } - protected override void OnDrawItem(DrawItemEventArgs e) + + protected override void OnPaint(PaintEventArgs e) { // base.OnDrawItem(e); Graphics g = e.Graphics; - Rectangle rectBounds = e.Bounds; + Rectangle rectBounds = e.ClipRectangle; Rectangle rectFill = new Rectangle(rectBounds.Left + 2, rectBounds.Top + 2, rectBounds.Width - 4, rectBounds.Height - 4); - bool bFocused = (((e.State & DrawItemState.Focus) != DrawItemState.None) || - ((e.State & DrawItemState.Selected) != DrawItemState.None)); + //bool bFocused = (((State & DrawItemState.Focus) != DrawItemState.None) || + // ((e.State & DrawItemState.Selected) != DrawItemState.None)); // e.DrawBackground(); // e.DrawFocusRectangle(); - using(SolidBrush sbBack = new SolidBrush(bFocused ? - SystemColors.Highlight : SystemColors.Menu)) + //using(SolidBrush sbBack = new SolidBrush(bFocused ? + // SystemColors.Highlight : SystemColors.Menu)) + using (SolidBrush sbBack = new SolidBrush(SystemColors.Menu)) { g.FillRectangle(sbBack, rectBounds); } @@ -72,12 +72,12 @@ protected override void OnDrawItem(DrawItemEventArgs e) } } - protected override void OnMeasureItem(MeasureItemEventArgs e) - { - // base.OnMeasureItem(e); + //protected override void OnMeasureItem(MeasureItemEventArgs e) + //{ + // // base.OnMeasureItem(e); - e.ItemWidth = m_qSize; - e.ItemHeight = m_qSize; - } + // e.ItemWidth = m_qSize; + // e.ItemHeight = m_qSize; + //} } } diff --git a/KeePass/UI/CustomContextMenuEx.cs b/KeePass/UI/CustomContextMenuEx.cs index c9b05a5..057b1d3 100644 --- a/KeePass/UI/CustomContextMenuEx.cs +++ b/KeePass/UI/CustomContextMenuEx.cs @@ -26,21 +26,20 @@ You should have received a copy of the GNU General Public License namespace KeePass.UI { - public sealed class CustomContextMenuEx : ContextMenu - { - public CustomContextMenuEx() : base() { } + public sealed class CustomContextMenuEx : ContextMenuStrip + { + public CustomContextMenuEx() : base() { } - public void ShowEx(Control cParent) - { - if(cParent == null) { Debug.Assert(false); return; } + public void ShowEx(Control cParent) + { + if (cParent == null) { Debug.Assert(false); return; } - if(cParent.RightToLeft == RightToLeft.Yes) - { - this.RightToLeft = RightToLeft.Yes; - Show(cParent, new Point(cParent.Width, cParent.Height), - LeftRightAlignment.Left); - } - else Show(cParent, new Point(0, cParent.Height)); - } - } + if (cParent.RightToLeft == RightToLeft.Yes) + { + this.RightToLeft = RightToLeft.Yes; + Show(cParent, new Point(cParent.Width, cParent.Height), ToolStripDropDownDirection.Left); + } + else Show(cParent, new Point(0, cParent.Height)); + } + } } diff --git a/KeePass/UI/EnableThemingInScope.cs b/KeePass/UI/EnableThemingInScope.cs index b413576..d6ad64c 100644 --- a/KeePass/UI/EnableThemingInScope.cs +++ b/KeePass/UI/EnableThemingInScope.cs @@ -105,12 +105,7 @@ private static bool EnsureActCtxCreated() { if(m_nhCtx.HasValue) return true; - string strAsmLoc; - FileIOPermission p = new FileIOPermission(PermissionState.None); - p.AllFiles = FileIOPermissionAccess.PathDiscovery; - p.Assert(); - try { strAsmLoc = typeof(object).Assembly.Location; } - finally { CodeAccessPermission.RevertAssert(); } + string strAsmLoc = typeof(object).Assembly.Location; if(string.IsNullOrEmpty(strAsmLoc)) { Debug.Assert(false); return false; } string strInstDir = Path.GetDirectoryName(strAsmLoc); diff --git a/KeePass/UI/UIUtil.cs b/KeePass/UI/UIUtil.cs index cfb3c7a..73b5a9f 100644 --- a/KeePass/UI/UIUtil.cs +++ b/KeePass/UI/UIUtil.cs @@ -400,7 +400,7 @@ public static List BuildImageListEx(List lIcons, if(img == null) { Debug.Assert(false); - img = UIUtil.CreateColorBitmap24(nWidth, nHeight, Color.White); + img = CreateColorBitmap24(nWidth, nHeight, Color.White); } if((img.Width != nWidth) || (img.Height != nHeight)) @@ -2629,7 +2629,7 @@ public static Image ExtractVistaIcon(Icon ico) { if(ico == null) { Debug.Assert(false); return null; } - MemoryStream ms = new MemoryStream(); + using MemoryStream ms = new (); try { ico.Save(ms); @@ -2638,7 +2638,6 @@ public static Image ExtractVistaIcon(Icon ico) return GfxUtil.LoadImage(pb); // Extracts best image from ICO } catch { Debug.Assert(false); } - finally { ms.Close(); } return null; } @@ -3342,7 +3341,7 @@ public static bool HandleCommonKeyEvent(KeyEventArgs e, bool bDown, if(bOp) { - ContextMenu cm = cCtx.ContextMenu; + var cm = cCtx.ContextMenuStrip; ContextMenuStrip cms = cCtx.ContextMenuStrip; if(cms != null) cms.Show(Cursor.Position); diff --git a/KeePassLib/Cryptography/CryptoRandom.cs b/KeePassLib/Cryptography/CryptoRandom.cs index ab3fa86..01d920d 100644 --- a/KeePassLib/Cryptography/CryptoRandom.cs +++ b/KeePassLib/Cryptography/CryptoRandom.cs @@ -27,13 +27,13 @@ You should have received a copy of the GNU General Public License #if !KeePassUAP using System.Drawing; using System.Security.Cryptography; -using System.Windows.Forms; #endif using KeePassLib.Delegates; using KeePassLib.Native; using KeePassLib.Security; using KeePassLib.Utility; +using System.Windows.Forms; namespace KeePassLib.Cryptography { @@ -42,16 +42,16 @@ namespace KeePassLib.Cryptography /// The returned values are unpredictable and cannot be reproduced. /// CryptoRandom is a singleton class. /// - public sealed class CryptoRandom + public sealed class CryptoRandom : IDisposable { - private ProtectedBinary m_pbEntropyPool = new ProtectedBinary( + private ProtectedBinary m_pbEntropyPool = new( true, new byte[64]); - private readonly RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider(); + private readonly RNGCryptoServiceProvider m_rng = new(); private ulong m_uCounter; private ulong m_uGeneratedBytesCount = 0; - private static readonly object g_oSyncRoot = new object(); - private readonly object m_oSyncRoot = new object(); + private static readonly object g_oSyncRoot = new(); + private readonly object m_oSyncRoot = new(); private static CryptoRandom g_pInstance = null; public static CryptoRandom Instance @@ -157,33 +157,33 @@ public void AddEntropy(byte[] pbEntropy) private byte[] GetSystemEntropy() { - var h = new SHA512Managed(); + using var h = new SHA512Managed(); var pb4 = new byte[4]; var pb8 = new byte[8]; - GAction f = delegate (byte[] pbValue, bool bClearValue) + void f(byte[] pbValue, bool bClearValue) { if (pbValue == null) { Debug.Assert(false); return; } if (pbValue.Length == 0) return; h.TransformBlock(pbValue, 0, pbValue.Length, pbValue, 0); if (bClearValue) MemUtil.ZeroByteArray(pbValue); - }; - Action fI32 = delegate (int iValue) + } + void fI32(int iValue) { MemUtil.Int32ToBytesEx(iValue, pb4, 0); f(pb4, false); - }; - Action fI64 = delegate (long lValue) + } + void fI64(long lValue) { MemUtil.Int64ToBytesEx(lValue, pb8, 0); f(pb8, false); - }; - Action fStr = delegate (string strValue) + } + void fStr(string strValue) { if (strValue == null) { Debug.Assert(false); return; } if (strValue.Length == 0) return; f(StrUtil.Utf8.GetBytes(strValue), false); - }; + } fI32(Environment.TickCount); fI64(DateTime.UtcNow.ToBinary()); @@ -233,25 +233,23 @@ private byte[] GetSystemEntropy() #if KeePassUAP f(DiagnosticsExt.GetProcessEntropy(), true); #elif !KeePassLibSD - using (var p = Process.GetCurrentProcess()) - { - fI64(p.Handle.ToInt64()); - fI32(p.HandleCount); - fI32(p.Id); - fI64(p.NonpagedSystemMemorySize64); - fI64(p.PagedMemorySize64); - fI64(p.PagedSystemMemorySize64); - fI64(p.PeakPagedMemorySize64); - fI64(p.PeakVirtualMemorySize64); - fI64(p.PeakWorkingSet64); - fI64(p.PrivateMemorySize64); - fI64(p.StartTime.ToBinary()); - fI64(p.VirtualMemorySize64); - fI64(p.WorkingSet64); - - // Not supported in Mono 1.2.6: - // fI32(p.SessionId); - } + using var p = Process.GetCurrentProcess(); + fI64(p.Handle.ToInt64()); + fI32(p.HandleCount); + fI32(p.Id); + fI64(p.NonpagedSystemMemorySize64); + fI64(p.PagedMemorySize64); + fI64(p.PagedSystemMemorySize64); + fI64(p.PeakPagedMemorySize64); + fI64(p.PeakVirtualMemorySize64); + fI64(p.PeakWorkingSet64); + fI64(p.PrivateMemorySize64); + fI64(p.StartTime.ToBinary()); + fI64(p.VirtualMemorySize64); + fI64(p.WorkingSet64); + + // Not supported in Mono 1.2.6: + // fI32(p.SessionId); #endif } catch (Exception) { Debug.Assert(NativeLib.IsUnix()); } @@ -381,5 +379,7 @@ public static Random NewWeakRandom() return new Random(s32); } + + public void Dispose() => m_rng?.Dispose(); } } diff --git a/KeePassLib/KeePassLib.csproj b/KeePassLib/KeePassLib.csproj index c821dff..f2f918f 100644 --- a/KeePassLib/KeePassLib.csproj +++ b/KeePassLib/KeePassLib.csproj @@ -1,13 +1,9 @@ - + - net40 + net5.0-windows KeePassLib.pfx + true - - - - - diff --git a/KeePassLib/Keys/CompositeKey.cs b/KeePassLib/Keys/CompositeKey.cs index f8cf794..cbc535f 100644 --- a/KeePassLib/Keys/CompositeKey.cs +++ b/KeePassLib/Keys/CompositeKey.cs @@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License using System.Diagnostics; using System.Text; using System.Threading; - +using System.Threading.Tasks; using KeePassLib.Cryptography; using KeePassLib.Cryptography.KeyDerivation; using KeePassLib.Interfaces; @@ -33,325 +33,322 @@ You should have received a copy of the GNU General Public License namespace KeePassLib.Keys { - /// - /// Represents a key. A key can be build up using several user key data sources - /// like a password, a key file, the currently logged on user credentials, - /// the current computer ID, etc. - /// - public sealed class CompositeKey - { - private List m_vUserKeys = new List(); - - /// - /// List of all user keys contained in the current composite key. - /// - public IEnumerable UserKeys - { - get { return m_vUserKeys; } - } - - public uint UserKeyCount - { - get { return (uint)m_vUserKeys.Count; } - } - - /// - /// Construct a new, empty key object. - /// - public CompositeKey() - { - } - - // /// - // /// Deconstructor, clears up the key. - // /// - // ~CompositeKey() - // { - // Clear(); - // } - - // /// - // /// Clears the key. This function also erases all previously stored - // /// user key data objects. - // /// - // public void Clear() - // { - // foreach(IUserKey pKey in m_vUserKeys) - // pKey.Clear(); - // m_vUserKeys.Clear(); - // } - - /// - /// Add a user key. - /// - /// User key to add. - public void AddUserKey(IUserKey pKey) - { - Debug.Assert(pKey != null); if(pKey == null) throw new ArgumentNullException("pKey"); - - m_vUserKeys.Add(pKey); - } - - /// - /// Remove a user key. - /// - /// User key to remove. - /// Returns true if the key was removed successfully. - public bool RemoveUserKey(IUserKey pKey) - { - Debug.Assert(pKey != null); if(pKey == null) throw new ArgumentNullException("pKey"); - - Debug.Assert(m_vUserKeys.IndexOf(pKey) >= 0); - return m_vUserKeys.Remove(pKey); - } - - /// - /// Test whether the composite key contains a specific type of - /// user keys (password, key file, ...). If at least one user - /// key of that type is present, the function returns true. - /// - /// User key type. - /// Returns true, if the composite key contains - /// a user key of the specified type. - public bool ContainsType(Type tUserKeyType) - { - Debug.Assert(tUserKeyType != null); - if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType"); - - foreach(IUserKey pKey in m_vUserKeys) - { - if(pKey == null) { Debug.Assert(false); continue; } + /// + /// Represents a key. A key can be build up using several user key data sources + /// like a password, a key file, the currently logged on user credentials, + /// the current computer ID, etc. + /// + public sealed class CompositeKey + { + private List m_vUserKeys = new List(); + + /// + /// List of all user keys contained in the current composite key. + /// + public IEnumerable UserKeys + { + get { return m_vUserKeys; } + } + + public uint UserKeyCount + { + get { return (uint)m_vUserKeys.Count; } + } + + /// + /// Construct a new, empty key object. + /// + public CompositeKey() + { + } + + // /// + // /// Deconstructor, clears up the key. + // /// + // ~CompositeKey() + // { + // Clear(); + // } + + // /// + // /// Clears the key. This function also erases all previously stored + // /// user key data objects. + // /// + // public void Clear() + // { + // foreach(IUserKey pKey in m_vUserKeys) + // pKey.Clear(); + // m_vUserKeys.Clear(); + // } + + /// + /// Add a user key. + /// + /// User key to add. + public void AddUserKey(IUserKey pKey) + { + Debug.Assert(pKey != null); if (pKey == null) throw new ArgumentNullException("pKey"); + + m_vUserKeys.Add(pKey); + } + + /// + /// Remove a user key. + /// + /// User key to remove. + /// Returns true if the key was removed successfully. + public bool RemoveUserKey(IUserKey pKey) + { + Debug.Assert(pKey != null); if (pKey == null) throw new ArgumentNullException("pKey"); + + Debug.Assert(m_vUserKeys.IndexOf(pKey) >= 0); + return m_vUserKeys.Remove(pKey); + } + + /// + /// Test whether the composite key contains a specific type of + /// user keys (password, key file, ...). If at least one user + /// key of that type is present, the function returns true. + /// + /// User key type. + /// Returns true, if the composite key contains + /// a user key of the specified type. + public bool ContainsType(Type tUserKeyType) + { + Debug.Assert(tUserKeyType != null); + if (tUserKeyType == null) throw new ArgumentNullException("tUserKeyType"); + + foreach (IUserKey pKey in m_vUserKeys) + { + if (pKey == null) { Debug.Assert(false); continue; } #if KeePassUAP if(pKey.GetType() == tUserKeyType) return true; #else - if(tUserKeyType.IsInstanceOfType(pKey)) - return true; + if (tUserKeyType.IsInstanceOfType(pKey)) + return true; #endif - } - - return false; - } - - /// - /// Get the first user key of a specified type. - /// - /// Type of the user key to get. - /// Returns the first user key of the specified type - /// or null if no key of that type is found. - public IUserKey GetUserKey(Type tUserKeyType) - { - Debug.Assert(tUserKeyType != null); - if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType"); - - foreach(IUserKey pKey in m_vUserKeys) - { - if(pKey == null) { Debug.Assert(false); continue; } + } + + return false; + } + + /// + /// Get the first user key of a specified type. + /// + /// Type of the user key to get. + /// Returns the first user key of the specified type + /// or null if no key of that type is found. + public IUserKey GetUserKey(Type tUserKeyType) + { + Debug.Assert(tUserKeyType != null); + if (tUserKeyType == null) throw new ArgumentNullException("tUserKeyType"); + + foreach (IUserKey pKey in m_vUserKeys) + { + if (pKey == null) { Debug.Assert(false); continue; } #if KeePassUAP if(pKey.GetType() == tUserKeyType) return pKey; #else - if(tUserKeyType.IsInstanceOfType(pKey)) - return pKey; + if (tUserKeyType.IsInstanceOfType(pKey)) + return pKey; #endif - } - - return null; - } - - /// - /// Creates the composite key from the supplied user key sources (password, - /// key file, user account, computer ID, etc.). - /// - private byte[] CreateRawCompositeKey32() - { - ValidateUserKeys(); - - List lData = new List(); - int cbData = 0; - foreach(IUserKey pKey in m_vUserKeys) - { - ProtectedBinary b = pKey.KeyData; - if(b != null) - { - byte[] pbKeyData = b.ReadData(); - lData.Add(pbKeyData); - cbData += pbKeyData.Length; - } - } - - byte[] pbAllData = new byte[cbData]; - int p = 0; - foreach(byte[] pbData in lData) - { - Array.Copy(pbData, 0, pbAllData, p, pbData.Length); - p += pbData.Length; - MemUtil.ZeroByteArray(pbData); - } - Debug.Assert(p == cbData); - - byte[] pbHash = CryptoUtil.HashSha256(pbAllData); - MemUtil.ZeroByteArray(pbAllData); - return pbHash; - } - - public bool EqualsValue(CompositeKey ckOther) - { - if(ckOther == null) throw new ArgumentNullException("ckOther"); - - bool bEqual; - byte[] pbThis = CreateRawCompositeKey32(); - try - { - byte[] pbOther = ckOther.CreateRawCompositeKey32(); - bEqual = MemUtil.ArraysEqual(pbThis, pbOther); - MemUtil.ZeroByteArray(pbOther); - } - finally { MemUtil.ZeroByteArray(pbThis); } - - return bEqual; - } - - [Obsolete] - public ProtectedBinary GenerateKey32(byte[] pbKeySeed32, ulong uNumRounds) - { - Debug.Assert(pbKeySeed32 != null); - if(pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32"); - Debug.Assert(pbKeySeed32.Length == 32); - if(pbKeySeed32.Length != 32) throw new ArgumentException("pbKeySeed32"); - - AesKdf kdf = new AesKdf(); - KdfParameters p = kdf.GetDefaultParameters(); - p.SetUInt64(AesKdf.ParamRounds, uNumRounds); - p.SetByteArray(AesKdf.ParamSeed, pbKeySeed32); - - return GenerateKey32(p); - } - - /// - /// Generate a 32-byte (256-bit) key from the composite key. - /// - public ProtectedBinary GenerateKey32(KdfParameters p) - { - if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); } - - byte[] pbRaw32 = null, pbTrf32 = null; - ProtectedBinary pbRet = null; - - try - { - pbRaw32 = CreateRawCompositeKey32(); - if((pbRaw32 == null) || (pbRaw32.Length != 32)) - { Debug.Assert(false); return null; } - - KdfEngine kdf = KdfPool.Get(p.KdfUuid); - if(kdf == null) // CryptographicExceptions are translated to "file corrupted" - throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph + - KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph + - "UUID: " + p.KdfUuid.ToHexString() + "."); - - pbTrf32 = kdf.Transform(pbRaw32, p); - if(pbTrf32 == null) { Debug.Assert(false); return null; } - if(pbTrf32.Length != 32) - { - Debug.Assert(false); - pbTrf32 = CryptoUtil.HashSha256(pbTrf32); - } - - pbRet = new ProtectedBinary(true, pbTrf32); - } - finally - { - if(pbRaw32 != null) MemUtil.ZeroByteArray(pbRaw32); - if(pbTrf32 != null) MemUtil.ZeroByteArray(pbTrf32); - } - - return pbRet; - } - - private sealed class CkGkTaskInfo - { - public volatile ProtectedBinary Key = null; - public volatile string Error = null; - } - - internal ProtectedBinary GenerateKey32Ex(KdfParameters p, IStatusLogger sl) - { - if(sl == null) return GenerateKey32(p); - - CkGkTaskInfo ti = new CkGkTaskInfo(); - - ThreadStart f = delegate() - { - if(ti == null) { Debug.Assert(false); return; } - - try { ti.Key = GenerateKey32(p); } - catch(ThreadAbortException exAbort) - { - ti.Error = ((exAbort != null) ? exAbort.Message : null); - Thread.ResetAbort(); - } - catch(Exception ex) - { - Debug.Assert(false); - ti.Error = ((ex != null) ? ex.Message : null); - } - }; - - Thread th = new Thread(f); - th.Start(); - - Debug.Assert(PwDefs.UIUpdateDelay >= 2); - while(!th.Join(PwDefs.UIUpdateDelay / 2)) - { - if(!sl.ContinueWork()) - { - try { th.Abort(); } - catch(Exception) { Debug.Assert(false); } - - throw new OperationCanceledException(); - } - } - - if(!string.IsNullOrEmpty(ti.Error)) throw new Exception(ti.Error); - - Debug.Assert(ti.Key != null); - return ti.Key; - } - - private void ValidateUserKeys() - { - int nAccounts = 0; - - foreach(IUserKey uKey in m_vUserKeys) - { - if(uKey is KcpUserAccount) - ++nAccounts; - } - - if(nAccounts >= 2) - { - Debug.Assert(false); - throw new InvalidOperationException(); - } - } - } - - public sealed class InvalidCompositeKeyException : Exception - { - public override string Message - { - get - { - return (KLRes.InvalidCompositeKey + MessageService.NewParagraph + - KLRes.InvalidCompositeKeyHint); - } - } - - public InvalidCompositeKeyException() - { - } - } + } + + return null; + } + + /// + /// Creates the composite key from the supplied user key sources (password, + /// key file, user account, computer ID, etc.). + /// + private byte[] CreateRawCompositeKey32() + { + ValidateUserKeys(); + + List lData = new List(); + int cbData = 0; + foreach (IUserKey pKey in m_vUserKeys) + { + ProtectedBinary b = pKey.KeyData; + if (b != null) + { + byte[] pbKeyData = b.ReadData(); + lData.Add(pbKeyData); + cbData += pbKeyData.Length; + } + } + + byte[] pbAllData = new byte[cbData]; + int p = 0; + foreach (byte[] pbData in lData) + { + Array.Copy(pbData, 0, pbAllData, p, pbData.Length); + p += pbData.Length; + MemUtil.ZeroByteArray(pbData); + } + Debug.Assert(p == cbData); + + byte[] pbHash = CryptoUtil.HashSha256(pbAllData); + MemUtil.ZeroByteArray(pbAllData); + return pbHash; + } + + public bool EqualsValue(CompositeKey ckOther) + { + if (ckOther == null) throw new ArgumentNullException("ckOther"); + + bool bEqual; + byte[] pbThis = CreateRawCompositeKey32(); + try + { + byte[] pbOther = ckOther.CreateRawCompositeKey32(); + bEqual = MemUtil.ArraysEqual(pbThis, pbOther); + MemUtil.ZeroByteArray(pbOther); + } + finally { MemUtil.ZeroByteArray(pbThis); } + + return bEqual; + } + + [Obsolete] + public ProtectedBinary GenerateKey32(byte[] pbKeySeed32, ulong uNumRounds) + { + Debug.Assert(pbKeySeed32 != null); + if (pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32"); + Debug.Assert(pbKeySeed32.Length == 32); + if (pbKeySeed32.Length != 32) throw new ArgumentException("pbKeySeed32"); + + AesKdf kdf = new AesKdf(); + KdfParameters p = kdf.GetDefaultParameters(); + p.SetUInt64(AesKdf.ParamRounds, uNumRounds); + p.SetByteArray(AesKdf.ParamSeed, pbKeySeed32); + + return GenerateKey32(p); + } + + /// + /// Generate a 32-byte (256-bit) key from the composite key. + /// + public ProtectedBinary GenerateKey32(KdfParameters p) + { + if (p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); } + + byte[] pbRaw32 = null, pbTrf32 = null; + ProtectedBinary pbRet = null; + + try + { + pbRaw32 = CreateRawCompositeKey32(); + if ((pbRaw32 == null) || (pbRaw32.Length != 32)) + { Debug.Assert(false); return null; } + + KdfEngine kdf = KdfPool.Get(p.KdfUuid); + if (kdf == null) // CryptographicExceptions are translated to "file corrupted" + throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph + + KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph + + "UUID: " + p.KdfUuid.ToHexString() + "."); + + pbTrf32 = kdf.Transform(pbRaw32, p); + if (pbTrf32 == null) { Debug.Assert(false); return null; } + if (pbTrf32.Length != 32) + { + Debug.Assert(false); + pbTrf32 = CryptoUtil.HashSha256(pbTrf32); + } + + pbRet = new ProtectedBinary(true, pbTrf32); + } + finally + { + if (pbRaw32 != null) MemUtil.ZeroByteArray(pbRaw32); + if (pbTrf32 != null) MemUtil.ZeroByteArray(pbTrf32); + } + + return pbRet; + } + + private sealed class CkGkTaskInfo + { + public volatile ProtectedBinary Key = null; + public volatile string Error = null; + } + + internal ProtectedBinary GenerateKey32Ex(KdfParameters p, IStatusLogger sl) + { + if (sl == null) return GenerateKey32(p); + + CkGkTaskInfo ti = new CkGkTaskInfo(); + + void f(CancellationToken token) + { + token.ThrowIfCancellationRequested(); + + if (ti == null) { Debug.Assert(false); return; } + + try { ti.Key = GenerateKey32(p); } + catch (Exception ex) + { + Debug.Assert(false); + ti.Error = ((ex != null) ? ex.Message : null); + } + } + + using var source = new CancellationTokenSource(); + var th = Task.Run(() => f(source.Token), source.Token); + + Debug.Assert(PwDefs.UIUpdateDelay >= 2); + while (!th.Wait(PwDefs.UIUpdateDelay / 2)) + { + if (!sl.ContinueWork()) + { + try { source.Cancel(); } + catch (Exception) { Debug.Assert(false); } + + throw new OperationCanceledException(); + } + } + + if (!string.IsNullOrEmpty(ti.Error)) throw new Exception(ti.Error); + + Debug.Assert(ti.Key != null); + return ti.Key; + } + + private void ValidateUserKeys() + { + int nAccounts = 0; + + foreach (IUserKey uKey in m_vUserKeys) + { + if (uKey is KcpUserAccount) + ++nAccounts; + } + + if (nAccounts >= 2) + { + Debug.Assert(false); + throw new InvalidOperationException(); + } + } + } + + public sealed class InvalidCompositeKeyException : Exception + { + public override string Message + { + get + { + return (KLRes.InvalidCompositeKey + MessageService.NewParagraph + + KLRes.InvalidCompositeKeyHint); + } + } + + public InvalidCompositeKeyException() + { + } + } } diff --git a/KeePassLib/Native/NativeLib.cs b/KeePassLib/Native/NativeLib.cs index 8aac9fb..767bb05 100644 --- a/KeePassLib/Native/NativeLib.cs +++ b/KeePassLib/Native/NativeLib.cs @@ -29,11 +29,11 @@ You should have received a copy of the GNU General Public License #if !KeePassUAP using System.IO; using System.Threading; -using System.Windows.Forms; #endif using KeePassLib.Resources; using KeePassLib.Utility; +using System.Windows.Forms; namespace KeePassLib.Native { diff --git a/KeePassLib/Security/ProtectedBinary.cs b/KeePassLib/Security/ProtectedBinary.cs index 97eee5a..311b2fa 100644 --- a/KeePassLib/Security/ProtectedBinary.cs +++ b/KeePassLib/Security/ProtectedBinary.cs @@ -29,6 +29,7 @@ You should have received a copy of the GNU General Public License using KeePassLib.Cryptography.Cipher; using KeePassLib.Native; using KeePassLib.Utility; +using System.Security; #if KeePassLibSD using KeePassLibSD; @@ -79,51 +80,7 @@ private enum PbMemProt ExtCrypt } - // ProtectedMemory is supported only on Windows 2000 SP3 and higher -#if !KeePassLibSD - private static bool? g_obProtectedMemorySupported = null; -#endif - private static bool ProtectedMemorySupported - { - get - { -#if KeePassLibSD - return false; -#else - bool? ob = g_obProtectedMemorySupported; - if(ob.HasValue) return ob.Value; - - // Mono does not implement any encryption for ProtectedMemory - // on Linux (Mono uses DPAPI on Windows); - // https://sourceforge.net/p/keepass/feature-requests/1907/ - if(NativeLib.IsUnix()) - { - g_obProtectedMemorySupported = false; - return false; - } - - ob = false; - try // Test whether ProtectedMemory is supported - { - // BlockSize * 3 in order to test encryption for multiple - // blocks, but not introduce a power of 2 as factor - byte[] pb = new byte[ProtectedBinary.BlockSize * 3]; - for(int i = 0; i < pb.Length; ++i) pb[i] = (byte)i; - - ProtectedMemory.Protect(pb, MemoryProtectionScope.SameProcess); - - for(int i = 0; i < pb.Length; ++i) - { - if(pb[i] != (byte)i) { ob = true; break; } - } - } - catch(Exception) { } // Windows 98 / ME - - g_obProtectedMemorySupported = ob; - return ob.Value; -#endif - } - } + private static bool ProtectedMemorySupported => false; //.NET 5.0 no longer Support ProtectedMemory private static long g_lCurID = 0; private long m_lID; @@ -270,7 +227,7 @@ private void Encrypt() if(ProtectedBinary.ProtectedMemorySupported) { - ProtectedMemory.Protect(m_pbData, MemoryProtectionScope.SameProcess); + //ProtectedMemory.Protect(m_pbData, MemoryProtectionScope.SameProcess); m_mp = PbMemProt.ProtectedMemory; return; @@ -298,9 +255,7 @@ private void Decrypt() { if(m_pbData.Length == 0) return; - if(m_mp == PbMemProt.ProtectedMemory) - ProtectedMemory.Unprotect(m_pbData, MemoryProtectionScope.SameProcess); - else if(m_mp == PbMemProt.ChaCha20) + if(m_mp == PbMemProt.ChaCha20) { byte[] pbIV = new byte[12]; MemUtil.UInt64ToBytesEx((ulong)m_lID, pbIV, 4); diff --git a/KeePassLib/Serialization/FileTransactionEx.cs b/KeePassLib/Serialization/FileTransactionEx.cs index f66a8b6..bcf1d1e 100644 --- a/KeePassLib/Serialization/FileTransactionEx.cs +++ b/KeePassLib/Serialization/FileTransactionEx.cs @@ -230,8 +230,8 @@ private void CommitWriteTransaction() otCreation = File.GetCreationTimeUtc(m_iocBase.Path); sStat = SimpleStat.Get(m_iocBase.Path); #if !KeePassUAP - // May throw with Mono - FileSecurity sec = File.GetAccessControl(m_iocBase.Path, acs); + // May throw with Mono + FileSecurity sec = new (m_iocBase.Path, acs); if(sec != null) pbSec = sec.GetSecurityDescriptorBinaryForm(); #endif } @@ -274,10 +274,8 @@ private void CommitWriteTransaction() // https://msdn.microsoft.com/en-us/library/system.io.file.setaccesscontrol.aspx if((pbSec != null) && (pbSec.Length != 0)) { - FileSecurity sec = new FileSecurity(); + FileSecurity sec = new FileSecurity(m_iocBase.Path, acs); sec.SetSecurityDescriptorBinaryForm(pbSec, acs); - - File.SetAccessControl(m_iocBase.Path, sec); } #endif } diff --git a/KeePassLib/Serialization/IOConnection.cs b/KeePassLib/Serialization/IOConnection.cs index 36e33e0..00951a4 100644 --- a/KeePassLib/Serialization/IOConnection.cs +++ b/KeePassLib/Serialization/IOConnection.cs @@ -508,7 +508,7 @@ private static void PrepareWebAccess(IOConnectionInfo ioc) try { - SecurityProtocolType spt = (SecurityProtocolType.Ssl3 | + SecurityProtocolType spt = (SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls); // The flags Tls11 and Tls12 in SecurityProtocolType have been diff --git a/KeePassLib/Utility/MonoWorkarounds.cs b/KeePassLib/Utility/MonoWorkarounds.cs index f6b7e6f..ead9f54 100644 --- a/KeePassLib/Utility/MonoWorkarounds.cs +++ b/KeePassLib/Utility/MonoWorkarounds.cs @@ -30,6 +30,7 @@ You should have received a copy of the GNU General Public License using System.Text; using System.Threading; using System.Xml; +using System.Threading.Tasks; #if !KeePassUAP using System.Windows.Forms; @@ -44,7 +45,7 @@ public static class MonoWorkarounds private const string AppXDoTool = "xdotool"; private static readonly Dictionary g_dForceReq = new Dictionary(); - private static Thread g_thFixClip = null; + private static Task g_thFixClip = null; // private static Predicate g_fOwnWindow = null; #if DEBUG_BREAKONFAIL @@ -256,9 +257,9 @@ internal static void Initialize() { try { - var ts = new ThreadStart(MonoWorkarounds.FixClipThread); - g_thFixClip = new Thread(ts); + g_thFixClip = new Task(FixClipThread, CancellationToken.None, TaskCreationOptions.LongRunning); g_thFixClip.Start(); + } catch (Exception) { Debug.Assert(false); } } @@ -276,7 +277,7 @@ internal static void Terminate() { if (g_thFixClip != null) { - try { g_thFixClip.Abort(); } + try { g_thFixClip.Dispose(); } catch (Exception) { Debug.Assert(false); } g_thFixClip = null; diff --git a/KeePassLib/Utility/XmlUtilEx.cs b/KeePassLib/Utility/XmlUtilEx.cs index cca4a19..29d040f 100644 --- a/KeePassLib/Utility/XmlUtilEx.cs +++ b/KeePassLib/Utility/XmlUtilEx.cs @@ -55,15 +55,9 @@ public static XmlReaderSettings CreateXmlReaderSettings() xrs.IgnoreProcessingInstructions = true; xrs.IgnoreWhitespace = true; -#if KeePassUAP - xrs.DtdProcessing = DtdProcessing.Prohibit; -#else - // Also see PrepMonoDev.sh script - xrs.ProhibitDtd = true; // Obsolete in .NET 4, but still there - // xrs.DtdProcessing = DtdProcessing.Prohibit; // .NET 4 only -#endif + xrs.DtdProcessing = DtdProcessing.Prohibit; - xrs.ValidationType = ValidationType.None; + xrs.ValidationType = ValidationType.None; xrs.XmlResolver = null; return xrs; diff --git a/Translation/TrlUtil/TrlUtil.csproj b/Translation/TrlUtil/TrlUtil.csproj index 6a97524..90b3d69 100644 --- a/Translation/TrlUtil/TrlUtil.csproj +++ b/Translation/TrlUtil/TrlUtil.csproj @@ -2,7 +2,7 @@ WinExe - net40 + net5.0-windows true Resources\KeePass.ico