mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 23:50:18 -04:00
ModernKeePassLib custom PCL version
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,42 +22,74 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
public sealed class BinaryReaderEx : BinaryReader
|
||||
public sealed class BinaryReaderEx
|
||||
{
|
||||
private string m_strReadExcp = null;
|
||||
private Stream m_s;
|
||||
// private Encoding m_enc; // See constructor
|
||||
|
||||
private string m_strReadExcp;
|
||||
public string ReadExceptionText
|
||||
{
|
||||
get { return m_strReadExcp; }
|
||||
set { m_strReadExcp = value; }
|
||||
}
|
||||
|
||||
public BinaryReaderEx(Stream input, Encoding encoding,
|
||||
string strReadExceptionText) :
|
||||
base(input, encoding)
|
||||
private Stream m_sCopyTo = null;
|
||||
/// <summary>
|
||||
/// If this property is set to a non-null stream, all data that
|
||||
/// is read from the input stream is automatically written to
|
||||
/// the copy stream (before returning the read data).
|
||||
/// </summary>
|
||||
public Stream CopyDataTo
|
||||
{
|
||||
get { return m_sCopyTo; }
|
||||
set { m_sCopyTo = value; }
|
||||
}
|
||||
|
||||
public BinaryReaderEx(Stream input, Encoding encoding,
|
||||
string strReadExceptionText)
|
||||
{
|
||||
if(input == null)
|
||||
throw new ArgumentNullException("input");
|
||||
|
||||
m_s = input;
|
||||
// m_enc = encoding; // Not used yet
|
||||
m_strReadExcp = strReadExceptionText;
|
||||
}
|
||||
|
||||
public override byte[] ReadBytes(int count)
|
||||
public byte[] ReadBytes(int nCount)
|
||||
{
|
||||
/*try
|
||||
{*/
|
||||
byte[] pb = base.ReadBytes(count);
|
||||
if((pb == null) || (pb.Length != count))
|
||||
try
|
||||
{
|
||||
byte[] pb = MemUtil.Read(m_s, nCount);
|
||||
if((pb == null) || (pb.Length != nCount))
|
||||
{
|
||||
if(m_strReadExcp != null) throw new IOException(m_strReadExcp);
|
||||
else throw new EndOfStreamException();
|
||||
if(m_strReadExcp != null)
|
||||
throw new IOException(m_strReadExcp);
|
||||
else
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
if(m_sCopyTo != null)
|
||||
m_sCopyTo.Write(pb, 0, pb.Length);
|
||||
return pb;
|
||||
/*}
|
||||
catch(Exception ex)
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
if(m_strReadExcp != null) throw new IOException(m_strReadExcp);
|
||||
if(m_strReadExcp != null)
|
||||
throw new IOException(m_strReadExcp);
|
||||
else throw;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
public byte ReadByte()
|
||||
{
|
||||
byte[] pb = ReadBytes(1);
|
||||
return pb[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,139 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Windows.Security.Cryptography;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
// An adaptor function to provide a stream interface from an IBuffer.
|
||||
|
||||
class CryptoStream : Stream
|
||||
{
|
||||
|
||||
private int m_blockSize = 16 ;
|
||||
private byte[] m_decoded;
|
||||
private IEnumerator<byte> m_enumerator = null;
|
||||
|
||||
public CryptoStream(Stream s, String strAlgName, bool bEncrypt, byte[] pbKey, byte[] pbIV)
|
||||
{
|
||||
IBuffer iv = CryptographicBuffer.CreateFromByteArray(pbIV);
|
||||
SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName);
|
||||
CryptographicKey key = objAlg.CreateSymmetricKey( CryptographicBuffer.CreateFromByteArray(pbKey) );
|
||||
if (bEncrypt)
|
||||
{
|
||||
Debug.Assert(false, "Not implemented yet");
|
||||
}
|
||||
else
|
||||
{
|
||||
// For the time being, WinRT CryptographicEngine doesn't support stream decoding. Bummer.
|
||||
// Copy the file to a memory buffer, then decode all at once.
|
||||
|
||||
|
||||
byte[] block = new byte[s.Length]; // We are not at the beginning of the stream
|
||||
// There is always less than s.Lenght bytes remaining to be read.
|
||||
int readItemCount = s.Read(block, 0, (int) s.Length);
|
||||
Array.Resize(ref block, readItemCount);
|
||||
|
||||
IBuffer input = CryptographicBuffer.CreateFromByteArray(block);
|
||||
IBuffer decoded = null;
|
||||
|
||||
try
|
||||
{
|
||||
decoded = CryptographicEngine.Decrypt(key, input, iv);
|
||||
} catch (System.Exception)
|
||||
{
|
||||
throw new Keys.InvalidCompositeKeyException();
|
||||
}
|
||||
CryptographicBuffer.CopyToByteArray(decoded, out m_decoded);
|
||||
m_enumerator = m_decoded.AsEnumerable().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override bool CanRead { get { return true; } }
|
||||
public override bool CanSeek { get { return false; } }
|
||||
public override bool CanTimeout { get { return false; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Debug.Assert(false, "Not yet implemented");
|
||||
}
|
||||
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
// Exceptions:
|
||||
// System.ArgumentException:
|
||||
// The sum of offset and count is larger than the buffer length.
|
||||
//
|
||||
// System.ArgumentNullException:
|
||||
// buffer is null.
|
||||
//
|
||||
// System.ArgumentOutOfRangeException:
|
||||
// offset or count is negative.
|
||||
//
|
||||
// System.IO.IOException:
|
||||
// An I/O error occurs.
|
||||
//
|
||||
// System.NotSupportedException:
|
||||
// The stream does not support reading.
|
||||
//
|
||||
// System.ObjectDisposedException:
|
||||
// Methods were called after the stream was closed.
|
||||
|
||||
if ((count <0) || (offset <0))
|
||||
throw new System.ArgumentOutOfRangeException();
|
||||
if (buffer == null)
|
||||
throw new System.ArgumentNullException();
|
||||
if (m_enumerator == null)
|
||||
throw new System.ArgumentNullException();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!m_enumerator.MoveNext())
|
||||
return i;
|
||||
buffer[i + offset] = m_enumerator.Current;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -21,7 +21,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
#if PCL
|
||||
using System.Threading.Tasks;
|
||||
#else
|
||||
using System.Threading;
|
||||
#endif
|
||||
using System.Diagnostics;
|
||||
|
||||
using ModernKeePassLib.Cryptography;
|
||||
@@ -41,28 +45,24 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
public FileLockException(string strBaseFile, string strUser)
|
||||
{
|
||||
Debug.Assert(false, "Not yet implemented");
|
||||
return;
|
||||
#if TODO
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!string.IsNullOrEmpty(strBaseFile))
|
||||
{
|
||||
sb.Append(strBaseFile);
|
||||
sb.Append(MessageService.NewParagraph);
|
||||
sb.Append(Environment.NewLine + Environment.NewLine);
|
||||
}
|
||||
|
||||
sb.Append(KLRes.FileLockedWrite);
|
||||
sb.Append(MessageService.NewLine);
|
||||
sb.Append(Environment.NewLine);
|
||||
|
||||
if(!string.IsNullOrEmpty(strUser)) sb.Append(strUser);
|
||||
else sb.Append("?");
|
||||
|
||||
sb.Append(MessageService.NewParagraph);
|
||||
sb.Append(Environment.NewLine + Environment.NewLine);
|
||||
sb.Append(KLRes.TryAgainSecs);
|
||||
|
||||
m_strMsg = sb.ToString();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,9 +124,6 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
public static LockFileInfo Load(IOConnectionInfo iocLockFile)
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return null;
|
||||
#if TODO
|
||||
Stream s = null;
|
||||
try
|
||||
{
|
||||
@@ -134,7 +131,7 @@ namespace ModernKeePassLib.Serialization
|
||||
if(s == null) return null;
|
||||
StreamReader sr = new StreamReader(s, StrUtil.Utf8);
|
||||
string str = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
sr.Dispose();
|
||||
if(str == null) { Debug.Assert(false); return null; }
|
||||
|
||||
str = StrUtil.NormalizeNewLines(str, false);
|
||||
@@ -146,18 +143,14 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
catch(FileNotFoundException) { }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
finally { if(s != null) s.Close(); }
|
||||
finally { if(s != null) s.Dispose(); }
|
||||
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Throws on error
|
||||
public static LockFileInfo Create(IOConnectionInfo iocLockFile)
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return null;
|
||||
#if TODO
|
||||
LockFileInfo lfi;
|
||||
Stream s = null;
|
||||
try
|
||||
@@ -165,7 +158,7 @@ namespace ModernKeePassLib.Serialization
|
||||
byte[] pbID = CryptoRandom.Instance.GetRandomBytes(16);
|
||||
string strTime = TimeUtil.SerializeUtc(DateTime.Now);
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
lfi = new LockFileInfo(Convert.ToBase64String(pbID), strTime,
|
||||
Environment.UserName, Environment.MachineName,
|
||||
Environment.UserDomainName);
|
||||
@@ -175,7 +168,7 @@ namespace ModernKeePassLib.Serialization
|
||||
#endif
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
#if !KeePassLibSD && TODO
|
||||
#if !KeePassLibSD
|
||||
sb.AppendLine(LockFileHeader);
|
||||
sb.AppendLine(lfi.ID);
|
||||
sb.AppendLine(strTime);
|
||||
@@ -197,18 +190,14 @@ namespace ModernKeePassLib.Serialization
|
||||
if(s == null) throw new IOException(iocLockFile.GetDisplayName());
|
||||
s.Write(pbFile, 0, pbFile.Length);
|
||||
}
|
||||
finally { if(s != null) s.Close(); }
|
||||
finally { if(s != null) s.Dispose(); }
|
||||
|
||||
return lfi;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FileLock(IOConnectionInfo iocBaseFile)
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return ;
|
||||
#if TODO
|
||||
if(iocBaseFile == null) throw new ArgumentNullException("strBaseFile");
|
||||
|
||||
m_iocLockFile = iocBaseFile.CloneDeep();
|
||||
@@ -223,7 +212,6 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
LockFileInfo.Create(m_iocLockFile);
|
||||
#endif
|
||||
}
|
||||
|
||||
~FileLock()
|
||||
@@ -239,9 +227,6 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
private void Dispose(bool bDisposing)
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return ;
|
||||
#if TODO
|
||||
if(m_iocLockFile == null) return;
|
||||
|
||||
bool bFileDeleted = false;
|
||||
@@ -258,14 +243,18 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
if(bFileDeleted) break;
|
||||
|
||||
#if PCL
|
||||
if(bDisposing)
|
||||
Task.Delay(50).Wait();
|
||||
#else
|
||||
if(bDisposing) Thread.Sleep(50);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(bDisposing && !bFileDeleted)
|
||||
IOConnection.DeleteFile(m_iocLockFile); // Possibly with exception
|
||||
|
||||
m_iocLockFile = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
// private bool OwnLockFile()
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,13 +22,8 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// Bert TODO: For now, remove the accesscontrol from this class.
|
||||
// In WinRT, the security of file has changed, and something could potentially be done
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364399%28v=vs.85%29.aspx
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
using System.Security.AccessControl;
|
||||
#endif
|
||||
|
||||
@@ -63,6 +58,16 @@ namespace ModernKeePassLib.Serialization
|
||||
m_bTransacted = bTransacted;
|
||||
m_iocBase = iocBaseFile.CloneDeep();
|
||||
|
||||
// ModernKeePassLib is currently targeting .NET 4.5
|
||||
#if !PCL
|
||||
// Prevent transactions for FTP URLs under .NET 4.0 in order to
|
||||
// avoid/workaround .NET bug 621450:
|
||||
// https://connect.microsoft.com/VisualStudio/feedback/details/621450/problem-renaming-file-on-ftp-server-using-ftpwebrequest-in-net-framework-4-0-vs2010-only
|
||||
if(m_iocBase.Path.StartsWith("ftp:", StrUtil.CaseIgnoreCmp) &&
|
||||
(Environment.Version.Major >= 4) && !NativeLib.IsUnix())
|
||||
m_bTransacted = false;
|
||||
#endif
|
||||
|
||||
if(m_bTransacted)
|
||||
{
|
||||
m_iocTemp = m_iocBase.CloneDeep();
|
||||
@@ -71,7 +76,7 @@ namespace ModernKeePassLib.Serialization
|
||||
else m_iocTemp = m_iocBase;
|
||||
}
|
||||
|
||||
public async Task<Stream> OpenWrite()
|
||||
public Stream OpenWrite()
|
||||
{
|
||||
if(!m_bTransacted) m_bMadeUnhidden = UrlUtil.UnhideFile(m_iocTemp.Path);
|
||||
else // m_bTransacted
|
||||
@@ -80,7 +85,7 @@ namespace ModernKeePassLib.Serialization
|
||||
catch(Exception) { }
|
||||
}
|
||||
|
||||
return await IOConnection.OpenWrite(m_iocTemp);
|
||||
return IOConnection.OpenWrite(m_iocTemp);
|
||||
}
|
||||
|
||||
public void CommitWrite()
|
||||
@@ -96,14 +101,14 @@ namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
bool bMadeUnhidden = UrlUtil.UnhideFile(m_iocBase.Path);
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
FileSecurity bkSecurity = null;
|
||||
bool bEfsEncrypted = false;
|
||||
#endif
|
||||
|
||||
if(IOConnection.FileExists(m_iocBase))
|
||||
{
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
if(m_iocBase.IsLocalFile())
|
||||
{
|
||||
try
|
||||
@@ -125,7 +130,7 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
IOConnection.RenameFile(m_iocTemp, m_iocBase);
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
if(m_iocBase.IsLocalFile())
|
||||
{
|
||||
try
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,19 +19,24 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
#if PCL
|
||||
using System.Linq;
|
||||
#else
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Native;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using ModernKeePassLib.Utility;
|
||||
using ModernKeePassLib.Cryptography;
|
||||
|
||||
#if KeePassLibSD
|
||||
using ModernKeePassLibSD;
|
||||
using KeePassLibSD;
|
||||
#endif
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
public sealed class HashedBlockStream : Stream
|
||||
public sealed class HashedBlockStream : Stream
|
||||
{
|
||||
private const int m_nDefaultBufferSize = 1024 * 1024; // 1 MB
|
||||
|
||||
@@ -93,12 +98,13 @@ namespace ModernKeePassLib.Serialization
|
||||
private void Initialize(Stream sBaseStream, bool bWriting, int nBufferSize,
|
||||
bool bVerify)
|
||||
{
|
||||
if(sBaseStream == null) throw new ArgumentNullException("sBaseStream");
|
||||
if(nBufferSize < 0) throw new ArgumentOutOfRangeException("nBufferSize");
|
||||
if (sBaseStream == null) throw new ArgumentNullException(nameof(sBaseStream));
|
||||
m_sBaseStream = sBaseStream;
|
||||
if (nBufferSize < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(nBufferSize));
|
||||
|
||||
if(nBufferSize == 0) nBufferSize = m_nDefaultBufferSize;
|
||||
|
||||
m_sBaseStream = sBaseStream;
|
||||
if(nBufferSize == 0)
|
||||
nBufferSize = m_nDefaultBufferSize;
|
||||
m_bWriting = bWriting;
|
||||
m_bVerify = bVerify;
|
||||
|
||||
@@ -128,14 +134,20 @@ namespace ModernKeePassLib.Serialization
|
||||
if(m_bWriting) m_bwOutput.Flush();
|
||||
}
|
||||
|
||||
#if TODO
|
||||
#if PCL || KeePassRT
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(!disposing) return;
|
||||
#else
|
||||
public override void Close()
|
||||
{
|
||||
#endif
|
||||
if(m_sBaseStream != null)
|
||||
{
|
||||
if(m_bWriting == false) // Reading mode
|
||||
{
|
||||
m_brInput.Close();
|
||||
try { m_brInput.Dispose(); } catch { }
|
||||
|
||||
m_brInput = null;
|
||||
}
|
||||
else // Writing mode
|
||||
@@ -149,15 +161,14 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
Flush();
|
||||
m_bwOutput.Close();
|
||||
m_bwOutput.Dispose();
|
||||
m_bwOutput = null;
|
||||
}
|
||||
|
||||
m_sBaseStream.Close();
|
||||
try { m_sBaseStream.Dispose(); } catch { }
|
||||
m_sBaseStream = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public override long Seek(long lOffset, SeekOrigin soOrigin)
|
||||
{
|
||||
@@ -210,11 +221,11 @@ namespace ModernKeePassLib.Serialization
|
||||
throw new InvalidDataException();
|
||||
|
||||
int nBufferSize = 0;
|
||||
try { nBufferSize = m_brInput.ReadInt32(); }
|
||||
/*try {*/ nBufferSize = m_brInput.ReadInt32(); /*}
|
||||
catch(NullReferenceException) // Mono bug workaround (LaunchPad 783268)
|
||||
{
|
||||
if(!NativeLib.IsUnix()) throw;
|
||||
}
|
||||
}*/
|
||||
|
||||
if(nBufferSize < 0)
|
||||
throw new InvalidDataException();
|
||||
@@ -238,17 +249,22 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
if(m_bVerify)
|
||||
{
|
||||
byte[] pbComputedHash = SHA256Managed.Instance.ComputeHash(m_pbBuffer);
|
||||
#if PCL
|
||||
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||
var pbComputedHash = sha256.HashData(m_pbBuffer.AsBuffer()).ToArray();
|
||||
#else
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
byte[] pbComputedHash = sha256.ComputeHash(m_pbBuffer);
|
||||
#endif
|
||||
if((pbComputedHash == null) || (pbComputedHash.Length != 32))
|
||||
throw new InvalidOperationException();
|
||||
|
||||
|
||||
for(int iHashPos = 0; iHashPos < 32; ++iHashPos)
|
||||
{
|
||||
if(pbStoredHash[iHashPos] != pbComputedHash[iHashPos])
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -275,14 +291,16 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
private void WriteHashedBlock()
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return ;
|
||||
#if TODO
|
||||
m_bwOutput.Write(m_uBufferIndex);
|
||||
++m_uBufferIndex;
|
||||
|
||||
if(m_nBufferPos > 0)
|
||||
{
|
||||
#if PCL
|
||||
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||
var pbHash = sha256.HashData(m_pbBuffer.Where((x, i) => i < m_nBufferPos).ToArray().AsBuffer()).ToArray();
|
||||
#else
|
||||
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
|
||||
#if !KeePassLibSD
|
||||
@@ -297,6 +315,8 @@ namespace ModernKeePassLib.Serialization
|
||||
Array.Copy(m_pbBuffer, 0, pbData, 0, m_nBufferPos);
|
||||
pbHash = sha256.ComputeHash(pbData);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
m_bwOutput.Write(pbHash);
|
||||
@@ -315,7 +335,6 @@ namespace ModernKeePassLib.Serialization
|
||||
m_bwOutput.Write(m_pbBuffer, 0, m_nBufferPos);
|
||||
|
||||
m_nBufferPos = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,13 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
@@ -18,27 +19,32 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Storage;
|
||||
// BERT TODO: For the time being, the web functionality is not available for WinRT
|
||||
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
using System.Net.Cache;
|
||||
using System.Net.Security;
|
||||
#endif
|
||||
|
||||
#if !PCL && !KeePassRT
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
#endif
|
||||
|
||||
#if PCL
|
||||
using Windows.Storage;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
#if !KeePassLibSD && false
|
||||
public sealed class IOWebClient : HttpClient
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
internal sealed class IOWebClient : WebClient
|
||||
{
|
||||
protected override WebRequest GetWebRequest(Uri address)
|
||||
{
|
||||
@@ -49,14 +55,192 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
#endif
|
||||
|
||||
public class IOConnection
|
||||
#if !PCL
|
||||
internal abstract class WrapperStream : Stream
|
||||
{
|
||||
#if !KeePassLibSD && TODO
|
||||
private readonly Stream m_s;
|
||||
protected Stream BaseStream
|
||||
{
|
||||
get { return m_s; }
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return m_s.CanRead; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return m_s.CanSeek; }
|
||||
}
|
||||
|
||||
public override bool CanTimeout
|
||||
{
|
||||
get { return m_s.CanTimeout; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return m_s.CanWrite; }
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { return m_s.Length; }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return m_s.Position; }
|
||||
set { m_s.Position = value; }
|
||||
}
|
||||
|
||||
public override int ReadTimeout
|
||||
{
|
||||
get { return m_s.ReadTimeout; }
|
||||
set { m_s.ReadTimeout = value; }
|
||||
}
|
||||
|
||||
public override int WriteTimeout
|
||||
{
|
||||
get { return m_s.WriteTimeout; }
|
||||
set { m_s.WriteTimeout = value; }
|
||||
}
|
||||
|
||||
public WrapperStream(Stream sBase) : base()
|
||||
{
|
||||
if(sBase == null) throw new ArgumentNullException("sBase");
|
||||
|
||||
m_s = sBase;
|
||||
}
|
||||
|
||||
public override IAsyncResult BeginRead(byte[] buffer, int offset,
|
||||
int count, AsyncCallback callback, object state)
|
||||
{
|
||||
return m_s.BeginRead(buffer, offset, count, callback, state);
|
||||
}
|
||||
|
||||
public override IAsyncResult BeginWrite(byte[] buffer, int offset,
|
||||
int count, AsyncCallback callback, object state)
|
||||
{
|
||||
return BeginWrite(buffer, offset, count, callback, state);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
m_s.Close();
|
||||
}
|
||||
|
||||
public override int EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
return m_s.EndRead(asyncResult);
|
||||
}
|
||||
|
||||
public override void EndWrite(IAsyncResult asyncResult)
|
||||
{
|
||||
m_s.EndWrite(asyncResult);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
m_s.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return m_s.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
return m_s.ReadByte();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return m_s.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
m_s.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
m_s.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
m_s.WriteByte(value);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class IocStream : WrapperStream
|
||||
{
|
||||
private readonly bool m_bWrite; // Initially opened for writing
|
||||
|
||||
public IocStream(Stream sBase) : base(sBase)
|
||||
{
|
||||
m_bWrite = sBase.CanWrite;
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
|
||||
if(MonoWorkarounds.IsRequired(10163) && m_bWrite)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream s = this.BaseStream;
|
||||
Type t = s.GetType();
|
||||
if(t.Name == "WebConnectionStream")
|
||||
{
|
||||
PropertyInfo pi = t.GetProperty("Request",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if(pi != null)
|
||||
{
|
||||
WebRequest wr = (pi.GetValue(s, null) as WebRequest);
|
||||
if(wr != null)
|
||||
IOConnection.DisposeResponse(wr.GetResponse(), false);
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
|
||||
public static Stream WrapIfRequired(Stream s)
|
||||
{
|
||||
if(s == null) { Debug.Assert(false); return null; }
|
||||
|
||||
if(MonoWorkarounds.IsRequired(10163) && s.CanWrite)
|
||||
return new IocStream(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static class IOConnection
|
||||
{
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
private static ProxyServerType m_pstProxyType = ProxyServerType.System;
|
||||
private static string m_strProxyAddr = string.Empty;
|
||||
private static string m_strProxyPort = string.Empty;
|
||||
private static string m_strProxyUserName = string.Empty;
|
||||
private static string m_strProxyPassword = string.Empty;
|
||||
|
||||
private static bool m_bSslCertsAcceptInvalid = false;
|
||||
internal static bool SslCertsAcceptInvalid
|
||||
{
|
||||
// get { return m_bSslCertsAcceptInvalid; }
|
||||
set { m_bSslCertsAcceptInvalid = value; }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Web request methods
|
||||
@@ -66,16 +250,18 @@ namespace ModernKeePassLib.Serialization
|
||||
// Web request headers
|
||||
public const string WrhMoveFileTo = "MoveFileTo";
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
public static event EventHandler<IOAccessEventArgs> IOAccessPre;
|
||||
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
// Allow self-signed certificates, expired certificates, etc.
|
||||
private static bool ValidateServerCertificate(object sender,
|
||||
private static bool AcceptCertificate(object sender,
|
||||
X509Certificate certificate, X509Chain chain,
|
||||
SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void SetProxy(ProxyServerType pst, string strAddr,
|
||||
internal static void SetProxy(ProxyServerType pst, string strAddr,
|
||||
string strPort, string strUserName, string strPassword)
|
||||
{
|
||||
m_pstProxyType = pst;
|
||||
@@ -185,12 +371,27 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
private static void PrepareWebAccess()
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback =
|
||||
ValidateServerCertificate;
|
||||
if(m_bSslCertsAcceptInvalid)
|
||||
ServicePointManager.ServerCertificateValidationCallback =
|
||||
IOConnection.AcceptCertificate;
|
||||
else
|
||||
ServicePointManager.ServerCertificateValidationCallback = null;
|
||||
}
|
||||
|
||||
private static IOWebClient CreateWebClient(IOConnectionInfo ioc)
|
||||
{
|
||||
PrepareWebAccess();
|
||||
|
||||
IOWebClient wc = new IOWebClient();
|
||||
ConfigureWebClient(wc);
|
||||
|
||||
if((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
|
||||
wc.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
|
||||
else if(NativeLib.IsUnix()) // Mono requires credentials
|
||||
wc.Credentials = new NetworkCredential("anonymous", string.Empty);
|
||||
|
||||
return wc;
|
||||
}
|
||||
|
||||
private static WebRequest CreateWebRequest(IOConnectionInfo ioc)
|
||||
{
|
||||
@@ -206,122 +407,124 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
return req;
|
||||
}
|
||||
#endif
|
||||
|
||||
private async Task<Stream> OpenReadHttp(IOConnectionInfo ioc)
|
||||
{
|
||||
|
||||
// TODO: Configure the httpClient
|
||||
// PrepareWebAccess();
|
||||
// ConfigureWebClient(wc);
|
||||
|
||||
HttpClient hc = new HttpClient();
|
||||
HttpResponseMessage response = await hc.GetAsync(ioc.Path);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// Read content into buffer
|
||||
// Not the most efficient thing to do,
|
||||
// but simplifies our life by allowing to use stream.length later on.
|
||||
await response.Content.LoadIntoBufferAsync();
|
||||
return await response.Content.ReadAsStreamAsync();
|
||||
#if false
|
||||
if((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
|
||||
wc.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
|
||||
else if(NativeLib.IsUnix()) // Mono requires credentials
|
||||
wc.Credentials = new NetworkCredential("anonymous", string.Empty);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public async Task<Stream> OpenRead(IOConnectionInfo ioc)
|
||||
public static Stream OpenRead(IOConnectionInfo ioc)
|
||||
{
|
||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Read);
|
||||
|
||||
if(StrUtil.IsDataUri(ioc.Path))
|
||||
{
|
||||
byte[] pbData = StrUtil.DataUriToData(ioc.Path);
|
||||
if(pbData != null) return new MemoryStream(pbData, false);
|
||||
}
|
||||
|
||||
if(ioc.IsLocalFile()) return await OpenReadLocal(ioc);
|
||||
if(ioc.IsLocalFile()) return OpenReadLocal(ioc);
|
||||
|
||||
|
||||
return await OpenReadHttp(ioc);
|
||||
}
|
||||
|
||||
|
||||
private async Task<Stream> OpenReadLocal(IOConnectionInfo ioc)
|
||||
return IocStream.WrapIfRequired(CreateWebClient(ioc).OpenRead(
|
||||
new Uri(ioc.Path)));
|
||||
}
|
||||
#else
|
||||
public static Stream OpenRead(IOConnectionInfo ioc)
|
||||
{
|
||||
try
|
||||
{
|
||||
IRandomAccessStream stream = await ioc.StorageFile.OpenAsync(FileAccessMode.Read);
|
||||
return stream.AsStream();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Assert(false, ex.Message);
|
||||
return null;
|
||||
}
|
||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Read);
|
||||
|
||||
return OpenReadLocal(ioc);
|
||||
}
|
||||
#endif
|
||||
|
||||
private static Stream OpenReadLocal(IOConnectionInfo ioc)
|
||||
{
|
||||
#if PCL
|
||||
/*var file = FileSystem.Current.GetFileFromPathAsync(ioc.Path).Result;
|
||||
return file.OpenAsync(PCLStorage.FileAccess.Read).Result;*/
|
||||
return ioc.StorageFile.OpenAsync(FileAccessMode.Read).GetResults().AsStream();
|
||||
#else
|
||||
return new FileStream(ioc.Path, FileMode.Open, FileAccess.Read,
|
||||
FileShare.Read);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
public static Stream OpenWrite(IOConnectionInfo ioc)
|
||||
{
|
||||
if(ioc == null) { Debug.Assert(false); return null; }
|
||||
|
||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Write);
|
||||
|
||||
if(ioc.IsLocalFile()) return OpenWriteLocal(ioc);
|
||||
|
||||
Uri uri = new Uri(ioc.Path);
|
||||
Stream s;
|
||||
|
||||
// Mono does not set HttpWebRequest.Method to POST for writes,
|
||||
// so one needs to set the method to PUT explicitly
|
||||
if(NativeLib.IsUnix() && (uri.Scheme.Equals(Uri.UriSchemeHttp,
|
||||
StrUtil.CaseIgnoreCmp) || uri.Scheme.Equals(Uri.UriSchemeHttps,
|
||||
StrUtil.CaseIgnoreCmp)))
|
||||
return CreateWebClient(ioc).OpenWrite(uri, WebRequestMethods.Http.Put);
|
||||
s = CreateWebClient(ioc).OpenWrite(uri, WebRequestMethods.Http.Put);
|
||||
else s = CreateWebClient(ioc).OpenWrite(uri);
|
||||
|
||||
return CreateWebClient(ioc).OpenWrite(uri);
|
||||
return IocStream.WrapIfRequired(s);
|
||||
}
|
||||
#else
|
||||
public static async Task<Stream> OpenWrite(IOConnectionInfo ioc)
|
||||
public static Stream OpenWrite(IOConnectionInfo ioc)
|
||||
{
|
||||
return await OpenWriteLocal(ioc);
|
||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Write);
|
||||
|
||||
return OpenWriteLocal(ioc);
|
||||
}
|
||||
#endif
|
||||
|
||||
private static async Task<Stream> OpenWriteLocal(IOConnectionInfo ioc)
|
||||
private static Stream OpenWriteLocal(IOConnectionInfo ioc)
|
||||
{
|
||||
try
|
||||
{
|
||||
IRandomAccessStream stream = await ioc.StorageFile.OpenAsync(FileAccessMode.ReadWrite);
|
||||
return stream.AsStream();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Assert(false, ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#if PCL
|
||||
return ioc.StorageFile.OpenAsync(FileAccessMode.ReadWrite).GetResults().AsStream();
|
||||
/*var file = FileSystem.Current.GetFileFromPathAsync(ioc.Path).Result;
|
||||
return file.OpenAsync(FileAccess.ReadAndWrite).Result;*/
|
||||
#else
|
||||
return new FileStream(ioc.Path, FileMode.Create, FileAccess.Write,
|
||||
FileShare.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool FileExists(IOConnectionInfo ioc)
|
||||
{
|
||||
//return FileExists(ioc, false);
|
||||
return true;
|
||||
return FileExists(ioc, false);
|
||||
}
|
||||
|
||||
/*public static bool FileExists(IOConnectionInfo ioc, bool bThrowErrors)
|
||||
{
|
||||
public static bool FileExists(IOConnectionInfo ioc, bool bThrowErrors)
|
||||
{
|
||||
if(ioc == null) { Debug.Assert(false); return false; }
|
||||
|
||||
if(ioc.IsLocalFile()) return ioc.StorageFile.IsAvailable;
|
||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Exists);
|
||||
|
||||
#if PCL
|
||||
if(ioc.IsLocalFile())
|
||||
return ioc.StorageFile.IsAvailable;
|
||||
#else
|
||||
if(ioc.IsLocalFile()) return File.Exists(ioc.Path);
|
||||
#endif
|
||||
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
if(ioc.Path.StartsWith("ftp://", StrUtil.CaseIgnoreCmp))
|
||||
{
|
||||
bool b = SendCommand(ioc, WebRequestMethods.Ftp.GetDateTimestamp);
|
||||
if(!b && bThrowErrors) throw new InvalidOperationException();
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
Stream s = OpenRead(ioc);
|
||||
if(s == null) throw new FileNotFoundException();
|
||||
|
||||
// For FTP clients we called RETR to get the file, but we never
|
||||
// followed-up and downloaded the file; close may produce a
|
||||
// 550 error -- that's okay
|
||||
try { s.Close(); }
|
||||
try { s.ReadByte(); }
|
||||
catch(Exception) { }
|
||||
|
||||
// We didn't download the file completely; close may throw
|
||||
// an exception -- that's okay
|
||||
try { s.Dispose(); }
|
||||
catch(Exception) { }
|
||||
}
|
||||
catch(Exception)
|
||||
@@ -331,19 +534,29 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
public static async void DeleteFile(IOConnectionInfo ioc)
|
||||
public static void DeleteFile(IOConnectionInfo ioc)
|
||||
{
|
||||
if(ioc.IsLocalFile()) { await ioc.StorageFile.DeleteAsync(StorageDeleteOption.Default);
|
||||
}
|
||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Delete);
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if PCL
|
||||
if(ioc.IsLocalFile()) {
|
||||
/*var file = FileSystem.Current.GetFileFromPathAsync(ioc.Path).Result;
|
||||
file.DeleteAsync().RunSynchronously();*/
|
||||
ioc.StorageFile.DeleteAsync(StorageDeleteOption.Default).GetResults();
|
||||
}
|
||||
#else
|
||||
if(ioc.IsLocalFile()) { File.Delete(ioc.Path); return; }
|
||||
#endif
|
||||
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
WebRequest req = CreateWebRequest(ioc);
|
||||
if(req != null)
|
||||
{
|
||||
if(req is HttpWebRequest) req.Method = "DELETE";
|
||||
else if(req is FtpWebRequest) req.Method = WebRequestMethods.Ftp.DeleteFile;
|
||||
else if(req is FtpWebRequest)
|
||||
req.Method = WebRequestMethods.Ftp.DeleteFile;
|
||||
else if(req is FileWebRequest)
|
||||
{
|
||||
File.Delete(UrlUtil.FileUrlToPath(ioc.Path));
|
||||
@@ -365,11 +578,22 @@ namespace ModernKeePassLib.Serialization
|
||||
/// </summary>
|
||||
/// <param name="iocFrom">Source file path.</param>
|
||||
/// <param name="iocTo">Target file path.</param>
|
||||
public static async void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo)
|
||||
public static void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo)
|
||||
{
|
||||
if(iocFrom.IsLocalFile()) { await iocTo.StorageFile.RenameAsync(iocTo.Path, NameCollisionOption.GenerateUniqueName); }
|
||||
RaiseIOAccessPreEvent(iocFrom, iocTo, IOAccessType.Move);
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if PCL
|
||||
if(iocFrom.IsLocalFile()) {
|
||||
/*var file = FileSystem.Current.GetFileFromPathAsync(iocFrom.Path).Result;
|
||||
file.MoveAsync(iocTo.Path).RunSynchronously();*/
|
||||
iocFrom.StorageFile.RenameAsync(iocTo.Path).GetResults();
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if(iocFrom.IsLocalFile()) { File.Move(iocFrom.Path, iocTo.Path); return; }
|
||||
#endif
|
||||
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
WebRequest req = CreateWebRequest(iocFrom);
|
||||
if(req != null)
|
||||
{
|
||||
@@ -381,7 +605,13 @@ namespace ModernKeePassLib.Serialization
|
||||
else if(req is FtpWebRequest)
|
||||
{
|
||||
req.Method = WebRequestMethods.Ftp.Rename;
|
||||
((FtpWebRequest)req).RenameTo = UrlUtil.GetFileName(iocTo.Path);
|
||||
string strTo = UrlUtil.GetFileName(iocTo.Path);
|
||||
|
||||
// We're affected by .NET bug 621450:
|
||||
// https://connect.microsoft.com/VisualStudio/feedback/details/621450/problem-renaming-file-on-ftp-server-using-ftpwebrequest-in-net-framework-4-0-vs2010-only
|
||||
// Prepending "./", "%2E/" or "Dummy/../" doesn't work.
|
||||
|
||||
((FtpWebRequest)req).RenameTo = strTo;
|
||||
}
|
||||
else if(req is FileWebRequest)
|
||||
{
|
||||
@@ -412,11 +642,23 @@ namespace ModernKeePassLib.Serialization
|
||||
// DeleteFile(iocFrom);
|
||||
}
|
||||
|
||||
private static void DisposeResponse(WebResponse wr, bool bGetStream)
|
||||
#if (!PCL && !KeePassLibSD && !KeePassRT)
|
||||
private static bool SendCommand(IOConnectionInfo ioc, string strMethod)
|
||||
{
|
||||
try
|
||||
{
|
||||
WebRequest req = CreateWebRequest(ioc);
|
||||
req.Method = strMethod;
|
||||
DisposeResponse(req.GetResponse(), true);
|
||||
}
|
||||
catch(Exception) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static void DisposeResponse(WebResponse wr, bool bGetStream)
|
||||
{
|
||||
Debug.Assert(false, "Not implemented yet");
|
||||
return;
|
||||
#if TODO
|
||||
if(wr == null) return;
|
||||
|
||||
try
|
||||
@@ -424,12 +666,12 @@ namespace ModernKeePassLib.Serialization
|
||||
if(bGetStream)
|
||||
{
|
||||
Stream s = wr.GetResponseStream();
|
||||
if(s != null) s.Close();
|
||||
if(s != null) s.Dispose();
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
try { wr.Close(); }
|
||||
try { wr.Dispose(); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
|
||||
@@ -450,12 +692,30 @@ namespace ModernKeePassLib.Serialization
|
||||
catch(Exception) { }
|
||||
finally
|
||||
{
|
||||
if(sIn != null) sIn.Close();
|
||||
if(ms != null) ms.Close();
|
||||
if(sIn != null) sIn.Dispose();
|
||||
if(ms != null) ms.Dispose();
|
||||
}
|
||||
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private static void RaiseIOAccessPreEvent(IOConnectionInfo ioc, IOAccessType t)
|
||||
{
|
||||
RaiseIOAccessPreEvent(ioc, null, t);
|
||||
}
|
||||
|
||||
private static void RaiseIOAccessPreEvent(IOConnectionInfo ioc,
|
||||
IOConnectionInfo ioc2, IOAccessType t)
|
||||
{
|
||||
if(ioc == null) { Debug.Assert(false); return; }
|
||||
// ioc2 may be null
|
||||
|
||||
if(IOConnection.IOAccessPre != null)
|
||||
{
|
||||
IOConnectionInfo ioc2Lcl = ((ioc2 != null) ? ioc2.CloneDeep() : null);
|
||||
IOAccessEventArgs e = new IOAccessEventArgs(ioc.CloneDeep(), ioc2Lcl, t);
|
||||
IOConnection.IOAccessPre(null, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -23,11 +23,15 @@ using System.Text;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using System.Diagnostics;
|
||||
|
||||
#if PCL
|
||||
using Windows.Storage;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Utility;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
@@ -65,7 +69,7 @@ namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
// private IOFileFormatHint m_ioHint = IOFileFormatHint.None;
|
||||
|
||||
public StorageFile StorageFile { get; set; }
|
||||
public StorageFile StorageFile { get; set; }
|
||||
|
||||
private string m_strUrl = string.Empty;
|
||||
public string Path
|
||||
@@ -122,6 +126,14 @@ namespace ModernKeePassLib.Serialization
|
||||
set { m_ioCredSaveMode = value; }
|
||||
}
|
||||
|
||||
private bool m_bComplete = false;
|
||||
[XmlIgnore]
|
||||
public bool IsComplete // Credentials etc. fully specified
|
||||
{
|
||||
get { return m_bComplete; }
|
||||
set { m_bComplete = value; }
|
||||
}
|
||||
|
||||
/* public IOFileFormatHint FileFormatHint
|
||||
{
|
||||
get { return m_ioHint; }
|
||||
@@ -133,11 +145,17 @@ namespace ModernKeePassLib.Serialization
|
||||
return (IOConnectionInfo)this.MemberwiseClone();
|
||||
}
|
||||
|
||||
#if DEBUG // For debugger display only
|
||||
public override string ToString()
|
||||
{
|
||||
return GetDisplayName();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Serialize the current connection info to a string. Credentials
|
||||
/// are only serialized if the <c>SaveCredentials</c> property
|
||||
/// is <c>true</c>.
|
||||
/// are serialized based on the <c>CredSaveMode</c> property.
|
||||
/// </summary>
|
||||
/// <param name="iocToCompile">Input object to be serialized.</param>
|
||||
/// <returns>Serialized object as string.</returns>
|
||||
@@ -149,31 +167,9 @@ namespace ModernKeePassLib.Serialization
|
||||
string strUrl = iocToCompile.Path;
|
||||
string strUser = TransformUnreadable(iocToCompile.UserName, true);
|
||||
string strPassword = TransformUnreadable(iocToCompile.Password, true);
|
||||
string strAll = strUrl + strUser + strPassword;
|
||||
char chSep = char.MinValue;
|
||||
|
||||
char[] vPrefSeps = new char[]{ '@', '#', '!', '$', '*' };
|
||||
foreach(char ch in vPrefSeps)
|
||||
{
|
||||
if(strAll.IndexOf(ch) < 0)
|
||||
{
|
||||
chSep = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(chSep == char.MinValue)
|
||||
{
|
||||
for(char chEnum = '!'; chEnum < char.MaxValue; ++chEnum)
|
||||
{
|
||||
if(strAll.IndexOf(chEnum) < 0)
|
||||
{
|
||||
chSep = chEnum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string strAll = strUrl + strUser + strPassword + "CUN";
|
||||
char chSep = StrUtil.GetUnusedChar(strAll);
|
||||
if(chSep == char.MinValue) throw new FormatException();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -279,7 +275,7 @@ namespace ModernKeePassLib.Serialization
|
||||
string str = m_strUrl;
|
||||
|
||||
if(m_strUser.Length > 0)
|
||||
str += @": " + m_strUser;
|
||||
str += " (" + m_strUser + ")";
|
||||
|
||||
return str;
|
||||
}
|
||||
@@ -299,30 +295,33 @@ namespace ModernKeePassLib.Serialization
|
||||
return ioc;
|
||||
}
|
||||
|
||||
public static IOConnectionInfo FromFile(StorageFile file)
|
||||
{
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
public static IOConnectionInfo FromFile(StorageFile file)
|
||||
{
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
|
||||
ioc.Path = file.Path;
|
||||
ioc.CredSaveMode = IOCredSaveMode.NoSave;
|
||||
ioc.StorageFile = file;
|
||||
ioc.Path = file.Path;
|
||||
ioc.CredSaveMode = IOCredSaveMode.NoSave;
|
||||
ioc.StorageFile = file;
|
||||
|
||||
return ioc;
|
||||
}
|
||||
return ioc;
|
||||
}
|
||||
|
||||
public bool CanProbablyAccess()
|
||||
|
||||
public bool CanProbablyAccess()
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return false;
|
||||
#if TODO
|
||||
#if PCL
|
||||
if(IsLocalFile())
|
||||
return (StorageFile.IsAvailable);
|
||||
#else
|
||||
if(IsLocalFile()) return File.Exists(m_strUrl);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool IsLocalFile()
|
||||
{
|
||||
// Not just ":/", see e.g. AppConfigEx.ChangePathRelAbs
|
||||
return (m_strUrl.IndexOf(@"://") < 0);
|
||||
}
|
||||
|
||||
@@ -355,15 +354,5 @@ namespace ModernKeePassLib.Serialization
|
||||
m_ioCredProtMode = IOCredProtMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is IOConnectionInfo)) return false;
|
||||
IOConnectionInfo ioc = obj as IOConnectionInfo;
|
||||
if (ioc.Path != this.Path) return false;
|
||||
if (ioc.UserName != this.UserName) return false;
|
||||
if (ioc.Password != this.Password) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,17 +19,27 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
//using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Security;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
using ModernKeePassLib;
|
||||
using ModernKeePassLib.Collections;
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Cryptography.Cipher;
|
||||
using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
public sealed partial class Kdb4File
|
||||
/// <summary>
|
||||
/// Serialization to KeePass KDBX files.
|
||||
/// </summary>
|
||||
public sealed partial class KdbxFile
|
||||
{
|
||||
private enum KdbContext
|
||||
{
|
||||
@@ -88,13 +98,17 @@ namespace ModernKeePassLib.Serialization
|
||||
xrs.IgnoreProcessingInstructions = true;
|
||||
xrs.IgnoreWhitespace = true;
|
||||
|
||||
#if !KeePassLibSD && TODO
|
||||
#if !PCL
|
||||
// these are default values, so no need to set them
|
||||
#if !KeePassRT
|
||||
#if !KeePassLibSD
|
||||
xrs.ProhibitDtd = true;
|
||||
#endif
|
||||
|
||||
#if TODO
|
||||
xrs.ValidationType = ValidationType.None;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return xrs;
|
||||
}
|
||||
|
||||
@@ -199,6 +213,17 @@ namespace ModernKeePassLib.Serialization
|
||||
case KdbContext.Meta:
|
||||
if(xr.Name == ElemGenerator)
|
||||
ReadString(xr); // Ignore
|
||||
else if(xr.Name == ElemHeaderHash)
|
||||
{
|
||||
string strHash = ReadString(xr);
|
||||
if(!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
|
||||
!m_bRepairMode)
|
||||
{
|
||||
byte[] pbHash = Convert.FromBase64String(strHash);
|
||||
if(!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
|
||||
throw new IOException(KLRes.FileCorrupted);
|
||||
}
|
||||
}
|
||||
else if(xr.Name == ElemDbName)
|
||||
m_pwDatabase.Name = ReadString(xr);
|
||||
else if(xr.Name == ElemDbNameChanged)
|
||||
@@ -216,10 +241,8 @@ namespace ModernKeePassLib.Serialization
|
||||
else if(xr.Name == ElemDbColor)
|
||||
{
|
||||
string strColor = ReadString(xr);
|
||||
#if TODO
|
||||
if(!string.IsNullOrEmpty(strColor))
|
||||
m_pwDatabase.Color = ColorTranslator.FromHtml(strColor);
|
||||
#endif
|
||||
/*if(!string.IsNullOrEmpty(strColor))
|
||||
m_pwDatabase.Color = ColorTranslator.FromHtml(strColor);*/
|
||||
}
|
||||
else if(xr.Name == ElemDbKeyChanged)
|
||||
m_pwDatabase.MasterKeyChanged = ReadTime(xr);
|
||||
@@ -390,19 +413,14 @@ namespace ModernKeePassLib.Serialization
|
||||
else if(xr.Name == ElemFgColor)
|
||||
{
|
||||
string strColor = ReadString(xr);
|
||||
#if TODO
|
||||
if(!string.IsNullOrEmpty(strColor))
|
||||
m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);
|
||||
#endif
|
||||
/*if(!string.IsNullOrEmpty(strColor))
|
||||
m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);*/
|
||||
}
|
||||
else if(xr.Name == ElemBgColor)
|
||||
{
|
||||
|
||||
string strColor = ReadString(xr);
|
||||
#if TODO
|
||||
if(!string.IsNullOrEmpty(strColor))
|
||||
m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);
|
||||
#endif
|
||||
/*if(!string.IsNullOrEmpty(strColor))
|
||||
m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);*/
|
||||
}
|
||||
else if(xr.Name == ElemOverrideUrl)
|
||||
m_ctxEntry.OverrideUrl = ReadString(xr);
|
||||
@@ -436,10 +454,10 @@ namespace ModernKeePassLib.Serialization
|
||||
(ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
|
||||
Debug.Assert(tl != null);
|
||||
|
||||
if(xr.Name == ElemLastModTime)
|
||||
tl.LastModificationTime = ReadTime(xr);
|
||||
else if(xr.Name == ElemCreationTime)
|
||||
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)
|
||||
@@ -545,7 +563,8 @@ namespace ModernKeePassLib.Serialization
|
||||
return KdbContext.Meta;
|
||||
else if((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem))
|
||||
{
|
||||
if((m_uuidCustomIconID != PwUuid.Zero) && (m_pbCustomIconData != null))
|
||||
if(!m_uuidCustomIconID.Equals(PwUuid.Zero) &&
|
||||
(m_pbCustomIconData != null))
|
||||
m_pwDatabase.CustomIcons.Add(new PwCustomIcon(
|
||||
m_uuidCustomIconID, m_pbCustomIconData));
|
||||
else { Debug.Assert(false); }
|
||||
@@ -572,7 +591,7 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
else if((ctx == KdbContext.Group) && (xr.Name == ElemGroup))
|
||||
{
|
||||
if(PwUuid.Zero.EqualsValue(m_ctxGroup.Uuid))
|
||||
if(PwUuid.Zero.Equals(m_ctxGroup.Uuid))
|
||||
m_ctxGroup.Uuid = new PwUuid(true); // No assert (import)
|
||||
|
||||
m_ctxGroups.Pop();
|
||||
@@ -593,7 +612,7 @@ namespace ModernKeePassLib.Serialization
|
||||
else if((ctx == KdbContext.Entry) && (xr.Name == ElemEntry))
|
||||
{
|
||||
// Create new UUID if absent
|
||||
if(PwUuid.Zero.EqualsValue(m_ctxEntry.Uuid))
|
||||
if(PwUuid.Zero.Equals(m_ctxEntry.Uuid))
|
||||
m_ctxEntry.Uuid = new PwUuid(true); // No assert (import)
|
||||
|
||||
if(m_bEntryInHistory)
|
||||
@@ -670,13 +689,21 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
m_bReadNextNode = false; // ReadElementString skips end tag
|
||||
#if PCL
|
||||
return xr.ReadElementContentAsString();
|
||||
#else
|
||||
return xr.ReadElementString();
|
||||
#endif
|
||||
}
|
||||
|
||||
private string ReadStringRaw(XmlReader xr)
|
||||
{
|
||||
m_bReadNextNode = false; // ReadElementString skips end tag
|
||||
return xr.ReadElementContentAsString();
|
||||
#if PCL
|
||||
return xr.ReadElementContentAsString();
|
||||
#else
|
||||
return xr.ReadElementString();
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool ReadBool(XmlReader xr, bool bDefault)
|
||||
@@ -701,6 +728,9 @@ namespace ModernKeePassLib.Serialization
|
||||
string str = ReadString(xr);
|
||||
|
||||
int n;
|
||||
if(StrUtil.TryParseIntInvariant(str, out n)) return n;
|
||||
|
||||
// Backward compatibility
|
||||
if(StrUtil.TryParseInt(str, out n)) return n;
|
||||
|
||||
Debug.Assert(false);
|
||||
@@ -712,6 +742,9 @@ namespace ModernKeePassLib.Serialization
|
||||
string str = ReadString(xr);
|
||||
|
||||
uint u;
|
||||
if(StrUtil.TryParseUIntInvariant(str, out u)) return u;
|
||||
|
||||
// Backward compatibility
|
||||
if(StrUtil.TryParseUInt(str, out u)) return u;
|
||||
|
||||
Debug.Assert(false);
|
||||
@@ -723,6 +756,9 @@ namespace ModernKeePassLib.Serialization
|
||||
string str = ReadString(xr);
|
||||
|
||||
long l;
|
||||
if(StrUtil.TryParseLongInvariant(str, out l)) return l;
|
||||
|
||||
// Backward compatibility
|
||||
if(StrUtil.TryParseLong(str, out l)) return l;
|
||||
|
||||
Debug.Assert(false);
|
||||
@@ -734,6 +770,9 @@ namespace ModernKeePassLib.Serialization
|
||||
string str = ReadString(xr);
|
||||
|
||||
ulong u;
|
||||
if(StrUtil.TryParseULongInvariant(str, out u)) return u;
|
||||
|
||||
// Backward compatibility
|
||||
if(StrUtil.TryParseULong(str, out u)) return u;
|
||||
|
||||
Debug.Assert(false);
|
||||
@@ -757,7 +796,7 @@ namespace ModernKeePassLib.Serialization
|
||||
if(xb != null) return new ProtectedString(true, xb);
|
||||
|
||||
bool bProtect = false;
|
||||
if(m_format == Kdb4Format.PlainXml)
|
||||
if(m_format == KdbxFormat.PlainXml)
|
||||
{
|
||||
if(xr.MoveToAttribute(AttrProtectedInMemPlainXml))
|
||||
{
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -21,12 +21,20 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Security;
|
||||
|
||||
#if PCL
|
||||
using Windows.Security.Cryptography;
|
||||
#else
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
using System.Xml;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
#if !KeePassLibSD
|
||||
using System.IO.Compression;
|
||||
#else
|
||||
using ModernKeePassLibSD;
|
||||
using KeePassLibSD;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Cryptography;
|
||||
@@ -35,41 +43,35 @@ using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Keys;
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Utility;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialization to KeePass KDBX files.
|
||||
/// </summary>
|
||||
public sealed partial class Kdb4File
|
||||
/// <summary>
|
||||
/// Serialization to KeePass KDBX files.
|
||||
/// </summary>
|
||||
public sealed partial class KdbxFile
|
||||
{
|
||||
private IOConnection m_connection;
|
||||
|
||||
/// <summary>
|
||||
/// Load a KDB file from a file.
|
||||
/// </summary>
|
||||
/// <param name="strFilePath">File to load.</param>
|
||||
/// <param name="kdbFormat">Format specifier.</param>
|
||||
/// <param name="slLogger">Status logger (optional).</param>
|
||||
public async Task Load(string strFilePath, Kdb4Format kdbFormat, IStatusLogger slLogger)
|
||||
public void Load(string strFilePath, KdbxFormat kdbFormat, IStatusLogger slLogger)
|
||||
{
|
||||
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFilePath);
|
||||
IOConnection ioConnection = new IOConnection();
|
||||
Stream abc = await ioConnection.OpenRead(ioc);
|
||||
Load(abc, kdbFormat, slLogger);
|
||||
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFilePath);
|
||||
Load(IOConnection.OpenRead(ioc), kdbFormat, slLogger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load a KDB file from a stream.
|
||||
/// </summary>
|
||||
/// <param name="sSource">Stream to read the data from. Must contain
|
||||
/// a KDB4 stream.</param>
|
||||
/// a KDBX stream.</param>
|
||||
/// <param name="kdbFormat">Format specifier.</param>
|
||||
/// <param name="slLogger">Status logger (optional).</param>
|
||||
public void Load(Stream sSource, Kdb4Format kdbFormat, IStatusLogger slLogger)
|
||||
public void Load(Stream sSource, KdbxFormat kdbFormat, IStatusLogger slLogger)
|
||||
{
|
||||
|
||||
Debug.Assert(sSource != null);
|
||||
if(sSource == null) throw new ArgumentNullException("sSource");
|
||||
|
||||
@@ -85,7 +87,7 @@ namespace ModernKeePassLib.Serialization
|
||||
BinaryReaderEx brDecrypted = null;
|
||||
Stream readerStream = null;
|
||||
|
||||
if(kdbFormat == Kdb4Format.Default)
|
||||
if(kdbFormat == KdbxFormat.Default)
|
||||
{
|
||||
br = new BinaryReaderEx(hashedStream, encNoBom, KLRes.FileCorrupted);
|
||||
ReadHeader(br);
|
||||
@@ -113,11 +115,11 @@ namespace ModernKeePassLib.Serialization
|
||||
readerStream = new GZipStream(sHashed, CompressionMode.Decompress);
|
||||
else readerStream = sHashed;
|
||||
}
|
||||
else if(kdbFormat == Kdb4Format.PlainXml)
|
||||
else if(kdbFormat == KdbxFormat.PlainXml)
|
||||
readerStream = hashedStream;
|
||||
else { Debug.Assert(false); throw new FormatException("KdbFormat"); }
|
||||
|
||||
if(kdbFormat != Kdb4Format.PlainXml) // Is an encrypted format
|
||||
if(kdbFormat != KdbxFormat.PlainXml) // Is an encrypted format
|
||||
{
|
||||
if(m_pbProtectedStreamKey == null)
|
||||
{
|
||||
@@ -130,53 +132,64 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
else m_randomStream = null; // No random stream for plain-text files
|
||||
|
||||
#if KeePassDebug_WriteXml
|
||||
// FileStream fsOut = new FileStream("Raw.xml", FileMode.Create,
|
||||
// FileAccess.Write, FileShare.None);
|
||||
// try
|
||||
// {
|
||||
// while(true)
|
||||
// {
|
||||
// int b = readerStream.ReadByte();
|
||||
// if(b == -1) break;
|
||||
// fsOut.WriteByte((byte)b);
|
||||
// }
|
||||
// }
|
||||
// catch(Exception) { }
|
||||
// fsOut.Close();
|
||||
#endif
|
||||
|
||||
ReadXmlStreamed(readerStream, hashedStream);
|
||||
// ReadXmlDom(readerStream);
|
||||
|
||||
#if !KeePassWinRT
|
||||
readerStream.Close();
|
||||
#endif
|
||||
GC.KeepAlive(brDecrypted);
|
||||
GC.KeepAlive(br);
|
||||
readerStream.Dispose();
|
||||
// GC.KeepAlive(br);
|
||||
// GC.KeepAlive(brDecrypted);
|
||||
}
|
||||
#if !KeePassWinRT
|
||||
#if !PCL
|
||||
catch(CryptographicException) // Thrown on invalid padding
|
||||
{
|
||||
throw new CryptographicException(KLRes.FileCorrupted);
|
||||
}
|
||||
#endif
|
||||
finally { CommonCleanUpRead(sSource, hashedStream); }
|
||||
|
||||
}
|
||||
|
||||
private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream)
|
||||
{
|
||||
m_pbHashOfFileOnDisk = hashedStream.Hash;
|
||||
// Reset memory protection settings (to always use reasonable
|
||||
// defaults)
|
||||
m_pwDatabase.MemoryProtection = new MemoryProtectionConfig();
|
||||
{
|
||||
hashedStream.Dispose();
|
||||
m_pbHashOfFileOnDisk = hashedStream.Hash;
|
||||
|
||||
return;
|
||||
sSource.Dispose();
|
||||
|
||||
#if !KeePassWinRT
|
||||
// Remove old backups (this call is required here in order to apply
|
||||
// the default history maintenance settings for people upgrading from
|
||||
// KeePass <= 2.14 to >= 2.15; also it ensures history integrity in
|
||||
// case a different application has created the KDBX file and ignored
|
||||
// the history maintenance settings)
|
||||
m_pwDatabase.MaintainBackups(); // Don't mark database as modified
|
||||
// Reset memory protection settings (to always use reasonable
|
||||
// defaults)
|
||||
m_pwDatabase.MemoryProtection = new MemoryProtectionConfig();
|
||||
|
||||
// Remove old backups (this call is required here in order to apply
|
||||
// the default history maintenance settings for people upgrading from
|
||||
// KeePass <= 2.14 to >= 2.15; also it ensures history integrity in
|
||||
// case a different application has created the KDBX file and ignored
|
||||
// the history maintenance settings)
|
||||
m_pwDatabase.MaintainBackups(); // Don't mark database as modified
|
||||
|
||||
// Is it ok to leave the stream open ????
|
||||
hashedStream.Close();
|
||||
sSource.Close();
|
||||
#endif
|
||||
}
|
||||
m_pbHashOfHeader = null;
|
||||
}
|
||||
|
||||
private void ReadHeader(BinaryReaderEx br)
|
||||
{
|
||||
Debug.Assert(br != null);
|
||||
if(br == null) throw new ArgumentNullException("br");
|
||||
MemoryStream msHeader = new MemoryStream();
|
||||
Debug.Assert(br.CopyDataTo == null);
|
||||
br.CopyDataTo = msHeader;
|
||||
|
||||
byte[] pbSig1 = br.ReadBytes(4);
|
||||
uint uSig1 = MemUtil.BytesToUInt32(pbSig1);
|
||||
@@ -194,19 +207,27 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
byte[] pb = br.ReadBytes(4);
|
||||
uint uVersion = MemUtil.BytesToUInt32(pb);
|
||||
|
||||
if ((uVersion & FileVersionCriticalMask) > (FileVersion32 & FileVersionCriticalMask))
|
||||
#if TODO
|
||||
if((uVersion & FileVersionCriticalMask) > (FileVersion32 & FileVersionCriticalMask))
|
||||
throw new FormatException(KLRes.FileVersionUnsupported +
|
||||
MessageService.NewParagraph + KLRes.FileNewVerReq);
|
||||
#else
|
||||
throw new FormatException();
|
||||
#endif
|
||||
Environment.NewLine + Environment.NewLine + KLRes.FileNewVerReq);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(ReadHeaderField(br) == false)
|
||||
break;
|
||||
}
|
||||
|
||||
br.CopyDataTo = null;
|
||||
byte[] pbHeader = msHeader.ToArray();
|
||||
msHeader.Dispose();
|
||||
|
||||
#if PCL
|
||||
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||
m_pbHashOfHeader = sha256.HashData(pbHeader.AsBuffer()).ToArray();
|
||||
#else
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
m_pbHashOfHeader = sha256.ComputeHash(pbHeader);
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool ReadHeaderField(BinaryReaderEx brSource)
|
||||
@@ -229,49 +250,49 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
bool bResult = true;
|
||||
Kdb4HeaderFieldID kdbID = (Kdb4HeaderFieldID)btFieldID;
|
||||
KdbxHeaderFieldID kdbID = (KdbxHeaderFieldID)btFieldID;
|
||||
switch(kdbID)
|
||||
{
|
||||
case Kdb4HeaderFieldID.EndOfHeader:
|
||||
case KdbxHeaderFieldID.EndOfHeader:
|
||||
bResult = false; // Returning false indicates end of header
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.CipherID:
|
||||
case KdbxHeaderFieldID.CipherID:
|
||||
SetCipher(pbData);
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.CompressionFlags:
|
||||
case KdbxHeaderFieldID.CompressionFlags:
|
||||
SetCompressionFlags(pbData);
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.MasterSeed:
|
||||
case KdbxHeaderFieldID.MasterSeed:
|
||||
m_pbMasterSeed = pbData;
|
||||
CryptoRandom.Instance.AddEntropy(pbData);
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.TransformSeed:
|
||||
case KdbxHeaderFieldID.TransformSeed:
|
||||
m_pbTransformSeed = pbData;
|
||||
CryptoRandom.Instance.AddEntropy(pbData);
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.TransformRounds:
|
||||
case KdbxHeaderFieldID.TransformRounds:
|
||||
m_pwDatabase.KeyEncryptionRounds = MemUtil.BytesToUInt64(pbData);
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.EncryptionIV:
|
||||
case KdbxHeaderFieldID.EncryptionIV:
|
||||
m_pbEncryptionIV = pbData;
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.ProtectedStreamKey:
|
||||
case KdbxHeaderFieldID.ProtectedStreamKey:
|
||||
m_pbProtectedStreamKey = pbData;
|
||||
CryptoRandom.Instance.AddEntropy(pbData);
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.StreamStartBytes:
|
||||
case KdbxHeaderFieldID.StreamStartBytes:
|
||||
m_pbStreamStartBytes = pbData;
|
||||
break;
|
||||
|
||||
case Kdb4HeaderFieldID.InnerRandomStreamID:
|
||||
case KdbxHeaderFieldID.InnerRandomStreamID:
|
||||
SetInnerRandomStreamID(pbData);
|
||||
break;
|
||||
|
||||
@@ -312,46 +333,39 @@ namespace ModernKeePassLib.Serialization
|
||||
m_craInnerRandomStream = (CrsAlgorithm)uID;
|
||||
}
|
||||
|
||||
private Stream AttachStreamDecryptor(Stream s)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
private Stream AttachStreamDecryptor(Stream s)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
Debug.Assert(m_pbMasterSeed.Length == 32);
|
||||
if (m_pbMasterSeed.Length != 32)
|
||||
throw new FormatException(KLRes.MasterSeedLengthInvalid);
|
||||
ms.Write(m_pbMasterSeed, 0, 32);
|
||||
|
||||
Debug.Assert(m_pbMasterSeed.Length == 32);
|
||||
if(m_pbMasterSeed.Length != 32)
|
||||
throw new FormatException(KLRes.MasterSeedLengthInvalid);
|
||||
ms.Write(m_pbMasterSeed, 0, 32);
|
||||
byte[] pKey32 = m_pwDatabase.MasterKey.GenerateKey32(m_pbTransformSeed,
|
||||
m_pwDatabase.KeyEncryptionRounds).ReadData();
|
||||
if (pKey32 == null || pKey32.Length != 32)
|
||||
throw new SecurityException(KLRes.InvalidCompositeKey);
|
||||
ms.Write(pKey32, 0, 32);
|
||||
|
||||
Security.ProtectedBinary pb = m_pwDatabase.MasterKey.GenerateKey32(m_pbTransformSeed,
|
||||
m_pwDatabase.KeyEncryptionRounds);
|
||||
#if PCL
|
||||
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||
var aesKey = sha256.HashData(ms.GetWindowsRuntimeBuffer()).ToArray();
|
||||
#else
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
byte[] aesKey = sha256.ComputeHash(ms.ToArray());
|
||||
#endif
|
||||
Array.Clear(pKey32, 0, 32);
|
||||
|
||||
byte[] pKey32 = pb.ReadData();
|
||||
if((pKey32 == null) || (pKey32.Length != 32))
|
||||
throw new SecurityException(KLRes.InvalidCompositeKey);
|
||||
ms.Write(pKey32, 0, 32);
|
||||
|
||||
byte[] aesKey = SHA256Managed.Instance.ComputeHash(ms.ToArray());
|
||||
|
||||
//SHA256Managed sha256 = new SHA256Managed();
|
||||
//byte[] aesKey = sha256.ComputeHash(ms.ToArray());
|
||||
|
||||
//ms.Close();
|
||||
Array.Clear(pKey32, 0, 32);
|
||||
|
||||
if((aesKey == null) || (aesKey.Length != 32))
|
||||
throw new SecurityException(KLRes.FinalKeyCreationFailed);
|
||||
|
||||
ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
|
||||
if(iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
|
||||
return iEngine.DecryptStream(s, aesKey, m_pbEncryptionIV);
|
||||
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public static List<PwEntry> ReadEntries(PwDatabase pwDatabase, Stream msData)
|
||||
{
|
||||
return ReadEntries(msData);
|
||||
}
|
||||
if (aesKey == null || aesKey.Length != 32)
|
||||
throw new SecurityException(KLRes.FinalKeyCreationFailed);
|
||||
|
||||
ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
|
||||
if (iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
|
||||
return iEngine.DecryptStream(s, aesKey, m_pbEncryptionIV);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read entries from a stream.
|
||||
/// </summary>
|
||||
@@ -359,11 +373,8 @@ namespace ModernKeePassLib.Serialization
|
||||
/// <returns>Extracted entries.</returns>
|
||||
public static List<PwEntry> ReadEntries(Stream msData)
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return null;
|
||||
#if TODO
|
||||
/* Kdb4File f = new Kdb4File(pwDatabase);
|
||||
f.m_format = Kdb4Format.PlainXml;
|
||||
/* KdbxFile f = new KdbxFile(pwDatabase);
|
||||
f.m_format = KdbxFormat.PlainXml;
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(msData);
|
||||
@@ -391,8 +402,8 @@ namespace ModernKeePassLib.Serialization
|
||||
return vEntries; */
|
||||
|
||||
PwDatabase pd = new PwDatabase();
|
||||
Kdb4File f = new Kdb4File(pd);
|
||||
f.Load(msData, Kdb4Format.PlainXml, null);
|
||||
KdbxFile f = new KdbxFile(pd);
|
||||
f.Load(msData, KdbxFormat.PlainXml, null);
|
||||
|
||||
List<PwEntry> vEntries = new List<PwEntry>();
|
||||
foreach(PwEntry pe in pd.RootGroup.Entries)
|
||||
@@ -402,7 +413,6 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
return vEntries;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,39 +19,43 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
//using System.Drawing;
|
||||
//using System.Drawing.Imaging;
|
||||
|
||||
#if !KeePassLibSD
|
||||
using System.Security;
|
||||
#if PCL
|
||||
using Windows.Security.Cryptography;
|
||||
#else
|
||||
using ModernKeePassLibSD;
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
#if !KeePassLibSD
|
||||
using System.IO.Compression;
|
||||
#else
|
||||
using KeePassLibSD;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Collections;
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Cryptography.Cipher;
|
||||
using ModernKeePassLib.Delegates;
|
||||
using ModernKeePassLib.Interfaces;
|
||||
using ModernKeePassLib.Keys;
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
using ModernKeePassLib.Delegates;
|
||||
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialization to KeePass KDB files.
|
||||
/// </summary>
|
||||
public sealed partial class Kdb4File
|
||||
/// <summary>
|
||||
/// Serialization to KeePass KDBX files.
|
||||
/// </summary>
|
||||
public sealed partial class KdbxFile
|
||||
{
|
||||
// public void Save(string strFile, PwGroup pgDataSource, Kdb4Format format,
|
||||
// public void Save(string strFile, PwGroup pgDataSource, KdbxFormat format,
|
||||
// IStatusLogger slLogger)
|
||||
// {
|
||||
// bool bMadeUnhidden = UrlUtil.UnhideFile(strFile);
|
||||
@@ -71,7 +75,7 @@ namespace ModernKeePassLib.Serialization
|
||||
/// be written.</param>
|
||||
/// <param name="format">Format of the file to create.</param>
|
||||
/// <param name="slLogger">Logger that recieves status information.</param>
|
||||
public void Save(Stream sSaveTo, PwGroup pgDataSource, Kdb4Format format,
|
||||
public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat format,
|
||||
IStatusLogger slLogger)
|
||||
{
|
||||
Debug.Assert(sSaveTo != null);
|
||||
@@ -85,152 +89,167 @@ namespace ModernKeePassLib.Serialization
|
||||
UTF8Encoding encNoBom = StrUtil.Utf8;
|
||||
CryptoRandom cr = CryptoRandom.Instance;
|
||||
|
||||
try
|
||||
{
|
||||
m_pbMasterSeed = cr.GetRandomBytes(32);
|
||||
m_pbTransformSeed = cr.GetRandomBytes(32);
|
||||
m_pbEncryptionIV = cr.GetRandomBytes(16);
|
||||
try
|
||||
{
|
||||
m_pbMasterSeed = cr.GetRandomBytes(32);
|
||||
m_pbTransformSeed = cr.GetRandomBytes(32);
|
||||
m_pbEncryptionIV = cr.GetRandomBytes(16);
|
||||
|
||||
m_pbProtectedStreamKey = cr.GetRandomBytes(32);
|
||||
m_craInnerRandomStream = CrsAlgorithm.Salsa20;
|
||||
m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
|
||||
m_pbProtectedStreamKey);
|
||||
m_pbProtectedStreamKey = cr.GetRandomBytes(32);
|
||||
m_craInnerRandomStream = CrsAlgorithm.Salsa20;
|
||||
m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
|
||||
m_pbProtectedStreamKey);
|
||||
|
||||
m_pbStreamStartBytes = cr.GetRandomBytes(32);
|
||||
m_pbStreamStartBytes = cr.GetRandomBytes(32);
|
||||
|
||||
Stream writerStream;
|
||||
BinaryWriter bw = null;
|
||||
if (m_format == Kdb4Format.Default)
|
||||
{
|
||||
bw = new BinaryWriter(hashedStream, encNoBom);
|
||||
WriteHeader(bw); // Also flushes bw
|
||||
Stream writerStream;
|
||||
if(m_format == KdbxFormat.Default)
|
||||
{
|
||||
WriteHeader(hashedStream); // Also flushes the stream
|
||||
|
||||
Stream sEncrypted = AttachStreamEncryptor(hashedStream);
|
||||
if ((sEncrypted == null) || (sEncrypted == hashedStream))
|
||||
throw new SecurityException(KLRes.CryptoStreamFailed);
|
||||
Stream sEncrypted = AttachStreamEncryptor(hashedStream);
|
||||
if((sEncrypted == null) || (sEncrypted == hashedStream))
|
||||
throw new SecurityException(KLRes.CryptoStreamFailed);
|
||||
|
||||
sEncrypted.Write(m_pbStreamStartBytes, 0, m_pbStreamStartBytes.Length);
|
||||
sEncrypted.Write(m_pbStreamStartBytes, 0, m_pbStreamStartBytes.Length);
|
||||
|
||||
Stream sHashed = new HashedBlockStream(sEncrypted, true);
|
||||
Stream sHashed = new HashedBlockStream(sEncrypted, true);
|
||||
|
||||
if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
|
||||
writerStream = new GZipStream(sHashed, CompressionMode.Compress);
|
||||
else
|
||||
writerStream = sHashed;
|
||||
}
|
||||
else if (m_format == Kdb4Format.PlainXml)
|
||||
writerStream = hashedStream;
|
||||
else
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new FormatException("KdbFormat");
|
||||
}
|
||||
if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
|
||||
writerStream = new GZipStream(sHashed, CompressionMode.Compress);
|
||||
else
|
||||
writerStream = sHashed;
|
||||
}
|
||||
else if(m_format == KdbxFormat.PlainXml)
|
||||
writerStream = hashedStream;
|
||||
else { Debug.Assert(false); throw new FormatException("KdbFormat"); }
|
||||
|
||||
using (m_xmlWriter = XmlWriter.Create(writerStream, new XmlWriterSettings {Encoding = encNoBom}))
|
||||
{
|
||||
WriteDocument(pgDataSource);
|
||||
#if PCL
|
||||
var settings = new XmlWriterSettings() {
|
||||
Encoding = encNoBom,
|
||||
Indent = true,
|
||||
IndentChars = "\t",
|
||||
NewLineChars = "\r\n",
|
||||
};
|
||||
m_xmlWriter = XmlWriter.Create(writerStream, settings);
|
||||
#else
|
||||
m_xmlWriter = new XmlTextWriter(writerStream, encNoBom);
|
||||
#endif
|
||||
WriteDocument(pgDataSource);
|
||||
|
||||
m_xmlWriter.Flush();
|
||||
writerStream.Dispose();
|
||||
}
|
||||
GC.KeepAlive(bw);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
m_xmlWriter.Flush();
|
||||
m_xmlWriter.Dispose();
|
||||
writerStream.Dispose();
|
||||
}
|
||||
finally { CommonCleanUpWrite(sSaveTo, hashedStream); }
|
||||
}
|
||||
|
||||
private void CommonCleanUpWrite(Stream sSaveTo, HashingStreamEx hashedStream)
|
||||
{
|
||||
//hashedStream.Close();
|
||||
hashedStream.Dispose();
|
||||
m_pbHashOfFileOnDisk = hashedStream.Hash;
|
||||
|
||||
sSaveTo.Dispose();
|
||||
|
||||
m_xmlWriter = null;
|
||||
m_pbHashOfHeader = null;
|
||||
}
|
||||
|
||||
private void WriteHeader(BinaryWriter bw)
|
||||
private void WriteHeader(Stream s)
|
||||
{
|
||||
Debug.Assert(bw != null);
|
||||
if(bw == null) throw new ArgumentNullException("bw");
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
bw.Write(MemUtil.UInt32ToBytes(FileSignature1));
|
||||
bw.Write(MemUtil.UInt32ToBytes(FileSignature2));
|
||||
bw.Write(MemUtil.UInt32ToBytes(FileVersion32));
|
||||
MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature1));
|
||||
MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature2));
|
||||
MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileVersion32));
|
||||
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.CipherID,
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.CipherID,
|
||||
m_pwDatabase.DataCipherUuid.UuidBytes);
|
||||
|
||||
int nCprID = (int)m_pwDatabase.Compression;
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.CompressionFlags,
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.CompressionFlags,
|
||||
MemUtil.UInt32ToBytes((uint)nCprID));
|
||||
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.MasterSeed, m_pbMasterSeed);
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.TransformSeed, m_pbTransformSeed);
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.TransformRounds, MemUtil.UInt64ToBytes(m_pwDatabase.KeyEncryptionRounds));
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.EncryptionIV, m_pbEncryptionIV);
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.ProtectedStreamKey, m_pbProtectedStreamKey);
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.StreamStartBytes, m_pbStreamStartBytes);
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.MasterSeed, m_pbMasterSeed);
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.TransformSeed, m_pbTransformSeed);
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.TransformRounds,
|
||||
MemUtil.UInt64ToBytes(m_pwDatabase.KeyEncryptionRounds));
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.EncryptionIV, m_pbEncryptionIV);
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.ProtectedStreamKey, m_pbProtectedStreamKey);
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.StreamStartBytes, m_pbStreamStartBytes);
|
||||
|
||||
int nIrsID = (int)m_craInnerRandomStream;
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.InnerRandomStreamID,
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamID,
|
||||
MemUtil.UInt32ToBytes((uint)nIrsID));
|
||||
|
||||
WriteHeaderField(bw, Kdb4HeaderFieldID.EndOfHeader, new byte[]{ (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' });
|
||||
bw.Flush();
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.EndOfHeader, new byte[]{
|
||||
(byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' });
|
||||
|
||||
byte[] pbHeader = ms.ToArray();
|
||||
ms.Dispose();
|
||||
|
||||
#if PCL
|
||||
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||
m_pbHashOfHeader = sha256.HashData(pbHeader.AsBuffer()).ToArray();
|
||||
#else
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
m_pbHashOfHeader = sha256.ComputeHash(pbHeader);
|
||||
#endif
|
||||
|
||||
s.Write(pbHeader, 0, pbHeader.Length);
|
||||
s.Flush();
|
||||
}
|
||||
|
||||
private static void WriteHeaderField(BinaryWriter bwOut,
|
||||
Kdb4HeaderFieldID kdbID, byte[] pbData)
|
||||
private static void WriteHeaderField(Stream s, KdbxHeaderFieldID kdbID,
|
||||
byte[] pbData)
|
||||
{
|
||||
Debug.Assert(bwOut != null);
|
||||
if(bwOut == null) throw new ArgumentNullException("bwOut");
|
||||
|
||||
bwOut.Write((byte)kdbID);
|
||||
s.WriteByte((byte)kdbID);
|
||||
|
||||
if(pbData != null)
|
||||
{
|
||||
ushort uLength = (ushort)pbData.Length;
|
||||
bwOut.Write(uLength);
|
||||
MemUtil.Write(s, MemUtil.UInt16ToBytes(uLength));
|
||||
|
||||
if(uLength > 0) bwOut.Write(pbData);
|
||||
if(uLength > 0) s.Write(pbData, 0, pbData.Length);
|
||||
}
|
||||
else bwOut.Write((ushort)0);
|
||||
else MemUtil.Write(s, MemUtil.UInt16ToBytes((ushort)0));
|
||||
}
|
||||
|
||||
private Stream AttachStreamEncryptor(Stream s)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
Debug.Assert(m_pbMasterSeed != null);
|
||||
Debug.Assert(m_pbMasterSeed.Length == 32);
|
||||
ms.Write(m_pbMasterSeed, 0, 32);
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
Debug.Assert(m_pwDatabase != null);
|
||||
Debug.Assert(m_pwDatabase.MasterKey != null);
|
||||
ProtectedBinary pbinKey = m_pwDatabase.MasterKey.GenerateKey32(
|
||||
m_pbTransformSeed, m_pwDatabase.KeyEncryptionRounds);
|
||||
Debug.Assert(pbinKey != null);
|
||||
if (pbinKey == null)
|
||||
throw new SecurityException(KLRes.InvalidCompositeKey);
|
||||
byte[] pKey32 = pbinKey.ReadData();
|
||||
if ((pKey32 == null) || (pKey32.Length != 32))
|
||||
throw new SecurityException(KLRes.InvalidCompositeKey);
|
||||
ms.Write(pKey32, 0, 32);
|
||||
Debug.Assert(m_pbMasterSeed != null);
|
||||
Debug.Assert(m_pbMasterSeed.Length == 32);
|
||||
ms.Write(m_pbMasterSeed, 0, 32);
|
||||
|
||||
SHA256Managed sha256 = SHA256Managed.Instance;
|
||||
byte[] aesKey = sha256.ComputeHash(ms.ToArray());
|
||||
|
||||
Array.Clear(pKey32, 0, 32);
|
||||
Debug.Assert(m_pwDatabase != null);
|
||||
Debug.Assert(m_pwDatabase.MasterKey != null);
|
||||
ProtectedBinary pbinKey = m_pwDatabase.MasterKey.GenerateKey32(
|
||||
m_pbTransformSeed, m_pwDatabase.KeyEncryptionRounds);
|
||||
Debug.Assert(pbinKey != null);
|
||||
if(pbinKey == null)
|
||||
throw new SecurityException(KLRes.InvalidCompositeKey);
|
||||
byte[] pKey32 = pbinKey.ReadData();
|
||||
if((pKey32 == null) || (pKey32.Length != 32))
|
||||
throw new SecurityException(KLRes.InvalidCompositeKey);
|
||||
ms.Write(pKey32, 0, 32);
|
||||
|
||||
Debug.Assert(CipherPool.GlobalPool != null);
|
||||
ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
|
||||
if(iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
|
||||
return iEngine.EncryptStream(s, aesKey, m_pbEncryptionIV);
|
||||
}
|
||||
#if PCL
|
||||
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||
var aesKey = sha256.HashData(ms.GetWindowsRuntimeBuffer()).ToArray();
|
||||
#else
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
byte[] aesKey = sha256.ComputeHash(ms.ToArray());
|
||||
#endif
|
||||
|
||||
ms.Dispose();
|
||||
Array.Clear(pKey32, 0, 32);
|
||||
|
||||
Debug.Assert(CipherPool.GlobalPool != null);
|
||||
ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
|
||||
if(iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
|
||||
return iEngine.EncryptStream(s, aesKey, m_pbEncryptionIV);
|
||||
}
|
||||
|
||||
private void WriteDocument(PwGroup pgDataSource)
|
||||
@@ -245,8 +264,11 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
BinPoolBuild(pgRoot);
|
||||
|
||||
m_xmlWriter.Settings.Indent = true;
|
||||
m_xmlWriter.Settings.IndentChars = "\t";
|
||||
#if !PCL
|
||||
m_xmlWriter.Formatting = Formatting.Indented;
|
||||
m_xmlWriter.IndentChar = '\t';
|
||||
m_xmlWriter.Indentation = 1;
|
||||
#endif
|
||||
|
||||
m_xmlWriter.WriteStartDocument(true);
|
||||
m_xmlWriter.WriteStartElement(ElemDocNode);
|
||||
@@ -320,6 +342,11 @@ namespace ModernKeePassLib.Serialization
|
||||
m_xmlWriter.WriteStartElement(ElemMeta);
|
||||
|
||||
WriteObject(ElemGenerator, PwDatabase.LocalizedAppName, false); // Generator name
|
||||
|
||||
if(m_pbHashOfHeader != null)
|
||||
WriteObject(ElemHeaderHash, Convert.ToBase64String(
|
||||
m_pbHashOfHeader), false);
|
||||
|
||||
WriteObject(ElemDbName, m_pwDatabase.Name, true);
|
||||
WriteObject(ElemDbNameChanged, m_pwDatabase.NameChanged);
|
||||
WriteObject(ElemDbDesc, m_pwDatabase.Description, true);
|
||||
@@ -361,7 +388,7 @@ namespace ModernKeePassLib.Serialization
|
||||
WriteObject(ElemNotes, pg.Notes, true);
|
||||
WriteObject(ElemIcon, (int)pg.IconId);
|
||||
|
||||
if(pg.CustomIconUuid != PwUuid.Zero)
|
||||
if(!pg.CustomIconUuid.Equals(PwUuid.Zero))
|
||||
WriteObject(ElemCustomIconID, pg.CustomIconUuid);
|
||||
|
||||
WriteList(ElemTimes, pg);
|
||||
@@ -386,7 +413,7 @@ namespace ModernKeePassLib.Serialization
|
||||
WriteObject(ElemUuid, pe.Uuid);
|
||||
WriteObject(ElemIcon, (int)pe.IconId);
|
||||
|
||||
if(pe.CustomIconUuid != PwUuid.Zero)
|
||||
if(!pe.CustomIconUuid.Equals(PwUuid.Zero))
|
||||
WriteObject(ElemCustomIconID, pe.CustomIconUuid);
|
||||
|
||||
WriteObject(ElemFgColor, StrUtil.ColorToUnnamedHtml(pe.ForegroundColor, true), false);
|
||||
@@ -452,8 +479,8 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
m_xmlWriter.WriteStartElement(name);
|
||||
|
||||
WriteObject(ElemLastModTime, times.LastModificationTime);
|
||||
WriteObject(ElemCreationTime, times.CreationTime);
|
||||
WriteObject(ElemLastModTime, times.LastModificationTime);
|
||||
WriteObject(ElemLastAccessTime, times.LastAccessTime);
|
||||
WriteObject(ElemExpiryTime, times.ExpiryTime);
|
||||
WriteObject(ElemExpires, times.Expires);
|
||||
@@ -575,7 +602,7 @@ namespace ModernKeePassLib.Serialization
|
||||
Debug.Assert(name != null);
|
||||
|
||||
m_xmlWriter.WriteStartElement(name);
|
||||
m_xmlWriter.WriteString(value.ToString());
|
||||
m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
|
||||
m_xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
@@ -584,7 +611,7 @@ namespace ModernKeePassLib.Serialization
|
||||
Debug.Assert(name != null);
|
||||
|
||||
m_xmlWriter.WriteStartElement(name);
|
||||
m_xmlWriter.WriteString(value.ToString());
|
||||
m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
|
||||
m_xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
@@ -593,7 +620,7 @@ namespace ModernKeePassLib.Serialization
|
||||
Debug.Assert(name != null);
|
||||
|
||||
m_xmlWriter.WriteStartElement(name);
|
||||
m_xmlWriter.WriteString(value.ToString());
|
||||
m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
|
||||
m_xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
@@ -602,7 +629,7 @@ namespace ModernKeePassLib.Serialization
|
||||
Debug.Assert(name != null);
|
||||
|
||||
m_xmlWriter.WriteStartElement(name);
|
||||
m_xmlWriter.WriteString(value.ToString());
|
||||
m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
|
||||
m_xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
@@ -657,7 +684,7 @@ namespace ModernKeePassLib.Serialization
|
||||
bProtected = m_pwDatabase.MemoryProtection.ProtectNotes;
|
||||
}
|
||||
|
||||
if(bProtected && (m_format != Kdb4Format.PlainXml))
|
||||
if(bProtected && (m_format != KdbxFormat.PlainXml))
|
||||
{
|
||||
m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
|
||||
|
||||
@@ -667,7 +694,6 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
string strValue = value.ReadString();
|
||||
|
||||
// If names should be localized, we need to apply the language-dependent
|
||||
@@ -685,7 +711,8 @@ namespace ModernKeePassLib.Serialization
|
||||
// page area
|
||||
if(char.IsSymbol(ch) || char.IsSurrogate(ch))
|
||||
{
|
||||
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory(ch);
|
||||
System.Globalization.UnicodeCategory cat =
|
||||
CharUnicodeInfo.GetUnicodeCategory(ch);
|
||||
// Map character to correct position in code page
|
||||
chMapped = (char)((int)cat * 32 + ch);
|
||||
}
|
||||
@@ -697,7 +724,11 @@ namespace ModernKeePassLib.Serialization
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,8 +738,7 @@ namespace ModernKeePassLib.Serialization
|
||||
strValue = sb.ToString(); // Correct string for current code page
|
||||
}
|
||||
|
||||
|
||||
if((m_format == Kdb4Format.PlainXml) && bProtected)
|
||||
if((m_format == KdbxFormat.PlainXml) && bProtected)
|
||||
m_xmlWriter.WriteAttributeString(AttrProtectedInMemPlainXml, ValTrue);
|
||||
|
||||
m_xmlWriter.WriteString(StrUtil.SafeXmlString(strValue));
|
||||
@@ -716,7 +746,7 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
m_xmlWriter.WriteEndElement(); // ElemValue
|
||||
m_xmlWriter.WriteEndElement(); // ElemString
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteObject(string name, ProtectedBinary value, bool bAllowRef)
|
||||
{
|
||||
@@ -742,7 +772,7 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
private void SubWriteValue(ProtectedBinary value)
|
||||
{
|
||||
if(value.IsProtected && (m_format != Kdb4Format.PlainXml))
|
||||
if(value.IsProtected && (m_format != KdbxFormat.PlainXml))
|
||||
{
|
||||
m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
|
||||
|
||||
@@ -810,8 +840,8 @@ namespace ModernKeePassLib.Serialization
|
||||
/// to the stream.</returns>
|
||||
public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries)
|
||||
{
|
||||
/* Kdb4File f = new Kdb4File(pwDatabase);
|
||||
f.m_format = Kdb4Format.PlainXml;
|
||||
/* KdbxFile f = new KdbxFile(pwDatabase);
|
||||
f.m_format = KdbxFormat.PlainXml;
|
||||
|
||||
XmlTextWriter xtw = null;
|
||||
try { xtw = new XmlTextWriter(msOutput, StrUtil.Utf8); }
|
||||
@@ -843,8 +873,8 @@ namespace ModernKeePassLib.Serialization
|
||||
foreach(PwEntry peCopy in vEntries)
|
||||
pd.RootGroup.AddEntry(peCopy.CloneDeep(), true);
|
||||
|
||||
Kdb4File f = new Kdb4File(pd);
|
||||
f.Save(msOutput, null, Kdb4Format.PlainXml, null);
|
||||
KdbxFile f = new KdbxFile(pd);
|
||||
f.Save(msOutput, null, KdbxFormat.PlainXml, null);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -29,6 +29,10 @@ using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
#endif
|
||||
|
||||
#if PCL
|
||||
using Windows.Storage;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Collections;
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Delegates;
|
||||
@@ -39,10 +43,10 @@ using ModernKeePassLib.Utility;
|
||||
namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// The <c>Kdb4File</c> class supports saving the data to various
|
||||
/// The <c>KdbxFile</c> class supports saving the data to various
|
||||
/// formats.
|
||||
/// </summary>
|
||||
public enum Kdb4Format
|
||||
public enum KdbxFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// The default, encrypted file format.
|
||||
@@ -56,37 +60,37 @@ namespace ModernKeePassLib.Serialization
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialization to KeePass KDB files.
|
||||
/// Serialization to KeePass KDBX files.
|
||||
/// </summary>
|
||||
public sealed partial class Kdb4File
|
||||
public sealed partial class KdbxFile
|
||||
{
|
||||
/// <summary>
|
||||
/// File identifier, first 32-bit value.
|
||||
/// </summary>
|
||||
private const uint FileSignature1 = 0x9AA2D903;
|
||||
internal const uint FileSignature1 = 0x9AA2D903;
|
||||
|
||||
/// <summary>
|
||||
/// File identifier, second 32-bit value.
|
||||
/// </summary>
|
||||
private const uint FileSignature2 = 0xB54BFB67;
|
||||
internal const uint FileSignature2 = 0xB54BFB67;
|
||||
|
||||
/// <summary>
|
||||
/// File version of files saved by the current <c>Kdb4File</c> class.
|
||||
/// File version of files saved by the current <c>KdbxFile</c> class.
|
||||
/// KeePass 2.07 has version 1.01, 2.08 has 1.02, 2.09 has 2.00,
|
||||
/// 2.10 has 2.02, 2.11 has 2.04, 2.15 has 3.00.
|
||||
/// 2.10 has 2.02, 2.11 has 2.04, 2.15 has 3.00, 2.20 has 3.01.
|
||||
/// The first 2 bytes are critical (i.e. loading will fail, if the
|
||||
/// file version is too high), the last 2 bytes are informational.
|
||||
/// </summary>
|
||||
private const uint FileVersion32 = 0x00030000;
|
||||
private const uint FileVersion32 = 0x00030001;
|
||||
|
||||
private const uint FileVersionCriticalMask = 0xFFFF0000;
|
||||
|
||||
// KeePass 1.x signature
|
||||
private const uint FileSignatureOld1 = 0x9AA2D903;
|
||||
private const uint FileSignatureOld2 = 0xB54BFB65;
|
||||
internal const uint FileSignatureOld1 = 0x9AA2D903;
|
||||
internal const uint FileSignatureOld2 = 0xB54BFB65;
|
||||
// KeePass 2.x pre-release (alpha and beta) signature
|
||||
private const uint FileSignaturePreRelease1 = 0x9AA2D903;
|
||||
private const uint FileSignaturePreRelease2 = 0xB54BFB66;
|
||||
internal const uint FileSignaturePreRelease1 = 0x9AA2D903;
|
||||
internal const uint FileSignaturePreRelease2 = 0xB54BFB66;
|
||||
|
||||
private const string ElemDocNode = "KeePassFile";
|
||||
private const string ElemMeta = "Meta";
|
||||
@@ -95,6 +99,7 @@ namespace ModernKeePassLib.Serialization
|
||||
private const string ElemEntry = "Entry";
|
||||
|
||||
private const string ElemGenerator = "Generator";
|
||||
private const string ElemHeaderHash = "HeaderHash";
|
||||
private const string ElemDbName = "DatabaseName";
|
||||
private const string ElemDbNameChanged = "DatabaseNameChanged";
|
||||
private const string ElemDbDesc = "DatabaseDescription";
|
||||
@@ -190,9 +195,13 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
private PwDatabase m_pwDatabase; // Not null, see constructor
|
||||
|
||||
#if PCL
|
||||
private XmlWriter m_xmlWriter = null;
|
||||
#else
|
||||
private XmlTextWriter m_xmlWriter = null;
|
||||
#endif
|
||||
private CryptoRandomStream m_randomStream = null;
|
||||
private Kdb4Format m_format = Kdb4Format.Default;
|
||||
private KdbxFormat m_format = KdbxFormat.Default;
|
||||
private IStatusLogger m_slLogger = null;
|
||||
|
||||
private byte[] m_pbMasterSeed = null;
|
||||
@@ -208,6 +217,7 @@ namespace ModernKeePassLib.Serialization
|
||||
private Dictionary<string, ProtectedBinary> m_dictBinPool =
|
||||
new Dictionary<string, ProtectedBinary>();
|
||||
|
||||
private byte[] m_pbHashOfHeader = null;
|
||||
private byte[] m_pbHashOfFileOnDisk = null;
|
||||
|
||||
private readonly DateTime m_dtNow = DateTime.Now; // Cache current time
|
||||
@@ -217,7 +227,7 @@ namespace ModernKeePassLib.Serialization
|
||||
private const uint NeutralLanguageID = NeutralLanguageOffset + NeutralLanguageIDSec;
|
||||
private static bool m_bLocalizedNames = false;
|
||||
|
||||
private enum Kdb4HeaderFieldID : byte
|
||||
private enum KdbxHeaderFieldID : byte
|
||||
{
|
||||
EndOfHeader = 0,
|
||||
Comment = 1,
|
||||
@@ -261,7 +271,7 @@ namespace ModernKeePassLib.Serialization
|
||||
/// </summary>
|
||||
/// <param name="pwDataStore">The <c>PwDatabase</c> instance that the
|
||||
/// class will load file data into or use to create a KDBX file.</param>
|
||||
public Kdb4File(PwDatabase pwDataStore)
|
||||
public KdbxFile(PwDatabase pwDataStore)
|
||||
{
|
||||
Debug.Assert(pwDataStore != null);
|
||||
if(pwDataStore == null) throw new ArgumentNullException("pwDataStore");
|
||||
@@ -322,7 +332,8 @@ namespace ModernKeePassLib.Serialization
|
||||
|
||||
if(BinPoolFind(pb) != null) return; // Exists already
|
||||
|
||||
m_dictBinPool.Add(m_dictBinPool.Count.ToString(), pb);
|
||||
m_dictBinPool.Add(m_dictBinPool.Count.ToString(
|
||||
NumberFormatInfo.InvariantInfo), pb);
|
||||
}
|
||||
|
||||
private string BinPoolFind(ProtectedBinary pb)
|
||||
@@ -350,12 +361,6 @@ namespace ModernKeePassLib.Serialization
|
||||
private static void SaveBinary(string strName, ProtectedBinary pb,
|
||||
string strSaveDir)
|
||||
{
|
||||
// TODO Bert: Needs to be implemented.
|
||||
#if !TODO
|
||||
Debug.Assert(false,"not implemented");
|
||||
#else
|
||||
|
||||
|
||||
if(pb == null) { Debug.Assert(false); return; }
|
||||
|
||||
if(string.IsNullOrEmpty(strName)) strName = "File.bin";
|
||||
@@ -370,15 +375,28 @@ namespace ModernKeePassLib.Serialization
|
||||
string strDesc = UrlUtil.StripExtension(strName);
|
||||
|
||||
strPath += strDesc;
|
||||
if(iTry > 1) strPath += " (" + iTry.ToString() + ")";
|
||||
if(iTry > 1)
|
||||
strPath += " (" + iTry.ToString(NumberFormatInfo.InvariantInfo) +
|
||||
")";
|
||||
|
||||
if(!string.IsNullOrEmpty(strExt)) strPath += "." + strExt;
|
||||
|
||||
++iTry;
|
||||
}
|
||||
#if PCL
|
||||
while(ApplicationData.Current.RoamingFolder.GetFileAsync(strPath).GetResults() != null);
|
||||
#else
|
||||
while(File.Exists(strPath));
|
||||
#endif
|
||||
|
||||
#if !KeePassLibSD
|
||||
#if PCL
|
||||
byte[] pbData = pb.ReadData();
|
||||
var file = ApplicationData.Current.RoamingFolder.GetFileAsync(strPath).GetResults();
|
||||
using (var stream = file.OpenAsync(FileAccessMode.ReadWrite).GetResults().AsStream()) {
|
||||
stream.Write (pbData, 0, pbData.Length);
|
||||
}
|
||||
MemUtil.ZeroByteArray(pbData);
|
||||
#elif !KeePassLibSD
|
||||
byte[] pbData = pb.ReadData();
|
||||
File.WriteAllBytes(strPath, pbData);
|
||||
MemUtil.ZeroByteArray(pbData);
|
||||
@@ -389,9 +407,6 @@ namespace ModernKeePassLib.Serialization
|
||||
fs.Write(pbData, 0, pbData.Length);
|
||||
fs.Close();
|
||||
#endif
|
||||
|
||||
#endif // TODO
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
@@ -41,17 +41,13 @@ namespace ModernKeePassLib.Serialization
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(false, "not yet implemented");
|
||||
return null;
|
||||
#if TODO
|
||||
string str = KLRes.OldFormat + ((m_strFormat.Length > 0) ?
|
||||
(@" (" + m_strFormat + @")") : string.Empty) + ".";
|
||||
|
||||
if(m_type == OldFormatType.KeePass1x)
|
||||
str += MessageService.NewParagraph + KLRes.KeePass1xHint;
|
||||
str += Environment.NewLine + Environment.NewLine + KLRes.KeePass1xHint;
|
||||
|
||||
return str;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user