]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add responder support to get_as_key()
authorNathaniel McCallum <npmccallum@redhat.com>
Fri, 12 Oct 2012 14:33:36 +0000 (10:33 -0400)
committerGreg Hudson <ghudson@mit.edu>
Fri, 12 Oct 2012 15:44:14 +0000 (11:44 -0400)
This follows the design laid out on the project page:
  http://k5wiki.kerberos.org/wiki/Projects/Password_response_item

src/include/k5-int.h
src/include/krb5/krb5.hin
src/include/krb5/preauth_plugin.h
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/gic_keytab.c
src/lib/krb5/krb/gic_pwd.c
src/lib/krb5/krb/init_creds_ctx.h
src/lib/krb5/krb/preauth2.c
src/lib/krb5/krb/preauth_sam2.c

index b96d9675d8bcb1d7e496e4e558b5dc1185ff6d03..57a6277a83c521d2d2eb055e59d8c7b29e7535ad 100644 (file)
@@ -802,7 +802,8 @@ typedef krb5_error_code
 (*krb5_gic_get_as_key_fct)(krb5_context, krb5_principal, krb5_enctype,
                            krb5_prompter_fct, void *prompter_data,
                            krb5_data *salt, krb5_data *s2kparams,
-                           krb5_keyblock *as_key, void *gak_data);
+                           krb5_keyblock *as_key, void *gak_data,
+                           k5_response_items *ritems);
 
 #define CLIENT_ROCK_MAGIC 0x4352434b
 /*
index 933d2b450a0f38a298fc3ca1e1926a771c34addf..db71f962d4104777fd7a42ceecf25cd5ef46a131 100644 (file)
@@ -6357,6 +6357,16 @@ krb5_prompter_posix(krb5_context context, void *data, const char *name,
                     const char *banner, int num_prompts,
                     krb5_prompt prompts[]);
 
+/**
+ * Long-term password responder question
+ *
+ * This question is asked when the long-term password is needed. It has no
+ * challenge and the response is simply the password string.
+ *
+ * @version First introduced in 1.11
+ */
+#define KRB5_RESPONDER_QUESTION_PASSWORD "password"
+
 typedef struct krb5_responder_context_st *krb5_responder_context;
 
 /**
index a9a2ab9d2c65d8dce0517418b085bd98e39a7132..2ae077c941f8b6732f4926790d0116b18b15cc96 100644 (file)
@@ -206,6 +206,9 @@ typedef struct krb5_clpreauth_callbacks_st {
                                         krb5_clpreauth_rock rock,
                                         const char *question);
 
+    /* Indicate interest in the AS key through the responder interface. */
+    void (*need_as_key)(krb5_context context, krb5_clpreauth_rock rock);
+
     /* End of version 2 clpreauth callbacks (added in 1.11). */
 } *krb5_clpreauth_callbacks;
 
index d52147ac26847c2b3d11da6c4412b58140ef4b5d..01eba6b040ba8ef5c78b9eeeb727d95009f459e3 100644 (file)
@@ -1458,7 +1458,7 @@ init_creds_step_reply(krb5_context context,
                                ctx->reply->enc_part.enctype,
                                ctx->prompter, ctx->prompter_data,
                                &ctx->salt, &ctx->s2kparams,
-                               &ctx->as_key, ctx->gak_data);
+                               &ctx->as_key, ctx->gak_data, NULL);
         if (code != 0)
             goto cleanup;
         TRACE_INIT_CREDS_AS_KEY_GAK(context, &ctx->as_key);
index 38051dbfdb63f95ee8cc682824a8f620e7a75fcd..0fd1034a38b1bbb7653c9ac32488c68cc9887d82 100644 (file)
@@ -38,13 +38,18 @@ get_as_key_keytab(krb5_context context,
                   krb5_data *salt,
                   krb5_data *params,
                   krb5_keyblock *as_key,
-                  void *gak_data)
+                  void *gak_data,
+                  k5_response_items *ritems)
 {
     krb5_keytab keytab = (krb5_keytab) gak_data;
     krb5_error_code ret;
     krb5_keytab_entry kt_ent;
     krb5_keyblock *kt_key;
 
+    /* We don't need the password from the responder to create the AS key. */
+    if (as_key == NULL)
+        return 0;
+
     /* if there's already a key of the correct etype, we're done.
        if the etype is wrong, free the existing key, and make
        a new one. */
index f5c0b302788fdc17713167a19165e1aa51c667ba..8ffa342be62295f95d6239008d4b1a552306969c 100644 (file)
@@ -2,6 +2,7 @@
 #include "k5-int.h"
 #include "com_err.h"
 #include "init_creds_ctx.h"
+#include "int-proto.h"
 
 krb5_error_code
 krb5_get_as_key_password(krb5_context context,
@@ -12,7 +13,8 @@ krb5_get_as_key_password(krb5_context context,
                          krb5_data *salt,
                          krb5_data *params,
                          krb5_keyblock *as_key,
-                         void *gak_data)
+                         void *gak_data,
+                         k5_response_items *ritems)
 {
     krb5_data *password;
     krb5_error_code ret;
@@ -21,8 +23,21 @@ krb5_get_as_key_password(krb5_context context,
     char promptstr[1024];
     krb5_prompt prompt;
     krb5_prompt_type prompt_type;
+    const char *rpass;
 
     password = (krb5_data *) gak_data;
+    assert(password->length > 0);
+
+    /* If we need to get the AS key via the responder, ask for it. */
+    if (as_key == NULL) {
+        /* However, if we already have a password, don't ask. */
+        if (password->data[0] != '\0')
+            return 0;
+
+        return k5_response_items_ask_question(ritems,
+                                              KRB5_RESPONDER_QUESTION_PASSWORD,
+                                              NULL );
+    }
 
     /* If there's already a key of the correct etype, we're done.
        If the etype is wrong, free the existing key, and make
@@ -39,7 +54,17 @@ krb5_get_as_key_password(krb5_context context,
         }
     }
 
-    if (password->length == 0 || password->data[0] == '\0') {
+    if (password->data[0] == '\0') {
+        /* Check the responder for the password. */
+        rpass = k5_response_items_get_answer(ritems,
+                                             KRB5_RESPONDER_QUESTION_PASSWORD);
+        if (rpass != NULL) {
+            strlcpy(password->data, rpass, password->length);
+            password->length = strlen(password->data);
+        }
+    }
+
+    if (password->data[0] == '\0') {
         if (prompter == NULL)
             return(EIO);
 
index ae69ed082895a3efcee94d6e7a75f01defce3a65..eb7b608c44b7044e7c8adbd1e1bc224e65497270 100644 (file)
@@ -58,6 +58,7 @@ krb5_get_as_key_password(krb5_context context,
                          krb5_data *salt,
                          krb5_data *params,
                          krb5_keyblock *as_key,
-                         void *gak_data);
+                         void *gak_data,
+                         k5_response_items *ritems);
 
 #endif /* !KRB5_INIT_CREDS_CONTEXT */
index cf46845e2e477c9821cea761c7f81c2db03fe3d8..1ee53a6b72338a0aa86706be9bc08d8183f42b25 100644 (file)
@@ -372,7 +372,8 @@ get_as_key(krb5_context context, krb5_clpreauth_rock rock,
         salt = (*rock->default_salt) ? NULL : rock->salt;
         ret = (*rock->gak_fct)(context, rock->client, *rock->etype,
                                rock->prompter, rock->prompter_data, salt,
-                               rock->s2kparams, rock->as_key, *rock->gak_data);
+                               rock->s2kparams, rock->as_key, *rock->gak_data,
+                               rock->rctx.items);
         if (ret)
             return ret;
     }
@@ -410,6 +411,9 @@ static krb5_error_code
 responder_ask_question(krb5_context context, krb5_clpreauth_rock rock,
                        const char *question, const char *challenge)
 {
+    /* Force plugins to use need_as_key(). */
+    if (strcmp(KRB5_RESPONDER_QUESTION_PASSWORD, question) == 0)
+        return EINVAL;
     return k5_response_items_ask_question(rock->rctx.items, question,
                                           challenge);
 }
@@ -418,9 +422,20 @@ static const char *
 responder_get_answer(krb5_context context, krb5_clpreauth_rock rock,
                      const char *question)
 {
+    /* Don't let plugins get the raw password. */
+    if (question && strcmp(KRB5_RESPONDER_QUESTION_PASSWORD, question) == 0)
+        return NULL;
     return k5_response_items_get_answer(rock->rctx.items, question);
 }
 
+static void
+need_as_key(krb5_context context, krb5_clpreauth_rock rock)
+{
+    /* Calling gac_fct() with NULL as_key indicates desire for the AS key. */
+    (*rock->gak_fct)(context, rock->client, *rock->etype, NULL, NULL, NULL,
+                     NULL, NULL, *rock->gak_data, rock->rctx.items);
+}
+
 static struct krb5_clpreauth_callbacks_st callbacks = {
     2,
     get_etype,
@@ -429,7 +444,8 @@ static struct krb5_clpreauth_callbacks_st callbacks = {
     set_as_key,
     get_preauth_time,
     responder_ask_question,
-    responder_get_answer
+    responder_get_answer,
+    need_as_key
 };
 
 /* Tweak the request body, for now adding any enctypes which the module claims
index 4c63ff42c2206abaeb1cde5fb4920a5c093358a4..0190137e960c6ce048567d657384a0cc4405adff 100644 (file)
@@ -155,7 +155,7 @@ sam2_process(krb5_context context, krb5_clpreauth_moddata moddata,
         retval = (*rock->gak_fct)(context, request->client, sc2b->sam_etype,
                                   prompter, prompter_data, rock->salt,
                                   rock->s2kparams, rock->as_key,
-                                  *rock->gak_data);
+                                  *rock->gak_data, rock->rctx.items);
         if (retval) {
             krb5_free_sam_challenge_2(context, sc2);
             krb5_free_sam_challenge_2_body(context, sc2b);