Beispiel #1
0
        public static void Save(KPTranslation kpTrl, Stream sOut,
                                IXmlSerializerEx xs)
        {
            if (xs == null)
            {
                throw new ArgumentNullException("xs");
            }

#if !KeePassLibSD
            using (GZipStream gz = new GZipStream(sOut, CompressionMode.Compress))
#else
            using (GZipOutputStream gz = new GZipOutputStream(sOut))
#endif
            {
                using (XmlWriter xw = XmlUtilEx.CreateXmlWriter(gz))
                {
                    xs.Serialize(xw, kpTrl);
                }
            }

#if KeePassUWP
            sOut.Dispose();
#else
            sOut.Close();
#endif
        }
Beispiel #2
0
		private static void CreateXmlKeyFile(string strFile, byte[] pbKeyData)
		{
			Debug.Assert(strFile != null);
			if(strFile == null) throw new ArgumentNullException("strFile");
			Debug.Assert(pbKeyData != null);
			if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");

			IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
			using(Stream s = IOConnection.OpenWrite(ioc))
			{
				using(XmlWriter xw = XmlUtilEx.CreateXmlWriter(s))
				{
					xw.WriteStartDocument();
					xw.WriteStartElement(RootElementName); // <KeyFile>

					xw.WriteStartElement(MetaElementName); // <Meta>
					xw.WriteStartElement(VersionElementName); // <Version>
					xw.WriteString("1.00");
					xw.WriteEndElement(); // </Version>
					xw.WriteEndElement(); // </Meta>

					xw.WriteStartElement(KeyElementName); // <Key>

					xw.WriteStartElement(KeyDataElementName); // <Data>
					xw.WriteString(Convert.ToBase64String(pbKeyData));
					xw.WriteEndElement(); // </Data>

					xw.WriteEndElement(); // </Key>

					xw.WriteEndElement(); // </KeyFile>
					xw.WriteEndDocument();
				}
			}
		}
Beispiel #3
0
        private static void CreateXmlKeyFile(string strFile, byte[] pbKeyData)
        {
            Debug.Assert(strFile != null);
            if (strFile == null)
            {
                throw new ArgumentNullException("strFile");
            }
#endif
            Debug.Assert(pbKeyData != null);
            if (pbKeyData == null)
            {
                throw new ArgumentNullException("pbKeyData");
            }

#if ModernKeePassLib
            var fileContents = new byte[0];
            var ioc          = IOConnectionInfo.FromByteArray(fileContents);
#else
            IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
#endif
            using (Stream s = IOConnection.OpenWrite(ioc))
            {
                using (XmlWriter xw = XmlUtilEx.CreateXmlWriter(s))
                {
                    xw.WriteStartDocument();
                    xw.WriteStartElement(RootElementName);    // <KeyFile>

                    xw.WriteStartElement(MetaElementName);    // <Meta>
                    xw.WriteStartElement(VersionElementName); // <Version>
                    xw.WriteString("1.00");
                    xw.WriteEndElement();                     // </Version>
                    xw.WriteEndElement();                     // </Meta>

                    xw.WriteStartElement(KeyElementName);     // <Key>

                    xw.WriteStartElement(KeyDataElementName); // <Data>
                    xw.WriteString(Convert.ToBase64String(pbKeyData));
                    xw.WriteEndElement();                     // </Data>

                    xw.WriteEndElement();                     // </Key>

                    xw.WriteEndElement();                     // </KeyFile>
                    xw.WriteEndDocument();
                }
#if ModernKeePassLib
                return(((MemoryStream)s).ToArray());
#endif
            }
        }
Beispiel #4
0
        private static bool SaveConfigFileEx(AppConfigEx tConfig,
                                             string strFilePath, bool bRemoveConfigPref)
        {
            tConfig.OnSavePre();

            // Temporarily remove user file preference (restore after saving)
            bool bConfigPref = tConfig.Meta.PreferUserConfiguration;

            if (bRemoveConfigPref)
            {
                tConfig.Meta.PreferUserConfiguration = false;
            }

            bool bResult = true;

            try
            {
                Debug.Assert(!string.IsNullOrEmpty(strFilePath));
                IOConnectionInfo iocPath = IOConnectionInfo.FromPath(strFilePath);

                using (FileTransactionEx ft = new FileTransactionEx(iocPath,
                                                                    Program.Config.Application.UseTransactedConfigWrites))
                {
                    using (Stream s = ft.OpenWrite())
                    {
                        using (XmlWriter xw = XmlUtilEx.CreateXmlWriter(s))
                        {
                            XmlSerializerEx xs = new XmlSerializerEx(typeof(AppConfigEx));
                            xs.Serialize(xw, tConfig);
                        }
                    }

                    ft.CommitWrite();
                }
            }
            catch (Exception) { Debug.Assert(false); bResult = false; }

            if (bRemoveConfigPref)
            {
                tConfig.Meta.PreferUserConfiguration = bConfigPref;
            }

            AssertConfigPref(tConfig);

            tConfig.OnSavePost();
            return(bResult);
        }
        // public void Save(string strFile, PwGroup pgDataSource, KdbxFormat fmt,
        //	IStatusLogger slLogger)
        // {
        //	bool bMadeUnhidden = UrlUtil.UnhideFile(strFile);
        //
        //	IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
        //	this.Save(IOConnection.OpenWrite(ioc), pgDataSource, format, slLogger);
        //
        //	if(bMadeUnhidden) UrlUtil.HideFile(strFile, true); // Hide again
        // }

        /// <summary>
        /// Save the contents of the current <c>PwDatabase</c> to a KDBX file.
        /// </summary>
        /// <param name="sSaveTo">Stream to write the KDBX file into.</param>
        /// <param name="pgDataSource">Group containing all groups and
        /// entries to write. If <c>null</c>, the complete database will
        /// be written.</param>
        /// <param name="fmt">Format of the file to create.</param>
        /// <param name="slLogger">Logger that recieves status information.</param>
        public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat fmt,
                         IStatusLogger slLogger)
        {
            Debug.Assert(sSaveTo != null);
            if (sSaveTo == null)
            {
                throw new ArgumentNullException("sSaveTo");
            }

            if (m_bUsedOnce)
            {
                throw new InvalidOperationException("Do not reuse KdbxFile objects!");
            }
            m_bUsedOnce = true;

            m_format    = fmt;
            m_slLogger  = slLogger;
            m_xmlWriter = null;

            PwGroup      pgRoot   = (pgDataSource ?? m_pwDatabase.RootGroup);
            UTF8Encoding encNoBom = StrUtil.Utf8;
            CryptoRandom cr       = CryptoRandom.Instance;

            byte[] pbCipherKey = null;
            byte[] pbHmacKey64 = null;

            m_pbsBinaries.Clear();
            m_pbsBinaries.AddFrom(pgRoot);

            List <Stream> lStreams = new List <Stream>();

            lStreams.Add(sSaveTo);

            HashingStreamEx sHashing = new HashingStreamEx(sSaveTo, true, null);

            lStreams.Add(sHashing);

            try
            {
                m_uFileVersion = GetMinKdbxVersion();

                int           cbEncKey, cbEncIV;
                ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);

                m_pbMasterSeed   = cr.GetRandomBytes(32);
                m_pbEncryptionIV = cr.GetRandomBytes((uint)cbEncIV);

                // m_pbTransformSeed = cr.GetRandomBytes(32);
                PwUuid    puKdf = m_pwDatabase.KdfParameters.KdfUuid;
                KdfEngine kdf   = KdfPool.Get(puKdf);
                if (kdf == null)
                {
                    throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
                                        // KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
                                        "UUID: " + puKdf.ToHexString() + ".");
                }
                kdf.Randomize(m_pwDatabase.KdfParameters);

                if (m_format == KdbxFormat.Default)
                {
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.Salsa20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(32);
                    }
                    else                     // KDBX >= 4
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.ChaCha20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(64);
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbInnerRandomStreamKey);
                }

                if (m_uFileVersion < FileVersion32_4)
                {
                    m_pbStreamStartBytes = cr.GetRandomBytes(32);
                }

                Stream sXml;
                if (m_format == KdbxFormat.Default)
                {
                    byte[] pbHeader = GenerateHeader();
                    m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);

                    MemUtil.Write(sHashing, pbHeader);
                    sHashing.Flush();

                    ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);

                    Stream sPlain;
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        Stream sEncrypted = EncryptStream(sHashing, iCipher,
                                                          pbCipherKey, cbEncIV, true);
                        if ((sEncrypted == null) || (sEncrypted == sHashing))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                        lStreams.Add(sEncrypted);

                        MemUtil.Write(sEncrypted, m_pbStreamStartBytes);

                        sPlain = new HashedBlockStream(sEncrypted, true);
                    }
                    else                     // KDBX >= 4
                    {
                        // For integrity checking (without knowing the master key)
                        MemUtil.Write(sHashing, m_pbHashOfHeader);

                        byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
                        MemUtil.Write(sHashing, pbHeaderHmac);

                        Stream sBlocks = new HmacBlockStream(sHashing, true,
                                                             true, pbHmacKey64);
                        lStreams.Add(sBlocks);

                        sPlain = EncryptStream(sBlocks, iCipher, pbCipherKey,
                                               cbEncIV, true);
                        if ((sPlain == null) || (sPlain == sBlocks))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                    }
                    lStreams.Add(sPlain);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        sXml = new GZipStream(sPlain, CompressionMode.Compress);
                        lStreams.Add(sXml);
                    }
                    else
                    {
                        sXml = sPlain;
                    }

                    if (m_uFileVersion >= FileVersion32_4)
                    {
                        WriteInnerHeader(sXml);                         // Binary header before XML
                    }
                }
                else if (m_format == KdbxFormat.PlainXml)
                {
                    sXml = sHashing;
                }
                else
                {
                    Debug.Assert(false);
                    throw new ArgumentOutOfRangeException("fmt");
                }

                m_xmlWriter = XmlUtilEx.CreateXmlWriter(sXml);

                WriteDocument(pgRoot);

                m_xmlWriter.Flush();
            }
            finally
            {
                CommonCleanUpWrite(lStreams, sHashing);

                if (pbCipherKey != null)
                {
                    MemUtil.ZeroByteArray(pbCipherKey);
                }
                if (pbHmacKey64 != null)
                {
                    MemUtil.ZeroByteArray(pbHmacKey64);
                }
            }
        }
Beispiel #6
0
        private static void PerformXmlReplace(PwDatabase pd, XmlReplaceOptions opt,
                                              IStatusLogger sl)
        {
            if (opt.SelectNodesXPath.Length == 0)
            {
                return;
            }
            if (opt.Operation == XmlReplaceOp.None)
            {
                return;
            }

            bool bRemove    = (opt.Operation == XmlReplaceOp.RemoveNodes);
            bool bReplace   = (opt.Operation == XmlReplaceOp.ReplaceData);
            bool bMatchCase = ((opt.Flags & XmlReplaceFlags.CaseSensitive) != XmlReplaceFlags.None);
            bool bRegex     = ((opt.Flags & XmlReplaceFlags.Regex) != XmlReplaceFlags.None);

            Regex rxFind = null;

            if (bReplace && bRegex)
            {
                rxFind = new Regex(opt.FindText, (bMatchCase ? RegexOptions.None :
                                                  RegexOptions.IgnoreCase));
            }

            EnsureStandardFieldsExist(pd);

            KdbxFile     kdbxOrg = new KdbxFile(pd);
            MemoryStream msOrg   = new MemoryStream();

            kdbxOrg.Save(msOrg, null, KdbxFormat.PlainXml, sl);
            byte[] pbXml = msOrg.ToArray();
            msOrg.Close();
            string strXml = StrUtil.Utf8.GetString(pbXml);

            XmlDocument xd = XmlUtilEx.CreateXmlDocument();

            xd.LoadXml(strXml);

            XPathNavigator    xpNavRoot = xd.CreateNavigator();
            XPathNodeIterator xpIt      = xpNavRoot.Select(opt.SelectNodesXPath);

            // XPathNavigators must be cloned to make them independent
            List <XPathNavigator> lNodes = new List <XPathNavigator>();

            while (xpIt.MoveNext())
            {
                lNodes.Add(xpIt.Current.Clone());
            }

            if (lNodes.Count == 0)
            {
                return;
            }

            for (int i = lNodes.Count - 1; i >= 0; --i)
            {
                if ((sl != null) && !sl.ContinueWork())
                {
                    return;
                }

                XPathNavigator xpNav = lNodes[i];

                if (bRemove)
                {
                    xpNav.DeleteSelf();
                }
                else if (bReplace)
                {
                    ApplyReplace(xpNav, opt, rxFind);
                }
                else
                {
                    Debug.Assert(false);
                }                                             // Unknown action
            }

            MemoryStream msMod = new MemoryStream();

            using (XmlWriter xw = XmlUtilEx.CreateXmlWriter(msMod))
            {
                xd.Save(xw);
            }
            byte[] pbMod = msMod.ToArray();
            msMod.Close();

            PwDatabase pdMod = new PwDatabase();

            msMod = new MemoryStream(pbMod, false);
            try
            {
                KdbxFile kdbxMod = new KdbxFile(pdMod);
                kdbxMod.Load(msMod, KdbxFormat.PlainXml, sl);
            }
            catch (Exception)
            {
                throw new Exception(KPRes.XmlModInvalid + MessageService.NewParagraph +
                                    KPRes.OpAborted + MessageService.NewParagraph +
                                    KPRes.DbNoModBy.Replace(@"{PARAM}", @"'" + KPRes.XmlReplace + @"'"));
            }
            finally { msMod.Close(); }

            PrepareModDbForMerge(pdMod, pd);

            pd.Modified          = true;
            pd.UINeedsIconUpdate = true;
            pd.MergeIn(pdMod, PwMergeMethod.Synchronize, sl);
        }