Пример #1
0
        private void setPwEntryFromEntry(PwEntry pwe, Entry login)
        {
            bool firstPasswordFound = false;

            foreach (FormField kpff in login.FormFieldList)
            {
                if (kpff.Type == FormFieldType.FFTpassword && !firstPasswordFound)
                {
                    pwe.Strings.Set("Password", new ProtectedString(host.Database.MemoryProtection.ProtectPassword, kpff.Value));
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "password"));
                    firstPasswordFound = true;
                }
                else if (kpff.Type == FormFieldType.FFTpassword)
                {
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " value", new ProtectedString(host.Database.MemoryProtection.ProtectPassword, kpff.Value)); // we protect this string if user has asked to protect passwords
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "password"));
                }
                else if (kpff.Type == FormFieldType.FFTusername)
                {
                    pwe.Strings.Set("UserName", new ProtectedString(host.Database.MemoryProtection.ProtectUserName, kpff.Value));
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "username"));
                }
                else if (kpff.Type == FormFieldType.FFTtext)
                {
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " value", new ProtectedString(false, kpff.Value));
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "text"));
                }
                else if (kpff.Type == FormFieldType.FFTcheckbox)
                {
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " value", new ProtectedString(false, kpff.Value));
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "checkbox"));
                }
                else if (kpff.Type == FormFieldType.FFTradio)
                {
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " value", new ProtectedString(false, kpff.Value));
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "radio"));
                }
                else if (kpff.Type == FormFieldType.FFTselect)
                {
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " value", new ProtectedString(false, kpff.Value));
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " type", new ProtectedString(false, "select"));
                }

                pwe.Strings.Set("KPRPC Form field " + kpff.Name + " page", new ProtectedString(false, kpff.Page.ToString()));

                if (kpff.Id != null && kpff.Id.Length > 0)
                    pwe.Strings.Set("KPRPC Form field " + kpff.Name + " id", new ProtectedString(false, kpff.Id));
            }

            string altURLs = "";

            for (int i = 0; i < login.URLs.Length; i++)
            {
                string url = login.URLs[i];
                if (i == 0)
                    pwe.Strings.Set("URL", new ProtectedString(host.Database.MemoryProtection.ProtectUrl, url ?? ""));
                else if (i == 1)
                    altURLs += url;
                else
                    altURLs += " " + url;
            }
            if (altURLs.Length > 0)
                pwe.Strings.Set("KPRPC Alternative URLs", new ProtectedString(host.Database.MemoryProtection.ProtectUrl, altURLs));

            pwe.Strings.Set("Form match URL", new ProtectedString(host.Database.MemoryProtection.ProtectUrl, login.FormActionURL ?? ""));
            pwe.Strings.Set("KPRPC HTTP realm", new ProtectedString(host.Database.MemoryProtection.ProtectUrl, login.HTTPRealm ?? ""));

            // Set some of the string fields
            pwe.Strings.Set(PwDefs.TitleField, new ProtectedString(host.Database.MemoryProtection.ProtectTitle, login.Title ?? ""));

            // update the icon for this entry (in most cases we'll
            // just detect that it is the same standard icon as before)
            PwUuid customIconUUID = PwUuid.Zero;
            PwIcon iconId = PwIcon.Key;
            if (login.IconImageData != null
                && login.IconImageData.Length > 0
                && base64ToIcon(login.IconImageData, ref customIconUUID, ref iconId))
            {
                if (customIconUUID == PwUuid.Zero)
                    pwe.IconId = iconId;
                else
                    pwe.CustomIconUuid = customIconUUID;
            }
        }
Пример #2
0
        public Entry[] FindLogins(string[] URLs, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches, string uniqueID, string dbFileName, string freeTextSearch)
        {
            List<PwDatabase> dbs = null;
            int count = 0;
            List<Entry> allEntries = new List<Entry>();

            if (!string.IsNullOrEmpty(dbFileName))
            {
                // find the database
                PwDatabase db = SelectDatabase(dbFileName);
                dbs = new List<PwDatabase>();
                dbs.Add(db);
            } else
                // if DB list is not populated, look in all open DBs
                dbs = host.MainWindow.DocumentManager.GetOpenDatabases();

            //string hostname = URLs[0];
            string actionHost = actionURL;

            // Make sure there is an active database
            if (!ensureDBisOpen()) { return null; }

            // if uniqueID is supplied, match just that one login. if not found, move on to search the content of the logins...
            if (uniqueID != null && uniqueID.Length > 0)
            {
                PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(uniqueID));

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    PwEntry matchedLogin = GetRootPwGroup(db).FindEntry(pwuuid, true);

                    if (matchedLogin == null)
                        continue;

                    Entry[] logins = new Entry[1];
                    logins[0] = (Entry)GetEntryFromPwEntry(matchedLogin, true, true, db);
                    if (logins[0] != null)
                        return logins;
                }
            }

            if (!string.IsNullOrEmpty(freeTextSearch))
            {
                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    //output = searchGroup.GetEntries(true);
                    SearchParameters sp = new SearchParameters();
                    sp.ComparisonMode = StringComparison.InvariantCultureIgnoreCase;
                    sp.SearchString = freeTextSearch;
                    sp.SearchInUserNames = true;
                    sp.SearchInTitles = true;
                    sp.SearchInTags = true;
                    searchGroup.SearchEntries(sp, output, false);

                    foreach (PwEntry pwe in output)
                    {
                        Entry kpe = (Entry)GetEntryFromPwEntry(pwe, true, true, db);
                        allEntries.Add(kpe);
                        count++;
                    }
                }

            }
            // else we search for the URLs

            if (count == 0 && URLs.Length > 0 && !string.IsNullOrEmpty(URLs[0]))
            {
                int protocolIndex = -1;
                Dictionary<string, string> URLHostnames = new Dictionary<string, string>();

                // make sure that hostname and actionURL always represent only the hostname portion
                // of the URL
                // It's tempting to demand that the protocol must match too (e.g. http forms won't
                // match a stored https login) but best not to define such a restriction in KeePassRPC
                // - the RPC client (e.g. KeeFox) can decide to penalise protocol mismatches,
                // potentially dependant on user configuration options in the client.
                for (int i = 0; i < URLs.Length; i++)
                {
                    string URL = URLs[i];
                    string newURL = URL;
                    protocolIndex = URL.IndexOf("://");
                    string hostAndPort = "";
                    if (URL.IndexOf("file://") > -1)
                    {
                        // the "host and port" of a file is the actual file name (i.e. just not the query string)

                        int qsIndex = URL.IndexOf("?");
                        if (qsIndex > -1)
                            newURL = URL.Substring(8, qsIndex - 8);
                        else
                            newURL = URL.Substring(8);
                    }
                    else if (protocolIndex > -1)
                    {
                        string URLExcludingProt = URL.Substring(protocolIndex + 3);
                        int pathStart = URLExcludingProt.IndexOf("/", 0);

                        if (pathStart > -1 && URLExcludingProt.Length > pathStart)
                        {
                            hostAndPort = URL.Substring(protocolIndex + 3, pathStart);
                            newURL = URL.Substring(0, pathStart + protocolIndex + 3);
                        }
                        else if (pathStart == -1) // it's already just a hostname
                        {
                            hostAndPort = URLExcludingProt;
                        }
                    }
                    else
                    {
                        // we havn't received a protocol but may still have a query string
                        // we'd like to remove from the URL (e.g. especially if we're dealing with an unknown file:///)
                        int qsIndex = URL.IndexOf("?");
                        if (qsIndex > -1)
                            newURL = URL.Substring(1, qsIndex - 1);
                    }

                    URLHostnames.Add(URLs[i], hostAndPort);
                }

                protocolIndex = (actionURL == null) ? -1 : actionURL.IndexOf("://");
                if (protocolIndex > -1)
                {
                    string actionURLAndPort = actionURL.Substring(protocolIndex + 3);
                    int pathStart = actionURLAndPort.IndexOf("/", 0);
                    if (pathStart > -1 && actionURLAndPort.Length > pathStart)
                    {
                        actionHost = actionURL.Substring(0, pathStart + protocolIndex + 3);
                    }
                }

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    output = searchGroup.GetEntries(true);

                    // Search every entry in the DB
                    foreach (PwEntry pwe in output)
                    {
                        if (db.RecycleBinUuid.EqualsValue(pwe.ParentGroup.Uuid))
                            continue; // ignore if it's in the recycle bin

                        if (pwe.Strings.Exists("Hide from KeeFox") || pwe.Strings.Exists("Hide from KPRPC") || string.IsNullOrEmpty(pwe.Strings.ReadSafe("URL")))
                            continue; // entries must have a standard URL entry

                        bool allowHostnameOnlyMatch = true;
                        if (pwe.Strings.Exists("KPRPC Block hostname-only match"))
                        {
                            allowHostnameOnlyMatch = false;
                        }

                        bool entryIsAMatch = false;
                        bool entryIsAnExactMatch = false;

                        string regexPatterns = null;
                        if (pwe.Strings.Exists("KeeFox URL Regex match"))
                            regexPatterns = pwe.Strings.ReadSafe("KeeFox URL Regex match");
                        if (pwe.Strings.Exists("KPRPC URL Regex match"))
                            regexPatterns = pwe.Strings.ReadSafe("KPRPC URL Regex match");
                        if (!string.IsNullOrEmpty(regexPatterns))
                            foreach (string URL in URLs)
                                foreach (string regexPattern in regexPatterns.Split(' '))
                                {
                                    if (!string.IsNullOrEmpty(regexPattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, regexPattern))
                                    {
                                        entryIsAMatch = true;
                                        break;
                                    }
                                }

                        foreach (string URL in URLs)
                        {
                            if (!entryIsAMatch && lst != LoginSearchType.LSTnoForms && matchesAnyURL(pwe, URL, URLHostnames[URL], allowHostnameOnlyMatch))
                            {
                                if (pwe.Strings.Exists("Form match URL") && pwe.Strings.ReadSafe("Form match URL") == actionURL && pwe.Strings.ReadSafe("URL") == URL)
                                {
                                    entryIsAnExactMatch = true;
                                    entryIsAMatch = true;
                                }
                                else if (!requireFullURLMatches)
                                    entryIsAMatch = true;
                            }
                        }

                        foreach (string URL in URLs)
                        {
                            if (!entryIsAMatch && lst != LoginSearchType.LSTnoRealms && matchesAnyURL(pwe, URL, URLHostnames[URL], allowHostnameOnlyMatch))
                            {
                                if ((
                                    (pwe.Strings.Exists("Form HTTP realm")
                                    && pwe.Strings.ReadSafe("Form HTTP realm").Length > 0
                                    && (httpRealm == "" || pwe.Strings.ReadSafe("Form HTTP realm") == httpRealm)
                                    )
                                    ||
                                    (pwe.Strings.Exists("KPRPC HTTP realm")
                                    && pwe.Strings.ReadSafe("KPRPC HTTP realm").Length > 0
                                    && (httpRealm == "" || pwe.Strings.ReadSafe("KPRPC HTTP realm") == httpRealm)
                                    ))
                                    && pwe.Strings.ReadSafe("URL") == URL)
                                {
                                    entryIsAnExactMatch = true;
                                    entryIsAMatch = true;
                                }
                                else if (!requireFullURLMatches)
                                    entryIsAMatch = true;
                            }
                        }

                        foreach (string URL in URLs)
                        {
                            // If we think we found a match, check it's not on a block list
                            if (entryIsAMatch && matchesAnyBlockedURL(pwe, URL))
                            {
                                entryIsAMatch = false;
                                break;
                            }
                            if (entryIsAMatch && pwe.Strings.Exists("KPRPC URL Regex block"))
                            {
                                string patterns = pwe.Strings.ReadSafe("KPRPC URL Regex block");
                                foreach (string pattern in patterns.Split(' '))
                                {
                                    if (!string.IsNullOrEmpty(pattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, pattern))
                                    {
                                        entryIsAMatch = false;
                                        break;
                                    }
                                }
                            }
                        }

                        if (entryIsAMatch)
                        {
                            Entry kpe = (Entry)GetEntryFromPwEntry(pwe, entryIsAnExactMatch, true, db);
                            allEntries.Add(kpe);
                            count++;
                        }
                    }
                }
            }

            allEntries.Sort(delegate(Entry e1, Entry e2)
                {
                    return e1.Title.CompareTo(e2.Title);
                });

            return allEntries.ToArray();
        }
Пример #3
0
        public Entry AddLogin(Entry login, string parentUUID, string dbFileName)
        {
            // Make sure there is an active database
            if (!ensureDBisOpen()) return null;

            PwEntry newLogin = new PwEntry(true, true);

            setPwEntryFromEntry(newLogin, login);

            // find the database
            PwDatabase chosenDB = SelectDatabase(dbFileName);

            PwGroup parentGroup = GetRootPwGroup(chosenDB); // if in doubt we'll stick it in the root folder

            if (parentUUID != null && parentUUID.Length > 0)
            {
                PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(parentUUID));

                PwGroup matchedGroup = GetRootPwGroup(chosenDB).FindGroup(pwuuid, true);

                if (matchedGroup != null)
                    parentGroup = matchedGroup;
            }

            parentGroup.AddEntry(newLogin, true);

            host.MainWindow.BeginInvoke(new dlgSaveDB(saveDB), chosenDB);

            Entry output = (Entry)GetEntryFromPwEntry(newLogin, true, true, chosenDB);

            return output;
        }
Пример #4
0
        private LightEntry GetEntryFromPwEntry(PwEntry pwe, bool isExactMatch, bool fullDetails, PwDatabase db)
        {
            //Debug.Indent();
            //Stopwatch sw = Stopwatch.StartNew();

            ArrayList formFieldList = new ArrayList();
            ArrayList URLs = new ArrayList();
            URLs.Add(pwe.Strings.ReadSafe("URL"));
            bool usernameFound = false;
            bool passwordFound = false;
            bool alwaysAutoFill = false;
            bool neverAutoFill = false;
            bool alwaysAutoSubmit = false;
            bool neverAutoSubmit = false;
            int priority = 0;
            string usernameName = "";
            string usernameValue = "";

            if (!fullDetails)
            {

            }
            else
            {

                foreach (System.Collections.Generic.KeyValuePair
                    <string, KeePassLib.Security.ProtectedString> pwestring in pwe.Strings)
                {
                    string pweKey = pwestring.Key;
                    string pweValue = pwestring.Value.ReadString();

                    if (!fullDetails && pweValue != "username")
                        continue;

                    if ((pweKey.StartsWith("Form field ") || pweKey.StartsWith("KPRPC Form field ")) && pweKey.EndsWith(" type") && pweKey.Length > 16)
                    {
                        string fieldName = "";
                        if (pweKey.StartsWith("Form field "))
                            fieldName = pweKey.Substring(11).Substring(0, pweKey.Length - 11 - 5);
                        else
                            fieldName = pweKey.Substring(17).Substring(0, pweKey.Length - 17 - 5);

                        string fieldId = "";
                        int fieldPage = 1;

                        if (pwe.Strings.Exists("Form field " + fieldName + " page"))
                        {
                            try
                            {
                                fieldPage = int.Parse(GetPwEntryString(pwe, "Form field " + fieldName + " page"));
                            }
                            catch (Exception)
                            {
                                fieldPage = 1;
                            }
                        }
                        else if (pwe.Strings.Exists("KPRPC Form field " + fieldName + " page"))
                        {
                            try
                            {
                                fieldPage = int.Parse(GetPwEntryString(pwe, "KPRPC Form field " + fieldName + " page"));
                            }
                            catch (Exception)
                            {
                                fieldPage = 1;
                            }
                        }

                        if (pwe.Strings.Exists("Form field " + fieldName + " id"))
                            fieldId = GetPwEntryString(pwe, "Form field " + fieldName + " id");
                        else if (pwe.Strings.Exists("KPRPC Form field " + fieldName + " id"))
                            fieldId = GetPwEntryString(pwe, "KPRPC Form field " + fieldName + " id");

                        if (pweValue == "password")
                        {
                            // If there is a matching custom string for this password, use that but if not
                            // we can just use the standard entry password.
                            if (pwe.Strings.Exists("Form field " + fieldName + " value"))
                                formFieldList.Add(new FormField(fieldName,
                    "Password", GetPwEntryString(pwe, "Form field " + fieldName + " value"), FormFieldType.FFTpassword, fieldId, fieldPage));
                            else if (pwe.Strings.Exists("KPRPC Form field " + fieldName + " value"))
                                formFieldList.Add(new FormField(fieldName,
                    "Password", GetPwEntryString(pwe, "KPRPC Form field " + fieldName + " value"), FormFieldType.FFTpassword, fieldId, fieldPage));
                            else
                                formFieldList.Add(new FormField(fieldName,
                    "Password", GetPwEntryString(pwe, "Password"), FormFieldType.FFTpassword, fieldId, fieldPage));
                            passwordFound = true;
                        }
                        else if (pweValue == "username")
                        {
                            formFieldList.Add(new FormField(fieldName,
                    "User name", GetPwEntryString(pwe, "UserName"), FormFieldType.FFTusername, fieldId, fieldPage));
                            usernameName = fieldName;
                            usernameValue = GetPwEntryString(pwe, "UserName", fullDetails);
                            usernameFound = true;
                        }
                        else if (pweValue == "text")
                        {
                            formFieldList.Add(new FormField(fieldName,
                    fieldName, GetFormFieldValue(pwe, fieldName), FormFieldType.FFTtext, fieldId, fieldPage));
                        }
                        else if (pweValue == "radio")
                        {
                            formFieldList.Add(new FormField(fieldName,
                    fieldName, GetFormFieldValue(pwe, fieldName), FormFieldType.FFTradio, fieldId, fieldPage));
                        }
                        else if (pweValue == "select")
                        {
                            formFieldList.Add(new FormField(fieldName,
                    fieldName, GetFormFieldValue(pwe, fieldName), FormFieldType.FFTselect, fieldId, fieldPage));
                        }
                        else if (pweValue == "checkbox")
                        {
                            formFieldList.Add(new FormField(fieldName,
                    fieldName, GetFormFieldValue(pwe, fieldName), FormFieldType.FFTcheckbox, fieldId, fieldPage));
                        }
                    }
                    else if (pweKey == "Alternative URLs" || pweKey == "KPRPC Alternative URLs")
                    {
                        string[] urlsArray = pweValue.Split(new char[]{' '});
                        foreach (string altURL in urlsArray)
                            URLs.Add(altURL);

                    }
                    //Debug.WriteLine("GetEntryFromPwEntry field processed: " + sw.Elapsed);
                }
            }

            // If we didn't find an explicit password field, we assume any value
            // in the KeePass "password" box is what we are looking for
            if (fullDetails && !passwordFound)
            {
                formFieldList.Add(new FormField("password",
                    "Password", GetPwEntryString(pwe, "Password"), FormFieldType.FFTpassword, "password", 1));
            }

            // If we didn't find an explicit username field, we assume any value
            // in the KeePass "username" box is what we are looking for
            if (!usernameFound)
            {
                formFieldList.Add(new FormField("username",
                    "Username", GetPwEntryString(pwe, "UserName"), FormFieldType.FFTusername, "username", 1));
                usernameName = "username";
                usernameValue = GetPwEntryString(pwe, "UserName");
            }

            string imageData = iconToBase64(pwe.CustomIconUuid, pwe.IconId);
            //Debug.WriteLine("GetEntryFromPwEntry icon converted: " + sw.Elapsed);

            if (fullDetails)
            {
                if (pwe.Strings.Exists("KeeFox Always Auto Fill") || pwe.Strings.Exists("KPRPC Always Auto Fill"))
                    alwaysAutoFill = true;
                if (pwe.Strings.Exists("KeeFox Always Auto Submit") || pwe.Strings.Exists("KPRPC Always Auto Submit"))
                    alwaysAutoSubmit = true;
                if (pwe.Strings.Exists("KeeFox Never Auto Fill") || pwe.Strings.Exists("KPRPC Never Auto Fill"))
                    neverAutoFill = true;
                if (pwe.Strings.Exists("KeeFox Never Auto Submit") || pwe.Strings.Exists("KPRPC Never Auto Submit"))
                    neverAutoSubmit = true;

                if (pwe.Strings.Exists("KeeFox Priority"))
                {
                    string priorityString = pwe.Strings.ReadSafe("KeeFox Priority");
                    if (!string.IsNullOrEmpty(priorityString))
                    {
                        try
                        {
                            priority = int.Parse(priorityString);
                        }
                        catch
                        { }

                        if (priority < 0 || priority > 100000)
                            priority = 0;
                    }
                }
                if (pwe.Strings.Exists("KPRPC Priority"))
                {
                    string priorityString = pwe.Strings.ReadSafe("KPRPC Priority");
                    if (!string.IsNullOrEmpty(priorityString))
                    {
                        try
                        {
                            priority = int.Parse(priorityString);
                        }
                        catch
                        { }

                        if (priority < 0 || priority > 100000)
                            priority = 0;
                    }
                }
            }

            //sw.Stop();
            //Debug.WriteLine("GetEntryFromPwEntry execution time: " + sw.Elapsed);
            //Debug.Unindent();

            if (fullDetails)
            {
                string realm = "";
                try
                {
                    realm = GetPwEntryString(pwe, "Form HTTP realm");
                }
                catch (Exception) { realm = ""; }
                if (string.IsNullOrEmpty(realm))
                {
                    try
                    {
                        realm = GetPwEntryString(pwe, "KPRPC Form HTTP realm");
                    }
                    catch (Exception) { realm = ""; }
                }
                if (string.IsNullOrEmpty(realm))
                {
                    try
                    {
                        realm = GetPwEntryString(pwe, "KPRPC HTTP realm");
                    }
                    catch (Exception) { realm = ""; }
                }

                FormField[] temp = (FormField[])formFieldList.ToArray(typeof(FormField));
                Entry kpe = new Entry(
                (string[])URLs.ToArray(typeof(string)),
                GetPwEntryString(pwe, "Form match URL"), realm,
                pwe.Strings.ReadSafe(PwDefs.TitleField), temp,
                KeePassLib.Utility.MemUtil.ByteArrayToHexString(pwe.Uuid.UuidBytes),
                alwaysAutoFill, neverAutoFill, alwaysAutoSubmit, neverAutoSubmit, priority,
                GetGroupFromPwGroup(pwe.ParentGroup), imageData, GetDatabaseFromPwDatabase(db, false, true));
                return kpe;
            }
            else
            {
                return new LightEntry((string[])URLs.ToArray(typeof(string)),
                    pwe.Strings.ReadSafe(PwDefs.TitleField),
                    KeePassLib.Utility.MemUtil.ByteArrayToHexString(pwe.Uuid.UuidBytes),
                    imageData, usernameName, usernameValue);
            }
        }
Пример #5
0
        public void ModifyLogin(Entry oldLogin, Entry newLogin)
        {
            if (oldLogin == null)
                throw new Exception("old login must be passed to the ModifyLogin function. It wasn't");
            if (newLogin == null)
                throw new Exception("new login must be passed to the ModifyLogin function. It wasn't");
            if (oldLogin.UniqueID == null || oldLogin.UniqueID == "")
                throw new Exception("old login doesn't contain a uniqueID");

            // Make sure there is an active database
            if (!ensureDBisOpen()) return;

            PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(oldLogin.UniqueID));

            PwEntry modificationTarget = GetRootPwGroup(host.Database).FindEntry(pwuuid, true);

            if (modificationTarget == null)
                throw new Exception("Could not find correct entry to modify. No changes made to KeePass database.");

            setPwEntryFromEntry(modificationTarget, newLogin);

            host.MainWindow.BeginInvoke(new dlgSaveDB(saveDB), host.Database);
        }
Пример #6
0
        public Entry[] FindLogins(string[] URLs, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches, 
            string uniqueID, string dbFileName, string freeTextSearch, string username)
        {
            List<PwDatabase> dbs = null;
            int count = 0;
            List<Entry> allEntries = new List<Entry>();

            if (!string.IsNullOrEmpty(dbFileName))
            {
                // find the database
                PwDatabase db = SelectDatabase(dbFileName);
                dbs = new List<PwDatabase>();
                dbs.Add(db);
            }
            else
            {
                // if DB list is not populated, look in all open DBs
                dbs = host.MainWindow.DocumentManager.GetOpenDatabases();
                // unless the DB is the wrong version
                dbs = dbs.FindAll(ConfigIsCorrectVersion);
            }

            //string hostname = URLs[0];
            string actionHost = actionURL;

            // Make sure there is an active database
            if (!ensureDBisOpen()) { return null; }

            // if uniqueID is supplied, match just that one login. if not found, move on to search the content of the logins...
            if (uniqueID != null && uniqueID.Length > 0)
            {
                PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(uniqueID));

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    PwEntry matchedLogin = GetRootPwGroup(db).FindEntry(pwuuid, true);

                    if (matchedLogin == null)
                        continue;

                    Entry[] logins = new Entry[1];
                    logins[0] = (Entry)GetEntryFromPwEntry(matchedLogin, MatchAccuracy.Best, true, db);
                    if (logins[0] != null)
                        return logins;
                }
            }

            if (!string.IsNullOrEmpty(freeTextSearch))
            {
                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    //output = searchGroup.GetEntries(true);
                    SearchParameters sp = new SearchParameters();
                    sp.ComparisonMode = StringComparison.InvariantCultureIgnoreCase;
                    sp.SearchString = freeTextSearch;
                    sp.SearchInUserNames = true;
                    sp.SearchInTitles = true;
                    sp.SearchInTags = true;
                    MethodInfo mi;

                    // SearchEntries method signature changed in KP 2.17 so we use
                    // reflection to enable support for both 2.17 and earlier versions
                    try
                    {
                        mi = typeof(PwGroup).GetMethod("SearchEntries", new Type[] { typeof(SearchParameters), typeof(KeePassLib.Collections.PwObjectList<PwEntry>) });
                        mi.Invoke(searchGroup, new object[] { sp, output });
                    }
                    catch (AmbiguousMatchException ex)
                    {
                        // can't find the 2.17 method definition so try for an earlier version
                        mi = typeof(PwGroup).GetMethod("SearchEntries", new Type[] { typeof(SearchParameters), typeof(KeePassLib.Collections.PwObjectList<PwEntry>), typeof(bool) });
                        mi.Invoke(searchGroup, new object[] { sp, output, false });

                        // If an exception is thrown here it would be unexpected and
                        // require a new version of the application to be released
                    }

                    foreach (PwEntry pwe in output)
                    {
                        Entry kpe = (Entry)GetEntryFromPwEntry(pwe, MatchAccuracy.None, true, db);
                        if (kpe != null)
                        {
                            allEntries.Add(kpe);
                            count++;
                        }
                    }
                }

            }
            // else we search for the URLs

            if (count == 0 && URLs.Length > 0 && !string.IsNullOrEmpty(URLs[0]))
            {
                int protocolIndex = -1;
                Dictionary<string, URLSummary> URLHostnameAndPorts = new Dictionary<string, URLSummary>();

                // make sure that hostname and actionURL always represent only the hostname portion
                // of the URL
                // It's tempting to demand that the protocol must match too (e.g. http forms won't
                // match a stored https login) but best not to define such a restriction in KeePassRPC
                // - the RPC client (e.g. KeeFox) can decide to penalise protocol mismatches,
                // potentially dependant on user configuration options in the client.
                for (int i = 0; i < URLs.Length; i++)
                {
                    URLHostnameAndPorts.Add(URLs[i], URLSummary.FromURL(URLs[i]));
                }

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    output = searchGroup.GetEntries(true);
                    List<string> configErrors = new List<string>(1);

                    // Search every entry in the DB
                    foreach (PwEntry pwe in output)
                    {
                        string entryUserName = pwe.Strings.ReadSafe(PwDefs.UserNameField);
                        entryUserName = KeePassRPCPlugin.GetPwEntryStringFromDereferencableValue(pwe, entryUserName, db);
                        if (EntryIsInRecycleBin(pwe, db))
                            continue; // ignore if it's in the recycle bin

                        //if (string.IsNullOrEmpty(pwe.Strings.ReadSafe("URL")))
                        //    continue; // entries must have a standard URL entry

                        string json = KeePassRPCPlugin.GetPwEntryString(pwe, "KPRPC JSON", db);
                        EntryConfig conf;
                        if (string.IsNullOrEmpty(json))
                        {
                            conf = new EntryConfig();
                        }
                        else
                        {
                            try
                            {
                                conf = (EntryConfig)Jayrock.Json.Conversion.JsonConvert.Import(typeof(EntryConfig), json);
                            }
                            catch (Exception ex)
                            {
                                configErrors.Add("Username: "******". URL: " + pwe.Strings.ReadSafe("URL"));
                                continue;
                            }
                        }

                        if (conf.Hide)
                            continue;

                        bool entryIsAMatch = false;
                        int bestMatchAccuracy = MatchAccuracy.None;

                        if (conf.RegExURLs != null)
                            foreach (string URL in URLs)
                                foreach (string regexPattern in conf.RegExURLs)
                                {
                                    try
                                    {
                                        if (!string.IsNullOrEmpty(regexPattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, regexPattern))
                                        {
                                            entryIsAMatch = true;
                                            bestMatchAccuracy = MatchAccuracy.Best;
                                            break;
                                        }
                                    }
                                    catch (ArgumentException)
                                    {
                                        MessageBox.Show("'" + regexPattern + "' is not a valid regular expression. This error was found in an entry in your database called '" + pwe.Strings.ReadSafe(PwDefs.TitleField) + "'. You need to fix or delete this regular expression to prevent this warning message appearing.", "Warning: Broken regular expression", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        break;
                                    }
                                }

                        // Check for matching URLs for the page containing the form
                        if (!entryIsAMatch && lst != LoginSearchType.LSTnoForms
                                && (string.IsNullOrEmpty(username) || username == entryUserName))
                        {
                            foreach (string URL in URLs)
                        {

                                int accuracy = bestMatchAccuracyForAnyURL(pwe, conf, URL, URLHostnameAndPorts[URL]);
                                if (accuracy > bestMatchAccuracy)
                                    bestMatchAccuracy = accuracy;

                            }
                        }

                        // Check for matching URLs for the HTTP Auth containing the form
                        if (!entryIsAMatch && lst != LoginSearchType.LSTnoRealms
                                && (string.IsNullOrEmpty(username) || username == entryUserName))

                        {
                            foreach (string URL in URLs)
                            {
                                int accuracy = bestMatchAccuracyForAnyURL(pwe, conf, URL, URLHostnameAndPorts[URL]);
                                if (accuracy > bestMatchAccuracy)
                                    bestMatchAccuracy = accuracy;
                            }
                        }

                        if (bestMatchAccuracy == MatchAccuracy.Best
                            || (!requireFullURLMatches && bestMatchAccuracy > MatchAccuracy.None))
                            entryIsAMatch = true;

                        foreach (string URL in URLs)
                        {
                            // If we think we found a match, check it's not on a block list
                            if (entryIsAMatch && matchesAnyBlockedURL(pwe, conf, URL))
                            {
                                entryIsAMatch = false;
                                break;
                            }
                            if (conf.RegExBlockedURLs != null)
                                foreach (string pattern in conf.RegExBlockedURLs)
                                {
                                    try
                                    {
                                        if (!string.IsNullOrEmpty(pattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, pattern))
                                        {
                                            entryIsAMatch = false;
                                            break;
                                        }
                                    }
                                    catch (ArgumentException)
                                    {
                                        MessageBox.Show("'" + pattern + "' is not a valid regular expression. This error was found in an entry in your database called '" + pwe.Strings.ReadSafe(PwDefs.TitleField) + "'. You need to fix or delete this regular expression to prevent this warning message appearing.", "Warning: Broken regular expression", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        break;
                                    }
                                }
                        }

                        if (entryIsAMatch)
                        {
                            Entry kpe = (Entry)GetEntryFromPwEntry(pwe, bestMatchAccuracy, true, db);
                            if (kpe != null)
                            {
                                allEntries.Add(kpe);
                                count++;
                            }
                        }

                    }
                    if (configErrors.Count > 0)
                        MessageBox.Show("There are configuration errors in your database called '" + db.Name + "'. To fix the entries listed below and prevent this warning message appearing, please edit the value of the 'KeePassRPC JSON config' advanced string. Please ask for help on http://keefox.org/help/forum if you're not sure how to fix this. These entries are affected:" + Environment.NewLine + string.Join(Environment.NewLine, configErrors.ToArray()), "Warning: Configuration errors", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            allEntries.Sort(delegate(Entry e1, Entry e2)
            {
                return e1.Title.CompareTo(e2.Title);
            });

            return allEntries.ToArray();
        }
Пример #7
0
        private void setPwEntryFromEntry(PwEntry pwe, Entry login)
        {
            bool firstPasswordFound = false;
            EntryConfig conf = new EntryConfig();
            List<FormField> ffl = new List<FormField>();

            // Go through each form field, mostly just making a copy but with occasional tweaks such as default username and password selection
            // by convention, we'll always have the first text field as the username when both reading and writing from the EntryConfig
            foreach (FormField kpff in login.FormFieldList)
            {
                if (kpff.Type == FormFieldType.FFTpassword && !firstPasswordFound)
                {
                    ffl.Add(new FormField(kpff.Name, "KeePass password", "{PASSWORD}", kpff.Type, kpff.Id, kpff.Page));
                    pwe.Strings.Set("Password", new ProtectedString(host.Database.MemoryProtection.ProtectPassword, kpff.Value));
                    firstPasswordFound = true;
                }
                else if (kpff.Type == FormFieldType.FFTusername)
                {
                    ffl.Add(new FormField(kpff.Name, "KeePass username", "{USERNAME}", kpff.Type, kpff.Id, kpff.Page));
                    pwe.Strings.Set("UserName", new ProtectedString(host.Database.MemoryProtection.ProtectUserName, kpff.Value));
                }
                else
                {
                    ffl.Add(new FormField(kpff.Name, kpff.Name, kpff.Value, kpff.Type, kpff.Id, kpff.Page));
                }
            }
            conf.FormFieldList = ffl.ToArray();

            List<string> altURLs = new List<string>();

            for (int i = 0; i < login.URLs.Length; i++)
            {
                string url = login.URLs[i];
                if (i == 0)
                {
                    URLSummary urlsum = URLSummary.FromURL(url);

                    // Require more strict default matching for entries that come
                    // with a port configured (user can override in the rare case
                    // that they want the loose domain-level matching)
                    if (!string.IsNullOrEmpty(urlsum.Port))
                        conf.BlockDomainOnlyMatch = true;

                    pwe.Strings.Set("URL", new ProtectedString(host.Database.MemoryProtection.ProtectUrl, url ?? ""));
                }
                else
                    altURLs.Add(url);
            }
            conf.AltURLs = altURLs.ToArray();
            conf.HTTPRealm = login.HTTPRealm;
            conf.Version = 1;

            // Set some of the string fields
            pwe.Strings.Set(PwDefs.TitleField, new ProtectedString(host.Database.MemoryProtection.ProtectTitle, login.Title ?? ""));

            // update the icon for this entry (in most cases we'll
            // just detect that it is the same standard icon as before)
            PwUuid customIconUUID = PwUuid.Zero;
            PwIcon iconId = PwIcon.Key;
            if (login.IconImageData != null
                && login.IconImageData.Length > 0
                && base64ToIcon(login.IconImageData, ref customIconUUID, ref iconId))
            {
                if (customIconUUID == PwUuid.Zero)
                    pwe.IconId = iconId;
                else
                    pwe.CustomIconUuid = customIconUUID;
            }

            pwe.Strings.Set("KPRPC JSON", new ProtectedString(true, Jayrock.Json.Conversion.JsonConvert.ExportToString(conf)));
        }
Пример #8
0
        private LightEntry GetEntryFromPwEntry(PwEntry pwe, EntryConfig conf, int matchAccuracy, bool fullDetails, PwDatabase db, bool abortIfHidden)
        {
            ArrayList formFieldList = new ArrayList();
            ArrayList URLs = new ArrayList();
            URLs.Add(pwe.Strings.ReadSafe("URL"));
            bool usernameFound = false;
            bool passwordFound = false;
            bool alwaysAutoFill = false;
            bool neverAutoFill = false;
            bool alwaysAutoSubmit = false;
            bool neverAutoSubmit = false;
            int priority = 0;
            string usernameName = "";
            string usernameValue = "";

            if (abortIfHidden && conf.Hide)
                return null;

            if (!fullDetails)
            {

            }
            else
            {
                if (conf.FormFieldList != null)
                {
                    foreach (FormField ff in conf.FormFieldList)
                    {
                        if (ff.Type == FormFieldType.FFTpassword)
                        {
                            string ffValue = KeePassRPCPlugin.GetPwEntryStringFromDereferencableValue(pwe, ff.Value, db);
                            if (!string.IsNullOrEmpty(ffValue))
                            {
                                formFieldList.Add(new FormField(ff.Name, "KeePass password", ffValue, ff.Type, ff.Id, ff.Page));
                                passwordFound = true;
                            }
                        }
                        else if (ff.Type == FormFieldType.FFTusername)
                        {
                            string ffValue = KeePassRPCPlugin.GetPwEntryStringFromDereferencableValue(pwe, ff.Value, db);
                            if (!string.IsNullOrEmpty(ffValue))
                            {
                                formFieldList.Add(new FormField(ff.Name, "KeePass username", ffValue, ff.Type, ff.Id, ff.Page));
                                usernameFound = true;
                            }
                        }
                        else
                            formFieldList.Add(new FormField(ff.Name, ff.Name, ff.Value, ff.Type, ff.Id, ff.Page));
                    }
                }
            }
            if (conf.AltURLs != null)
                URLs.AddRange(conf.AltURLs);

            // If we didn't find an explicit password field, we assume any value
            // in the KeePass "password" box is what we are looking for
            if (fullDetails && !passwordFound)
            {
                string ffValue = KeePassRPCPlugin.GetPwEntryString(pwe, "Password", db);
                ffValue = KeePassRPCPlugin.GetPwEntryStringFromDereferencableValue(pwe, ffValue, db);
                if (!string.IsNullOrEmpty(ffValue))
                {
                    formFieldList.Add(new FormField("password",
                        "KeePass password", ffValue, FormFieldType.FFTpassword, "password", 1));
                }
            }

            // If we didn't find an explicit username field, we assume any value
            // in the KeePass "username" box is what we are looking for
            if (!usernameFound)
            {
                string ffValue = KeePassRPCPlugin.GetPwEntryString(pwe, "UserName", db);
                ffValue = KeePassRPCPlugin.GetPwEntryStringFromDereferencableValue(pwe, ffValue, db);
                if (!string.IsNullOrEmpty(ffValue))
                {
                    formFieldList.Add(new FormField("username",
                        "KeePass username", ffValue, FormFieldType.FFTusername, "username", 1));
                    usernameName = "username";
                    usernameValue = ffValue;
                }
            }

            string imageData = iconToBase64(pwe.CustomIconUuid, pwe.IconId);
            //Debug.WriteLine("GetEntryFromPwEntry icon converted: " + sw.Elapsed);

            if (fullDetails)
            {
                alwaysAutoFill = conf.AlwaysAutoFill;
                alwaysAutoSubmit = conf.AlwaysAutoSubmit;
                neverAutoFill = conf.NeverAutoFill;
                neverAutoSubmit = conf.NeverAutoSubmit;
                priority = conf.Priority;

            }

            //sw.Stop();
            //Debug.WriteLine("GetEntryFromPwEntry execution time: " + sw.Elapsed);
            //Debug.Unindent();

            if (fullDetails)
            {
                string realm = "";
                if (!string.IsNullOrEmpty(conf.HTTPRealm))
                    realm = conf.HTTPRealm;

                FormField[] temp = (FormField[])formFieldList.ToArray(typeof(FormField));
                Entry kpe = new Entry(
                (string[])URLs.ToArray(typeof(string)), realm,
                pwe.Strings.ReadSafe(PwDefs.TitleField), temp,
                KeePassLib.Utility.MemUtil.ByteArrayToHexString(pwe.Uuid.UuidBytes),
                alwaysAutoFill, neverAutoFill, alwaysAutoSubmit, neverAutoSubmit, priority,
                GetGroupFromPwGroup(pwe.ParentGroup), imageData,
                GetDatabaseFromPwDatabase(db, false, true),matchAccuracy);
                return kpe;
            }
            else
            {
                return new LightEntry((string[])URLs.ToArray(typeof(string)),
                    pwe.Strings.ReadSafe(PwDefs.TitleField),
                    KeePassLib.Utility.MemUtil.ByteArrayToHexString(pwe.Uuid.UuidBytes),
                    imageData, usernameName, usernameValue);
            }
        }
Пример #9
0
        public Entry UpdateLogin(Entry login, string oldLoginUUID, int urlMergeMode, string dbFileName)
        {
            if (login == null)
                throw new ArgumentException("(new) login was not passed to the updateLogin function");
            if (string.IsNullOrEmpty(oldLoginUUID))
                throw new ArgumentException("oldLoginUUID was not passed to the updateLogin function");
            if (string.IsNullOrEmpty(dbFileName))
                throw new ArgumentException("dbFileName was not passed to the updateLogin function");

            // Make sure there is an active database
            if (!ensureDBisOpen()) return null;

            // There are odd bits of the resulting new login that we don't
            // need but the vast majority is going to be useful
            PwEntry newLoginData = new PwEntry(true, true);
            setPwEntryFromEntry(newLoginData, login);

            // find the database
            PwDatabase chosenDB = SelectDatabase(dbFileName);

            PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(oldLoginUUID));
            PwEntry entryToUpdate = GetRootPwGroup(chosenDB).FindEntry(pwuuid, true);
            if (entryToUpdate == null)
                throw new Exception("oldLoginUUID could not be resolved to an existing entry.");

            MergeEntries(entryToUpdate, newLoginData, urlMergeMode, chosenDB);

            host.MainWindow.BeginInvoke(new dlgSaveDB(saveDB), chosenDB);

            Entry updatedEntry = (Entry)GetEntryFromPwEntry(entryToUpdate, MatchAccuracy.Best, true, chosenDB);

            return updatedEntry;
        }