diff options
Diffstat (limited to 'src/lib/krb5/krb')
39 files changed, 1501 insertions, 375 deletions
diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog index 59d8765..470ee9c 100644 --- a/src/lib/krb5/krb/ChangeLog +++ b/src/lib/krb5/krb/ChangeLog @@ -1,3 +1,287 @@ +2002-10-30 Tom Yu <tlyu@mit.edu> + + * chk_trans.c (krb5_check_transited_list): Style nit: check + character against '\0' not NULL. + [pullup from trunk] + +2002-10-30 Sam Hartman <hartmans@mit.edu> + + * chk_trans.c: Ignore trailing null in transited encoding; older + versions of MIT code included this. + [pullup from trunk] + +2002-08-12 Tom Yu <tlyu@mit.edu> + + * unparse.c (krb5_unparse_name_ext): Error out if passed a NULL + pointer. Patch from Mark Levinson; fixes [krb5-admin/1140]. + [pullup from trunk] + +2002-04-05 Danilo Almeida <dalmeida@mit.edu> + + * princ_comp.c (krb5_realm_compare), auth_con.c + (krb5_auth_con_setports, krb5_auth_con_getaddrs, + krb5_auth_con_initivector), addr_order.c (krb5_address_order), + addr_comp.c (krb5_address_compare): Make KRB5_CALLCONV. + +2002-04-03 Danilo Almeida <dalmeida@mit.edu> + + * bld_princ.c (krb5_build_principal_va): Make + krb5_build_principal_va() KRB5_CALLCONV. + +2002-04-02 Sam Hartman <hartmans@mit.edu> + + * init_keyblock.c: Merge from mainline + +2002-03-15 Sam Hartman <hartmans@mit.edu> + + * walk_rtree.c (krb5_walk_realm_tree): Fix handling of null realms + +2002-03-14 Alexandra Ellwood <lxs@mit.edu> + * appdefault.c, get_in_tkt.c: made conf_yes and conf_no const to + improve load time on Mach-O + +2002-03-13 Sam Hartman <hartmans@mit.edu> + + * rd_cred.c (krb5_rd_cred): Don't check IP addresses; improves + Heimdal compatibility. + +2002-02-28 Alexandra Ellwood <lxs@mit.edu> + * conv_princ.c: removed unused variable cpp to reduce warnings + * get_creds.c: removed unused variables fields and mcreds to + reduce warnings + * get_in_tkt.c: removed unused variables cpp and preauth_to_use + to reduce warnings + * init_ctx: fixed Mac OS macros + * parse.c: added type in to avoid "defaults to int" warning + * send_tgs.c: removed unused variable enclen + +2001-12-20 Ken Raeburn <raeburn@mit.edu> + + * ser_actx.c (krb5_auth_context_externalize): Pass address of a + size_t, not a krb5_int32, to krb5_c_block_size. + +2001-11-29 Ken Raeburn <raeburn@mit.edu> + + * fwd_tgt.c (krb5_fwd_tgt_creds): If no session key has been set, + try getting credentials and use the session key type as a hint + for the enctype to use for the forwarded credentials. + + 2001-11-24 Sam Hartman <hartmans@mit.edu> + + * fwd_tgt.c (krb5_fwd_tgt_creds): Get a session key for the + forwarded tgt that is the same as the session key for the + auth_context. This is an enctype we know the remote side + supports. + +2001-10-29 Miro Jurisic <meeroh@mit.edu> + * pullup from krb5-1-2 branch after krb5-1-2-2-bp + * rd_safe.c, rd_priv.c, rd_cred.c, preauth.c, mk_safe.c, + mk_cred.c, appdefault.c: use "" includes for krb5.h, k5-int.h and + syslog.h + * gic_pwd.c, sendauth.c, recvauth.c: com_err.h is already included by + k5-int.h. Removed #include because it was confusing the Mac OS X builds + +2001-09-25 Ken Raeburn <raeburn@mit.edu> + + * chk_trans.c: Reimplemented from scratch. + +2001-01-30 Tom Yu <tlyu@mit.edu> + + * preauth.c (krb5_obtain_padata): Don't dereference a NULL pointer + if we receive an empty ETYPE_INFO preauth. [krb5-libs/903 from + craziboy77@hotmail.com] + + * preauth2.c (krb5_do_preauth): Don't dereference a NULL pointer + if we receive an empty ETYPE_INFO preauth. [krb5-libs/903 from + craziboy77@hotmail.com] + +2001-01-30 Ezra Peisach <epeisach@mit.edu> + + * rd_req_dec.c (krb5_rd_req_decrypt_tkt_part): Free + krb5_keytab_entry if call to krb5_decrypt_tkt_part() + fails. [krb5-libs/855 reported by guy@packeteer.com] + +2001-01-30 Ken Raeburn <raeburn@mit.edu> + + * mk_safe.c (krb5_mk_safe): Only use safe_cksumtype from the + auth_context (derived from the config file or hardcoded default) + if it's suitable for the enctype of the key we're going to use. + +2001-01-29 Alexandra Ellwood <lxs@mit.edu> + + * conv_princ.c (krb5_524_conv_principal): Fixed strncmp bug where principals + which are left substrings of "changepw" were being remapped into "changepw". + Added length check to if() statement. + +2001-01-29 Ken Raeburn <raeburn@mit.edu> + + * preauth2.c (pa_sam): Check for a null prompter function pointer, + and return an error for that case rather than crashing. + +2000-10-02 Alexandra Ellwood <lxs@mit.edu> + + * init_ctx.c: Added #defines for Mac OS X (__MACH__) + +2000-06-29 Tom Yu <tlyu@mit.edu> + + * conv_princ.c (krb5_425_conv_principal): NULL, not nil. + +2000-06-28 Miro Jurisic <meeroh@mit.edu> + + * conv_princ.c (krb5_425_conv_principal): Fixed a memory leak + +2000-06-17 Miro Jurisic <meeroh@mit.edu> + + * conv_princ.c (krb5_425_conv_principal): Fixed v4->v5 realm + name conversion + +2000-06-17 Miro Jurisic <meeroh@mit.edu> + + * conv_princ.c (krb5_425_conv_principal): Honor v4/v5 realm name + differences when convertion from v4 principals to v5. + +2000-06-07 Tom Yu <tlyu@mit.edu> + + * get_creds.c (krb5_get_credentials): Translate KRB5_CC_NOTFOUND + returned from krb5_get_cred_from_kdc() if a prior call to + krb5_cc_retrieve_cred() returned KRB5_CC_NOT_KTYPE. + +2000-06-03 Tom Yu <tlyu@mit.edu> + + * rd_priv.c (krb5_rd_priv_basic): Delete code that was incorrectly + doing explicit ivec chaining; c_decrypt() does it now. + + * mk_priv.c (krb5_mk_priv_basic): Delete code that was incorrectly + doing explicit ivec chaining; c_encrypt() does it now. + +2000-06-03 Ken Raeburn <raeburn@mit.edu> + + * get_in_tkt.c (krb5_get_in_tkt): If enctypes are specified, send + the server the intersection of that list and the supported types, + in the order requested. + +2000-06-02 Danilo Almeida <dalmeida@mit.edu> + + * init_ctx.c (krb5_get_tgs_ktypes, krb5_free_ktypes): Fix linkage to + be KRB5_CALLCONV. + +2000-05-31 Ken Raeburn <raeburn@mit.edu> + + * recvauth.c (krb5_recvauth_version): New routine, takes a + krb5_data in which to store the client's application version + string. + (recvauth_common): Renamed from krb5_recvauth, added above + functionality depending on extra argument values. + (krb5_recvauth): New stub, calls above routine with extra dummy + values. + +2000-5-19 Alexandra Ellwood <lxs@mit.edu> + + * sendauth.c, fwd_tgt.c: Changed to use krb5int_cc_default. This function + supports the Kerberos Login Library and pops up a dialog if the cache does + not contain valid tickets. This is used to automatically get a tgt before + obtaining service tickets. Note that this should be an internal function + because callers don't expect krb5_cc_default to pop up a dialog! + (We found this out the hard way :-) + +2000-05-16 Ken Raeburn <raeburn@mit.edu> + Nalin Dahyabhai <nalin@redhat.com> + + * conv_princ.c (krb5_524_conv_principal): Return an error if name + is too long. Use memcpy for character data since we already know + the length. + +2000-05-16 Ken Raeburn <raeburn@mit.edu> + + * kfree.c: Remove unneeded "return" statements at the end of many + functions. + (krb5_free_*_content, krb5_free_*_contents, + krb5_free_cred_enc_part, krb5_free_pwd_sequences): Set freed + pointer members to null when containing structure isn't being + freed. + +2000-05-16 Tom Yu <tlyu@mit.edu> + + * conv_princ.c (krb5_524_conv_principal): Make a copy of the krb5 + realm that is nul-terminated to avoid falling off the end of the + krb5 realm, which is not necessarily nul-terminated. + +2000-05-16 Nalin Dahyabhai <nalin@redhat.com> + + * kfree.c (krb5_free_keyblock_contents): Set contents pointer to + null after freeing. + +2000-05-15 Jeffrey Altman <jaltman@columbia.edu> + + * Added new source file appdefault.c + Implements new public functions + + krb5_appdefault_string + krb5_appdefault_boolean + +2000-05-12 Ken Raeburn <raeburn@mit.edu> + + * t_kerb.c (test_524_conv_principal): New test code, to exercise + yesterday's code addition. + (main, usage): Updated. + * t_krb5.conf: Added stanford.edu->IR.STANFORD.EDU mapping, and a + test case for improperly long v4 realm names. + * Makefile.in (check-unix): Run 524 conversion test for some test + Athena and Stanford names. + * t_ref_kerb.out: Updated. + + * init_ctx.c (init_common): Feed current-microsecond time and + process-id into PRNG, instead of just current-second time. + * mk_req_ext.c (krb5_mk_req_extended): Feed current time into + PRNG if a subkey will be generated. + * sendauth.c (krb5_sendauth): Feed local and remote addresses of + socket, if they can be determined, into the PRNG if a subkey will + be used. + +2000-05-11 Ken Raeburn <raeburn@mit.edu> + Booker C. Bense <bbense@networking.stanford.edu> + + * conv_princ.c (krb5_524_conv_principal): Look up v4_realm in + config file, in case site's krb4 realm name isn't the same as the + krb5 realm name. + +2000-04-28 Nalin Dahyabhai <nalin@redhat.com> + + * chk_trans.c (krb5_check_transited_list): Don't overflow buffers + "prev" and "next". + * conv_princ.c (krb5_425_conv_principal): Don't overflow buffer + "buf". + +2000-04-28 Alexandra Ellwood <lxs@mit.edu> + + * gic_pwd.c (krb5_init_creds_password) added code to return to + login library if the password is expired (login library handles + this error appropriately). + +2000-04-18 Ken Raeburn <raeburn@mit.edu> + + * init_ctx.c (krb5_free_ktypes): New routine, to free values + returned by krb5_get_tgs_ktypes, krb5_get_permitted_enctypes, and + krb5_get_default_in_tkt_ktypes. + (krb5_set_default_tgs_ktypes, krb5_is_permitted_enctype): Use it. + (get_profile_etype_list): Use passed-in enctype list if the + passed-in count is non-zero, instead of checking the + in_tkt_ktype_count value in the context. + +2000-04-08 Tom Yu <tlyu@mit.edu> + + * vfy_increds.c (krb5_verify_init_creds): appdefault_boolean -> + libdefault_boolean; it somehow got missed earlier. + +2000-04-07 Jeffrey Altman <jaltman@columbia.edu> + + * gic_pwd.c (krb5_get_init_creds_keytab), gic_pwd.c + (krb5_get_init_creds_password) when determining whether or not to + retry with a "master kdc" do not retry if the return value from + the first attempt was KRB5_REALM_CANT_RESOLV. Also, do not + overwrite the return code if the return value from the access to + the "master kdc" was KRB5_REALM_CANT_RESOLV. + 2000-03-15 Danilo Almeida <dalmeida@mit.edu> * init_ctx.c (init_common), gic_pwd.c (krb5_get_as_key_password, diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index ba76662..484cd39 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -15,6 +15,7 @@ STLIBOBJS= \ addr_comp.o \ addr_order.o \ addr_srch.o \ + appdefault.o \ auth_con.o \ bld_pr_ext.o \ bld_princ.o \ @@ -52,6 +53,7 @@ STLIBOBJS= \ in_tkt_pwd.o \ in_tkt_sky.o \ init_ctx.o \ + init_keyblock.o \ kdc_rep_dc.o \ kfree.o \ mk_cred.o \ @@ -99,6 +101,7 @@ STLIBOBJS= \ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ $(OUTPRE)addr_order.$(OBJEXT) \ $(OUTPRE)addr_srch.$(OBJEXT) \ + $(OUTPRE)appdefault.$(OBJEXT) \ $(OUTPRE)auth_con.$(OBJEXT) \ $(OUTPRE)bld_pr_ext.$(OBJEXT) \ $(OUTPRE)bld_princ.$(OBJEXT) \ @@ -136,6 +139,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ $(OUTPRE)in_tkt_pwd.$(OBJEXT) \ $(OUTPRE)in_tkt_sky.$(OBJEXT) \ $(OUTPRE)init_ctx.$(OBJEXT) \ + $(OUTPRE)init_keyblock.$(OBJEXT) \ $(OUTPRE)kdc_rep_dc.$(OBJEXT) \ $(OUTPRE)kfree.$(OBJEXT) \ $(OUTPRE)mk_cred.$(OBJEXT) \ @@ -183,6 +187,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/addr_order.c \ $(srcdir)/addr_srch.c \ + $(srcdir)/appdefault.c \ $(srcdir)/auth_con.c \ $(srcdir)/bld_pr_ext.c \ $(srcdir)/bld_princ.c \ @@ -221,6 +226,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/in_tkt_pwd.c \ $(srcdir)/in_tkt_sky.c \ $(srcdir)/init_ctx.c \ + $(srcdir)/init_keyblock.c \ $(srcdir)/kdc_rep_dc.c \ $(srcdir)/kfree.c \ $(srcdir)/mk_cred.c \ @@ -324,6 +330,8 @@ check-unix:: $(TEST_PROGS) 425_conv_principal rcmd uunet UU.NET \ 425_conv_principal zephyr zephyr ATHENA.MIT.EDU \ 425_conv_principal kadmin ATHENA.MIT.EDU ATHENA.MIT.EDU \ + 524_conv_principal host/e40-po.mit.edu@ATHENA.MIT.EDU \ + 524_conv_principal host/foobar.stanford.edu@stanford.edu \ set_realm marc@MIT.EDU CYGNUS.COM \ > test.out cmp test.out $(srcdir)/t_ref_kerb.out diff --git a/src/lib/krb5/krb/addr_comp.c b/src/lib/krb5/krb/addr_comp.c index 587bd5f..f9e10bb 100644 --- a/src/lib/krb5/krb/addr_comp.c +++ b/src/lib/krb5/krb/addr_comp.c @@ -32,7 +32,7 @@ /* * If the two addresses are the same, return TRUE, else return FALSE */ -krb5_boolean +krb5_boolean KRB5_CALLCONV krb5_address_compare(context, addr1, addr2) krb5_context context; krb5_const krb5_address *addr1; diff --git a/src/lib/krb5/krb/addr_order.c b/src/lib/krb5/krb/addr_order.c index 800fa2b..2598205 100644 --- a/src/lib/krb5/krb/addr_order.c +++ b/src/lib/krb5/krb/addr_order.c @@ -37,7 +37,7 @@ * Return an ordering on two addresses: 0 if the same, * < 0 if first is less than 2nd, > 0 if first is greater than 2nd. */ -int +int KRB5_CALLCONV krb5_address_order(context, addr1, addr2) krb5_context context; register krb5_const krb5_address *addr1; diff --git a/src/lib/krb5/krb/appdefault.c b/src/lib/krb5/krb/appdefault.c new file mode 100644 index 0000000..65a9459 --- /dev/null +++ b/src/lib/krb5/krb/appdefault.c @@ -0,0 +1,183 @@ +/* + * appdefault - routines designed to be called from applications to + * handle the [appdefaults] profile section + */ + +#include <stdio.h> +#include <string.h> +#include "k5-int.h" + + + + /*xxx Duplicating this is annoying; try to work on a better way.*/ +static const char *conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +static int conf_boolean(s) + char *s; +{ + char **p; + for(p=conf_yes; *p; p++) { + if (!strcasecmp(*p,s)) + return 1; + } + for(p=conf_no; *p; p++) { + if (!strcasecmp(*p,s)) + return 0; + } + /* Default to "no" */ + return 0; +} + +static krb5_error_code appdefault_get(context, appname, realm, option, + ret_value) + krb5_context context; + const char *appname, *option; + const krb5_data *realm; + char **ret_value; +{ + profile_t profile; + const char *names[5]; + char **nameval = NULL; + krb5_error_code retval; + const char * realmstr = realm?realm->data:NULL; + + if (!context || (context->magic != KV5M_CONTEXT)) + return KV5M_CONTEXT; + + profile = context->profile; + + /* + * Try number one: + * + * [appdefaults] + * app = { + * SOME.REALM = { + * option = <boolean> + * } + * } + */ + + names[0] = "appdefaults"; + names[1] = appname; + + if (realmstr) { + names[2] = realmstr; + names[3] = option; + names[4] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + goto goodbye; + } + } + + /* + * Try number two: + * + * [appdefaults] + * app = { + * option = <boolean> + * } + */ + + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + goto goodbye; + } + + /* + * Try number three: + * + * [appdefaults] + * realm = { + * option = <boolean> + */ + + if (realmstr) { + names[1] = realmstr; + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + goto goodbye; + } + } + + /* + * Try number four: + * + * [appdefaults] + * option = <boolean> + */ + + names[1] = option; + names[2] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + } else { + return retval; + } + +goodbye: + if (nameval) { + char **cpp; + for (cpp = nameval; *cpp; cpp++) + free(*cpp); + free(nameval); + } + return 0; +} + +KRB5_DLLIMP void KRB5_CALLCONV +krb5_appdefault_boolean(context, appname, realm, option, + default_value, ret_value) + krb5_context context; + const char *appname, *option; + const krb5_data *realm; + int default_value; + int *ret_value; +{ + char *string = NULL; + krb5_error_code retval; + + retval = appdefault_get(context, appname, realm, option, &string); + + if (! retval && string) { + *ret_value = conf_boolean(string); + free(string); + } else + *ret_value = default_value; +} + +KRB5_DLLIMP void KRB5_CALLCONV +krb5_appdefault_string(context, appname, realm, option, default_value, + ret_value) + krb5_context context; + const char *appname, *option, *default_value; + char **ret_value; + const krb5_data *realm; + { + krb5_error_code retval; + char *string; + + retval = appdefault_get(context, appname, realm, option, &string); + + if (! retval && string) { + *ret_value = string; + } else { + *ret_value = strdup(default_value); + } +} diff --git a/src/lib/krb5/krb/auth_con.c b/src/lib/krb5/krb/auth_con.c index 335f7ae..f80a167 100644 --- a/src/lib/krb5/krb/auth_con.c +++ b/src/lib/krb5/krb/auth_con.c @@ -109,7 +109,7 @@ krb5_auth_con_setaddrs(context, auth_context, local_addr, remote_addr) return retval; } -krb5_error_code +krb5_error_code KRB5_CALLCONV krb5_auth_con_getaddrs(context, auth_context, local_addr, remote_addr) krb5_context context; krb5_auth_context auth_context; @@ -132,7 +132,7 @@ krb5_auth_con_getaddrs(context, auth_context, local_addr, remote_addr) return retval; } -krb5_error_code +krb5_error_code KRB5_CALLCONV krb5_auth_con_setports(context, auth_context, local_port, remote_port) krb5_context context; krb5_auth_context auth_context; @@ -270,7 +270,7 @@ krb5_auth_con_getremoteseqnumber(context, auth_context, seqnumber) return 0; } -krb5_error_code +krb5_error_code KRB5_CALLCONV krb5_auth_con_initivector(context, auth_context) krb5_context context; krb5_auth_context auth_context; diff --git a/src/lib/krb5/krb/bld_princ.c b/src/lib/krb5/krb/bld_princ.c index bf49105..34b50c0 100644 --- a/src/lib/krb5/krb/bld_princ.c +++ b/src/lib/krb5/krb/bld_princ.c @@ -37,6 +37,7 @@ #endif krb5_error_code +KRB5_CALLCONV krb5_build_principal_va(context, princ, rlen, realm, ap) krb5_context context; krb5_principal princ; diff --git a/src/lib/krb5/krb/chk_trans.c b/src/lib/krb5/krb/chk_trans.c index c2ac716..9fe73c8 100644 --- a/src/lib/krb5/krb/chk_trans.c +++ b/src/lib/krb5/krb/chk_trans.c @@ -1,12 +1,14 @@ /* - * Copyright (c) 1994 CyberSAFE Corporation. - * All rights reserved. + * lib/krb5/krb/chk_trans.c + * + * Copyright 2001 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 @@ -14,97 +16,426 @@ * 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. Neither M.I.T., the Open Computing Security Group, nor - * CyberSAFE Corporation make any representations about the suitability of + * 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. + * + * + * krb5_check_transited_list() */ - #include "k5-int.h" -#include <stdio.h> +#include <stdarg.h> -#define MAX_REALM_LN 500 +#if defined (TEST) || defined (TEST2) +# undef DEBUG +# define DEBUG +#endif -krb5_error_code -krb5_check_transited_list(context, trans, realm1, realm2) - krb5_context context; -krb5_data *trans; -krb5_data *realm1; -krb5_data *realm2; +#ifdef DEBUG +#define verbose krb5int_chk_trans_verbose +static int verbose = 0; +# define Tprintf(ARGS) if (verbose) printf ARGS +#else +# define Tprintf(ARGS) (void)(0) +#endif + +#define MAXLEN 512 + +static krb5_error_code +process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data, + const krb5_data *n1, const krb5_data *n2) { + unsigned int len1, len2, i; + char *p1, *p2; + + Tprintf (("process_intermediates(%.*s,%.*s)\n", + (int) n1->length, n1->data, (int) n2->length, n2->data)); + + len1 = n1->length; + len2 = n2->length; + + Tprintf (("(walking intermediates now)\n")); + /* Simplify... */ + if (len1 > len2) { + const krb5_data *p; + int tmp = len1; + len1 = len2; + len2 = tmp; + p = n1; + n1 = n2; + n2 = p; + } + /* Okay, now len1 is always shorter or equal. */ + if (len1 == len2) { + if (memcmp (n1->data, n2->data, len1)) { + Tprintf (("equal length but different strings in path: '%.*s' '%.*s'\n", + (int) n1->length, n1->data, (int) n2->length, n2->data)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + Tprintf (("(end intermediates)\n")); + return 0; + } + /* Now len1 is always shorter. */ + if (len1 == 0) + /* Shouldn't be possible. Internal error? */ + return KRB5KRB_AP_ERR_ILL_CR_TKT; + p1 = n1->data; + p2 = n2->data; + if (p1[0] == '/') { + /* X.500 style names, with common prefix. */ + if (p2[0] != '/') { + Tprintf (("mixed name formats in path: x500='%.*s' domain='%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + if (memcmp (p1, p2, len1)) { + Tprintf (("x500 names with different prefixes '%.*s' '%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + for (i = len1 + 1; i < len2; i++) + if (p2[i] == '/') { + krb5_data d; + krb5_error_code r; + + d.data = p2; + d.length = i; + r = (*fn) (&d, data); + if (r) + return r; + } + } else { + /* Domain style names, with common suffix. */ + if (p2[0] == '/') { + Tprintf (("mixed name formats in path: domain='%.*s' x500='%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + if (memcmp (p1, p2 + (len2 - len1), len1)) { + Tprintf (("domain names with different suffixes '%.*s' '%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + for (i = len2 - len1 - 1; i > 0; i--) { + Tprintf (("looking at '%.*s'\n", (int) (len2 - i), p2+i)); + if (p2[i-1] == '.') { + krb5_data d; + krb5_error_code r; + + d.data = p2+i; + d.length = len2 - i; + r = (*fn) (&d, data); + if (r) + return r; + } + } + } + Tprintf (("(end intermediates)\n")); + return 0; +} + +static krb5_error_code +maybe_join (krb5_data *last, krb5_data *buf, int bufsiz) +{ + if (buf->length == 0) + return 0; + if (buf->data[0] == '/') { + if (last->length + buf->length > bufsiz) { + Tprintf (("too big: last=%d cur=%d max=%d\n", last->length, buf->length, bufsiz)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + memmove (buf->data+last->length, buf->data, buf->length); + memcpy (buf->data, last->data, last->length); + buf->length += last->length; + } else if (buf->data[buf->length-1] == '.') { + /* We can ignore the case where the previous component was + empty; the strcat will be a no-op. It should probably + be an error case, but let's be flexible. */ + if (last->length+buf->length > bufsiz) { + Tprintf (("too big\n")); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + memcpy (buf->data + buf->length, last->data, last->length); + buf->length += last->length; + } + /* Otherwise, do nothing. */ + return 0; +} + +/* The input strings cannot contain any \0 bytes, according to the + spec, but our API is such that they may not be \0 terminated + either. Thus we keep on treating them as krb5_data objects instead + of C strings. */ +static krb5_error_code +foreach_realm (krb5_error_code (*fn)(krb5_data *comp,void *data), void *data, + const krb5_data *crealm, const krb5_data *srealm, + const krb5_data *transit) +{ + char buf[MAXLEN], last[MAXLEN]; + char *p, *bufp; + int next_lit, intermediates, l; + krb5_data this_component; + krb5_error_code r; + krb5_data last_component; + + /* Invariants: + - last_component points to last[] + - this_component points to buf[] + - last_component has length of last + - this_component has length of buf when calling out + Keep these consistent, and we should be okay. */ + + next_lit = 0; + intermediates = 0; + memset (buf, 0, sizeof (buf)); + + this_component.data = buf; + last_component.data = last; + last_component.length = 0; + +#define print_data(fmt,d) Tprintf((fmt,(int)(d)->length,(d)->data)) + print_data ("client realm: %.*s\n", crealm); + print_data ("server realm: %.*s\n", srealm); + print_data ("transit enc.: %.*s\n", transit); + + if (transit->length == 0) { + Tprintf (("no other realms transited\n")); + return 0; + } + + bufp = buf; + for (p = transit->data, l = transit->length; l; p++, l--) { + if (next_lit) { + *bufp++ = *p; + if (bufp == buf+sizeof(buf)) + return KRB5KRB_AP_ERR_ILL_CR_TKT; + next_lit = 0; + } else if (*p == '\\') { + next_lit = 1; + } else if (*p == ',') { + if (bufp != buf) { + this_component.length = bufp - buf; + r = maybe_join (&last_component, &this_component, sizeof(buf)); + if (r) + return r; + r = (*fn) (&this_component, data); + if (r) + return r; + if (intermediates) { + if (p == transit->data) + r = process_intermediates (fn, data, + &this_component, crealm); + else { + r = process_intermediates (fn, data, &this_component, + &last_component); + } + if (r) + return r; + } + intermediates = 0; + memcpy (last, buf, sizeof (buf)); + last_component.length = this_component.length; + memset (buf, 0, sizeof (buf)); + bufp = buf; + } else { + intermediates = 1; + if (p == transit->data) { + if (crealm->length >= MAXLEN) + return KRB5KRB_AP_ERR_ILL_CR_TKT; + memcpy (last, crealm->data, crealm->length); + last[crealm->length] = '\0'; + last_component.length = crealm->length; + } + } + } else if (*p == ' ' && bufp == buf) { + /* This next component stands alone, even if it has a + trailing dot or leading slash. */ + memset (last, 0, sizeof (last)); + last_component.length = 0; + } else { + /* Not a special character; literal. */ + *bufp++ = *p; + if (bufp == buf+sizeof(buf)) + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + } + /* At end. Must be normal state. */ + if (next_lit) + Tprintf (("ending in next-char-literal state\n")); + /* Process trailing element or comma. */ + if (bufp == buf) { + /* Trailing comma. */ + r = process_intermediates (fn, data, &last_component, srealm); + } else { + /* Trailing component. */ + this_component.length = bufp - buf; + r = maybe_join (&last_component, &this_component, sizeof(buf)); + if (r) + return r; + r = (*fn) (&this_component, data); + if (r) + return r; + if (intermediates) + r = process_intermediates (fn, data, &this_component, + &last_component); + } + if (r != 0) + return r; + return 0; +} + + +struct check_data { + krb5_context ctx; + krb5_principal *tgs; +}; + +static int +same_data (krb5_data *d1, krb5_data *d2) { - char prev[MAX_REALM_LN+1]; - char next[MAX_REALM_LN+1]; - char *nextp; - int i, j; - int trans_length; - krb5_error_code retval = 0; - krb5_principal *tgs_list; - - if (trans == NULL || trans->data == NULL || trans->length == 0) - return(0); - trans_length = trans->data[trans->length-1] ? - trans->length : trans->length - 1; - - for (i = 0; i < trans_length; i++) - if (trans->data[i] == '\0') { - /* Realms may not contain ASCII NUL character. */ - return(KRB5KRB_AP_ERR_ILL_CR_TKT); + return (d1->length == d2->length + && !memcmp (d1->data, d2->data, d1->length)); +} + +static krb5_error_code +check_realm_in_list (krb5_data *realm, void *data) +{ + struct check_data *cdata = data; + int i; + + Tprintf ((".. checking '%.*s'\n", (int) realm->length, realm->data)); + for (i = 0; cdata->tgs[i]; i++) { + if (same_data (krb5_princ_realm (cdata->ctx, cdata->tgs[i]), realm)) + return 0; } + Tprintf (("BAD!\n")); + return KRB5KRB_AP_ERR_ILL_CR_TKT; +} + +krb5_error_code +krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in, + const krb5_data *crealm, const krb5_data *srealm) +{ + krb5_data trans; + struct check_data cdata; + krb5_error_code r; - if ((retval = krb5_walk_realm_tree(context, realm1, realm2, &tgs_list, - KRB5_REALM_BRANCH_CHAR))) { - return(retval); - } - - memset(prev, 0, MAX_REALM_LN + 1); - memset(next, 0, MAX_REALM_LN + 1), nextp = next; - for (i = 0; i < trans_length; i++) { - if (i < trans_length-1 && trans->data[i] == '\\') { - i++; - *nextp++ = trans->data[i]; - if (nextp - next > MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto finish; - } - continue; + trans.length = trans_in->length; + trans.data = (char *) trans_in->data; + if (trans.length && (trans.data[trans.length-1] == '\0')) + trans.length--; + + Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n", + (int) trans.length, trans.data, + (int) crealm->length, crealm->data, + (int) srealm->length, srealm->data)); + if (trans.length == 0) + return 0; + r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs, + KRB5_REALM_BRANCH_CHAR); + if (r) { + Tprintf (("error %ld\n", (long) r)); + return r; + } +#ifdef DEBUG /* avoid compiler warning about 'd' unused */ + { + int i; + Tprintf (("tgs list = {\n")); + for (i = 0; cdata.tgs[i]; i++) { + char *name; + r = krb5_unparse_name (ctx, cdata.tgs[i], &name); + Tprintf (("\t'%s'\n", name)); + free (name); + } + Tprintf (("}\n")); } - if (i < trans_length && trans->data[i] != ',') { - *nextp++ = trans->data[i]; - if (nextp - next > MAX_REALM_LN) { - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - goto finish; - } - continue; +#endif + cdata.ctx = ctx; + r = foreach_realm (check_realm_in_list, &cdata, crealm, srealm, &trans); + krb5_free_realm_tree (ctx, cdata.tgs); + return r; +} + +#ifdef TEST + +static krb5_error_code +print_a_realm (krb5_data *realm, void *data) +{ + printf ("%.*s\n", (int) realm->length, realm->data); + return 0; +} + +int main (int argc, char *argv[]) { + const char *me; + krb5_data crealm, srealm, transit; + krb5_error_code r; + int expand_only = 0; + + me = strrchr (argv[0], '/'); + me = me ? me+1 : argv[0]; + + while (argc > 3 && argv[1][0] == '-') { + if (!strcmp ("-v", argv[1])) + verbose++, argc--, argv++; + else if (!strcmp ("-x", argv[1])) + expand_only++, argc--, argv++; + else + goto usage; } - if (strlen(next) > 0) { - if (next[0] != '/') { - if (*(nextp-1) == '.' && strlen(next) + strlen(prev) <= MAX_REALM_LN) - strcat(next, prev); - retval = KRB5KRB_AP_ERR_ILL_CR_TKT; - for (j = 0; tgs_list[j]; j++) { - if (strlen(next) == (size_t) krb5_princ_realm(context, tgs_list[j])->length && - !memcmp(next, krb5_princ_realm(context, tgs_list[j])->data, - strlen(next))) { - retval = 0; - break; - } - } - if (retval) goto finish; - } - if (i+1 < trans_length && trans->data[i+1] == ' ') { - i++; - memset(next, 0, MAX_REALM_LN + 1), nextp = next; - continue; - } - if (i+1 < trans_length && trans->data[i+1] != '/') { - strcpy(prev, next); - memset(next, 0, MAX_REALM_LN + 1), nextp = next; - continue; - } + + if (argc != 4) { + usage: + printf ("usage: %s [-v] [-x] clientRealm serverRealm transitEncoding\n", + me); + return 1; } - } -finish: - krb5_free_realm_tree(context, tgs_list); - return(retval); + crealm.data = argv[1]; + crealm.length = strlen(argv[1]); + srealm.data = argv[2]; + srealm.length = strlen(argv[2]); + transit.data = argv[3]; + transit.length = strlen(argv[3]); + + if (expand_only) { + + printf ("client realm: %s\n", argv[1]); + printf ("server realm: %s\n", argv[2]); + printf ("transit enc.: %s\n", argv[3]); + + if (argv[3][0] == 0) { + printf ("no other realms transited\n"); + return 0; + } + + r = foreach_realm (print_a_realm, NULL, &crealm, &srealm, &transit); + if (r) + printf ("--> returned error %ld\n", (long) r); + return r != 0; + + } else { + + /* Actually check the values against the supplied krb5.conf file. */ + krb5_context ctx; + r = krb5_init_context (&ctx); + if (r) { + com_err (me, r, "initializing krb5 context"); + return 1; + } + r = krb5_check_transited_list (ctx, &transit, &crealm, &srealm); + if (r == KRB5KRB_AP_ERR_ILL_CR_TKT) { + printf ("NO\n"); + } else if (r == 0) { + printf ("YES\n"); + } else { + printf ("kablooey!\n"); + com_err (me, r, "checking transited-realm list"); + return 1; + } + return 0; + } } + +#endif /* TEST */ diff --git a/src/lib/krb5/krb/conv_princ.c b/src/lib/krb5/krb/conv_princ.c index b90289a..e7aab77 100644 --- a/src/lib/krb5/krb/conv_princ.c +++ b/src/lib/krb5/krb/conv_princ.c @@ -137,7 +137,8 @@ krb5_524_conv_principal(context, princ, name, inst, realm) { const struct krb_convert *p; krb5_data *compo; - char *c; + char *c, *tmp_realm, *tmp_prealm; + int tmp_realm_len, retval; *name = *inst = '\0'; switch (krb5_princ_size(context, princ)) { @@ -146,19 +147,24 @@ krb5_524_conv_principal(context, princ, name, inst, realm) compo = krb5_princ_component(context, princ, 0); p = sconv_list; while (p->v4_str) { - if (strncmp(p->v5_str, compo->data, compo->length) == 0) { - /* It is, so set the new name now, and chop off */ - /* instance's domain name if requested */ - strcpy(name, p->v4_str); - if (p->flags & DO_REALM_CONVERSION) { - compo = krb5_princ_component(context, princ, 1); - c = strnchr(compo->data, '.', compo->length); - if (!c || (c - compo->data) > INST_SZ - 1) - return KRB5_INVALID_PRINCIPAL; - strncpy(inst, compo->data, c - compo->data); - inst[c - compo->data] = '\0'; - } - break; + if (strncmp(p->v5_str, compo->data, compo->length) == 0 && + strlen(p->v5_str) == compo->length) { + /* + * It is, so set the new name now, and chop off + * instance's domain name if requested. + */ + if (strlen (p->v4_str) > ANAME_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strcpy(name, p->v4_str); + if (p->flags & DO_REALM_CONVERSION) { + compo = krb5_princ_component(context, princ, 1); + c = strnchr(compo->data, '.', compo->length); + if (!c || (c - compo->data) >= INST_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + memcpy(inst, compo->data, c - compo->data); + inst[c - compo->data] = '\0'; + } + break; } p++; } @@ -168,7 +174,7 @@ krb5_524_conv_principal(context, princ, name, inst, realm) compo = krb5_princ_component(context, princ, 1); if (compo->length >= INST_SZ - 1) return KRB5_INVALID_PRINCIPAL; - strncpy(inst, compo->data, compo->length); + memcpy(inst, compo->data, compo->length); inst[compo->length] = '\0'; } /* fall through */ @@ -178,7 +184,7 @@ krb5_524_conv_principal(context, princ, name, inst, realm) compo = krb5_princ_component(context, princ, 0); if (compo->length >= ANAME_SZ) return KRB5_INVALID_PRINCIPAL; - strncpy(name, compo->data, compo->length); + memcpy(name, compo->data, compo->length); name[compo->length] = '\0'; } break; @@ -187,11 +193,39 @@ krb5_524_conv_principal(context, princ, name, inst, realm) } compo = krb5_princ_realm(context, princ); - if (compo->length > REALM_SZ - 1) - return KRB5_INVALID_PRINCIPAL; - strncpy(realm, compo->data, compo->length); - realm[compo->length] = '\0'; + tmp_prealm = malloc(compo->length + 1); + if (tmp_prealm == NULL) + return ENOMEM; + strncpy(tmp_prealm, compo->data, compo->length); + tmp_prealm[compo->length] = '\0'; + + /* Ask for v4_realm corresponding to + krb5 principal realm from krb5.conf realms stanza */ + + if (context->profile == 0) + return KRB5_CONFIG_CANTOPEN; + retval = profile_get_string(context->profile, "realms", + tmp_prealm, "v4_realm", 0, + &tmp_realm); + free(tmp_prealm); + if (retval) { + return retval; + } else { + if (tmp_realm == 0) { + if (compo->length > REALM_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strncpy(realm, compo->data, compo->length); + realm[compo->length] = '\0'; + } else { + tmp_realm_len = strlen(tmp_realm); + if (tmp_realm_len > REALM_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strncpy(realm, tmp_realm, tmp_realm_len); + realm[tmp_realm_len] = '\0'; + profile_release_string(tmp_realm); + } + } return 0; } @@ -207,8 +241,47 @@ krb5_425_conv_principal(context, name, instance, realm, princ) char buf[256]; /* V4 instances are limited to 40 characters */ krb5_error_code retval; char *domain, *cp; - char **full_name = 0, **cpp; + char **full_name = 0; const char *names[5]; + void* iterator = NULL; + char** v4realms = NULL; + char* realm_name = NULL; + char* dummy_value = NULL; + + /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm + To do that, iterate over all the realms in the config file, looking for a matching + v4_realm line */ + names [0] = "realms"; + names [1] = NULL; + retval = profile_iterator_create (context -> profile, names, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator); + while (retval == 0) { + retval = profile_iterator (&iterator, &realm_name, &dummy_value); + if ((retval == 0) && (realm_name != NULL)) { + names [0] = "realms"; + names [1] = realm_name; + names [2] = "v4_realm"; + names [3] = NULL; + + retval = profile_get_values (context -> profile, names, &v4realms); + if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) { + realm = realm_name; + break; + } else if (retval == PROF_NO_RELATION) { + /* If it's not found, just keep going */ + retval = 0; + } + } else if ((retval == 0) && (realm_name == NULL)) { + break; + } + if (realm_name != NULL) { + profile_release_string (realm_name); + realm_name = NULL; + } + if (dummy_value != NULL) { + profile_release_string (dummy_value); + dummy_value = NULL; + } + } if (instance) { if (instance[0] == '\0') { @@ -234,7 +307,8 @@ krb5_425_conv_principal(context, name, instance, realm, princ) if (retval == 0 && full_name && full_name[0]) { instance = full_name[0]; } else { - strcpy(buf, instance); + strncpy(buf, instance, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; retval = krb5_get_realm_domain(context, realm, &domain); if (retval) return retval; @@ -242,8 +316,8 @@ krb5_425_conv_principal(context, name, instance, realm, princ) for (cp = domain; *cp; cp++) if (isupper(*cp)) *cp = tolower(*cp); - strcat(buf, "."); - strcat(buf, domain); + strncat(buf, ".", sizeof(buf) - 1 - strlen(buf)); + strncat(buf, domain, sizeof(buf) - 1 - strlen(buf)); krb5_xfree(domain); } instance = buf; @@ -254,6 +328,10 @@ krb5_425_conv_principal(context, name, instance, realm, princ) not_service: retval = krb5_build_principal(context, princ, strlen(realm), realm, name, instance, 0); + profile_iterator_free (&iterator); profile_free_list(full_name); + profile_free_list(v4realms); + profile_release_string (realm_name); + profile_release_string (dummy_value); return retval; } diff --git a/src/lib/krb5/krb/fwd_tgt.c b/src/lib/krb5/krb/fwd_tgt.c index 814195a..2e2c5db 100644 --- a/src/lib/krb5/krb/fwd_tgt.c +++ b/src/lib/krb5/krb/fwd_tgt.c @@ -53,6 +53,8 @@ krb5_fwd_tgt_creds(context, auth_context, rhost, client, server, cc, krb5_flags kdcoptions; int close_cc = 0; int free_rhost = 0; + krb5_enctype enctype = 0; + krb5_keyblock *session_key; memset((char *)&creds, 0, sizeof(creds)); memset((char *)&tgt, 0, sizeof(creds)); @@ -71,7 +73,36 @@ krb5_fwd_tgt_creds(context, auth_context, rhost, client, server, cc, memcpy(rhost, server->data[1].data, server->data[1].length); rhost[server->data[1].length] = '\0'; } - + retval = krb5_auth_con_getkey (context, auth_context, &session_key); + if (retval) + goto errout; + if (session_key) { + enctype = session_key->enctype; + krb5_free_keyblock (context, session_key); + session_key = NULL; + } else if (server) { /* must server be non-NULL when rhost is given? */ + /* Try getting credentials to see what the remote side supports. + Not bulletproof, just a heuristic. */ + krb5_creds in, *out = 0; + memset (&in, 0, sizeof(in)); + + retval = krb5_copy_principal (context, server, &in.server); + if (retval) + goto punt; + retval = krb5_copy_principal (context, client, &in.client); + if (retval) + goto punt; + retval = krb5_get_credentials (context, 0, cc, &in, &out); + if (retval) + goto punt; + /* Got the credentials. Okay, now record the enctype and + throw them away. */ + enctype = out->keyblock.enctype; + krb5_free_creds (context, out); + punt: + krb5_free_cred_contents (context, &in); + } + retval = krb5_os_hostaddr(context, rhost, &addrs); if (retval) goto errout; @@ -90,7 +121,7 @@ krb5_fwd_tgt_creds(context, auth_context, rhost, client, server, cc, goto errout; if (cc == 0) { - if ((retval = krb5_cc_default(context, &cc))) + if ((retval = krb5int_cc_default(context, &cc))) goto errout; close_cc = 1; } @@ -111,7 +142,8 @@ krb5_fwd_tgt_creds(context, auth_context, rhost, client, server, cc, retval = KRB5_NO_TKT_SUPPLIED; goto errout; } - + + creds.keyblock.enctype = enctype; creds.times = tgt.times; creds.times.starttime = 0; kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED; diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c index 3bcaa0b..de8d29f 100644 --- a/src/lib/krb5/krb/get_creds.c +++ b/src/lib/krb5/krb/get_creds.c @@ -102,6 +102,7 @@ krb5_get_credentials(context, options, ccache, in_creds, out_creds) krb5_creds *ncreds; krb5_creds **tgts; krb5_flags fields; + int not_ktype; retval = krb5_get_credentials_core(context, options, ccache, in_creds, out_creds, @@ -128,6 +129,11 @@ krb5_get_credentials(context, options, ccache, in_creds, out_creds) || options & KRB5_GC_CACHED) return retval; + if (retval == KRB5_CC_NOT_KTYPE) + not_ktype = 1; + else + not_ktype = 0; + retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts); if (tgts) { register int i = 0; @@ -141,6 +147,21 @@ krb5_get_credentials(context, options, ccache, in_creds, out_creds) } krb5_free_tgt_creds(context, tgts); } + /* + * Translate KRB5_CC_NOTFOUND if we previously got + * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to + * handle the case where there is no TGT in the ccache and the + * input enctype didn't match. This handling is necessary because + * some callers, such as GSSAPI, iterate through enctypes and + * KRB5_CC_NOTFOUND passed through from the + * krb5_get_cred_from_kdc() is semantically incorrect, since the + * actual failure was the non-existence of a ticket of the correct + * enctype rather than the missing TGT. + */ + if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE) + && not_ktype) + retval = KRB5_CC_NOT_KTYPE; + if (!retval) retval = krb5_cc_store_cred(context, ccache, *out_creds); return retval; @@ -160,10 +181,8 @@ krb5_get_credentials_val_renew_core(context, options, ccache, int which; { krb5_error_code retval; - krb5_creds mcreds; krb5_principal tmp; krb5_creds **tgts = 0; - krb5_flags fields; switch(which) { case INT_GC_VALIDATE: diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index c1c6df1..57d0313 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -84,13 +84,13 @@ static krb5_error_code make_preauth_list PROTOTYPE((krb5_context, */ static krb5_error_code send_as_request(context, request, time_now, ret_err_reply, ret_as_reply, - master) + use_master) krb5_context context; krb5_kdc_req *request; krb5_timestamp *time_now; krb5_error ** ret_err_reply; krb5_kdc_rep ** ret_as_reply; - int * master; + int use_master; { krb5_kdc_rep *as_reply = 0; krb5_error_code retval; @@ -116,7 +116,7 @@ send_as_request(context, request, time_now, ret_err_reply, ret_as_reply, k4_version = packet->data[0]; retval = krb5_sendto_kdc(context, packet, krb5_princ_realm(context, request->client), - &reply, master); + &reply, use_master); krb5_free_data(context, packet); if (retval) goto cleanup; @@ -367,7 +367,6 @@ make_preauth_list(context, ptypes, nptypes, ret_list) { krb5_preauthtype * ptypep; krb5_pa_data ** preauthp; - krb5_pa_data ** preauth_to_use; int i; if (nptypes < 0) { @@ -457,12 +456,35 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed, request.from = creds->times.starttime; request.till = creds->times.endtime; request.rtime = creds->times.renew_till; - if (ktypes) - request.ktype = ktypes; - else - if ((retval = krb5_get_default_in_tkt_ktypes(context, &request.ktype))) - goto cleanup; + if ((retval = krb5_get_default_in_tkt_ktypes(context, &request.ktype))) + goto cleanup; for (request.nktypes = 0;request.ktype[request.nktypes];request.nktypes++); + if (ktypes) { + int i, req, next = 0; + for (req = 0; ktypes[req]; req++) { + if (ktypes[req] == request.ktype[next]) { + next++; + continue; + } + for (i = next + 1; i < request.nktypes; i++) + if (ktypes[req] == request.ktype[i]) { + /* Found the enctype we want, but not in the + position we want. Move it, but keep the old + one from the desired slot around in case it's + later in our requested-ktypes list. */ + krb5_enctype t; + t = request.ktype[next]; + request.ktype[next] = request.ktype[i]; + request.ktype[i] = t; + next++; + break; + } + /* If we didn't find it, don't do anything special, just + drop it. */ + } + request.ktype[next] = 0; + request.nktypes = next; + } request.authorization_data.ciphertext.length = 0; request.authorization_data.ciphertext.data = 0; request.unenc_authdata = 0; @@ -538,7 +560,7 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed, goto cleanup; cleanup: - if (!ktypes && request.ktype) + if (request.ktype) free(request.ktype); if (!addrs && request.addresses) krb5_free_addresses(context, request.addresses); @@ -559,17 +581,17 @@ cleanup: return (retval); } -/* begin appdefaults parsing code. This should almost certainly move +/* begin libdefaults parsing code. This should almost certainly move somewhere else, but I don't know where the correct somewhere else is yet. */ /* XXX Duplicating this is annoying; try to work on a better way.*/ -static char *conf_yes[] = { +static const char *conf_yes[] = { "y", "yes", "true", "t", "1", "on", 0, }; -static char *conf_no[] = { +static const char *conf_no[] = { "n", "no", "false", "nil", "0", "off", 0, }; @@ -595,7 +617,7 @@ _krb5_conf_boolean(s) } static krb5_error_code -krb5_appdefault_string(context, realm, option, ret_value) +krb5_libdefault_string(context, realm, option, ret_value) krb5_context context; const krb5_data *realm; const char *option; @@ -606,7 +628,6 @@ krb5_appdefault_string(context, realm, option, ret_value) char **nameval = NULL; krb5_error_code retval; char realmstr[1024]; - char **cpp; if (realm->length > sizeof(realmstr)-1) return(EINVAL); @@ -673,7 +694,7 @@ goodbye: /* as well as the DNS code */ krb5_error_code -krb5_appdefault_boolean(context, realm, option, ret_value) +krb5_libdefault_boolean(context, realm, option, ret_value) krb5_context context; const char *option; const krb5_data *realm; @@ -682,7 +703,7 @@ krb5_appdefault_boolean(context, realm, option, ret_value) char *string = NULL; krb5_error_code retval; - retval = krb5_appdefault_string(context, realm, option, &string); + retval = krb5_libdefault_string(context, realm, option, &string); if (retval) return(retval); @@ -696,7 +717,7 @@ krb5_appdefault_boolean(context, realm, option, ret_value) KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_get_init_creds(context, creds, client, prompter, prompter_data, start_time, in_tkt_service, options, gak_fct, gak_data, - master, as_reply) + use_master, as_reply) krb5_context context; krb5_creds *creds; krb5_principal client; @@ -707,7 +728,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data, krb5_get_init_creds_opt *options; krb5_gic_get_as_key_fct gak_fct; void *gak_data; - int *master; + int use_master; krb5_kdc_rep **as_reply; { krb5_error_code ret; @@ -751,7 +772,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data, if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)) tempint = options->forwardable; - else if ((ret = krb5_appdefault_boolean(context, &client->realm, + else if ((ret = krb5_libdefault_boolean(context, &client->realm, "forwardable", &tempint)) == 0) ; else @@ -763,7 +784,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data, if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)) tempint = options->proxiable; - else if ((ret = krb5_appdefault_boolean(context, &client->realm, + else if ((ret = krb5_libdefault_boolean(context, &client->realm, "proxiable", &tempint)) == 0) ; else @@ -775,7 +796,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data, if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)) { renew_life = options->renew_life; - } else if ((ret = krb5_appdefault_string(context, &client->realm, + } else if ((ret = krb5_libdefault_string(context, &client->realm, "renew_lifetime", &tempstr)) == 0) { if (ret = krb5_string_to_deltat(tempstr, &renew_life)) { @@ -868,7 +889,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data, } /* it would be nice if this parsed out an address list, but that would be work. */ - else if (((ret = krb5_appdefault_boolean(context, &client->realm, + else if (((ret = krb5_libdefault_boolean(context, &client->realm, "noaddresses", &tempint)) == 0) && tempint) { ; @@ -923,7 +944,7 @@ krb5_get_init_creds(context, creds, client, prompter, prompter_data, err_reply = 0; local_as_reply = 0; if ((ret = send_as_request(context, &request, &time_now, &err_reply, - &local_as_reply, master))) + &local_as_reply, use_master))) goto cleanup; if (err_reply) { diff --git a/src/lib/krb5/krb/gic_keytab.c b/src/lib/krb5/krb/gic_keytab.c index 8b6f231..98bbbd0 100644 --- a/src/lib/krb5/krb/gic_keytab.c +++ b/src/lib/krb5/krb/gic_keytab.c @@ -61,7 +61,7 @@ krb5_get_init_creds_keytab(context, creds, client, arg_keytab, krb5_get_init_creds_opt *options; { krb5_error_code ret, ret2; - int master; + int use_master; krb5_keytab keytab; if (arg_keytab == NULL) { @@ -71,14 +71,14 @@ krb5_get_init_creds_keytab(context, creds, client, arg_keytab, keytab = arg_keytab; } - master = 0; + 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, krb5_get_as_key_keytab, (void *) keytab, - &master, NULL); + use_master,NULL); /* check for success */ @@ -87,19 +87,19 @@ krb5_get_init_creds_keytab(context, creds, client, arg_keytab, /* If all the kdc's are unavailable fail */ - if (ret == KRB5_KDC_UNREACH) + if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE)) goto cleanup; /* if the reply did not come from the master kdc, try again with the master kdc */ - if (!master) { - master = 1; + if (!use_master) { + use_master = 1; ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL, start_time, in_tkt_service, options, krb5_get_as_key_keytab, (void *) keytab, - &master, NULL); + use_master, NULL); if (ret2 == 0) { ret = 0; @@ -109,7 +109,7 @@ krb5_get_init_creds_keytab(context, creds, client, arg_keytab, /* if the master is unreachable, return the error from the slave we were able to contact */ - if (ret2 == KRB5_KDC_UNREACH) + if ((ret2 == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE)) goto cleanup; ret = ret2; diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c index 7ca4343..f867989 100644 --- a/src/lib/krb5/krb/gic_pwd.c +++ b/src/lib/krb5/krb/gic_pwd.c @@ -1,5 +1,4 @@ #include "k5-int.h" -#include "com_err.h" static krb5_error_code krb5_get_as_key_password(context, client, etype, prompter, prompter_data, @@ -97,7 +96,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, krb5_get_init_creds_opt *options; { krb5_error_code ret, ret2; - int master; + int use_master; krb5_kdc_rep *as_reply; int tries; krb5_creds chpw_creds; @@ -107,7 +106,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, krb5_prompt prompt[2]; krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])]; - master = 0; + use_master = 0; as_reply = NULL; memset(&chpw_creds, 0, sizeof(chpw_creds)); @@ -133,7 +132,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, ret = krb5_get_init_creds(context, creds, client, prompter, data, start_time, in_tkt_service, options, krb5_get_as_key_password, (void *) &pw0, - &master, &as_reply); + use_master, &as_reply); /* check for success */ @@ -144,19 +143,20 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, user interrupt, fail */ if ((ret == KRB5_KDC_UNREACH) || - (ret == KRB5_LIBOS_PWDINTR)) + (ret == KRB5_LIBOS_PWDINTR) || + (ret == KRB5_REALM_CANT_RESOLVE)) goto cleanup; /* if the reply did not come from the master kdc, try again with the master kdc */ - if (!master) { - master = 1; + if (!use_master) { + use_master = 1; ret2 = krb5_get_init_creds(context, creds, client, prompter, data, start_time, in_tkt_service, options, krb5_get_as_key_password, (void *) &pw0, - &master, &as_reply); + use_master, &as_reply); if (ret2 == 0) { ret = 0; @@ -166,12 +166,18 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, /* if the master is unreachable, return the error from the slave we were able to contact */ - if (ret2 == KRB5_KDC_UNREACH) + if ((ret2 == KRB5_KDC_UNREACH) || + (ret2 == KRB5_REALM_CANT_RESOLVE)) goto cleanup; ret = ret2; } +#ifdef USE_LOGIN_LIBRARY + if (ret == KRB5KDC_ERR_KEY_EXP) + goto cleanup; /* Login library will deal appropriately with this error */ +#endif + /* at this point, we have an error from the master. if the error is not password expired, or if it is but there's no prompter, return this error */ @@ -195,7 +201,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, prompter, data, start_time, "kadmin/changepw", &chpw_opts, krb5_get_as_key_password, (void *) &pw0, - &master, NULL))) + use_master, NULL))) goto cleanup; prompt[0].prompt = "Enter new password"; @@ -282,7 +288,7 @@ krb5_get_init_creds_password(context, creds, client, password, prompter, data, ret = krb5_get_init_creds(context, creds, client, prompter, data, start_time, in_tkt_service, options, krb5_get_as_key_password, (void *) &pw0, - &master, &as_reply); + use_master, &as_reply); cleanup: krb5int_set_prompt_types(context, 0); diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index e2eccc4..abcb573 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -1,7 +1,7 @@ /* * lib/krb5/krb/init_ctx.c * - * Copyright 1994 by the Massachusetts Institute of Technology. + * Copyright 1994,1999,2000 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -84,7 +84,10 @@ init_common (context, secure) { krb5_context ctx = 0; krb5_error_code retval; - krb5_timestamp now; + struct { + krb5_int32 now, now_usec; + long pid; + } seed_data; krb5_data seed; int tmp; @@ -129,10 +132,11 @@ init_common (context, secure) goto cleanup; /* initialize the prng (not well, but passable) */ - if ((retval = krb5_timeofday(ctx, &now))) + if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec))) goto cleanup; - seed.length = sizeof(now); - seed.data = (char *) &now; + seed_data.pid = getpid (); + seed.length = sizeof(seed_data); + seed.data = (char *) &seed_data; if ((retval = krb5_c_random_seed(ctx, &seed))) goto cleanup; @@ -169,7 +173,7 @@ init_common (context, secure) "kdc_default_options", 0, KDC_OPT_RENEWABLE_OK, &tmp); ctx->kdc_default_options = KDC_OPT_RENEWABLE_OK; -#ifdef macintosh +#if TARGET_OS_MAC #define DEFAULT_KDC_TIMESYNC 1 #else #define DEFAULT_KDC_TIMESYNC 0 @@ -187,7 +191,7 @@ init_common (context, secure) * Note: DCE 1.0.3a only supports a cache type of 1 * DCE 1.1 supports a cache type of 2. */ -#ifdef macintosh +#if TARGET_OS_MAC #define DEFAULT_CCACHE_TYPE 4 #else #define DEFAULT_CCACHE_TYPE 3 @@ -281,7 +285,7 @@ get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list) { krb5_enctype *old_ktypes; - if (context->in_tkt_ktype_count) { + if (ctx_count) { /* application-set defaults */ if ((old_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * @@ -370,8 +374,8 @@ krb5_get_default_in_tkt_ktypes(context, ktypes) context->in_tkt_ktypes)); } -krb5_error_code -krb5_set_default_tgs_ktypes(context, ktypes) +krb5_error_code KRB5_CALLCONV +krb5_set_default_tgs_enctypes (context, ktypes) krb5_context context; const krb5_enctype *ktypes; { @@ -396,13 +400,30 @@ krb5_set_default_tgs_ktypes(context, ktypes) } if (context->tgs_ktypes) - free(context->tgs_ktypes); + krb5_free_ktypes(context, context->tgs_ktypes); context->tgs_ktypes = new_ktypes; context->tgs_ktype_count = i; return 0; } +krb5_error_code krb5_set_default_tgs_ktypes +(krb5_context context, const krb5_enctype *etypes) +{ + return (krb5_set_default_tgs_enctypes (context, etypes)); +} + + +void +KRB5_CALLCONV +krb5_free_ktypes (context, val) + krb5_context context; + krb5_enctype FAR *val; +{ + free (val); +} + krb5_error_code +KRB5_CALLCONV krb5_get_tgs_ktypes(context, princ, ktypes) krb5_context context; krb5_const_principal princ; @@ -441,7 +462,7 @@ krb5_is_permitted_enctype(context, etype) if (*ptr == etype) ret = 1; - krb5_xfree(list); + krb5_free_ktypes (context, list); return(ret); } diff --git a/src/lib/krb5/krb/init_keyblock.c b/src/lib/krb5/krb/init_keyblock.c new file mode 100644 index 0000000..eb60b06 --- /dev/null +++ b/src/lib/krb5/krb/init_keyblock.c @@ -0,0 +1,61 @@ +/* + * lib/krb5/krb/init_keyblock.c + * + * Copyright (C) 2002 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. + * + * + * + * krb5_init_keyblock- a function to set up + * an empty keyblock + */ + + +#include "k5-int.h" +#include <assert.h> + +krb5_error_code KRB5_CALLCONV +krb5_init_keyblock(krb5_context context, krb5_enctype enctype, + size_t length, krb5_keyblock **out) +{ + krb5_keyblock *kb; + kb = malloc (sizeof(krb5_keyblock)); + assert (out); + *out = NULL; + if (!kb) { + return ENOMEM; + } + kb->magic = KV5M_KEYBLOCK; + kb->enctype = enctype; + kb->length = length; + if(length) { + kb->contents = malloc (length); + if(!kb->contents) { + free (kb); + return ENOMEM; + } + } else { + kb->contents = NULL; + } + *out = kb; + return 0; +} diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index 24d8aaf..8e57f83 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -36,7 +36,6 @@ krb5_free_address(context, val) if (val->contents) krb5_xfree(val->contents); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -52,7 +51,6 @@ krb5_free_addresses(context, val) krb5_xfree(*temp); } krb5_xfree(val); - return; } @@ -64,7 +62,6 @@ krb5_free_ap_rep(context, val) if (val->enc_part.ciphertext.data) krb5_xfree(val->enc_part.ciphertext.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -77,7 +74,6 @@ krb5_free_ap_req(context, val) if (val->authenticator.ciphertext.data) krb5_xfree(val->authenticator.ciphertext.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -88,7 +84,6 @@ krb5_free_ap_rep_enc_part(context, val) if (val->subkey) krb5_free_keyblock(context, val->subkey); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -96,15 +91,22 @@ krb5_free_authenticator_contents(context, val) krb5_context context; krb5_authenticator FAR *val; { - if (val->checksum) + if (val->checksum) { krb5_free_checksum(context, val->checksum); - if (val->client) + val->checksum = 0; + } + if (val->client) { krb5_free_principal(context, val->client); - if (val->subkey) + val->client = 0; + } + if (val->subkey) { krb5_free_keyblock(context, val->subkey); - if (val->authorization_data) - krb5_free_authdata(context, val->authorization_data); - return; + val->subkey = 0; + } + if (val->authorization_data) { + krb5_free_authdata(context, val->authorization_data); + val->authorization_data = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -120,7 +122,6 @@ krb5_free_authdata(context, val) krb5_xfree(*temp); } krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -128,16 +129,8 @@ krb5_free_authenticator(context, val) krb5_context context; krb5_authenticator FAR *val; { - if (val->checksum) - krb5_free_checksum(context, val->checksum); - if (val->client) - krb5_free_principal(context, val->client); - if (val->subkey) - krb5_free_keyblock(context, val->subkey); - if (val->authorization_data) - krb5_free_authdata(context, val->authorization_data); + krb5_free_authenticator_contents(context, val); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -145,10 +138,8 @@ krb5_free_checksum(context, val) krb5_context context; register krb5_checksum *val; { - if (val->contents) - krb5_xfree(val->contents); + krb5_free_checksum_contents(context, val); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -156,9 +147,10 @@ krb5_free_checksum_contents(context, val) krb5_context context; register krb5_checksum *val; { - if (val->contents) + if (val->contents) { krb5_xfree(val->contents); - return; + val->contents = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -171,7 +163,6 @@ krb5_free_cred(context, val) if (val->enc_part.ciphertext.data) krb5_xfree(val->enc_part.ciphertext.data); krb5_xfree(val); - return; } /* @@ -184,23 +175,35 @@ krb5_free_cred_contents(context, val) krb5_context context; krb5_creds FAR *val; { - if (val->client) + if (val->client) { krb5_free_principal(context, val->client); - if (val->server) + val->client = 0; + } + if (val->server) { krb5_free_principal(context, val->server); + val->server = 0; + } if (val->keyblock.contents) { memset((char *)val->keyblock.contents, 0, val->keyblock.length); krb5_xfree(val->keyblock.contents); + val->keyblock.contents = 0; } - if (val->ticket.data) + if (val->ticket.data) { krb5_xfree(val->ticket.data); - if (val->second_ticket.data) + val->ticket.data = 0; + } + if (val->second_ticket.data) { krb5_xfree(val->second_ticket.data); - if (val->addresses) + val->second_ticket.data = 0; + } + if (val->addresses) { krb5_free_addresses(context, val->addresses); - if (val->authdata) + val->addresses = 0; + } + if (val->authdata) { krb5_free_authdata(context, val->authdata); - return; + val->authdata = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -210,10 +213,14 @@ krb5_free_cred_enc_part(context, val) { register krb5_cred_info **temp; - if (val->r_address) - krb5_free_address(context, val->r_address); - if (val->s_address) - krb5_free_address(context, val->s_address); + if (val->r_address) { + krb5_free_address(context, val->r_address); + val->r_address = 0; + } + if (val->s_address) { + krb5_free_address(context, val->s_address); + val->s_address = 0; + } if (val->ticket_info) { for (temp = val->ticket_info; *temp; temp++) { @@ -228,8 +235,8 @@ krb5_free_cred_enc_part(context, val) krb5_xfree((*temp)); } krb5_xfree(val->ticket_info); + val->ticket_info = 0; } - return; } @@ -240,7 +247,6 @@ krb5_free_creds(context, val) { krb5_free_cred_contents(context, val); krb5_xfree(val); - return; } @@ -252,7 +258,6 @@ krb5_free_data(context, val) if (val->data) krb5_xfree(val->data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -260,9 +265,10 @@ krb5_free_data_contents(context, val) krb5_context context; krb5_data FAR * val; { - if (val->data) + if (val->data) { krb5_xfree(val->data); - return; + val->data = 0; + } } void krb5_free_etype_info(context, info) @@ -294,7 +300,6 @@ krb5_free_enc_kdc_rep_part(context, val) if (val->caddrs) krb5_free_addresses(context, val->caddrs); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -313,7 +318,6 @@ krb5_free_enc_tkt_part(context, val) if (val->authorization_data) krb5_free_authdata(context, val->authorization_data); krb5_xfree(val); - return; } @@ -331,7 +335,6 @@ krb5_free_error(context, val) if (val->e_data.data) krb5_xfree(val->e_data.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -350,7 +353,6 @@ krb5_free_kdc_rep(context, val) if (val->enc_part2) krb5_free_enc_kdc_rep_part(context, val->enc_part2); krb5_xfree(val); - return; } @@ -376,7 +378,6 @@ krb5_free_kdc_req(context, val) if (val->second_ticket) krb5_free_tickets(context, val->second_ticket); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -387,8 +388,8 @@ krb5_free_keyblock_contents(context, key) if (key->contents) { memset(key->contents, 0, key->length); krb5_xfree(key->contents); + key->contents = 0; } - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -398,7 +399,6 @@ krb5_free_keyblock(context, val) { krb5_free_keyblock_contents(context, val); krb5_xfree(val); - return; } @@ -413,7 +413,6 @@ krb5_free_last_req(context, val) for (temp = val; *temp; temp++) krb5_xfree(*temp); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -429,7 +428,6 @@ krb5_free_pa_data(context, val) krb5_xfree(*temp); } krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -451,7 +449,6 @@ krb5_free_principal(context, val) if (val->realm.data) krb5_xfree(val->realm.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -462,7 +459,6 @@ krb5_free_priv(context, val) if (val->enc_part.ciphertext.data) krb5_xfree(val->enc_part.ciphertext.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -477,7 +473,6 @@ krb5_free_priv_enc_part(context, val) if (val->s_address) krb5_free_address(context, val->s_address); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -488,7 +483,6 @@ krb5_free_pwd_data(context, val) if (val->element) krb5_free_pwd_sequences(context, val->element); krb5_xfree(val); - return; } @@ -497,11 +491,14 @@ krb5_free_pwd_sequences(context, val) krb5_context context; passwd_phrase_element FAR * FAR *val; { - if ((*val)->passwd) + if ((*val)->passwd) { krb5_xfree((*val)->passwd); - if ((*val)->phrase) + (*val)->passwd = 0; + } + if ((*val)->phrase) { krb5_xfree((*val)->phrase); - return; + (*val)->phrase = 0; + } } @@ -519,7 +516,6 @@ krb5_free_safe(context, val) if (val->checksum) krb5_free_checksum(context, val->checksum); krb5_xfree(val); - return; } @@ -535,7 +531,6 @@ krb5_free_ticket(context, val) if (val->enc_part2) krb5_free_enc_tkt_part(context, val->enc_part2); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -548,7 +543,6 @@ krb5_free_tickets(context, val) for (temp = val; *temp; temp++) krb5_free_ticket(context, *temp); krb5_xfree(val); - return; } @@ -573,7 +567,6 @@ krb5_free_tkt_authent(context, val) if (val->authenticator) krb5_free_authenticator(context, val->authenticator); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -583,7 +576,6 @@ krb5_free_unparsed_name(context, val) { if (val) krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -612,8 +604,10 @@ krb5_free_sam_challenge_contents(krb5_context ctx, krb5_sam_challenge FAR *sc) krb5_free_data_contents(ctx, &sc->sam_response_prompt); if (sc->sam_pk_for_sad.data) krb5_free_data_contents(ctx, &sc->sam_pk_for_sad); - if (sc->sam_cksum.contents) + if (sc->sam_cksum.contents) { krb5_xfree(sc->sam_cksum.contents); + sc->sam_cksum.contents = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -656,8 +650,10 @@ krb5_free_predicted_sam_response_contents(krb5_context ctx, return; if (psr->sam_key.contents) krb5_free_keyblock_contents(ctx, &psr->sam_key); - if (psr->client) + if (psr->client) { krb5_free_principal(ctx, psr->client); + psr->client = 0; + } if (psr->msd.data) krb5_free_data_contents(ctx, &psr->msd); } @@ -689,4 +685,3 @@ krb5_free_pa_enc_ts(krb5_context ctx, krb5_pa_enc_ts FAR *pa_enc_ts) return; krb5_xfree(pa_enc_ts); } - diff --git a/src/lib/krb5/krb/mk_cred.c b/src/lib/krb5/krb/mk_cred.c index cdda80d..9bcfe84 100644 --- a/src/lib/krb5/krb/mk_cred.c +++ b/src/lib/krb5/krb/mk_cred.c @@ -7,7 +7,7 @@ * structures. * */ -#include <k5-int.h> +#include "k5-int.h" #include "cleanup.h" #include "auth_con.h" diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c index 7685817..d72f6b2 100644 --- a/src/lib/krb5/krb/mk_priv.c +++ b/src/lib/krb5/krb/mk_priv.c @@ -93,14 +93,6 @@ krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr, scratch1, &privmsg.enc_part))) goto clean_encpart; - /* put last block into the i_vector */ - - if (i_vector) - memcpy(i_vector, - privmsg.enc_part.ciphertext.data + - (privmsg.enc_part.ciphertext.length - blocksize), - blocksize); - if ((retval = encode_krb5_priv(&privmsg, &scratch2))) goto clean_encpart; diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index a8b20eb..88daab5 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -126,10 +126,24 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, /* generate subkey if needed */ - if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey)) + if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey)) { + /* Provide some more fodder for random number code. + This isn't strong cryptographically; the point here is not + to guarantee randomness, but to make it less likely that multiple + sessions could pick the same subkey. */ + struct { + krb5_int32 sec, usec; + } rnd_data; + krb5_data d; + krb5_crypto_us_timeofday (&rnd_data.sec, &rnd_data.usec); + d.length = sizeof (rnd_data); + d.data = (char *) &rnd_data; + (void) krb5_c_random_seed (context, &d); + if ((retval = krb5_generate_subkey(context, &(in_creds)->keyblock, &(*auth_context)->local_subkey))) goto cleanup; + } if (in_data) { if ((*auth_context)->req_cksumtype == 0x8003) { diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index 781e256..dd7d1ef 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -27,7 +27,7 @@ * krb5_mk_safe() */ -#include <k5-int.h> +#include "k5-int.h" #include "cleanup.h" #include "auth_con.h" @@ -169,6 +169,7 @@ krb5_mk_safe(context, auth_context, userdata, outbuf, outdata) krb5_address * plocal_fulladdr = NULL; krb5_address remote_fulladdr; krb5_address local_fulladdr; + krb5_cksumtype sumtype; CLEANUP_INIT(2); @@ -204,9 +205,33 @@ krb5_mk_safe(context, auth_context, userdata, outbuf, outdata) } } + { + unsigned int nsumtypes; + unsigned int i; + krb5_cksumtype *sumtypes; + retval = krb5_c_keyed_checksum_types (context, keyblock->enctype, + &nsumtypes, &sumtypes); + if (retval) { + CLEANUP_DONE (); + goto error; + } + if (nsumtypes == 0) { + retval = KRB5_BAD_ENCTYPE; + krb5_free_cksumtypes (context, sumtypes); + CLEANUP_DONE (); + goto error; + } + for (i = 0; i < nsumtypes; i++) + if (auth_context->safe_cksumtype == sumtypes[i]) + break; + if (i == nsumtypes) + i = 0; + sumtype = sumtypes[i]; + krb5_free_cksumtypes (context, sumtypes); + } if ((retval = krb5_mk_safe_basic(context, userdata, keyblock, &replaydata, plocal_fulladdr, premote_fulladdr, - auth_context->safe_cksumtype, outbuf))) { + sumtype, outbuf))) { CLEANUP_DONE(); goto error; } diff --git a/src/lib/krb5/krb/parse.c b/src/lib/krb5/krb/parse.c index b628a0d..3e18aba 100644 --- a/src/lib/krb5/krb/parse.c +++ b/src/lib/krb5/krb/parse.c @@ -71,7 +71,7 @@ krb5_parse_name(context, name, nprincipal) { register const char *cp; register char *q; - register i,c,size; + register int i,c,size; int components = 0; const char *parsed_realm = NULL; int fcompsize[FCOMPNUM]; diff --git a/src/lib/krb5/krb/preauth.c b/src/lib/krb5/krb/preauth.c index 9f301da..173170a 100644 --- a/src/lib/krb5/krb/preauth.c +++ b/src/lib/krb5/krb/preauth.c @@ -32,7 +32,6 @@ #include "k5-int.h" #include <stdio.h> #include <time.h> -#include <syslog.h> #ifdef _MSDOS #define getpid _getpid #include <process.h> @@ -172,6 +171,10 @@ krb5_error_code krb5_obtain_padata(context, preauth_to_use, key_proc, retval = decode_krb5_etype_info(&scratch, &etype_info); if (retval) return retval; + if (etype_info[0] == NULL) { + krb5_free_etype_info(context, etype_info); + etype_info = NULL; + } } } diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 5ea61c9..78afab9 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -256,6 +256,9 @@ krb5_error_code pa_sam(krb5_context context, krb5_data * scratch; krb5_pa_data * pa; + if (prompter == NULL) + return KRB5_LIBOS_CANTREADPWD; + tmpsam.length = in_padata->length; tmpsam.data = (char *) in_padata->contents; if (ret = decode_krb5_sam_challenge(&tmpsam, &sam_challenge)) @@ -530,6 +533,11 @@ krb5_do_preauth(krb5_context context, } return ret; } + if (etype_info[0] == NULL) { + krb5_free_etype_info(context, etype_info); + etype_info = NULL; + break; + } salt->data = (char *) etype_info[0]->salt; salt->length = etype_info[0]->length; *etype = etype_info[0]->etype; diff --git a/src/lib/krb5/krb/princ_comp.c b/src/lib/krb5/krb/princ_comp.c index cba26a6..dbcd29d 100644 --- a/src/lib/krb5/krb/princ_comp.c +++ b/src/lib/krb5/krb/princ_comp.c @@ -30,7 +30,7 @@ #include "k5-int.h" -krb5_boolean +krb5_boolean KRB5_CALLCONV krb5_realm_compare(context, princ1, princ2) krb5_context context; krb5_const_principal princ1; diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c index 86c5ccf..593eb42 100644 --- a/src/lib/krb5/krb/rd_cred.c +++ b/src/lib/krb5/krb/rd_cred.c @@ -1,4 +1,4 @@ -#include <k5-int.h> +#include "k5-int.h" #include "cleanup.h" #include "auth_con.h" @@ -55,24 +55,22 @@ cleanup: /*----------------------- krb5_rd_cred_basic -----------------------*/ static krb5_error_code -krb5_rd_cred_basic(context, pcreddata, pkeyblock, local_addr, remote_addr, +krb5_rd_cred_basic(context, pcreddata, pkeyblock, replaydata, pppcreds) krb5_context context; krb5_data * pcreddata; krb5_keyblock * pkeyblock; - krb5_address * local_addr; - krb5_address * remote_addr; krb5_replay_data * replaydata; krb5_creds *** pppcreds; { - krb5_error_code retval; - krb5_cred * pcred; + krb5_error_code retval; + krb5_cred * pcred; krb5_int32 ncreds; krb5_int32 i = 0; krb5_cred_enc_part encpart; /* decode cred message */ - if ((retval = decode_krb5_cred(pcreddata, &pcred))) + if ((retval = decode_krb5_cred(pcreddata, &pcred))) return retval; memset(&encpart, 0, sizeof(encpart)); @@ -80,38 +78,6 @@ krb5_rd_cred_basic(context, pcreddata, pkeyblock, local_addr, remote_addr, if ((retval = decrypt_credencdata(context, pcred, pkeyblock, &encpart))) goto cleanup_cred; - /* - * Only check the remote address if the KRB_CRED message was - * protected by encryption. If it came in the checksum field of - * an init_sec_context message, skip over this check. - */ - if (remote_addr && encpart.s_address && pkeyblock != NULL) { - if (!krb5_address_compare(context, remote_addr, encpart.s_address)) { - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup_cred; - } - } - - if (encpart.r_address) { - if (local_addr) { - if (!krb5_address_compare(context, local_addr, encpart.r_address)) { - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup_cred; - } - } else { - krb5_address **our_addrs; - - if ((retval = krb5_os_localaddr(context, &our_addrs))) { - goto cleanup_cred; - } - if (!krb5_address_search(context, encpart.r_address, our_addrs)) { - krb5_free_addresses(context, our_addrs); - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup_cred; - } - krb5_free_addresses(context, our_addrs); - } - } replaydata->timestamp = encpart.timestamp; replaydata->usec = encpart.usec; @@ -232,54 +198,12 @@ krb5_rd_cred(context, auth_context, pcreddata, pppcreds, outdata) (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; -{ - krb5_address * premote_fulladdr = NULL; - krb5_address * plocal_fulladdr = NULL; - krb5_address remote_fulladdr; - krb5_address local_fulladdr; - CLEANUP_INIT(2); - - if (auth_context->local_addr) { - if (auth_context->local_port) { - if (!(retval = krb5_make_fulladdr(context,auth_context->local_addr, - auth_context->local_port, - &local_fulladdr))){ - CLEANUP_PUSH(local_fulladdr.contents, free); - plocal_fulladdr = &local_fulladdr; - } else { - return retval; - } - } else { - plocal_fulladdr = auth_context->local_addr; - } - } - - if (auth_context->remote_addr) { - if (auth_context->remote_port) { - if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, - auth_context->remote_port, - &remote_fulladdr))){ - CLEANUP_PUSH(remote_fulladdr.contents, free); - premote_fulladdr = &remote_fulladdr; - } else { - return retval; - } - } else { - premote_fulladdr = auth_context->remote_addr; - } - } if ((retval = krb5_rd_cred_basic(context, pcreddata, keyblock, - plocal_fulladdr, premote_fulladdr, &replaydata, pppcreds))) { - CLEANUP_DONE(); - return retval; + return retval; } - CLEANUP_DONE(); -} - - if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; krb5_timestamp currenttime; @@ -327,4 +251,3 @@ error:; return retval; } - diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index 9629b0c..bf33ad2 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -27,7 +27,7 @@ * krb5_rd_priv() */ -#include <k5-int.h> +#include "k5-int.h" #include "cleanup.h" #include "auth_con.h" @@ -101,13 +101,6 @@ krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr, &privmsg->enc_part, &scratch))) goto cleanup_scratch; - /* if i_vector is set, put last block into the i_vector */ - if (i_vector) - memcpy(i_vector, - privmsg->enc_part.ciphertext.data + - (privmsg->enc_part.ciphertext.length - blocksize), - blocksize); - /* now decode the decrypted stuff */ if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part))) goto cleanup_scratch; diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c index 442e78b..4e9f44e 100644 --- a/src/lib/krb5/krb/rd_req_dec.c +++ b/src/lib/krb5/krb/rd_req_dec.c @@ -83,8 +83,8 @@ krb5_rd_req_decrypt_tkt_part(context, req, keytab) enctype, &ktent))) return retval; - if ((retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket))) - return retval; + retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket); + /* Upon error, Free keytab entry first, then return */ (void) krb5_kt_free_entry(context, &ktent); return retval; diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index 19c541f..3909f16 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -27,7 +27,7 @@ * krb5_rd_safe() */ -#include <k5-int.h> +#include "k5-int.h" #include "cleanup.h" #include "auth_con.h" diff --git a/src/lib/krb5/krb/recvauth.c b/src/lib/krb5/krb/recvauth.c index 3d5bce4..7458cb9 100644 --- a/src/lib/krb5/krb/recvauth.c +++ b/src/lib/krb5/krb/recvauth.c @@ -30,27 +30,24 @@ #define NEED_SOCKETS #include "k5-int.h" #include "auth_con.h" -#include "com_err.h" #include <errno.h> #include <stdio.h> #include <string.h> static char *sendauth_version = "KRB5_SENDAUTH_V1.0"; -KRB5_DLLIMP krb5_error_code KRB5_CALLCONV -krb5_recvauth(context, auth_context, - /* IN */ - fd, appl_version, server, flags, keytab, - /* OUT */ - ticket) - krb5_context context; - krb5_auth_context FAR * auth_context; - krb5_pointer fd; - char FAR * appl_version; - krb5_principal server; - krb5_int32 flags; - krb5_keytab keytab; - krb5_ticket FAR * FAR * ticket; +krb5_error_code +recvauth_common(krb5_context context, + krb5_auth_context FAR * auth_context, + /* IN */ + krb5_pointer fd, + char FAR *appl_version, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + /* OUT */ + krb5_ticket FAR * FAR * ticket, + krb5_data FAR *version) { krb5_auth_context new_auth_context; krb5_flags ap_option; @@ -91,12 +88,15 @@ krb5_recvauth(context, auth_context, */ if ((retval = krb5_read_message(context, fd, &inbuf))) return(retval); - if (strcmp(inbuf.data, appl_version)) { + if (appl_version && strcmp(inbuf.data, appl_version)) { krb5_xfree(inbuf.data); if (!problem) problem = KRB5_SENDAUTH_BADAPPLVERS; } - krb5_xfree(inbuf.data); + if (version && !problem) + *version = inbuf; + else + krb5_xfree(inbuf.data); /* * OK, now check the problem variable. If it's zero, we're * fine and we can continue. Otherwise, we have to signal an @@ -243,3 +243,38 @@ cleanup:; } return retval; } + +KRB5_DLLIMP krb5_error_code KRB5_CALLCONV +krb5_recvauth(context, auth_context, + /* IN */ + fd, appl_version, server, flags, keytab, + /* OUT */ + ticket) + krb5_context context; + krb5_auth_context FAR * auth_context; + krb5_pointer fd; + char FAR * appl_version; + krb5_principal server; + krb5_int32 flags; + krb5_keytab keytab; + krb5_ticket FAR * FAR * ticket; +{ + return recvauth_common (context, auth_context, fd, appl_version, + server, flags, keytab, ticket, 0); +} + +KRB5_DLLIMP krb5_error_code KRB5_CALLCONV +krb5_recvauth_version(krb5_context context, + krb5_auth_context FAR *auth_context, + /* IN */ + krb5_pointer fd, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + /* OUT */ + krb5_ticket FAR * FAR *ticket, + krb5_data FAR *version) +{ + return recvauth_common (context, auth_context, fd, 0, + server, flags, keytab, ticket, version); +} diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index 520c0e2..49bc1c9 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -150,7 +150,6 @@ krb5_send_tgs(context, kdcoptions, timestruct, ktypes, sname, addrs, krb5_timestamp time_now; krb5_pa_data **combined_padata; krb5_pa_data ap_req_padata; - size_t enclen; /* * in_creds MUST be a valid credential NOT just a partially filled in diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index 4e7c3a7..24d8a8e 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -30,7 +30,6 @@ #define NEED_SOCKETS #include "k5-int.h" -#include "com_err.h" #include "auth_con.h" #include <errno.h> #include <stdio.h> @@ -119,7 +118,7 @@ krb5_sendauth(context, auth_context, if (!in_creds || !in_creds->ticket.length) { if (ccache) use_ccache = ccache; - else if ((retval = krb5_cc_default(context, &use_ccache))) + else if ((retval = krb5int_cc_default(context, &use_ccache))) goto error_return; } if (!in_creds) { @@ -152,9 +151,32 @@ krb5_sendauth(context, auth_context, credsp = in_creds; } - if ((retval = krb5_mk_req_extended(context, auth_context, ap_req_options, - in_data, credsp, &outbuf))) - goto error_return; + if (ap_req_options & AP_OPTS_USE_SUBKEY) { + /* Provide some more fodder for random number code. + This isn't strong cryptographically; the point here is + not to guarantee randomness, but to make it less likely + that multiple sessions could pick the same subkey. */ + char rnd_data[1024]; + size_t len; + krb5_data d; + d.length = sizeof (rnd_data); + d.data = rnd_data; + len = sizeof (rnd_data); + if (getpeername (*(int*)fd, (struct sockaddr *) rnd_data, &len) == 0) { + d.length = len; + (void) krb5_c_random_seed (context, &d); + } + len = sizeof (rnd_data); + if (getsockname (*(int*)fd, (struct sockaddr *) rnd_data, &len) == 0) { + d.length = len; + (void) krb5_c_random_seed (context, &d); + } + } + + if ((retval = krb5_mk_req_extended(context, auth_context, + ap_req_options, in_data, credsp, + &outbuf))) + goto error_return; /* * First write the length of the AP_REQ message, then write diff --git a/src/lib/krb5/krb/ser_actx.c b/src/lib/krb5/krb/ser_actx.c index bac90e3..fdebbe3 100644 --- a/src/lib/krb5/krb/ser_actx.c +++ b/src/lib/krb5/krb/ser_actx.c @@ -208,6 +208,7 @@ krb5_auth_context_externalize(kcontext, arg, buffer, lenremain) krb5_octet *bp; size_t remain; krb5_int32 obuf; + size_t vecsize; required = 0; bp = *buffer; @@ -237,11 +238,14 @@ krb5_auth_context_externalize(kcontext, arg, buffer, lenremain) if (auth_context->i_vector) { kret = krb5_c_block_size(kcontext, auth_context->keyblock->enctype, - &obuf); + &vecsize); } else { - obuf = 0; + vecsize = 0; } - + obuf = vecsize; + if (obuf != vecsize) + kret = EINVAL; + if (!kret) (void) krb5_ser_pack_int32(obuf, &bp, &remain); diff --git a/src/lib/krb5/krb/t_kerb.c b/src/lib/krb5/krb/t_kerb.c index 2feef39..458015d 100644 --- a/src/lib/krb5/krb/t_kerb.c +++ b/src/lib/krb5/krb/t_kerb.c @@ -4,6 +4,7 @@ */ #include "krb5.h" +#include "kerberosIV/krb.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -56,6 +57,32 @@ void test_425_conv_principal(ctx, name, inst, realm) krb5_free_principal(ctx, princ); } +void test_524_conv_principal(ctx, name) + krb5_context ctx; + char *name; +{ + krb5_principal princ = 0; + krb5_error_code retval; + char aname[ANAME_SZ+1], inst[INST_SZ+1], realm[REALM_SZ+1]; + + aname[ANAME_SZ] = inst[INST_SZ] = realm[REALM_SZ] = 0; + retval = krb5_parse_name(ctx, name, &princ); + if (retval) { + com_err("krb5_parse_name", retval, 0); + goto fail; + } + retval = krb5_524_conv_principal(ctx, princ, aname, inst, realm); + if (retval) { + com_err("krb5_524_conv_principal", retval, 0); + goto fail; + } + printf("524_converted_principal(%s): '%s' '%s' '%s'\n", + name, aname, inst, realm); + fail: + if (princ) + krb5_free_principal (ctx, princ); +} + void test_parse_name(ctx, name) krb5_context ctx; const char *name; @@ -131,6 +158,7 @@ void usage(progname) { fprintf(stderr, "%s: Usage: %s 425_conv_principal <name> <inst> <realm\n", progname, progname); + fprintf(stderr, "\t%s 524_conv_principal <name>\n", progname); fprintf(stderr, "\t%s parse_name <name>\n", progname); fprintf(stderr, "\t%s set_realm <name> <realm>\n", progname); fprintf(stderr, "\t%s string_to_timestamp <time>\n", progname); @@ -186,6 +214,10 @@ main(argc, argv) argc--; argv++; if (!argc) usage(progname); test_string_to_timestamp(ctx, *argv); + } else if (strcmp(*argv, "524_conv_principal") == 0) { + argc--; argv++; + if (!argc) usage(progname); + test_524_conv_principal(ctx, *argv); } else usage(progname); diff --git a/src/lib/krb5/krb/t_krb5.conf b/src/lib/krb5/krb/t_krb5.conf index 5882d97..8d7a4d9 100644 --- a/src/lib/krb5/krb/t_krb5.conf +++ b/src/lib/krb5/krb/t_krb5.conf @@ -19,6 +19,12 @@ kdc = KERBEROS.CYGNUS.COM admin_server = KERBEROS.MIT.EDU } + stanford.edu = { + v4_realm = IR.STANFORD.EDU + } + LONGNAMES.COM = { + v4_realm = SOME-REALLY-LONG-REALM-NAME-V4-CANNOT-HANDLE.COM + } [domain_realm] .mit.edu = ATHENA.MIT.EDU diff --git a/src/lib/krb5/krb/t_ref_kerb.out b/src/lib/krb5/krb/t_ref_kerb.out index 9423944..08a5334 100644 --- a/src/lib/krb5/krb/t_ref_kerb.out +++ b/src/lib/krb5/krb/t_ref_kerb.out @@ -14,4 +14,6 @@ parsed (and unparsed) principal(\/slash/\@atsign/octa\/thorpe@\/slash\@at\/sign) 425_converted principal(rcmd, uunet, UU.NET): 'host/uunet.uu.net@UU.NET' 425_converted principal(zephyr, zephyr, ATHENA.MIT.EDU): 'zephyr/zephyr@ATHENA.MIT.EDU' 425_converted principal(kadmin, ATHENA.MIT.EDU, ATHENA.MIT.EDU): 'kadmin/ATHENA.MIT.EDU@ATHENA.MIT.EDU' +524_converted_principal(host/e40-po.mit.edu@ATHENA.MIT.EDU): 'rcmd' 'e40-po' 'ATHENA.MIT.EDU' +524_converted_principal(host/foobar.stanford.edu@stanford.edu): 'rcmd' 'foobar' 'IR.STANFORD.EDU' old principal: marc@MIT.EDU, modified principal: marc@CYGNUS.COM diff --git a/src/lib/krb5/krb/unparse.c b/src/lib/krb5/krb/unparse.c index f7df6ab..994f94b 100644 --- a/src/lib/krb5/krb/unparse.c +++ b/src/lib/krb5/krb/unparse.c @@ -70,6 +70,9 @@ krb5_unparse_name_ext(context, principal, name, size) krb5_int32 nelem; register int totalsize = 0; + if (!principal) + return KRB5_PARSE_MALFORMED; + cp = krb5_princ_realm(context, principal)->data; length = krb5_princ_realm(context, principal)->length; totalsize += length; diff --git a/src/lib/krb5/krb/vfy_increds.c b/src/lib/krb5/krb/vfy_increds.c index 85a8465..f046ab5 100644 --- a/src/lib/krb5/krb/vfy_increds.c +++ b/src/lib/krb5/krb/vfy_increds.c @@ -109,7 +109,7 @@ krb5_verify_init_creds(krb5_context context, (options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL)) { if (options->ap_req_nofail) goto cleanup; - } else if ((ret2 = krb5_appdefault_boolean(context, + } else if ((ret2 = krb5_libdefault_boolean(context, &creds->client->realm, "verify_ap_req_nofail", &nofail)) diff --git a/src/lib/krb5/krb/walk_rtree.c b/src/lib/krb5/krb/walk_rtree.c index 833ec61..163b7bb 100644 --- a/src/lib/krb5/krb/walk_rtree.c +++ b/src/lib/krb5/krb/walk_rtree.c @@ -93,6 +93,27 @@ #define max(x,y) ((x) > (y) ? (x) : (y)) #endif +/* + * xxx The following function is very confusing to read and probably + * is buggy. It should be documented better. Here is what I've + * learned about it doing a quick bug fixing walk through. The + * function takes a client and server realm name and returns the set + * of realms (in a field called tree) that you need to get tickets in + * in order to get from the source realm to the destination realm. It + * takes a realm separater character (normally ., but presumably there + * for all those X.500 realms) . There are two modes it runs in: the + * ANL krb5.confmode and the hierarchy mode. The ANL mode is + * fairly obvious. The hierarchy mode looks for common components in + * both the client and server realms. In general, the pointer scp and + * ccp are used to walk through the client and server realms. The + * com_sdot and com_cdot pointers point to (I think) the beginning of + * the common part of the realm names. I.E. strcmp(com_cdot, + * com_sdot) ==0 is roughly an invarient. However, there are cases + * where com_sdot and com_cdot are set to point before the start of + * the client or server strings. I think this only happens when there + * are no common components. --hartmans 2002/03/14 + */ + krb5_error_code krb5_walk_realm_tree(context, client, server, tree, realm_branch_char) krb5_context context; @@ -115,6 +136,10 @@ krb5_walk_realm_tree(context, client, server, tree, realm_branch_char) char *cap_client, *cap_server; char **cap_nodes; krb5_error_code cap_code; +#endif + if (!(client->data &&server->data)) + return KRB5_NO_TKT_IN_RLM; +#ifdef CONFIGURABLE_AUTHENTICATION_PATH if ((cap_client = (char *)malloc(client->length + 1)) == NULL) return ENOMEM; strncpy(cap_client, client->data, client->length); |