439
edits
| Line 344: | Line 344: | ||
==== Database Upgrade ==== | ==== Database Upgrade ==== | ||
Because there are some semantic differences between the Shared Database version | |||
of NSS and the traditional database, We really have 3 modes of operation for | |||
the NSS and shared databases. | |||
Mode 1: Legacy applications which upgrade to the new version of NSS without | |||
making changes to the application itself. | |||
A | These applications will continue to use the legacy database support and the | ||
old database format. The applications cannot take advantage of new features | |||
in the shared database. In this Mode, the nssdbm3 shared library must be | |||
present. No update is needed in this case. | |||
Summary: | |||
nssdbm3 shared library: Must be Present | |||
Update: none needed. | |||
Application Changes: none. | |||
Mode 2: Applications which maintain private copies of their certs and key | |||
stores (various servers, for instance). | |||
These applications will use the shared database. NSS will automatically | |||
detect instances of legacy databases when first creating the shared database | |||
and upgrade those legacy databases without user interaction. | |||
Summary: | |||
nssdbm3 shared library: need only for update | |||
Update: automatic, no application/user intervention. | |||
Application Changes: | |||
minor changes to Init, | |||
Changes to code that updates trust values or imports certificates with | |||
trust. | |||
Mode 3: Applications which intend to share their keys and certs with other | |||
applications (the common case - browsers, mail clients, secure shells, | |||
vpns, etc.) | |||
These applications will share a common database. In order for this to work, | |||
these applications must all open the same set of databases. Currently these | |||
applications have their own independent copies of the databases. These | |||
independent copies must be merged. In order or NSS to complete this merge, it | |||
will need some extra support from the application itself, possibly user | |||
intervention as well. | |||
Summary: | |||
nssdbm3 shared library: need only for update | |||
Update: partially automated, requires application interaction, possibly | |||
user interaction. | |||
Application Changes: | |||
minor changes to Init, | |||
Changes to code that updates trust values or imports certificates with | |||
trust. | |||
Changes to aid in update | |||
Type A: Type A applications have existing NSS databases. These applications | |||
have upgraded to NSS, and need to merge old databases. All Mode 1 applications | |||
are type A. All Type A applications need nssdbm3 to either upgrade or run. | |||
Type B: Type B applications are applications ported to NSS after the new shared | |||
database code. All Type B applications should be either Mode 2 or Mode 3. | |||
Type B applications need no update interactions, nor do the need nssdbm3. | |||
===Update complications.=== | |||
Updated complications only affect Type A applications. In order to merge a | |||
legacy database into an existing shared database, NSS needs the password for | |||
both databases. | |||
In Mode 1, NSS never needs to do an update or a merge. | |||
Flow chart of NSS update actions for Mode 3: | |||
NSS initialize | |||
| | |||
V | |||
open legacy DB | |||
| | |||
V | |||
done | |||
In Mode 2, the new database is uninitialized, so NSS only needs the | |||
password for the legacy database so it can read the secret keys | |||
in that legacy database, and so the new shared database password | |||
matches the old one. NSS can find the legacy database because | |||
it's in the same directory that the shared database lives in. NSS opens both | |||
databases at initialization time and uses the legacy database until the user | |||
authenticates (providing the legacy database password). NSS then uses that | |||
password to update the new shared database with the records from the old. | |||
The new database takes on the password from the legacy database, and the | |||
legacy database is closed. Future NSS initializations only open the new | |||
shared database. If the user never supplies a password, NSS will continue to | |||
treat the new shared database as uninitialized and will attempt to update from | |||
the old database on future opens until the update succeeds. | |||
Flow chart of NSS update actions for Mode 2: | |||
NSS initialize | |||
| | |||
V | |||
open shared DB | |||
| | |||
V | |||
< is open shared DB > yes | |||
< initialized? >-------> done | |||
| no | |||
V | |||
< does legacy DB > no | |||
< exist? >-------> done | |||
| yes | |||
V | |||
open legacy DB | |||
| | |||
V | |||
no < does legacy DB > | |||
+-------< have a password? > | |||
| | yes | |||
| V | |||
| use legacy DB | |||
| until password | |||
| is supplied | |||
| | | |||
| V | |||
| < is password > no | |||
| < supplied? >-------> done | |||
| | | |||
+--------------+ | |||
V | |||
update shared DB | |||
| | |||
V | |||
close legacy DB | |||
| | |||
V | |||
done | |||
In Mode 3, the new database may or may not be initialized. For the first mode 3 | |||
application, the new database will be uninitialized. NSS can procede the with | |||
the same procedure as Mode 2. When the second and subsequent applications | |||
start, the new shared database will already be initialized with it's own | |||
password. We potentially need both passwords, the first to read the keys | |||
out of the legacy database, and the second to write those keys, as well as | |||
the required authentication values for any trust data. In order to preserve | |||
the existing data in the second application, NSS must be able to merge the | |||
data in the second application with the data in the existing database. | |||
We only want the merge to happen once, not every time the application starts. | |||
In Mode three we need to be able to identify when a database has already been | |||
updated, so the applications needs to tell us some unique identifier for its | |||
database. The application must be able to tell us where the old database lives, | |||
since it's a application private directory compared the the multiple | |||
application shared directory that the shared DB lives in. | |||
Flow chart of NSS update actions for Mode 3: | |||
Start | |||
| | |||
V | |||
open shared DB | |||
| | |||
V | |||
< is open shared DB > yes | |||
< updated with given >-------> done | |||
< legacy DB? > | |||
| no | |||
V | |||
< does legacy DB > no | |||
< exist? >-----------+ | |||
| yes | | |||
V V | |||
open legacy DB mark given | |||
| legacy Updated---> done | |||
V | |||
no < does legacy DB > | |||
+-------< have a password? > | |||
| | yes | |||
| V | |||
| no < does legacy DB > | |||
+-------< have any private > | |||
| < or secret keys? > | |||
| | yes | |||
| V | |||
| use legacy DB | |||
| until password | |||
| is supplied | |||
| | | |||
| V | |||
| < is password > no | |||
| < supplied? >-------> exception A | |||
| | | |||
+--------------+ | |||
V | |||
no < does shared DB > | |||
+-------< have a password? > | |||
| | yes | |||
| V | |||
| yes < does shared DB's > | |||
+--------< password match > | |||
| < legacy DB's PW? > | |||
| | no | |||
| V | |||
| get shared DB | |||
| password | |||
| | | |||
| V | |||
| < is password > no | |||
| < supplied? >-------> exception B | |||
| | | |||
+--------------+ | |||
V | |||
update/merge shared DB | |||
| | |||
V | |||
close legacy DB | |||
| | |||
V | |||
done | |||
exception A. Application needs to decide what happens if the legacy password | |||
is not supplied. Application can choose to: | |||
1) continue to use the legacy DB and try to update later. | |||
2) force NSS to mark legacy DB to be updated without actually updating | |||
the legacy DB (throwing away everything in the legacy DB). | |||
3) force NSS to update those objects it can from the legacy DB, throwing | |||
away private keys and saved passwords. | |||
exception B. Applications needs to decide what happens if the new shared DB | |||
password is not supplied. Application can choose to: | |||
1) continue to use the legacy DB and try to update later. | |||
2) force NSS to mark legacy DB to be updated without actually updating | |||
the legacy DB (throwing away everything in the legacy DB). | |||
3) force NSS to update those objects it can from the legacy DB, | |||
throwing away private keys and saved passwords, and trust information | |||
from the legacy DB. | |||
4) force NSS to reset the shared database password, | |||
throwing away private keys and saved passwords, and trust information | |||
from the shared DB. | |||
NOTE: Since we are potentially dealing with 2 different passwords, The | |||
application needs to be clear to the user which password it needs. | |||
Merge Conflicts (Mode 3A only) | |||
When merging databases in, it's possible (even likely), that the shared | |||
database and legacy DB's have the same objects. In the case of certs and keys, | |||
the merge is a simple matter of identifying duplicates and not updating them. | |||
In the case of trust attributes, however, there are a number of choices: | |||
1) don't update duplicate trust (shared database copy wins). | |||
2) overwrite trust from the legacy DB (legacy db copy wins). | |||
3) calculate the least common denominator trust between them (take the least | |||
trusted values). (turning off trust wins). | |||
4) calculate the most common demonimnator trust between the two (turning on | |||
trust wins). | |||
From the user perspective, each of these choices means: | |||
1) after the update the application that just updated may trust certs that | |||
it had previously marked untrusted, or certs that it has marked trusted are | |||
no longer trusted. | |||
2) after the update other applications that share the database may trust | |||
certs they had previously marked untrusted, or certs that they had marked as | |||
trusted are no longer trusted. | |||
3) after the update all apps may find the certs that they marked trust are | |||
no longer trusted. | |||
4) after the update all apps may find that they trust certs that have | |||
previously been marked untrusted. | |||
Option 3 is the most secure, Option 4 will break have less breakage. Trust | |||
merge conflicts that are real conflicts (application 'A' turned off trust and | |||
application 'B' turned on trust) are expected to be rare. The common case would | |||
be application 'A' turned on SSL trust and application 'B' turned on email | |||
trust. In this case Option 4 is clearly the correct choice. | |||
From a programming point of view, NSS should pick a default and implement it. | |||
Ideally no user interaction will occur. | |||
Finally password entries are merge issues. If the two databases have different | |||
passwords, the merged database will have to have a | |||
Mozilla Applications. | |||
Mozilla applications are Mode 3A applications. In fact, for all intents and | |||
purposes, mozilla applications make the complete set of interesting 3A | |||
application. This section tries to map the issues above into actual code for | |||
Mozilla applications. | |||
As 3A applications, Mozilla apps need to send NSS a unique identifier for | |||
the old cert and key database, as well as the old profile directory where | |||
the databases are stored. The profile 'salt' value would make a good unique | |||
identifier for mozilla products. | |||
On startup, Mozilla apps should note when they are not in done state at | |||
initial nss startup (see flow chart for Mode 3A update above). If mozilla apps | |||
are not at 'done' state after startup, they should proceed to attempt to | |||
enter done state before PSM initialize completes. | |||
Mozilla app will be in done state in the following cases | |||
(any of the below apply): | |||
1) The Mozilla app is starting as a fresh instance. | |||
2) The Mozilla app has already been updated. | |||
3) The shared database does not have a master password set and | |||
The legacy database for Mozilla app does a master password set. | |||
These are the most common cases. | |||
If the state is not done, then we know that this app has not already been | |||
updated, and either the shared database or the legacy database for the Mozilla | |||
app has a master password set. | |||
UI question. At this point should we notify the user that we are updating | |||
the database to a shared database? In order to complete this we will need | |||
to do user interaction below. | |||
If the legacy db for the mozilla app has a master password set, we prompt for | |||
it. This prompt must be clear we are asking for the master password for | |||
the running Mozilla app (Thunderbird, Firefox, Seamonkey, etc). | |||
Exception case A | |||
If we fail to get this password, we need to handle the exception A case. | |||
If the user has a master password set, but does not know what the master | |||
password is, then the following data is lost for sure: | |||
The user's private keys. | |||
The user's secret keys. | |||
Any data encrypted to the private keys. | |||
Any data encrpted with the secret keys. | |||
I believe we can identify if the private keys are associated with a | |||
certificate. If so, then we can tell the user what certificate would no | |||
longer work. Data encrypted with the private keys in Mozilla products are | |||
currently only email messages. Secret keys encrypt saved passwords. The | |||
Mozilla app knows which saved passwords are encrypted with that key. | |||
If we hit Exception case A we can do one of the following: | |||
1) attempt to just update the certs, trust, crl and s/mime records, skipping | |||
the all the keys. We would loose all the data described above. | |||
2) decide not to update. In this case we would loose all the data in the | |||
paragraph above as well as all the certs, trust crl and s/mime records. | |||
3) run with the legacy database and allow the user to update later. | |||
4) run with the new shared database and allow the user to update later. | |||
I would suggest we only offer the user the choice of 1 or 4. Note: if the user | |||
selects 1, the update could fail again in exception case B. From a UI | |||
perspective, we may want to handle exception case B as we handle case A so | |||
the user is only asked once about forcing an update while losing data. | |||
Once we have a legacy db password, or if we determine we don't need the legacy | |||
db password (either because there isn't one, or because we are willing to loose | |||
the data that was protected by it). We need to acquire the shared db's | |||
password so we can encrypt and mac the data properly. If the shared db doesn't | |||
have a password we can proceed with the update without further prompting the | |||
user. If the shared db has the same password as the legacy db, then we can | |||
detect that and again proceed with the update without further prompting. | |||
If both of these fail, we prompt for the password for the shared database. This | |||
prompt is trickier, because we need to ask the user for the password that | |||
he percieves to be the Master password for a different mozilla app. Note: at | |||
this point we are in a pretty uncommon corner case. Most users will not have | |||
different Master passwords for both Thunderbird and Firefox, for instance. | |||
However if we do arrive at this case, it is highly likely the user is not an | |||
experienced/informed user, so we need to treat this case carefully. | |||
If we get the password, we complete the update as planned. | |||
Exception case B | |||
If we fail to get this password, we need to handle the exception B case. | |||
If the user has a master password set on his shared database, but does not | |||
know what that master password is, we now have the following choices: | |||
1) eshew any private keys, secret keys and trust updates from the | |||
legacy database. | |||
2) reset the password on the shared database (loosing all private and secret | |||
keys, possibly loosing some trust). | |||
3) run with the legacy database and allow the user to update later. | |||
4) run with the new shared database and allow the user to update later. | |||
It seems pretty unlikely that the user truly does not know the shared database | |||
password, since he had to create or set it recently. However as the deployment | |||
time increases, this becomes more likely. | |||
Again, I think giving the user a choice between options 1) and 4) are the | |||
best alternatives. If the user had already tripped over Exception case A, we | |||
can presume the user intends to make a similiar choice here. Case 2 can be | |||
handled later under the same way the user handles a forgotten master password | |||
today (only now resetting the master password affects all mozilla apps). | |||
Profile issues. | |||
Mozilla apps can create more than one profile. Developers use this capability | |||
to test bugs that new users are likely to run into without loosing their own | |||
production evironment. | |||
Shared databases, in general, means that some of the current semantics of user | |||
profiles will break. Creating a new profile will not create a new | |||
key/cert/master password profile. For developers (the primary users of profiles) | |||
it seems importan to preserve some of the existing semantics. I can see a | |||
couple of options. | |||
1) Allow profiles to be marked with 'private key/cert DB's. This will change | |||
The Mozilla app from a Mode 3A app to a Mode 2A app. This will return | |||
developers to their previous semantic if they want, while allowing them to | |||
also test the interaction of different profiles and the same database. It would | |||
require UI changes to the profile manager, and it will require action on the | |||
part of the developer to get back to the old semantic. | |||
2) Treat only the default profile as Mode 3A and all other profiles as Mode 2A. | |||
This will allow profile separation to operate as is today with no changes. It | |||
does mean, however, that only default profiles will share keys with | |||
appllication. | |||
3) Provide the checkbox in option 1, but make it default as in option 2. | |||
I think option 3 probably provides the best solution for all worlds. | |||
==== Layering ==== | ==== Layering ==== | ||
edits