1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 1995, 2003, 2008 by the Massachusetts Institute of Technology. All
6 * Export of this software from the United States of America may
7 * require a specific license from the United States Government.
8 * It is the responsibility of any person or organization contemplating
9 * export to obtain such a license before exporting.
11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12 * distribute this software and its documentation for any purpose and
13 * without fee is hereby granted, provided that the above copyright
14 * notice appear in all copies and that both that copyright notice and
15 * this permission notice appear in supporting documentation, and that
16 * the name of M.I.T. not be used in advertising or publicity pertaining
17 * to distribution of the software without specific, written prior
18 * permission. Furthermore if you modify this software you must label
19 * your software as modified software and not distribute it in such a
20 * fashion that it might be confused with the original M.I.T. software.
21 * M.I.T. makes no representations about the suitability of
22 * this software for any purpose. It is provided "as is" without express
23 * or implied warranty.
28 * This file contains routines for establishing, verifying, and any other
29 * necessary functions, for utilizing the pre-authentication field of the
30 * kerberos kdc request, with various hardware/software verification devices.
35 #include <krb5/preauth_plugin.h>
36 #include "int-proto.h"
43 /* This structure lets us keep track of all of the modules which are loaded,
44 * turning the list of modules and their lists of implemented preauth types
45 * into a single list which we can walk easily. */
46 struct krb5_preauth_context_st {
48 struct krb5_preauth_context_module_st {
49 /* Which of the possibly more than one preauth types which the
50 * module supports we're using at this point in the list. */
51 krb5_preauthtype pa_type;
52 /* Encryption types which the client claims to support -- we
53 * copy them directly into the krb5_kdc_req structure during
54 * krb5_preauth_prepare_request(). */
55 krb5_enctype *enctypes;
56 /* The plugin's module data and a function to clear it. */
57 krb5_clpreauth_moddata moddata;
58 krb5_clpreauth_fini_fn client_fini;
59 /* The module's table, and some of its members, copied here for
60 * convenience when we populated the list. */
63 krb5_clpreauth_process_fn client_process;
64 krb5_clpreauth_tryagain_fn client_tryagain;
65 krb5_clpreauth_supply_gic_opts_fn client_supply_gic_opts;
66 krb5_clpreauth_request_init_fn client_req_init;
67 krb5_clpreauth_request_fini_fn client_req_fini;
68 /* The per-request context which the client_req_init() function
69 * might allocate, which we'll need to clean up later by
70 * calling the client_req_fini() function. */
71 krb5_clpreauth_modreq modreq;
72 /* A pointer to the request_context pointer. All modules within
73 * a plugin will point at the request_context of the first
74 * module within the plugin. */
75 krb5_clpreauth_modreq *modreq_p;
79 typedef krb5_error_code (*pa_function)(krb5_context,
80 krb5_kdc_req *request,
81 krb5_pa_data *in_padata,
82 krb5_pa_data **out_padata,
83 krb5_data *salt, krb5_data *s2kparams,
85 krb5_keyblock *as_key,
86 krb5_prompter_fct prompter_fct,
88 krb5_gic_get_as_key_fct gak_fct,
91 typedef struct _pa_types_t {
92 krb5_preauthtype type;
97 /* Create the per-krb5_context context. This means loading the modules
98 * if we haven't done that yet (applications which never obtain initial
99 * credentials should never hit this routine), breaking up the module's
100 * list of support pa_types so that we can iterate over the modules more
101 * easily, and copying over the relevant parts of the module's table. */
103 krb5_init_preauth_context(krb5_context kcontext)
105 int n_tables, n_modules, i, count;
106 krb5_plugin_initvt_fn *plugins = NULL, *pl;
107 struct krb5_clpreauth_vtable_st *vtables = NULL, *vt;
108 struct krb5_preauth_context_module_st *mod;
109 krb5_preauth_context *context = NULL;
110 krb5_clpreauth_moddata moddata;
111 krb5_preauthtype pa_type, *pat;
113 krb5_clpreauth_modreq *rcpp;
115 /* Only do this once for each krb5_context */
116 if (kcontext->preauth_context != NULL)
119 /* Auto-register built-in modules. */
120 k5_plugin_register_dyn(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "pkinit",
122 k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH,
123 "encrypted_challenge",
124 clpreauth_encrypted_challenge_initvt);
125 k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH,
126 "encrypted_timestamp",
127 clpreauth_encrypted_timestamp_initvt);
128 k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "sam2",
129 clpreauth_sam2_initvt);
131 /* Get all available clpreauth vtables. */
132 if (k5_plugin_load_all(kcontext, PLUGIN_INTERFACE_CLPREAUTH, &plugins))
134 for (count = 0; plugins[count] != NULL; count++);
135 vtables = calloc(count, sizeof(*vtables));
138 for (pl = plugins, n_tables = 0; *pl != NULL; pl++) {
139 if ((*pl)(kcontext, 1, 1, (krb5_plugin_vtable)&vtables[n_tables]) == 0)
143 /* Count how many modules we ended up loading, and how many preauth
144 * types we may claim to support as a result. */
146 for (i = 0; i < n_tables; i++) {
147 for (count = 0; vtables[i].pa_type_list[count] > 0; count++);
151 /* Allocate the space we need. */
152 context = malloc(sizeof(*context));
155 context->modules = calloc(n_modules, sizeof(*context->modules));
156 if (context->modules == NULL)
159 /* fill in the structure */
161 for (i = 0; i < n_tables; i++) {
163 if ((vt->pa_type_list != NULL) && (vt->process != NULL)) {
165 if (vt->init != NULL && vt->init(kcontext, &moddata) != 0) {
167 fprintf(stderr, "init err, skipping module \"%s\"\n",
174 for (pat = vt->pa_type_list, first = TRUE; *pat > 0;
175 pat++, first = FALSE) {
177 mod = &context->modules[n_modules];
178 mod->pa_type = pa_type;
179 mod->enctypes = vt->enctype_list;
180 mod->moddata = moddata;
181 /* Only call client_fini once per plugin */
183 mod->client_fini = vt->fini;
185 mod->client_fini = NULL;
186 mod->name = vt->name;
187 mod->flags = (*vt->flags)(kcontext, pa_type);
189 mod->client_process = vt->process;
190 mod->client_tryagain = vt->tryagain;
191 mod->client_supply_gic_opts = first ? vt->gic_opts : NULL;
194 * Only call request_init and request_fini once per plugin.
195 * Only the first module within each plugin will ever
196 * have request_context filled in. Every module within
197 * the plugin will have its request_context_pp pointing
198 * to that entry's request_context. That way all the
199 * modules within the plugin share the same request_context
202 mod->client_req_init = vt->request_init;
203 mod->client_req_fini = vt->request_fini;
206 mod->client_req_init = NULL;
207 mod->client_req_fini = NULL;
209 mod->modreq_p = rcpp;
211 fprintf(stderr, "init module \"%s\", pa_type %d, flag %d\n",
212 mod->name, mod->pa_type, mod->flags);
218 context->n_modules = n_modules;
220 /* Place the constructed preauth context into the krb5 context. */
221 kcontext->preauth_context = context;
226 free(context->modules);
228 k5_plugin_free_modules(kcontext, plugins);
232 /* Zero the use counts for the modules herein. Usually used before we
233 * start processing any data from the server, at which point every module
234 * will again be able to take a crack at whatever the server sent. */
236 krb5_clear_preauth_context_use_counts(krb5_context context)
239 if (context->preauth_context != NULL) {
240 for (i = 0; i < context->preauth_context->n_modules; i++) {
241 context->preauth_context->modules[i].use_count = 0;
247 /* Free the per-krb5_context preauth_context. This means clearing any
248 * plugin-specific context which may have been created, and then
249 * freeing the context itself. */
251 krb5_free_preauth_context(krb5_context context)
254 struct krb5_preauth_context_module_st *mod;
256 if (context == NULL || context->preauth_context == NULL)
258 for (i = 0; i < context->preauth_context->n_modules; i++) {
259 mod = &context->preauth_context->modules[i];
260 if (mod->client_fini != NULL)
261 mod->client_fini(context, mod->moddata);
262 zap(mod, sizeof(*mod));
264 free(context->preauth_context->modules);
265 free(context->preauth_context);
266 context->preauth_context = NULL;
269 /* Initialize the per-AS-REQ context. This means calling the client_req_init
270 * function to give the plugin a chance to allocate a per-request context. */
272 krb5_preauth_request_context_init(krb5_context context)
275 struct krb5_preauth_context_module_st *mod;
277 if (context->preauth_context == NULL)
278 krb5_init_preauth_context(context);
279 if (context->preauth_context == NULL)
281 for (i = 0; i < context->preauth_context->n_modules; i++) {
282 context->preauth_context->modules[i].use_count = 0;
283 mod = &context->preauth_context->modules[i];
284 if (mod->client_req_init != NULL)
285 mod->client_req_init(context, mod->moddata, mod->modreq_p);
289 /* Free the per-AS-REQ context. This means clearing any request-specific
290 * context which the plugin may have created. */
292 krb5_preauth_request_context_fini(krb5_context context)
295 struct krb5_preauth_context_module_st *mod;
297 if (context->preauth_context == NULL)
299 for (i = 0; i < context->preauth_context->n_modules; i++) {
300 mod = &context->preauth_context->modules[i];
301 if (mod->modreq != NULL) {
302 if (mod->client_req_fini != NULL)
303 mod->client_req_fini(context, mod->moddata, mod->modreq);
309 /* Add the named encryption type to the existing list of ktypes. */
311 grow_ktypes(krb5_enctype **out_ktypes, int *out_nktypes, krb5_enctype ktype)
314 krb5_enctype *ktypes;
315 for (i = 0; i < *out_nktypes; i++) {
316 if ((*out_ktypes)[i] == ktype)
319 ktypes = malloc((*out_nktypes + 2) * sizeof(ktype));
321 for (i = 0; i < *out_nktypes; i++)
322 ktypes[i] = (*out_ktypes)[i];
326 *out_ktypes = ktypes;
332 * Add the given list of pa_data items to the existing list of items.
333 * Factored out here to make reading the do_preauth logic easier to read.
336 grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size,
337 krb5_pa_data **addition, int num_addition)
339 krb5_pa_data **pa_list;
342 if (out_pa_list == NULL || addition == NULL) {
346 if (*out_pa_list == NULL) {
347 /* Allocate room for the new additions and a NULL terminator. */
348 pa_list = malloc((num_addition + 1) * sizeof(krb5_pa_data *));
351 for (i = 0; i < num_addition; i++)
352 pa_list[i] = addition[i];
354 *out_pa_list = pa_list;
355 *out_pa_list_size = num_addition;
358 * Allocate room for the existing entries plus
359 * the new additions and a NULL terminator.
361 pa_list = malloc((*out_pa_list_size + num_addition + 1)
362 * sizeof(krb5_pa_data *));
365 for (i = 0; i < *out_pa_list_size; i++)
366 pa_list[i] = (*out_pa_list)[i];
367 for (j = 0; j < num_addition;)
368 pa_list[i++] = addition[j++];
371 *out_pa_list = pa_list;
372 *out_pa_list_size = i;
378 get_etype(krb5_context context, krb5_clpreauth_rock rock)
383 static krb5_keyblock *
384 fast_armor(krb5_context context, krb5_clpreauth_rock rock)
386 return rock->fast_state->armor_key;
389 static krb5_error_code
390 get_as_key(krb5_context context, krb5_clpreauth_rock rock,
391 krb5_keyblock **keyblock)
395 if (rock->as_key->length == 0) {
396 ret = (*rock->gak_fct)(context, rock->client, *rock->etype,
397 rock->prompter, rock->prompter_data, rock->salt,
398 rock->s2kparams, rock->as_key, *rock->gak_data);
402 *keyblock = rock->as_key;
406 static krb5_error_code
407 set_as_key(krb5_context context, krb5_clpreauth_rock rock,
408 const krb5_keyblock *keyblock)
410 krb5_free_keyblock_contents(context, rock->as_key);
411 return krb5_copy_keyblock_contents(context, keyblock, rock->as_key);
414 static krb5_error_code
415 get_preauth_time(krb5_context context, krb5_clpreauth_rock rock,
416 krb5_boolean allow_unauth_time, krb5_timestamp *time_out,
417 krb5_int32 *usec_out)
419 if (rock->pa_offset_state != NO_OFFSET &&
420 (allow_unauth_time || rock->pa_offset_state == AUTH_OFFSET) &&
421 (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME)) {
422 /* Use the offset we got from the preauth-required error. */
423 return k5_time_with_offset(rock->pa_offset, rock->pa_offset_usec,
427 /* Use the time offset from the context, or no offset. */
428 return krb5_us_timeofday(context, time_out, usec_out);
432 static struct krb5_clpreauth_callbacks_st callbacks = {
441 /* Tweak the request body, for now adding any enctypes which the module claims
442 * to add support for to the list, but in the future perhaps doing more
443 * involved things. */
445 krb5_preauth_prepare_request(krb5_context kcontext,
446 krb5_gic_opt_ext *opte,
447 krb5_kdc_req *request)
451 if (kcontext->preauth_context == NULL) {
454 /* Add the module-specific enctype list to the request, but only if
455 * it's something we can safely modify. */
456 if (!(opte && (opte->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))) {
457 for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
458 if (kcontext->preauth_context->modules[i].enctypes == NULL)
460 for (j = 0; kcontext->preauth_context->modules[i].enctypes[j] != 0; j++) {
461 grow_ktypes(&request->ktype, &request->nktypes,
462 kcontext->preauth_context->modules[i].enctypes[j]);
468 /* Find the first module which provides for the named preauth type which also
469 * hasn't had a chance to run yet (INFO modules don't count, because as a rule
470 * they don't generate preauth data), and run it. */
471 static krb5_error_code
472 run_preauth_plugins(krb5_context kcontext,
473 int module_required_flags,
474 krb5_kdc_req *request,
475 krb5_data *encoded_request_body,
476 krb5_data *encoded_previous_request,
477 krb5_pa_data *in_padata,
478 krb5_prompter_fct prompter,
480 krb5_clpreauth_rock preauth_rock,
481 krb5_pa_data ***out_pa_list,
482 int *out_pa_list_size,
485 krb5_gic_opt_ext *opte)
488 krb5_pa_data **out_pa_data;
490 struct krb5_preauth_context_module_st *module;
492 if (kcontext->preauth_context == NULL) {
495 /* iterate over all loaded modules */
496 for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
497 module = &kcontext->preauth_context->modules[i];
498 /* skip over those which don't match the preauth type */
499 if (module->pa_type != in_padata->pa_type)
501 /* skip over those which don't match the flags (INFO vs REAL, mainly) */
502 if ((module->flags & module_required_flags) == 0)
504 /* if it's a REAL module, try to call it only once per library call */
505 if (module_required_flags & PA_REAL) {
506 if (module->use_count > 0) {
507 TRACE_PREAUTH_SKIP(kcontext, module->name, module->pa_type);
512 /* run the module's callback function */
515 fprintf(stderr, "using module \"%s\" (%d), flags = %d\n",
516 module->name, module->pa_type, module->flags);
518 ret = module->client_process(kcontext, module->moddata,
520 (krb5_get_init_creds_opt *)opte,
521 &callbacks, preauth_rock,
522 request, encoded_request_body,
523 encoded_previous_request, in_padata,
524 prompter, prompter_data, &out_pa_data);
525 TRACE_PREAUTH_PROCESS(kcontext, module->name, module->pa_type,
527 /* Make note of the module's flags and status. */
528 *module_flags = module->flags;
530 /* Save the new preauth data item. */
531 if (out_pa_data != NULL) {
533 for (j = 0; out_pa_data[j] != NULL; j++);
534 ret = grow_pa_list(out_pa_list, out_pa_list_size, out_pa_data, j);
541 if (i >= kcontext->preauth_context->n_modules) {
547 static inline krb5_data
548 padata2data(krb5_pa_data p)
553 d.data = (char *) p.contents;
557 static krb5_error_code
558 pa_salt(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata,
559 krb5_pa_data **out_padata, krb5_data *salt, krb5_data *s2kparams,
560 krb5_enctype *etype, krb5_keyblock *as_key, krb5_prompter_fct prompter,
561 void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data)
564 krb5_error_code retval;
566 tmp = padata2data(*in_padata);
567 krb5_free_data_contents(context, salt);
568 retval = krb5int_copy_data_contents_add0(context, &tmp, salt);
572 TRACE_PREAUTH_SALT(context, salt, in_padata->pa_type);
573 if (in_padata->pa_type == KRB5_PADATA_AFS3_SALT)
574 salt->length = SALT_TYPE_AFS_LENGTH;
579 static krb5_error_code
580 pa_fx_cookie(krb5_context context, krb5_kdc_req *request,
581 krb5_pa_data *in_padata, krb5_pa_data **out_padata,
582 krb5_data *salt, krb5_data *s2kparams, krb5_enctype *etype,
583 krb5_keyblock *as_key, krb5_prompter_fct prompter,
584 void *prompter_data, krb5_gic_get_as_key_fct gak_fct,
587 krb5_pa_data *pa = calloc(1, sizeof(krb5_pa_data));
588 krb5_octet *contents;
590 TRACE_PREAUTH_COOKIE(context, in_padata->length, in_padata->contents);
593 contents = malloc(in_padata->length);
594 if (contents == NULL) {
599 pa->contents = contents;
600 memcpy(contents, in_padata->contents, pa->length);
605 static krb5_error_code
606 pa_s4u_x509_user(krb5_context context, krb5_kdc_req *request,
607 krb5_pa_data *in_padata, krb5_pa_data **out_padata,
608 krb5_data *salt, krb5_data *s2kparams, krb5_enctype *etype,
609 krb5_keyblock *as_key, krb5_prompter_fct prompter,
610 void *prompter_data, krb5_gic_get_as_key_fct gak_fct,
613 krb5_s4u_userid *userid = (krb5_s4u_userid *)gak_data; /* XXX private contract */
614 krb5_pa_data *s4u_padata;
615 krb5_error_code code;
616 krb5_principal client;
623 code = krb5_copy_principal(context, request->client, &client);
627 if (userid->user != NULL)
628 krb5_free_principal(context, userid->user);
629 userid->user = client;
631 if (userid->subject_cert.length != 0) {
632 s4u_padata = malloc(sizeof(*s4u_padata));
633 if (s4u_padata == NULL)
636 s4u_padata->magic = KV5M_PA_DATA;
637 s4u_padata->pa_type = KRB5_PADATA_S4U_X509_USER;
638 s4u_padata->contents = malloc(userid->subject_cert.length);
639 if (s4u_padata->contents == NULL) {
643 memcpy(s4u_padata->contents, userid->subject_cert.data, userid->subject_cert.length);
644 s4u_padata->length = userid->subject_cert.length;
646 *out_padata = s4u_padata;
652 /* FIXME - order significant? */
653 static const pa_types_t pa_types[] = {
660 KRB5_PADATA_AFS3_SALT,
665 KRB5_PADATA_FX_COOKIE,
670 KRB5_PADATA_S4U_X509_USER,
682 * If one of the modules can adjust its AS_REQ data using the contents of the
683 * err_reply, return 0. If it's the sort of correction which requires that we
684 * ask the user another question, we let the calling application deal with it.
686 krb5_error_code KRB5_CALLCONV
687 krb5_do_preauth_tryagain(krb5_context kcontext,
688 krb5_kdc_req *request,
689 krb5_data *encoded_request_body,
690 krb5_data *encoded_previous_request,
691 krb5_pa_data **padata,
692 krb5_pa_data ***return_padata,
693 krb5_error *err_reply,
694 krb5_pa_data **err_padata,
695 krb5_prompter_fct prompter, void *prompter_data,
696 krb5_clpreauth_rock preauth_rock,
697 krb5_gic_opt_ext *opte)
700 krb5_pa_data **out_padata;
701 krb5_preauth_context *context;
702 struct krb5_preauth_context_module_st *module;
704 int out_pa_list_size = 0;
706 ret = KRB5KRB_ERR_GENERIC;
707 if (kcontext->preauth_context == NULL) {
708 return KRB5KRB_ERR_GENERIC;
710 context = kcontext->preauth_context;
711 if (context == NULL) {
712 return KRB5KRB_ERR_GENERIC;
715 TRACE_PREAUTH_TRYAGAIN_INPUT(kcontext, padata);
717 for (i = 0; padata[i] != NULL && padata[i]->pa_type != 0; i++) {
719 for (j = 0; j < context->n_modules; j++) {
720 module = &context->modules[j];
721 if (module->pa_type != padata[i]->pa_type) {
724 if (module->client_tryagain == NULL) {
727 if ((*module->client_tryagain)(kcontext, module->moddata,
729 (krb5_get_init_creds_opt *)opte,
730 &callbacks, preauth_rock,
732 encoded_request_body,
733 encoded_previous_request,
735 err_reply, err_padata,
736 prompter, prompter_data,
738 if (out_padata != NULL) {
740 for (k = 0; out_padata[k] != NULL; k++);
741 grow_pa_list(return_padata, &out_pa_list_size,
744 TRACE_PREAUTH_TRYAGAIN_OUTPUT(kcontext, *return_padata);
753 krb5_error_code KRB5_CALLCONV
754 krb5_do_preauth(krb5_context context, krb5_kdc_req *request,
755 krb5_data *encoded_request_body,
756 krb5_data *encoded_previous_request,
757 krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
758 krb5_prompter_fct prompter, void *prompter_data,
759 krb5_clpreauth_rock rock, krb5_gic_opt_ext *opte,
760 krb5_boolean *got_real_out)
763 int i, j, out_pa_list_size;
764 int seen_etype_info2 = 0;
765 krb5_pa_data *out_pa = NULL, **out_pa_list = NULL;
767 krb5_etype_info etype_info = NULL;
769 static const int paorder[] = { PA_INFO, PA_REAL };
772 *got_real_out = FALSE;
774 if (in_padata == NULL) {
779 TRACE_PREAUTH_INPUT(context, in_padata);
782 out_pa_list_size = 0;
784 /* first do all the informational preauths, then the first real one */
786 for (h=0; h<(sizeof(paorder)/sizeof(paorder[0])); h++) {
788 for (i=0; in_padata[i] && !realdone; i++) {
789 int k, l, etype_found, valid_etype_found;
791 * This is really gross, but is necessary to prevent
792 * lossage when talking to a 1.0.x KDC, which returns an
793 * erroneous PA-PW-SALT when it returns a KRB-ERROR
794 * requiring additional preauth.
796 switch (in_padata[i]->pa_type) {
797 case KRB5_PADATA_ETYPE_INFO:
798 case KRB5_PADATA_ETYPE_INFO2:
800 krb5_preauthtype pa_type = in_padata[i]->pa_type;
802 if (seen_etype_info2 || pa_type != KRB5_PADATA_ETYPE_INFO2)
804 if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
805 krb5_free_etype_info( context, etype_info);
810 scratch.length = in_padata[i]->length;
811 scratch.data = (char *) in_padata[i]->contents;
812 if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
814 ret = decode_krb5_etype_info2(&scratch, &etype_info);
816 else ret = decode_krb5_etype_info(&scratch, &etype_info);
818 ret = 0; /*Ignore error and etype_info element*/
820 krb5_free_etype_info( context, etype_info);
824 if (etype_info[0] == NULL) {
825 krb5_free_etype_info(context, etype_info);
830 * Select first etype in our request which is also in
831 * etype-info (preferring client request ktype order).
833 for (etype_found = 0, valid_etype_found = 0, k = 0;
834 !etype_found && k < request->nktypes; k++) {
835 for (l = 0; etype_info[l]; l++) {
836 if (etype_info[l]->etype == request->ktype[k]) {
840 /* check if program has support for this etype for more
841 * precise error reporting.
843 if (krb5_c_valid_enctype(etype_info[l]->etype))
848 if (valid_etype_found) {
849 /* supported enctype but not requested */
850 ret = KRB5_CONFIG_ETYPE_NOSUPP;
854 /* unsupported enctype */
855 ret = KRB5_PROG_ETYPE_NOSUPP;
860 scratch.data = (char *) etype_info[l]->salt;
861 scratch.length = etype_info[l]->length;
862 krb5_free_data_contents(context, rock->salt);
863 if (scratch.length == KRB5_ETYPE_NO_SALT)
864 rock->salt->data = NULL;
866 ret = krb5int_copy_data_contents(context, &scratch,
871 *rock->etype = etype_info[l]->etype;
872 krb5_free_data_contents(context, rock->s2kparams);
873 ret = krb5int_copy_data_contents(context,
874 &etype_info[l]->s2kparams,
878 TRACE_PREAUTH_ETYPE_INFO(context, *rock->etype, rock->salt,
882 case KRB5_PADATA_PW_SALT:
883 case KRB5_PADATA_AFS3_SALT:
890 /* Try the internally-provided preauth type list. */
891 if (!realdone) for (j=0; pa_types[j].type >= 0; j++) {
892 if ((in_padata[i]->pa_type == pa_types[j].type) &&
893 (pa_types[j].flags & paorder[h])) {
895 fprintf (stderr, "calling internal function for pa_type "
896 "%d, flag %d\n", pa_types[j].type, paorder[h]);
900 ret = pa_types[j].fct(context, request, in_padata[i],
902 rock->s2kparams, rock->etype,
903 rock->as_key, prompter,
904 prompter_data, *rock->gak_fct,
907 if (paorder[h] == PA_INFO) {
908 TRACE_PREAUTH_INFO_FAIL(context,
909 in_padata[i]->pa_type,
912 continue; /* PA_INFO type failed, ignore */
918 ret = grow_pa_list(&out_pa_list, &out_pa_list_size,
923 if (paorder[h] == PA_REAL)
928 /* Try to use plugins now. */
930 krb5_init_preauth_context(context);
931 if (context->preauth_context != NULL) {
932 int module_ret = 0, module_flags;
934 fprintf (stderr, "trying modules for pa_type %d, flag %d\n",
935 in_padata[i]->pa_type, paorder[h]);
937 ret = run_preauth_plugins(context,
940 encoded_request_body,
941 encoded_previous_request,
952 if (module_ret == 0) {
953 if (paorder[h] == PA_REAL) {
963 TRACE_PREAUTH_OUTPUT(context, out_pa_list);
964 *out_padata = out_pa_list;
966 krb5_free_etype_info(context, etype_info);
968 *got_real_out = realdone;
972 out_pa_list[out_pa_list_size++] = NULL;
973 krb5_free_pa_data(context, out_pa_list);
976 krb5_free_etype_info(context, etype_info);
981 * Give all the preauth plugins a look at the preauth option which
985 krb5_preauth_supply_preauth_data(krb5_context context, krb5_gic_opt_ext *opte,
986 const char *attr, const char *value)
988 krb5_error_code retval = 0;
990 struct krb5_preauth_context_module_st *mod;
991 const char *emsg = NULL;
993 if (context->preauth_context == NULL)
994 krb5_init_preauth_context(context);
995 if (context->preauth_context == NULL) {
997 krb5_set_error_message(context, retval,
998 _("Unable to initialize preauth context"));
1003 * Go down the list of preauth modules, and supply them with the
1004 * attribute/value pair.
1006 for (i = 0; i < context->preauth_context->n_modules; i++) {
1007 mod = &context->preauth_context->modules[i];
1008 if (mod->client_supply_gic_opts == NULL)
1010 retval = mod->client_supply_gic_opts(context, mod->moddata,
1011 (krb5_get_init_creds_opt *)opte,
1014 emsg = krb5_get_error_message(context, retval);
1015 krb5_set_error_message(context, retval, _("Preauth plugin %s: %s"),
1017 krb5_free_error_message(context, emsg);