NSS Shared DB And LINUX: Difference between revisions

 
(20 intermediate revisions by 4 users not shown)
Line 6: Line 6:


rv = NSS_InitReadWrite(“sql:/etc/pki/nssdb”);
rv = NSS_InitReadWrite(“sql:/etc/pki/nssdb”);
[Can we have a macro for this, e.g. NSS_DEFAULT_DB or somesuch?]


There are 3 classes of Exceptions.  
There are 3 classes of Exceptions.  
Line 22: Line 24:


The application should then follow the automatic merge instructions in the shared database documentation.
The application should then follow the automatic merge instructions in the shared database documentation.
(NSS_InitWithMerge() only works if a shared db already exists at the target directory [https://bugzilla.mozilla.org/show_bug.cgi?id=465709 Bug#465709] so it needs to be created first using NSS_Initialize? - bob: no, bug 465709 is a bug and should be fixed for this to plan to work. )


3. The third exception is applications that must have a separately managed environment. Typically these applications would have a mode (probably default) which would open NSS normally, but could be configured to use their own NSS environment. The options to use the system or private environment should not be hard coded in the application, but should be under user/administrator control. Applications of this class would include Server products or test modes of application products (like Firefox profiles). In this mode the application should initialize NSS with it's traditional Init call, passing in the appropriate private database.
3. The third exception is applications that must have a separately managed environment. Typically these applications would have a mode (probably default) which would open NSS normally, but could be configured to use their own NSS environment. The options to use the system or private environment should not be hard coded in the application, but should be under user/administrator control. Applications of this class would include Server products or test modes of application products (like Firefox profiles). In this mode the application should initialize NSS with it's traditional Init call, passing in the appropriate private database.


On Linux, the effect of the above initialization (which one?) will be to:
On Linux, the effect of first initialization as well as exceptions 1 or 2 will be to:


#Open a database in the home directory of the user running. With the flags specified by the application (probably ~/.pki/nssdb).
#Open a database in the home directory of the user running. With the flags specified by the application (R/W, Optimize space, etc).
#Load any User specified PKCS #11 modules.
#Load any User specified PKCS #11 modules (chosed by the OS).
#Open the system database in /etc/pki/nssdb readonly.
#Open the system database in /etc/pki/nssdb readonly.
#Load any System specified PKCS #11 modules.
#Load any System specified PKCS #11 modules (specified in /etc/pki/nssdb/pkcs11.txt).
#Load the NSS builtins module.
#Load the NSS builtins module.


How this happens will be explained later, but first we discuss where the requirements for the above come from.
How this happens will be explained later, but first we discuss where the requirements for the above come from.
[#1 is alarming, and looks like black magic. Why, when I tell the API to look in /etc/pki, should I expect it to look anywhere else? This always happens, /etc/pki/nssdb has a file called pkcs11.txt that loads all the databases/modules related to opening that directory. The change here is softoken can now automatically open more then one itself.]


= Requirements by Package Type =
= Requirements by Package Type =
Line 51: Line 53:
User applications should open NSS using a shared database stored in ~/.pki/nssdb in the user's home directory. If the application needs to store new certificates (like a web browser), then it should open this database read/write. User's local preferences would be stored in this database. Changes the application wants to make will occur in this database. Any user specified tokens would also be stored in this database.
User applications should open NSS using a shared database stored in ~/.pki/nssdb in the user's home directory. If the application needs to store new certificates (like a web browser), then it should open this database read/write. User's local preferences would be stored in this database. Changes the application wants to make will occur in this database. Any user specified tokens would also be stored in this database.


In addition, the application should own the system database /etc/pki/nssdb. This database should be opened read only. The user will typically not have permission to modify this database. This database will provide system level defaults for tokens to load and root certs to trust. This gives us hooks form things like IPA to manage and distribute trusted root certs system wide.
In addition, the application should open the system database /etc/pki/nssdb. This database should be opened read only. The user will typically not have permission to modify this database. This database will provide system level defaults for tokens to load and root certs to trust. This gives us hooks form things like IPA to manage and distribute trusted root certs system wide.
 
[I'm almost certain there's a typo there - how can every application *own* the system database? Don't you mean *open*? - bob: you are correct, changed.]
 
[How does an application open first the user database at ~/.pki/nssdb, with NSS_InitReadWrite I presume, and then opens the system database in /etc/pki/nssdb? Since the NSS intialization calls are idempotent, does it need to use NSS_InitContext to accomplish this?]


== Type 2 packages: Services applications ==
== Type 2 packages: Services applications ==
Line 60: Line 66:


Option 3: Either option 1 or option 2 except the 'user' database for the server isn't necessarily stored in ~/.pki/{server_user}, but is configurable for each server.
Option 3: Either option 1 or option 2 except the 'user' database for the server isn't necessarily stored in ~/.pki/{server_user}, but is configurable for each server.
[Option 1 certainly makes the least sense. The point behind PK crypto is that public keys can be public and private keys must be private. Storing every services' private keys in a shared DB that everyone has equal access to seems counterproductive. - bob: agree, it's probably a bad idea to put key material in /etc/pki/nssdb for more than one reason, though it may make sense for servers to have a shared key store (between other servers) along with a private one.]


== Type 3 packages: Libraries ==
== Type 3 packages: Libraries ==


Type 3 packages should open ~/.pki/nssdb and /etc/pki/nssdb read only. If the packages are stand alone, this should be sufficient. If the packages are part of a bigger application, then it should follow the needs of that bigger application.
Type 3 packages should open ~/.pki/nssdb and /etc/pki/nssdb read only. If the packages are stand alone, this should be sufficient. If the packages are part of a bigger application, then it should follow the needs of that bigger application.
[Is the order of initialization important? order only has a tangential effect (what slot the DB's wind up in. What happens when the library opens things read-only, but it's linked into an application that wants read-write access? What happens when the lib is init'd first? What happens when the app inits NSS first? Most of these issues are handled in the multi init call, but the short answer is if a database is opened ro and it needs to be opened r/w,  we will open the database again, r/w]


== Summary of Requirements ==
== Summary of Requirements ==
Line 106: Line 116:
* How does a library know if it is the first caller of NSS?  Does it need to know?
* How does a library know if it is the first caller of NSS?  Does it need to know?
** [ There is already a call to tell if NSS is already initialized. I don't think knowing that info, however, solves all the problems. The primary problem it doesn't solve is how to deal with shutdown. It probably solves the 97% case, which is bad because we may not trip over the 3% case until someone makes it a firedrill. ]
** [ There is already a call to tell if NSS is already initialized. I don't think knowing that info, however, solves all the problems. The primary problem it doesn't solve is how to deal with shutdown. It probably solves the 97% case, which is bad because we may not trip over the 3% case until someone makes it a firedrill. ]
*** This is the approach I've taken with OpenLDAP libldap - if NSS was already initialized when we started, we will not call NSS_Shutdown when we're torn down. If whoever initialized NSS doesn't clean up properly, it's not our fault and there's nothing we can do to help the situation. But obviously that means setup and teardown have to occur in the correct order in the app.


= Other comments =
= Other comments =
Line 112: Line 123:
** [The primarily tie is the suggestion that apps open /etc/pki/nssdb, and the expectation that the OS will supply appropriate code so that a user specific database will be opened when one opened /etc/pki/nssdb. It's true that any OS can implement this proposal. Some OS's may chose a different path for /etc/pki/nssdb [Windows will certainly have to, Mac probably would as well, though they wouldn't need to]. The purpose was to nail down the exact specifics for Linux, and thus the title I initially gave it.]
** [The primarily tie is the suggestion that apps open /etc/pki/nssdb, and the expectation that the OS will supply appropriate code so that a user specific database will be opened when one opened /etc/pki/nssdb. It's true that any OS can implement this proposal. Some OS's may chose a different path for /etc/pki/nssdb [Windows will certainly have to, Mac probably would as well, though they wouldn't need to]. The purpose was to nail down the exact specifics for Linux, and thus the title I initially gave it.]
* in the old dbm days, secmod.db was combined in the softoken PKCS #11 module primarily because that's where the dbm code was. With the sql database, it's possible to separate the moduleDB load from softoken. That might be a good plan for 3.13, removing yet more code from the cryptographic boundary of NSS.
* in the old dbm days, secmod.db was combined in the softoken PKCS #11 module primarily because that's where the dbm code was. With the sql database, it's possible to separate the moduleDB load from softoken. That might be a good plan for 3.13, removing yet more code from the cryptographic boundary of NSS.
* IMO, hardcoding magic behavior like this (open two locations when only one path was passed into the API) is a mistake. It's obvious that /etc/pki/nssdb is "special" and the API ought to highlight this fact. There should be a distinct API call for initializing the system default location, separate from the call for accessing a user-specified configuration, and every app/caller that needs instance-specific configuration should explicitly call both APIs.
**[bob:It's only special because the 'system' configured it to be special. I can set *any* directory up to do exactly this without change to NSS. What's important is it's a single roundevous point. If your app has a config file that selects the NSS database, you can force that app into the new scheme by adding sql:/etc/pki/nssdb in that config file. NOTE: you will not find the string /etc/pki/nssdb anywhere inside NSS itself]
*The overall feel I get from reading this page is still that NSS was designed for single-user client usage, and server/library usage are a hasty afterthought. The only way to get away from the NSS_Shutdown problem is by introducing new APIs that are specifically designed for these new use cases, and punting backward compatibility. (I.e., stability of apps that only use the existing APIs cannot be guaranteed in this new environment.)
[bob: This is not supposed to address *that* issue. The idea here is that control of what gets opened or not now rests with the OS (under administrator control). Many of the issues you were looking for are in the multinit proposal]
E.g.: use a distinct API call to initialize the default /etc/pki/nssdb database. Refcount all DB opens. Use a distinct API call to close each database, instead of a one-call-destroys-everything Shutdown. Use an atexit() or similar destructor to make sure that Shutdown on hardware tokens occurs if an app exits without cleaning up nicely. (You're still SOL if you get SIGKILL but you always were...)
[bob: several of these are in the multi init proposal] [[NSS_Library_Init|here]]
14

edits