diff --git a/krb5-1.6-post.dif b/krb5-1.6-post.dif index 75acc7c..ec4e366 100644 --- a/krb5-1.6-post.dif +++ b/krb5-1.6-post.dif @@ -1,7 +1,753 @@ +Index: src/plugins/preauth/cksum_body/cksum_body_main.c +=================================================================== +--- src/plugins/preauth/cksum_body/cksum_body_main.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/plugins/preauth/cksum_body/cksum_body_main.c (.../branches/krb5-1-6) (Revision 19151) +@@ -78,6 +78,7 @@ + client_process(krb5_context kcontext, + void *client_plugin_context, + void *client_request_context, ++ krb5_get_init_creds_opt *opt, + preauth_get_client_data_proc client_get_data_proc, + struct _krb5_preauth_client_rock *rock, + krb5_kdc_req *request, +@@ -99,7 +100,28 @@ + krb5_error_code status = 0; + krb5_int32 cksumtype, *enctypes; + unsigned int i, n_enctypes, cksumtype_count; ++ int num_gic_info = 0; ++ krb5_gic_opt_pa_data *gic_info; + ++ status = krb5_get_init_creds_opt_get_pa(kcontext, opt, ++ &num_gic_info, &gic_info); ++ if (status && status != ENOENT) { ++#ifdef DEBUG ++ fprintf(stderr, "Error from krb5_get_init_creds_opt_get_pa: %s\n", ++ error_message(status)); ++#endif ++ return status; ++ } ++#ifdef DEBUG ++ fprintf(stderr, "(cksum_body) Got the following gic options:\n"); ++#endif ++ for (i = 0; i < num_gic_info; i++) { ++#ifdef DEBUG ++ fprintf(stderr, " '%s' = '%s'\n", gic_info[i].attr, gic_info[i].value); ++#endif ++ } ++ krb5_get_init_creds_opt_free_pa(kcontext, num_gic_info, gic_info); ++ + memset(&checksum, 0, sizeof(checksum)); + + /* Get the user's long-term key if we haven't asked for it yet. Try +@@ -193,6 +215,20 @@ + return 0; + } + ++static krb5_error_code ++client_gic_opt(krb5_context kcontext, ++ void *plugin_context, ++ krb5_get_init_creds_opt *opt, ++ const char *attr, ++ const char *value) ++{ ++#ifdef DEBUG ++ fprintf(stderr, "(cksum_body) client_gic_opt: received '%s' = '%s'\n", ++ attr, value); ++#endif ++ return 0; ++} ++ + /* Initialize and tear down the server-side module, and do stat tracking. */ + static krb5_error_code + server_init(krb5_context kcontext, void **module_context) +@@ -200,7 +236,7 @@ + struct server_stats *stats; + stats = malloc(sizeof(struct server_stats)); + if (stats == NULL) +- return ENOMEM; ++ return ENOMEM; + stats->successes = 0; + stats->failures = 0; + *module_context = stats; +@@ -506,6 +542,7 @@ + NULL, /* request fini function */ + client_process, /* process function */ + NULL, /* try_again function */ ++ client_gic_opt /* get init creds opt function */ + }; + + struct krb5plugin_preauth_server_ftable_v0 preauthentication_server_0 = { +Index: src/plugins/preauth/wpse/wpse_main.c +=================================================================== +--- src/plugins/preauth/wpse/wpse_main.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/plugins/preauth/wpse/wpse_main.c (.../branches/krb5-1-6) (Revision 19151) +@@ -90,6 +90,7 @@ + client_process(krb5_context kcontext, + void *plugin_context, + void *request_context, ++ krb5_get_init_creds_opt *opt, + preauth_get_client_data_proc client_get_data_proc, + struct _krb5_preauth_client_rock *rock, + krb5_kdc_req *request, +@@ -208,6 +209,21 @@ + return; + } + ++static krb5_error_code ++client_gic_opt(krb5_context kcontext, ++ void *plugin_context, ++ krb5_get_init_creds_opt *opt, ++ const char *attr, ++ const char *value) ++{ ++#ifdef DEBUG ++ fprintf(stderr, "(wpse) client_gic_opt: received '%s' = '%s'\n", ++ attr, value); ++#endif ++ return 0; ++} ++ ++ + /* Free state. */ + static krb5_error_code + server_free_pa_request_context(krb5_context kcontext, void *plugin_context, +@@ -378,6 +394,7 @@ + client_req_cleanup, /* request fini function */ + client_process, /* process function */ + NULL, /* try_again function */ ++ client_gic_opt /* get init creds opts function */ + }; + + struct krb5plugin_preauth_server_ftable_v0 preauthentication_server_0 = { +Index: src/include/Makefile.in +=================================================================== +--- src/include/Makefile.in (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/include/Makefile.in (.../branches/krb5-1-6) (Revision 19151) +@@ -85,9 +85,14 @@ + asn1_err.h >> krb5/krb5.h + echo "#endif /* KRB5_KRB5_H_INCLUDED */" >> krb5/krb5.h + +-verify-calling-conventions-krb5: krb5/krb5.h +- $(PERL) -w $(SRCTOP)/util/def-check.pl krb5/krb5.h $(SRCTOP)/lib/krb5_32.def ++verify-calling-conventions-krb5: private-and-public-decls ++ $(PERL) -w $(SRCTOP)/util/def-check.pl private-and-public-decls $(SRCTOP)/lib/krb5_32.def + ++HEADERS_TO_CHECK = krb5/krb5.h $(srcdir)/k5-int.h $(srcdir)/krb5/preauth_plugin.h ++ ++private-and-public-decls: $(HEADERS_TO_CHECK) ++ cat $(HEADERS_TO_CHECK) > $@ ++ + # + # Build the error table include files: + # asn1_err.h kdb5_err.h krb5_err.h kv5m_err.h krb524_err.h +Index: src/include/k5-int.h +=================================================================== +--- src/include/k5-int.h (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/include/k5-int.h (.../branches/krb5-1-6) (Revision 19151) +@@ -876,6 +876,7 @@ + krb5_error_code (*client_process)(krb5_context context, + void *plugin_context, + void *request_context, ++ krb5_get_init_creds_opt *opt, + preauth_get_client_data_proc get_data_proc, + krb5_preauth_client_rock *rock, + krb5_kdc_req *request, +@@ -893,6 +894,7 @@ + krb5_error_code (*client_tryagain)(krb5_context context, + void *plugin_context, + void *request_context, ++ krb5_get_init_creds_opt *opt, + preauth_get_client_data_proc get_data_proc, + krb5_preauth_client_rock *rock, + krb5_kdc_req *request, +@@ -908,6 +910,7 @@ + krb5_data *s2kparams, + krb5_keyblock *as_key, + krb5_pa_data **new_pa_data); ++ supply_gic_opts_proc client_supply_gic_opts; + void (*client_req_init)(krb5_context context, void *plugin_context, + void **request_context); + void (*client_req_fini)(krb5_context context, void *plugin_context, +@@ -1014,7 +1017,75 @@ + /* + * End "preauth.h" + */ ++ ++/* ++ * Extending the krb5_get_init_creds_opt structure. The original ++ * krb5_get_init_creds_opt structure is defined publicly. The ++ * new extended version is private. The original interface ++ * assumed a pre-allocated structure which was passed to ++ * krb5_get_init_creds_init(). The new interface assumes that ++ * the caller will call krb5_get_init_creds_alloc() and ++ * krb5_get_init_creds_free(). ++ * ++ * Callers MUST NOT call krb5_get_init_creds_init() after allocating an ++ * opts structure using krb5_get_init_creds_alloc(). To do so will ++ * introduce memory leaks. Unfortunately, there is no way to enforce ++ * this behavior. ++ * ++ * Two private flags are added for backward compatibility. ++ * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated ++ * with the new krb5_get_init_creds_opt_alloc() function. ++ * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended ++ * structure is a shadow copy of an original krb5_get_init_creds_opt ++ * structure. ++ * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to ++ * krb5int_gic_opt_to_opte(), the resulting extended structure should be ++ * freed (using krb5_get_init_creds_free). Otherwise, the original ++ * structure was already extended and there is no need to free it. ++ */ ++ ++#define KRB5_GET_INIT_CREDS_OPT_EXTENDED 0x80000000 ++#define KRB5_GET_INIT_CREDS_OPT_SHADOWED 0x40000000 ++ ++#define krb5_gic_opt_is_extended(s) \ ++ (((s)->flags & KRB5_GET_INIT_CREDS_OPT_EXTENDED) ? 1 : 0) ++#define krb5_gic_opt_is_shadowed(s) \ ++ (((s)->flags & KRB5_GET_INIT_CREDS_OPT_SHADOWED) ? 1 : 0) ++ ++ ++typedef struct _krb5_gic_opt_private { ++ int num_preauth_data; ++ krb5_gic_opt_pa_data *preauth_data; ++} krb5_gic_opt_private; ++ ++typedef struct _krb5_gic_opt_ext { ++ krb5_flags flags; ++ krb5_deltat tkt_life; ++ krb5_deltat renew_life; ++ int forwardable; ++ int proxiable; ++ krb5_enctype *etype_list; ++ int etype_list_length; ++ krb5_address **address_list; ++ krb5_preauthtype *preauth_list; ++ int preauth_list_length; ++ krb5_data *salt; ++ /* ++ * Do not change anything above this point in this structure. ++ * It is identical to the public krb5_get_init_creds_opt structure. ++ * New members must be added below. ++ */ ++ krb5_gic_opt_private *opt_private; ++} krb5_gic_opt_ext; ++ + krb5_error_code ++krb5int_gic_opt_to_opte(krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ krb5_gic_opt_ext **opte, ++ unsigned int force, ++ const char *where); ++ ++krb5_error_code + krb5int_copy_data_contents (krb5_context, const krb5_data *, krb5_data *); + + typedef krb5_error_code (*krb5_gic_get_as_key_fct) +@@ -1037,14 +1108,14 @@ + void *prompter_data, + krb5_deltat start_time, + char *in_tkt_service, +- krb5_get_init_creds_opt *gic_options, ++ krb5_gic_opt_ext *gic_options, + krb5_gic_get_as_key_fct gak, + void *gak_data, + int *master, + krb5_kdc_rep **as_reply); + +-void krb5int_populate_gic_opt ( +- krb5_context, krb5_get_init_creds_opt *, ++krb5_error_code krb5int_populate_gic_opt ( ++ krb5_context, krb5_gic_opt_ext **, + krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, krb5_creds *creds); + +@@ -1059,7 +1130,8 @@ + 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, +- krb5_preauth_client_rock *get_data_rock); ++ krb5_preauth_client_rock *get_data_rock, ++ krb5_gic_opt_ext *opte); + krb5_error_code KRB5_CALLCONV krb5_do_preauth_tryagain + (krb5_context context, + krb5_kdc_req *request, +@@ -1071,7 +1143,8 @@ + 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, +- krb5_preauth_client_rock *get_data_rock); ++ krb5_preauth_client_rock *get_data_rock, ++ krb5_gic_opt_ext *opte); + void KRB5_CALLCONV krb5_init_preauth_context + (krb5_context); + void KRB5_CALLCONV krb5_free_preauth_context +@@ -1079,7 +1152,7 @@ + void KRB5_CALLCONV krb5_clear_preauth_context_use_counts + (krb5_context); + void KRB5_CALLCONV krb5_preauth_prepare_request +- (krb5_context, krb5_get_init_creds_opt *, krb5_kdc_req *); ++ (krb5_context, krb5_gic_opt_ext *, krb5_kdc_req *); + void KRB5_CALLCONV krb5_preauth_request_context_init + (krb5_context); + void KRB5_CALLCONV krb5_preauth_request_context_fini +Index: src/include/krb5/krb5.hin +=================================================================== +--- src/include/krb5/krb5.hin (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/include/krb5/krb5.hin (.../branches/krb5-1-6) (Revision 19151) +@@ -2431,7 +2431,17 @@ + #define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 + #define KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT 0x0100 + ++krb5_error_code KRB5_CALLCONV ++krb5_get_init_creds_opt_alloc ++(krb5_context context, ++ krb5_get_init_creds_opt **opt); ++ + void KRB5_CALLCONV ++krb5_get_init_creds_opt_free ++(krb5_context context, ++ krb5_get_init_creds_opt *opt); ++ ++void KRB5_CALLCONV + krb5_get_init_creds_opt_init + (krb5_get_init_creds_opt *opt); + +@@ -2482,7 +2492,28 @@ + (krb5_get_init_creds_opt *opt, + int prompt); + ++/* Generic preauth option attribute/value pairs */ ++typedef struct _krb5_gic_opt_pa_data { ++ char *attr; ++ char *value; ++} krb5_gic_opt_pa_data; ++ ++/* ++ * This function allows the caller to supply options to preauth ++ * plugins. Preauth plugin modules are given a chance to look ++ * at each option at the time this function is called in ordre ++ * to check the validity of the option. ++ * The 'opt' pointer supplied to this function must have been ++ * obtained using krb5_get_init_creds_opt_alloc() ++ */ + krb5_error_code KRB5_CALLCONV ++krb5_get_init_creds_opt_set_pa ++ (krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ const char *attr, ++ const char *value); ++ ++krb5_error_code KRB5_CALLCONV + krb5_get_init_creds_password + (krb5_context context, + krb5_creds *creds, +Index: src/include/krb5/preauth_plugin.h +=================================================================== +--- src/include/krb5/preauth_plugin.h (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/include/krb5/preauth_plugin.h (.../branches/krb5-1-6) (Revision 19151) +@@ -158,6 +158,17 @@ + void *gak_data); + + /* ++ * Client function which receives krb5_get_init_creds_opt information. ++ * The attr and value information supplied should be copied locally by ++ * the module if it wishes to reference it after returning from this call. ++ */ ++typedef krb5_error_code ++(*supply_gic_opts_proc)(krb5_context context, ++ void *plugin_context, ++ krb5_get_init_creds_opt *opt, ++ const char *attr, ++ const char *value); ++/* + * The function table / structure which a preauth client module must export as + * "preauthentication_client_0". If the interfaces work correctly, future + * versions of the table will add either more callbacks or more arguments to +@@ -207,6 +218,7 @@ + krb5_error_code (*process)(krb5_context context, + void *plugin_context, + void *request_context, ++ krb5_get_init_creds_opt *opt, + preauth_get_client_data_proc get_data_proc, + struct _krb5_preauth_client_rock *rock, + krb5_kdc_req *request, +@@ -227,8 +239,9 @@ + krb5_error_code (*tryagain)(krb5_context context, + void *plugin_context, + void *request_context, ++ krb5_get_init_creds_opt *opt, + preauth_get_client_data_proc get_data_proc, +- struct _krb5_preauth_client_rock *rock, ++ struct _krb5_preauth_client_rock *rock, + krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, +@@ -241,6 +254,12 @@ + krb5_data *salt, krb5_data *s2kparams, + krb5_keyblock *as_key, + krb5_pa_data **out_pa_data); ++ /* ++ * Client function which receives krb5_get_init_creds_opt information. ++ * The attr and value information supplied should be copied locally by ++ * the module if it wishes to reference it after returning from this call. ++ */ ++ supply_gic_opts_proc gic_opts; + } krb5plugin_preauth_client_ftable_v0; + + /* +@@ -323,4 +342,31 @@ + void *pa_module_context, + void **request_pa_context); + } krb5plugin_preauth_server_ftable_v0; ++ ++ ++/* ++ * This function allows a preauth plugin to obtain preauth ++ * options. The preauth_data returned from this function ++ * should be freed by calling krb5_get_init_creds_opt_free_pa(). ++ * ++ * The 'opt' pointer supplied to this function must have been ++ * obtained using krb5_get_init_creds_opt_alloc() ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_get_init_creds_opt_get_pa ++ (krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ int *num_preauth_data, ++ krb5_gic_opt_pa_data **preauth_data); ++ ++/* ++ * This function frees the preauth_data that was returned by ++ * krb5_get_init_creds_opt_get_pa(). ++ */ ++void KRB5_CALLCONV ++krb5_get_init_creds_opt_free_pa ++ (krb5_context context, ++ int num_preauth_data, ++ krb5_gic_opt_pa_data *preauth_data); ++ + #endif /* KRB5_PREAUTH_PLUGIN_H_INCLUDED */ +Index: src/clients/kpasswd/ksetpwd.c +=================================================================== +--- src/clients/kpasswd/ksetpwd.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/clients/kpasswd/ksetpwd.c (.../branches/krb5-1-6) (Revision 19151) +@@ -34,8 +34,6 @@ + { + krb5_preauthtype preauth[] = { KRB5_PADATA_ENC_TIMESTAMP }; + krb5_enctype etypes[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC}; +- memset( outOptions, 0, sizeof(*outOptions) ); +- krb5_get_init_creds_opt_init(outOptions); + krb5_get_init_creds_opt_set_address_list(outOptions, NULL); + krb5_get_init_creds_opt_set_etype_list( outOptions, etypes, sizeof(etypes)/sizeof(krb5_enctype) ); + krb5_get_init_creds_opt_set_preauth_list(outOptions, preauth, sizeof(preauth)/sizeof(krb5_preauthtype) ); +@@ -128,17 +126,21 @@ + } + if( kres != 0 || have_credentials == 0 ) + { +- krb5_get_init_creds_opt options; +- get_init_creds_opt_init(&options); ++ krb5_get_init_creds_opt *options = NULL; ++ kres = krb5_get_init_creds_opt_alloc(kcontext, &options); ++ if ( kres == 0 ) ++ { ++ get_init_creds_opt_init(options); + /* + ** no valid credentials - get new ones + */ +- kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass, +- NULL /*prompter*/, +- NULL /*data*/, +- 0 /*starttime*/, +- 0 /*in_tkt_service*/, +- &options /*options*/ ); ++ kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass, ++ NULL /*prompter*/, ++ NULL /*data*/, ++ 0 /*starttime*/, ++ 0 /*in_tkt_service*/, ++ options /*options*/ ); ++ } + if( kres == 0 ) + { + if( numCreds <= 0 ) +@@ -148,6 +150,7 @@ + if( kres == 0 ) + have_credentials = 1; + } ++ krb5_get_init_creds_opt_free(kcontext, options); + } + #ifdef NOTUSED + if( have_credentials ) +Index: src/clients/kpasswd/kpasswd.c +=================================================================== +--- src/clients/kpasswd/kpasswd.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/clients/kpasswd/kpasswd.c (.../branches/krb5-1-6) (Revision 19151) +@@ -49,7 +49,7 @@ + krb5_principal princ; + char *pname; + krb5_ccache ccache; +- krb5_get_init_creds_opt opts; ++ krb5_get_init_creds_opt *opts = NULL; + krb5_creds creds; + + char pw[1024]; +@@ -102,26 +102,31 @@ + get_name_from_passwd_file(argv[0], context, &princ); + } + +- krb5_get_init_creds_opt_init(&opts); +- krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); +- krb5_get_init_creds_opt_set_renew_life(&opts, 0); +- krb5_get_init_creds_opt_set_forwardable(&opts, 0); +- krb5_get_init_creds_opt_set_proxiable(&opts, 0); ++ if ((ret = krb5_get_init_creds_opt_alloc(context, &opts))) { ++ com_err(argv[0], ret, "allocating krb5_get_init_creds_opt"); ++ exit(1); ++ } ++ krb5_get_init_creds_opt_set_tkt_life(opts, 5*60); ++ krb5_get_init_creds_opt_set_renew_life(opts, 0); ++ krb5_get_init_creds_opt_set_forwardable(opts, 0); ++ krb5_get_init_creds_opt_set_proxiable(opts, 0); + + if ((ret = krb5_get_init_creds_password(context, &creds, princ, NULL, + krb5_prompter_posix, NULL, +- 0, "kadmin/changepw", &opts))) { ++ 0, "kadmin/changepw", opts))) { + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + com_err(argv[0], 0, + "Password incorrect while getting initial ticket"); + else + com_err(argv[0], ret, "getting initial ticket"); ++ krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + pwlen = sizeof(pw); + if ((ret = krb5_read_password(context, P1, P2, pw, &pwlen))) { + com_err(argv[0], ret, "while reading password"); ++ krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + +@@ -129,6 +134,7 @@ + &result_code, &result_code_string, + &result_string))) { + com_err(argv[0], ret, "changing password"); ++ krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + +@@ -138,6 +144,7 @@ + result_string.length?": ":"", + (int) result_string.length, + result_string.data ? result_string.data : ""); ++ krb5_get_init_creds_opt_free(context, opts); + exit(2); + } + +@@ -145,6 +152,7 @@ + free(result_string.data); + if (result_code_string.data != NULL) + free(result_code_string.data); ++ krb5_get_init_creds_opt_free(context, opts); + + printf("Password changed.\n"); + exit(0); +Index: src/clients/kinit/kinit.c +=================================================================== +--- src/clients/kinit/kinit.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/clients/kinit/kinit.c (.../branches/krb5-1-6) (Revision 19151) +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + + #ifdef GETOPT_LONG +@@ -143,6 +144,9 @@ + char* k4_cache_name; + + action_type action; ++ ++ int num_pa_opts; ++ krb5_gic_opt_pa_data *pa_opts; + }; + + struct k5_data +@@ -283,6 +287,37 @@ + fprintf (stderr, "\n"); + } + ++static int ++add_preauth_opt(struct k_opts *opts, char *av) ++{ ++ char *sep, *v; ++ krb5_gic_opt_pa_data *p, *x; ++ ++ if (opts->num_pa_opts == 0) { ++ opts->pa_opts = malloc(sizeof(krb5_gic_opt_pa_data)); ++ if (opts->pa_opts == NULL) ++ return ENOMEM; ++ } else { ++ size_t newsize = (opts->num_pa_opts + 1) * sizeof(krb5_gic_opt_pa_data); ++ x = realloc(opts->pa_opts, newsize); ++ if (x == NULL) ++ return ENOMEM; ++ opts->pa_opts = x; ++ } ++ p = &opts->pa_opts[opts->num_pa_opts]; ++ sep = strchr(av, '='); ++ if (sep) { ++ *sep = '\0'; ++ v = ++sep; ++ p->value = v; ++ } else { ++ p->value = "yes"; ++ } ++ p->attr = av; ++ opts->num_pa_opts++; ++ return 0; ++} ++ + static char * + parse_options(argc, argv, opts, progname) + int argc; +@@ -296,7 +331,7 @@ + int use_k5 = 0; + int i; + +- while ((i = GETOPT(argc, argv, "r:fpFP54aAVl:s:c:kt:RS:v")) ++ while ((i = GETOPT(argc, argv, "r:fpFP54aAVl:s:c:kt:RS:vX:")) + != -1) { + switch (i) { + case 'V': +@@ -380,6 +415,14 @@ + opts->k5_cache_name = optarg; + } + break; ++ case 'X': ++ code = add_preauth_opt(opts, optarg); ++ if (code) ++ { ++ com_err(progname, code, "while adding preauth option"); ++ errflg++; ++ } ++ break; + #if 0 + /* + A little more work is needed before we can enable this +@@ -752,12 +795,15 @@ + krb5_keytab keytab = 0; + krb5_creds my_creds; + krb5_error_code code = 0; +- krb5_get_init_creds_opt options; ++ krb5_get_init_creds_opt *options = NULL; ++ int i; + + if (!got_k5) + return 0; + +- krb5_get_init_creds_opt_init(&options); ++ code = krb5_get_init_creds_opt_alloc(k5->ctx, &options); ++ if (code) ++ goto cleanup; + memset(&my_creds, 0, sizeof(my_creds)); + + /* +@@ -766,17 +812,17 @@ + */ + + if (opts->lifetime) +- krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime); ++ krb5_get_init_creds_opt_set_tkt_life(options, opts->lifetime); + if (opts->rlife) +- krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife); ++ krb5_get_init_creds_opt_set_renew_life(options, opts->rlife); + if (opts->forwardable) +- krb5_get_init_creds_opt_set_forwardable(&options, 1); ++ krb5_get_init_creds_opt_set_forwardable(options, 1); + if (opts->not_forwardable) +- krb5_get_init_creds_opt_set_forwardable(&options, 0); ++ krb5_get_init_creds_opt_set_forwardable(options, 0); + if (opts->proxiable) +- krb5_get_init_creds_opt_set_proxiable(&options, 1); ++ krb5_get_init_creds_opt_set_proxiable(options, 1); + if (opts->not_proxiable) +- krb5_get_init_creds_opt_set_proxiable(&options, 0); ++ krb5_get_init_creds_opt_set_proxiable(options, 0); + if (opts->addresses) + { + krb5_address **addresses = NULL; +@@ -785,10 +831,10 @@ + com_err(progname, code, "getting local addresses"); + goto cleanup; + } +- krb5_get_init_creds_opt_set_address_list(&options, addresses); ++ krb5_get_init_creds_opt_set_address_list(options, addresses); + } + if (opts->no_addresses) +- krb5_get_init_creds_opt_set_address_list(&options, NULL); ++ krb5_get_init_creds_opt_set_address_list(options, NULL); + + if ((opts->action == INIT_KT) && opts->keytab_name) + { +@@ -800,20 +846,31 @@ + } + } + ++ for (i = 0; i < opts->num_pa_opts; i++) { ++ code = krb5_get_init_creds_opt_set_pa(k5->ctx, options, ++ opts->pa_opts[i].attr, ++ opts->pa_opts[i].value); ++ if (code != 0) { ++ com_err(progname, code, "while setting '%s'='%s'", ++ opts->pa_opts[i].attr, opts->pa_opts[i].value); ++ goto cleanup; ++ } ++ } ++ + switch (opts->action) { + case INIT_PW: + code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, + 0, kinit_prompter, 0, + opts->starttime, + opts->service_name, +- &options); ++ options); + break; + case INIT_KT: + code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, + keytab, + opts->starttime, + opts->service_name, +- &options); ++ options); + break; + case VALIDATE: + code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc, +@@ -876,9 +933,16 @@ + notix = 0; + + cleanup: ++ if (options) ++ krb5_get_init_creds_opt_free(k5->ctx, options); + if (my_creds.client == k5->me) { + my_creds.client = 0; + } ++ if (opts->pa_opts) { ++ free(opts->pa_opts); ++ opts->pa_opts = NULL; ++ opts->num_pa_opts = 0; ++ } + krb5_free_cred_contents(k5->ctx, &my_creds); + if (keytab) + krb5_kt_close(k5->ctx, keytab); Index: src/lib/gssapi/krb5/k5sealv3.c =================================================================== ---- src/lib/gssapi/krb5/k5sealv3.c (.../tags/krb5-1-6-final) (Revision 19119) -+++ src/lib/gssapi/krb5/k5sealv3.c (.../branches/krb5-1-6) (Revision 19119) +--- src/lib/gssapi/krb5/k5sealv3.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/gssapi/krb5/k5sealv3.c (.../branches/krb5-1-6) (Revision 19151) @@ -412,10 +412,16 @@ if (load_16_be(althdr) != 0x0504 || althdr[2] != ptr[2] @@ -22,8 +768,8 @@ Index: src/lib/gssapi/krb5/k5sealv3.c if (conf_state) Index: src/lib/krb5/keytab/kt_file.c =================================================================== ---- src/lib/krb5/keytab/kt_file.c (.../tags/krb5-1-6-final) (Revision 19119) -+++ src/lib/krb5/keytab/kt_file.c (.../branches/krb5-1-6) (Revision 19119) +--- src/lib/krb5/keytab/kt_file.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/keytab/kt_file.c (.../branches/krb5-1-6) (Revision 19151) @@ -193,6 +193,7 @@ err = k5_mutex_init(&data->lock); @@ -42,8 +788,8 @@ Index: src/lib/krb5/keytab/kt_file.c } Index: src/lib/krb5/os/sendto_kdc.c =================================================================== ---- src/lib/krb5/os/sendto_kdc.c (.../tags/krb5-1-6-final) (Revision 19119) -+++ src/lib/krb5/os/sendto_kdc.c (.../branches/krb5-1-6) (Revision 19119) +--- src/lib/krb5/os/sendto_kdc.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/os/sendto_kdc.c (.../branches/krb5-1-6) (Revision 19151) @@ -1127,7 +1127,7 @@ return ENOMEM; } @@ -64,8 +810,8 @@ Index: src/lib/krb5/os/sendto_kdc.c for (i = 0; i < n_conns; i++) { Index: src/lib/krb5/os/changepw.c =================================================================== ---- src/lib/krb5/os/changepw.c (.../tags/krb5-1-6-final) (Revision 19119) -+++ src/lib/krb5/os/changepw.c (.../branches/krb5-1-6) (Revision 19119) +--- src/lib/krb5/os/changepw.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/os/changepw.c (.../branches/krb5-1-6) (Revision 19151) @@ -70,12 +70,14 @@ locate_service_kadmin, SOCK_STREAM, 0); if (!code) { @@ -84,8 +830,8 @@ Index: src/lib/krb5/os/changepw.c } Index: src/lib/krb5/ccache/ccapi/stdcc.c =================================================================== ---- src/lib/krb5/ccache/ccapi/stdcc.c (.../tags/krb5-1-6-final) (Revision 19119) -+++ src/lib/krb5/ccache/ccapi/stdcc.c (.../branches/krb5-1-6) (Revision 19119) +--- src/lib/krb5/ccache/ccapi/stdcc.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/ccache/ccapi/stdcc.c (.../branches/krb5-1-6) (Revision 19151) @@ -56,6 +56,7 @@ #ifdef USE_CCAPI_V3 @@ -236,6 +982,897 @@ Index: src/lib/krb5/ccache/ccapi/stdcc.c return cc_err_xlate(err); } +Index: src/lib/krb5/libkrb5.exports +=================================================================== +--- src/lib/krb5/libkrb5.exports (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/libkrb5.exports (.../branches/krb5-1-6) (Revision 19151) +@@ -436,11 +436,16 @@ + krb5_get_in_tkt_with_skey + krb5_get_init_creds + krb5_get_init_creds_keytab ++krb5_get_init_creds_opt_alloc ++krb5_get_init_creds_opt_free ++krb5_get_init_creds_opt_free_pa ++krb5_get_init_creds_opt_get_pa + krb5_get_init_creds_opt_init + krb5_get_init_creds_opt_set_address_list + krb5_get_init_creds_opt_set_change_password_prompt + krb5_get_init_creds_opt_set_etype_list + krb5_get_init_creds_opt_set_forwardable ++krb5_get_init_creds_opt_set_pa + krb5_get_init_creds_opt_set_preauth_list + krb5_get_init_creds_opt_set_proxiable + krb5_get_init_creds_opt_set_renew_life +Index: src/lib/krb5/krb/gic_keytab.c +=================================================================== +--- src/lib/krb5/krb/gic_keytab.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/krb/gic_keytab.c (.../branches/krb5-1-6) (Revision 19151) +@@ -76,11 +76,18 @@ + } + + krb5_error_code KRB5_CALLCONV +-krb5_get_init_creds_keytab(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_keytab arg_keytab, krb5_deltat start_time, char *in_tkt_service, krb5_get_init_creds_opt *options) ++krb5_get_init_creds_keytab(krb5_context context, ++ krb5_creds *creds, ++ krb5_principal client, ++ krb5_keytab arg_keytab, ++ krb5_deltat start_time, ++ char *in_tkt_service, ++ krb5_get_init_creds_opt *options) + { + krb5_error_code ret, ret2; + int use_master; + krb5_keytab keytab; ++ krb5_gic_opt_ext *opte = NULL; + + if (arg_keytab == NULL) { + if ((ret = krb5_kt_default(context, &keytab))) +@@ -89,12 +96,17 @@ + keytab = arg_keytab; + } + ++ ret = krb5int_gic_opt_to_opte(context, options, &opte, 1, ++ "krb5_get_init_creds_keytab"); ++ if (ret) ++ return ret; ++ + use_master = 0; + + /* first try: get the requested tkt from any kdc */ + + ret = krb5_get_init_creds(context, creds, client, NULL, NULL, +- start_time, in_tkt_service, options, ++ start_time, in_tkt_service, opte, + krb5_get_as_key_keytab, (void *) keytab, + &use_master,NULL); + +@@ -115,7 +127,7 @@ + use_master = 1; + + ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL, +- start_time, in_tkt_service, options, ++ start_time, in_tkt_service, opte, + krb5_get_as_key_keytab, (void *) keytab, + &use_master, NULL); + +@@ -139,6 +151,8 @@ + do any prompting or changing for keytabs, that's it. */ + + cleanup: ++ if (opte && krb5_gic_opt_is_shadowed(opte)) ++ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte); + if (arg_keytab == NULL) + krb5_kt_close(context, keytab); + +@@ -152,15 +166,18 @@ + krb5_creds *creds, krb5_kdc_rep **ret_as_reply) + { + krb5_error_code retval; +- krb5_get_init_creds_opt opt; ++ krb5_gic_opt_ext *opte; + char * server = NULL; + krb5_keytab keytab; + krb5_principal client_princ, server_princ; + int use_master = 0; + +- krb5int_populate_gic_opt(context, &opt, +- options, addrs, ktypes, +- pre_auth_types, creds); ++ retval = krb5int_populate_gic_opt(context, &opte, ++ options, addrs, ktypes, ++ pre_auth_types, creds); ++ if (retval) ++ return retval; ++ + if (arg_keytab == NULL) { + retval = krb5_kt_default(context, &keytab); + if (retval) +@@ -176,10 +193,11 @@ + retval = krb5_get_init_creds (context, + creds, creds->client, + krb5_prompter_posix, NULL, +- 0, server, &opt, ++ 0, server, opte, + krb5_get_as_key_keytab, (void *)keytab, + &use_master, ret_as_reply); + krb5_free_unparsed_name( context, server); ++ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte); + if (retval) { + goto cleanup; + } +Index: src/lib/krb5/krb/gic_opt.c +=================================================================== +--- src/lib/krb5/krb/gic_opt.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/krb/gic_opt.c (.../branches/krb5-1-6) (Revision 19151) +@@ -72,3 +72,357 @@ + else + opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT; + } ++ ++/* ++ * Extending the krb5_get_init_creds_opt structure. The original ++ * krb5_get_init_creds_opt structure is defined publicly. The ++ * new extended version is private. The original interface ++ * assumed a pre-allocated structure which was passed to ++ * krb5_get_init_creds_init(). The new interface assumes that ++ * the caller will call krb5_get_init_creds_alloc() and ++ * krb5_get_init_creds_free(). ++ * ++ * Callers MUST NOT call krb5_get_init_creds_init() after allocating an ++ * opts structure using krb5_get_init_creds_alloc(). To do so will ++ * introduce memory leaks. Unfortunately, there is no way to enforce ++ * this behavior. ++ * ++ * Two private flags are added for backward compatibility. ++ * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated ++ * with the new krb5_get_init_creds_opt_alloc() function. ++ * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended ++ * structure is a shadow copy of an original krb5_get_init_creds_opt ++ * structure. ++ * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to ++ * krb5int_gic_opt_to_opte(), the resulting extended structure should be ++ * freed (using krb5_get_init_creds_free). Otherwise, the original ++ * structure was already extended and there is no need to free it. ++ */ ++ ++/* Forward prototype */ ++static void ++free_gic_opt_ext_preauth_data(krb5_context context, ++ krb5_gic_opt_ext *opte); ++ ++static krb5_error_code ++krb5int_gic_opte_private_alloc(krb5_context context, krb5_gic_opt_ext *opte) ++{ ++ if (NULL == opte || !krb5_gic_opt_is_extended(opte)) ++ return EINVAL; ++ ++ opte->opt_private = calloc(1, sizeof(*opte->opt_private)); ++ if (NULL == opte->opt_private) { ++ return ENOMEM; ++ } ++ /* Allocate any private stuff */ ++ opte->opt_private->num_preauth_data = 0; ++ opte->opt_private->preauth_data = NULL; ++ return 0; ++} ++ ++static krb5_error_code ++krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte) ++{ ++ if (NULL == opte || !krb5_gic_opt_is_extended(opte)) ++ return EINVAL; ++ ++ /* Free up any private stuff */ ++ if (opte->opt_private->preauth_data != NULL) ++ free_gic_opt_ext_preauth_data(context, opte); ++ free(opte->opt_private); ++ opte->opt_private = NULL; ++ return 0; ++} ++ ++static krb5_gic_opt_ext * ++krb5int_gic_opte_alloc(krb5_context context) ++{ ++ krb5_gic_opt_ext *opte; ++ krb5_error_code code; ++ ++ opte = calloc(1, sizeof(*opte)); ++ if (NULL == opte) ++ return NULL; ++ opte->flags = KRB5_GET_INIT_CREDS_OPT_EXTENDED; ++ ++ code = krb5int_gic_opte_private_alloc(context, opte); ++ if (code) { ++ krb5int_set_error(&context->err, code, ++ "krb5int_gic_opte_alloc: krb5int_gic_opte_private_alloc failed"); ++ free(opte); ++ return NULL; ++ } ++ return(opte); ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_get_init_creds_opt_alloc(krb5_context context, ++ krb5_get_init_creds_opt **opt) ++{ ++ krb5_gic_opt_ext *opte; ++ ++ if (NULL == opt) ++ return EINVAL; ++ *opt = NULL; ++ ++ /* ++ * We return a new extended structure cast as a krb5_get_init_creds_opt ++ */ ++ opte = krb5int_gic_opte_alloc(context); ++ if (NULL == opte) ++ return ENOMEM; ++ ++ *opt = (krb5_get_init_creds_opt *) opte; ++ return 0; ++} ++ ++void KRB5_CALLCONV ++krb5_get_init_creds_opt_free(krb5_context context, ++ krb5_get_init_creds_opt *opt) ++{ ++ krb5_gic_opt_ext *opte; ++ ++ if (NULL == opt) ++ return; ++ ++ /* Don't touch it if we didn't allocate it */ ++ if (!krb5_gic_opt_is_extended(opt)) ++ return; ++ ++ opte = (krb5_gic_opt_ext *)opt; ++ if (opte->opt_private) ++ krb5int_gic_opte_private_free(context, opte); ++ ++ free(opte); ++} ++ ++static krb5_error_code ++krb5int_gic_opte_copy(krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ krb5_gic_opt_ext **opte) ++{ ++ krb5_gic_opt_ext *oe; ++ ++ oe = krb5int_gic_opte_alloc(context); ++ if (NULL == oe) ++ return ENOMEM; ++ memcpy(oe, opt, sizeof(*opt)); ++ /* Fix these -- overwritten by the copy */ ++ oe->flags |= ( KRB5_GET_INIT_CREDS_OPT_EXTENDED | ++ KRB5_GET_INIT_CREDS_OPT_SHADOWED); ++ ++ *opte = oe; ++ return 0; ++} ++ ++/* ++ * Convert a krb5_get_init_creds_opt pointer to a pointer to ++ * an extended, krb5_gic_opt_ext pointer. If the original ++ * pointer already points to an extended structure, then simply ++ * return the original pointer. Otherwise, if 'force' is non-zero, ++ * allocate an extended structure and copy the original over it. ++ * If the original pointer did not point to an extended structure ++ * and 'force' is zero, then return an error. This is used in ++ * cases where the original *should* be an extended structure. ++ */ ++krb5_error_code ++krb5int_gic_opt_to_opte(krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ krb5_gic_opt_ext **opte, ++ unsigned int force, ++ const char *where) ++{ ++ if (!krb5_gic_opt_is_extended(opt)) { ++ if (force) { ++ return krb5int_gic_opte_copy(context, opt, opte); ++ } else { ++ krb5int_set_error(&context->err, EINVAL, ++ "%s: attempt to convert non-extended krb5_get_init_creds_opt", ++ where); ++ return EINVAL; ++ } ++ } ++ /* If it is already extended, just return it */ ++ *opte = (krb5_gic_opt_ext *)opt; ++ return 0; ++} ++ ++static void ++free_gic_opt_ext_preauth_data(krb5_context context, ++ krb5_gic_opt_ext *opte) ++{ ++ int i; ++ ++ if (NULL == opte || !krb5_gic_opt_is_extended(opte)) ++ return; ++ if (NULL == opte->opt_private || NULL == opte->opt_private->preauth_data) ++ return; ++ ++ for (i = 0; i < opte->opt_private->num_preauth_data; i++) { ++ if (opte->opt_private->preauth_data[i].attr != NULL) ++ free(opte->opt_private->preauth_data[i].attr); ++ if (opte->opt_private->preauth_data[i].value != NULL) ++ free(opte->opt_private->preauth_data[i].value); ++ } ++ free(opte->opt_private->preauth_data); ++ opte->opt_private->preauth_data = NULL; ++ opte->opt_private->num_preauth_data = 0; ++} ++ ++static krb5_error_code ++add_gic_opt_ext_preauth_data(krb5_context context, ++ krb5_gic_opt_ext *opte, ++ const char *attr, ++ const char *value) ++{ ++ size_t newsize; ++ int i; ++ krb5_gic_opt_pa_data *newpad; ++ ++ newsize = opte->opt_private->num_preauth_data + 1; ++ newsize = newsize * sizeof(*opte->opt_private->preauth_data); ++ if (opte->opt_private->preauth_data == NULL) ++ newpad = malloc(newsize); ++ else ++ newpad = realloc(opte->opt_private->preauth_data, newsize); ++ if (newpad == NULL) ++ return ENOMEM; ++ ++ i = opte->opt_private->num_preauth_data; ++ newpad[i].attr = strdup(attr); ++ if (newpad[i].attr == NULL) ++ return ENOMEM; ++ newpad[i].value = strdup(value); ++ if (newpad[i].value == NULL) { ++ free(newpad[i].attr); ++ return ENOMEM; ++ } ++ opte->opt_private->num_preauth_data += 1; ++ opte->opt_private->preauth_data = newpad; ++ return 0; ++} ++ ++/* ++ * This function allows the caller to supply options to preauth ++ * plugins. Preauth plugin modules are given a chance to look ++ * at each option at the time this function is called in ordre ++ * to check the validity of the option. ++ * The 'opt' pointer supplied to this function must have been ++ * obtained using krb5_get_init_creds_opt_alloc() ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_get_init_creds_opt_set_pa(krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ const char *attr, ++ const char *value) ++{ ++ krb5_error_code retval; ++ krb5_gic_opt_ext *opte; ++ ++ retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0, ++ "krb5_get_init_creds_opt_set_pa"); ++ if (retval) ++ return retval; ++ ++ /* ++ * Copy the option into the extended get_init_creds_opt structure ++ */ ++ retval = add_gic_opt_ext_preauth_data(context, opte, attr, value); ++ if (retval) ++ return retval; ++ ++ /* ++ * Give the plugins a chance to look at the option now. ++ */ ++ retval = krb5_preauth_supply_preauth_data(context, opte, attr, value); ++ return retval; ++} ++ ++/* ++ * This function allows a preauth plugin to obtain preauth ++ * options. The preauth_data returned from this function ++ * should be freed by calling krb5_get_init_creds_opt_free_pa(). ++ * ++ * The 'opt' pointer supplied to this function must have been ++ * obtained using krb5_get_init_creds_opt_alloc() ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_get_init_creds_opt_get_pa(krb5_context context, ++ krb5_get_init_creds_opt *opt, ++ int *num_preauth_data, ++ krb5_gic_opt_pa_data **preauth_data) ++{ ++ krb5_error_code retval; ++ krb5_gic_opt_ext *opte; ++ krb5_gic_opt_pa_data *p = NULL; ++ int i; ++ size_t allocsize; ++ ++ retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0, ++ "krb5_get_init_creds_opt_get_pa"); ++ if (retval) ++ return retval; ++ ++ if (num_preauth_data == NULL || preauth_data == NULL) ++ return EINVAL; ++ ++ *num_preauth_data = 0; ++ *preauth_data = NULL; ++ ++ if (opte->opt_private->num_preauth_data == 0) ++ return 0; ++ ++ allocsize = ++ opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data); ++ p = malloc(allocsize); ++ if (p == NULL) ++ return ENOMEM; ++ ++ /* Init these to make cleanup easier */ ++ for (i = 0; i < opte->opt_private->num_preauth_data; i++) { ++ p[i].attr = NULL; ++ p[i].value = NULL; ++ } ++ ++ for (i = 0; i < opte->opt_private->num_preauth_data; i++) { ++ p[i].attr = strdup(opte->opt_private->preauth_data[i].attr); ++ p[i].value = strdup(opte->opt_private->preauth_data[i].value); ++ if (p[i].attr == NULL || p[i].value == NULL) ++ goto cleanup; ++ } ++ *num_preauth_data = i; ++ *preauth_data = p; ++ return 0; ++cleanup: ++ for (i = 0; i < opte->opt_private->num_preauth_data; i++) { ++ if (p[i].attr != NULL) ++ free(p[i].attr); ++ if (p[i].value != NULL) ++ free(p[i].value); ++ } ++ free(p); ++ return ENOMEM; ++} ++ ++/* ++ * This function frees the preauth_data that was returned by ++ * krb5_get_init_creds_opt_get_pa(). ++ */ ++void KRB5_CALLCONV ++krb5_get_init_creds_opt_free_pa(krb5_context context, ++ int num_preauth_data, ++ krb5_gic_opt_pa_data *preauth_data) ++{ ++ int i; ++ ++ if (num_preauth_data <= 0 || preauth_data == NULL) ++ return; ++ ++ for (i = 0; i < num_preauth_data; i++) { ++ if (preauth_data[i].attr != NULL) ++ free(preauth_data[i].attr); ++ if (preauth_data[i].value != NULL) ++ free(preauth_data[i].value); ++ } ++ free(preauth_data); ++} +Index: src/lib/krb5/krb/get_in_tkt.c +=================================================================== +--- src/lib/krb5/krb/get_in_tkt.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/krb/get_in_tkt.c (.../branches/krb5-1-6) (Revision 19151) +@@ -843,7 +843,7 @@ + void *prompter_data, + krb5_deltat start_time, + char *in_tkt_service, +- krb5_get_init_creds_opt *options, ++ krb5_gic_opt_ext *options, + krb5_gic_get_as_key_fct gak_fct, + void *gak_data, + int *use_master, +@@ -1111,7 +1111,7 @@ + &salt, &s2kparams, &etype, &as_key, + prompter, prompter_data, + gak_fct, gak_data, +- &get_data_rock))) ++ &get_data_rock, options))) + goto cleanup; + } else { + if (preauth_to_use != NULL) { +@@ -1129,7 +1129,7 @@ + &as_key, + prompter, prompter_data, + gak_fct, gak_data, +- &get_data_rock); ++ &get_data_rock, options); + } else { + /* No preauth supplied, so can't query the plug-ins. */ + ret = KRB5KRB_ERR_GENERIC; +@@ -1214,7 +1214,7 @@ + local_as_reply->padata, &kdc_padata, + &salt, &s2kparams, &etype, &as_key, prompter, + prompter_data, gak_fct, gak_data, +- &get_data_rock))) ++ &get_data_rock, options))) + goto cleanup; + + /* XXX For 1.1.1 and prior KDC's, when SAM is used w/ USE_SAD_AS_KEY, +Index: src/lib/krb5/krb/preauth2.c +=================================================================== +--- src/lib/krb5/krb/preauth2.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/krb/preauth2.c (.../branches/krb5-1-6) (Revision 19151) +@@ -163,6 +163,10 @@ + context->modules[k].use_count = 0; + context->modules[k].client_process = table->process; + context->modules[k].client_tryagain = table->tryagain; ++ if (j == 0) ++ context->modules[k].client_supply_gic_opts = table->gic_opts; ++ else ++ context->modules[k].client_supply_gic_opts = NULL; + context->modules[k].request_context = NULL; + /* + * Only call request_init and request_fini once per plugin. +@@ -211,6 +215,52 @@ + } + } + ++/* ++ * Give all the preauth plugins a look at the preauth option which ++ * has just been set ++ */ ++krb5_error_code ++krb5_preauth_supply_preauth_data(krb5_context context, ++ krb5_gic_opt_ext *opte, ++ const char *attr, ++ const char *value) ++{ ++ krb5_error_code retval; ++ int i; ++ void *pctx; ++ const char *emsg = NULL; ++ ++ if (context->preauth_context == NULL) ++ krb5_init_preauth_context(context); ++ if (context->preauth_context == NULL) { ++ retval = EINVAL; ++ krb5int_set_error(&context->err, retval, ++ "krb5_preauth_supply_preauth_data: " ++ "Unable to initialize preauth context"); ++ return retval; ++ } ++ ++ /* ++ * Go down the list of preauth modules, and supply them with the ++ * attribute/value pair. ++ */ ++ for (i = 0; i < context->preauth_context->n_modules; i++) { ++ if (context->preauth_context->modules[i].client_supply_gic_opts == NULL) ++ continue; ++ pctx = context->preauth_context->modules[i].plugin_context; ++ retval = (*context->preauth_context->modules[i].client_supply_gic_opts) ++ (context, pctx, ++ (krb5_get_init_creds_opt *)opte, attr, value); ++ if (retval) { ++ emsg = krb5_get_error_message(context, retval); ++ krb5int_set_error(&context->err, retval, "Preauth plugin %s: %s", ++ context->preauth_context->modules[i].name, emsg); ++ break; ++ } ++ } ++ return retval; ++} ++ + /* Free the per-krb5_context preauth_context. This means clearing any + * plugin-specific context which may have been created, and then + * freeing the context itself. */ +@@ -405,7 +455,7 @@ + * involved things. */ + void KRB5_CALLCONV + krb5_preauth_prepare_request(krb5_context kcontext, +- krb5_get_init_creds_opt *options, ++ krb5_gic_opt_ext *opte, + krb5_kdc_req *request) + { + int i, j; +@@ -415,7 +465,7 @@ + } + /* Add the module-specific enctype list to the request, but only if + * it's something we can safely modify. */ +- if (!(options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))) { ++ if (!(opte && (opte->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))) { + for (i = 0; i < kcontext->preauth_context->n_modules; i++) { + if (kcontext->preauth_context->modules[i].enctypes == NULL) + continue; +@@ -448,7 +498,8 @@ + krb5_pa_data ***out_pa_list, + int *out_pa_list_size, + int *module_ret, +- int *module_flags) ++ int *module_flags, ++ krb5_gic_opt_ext *opte) + { + int i; + krb5_pa_data *out_pa_data; +@@ -487,6 +538,7 @@ + ret = module->client_process(kcontext, + module->plugin_context, + *module->request_context_pp, ++ (krb5_get_init_creds_opt *)opte, + client_data_proc, + get_data_rock, + request, +@@ -1299,7 +1351,8 @@ + krb5_keyblock *as_key, + krb5_prompter_fct prompter, void *prompter_data, + krb5_gic_get_as_key_fct gak_fct, void *gak_data, +- krb5_preauth_client_rock *get_data_rock) ++ krb5_preauth_client_rock *get_data_rock, ++ krb5_gic_opt_ext *opte) + { + krb5_error_code ret; + krb5_pa_data *out_padata; +@@ -1330,6 +1383,7 @@ + if ((*module->client_tryagain)(kcontext, + module->plugin_context, + *module->request_context_pp, ++ (krb5_get_init_creds_opt *)opte, + client_data_proc, + get_data_rock, + request, +@@ -1362,7 +1416,8 @@ + krb5_keyblock *as_key, + krb5_prompter_fct prompter, void *prompter_data, + krb5_gic_get_as_key_fct gak_fct, void *gak_data, +- krb5_preauth_client_rock *get_data_rock) ++ krb5_preauth_client_rock *get_data_rock, ++ krb5_gic_opt_ext *opte) + { + int h, i, j, out_pa_list_size; + int seen_etype_info2 = 0; +@@ -1555,7 +1610,8 @@ + &out_pa_list, + &out_pa_list_size, + &module_ret, +- &module_flags); ++ &module_flags, ++ opte); + if (ret == 0) { + if (module_ret == 0) { + if (paorder[h] == PA_REAL) { +Index: src/lib/krb5/krb/gic_pwd.c +=================================================================== +--- src/lib/krb5/krb/gic_pwd.c (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5/krb/gic_pwd.c (.../branches/krb5-1-6) (Revision 19151) +@@ -85,18 +85,28 @@ + } + + krb5_error_code KRB5_CALLCONV +-krb5_get_init_creds_password(krb5_context context, krb5_creds *creds, krb5_principal client, char *password, krb5_prompter_fct prompter, void *data, krb5_deltat start_time, char *in_tkt_service, krb5_get_init_creds_opt *options) ++krb5_get_init_creds_password(krb5_context context, ++ krb5_creds *creds, ++ krb5_principal client, ++ char *password, ++ krb5_prompter_fct prompter, ++ void *data, ++ krb5_deltat start_time, ++ char *in_tkt_service, ++ krb5_get_init_creds_opt *options) + { + krb5_error_code ret, ret2; + int use_master; + krb5_kdc_rep *as_reply; + int tries; + krb5_creds chpw_creds; +- krb5_get_init_creds_opt chpw_opts; ++ krb5_get_init_creds_opt *chpw_opts = NULL; + krb5_data pw0, pw1; + char banner[1024], pw0array[1024], pw1array[1024]; + krb5_prompt prompt[2]; + krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])]; ++ krb5_gic_opt_ext *opte = NULL; ++ krb5_gic_opt_ext *chpw_opte = NULL; + + use_master = 0; + as_reply = NULL; +@@ -119,10 +129,15 @@ + pw1.data[0] = '\0'; + pw1.length = sizeof(pw1array); + ++ ret = krb5int_gic_opt_to_opte(context, options, &opte, 1, ++ "krb5_get_init_creds_password"); ++ if (ret) ++ goto cleanup; ++ + /* first try: get the requested tkt from any kdc */ + + ret = krb5_get_init_creds(context, creds, client, prompter, data, +- start_time, in_tkt_service, options, ++ start_time, in_tkt_service, opte, + krb5_get_as_key_password, (void *) &pw0, + &use_master, &as_reply); + +@@ -151,7 +166,7 @@ + as_reply = NULL; + } + ret2 = krb5_get_init_creds(context, creds, client, prompter, data, +- start_time, in_tkt_service, options, ++ start_time, in_tkt_service, opte, + krb5_get_as_key_password, (void *) &pw0, + &use_master, &as_reply); + +@@ -197,15 +212,21 @@ + + /* use a minimal set of options */ + +- krb5_get_init_creds_opt_init(&chpw_opts); +- krb5_get_init_creds_opt_set_tkt_life(&chpw_opts, 5*60); +- krb5_get_init_creds_opt_set_renew_life(&chpw_opts, 0); +- krb5_get_init_creds_opt_set_forwardable(&chpw_opts, 0); +- krb5_get_init_creds_opt_set_proxiable(&chpw_opts, 0); ++ ret = krb5_get_init_creds_opt_alloc(context, &chpw_opts); ++ if (ret) ++ goto cleanup; ++ krb5_get_init_creds_opt_set_tkt_life(chpw_opts, 5*60); ++ krb5_get_init_creds_opt_set_renew_life(chpw_opts, 0); ++ krb5_get_init_creds_opt_set_forwardable(chpw_opts, 0); ++ krb5_get_init_creds_opt_set_proxiable(chpw_opts, 0); ++ ret = krb5int_gic_opt_to_opte(context, chpw_opts, &chpw_opte, 0, ++ "krb5_get_init_creds_password (changing password)"); ++ if (ret) ++ goto cleanup; + + if ((ret = krb5_get_init_creds(context, &chpw_creds, client, + prompter, data, +- start_time, "kadmin/changepw", &chpw_opts, ++ start_time, "kadmin/changepw", chpw_opte, + krb5_get_as_key_password, (void *) &pw0, + &use_master, NULL))) + goto cleanup; +@@ -293,7 +314,7 @@ + is final. */ + + ret = krb5_get_init_creds(context, creds, client, prompter, data, +- start_time, in_tkt_service, options, ++ start_time, in_tkt_service, opte, + krb5_get_as_key_password, (void *) &pw0, + &use_master, &as_reply); + +@@ -373,6 +394,10 @@ + } + } + ++ if (chpw_opts) ++ krb5_get_init_creds_opt_free(context, chpw_opts); ++ if (opte && krb5_gic_opt_is_shadowed(opte)) ++ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte); + memset(pw0array, 0, sizeof(pw0array)); + memset(pw1array, 0, sizeof(pw1array)); + krb5_free_cred_contents(context, &chpw_creds); +@@ -381,15 +406,20 @@ + + return(ret); + } +-void krb5int_populate_gic_opt ( +- krb5_context context, krb5_get_init_creds_opt *opt, ++krb5_error_code krb5int_populate_gic_opt ( ++ krb5_context context, krb5_gic_opt_ext **opte, + krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, krb5_creds *creds) + { + int i; + krb5_int32 starttime; ++ krb5_get_init_creds_opt *opt; ++ krb5_error_code retval; + +- krb5_get_init_creds_opt_init(opt); ++ retval = krb5_get_init_creds_opt_alloc(context, &opt); ++ if (retval) ++ return(retval); ++ + if (addrs) + krb5_get_init_creds_opt_set_address_list(opt, (krb5_address **) addrs); + if (ktypes) { +@@ -413,6 +443,8 @@ + if (creds->times.starttime) starttime = creds->times.starttime; + krb5_get_init_creds_opt_set_tkt_life(opt, creds->times.endtime - starttime); + } ++ return krb5int_gic_opt_to_opte(context, opt, opte, 0, ++ "krb5int_populate_gic_opt"); + } + + /* +@@ -445,10 +477,10 @@ + krb5_error_code retval; + krb5_data pw0; + char pw0array[1024]; +- krb5_get_init_creds_opt opt; + char * server; + krb5_principal server_princ, client_princ; + int use_master = 0; ++ krb5_gic_opt_ext *opte = NULL; + + pw0array[0] = '\0'; + pw0.data = pw0array; +@@ -462,21 +494,26 @@ + } else { + pw0.length = sizeof(pw0array); + } +- krb5int_populate_gic_opt(context, &opt, +- options, addrs, ktypes, +- pre_auth_types, creds); +- retval = krb5_unparse_name( context, creds->server, &server); ++ retval = krb5int_populate_gic_opt(context, &opte, ++ options, addrs, ktypes, ++ pre_auth_types, creds); + if (retval) + return (retval); ++ retval = krb5_unparse_name( context, creds->server, &server); ++ if (retval) { ++ return (retval); ++ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte); ++ } + server_princ = creds->server; + client_princ = creds->client; + retval = krb5_get_init_creds (context, + creds, creds->client, + krb5_prompter_posix, NULL, +- 0, server, &opt, ++ 0, server, opte, + krb5_get_as_key_password, &pw0, + &use_master, ret_as_reply); + krb5_free_unparsed_name( context, server); ++ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte); + if (retval) { + return (retval); + } +Index: src/lib/krb5_32.def +=================================================================== +--- src/lib/krb5_32.def (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/lib/krb5_32.def (.../branches/krb5-1-6) (Revision 19151) +@@ -155,7 +155,12 @@ + krb5_get_in_tkt_with_password ; DEPRECATED + krb5_get_in_tkt_with_skey ; DEPRECATED + krb5_get_init_creds_keytab ++ krb5_get_init_creds_opt_alloc ++ krb5_get_init_creds_opt_free ++ krb5_get_init_creds_opt_free_pa ++ krb5_get_init_creds_opt_get_pa + krb5_get_init_creds_opt_init ++ krb5_get_init_creds_opt_set_pa + krb5_get_init_creds_opt_set_address_list + krb5_get_init_creds_opt_set_etype_list + krb5_get_init_creds_opt_set_forwardable +Index: src/patchlevel.h +=================================================================== +--- src/patchlevel.h ++++ src/patchlevel.h 2007/02/09 10:18:23 +@@ -53,6 +53,6 @@ + #define KRB5_MAJOR_RELEASE 1 + #define KRB5_MINOR_RELEASE 6 + #define KRB5_PATCHLEVEL 0 +-/* #undef KRB5_RELTAIL */ ++#define KRB5_RELTAIL "postrelease" + #define KRB5_RELDATE "20070109" +-#define KRB5_RELTAG "tags/krb5-1-6-final" ++#define KRB5_RELTAG "branches/krb5-1-6" +Index: src/util/def-check.pl +=================================================================== +--- src/util/def-check.pl (.../tags/krb5-1-6-final) (Revision 19151) ++++ src/util/def-check.pl (.../branches/krb5-1-6) (Revision 19151) +@@ -165,7 +165,7 @@ + goto Hadcallc; + } + # deal with no CALLCONV indicator +- s/^.* (\w+) *$/$1/; ++ s/^.* \**(\w+) *$/$1/; + die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/); + push @convD, $_; + push @vararg, $_ if $vararg; Eigenschaftsänderungen: . ___________________________________________________________________ @@ -244,7 +1881,7 @@ Name: svk:merge 304ed8f4-7412-0410-a0db-8249d8f37659:/my-branches/kdb-config:339 dc483132-0cff-0310-8789-dd5450dbe970:/branches/ccapi:18199 dc483132-0cff-0310-8789-dd5450dbe970:/branches/referrals/trunk:18581 - + 122d7f7f-0217-0410-a6d0-d37b9a318acc:/local/krb5/branches/krb5-1-6:19411 + + 122d7f7f-0217-0410-a6d0-d37b9a318acc:/local/krb5/branches/krb5-1-6:19458 304ed8f4-7412-0410-a0db-8249d8f37659:/my-branches/kdb-config:339 dc483132-0cff-0310-8789-dd5450dbe970:/branches/ccapi:18199 dc483132-0cff-0310-8789-dd5450dbe970:/branches/referrals/trunk:18581 diff --git a/krb5-doc.spec b/krb5-doc.spec index 77ed7ef..91b55d6 100644 --- a/krb5-doc.spec +++ b/krb5-doc.spec @@ -13,7 +13,7 @@ Name: krb5-doc BuildRequires: ghostscript-library latex2html te_ams Version: 1.6 -Release: 5 +Release: 7 %define srcRoot krb5-1.6 Summary: MIT Kerberos5 Implementation--Documentation License: X11/MIT diff --git a/krb5-plugins.changes b/krb5-plugins.changes index 6a80aec..7a614c2 100644 --- a/krb5-plugins.changes +++ b/krb5-plugins.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Feb 9 13:31:54 CET 2007 - mc@suse.de + +- update krb5-1.6-post.dif + ------------------------------------------------------------------- Mon Jan 29 17:47:22 CET 2007 - ro@suse.de diff --git a/krb5-plugins.spec b/krb5-plugins.spec index 1b9c09f..0673805 100644 --- a/krb5-plugins.spec +++ b/krb5-plugins.spec @@ -13,7 +13,7 @@ Name: krb5-plugins Version: 1.6 -Release: 5 +Release: 6 BuildRequires: krb5-devel openldap2-devel %define srcRoot krb5-1.6 %define vendorFiles %{_builddir}/%{srcRoot}/vendor-files/ @@ -205,6 +205,8 @@ rm -rf %{buildroot} %{_mandir}/man8/* %changelog -n krb5-plugins +* Fri Feb 09 2007 - mc@suse.de +- update krb5-1.6-post.dif * Mon Jan 29 2007 - ro@suse.de - no main package, no debuginfo * Mon Jan 29 2007 - mc@suse.de diff --git a/krb5.changes b/krb5.changes index fec48ae..db68b29 100644 --- a/krb5.changes +++ b/krb5.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Feb 9 13:31:22 CET 2007 - mc@suse.de + +- update krb5-1.6-post.dif + ------------------------------------------------------------------- Mon Jan 29 11:27:23 CET 2007 - mc@suse.de diff --git a/krb5.spec b/krb5.spec index f751e63..6052f5f 100644 --- a/krb5.spec +++ b/krb5.spec @@ -12,7 +12,7 @@ Name: krb5 Version: 1.6 -Release: 5 +Release: 7 BuildRequires: libcom_err %if %{suse_version} > 1010 BuildRequires: keyutils keyutils-devel @@ -488,6 +488,8 @@ rm -rf %{buildroot} %{_mandir}/man1/krb5-config.1* %changelog -n krb5 +* Fri Feb 09 2007 - mc@suse.de +- update krb5-1.6-post.dif * Mon Jan 29 2007 - mc@suse.de - krb5-1.6-fix-passwd-tcp.dif and krb5-1.6-fix-sendto_kdc-memset.dif are now upstream. Remove patches.