public static bool IsLibraryInstalled(out Exception ex) { try { KdbManager mgr = new KdbManager(); mgr.Dispose(); } catch(Exception exMgr) { ex = exMgr; return false; } ex = null; return true; }
private static KdbErrorCode SetDatabaseKey(KdbManager mgr, CompositeKey pwKey) { KdbErrorCode e; bool bPassword = pwKey.ContainsType(typeof(KcpPassword)); bool bKeyFile = pwKey.ContainsType(typeof(KcpKeyFile)); string strPassword = (bPassword ? (pwKey.GetUserKey( typeof(KcpPassword)) as KcpPassword).Password.ReadString() : string.Empty); string strKeyFile = (bKeyFile ? (pwKey.GetUserKey( typeof(KcpKeyFile)) as KcpKeyFile).Path : string.Empty); if(bPassword && bKeyFile) e = mgr.SetMasterKey(strKeyFile, true, strPassword, IntPtr.Zero, false); else if(bPassword && !bKeyFile) e = mgr.SetMasterKey(strPassword, false, null, IntPtr.Zero, false); else if(!bPassword && bKeyFile) e = mgr.SetMasterKey(strKeyFile, true, null, IntPtr.Zero, false); else if(pwKey.ContainsType(typeof(KcpUserAccount))) throw new Exception(KPRes.KdbWUA); else throw new Exception(KLRes.InvalidCompositeKey); return e; }
private void WriteEntries(KdbManager mgr, Dictionary<PwGroup, uint> dictGroups, PwGroup pgRoot) { bool bWarnedOnce = false; uint uGroupCount, uEntryCount, uEntriesSaved = 0; pgRoot.GetCounts(true, out uGroupCount, out uEntryCount); DateTime dtNeverExpire = KdbManager.GetNeverExpireTime(); EntryHandler eh = delegate(PwEntry pe) { KdbEntry e = new KdbEntry(); e.Uuid.Set(pe.Uuid.UuidBytes); if(pe.ParentGroup != pgRoot) e.GroupId = dictGroups[pe.ParentGroup]; else { e.GroupId = 1; if((m_slLogger != null) && !bWarnedOnce) { m_slLogger.SetText(KdbPrefix + KPRes.FormatNoRootEntries, LogStatusType.Warning); bWarnedOnce = true; } if(dictGroups.Count == 0) throw new Exception(KPRes.FormatNoSubGroupsInRoot); } e.ImageId = (uint)pe.IconId; e.Title = pe.Strings.ReadSafe(PwDefs.TitleField); e.UserName = pe.Strings.ReadSafe(PwDefs.UserNameField); e.Password = pe.Strings.ReadSafe(PwDefs.PasswordField); e.Url = pe.Strings.ReadSafe(PwDefs.UrlField); string strNotes = pe.Strings.ReadSafe(PwDefs.NotesField); ExportCustomStrings(pe, ref strNotes); ExportAutoType(pe, ref strNotes); ExportUrlOverride(pe, ref strNotes); e.Additional = strNotes; e.PasswordLength = (uint)e.Password.Length; Debug.Assert(TimeUtil.PwTimeLength == 7); e.CreationTime.Set(pe.CreationTime); e.LastModificationTime.Set(pe.LastModificationTime); e.LastAccessTime.Set(pe.LastAccessTime); if(pe.Expires) e.ExpirationTime.Set(pe.ExpiryTime); else e.ExpirationTime.Set(dtNeverExpire); IntPtr hBinaryData = IntPtr.Zero; if(pe.Binaries.UCount >= 1) { foreach(KeyValuePair<string, ProtectedBinary> kvp in pe.Binaries) { e.BinaryDescription = kvp.Key; byte[] pbAttached = kvp.Value.ReadData(); e.BinaryDataLength = (uint)pbAttached.Length; if(e.BinaryDataLength > 0) { hBinaryData = Marshal.AllocHGlobal((int)e.BinaryDataLength); Marshal.Copy(pbAttached, 0, hBinaryData, (int)e.BinaryDataLength); e.BinaryData = hBinaryData; } break; } if((pe.Binaries.UCount > 1) && (m_slLogger != null)) m_slLogger.SetText(KdbPrefix + KPRes.FormatOnlyOneAttachment + "\r\n\r\n" + KPRes.Entry + ":\r\n" + KPRes.Title + ": " + e.Title + "\r\n" + KPRes.UserName + ": " + e.UserName, LogStatusType.Warning); } bool bResult = mgr.AddEntry(ref e); Marshal.FreeHGlobal(hBinaryData); hBinaryData = IntPtr.Zero; if(!bResult) { Debug.Assert(false); throw new InvalidOperationException(); } ++uEntriesSaved; if(m_slLogger != null) if(!m_slLogger.SetProgress((100 * uEntriesSaved) / uEntryCount)) return false; return true; }; if(!pgRoot.TraverseTree(TraversalMethod.PreOrder, null, eh)) throw new InvalidOperationException(); }
private static void WriteGroup(PwGroup pg, PwGroup pgRoot, ref uint uGroupIndex, Dictionary<PwGroup, UInt32> dictGroups, DateTime dtNeverExpire, KdbManager mgr, bool bForceLevel0) { if(pg == pgRoot) return; KdbGroup grp = new KdbGroup(); grp.GroupId = uGroupIndex; dictGroups[pg] = grp.GroupId; grp.ImageId = (uint)pg.IconId; grp.Name = pg.Name; grp.CreationTime.Set(pg.CreationTime); grp.LastModificationTime.Set(pg.LastModificationTime); grp.LastAccessTime.Set(pg.LastAccessTime); if(pg.Expires) grp.ExpirationTime.Set(pg.ExpiryTime); else grp.ExpirationTime.Set(dtNeverExpire); grp.Level = (bForceLevel0 ? (ushort)0 : (ushort)(pg.GetLevel() - 1)); if(pg.IsExpanded) grp.Flags |= (uint)KdbGroupFlags.Expanded; if(!mgr.AddGroup(ref grp)) { Debug.Assert(false); throw new InvalidOperationException(); } ++uGroupIndex; }
private static void EnsureParentGroupsExported(PwGroup pgRoot, ref uint uGroupIndex, Dictionary<PwGroup, UInt32> dictGroups, DateTime dtNeverExpires, KdbManager mgr) { bool bHasAtLeastOneGroup = (dictGroups.Count > 0); uint uLocalIndex = uGroupIndex; // Local copy, can't use ref in delegate EntryHandler eh = delegate(PwEntry pe) { PwGroup pg = pe.ParentGroup; if(pg == null) { Debug.Assert(false); return true; } if(bHasAtLeastOneGroup && (pg == pgRoot)) return true; if(dictGroups.ContainsKey(pg)) return true; WriteGroup(pg, pgRoot, ref uLocalIndex, dictGroups, dtNeverExpires, mgr, true); return true; }; pgRoot.TraverseTree(TraversalMethod.PreOrder, null, eh); uGroupIndex = uLocalIndex; }
private static Dictionary<PwGroup, UInt32> WriteGroups(KdbManager mgr, PwGroup pgRoot) { Dictionary<PwGroup, UInt32> dictGroups = new Dictionary<PwGroup, uint>(); uint uGroupIndex = 1; DateTime dtNeverExpire = KdbManager.GetNeverExpireTime(); GroupHandler gh = delegate(PwGroup pg) { WriteGroup(pg, pgRoot, ref uGroupIndex, dictGroups, dtNeverExpire, mgr, false); return true; }; pgRoot.TraverseTree(TraversalMethod.PreOrder, gh, null); Debug.Assert(dictGroups.Count == (int)(uGroupIndex - 1)); EnsureParentGroupsExported(pgRoot, ref uGroupIndex, dictGroups, dtNeverExpire, mgr); return dictGroups; }
/// <summary> /// Save the contents of the current <c>PwDatabase</c> to a KDB file. /// </summary> /// <param name="strSaveToFile">Location to save the KDB file to.</param> public void Save(string strSaveToFile, PwGroup pgDataSource) { Debug.Assert(strSaveToFile != null); if(strSaveToFile == null) throw new ArgumentNullException("strSaveToFile"); using(KdbManager mgr = new KdbManager()) { KdbErrorCode e = KdbFile.SetDatabaseKey(mgr, m_pwDatabase.MasterKey); if(e != KdbErrorCode.Success) { Debug.Assert(false); throw new Exception(KLRes.InvalidCompositeKey); } if(m_slLogger != null) { if(m_pwDatabase.MasterKey.ContainsType(typeof(KcpUserAccount))) m_slLogger.SetText(KPRes.KdbWUA, LogStatusType.Warning); if(m_pwDatabase.Name.Length != 0) m_slLogger.SetText(KdbPrefix + KPRes.FormatNoDatabaseName, LogStatusType.Warning); if(m_pwDatabase.Description.Length != 0) m_slLogger.SetText(KdbPrefix + KPRes.FormatNoDatabaseDesc, LogStatusType.Warning); } // Set properties if(m_pwDatabase.KeyEncryptionRounds >= (ulong)UInt32.MaxValue) mgr.KeyTransformationRounds = 0xFFFFFFFEU; else mgr.KeyTransformationRounds = (uint)m_pwDatabase.KeyEncryptionRounds; PwGroup pgRoot = (pgDataSource ?? m_pwDatabase.RootGroup); // Write groups and entries Dictionary<PwGroup, UInt32> dictGroups = WriteGroups(mgr, pgRoot); WriteEntries(mgr, dictGroups, pgRoot); e = mgr.SaveDatabase(strSaveToFile); if(e != KdbErrorCode.Success) throw new Exception(KLRes.FileSaveFailed); } }
private void ReadEntries(KdbManager mgr, Dictionary<UInt32, PwGroup> dictGroups) { DateTime dtNeverExpire = KdbManager.GetNeverExpireTime(); uint uEntryCount = mgr.EntryCount; for(uint uEntry = 0; uEntry < uEntryCount; ++uEntry) { KdbEntry e = mgr.GetEntry(uEntry); PwGroup pgContainer; if(!dictGroups.TryGetValue(e.GroupId, out pgContainer)) { Debug.Assert(false); continue; } PwEntry pe = new PwEntry(false, false); pe.SetUuid(new PwUuid(e.Uuid.ToByteArray()), false); pgContainer.AddEntry(pe, true, true); pe.IconId = (e.ImageId < (uint)PwIcon.Count) ? (PwIcon)e.ImageId : PwIcon.Key; pe.Strings.Set(PwDefs.TitleField, new ProtectedString( m_pwDatabase.MemoryProtection.ProtectTitle, e.Title)); pe.Strings.Set(PwDefs.UserNameField, new ProtectedString( m_pwDatabase.MemoryProtection.ProtectUserName, e.UserName)); pe.Strings.Set(PwDefs.PasswordField, new ProtectedString( m_pwDatabase.MemoryProtection.ProtectPassword, e.Password)); pe.Strings.Set(PwDefs.UrlField, new ProtectedString( m_pwDatabase.MemoryProtection.ProtectUrl, e.Url)); string strNotes = e.Additional; ImportAutoType(ref strNotes, pe); ImportUrlOverride(ref strNotes, pe); pe.Strings.Set(PwDefs.NotesField, new ProtectedString( m_pwDatabase.MemoryProtection.ProtectNotes, strNotes)); pe.CreationTime = e.CreationTime.ToDateTime(); pe.LastModificationTime = e.LastModificationTime.ToDateTime(); pe.LastAccessTime = e.LastAccessTime.ToDateTime(); pe.ExpiryTime = e.ExpirationTime.ToDateTime(); pe.Expires = (pe.ExpiryTime != dtNeverExpire); if((e.BinaryDataLength > 0) && (e.BinaryData != IntPtr.Zero)) { byte[] pbData = KdbManager.ReadBinary(e.BinaryData, e.BinaryDataLength); Debug.Assert(pbData.Length == e.BinaryDataLength); string strDesc = e.BinaryDescription; if(string.IsNullOrEmpty(strDesc)) strDesc = "Attachment"; pe.Binaries.Set(strDesc, new ProtectedBinary(false, pbData)); } if(m_slLogger != null) { if(!m_slLogger.SetProgress((100 * uEntry) / uEntryCount)) throw new Exception(KPRes.Cancel); } } }
private Dictionary<UInt32, PwGroup> ReadGroups(KdbManager mgr) { uint uGroupCount = mgr.GroupCount; Dictionary<UInt32, PwGroup> dictGroups = new Dictionary<uint, PwGroup>(); Stack<PwGroup> vGroupStack = new Stack<PwGroup>(); vGroupStack.Push(m_pwDatabase.RootGroup); DateTime dtNeverExpire = KdbManager.GetNeverExpireTime(); for(uint uGroup = 0; uGroup < uGroupCount; ++uGroup) { KdbGroup g = mgr.GetGroup(uGroup); PwGroup pg = new PwGroup(true, false); pg.Name = g.Name; pg.IconId = (g.ImageId < (uint)PwIcon.Count) ? (PwIcon)g.ImageId : PwIcon.Folder; pg.CreationTime = g.CreationTime.ToDateTime(); pg.LastModificationTime = g.LastModificationTime.ToDateTime(); pg.LastAccessTime = g.LastAccessTime.ToDateTime(); pg.ExpiryTime = g.ExpirationTime.ToDateTime(); pg.Expires = (pg.ExpiryTime != dtNeverExpire); pg.IsExpanded = ((g.Flags & (uint)KdbGroupFlags.Expanded) != 0); while(g.Level < (vGroupStack.Count - 1)) vGroupStack.Pop(); vGroupStack.Peek().AddGroup(pg, true); dictGroups[g.GroupId] = pg; if(g.Level == (uint)(vGroupStack.Count - 1)) vGroupStack.Push(pg); } return dictGroups; }
/// <summary> /// Loads a KDB file and stores all loaded entries in the current /// PwDatabase instance. /// </summary> /// <param name="strFilePath">Relative or absolute path to the file to open.</param> public void Load(string strFilePath) { Debug.Assert(strFilePath != null); if(strFilePath == null) throw new ArgumentNullException("strFilePath"); using(KdbManager mgr = new KdbManager()) { KdbErrorCode e; e = KdbFile.SetDatabaseKey(mgr, m_pwDatabase.MasterKey); if(e != KdbErrorCode.Success) throw new Exception(KLRes.InvalidCompositeKey); e = mgr.OpenDatabase(strFilePath, IntPtr.Zero); if(e != KdbErrorCode.Success) throw new Exception(KLRes.FileLoadFailed); // Copy properties m_pwDatabase.KeyEncryptionRounds = mgr.KeyTransformationRounds; // Read groups and entries Dictionary<UInt32, PwGroup> dictGroups = ReadGroups(mgr); ReadEntries(mgr, dictGroups); } }