Subject Re: [Firebird-Architect] Security Plugins: An Architecture
Author Jim Starkey
Pavel Cisar wrote:

>Ok, but your spec is more a sketch than complete RFC, so it's a little
>bit harder to get a handle on it for us less experienced. Well, let me
>try again to get into it.
There is also a working prototype in Vulcan. See src/jrd/SecurityDb.cpp.

>If it's really as described above, then I like it a lot. This basic idea
>is very simple but very flexible. Unfortunately, there are some points in
>your spec that are not clear to me.
>What's not clear from your spec is how many chains and at what levels
>there could be. Chain of SP instances reflects the particular set of
>configuration values, so if there could be various configuration chains /
>cascades simultaneously applicable on a running system, there definitely
>must be more chains of SP instances (or am I wrong ?)
There is the full order of battle for establishing a database
connection through the configuration file:

1. The Y-valve does a lookup for an configuration object of type
"database" and a name that matches the user given database name.
2. The Y-valve looks up the attribute "provider" in the database object.
3. The Y-valve iterations through the provider names looking for an
configuration object of type "provider" that matches the given name
4. The Y-valve looks up the attribute "library" in the provider object
5. The Y-valve iterations through the libraries listed until one loads
6. The Y-valve calls the "attachDatabase" method of the loaded
provider passing it, among other things, the database and provider
configuration objects. ( If the call succeeds, the Y-valve is done)
7. The engine provider (aka The Engine) links the object
configuration object so subsequent attribute lookups will cascade
to the provide configuration if they can't be found the database
8. The engine provider (aka the engine) calls to the database manager
with the database name. The database manager either returns an
existing instance of the Database object or creates a new one.
9. The Database constructor receives the chained configuration object
and looks up a SecurityManager attribute
10. If a SecurityManager attribute if found, it looks for a
configuration object of type "SecurityManager" with the name give.
11. If an object is found, the Database looks up "library" and
iterates through the libraries listed (a builtin name match will
short circuit the lookup)
12. If the plugin library can be loaded, it is spliced into the
configuration chain between the database and provider
confiiguration objects

Whew! So, a) lots of plugins can be listed, b) they're loaded in the
order listed, c) there is one chain for the engine, and d) nobody but
the engine uses security plugins. Each plugin has full access to the
configuration chain which will be searched in the order:

1. Database object
2. Security plugins in the order listed
3. Provider object
4. Global attributes

The configuration file subsystem knows nothing of object type or
attribute names until queried, so security plugins can have any
attributes they wish.

[Note: in writing that, it became obvious that a config file
SecurityPlugin is required so an error can be thrown if the plugin can't
be loaded]

>I guess that each active database would definitely have it's own SP chain
>(at lest I read your spec that way). But is it possible for server or
>engine to have its own chain (that doesn't extend to db level) ? It may
>make sense. For example server may have wire comm. encryption SP, and not
>all server comm. is tied to active db attachment, so db level chain can't
>be used.
No, neither the Y-valve, the server, or remote objects use security
plugins. Security plugins are specific to the database engine(s).

>Next in the pipe is how FB code calls SP's...
>If I understood you correctly, a SP chain can contain SP's of different
>types (even those that are not yet invented), hence with different
>interfaces. Is not clear from your spec how it's supposed to be handled.
The database object as a pointer to the head of the security plugin
chain. At initialization time, it determined the version level of the
aggregate chain (lowest version number of all plugs). All calls to the
security subsystem go through the database object. When a call is made
that wasn't defined in the first version, the database object checks the
chain version number and ignores the call (yes, this means that a very
old security plugin can disable a new one). If the version is OK, it
calls the head of the security provider chain, and somebody does something.

>A detail, of course, but IMO very important one. We can't use one big SP
>interface enhanced with new calls whenever we come up with new SP type or
>fix old one. When SP's would support COM interfaces or similar method of
>introspection, then they could be handled by single chain very easily,
>but there are other possibilities.
If you think about, any SecurityPlugin that can't handle an interface
breaks the chain and can't be used. But because every plugin inherits
from SecurityPlugin, it automatically handles all entrypoints defined at
the point in the code base. COM style negotiated interfaces don't bring
anything to the table. Bottom line: any give security plugin doesn't
need to worry about the whole API because it inherits from someone who does.

>Pure class hierarchy should work too,
>but multipurpose SP's would need to use multiple inheritance, and I'm not
>sure how good it would work with late binding and dynamic libraries as
>i'm not a C++ developer. Would be nice to know what method you have in
Multiple inheritence is mother nature's way of telling you that your
design is wrong. Single inheritence works just fine in this case.

>Sidenote: That bring us to your proposed general interface for SP. There
>is IMO no point to place userInfo and updateAccountInfo into general SP
>interface as they belong to authentication SP interface, or did I miss
>something here ?
See above.

>What is also important to know is how connection between calling code and
>SP would be handled. Well, there is a chain of SP's where called SP pass
>the unhandled call to next one, but is it practical to do that on every
>call ? I think that in many cases it's not practical, because once the
>responsibility who will handle the call is sorted out, there is no gain
>to do that again until context changes, so direct binding to particular
>SP entry point is beneficial.
Not at all true. When I get to it, all physical I/O will go through the
chain to enable an encryption plugin. Many potential plugins will want
access to the database file name string which they get from the chain.
The encryption plugin will want to encrypt and decryption on page writes
and reads but not do physical I/O. But we may have a plugin that
handles physical I/O for a file on either an encrypted file systems or
something like IBM's intrusion resistent secruity module. Who knows?
The idea is that many guys might handle a single call before or after
passing it down the line. There is no way the engine can possibly
understand this.

>Here is also the point where the idea of Security Manager comes into play
>again. SM would act as a single point of call from code to whole SP
>chain. It can handle the pass the call around or direct binding
>transparently (among other thing).
I don't think this is necessary.

Pavel, thanks for your thoughtful comments.

[Non-text portions of this message have been removed]