Wallet Implementation Notes

Introduction

Collected here are implementation notes about design decisions, external interfaces, integration, internal structure, and related issues. This document will mostly be of interest to people who want to modify the wallet code or who are curious about its design.

This is now mostly of historical interest. For information about how the wallet now works, see the documentation for each of the server classes, the other design documents, and the man pages for the programs. Some portions of this document may be inaccurate or not reflect how the wallet system is currently implemented.

Server Issues

Interface

We need two interfaces for retrieving items, one which retrieves the current stored item and one which generates a new item. This particularly applies to keytabs. We also don't want new keytabs to be generated for certain keys even by accident without an explicit action taken, but for most keytabs we want to generate new keys each time. So we need an interface like:

get keytab

Generates a new keytab normally, but retrieves the existing keytab if we've marked the key as unchanging.

flag set unchanging
flag clear unchanging

Change the state to generate new keytabs each time or always try to pull the existing key. This operation should probably be privileged.

So if you want to generate a new key for a keytab that would otherwise be persistant, mark it changing, download the new key, and then mark it unchanging again.

Possibly need to do something about occasionally changing keys of keytabs that are otherwise marked unchanging, or we're going to open ourselves to brute force attacks.

ACL Management

Supported operations are: get, store, create (possibly triggered by a get or store of something that didn't already exist), destroy, show, and setting or clearing flags. Each of these need a separate ACL potentially. Not sure if we're going to need separate ACLs for each flag operation.

Administrators get implicit access to do anything except get and store. They can give themselves get and store access just by changing ACLs, of course, but it encourages sloppy ACLs to let them get and store without an explicit ACL (administrators then end up relying on that privilege and not reflecting it in ACLs). There does need to be an ACL on create, but that should probably be implemented via some sort of policy callout. The user will write a simple Perl function that returns a default ACL given the object type and name if the object doesn't already exist.

Owner rights provides get, store, show, and destroy, but not setting or clearing flags. This can be overridden by more precise ACL settings. So the ACL logic would go like this:

I think the owner abstraction is worth it over just setting the ACL for get, store, and show.

Flags

locked      --  No operations permitted except show
unchanging  --  Pull existing value from file store

For backends like secure files, all values are unchanging implicitly, but I don't think we should represent this by setting flags on every instance of those backends; it's just confusing and doesn't provide more information. In other words, unchanging is only meaningful for backends that normally dynamically generate new keys on get, like the keytab backend.

Expiration

The database has a field to store an expiration date for every object. We can implement expiration methods in the backend to automatically destroy some objects (or perhaps lock them) when they pass their expiration date, but a more useful method might be to provide warnings when objects are about to expire via warning methods for a backend that take the object name and the expiration date. This would be great for certificates, for instance.

Not clear whether every get and store should check the expiration or just a nightly cron job that blows away or locks objects when they pass their expiration.

Keytab Backend

As of the deployment of the wallet, we want to stop limiting nearly all keytabs from being forced to single DES keys. We're probably still going to have some keys for which only particular enctypes are permitted, however. This means keeping a side table of allowable enctypes per keytab name, where if there are no entries in the table we allow any enctype. We can pass a list of enctypes into kadmin when doing the principal creation or randomization, separated by spaces and enclosed in double quotes.

When creating a new principal with addprinc, pass the -clearpolicy flag. Otherwise, the principal will be placed in the default policy and will be subject to password strength checking, and the initial password used with -randkey will fail.

Whenever we generate a new keytab, we may need to push the key into K4. We could make the client send a flag saying whether they want synchronization with K4, but it's easier to just always do it (except maybe for some exception cases). The user doesn't have to ask the client program for the srvtab if they don't want it, and it doesn't hurt to create the KDC entry. We use kasetkey for this.

Certificate Creation

We probably want to handle all requested certificates from Comodo using this interface since we can use its expiration handling to do warnings and since that way users can re-download the certificate any time they want. Certificates are actually pairs of certificate and key, though, and we need to figure out what we're storing. There is the key, which we want to be able to store but we don't really do anything with (except ideally it's associated with a certificate), there's the CSR (which we could reuse for renewals although that doesn't get people to change their key), and there's the certificate itself (which is actually public data).

People seem to like to have CSRs kept around, but I don't understand why and need to investigate this further. It makes more sense to me to generate a new key every time the cert is renewed, for additional security.

We may be able to just store a file that contains both the key and the public certificate and change our practices on web server configuration to point them at the combined file.

Cleanup of Old Entries

We should periodically scan the wallet for host-based entries for hosts that aren't in NetDB. Rather than removing them immediately, wait until we haven't seen the host for several consecutive passes and then purge them. Send notification of the hosts that are being purged (and maybe of the hosts that will be purged soon if nothing happens), although that raises the question of where to send the notification.

Client Issues

Command-Line Options

Some of the specific data types are going to need their own flags to operations like get. As an example, the keytab get operation will need an optional flag to specify the srvtab file to which to also write the key, and will need an optional flag specifying the time delta at which old kvnos should be pruned from the keytab. These flags need to be globally unique in the wallet client so that we can use a naive option parser. It would also be nice to support the flags anywhere in the command and not go down the weird CVS route of flags meaning different things in different places.

Keytab Handling

The server is going to hand the client a keytab that contains the current keys for the given service. Unless the keytab was marked as unchanging, these entries will have a higher kvno than any keys already in the keytab on the local system.

The only interfaces to read keytabs require a file, so the client will need to save the keytab to a temporary file in order to extract individual keys. If there is no keytab on the local system in the path given to the wallet, this is simple; just write the keytab as returned by the server into the file.

If the keytab already exists, we want the following behavior:

We want to try to add the new keys first to minimize the outage window where service tickets handed out by the KDC aren't recognized by the host. Adding the keys does just append them to the end, but we probably have to clean out any keys with the same kvno first. That's a rare case, so I don't think we have to worry about the outage window there.

Srvtab Handling

If a srvtab was requested, we search for the key in the new keytab that has an enctype of ENCTYPE_DES_CBC_CRC and then write it out to a srvtab file. The MIT Kerberos library doesn't support writable srvtabs in the keytab backend, so we roll that ourselves.

Look at src/lib/krb5/keytab/kt_srvtab.c in the MIT Kerberos source for the format of a srvtab file (see the end of that file).

The kvno that we get from K5 may have no bearing on the kvno in K4. In order to get the K4 kvno, use the new key to obtain a K4 service ticket for ourselves and then read the kvno off that service ticket. There are other approaches, but the other approaches all require changes to the server side as well, whereas this is self-contained in the client and can be more easily dropped when we drop K4.

License

Copyright 2006, 2007, 2008, 2013

The Board of Trustees of the Leland Stanford Junior University

Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.

Converted to XHTML by faq2html version 1.33