Example #1
0
        /// <summary>
        /// Unlocks the database prompted to unlock on the KeyPromptForm
        /// </summary>
        /// <param name="ioInfo">IOConnectionInfo that represents the database.</param>
        /// <param name="keyPromptForm">KeyPromptForm to unlock the database from.</param>
        internal async static void UnlockDatabase(IOConnectionInfo ioInfo, KeyPromptForm keyPromptForm)
        {
            // Only one try is allowed
            if (WinHelloUnlockExt.tries < 1)
            {
                if (KeePass.Program.Config.Security.MasterKeyOnSecureDesktop)
                {
                    WinHelloUnlockExt.secureChaged = true;
                    WinHelloUnlockExt.isMonitoring = true;
                    var _ = Task.Factory.StartNew(() => CloseWarning());
                    KeePass.Program.Config.Security.MasterKeyOnSecureDesktop = false;

                    UWPLibrary.Unlock(keyPromptForm, new CompositeKey());
                }
                else
                {
                    await UWPLibrary.UnlockDatabase(ioInfo, keyPromptForm);

                    ++WinHelloUnlockExt.tries;

                    if (WinHelloUnlockExt.secureChaged)
                    {
                        KeePass.Program.Config.Security.MasterKeyOnSecureDesktop = true;
                        WinHelloUnlockExt.secureChaged = false;
                    }
                }
            }
            else
            {
                keyPromptForm.Visible = true;
                keyPromptForm.Opacity = 1;
            }

            WinHelloUnlockExt.opened = true;
        }
        /// <summary>
        /// Called everytime a database is opened.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void FileOpenedHandler(object sender, FileOpenedEventArgs e)
        {
            var ioInfo = e.Database.IOConnectionInfo;

            if (e.Database.CustomData.Get(ProductName) == null) // If there is no CustomData in this database
            {
                // Create CustomData to save global setting to enable or disable the plugin
                e.Database.CustomData.Set(ProductName, "true");
                e.Database.Modified = true;

                // Try to save the database
                try { e.Database.Save(null); }
                catch { }
            }

            // Global settings to be used in the Options Panel
            dbName        = Library.CharChange(ioInfo.Path);
            database      = e.Database;
            UWPLibrary.ck = database.MasterKey;
            if (e.Database.CustomData.Get(ProductName + "AT") == "true")
            {
                LockAfterAutoType = true;
            }
            else
            {
                LockAfterAutoType = false;
            }

            if (e.Database.CustomData.Get(ProductName) == "true")
            {
                enablePlugin = true;
            }
            if (e.Database.CustomData.Get(ProductName) == "false") // if plugin is disabled for the database
            {
                enablePlugin = false;
                return; // Don't do anything else
            }

            if (await UWPLibrary.FirstTime(dbName)) // If the database has no credentials saved
            {
                bool isHelloAvailable = await UWPLibrary.IsHelloAvailable();

                if (isHelloAvailable)
                {
                    // Ask the user if he/she wants to configure the plugin
                    bool yesOrNo = MessageService.AskYesNo("Do You want to set " +
                                                           WinHelloUnlockExt.ProductName + " for " + dbName + " now?", WinHelloUnlockExt.ShortProductName, true);

                    // In case he/she wants, create the credentials
                    if (yesOrNo)
                    {
                        await UWPLibrary.CreateHelloData(dbName);
                    }
                }
            }

            // Set global settings back to default
            tries  = 0;
            opened = true;
        }
        /// <summary>
        /// Used to detect if the master key has been changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void OnSavedDB(Object sender, FileSavedEventArgs args)
        {
            var    db     = args.Database;
            var    ioInfo = db.IOConnectionInfo;
            string dbPath = Library.CharChange(ioInfo.Path);

            if (!await UWPLibrary.FirstTime(dbPath) && await UWPLibrary.IsHelloAvailable() && !Library.CheckMasterKey(ioInfo, UWPLibrary.ck))
            {
                await Library.HandleMasterKeyChange(ioInfo, dbPath, false);
            }
        }
Example #4
0
        /// <summary>Updates the form when the CheckBox is clicked.</summary>
        private void CheckBox_Change(object sender, EventArgs e)
        {
            bool check = checkBox.Checked;

            first = Task.Run(() => UWPLibrary.FirstTime(db)).Result;

            checkBox1.Enabled    = check;
            createButton.Enabled = first && check;
            deleteButton.Enabled = !first;
            label1.Text          = "";
            if (!check && !first)
            {
                label1.Text = "WinHelloUnlock Data will be deleted";
            }
        }
Example #5
0
        /// <summary>Register for the FormClosing event.</summary>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (ParentForm != null)
            {
                // Save the settings on FormClosing.
                ParentForm.FormClosing += delegate(object sender2, FormClosingEventArgs e2)
                {
                    if (ParentForm.DialogResult == DialogResult.OK)
                    {
                        WinHelloUnlockExt.LockAfterAutoType = checkBox1.Checked;
                        if (checkBox1.Checked)
                        {
                            WinHelloUnlockExt.database.CustomData.Set(WinHelloUnlockExt.ProductName + "AT", "true");
                        }
                        else
                        {
                            WinHelloUnlockExt.database.CustomData.Set(WinHelloUnlockExt.ProductName + "AT", "false");
                        }

                        if (onOpenEnabled != checkBox.Checked.ToString())
                        {
                            if (checkBox.Checked)
                            {
                                WinHelloUnlockExt.database.CustomData.Set(WinHelloUnlockExt.ProductName, "true");
                                WinHelloUnlockExt.enablePlugin = true;
                            }
                            else
                            {
                                if (deleteButton.Enabled)
                                {
                                    UWPLibrary.DeleteHelloData(WinHelloUnlockExt.dbName);
                                }
                                WinHelloUnlockExt.database.CustomData.Set(WinHelloUnlockExt.ProductName, "false");
                                WinHelloUnlockExt.enablePlugin = false;
                            }
                        }

                        WinHelloUnlockExt.database.Modified = true;
                        try { WinHelloUnlockExt.database.Save(null); }
                        catch { }

                        //WinHelloUnlockExt.database.Save(null);
                    }
                };
            }
        }
Example #6
0
        /// <summary>
        /// Creates the data for WinHelloUnlock to work.
        /// 1. A Key Credential to sign a cryptographic key.
        /// 2. A Password vault to save the data into
        /// 3. A Password Credential in which to save the encrypted data (using the signed cryptographic key).
        /// </summary>
        /// <param name="dbPath">Database path. This is the identity of the database, if Database is moved or renamed,
        /// WinHelloUnlock will not work and new data needs to be created.
        /// </param>
        /// <returns>True if all the data was saved successfully.</returns>
        internal static async Task <bool> CreateHelloData(string dbPath)
        {
            bool isHelloAvailable = await UWPLibrary.IsHelloAvailable();

            if (isHelloAvailable)
            {
                KeyCredentialCreationOption  optionNew       = KeyCredentialCreationOption.ReplaceExisting;
                KeyCredentialRetrievalResult retrievalResult = await UWPLibrary.CreateCredential(dbPath, optionNew);

                if (retrievalResult.Status == KeyCredentialStatus.Success)
                {
                    KeyList keyList    = Library.GetKeys(WinHelloUnlockExt.database);
                    string  resultSave = await UWPLibrary.SaveKeys(dbPath, keyList, retrievalResult);

                    if (resultSave == "Success")
                    {
                        MessageService.ShowInfo("Database Keys saved successfuly");
                        UWPLibrary.ck = KeePass.Program.MainForm.ActiveDatabase.MasterKey;
                        return(true);
                    }
                    else
                    {
                        if (resultSave.Substring(0, 20) == "Value cannot be null")
                        {
                            MessageService.ShowWarning("Error saving the composite key: MasterKey was null." +
                                                       " Verify that \"Remember master password (in encrypted form) of a database while it is open\" option under Tools/Options/Security" +
                                                       " is enabled, then lock and unlock the database.");
                        }
                        else
                        {
                            MessageService.ShowWarning("Error saving the composite key: " + resultSave);
                        }
                    }
                }
                else
                {
                    WinHelloErrors(retrievalResult.Status, "Error creating the credential: ");
                }
            }
            else
            {
                MessageService.ShowWarning("Windows Hello is NOT Available");
            }
            return(false);
        }
Example #7
0
        /// <summary>
        /// Reopens the KeyPromptForm whenever a change in MasterKeyOnSecureDesktop is made.
        /// </summary>
        internal static void ReopenKeyPromptForm(KeyPromptForm keyPromptForm)
        {
            if (WinHelloUnlockExt.secureChaged)
            {
                KeePass.Program.Config.Security.MasterKeyOnSecureDesktop = true;
                WinHelloUnlockExt.secureChaged = false;

                WinHelloUnlockExt.isMonitoring = true;
                var _ = Task.Factory.StartNew(() => Library.CloseWarning());

                UWPLibrary.Unlock(keyPromptForm, new CompositeKey());
            }
            else
            {
                keyPromptForm.Visible = true;
                keyPromptForm.Opacity = 1;
            }
        }
Example #8
0
        private void RefreshOptions()
        {
            string text     = "";
            string path     = WinHelloUnlockExt.database.IOConnectionInfo.Path;
            string fileName = Path.GetFileName(path);

            if (path.Length > 50)
            {
                text = path.Substring(0, Math.Max(0, 45 - fileName.Length)) + " ... " + fileName;
            }
            else
            {
                text = path;
            }
            settingsGroupBox.Text = "WinHelloUnlock Settings for " + text;

            first         = Task.Run(() => UWPLibrary.FirstTime(db)).Result;
            onOpenEnabled = WinHelloUnlockExt.database.CustomData.Get(WinHelloUnlockExt.ProductName);

            enabled = true;
            if (onOpenEnabled == "false")
            {
                enabled = false;
            }

            if (enabled && !first)
            {
                infoLabel.Text = "WinHelloUnlock is configured for this Database";
            }
            else
            {
                infoLabel.Text = "WinHelloUnlock is NOT configured for this Database";
            }

            //checkBox.Checked = enabled;
            createButton.Enabled = first && (enabled || checkBox.Checked);
            deleteButton.Enabled = !first;
            //checkBox1.Checked = WinHelloUnlockExt.LockAfterAutoType;
            checkBox1.Enabled = enabled;
        }
Example #9
0
        /// <summary>
        /// Creates the data for WinHelloUnlock to work.
        /// 1. A Key Credential to sign a cryptographic key.
        /// 2. A Password vault to save the data into
        /// 3. A Password Credential in which to save the encrypted data (using the signed cryptographic key).
        /// </summary>
        /// <param name="dbPath">Database path. This is the identity of the database, if Database is moved or renamed,
        /// WinHelloUnlock will not work and new data needs to be created.
        /// </param>
        /// <returns>True if all the data was saved successfully.</returns>
        internal static async Task <bool> CreateHelloData(string dbPath)
        {
            bool isHelloAvailable = await UWPLibrary.IsHelloAvailable();

            if (isHelloAvailable)
            {
                KeyCredentialCreationOption  optionNew       = KeyCredentialCreationOption.ReplaceExisting;
                KeyCredentialRetrievalResult retrievalResult = await UWPLibrary.CreateCredential(dbPath, optionNew);

                if (retrievalResult.Status == KeyCredentialStatus.Success)
                {
                    KeyList keyList    = Library.GetKeys(WinHelloUnlockExt.database);
                    string  resultSave = await UWPLibrary.SaveKeys(dbPath, keyList, retrievalResult);

                    if (resultSave == "Success")
                    {
                        MessageService.ShowInfo("Database Keys saved successfuly");
                        UWPLibrary.ck = KeePass.Program.MainForm.ActiveDatabase.MasterKey;
                        return(true);
                    }
                    else
                    {
                        MessageService.ShowWarning("Error saving the composite key: " + resultSave);
                    }
                }
                else
                {
                    WinHelloErrors(retrievalResult.Status, "Error creating the credential: ");
                }
            }
            else
            {
                MessageService.ShowWarning("Windows Hello is NOT Available");
            }
            return(false);
        }
Example #10
0
 /// <summary>
 /// When the plugin detects a change in the MasterKey, it uses this method to prompt the user to update or delete the data
 /// </summary>
 /// <param name="ioInfo">IOConnectionInfo that represents the database.</param>
 /// <param name="dbPath">Name of the credential to update or delete.</param>
 /// <param name="opening">If the masterkey change was detected during database unlock use true.</param>
 internal static async Task HandleMasterKeyChange(IOConnectionInfo ioInfo, string dbPath, bool opening)
 {
     if (opening)
     {
         string str = WinHelloUnlockExt.ProductName + " could not unlock this database." +
                      " MasterKey must have changed. Delete " + WinHelloUnlockExt.ProductName + " data?";
         if (MessageService.AskYesNo(str, WinHelloUnlockExt.ProductName))
         {
             UWPLibrary.DeleteHelloData(dbPath);
         }
         WinHelloUnlockExt.opened = true;
         WinHelloUnlockExt.Host.MainWindow.OpenDatabase(ioInfo, null, false);
     }
     else
     {
         string str = "A change in MasterKey has been detected. Do you want to update " +
                      WinHelloUnlockExt.ProductName + " data?";
         if (MessageService.AskYesNo(str, WinHelloUnlockExt.ProductName))
         {
             UWPLibrary.DeleteHelloData(dbPath);
             await UWPLibrary.CreateHelloData(dbPath);
         }
     }
 }
        /// <summary>
        /// Used to modify other form when they load.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void WindowAddedHandler(object sender, GwmWindowEventArgs e)
        {
            // If a database is attempted to be unlocked
            if (e.Form is KeyPromptForm keyPromptForm)
            {
                keyPromptForm.Opacity = 0;
                keyPromptForm.Visible = false;
                var mf = KeePass.Program.MainForm;
                isAutoTyping = (bool)mf.GetType().GetField("m_bIsAutoTyping", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(mf);

                var    fieldInfo        = keyPromptForm.GetType().GetField("m_ioInfo", BindingFlags.Instance | BindingFlags.NonPublic);
                var    ioInfo           = fieldInfo.GetValue(keyPromptForm) as IOConnectionInfo;
                string dbName           = Library.CharChange(ioInfo.Path);
                bool   isHelloAvailable = await UWPLibrary.IsHelloAvailable();

                // if the database has credentials saved and Windows Hello is available
                if (!await UWPLibrary.FirstTime(dbName) && isHelloAvailable)
                {
                    // If there is no other Windows Hello Prompt opened
                    if (opened)
                    {
                        opened = false;

                        Library.UnlockDatabase(ioInfo, keyPromptForm);
                    }
                    else // If there is another Windows Hello Prompt opened, just close this regular prompt
                         // This is usefull for when there is a double attempt to unlock the database by some plugins (ChromeIPass)
                    {
                        Library.CloseFormWithResult(keyPromptForm, DialogResult.Cancel);
                    }
                }
                else if (!await UWPLibrary.FirstTime(dbName))
                {
                    MessageService.ShowInfo("This Database has credential data saved. Enable Windows Hello to use.");
                    keyPromptForm.Opacity = 1;
                    keyPromptForm.Visible = true;
                }
                else
                {
                    keyPromptForm.Opacity = 1;
                    keyPromptForm.Visible = true;
                }
            }

            // If the Options window is opened
            if (e.Form is OptionsForm optionsForm)
            {
                if (!host.MainWindow.ActiveDatabase.IsOpen)
                {
                    return;                                         //  If there is no database opened, don't do anything
                }
                optionsForm.Shown += (object sender2, EventArgs e2) =>
                {
                    try
                    {
                        Library.AddWinHelloOptions(optionsForm);
                    }
                    catch (Exception ex)
                    {
                        MessageService.ShowWarning("WinHelloUnlock Error: " + ex.Message);
                    }
                };
            }

            // If the Update Check Window is opened.
            // This is used because the Update Check Window prevents the a database from being opened
            if (e.Form is UpdateCheckForm ucf && !opened)
            {
                WinHelloUnlockExt.updateCheckForm = ucf;
            }
        }
Example #12
0
 /// <summary>Deletes WinHelloUnock data when the Delete Button is clicked.</summary>
 private void DeleteteButton_Click(object sender, EventArgs e)
 {
     UWPLibrary.DeleteHelloData(WinHelloUnlockExt.dbName);
     RefreshOptions();
 }
Example #13
0
        /// <summary>Creates WinHelloUnock data when the Create Button is clicked.</summary>
        private async void CreateButton_Click(object sender, EventArgs e)
        {
            await UWPLibrary.CreateHelloData(WinHelloUnlockExt.dbName);

            RefreshOptions();
        }