UI should lazy init so that init and fini are only called if one
authorAlexandra Ellwood <lxs@mit.edu>
Mon, 29 Sep 2008 18:52:53 +0000 (18:52 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Mon, 29 Sep 2008 18:52:53 +0000 (18:52 +0000)
of the UI calls is called.  The problem is that when you call
krb5_get_init_creds_* you don't know if it will call the prompter
or not.  (It won't if the password is saved in the keychain or
if pkinit succeeds.)

ticket: 6055

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

src/kim/lib/kim_ui.c
src/kim/lib/kim_ui_private.h
src/kim/lib/mac/kim_os_ui_gui.c

index 819efbf5ba57f0d48d16a73ae02baea1cd5625c2..3abc3f95cec8b9709dddb74434f259e870f1e096 100644 (file)
@@ -40,18 +40,17 @@ static kim_prompt_type kim_ui_ptype2ktype (krb5_prompt_type type)
     return kim_prompt_type_preauth;
 }
 
-
 #pragma mark -
 
 /* ------------------------------------------------------------------------ */
 
-kim_error kim_ui_init (kim_ui_context *io_context)
+static kim_error kim_ui_init_lazy (kim_ui_context *io_context)
 {
     kim_error err = KIM_NO_ERROR;
     
     if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
-    if (!err) {
+    if (!err && !io_context->initialized) {
 #ifndef LEAN_CLIENT
         kim_ui_environment environment = kim_library_ui_environment ();
         
@@ -78,9 +77,30 @@ kim_error kim_ui_init (kim_ui_context *io_context)
             err = check_error (KIM_NO_UI_ERR);
         }
 #endif /* LEAN_CLIENT */
+
+        if (!err) {
+            io_context->initialized = 1;
+        }        
     }
     
+    return check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+kim_error kim_ui_init (kim_ui_context *io_context)
+{
+    kim_error err = KIM_NO_ERROR;
+    
+    if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
     if (!err) {
+        /* Lazy initialization so we only actually initialize if a prompt
+         * gets called.  This is important because krb5_get_init_creds_*
+         * can't tell us if a prompt is going to get called in advance */
+        io_context->initialized = 0;
         io_context->identity = NULL;
         io_context->prompt_count = 0;
     }
@@ -98,6 +118,10 @@ kim_error kim_ui_enter_identity (kim_ui_context      *in_context,
     if (!err && !in_context  ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
+    if (!err) {
+        err = kim_ui_init_lazy (in_context);
+    }
+    
     if (!err) {
         if (in_context->type == kim_ui_type_gui_plugin) {
             err = kim_ui_plugin_enter_identity (in_context, 
@@ -134,6 +158,10 @@ kim_error kim_ui_select_identity (kim_ui_context      *in_context,
     if (!err && !in_hints    ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
+    if (!err) {
+        err = kim_ui_init_lazy (in_context);
+    }
+    
     if (!err) {
         if (in_context->type == kim_ui_type_gui_plugin) {
             err = kim_ui_plugin_select_identity (in_context, 
@@ -201,44 +229,48 @@ krb5_error_code kim_ui_prompter (krb5_context  in_krb5_context,
         
         if (!got_saved_password) {
             context->prompt_count++;
-            
-            if (context->type == kim_ui_type_gui_plugin) {
-                err = kim_ui_plugin_auth_prompt (context, 
-                                                 context->identity, 
-                                                 type,
-                                                 in_prompts[i].hidden,
-                                                 in_name,
-                                                 in_banner,
-                                                 in_prompts[i].prompt,
-                                                 &reply);
-                
+
+            err = kim_ui_init_lazy (in_context);
+
+            if (!err) {
+                if (context->type == kim_ui_type_gui_plugin) {
+                    err = kim_ui_plugin_auth_prompt (context, 
+                                                     context->identity, 
+                                                     type,
+                                                     in_prompts[i].hidden,
+                                                     in_name,
+                                                     in_banner,
+                                                     in_prompts[i].prompt,
+                                                     &reply);
+                    
 #ifndef LEAN_CLIENT
-            } else if (context->type == kim_ui_type_gui_builtin) {
-                err = kim_os_ui_gui_auth_prompt (context, 
-                                                 context->identity, 
-                                                 type,
-                                                 in_prompts[i].hidden,
-                                                 in_name,
-                                                 in_banner,
-                                                 in_prompts[i].prompt,
-                                                 &reply);
-                
-            } else if (context->type == kim_ui_type_cli) {
-                err = kim_ui_cli_auth_prompt (context, 
-                                              context->identity, 
-                                              type,
-                                              in_prompts[i].hidden,
-                                              in_name,
-                                              in_banner,
-                                              in_prompts[i].prompt,
-                                              &reply);
+                } else if (context->type == kim_ui_type_gui_builtin) {
+                    err = kim_os_ui_gui_auth_prompt (context, 
+                                                     context->identity, 
+                                                     type,
+                                                     in_prompts[i].hidden,
+                                                     in_name,
+                                                     in_banner,
+                                                     in_prompts[i].prompt,
+                                                     &reply);
+                    
+                } else if (context->type == kim_ui_type_cli) {
+                    err = kim_ui_cli_auth_prompt (context, 
+                                                  context->identity, 
+                                                  type,
+                                                  in_prompts[i].hidden,
+                                                  in_name,
+                                                  in_banner,
+                                                  in_prompts[i].prompt,
+                                                  &reply);
 #endif /* LEAN_CLIENT */
-                
-            } else {
-                err = check_error (KIM_NO_UI_ERR);
+                    
+                } else {
+                    err = check_error (KIM_NO_UI_ERR);
+                }
             }
         }
-
+        
         if (!err) {
             uint32_t reply_len = strlen (reply);
             
@@ -284,6 +316,10 @@ kim_error kim_ui_change_password (kim_ui_context  *in_context,
     if (!err && !out_new_password   ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !out_verify_password) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
+    if (!err) {
+        err = kim_ui_init_lazy (in_context);
+    }
+
     if (!err) {
         if (in_context->type == kim_ui_type_gui_plugin) {
             err = kim_ui_plugin_change_password (in_context, 
@@ -319,58 +355,6 @@ kim_error kim_ui_change_password (kim_ui_context  *in_context,
     return check_error (err);
 }
 
-/* ------------------------------------------------------------------------ */
-/* Helper function */
-
-kim_error kim_ui_handle_kim_error (kim_ui_context         *in_context,
-                                   kim_identity            in_identity,
-                                   enum kim_ui_error_type  in_type,
-                                   kim_error               in_error)
-{
-    kim_error err = KIM_NO_ERROR;
-    kim_string message = NULL;
-    kim_string description = NULL;
-    
-    if (!err) {
-        /* Do this first so last error doesn't get overwritten */
-        err = kim_string_create_for_last_error (&description, in_error);
-    }
-    
-    if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
-    
-    if (!err) {
-        kim_string key = NULL;
-        
-        switch (in_type) {
-            case kim_ui_error_type_authentication:
-                key = "Kerberos Login Failed:";
-                break;
-                
-            case kim_ui_error_type_change_password:
-                key = "Kerberos Change Password Failed:";
-                break;
-                
-            case kim_ui_error_type_selection:
-            case kim_ui_error_type_generic:
-            default:
-                key = "Kerberos Operation Failed:";
-                break;
-        }
-        
-        err = kim_os_string_create_localized (&message, key);
-    }
-    
-    if (!err) {
-        err = kim_ui_handle_error (in_context, in_identity,
-                                   in_error, message, description);        
-    }
-    
-    kim_string_free (&description);
-    kim_string_free (&message);
-    
-    return check_error (err);
-}
-
 /* ------------------------------------------------------------------------ */
 
 kim_error kim_ui_handle_error (kim_ui_context *in_context,
@@ -385,6 +369,10 @@ kim_error kim_ui_handle_error (kim_ui_context *in_context,
     if (!err && !in_error_message    ) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     if (!err && !in_error_description) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
+    if (!err) {
+        err = kim_ui_init_lazy (in_context);
+    }
+    
     if (!err) {
         if (in_context->type == kim_ui_type_gui_plugin) {
             err = kim_ui_plugin_handle_error (in_context, 
@@ -422,7 +410,9 @@ kim_error kim_ui_handle_error (kim_ui_context *in_context,
 void kim_ui_free_string (kim_ui_context  *in_context,
                          char           **io_string)
 {
-    if (in_context && io_string && *io_string) {
+    kim_error err = kim_ui_init_lazy (in_context);
+    
+    if (!err && in_context && io_string && *io_string) {
         if (in_context->type == kim_ui_type_gui_plugin) {
             kim_ui_plugin_free_string (in_context, 
                                        io_string);
@@ -436,7 +426,6 @@ void kim_ui_free_string (kim_ui_context  *in_context,
             kim_ui_cli_free_string (in_context, 
                                     io_string);
 #endif /* LEAN_CLIENT */    
-            
         }
     }
 }
@@ -449,7 +438,7 @@ kim_error kim_ui_fini (kim_ui_context *io_context)
     
     if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
     
-    if (!err) {
+    if (!err && io_context->initialized) {
         if (io_context->type == kim_ui_type_gui_plugin) {
             err = kim_ui_plugin_fini (io_context);
             
@@ -468,3 +457,57 @@ kim_error kim_ui_fini (kim_ui_context *io_context)
     
     return check_error (err);
 }
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+/* Helper function */
+
+kim_error kim_ui_handle_kim_error (kim_ui_context         *in_context,
+                                   kim_identity            in_identity,
+                                   enum kim_ui_error_type  in_type,
+                                   kim_error               in_error)
+{
+    kim_error err = KIM_NO_ERROR;
+    kim_string message = NULL;
+    kim_string description = NULL;
+    
+    if (!err) {
+        /* Do this first so last error doesn't get overwritten */
+        err = kim_string_create_for_last_error (&description, in_error);
+    }
+    
+    if (!err && !in_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
+    if (!err) {
+        kim_string key = NULL;
+        
+        switch (in_type) {
+            case kim_ui_error_type_authentication:
+                key = "Kerberos Login Failed:";
+                break;
+                
+            case kim_ui_error_type_change_password:
+                key = "Kerberos Change Password Failed:";
+                break;
+                
+            case kim_ui_error_type_selection:
+            case kim_ui_error_type_generic:
+            default:
+                key = "Kerberos Operation Failed:";
+                break;
+        }
+        
+        err = kim_os_string_create_localized (&message, key);
+    }
+    
+    if (!err) {
+        err = kim_ui_handle_error (in_context, in_identity,
+                                   in_error, message, description);        
+    }
+    
+    kim_string_free (&description);
+    kim_string_free (&message);
+    
+    return check_error (err);
+}
index 548836f8d07bbbede3785e7d786f03a5dd6eb7d2..d280f5997489575ade6426825e5c3d8a8e90bf82 100644 (file)
@@ -45,6 +45,7 @@ enum kim_ui_error_type {
 
 /* declare struct on stack.  Deep contents will be freed by kim_ui_fini. */
 typedef struct kim_ui_context {
+    kim_boolean initialized;
     enum kim_ui_type type;
     void *tcontext;
     kim_identity identity;
index 832724f32a17fcbc6d68301209a28a203abeee71..1ada9e21306e1cb9c832f33690986603d719b27c 100644 (file)
@@ -58,6 +58,8 @@ kim_error kim_os_ui_gui_init (kim_ui_context *io_context)
     k5_ipc_stream request = NULL;
     k5_ipc_stream reply = NULL;
     
+    if (!err && !io_context) { err = check_error (KIM_NULL_PARAMETER_ERR); }
+    
     if (!err) {
         err = kim_library_get_application_name (&name);
     }