krb5 commit: Refactor AS-REQ nonce and timestamp handling
Greg Hudson
ghudson at MIT.EDU
Wed Jun 5 18:28:56 EDT 2013
https://github.com/krb5/krb5/commit/f2600131fb358339ceccecb1c80af7d471c0501b
commit f2600131fb358339ceccecb1c80af7d471c0501b
Author: Greg Hudson <ghudson at mit.edu>
Date: Sun Jun 2 00:31:04 2013 -0400
Refactor AS-REQ nonce and timestamp handling
Create helper functions to set the request nonce and to set the
request timestamp. Don't bother picking a nonce in
restart_init_creds_loop since we will just pick a new one in
init_creds_step_request. Create a library-internal function to get
the current time with possible adjustment from a preauth-required
error. Only set ctx->request_time in one place (just before encoding
each request). Remove unused parameters from stash_as_reply.
Partially based on a patch from Stef Walter.
src/lib/krb5/krb/get_in_tkt.c | 125 +++++++++++++++++++++++------------------
src/lib/krb5/krb/int-proto.h | 5 ++
src/lib/krb5/krb/preauth2.c | 15 +----
3 files changed, 78 insertions(+), 67 deletions(-)
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 0dd497e..b422d91 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -211,8 +211,6 @@ verify_as_reply(krb5_context context,
static krb5_error_code
stash_as_reply(krb5_context context,
- krb5_timestamp time_now,
- krb5_kdc_req *request,
krb5_kdc_rep *as_reply,
krb5_creds * creds,
krb5_ccache ccache)
@@ -651,6 +649,68 @@ cleanup:
return code;
}
+/* Return the current time, possibly using the offset from a previously
+ * received preauth-required error. */
+krb5_error_code
+k5_init_creds_current_time(krb5_context context, krb5_init_creds_context ctx,
+ krb5_boolean allow_unauth, krb5_timestamp *time_out,
+ krb5_int32 *usec_out)
+{
+ if (ctx->pa_offset_state != NO_OFFSET &&
+ (allow_unauth || ctx->pa_offset_state == AUTH_OFFSET) &&
+ (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME)) {
+ /* Use the offset we got from a preauth-required error. */
+ return k5_time_with_offset(ctx->pa_offset, ctx->pa_offset_usec,
+ time_out, usec_out);
+ } else {
+ /* Use the time offset from the context, or no offset. */
+ return krb5_us_timeofday(context, time_out, usec_out);
+ }
+}
+
+/* Choose a random nonce for ctx->request. */
+static krb5_error_code
+pick_nonce(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_error_code code = 0;
+ unsigned char random_buf[4];
+ krb5_data random_data = make_data(random_buf, 4);
+
+ /* We incorrectly encode this as signed, so make sure we use an unsigned
+ * value to avoid interoperability issues. */
+ code = krb5_c_random_make_octets(context, &random_data);
+ if (code != 0)
+ return code;
+ ctx->request->nonce = 0x7fffffff & load_32_n(random_buf);
+ return 0;
+}
+
+/* Set the timestamps for ctx->request based on the desired lifetimes. */
+static krb5_error_code
+set_request_times(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_timestamp from, now = time(NULL);
+
+ /* Omit request start time unless the caller explicitly asked for one. */
+ from = krb5int_addint32(now, ctx->start_time);
+ if (ctx->start_time != 0)
+ ctx->request->from = from;
+
+ ctx->request->till = krb5int_addint32(from, ctx->tkt_life);
+
+ if (ctx->renew_life > 0) {
+ /* Don't ask for a smaller renewable time than the lifetime. */
+ ctx->request->rtime = krb5int_addint32(from, ctx->renew_life);
+ if (ctx->request->rtime < ctx->request->till)
+ ctx->request->rtime = ctx->request->till;
+ ctx->request->kdc_options &= ~KDC_OPT_RENEWABLE_OK;
+ } else {
+ ctx->request->rtime = 0;
+ }
+
+ return 0;
+}
+
/**
* Throw away any state related to specific realm either at the beginning of a
* request, or when a realm changes, or when we start to use FAST after
@@ -665,9 +725,6 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
krb5_pa_data **padata)
{
krb5_error_code code = 0;
- unsigned char random_buf[4];
- krb5_data random_data;
- krb5_timestamp from;
if (ctx->preauth_to_use) {
krb5_free_pa_data(context, ctx->preauth_to_use);
@@ -694,18 +751,10 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
goto cleanup;
}
- /* Set the request nonce. */
- random_data.length = 4;
- random_data.data = (char *)random_buf;
- code = krb5_c_random_make_octets(context, &random_data);
- if (code !=0)
+ code = set_request_times(context, ctx);
+ if (code != 0)
goto cleanup;
- /*
- * See RT ticket 3196 at MIT. If we set the high bit, we may have
- * compatibility problems with Heimdal, because we (incorrectly) encode
- * this value as signed.
- */
- ctx->request->nonce = 0x7fffffff & load_32_n(random_buf);
+
krb5_free_principal(context, ctx->request->server);
ctx->request->server = NULL;
@@ -715,8 +764,6 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
if (code != 0)
goto cleanup;
- ctx->request_time = time(NULL);
-
code = krb5int_fast_as_armor(context, ctx->fast_state,
ctx->opte, ctx->request);
if (code != 0)
@@ -730,23 +777,6 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
/* give the preauth plugins a chance to prep the request body */
k5_preauth_prepare_request(context, ctx->opte, ctx->request);
- /* Omit request start time in the common case. MIT and Heimdal KDCs will
- * ignore it for non-postdated tickets anyway. */
- from = krb5int_addint32(ctx->request_time, ctx->start_time);
- if (ctx->start_time != 0)
- ctx->request->from = from;
- ctx->request->till = krb5int_addint32(from, ctx->tkt_life);
-
- if (ctx->renew_life > 0) {
- ctx->request->rtime =
- krb5int_addint32(from, ctx->renew_life);
- if (ctx->request->rtime < ctx->request->till) {
- /* don't ask for a smaller renewable time than the lifetime */
- ctx->request->rtime = ctx->request->till;
- }
- ctx->request->kdc_options &= ~(KDC_OPT_RENEWABLE_OK);
- } else
- ctx->request->rtime = 0;
code = krb5int_fast_prep_req_body(context, ctx->fast_state,
ctx->request,
&ctx->outer_request_body);
@@ -791,7 +821,6 @@ krb5_init_creds_init(krb5_context context,
ctx->gak_fct = krb5_get_as_key_password;
ctx->gak_data = &ctx->gakpw;
- ctx->request_time = 0; /* filled in later */
ctx->start_time = start_time;
if (options == NULL) {
@@ -1189,28 +1218,17 @@ init_creds_step_request(krb5_context context,
krb5_data *out)
{
krb5_error_code code;
- char random_buf[4];
- krb5_data random_data;
if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
code = KRB5_GET_IN_TKT_LOOP;
goto cleanup;
}
- /*
- * RFC 6113 requires a new nonce for the inner request on each try. It's
- * permitted to change the nonce even for non-FAST so we do here.
- */
- random_data.length = 4;
- random_data.data = (char *)random_buf;
- code = krb5_c_random_make_octets(context, &random_data);
- if (code !=0)
+
+ /* RFC 6113 requires a new nonce for the inner request on each try. */
+ code = pick_nonce(context, ctx);
+ if (code != 0)
goto cleanup;
- /*
- * See RT ticket 3196 at MIT. If we set the high bit, we may have
- * compatibility problems with Heimdal, because we (incorrectly) encode
- * this value as signed.
- */
- ctx->request->nonce = 0x7fffffff & load_32_n(random_buf);
+
krb5_free_data(context, ctx->inner_request_body);
ctx->inner_request_body = NULL;
code = encode_krb5_kdc_req_body(ctx->request, &ctx->inner_request_body);
@@ -1574,8 +1592,7 @@ init_creds_step_reply(krb5_context context,
if (code)
goto cleanup;
- code = stash_as_reply(context, ctx->request_time, ctx->request,
- ctx->reply, &ctx->cred, NULL);
+ code = stash_as_reply(context, ctx->reply, &ctx->cred, NULL);
if (code != 0)
goto cleanup;
if (ctx->opte && ctx->opte->opt_private->out_ccache) {
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
index 3326154..3a139b5 100644
--- a/src/lib/krb5/krb/int-proto.h
+++ b/src/lib/krb5/krb/int-proto.h
@@ -255,6 +255,11 @@ k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx,
int *use_master);
krb5_error_code
+k5_init_creds_current_time(krb5_context context, krb5_init_creds_context ctx,
+ krb5_boolean allow_unauth, krb5_timestamp *time_out,
+ krb5_int32 *usec_out);
+
+krb5_error_code
k5_preauth(krb5_context context, krb5_init_creds_context ctx,
krb5_pa_data **in_padata, krb5_boolean must_preauth,
krb5_pa_data ***padata_out, krb5_preauthtype *pa_type_out);
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
index 747611e..f1b364d 100644
--- a/src/lib/krb5/krb/preauth2.c
+++ b/src/lib/krb5/krb/preauth2.c
@@ -396,19 +396,8 @@ get_preauth_time(krb5_context context, krb5_clpreauth_rock rock,
krb5_boolean allow_unauth_time, krb5_timestamp *time_out,
krb5_int32 *usec_out)
{
- krb5_init_creds_context ctx = (krb5_init_creds_context)rock;
-
- if (ctx->pa_offset_state != NO_OFFSET &&
- (allow_unauth_time || ctx->pa_offset_state == AUTH_OFFSET) &&
- (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME)) {
- /* Use the offset we got from the preauth-required error. */
- return k5_time_with_offset(ctx->pa_offset, ctx->pa_offset_usec,
- time_out, usec_out);
-
- } else {
- /* Use the time offset from the context, or no offset. */
- return krb5_us_timeofday(context, time_out, usec_out);
- }
+ return k5_init_creds_current_time(context, (krb5_init_creds_context)rock,
+ allow_unauth_time, time_out, usec_out);
}
static krb5_error_code
More information about the cvs-krb5
mailing list