Add krb5_get_prompt_types() functionality
authorDanilo Almeida <dalmeida@mit.edu>
Thu, 16 Mar 2000 00:47:21 +0000 (00:47 +0000)
committerDanilo Almeida <dalmeida@mit.edu>
Thu, 16 Mar 2000 00:47:21 +0000 (00:47 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12118 dc483132-0cff-0310-8789-dd5450dbe970

13 files changed:
src/clients/kinit/ChangeLog
src/clients/kinit/kinit.c
src/include/ChangeLog
src/include/k5-int.h
src/include/krb5.hin
src/lib/ChangeLog
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/gic_pwd.c
src/lib/krb5/krb/init_ctx.c
src/lib/krb5/krb/preauth2.c
src/lib/krb5/os/ChangeLog
src/lib/krb5/os/prompter.c
src/lib/krb5_32.def

index e6637351bc7c9a83ea6d6e7e0bb5779d2c9c2d24..b4a79a00292f43d884f3162c9e3d1584d98e5893 100644 (file)
@@ -1,3 +1,7 @@
+2000-03-15  Danilo Almeida  <dalmeida@mit.edu>
+
+       * kinit.c: Add support for krb5_get_prompt_types.
+
 2000-03-07  Danilo Almeida  <dalmeida@mit.edu>
 
        * kinit.c: Add support for using both -4 and -5.  Default to krb5
index 4587cb83867758fa91c9513a2c91f704fa4262e0..a78be21bb71a9af34f24ca7ee400eee57cd1f5db 100644 (file)
@@ -240,9 +240,9 @@ fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2)
     fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
     fprintf(stderr, "\t   (Default behavior is to try %s%s%s%s)\n",
            default_k5?"Kerberos 5":"",
-            (default_k5 && default_k4)?" and ":"",
+           (default_k5 && default_k4)?" and ":"",
            default_k4?"Kerberos 4":"",
-            (!default_k5 && !default_k4)?"neither":"");
+           (!default_k5 && !default_k4)?"neither":"");
     ULINE("\t", "-V verbose",                   OPTTYPE_EITHER);
     ULINE("\t", "-l lifetime",                  OPTTYPE_EITHER);
     ULINE("\t", "-s start time",                OPTTYPE_KRB5);
@@ -679,11 +679,40 @@ k4_end(k4)
     memset(k4, 0, sizeof(*k4));
 }
 
+static char stash_password[1024];
+static int got_password = 0;
+
+krb5_error_code
+KRB5_CALLCONV
+kinit_prompter(
+    krb5_context ctx,
+    void *data,
+    const char *name,
+    const char *banner,
+    int num_prompts,
+    krb5_prompt prompts[]
+    )
+{
+    int i;
+    krb5_prompt_type *types;
+    krb5_error_code rc =
+       krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts);
+    if (!rc && (types = krb5_get_prompt_types(ctx)))
+       for (i = 0; i < num_prompts; i++)
+           if ((types[i] == KRB5_PROMPT_TYPE_PASSWORD) ||
+               (types[i] == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN))
+           {
+               strncpy(stash_password, prompts[i].reply->data,
+                       sizeof(stash_password));
+               got_password = 1;
+           }
+    return rc;
+}
+
 int
-k5_kinit(opts, k5, password)
+k5_kinit(opts, k5)
     struct k_opts* opts;
     struct k5_data* k5;
-    char* password;
 {
     char* progname = progname_v5;
     int notix = 1;
@@ -742,7 +771,7 @@ k5_kinit(opts, k5, password)
     switch (opts->action) {
     case INIT_PW:
        code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
-                                           password, krb5_prompter_posix, 0,
+                                           0, kinit_prompter, 0,
                                            opts->starttime, 
                                            opts->service_name,
                                            &options);
@@ -823,10 +852,10 @@ k5_kinit(opts, k5, password)
 }
 
 int
-k4_kinit(opts, k4, password)
+k4_kinit(opts, k4, ctx)
     struct k_opts* opts;
     struct k4_data* k4;
-    char* password;
+    krb5_context ctx;
 {
     char* progname = progname_v4;
     int k_errno = 0;
@@ -852,17 +881,37 @@ k4_kinit(opts, k4, password)
     switch (opts->action)
     {
     case INIT_PW:
+       if (!got_password) {
+           int pwsize = sizeof(stash_password);
+           krb5_error_code code;
+
+           sprintf(prompt, "Password for %s: ", opts.principal_name);
+           password[0] = 0;
+           /*
+             Note: krb5_read_password does not actually look at the
+             context, so we're ok even if we don't have a context.  If
+             we cannot dynamically load krb5, we can substitute any
+             decent read password function instead of the krb5 one.
+           */
+           code = krb5_read_password(ctx, prompt, 0, stash_password, &pwsize);
+           if (code || pwsize == 0)
+           {
+               fprintf(stderr, "Error while reading password for '%s'\n",
+                       opts.principal_name);
+               memset(stash_password, 0, sizeof(stash_password));
+               return 0;
+           }
+           got_password = 1;
+       }
        k_errno = krb_get_pw_in_tkt(k4->aname, k4->inst, k4->realm, "krbtgt", 
-                                   k4->realm, k4->lifetime, password);
+                                   k4->realm, k4->lifetime, stash_password);
 
        if (k_errno) {
-#ifndef HAVE_KRB524
            fprintf(stderr, "%s: %s\n", progname, 
                    krb_get_err_text(k_errno));
            if (authed_k5)
                fprintf(stderr, "Maybe your KDC does not support v4.  "
                        "Try the -5 option next time.\n");
-#endif
            return 0;
        }
        return 1;
@@ -994,7 +1043,6 @@ main(argc, argv)
     struct k_opts opts;
     struct k5_data k5;
     struct k4_data k4;
-    char password[255];
 
     progname = GET_PROGNAME(argv[0]);
     progname_v5 = getvprogname("5");
@@ -1029,38 +1077,14 @@ main(argc, argv)
     got_k5 = k5_begin(&opts, &k5, &k4);
     got_k4 = k4_begin(&opts, &k4);
 
-    if (opts.action == INIT_PW)
-    {
-       char prompt[255];
-       int pwsize = sizeof(password);
-       krb5_error_code code;
-
-       sprintf(prompt, "Password for %s: ", opts.principal_name);
-       password[0] = 0;
-       /*
-         Note: krb5_read_password does not actually look at the
-         context, so we're ok even if we don't have a context.  If
-         we cannot dynamically load krb5, we can substitute any
-         decent read password function instead of the krb5 one.
-       */
-       code = krb5_read_password(k5.ctx, prompt, 0, password, &pwsize);
-       if (code || pwsize == 0)
-       {
-           fprintf(stderr, "Error while reading password for '%s'\n",
-                   opts.principal_name);
-           memset(password, 0, sizeof(password));
-           exit(1);
-       }
-    }
-
-    authed_k5 = k5_kinit(&opts, &k5, password);
-    authed_k4 = k4_kinit(&opts, &k4, password);
-    memset(password, 0, sizeof(password));
-
+    authed_k5 = k5_kinit(&opts, &k5);
 #ifdef HAVE_KRB524
-    if (!authed_k4 && authed_k5)
+    if (authed_k5)
        authed_k4 = try_convert524(&k5);
 #endif
+    if (!authed_k4)
+       authed_k4 = k4_kinit(&opts, &k4, k5.ctx);
+    memset(stash_password, 0, sizeof(stash_password));
 
     if (authed_k5 && opts.verbose)
        fprintf(stderr, "Authenticated to Kerberos v5\n");
index 6ef98ebccf4d55686f4d0171b5ca1b45b0477394..928ecb1fc81d270b8c4377ee01566af65652907c 100644 (file)
@@ -1,3 +1,8 @@
+2000-03-15  Danilo Almeida  <dalmeida@mit.edu>
+
+       * krb5.hin: Add krb5_get_prompt_types() and related defs..
+       * k5-int.h: Add krb5int_set_prompt_types().
+
 2000-03-13  Tom Yu  <tlyu@mit.edu>
 
        * k5-int.h: Update prototype to sync with changes in preauth2.c.
index 26a9c73d6299ce138c2a57091c935133e0906458..1c48809975936c8fa07b695b7b412a730d588b41 100644 (file)
@@ -943,7 +943,6 @@ void krb5_free_etype_info
  * End "preauth.h"
  */
 
-
 typedef krb5_error_code (*krb5_gic_get_as_key_fct)
     KRB5_NPROTOTYPE((krb5_context,
                     krb5_principal,
@@ -1022,6 +1021,7 @@ struct _krb5_context {
        krb5_boolean    profile_secure;
        int             fcc_default_format;
        int             scc_default_format;
+       krb5_prompt_type *prompt_types;
 #ifdef KRB5_DNS_LOOKUP
         krb5_boolean    profile_in_memory;
 #endif /* KRB5_DNS_LOOKUP */
@@ -1511,6 +1511,9 @@ krb5_error_code KRB5_CALLCONV krb5_cc_retrieve_cred_default
        KRB5_PROTOTYPE((krb5_context, krb5_ccache, krb5_flags,
                        krb5_creds *, krb5_creds *));
 
+void krb5int_set_prompt_types
+       KRB5_PROTOTYPE((krb5_context, krb5_prompt_type *));
+
 #if defined(macintosh) && defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
 #pragma import reset
 #endif
index b66d2d3e5505b316a4478af58a35ae2abdd476ff..ea8f93e879e63c3015c80dbedecd00a174a84807 100644 (file)
@@ -2400,6 +2400,20 @@ KRB5_DLLIMP void KRB5_CALLCONV krb5_realm_iterator_free
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_realm_string
        KRB5_PROTOTYPE((krb5_context context, char *str));
 
+/*
+ * Prompter enhancements
+ */
+
+#define KRB5_PROMPT_TYPE_PASSWORD            0x1
+#define KRB5_PROMPT_TYPE_NEW_PASSWORD        0x2
+#define KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN  0x3
+#define KRB5_PROMPT_TYPE_PREAUTH             0x4
+
+typedef krb5_int32 krb5_prompt_type;
+
+KRB5_DLLIMP krb5_prompt_type* KRB5_CALLCONV krb5_get_prompt_types
+       KRB5_PROTOTYPE((krb5_context context));
+
 #ifdef __cplusplus
 }
 #endif
index bbc0f8e598b019674050ef6dd51fdb07e1470c2f..b5abe94b8a8eaab8f777355214b9b140cefd7a62 100644 (file)
@@ -1,3 +1,7 @@
+2000-03-15  Danilo Almeida  <dalmeida@mit.edu>
+
+       * krb5_32.def: Add krb5_get_prompt_types.
+
 2000-02-01  Danilo Almeida  <dalmeida@mit.edu>
 
        * krb5_32.def: Replace decode_krb5_ticket with krb5_decode_ticket.
index 97265206f7d6d025d0332a8c506aa2c240e9ef42..59d8765aa697e72d3e1c99afb62920be2d2a2bd3 100644 (file)
@@ -1,3 +1,9 @@
+2000-03-15  Danilo Almeida  <dalmeida@mit.edu>
+
+       * init_ctx.c (init_common), gic_pwd.c (krb5_get_as_key_password,
+       krb5_get_init_creds_password), preauth2.c (pa_sam): Add support
+       for krb5_get_prompt_types().
+
 2000-03-13  Ken Raeburn  <raeburn@mit.edu>
 
        * preauth2.c (pa_function): Called function now takes new
index c2ee423cc0097e5bf288011db98b1dfeb96f6bc2..7ca43430e8b83d52da3aae634edf069761851276 100644 (file)
@@ -19,6 +19,7 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data,
     char *clientstr;
     char promptstr[1024];
     krb5_prompt prompt;
+    krb5_prompt_type prompt_type;
 
     password = (krb5_data *) gak_data;
 
@@ -53,10 +54,16 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data,
        prompt.prompt = promptstr;
        prompt.hidden = 1;
        prompt.reply = password;
+       prompt_type = KRB5_PROMPT_TYPE_PASSWORD;
 
+       /* PROMPTER_INVOCATION */
+       krb5int_set_prompt_types(context, &prompt_type);
        if (ret = (((*prompter)(context, prompter_data, NULL, NULL,
-                               1, &prompt))))
+                               1, &prompt)))) {
+           krb5int_set_prompt_types(context, 0);
            return(ret);
+       }
+       krb5int_set_prompt_types(context, 0);
     }
 
     if ((salt->length == -1) && (salt->data == NULL)) {
@@ -98,6 +105,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data,
    krb5_data pw0, pw1;
    char banner[1024], pw0array[1024], pw1array[1024];
    krb5_prompt prompt[2];
+   krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])];
 
    master = 0;
    as_reply = NULL;
@@ -193,10 +201,12 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data,
    prompt[0].prompt = "Enter new password";
    prompt[0].hidden = 1;
    prompt[0].reply = &pw0;
+   prompt_types[0] = KRB5_PROMPT_TYPE_NEW_PASSWORD;
 
    prompt[1].prompt = "Enter it again";
    prompt[1].hidden = 1;
    prompt[1].reply = &pw1;
+   prompt_types[1] = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;
 
    strcpy(banner, "Password expired.  You must change it now.");
 
@@ -204,9 +214,13 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data,
       pw0.length = sizeof(pw0array);
       pw1.length = sizeof(pw1array);
 
+      /* PROMPTER_INVOCATION */
+      krb5int_set_prompt_types(context, prompt_types);
       if (ret = ((*prompter)(context, data, 0, banner,
                             sizeof(prompt)/sizeof(prompt[0]), prompt)))
         goto cleanup;
+      krb5int_set_prompt_types(context, 0);
+
 
       if (strcmp(pw0.data, pw1.data) != 0) {
         ret = KRB5_LIBOS_BADPWDMATCH;
@@ -271,6 +285,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data,
                             &master, &as_reply);
 
 cleanup:
+   krb5int_set_prompt_types(context, 0);
    /* if getting the password was successful, then check to see if the
       password is about to expire, and warn if so */
 
@@ -300,6 +315,7 @@ cleanup:
                    hours/24);
 
         /* ignore an error here */
+         /* PROMPTER_INVOCATION */
         (*prompter)(context, data, 0, banner, 0, 0);
       }
    }
index 9159a3717d698bb8895692ff96233f72493b4fd1..e2eccc4021fab5c0c66a4a2f398c6373c5a02bf7 100644 (file)
@@ -196,7 +196,7 @@ init_common (context, secure)
                            0, DEFAULT_CCACHE_TYPE, &tmp);
        ctx->fcc_default_format = tmp + 0x0500;
        ctx->scc_default_format = tmp + 0x0500;
-
+       ctx->prompt_types = 0;
        *context = ctx;
        return 0;
 
index ec80c6520ae04bf8d040209a890e73e26c8be0c7..5ea61c9dc018d68b5ef6d9672ee51282a9f47a76 100644 (file)
@@ -247,6 +247,7 @@ krb5_error_code pa_sam(krb5_context context,
     char                       prompt[100], response[100];
     krb5_data                  response_data;
     krb5_prompt                        kprompt;
+    krb5_prompt_type           prompt_type;
     krb5_data                  defsalt;
     krb5_sam_challenge         *sam_challenge = 0;
     krb5_sam_response          sam_response;
@@ -287,12 +288,17 @@ krb5_error_code pa_sam(krb5_context context,
     kprompt.prompt = prompt;
     kprompt.hidden = sam_challenge->sam_challenge.length?0:1;
     kprompt.reply = &response_data;
+    prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
 
+    /* PROMPTER_INVOCATION */
+    krb5int_set_prompt_types(context, &prompt_type);
     if (ret = ((*prompter)(context, prompter_data, name,
                           banner, 1, &kprompt))) {
        krb5_xfree(sam_challenge);
+       krb5int_set_prompt_types(context, 0);
        return(ret);
     }
+    krb5int_set_prompt_types(context, 0);
 
     enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce;
     if (sam_challenge->sam_nonce == 0) {
index ded442bda1631329ef99278318258ccdc112486f..8f8c018214b2fbe5b969989ef6682bf61e450109 100644 (file)
@@ -1,3 +1,8 @@
+2000-03-15  Danilo Almeida  <dalmeida@mit.edu>
+
+       * prompter.c: Add krb5int_set_prompt_types() and
+       krb5_get_prompt_types().
+
 2000-03-14  Ken Raeburn  <raeburn@mit.edu>
 
        * init_os_ctx.c (os_get_default_config_files): Remove unused
index 800377f78cc6bc54dd9249ef645e104cd2341513..933ff2ceaf577efcc6b38afc953da6c40a549434 100644 (file)
@@ -229,3 +229,20 @@ krb5_prompter_posix(krb5_context context,
 }
 #endif /* !_WIN32 */
 #endif /* !MSDOS */
+
+void
+krb5int_set_prompt_types(context, types)
+    krb5_context context;
+    krb5_prompt_type *types;
+{
+    context->prompt_types = 0;
+}
+
+KRB5_DLLIMP
+krb5_prompt_type*
+KRB5_CALLCONV
+krb5_get_prompt_types(context)
+    krb5_context context;
+{
+    return context->prompt_types;
+}
index df5209df0ca22bacdbf787486271b9a77361ec0e..4c5f271b25203d397f4dff038c063f1600b484b9 100644 (file)
@@ -110,6 +110,7 @@ EXPORTS
        krb5_parse_name
        krb5_principal_compare
        krb5_prompter_posix
+       krb5_get_prompt_types
        krb5_rd_cred
        krb5_rd_error
        krb5_rd_priv