How to extend kadmin

Nicolas Williams Nicolas.Williams at
Mon Oct 26 16:51:13 EDT 2009

On Mon, Oct 26, 2009 at 03:44:58PM -0400, ghudson at MIT.EDU wrote:
> We've had some private discussions recently about how to best extend
> kadmin, prompted by the account lockout work.  I'm bringing this to
> the larger community.
> There are three plausible ways to extend kadmin:
> 1. Bump the api_version, which is communicated to the server through
> the init_2 RPC when a connection is established.  This has now been
> done three times: twice before the code was incorporated into the MIT
> tree in 1996, and once for the lockout code.  The api_version is
> explicitly chosen by the caller.  Support for API versions 0 and 1 was
> removed from the trunk (by me) in August 2009.

This doesn't achieve much.  You could not, for example, change the
arguments/results of any RPCs this way.

> 2. Bump the struct_version.  This field's value is determined by
> admin.h, rather than the caller.  Its value is passed to the
> kadm5_init functions but is never communicated to the server.  The
> struct_version has never been bumped before; when the principal
> structure was changed prior to 1996, the OpenVision developers
> apparently chose to bump the api_version instead of the
> struct_version.  Because the struct_version is not communicated to the
> server, protocol compatibility would demand that this mechanism be
> used in combination with (3) below.

This also doesn't achieve much: at most it tells the implementation to
expect the caller to call various extensions (new functions).

> 3. Define new RPCs.  This was done once in 1998 when keysalt support
> was added to chpass_principal, create_principal, setkey_principal, and
> randkey_principal.  The client side of those functions choose whether
> to use the new or old RPCs depending on whether keysalts are
> specified.  I do not currently know whether the GSSRPC encoding allows
> a client to try a newer RPC and then fall back to an old one--that is,
> I don't know if the server can try and fail to process an unknown RPC
> type and still keep the connection in sync.

This is fine, and a very reasonable way forward.  Yes, if you call an
undefined RPC you get an error (the server doesn't blow up; the client
doesn't blow up).

> The api_version bumps from 1->2 (ancient history) and 2->3 (lockout)
> both correspond to structure changes.  The encoding of a
> principal_ent_rec changed from 1->2 and the encoding of a
> policy_ent_rec changed from 2->3.  To accomplish this, the output of
> rpcgen was hacked to pass the version number into the relevant
> encoding functions and conditionalize on the version.  As a result,

I know.  That's... horrible.  Well and truly horrible.

> the MIT tree has never generated the kadmin RPC encoders at build or
> distro-preparation time; we have always stored modified rpcgen C
> output in the source tree.  I am told that Sun uses rpcgen at build
> time instead (they removed api v1 support in order to do this), and
> that they may have trouble with the lockout code in its current form
> as a result.

No, we don't even have a .x for the kadmin protocol (as none can now be
constructed).  Incremental propagation does use a .x file and rpcgen-
generated code.

> I don't personally have a strong opinion as to how this should work.
> I have never been a fan of the RPC model of network protocols, so for
> me this is a question of how to make the best of an architecture I
> wouldn't have chosen.

There's also:

4. Bump the RPC program version number (and start fresh).

Given the code you already have, more of the same (see (3)) is probably
the most expedient way forward.  If you could re-write that code I'd say
go with (4), and this time have clean XDR and rpcgen-generated
marshalling code.

IMO there are few serious problems with ONC RPC, mostly: a) the fact
that implementations tend to be _synchronous_, even though nothing about
the protocol framework requires it, b) the RPCSEC_GSS API we have sucks.
The rest is fine.

Think of XDR-the-syntax as ASN.1-lite, and XDR-the-encoding as like a
PER with four octet alignment for XDR-the-syntax-as-ASN.1-lite (that's
actually very close to the mark, IMO).  Now, what is wrong with that?
Would you really prefer the full power of ASN.1?  (In some cases I
would, but not for kadmin.)  Would you really prefer BER/DER/CER?  (Same

ONC RPC/XDR comes with a compiler that works and has worked for decades,
though the compiler doesn't generate high-performance code (but for this
it's just fine).  The RPC framework has been contributed (dunno the
exact terms, but you do, I'm sure) to MIT, so the implementation is
free, including, I think, the compiler.

You're going to need an encoding for any kadmin extensions.  You get to
choose whether to use an off-the-shelf encoding or a hand-crafted one.
If the former you also get to choose whether to use a formal syntax or
hand-craft the code.  If you want to minimize security bugs you should
use a formal syntax and a compiler and run-time.  You don't have a whole
lot of options in that department.  ASN.1 is great, but until you have a
compiler that you can use in MIT krb5, forget it -- it's bad enough that
you have to hand- craft ASN.1/DER code for every Kerberos extension that
comes along.

In this case, I'm afraid that the most expedient option is (3): more of
the same.  That's unfortunate.


More information about the krbdev mailing list