Ejemplo n.º 1
0
        public static PwEntry DuplicateTo(this PwEntry entry, PwGroup parent)
        {
            PwEntry copy = new PwEntry(false, false);

            copy.Uuid = entry.Uuid;
            copy.AssignProperties(entry, false, false, true);
            //TODO MST: clear this comment and it's ramifications!
            //HACK: CloneDeep introduces the copy into the parent node, therefore SetParent triggers a change of the parent
            //      which shouldn't be - the extended ProtectionSection in KeeShare should prevent interference, but a
            //      a clean way to clone a node without cloning children and without hooking it into a tree would be nice
            copy.SetParent(parent);
            return(copy);
        }
Ejemplo n.º 2
0
            public override void Run()
            {
                if (Success)
                {
                    // Mark parent group dirty. Even only the last modification date changed, this might affect sort order
                    PwGroup parent = _updatedEntry.ParentGroup;
                    if (parent != null)
                    {
                        // Mark parent group dirty
                        _app.GetDb().Dirty.Add(parent);
                    }
                }
                else
                {
                    StatusLogger.UpdateMessage(UiStringKey.UndoingChanges);
                    // If we fail to save, back out changes to global structure
                    //TODO test fail
                    _updatedEntry.AssignProperties(_backup, false, true, false);
                }

                base.Run();
            }
Ejemplo n.º 3
0
        /// <summary>
        /// Synchronize the current database with another one.
        /// </summary>
        /// <param name="pwSource">Input database to synchronize with. This input
        /// database is used to update the current one, but is not modified! You
        /// must copy the current object if you want a second instance of the
        /// synchronized database. The input database must not be seen as valid
        /// database any more after calling <c>Synchronize</c>.</param>
        /// <param name="mm">Merge method.</param>
        public void MergeIn(PwDatabase pwSource, PwMergeMethod mm)
        {
            if(mm == PwMergeMethod.CreateNewUuids)
            {
                pwSource.RootGroup.CreateNewItemUuids(true, true, true);
            }

            GroupHandler gh = delegate(PwGroup pg)
            {
                if(pg == pwSource.m_pgRootGroup) return true;

                PwGroup pgLocal = m_pgRootGroup.FindGroup(pg.Uuid, true);
                if(pgLocal == null)
                {
                    PwGroup pgSourceParent = pg.ParentGroup;
                    PwGroup pgLocalContainer;
                    if(pgSourceParent == pwSource.m_pgRootGroup)
                        pgLocalContainer = m_pgRootGroup;
                    else
                        pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true);
                    Debug.Assert(pgLocalContainer != null);

                    PwGroup pgNew = new PwGroup();
                    pgNew.Uuid = pg.Uuid;
                    pgNew.AssignProperties(pg, false);
                    pgLocalContainer.AddGroup(pgNew, true);
                }
                else // pgLocal != null
                {
                    Debug.Assert(mm != PwMergeMethod.CreateNewUuids);

                    if(mm == PwMergeMethod.OverwriteExisting)
                        pgLocal.AssignProperties(pg, false);
                    else if((mm == PwMergeMethod.OverwriteIfNewer) ||
                        (mm == PwMergeMethod.Synchronize))
                    {
                        pgLocal.AssignProperties(pg, true);
                    }
                    // else if(mm == PwMergeMethod.KeepExisting) ...
                }

                return true;
            };

            EntryHandler eh = delegate(PwEntry pe)
            {
                PwEntry peLocal = m_pgRootGroup.FindEntry(pe.Uuid, true);
                if(peLocal == null)
                {
                    PwGroup pgSourceParent = pe.ParentGroup;
                    PwGroup pgLocalContainer;
                    if(pgSourceParent == pwSource.m_pgRootGroup)
                        pgLocalContainer = m_pgRootGroup;
                    else
                        pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true);
                    Debug.Assert(pgLocalContainer != null);

                    PwEntry peNew = new PwEntry(false, false);
                    peNew.Uuid = pe.Uuid;
                    peNew.AssignProperties(pe, false, true);
                    pgLocalContainer.AddEntry(peNew, true);
                }
                else // peLocal == null
                {
                    Debug.Assert(mm != PwMergeMethod.CreateNewUuids);

                    if(mm == PwMergeMethod.OverwriteExisting)
                        peLocal.AssignProperties(pe, false, true);
                    else if((mm == PwMergeMethod.OverwriteIfNewer) ||
                        (mm == PwMergeMethod.Synchronize))
                    {
                        peLocal.AssignProperties(pe, true, true);
                    }
                    // else if(mm == PwMergeMethod.KeepExisting) ...
                }

                return true;
            };

            if(!pwSource.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh))
                throw new InvalidOperationException();

            if(mm == PwMergeMethod.Synchronize)
            {
                ApplyDeletions(pwSource.m_vDeletedObjects, true);
                ApplyDeletions(m_vDeletedObjects, false);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Exports all entries with the given tag to a new database at the given path.
        /// </summary>
        /// <param name="sourceDb">The source database.</param>
        /// <param name="settings">The settings for this job.</param>
        private static void CopyToNewDb(PwDatabase sourceDb, Settings settings)
        {
            // Create a key for the target database
            CompositeKey key = new CompositeKey();

            bool hasPassword = false;
            bool hasKeyFile  = false;

            if (!settings.Password.IsEmpty)
            {
                byte[] passwordByteArray = settings.Password.ReadUtf8();
                key.AddUserKey(new KcpPassword(passwordByteArray));
                MemUtil.ZeroByteArray(passwordByteArray);
                hasPassword = true;
            }

            // Load a keyfile for the target database if requested (and add it to the key)
            if (!string.IsNullOrEmpty(settings.KeyFilePath))
            {
                bool bIsKeyProv = Program.KeyProviderPool.IsKeyProvider(settings.KeyFilePath);

                if (!bIsKeyProv)
                {
                    try
                    {
                        key.AddUserKey(new KcpKeyFile(settings.KeyFilePath, true));
                        hasKeyFile = true;
                    }
                    catch (InvalidDataException exId)
                    {
                        MessageService.ShowWarning(settings.KeyFilePath, exId);
                    }
                    catch (Exception exKf)
                    {
                        MessageService.ShowWarning(settings.KeyFilePath, KPRes.KeyFileError, exKf);
                    }
                }
                else
                {
                    KeyProviderQueryContext ctxKp = new KeyProviderQueryContext(
                        ConnectionInfo, true, false);

                    KeyProvider prov         = Program.KeyProviderPool.Get(settings.KeyFilePath);
                    bool        bPerformHash = !prov.DirectKey;
                    byte[]      pbCustomKey  = prov.GetKey(ctxKp);

                    if ((pbCustomKey != null) && (pbCustomKey.Length > 0))
                    {
                        try
                        {
                            key.AddUserKey(new KcpCustomKey(settings.KeyFilePath, pbCustomKey, bPerformHash));
                            hasKeyFile = true;
                        }
                        catch (Exception exCkp)
                        {
                            MessageService.ShowWarning(exCkp);
                        }

                        MemUtil.ZeroByteArray(pbCustomKey);
                    }
                }
            }

            // Check if at least a password or a keyfile have been added to the key object
            if (!hasPassword && !hasKeyFile)
            {
                // Fail if not
                throw new InvalidOperationException("For the target database at least a password or a keyfile is required.");
            }

            // Create a new database
            PwDatabase targetDatabase = new PwDatabase();

            // Apply the created key to the new database
            targetDatabase.New(new IOConnectionInfo(), key);

            // Copy database settings
            targetDatabase.Color                  = sourceDb.Color;
            targetDatabase.Compression            = sourceDb.Compression;
            targetDatabase.DataCipherUuid         = sourceDb.DataCipherUuid;
            targetDatabase.DefaultUserName        = sourceDb.DefaultUserName;
            targetDatabase.Description            = sourceDb.Description;
            targetDatabase.HistoryMaxItems        = sourceDb.HistoryMaxItems;
            targetDatabase.HistoryMaxSize         = sourceDb.HistoryMaxSize;
            targetDatabase.MaintenanceHistoryDays = sourceDb.MaintenanceHistoryDays;
            targetDatabase.MasterKeyChangeForce   = sourceDb.MasterKeyChangeForce;
            targetDatabase.MasterKeyChangeRec     = sourceDb.MasterKeyChangeRec;
            targetDatabase.Name = sourceDb.Name;
            targetDatabase.RecycleBinEnabled = sourceDb.RecycleBinEnabled;

            if (settings.KeyTransformationRounds == 0)
            {
                // keyTransformationRounds was not set -> use the one from the source database
                settings.KeyTransformationRounds = sourceDb.KdfParameters.GetUInt64(AesKdf.ParamRounds, 0);
            }

            // Set keyTransformationRounds (min PwDefs.DefaultKeyEncryptionRounds)
            targetDatabase.KdfParameters.SetUInt64(AesKdf.ParamRounds, Math.Max(PwDefs.DefaultKeyEncryptionRounds, settings.KeyTransformationRounds));

            // Assign the properties of the source root group to the target root group
            targetDatabase.RootGroup.AssignProperties(sourceDb.RootGroup, false, true);
            HandleCustomIcon(targetDatabase, sourceDb, sourceDb.RootGroup);

            // Overwrite the root group name if requested
            if (!string.IsNullOrEmpty(settings.RootGroupName))
            {
                targetDatabase.RootGroup.Name = settings.RootGroupName;
            }

            // Find all entries matching the tag
            PwObjectList <PwEntry> entries = new PwObjectList <PwEntry>();

            if (!string.IsNullOrEmpty(settings.Tag) && string.IsNullOrEmpty(settings.Group))
            {
                // Tag only export
                sourceDb.RootGroup.FindEntriesByTag(settings.Tag, entries, true);
            }
            else if (string.IsNullOrEmpty(settings.Tag) && !string.IsNullOrEmpty(settings.Group))
            {
                // Tag and group export
                PwGroup groupToExport = sourceDb.RootGroup.GetFlatGroupList().FirstOrDefault(g => g.Name == settings.Group);

                if (groupToExport == null)
                {
                    throw new ArgumentException("No group with the name of the Group-Setting found.");
                }

                entries = groupToExport.GetEntries(true);
            }
            else if (!string.IsNullOrEmpty(settings.Tag) && !string.IsNullOrEmpty(settings.Group))
            {
                // Tag and group export
                PwGroup groupToExport = sourceDb.RootGroup.GetFlatGroupList().FirstOrDefault(g => g.Name == settings.Group);

                if (groupToExport == null)
                {
                    throw new ArgumentException("No group with the name of the Group-Setting found.");
                }

                groupToExport.FindEntriesByTag(settings.Tag, entries, true);
            }
            else
            {
                throw new ArgumentException("At least one of Tag or ExportFolderName must be set.");
            }


            // Copy all entries to the new database
            foreach (PwEntry entry in entries)
            {
                // Get or create the target group in the target database (including hierarchy)
                PwGroup targetGroup = CreateTargetGroupInDatebase(entry, targetDatabase, sourceDb);

                // Clone entry
                PwEntry peNew = new PwEntry(false, false);
                peNew.Uuid = entry.Uuid;
                peNew.AssignProperties(entry, false, true, true);

                // Handle custom icon
                HandleCustomIcon(targetDatabase, sourceDb, entry);

                // Add entry to the target group in the new database
                targetGroup.AddEntry(peNew, true);
            }

            // Create target folder (if not exist)
            string targetFolder = Path.GetDirectoryName(settings.TargetFilePath);

            if (targetFolder == null)
            {
                throw new ArgumentException("Can't get target folder.");
            }
            Directory.CreateDirectory(targetFolder);

            // Save the new database under the target path
            KdbxFile kdbx = new KdbxFile(targetDatabase);

            using (FileStream outputStream = new FileStream(settings.TargetFilePath, FileMode.Create))
            {
                kdbx.Save(outputStream, null, KdbxFormat.Default, new NullStatusLogger());
            }
        }