예제 #1
0
파일: Entry.cs 프로젝트: Stoom/KeePass-TDD
 /// <summary>
 /// Constructs a empty KeePass entry.
 /// </summary>
 public Entry()
 {
     Username = new ProtectedString();
     Password = new ProtectedString();
     Url = new ProtectedString();
     Notes = new ProtectedString();
 }
예제 #2
0
 public void ChangingProtectedStringDoesNotThrowException()
 {
     // Assign
     var str = new ProtectedString("Test");
     // Act / Assert
     AssertExtensions.NoExpectedException<Exception>(() => { str.Value = "Test2"; });
     Assert.AreEqual("Test2", str.ToString());
 }
예제 #3
0
 public void CleaningResolvedStringClearsTheString()
 {
     // Assign
     const string expected = "\0\0\0\0";
     var proStr = new ProtectedString("Test");
     var str = proStr.ToString();
     // Act
     proStr.Clear();
     // Assert
     Assert.AreEqual(expected, str);
 }
예제 #4
0
 public void ChangingToSecureStringChangesModeToFull()
 {
     // Assign
     var str = new ProtectedString();
     //  Assert 1
     Assert.AreEqual(ProtectedStringMode.None, str.Mode);
     // Act
     str.Value = new SecureString();
     // Assert 2
     Assert.AreEqual(ProtectedStringMode.Full, str.Mode);
 }
예제 #5
0
 public void ClearingRemovesAllData()
 {
     // Assign
     var str = new ProtectedString(new SecureString());
     // Act
     str.Clear();
     // Assert
     str.Mode = ProtectedStringMode.None;
     Assert.AreEqual(null, str.ToString());
     str.Mode = ProtectedStringMode.Full;
     Assert.AreEqual(null, str.ToSecureString());
 }
예제 #6
0
        private static PwgError GenerateCustom(out ProtectedString psOut,
                                               PwProfile pwProfile, CryptoRandomStream crs,
                                               CustomPwGeneratorPool pwAlgorithmPool)
        {
            psOut = ProtectedString.Empty;

            Debug.Assert(pwProfile.GeneratorType == PasswordGeneratorType.Custom);
            if (pwAlgorithmPool == null)
            {
                return(PwgError.UnknownAlgorithm);
            }

            string strID = pwProfile.CustomAlgorithmUuid;

            if (string.IsNullOrEmpty(strID))
            {
                Debug.Assert(false); return(PwgError.UnknownAlgorithm);
            }

            byte[]            pbUuid = Convert.FromBase64String(strID);
            PwUuid            uuid   = new PwUuid(pbUuid);
            CustomPwGenerator pwg    = pwAlgorithmPool.Find(uuid);

            if (pwg == null)
            {
                Debug.Assert(false); return(PwgError.UnknownAlgorithm);
            }

            ProtectedString pwd = pwg.Generate(pwProfile.CloneDeep(), crs);

            if (pwd == null)
            {
                return(PwgError.Unknown);
            }

            psOut = pwd;
            return(PwgError.Success);
        }
예제 #7
0
        private void RemoveInsert(int nLeftRem, int nRightRem, string strInsert)
        {
            Debug.Assert(nLeftRem >= 0);

            // if(m_secString != null)
            // {
            //	while(m_secString.Length > (nLeftRem + nRightRem))
            //		m_secString.RemoveAt(nLeftRem);
            //	for(int i = 0; i < strInsert.Length; ++i)
            //		m_secString.InsertAt(nLeftRem + i, strInsert[i]);
            // }
            // else
            // {
            //	StringBuilder sb = new StringBuilder(m_strAlternativeSecString);
            //	while(sb.Length > (nLeftRem + nRightRem))
            //		sb.Remove(nLeftRem, 1);
            //	sb.Insert(nLeftRem, strInsert);
            //	m_strAlternativeSecString = sb.ToString();
            // }

            try
            {
                int cr = m_psText.Length - (nLeftRem + nRightRem);
                if (cr >= 0)
                {
                    m_psText = m_psText.Remove(nLeftRem, cr);
                }
                else
                {
                    Debug.Assert(false);
                }
                Debug.Assert(m_psText.Length == (nLeftRem + nRightRem));
            }
            catch (Exception) { Debug.Assert(false); }

            try { m_psText = m_psText.Insert(nLeftRem, strInsert); }
            catch (Exception) { Debug.Assert(false); }
        }
예제 #8
0
        public static bool CopyAndMinimize(ProtectedString psToCopy, bool bIsEntryInfo,
                                           Form formContext, PwEntry peEntryInfo, PwDatabase pwReferenceSource)
        {
            if (ClipboardUtil.Copy(psToCopy, bIsEntryInfo, peEntryInfo, pwReferenceSource))
            {
                if (formContext != null)
                {
                    if (Program.Config.MainWindow.DropToBackAfterClipboardCopy)
                    {
                        NativeMethods.LoseFocus(formContext);
                    }

                    if (Program.Config.MainWindow.MinimizeAfterClipboardCopy)
                    {
                        formContext.WindowState = FormWindowState.Minimized;
                    }
                }

                return(true);
            }

            return(false);
        }
예제 #9
0
        private bool SearchScreenForQRCode(int iSeconds)
        {
            int iSleep = 250;

            try
            {
                DateTime dtEnd = DateTime.Now.AddSeconds(iSeconds);
                while (dtEnd > DateTime.Now)
                {
                    System.Threading.Thread.Sleep(iSleep);
                    Application.DoEvents();
                    Bitmap bmp = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height, PixelFormat.Format32bppArgb);

                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.CopyFromScreen(SystemInformation.VirtualScreen.X, SystemInformation.VirtualScreen.Y, 0, 0, SystemInformation.VirtualScreen.Size, CopyPixelOperation.SourceCopy);
                    }

                    ProtectedString otp = ParseFromImage(bmp);
                    bmp.Dispose();
                    if (IsValidOtpAuth(otp))
                    {
                        OTP.OTPAuthString = otp;
                        m_NoUpdate        = true;
                        InitSettings(true);
                        m_NoUpdate = false;
                        return(true);
                    }
                    if (pbSearchScreen.Text == PluginTranslate.ReadScreenForQRCode)
                    {
                        return(false);
                    }
                }
            }
            catch { }
            return(false);
        }
예제 #10
0
        public static string FillPlaceholders(string strText, PwEntry pe,
                                              SprContentFlags cf)
        {
            if (pe == null)
            {
                return(strText);
            }

            string str = strText;

            if (str.ToUpper().IndexOf(@"{PICKPASSWORDCHARS}") >= 0)
            {
                ProtectedString ps = pe.Strings.Get(PwDefs.PasswordField);
                if (ps != null)
                {
                    byte[] pb        = ps.ReadUtf8();
                    bool   bNotEmpty = (pb.Length > 0);
                    Array.Clear(pb, 0, pb.Length);

                    if (bNotEmpty)
                    {
                        CharPickerForm cpf = new CharPickerForm();
                        cpf.InitEx(ps, true, true);

                        if (cpf.ShowDialog() == DialogResult.OK)
                        {
                            str = StrUtil.ReplaceCaseInsensitive(str, @"{PICKPASSWORDCHARS}",
                                                                 SprEngine.TransformContent(cpf.SelectedCharacters.ReadString(), cf));
                        }
                    }
                }

                str = StrUtil.ReplaceCaseInsensitive(str, @"{PICKPASSWORDCHARS}", string.Empty);
            }

            return(str);
        }
예제 #11
0
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;
            if (pwProfile.Length == 0)
            {
                return(PwgError.Success);
            }

            PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString());

            PwGenerator.PrepareCharSet(pcs, pwProfile);

            char[] v = new char[pwProfile.Length];
            try
            {
                for (int i = 0; i < v.Length; ++i)
                {
                    char ch = PwGenerator.GenerateCharacter(pwProfile,
                                                            pcs, crsRandomSource);

                    if (ch == char.MinValue)
                    {
                        return(PwgError.TooFewCharacters);
                    }

                    v[i] = ch;
                }

                byte[] pbUtf8 = StrUtil.Utf8.GetBytes(v);
                psOut = new ProtectedString(true, pbUtf8);
                MemUtil.ZeroByteArray(pbUtf8);
            }
            finally { MemUtil.ZeroArray <char>(v); }

            return(PwgError.Success);
        }
예제 #12
0
        /*
         * protected override void SetFieldValueInternal(RowObject rowObject, ProtectedString newValue)
         * {
         *      var allEntries = Entries.ToArray();
         *      if (!IsMultiValuedField(rowObject) || // No need to confirm to change the value of a field that isn't multi-valued
         *              ConfirmOperationOnAllEntries(String.Format(Properties.Resources.MultipleEntryFieldSetValueQuestion, rowObject.DisplayName), Properties.Resources.MultpleEntryFieldSetValueCommand, allEntries))
         *      {
         *              var createBackups = AllowCreateHistoryNow;
         *              foreach (var entry in allEntries)
         *              {
         *                      if (createBackups)
         *                      {
         *                              entry.CreateBackup(Database);
         *                      }
         *
         *                      entry.Strings.Set(rowObject.FieldName, newValue); // ProtectedStrings are immutable, so OK to assign the same one to all entries
         *              }
         *              rowObject.Value = newValue;
         *
         *              OnModified(EventArgs.Empty);
         *      }
         * }
         */
        protected override void SetFieldValueInternal(RowObject rowObject, ProtectedString newValue)
        {
            var allEntries = Entries.ToArray();

            if (!IsMultiValuedField(rowObject) ||             // No need to confirm to change the value of a field that isn't multi-valued
                ConfirmOperationOnAllEntries(String.Format(Properties.Resources.MultipleEntryFieldSetValueQuestion, rowObject.DisplayName), Properties.Resources.MultpleEntryFieldSetValueCommand, allEntries))
            {
                var    createBackups = AllowCreateHistoryNow;
                string val           = newValue.ReadString();
                if (createBackups)
                {
                    foreach (var entry in allEntries)
                    {
                        entry.CreateBackup(Database);
                    }
                }
                if (val.StartsWith("="))
                {
                    foreach (var entry in allEntries)
                    {
                        SprContext ctx = new SprContext(entry, Database, SprCompileFlags.All, false, false);
                        entry.Strings.Set(rowObject.FieldName,
                                          new ProtectedString(newValue.IsProtected, SprEngine.Compile(val.Substring(1), ctx)));
                    }
                    OnEntriesChanged(EventArgs.Empty);
                }
                else
                {
                    foreach (var entry in allEntries)
                    {
                        entry.Strings.Set(rowObject.FieldName, newValue);                         // ProtectedStrings are immutable, so OK to assign the same one to all entries
                        rowObject.Value = newValue;
                    }
                }
                OnModified(EventArgs.Empty);
            }
        }
예제 #13
0
        /// <summary>
        /// Decypts a string using a key signed by a KeyCredential.
        /// </summary>
        /// <param name="strProtected">Text to decrypt.</param>
        /// <param name="rResult">KeyCredential object used to sign a key to encrypt the text.</param>
        /// <returns>Decrypted text.</returns>
        internal static async Task <ProtectedString> Decrypt(string strProtected, KeyCredentialRetrievalResult rResult)
        {
            // The same text must be used to decrypt the data
            Assembly assembly  = Assembly.GetExecutingAssembly();
            var      attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
            var      id        = attribute.Value;
            IBuffer  buffMsg   = CryptographicBuffer.ConvertStringToBinary(id, encoding);

            // Start a background thread to ensure Windows Security prompt is opened in foreground
            var _ = Task.Factory.StartNew(() => EnsureForeground());

            // The actual Signing of the string
            KeyCredentialOperationResult opResult = await rResult.Credential.RequestSignAsync(buffMsg);

            if (opResult.Status == KeyCredentialStatus.Success)
            {
                IBuffer signedData = opResult.Result;

                // Creation of the key with the signed string
                SymmetricKeyAlgorithmProvider provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
                CryptographicKey myKey = provider.CreateSymmetricKey(signedData);

                // Decryption of the data using the key created (mKey)
                IBuffer buffProtected = CryptographicBuffer.DecodeFromBase64String(strProtected);
                CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(myKey, buffProtected, null), out var ba);
                ProtectedString ps = new ProtectedString(true, ba);
                MemUtil.ZeroByteArray(ba);
                return(ps);
            }
            else
            {
                WinHelloUnlockExt.opened = true;
                WinHelloErrors(opResult.Status, "Error decrypting the data: ");
                return(null);
            }
        }
예제 #14
0
        private static void ImportFields(JsonObject[] vFields, PwEntry pe, PwDatabase pd)
        {
            foreach (JsonObject jo in vFields)
            {
                if (jo == null)
                {
                    Debug.Assert(false); continue;
                }

                string strName  = jo.GetValue <string>("name");
                string strValue = jo.GetValue <string>("value");
                long   lType    = jo.GetValue <long>("type", 0);

                if (!string.IsNullOrEmpty(strName))
                {
                    ImportUtil.AppendToField(pe, strName, strValue, pd);

                    if ((lType == 1) && !PwDefs.IsStandardField(strName))
                    {
                        ProtectedString ps = pe.Strings.Get(strName);
                        if (ps == null)
                        {
                            Debug.Assert(false);
                        }
                        else
                        {
                            pe.Strings.Set(strName, ps.WithProtection(true));
                        }
                    }
                }
                else
                {
                    Debug.Assert(false);
                }
            }
        }
예제 #15
0
        private static string ReplacePickPwPlaceholder(string str,
                                                       string strPlaceholder, uint uCharCount, SprContext ctx,
                                                       uint uRecursionLevel)
        {
            if (str.IndexOf(strPlaceholder, StrUtil.CaseIgnoreCmp) < 0)
            {
                return(str);
            }

            ProtectedString ps = ctx.Entry.Strings.Get(PwDefs.PasswordField);

            if (ps != null)
            {
                string strPassword = ps.ReadString();

                string strPick = SprEngine.CompileInternal(strPassword,
                                                           ctx.WithoutContentTransformations(), uRecursionLevel + 1);

                if (!string.IsNullOrEmpty(strPick))
                {
                    ProtectedString psPick = new ProtectedString(false, strPick);
                    CharPickerForm  dlg    = new CharPickerForm();
                    dlg.InitEx(psPick, true, true, uCharCount, null);

                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        str = StrUtil.ReplaceCaseInsensitive(str, strPlaceholder,
                                                             SprEngine.TransformContent(
                                                                 dlg.SelectedCharacters.ReadString(), ctx));
                    }
                    UIUtil.DestroyForm(dlg);
                }
            }

            return(StrUtil.ReplaceCaseInsensitive(str, strPlaceholder, string.Empty));
        }
예제 #16
0
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;
            if (pwProfile.Length == 0)
            {
                return(PwgError.Success);
            }

            PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString());

            char[] vGenerated = new char[pwProfile.Length];

            PwGenerator.PrepareCharSet(pcs, pwProfile);

            for (int nIndex = 0; nIndex < (int)pwProfile.Length; ++nIndex)
            {
                char ch = PwGenerator.GenerateCharacter(pwProfile, pcs,
                                                        crsRandomSource);

                if (ch == char.MinValue)
                {
                    Array.Clear(vGenerated, 0, vGenerated.Length);
                    return(PwgError.TooFewCharacters);
                }

                vGenerated[nIndex] = ch;
            }

            byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vGenerated);
            psOut = new ProtectedString(true, pbUtf8);
            MemUtil.ZeroByteArray(pbUtf8);
            Array.Clear(vGenerated, 0, vGenerated.Length);

            return(PwgError.Success);
        }
예제 #17
0
        private static string Fill(string strData, string strPlaceholder,
                                   ProtectedString psReplacement, SprContext ctx, uint?ouRecursionLevel)
        {
            if (strData == null)
            {
                Debug.Assert(false); return(string.Empty);
            }
            if (string.IsNullOrEmpty(strPlaceholder))
            {
                Debug.Assert(false); return(strData);
            }
            if (psReplacement == null)
            {
                Debug.Assert(false); psReplacement = ProtectedString.Empty;
            }

            if (strData.IndexOf(strPlaceholder, SprEngine.ScMethod) < 0)
            {
                return(strData);
            }

            return(Fill(strData, strPlaceholder, psReplacement.ReadString(),
                        ctx, ouRecursionLevel));
        }
예제 #18
0
        public void WriteProperty(Property prop, XmlDocument doc, XmlNode node)
        {
            ProtectedString value = prop.CastValue <ProtectedString>();

            if (value.IsCompiled)
            {
                var binary = XmlPropertyTokens.GetHandler <BinaryStringToken>();
                binary.WriteProperty(prop, doc, node);
            }
            else
            {
                string contents = Encoding.UTF8.GetString(value.RawBuffer);

                if (contents.Contains("\r") || contents.Contains("\n"))
                {
                    XmlCDataSection cdata = doc.CreateCDataSection(contents);
                    node.AppendChild(cdata);
                }
                else
                {
                    node.InnerText = contents;
                }
            }
        }
예제 #19
0
        private static string FillGroupPlh(string strData, string strPlhPrefix,
                                           PwGroup pg, SprContext ctx, uint uRecursionLevel)
        {
            Debug.Assert(strPlhPrefix.StartsWith("{"));
            Debug.Assert(!strPlhPrefix.EndsWith("_"));
            Debug.Assert(!strPlhPrefix.EndsWith("}"));

            string str = strData;

            str = SprEngine.FillIfExists(str, strPlhPrefix + @"}",
                                         new ProtectedString(false, pg.Name), ctx, uRecursionLevel);

            ProtectedString psGroupPath = new ProtectedString(false, pg.GetFullPath());

            str = SprEngine.FillIfExists(str, strPlhPrefix + @"_PATH}", psGroupPath,
                                         ctx, uRecursionLevel);
            str = SprEngine.FillIfExists(str, strPlhPrefix + @"PATH}", psGroupPath,
                                         ctx, uRecursionLevel); // Obsolete; for backward compatibility

            str = SprEngine.FillIfExists(str, strPlhPrefix + @"_NOTES}",
                                         new ProtectedString(false, pg.Notes), ctx, uRecursionLevel);

            return(str);
        }
예제 #20
0
        public void SetPassword(byte[] pbUtf8)
        {
            Debug.Assert(pbUtf8 != null);
            if (pbUtf8 == null)
            {
                throw new ArgumentNullException("pbUtf8");
            }

            // if(m_secString != null)
            // {
            //	m_secString.Clear();
            //	char[] vChars = StrUtil.Utf8.GetChars(pbUtf8);
            //	for(int i = 0; i < vChars.Length; ++i)
            //	{
            //		m_secString.AppendChar(vChars[i]);
            //		vChars[i] = char.MinValue;
            //	}
            // }
            // else m_strAlternativeSecString = StrUtil.Utf8.GetString(pbUtf8);

            m_psText = new ProtectedString(true, pbUtf8);

            ShowCurrentPassword(0, 0);
        }
예제 #21
0
        /// <summary>
        /// Convert the composite key to a KeyList class
        /// </summary>
        /// <param name="db">The source database.</param>
        /// <returns>A KeyList object containing the composite key.</returns>
        internal static KeyList GetKeys(PwDatabase db)
        {
            CompositeKey           dKey        = db.MasterKey;
            var                    passwordKey = dKey.UserKeys.Where(k => k is KcpPassword).FirstOrDefault() as KcpPassword;
            var                    kFile       = dKey.UserKeys.Where(k => k is KcpKeyFile).FirstOrDefault() as KcpKeyFile;
            var                    uAccount    = dKey.UserKeys.Where(k => k is KcpUserAccount).FirstOrDefault() as KcpUserAccount;
            IEnumerable <IUserKey> kList       = dKey.UserKeys;
            int                    kNumber     = kList.Count();

            ProtectedString[] pString = new ProtectedString[kNumber];
            String[]          tString = new String[kNumber];
            int i = 0;

            foreach (var uKey in kList)
            {
                switch (uKey.GetType().ToString())
                {
                case "KeePassLib.Keys.KcpPassword":
                    pString[i] = passwordKey.Password;
                    tString[i] = "KeePassLib.Keys.KcpPassword";
                    break;

                case "KeePassLib.Keys.KcpKeyFile":
                    pString[i] = new ProtectedString(true, kFile.Path);
                    tString[i] = "KeePassLib.Keys.KcpKeyFile";
                    break;

                case "KeePassLib.Keys.KcpUserAccount":
                    pString[i] = new ProtectedString(true, "WithUA");
                    tString[i] = "KeePassLib.Keys.KcpUserAccount";
                    break;
                }
                ++i;
            }
            return(new KeyList(tString, pString));
        }
예제 #22
0
        private ProtectedString ReadProtectedString(XmlReader xr)
        {
            XorredBuffer xb = ProcessNode(xr);

            if (xb != null)
            {
                return(new ProtectedString(true, xb));
            }

            bool bProtect = false;

            if (m_format == KdbxFormat.PlainXml)
            {
                if (xr.MoveToAttribute(AttrProtectedInMemPlainXml))
                {
                    string strProtect = xr.Value;
                    bProtect = ((strProtect != null) && (strProtect == ValTrue));
                }
            }

            ProtectedString ps = new ProtectedString(bProtect, ReadString(xr));

            return(ps);
        }
예제 #23
0
        /// <summary>
        /// Displays the character selection form for the protected string referenced by the
        /// clicked <see cref="ProtectedStringMenuItem" />.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnEntryMenuItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem is ProtectedStringMenuItem)
            {
                ProtectedStringMenuItem item = (ProtectedStringMenuItem)e.ClickedItem;

                PwEntry entry = this.host.Database.RootGroup.FindEntry(item.EntryUuid, true);
                if (entry != null)
                {
                    if (entry.Strings.Exists(item.ProtectedStringKey))
                    {
                        ProtectedString procString = entry.Strings.Get(item.ProtectedStringKey);

                        // Display character selector form for the protected string
                        using (CharacterSelectorForm selectorForm = new CharacterSelectorForm(this.host, procString))
                        {
                            selectorForm.ShowDialog(this.host.MainWindow);
                        }

                        entry.Touch(false);
                    }
                }
            }
        }
예제 #24
0
        public override void Import(PwDatabase pwStorage, Stream sInput,
                                    IStatusLogger slLogger)
        {
            StreamReader sr      = new StreamReader(sInput, StrUtil.Utf8, true);
            string       strData = sr.ReadToEnd();

            sr.Close();

            PwGroup      pg     = pwStorage.RootGroup;
            const string strSep = ": ";             // Both ": " and " : " are used

            strData = StrUtil.NormalizeNewLines(strData, false);

            int iSep = strData.IndexOf(strSep);

            if (iSep < 0)
            {
                throw new FormatException();
            }
            string strTitleKey = strData.Substring(0, iSep).Trim();

            if (strTitleKey.Length == 0)
            {
                throw new FormatException();
            }
            if (strTitleKey.IndexOf('\n') >= 0)
            {
                throw new FormatException();
            }

            PwEntry pe      = null;
            string  strName = PwDefs.TitleField;

            string[] vLines = strData.Split('\n');
            foreach (string strLine in vLines)
            {
                if (strLine == null)
                {
                    Debug.Assert(false); continue;
                }
                // Do not trim strLine, otherwise strSep might not be detected

                string strValue = strLine;

                iSep = strLine.IndexOf(strSep);
                if (iSep >= 0)
                {
                    string strCurName = strLine.Substring(0, iSep).Trim();
                    strValue = strLine.Substring(iSep + strSep.Length);

                    if (strCurName == strTitleKey)
                    {
                        FinishEntry(pe);

                        pe = new PwEntry(true, true);
                        pg.AddEntry(pe, true);

                        strName = PwDefs.TitleField;
                    }
                    else if (strName == PwDefs.NotesField)
                    {
                        strValue = strLine;                         // Restore
                    }
                    else
                    {
                        strName = ImportUtil.MapNameToStandardField(strCurName, true);
                        if (string.IsNullOrEmpty(strName))
                        {
                            strName = strCurName;
                            if (string.IsNullOrEmpty(strName))
                            {
                                Debug.Assert(false);
                                strName  = PwDefs.NotesField;
                                strValue = strLine;                                 // Restore
                            }
                        }
                    }
                }

                if (pe != null)
                {
                    strValue = strValue.Trim();

                    if (strValue.Length != 0)
                    {
                        ImportUtil.AppendToField(pe, strName, strValue, pwStorage);
                    }
                    else if (strName == PwDefs.NotesField)
                    {
                        ProtectedString ps = pe.Strings.GetSafe(strName);
                        pe.Strings.Set(strName, ps + MessageService.NewLine);
                    }
                }
                else
                {
                    Debug.Assert(false);
                }
            }

            FinishEntry(pe);
        }
예제 #25
0
        internal KdbContext ReadXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.Element);

            switch (ctx)
            {
            case KdbContext.Null:
                if (xr.Name == ElemDocNode)
                {
                    return(SwitchContext(ctx, KdbContext.KeePassFile, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.KeePassFile:
                if (xr.Name == ElemMeta)
                {
                    return(SwitchContext(ctx, KdbContext.Meta, xr));
                }
                else if (xr.Name == ElemRoot)
                {
                    return(SwitchContext(ctx, KdbContext.Root, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Meta:
                if (xr.Name == ElemGenerator)
                {
                    ReadString(xr);                             // Ignore
                }
                else if (xr.Name == ElemDbName)
                {
                    m_pwDatabase.Name = ReadString(xr);
                }
                else if (xr.Name == ElemDbNameChanged)
                {
                    m_pwDatabase.NameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDesc)
                {
                    m_pwDatabase.Description = ReadString(xr);
                }
                else if (xr.Name == ElemDbDescChanged)
                {
                    m_pwDatabase.DescriptionChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDefaultUser)
                {
                    m_pwDatabase.DefaultUserName = ReadString(xr);
                }
                else if (xr.Name == ElemDbDefaultUserChanged)
                {
                    m_pwDatabase.DefaultUserNameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbMntncHistoryDays)
                {
                    m_pwDatabase.MaintenanceHistoryDays = ReadUInt(xr, 365);
                }
                else if (xr.Name == ElemMemoryProt)
                {
                    return(SwitchContext(ctx, KdbContext.MemoryProtection, xr));
                }
                else if (xr.Name == ElemCustomIcons)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcons, xr));
                }
                else if (xr.Name == ElemRecycleBinEnabled)
                {
                    m_pwDatabase.RecycleBinEnabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemRecycleBinUuid)
                {
                    m_pwDatabase.RecycleBinUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemRecycleBinChanged)
                {
                    m_pwDatabase.RecycleBinChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroup)
                {
                    m_pwDatabase.EntryTemplatesGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroupChanged)
                {
                    m_pwDatabase.EntryTemplatesGroupChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemLastSelectedGroup)
                {
                    m_pwDatabase.LastSelectedGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemLastTopVisibleGroup)
                {
                    m_pwDatabase.LastTopVisibleGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.CustomData, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.MemoryProtection:
                if (xr.Name == ElemProtTitle)
                {
                    m_pwDatabase.MemoryProtection.ProtectTitle = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtUserName)
                {
                    m_pwDatabase.MemoryProtection.ProtectUserName = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtPassword)
                {
                    m_pwDatabase.MemoryProtection.ProtectPassword = ReadBool(xr, true);
                }
                else if (xr.Name == ElemProtURL)
                {
                    m_pwDatabase.MemoryProtection.ProtectUrl = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtNotes)
                {
                    m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtAutoHide)
                {
                    m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = ReadBool(xr, true);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcons:
                if (xr.Name == ElemCustomIconItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcon, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcon:
                if (xr.Name == ElemCustomIconItemID)
                {
                    m_uuidCustomIconID = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomIconItemData)
                {
                    string strData = ReadString(xr);
                    if ((strData != null) && (strData.Length > 0))
                    {
                        m_pbCustomIconData = Convert.FromBase64String(strData);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Root:
                if (xr.Name == ElemGroup)
                {
                    Debug.Assert(m_ctxGroups.Count == 0);
                    if (m_ctxGroups.Count != 0)
                    {
                        throw new FormatException();
                    }

                    m_pwDatabase.RootGroup = new PwGroup(false, false);
                    m_ctxGroups.Push(m_pwDatabase.RootGroup);
                    m_ctxGroup = m_ctxGroups.Peek();

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemDeletedObjects)
                {
                    return(SwitchContext(ctx, KdbContext.RootDeletedObjects, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Group:
                if (xr.Name == ElemUuid)
                {
                    m_ctxGroup.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemName)
                {
                    m_ctxGroup.Name = ReadString(xr);
                }
                else if (xr.Name == ElemNotes)
                {
                    m_ctxGroup.Notes = ReadString(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxGroup.IconId = (PwIcon)ReadUInt(xr, (uint)PwIcon.Folder);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxGroup.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.GroupTimes, xr));
                }
                else if (xr.Name == ElemIsExpanded)
                {
                    m_ctxGroup.IsExpanded = ReadBool(xr, true);
                }
                else if (xr.Name == ElemGroupDefaultAutoTypeSeq)
                {
                    m_ctxGroup.DefaultAutoTypeSequence = ReadString(xr);
                }
                else if (xr.Name == ElemEnableAutoType)
                {
                    m_ctxGroup.EnableAutoType = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemEnableSearching)
                {
                    m_ctxGroup.EnableSearching = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemLastTopVisibleEntry)
                {
                    m_ctxGroup.LastTopVisibleEntry = ReadUuid(xr);
                }
                else if (xr.Name == ElemGroup)
                {
                    m_ctxGroup = new PwGroup(false, false);
                    m_ctxGroups.Peek().AddGroup(m_ctxGroup, true);

                    m_ctxGroups.Push(m_ctxGroup);

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxGroup.AddEntry(m_ctxEntry, true);

                    m_bEntryInHistory = false;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Entry:
                if (xr.Name == ElemUuid)
                {
                    m_ctxEntry.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxEntry.IconId = (PwIcon)ReadUInt(xr, (uint)PwIcon.Key);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxEntry.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemFgColor)
                {
                    string strColor = ReadString(xr);
                    if ((strColor != null) && (strColor.Length > 0))
                    {
                        m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);
                    }
                }
                else if (xr.Name == ElemBgColor)
                {
                    string strColor = ReadString(xr);
                    if ((strColor != null) && (strColor.Length > 0))
                    {
                        m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);
                    }
                }
                else if (xr.Name == ElemOverrideUrl)
                {
                    m_ctxEntry.OverrideUrl = ReadString(xr);
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.EntryTimes, xr));
                }
                else if (xr.Name == ElemString)
                {
                    return(SwitchContext(ctx, KdbContext.EntryString, xr));
                }
                else if (xr.Name == ElemBinary)
                {
                    return(SwitchContext(ctx, KdbContext.EntryBinary, xr));
                }
                else if (xr.Name == ElemAutoType)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoType, xr));
                }
                else if (xr.Name == ElemHistory)
                {
                    Debug.Assert(m_bEntryInHistory == false);

                    if (m_bEntryInHistory == false)
                    {
                        m_ctxHistoryBase = m_ctxEntry;
                        return(SwitchContext(ctx, KdbContext.EntryHistory, xr));
                    }
                    else
                    {
                        ReadUnknown(xr);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupTimes:
            case KdbContext.EntryTimes:
                ITimeLogger tl = ((ctx == KdbContext.GroupTimes) ?
                                  (ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
                Debug.Assert(tl != null);

                if (xr.Name == ElemLastModTime)
                {
                    tl.LastModificationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemCreationTime)
                {
                    tl.CreationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemLastAccessTime)
                {
                    tl.LastAccessTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpiryTime)
                {
                    tl.ExpiryTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpires)
                {
                    tl.Expires = ReadBool(xr, false);
                }
                else if (xr.Name == ElemUsageCount)
                {
                    tl.UsageCount = ReadULong(xr, 0);
                }
                else if (xr.Name == ElemLocationChanged)
                {
                    tl.LocationChanged = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryString:
                if (xr.Name == ElemKey)
                {
                    m_ctxStringName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxStringValue = ReadProtectedString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryBinary:
                if (xr.Name == ElemKey)
                {
                    m_ctxBinaryName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxBinaryValue = ReadProtectedBinary(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoType:
                if (xr.Name == ElemAutoTypeEnabled)
                {
                    m_ctxEntry.AutoType.Enabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemAutoTypeObfuscation)
                {
                    m_ctxEntry.AutoType.ObfuscationOptions =
                        (AutoTypeObfuscationOptions)ReadUInt(xr, 0);
                }
                else if (xr.Name == ElemAutoTypeDefaultSeq)
                {
                    m_ctxEntry.AutoType.DefaultSequence = ReadString(xr);
                }
                else if (xr.Name == ElemAutoTypeItem)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoTypeItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoTypeItem:
                if (xr.Name == ElemWindow)
                {
                    m_ctxATName = ReadString(xr);
                }
                else if (xr.Name == ElemKeystrokeSequence)
                {
                    m_ctxATSeq = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryHistory:
                if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxHistoryBase.History.Add(m_ctxEntry);

                    m_bEntryInHistory = true;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.RootDeletedObjects:
                if (xr.Name == ElemDeletedObject)
                {
                    m_ctxDeletedObject = new PwDeletedObject();
                    m_pwDatabase.DeletedObjects.Add(m_ctxDeletedObject);

                    return(SwitchContext(ctx, KdbContext.DeletedObject, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.DeletedObject:
                if (xr.Name == ElemUuid)
                {
                    m_ctxDeletedObject.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemDeletionTime)
                {
                    m_ctxDeletedObject.DeletionTime = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            default:
                ReadUnknown(xr);
                break;
            }

            return(ctx);
        }
예제 #26
0
        private static void TestProtectedObjects()
        {
#if DEBUG
            byte[]          pbData = Encoding.ASCII.GetBytes("Test Test Test Test");
            ProtectedBinary pb     = new ProtectedBinary(true, pbData);
            if (!pb.IsProtected)
            {
                throw new SecurityException("ProtectedBinary-1");
            }

            byte[] pbDec = pb.ReadData();
            if (!MemUtil.ArraysEqual(pbData, pbDec))
            {
                throw new SecurityException("ProtectedBinary-2");
            }
            if (!pb.IsProtected)
            {
                throw new SecurityException("ProtectedBinary-3");
            }

            byte[]          pbData2 = Encoding.ASCII.GetBytes("Test Test Test Test");
            byte[]          pbData3 = Encoding.ASCII.GetBytes("Test Test Test Test Test");
            ProtectedBinary pb2     = new ProtectedBinary(true, pbData2);
            ProtectedBinary pb3     = new ProtectedBinary(true, pbData3);
            if (!pb.Equals(pb2))
            {
                throw new SecurityException("ProtectedBinary-4");
            }
            if (pb.Equals(pb3))
            {
                throw new SecurityException("ProtectedBinary-5");
            }
            if (pb2.Equals(pb3))
            {
                throw new SecurityException("ProtectedBinary-6");
            }

            if (pb.GetHashCode() != pb2.GetHashCode())
            {
                throw new SecurityException("ProtectedBinary-7");
            }
            if (!((object)pb).Equals((object)pb2))
            {
                throw new SecurityException("ProtectedBinary-8");
            }
            if (((object)pb).Equals((object)pb3))
            {
                throw new SecurityException("ProtectedBinary-9");
            }
            if (((object)pb2).Equals((object)pb3))
            {
                throw new SecurityException("ProtectedBinary-10");
            }

            ProtectedString ps = new ProtectedString();
            if (ps.Length != 0)
            {
                throw new SecurityException("ProtectedString-1");
            }
            if (!ps.IsEmpty)
            {
                throw new SecurityException("ProtectedString-2");
            }
            if (ps.ReadString().Length != 0)
            {
                throw new SecurityException("ProtectedString-3");
            }

            ps = new ProtectedString(true, "Test");
            ProtectedString ps2 = new ProtectedString(true,
                                                      StrUtil.Utf8.GetBytes("Test"));
            if (ps.IsEmpty)
            {
                throw new SecurityException("ProtectedString-4");
            }
            pbData  = ps.ReadUtf8();
            pbData2 = ps2.ReadUtf8();
            if (!MemUtil.ArraysEqual(pbData, pbData2))
            {
                throw new SecurityException("ProtectedString-5");
            }
            if (pbData.Length != 4)
            {
                throw new SecurityException("ProtectedString-6");
            }
            if (ps.ReadString() != ps2.ReadString())
            {
                throw new SecurityException("ProtectedString-7");
            }
            pbData  = ps.ReadUtf8();
            pbData2 = ps2.ReadUtf8();
            if (!MemUtil.ArraysEqual(pbData, pbData2))
            {
                throw new SecurityException("ProtectedString-8");
            }
            if (!ps.IsProtected)
            {
                throw new SecurityException("ProtectedString-9");
            }
            if (!ps2.IsProtected)
            {
                throw new SecurityException("ProtectedString-10");
            }
#endif
        }
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;
            LinkedList <char> vGenerated = new LinkedList <char>();
            PwCharSet         pcsCurrent = new PwCharSet();
            PwCharSet         pcsCustom  = new PwCharSet();
            PwCharSet         pcsUsed    = new PwCharSet();
            bool bInCharSetDef           = false;

            string strPattern = ExpandPattern(pwProfile.Pattern);

            if (strPattern.Length == 0)
            {
                return(PwgError.Success);
            }

            CharStream csStream = new CharStream(strPattern);
            char       ch       = csStream.ReadChar();

            while (ch != char.MinValue)
            {
                pcsCurrent.Clear();

                bool bGenerateChar = false;

                if (ch == '\\')
                {
                    ch = csStream.ReadChar();
                    if (ch == char.MinValue)                    // Backslash at the end
                    {
                        vGenerated.AddLast('\\');
                        break;
                    }

                    if (bInCharSetDef)
                    {
                        pcsCustom.Add(ch);
                    }
                    else
                    {
                        vGenerated.AddLast(ch);
                        pcsUsed.Add(ch);
                    }
                }
                else if (ch == '^')
                {
                    ch = csStream.ReadChar();
                    if (ch == char.MinValue)                    // ^ at the end
                    {
                        vGenerated.AddLast('^');
                        break;
                    }

                    if (bInCharSetDef)
                    {
                        pcsCustom.Remove(ch);
                    }
                }
                else if (ch == '[')
                {
                    pcsCustom.Clear();
                    bInCharSetDef = true;
                }
                else if (ch == ']')
                {
                    pcsCurrent.Add(pcsCustom.ToString());

                    bInCharSetDef = false;
                    bGenerateChar = true;
                }
                else if (bInCharSetDef)
                {
                    if (pcsCustom.AddCharSet(ch) == false)
                    {
                        pcsCustom.Add(ch);
                    }
                }
                else if (pcsCurrent.AddCharSet(ch) == false)
                {
                    vGenerated.AddLast(ch);
                    pcsUsed.Add(ch);
                }
                else
                {
                    bGenerateChar = true;
                }

                if (bGenerateChar)
                {
                    PwGenerator.PrepareCharSet(pcsCurrent, pwProfile);

                    if (pwProfile.NoRepeatingCharacters)
                    {
                        pcsCurrent.Remove(pcsUsed.ToString());
                    }

                    char chGen = PwGenerator.GenerateCharacter(pwProfile,
                                                               pcsCurrent, crsRandomSource);

                    if (chGen == char.MinValue)
                    {
                        return(PwgError.TooFewCharacters);
                    }

                    vGenerated.AddLast(chGen);
                    pcsUsed.Add(chGen);
                }

                ch = csStream.ReadChar();
            }

            if (vGenerated.Count == 0)
            {
                return(PwgError.Success);
            }

            char[] vArray = new char[vGenerated.Count];
            vGenerated.CopyTo(vArray, 0);

            if (pwProfile.PatternPermutePassword)
            {
                PwGenerator.ShufflePassword(vArray, crsRandomSource);
            }

            byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vArray);
            psOut = new ProtectedString(true, pbUtf8);
            MemUtil.ZeroByteArray(pbUtf8);
            MemUtil.ZeroArray <char>(vArray);
            vGenerated.Clear();

            return(PwgError.Success);
        }
예제 #28
0
 public void ReadingStringWhenProtectionIsFullThrowsException()
 {
     // Assign
     var str = new ProtectedString("Test")
     {
         Mode = ProtectedStringMode.Full
     };
     // Act / Assert
     // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
     str.ToString();
 }
예제 #29
0
        private KdbContext EndXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.EndElement);

            if ((ctx == KdbContext.KeePassFile) && (xr.Name == ElemDocNode))
            {
                return(KdbContext.Null);
            }
            else if ((ctx == KdbContext.Meta) && (xr.Name == ElemMeta))
            {
                return(KdbContext.KeePassFile);
            }
            else if ((ctx == KdbContext.Root) && (xr.Name == ElemRoot))
            {
                return(KdbContext.KeePassFile);
            }
            else if ((ctx == KdbContext.MemoryProtection) && (xr.Name == ElemMemoryProt))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomIcons) && (xr.Name == ElemCustomIcons))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem))
            {
                if (!m_uuidCustomIconID.Equals(PwUuid.Zero) &&
                    (m_pbCustomIconData != null))
                {
                    m_pwDatabase.CustomIcons.Add(new PwCustomIcon(
                                                     m_uuidCustomIconID, m_pbCustomIconData));
                }
                else
                {
                    Debug.Assert(false);
                }

                m_uuidCustomIconID = PwUuid.Zero;
                m_pbCustomIconData = null;

                return(KdbContext.CustomIcons);
            }
            else if ((ctx == KdbContext.Binaries) && (xr.Name == ElemBinaries))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomData) && (xr.Name == ElemCustomData))
            {
                return(KdbContext.Meta);
            }
            else if ((ctx == KdbContext.CustomDataItem) && (xr.Name == ElemStringDictExItem))
            {
                if ((m_strCustomDataKey != null) && (m_strCustomDataValue != null))
                {
                    m_pwDatabase.CustomData.Set(m_strCustomDataKey, m_strCustomDataValue);
                }
                else
                {
                    Debug.Assert(false);
                }

                m_strCustomDataKey   = null;
                m_strCustomDataValue = null;

                return(KdbContext.CustomData);
            }
            else if ((ctx == KdbContext.Group) && (xr.Name == ElemGroup))
            {
                if (PwUuid.Zero.Equals(m_ctxGroup.Uuid))
                {
                    m_ctxGroup.Uuid = new PwUuid(true);                     // No assert (import)
                }
                m_ctxGroups.Pop();

                if (m_ctxGroups.Count == 0)
                {
                    m_ctxGroup = null;
                    return(KdbContext.Root);
                }
                else
                {
                    m_ctxGroup = m_ctxGroups.Peek();
                    return(KdbContext.Group);
                }
            }
            else if ((ctx == KdbContext.GroupTimes) && (xr.Name == ElemTimes))
            {
                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.GroupCustomData) && (xr.Name == ElemCustomData))
            {
                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.GroupCustomDataItem) && (xr.Name == ElemStringDictExItem))
            {
                if ((m_strGroupCustomDataKey != null) && (m_strGroupCustomDataValue != null))
                {
                    m_ctxGroup.CustomData.Set(m_strGroupCustomDataKey, m_strGroupCustomDataValue);
                }
                else
                {
                    Debug.Assert(false);
                }

                m_strGroupCustomDataKey   = null;
                m_strGroupCustomDataValue = null;

                return(KdbContext.GroupCustomData);
            }
            else if ((ctx == KdbContext.Entry) && (xr.Name == ElemEntry))
            {
                // Create new UUID if absent
                if (PwUuid.Zero.Equals(m_ctxEntry.Uuid))
                {
                    m_ctxEntry.Uuid = new PwUuid(true);                     // No assert (import)
                }
                if (m_bEntryInHistory)
                {
                    m_ctxEntry = m_ctxHistoryBase;
                    return(KdbContext.EntryHistory);
                }

                return(KdbContext.Group);
            }
            else if ((ctx == KdbContext.EntryTimes) && (xr.Name == ElemTimes))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryString) && (xr.Name == ElemString))
            {
                m_ctxEntry.Strings.Set(m_ctxStringName, m_ctxStringValue);
                m_ctxStringName  = null;
                m_ctxStringValue = null;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryBinary) && (xr.Name == ElemBinary))
            {
                if (string.IsNullOrEmpty(m_strDetachBins))
                {
                    m_ctxEntry.Binaries.Set(m_ctxBinaryName, m_ctxBinaryValue);
                }
                else
                {
                    SaveBinary(m_ctxBinaryName, m_ctxBinaryValue, m_strDetachBins);

                    m_ctxBinaryValue = null;
                    GC.Collect();
                }

                m_ctxBinaryName  = null;
                m_ctxBinaryValue = null;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryAutoType) && (xr.Name == ElemAutoType))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryAutoTypeItem) && (xr.Name == ElemAutoTypeItem))
            {
                AutoTypeAssociation atAssoc = new AutoTypeAssociation(m_ctxATName,
                                                                      m_ctxATSeq);
                m_ctxEntry.AutoType.Add(atAssoc);
                m_ctxATName = null;
                m_ctxATSeq  = null;
                return(KdbContext.EntryAutoType);
            }
            else if ((ctx == KdbContext.EntryCustomData) && (xr.Name == ElemCustomData))
            {
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.EntryCustomDataItem) && (xr.Name == ElemStringDictExItem))
            {
                if ((m_strEntryCustomDataKey != null) && (m_strEntryCustomDataValue != null))
                {
                    m_ctxEntry.CustomData.Set(m_strEntryCustomDataKey, m_strEntryCustomDataValue);
                }
                else
                {
                    Debug.Assert(false);
                }

                m_strEntryCustomDataKey   = null;
                m_strEntryCustomDataValue = null;

                return(KdbContext.EntryCustomData);
            }
            else if ((ctx == KdbContext.EntryHistory) && (xr.Name == ElemHistory))
            {
                m_bEntryInHistory = false;
                return(KdbContext.Entry);
            }
            else if ((ctx == KdbContext.RootDeletedObjects) && (xr.Name == ElemDeletedObjects))
            {
                return(KdbContext.Root);
            }
            else if ((ctx == KdbContext.DeletedObject) && (xr.Name == ElemDeletedObject))
            {
                m_ctxDeletedObject = null;
                return(KdbContext.RootDeletedObjects);
            }
            else
            {
                Debug.Assert(false);
                throw new FormatException();
            }
        }
예제 #30
0
 public void NewWithStringSetsProtectionToPartialAndStoresString()
 {
     // Assign / Act
     var str = new ProtectedString("Test");
     // Assert
     Assert.AreEqual(ProtectedStringMode.Partial, str.Mode);
     Assert.AreEqual("Test", str.ToString());
 }
예제 #31
0
        private void WriteObject(string name, ProtectedString value, bool bIsEntryString)
        {
            Debug.Assert(name != null);
            Debug.Assert(value != null); if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            m_xmlWriter.WriteStartElement(ElemString);
            m_xmlWriter.WriteStartElement(ElemKey);
            m_xmlWriter.WriteString(StrUtil.SafeXmlString(name));
            m_xmlWriter.WriteEndElement();
            m_xmlWriter.WriteStartElement(ElemValue);

            bool bProtected = value.IsProtected;

            if (bIsEntryString)
            {
                // Adjust memory protection setting (which might be different
                // from the database default, e.g. due to an import which
                // didn't specify the correct setting)
                if (name == PwDefs.TitleField)
                {
                    bProtected = m_pwDatabase.MemoryProtection.ProtectTitle;
                }
                else if (name == PwDefs.UserNameField)
                {
                    bProtected = m_pwDatabase.MemoryProtection.ProtectUserName;
                }
                else if (name == PwDefs.PasswordField)
                {
                    bProtected = m_pwDatabase.MemoryProtection.ProtectPassword;
                }
                else if (name == PwDefs.UrlField)
                {
                    bProtected = m_pwDatabase.MemoryProtection.ProtectUrl;
                }
                else if (name == PwDefs.NotesField)
                {
                    bProtected = m_pwDatabase.MemoryProtection.ProtectNotes;
                }
            }

            if (bProtected && (m_format == KdbxFormat.Default))
            {
                m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);

                byte[] pbEncoded = value.ReadXorredString(m_randomStream);
                if (pbEncoded.Length > 0)
                {
                    m_xmlWriter.WriteBase64(pbEncoded, 0, pbEncoded.Length);
                }
            }
            else
            {
                string strValue = value.ReadString();

                // If names should be localized, we need to apply the language-dependent
                // string transformation here. By default, language-dependent conversions
                // should be applied, otherwise characters could be rendered incorrectly
                // (code page problems).
                if (m_bLocalizedNames)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (char ch in strValue)
                    {
                        char chMapped = ch;

                        // Symbols and surrogates must be moved into the correct code
                        // page area
                        if (char.IsSymbol(ch) || char.IsSurrogate(ch))
                        {
                            System.Globalization.UnicodeCategory cat =
                                CharUnicodeInfo.GetUnicodeCategory(ch);
                            // Map character to correct position in code page
                            chMapped = (char)((int)cat * 32 + ch);
                        }
                        else if (char.IsControl(ch))
                        {
                            if (ch >= 256)                            // Control character in high ANSI code page
                            {
                                // Some of the control characters map to corresponding ones
                                // in the low ANSI range (up to 255) when calling
                                // ToLower on them with invariant culture (see
                                // http://lists.ximian.com/pipermail/mono-patches/2002-February/086106.html )
#if !KeePassLibSD
                                chMapped = char.ToLowerInvariant(ch);
#else
                                chMapped = char.ToLower(ch);
#endif
                            }
                        }

                        sb.Append(chMapped);
                    }

                    strValue = sb.ToString();                     // Correct string for current code page
                }

                if ((m_format == KdbxFormat.PlainXml) && bProtected)
                {
                    m_xmlWriter.WriteAttributeString(AttrProtectedInMemPlainXml, ValTrue);
                }

                m_xmlWriter.WriteString(StrUtil.SafeXmlString(strValue));
            }

            m_xmlWriter.WriteEndElement();             // ElemValue
            m_xmlWriter.WriteEndElement();             // ElemString
        }
예제 #32
0
        public static PwProfile DeriveFromPassword(ProtectedString psPassword)
        {
            PwProfile pp = new PwProfile();

            Debug.Assert(psPassword != null); if (psPassword == null)
            {
                return(pp);
            }

            byte[] pbUTF8 = psPassword.ReadUtf8();
            char[] vChars = Encoding.UTF8.GetChars(pbUTF8);

            pp.GeneratorType = PasswordGeneratorType.CharSet;
            pp.Length        = (uint)vChars.Length;

            PwCharSet pcs = pp.CharSet;

            pcs.Clear();

            foreach (char ch in vChars)
            {
                if ((ch >= 'A') && (ch <= 'Z'))
                {
                    pcs.Add(PwCharSet.UpperCase);
                }
                else if ((ch >= 'a') && (ch <= 'z'))
                {
                    pcs.Add(PwCharSet.LowerCase);
                }
                else if ((ch >= '0') && (ch <= '9'))
                {
                    pcs.Add(PwCharSet.Digits);
                }
                else if ((@"!#$%&'*+,./:;=?@^").IndexOf(ch) >= 0)
                {
                    pcs.Add(pcs.SpecialChars);
                }
                else if (ch == ' ')
                {
                    pcs.Add(' ');
                }
                else if (ch == '-')
                {
                    pcs.Add('-');
                }
                else if (ch == '_')
                {
                    pcs.Add('_');
                }
                else if (ch == '\"')
                {
                    pcs.Add(pcs.SpecialChars);
                }
                else if (ch == '\\')
                {
                    pcs.Add(pcs.SpecialChars);
                }
                else if ((@"()[]{}<>").IndexOf(ch) >= 0)
                {
                    pcs.Add(PwCharSet.Brackets);
                }
                else if ((ch >= '~') && (ch <= 255))
                {
                    pcs.Add(pcs.HighAnsiChars);
                }
                else
                {
                    pcs.Add(ch);
                }
            }

            Array.Clear(vChars, 0, vChars.Length);
            Array.Clear(pbUTF8, 0, pbUTF8.Length);

            return(pp);
        }
예제 #33
0
 public void SettingValueToNullClearsProtectedString()
 {
     // Assign
     var str = new ProtectedString("Test");
     // Act
     str.Value = null;
     // Assert
     Assert.IsNull(str.ToString());
     str.Mode = ProtectedStringMode.Full;
     Assert.IsNull(str.ToSecureString());
 }
예제 #34
0
        private KdbContext ReadXmlElement(KdbContext ctx, XmlReader xr)
        {
            Debug.Assert(xr.NodeType == XmlNodeType.Element);

            switch (ctx)
            {
            case KdbContext.Null:
                if (xr.Name == ElemDocNode)
                {
                    return(SwitchContext(ctx, KdbContext.KeePassFile, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.KeePassFile:
                if (xr.Name == ElemMeta)
                {
                    return(SwitchContext(ctx, KdbContext.Meta, xr));
                }
                else if (xr.Name == ElemRoot)
                {
                    return(SwitchContext(ctx, KdbContext.Root, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Meta:
                if (xr.Name == ElemGenerator)
                {
                    ReadString(xr);                             // Ignore
                }
                else if (xr.Name == ElemHeaderHash)
                {
                    // The header hash is typically only stored in
                    // KDBX <= 3.1 files, not in KDBX >= 4 files
                    // (here, the header is verified via a HMAC),
                    // but we also support it for KDBX >= 4 files
                    // (i.e. if it's present, we check it)

                    string strHash = ReadString(xr);
                    if (!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
                        !m_bRepairMode)
                    {
                        Debug.Assert(m_uFileVersion < FileVersion32_4);

                        byte[] pbHash = Convert.FromBase64String(strHash);
                        if (!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
                        {
                            throw new InvalidDataException(KLRes.FileCorrupted);
                        }
                    }
                }
                else if (xr.Name == ElemSettingsChanged)
                {
                    m_pwDatabase.SettingsChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbName)
                {
                    m_pwDatabase.Name = ReadString(xr);
                }
                else if (xr.Name == ElemDbNameChanged)
                {
                    m_pwDatabase.NameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDesc)
                {
                    m_pwDatabase.Description = ReadString(xr);
                }
                else if (xr.Name == ElemDbDescChanged)
                {
                    m_pwDatabase.DescriptionChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbDefaultUser)
                {
                    m_pwDatabase.DefaultUserName = ReadString(xr);
                }
                else if (xr.Name == ElemDbDefaultUserChanged)
                {
                    m_pwDatabase.DefaultUserNameChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbMntncHistoryDays)
                {
                    m_pwDatabase.MaintenanceHistoryDays = ReadUInt(xr, 365);
                }
                else if (xr.Name == ElemDbColor)
                {
                    string strColor = ReadString(xr);
                    if (!string.IsNullOrEmpty(strColor))
                    {
                        if (strColor.StartsWith("#"))
                        {
                            m_pwDatabase.Color = Color.FromArgb(0xFF, Color.FromArgb(
                                                                    Convert.ToInt32(strColor.Substring(1), 16)));
                        }
                        else
                        {
                            m_pwDatabase.Color = Color.FromName(strColor);
                        }
                    }
                }
                else if (xr.Name == ElemDbKeyChanged)
                {
                    m_pwDatabase.MasterKeyChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemDbKeyChangeRec)
                {
                    m_pwDatabase.MasterKeyChangeRec = ReadLong(xr, -1);
                }
                else if (xr.Name == ElemDbKeyChangeForce)
                {
                    m_pwDatabase.MasterKeyChangeForce = ReadLong(xr, -1);
                }
                else if (xr.Name == ElemDbKeyChangeForceOnce)
                {
                    m_pwDatabase.MasterKeyChangeForceOnce = ReadBool(xr, false);
                }
                else if (xr.Name == ElemMemoryProt)
                {
                    return(SwitchContext(ctx, KdbContext.MemoryProtection, xr));
                }
                else if (xr.Name == ElemCustomIcons)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcons, xr));
                }
                else if (xr.Name == ElemRecycleBinEnabled)
                {
                    m_pwDatabase.RecycleBinEnabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemRecycleBinUuid)
                {
                    m_pwDatabase.RecycleBinUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemRecycleBinChanged)
                {
                    m_pwDatabase.RecycleBinChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroup)
                {
                    m_pwDatabase.EntryTemplatesGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemEntryTemplatesGroupChanged)
                {
                    m_pwDatabase.EntryTemplatesGroupChanged = ReadTime(xr);
                }
                else if (xr.Name == ElemHistoryMaxItems)
                {
                    m_pwDatabase.HistoryMaxItems = ReadInt(xr, -1);
                }
                else if (xr.Name == ElemHistoryMaxSize)
                {
                    m_pwDatabase.HistoryMaxSize = ReadLong(xr, -1);
                }
                else if (xr.Name == ElemLastSelectedGroup)
                {
                    m_pwDatabase.LastSelectedGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemLastTopVisibleGroup)
                {
                    m_pwDatabase.LastTopVisibleGroup = ReadUuid(xr);
                }
                else if (xr.Name == ElemBinaries)
                {
                    return(SwitchContext(ctx, KdbContext.Binaries, xr));
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.CustomData, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.MemoryProtection:
                if (xr.Name == ElemProtTitle)
                {
                    m_pwDatabase.MemoryProtection.ProtectTitle = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtUserName)
                {
                    m_pwDatabase.MemoryProtection.ProtectUserName = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtPassword)
                {
                    m_pwDatabase.MemoryProtection.ProtectPassword = ReadBool(xr, true);
                }
                else if (xr.Name == ElemProtUrl)
                {
                    m_pwDatabase.MemoryProtection.ProtectUrl = ReadBool(xr, false);
                }
                else if (xr.Name == ElemProtNotes)
                {
                    m_pwDatabase.MemoryProtection.ProtectNotes = ReadBool(xr, false);
                }
                // else if(xr.Name == ElemProtAutoHide)
                //	m_pwDatabase.MemoryProtection.AutoEnableVisualHiding = ReadBool(xr, true);
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcons:
                if (xr.Name == ElemCustomIconItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomIcon, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomIcon:
                if (xr.Name == ElemCustomIconItemID)
                {
                    m_uuidCustomIconID = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomIconItemData)
                {
                    string strData = ReadString(xr);
                    if (!string.IsNullOrEmpty(strData))
                    {
                        m_pbCustomIconData = Convert.FromBase64String(strData);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Binaries:
                if (xr.Name == ElemBinary)
                {
                    if (xr.MoveToAttribute(AttrId))
                    {
                        string          strKey = xr.Value;
                        ProtectedBinary pbData = ReadProtectedBinary(xr);

                        int iKey;
                        if (!StrUtil.TryParseIntInvariant(strKey, out iKey))
                        {
                            throw new FormatException();
                        }
                        if (iKey < 0)
                        {
                            throw new FormatException();
                        }

                        Debug.Assert(m_pbsBinaries.Get(iKey) == null);
                        Debug.Assert(m_pbsBinaries.Find(pbData) < 0);
                        m_pbsBinaries.Set(iKey, pbData);
                    }
                    else
                    {
                        ReadUnknown(xr);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.CustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.CustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Root:
                if (xr.Name == ElemGroup)
                {
                    Debug.Assert(m_ctxGroups.Count == 0);
                    if (m_ctxGroups.Count != 0)
                    {
                        throw new FormatException();
                    }

                    m_pwDatabase.RootGroup = new PwGroup(false, false);
                    m_ctxGroups.Push(m_pwDatabase.RootGroup);
                    m_ctxGroup = m_ctxGroups.Peek();

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemDeletedObjects)
                {
                    return(SwitchContext(ctx, KdbContext.RootDeletedObjects, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Group:
                if (xr.Name == ElemUuid)
                {
                    m_ctxGroup.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemName)
                {
                    m_ctxGroup.Name = ReadString(xr);
                }
                else if (xr.Name == ElemNotes)
                {
                    m_ctxGroup.Notes = ReadString(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxGroup.IconId = ReadIconId(xr, PwIcon.Folder);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxGroup.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.GroupTimes, xr));
                }
                else if (xr.Name == ElemIsExpanded)
                {
                    m_ctxGroup.IsExpanded = ReadBool(xr, true);
                }
                else if (xr.Name == ElemGroupDefaultAutoTypeSeq)
                {
                    m_ctxGroup.DefaultAutoTypeSequence = ReadString(xr);
                }
                else if (xr.Name == ElemEnableAutoType)
                {
                    m_ctxGroup.EnableAutoType = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemEnableSearching)
                {
                    m_ctxGroup.EnableSearching = StrUtil.StringToBoolEx(ReadString(xr));
                }
                else if (xr.Name == ElemLastTopVisibleEntry)
                {
                    m_ctxGroup.LastTopVisibleEntry = ReadUuid(xr);
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.GroupCustomData, xr));
                }
                else if (xr.Name == ElemGroup)
                {
                    m_ctxGroup = new PwGroup(false, false);
                    m_ctxGroups.Peek().AddGroup(m_ctxGroup, true);

                    m_ctxGroups.Push(m_ctxGroup);

                    return(SwitchContext(ctx, KdbContext.Group, xr));
                }
                else if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxGroup.AddEntry(m_ctxEntry, true);

                    m_bEntryInHistory = false;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupCustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.GroupCustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupCustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strGroupCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strGroupCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.Entry:
                if (xr.Name == ElemUuid)
                {
                    m_ctxEntry.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemIcon)
                {
                    m_ctxEntry.IconId = ReadIconId(xr, PwIcon.Key);
                }
                else if (xr.Name == ElemCustomIconID)
                {
                    m_ctxEntry.CustomIconUuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemFgColor)
                {
                    string strColor = ReadString(xr);
                    if (!string.IsNullOrEmpty(strColor))
                    {
                        m_ctxEntry.ForegroundColor = Color.FromName(strColor);
                    }
                }
                else if (xr.Name == ElemBgColor)
                {
                    string strColor = ReadString(xr);
                    if (!string.IsNullOrEmpty(strColor))
                    {
                        m_ctxEntry.BackgroundColor = Color.FromName(strColor);
                    }
                }
                else if (xr.Name == ElemOverrideUrl)
                {
                    m_ctxEntry.OverrideUrl = ReadString(xr);
                }
                else if (xr.Name == ElemTags)
                {
                    m_ctxEntry.Tags = StrUtil.StringToTags(ReadString(xr));
                }
                else if (xr.Name == ElemTimes)
                {
                    return(SwitchContext(ctx, KdbContext.EntryTimes, xr));
                }
                else if (xr.Name == ElemString)
                {
                    return(SwitchContext(ctx, KdbContext.EntryString, xr));
                }
                else if (xr.Name == ElemBinary)
                {
                    return(SwitchContext(ctx, KdbContext.EntryBinary, xr));
                }
                else if (xr.Name == ElemAutoType)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoType, xr));
                }
                else if (xr.Name == ElemCustomData)
                {
                    return(SwitchContext(ctx, KdbContext.EntryCustomData, xr));
                }
                else if (xr.Name == ElemHistory)
                {
                    Debug.Assert(m_bEntryInHistory == false);

                    if (m_bEntryInHistory == false)
                    {
                        m_ctxHistoryBase = m_ctxEntry;
                        return(SwitchContext(ctx, KdbContext.EntryHistory, xr));
                    }
                    else
                    {
                        ReadUnknown(xr);
                    }
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.GroupTimes:
            case KdbContext.EntryTimes:
                ITimeLogger tl = ((ctx == KdbContext.GroupTimes) ?
                                  (ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
                Debug.Assert(tl != null);

                if (xr.Name == ElemCreationTime)
                {
                    tl.CreationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemLastModTime)
                {
                    tl.LastModificationTime = ReadTime(xr);
                }
                else if (xr.Name == ElemLastAccessTime)
                {
                    tl.LastAccessTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpiryTime)
                {
                    tl.ExpiryTime = ReadTime(xr);
                }
                else if (xr.Name == ElemExpires)
                {
                    tl.Expires = ReadBool(xr, false);
                }
                else if (xr.Name == ElemUsageCount)
                {
                    tl.UsageCount = ReadULong(xr, 0);
                }
                else if (xr.Name == ElemLocationChanged)
                {
                    tl.LocationChanged = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryString:
                if (xr.Name == ElemKey)
                {
                    m_ctxStringName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxStringValue = ReadProtectedString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryBinary:
                if (xr.Name == ElemKey)
                {
                    m_ctxBinaryName = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_ctxBinaryValue = ReadProtectedBinary(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoType:
                if (xr.Name == ElemAutoTypeEnabled)
                {
                    m_ctxEntry.AutoType.Enabled = ReadBool(xr, true);
                }
                else if (xr.Name == ElemAutoTypeObfuscation)
                {
                    m_ctxEntry.AutoType.ObfuscationOptions =
                        (AutoTypeObfuscationOptions)ReadInt(xr, 0);
                }
                else if (xr.Name == ElemAutoTypeDefaultSeq)
                {
                    m_ctxEntry.AutoType.DefaultSequence = ReadString(xr);
                }
                else if (xr.Name == ElemAutoTypeItem)
                {
                    return(SwitchContext(ctx, KdbContext.EntryAutoTypeItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryAutoTypeItem:
                if (xr.Name == ElemWindow)
                {
                    m_ctxATName = ReadString(xr);
                }
                else if (xr.Name == ElemKeystrokeSequence)
                {
                    m_ctxATSeq = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryCustomData:
                if (xr.Name == ElemStringDictExItem)
                {
                    return(SwitchContext(ctx, KdbContext.EntryCustomDataItem, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryCustomDataItem:
                if (xr.Name == ElemKey)
                {
                    m_strEntryCustomDataKey = ReadString(xr);
                }
                else if (xr.Name == ElemValue)
                {
                    m_strEntryCustomDataValue = ReadString(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.EntryHistory:
                if (xr.Name == ElemEntry)
                {
                    m_ctxEntry = new PwEntry(false, false);
                    m_ctxHistoryBase.History.Add(m_ctxEntry);

                    m_bEntryInHistory = true;
                    return(SwitchContext(ctx, KdbContext.Entry, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.RootDeletedObjects:
                if (xr.Name == ElemDeletedObject)
                {
                    m_ctxDeletedObject = new PwDeletedObject();
                    m_pwDatabase.DeletedObjects.Add(m_ctxDeletedObject);

                    return(SwitchContext(ctx, KdbContext.DeletedObject, xr));
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            case KdbContext.DeletedObject:
                if (xr.Name == ElemUuid)
                {
                    m_ctxDeletedObject.Uuid = ReadUuid(xr);
                }
                else if (xr.Name == ElemDeletionTime)
                {
                    m_ctxDeletedObject.DeletionTime = ReadTime(xr);
                }
                else
                {
                    ReadUnknown(xr);
                }
                break;

            default:
                ReadUnknown(xr);
                break;
            }

            return(ctx);
        }
예제 #35
0
 public void NewWithSecureStringSetsProtectionToFullAndStoresString()
 {
     // Assign / Act
     var secStr = new SecureString();
     var str = new ProtectedString(secStr);
     // Assert
     Assert.AreEqual(ProtectedStringMode.Full, str.Mode);
     Assert.AreEqual(secStr, str.ToSecureString());
 }
예제 #36
0
        private void OnFormLoad(object sender, EventArgs e)
        {
            m_bInitializing = true;

            GlobalWindowManager.AddWindow(this);
            // if(m_bRedirectActivation) Program.MainForm.RedirectActivationPush(this);

            string strBannerTitle = (!string.IsNullOrEmpty(m_strCustomTitle) ?
                                     m_strCustomTitle : KPRes.EnterCompositeKey);
            string strBannerDesc = WinUtil.CompactPath(m_ioInfo.Path, 45);

            BannerFactory.CreateBannerEx(this, m_bannerImage,
                                         Properties.Resources.B48x48_KGPG_Key2, strBannerTitle, strBannerDesc);
            this.Icon = AppIcons.Default;

            FontUtil.SetDefaultFont(m_cbPassword);
            FontUtil.AssignDefaultBold(m_cbPassword);
            FontUtil.AssignDefaultBold(m_cbKeyFile);
            FontUtil.AssignDefaultBold(m_cbUserAccount);

            UIUtil.ConfigureToolTip(m_ttRect);
            // m_ttRect.SetToolTip(m_cbHidePassword, KPRes.TogglePasswordAsterisks);
            m_ttRect.SetToolTip(m_btnOpenKeyFile, KPRes.KeyFileSelect);

            PwInputControlGroup.ConfigureHideButton(m_cbHidePassword, m_ttRect);

            string strStart = (!string.IsNullOrEmpty(m_strCustomTitle) ?
                               m_strCustomTitle : KPRes.OpenDatabase);
            string strNameEx = UrlUtil.GetFileName(m_ioInfo.Path);

            if (!string.IsNullOrEmpty(strNameEx))
            {
                this.Text = strStart + " - " + strNameEx;
            }
            else
            {
                this.Text = strStart;
            }

            // Must be set manually due to possible object override
            m_tbPassword.TextChanged += this.ProcessTextChangedPassword;

            // m_cmbKeyFile.OrderedImageList = m_lKeyFileImages;
            AddKeyFileSuggPriv(KPRes.NoKeyFileSpecifiedMeta, true);

            // Do not directly compare with Program.CommandLineArgs.FileName,
            // because this may be a relative path instead of an absolute one
            string strCmdLineFile = Program.CommandLineArgs.FileName;

            if ((strCmdLineFile != null) && (Program.MainForm != null))
            {
                strCmdLineFile = Program.MainForm.IocFromCommandLine().Path;
            }
            if ((strCmdLineFile != null) && strCmdLineFile.Equals(m_ioInfo.Path,
                                                                  StrUtil.CaseIgnoreCmp))
            {
                string str;

                str = Program.CommandLineArgs[AppDefs.CommandLineOptions.Password];
                if (str != null)
                {
                    m_cbPassword.Checked = true;
                    m_tbPassword.Text    = str;
                }

                str = Program.CommandLineArgs[AppDefs.CommandLineOptions.PasswordEncrypted];
                if (str != null)
                {
                    m_cbPassword.Checked = true;
                    m_tbPassword.Text    = StrUtil.DecryptString(str);
                }

                str = Program.CommandLineArgs[AppDefs.CommandLineOptions.PasswordStdIn];
                if (str != null)
                {
                    ProtectedString ps = KeyUtil.ReadPasswordStdIn(true);
                    if (ps != null)
                    {
                        m_cbPassword.Checked = true;
                        m_tbPassword.TextEx  = ps;
                    }
                }

                str = Program.CommandLineArgs[AppDefs.CommandLineOptions.KeyFile];
                if (str != null)
                {
                    m_cbKeyFile.Checked = true;
                    AddKeyFileSuggPriv(str, true);
                }

                str = Program.CommandLineArgs[AppDefs.CommandLineOptions.PreSelect];
                if (str != null)
                {
                    m_cbKeyFile.Checked = true;
                    AddKeyFileSuggPriv(str, true);
                }
            }

            m_cbHidePassword.Checked = true;
            OnCheckedHidePassword(sender, e);

            Debug.Assert(m_cmbKeyFile.Text.Length != 0);

            m_btnExit.Enabled = m_bCanExit;
            m_btnExit.Visible = m_bCanExit;

            ulong uKpf = Program.Config.UI.KeyPromptFlags;

            UIUtil.ApplyKeyUIFlags(uKpf, m_cbPassword, m_cbKeyFile,
                                   m_cbUserAccount, m_cbHidePassword);

            if ((uKpf & (ulong)AceKeyUIFlags.DisableKeyFile) != 0)
            {
                UIUtil.SetEnabled(m_cmbKeyFile, m_cbKeyFile.Checked);
                UIUtil.SetEnabled(m_btnOpenKeyFile, m_cbKeyFile.Checked);
            }

            if (((uKpf & (ulong)AceKeyUIFlags.CheckPassword) != 0) ||
                ((uKpf & (ulong)AceKeyUIFlags.UncheckPassword) != 0))
            {
                m_bPwStatePreset = true;
            }
            if (((uKpf & (ulong)AceKeyUIFlags.CheckUserAccount) != 0) ||
                ((uKpf & (ulong)AceKeyUIFlags.UncheckUserAccount) != 0))
            {
                m_bUaStatePreset = true;
            }

            CustomizeForScreenReader();
            EnableUserControls();

            m_bInitializing = false;

            // E.g. command line options have higher priority
            m_bCanModKeyFile = (m_cmbKeyFile.SelectedIndex == 0);

            m_aKeyAssoc = Program.Config.Defaults.GetKeySources(m_ioInfo);
            if (m_aKeyAssoc != null)
            {
                if (m_aKeyAssoc.Password && !m_bPwStatePreset)
                {
                    m_cbPassword.Checked = true;
                }

                if (m_aKeyAssoc.KeyFilePath.Length > 0)
                {
                    AddKeyFileSuggPriv(m_aKeyAssoc.KeyFilePath, null);
                }

                if (m_aKeyAssoc.UserAccount && !m_bUaStatePreset)
                {
                    m_cbUserAccount.Checked = true;
                }
            }

            foreach (KeyProvider prov in Program.KeyProviderPool)
            {
                AddKeyFileSuggPriv(prov.Name, null);
            }

            // Local, but thread will continue to run anyway
            Thread th = new Thread(new ThreadStart(this.AsyncFormLoad));

            th.Start();
            // ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncFormLoad));

            this.BringToFront();
            this.Activate();
            // UIUtil.SetFocus(m_tbPassword, this); // See OnFormShown
        }
예제 #37
0
 public void ReadingSecuredStringWhenProtectionNotFullThrowsException()
 {
     // Assign
     var str = new ProtectedString(new SecureString())
     {
         Mode = ProtectedStringMode.None
     };
     // Act / Assert
     str.ToSecureString();
 }
예제 #38
0
 private void OnBtnOK(object sender, EventArgs e)
 {
     byte[] pbUtf8 = m_secWord.ToUtf8();
     m_psSelected = new ProtectedString(true, pbUtf8);
     MemUtil.ZeroByteArray(pbUtf8);
 }
예제 #39
0
 public void NewWithoutInitialSetsProtectionToNone()
 {
     // Assign / Act
     var str = new ProtectedString();
     // Assert
     Assert.AreEqual(ProtectedStringMode.None, str.Mode);
 }
        public void PrepareForm()
        {
            if (KeePassPasswordChangerExt.PrepareDatabase())
            {
                DialogResult allEntriesResult =
                    MessageBox.Show("Notice: Please read the about section of the plugin. This is an alpha release. Backup your Database before you use this plugin.\r\n\r\nDo you want to proceed?",
                                    "Notice", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (allEntriesResult == DialogResult.No)
                {
                    KeePassPasswordChangerExt.ExtentEntryNote("User aborted...");
                    this.Close();
                }
                else
                {
                    foreach (var pwEntry in KeePassPasswordChangerExt._mHost.MainWindow.ActiveDatabase.RootGroup.GetEntries(true))
                    {
                        try
                        {
                            if (KeePassPasswordChangerExt.GroupPlugin.FindEntry(pwEntry.Uuid, true) != null)
                            {
                                continue;
                            }
                            if (pwEntry.Strings.Get(PwDefs.UrlField) == null)
                            {
                                continue;
                            }

                            string   uri      = pwEntry.Strings.Get(PwDefs.UrlField).ReadString();
                            int      count    = 0;
                            Template template = null;
                            TemplateManagement.LoadTemplates();
                            foreach (var availableTemplate in TemplateManagement.AvailableTemplates)
                            {
                                if (availableTemplate.Value.BoundUrl.IsRegex.Value)
                                {
                                    if (Regex.IsMatch(uri, availableTemplate.Value.BoundUrl.Value.Value))
                                    {
                                        template = availableTemplate.Value;
                                        count++;
                                    }
                                }
                                else
                                {
                                    if (uri.Contains(availableTemplate.Value.BoundUrl.Value.Value) ||
                                        availableTemplate.Value.BoundUrl.Value.Value.Contains(uri))
                                    {
                                        template = availableTemplate.Value;
                                        count++;
                                    }
                                }
                            }
                            switch (count)
                            {
                            case 0:
                                KeePassPasswordChangerExt.ExtentEntryNote("Ignoring entry " +
                                                                          pwEntry.Strings.Get(PwDefs.TitleField).ReadString() + "(UID: " +
                                                                          pwEntry.Uuid.ToString() + ") it has no template");
                                continue;

                            case 1:
                            {
                                PwGroup dustbin =
                                    KeePassPasswordChangerExt._mHost.MainWindow.ActiveDatabase.RootGroup.FindGroup(
                                        KeePassPasswordChangerExt._mHost.MainWindow.ActiveDatabase.RecycleBinUuid, true);
                                if (dustbin != null)
                                {
                                    if (dustbin.FindEntry(pwEntry.Uuid, true) != null)
                                    {
                                        KeePassPasswordChangerExt.ExtentEntryNote("Ignoring entry " +
                                                                                  pwEntry.Strings.Get(
                                                                                      PwDefs.TitleField)
                                                                                  .ReadString() +
                                                                                  "(UID: " +
                                                                                  pwEntry.Uuid.ToString() +
                                                                                  ") because it is dustbinned");
                                        continue;
                                    }
                                    if (DateTimeNotLaterThan != DateTime.MinValue &&
                                        pwEntry.LastModificationTime >= DateTimeNotLaterThan)
                                    {
                                        KeePassPasswordChangerExt.ExtentEntryNote("Ignoring entry " +
                                                                                  pwEntry.Strings.Get(
                                                                                      PwDefs.TitleField)
                                                                                  .ReadString() +
                                                                                  "(UID: " +
                                                                                  pwEntry.Uuid.ToString() +
                                                                                  ") because was modified @ " +
                                                                                  pwEntry
                                                                                  .LastModificationTime
                                                                                  .ToString() +
                                                                                  "(UTC) and Limit is: " +
                                                                                  DateTimeNotLaterThan
                                                                                  .ToString() + "(UTC)");
                                        continue;
                                    }
                                }

                                KeePassPasswordChangerExt.ExtentEntryNote("Entry " + pwEntry.Strings.Get(PwDefs.TitleField).ReadString() + "(UID: " +
                                                                          pwEntry.Uuid.ToString() + ") matched on the template " + template.Name);
                                Template templateSibling = (Template)template.Clone();
                                List <KeyValuePairEx <string, ProtectedString> > parameters =
                                    new List <KeyValuePairEx <string, ProtectedString> >();
                                List <string> requiredParameters = template.GetRequiredKeepassVariables();
                                foreach (var requiredKeepassVariable in requiredParameters)
                                {
                                    try
                                    {
                                        if (
                                            BaseObject.ExtractSinglePlaceholderToString(requiredKeepassVariable) ==
                                            "")
                                        {
                                            ProtectedString newPassword = KeePassPasswordChangerExt
                                                                          .GeneratePassword(
                                                template.PasswordCreationPolicy);
                                            parameters.Add(
                                                new KeyValuePairEx <string, ProtectedString>(
                                                    BaseObject.ConvertStringToPlaceholderString(""), newPassword));
                                            continue;
                                        }
                                        bool foundPwDef = false;
                                        foreach (var pwdef in PwDefs.GetStandardFields())
                                        {
                                            if (pwdef ==
                                                BaseObject.ExtractSinglePlaceholderToString(
                                                    requiredKeepassVariable))
                                            {
                                                parameters.Add(
                                                    new KeyValuePairEx <string, ProtectedString>(
                                                        requiredKeepassVariable,
                                                        pwEntry.Strings.Get(
                                                            BaseObject.ExtractSinglePlaceholderToString(
                                                                requiredKeepassVariable))));
                                                foundPwDef = true;
                                                break;
                                            }
                                        }
                                        if (!foundPwDef)
                                        {
                                            parameters.Add(
                                                new KeyValuePairEx <string, ProtectedString>(
                                                    requiredKeepassVariable,
                                                    new ProtectedString(true, requiredKeepassVariable)));
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        ExceptionHandling.Handling.GetException("Unexpected", ex);
                                    }
                                }
                                if (requiredParameters.Count != parameters.Count)
                                {
                                    KeePassPasswordChangerExt.ExtentEntryNote(
                                        "Sorry, i could not gather all required parameters from the password entry " +
                                        pwEntry.Strings.Get(PwDefs.TitleField).ReadString());
                                }
                                else
                                {
                                    while (true)
                                    {
                                        try
                                        {
                                            templateSibling.GenerateNewUtid(KeePassPasswordChangerExt.Counter++.ToString());
                                            TemplateManagement.LockTemplates.AcquireWriterLock(Options.LockTimeOut);
                                            templateSibling.InitializeTemplate(parameters, KeePassPasswordChangerExt.CefControl, pwEntry.Strings.Get(PwDefs.TitleField).ReadString(), pwEntry.Uuid);
                                            TemplateManagement.TemplatesReady.Add(templateSibling.UTID,
                                                                                  templateSibling);
                                            break;
                                        }
                                        catch (ApplicationException ex)
                                        {
                                            ExceptionHandling.Handling.GetException("ReaderWriterLock", ex);
                                        }
                                        finally
                                        {
                                            if (TemplateManagement.LockTemplates.IsWriterLockHeld)
                                            {
                                                TemplateManagement.LockTemplates.ReleaseWriterLock();
                                            }
                                        }
                                    }
                                }
                            }
                            break;

                            default:     //Write detailed list!
                                KeePassPasswordChangerExt.ExtentEntryNote("Entry \"" + pwEntry.Strings.Get(PwDefs.TitleField).ReadString() +
                                                                          "\" matches on too many templates, ignoring this one, sorry");
                                continue;
                            }
                        }
                        catch (Exception ex)
                        {
                            ExceptionHandling.Handling.GetException("Unexpected", ex);
                        }
                    }
                }
            }
            else
            {
                return;
            }
            KeePassPasswordChangerExt.UnlockDatabase();
            CheckValues();
        }
예제 #41
0
 public void SettingValueToUnsupportedTypeThrowsException()
 {
     // Assign
     // ReSharper disable once UseObjectOrCollectionInitializer
     var str = new ProtectedString();
     // Act / Assert
     str.Value = new Object();
 }
예제 #42
0
        public bool EqualsDictionary(ProtectedStringDictionary dict,
                                     PwCompareOptions pwOpt, MemProtCmpMode mpCompare)
        {
            if (dict == null)
            {
                Debug.Assert(false); return(false);
            }

            bool bNeEqStd = ((pwOpt & PwCompareOptions.NullEmptyEquivStd) !=
                             PwCompareOptions.None);

            if (!bNeEqStd)
            {
                if (m_vStrings.Count != dict.m_vStrings.Count)
                {
                    return(false);
                }
            }

            foreach (KeyValuePair <string, ProtectedString> kvp in m_vStrings)
            {
                bool            bStdField = PwDefs.IsStandardField(kvp.Key);
                ProtectedString ps        = dict.Get(kvp.Key);

                if (bNeEqStd && (ps == null) && bStdField)
                {
                    ps = ProtectedString.Empty;
                }

                if (ps == null)
                {
                    return(false);
                }

                if (mpCompare == MemProtCmpMode.Full)
                {
                    if (ps.IsProtected != kvp.Value.IsProtected)
                    {
                        return(false);
                    }
                }
                else if (mpCompare == MemProtCmpMode.CustomOnly)
                {
                    if (!bStdField && (ps.IsProtected != kvp.Value.IsProtected))
                    {
                        return(false);
                    }
                }

                if (!ps.Equals(kvp.Value, false))
                {
                    return(false);
                }
            }

            if (bNeEqStd)
            {
                foreach (KeyValuePair <string, ProtectedString> kvp in dict.m_vStrings)
                {
                    ProtectedString ps = Get(kvp.Key);

                    if (ps != null)
                    {
                        continue;                                // Compared previously
                    }
                    if (!PwDefs.IsStandardField(kvp.Key))
                    {
                        return(false);
                    }
                    if (!kvp.Value.IsEmpty)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
예제 #43
0
 public void SwitchingFromSecureStringToStringChangesModeToProtected()
 {
     // Assign
     // ReSharper disable once UseObjectOrCollectionInitializer
     var str = new ProtectedString(new SecureString());
     // Act
     str.Value = "Test";
     // Assert
     Assert.AreEqual(ProtectedStringMode.Partial, str.Mode);
 }