Namespaces and inter-library private symbols

Nicolas Williams Nicolas.Williams at
Tue Nov 10 15:14:57 EST 2009

On Tue, Nov 10, 2009 at 02:08:18PM -0500, ghudson at wrote:
> I'd like to get a consensus on how we should handle library functions
> which are not part of the public API but are used by other parts of
> the tree.  Currently, we inconsistently do one of three things:
> 1. Use the accessor.  (Examples: ASN.1 encoders as used by the pkinit
> module; HMAC as used by gss-krb5.)

I don't mind this, but it'd be nice to have a set of macros to hide the

> 2. Name the function krb5_foo, export it, but prototype it in k5-int.h
> instead of krb5.h.  (Examples: krb5_get_cred_from_kdc as used by ksu;
> krb5_free_realm_tree as used by kdc.)

I don't mind this either.

> 3. Name the function krb5int_foo, export it, prototype it in k5-int.h,
> and use it directly from the other part of the tree.  (Examples:
> krb5int_cc_default as used by gss-krb5; krb5int_init_context_kdc as
> used by kdc and libkadm5.)

Nor this.  But I prefer (2), slightly.

> I would like to better understand why we have the accessor and when it
> should be used, if ever.  I consider it an overly heavyweight solution
> to the problem.  Tom tells me that the initial justification had
> something to do with Windows, but he didn't have details.

*shrug*.  It's not heavyweight, but, rather, a way of building your own
light-weight run-time linker.  It's... OK, not great, but there's
precedent (e.g., PKCS#11 is meant to be used in a similar way).

What you call the "accessor" approach may be particularly useful when
you might risk interposition at run-time and you want to ensure that you
don't (you dlopen() the exact object you want, dlsym() each function
from it, or a single function that outputs a pointer to a struct
containing the necessary function pointers).

> I think we have a partial consensus that (2) is bad, because those
> symbols can show up as available in an autoconf test even if they
> aren't part of the API in that version of Kerberos.  We've continued
> to add new examples of (2) in recent work, however--examples are
> krb5_c_weak_enctype (recently renamed to krb5int_c_weak enctype) and
> krb5_get_credentials_for_proxy.

I don't think (2) is bad.  Here's why: you must export symbols as far as
the _linker_ goes, no matter which of (1), (2), or (3) you pick, and in
_all_ cases you depend on a private header to obtain access to the
necessary C function prototype declarations -- (2) fits the bill with
minimal impact on the existing source.

The prefix that indicates "internal" is somewhat useful -- you know
instantly by looking at a function if it's internal -- but, what is
"internal"?  Internal to a single library?  To all of MIT krb5?  To
third-party code that has an "interface contract" with MIT krb5?  How
many prefixes do you actually need?

> I would like to see us move towards using (3) uniformly.  If I receive
> no feedback, I will document this as the preferred practice in
> and
> start converting cases to that form as I run into them.

Certainly having a single style adopted uniformly would be good.

> A fourth option is to invent a new namespace for inter-library private
> symbols, so that we can easily differentiate between "internal to this
> library" and "internal to the krb5 tree."  That might result in a lot
> of symbol renaming over time, though.

You can't invent a new namespace, only a new naming convention.  I
recommend against it.  I recommend that you concentrate efforts on
actual, useful features and bug fixes over mass symbol rename


More information about the krbdev mailing list