+2003-05-08 Sam Hartman <hartmans@mit.edu>
+
+ * krb5.hin: Add prototype for krb5_c_string_to_key_with_params
+
+ * k5-int.h: Add s2kparams to krb5_gic_get_as_key_fct
+
+2003-05-07 Sam Hartman <hartmans@mit.edu>
+
+ * krb5.hin: Add KRB5_PADATA_ETYPE_INFO2
+
2003-05-09 Ken Raeburn <raeburn@mit.edu>
* k5-int.h (struct _krb5_context): New fields conf_tgs_ktypes,
krb5_prompter_fct,
void *prompter_data,
krb5_data *salt,
+ krb5_data *s2kparams,
krb5_keyblock *as_key,
void *gak_data);
krb5_error_code krb5_do_preauth
(krb5_context, krb5_kdc_req *,
krb5_pa_data **, krb5_pa_data ***,
- krb5_data *, krb5_enctype *,
+ krb5_data *salt, krb5_data *s2kparams,
+ krb5_enctype *,
krb5_keyblock *,
krb5_prompter_fct, void *,
krb5_gic_get_as_key_fct, void *);
(krb5_context context, krb5_enctype enctype,
const krb5_data *string, const krb5_data *salt,
krb5_keyblock *key);
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key_with_params(krb5_context context,
+ krb5_enctype enctype,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
krb5_error_code KRB5_CALLCONV
krb5_c_enctype_compare
#define KRB5_PADATA_SAM_RESPONSE 13 /* draft challenge system response */
#define KRB5_PADATA_PK_AS_REQ 14 /* PKINIT */
#define KRB5_PADATA_PK_AS_REP 15 /* PKINIT */
-
+#define KRB5_PADATA_ETYPE_INFO2 19
#define KRB5_PADATA_SAM_CHALLENGE_2 30 /* draft challenge system, updated */
#define KRB5_PADATA_SAM_RESPONSE_2 31 /* draft challenge system, updated */
+2003-05-08 Sam Hartman <hartmans@mit.edu>
+
+ * kdc_preauth.c (return_pw_salt): Don't return pw-salt if the
+ client's enctype list mandates it supports enctype-info2
+
2003-05-09 Tom Yu <tlyu@mit.edu>
* kdc_util.c (kdc_process_tgs_req): Rename getremotesubkey ->
* kdc_preauth.c (get_etype_info): Patch from Sun to reorganize
code and make sure that even for md5 the database order is
preserved.
+ (enctype_requires_etype_info_2): new function; determines wether a
+ particular enctype in a client request means that the client is
+ required to support etype_info2 by Kerberos clarifications.
+ (etype_info_helper): Renamed from get_etype_info to abstract out
+ code in common between etype_info and etype_info2
+ (get_enctype_info): Return etype info only if request contains no
+ enctypes that require etype_info2
+ (return_etype_info2): New function.
2003-04-02 Sam Hartman <hartmans@mit.edu>
#include "adm_proto.h"
#include <syslog.h>
+#include <assert.h>
+
/* XXX This is ugly and should be in a header file somewhere */
#ifndef KRB5INT_DES_TYPES_DEFINED
#define KRB5INT_DES_TYPES_DEFINED
(krb5_context, krb5_kdc_req *request,
krb5_db_entry *client, krb5_db_entry *server,
krb5_pa_data *data);
+static krb5_error_code
+get_etype_info2(krb5_context context, krb5_kdc_req *request,
+ krb5_db_entry *client, krb5_db_entry *server,
+ krb5_pa_data *pa_data);
+static krb5_error_code
+return_etype_info2(krb5_context, krb5_pa_data * padata,
+ krb5_db_entry *client,
+ krb5_kdc_req *request, krb5_kdc_rep *reply,
+ krb5_key_data *client_key,
+ krb5_keyblock *encrypting_key,
+ krb5_pa_data **send_pa);
+
static krb5_error_code return_pw_salt
(krb5_context, krb5_pa_data * padata,
krb5_db_entry *client,
0,
0
},
+ {
+ "etype-info2",
+ KRB5_PADATA_ETYPE_INFO2,
+ 0,
+ get_etype_info2,
+ 0,
+ return_etype_info2
+ },
{
"pw-salt",
KRB5_PADATA_PW_SALT,
return (retval);
}
+static krb5_boolean
+enctype_requires_etype_info_2(krb5_enctype enctype)
+{
+ switch(enctype) {
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD4:
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES3_CBC_SHA1:
+ case ENCTYPE_DES3_CBC_RAW:
+ case ENCTYPE_ARCFOUR_HMAC:
+ case ENCTYPE_ARCFOUR_HMAC_EXP :
+ case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
+ return 0;
+ default:
+ if (krb5_c_valid_enctype(enctype))
+ return 1;
+ else return 0;
+ }
+}
+
static krb5_boolean
request_contains_enctype (krb5_context context, const krb5_kdc_req *request,
krb5_enctype enctype)
/*
* This function returns the etype information for a particular
* client, to be passed back in the preauth list in the KRB_ERROR
- * message.
+ * message. It supports generating both etype_info and etype_info2
+ * as most of the work is the same.
*/
static krb5_error_code
-get_etype_info(krb5_context context, krb5_kdc_req *request,
+etype_info_helper(krb5_context context, krb5_kdc_req *request,
krb5_db_entry *client, krb5_db_entry *server,
- krb5_pa_data *pa_data)
+ krb5_pa_data *pa_data, int etype_info2)
{
krb5_etype_info_entry ** entry = 0;
krb5_key_data *client_key;
db_etype = ENCTYPE_DES_CBC_MD5;
if (request_contains_enctype(context, request, db_etype)) {
+ assert(etype_info2 ||
+ !enctype_requires_etype_info_2(db_etype));
if ((retval = _make_etype_info_entry(context, request, client_key,
db_etype, &entry[i])) != 0) {
goto cleanup;
seen_des++;
}
}
- retval = encode_krb5_etype_info((const krb5_etype_info_entry **) entry,
+ if (etype_info2)
+ retval = encode_krb5_etype_info2((const krb5_etype_info_entry **) entry,
+ &scratch);
+ else retval = encode_krb5_etype_info((const krb5_etype_info_entry **) entry,
&scratch);
if (retval)
goto cleanup;
return retval;
}
+static krb5_error_code
+get_etype_info(krb5_context context, krb5_kdc_req *request,
+ krb5_db_entry *client, krb5_db_entry *server,
+ krb5_pa_data *pa_data)
+{
+ int i;
+ for (i=0; i < request->nktypes; i++) {
+ if (enctype_requires_etype_info_2(request->ktype[i]))
+ return KRB5KDC_ERR_PADATA_TYPE_NOSUPP ;;;; /*Caller will
+ * skip this
+ * type*/
+ }
+ return etype_info_helper(context, request, client, server, pa_data, 0);
+}
+
+static krb5_error_code
+get_etype_info2(krb5_context context, krb5_kdc_req *request,
+ krb5_db_entry *client, krb5_db_entry *server,
+ krb5_pa_data *pa_data)
+{
+ return etype_info_helper( context, request, client, server, pa_data, 1);
+}
+
+static krb5_error_code
+return_etype_info2(krb5_context context, krb5_pa_data * padata,
+ krb5_db_entry *client,
+ 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 retval;
+ krb5_pa_data *tmp_padata;
+ krb5_etype_info_entry **entry = NULL;
+ krb5_data *scratch = NULL;
+ tmp_padata = malloc( sizeof(krb5_pa_data));
+ if (tmp_padata == NULL)
+ return ENOMEM;
+ tmp_padata->pa_type = KRB5_PADATA_ETYPE_INFO2;
+ entry = malloc(2 * sizeof(krb5_etype_info_entry *));
+ if (entry == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ entry[0] = NULL;
+ entry[1] = NULL;
+ retval = _make_etype_info_entry(context, request, client_key, client_key->key_data_type[0],
+ entry);
+ if (retval)
+ goto cleanup;
+ retval = encode_krb5_etype_info2((const krb5_etype_info_entry **) entry, &scratch);
+ if (retval)
+ goto cleanup;
+ tmp_padata->contents = scratch->data;
+ tmp_padata->length = scratch->length;
+ *send_pa = tmp_padata;
+ cleanup:
+ if (entry)
+ krb5_free_etype_info(context, entry);
+ if (retval) {
+ if (tmp_padata)
+ free(tmp_padata);
+ if (scratch)
+ krb5_free_data(context, scratch);
+ }
+ return retval;
+}
+
+
static krb5_error_code
return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
krb5_db_entry *client, krb5_kdc_req *request,
krb5_pa_data * padata;
krb5_data * scratch;
krb5_data salt_data;
+ int i;
+ for (i = 0; i < request->nktypes; i++) {
+ if (enctype_requires_etype_info_2(request->ktype[i]))
+ return 0;
+ }
if (client_key->key_data_ver == 1 ||
client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)
return 0;
+2003-05-08 Sam Hartman <hartmans@mit.edu>
+
+ * krb5_32.def: Add krb5_c_string_to_key_with_params
+
2003-05-09 Tom Yu <tlyu@mit.edu>
* krb5_32.def: Add krb5_auth_con_getrecvsubkey,
+2003-05-08 Sam Hartman <hartmans@mit.edu>
+
+ * string_to_key.c: Move krb5_c_string_to_key_with_params to krb5.h
+
2003-04-13 Ken Raeburn <raeburn@mit.edu>
* pbkdf2.c (krb5int_pbkdf2): Provide a temporary buffer for the
#include "k5-int.h"
#include "etypes.h"
-/* Eventually this declaration should move to krb5.h. */
krb5_error_code KRB5_CALLCONV
krb5_c_string_to_key_with_params(krb5_context context,
krb5_enctype enctype,
+2003-05-09 Sam Hartman <hartmans@mit.edu>
+
+ * preauth2.c: Patch from Sun to reorganize code for handling
+ etype_info requests. More efficient and easier to implement etype_info2
+ (krb5_do_preauth): Support enctype_info2
+
+2003-05-08 Sam Hartman <hartmans@mit.edu>
+
+ * preauth2.c: Add s2kparams to the declaration of a preauth
+ function, to every instance of a preauth function and to every
+ call to gak_fct
+
+ * get_in_tkt.c (krb5_get_init_creds): Add s2kparams support
+
+ * gic_keytab.c (krb5_get_as_key_keytab): Add s2kparams
+
+ * gic_pwd.c (krb5_get_as_key_password): Add s2kparams support
+
2003-05-09 Ken Raeburn <raeburn@mit.edu>
* init_ctx.c (init_common): Copy tgs_ktypes array to
/*
* lib/krb5/krb/get_in_tkt.c
*
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991, 2003 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
krb5_deltat renew_life;
int loopcount;
krb5_data salt;
+ krb5_data s2kparams;
krb5_keyblock as_key;
krb5_error *err_reply;
krb5_kdc_rep *local_as_reply;
/* initialize everything which will be freed at cleanup */
+ s2kparams.data = NULL;
+ s2kparams.length = 0;
request.server = NULL;
request.ktype = NULL;
request.addresses = NULL;
if ((ret = krb5_do_preauth(context, &request,
padata, &request.padata,
- &salt, &etype, &as_key, prompter,
+ &salt, &s2kparams, &etype, &as_key, prompter,
prompter_data, gak_fct, gak_data)))
goto cleanup;
if ((ret = krb5_do_preauth(context, &request,
local_as_reply->padata, &padata,
- &salt, &etype, &as_key, prompter,
+ &salt, &s2kparams, &etype, &as_key, prompter,
prompter_data, gak_fct, gak_data)))
goto cleanup;
if ((ret = ((*gak_fct)(context, request.client,
local_as_reply->enc_part.enctype,
- prompter, prompter_data, &salt,
+ prompter, prompter_data, &salt, &s2kparams,
&as_key, gak_data))))
goto cleanup;
krb5_prompter_fct prompter,
void *prompter_data,
krb5_data *salt,
+ krb5_data *params,
krb5_keyblock *as_key,
void *gak_data)
{
krb5_prompter_fct prompter,
void *prompter_data,
krb5_data *salt,
+ krb5_data *params,
krb5_keyblock *as_key,
void *gak_data)
{
defsalt.length = 0;
}
- ret = krb5_c_string_to_key(context, etype, password, salt, as_key);
+ ret = krb5_c_string_to_key_with_params(context, etype, password, salt,
+ params->data?params:NULL, as_key);
if (defsalt.length)
krb5_xfree(defsalt.data);
krb5_kdc_req *request,
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
- krb5_data *salt,
+ krb5_data *salt, krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter_fct,
krb5_kdc_req *request,
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
- krb5_data *salt,
+ krb5_data *salt, krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter, void *prompter_data,
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
krb5_data *salt,
+ krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter,
if ((ret = ((*gak_fct)(context, request->client,
*etype ? *etype : request->ktype[0],
prompter, prompter_data,
- salt, as_key, gak_data))))
+ salt, s2kparams, as_key, gak_data))))
return(ret);
}
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
krb5_data *salt,
+ krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter,
*etype = ENCTYPE_DES_CBC_CRC;
if ((ret = (gak_fct)(context, request->client, *etype, prompter,
- prompter_data, salt, as_key, gak_data)))
+ prompter_data, salt, s2kparams, as_key, gak_data)))
return(ret);
}
sprintf(name, "%.*s",
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
krb5_data *salt,
+ krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter,
retval = (gak_fct)(context, request->client,
sc2b->sam_etype, prompter,
- prompter_data, salt, as_key, gak_data);
+ prompter_data, salt, s2kparams, as_key, gak_data);
if (retval) {
krb5_free_sam_challenge_2(context, sc2);
krb5_free_sam_challenge_2_body(context, sc2b);
},
};
-static void
-sort_etype_info(krb5_context context, krb5_kdc_req *request,
- krb5_etype_info_entry **etype_info)
-{
-/* Originally adapted from a proposed solution in ticket 1006. This
- * solution is not efficient, but implementing an efficient sort
- * with a comparison function based on order in the kdc request would
- * be difficult.*/
- krb5_etype_info_entry *tmp;
- int i, j, e;
- krb5_boolean similar;
-
- if (etype_info == NULL)
- return;
-
- /* First, move up etype_info_entries whose enctype exactly matches a
- * requested enctype.
- */
- e = 0;
- for ( i = 0 ; i < request->nktypes && etype_info[e] != NULL ; i++ )
- {
- if (request->ktype[i] == etype_info[e]->etype)
- {
- e++;
- continue;
- }
- for ( j = e+1 ; etype_info[j] ; j++ )
- if (request->ktype[i] == etype_info[j]->etype)
- break;
- if (etype_info[j] == NULL)
- continue;
-
- tmp = etype_info[j];
- etype_info[j] = etype_info[e];
- etype_info[e] = tmp;
- e++;
- }
-
- /* Then move up etype_info_entries whose enctype is similar to a
- * requested enctype.
- */
- for ( i = 0 ; i < request->nktypes && etype_info[e] != NULL ; i++ )
- {
- if (krb5_c_enctype_compare(context, request->ktype[i], etype_info[e]->etype, &similar) != 0)
- continue;
-
- if (similar)
- {
- e++;
- continue;
- }
- for ( j = e+1 ; etype_info[j] ; j++ )
- {
- if (krb5_c_enctype_compare(context, request->ktype[i], etype_info[j]->etype, &similar) != 0)
- continue;
-
- if (similar)
- break;
- }
- if (etype_info[j] == NULL)
- continue;
-
- tmp = etype_info[j];
- etype_info[j] = etype_info[e];
- etype_info[e] = tmp;
- e++;
- }
-}
-
-
krb5_error_code
krb5_do_preauth(krb5_context context,
krb5_kdc_req *request,
krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
- krb5_data *salt, krb5_enctype *etype,
+ krb5_data *salt, krb5_data *s2kparams,
+ krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter, void *prompter_data,
krb5_gic_get_as_key_fct gak_fct, void *gak_data)
{
int h, i, j, out_pa_list_size;
+ int seen_etype_info2 = 0;
krb5_pa_data *out_pa, **out_pa_list;
krb5_data scratch;
krb5_etype_info etype_info = NULL;
for (h=0; h<(sizeof(paorder)/sizeof(paorder[0])); h++) {
realdone = 0;
for (i=0; in_padata[i] && !realdone; i++) {
+ int k, l, etype_found, valid_etype_found;
/*
* This is really gross, but is necessary to prevent
* lossge when talking to a 1.0.x KDC, which returns an
*/
switch (in_padata[i]->pa_type) {
case KRB5_PADATA_ETYPE_INFO:
- if (etype_info)
- continue;
+ case KRB5_PADATA_ETYPE_INFO2:
+ {
+ krb5_preauthtype pa_type = in_padata[i]->pa_type;
+ if (etype_info) {
+ if (seen_etype_info2 || pa_type != KRB5_PADATA_ETYPE_INFO2)
+ continue;
+ if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
+ krb5_free_etype_info( context, etype_info);
+ etype_info = NULL;
+ }
+ }
+
+ if (pa_type == KRB5_PADATA_ETYPE_INFO2)
+ seen_etype_info2++;
scratch.length = in_padata[i]->length;
scratch.data = (char *) in_padata[i]->contents;
ret = decode_krb5_etype_info(&scratch, &etype_info);
etype_info = NULL;
break;
}
- sort_etype_info(context, request, etype_info);
- salt->data = (char *) etype_info[0]->salt;
- salt->length = etype_info[0]->length;
- *etype = etype_info[0]->etype;
+ /*
+ * Select first etype in our request which is also in
+ * etype-info (preferring client request ktype order).
+ */
+ for (etype_found = 0, valid_etype_found = 0, k = 0;
+ !etype_found && k < request->nktypes; k++) {
+ for (l = 0; etype_info[l]; l++) {
+ if (etype_info[l]->etype == request->ktype[k]) {
+ etype_found++;
+ break;
+ }
+ /* check if program has support for this etype for more
+ * precise error reporting.
+ */
+ if (valid_enctype(etype_info[l]->etype))
+ valid_etype_found++;
+ }
+ }
+ if (!etype_found) {
+ if (valid_etype_found)
+ /* supported enctype but not requested */
+ return KRB5_CONFIG_ETYPE_NOSUPP;
+ else
+ /* unsupported enctype */
+ return KRB5_PROG_ETYPE_NOSUPP;
+
+ }
+ salt->data = (char *) etype_info[l]->salt;
+ salt->length = etype_info[l]->length;
+ *etype = etype_info[l]->etype;
+ *s2kparams = etype_info[l]->s2kparams;
#ifdef DEBUG
for (j = 0; etype_info[j]; j++) {
krb5_etype_info_entry *e = etype_info[j];
}
#endif
break;
+ }
case KRB5_PADATA_PW_SALT:
case KRB5_PADATA_AFS3_SALT:
if (etype_info)
if ((ret = ((*pa_types[j].fct)(context, request,
in_padata[i], &out_pa,
- salt, etype, as_key,
+ salt, s2kparams, etype, as_key,
prompter, prompter_data,
gak_fct, gak_data)))) {
if (out_pa_list) {
krb5_c_random_make_octets
krb5_c_random_seed
krb5_c_string_to_key
+krb5_c_string_to_key_with_params
krb5_c_valid_cksumtype
krb5_c_valid_enctype
krb5_c_verify_checksum