First pass at KLL shim layer. (no private apis)
authorAlexandra Ellwood <lxs@mit.edu>
Wed, 1 Oct 2008 07:56:57 +0000 (07:56 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Wed, 1 Oct 2008 07:56:57 +0000 (07:56 +0000)
KIM support for KLL shim layer.

Fixed a bug where the cli support was double freeing a credential
in the change password case.

ticket: 6055

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20789 dc483132-0cff-0310-8789-dd5450dbe970

src/kim/lib/kim_ccache.c
src/kim/lib/kim_ccache_private.h
src/kim/lib/kim_credential.c
src/kim/lib/kim_credential_private.h
src/kim/lib/kim_identity.c
src/kim/lib/kim_identity_private.h
src/kim/lib/mac/KerberosLogin.c [new file with mode: 0644]
src/kim/lib/mac/KerberosLogin.h [new file with mode: 0644]

index b30351c4ac7822a230e14a81906f868e6269d6d3..2e457be89f6e19cbb01c59d9107f8661bf5abe64 100644 (file)
@@ -207,6 +207,19 @@ static inline kim_error kim_ccache_allocate (kim_ccache *out_ccache)
 kim_error kim_ccache_create_new (kim_ccache          *out_ccache,
                                  kim_identity         in_client_identity,
                                  kim_options          in_options)
+{
+    return check_error (kim_ccache_create_new_with_password (out_ccache,
+                                                             in_client_identity,
+                                                             in_options,
+                                                             NULL));
+}
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_ccache_create_new_with_password (kim_ccache   *out_ccache,
+                                               kim_identity  in_client_identity,
+                                               kim_options   in_options,
+                                               kim_string    in_password)
 {
     kim_error err = KIM_NO_ERROR;
     kim_credential credential = NULL;
@@ -215,7 +228,10 @@ kim_error kim_ccache_create_new (kim_ccache          *out_ccache,
     if (!err && !out_ccache) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
     if (!err) {
-        err = kim_credential_create_new (&credential, in_client_identity, in_options);
+        err = kim_credential_create_new_with_password (&credential, 
+                                                       in_client_identity, 
+                                                       in_options,
+                                                       in_password);
     }
     
     if (!err) {
index 7856935c490e5fec462bffc941c9fec757bef98f..42f048455bd6b947da034ef6b4ebd602b8a5089e 100644 (file)
@@ -29,5 +29,9 @@
 
 #include <kim/kim.h>
 
+kim_error kim_ccache_create_new_with_password (kim_ccache   *out_ccache,
+                                               kim_identity  in_client_identity,
+                                               kim_options   in_options,
+                                               kim_string    in_password);
 
 #endif /* KIM_CCACHE_PRIVATE_H */
index 8465aa59d1c95d77d015107580b0f35fd47f6fc2..c143510d3b18b1e1386186f1cca637264c8bc36b 100644 (file)
@@ -204,6 +204,19 @@ static inline kim_error kim_credential_allocate (kim_credential *out_credential)
 kim_error kim_credential_create_new (kim_credential *out_credential,
                                      kim_identity    in_identity,
                                      kim_options     in_options)
+{
+    return check_error (kim_credential_create_new_with_password (out_credential,
+                                                                 in_identity,
+                                                                 in_options,
+                                                                 NULL));
+}
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_credential_create_new_with_password (kim_credential *out_credential,
+                                                   kim_identity    in_identity,
+                                                   kim_options     in_options,
+                                                   kim_string      in_password)
 {
     kim_error err = KIM_NO_ERROR;
     kim_credential credential = NULL;
@@ -261,7 +274,7 @@ kim_error kim_credential_create_new (kim_credential *out_credential,
                           krb5_get_init_creds_password (credential->context, 
                                                         &creds,
                                                         principal,
-                                                        NULL
+                                                        (char *) in_password
                                                         kim_ui_prompter, 
                                                         &context,
                                                         start_time, 
index 3f30d6c738ad63d7ada590b738c480ae5f5e4548..c9a975d59ea3c66964c13b9a78ddcbb9175ba424 100644 (file)
@@ -36,4 +36,9 @@ kim_error kim_credential_create_for_change_password (kim_credential  *out_creden
                                                      kim_ui_context  *in_ui_context,
                                                      kim_boolean     *out_user_was_prompted);
 
+kim_error kim_credential_create_new_with_password (kim_credential *out_credential,
+                                                   kim_identity    in_identity,
+                                                   kim_options     in_options,
+                                                   kim_string      in_password);
+
 #endif /* KIM_CREDENTIAL_PRIVATE_H */
index 33877746e2040206946792156966c541b9f2a9ee..41bf4a74a6965115689078d3da32391cc08d6367 100644 (file)
@@ -555,13 +555,13 @@ kim_error kim_identity_is_tgt_service (kim_identity  in_identity,
 
 /* ------------------------------------------------------------------------ */
 
-static kim_error kim_identity_change_password_with_credential (kim_identity    in_identity,
-                                                               kim_credential  in_credential,
-                                                               kim_string      in_new_password,
-                                                               kim_ui_context *in_ui_context,
-                                                               kim_error      *out_rejected_err,
-                                                               kim_string     *out_rejected_message,
-                                                               kim_string     *out_rejected_description)
+kim_error kim_identity_change_password_with_credential (kim_identity    in_identity,
+                                                        kim_credential  in_credential,
+                                                        kim_string      in_new_password,
+                                                        kim_ui_context *in_ui_context,
+                                                        kim_error      *out_rejected_err,
+                                                        kim_string     *out_rejected_message,
+                                                        kim_string     *out_rejected_description)
 {
     kim_error err = KIM_NO_ERROR;
     krb5_creds *creds = NULL;
@@ -734,6 +734,9 @@ kim_error kim_identity_change_password_common (kim_identity    in_identity,
             }  
             
             kim_credential_free (&credential);
+            if (in_ui_context->type == kim_ui_type_cli) { 
+                in_ui_context->tcontext = NULL; /* just freed our creds */
+            }
         }
         
         if (!err && rejected_err) {
index 2a212aa1cc07b05cb7bfc7331c6405092fe1287d..43c197d733e4922226ef42b153f3945a00475bcf 100644 (file)
@@ -50,6 +50,14 @@ kim_error kim_os_identity_set_saved_password (kim_identity in_identity,
 
 kim_error kim_os_identity_remove_saved_password (kim_identity in_identity);
 
+kim_error kim_identity_change_password_with_credential (kim_identity    in_identity,
+                                                        kim_credential  in_credential,
+                                                        kim_string      in_new_password,
+                                                        kim_ui_context *in_ui_context,
+                                                        kim_error      *out_rejected_err,
+                                                        kim_string     *out_rejected_message,
+                                                        kim_string     *out_rejected_description);
+
 kim_error kim_identity_change_password_common (kim_identity    in_identity,
                                                kim_boolean     in_old_password_expired,
                                                kim_ui_context *in_ui_context,
diff --git a/src/kim/lib/mac/KerberosLogin.c b/src/kim/lib/mac/KerberosLogin.c
new file mode 100644 (file)
index 0000000..e5fa384
--- /dev/null
@@ -0,0 +1,1546 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#define KERBEROSLOGIN_DEPRECATED
+
+#include "CredentialsCache.h"
+#include "KerberosLogin.h"
+#include <kim/kim.h>
+#include "kim_private.h"
+
+#define kl_check_error(x) (x)
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireTickets (KLPrincipal   inPrincipal,
+                           KLPrincipal  *outPrincipal,
+                           char        **outCredCacheName)
+{
+    return kl_check_error (KLAcquireInitialTickets (inPrincipal, 
+                                                    NULL, 
+                                                    outPrincipal, 
+                                                    outCredCacheName));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireNewTickets (KLPrincipal  inPrincipal,
+                              KLPrincipal  *outPrincipal,
+                              char        **outCredCacheName)
+{
+    return kl_check_error (KLAcquireNewInitialTickets (inPrincipal, 
+                                                       NULL, 
+                                                       outPrincipal, 
+                                                       outCredCacheName));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireTicketsWithPassword (KLPrincipal      inPrincipal,
+                                       KLLoginOptions   inLoginOptions,
+                                       const char      *inPassword,
+                                       char           **outCredCacheName)
+{
+    return kl_check_error (KLAcquireInitialTicketsWithPassword (inPrincipal, 
+                                                                inLoginOptions, 
+                                                                inPassword, 
+                                                                outCredCacheName));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireNewTicketsWithPassword (KLPrincipal      inPrincipal,
+                                          KLLoginOptions   inLoginOptions,
+                                          const char      *inPassword,
+                                          char           **outCredCacheName)
+{
+    return kl_check_error (KLAcquireNewInitialTicketsWithPassword (inPrincipal, 
+                                                                   inLoginOptions, 
+                                                                   inPassword, 
+                                                                   outCredCacheName));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLSetApplicationOptions (const KLApplicationOptions *inAppOptions)
+{
+    /* Deprecated */
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetApplicationOptions (KLApplicationOptions *outAppOptions)
+{
+    /* Deprecated */
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireInitialTickets (KLPrincipal      inPrincipal,
+                                  KLLoginOptions   inLoginOptions,
+                                  KLPrincipal     *outPrincipal,
+                                  char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    kim_string name = NULL;
+    kim_identity identity = NULL;
+    
+    if (!err) {
+        err = kim_ccache_create_from_client_identity (&ccache, 
+                                                      inPrincipal);
+        
+        if (err) {
+            /* ccache does not already exist, create a new one */
+            err = kim_ccache_create_new (&ccache, inPrincipal, inLoginOptions);
+        }
+    }
+    
+    if (!err && outPrincipal) {
+        err = kim_ccache_get_client_identity (ccache, &identity);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, &name);
+    }
+    
+    if (!err) {
+        if (outPrincipal) {
+            *outPrincipal = identity;
+            identity = NULL;
+        }
+        if (outCredCacheName) {
+            *outCredCacheName = (char *) name;
+            name = NULL;
+        }
+    }
+    
+    kim_string_free (&name);
+    kim_identity_free (&identity);    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireNewInitialTickets (KLPrincipal      inPrincipal,
+                                     KLLoginOptions   inLoginOptions,
+                                     KLPrincipal     *outPrincipal,
+                                     char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    kim_string name = NULL;
+    kim_identity identity = NULL;
+    
+    err = kim_ccache_create_new (&ccache, inPrincipal, inLoginOptions);
+    
+    if (!err && outPrincipal) {
+        err = kim_ccache_get_client_identity (ccache, &identity);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, &name);
+    }
+    
+    if (!err) {
+        if (outPrincipal) {
+            *outPrincipal = identity;
+            identity = NULL;
+        }
+        if (outCredCacheName) {
+            *outCredCacheName = (char *) name;
+            name = NULL;
+        }
+    }
+    
+    kim_string_free (&name);
+    kim_identity_free (&identity);    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLDestroyTickets (KLPrincipal inPrincipal)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    
+    if (!err) {
+        err = kim_ccache_destroy (&ccache);
+    }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLChangePassword (KLPrincipal inPrincipal)
+{
+    return kl_check_error (kim_identity_change_password (inPrincipal));
+}
+
+/* ------------------------------------------------------------------------ */
+
+
+/* Kerberos Login dialog low level functions */
+
+KLStatus KLAcquireInitialTicketsWithPassword (KLPrincipal      inPrincipal,
+                                              KLLoginOptions   inLoginOptions,
+                                              const char      *inPassword,
+                                              char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    if (!err) {
+        err = kim_ccache_create_from_client_identity (&ccache, 
+                                                      inPrincipal);
+        
+        if (err) {
+            /* ccache does not already exist, create a new one */
+            err = kim_ccache_create_new_with_password (&ccache, 
+                                                       inPrincipal,
+                                                       inLoginOptions,
+                                                       inPassword);
+        }
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, 
+                                           (kim_string *) outCredCacheName);
+    }    
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireNewInitialTicketsWithPassword (KLPrincipal      inPrincipal,
+                                                 KLLoginOptions   inLoginOptions,
+                                                 const char      *inPassword,
+                                                 char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    err = kim_ccache_create_new_with_password (&ccache, 
+                                               inPrincipal, 
+                                               inLoginOptions,
+                                               inPassword);
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, 
+                                           (kim_string *) outCredCacheName);
+    }    
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireNewInitialTicketCredentialsWithPassword (KLPrincipal      inPrincipal,
+                                                           KLLoginOptions   inLoginOptions,
+                                                           const char      *inPassword,
+                                                           krb5_context     inV5Context,
+                                                           KLBoolean       *outGotV4Credentials,
+                                                           KLBoolean       *outGotV5Credentials,
+                                                           void            *outV4Credentials,
+                                                           krb5_creds      *outV5Credentials)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_credential credential = NULL;
+    krb5_creds *creds = NULL;
+    
+    if (!err) {
+        err = kim_credential_create_new_with_password (&credential,
+                                                       inPrincipal,
+                                                       inLoginOptions,
+                                                       inPassword);
+    }
+    
+    if (!err) {
+        err = kim_credential_get_krb5_creds (credential, 
+                                             inV5Context,
+                                             &creds);
+    }
+    
+    if (!err) {
+        *outGotV5Credentials = 1;
+        *outGotV4Credentials = 0;
+        *outV5Credentials = *creds;
+        free (creds); /* eeeew */
+        creds = NULL;
+    }
+    
+    kim_credential_free (&credential);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLStoreNewInitialTicketCredentials (KLPrincipal     inPrincipal,
+                                             krb5_context    inV5Context,
+                                             void           *inV4Credentials,
+                                             krb5_creds     *inV5Credentials,
+                                             char          **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_credential credential = NULL;
+    kim_ccache ccache = NULL;
+    
+    err = kim_credential_create_from_krb5_creds (&credential,
+                                                 inV5Context, 
+                                                 inV5Credentials);
+    
+    if (!err) {
+        err = kim_credential_store (credential, inPrincipal, &ccache);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, 
+                                           (kim_string *) outCredCacheName);
+    }    
+    
+    kim_ccache_free (&ccache);
+    kim_credential_free (&credential);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLVerifyInitialTickets (KLPrincipal   inPrincipal,
+                                 KLBoolean     inFailIfNoHostKey,
+                                 char        **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    
+    if (!err) {
+        err = kim_ccache_verify (ccache, 
+                                 KIM_IDENTITY_ANY, 
+                                 NULL, 
+                                 inFailIfNoHostKey);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, 
+                                           (kim_string *) outCredCacheName);
+    }    
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLVerifyInitialTicketCredentials (void        *inV4Credentials,
+                                           krb5_creds  *inV5Credentials,
+                                           KLBoolean    inFailIfNoHostKey)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_credential credential = NULL;
+    krb5_context context = NULL;
+    
+    err = krb5_error (NULL, krb5_init_context (&context));
+    
+    if (!err) {
+        err = kim_credential_create_from_krb5_creds (&credential,
+                                                     context, 
+                                                     inV5Credentials);
+    }
+    
+    if (!err) {
+        err = kim_credential_verify (credential, KIM_IDENTITY_ANY, 
+                                     NULL, inFailIfNoHostKey);
+    }
+    
+    if (context) { krb5_free_context (context); }
+    kim_credential_free (&credential);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLAcquireNewInitialTicketsWithKeytab (KLPrincipal      inPrincipal,
+                                               KLLoginOptions   inLoginOptions,
+                                               const char      *inKeytabName,
+                                               char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    err = kim_ccache_create_from_keytab (&ccache, 
+                                         inPrincipal, 
+                                         inLoginOptions,
+                                         inKeytabName);
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, 
+                                           (kim_string *) outCredCacheName);
+    }    
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLRenewInitialTickets (KLPrincipal      inPrincipal,
+                                KLLoginOptions   inLoginOptions,
+                                KLPrincipal     *outPrincipal,
+                                char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    kim_string name = NULL;
+    kim_identity identity = NULL;
+    
+    err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    
+    if (!err) {
+        err = kim_ccache_renew (ccache, inLoginOptions);
+    }
+    
+    if (!err && outPrincipal) {
+        err = kim_ccache_get_client_identity (ccache, &identity);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, &name);
+    }
+    
+    if (!err) {
+        if (outPrincipal) {
+            *outPrincipal = identity;
+            identity = NULL;
+        }
+        if (outCredCacheName) {
+            *outCredCacheName = (char *) name;
+            name = NULL;
+        }
+    }
+    
+    kim_string_free (&name);
+    kim_identity_free (&identity);
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLValidateInitialTickets (KLPrincipal      inPrincipal,
+                                   KLLoginOptions   inLoginOptions,
+                                   char           **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    
+    if (!err) {
+        err = kim_ccache_validate (ccache, inLoginOptions);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, 
+                                           (kim_string *) outCredCacheName);
+    }    
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLastChangedTime (KLTime *outLastChangedTime)
+{
+    KLStatus     err = klNoErr;
+    cc_context_t context = NULL;
+    cc_time_t    ccChangeTime = 0;
+    
+    if (!outLastChangedTime) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        err = cc_initialize (&context, ccapi_version_4, NULL, NULL);
+    }
+    
+    if (!err) {
+        err = cc_context_get_change_time (context, &ccChangeTime);
+    }
+    
+    if (!err) {
+        *outLastChangedTime = ccChangeTime;
+    }
+    
+    if (context) { cc_context_release (context); }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLCacheHasValidTickets (KLPrincipal         inPrincipal,
+                                 KLKerberosVersion   inKerberosVersion,
+                                 KLBoolean          *outFoundValidTickets,
+                                 KLPrincipal        *outPrincipal,
+                                 char              **outCredCacheName)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    kim_credential_state state = kim_credentials_state_valid;
+    kim_identity identity = NULL;
+    kim_string name = NULL;
+    
+    if (!outFoundValidTickets) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        if (inPrincipal) {
+            err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+        } else {
+            err = kim_ccache_create_from_default (&ccache);
+        }
+    }
+    
+    if (!err) {
+        err = kim_ccache_get_state (ccache, &state);
+    }
+    
+    if (!err && outPrincipal) {
+        err = kim_ccache_get_client_identity (ccache, &identity);
+    }
+    
+    if (!err && outCredCacheName) {
+        err = kim_ccache_get_display_name (ccache, &name);
+    }
+    
+    if (!err) {
+        *outFoundValidTickets = (state == kim_credentials_state_valid);
+        if (outPrincipal) {
+            *outPrincipal = identity;
+            identity = NULL;
+        }
+        if (outCredCacheName) {
+            *outCredCacheName = (char *) name;
+            name = NULL;
+        }
+    }
+    
+    kim_string_free (&name);
+    kim_identity_free (&identity);
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLTicketStartTime (KLPrincipal        inPrincipal,
+                            KLKerberosVersion  inKerberosVersion,
+                            KLTime            *outStartTime)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    kim_time start_time = 0;
+    
+    if (!err) {
+        err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    }
+    
+    if (!err) {
+        err = kim_ccache_get_start_time (ccache, &start_time);
+    }
+    
+    if (!err) {
+        *outStartTime = start_time;
+    }
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLTicketExpirationTime (KLPrincipal        inPrincipal,
+                                 KLKerberosVersion  inKerberosVersion,
+                                 KLTime            *outExpirationTime)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    kim_time expiration_time = 0;
+    
+    if (!err) {
+        err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    }
+    
+    if (!err) {
+        err = kim_ccache_get_expiration_time (ccache, &expiration_time);
+    }
+    
+    if (!err) {
+        *outExpirationTime = expiration_time;
+    }
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLSetSystemDefaultCache (KLPrincipal inPrincipal)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ccache ccache = NULL;
+    
+    if (!err) {
+        err = kim_ccache_create_from_client_identity (&ccache, inPrincipal);
+    }
+    
+    if (!err) {
+        err = kim_ccache_set_default (ccache);
+    }
+    
+    kim_ccache_free (&ccache);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLHandleError (KLStatus           inError,
+                        KLDialogIdentifier inDialogIdentifier,
+                        KLBoolean          inShowAlert)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_ui_context context;
+    kim_boolean ui_inited = 0;
+    
+    if (!err) {
+        err = kim_ui_init (&context);
+        if (!err) { ui_inited = 1; }
+    }
+    
+    if (!err) {
+        int type = kim_ui_error_type_generic;
+        
+        switch (inDialogIdentifier) {
+            case loginLibrary_LoginDialog:
+                type = kim_ui_error_type_authentication;
+                break;
+            case loginLibrary_ChangePasswordDialog:
+                type = kim_ui_error_type_change_password;
+                break;
+            default:
+                type = kim_ui_error_type_generic;
+                break;
+        }
+        
+        err = kim_ui_handle_kim_error (&context, 
+                                       KIM_IDENTITY_ANY, type, inError);
+    }
+    
+    if (ui_inited) {
+        kim_error fini_err = kim_ui_fini (&context);
+        if (!err) { err = kl_check_error (fini_err); }
+    }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetErrorString (KLStatus   inError,
+                           char     **outErrorString)
+{
+    return kl_check_error (kim_string_create_for_last_error ((kim_string *) outErrorString,
+                                                             inError));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLCancelAllDialogs (void)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Kerberos change password dialog low level functions */
+
+KLStatus KLChangePasswordWithPasswords (KLPrincipal   inPrincipal,
+                                        const char   *inOldPassword,
+                                        const char   *inNewPassword,
+                                        KLBoolean    *outRejected,
+                                        char        **outRejectionError,
+                                        char        **outRejectionDescription)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_credential credential = NULL;
+    kim_ui_context context;
+    kim_boolean ui_inited = 0;
+    kim_error rejected_err = KIM_NO_ERROR;
+    kim_string rejected_message = NULL;
+    kim_string rejected_description = NULL;
+    
+    if (!inOldPassword) { err = kl_check_error (klParameterErr); }
+    if (!inNewPassword) { err = kl_check_error (klParameterErr); }
+    if (!outRejected  ) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        err = kim_ui_init (&context);
+        if (!err) { ui_inited = 1; }
+    }
+    
+    if (!err) {
+        kim_boolean was_prompted = 0;
+        
+        err = kim_credential_create_for_change_password (&credential,
+                                                         inPrincipal,
+                                                         inOldPassword,
+                                                         &context,
+                                                         &was_prompted);
+    }
+    
+    if (!err) {
+        err = kim_identity_change_password_with_credential (inPrincipal,
+                                                            credential, 
+                                                            inNewPassword,
+                                                            &context,
+                                                            &rejected_err,
+                                                            &rejected_message,
+                                                            &rejected_description);
+    }  
+    
+    if (!err) {
+        *outRejected = (rejected_err != 0);
+        if (rejected_err) {
+            if (outRejectionError) {
+                *outRejectionError = (char *) rejected_message;
+                rejected_message = NULL;
+            }
+            if (outRejectionDescription) {
+                *outRejectionDescription = (char *) rejected_description;
+                rejected_description = NULL;
+            }
+        }
+    }
+    
+    if (ui_inited) {
+        kim_error fini_err = kim_ui_fini (&context);
+        if (!err) { err = kl_check_error (fini_err); }
+    }
+    
+    kim_string_free (&rejected_message);
+    kim_string_free (&rejected_description);
+    kim_credential_free (&credential);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Application Configuration functions */
+
+KLStatus KLSetIdleCallback (const KLIdleCallback inCallback,
+                            const KLRefCon inRefCon)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetIdleCallback (KLIdleCallback* inCallback,
+                            KLRefCon* inRefCon)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Library configuration functions */
+/* Deprecated options which we now ignore */
+enum {
+    loginOption_ShowOptions                = 'sopt',
+    loginOption_RememberShowOptions        = 'ropt',
+    loginOption_LongTicketLifetimeDisplay  = 'hms ',
+    loginOption_RememberPassword           = 'pass'
+};
+
+
+KLStatus KLGetDefaultLoginOption (const KLDefaultLoginOption  inOption,
+                                  void                       *ioBuffer,
+                                  KLSize                     *ioBufferSize)
+{
+    KLStatus  err = klNoErr;
+    kim_preferences prefs = NULL;
+    KLSize targetSize = 0;
+    KLBoolean returnSizeOnly = (ioBuffer == NULL);
+    
+    if (!ioBufferSize) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        err = kim_preferences_create (&prefs);
+    }
+    
+    if (!err && inOption == loginOption_LoginName) {
+        kim_identity identity = NULL;
+        kim_string string = "";
+        
+        err = kim_preferences_get_client_identity (prefs, &identity);
+        
+        if (!err && identity) {
+            err = kim_identity_get_components_string (identity, &string);
+        }
+        
+        if (!err) {
+            targetSize = strlen (string);
+            if (!returnSizeOnly) {
+                if (*ioBufferSize < targetSize) {
+                    err = kl_check_error (klBufferTooSmallErr);
+                } else if (targetSize > 0) {
+                    memmove (ioBuffer, string, targetSize);
+                }
+            }
+        }
+        
+        if (string && string[0]) { kim_string_free (&string); }
+        
+    } else if (!err && inOption == loginOption_LoginInstance) {
+        targetSize = 0; /* Deprecated */
+        
+    } else if (!err && (inOption == loginOption_ShowOptions &&
+                        inOption == loginOption_RememberShowOptions &&
+                        inOption == loginOption_LongTicketLifetimeDisplay &&
+                        inOption == loginOption_RememberPrincipal &&
+                        inOption == loginOption_RememberExtras &&
+                        inOption == loginOption_RememberPassword)) {
+        targetSize = sizeof(KLBoolean);
+        
+        if (!returnSizeOnly) {
+            kim_boolean boolean = 0;
+            
+            if (inOption == loginOption_ShowOptions ||
+                inOption == loginOption_RememberShowOptions ||
+                inOption == loginOption_LongTicketLifetimeDisplay) {
+                boolean = 1; /* Deprecated */
+                
+            } else if (inOption == loginOption_RememberPrincipal) {
+                err = kim_preferences_get_remember_client_identity (prefs, &boolean);
+                
+            } else if (inOption == loginOption_RememberExtras) {
+                err = kim_preferences_get_remember_options (prefs, &boolean);
+                
+            } else if (inOption == loginOption_RememberPassword) {
+                boolean = kim_os_identity_allow_save_password ();
+            }
+            
+            if (!err) {
+                if (*ioBufferSize < targetSize) {
+                    err = kl_check_error (klBufferTooSmallErr);
+                } else {
+                    *(KLBoolean *)ioBuffer = boolean;
+                }
+            }
+        }
+        
+    } else if (!err && (inOption == loginOption_MinimalTicketLifetime &&
+                        inOption == loginOption_MaximalTicketLifetime &&
+                        inOption == loginOption_LongTicketLifetimeDisplay &&
+                        inOption == loginOption_RememberPrincipal &&
+                        inOption == loginOption_RememberExtras)) {
+        targetSize = sizeof(KLLifetime);
+        
+        if (!returnSizeOnly) {
+            kim_lifetime lifetime = 0;
+            
+            if (inOption == loginOption_MinimalTicketLifetime) {
+                err = kim_preferences_get_minimum_lifetime (prefs, &lifetime);
+                
+            } else if (inOption == loginOption_MaximalTicketLifetime) {
+                err = kim_preferences_get_maximum_lifetime (prefs, &lifetime);
+                
+            } else if (inOption == loginOption_MinimalRenewableLifetime) {
+                err = kim_preferences_get_minimum_renewal_lifetime (prefs, &lifetime);
+                
+            } else if (inOption == loginOption_MaximalRenewableLifetime) {
+                err = kim_preferences_get_maximum_renewal_lifetime (prefs, &lifetime);
+            }   
+            
+            if (!err) {
+                if (*ioBufferSize < targetSize) {
+                    err = kl_check_error (klBufferTooSmallErr);
+                } else {
+                    *(KLLifetime *)ioBuffer = lifetime;
+                }
+            }
+        }
+        
+    } else if (!err && (inOption == loginOption_DefaultRenewableTicket &&
+                        inOption == loginOption_DefaultForwardableTicket &&
+                        inOption == loginOption_DefaultProxiableTicket &&
+                        inOption == loginOption_DefaultAddresslessTicket)) {
+        targetSize = sizeof(KLBoolean);
+        
+        if (!returnSizeOnly) {
+            kim_options options = NULL;
+            kim_boolean boolean = 0;
+            
+            err = kim_preferences_get_options (prefs, &options);
+            
+            if (!err && inOption == loginOption_DefaultRenewableTicket) {
+                err = kim_options_get_renewable (options, &boolean);
+                
+            } else if (!err && inOption == loginOption_DefaultForwardableTicket) {
+                err = kim_options_get_forwardable (options, &boolean);
+                
+            } else if (!err && inOption == loginOption_DefaultProxiableTicket) {
+                err = kim_options_get_proxiable (options, &boolean);
+                
+            } else if (!err && inOption == loginOption_DefaultAddresslessTicket) {
+                err = kim_options_get_addressless (options, &boolean);
+            }   
+            
+            if (!err) {
+                if (*ioBufferSize < targetSize) {
+                    err = kl_check_error (klBufferTooSmallErr);
+                } else {
+                    *(KLBoolean *)ioBuffer = boolean;
+                }
+            }
+            
+            kim_options_free (&options);
+        }
+        
+        
+    } else if (!err && (inOption == loginOption_DefaultTicketLifetime &&
+                        inOption == loginOption_DefaultRenewableLifetime)) {
+        targetSize = sizeof(KLLifetime);
+        
+        if (!returnSizeOnly) {
+            kim_options options = NULL;
+            kim_lifetime lifetime = 0;
+            
+            err = kim_preferences_get_options (prefs, &options);
+            
+            if (!err && inOption == loginOption_DefaultTicketLifetime) {
+                err = kim_options_get_lifetime (options, &lifetime);
+                
+            } else if (!err && inOption == loginOption_DefaultRenewableLifetime) {
+                err = kim_options_get_renewal_lifetime (options, &lifetime);
+            }   
+            
+            if (!err) {
+                if (*ioBufferSize < targetSize) {
+                    err = kl_check_error (klBufferTooSmallErr);
+                } else {
+                    *(KLLifetime *)ioBuffer = lifetime;
+                }
+            }
+            
+            kim_options_free (&options);
+        }
+        
+    } else { 
+        err = kl_check_error (klInvalidOptionErr);
+    }
+    
+    if (!err) {
+        *ioBufferSize = targetSize;
+    }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLSetDefaultLoginOption (const KLDefaultLoginOption  inOption,
+                                  const void                 *inBuffer,
+                                  const KLSize                inBufferSize)
+{
+    KLStatus err = klNoErr;
+    kim_preferences prefs = NULL;
+    
+    if (inBuffer == NULL) { err = kl_check_error (klParameterErr); }
+    if (inBufferSize < 0) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        err = kim_preferences_create (&prefs);
+    }
+    
+    if (!err && inOption == loginOption_LoginName) {
+        kim_identity old_identity = NULL;
+        kim_identity new_identity = NULL;
+        kim_string new_identity_string = NULL;
+        kim_string realm = NULL;
+        kim_string components = NULL;
+        
+        err = kim_string_create_from_buffer (&components, inBuffer, inBufferSize);
+        
+        if (!err) {
+            err = kim_preferences_get_client_identity (prefs, &old_identity);
+            
+            if (!err && old_identity) {
+                err = kim_identity_get_realm (old_identity, &realm);
+            }
+        }
+        
+        if (!err && realm) {
+            err = kim_string_create_from_format (&new_identity_string, 
+                                                 "%s@%s", components, realm);
+        }
+        
+        if (!err) {
+            err = kim_identity_create_from_string (&new_identity,
+                                                   (new_identity_string ?
+                                                    new_identity_string :
+                                                    components));
+        }
+        
+        if (!err) {
+            err = kim_preferences_set_client_identity (prefs, new_identity);
+        }
+        
+        kim_string_free (&components);
+        kim_string_free (&realm);
+        kim_string_free (&new_identity_string);
+        kim_identity_free (&old_identity);
+        kim_identity_free (&new_identity);
+         
+    } else if (!err && inOption == loginOption_LoginInstance) {
+        /* Ignored */
+        
+    } else if (!err && (inOption == loginOption_ShowOptions &&
+                        inOption == loginOption_RememberShowOptions &&
+                        inOption == loginOption_LongTicketLifetimeDisplay &&
+                        inOption == loginOption_RememberPrincipal &&
+                        inOption == loginOption_RememberExtras &&
+                        inOption == loginOption_RememberPassword)) {
+        if (inBufferSize > sizeof (KLBoolean)) {
+            err = kl_check_error (klBufferTooLargeErr);
+        } else if (inBufferSize < sizeof (KLBoolean)) {
+            err = kl_check_error (klBufferTooSmallErr);
+        }
+        
+        if (!err && inOption == loginOption_RememberPrincipal) {
+            err = kim_preferences_set_remember_client_identity (prefs, *(kim_boolean *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_RememberExtras) {
+            err = kim_preferences_set_remember_options (prefs, *(kim_boolean *)inBuffer);
+        }
+        
+    } else if (!err && (inOption == loginOption_MinimalTicketLifetime &&
+                        inOption == loginOption_MaximalTicketLifetime &&
+                        inOption == loginOption_LongTicketLifetimeDisplay &&
+                        inOption == loginOption_RememberPrincipal &&
+                        inOption == loginOption_RememberExtras)) {
+        if (inBufferSize > sizeof (KLLifetime)) {
+            err = kl_check_error (klBufferTooLargeErr);
+        } else if (inBufferSize < sizeof (KLLifetime)) {
+            err = kl_check_error (klBufferTooSmallErr);
+        }
+        
+        if (!err && inOption == loginOption_MinimalTicketLifetime) {
+            err = kim_preferences_set_minimum_lifetime (prefs, *(kim_lifetime *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_MaximalTicketLifetime) {
+            err = kim_preferences_set_maximum_lifetime (prefs, *(kim_lifetime *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_MinimalRenewableLifetime) {
+            err = kim_preferences_set_minimum_renewal_lifetime (prefs, *(kim_lifetime *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_MaximalRenewableLifetime) {
+            err = kim_preferences_set_maximum_renewal_lifetime (prefs, *(kim_lifetime *)inBuffer);
+        }   
+        
+    } else if (!err && (inOption == loginOption_DefaultRenewableTicket &&
+                        inOption == loginOption_DefaultForwardableTicket &&
+                        inOption == loginOption_DefaultProxiableTicket &&
+                        inOption == loginOption_DefaultAddresslessTicket)) {
+        kim_options options = NULL;
+        
+        if (inBufferSize > sizeof (KLBoolean)) {
+            err = kl_check_error (klBufferTooLargeErr);
+        } else if (inBufferSize < sizeof (KLBoolean)) {
+            err = kl_check_error (klBufferTooSmallErr);
+        }
+        
+        if (!err) {
+            err = kim_preferences_get_options (prefs, &options);
+        }
+        
+        if (!err && inOption == loginOption_DefaultRenewableTicket) {
+            err = kim_options_set_renewable (options, *(kim_boolean *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_DefaultForwardableTicket) {
+            err = kim_options_set_forwardable (options, *(kim_boolean *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_DefaultProxiableTicket) {
+            err = kim_options_set_proxiable (options, *(kim_boolean *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_DefaultAddresslessTicket) {
+            err = kim_options_set_addressless (options, *(kim_boolean *)inBuffer);
+        }   
+        
+        if (!err) {
+            err = kim_preferences_set_options (prefs, options);
+        }
+        
+        kim_options_free (&options);
+        
+    } else if (!err && (inOption == loginOption_DefaultTicketLifetime &&
+                        inOption == loginOption_DefaultRenewableLifetime)) {
+        kim_options options = NULL;
+        
+        if (inBufferSize > sizeof (KLLifetime)) {
+            err = kl_check_error (klBufferTooLargeErr);
+        } else if (inBufferSize < sizeof (KLLifetime)) {
+            err = kl_check_error (klBufferTooSmallErr);
+        }
+        
+        if (!err) {
+            err = kim_preferences_get_options (prefs, &options);
+        }
+        
+        if (!err && inOption == loginOption_DefaultTicketLifetime) {
+            err = kim_options_set_lifetime (options, *(kim_lifetime *)inBuffer);
+            
+        } else if (!err && inOption == loginOption_DefaultRenewableLifetime) {
+            err = kim_options_set_renewal_lifetime (options, *(kim_lifetime *)inBuffer);
+        }   
+        
+        if (!err) {
+            err = kim_preferences_set_options (prefs, options);
+        }
+        
+        kim_options_free (&options);
+        
+    } else { 
+        err = kl_check_error (klInvalidOptionErr);
+    }
+    
+    if (!err) {
+        err = kim_preferences_synchronize (prefs);
+    }    
+    
+    kim_preferences_free (&prefs);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Realm configuration functions */
+
+KLStatus KLFindKerberosRealmByName (const char *inRealmName,
+                                    KLIndex    *outIndex)
+{
+    kim_error err = KIM_NO_ERROR;
+    char *realm = NULL;
+    
+    if (!err) {
+        err = KLGetKerberosDefaultRealmByName (&realm);
+    }
+    
+    if (!err) {
+        if (!strcmp (inRealmName, realm)) {
+            *outIndex = 0;
+        } else {
+            err = kl_check_error (klRealmDoesNotExistErr);
+        }
+    }
+    
+    kim_string_free ((kim_string *) &realm);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetKerberosRealm (KLIndex   inIndex,
+                             char    **outRealmName)
+{
+    kim_error err = KIM_NO_ERROR;
+    
+    if (!outRealmName) { err = kl_check_error (klParameterErr); }
+    if (!err && inIndex != 0) { err = kl_check_error (klRealmDoesNotExistErr); }
+    
+    if (!err) {
+        err = KLGetKerberosDefaultRealmByName (outRealmName);
+    }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLSetKerberosRealm (KLIndex     inIndex,
+                             const char *inRealmName)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLRemoveKerberosRealm (KLIndex inIndex)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLInsertKerberosRealm (KLIndex     inInsertBeforeIndex,
+                                const char *inRealmName)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLRemoveAllKerberosRealms (void)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLSize KLCountKerberosRealms (void)
+{
+    return 1;
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetKerberosDefaultRealm(KLIndex *outIndex)
+{
+    kim_error err = KIM_NO_ERROR;
+    
+    if (!outIndex) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        *outIndex = 0;
+    }
+    
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetKerberosDefaultRealmByName (char **outRealmName)
+{
+    kim_error err = KIM_NO_ERROR;
+    krb5_context context = NULL;
+    char *realm = NULL;
+    
+    if (!outRealmName) { err = kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        err = krb5_init_context (&context);
+    }
+    
+    if (!err) {
+       err = krb5_get_default_realm(context, &realm);
+    }
+    
+    if (!err) {
+        err = kim_string_copy ((kim_string *) outRealmName, realm);
+    }
+    
+    if (realm  ) { krb5_free_default_realm (context, realm); }
+    if (context) { krb5_free_context (context); }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLSetKerberosDefaultRealm (KLIndex inIndex)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLSetKerberosDefaultRealmByName (const char *inRealm)
+{
+    return kl_check_error (klNoErr);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* KLPrincipal functions */
+
+KLStatus KLCreatePrincipalFromTriplet (const char  *inName,
+                                       const char  *inInstance,
+                                       const char  *inRealm,
+                                       KLPrincipal *outPrincipal)
+{
+    return kl_check_error (kim_identity_create_from_components (outPrincipal,
+                                                                inRealm,
+                                                                inName, 
+                                                                inInstance,
+                                                                NULL));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLCreatePrincipalFromString (const char        *inFullPrincipal,
+                                      KLKerberosVersion  inKerberosVersion,
+                                      KLPrincipal       *outPrincipal)
+{
+    return kl_check_error (kim_identity_create_from_string (outPrincipal, 
+                                                            inFullPrincipal));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLCreatePrincipalFromKerberos5Principal (krb5_principal  inKerberos5Principal,
+                                                  KLPrincipal    *outPrincipal)
+{
+    return kl_check_error (kim_identity_create_from_krb5_principal (outPrincipal, 
+                                                                    NULL, /* context */
+                                                                    inKerberos5Principal));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLCreatePrincipalFromPrincipal (KLPrincipal inPrincipal,
+                                         KLPrincipal *outPrincipal)
+{
+    return kl_check_error (kim_identity_copy (outPrincipal, inPrincipal));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetTripletFromPrincipal (KLPrincipal   inPrincipal,
+                                    char        **outName,
+                                    char        **outInstance,
+                                    char        **outRealm)
+{
+    KLStatus err = klNoErr;
+    kim_string name = NULL;
+    kim_string instance = NULL;
+    kim_string realm = NULL;
+    kim_count count = 0;
+    
+    if (!inPrincipal) { return kl_check_error (klBadPrincipalErr); }
+    if (!outName    ) { return kl_check_error (klParameterErr); }
+    if (!outInstance) { return kl_check_error (klParameterErr); }
+    if (!outRealm   ) { return kl_check_error (klParameterErr); }
+    
+    if (!err) {
+        err = kim_identity_get_number_of_components (inPrincipal, &count);
+        if (!err && count > 2) { err = kl_check_error (klBadPrincipalErr); }
+    }
+    
+    if (!err) {
+        err = kim_identity_get_realm (inPrincipal, &realm);
+    }
+    
+    if (!err) {
+        err = kim_identity_get_component_at_index (inPrincipal, 0, &name);
+    }
+    
+    if (!err && count > 1) {
+        err = kim_identity_get_component_at_index (inPrincipal, 1, &instance);
+    }
+    
+    if (!err) {
+        *outName = (char *) name;
+        name = NULL;
+        *outInstance = (char *) instance;
+        instance = NULL;
+        *outRealm = (char *) realm;
+        realm = NULL;
+    }
+    
+    kim_string_free (&name);
+    kim_string_free (&instance);
+    kim_string_free (&realm);
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetStringFromPrincipal (KLPrincipal         inPrincipal,
+                                   KLKerberosVersion   inKerberosVersion,
+                                   char              **outFullPrincipal)
+{
+    return kl_check_error (kim_identity_get_string (inPrincipal, 
+                                                    (kim_string *) outFullPrincipal));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLGetDisplayStringFromPrincipal (KLPrincipal         inPrincipal,
+                                          KLKerberosVersion   inKerberosVersion,
+                                          char              **outFullPrincipal)
+{
+    return kl_check_error (kim_identity_get_display_string (inPrincipal, 
+                                                            (kim_string *) outFullPrincipal));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLComparePrincipal (KLPrincipal  inFirstPrincipal,
+                             KLPrincipal  inSecondPrincipal,
+                             KLBoolean   *outAreEquivalent)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_comparison comparison;
+    
+    err = kim_identity_compare (inFirstPrincipal, inSecondPrincipal, 
+                                &comparison);
+    
+    if (!err) {
+        *outAreEquivalent = kim_comparison_is_equal_to (comparison);
+    }
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLDisposePrincipal (KLPrincipal inPrincipal)
+{
+    kim_identity_free (&inPrincipal);
+    return klNoErr;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* KLLoginOptions functions */
+
+KLStatus KLCreateLoginOptions (KLLoginOptions *outOptions)
+{
+    return kl_check_error (kim_options_create (outOptions));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetTicketLifetime (KLLoginOptions ioOptions,
+                                          KLLifetime     inTicketLifetime)
+{
+    return kl_check_error (kim_options_set_lifetime (ioOptions, inTicketLifetime));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetForwardable (KLLoginOptions ioOptions,
+                                       KLBoolean      inForwardable)
+{
+    return kl_check_error (kim_options_set_forwardable (ioOptions, inForwardable));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetProxiable (KLLoginOptions ioOptions,
+                                     KLBoolean      inProxiable)
+{
+    return kl_check_error (kim_options_set_proxiable (ioOptions, inProxiable));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetRenewableLifetime (KLLoginOptions ioOptions,
+                                             KLLifetime     inRenewableLifetime)
+{
+    KLStatus err = klNoErr;
+    
+    err = kim_options_set_renewable (ioOptions, inRenewableLifetime > 0);
+    
+    if (!err && inRenewableLifetime > 0) {
+        err = kim_options_set_renewal_lifetime (ioOptions, inRenewableLifetime);
+    } 
+    
+    return kl_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetAddressless (KLLoginOptions ioOptions,
+                                       KLBoolean      inAddressless)
+{
+    return kl_check_error (kim_options_set_addressless (ioOptions, inAddressless));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetTicketStartTime (KLLoginOptions ioOptions,
+                                           KLTime         inStartTime)
+{
+    return kl_check_error (kim_options_set_start_time (ioOptions, inStartTime));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLLoginOptionsSetServiceName (KLLoginOptions  ioOptions,
+                                       const char     *inServiceName)
+{
+    return kl_check_error (kim_options_set_service_name (ioOptions, inServiceName));
+}
+
+/* ------------------------------------------------------------------------ */
+
+KLStatus KLDisposeLoginOptions(KLLoginOptions ioOptions)
+{
+    kim_options_free (&ioOptions);
+    return klNoErr;
+}
+
+/* ------------------------------------------------------------------------ */
+
+
+/* Misc function */
+
+KLStatus KLDisposeString (char *inStringToDispose)
+{
+    kim_string_free ((kim_string *)&inStringToDispose);
+    return klNoErr;
+}
diff --git a/src/kim/lib/mac/KerberosLogin.h b/src/kim/lib/mac/KerberosLogin.h
new file mode 100644 (file)
index 0000000..b9c8262
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+* Copyright 2008 Massachusetts Institute of Technology.
+* All Rights Reserved.
+*
+* Export of this software from the United States of America may
+* require a specific license from the United States Government.
+* It is the responsibility of any person or organization contemplating
+* export to obtain such a license before exporting.
+* 
+* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+* distribute this software and its documentation for any purpose and
+* without fee is hereby granted, provided that the above copyright
+* notice appear in all copies and that both that copyright notice and
+* this permission notice appear in supporting documentation, and that
+* the name of M.I.T. not be used in advertising or publicity pertaining
+* to distribution of the software without specific, written prior
+* permission.  Furthermore if you modify this software you must label
+* your software as modified software and not distribute it in such a
+* fashion that it might be confused with the original M.I.T. software.
+* M.I.T. makes no representations about the suitability of
+* this software for any purpose.  It is provided "as is" without express
+* or implied warranty.
+*/
+
+#ifndef __KERBEROSLOGIN__
+#define __KERBEROSLOGIN__
+
+#include <kim/kim.h>
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+#    include <TargetConditionals.h>
+#    if TARGET_RT_MAC_CFM
+#        error "Use KfM 4.0 SDK headers for CFM compilation."
+#    endif
+#endif
+
+#include <sys/types.h>
+#include <krb5.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if TARGET_OS_MAC
+#    pragma pack(push,2)
+#endif
+
+/* 
+ * Kerberos version constants
+ */
+enum {
+    kerberosVersion_Any                = 0,
+    kerberosVersion_V4         = 1,
+    kerberosVersion_V5         = 2,
+    kerberosVersion_All                = 0xFFFFFFFF
+};
+typedef int32_t KLEKerberosVersion;
+
+/* 
+ * Dialog identifier constants 
+ */
+enum {
+    loginLibrary_LoginDialog,
+    loginLibrary_OptionsDialog,
+    loginLibrary_ChangePasswordDialog,
+    loginLibrary_ProgressDialog,
+    loginLibrary_PrompterDialog,
+    loginLibrary_UnknownDialog = -1
+};
+typedef int32_t KLEDialogIdentifiers;
+
+
+/* 
+ * Option identifier constants 
+ */
+enum {
+    /* Initial values and ranges */
+    loginOption_LoginName                  = 'name',
+    loginOption_LoginInstance              = 'inst',
+    
+    loginOption_RememberPrincipal          = 'prin',
+    loginOption_RememberExtras             = 'extr',
+    
+    loginOption_MinimalTicketLifetime      = '-lif',
+    loginOption_MaximalTicketLifetime      = '+lif',
+    loginOption_DefaultTicketLifetime      = '0lif',
+    
+    loginOption_DefaultRenewableTicket     = '0rtx',
+    loginOption_MinimalRenewableLifetime   = '-rlf',
+    loginOption_MaximalRenewableLifetime   = '+rlf',
+    loginOption_DefaultRenewableLifetime   = '0rlf',
+    
+    loginOption_DefaultForwardableTicket   = '0fwd',
+    loginOption_DefaultProxiableTicket     = '0prx',
+    loginOption_DefaultAddresslessTicket   = '0adr'    
+};
+typedef int32_t KLEDefaultLoginOptions;
+
+
+/* 
+ * Realm list constants 
+ */
+enum {
+    realmList_Start  = 0,
+    realmList_End    = 0xFFFF
+};
+typedef int32_t KLERealmListIndexes;
+
+#define klFirstError 19276
+#define klLastError  19876
+
+/* 
+ * Error codes 
+ */
+enum {
+    klNoErr                             = 0,
+    
+    /* Parameter errors */
+    klParameterErr                      = 19276,
+    klBadPrincipalErr,
+    klBadPasswordErr,
+    klBadLoginOptionsErr,
+    klInvalidVersionErr,
+    klCapsLockErr,
+    klBadV5ContextErr,
+    
+    /* Get/SetKerberosOption errors */
+    klBufferTooSmallErr                 = 19376,
+    klBufferTooLargeErr,
+    klInvalidOptionErr,
+    klBadOptionValueErr,
+    
+    /* Runtime Login errors */
+    klUserCanceledErr                   = 19476,
+    klMemFullErr,
+    klPreferencesReadErr,
+    klPreferencesWriteErr,
+    klV5InitializationFailedErr,
+    klPrincipalDoesNotExistErr,
+    klSystemDefaultDoesNotExistErr,
+    klCredentialsExpiredErr,
+    klNoRealmsErr,
+    klRealmDoesNotExistErr,
+    klNoCredentialsErr,
+    klCredentialsBadAddressErr,
+    klCacheDoesNotExistErr,
+    klNoHostnameErr,
+    klCredentialsNeedValidationErr,
+    
+    /* Password changing errors */
+    klPasswordMismatchErr               = 19576,
+    klInsecurePasswordErr,
+    klPasswordChangeFailedErr,
+    
+#ifdef KERBEROSLOGIN_DEPRECATED
+    /* Dialog errors -- deprecated */
+    klDialogDoesNotExistErr             = 19676,
+    klDialogAlreadyExistsErr,
+    klNotInForegroundErr,
+    klNoAppearanceErr,
+    klFatalDialogErr,
+    klCarbonUnavailableErr,
+#endif
+    
+    /* Login IPC errors */
+    klCantContactServerErr              = 19776,
+    klCantDisplayUIErr,
+    klServerInsecureErr
+    
+};
+typedef int32_t KLEStatus;
+
+/*
+ * Types
+ */
+
+typedef        int32_t   KLStatus;               /* one of KLEStatus */
+typedef        u_int32_t KLKerberosVersion;      /* one of KLEKerberosVersion */
+typedef        u_int32_t KLDefaultLoginOption;   /* one of KLEDefaultLoginOptions */
+typedef        u_int32_t KLLoginMode;            /* one of KLELoginMode */
+typedef        u_int32_t KLDialogIdentifier;     /* one of KLEDialogIdentifiers */
+typedef        u_int32_t KLIndex;                /* index (used for the realm list) */
+typedef        u_int32_t KLLifetime;             /* Lifetime in seconds */
+typedef        u_int32_t KLTime;                 /* Unix time (seconds since 1/1/1970 00:00:00 GMT) */
+typedef        u_int32_t KLSize;                 /* size of a buffer */
+typedef        u_int32_t KLRefCon;               /* application ref con */
+typedef int8_t    KLBoolean;              /* true or false! (unsigned 8 byte value to match Boolean) */
+typedef        int16_t   KLSInt16;               /* used for Darwin-compat for KLApplicationOptions */
+
+/* Callback API for Kerberos Login Mach IPC idle filter */
+typedef void (*KLIdleCallback) (KLRefCon appData);
+#define CallKLIdleCallback(userRoutine, appData) ((userRoutine) (appData))
+
+#ifdef KERBEROSLOGIN_DEPRECATED
+
+/* Application options */
+typedef struct {
+    void *   deprecatedEventFilter;
+    KLRefCon deprecatedEventFilterAppData;
+    KLSInt16 deprecatedRealmsPopupMenuID;
+    KLSInt16 deprecatedLoginModeMenuID;
+} KLApplicationOptions;
+
+#endif
+
+/* Principal information */
+typedef kim_identity KLPrincipal;
+
+/* Login Options */
+typedef kim_options KLLoginOptions;
+
+/*
+ *
+ * Functions
+ *
+ */
+
+/* Deprecated functions -- provided for compatibility with KfM 4.0 */
+#ifdef KERBEROSLOGIN_DEPRECATED
+
+KLStatus KLAcquireTickets (KLPrincipal   inPrincipal,
+                           KLPrincipal  *outPrincipal,
+                           char        **outCredCacheName);
+
+KLStatus KLAcquireNewTickets (KLPrincipal  inPrincipal,
+                              KLPrincipal  *outPrincipal,
+                              char        **outCredCacheName);
+
+KLStatus KLAcquireTicketsWithPassword (KLPrincipal      inPrincipal,
+                                       KLLoginOptions   inLoginOptions,
+                                       const char      *inPassword,
+                                       char           **outCredCacheName);
+
+KLStatus KLAcquireNewTicketsWithPassword (KLPrincipal      inPrincipal,
+                                          KLLoginOptions   inLoginOptions,
+                                          const char      *inPassword,
+                                          char           **outCredCacheName);
+
+KLStatus KLSetApplicationOptions (const KLApplicationOptions *inAppOptions);
+
+KLStatus KLGetApplicationOptions (KLApplicationOptions *outAppOptions);
+
+#endif
+
+/* Kerberos Login high-level API */
+KLStatus KLAcquireInitialTickets (KLPrincipal      inPrincipal,
+                                  KLLoginOptions   inLoginOptions,
+                                  KLPrincipal     *outPrincipal,
+                                  char           **outCredCacheName);
+
+KLStatus KLAcquireNewInitialTickets (KLPrincipal      inPrincipal,
+                                     KLLoginOptions   inLoginOptions,
+                                     KLPrincipal     *outPrincipal,
+                                     char           **outCredCacheName);
+
+KLStatus KLDestroyTickets (KLPrincipal inPrincipal);
+
+KLStatus KLChangePassword (KLPrincipal inPrincipal);
+
+
+/* Kerberos Login dialog low level functions */
+
+KLStatus KLAcquireInitialTicketsWithPassword (KLPrincipal      inPrincipal,
+                                              KLLoginOptions   inLoginOptions,
+                                              const char      *inPassword,
+                                              char           **outCredCacheName);
+
+KLStatus KLAcquireNewInitialTicketsWithPassword (KLPrincipal      inPrincipal,
+                                                 KLLoginOptions   inLoginOptions,
+                                                 const char      *inPassword,
+                                                 char           **outCredCacheName);
+
+KLStatus KLAcquireNewInitialTicketCredentialsWithPassword (KLPrincipal      inPrincipal,
+                                                           KLLoginOptions   inLoginOptions,
+                                                           const char      *inPassword,
+                                                           krb5_context     inV5Context,
+                                                           KLBoolean       *outGotV4Credentials,
+                                                           KLBoolean       *outGotV5Credentials,
+                                                           void            *outV4Credentials,
+                                                           krb5_creds      *outV5Credentials);
+
+KLStatus KLStoreNewInitialTicketCredentials (KLPrincipal     inPrincipal,
+                                             krb5_context    inV5Context,
+                                             void           *inV4Credentials,
+                                             krb5_creds     *inV5Credentials,
+                                             char          **outCredCacheName);
+
+KLStatus KLVerifyInitialTickets (KLPrincipal   inPrincipal,
+                                 KLBoolean     inFailIfNoHostKey,
+                                 char        **outCredCacheName);
+
+KLStatus KLVerifyInitialTicketCredentials (void        *inV4Credentials,
+                                           krb5_creds  *inV5Credentials,
+                                           KLBoolean    inFailIfNoHostKey);
+
+KLStatus KLAcquireNewInitialTicketsWithKeytab (KLPrincipal      inPrincipal,
+                                               KLLoginOptions   inLoginOptions,
+                                               const char      *inKeytabName,
+                                               char           **outCredCacheName);
+
+KLStatus KLRenewInitialTickets (KLPrincipal      inPrincipal,
+                                KLLoginOptions   inLoginOptions,
+                                KLPrincipal     *outPrincipal,
+                                char           **outCredCacheName);
+
+KLStatus KLValidateInitialTickets (KLPrincipal      inPrincipal,
+                                   KLLoginOptions   inLoginOptions,
+                                   char           **outCredCacheName);
+
+KLStatus KLLastChangedTime (KLTime *outLastChangedTime);
+
+KLStatus KLCacheHasValidTickets (KLPrincipal         inPrincipal,
+                                 KLKerberosVersion   inKerberosVersion,
+                                 KLBoolean          *outFoundValidTickets,
+                                 KLPrincipal        *outPrincipal,
+                                 char              **outCredCacheName);
+
+KLStatus KLTicketStartTime (KLPrincipal        inPrincipal,
+                            KLKerberosVersion  inKerberosVersion,
+                            KLTime            *outStartTime);
+
+KLStatus KLTicketExpirationTime (KLPrincipal        inPrincipal,
+                                 KLKerberosVersion  inKerberosVersion,
+                                 KLTime            *outExpirationTime);
+
+KLStatus KLSetSystemDefaultCache (KLPrincipal inPrincipal);
+
+KLStatus KLHandleError (KLStatus           inError,
+                        KLDialogIdentifier inDialogIdentifier,
+                        KLBoolean          inShowAlert);
+
+KLStatus KLGetErrorString (KLStatus   inError,
+                           char     **outErrorString);
+
+KLStatus KLCancelAllDialogs (void);
+
+/* Kerberos change password dialog low level functions */
+
+KLStatus KLChangePasswordWithPasswords (KLPrincipal   inPrincipal,
+                                        const char   *inOldPassword,
+                                        const char   *inNewPassword,
+                                        KLBoolean    *outRejected,
+                                        char        **outRejectionError,
+                                        char        **outRejectionDescription);
+
+/* Application Configuration functions */
+
+KLStatus KLSetIdleCallback (const KLIdleCallback inCallback,
+                            const KLRefCon inRefCon);
+
+KLStatus KLGetIdleCallback (KLIdleCallback* inCallback,
+                            KLRefCon* inRefCon);
+
+/* Library configuration functions */
+
+KLStatus KLGetDefaultLoginOption (const KLDefaultLoginOption  inOption,
+                                  void                       *ioBuffer,
+                                  KLSize                     *ioBufferSize);
+
+KLStatus KLSetDefaultLoginOption (const KLDefaultLoginOption  inOption,
+                                  const void                 *inBuffer,
+                                  const KLSize                inBufferSize);
+
+/* Realm configuration functions */
+
+KLStatus KLFindKerberosRealmByName (const char *inRealmName,
+                                    KLIndex    *outIndex);
+
+KLStatus KLGetKerberosRealm (KLIndex   inIndex,
+                             char    **outRealmName);
+
+KLStatus KLSetKerberosRealm (KLIndex     inIndex,
+                             const char *inRealmName);
+
+KLStatus KLRemoveKerberosRealm (KLIndex inIndex);
+
+KLStatus KLInsertKerberosRealm (KLIndex     inInsertBeforeIndex,
+                                const char *inRealmName);
+
+KLStatus KLRemoveAllKerberosRealms (void);
+
+KLSize KLCountKerberosRealms (void);
+
+KLStatus KLGetKerberosDefaultRealm(KLIndex *outIndex);
+
+KLStatus KLGetKerberosDefaultRealmByName (char **outRealmName);
+
+KLStatus KLSetKerberosDefaultRealm (KLIndex inIndex);
+
+KLStatus KLSetKerberosDefaultRealmByName (const char *inRealm);
+
+/* KLPrincipal functions */
+
+KLStatus KLCreatePrincipalFromTriplet (const char  *inName,
+                                       const char  *inInstance,
+                                       const char  *inRealm,
+                                       KLPrincipal *outPrincipal);
+
+KLStatus KLCreatePrincipalFromString (const char        *inFullPrincipal,
+                                      KLKerberosVersion  inKerberosVersion,
+                                      KLPrincipal       *outPrincipal);
+
+KLStatus KLCreatePrincipalFromKerberos5Principal (krb5_principal  inKerberos5Principal,
+                                                  KLPrincipal    *outPrincipal);
+
+KLStatus KLCreatePrincipalFromPrincipal (KLPrincipal inPrincipal,
+                                         KLPrincipal *outPrincipal);
+
+KLStatus KLGetTripletFromPrincipal (KLPrincipal   inPrincipal,
+                                    char        **outName,
+                                    char        **outInstance,
+                                    char        **outRealm);
+
+KLStatus KLGetStringFromPrincipal (KLPrincipal         inPrincipal,
+                                   KLKerberosVersion   inKerberosVersion,
+                                   char              **outFullPrincipal);
+
+KLStatus KLGetDisplayStringFromPrincipal (KLPrincipal         inPrincipal,
+                                          KLKerberosVersion   inKerberosVersion,
+                                          char              **outFullPrincipal);
+
+KLStatus KLComparePrincipal (KLPrincipal  inFirstPrincipal,
+                             KLPrincipal  inSecondPrincipal,
+                             KLBoolean   *outAreEquivalent);
+
+KLStatus KLDisposePrincipal (KLPrincipal inPrincipal);
+
+/* KLLoginOptions functions */
+
+KLStatus KLCreateLoginOptions (KLLoginOptions *outOptions);
+
+KLStatus KLLoginOptionsSetTicketLifetime (KLLoginOptions ioOptions,
+                                          KLLifetime     inTicketLifetime);
+
+KLStatus KLLoginOptionsSetForwardable (KLLoginOptions ioOptions,
+                                       KLBoolean      inForwardable);
+
+KLStatus KLLoginOptionsSetProxiable (KLLoginOptions ioOptions,
+                                     KLBoolean      inProxiable);
+
+KLStatus KLLoginOptionsSetRenewableLifetime (KLLoginOptions ioOptions,
+                                             KLLifetime     inRenewableLifetime);
+
+KLStatus KLLoginOptionsSetAddressless (KLLoginOptions ioOptions,
+                                       KLBoolean      inAddressless);
+
+KLStatus KLLoginOptionsSetTicketStartTime (KLLoginOptions ioOptions,
+                                           KLTime         inStartTime);
+
+KLStatus KLLoginOptionsSetServiceName (KLLoginOptions  ioOptions,
+                                       const char     *inServiceName);
+
+KLStatus KLDisposeLoginOptions(KLLoginOptions ioOptions);
+
+
+/* Misc function */
+
+KLStatus KLDisposeString (char *inStringToDispose);
+
+#if TARGET_OS_MAC
+#    pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __KERBEROSLOGIN__ */