739 lines
24 KiB
Diff
739 lines
24 KiB
Diff
|
From 0afb9c336dd8573faa025915fcb97e643cc3e748 Mon Sep 17 00:00:00 2001
|
||
|
From: Greg Hudson <ghudson@mit.edu>
|
||
|
Date: Sun, 11 Feb 2018 15:23:35 -0500
|
||
|
Subject: [PATCH] Simplify kdc_preauth.c systems table
|
||
|
|
||
|
Get rid of static_preauth_systems, and replace it with explicit calls
|
||
|
to helper functions in get_preauth_hint_list() and return_padata().
|
||
|
Stop preallocating pa-data lists, instead reallocating on each
|
||
|
addition using add_pa_data_element(). Also simplify
|
||
|
maybe_add_etype_info2() using add_pa_data_element().
|
||
|
|
||
|
The KRB5_PADATA_PAC_REQUEST table entry did nothing, and was probably
|
||
|
originally added back when the KDC would error out on unrecognized
|
||
|
padata types. The KRB5_PADATA_SERVER_REFERRAL entry has been disabled
|
||
|
since it was first added.
|
||
|
|
||
|
(cherry picked from commit fea1a488924faa3938ef723feaa1ff12d22a91ff)
|
||
|
---
|
||
|
src/kdc/kdc_preauth.c | 526 ++++++++++++++++++--------------------------------
|
||
|
1 file changed, 184 insertions(+), 342 deletions(-)
|
||
|
|
||
|
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
|
||
|
index edc30bd83..6f34dc289 100644
|
||
|
--- a/src/kdc/kdc_preauth.c
|
||
|
+++ b/src/kdc/kdc_preauth.c
|
||
|
@@ -101,108 +101,14 @@ typedef struct preauth_system_st {
|
||
|
krb5_kdcpreauth_loop_fn loop;
|
||
|
} preauth_system;
|
||
|
|
||
|
+static preauth_system *preauth_systems;
|
||
|
+static size_t n_preauth_systems;
|
||
|
+
|
||
|
static krb5_error_code
|
||
|
make_etype_info(krb5_context context, krb5_preauthtype pa_type,
|
||
|
krb5_principal client, krb5_key_data *client_key,
|
||
|
krb5_enctype enctype, krb5_pa_data **pa_out);
|
||
|
|
||
|
-static void
|
||
|
-get_etype_info(krb5_context context, krb5_kdc_req *request,
|
||
|
- krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
|
||
|
- krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
|
||
|
- krb5_kdcpreauth_edata_respond_fn respond, void *arg);
|
||
|
-
|
||
|
-static krb5_error_code
|
||
|
-return_etype_info(krb5_context, krb5_pa_data *padata,
|
||
|
- krb5_data *req_pkt, krb5_kdc_req *request,
|
||
|
- krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
|
||
|
- krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
|
||
|
- krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
|
||
|
- krb5_kdcpreauth_modreq modreq);
|
||
|
-
|
||
|
-static krb5_error_code
|
||
|
-return_pw_salt(krb5_context, krb5_pa_data *padata,
|
||
|
- krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
|
||
|
- krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
|
||
|
- krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
|
||
|
- krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq);
|
||
|
-
|
||
|
-
|
||
|
-
|
||
|
-static preauth_system static_preauth_systems[] = {
|
||
|
- {
|
||
|
- "FAST",
|
||
|
- KRB5_PADATA_FX_FAST,
|
||
|
- PA_HARDWARE,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- 0
|
||
|
- },
|
||
|
- {
|
||
|
- "etype-info",
|
||
|
- KRB5_PADATA_ETYPE_INFO,
|
||
|
- PA_HARDWARE,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- get_etype_info,
|
||
|
- 0,
|
||
|
- return_etype_info
|
||
|
- },
|
||
|
- {
|
||
|
- "etype-info2",
|
||
|
- KRB5_PADATA_ETYPE_INFO2,
|
||
|
- PA_HARDWARE,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- get_etype_info,
|
||
|
- 0,
|
||
|
- return_etype_info
|
||
|
- },
|
||
|
- {
|
||
|
- "pw-salt",
|
||
|
- KRB5_PADATA_PW_SALT,
|
||
|
- PA_PSEUDO, /* Don't include this in the error list */
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- 0,
|
||
|
- 0,
|
||
|
- return_pw_salt
|
||
|
- },
|
||
|
- {
|
||
|
- "pac-request",
|
||
|
- KRB5_PADATA_PAC_REQUEST,
|
||
|
- PA_PSEUDO,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL,
|
||
|
- NULL
|
||
|
- },
|
||
|
-#if 0
|
||
|
- {
|
||
|
- "server-referral",
|
||
|
- KRB5_PADATA_SERVER_REFERRAL,
|
||
|
- PA_PSEUDO,
|
||
|
- 0,
|
||
|
- 0,
|
||
|
- return_server_referral
|
||
|
- },
|
||
|
-#endif
|
||
|
-};
|
||
|
-
|
||
|
-#define NUM_STATIC_PREAUTH_SYSTEMS (sizeof(static_preauth_systems) / \
|
||
|
- sizeof(*static_preauth_systems))
|
||
|
-
|
||
|
-static preauth_system *preauth_systems;
|
||
|
-static size_t n_preauth_systems;
|
||
|
-
|
||
|
/* Get all available kdcpreauth vtables and a count of preauth types they
|
||
|
* support. Return an empty list on failure. */
|
||
|
static void
|
||
|
@@ -284,7 +190,6 @@ load_preauth_plugins(struct server_handle *handle, krb5_context context,
|
||
|
get_plugin_vtables(context, &vtables, &n_tables, &n_systems);
|
||
|
|
||
|
/* Allocate the list of static and plugin preauth systems. */
|
||
|
- n_systems += NUM_STATIC_PREAUTH_SYSTEMS;
|
||
|
preauth_systems = calloc(n_systems + 1, sizeof(preauth_system));
|
||
|
if (preauth_systems == NULL)
|
||
|
goto cleanup;
|
||
|
@@ -292,13 +197,8 @@ load_preauth_plugins(struct server_handle *handle, krb5_context context,
|
||
|
if (get_realm_names(handle, &realm_names))
|
||
|
goto cleanup;
|
||
|
|
||
|
- /* Add the static system to the list first. No static systems require
|
||
|
- * initialization, so just make a direct copy. */
|
||
|
- memcpy(preauth_systems, static_preauth_systems,
|
||
|
- sizeof(static_preauth_systems));
|
||
|
-
|
||
|
/* Add the dynamically-loaded mechanisms to the list. */
|
||
|
- n_systems = NUM_STATIC_PREAUTH_SYSTEMS;
|
||
|
+ n_systems = 0;
|
||
|
for (i = 0; i < n_tables; i++) {
|
||
|
/* Try to initialize this module. */
|
||
|
vt = &vtables[i];
|
||
|
@@ -622,7 +522,9 @@ find_pa_system(int type, preauth_system **preauth)
|
||
|
{
|
||
|
preauth_system *ap;
|
||
|
|
||
|
- ap = preauth_systems ? preauth_systems : static_preauth_systems;
|
||
|
+ if (preauth_systems == NULL)
|
||
|
+ return KRB5_PREAUTH_BAD_TYPE;
|
||
|
+ ap = preauth_systems;
|
||
|
while ((ap->type != -1) && (ap->type != type))
|
||
|
ap++;
|
||
|
if (ap->type == -1)
|
||
|
@@ -776,6 +678,98 @@ const char *missing_required_preauth(krb5_db_entry *client,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/* Return true if request's enctypes indicate support for etype-info2. */
|
||
|
+static krb5_boolean
|
||
|
+requires_info2(const krb5_kdc_req *request)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; i < request->nktypes; i++) {
|
||
|
+ if (enctype_requires_etype_info_2(request->ktype[i]))
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+ return FALSE;
|
||
|
+}
|
||
|
+
|
||
|
+/* Add PA-ETYPE-INFO2 and possibly PA-ETYPE-INFO entries to pa_list as
|
||
|
+ * appropriate for the request and client principal. */
|
||
|
+static krb5_error_code
|
||
|
+add_etype_info(krb5_context context, krb5_kdcpreauth_rock rock,
|
||
|
+ krb5_pa_data ***pa_list)
|
||
|
+{
|
||
|
+ krb5_error_code ret;
|
||
|
+ krb5_pa_data *pa;
|
||
|
+
|
||
|
+ if (rock->client_key == NULL)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (!requires_info2(rock->request)) {
|
||
|
+ /* Include PA-ETYPE-INFO only for old clients. */
|
||
|
+ ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO,
|
||
|
+ rock->client->princ, rock->client_key,
|
||
|
+ rock->client_keyblock->enctype, &pa);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+ /* add_pa_data_element() claims pa on success or failure. */
|
||
|
+ ret = add_pa_data_element(pa_list, pa);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Always include PA-ETYPE-INFO2. */
|
||
|
+ ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
|
||
|
+ rock->client->princ, rock->client_key,
|
||
|
+ rock->client_keyblock->enctype, &pa);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+ /* add_pa_data_element() claims pa on success or failure. */
|
||
|
+ return add_pa_data_element(pa_list, pa);
|
||
|
+}
|
||
|
+
|
||
|
+/* Add PW-SALT or AFS3-SALT entries to pa_list as appropriate for the request
|
||
|
+ * and client principal. */
|
||
|
+static krb5_error_code
|
||
|
+add_pw_salt(krb5_context context, krb5_kdcpreauth_rock rock,
|
||
|
+ krb5_pa_data ***pa_list)
|
||
|
+{
|
||
|
+ krb5_error_code ret;
|
||
|
+ krb5_pa_data *pa;
|
||
|
+ krb5_data *salt = NULL;
|
||
|
+ krb5_int16 salttype;
|
||
|
+
|
||
|
+ /* Only include this pa-data for old clients. */
|
||
|
+ if (rock->client_key == NULL || requires_info2(rock->request))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ ret = krb5_dbe_compute_salt(context, rock->client_key,
|
||
|
+ rock->request->client, &salttype, &salt);
|
||
|
+ if (ret)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
|
||
|
+ ret = alloc_pa_data(KRB5_PADATA_AFS3_SALT, salt->length + 1, &pa);
|
||
|
+ if (ret)
|
||
|
+ goto cleanup;
|
||
|
+ memcpy(pa->contents, salt->data, salt->length);
|
||
|
+ pa->contents[salt->length] = '\0';
|
||
|
+ } else {
|
||
|
+ /* Steal memory from salt to make the pa-data entry. */
|
||
|
+ ret = alloc_pa_data(KRB5_PADATA_PW_SALT, 0, &pa);
|
||
|
+ if (ret)
|
||
|
+ goto cleanup;
|
||
|
+ pa->length = salt->length;
|
||
|
+ pa->contents = (uint8_t *)salt->data;
|
||
|
+ salt->data = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* add_pa_data_element() claims pa on success or failure. */
|
||
|
+ ret = add_pa_data_element(pa_list, pa);
|
||
|
+
|
||
|
+cleanup:
|
||
|
+ krb5_free_data(context, salt);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
struct hint_state {
|
||
|
kdc_hint_respond_fn respond;
|
||
|
void *arg;
|
||
|
@@ -787,7 +781,7 @@ struct hint_state {
|
||
|
|
||
|
int hw_only;
|
||
|
preauth_system *ap;
|
||
|
- krb5_pa_data **pa_data, **pa_cur;
|
||
|
+ krb5_pa_data **pa_data;
|
||
|
krb5_preauthtype pa_type;
|
||
|
};
|
||
|
|
||
|
@@ -799,7 +793,7 @@ hint_list_finish(struct hint_state *state, krb5_error_code code)
|
||
|
kdc_realm_t *kdc_active_realm = state->realm;
|
||
|
|
||
|
if (!code) {
|
||
|
- if (state->pa_data[0] == 0) {
|
||
|
+ if (state->pa_data == NULL) {
|
||
|
krb5_klog_syslog(LOG_INFO,
|
||
|
_("%spreauth required but hint list is empty"),
|
||
|
state->hw_only ? "hw" : "");
|
||
|
@@ -820,20 +814,27 @@ hint_list_next(struct hint_state *arg);
|
||
|
static void
|
||
|
finish_get_edata(void *arg, krb5_error_code code, krb5_pa_data *pa)
|
||
|
{
|
||
|
+ krb5_error_code ret;
|
||
|
struct hint_state *state = arg;
|
||
|
|
||
|
if (code == 0) {
|
||
|
if (pa == NULL) {
|
||
|
- /* Include an empty value of the current type. */
|
||
|
- pa = calloc(1, sizeof(*pa));
|
||
|
- pa->magic = KV5M_PA_DATA;
|
||
|
- pa->pa_type = state->pa_type;
|
||
|
+ ret = alloc_pa_data(state->pa_type, 0, &pa);
|
||
|
+ if (ret)
|
||
|
+ goto error;
|
||
|
}
|
||
|
- *state->pa_cur++ = pa;
|
||
|
+ /* add_pa_data_element() claims pa on success or failure. */
|
||
|
+ ret = add_pa_data_element(&state->pa_data, pa);
|
||
|
+ if (ret)
|
||
|
+ goto error;
|
||
|
}
|
||
|
|
||
|
state->ap++;
|
||
|
hint_list_next(state);
|
||
|
+ return;
|
||
|
+
|
||
|
+error:
|
||
|
+ hint_list_finish(state, ret);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -870,16 +871,16 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
|
||
|
krb5_pa_data ***e_data_out, kdc_hint_respond_fn respond,
|
||
|
void *arg)
|
||
|
{
|
||
|
+ kdc_realm_t *kdc_active_realm = rock->rstate->realm_data;
|
||
|
struct hint_state *state;
|
||
|
+ krb5_pa_data *pa;
|
||
|
|
||
|
*e_data_out = NULL;
|
||
|
|
||
|
/* Allocate our state. */
|
||
|
state = calloc(1, sizeof(*state));
|
||
|
- if (state == NULL) {
|
||
|
- (*respond)(arg);
|
||
|
- return;
|
||
|
- }
|
||
|
+ if (state == NULL)
|
||
|
+ goto error;
|
||
|
state->hw_only = isflagset(rock->client->attributes,
|
||
|
KRB5_KDB_REQUIRES_HW_AUTH);
|
||
|
state->respond = respond;
|
||
|
@@ -888,17 +889,27 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock,
|
||
|
state->rock = rock;
|
||
|
state->realm = rock->rstate->realm_data;
|
||
|
state->e_data_out = e_data_out;
|
||
|
-
|
||
|
- state->pa_data = calloc(n_preauth_systems + 1, sizeof(krb5_pa_data *));
|
||
|
- if (!state->pa_data) {
|
||
|
- free(state);
|
||
|
- (*respond)(arg);
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- state->pa_cur = state->pa_data;
|
||
|
+ state->pa_data = NULL;
|
||
|
state->ap = preauth_systems;
|
||
|
+
|
||
|
+ /* Add an empty PA-FX-FAST element to advertise FAST support. */
|
||
|
+ if (alloc_pa_data(KRB5_PADATA_FX_FAST, 0, &pa) != 0)
|
||
|
+ goto error;
|
||
|
+ /* add_pa_data_element() claims pa on success or failure. */
|
||
|
+ if (add_pa_data_element(&state->pa_data, pa) != 0)
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ if (add_etype_info(kdc_context, rock, &state->pa_data) != 0)
|
||
|
+ goto error;
|
||
|
+
|
||
|
hint_list_next(state);
|
||
|
+ return;
|
||
|
+
|
||
|
+error:
|
||
|
+ if (state != NULL)
|
||
|
+ krb5_free_pa_data(kdc_context, state->pa_data);
|
||
|
+ free(state);
|
||
|
+ (*respond)(arg);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
@@ -1029,10 +1040,10 @@ filter_preauth_error(krb5_error_code code)
|
||
|
static krb5_error_code
|
||
|
maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
|
||
|
{
|
||
|
+ krb5_error_code ret;
|
||
|
krb5_context context = state->context;
|
||
|
krb5_kdcpreauth_rock rock = state->rock;
|
||
|
- krb5_pa_data **list = state->pa_e_data;
|
||
|
- size_t count;
|
||
|
+ krb5_pa_data *pa;
|
||
|
|
||
|
/* Only add key information when requesting another preauth round trip. */
|
||
|
if (code != KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
|
||
|
@@ -1048,18 +1059,14 @@ maybe_add_etype_info2(struct padata_state *state, krb5_error_code code)
|
||
|
KRB5_PADATA_FX_COOKIE) != NULL)
|
||
|
return 0;
|
||
|
|
||
|
- /* Reallocate state->pa_e_data to make room for the etype-info2 element. */
|
||
|
- for (count = 0; list != NULL && list[count] != NULL; count++);
|
||
|
- list = realloc(list, (count + 2) * sizeof(*list));
|
||
|
- if (list == NULL)
|
||
|
- return ENOMEM;
|
||
|
- list[count] = list[count + 1] = NULL;
|
||
|
- state->pa_e_data = list;
|
||
|
+ ret = make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
|
||
|
+ rock->client->princ, rock->client_key,
|
||
|
+ rock->client_keyblock->enctype, &pa);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
|
||
|
- /* Generate an etype-info2 element in the new slot. */
|
||
|
- return make_etype_info(context, KRB5_PADATA_ETYPE_INFO2,
|
||
|
- rock->client->princ, rock->client_key,
|
||
|
- rock->client_keyblock->enctype, &list[count]);
|
||
|
+ /* add_pa_data_element() claims pa on success or failure. */
|
||
|
+ return add_pa_data_element(&state->pa_e_data, pa);
|
||
|
}
|
||
|
|
||
|
/* Release state and respond to the AS-REQ processing code with the result of
|
||
|
@@ -1279,17 +1286,20 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
|
||
|
{
|
||
|
krb5_error_code retval;
|
||
|
krb5_pa_data ** padata;
|
||
|
- krb5_pa_data ** send_pa_list;
|
||
|
- krb5_pa_data ** send_pa;
|
||
|
+ krb5_pa_data ** send_pa_list = NULL;
|
||
|
+ krb5_pa_data * send_pa;
|
||
|
krb5_pa_data * pa = 0;
|
||
|
krb5_pa_data null_item;
|
||
|
preauth_system * ap;
|
||
|
- int * pa_order;
|
||
|
+ int * pa_order = NULL;
|
||
|
int * pa_type;
|
||
|
int size = 0;
|
||
|
krb5_kdcpreauth_modreq *modreq_ptr;
|
||
|
krb5_boolean key_modified;
|
||
|
krb5_keyblock original_key;
|
||
|
+
|
||
|
+ memset(&original_key, 0, sizeof(original_key));
|
||
|
+
|
||
|
if ((!*padata_context) &&
|
||
|
(make_padata_context(context, padata_context) != 0)) {
|
||
|
return KRB5KRB_ERR_GENERIC;
|
||
|
@@ -1300,26 +1310,18 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
|
||
|
size++;
|
||
|
}
|
||
|
|
||
|
- if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
|
||
|
- return ENOMEM;
|
||
|
- if ((pa_order = malloc((size+1) * sizeof(int))) == NULL) {
|
||
|
- free(send_pa_list);
|
||
|
- return ENOMEM;
|
||
|
- }
|
||
|
+ pa_order = k5calloc(size + 1, sizeof(int), &retval);
|
||
|
+ if (pa_order == NULL)
|
||
|
+ goto cleanup;
|
||
|
sort_pa_order(context, request, pa_order);
|
||
|
|
||
|
retval = krb5_copy_keyblock_contents(context, encrypting_key,
|
||
|
&original_key);
|
||
|
- if (retval) {
|
||
|
- free(send_pa_list);
|
||
|
- free(pa_order);
|
||
|
- return retval;
|
||
|
- }
|
||
|
+ if (retval)
|
||
|
+ goto cleanup;
|
||
|
key_modified = FALSE;
|
||
|
null_item.contents = NULL;
|
||
|
null_item.length = 0;
|
||
|
- send_pa = send_pa_list;
|
||
|
- *send_pa = 0;
|
||
|
|
||
|
for (pa_type = pa_order; *pa_type != -1; pa_type++) {
|
||
|
ap = &preauth_systems[*pa_type];
|
||
|
@@ -1349,20 +1351,30 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
+ send_pa = NULL;
|
||
|
retval = ap->return_padata(context, pa, req_pkt, request, reply,
|
||
|
- encrypting_key, send_pa, &callbacks, rock,
|
||
|
+ encrypting_key, &send_pa, &callbacks, rock,
|
||
|
ap->moddata, *modreq_ptr);
|
||
|
if (retval)
|
||
|
goto cleanup;
|
||
|
|
||
|
- if (*send_pa)
|
||
|
- send_pa++;
|
||
|
- *send_pa = 0;
|
||
|
+ if (send_pa != NULL) {
|
||
|
+ /* add_pa_data_element() claims send_pa on success or failure. */
|
||
|
+ retval = add_pa_data_element(&send_pa_list, send_pa);
|
||
|
+ if (retval)
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
- retval = 0;
|
||
|
+ /* Add etype-info and pw-salt pa-data as needed. */
|
||
|
+ retval = add_etype_info(context, rock, &send_pa_list);
|
||
|
+ if (retval)
|
||
|
+ goto cleanup;
|
||
|
+ retval = add_pw_salt(context, rock, &send_pa_list);
|
||
|
+ if (retval)
|
||
|
+ goto cleanup;
|
||
|
|
||
|
- if (send_pa_list[0]) {
|
||
|
+ if (send_pa_list != NULL) {
|
||
|
reply->padata = send_pa_list;
|
||
|
send_pa_list = 0;
|
||
|
}
|
||
|
@@ -1370,8 +1382,7 @@ return_padata(krb5_context context, krb5_kdcpreauth_rock rock,
|
||
|
cleanup:
|
||
|
krb5_free_keyblock_contents(context, &original_key);
|
||
|
free(pa_order);
|
||
|
- if (send_pa_list)
|
||
|
- krb5_free_pa_data(context, send_pa_list);
|
||
|
+ krb5_free_pa_data(context, send_pa_list);
|
||
|
|
||
|
return (retval);
|
||
|
}
|
||
|
@@ -1438,9 +1449,8 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
|
||
|
krb5_enctype enctype, krb5_pa_data **pa_out)
|
||
|
{
|
||
|
krb5_error_code retval;
|
||
|
- krb5_pa_data *pa = NULL;
|
||
|
krb5_etype_info_entry **entry = NULL;
|
||
|
- krb5_data *scratch = NULL;
|
||
|
+ krb5_data *der_etype_info = NULL;
|
||
|
int etype_info2 = (pa_type == KRB5_PADATA_ETYPE_INFO2);
|
||
|
|
||
|
*pa_out = NULL;
|
||
|
@@ -1454,125 +1464,23 @@ make_etype_info(krb5_context context, krb5_preauthtype pa_type,
|
||
|
goto cleanup;
|
||
|
|
||
|
if (etype_info2)
|
||
|
- retval = encode_krb5_etype_info2(entry, &scratch);
|
||
|
+ retval = encode_krb5_etype_info2(entry, &der_etype_info);
|
||
|
else
|
||
|
- retval = encode_krb5_etype_info(entry, &scratch);
|
||
|
+ retval = encode_krb5_etype_info(entry, &der_etype_info);
|
||
|
if (retval)
|
||
|
goto cleanup;
|
||
|
- pa = k5alloc(sizeof(*pa), &retval);
|
||
|
- if (pa == NULL)
|
||
|
+
|
||
|
+ /* Steal the data from der_etype_info to create a pa-data element. */
|
||
|
+ retval = alloc_pa_data(pa_type, 0, pa_out);
|
||
|
+ if (retval)
|
||
|
goto cleanup;
|
||
|
- pa->magic = KV5M_PA_DATA;
|
||
|
- pa->pa_type = pa_type;
|
||
|
- pa->contents = (unsigned char *)scratch->data;
|
||
|
- pa->length = scratch->length;
|
||
|
- scratch->data = NULL;
|
||
|
- *pa_out = pa;
|
||
|
+ (*pa_out)->contents = (uint8_t *)der_etype_info->data;
|
||
|
+ (*pa_out)->length = der_etype_info->length;
|
||
|
+ der_etype_info->data = NULL;
|
||
|
|
||
|
cleanup:
|
||
|
krb5_free_etype_info(context, entry);
|
||
|
- krb5_free_data(context, scratch);
|
||
|
- return retval;
|
||
|
-}
|
||
|
-
|
||
|
-/* Return true if request's enctypes indicate support for etype-info2. */
|
||
|
-static krb5_boolean
|
||
|
-requires_info2(const krb5_kdc_req *request)
|
||
|
-{
|
||
|
- int i;
|
||
|
-
|
||
|
- for (i = 0; i < request->nktypes; i++) {
|
||
|
- if (enctype_requires_etype_info_2(request->ktype[i]))
|
||
|
- return TRUE;
|
||
|
- }
|
||
|
- return FALSE;
|
||
|
-}
|
||
|
-
|
||
|
-/* Generate hint list padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */
|
||
|
-static void
|
||
|
-get_etype_info(krb5_context context, krb5_kdc_req *request,
|
||
|
- krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
|
||
|
- krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
|
||
|
- krb5_kdcpreauth_edata_respond_fn respond, void *arg)
|
||
|
-{
|
||
|
- krb5_error_code ret;
|
||
|
- krb5_pa_data *pa = NULL;
|
||
|
-
|
||
|
- if (rock->client_key == NULL) {
|
||
|
- ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
|
||
|
- } else if (pa_type == KRB5_PADATA_ETYPE_INFO && requires_info2(request)) {
|
||
|
- ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
|
||
|
- } else {
|
||
|
- ret = make_etype_info(context, pa_type, rock->client->princ,
|
||
|
- rock->client_key, rock->client_keyblock->enctype,
|
||
|
- &pa);
|
||
|
- }
|
||
|
- (*respond)(arg, ret, pa);
|
||
|
-}
|
||
|
-
|
||
|
-/* Generate AS-REP padata for PA-ETYPE-INFO or PA-ETYPE-INFO2. */
|
||
|
-static krb5_error_code
|
||
|
-return_etype_info(krb5_context context, krb5_pa_data *padata,
|
||
|
- krb5_data *req_pkt, krb5_kdc_req *request,
|
||
|
- krb5_kdc_rep *reply, krb5_keyblock *encrypting_key,
|
||
|
- krb5_pa_data **send_pa, krb5_kdcpreauth_callbacks cb,
|
||
|
- krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
|
||
|
- krb5_kdcpreauth_modreq modreq)
|
||
|
-{
|
||
|
- *send_pa = NULL;
|
||
|
- if (rock->client_key == NULL)
|
||
|
- return 0;
|
||
|
- if (padata->pa_type == KRB5_PADATA_ETYPE_INFO && requires_info2(request))
|
||
|
- return 0;
|
||
|
- return make_etype_info(context, padata->pa_type, rock->client->princ,
|
||
|
- rock->client_key, encrypting_key->enctype, send_pa);
|
||
|
-}
|
||
|
-
|
||
|
-static krb5_error_code
|
||
|
-return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
|
||
|
- krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply,
|
||
|
- krb5_keyblock *encrypting_key, krb5_pa_data **send_pa,
|
||
|
- krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
|
||
|
- krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq)
|
||
|
-{
|
||
|
- krb5_error_code retval;
|
||
|
- krb5_pa_data * padata;
|
||
|
- krb5_data * salt = NULL;
|
||
|
- krb5_int16 salttype;
|
||
|
- krb5_key_data * client_key = rock->client_key;
|
||
|
-
|
||
|
- if (client_key == NULL || requires_info2(request))
|
||
|
- return 0;
|
||
|
-
|
||
|
- retval = krb5_dbe_compute_salt(context, client_key, request->client,
|
||
|
- &salttype, &salt);
|
||
|
- if (retval)
|
||
|
- return 0;
|
||
|
-
|
||
|
- padata = k5alloc(sizeof(*padata), &retval);
|
||
|
- if (padata == NULL)
|
||
|
- goto cleanup;
|
||
|
- padata->magic = KV5M_PA_DATA;
|
||
|
-
|
||
|
- if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
|
||
|
- padata->contents = k5memdup0(salt->data, salt->length, &retval);
|
||
|
- if (padata->contents == NULL)
|
||
|
- goto cleanup;
|
||
|
- padata->pa_type = KRB5_PADATA_AFS3_SALT;
|
||
|
- padata->length = salt->length + 1;
|
||
|
- } else {
|
||
|
- padata->pa_type = KRB5_PADATA_PW_SALT;
|
||
|
- padata->length = salt->length;
|
||
|
- padata->contents = (krb5_octet *)salt->data;
|
||
|
- salt->data = NULL;
|
||
|
- }
|
||
|
-
|
||
|
- *send_pa = padata;
|
||
|
- padata = NULL;
|
||
|
-
|
||
|
-cleanup:
|
||
|
- free(padata);
|
||
|
- krb5_free_data(context, salt);
|
||
|
+ krb5_free_data(context, der_etype_info);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
@@ -1656,69 +1564,3 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt,
|
||
|
cleanup:
|
||
|
return code;
|
||
|
}
|
||
|
-
|
||
|
-
|
||
|
-#if 0
|
||
|
-static krb5_error_code return_server_referral(krb5_context context,
|
||
|
- krb5_pa_data * padata,
|
||
|
- krb5_db_entry *client,
|
||
|
- krb5_db_entry *server,
|
||
|
- krb5_kdc_req *request,
|
||
|
- krb5_kdc_rep *reply,
|
||
|
- krb5_key_data *client_key,
|
||
|
- krb5_keyblock *encrypting_key,
|
||
|
- krb5_pa_data **send_pa)
|
||
|
-{
|
||
|
- krb5_error_code code;
|
||
|
- krb5_tl_data tl_data;
|
||
|
- krb5_pa_data *pa_data;
|
||
|
- krb5_enc_data enc_data;
|
||
|
- krb5_data plain;
|
||
|
- krb5_data *enc_pa_data;
|
||
|
-
|
||
|
- *send_pa = NULL;
|
||
|
-
|
||
|
- tl_data.tl_data_type = KRB5_TL_SERVER_REFERRAL;
|
||
|
-
|
||
|
- code = krb5_dbe_lookup_tl_data(context, server, &tl_data);
|
||
|
- if (code || tl_data.tl_data_length == 0)
|
||
|
- return 0; /* no server referrals to return */
|
||
|
-
|
||
|
- plain.length = tl_data.tl_data_length;
|
||
|
- plain.data = tl_data.tl_data_contents;
|
||
|
-
|
||
|
- /* Encrypt ServerReferralData */
|
||
|
- code = krb5_encrypt_helper(context, encrypting_key,
|
||
|
- KRB5_KEYUSAGE_PA_SERVER_REFERRAL_DATA,
|
||
|
- &plain, &enc_data);
|
||
|
- if (code)
|
||
|
- return code;
|
||
|
-
|
||
|
- /* Encode ServerReferralData into PA-SERVER-REFERRAL-DATA */
|
||
|
- code = encode_krb5_enc_data(&enc_data, &enc_pa_data);
|
||
|
- if (code) {
|
||
|
- krb5_free_data_contents(context, &enc_data.ciphertext);
|
||
|
- return code;
|
||
|
- }
|
||
|
-
|
||
|
- krb5_free_data_contents(context, &enc_data.ciphertext);
|
||
|
-
|
||
|
- /* Return PA-SERVER-REFERRAL-DATA */
|
||
|
- pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data));
|
||
|
- if (pa_data == NULL) {
|
||
|
- krb5_free_data(context, enc_pa_data);
|
||
|
- return ENOMEM;
|
||
|
- }
|
||
|
-
|
||
|
- pa_data->magic = KV5M_PA_DATA;
|
||
|
- pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO;
|
||
|
- pa_data->length = enc_pa_data->length;
|
||
|
- pa_data->contents = enc_pa_data->data;
|
||
|
-
|
||
|
- free(enc_pa_data); /* don't free contents */
|
||
|
-
|
||
|
- *send_pa = pa_data;
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-#endif
|