MIT Information Systems

Macintosh Development

[Home] [About Us] [People] [Information Systems]
[Kerberos for Macintosh] [Applications] [Miscellaneous Documentation]

KerberosLogin Principal Translation Plugin API

Purpose of principal translation plugins

A principal translation plugin provides realm-specific principal translation. For example, if a realm allows the users to type their full names into the Kerberos Login dialog and looks up their Kerberos principals in an outside database (such as the Dartmouth Name Directory), then the administrators of that realm can provide a plugin to perform the translation.

Principal translation plugins are invoked by the Kerberos Login library whenever a string needs to be converted to a Kerberos principal. For example, the translation is applied to the name, instance, and realm entered by the user into the Kerberos Login dialog.

Configuration of principal translation plugins

In order to activate a principal translation plugin for a realm, the realm stanza in the Kerberos Preferences file has to include a principal_translation line:

    principal_translation = "PluginName"

On that line, PluginName, should be a unique string describing the plugin. The string must not be longer than 127 characters.

The plugin file itself has to be located in the same folder as the Kerberos Library, on Mac OS 8 and 9. The location of the plugins under Mac OS X hasn't been worked out yet.

Format of principal translation plugins

A principal translation plugin is a Code Fragment Manager shared library file of type 'PTrn'.

The shared library file can contain any number of fragments. When loading the plugin, the library will attempt to load either the fragment whose name is PluginName, if running under Mac OS 8 or 9 inside a non-Carbon application, or PluginName;Carbon, if running on Mac OS X, or inside a Carbon application on Mac OS 9 (where PluginName is the name of the plugin as specified in the preferences file). Therefore, in order to be useful, the plugin file has to contain a fragment of the appropriate name. Note that Carbon plugins will not be loaded in a non-Carbonized application under Mac OS 8 and 9, and therefore, you must provide a plugin file containing both a Carbonized and non-Carbonized version of your translator if you want your plugin to work on Mac OS 8, 9, and X.

The plugin must export three functions, which are detailed in the next section.

The plugin can contain any other code, data, or resources, but it should be mindful of the fact that it may run in any application's heap under Mac OS 8 and 9, and therefore should handle low memory gracefully.

Functions exported by principal translation plugin

All three of these functions must be exported by every principal translation plugin. All functions use C linkage and standard CFM PPC calling conventions.


OSErr KerberosLoginPrincipalTranslation_InitializePlugin (
    UInt32          inAPIVersion);

This function is called by the Kerberos Login library when the plugin is loaded. The function must return noErr only if the plugin understands the API version passed in inAPIVersion; otherwise, it should return paramErr.

If this function returns anything but noErr, the other functions will not be called.

For example, a plugin which only understands the version 1 of the API (which is the current version), would do this:

KLStatus KerberosLoginPrincipalTranslation_InitializePlugin (
    KLPT_APIVersion      inAPIVersion)
    if (inAPIVersion == kKLPT_APIVersion1) {
        return noErr;
    } else {
        return paramErr;


KLStatus KerberosLoginPrincipalTranslation_TranslatePrincipal (
	const char*     inName,
	const char*     inInstance,
	const char*     inRealm,
	const char**    outName,
	const char**    outInstance,
	const char**    outRealm,
	KLBoolean*      outChanged);

This function performs principal translation. On input, inName, inInstance, and inRealm point to the components of the untranslated principal as C strings.

The function translates the principal components, and returns the translated components as newly allocated C strings in *outName, *outInstance, *outRealm. The memory for the translated components is allocated by this function.

The translation function must satisfy the following two constraints:

In other words, if the function is called to translate a principal, it must return a valid Kerberos principal. If it is called again, this time with the principal it returned, it must return it again, unchanged.

This property is also known as idempotency. When you are debugging your plugin, you should test it from the debugging version of the Kerberos control panel (Kerberos.debug). Then your plugin will be explicitly tested for idempotency, and you will take a trip to MacsBug if your plugin fails the test. Currently this test only works under Mac OS 9, but that will change in the future.

If the principal translation is successful, the function sets *outChanged to true, and returns noErr.

In case no translation is necessary, the function may return false in *outChanged, in which case the values returned in *outName, *outInstance, *outRealm will be ignored by the Kerberos Login library. The function is not obligated to take this shortcut -- it can also just copy the old components into new memory. It must not, however, just return pointers to the input components in the output components without allocating memory for them.

If the functions fails to perform the translation, it should return an appropriate error code and leave all outputs unchanged. For more information on error handling in principal translation plugins and reporting error messages to the user, see the error handling section below.

If an error occurs, the function should clean up after itself and leave all output components unchanged.

For example, a plugin which removes trailing letters 'x' from a principal would work like this:

OSErr KerberosLoginPrincipalTranslation_TranslatePrincipal (
    const char*     inName,
    const char*     inInstance,
    const char*     inRealm,
    const char**    outName,
    const char**    outInstance,
    const char**    outRealm,
    Boolean*        outChanged)
    *outChanged = false;
    OSErr err = noErr;

    UInt32  nameLength = strlen (inName);
    UInt32  instanceLength = strlen (inInstance);
    UInt32  realmLength = strlen (inRealm);

    char*   newName = NewPtr (nameLength + 1);
    char*   newInstance = NewPtr (instanceLength + 1);
    char*   newRealm = NewPtr (realmLength + 1);

    if ((newName == nil) || (newInstance == nil) || (newRealm == nil)) {
        err = memFullErr;
    if (err == noErr) {
        strcpy (newName, inName);
        strcpy (newInstance, inInstance);
        strcpy (newRealm, inRealm);

        // Remove trailing 'x'
        for (UInt32 i = 0; i < nameLength; i++) {
        	if (newName [nameLength - i - 1] == 'x') {
        		newName [nameLength - i - 1] = '\0';
        	} else {

        *outName = newName;
        *outInstance = inInstance;
        *outRealm = inRealm;

        *outChanged = true; 
    } else {
        if (newName != nil) {
            DisposePtr (newName);

        if (newInstance != nil) {
            DisposePtr (newInstance);

        if (newRealm != nil) {
            DisposePtr (newRealm);
    return err;


void KerberosLoginPrincipalTranslation_ReleasePrincipal (
	const char*     inName,
	const char*     inPrincipal,
	const char*     inRealm);

This function is called by the Kerberos Login library to release the memory allocated by the principal translation function. It is only called if the principal translation function returned noErr.

For example, the plugin example above, which allocated all three components with NewPtr() would release them like this:

void KerberosLoginPrincipalTranslation_ReleasePrincipal (
    char*   inName,
    char*   inInstance,
    char*   inRealm)
    DisposePtr (inName);
    DisposePtr (inInstance);
    DisposePtr (inRealm);

Error handling in principal translation plugins

KerberosLoginPrincipalTranslation_TranslatePrincipal() is allowed to return its private error codes. This error code will be propagated to the caller of the Login library, which in turn calls KLGetErrorString() to translate the error into a message for the user. The private error codes must not conflict with any existing Mac OS error codes.

In order to allow the login library to translate plugin's error codes into user messages, the plugin has to register an error table with the Error library. From the plugin's CFM initialization function, the plugin can discover the FSSpec of its library file, and pass that into Error library's RegisterErrorTable. After that, errors returned by the plugin will be mapped to the strings in the plugin's error table.

Questions or comments? Send mail to
Last updated on $Date: 2003/11/19 20:42:24 $
Last modified by $Author: smcguire $