Changes

Created page with 'Welcome to Simone Giustetti's wiki pages. Languages: '''English''' - [http://www.giustetti.net/wiki/index.php?title=seamonkey_password_migration Italiano] ---- == Seamonkey …'
Welcome to Simone Giustetti's wiki pages.


Languages: '''English''' - [http://www.giustetti.net/wiki/index.php?title=seamonkey_password_migration Italiano]

----


== Seamonkey 1.1.x to 2.0.x password migration ==

One really useful feature of '''Seamonkey''', the Mozilla foundation web suite consisting of an integrated browser, e-mail client, Html editor and chat program, consists of '''saving user passwords''' for web sites and performing authentication by means of but '''one single Master Password'''. I often need to access multiple authentication requiring sites to work and password management becomes a tiresome activity as the web site number increases. Recurring to a single password instead of dozens means a great saving of time not to mention a radical decrease in errors and mistakes. I recently '''upgraded Seamonkey''' from the old 1.1.8 version to the new 2.0.4 one while performing a Slackware version upgrade from 13.0 to 13.1. Upon upgrade completion I found out an issue concerning saved passwords: the migration procedure did not import data from the old user profile to the new one. An error message was prompted at each subsequent Seamonkey start up: some inconsistencies with the cryptographic subsystem prevented it from loading and as a consequence authentication was disabled.

Reconfiguring dozens of passwords was not an option so I managed to manually import passwords. What follows is the procedure I used to migrate Seamonkey 1.1.8 stored passwords to a fresh 2.0.4 install.


== A known problem ==

I was not the first and probably won't be the last to face the migration issue. Some "googling" returned several comments related to the 2.0 alpha versions of Seamonkey on the Bugzilla mailing list. The issue seemed to be a closed one, but the same symptoms were later reported by users on forums dedicated to the stable versions: [http://forums.mozillazine.org/viewtopic.php?f=40&t=1562745&start=30 forums.mozillazine.org]

I tried to follow the forum suggested workaround, removed the 2.0.4 version, reinstalled the 1.1.8 one and rerun the upgrade, but the password import did not work so I gave up automated tools and resolved to do it myself.

The first step consisted in studying the way passwords are stored by both version 1.0.x and 2.0.x of Seamonkey.
Some useful insight on the Seamonkey 1.0.x encryption subject was provided by the following links. What the documentation lacked I made up running tests.
http://kb.mozillazine.org/Transferring_data_to_a_new_profile_-_SeaMonkey
http://seamonkey.ilias.ca/profilefaq/#transferring_passwords


== Passwords in Seamonkey 1.1.x ==

Password related information are stored in files with the ''*.s'' extension in Seamonkey 1.0.8. If using a '''Masterkey''', a master password, the password itself and identifiers for the passwords list are stored in file ''key3.db''. Both files are located in the user profile directory.

For me the authentication data files were:
/home/twinstar/.mozilla/default/xt5ed1fd.slt/key3.db
/home/twinstar/.mozilla/default/xt5ed1fd.slt/52829682.s

Let's study part of file 52829682.s to understand how information are organized.
bash-4.1$ cd /home/twinstar/.mozilla/default/xt5ed1fd.slt
bash-4.1$ cat 52829682.s
#2c
http://localhost
http://www.giustetti.net
https://localhost
https://login.yahoo.com
.
http://appdb.winehq.org
sUserEmail
MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...
*sUserPassword
MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...
.
https://sourceforge.net
form_loginname
MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...
*form_pw
MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...
.

A line consisting of a single dot is a field or record terminator.

The first 4 file lines, the ones between code #2c and the first dot line consist of a list of sites for which a password shall never be saved.

Line http://appdb.winehq.org starts a password record related to web site appdb.winehq.org. The lines that follow contain information related to the authentication form for the web page. In short:
''http://appdb.winehq.org'' - It's the web address for the authentication requiring site.
''sUserEmail'' - It's the user name form field.
''MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...'' - It's the user name. Data are encrypted for better security.
''*sUserPassword'' - It's the password form field.
''MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC.'' - It's the encrypted password.

The following line dot marks the end for web site appdb.winehq.org authentication data. The next line marks the start for a new password record, coded as the previous one.


== Passwords in Seamonkey 2.0.x ==

Password coding and information retention for cookies, page history, download history and much more were fully rewritten in Seamonkey version 2.0.x. '''Sqlite''' was introduced to store in an homogeneous way all information. [http://www.sqlite.org Sqlite] is a library implementing a SQL relational database engine without the need for a server. Old text files were replaced by ''cookies.sqlite'', ''downloads.sqlite'', ''formhistory.sqlite'', ''permissions.sqlite'', ''places.sqlite'', '''signons.sqlite''' and ''urlbarhistory.sqlite''. File signons.sqlite is used to store passwords and replaces the old *.s extension one. Password management in Seamonkey 2.0.x is attained through the file couple '''signons.sqlite''' and '''key3.db'''.

To study file signons.sqlite format a SQL client is needed; a client able to decipher files with extension *.sqlite. A certain experience with the SQL language comes in handy too. Slackware 13.1 comes equipped with package sqlite-3.6.23.1-<''arch''>-1. Libraries needed to create databases and a client to manipulate data are part of the package. We'll use the client program, ''sqlite3'', to analyze the password file format.
bash-4.1$ sqlite3 signons.sqlite
SQLite version 3.6.23.1
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema
CREATE TABLE moz_disabledHosts (id INTEGER PRIMARY KEY,hostname TEXT UNIQUE ON CONFLICT REPLACE);
CREATE TABLE moz_logins (id INTEGER PRIMARY KEY, hostname TEXT NOT NULL, httpRealm TEXT, formSubmitURL TEXT,
usernameField TEXT NOT NULL, passwordField TEXT NOT NULL,encryptedUsername TEXT NOT NULL,
encryptedPassword TEXT NOT NULL,guid TEXT, encType INTEGER);
CREATE INDEX moz_logins_encType_index ON moz_logins(encType);
CREATE INDEX moz_logins_guid_index ON moz_logins(guid);
CREATE INDEX moz_logins_hostname_formSubmitURL_index ON moz_logins(hostname, formSubmitURL);
CREATE INDEX moz_logins_hostname_httpRealm_index ON moz_logins(hostname, httpRealm);
CREATE INDEX moz_logins_hostname_index ON moz_logins(hostname);

Command ''.schema'' prints out the '''database structure''' and '''a list of tables'''. Database signons.sqlite is made up of 2 tables only: moz_disabledHosts and moz_logins; the latter of which is the subject of our analysis.

We'll use command ''.dump'' to search through table '''moz_logins''' contents. The command will print out a series of SQL clauses needed to create a full back-up of the database data and table structure.
sqlite> .dump moz_logins
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE moz_logins (id INTEGER PRIMARY KEY, hostname TEXT NOT NULL, httpRealm TEXT, formSubmitURL TEXT,
usernameField TEXT NOT NULL, passwordField TEXT NOT NULL, encryptedUsername TEXT NOT NULL,
encryptedPassword TEXT NOT NULL, guid TEXT,encType INTEGER);
INSERT INTO "moz_logins" VALUES(1,'http://www.gemave.it',NULL,'http://www.gemave.it','username','password',
'MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...','MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...',
'{cae1a5bb-56f8-4366-91cc-20bc2f7af323}',1);
INSERT INTO "moz_logins" VALUES(3,'https://sourceforge.net',NULL,'https://sourceforge.net','form_loginname',
'form_pw','MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...','MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...',
'{2f7d87e6-64db-418a-8f26-1ee4b1fec787}',1);
INSERT INTO "moz_logins" VALUES(12,'http://appdb.winehq.org',NULL,'http://appdb.winehq.org','sUserEmail',
'sUserPassword','MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...','MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...',
'{3c600fba-7ec9-4deb-b644-f775defad46f}',1);
CREATE INDEX moz_logins_hostname_index ON moz_logins(hostname);
CREATE INDEX moz_logins_hostname_formSubmitURL_index ON moz_logins(hostname, formSubmitURL);
CREATE INDEX moz_logins_hostname_httpRealm_index ON moz_logins(hostname, httpRealm);
CREATE INDEX moz_logins_guid_index ON moz_logins(guid);
CREATE INDEX moz_logins_encType_index ON moz_logins(encType);
COMMIT;

Table ''moz_logins'' is made of 10 columns:
''id'' - It' a unique identifier for the row. An integer number greater than 0 that is sequentially increased by 1 at each
subsequent password save.
''hostname'' - It's the web site address.
''httpRealm'' - Was never populated during my tests. In the above examples it always contains the NULL value. Null value
means a not initialized database field.
''formSubmitURL'' - It's the form web address. It usually equals hostname.
''usernameField'' - It's the user name form field.
''passwordField'' - It's the password form field.
''encryptedUsername'' - It's the user name. Data are encrypted for better security.
''encryptedPassword'' - It's the encrypted password.
''guid'' - An identifier with format {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
''encType'' - A value of 1 means the password is encrypted.


== How to convert data ==

Before proceeding a full back-up of directory .mozilla from the user home is strongly suggested.
The easiest way to create such copy it using the tar command:
bash-4.1$ tar -jcpf mozilla_bck.tar.bz2 .mozilla
Doing so, if something were to go wrong, it will still be possible to recover the initial status by deleting the modified .mozilla directory and uncompressing the created archive:
bash-4.1$ rm -r .mozilla
bash-4.1$ tar -jxf mozilla_bck.tar.bz2

Please check for Seamonkey to be closed during data import.

=== Find user profile directories ===

I always used the default profile for my user and only that. As a consequence the user data containing directory is /home/twinstar/.mozilla/default/<random name> or: /home/twinstar/.mozilla/default/xt5ed1fd.slt/ for Seamonkey 1.1.8. The files in the directory contain candidate for migration data.

Starting Seamonkey 2.0.x will result in the creation of a new directory structure for user profiles: .mozilla/seamonkey/<random name>.default/; .mozilla/seamonkey/8i3q7qe7.default/ for my user. Data shall be migrated to that directory. Files contained therein are obviously empty.

=== Seamonkey 2.0.x configuration ===

Next step consists of Seamonkey configuration. Start the web browser and enter the "Edit -> Preferences" menu. Check for option "Remember Passwords" to be enabled. If not enable it and set a "'''Master Password'''". Set the same password used for Seamonkey 1.1.x.

Then replace file ''key3.db'' in the 2.0.x profile directory with the one from version 1.1.x directory.

The last step consists of converting the actual data from file with extension ''*.s'' to ''SQL'' insert clauses that should later be loaded into the database file ''signons.sqlite''. The data format cross reference being:

''id'' -> Whatever integer, greater than zero number. Increment it for each record. The starting value being the
higher value ever saved increased by 1. If the maximum is 4, for example, 5 will be the first available number.
''hostname'' -> The first record line from file xxxxxxx.s.
''httpRealm'' -> Use NULL.
''formSubmitURL'' -> The same value used for field ''hostname''.
''usernameField'' -> The second record line from file xxxxxxx.s.
''passwordField'' -> The fourth record line from file xxxxxxx.s.
''encryptedUsername'' -> The third record line from file xxxxxxx.s.
''encryptedPassword'' -> The fifth record line from file xxxxxxx.s.
''guid'' -> If a password were already saved into the file use the same value of field ''guid''. Use NULL otherwise.
''encType'' -> Use value 1 for password encryption.

=== SQL clauses ===

As an example, password data for web site http://appdb.winehq.org will be converted from the file 52829682.s format to the corresponding SQL clause.
http://appdb.winehq.org
sUserEmail
MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...
*sUserPassword
MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...
.
In our example the last previously inserted password has field ''id'' equal to 14. We are going to insert the fifteenth password in the list:
INSERT INTO "moz_logins" VALUES(15,'http://appdb.winehq.org',NULL,'http://appdb.winehq.org','sUserEmail',
'sUserPassword','MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...','MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...',
'{c9158a9c-022c-4413-8b40-f843b5c8a5ec}',1);
Please note: '''all string data are enclosed between ' characters''' as per SQL language standard for text data. Moreover note that the asterisk character from the '''*sUserPassword''' line was not included. The omission is an intentional one. Concerning field ''guid'' a value from a previously inserted password was used. The insert clause was terminated by a ';' character again as per SQL language standard.

To load the new password into the database open the '''sqlite3''' interpreter, copy the clause to '''sqlite3''' prompt and press enter:
bash-4.1$ sqlite3 signons.sqlite
SQLite version 3.6.23.1
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> INSERT INTO "moz_logins" VALUES(15,'http://appdb.winehq.org',NULL,'http://appdb.winehq.org','sUserEmail',
'sUserPassword','MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...','MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcEC...',
'{c9158a9c-022c-4413-8b40-f843b5c8a5ec}',1);
sqlite>
The password is now migrated and will be available from next Seamonkey start-up.
Use the .quit command to leave program sqlite3:
sqlite> .quit
bash-4.1$

=== Notes ===

To remove an imported by mistake password it's possible to use the following SQL clause:
sqlite> delete from "moz_logins" where id=<''identifier for the candidate for removal password''>;

Loading passwords to file ''signons.sqlite'' alone does not suffice to execute a full import. The ''key3.db'' file from the old user profile is needed too. Without the ''key3.db'' file imported passwords will be ignored by Seamonkey.

You are strongly suggested to close Seamonkey while importing passwords and to start it after completion to check the outcome and authentication subsystem behavior.

The proposed import procedure presumes a fresh Seamonkey 2.0.x install. If you were in need of other data from your old profile: e-mails, bookmarks and such, You'll need to move them from the old user profile to the new one.


== Summary ==

In the previous article the password storage format for some Seamonkey versions was described along with a non automated migration procedure between major releases of the program. A format conversion example was provided for a single password record. Whoever were in need to migrate many records could:
# Convert data by means of a text editor.
# Write a conversion script to read an input file and output a SQL formatted text file to use in conjunction with the sqlite3 program or another SQL client.

Whichever path you'll choose to follow, please always back-up your .mozilla data directory first.


External Links
----
* [http://www.seamonkey-project.org/ Seamonkey home page]


----

Languages: '''English''' - [http://www.giustetti.net/wiki/index.php?title=seamonkey_password_migration Italiano]