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 19164) +++ src/plugins/preauth/cksum_body/cksum_body_main.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/plugins/preauth/wpse/wpse_main.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/include/Makefile.in (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/include/k5-int.h (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/include/krb5/krb5.hin (.../branches/krb5-1-6) (Revision 19164) @@ -1469,8 +1469,20 @@ krb5_creds *, krb5_creds **, krb5_creds *** ); + +krb5_error_code KRB5_CALLCONV +krb5int_server_decrypt_ticket_keyblock + (krb5_context context, + const krb5_keyblock *key, + krb5_ticket *ticket); #endif +krb5_error_code KRB5_CALLCONV +krb5_server_decrypt_ticket_keytab + (krb5_context context, + const krb5_keytab kt, + krb5_ticket *ticket); + void KRB5_CALLCONV krb5_free_tgt_creds (krb5_context, krb5_creds **); /* XXX too hard to do with const */ @@ -2431,7 +2443,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 +2504,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 19164) +++ src/include/krb5/preauth_plugin.h (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/clients/kpasswd/ksetpwd.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/clients/kpasswd/kpasswd.c (.../branches/krb5-1-6) (Revision 19164) @@ -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/kvno/kvno.c =================================================================== --- src/clients/kvno/kvno.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/clients/kvno/kvno.c (.../branches/krb5-1-6) (Revision 19164) @@ -41,10 +41,10 @@ { #ifdef KRB5_KRB4_COMPAT fprintf(stderr, - "usage: %s [-4 | [-c ccache] [-e etype]] service1 service2 ...\n", + "usage: %s [-4 | [-c ccache] [-e etype] [-k keytab]] service1 service2 ...\n", prog); #else - fprintf(stderr, "usage: %s [-c ccache] [-e etype] service1 service2 ...\n", + fprintf(stderr, "usage: %s [-c ccache] [-e etype] [-k keytab] service1 service2 ...\n", prog); #endif exit(1); @@ -54,7 +54,7 @@ static void do_v4_kvno (int argc, char *argv[]); static void do_v5_kvno (int argc, char *argv[], - char *ccachestr, char *etypestr); + char *ccachestr, char *etypestr, char *keytab_name); #include static void extended_com_err_fn (const char *, errcode_t, const char *, @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { int option; - char *etypestr = 0, *ccachestr = 0; + char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL; int v4 = 0; set_com_err_hook (extended_com_err_fn); @@ -71,7 +71,7 @@ prog = strrchr(argv[0], '/'); prog = prog ? (prog + 1) : argv[0]; - while ((option = getopt(argc, argv, "c:e:hq4")) != -1) { + while ((option = getopt(argc, argv, "c:e:hk:q4")) != -1) { switch (option) { case 'c': ccachestr = optarg; @@ -82,6 +82,9 @@ case 'h': xusage(); break; + case 'k': + keytab_name = optarg; + break; case 'q': quiet = 1; break; @@ -97,13 +100,13 @@ if ((argc - optind) < 1) xusage(); - if ((ccachestr != 0 || etypestr != 0) && v4) + if ((ccachestr != NULL || etypestr != NULL || keytab_name != NULL) && v4) xusage(); if (v4) do_v4_kvno(argc - optind, argv + optind); else - do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr); + do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name); return 0; } @@ -169,7 +172,7 @@ } static void do_v5_kvno (int count, char *names[], - char * ccachestr, char *etypestr) + char * ccachestr, char *etypestr, char *keytab_name) { krb5_error_code ret; int i, errors; @@ -179,6 +182,7 @@ krb5_creds in_creds, *out_creds; krb5_ticket *ticket; char *princ; + krb5_keytab keytab = NULL; ret = krb5_init_context(&context); if (ret) { @@ -205,6 +209,14 @@ exit(1); } + if (keytab_name) { + ret = krb5_kt_resolve(context, keytab_name, &keytab); + if (ret) { + com_err(prog, ret, "resolving keytab %s", keytab_name); + exit(1); + } + } + ret = krb5_cc_get_principal(context, ccache, &me); if (ret) { com_err(prog, ret, "while getting client principal name"); @@ -261,14 +273,32 @@ continue; } - if (!quiet) - printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno); + if (keytab) { + ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket); + if (ret) { + if (!quiet) + printf("%s: kvno = %d, keytab entry invalid", princ, ticket->enc_part.kvno); + com_err(prog, ret, "while decrypting ticket for %s", princ); + krb5_free_ticket(context, ticket); + krb5_free_creds(context, out_creds); + krb5_free_unparsed_name(context, princ); - krb5_free_ticket(context, ticket); + errors++; + continue; + } + if (!quiet) + printf("%s: kvno = %d, keytab entry valid\n", princ, ticket->enc_part.kvno); + } else { + if (!quiet) + printf("%s: kvno = %d\n", princ, ticket->enc_part.kvno); + } + krb5_free_creds(context, out_creds); krb5_free_unparsed_name(context, princ); } + if (keytab) + krb5_kt_close(context, keytab); krb5_free_principal(context, me); krb5_cc_close(context, ccache); krb5_free_context(context); Index: src/clients/kinit/kinit.c =================================================================== --- src/clients/kinit/kinit.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/clients/kinit/kinit.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/lib/gssapi/krb5/k5sealv3.c (.../branches/krb5-1-6) (Revision 19164) @@ -412,10 +412,16 @@ if (load_16_be(althdr) != 0x0504 || althdr[2] != ptr[2] || althdr[3] != ptr[3] - || memcmp(althdr+8, ptr+8, 8)) + || memcmp(althdr+8, ptr+8, 8)) { + free(plain.data); goto defective; + } message_buffer->value = plain.data; message_buffer->length = plain.length - ec - 16; + if(message_buffer->length == 0) { + free(message_buffer->value); + message_buffer->value = NULL; + } } else { /* no confidentiality */ if (conf_state) Index: src/lib/krb5/keytab/kt_file.c =================================================================== --- src/lib/krb5/keytab/kt_file.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/keytab/kt_file.c (.../branches/krb5-1-6) (Revision 19164) @@ -193,6 +193,7 @@ err = k5_mutex_init(&data->lock); if (err) { + krb5_xfree(data); krb5_xfree(*id); return err; } @@ -791,6 +792,7 @@ err = k5_mutex_init(&data->lock); if (err) { + krb5_xfree(data); krb5_xfree(*id); return err; } Index: src/lib/krb5/os/sendto_kdc.c =================================================================== --- src/lib/krb5/os/sendto_kdc.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/os/sendto_kdc.c (.../branches/krb5-1-6) (Revision 19164) @@ -1127,7 +1127,7 @@ return ENOMEM; } - memset(conns, 0, n_conns * sizeof(conns[i])); + memset(conns, 0, n_conns * sizeof(struct conn_state)); if (callback_info) { callback_data = malloc(n_conns * sizeof(krb5_data)); @@ -1135,7 +1135,7 @@ return ENOMEM; } - memset(conns, 0, n_conns * sizeof(callback_data[i])); + memset(callback_data, 0, n_conns * sizeof(krb5_data)); } 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 19164) +++ src/lib/krb5/os/changepw.c (.../branches/krb5-1-6) (Revision 19164) @@ -70,12 +70,14 @@ locate_service_kadmin, SOCK_STREAM, 0); if (!code) { /* Success with admin_server but now we need to change the - port number to use DEFAULT_KPASSWD_PORT. */ + port number to use DEFAULT_KPASSWD_PORT and the socktype. */ int i; for (i=0; inaddrs; i++) { struct addrinfo *a = addrlist->addrs[i].ai; if (a->ai_family == AF_INET) sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT); + if (sockType != SOCK_STREAM) + a->ai_socktype = sockType; } } } Index: src/lib/krb5/ccache/ccapi/stdcc.c =================================================================== --- src/lib/krb5/ccache/ccapi/stdcc.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/ccache/ccapi/stdcc.c (.../branches/krb5-1-6) (Revision 19164) @@ -56,6 +56,7 @@ #ifdef USE_CCAPI_V3 cc_context_t gCntrlBlock = NULL; +cc_int32 gCCVersion = 0; #else apiCB *gCntrlBlock = NULL; #endif @@ -222,13 +223,59 @@ #ifdef USE_CCAPI_V3 + +static krb5_error_code stdccv3_get_timeoffset (krb5_context in_context, + cc_ccache_t in_ccache) +{ + krb5_error_code err = 0; + + if (gCCVersion >= ccapi_version_5) { + krb5_os_context os_ctx = (krb5_os_context) in_context->os_context; + cc_time_t time_offset = 0; + + err = cc_ccache_get_kdc_time_offset (in_ccache, cc_credentials_v5, + &time_offset); + + if (!err) { + os_ctx->time_offset = time_offset; + os_ctx->usec_offset = 0; + os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | + KRB5_OS_TOFFSET_VALID); + } + + if (err == ccErrTimeOffsetNotSet) { + err = 0; /* okay if there is no time offset */ + } + } + + return err; /* Don't translate. Callers will translate for us */ +} + +static krb5_error_code stdccv3_set_timeoffset (krb5_context in_context, + cc_ccache_t in_ccache) +{ + krb5_error_code err = 0; + + if (gCCVersion >= ccapi_version_5) { + krb5_os_context os_ctx = (krb5_os_context) in_context->os_context; + + if (!err && os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { + err = cc_ccache_set_kdc_time_offset (in_ccache, + cc_credentials_v5, + os_ctx->time_offset); + } + } + + return err; /* Don't translate. Callers will translate for us */ +} + static krb5_error_code stdccv3_setup (krb5_context context, stdccCacheDataPtr ccapi_data) { krb5_error_code err = 0; if (!err && !gCntrlBlock) { - err = cc_initialize (&gCntrlBlock, ccapi_version_max, NULL, NULL); + err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL); } if (!err && ccapi_data && !ccapi_data->NamedCache) { @@ -237,6 +284,10 @@ &ccapi_data->NamedCache); } + if (!err && ccapi_data && ccapi_data->NamedCache) { + err = stdccv3_get_timeoffset (context, ccapi_data->NamedCache); + } + return err; /* Don't translate. Callers will translate for us */ } @@ -245,6 +296,7 @@ { if (gCntrlBlock) { cc_context_release(gCntrlBlock); } gCntrlBlock = NULL; + gCCVersion = 0; } /* @@ -278,11 +330,15 @@ } if (!err) { - err = cc_context_create_new_ccache (gCntrlBlock, cc_credentials_v5, 0L, + err = cc_context_create_new_ccache (gCntrlBlock, cc_credentials_v5, "", &ccache); } if (!err) { + err = stdccv3_set_timeoffset (context, ccache); + } + + if (!err) { err = cc_ccache_get_name (ccache, &ccstring); } @@ -395,6 +451,7 @@ krb5_error_code err = 0; stdccCacheDataPtr ccapi_data = id->data; char *name = NULL; + cc_ccache_t ccache = NULL; if (id == NULL) { err = KRB5_CC_NOMEM; } @@ -406,23 +463,28 @@ err = krb5_unparse_name(context, princ, &name); } - if (!err && ccapi_data->NamedCache) { - err = cc_ccache_release(ccapi_data->NamedCache); - ccapi_data->NamedCache = NULL; - } - if (!err) { err = cc_context_create_ccache (gCntrlBlock, ccapi_data->cache_name, cc_credentials_v5, name, - &ccapi_data->NamedCache); + &ccache); } if (!err) { - cache_changed(); + err = stdccv3_set_timeoffset (context, ccache); } - if (name) { krb5_free_unparsed_name(context, name); } + if (!err) { + if (ccapi_data->NamedCache) { + err = cc_ccache_release (ccapi_data->NamedCache); + } + ccapi_data->NamedCache = ccache; + ccache = NULL; /* take ownership */ + cache_changed (); + } + if (ccache) { cc_ccache_release (ccache); } + if (name ) { krb5_free_unparsed_name(context, name); } + return cc_err_xlate(err); } Index: src/lib/krb5/libkrb5.exports =================================================================== --- src/lib/krb5/libkrb5.exports (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/libkrb5.exports (.../branches/krb5-1-6) (Revision 19164) @@ -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 @@ -614,6 +619,7 @@ krb5_ser_unpack_bytes krb5_ser_unpack_int32 krb5_ser_unpack_int64 +krb5_server_decrypt_ticket_keytab krb5_set_config_files krb5_set_debugging_time krb5_set_default_in_tkt_ktypes Index: src/lib/krb5/krb/gic_keytab.c =================================================================== --- src/lib/krb5/krb/gic_keytab.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/krb/gic_keytab.c (.../branches/krb5-1-6) (Revision 19164) @@ -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/Makefile.in =================================================================== --- src/lib/krb5/krb/Makefile.in (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/krb/Makefile.in (.../branches/krb5-1-6) (Revision 19164) @@ -89,6 +89,7 @@ ser_princ.o \ serialize.o \ set_realm.o \ + srv_dec_tkt.o \ srv_rcache.o \ str_conv.o \ tgtname.o \ @@ -175,6 +176,7 @@ $(OUTPRE)ser_princ.$(OBJEXT) \ $(OUTPRE)serialize.$(OBJEXT) \ $(OUTPRE)set_realm.$(OBJEXT) \ + $(OUTPRE)srv_dec_tkt.$(OBJEXT) \ $(OUTPRE)srv_rcache.$(OBJEXT) \ $(OUTPRE)str_conv.$(OBJEXT) \ $(OUTPRE)tgtname.$(OBJEXT) \ @@ -262,6 +264,7 @@ $(srcdir)/ser_princ.c \ $(srcdir)/serialize.c \ $(srcdir)/set_realm.c \ + $(srcdir)/srv_dec_tkt.c \ $(srcdir)/srv_rcache.c \ $(srcdir)/str_conv.c \ $(srcdir)/tgtname.c \ @@ -1041,6 +1044,15 @@ $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ set_realm.c +srv_dec_tkt.so srv_dec_tkt.po $(OUTPRE)srv_dec_tkt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + srv_dec_tkt.c srv_rcache.so srv_rcache.po $(OUTPRE)srv_rcache.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ Index: src/lib/krb5/krb/srv_dec_tkt.c =================================================================== --- src/lib/krb5/krb/srv_dec_tkt.c (.../tags/krb5-1-6-final) (Revision 0) +++ src/lib/krb5/krb/srv_dec_tkt.c (.../branches/krb5-1-6) (Revision 19164) @@ -0,0 +1,94 @@ +/* + * lib/krb5/krb/srv_dec_tkt.c + * + * Copyright 2006 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Server decrypt ticket via keytab or keyblock. + * + * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c) + * - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error. + * - No replay cache processing. + * - No skew checking or KRB5KRB_AP_ERR_SKEW error. + * - No address checking or KRB5KRB_AP_ERR_BADADDR error. + * - No time validation. + * - No permitted enctype validation or KRB5_NOPERM_ETYPE error. + * - Does not free ticket->enc_part2 on error. + */ + +#include + +krb5_error_code KRB5_CALLCONV +krb5int_server_decrypt_ticket_keyblock(krb5_context context, + const krb5_keyblock *key, + krb5_ticket *ticket) +{ + krb5_error_code retval; + krb5_data *realm; + krb5_transited *trans; + + retval = krb5_decrypt_tkt_part(context, key, ticket); + if (retval) + goto done; + + trans = &ticket->enc_part2->transited; + realm = &ticket->enc_part2->client->realm; + if (trans->tr_contents.data && *trans->tr_contents.data) { + retval = krb5_check_transited_list(context, &trans->tr_contents, + realm, &ticket->server->realm); + goto done; + } + + if (ticket->enc_part2->flags & TKT_FLG_INVALID) { /* ie, KDC_OPT_POSTDATED */ + retval = KRB5KRB_AP_ERR_TKT_INVALID; + goto done; + } + + done: + return retval; +} + + +krb5_error_code KRB5_CALLCONV +krb5_server_decrypt_ticket_keytab(krb5_context context, + const krb5_keytab kt, + krb5_ticket *ticket) +{ + krb5_error_code retval; + krb5_enctype enctype; + krb5_keytab_entry ktent; + + enctype = ticket->enc_part.enctype; + + if ((retval = krb5_kt_get_entry(context, kt, ticket->server, + ticket->enc_part.kvno, + enctype, &ktent))) + return retval; + + retval = krb5int_server_decrypt_ticket_keyblock(context, + &ktent.key, ticket); + /* Upon error, Free keytab entry first, then return */ + + (void) krb5_kt_free_entry(context, &ktent); + return retval; +} Index: src/lib/krb5/krb/gic_opt.c =================================================================== --- src/lib/krb5/krb/gic_opt.c (.../tags/krb5-1-6-final) (Revision 19164) +++ src/lib/krb5/krb/gic_opt.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/lib/krb5/krb/get_in_tkt.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/lib/krb5/krb/preauth2.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/lib/krb5/krb/gic_pwd.c (.../branches/krb5-1-6) (Revision 19164) @@ -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 19164) +++ src/lib/krb5_32.def (.../branches/krb5-1-6) (Revision 19164) @@ -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 @@ -219,6 +224,7 @@ krb5_recvauth_version krb5_salttype_to_string krb5_sendauth + krb5_server_decrypt_ticket_keytab krb5_set_default_realm krb5_set_default_tgs_enctypes krb5_set_password Index: src/util/def-check.pl =================================================================== --- src/util/def-check.pl (.../tags/krb5-1-6-final) (Revision 19164) +++ src/util/def-check.pl (.../branches/krb5-1-6) (Revision 19164) @@ -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: . ___________________________________________________________________ Name: svk:merge - 122d7f7f-0217-0410-a6d0-d37b9a318acc:/local/krb5/branches/krb5-1-6:19331 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:19480 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