/// <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); } }
/// <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(); } }