/// <summary>
        /// init this profile and validate its password
        /// </summary>
        /// <param name="password"></param>
        public void Login(string password)
        {
            if (this.ProfilePath == null)
            {
                throw new Exception("Failed to determine the location of the default Firefox Profile");
            }

            SECStatus initStatus = NSS3.NSS_Init(this.ProfilePath);

            if (initStatus != SECStatus.Success)
            {
                Int32  error     = NSPR4.PR_GetError();
                string errorName = NSPR4.PR_ErrorToName(error);
                throw new Exception("Failed to initialise profile for login at " + this.ProfilePath + " reason (" + error.ToString() + ") " + errorName);
            }



            SECStatus resultStatus = NSS3.CheckUserPassword(password);

            if (resultStatus != SECStatus.Success)
            {
                Int32  error     = NSPR4.PR_GetError();
                string errorName = NSPR4.PR_ErrorToName(error);
                throw new Exception("Failed to Validate Password: (" + error.ToString() + ") " + errorName);
            }
        }
        public static SECStatus CheckUserPassword(string password)
        {
            try
            {
                IntPtr slot = NSS3.PK11_GetInternalKeySlot();                 // get a slot to work with

                if (slot == IntPtr.Zero)
                {
                    throw new Exception("Failed to get slot");
                }

                try
                {
                    SECStatus result = NSS3.PK11_CheckUserPassword(slot, password);
                    return(result);
                }
                finally
                {
                    NSS3.PK11_FreeSlot(slot);
                }
            }
            finally
            {
                if (NSS3.NSS_Shutdown() != SECStatus.Success)
                {
                    Int32  error     = NSPR4.PR_GetError();
                    string errorName = NSPR4.PR_ErrorToName(error);
                    throw new Exception("Failed to shutdown: " + errorName);
                }
            }
        }
        /// <summary>
        /// use NSS to decode and decrypt a string
        /// </summary>
        /// <param name="base64EncryptedData">data that is encrypted and then base64 encoded</param>
        /// <param name="result">clear text result</param>
        /// <returns>success status</returns>
        private static SECStatus Decrypt(string base64EncryptedData, ref string result)
        {
            SECStatus status        = SECStatus.Success;
            SECItem   decodedItem   = new SECItem();
            IntPtr    decodedObject = IntPtr.Zero;

            result = string.Empty;

            decodedItem.Data   = IntPtr.Zero;
            decodedItem.Length = 0;

            try
            {
                decodedObject = NSS3.NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, base64EncryptedData, base64EncryptedData.Length);

                if (decodedObject == IntPtr.Zero)
                {
                    status = SECStatus.Failure;
                }
                else
                {
                    status = NSS3.PK11SDR_Decrypt(decodedObject, ref decodedItem, IntPtr.Zero);

                    if (status != SECStatus.Success)
                    {
                        Int32  error     = NSPR4.PR_GetError();
                        string errorName = NSPR4.PR_ErrorToName(error);
                        throw new Exception("Failed to decrypt data: " + errorName);
                    }

                    try
                    {
                        result = Marshal.PtrToStringAnsi(decodedItem.Data, decodedItem.Length);
                    }
                    finally
                    {
                        NSS3.SECITEM_FreeItem(ref decodedItem, 0);
                    }
                }
            }
            catch (Exception ex)
            {
                status = SECStatus.Failure;
                KeePassUtilities.LogException(ex);
            }
            finally
            {
                if (decodedObject != IntPtr.Zero)
                {
                    NSS3.SECITEM_FreeItem(decodedObject, 1);
                }

                if (decodedItem.Data != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(decodedItem.Data);
                }
            }

            return(status);
        }
        /// <summary>
        /// use NSS to decode a string
        /// </summary>
        /// <param name="base64Data">data that is base64 encoded</param>
        /// <param name="result">clear text result</param>
        /// <returns>success status</returns>
        private static SECStatus Decode(string base64Data, ref string result)
        {
            SECStatus status        = SECStatus.Success;
            SECItem   decodedItem   = new SECItem();
            IntPtr    decodedObject = IntPtr.Zero;

            result = string.Empty;

            try
            {
                decodedObject = NSS3.NSSBase64_DecodeBuffer(IntPtr.Zero, IntPtr.Zero, base64Data, base64Data.Length);

                if (decodedObject == IntPtr.Zero)
                {
                    status = SECStatus.Failure;
                }
                else
                {
                    try
                    {
                        decodedItem = (SECItem)Marshal.PtrToStructure(decodedObject, typeof(SECItem));

                        result = Marshal.PtrToStringAnsi(decodedItem.Data, decodedItem.Length);
                    }
                    finally
                    {
                        NSS3.SECITEM_FreeItem(decodedObject, 1);
                    }
                }
            }
            catch (Exception ex)
            {
                status = SECStatus.Failure;
                KeePassUtilities.LogException(ex);
            }
            finally
            {
                if (decodedObject != IntPtr.Zero)
                {
                    NSS3.SECITEM_FreeItem(decodedObject, 1);
                }

                if (decodedItem.Data != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(decodedItem.Data);
                }
            }

            return(status);
        }
        /// <summary>
        /// Sets NSS to use this profile
        /// </summary>
        public void Init()
        {
            if (this.ProfilePath == null)
            {
                throw new Exception("Failed to determine the location of the default Firefox Profile");
            }

            SECStatus initStatus = NSS3.NSS_Init(this.ProfilePath);

            if (initStatus != SECStatus.Success)
            {
                Int32  error     = NSPR4.PR_GetError();
                string errorName = NSPR4.PR_ErrorToName(error);
                throw new Exception("Failed to initialise profile at " + this.ProfilePath + " reason " + errorName);
            }
        }
예제 #6
0
        /// <summary>
        /// load this object with signon data related to the supplied profile
        /// </summary>
        /// <param name="profile"></param>
        public void Load(FirefoxProfile profile, string password)
        {
            Profile = profile;

            if (Profile.ProfilePath == null)
            {
                throw new Exception("Failed to determine the location of the default Firefox Profile");
            }

            SECStatus result1 = NSS3.NSS_Init(Profile.ProfilePath);             // init for profile


            if (result1 != SECStatus.Success)
            {
                Int32  error     = NSPR4.PR_GetError();
                string errorName = NSPR4.PR_ErrorToName(error);
                throw new Exception("Failed to initialise profile for load at " + Profile.ProfilePath + " reason " + errorName);
            }

            try
            {
                IntPtr slot = NSS3.PK11_GetInternalKeySlot();                 // get a slot to work with

                if (slot == IntPtr.Zero)
                {
                    throw new Exception("Failed to GetInternalKeySlot");
                }

                try
                {
                    SECStatus result2 = NSS3.PK11_CheckUserPassword(slot, password);

                    if (result2 != SECStatus.Success)
                    {
                        Int32  error     = NSPR4.PR_GetError();
                        string errorName = NSPR4.PR_ErrorToName(error);
                        throw new Exception("Failed to Validate Password: "******"signons.sqlite");

                    if (File.Exists(signonSqlLitePath))
                    {
                        if (_SQLite == null)
                        {
                            if (KeePassUtilities.Is64Bit)
                            {
                                _SQLite = Assembly.LoadFrom(Application.StartupPath + @"\WebSiteAdvantageKeePassFirefox-SQLite\4x64\System.Data.SQLite.dll");
                            }
                            else
                            {
                                _SQLite = Assembly.LoadFrom(Application.StartupPath + @"\WebSiteAdvantageKeePassFirefox-SQLite\4x32\System.Data.SQLite.DLL");
                            }
                        }

                        IDbConnection connection = (IDbConnection)_SQLite.CreateInstance("System.Data.SQLite.SQLiteConnection");

                        connection.ConnectionString = "Data Source=" + signonSqlLitePath + ";Version=3;New=False;Compress=True;";

                        //		SQLiteConnection connection = new SQLiteConnection("Data Source=" + signonSqlLitePath + ";Version=3;New=False;Compress=True;");

                        try
                        {
                            connection.Open();

                            //		SQLiteCommand command = new SQLiteCommand("select id, desc from mains", connection);

                            Type adapterType = _SQLite.GetType("System.Data.SQLite.SQLiteDataAdapter");

                            IDataAdapter adapter = (IDataAdapter)Activator.CreateInstance(adapterType, new object[] { "SELECT " +
                                                                                                                      "id, hostname, httpRealm, formSubmitURL, usernameField, passwordField, encryptedUsername, encryptedPassword, guid, encType " +
                                                                                                                      "FROM moz_logins ORDER BY hostname", connection });

                            //SQLiteDataAdapter adapter = new SQLiteDataAdapter(
                            //    "SELECT "+
                            //    "id, hostname, httpRealm, formSubmitURL, usernameField, passwordField, encryptedUsername, encryptedPassword, guid, encType "+
                            //    "FROM moz_logins ORDER BY hostname", connection);

                            DataSet dataSet = new DataSet();

                            adapter.Fill(dataSet);

                            foreach (DataRow row in dataSet.Tables[0].Rows)
                            {
                                FirefoxSignonSite signonSite = null;

                                foreach (DataColumn column in dataSet.Tables[0].Columns)
                                {
                                    Debug.WriteLine(column.ColumnName + "=" + (row.IsNull(column) ? "NULL" : row[column].ToString()));
                                }

                                string hostname = row["hostname"].ToString();

                                if (signonSite == null || signonSite.Site != hostname)
                                {
                                    signonSite      = new FirefoxSignonSite();
                                    signonSite.Site = hostname;
                                    this.SignonSites.Add(signonSite);
                                }
                                ;

                                FirefoxSignon signon = new FirefoxSignon();
                                signonSite.Signons.Add(signon);
                                string u = NSS3.DecodeAndDecrypt(row["encryptedUsername"].ToString());
                                Debug.WriteLine("U=" + u);
                                signon.UserName      = u;
                                signon.UserNameField = row.IsNull("usernameField") ? String.Empty : row["usernameField"].ToString();
                                string p = NSS3.DecodeAndDecrypt(row["encryptedPassword"].ToString());
                                Debug.WriteLine("P=" + p);
                                signon.Password        = p;
                                signon.PasswordField   = row.IsNull("passwordField") ? String.Empty : row["passwordField"].ToString();
                                signon.LoginFormDomain = row.IsNull("formSubmitURL") ? String.Empty : row["formSubmitURL"].ToString();
                            }
                        }
                        finally
                        {
                            connection.Close();
                        }
                    }
                    else
                    {
                        int version = 3;

                        while (signonFile == null && version > 0)
                        {
                            string signonPath = Path.Combine(Profile.ProfilePath, SignonFileNames[version]);
                            if (File.Exists(signonPath))
                            {
                                signonFile = signonPath;
                                header     = SignonHeaderValues[version];
                            }
                            else
                            {
                                version--;
                            }
                        }

                        Version = version;

                        if (version == 0)
                        {
                            throw new Exception("Cound not find a signon file to process");
                        }

                        StreamReader reader = File.OpenText(signonFile);

                        try
                        {
                            // first line is header
                            string line = reader.ReadLine();

                            if (line == null)
                            {
                                throw new Exception("signon file is empty");
                            }

                            if (line != header)
                            {
                                throw new Exception("signon file contains an invalid header");
                            }

                            // lines till the first dot are host excludes

                            while ((line = reader.ReadLine()) != null && line != ".")
                            {
                                Debug.WriteLine("# " + line);

                                Debug.WriteLine("ExcludeHost: " + line);

                                this.ExcludeHosts.Add(line);
                            }
                            FirefoxSignonSite signonSite = null;
                            // read each entry

                            while (line != null)
                            {
                                Debug.WriteLine("## " + line);

                                // here after any dot (.) therefore new site
                                // all new lines pass through if they contain a dot (.)

                                signonSite = null;


                                while ((line = reader.ReadLine()) != null && line != ".")
                                {
                                    Debug.WriteLine("# " + line);
                                    // first line is host
                                    // subsequent lines are pairs of name value
                                    // if name starts with * then its a password
                                    // values are encrypted

                                    if (signonSite == null)                                     // site is reset to null after each dot (.)
                                    {
                                        signonSite      = new FirefoxSignonSite();
                                        signonSite.Site = line;

                                        this.SignonSites.Add(signonSite);

                                        Debug.WriteLine("Site: " + line);

                                        line = reader.ReadLine();                                         // move to the next line
                                        Debug.WriteLine("# " + line);
                                    }
                                    // else stick to the same line for the next parser, second site entries dont have a dot (.) nor site line



                                    if (line != null && line != ".")
                                    {
                                        FirefoxSignon signon = new FirefoxSignon();
                                        signonSite.Signons.Add(signon);
                                        // User field
                                        signon.UserNameField = line;
                                        Debug.WriteLine("UserNameField: " + signon.UserNameField);

                                        if ((line = reader.ReadLine()) != null && line != ".")
                                        {
                                            Debug.WriteLine("# " + line);
                                            // User Value
                                            string u = NSS3.DecodeAndDecrypt(line);
                                            signon.UserName = u;
                                            Debug.WriteLine("UserName: "******".")
                                            {
                                                Debug.WriteLine("# " + line);
                                                // Password field
                                                signon.PasswordField = line.TrimStart(new char[] { '*' });
                                                Debug.WriteLine("PasswordField: " + signon.PasswordField);

                                                if ((line = reader.ReadLine()) != null && line != ".")
                                                {
                                                    Debug.WriteLine("# " + line);
                                                    // Password Value
                                                    string p = NSS3.DecodeAndDecrypt(line);
                                                    signon.Password = p;
                                                    Debug.WriteLine("Password: "******".")
                                                    {
                                                        Debug.WriteLine("# " + line);
                                                        // Domain
                                                        signon.LoginFormDomain = line;
                                                        Debug.WriteLine("LoginFormDomain: " + signon.LoginFormDomain);

                                                        if ((line = reader.ReadLine()) != null && line != ".")
                                                        {
                                                            Debug.WriteLine("# " + line);
                                                            // Filler
                                                            Debug.WriteLine("Filler: " + line);
                                                        }
                                                        // note: if there is not a dot (.) after this then its a subsequent entry for the same site
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        finally
                        {
                            reader.Close();
                        }
                    }
                }
                finally
                {
                    NSS3.PK11_FreeSlot(slot);
                }
            }
            finally
            {
                NSS3.NSS_Shutdown();
            }
        }