106
edits
(Deleted a HUGE block of duplicated text, and do some wordsmithing) |
m (More wordsmithing, use database and DBM consistently) |
||
Line 13: | Line 13: | ||
*Synchronized updates, with application down time: The applications share the database read-only. If any update is desired, all the applications are shut down, and a database update program performs the update, then all the applications are restarted in read-only mode. Some server products, for example, have an administration program that stops the servers, updates the database that they share, and then restarts the servers. This results in undesirable downtime and desired database changes are delayed until the next interval in which such downtime is acceptable. | *Synchronized updates, with application down time: The applications share the database read-only. If any update is desired, all the applications are shut down, and a database update program performs the update, then all the applications are restarted in read-only mode. Some server products, for example, have an administration program that stops the servers, updates the database that they share, and then restarts the servers. This results in undesirable downtime and desired database changes are delayed until the next interval in which such downtime is acceptable. | ||
*Multiple copies with duplicated updates. Each application keeps its own copy of its databases, and applications communicate their changes to each other, so that each application may apply received changes to its own | *Multiple copies with duplicated updates. Each application keeps its own copy of its databases, and applications communicate their changes to each other, so that each application may apply received changes to its own database. FireFox and Thunderbird are examples of this. When one of those applications gets a new certificate and private key, the user may "export" that pair to a PKCS#12 file, and then import that file into the other application. Most users never master these steps, and so have databases entirely out of sync. | ||
These workarounds for the DBM engine's limitations are sufficiently onerous | These workarounds for the DBM engine's limitations are sufficiently onerous | ||
Line 31: | Line 31: | ||
=== Where we are today === | === Where we are today === | ||
At initialization time, the application gives NSS a string that it uses as the pathname of a directory to store NSS's security and configuration data. NSS typically stores 3 | At initialization time, the application gives NSS a string that it uses as the pathname of a directory to store NSS's security and configuration data. NSS typically stores 3 DBM files in that directory: | ||
* cert8.db - stores publicly accessible objects (certs, CRLs, S/MIME records). | * cert8.db - stores publicly accessible objects (certs, CRLs, S/MIME records). | ||
Line 57: | Line 57: | ||
In the presence of a multiaccess initialization string, during initialization | In the presence of a multiaccess initialization string, during initialization | ||
NSS will try to find a shared library named librdb.so (rdb.dll on Windows) in its path and load it. This shared library is expected to implement a superset of the old | NSS will try to find a shared library named librdb.so (rdb.dll on Windows) in its path and load it. This shared library is expected to implement a superset of the old DBM interface. The main entry point is rdbopen, which will be passed the appName, database name, and open flags. The rdb shared library will pick a location or method to store the database (it may not necessarily be a file), then handle the raw database records from NSS. The records passed to and from this library use exactly the same schema and record formats as the records in the DBM library. | ||
=== The proposal === | === The proposal === | ||
Line 466: | Line 466: | ||
Mode 3A Applications are the most complicated. NSS provides some services to help applications get through and update and merge with the least interaction with the user of the application. Below is the steps a Mode 3A application should use whenever initializing NSS. | Mode 3A Applications are the most complicated. NSS provides some services to help applications get through and update and merge with the least interaction with the user of the application. Below is the steps a Mode 3A application should use whenever initializing NSS. | ||
Step 0: Preparation: collect the directory and prefix names of both the source and target | Step 0: Preparation: collect the directory and prefix names of both the source and target databases. Prepare two strings for the operation: | ||
# <nowiki>A string to uniquely identify the source | # <nowiki>A string to uniquely identify the source database, for the purpose of | ||
avoiding a repeat of this merge (making the merge idempotent). This | avoiding a repeat of this merge (making the merge idempotent). This | ||
string could be derived from the name of the application that used the | string could be derived from the name of the application that used the | ||
source | source database, from any application "instance" names (such as profile | ||
names), from the absolute path name of the source | names), from the absolute path name of the source database directory and the | ||
database prefixes, and from the last modification time of the source databases.</nowiki><br><br><nowiki> | |||
The algorithm for deriving this string should always produce the same | The algorithm for deriving this string should always produce the same | ||
result for the same set of source files, so that the code can detect a | result for the same set of source files, so that the code can detect a | ||
Line 479: | Line 479: | ||
Note: The purpose of this string is to prevent multiple updates from the same old Database. This merge sequence is meant to be light enough weight that applications can safely call it each time they initialize.</nowiki><br> | Note: The purpose of this string is to prevent multiple updates from the same old Database. This merge sequence is meant to be light enough weight that applications can safely call it each time they initialize.</nowiki><br> | ||
# <nowiki>A string that will be the name of the removable PKCS#11 token that | # <nowiki>A string that will be the name of the removable PKCS#11 token that | ||
will represent the source | will represent the source database. This string must follow the rules for a | ||
valid token name and must not contain any colon (:) characters.</nowiki> | valid token name and must not contain any colon (:) characters.</nowiki> | ||
Step 1: Call NSS_InitWithMerge, passing as arguments the destination | Step 1: Call NSS_InitWithMerge, passing as arguments the destination | ||
directory name, destination file name prefix, source directory name, | directory name, destination file name prefix, source directory name, | ||
source file name prefix, unique source | source file name prefix, unique source database identifier string, and source | ||
token name string. | token name string. | ||
Line 494: | Line 494: | ||
test for this. | test for this. | ||
* If the | * If the database slot token is not removable, then no update/merge is necessary, goto step 7. | ||
* (optional) If PK11_NeedLogin() is not true then NSS has already completed the merge for you (no passwords were needed), skip to step 7. | * (optional) If PK11_NeedLogin() is not true then NSS has already completed the merge for you (no passwords were needed), skip to step 7. | ||
* Otherwise it is necessary to authenticate to the source token, at step 3 below. | * Otherwise it is necessary to authenticate to the source token, at step 3 below. | ||
Line 511: | Line 511: | ||
#*Otherwise, continue with step 4. | #*Otherwise, continue with step 4. | ||
Step 4. Determine if it is necessary to authenticate to the target | Step 4. Determine if it is necessary to authenticate to the target database. | ||
This is done by calling PK11_IsLoggedIn for the | This is done by calling PK11_IsLoggedIn for the database slot. | ||
*If the function indicates that the | *If the function indicates that the database token is NOT logged in, then it is necessary to authenticate to the target database, with the step 5 below. | ||
*(optional) Otherwise skip down to step 7. | *(optional) Otherwise skip down to step 7. | ||
Step 5. Call PK11_IsPresent(). You may think of this step as telling | Step 5. Call PK11_IsPresent(). You may think of this step as telling | ||
you if the removable source token has been removed and the target token | you if the removable source token has been removed and the target token | ||
has been inserted into the | has been inserted into the database slot. In reality, this call makes those | ||
things happen. After this call succeeds the token name should be that | things happen. After this call succeeds the token name should be that | ||
of the target token (see next step). | of the target token (see next step). | ||
Line 535: | Line 535: | ||
====== Failures and recovery ====== | ====== Failures and recovery ====== | ||
Exception A. Application needs to decide what happens if the legacy password | Exception A. Failure to authenticate to the source database <P> | ||
Application needs to decide what happens if the legacy password | |||
is not supplied. Application can choose to: | is not supplied. Application can choose to: | ||
# continue to use the legacy | # continue to use the legacy database and try to update later. (Probably a future restart of the application). | ||
# reset the legacy database, throwing away any private or secret keys in the old database. | # reset the legacy database, throwing away any private or secret keys in the old database. | ||
# shutdown NSS and initialize it only with the new shareable database. | # shutdown NSS and initialize it only with the new shareable database. | ||
: The exact strategy for recovering is application dependent and depends on factors like | : The exact strategy for recovering is application dependent and depends on factors like | ||
:# the sensitivity of the application to | :# the sensitivity of the application to losing key data. | ||
:# possible input from the user. | :# possible input from the user. | ||
:# the likelihood that the password will every be recovered. | :# the likelihood that the password will every be recovered. | ||
</P> | |||
Exception B. Applications needs to decide what happens if the new shareable | Exception B. Failure to authenticate to the target database <P> | ||
Applications needs to decide what happens if the new shareable database | |||
password is not supplied. Application can choose to: | password is not supplied. Application can choose to: | ||
# continue to use the legacy | # continue to use the legacy database and try to update later. | ||
# force NSS to update those objects it can from the legacy | # force NSS to update those objects it can from the legacy database, throwing away private keys and saved passwords, and trust information from the legacy database. | ||
# force NSS to reset the shareable database password, throwing away private keys and saved passwords, and trust information from the shareable | # force NSS to reset the shareable database password, throwing away private keys and saved passwords, and trust information from the shareable database. | ||
</P> | |||
Notes: | Notes: | ||
Line 556: | Line 558: | ||
step 7; that is, during the call to NSS_InitWithMerge or during either | step 7; that is, during the call to NSS_InitWithMerge or during either | ||
of the calls to PK11_Authenticate. This will depend on the ability of | of the calls to PK11_Authenticate. This will depend on the ability of | ||
the code to open the necessary | the code to open the necessary databases, the presence or absence of passwords | ||
on the | on the databases, and if both have passwords, it will depend on whether they | ||
have the same password or different passwords, and when the | have the same password or different passwords, and when the | ||
authentication attempts, if any, succeed. The system tries to complete the | authentication attempts, if any, succeed. The system tries to complete the | ||
Line 565: | Line 567: | ||
2. If the attempt to open the | 2. If the attempt to open the | ||
source | source database fails for any reason, the operation will behave as if the | ||
source | source database was empty. It will record the unique source database identifier | ||
string in the target | string in the target database and act as if the merger is complete. This is similiar to what happens in all previous versions of NSS during database update. See "Database Merge" below for how to recover from this. | ||
<pre> | <pre> | ||
/* | /* | ||
Line 776: | Line 778: | ||
database. The application must be able to tell us where the old database lives, | database. The application must be able to tell us where the old database lives, | ||
since it's an application private directory compared the the multiple | since it's an application private directory compared the the multiple | ||
application shared directory that the shared | application shared directory that the shared database lives in. | ||
Flow chart of NSS update actions for Mode 3: | Flow chart of NSS update actions for Mode 3: | ||
Line 868: | Line 870: | ||
When merging databases in, it's possible (even likely), that the shared | When merging databases in, it's possible (even likely), that the shared | ||
database and legacy | database and legacy databases have the same objects. In the case of certs and keys, | ||
the merge is a simple matter of identifying duplicates and not updating them. | 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: | In the case of trust attributes, however, there are a number of choices: | ||
# don't update duplicate trust (shared database copy wins). | # don't update duplicate trust (shared database copy wins). | ||
# overwrite trust from the legacy | # overwrite trust from the legacy database (legacy database copy wins). | ||
# calculate the least common denominator trust between them (take the least trusted values). (turning off trust wins). | # calculate the least common denominator trust between them (take the least trusted values). (turning off trust wins). | ||
# calculate the most common demonimnator trust between the two (turning on trust wins). | # calculate the most common demonimnator trust between the two (turning on trust wins). | ||
Line 929: | Line 931: | ||
to do user interaction below. | to do user interaction below. | ||
If the legacy | If the legacy database 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 | it. This prompt must be clear we are asking for the master password for | ||
the running Mozilla app (Thunderbird, Firefox, Seamonkey, etc). | the running Mozilla app (Thunderbird, Firefox, Seamonkey, etc). | ||
Line 966: | Line 968: | ||
Once we have a legacy | Once we have a legacy database password, or if we determine we don't need the legacy | ||
database 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 shareable | the data that was protected by it). We need to acquire the shareable database's | ||
password so we can encrypt and MAC the data properly. If the shareable | password so we can encrypt and MAC the data properly. If the shareable database doesn't | ||
have a password we can proceed with the update without further prompting the | have a password we can proceed with the update without further prompting the | ||
user. If the shareable | user. If the shareable database has the same password as the legacy database, then we can | ||
detect that and again proceed with the update without further prompting. | detect that and again proceed with the update without further prompting. | ||
Line 1,012: | Line 1,014: | ||
Mozilla apps can create more than one profile. Developers use this capability | Mozilla apps can create more than one profile. Developers use this capability | ||
to test bugs that new users are likely to run into without | to test bugs that new users are likely to run into without losing their own | ||
production environment. | production environment. | ||
Line 1,021: | Line 1,023: | ||
couple of options. | couple of options. | ||
# Allow profiles to be marked with 'private key/cert | # Allow profiles to be marked with 'private key/cert databases. 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. | ||
# 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 application. | # 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 application. | ||
# Provide the checkbox in option 1, but make it default as in option 2. | # Provide the checkbox in option 1, but make it default as in option 2. | ||
Line 1,037: | Line 1,039: | ||
# Because merge does not require the complicated state machine to manage password acquisition, it can (and is) implemented outside the softoken itself. | # Because merge does not require the complicated state machine to manage password acquisition, it can (and is) implemented outside the softoken itself. | ||
Characteristic 3 allows database merge to work on arbitrary database types. You can merge a shareable | Characteristic 3 allows database merge to work on arbitrary database types. You can merge a shareable database into a shareable database as well as an old database into a shareable database (in fact, to a point, on arbitrary tokens - you can merge a hardware token into a shareable database as long as the keys are extractable). | ||
To merge 2 databases, the application simply opens the both databases and calls the new PK11_MergeTokens() call. PK11_MergeTokens() has the following signature: | To merge 2 databases, the application simply opens the both databases and calls the new PK11_MergeTokens() call. PK11_MergeTokens() has the following signature: | ||
Line 1,118: | Line 1,120: | ||
* directory full path to where the database lives. | * directory full path to where the database lives. | ||
* certPrefix a prefix string to add in front of the key and cert | * certPrefix a prefix string to add in front of the key and cert database names (if keyPrefix is null), null means add no prefix. | ||
* keyPrefix a prefix string to add in front of the key | * keyPrefix a prefix string to add in front of the key database name. Null means use the same prefix as the cert database name uses. | ||
* cert_version current version is the current database version | * cert_version current version is the current database version | ||
* key_version is the current key database version | * key_version is the current key database version | ||
Line 1,163: | Line 1,165: | ||
where: | where: | ||
* private is a pointer to opaque private data specific to the Shareable | * private is a pointer to opaque private data specific to the Shareable database implementation. | ||
* sdb_type is the type of database (key [aka private] or cert [aka public]). | * sdb_type is the type of database (key [aka private] or cert [aka public]). | ||
* sdb_flags specifies how the database was opened (ReadOnly, Create, etc). | * sdb_flags specifies how the database was opened (ReadOnly, Create, etc). | ||
Line 1,276: | Line 1,278: | ||
==== legacy DB support ==== | ==== legacy DB support ==== | ||
The old | The old DBM code can be supported with the above SDB structure with the following exceptions: | ||
# The old | # The old database code cannot be extensible (can't dynamically handle new types). | ||
# A private interface may be needed to unwrap the private keys, or provide a handle to the password so the keys can be presented in the attribute format. | # A private interface may be needed to unwrap the private keys, or provide a handle to the password so the keys can be presented in the attribute format. | ||
Line 1,285: | Line 1,287: | ||
* legacy_ReadSecmodDB, legacy_ReleaseSecmodDBData, legacy_DeleteSecmodDB, legacy_AddSecmodDB - These functions provide access to the old secmod databases. | * legacy_ReadSecmodDB, legacy_ReleaseSecmodDBData, legacy_DeleteSecmodDB, legacy_AddSecmodDB - These functions provide access to the old secmod databases. | ||
* legacy_Shutdown - This is called when NSS is through with all database support (that is when softoken shuts down). | * legacy_Shutdown - This is called when NSS is through with all database support (that is when softoken shuts down). | ||
* legacy_SetCryptFunctions - This is used to set some callbacks that the legacy | * legacy_SetCryptFunctions - This is used to set some callbacks that the legacy database can call to decrypt and encrypt password protected records (pkcs8 formatted keys, etc.). This allows the legacy database to translate it's database records to the new format without getting direct access to the keys. | ||
NSS will automatically load the legacy database support under the following conditions: | NSS will automatically load the legacy database support under the following conditions: |
edits