SHA256
1
0
forked from pool/krb5
krb5/krb5-1.6.2-post.dif

859 lines
28 KiB
Plaintext

Index: src/include/k5-int.h
===================================================================
--- src/include/k5-int.h (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/include/k5-int.h (.../branches/krb5-1-6) (Revision 19936)
@@ -216,6 +216,10 @@
/* required */
#define KDC_ERR_SERVER_NOMATCH 26 /* Requested server and */
/* ticket don't match*/
+#define KDC_ERR_SVC_UNAVAILABLE 29 /* A service is not
+ * available that is
+ * required to process the
+ * request */
/* Application errors */
#define KRB_AP_ERR_BAD_INTEGRITY 31 /* Decrypt integrity check failed */
#define KRB_AP_ERR_TKT_EXPIRED 32 /* Ticket expired */
@@ -498,7 +502,9 @@
krb5_error_code krb5int_sendto (krb5_context context, const krb5_data *message,
const struct addrlist *addrs, struct sendto_callback_info* callback_info,
krb5_data *reply, struct sockaddr *localaddr, socklen_t *localaddrlen,
- struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *addr_used);
+ struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *addr_used,
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data);
krb5_error_code krb5_get_krbhst (krb5_context, const krb5_data *, char *** );
krb5_error_code krb5_free_krbhst (krb5_context, char * const * );
@@ -1885,7 +1891,9 @@
krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg,
const struct addrlist *, struct sendto_callback_info*, krb5_data *reply,
struct sockaddr *, socklen_t *,struct sockaddr *,
- socklen_t *, int *);
+ socklen_t *, int *,
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data);
krb5_error_code (*add_host_to_list)(struct addrlist *lp,
const char *hostname,
int port, int secport,
Index: src/clients/kvno/kvno.M
===================================================================
--- src/clients/kvno/kvno.M (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/clients/kvno/kvno.M (.../branches/krb5-1-6) (Revision 19936)
@@ -55,6 +55,15 @@
specifies that Kerberos version 4 tickets should be acquired and
described. This option is only available if Kerberos 4 support was
enabled at compilation time.
+.TP
+.B \-S sname
+specifies that krb5_sname_to_principal() will be used to build
+principal names. If this flag is specified, the
+.B service1 service2 ...
+arguments are interpreted as hostnames (rather than principal names),
+and
+.B sname
+is interpreted as the service name.
.SH ENVIRONMENT
.B Kvno
uses the following environment variable:
Index: src/clients/kvno/kvno.c
===================================================================
--- src/clients/kvno/kvno.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/clients/kvno/kvno.c (.../branches/krb5-1-6) (Revision 19936)
@@ -41,10 +41,10 @@
{
#ifdef KRB5_KRB4_COMPAT
fprintf(stderr,
- "usage: %s [-4 | [-c ccache] [-e etype] [-k keytab]] service1 service2 ...\n",
+ "usage: %s [-4 | [-c ccache] [-e etype] [-k keytab] [-S sname]] service1 service2 ...\n",
prog);
#else
- fprintf(stderr, "usage: %s [-c ccache] [-e etype] [-k keytab] service1 service2 ...\n",
+ fprintf(stderr, "usage: %s [-c ccache] [-e etype] [-k keytab] [-S sname] service1 service2 ...\n",
prog);
#endif
exit(1);
@@ -54,7 +54,8 @@
static void do_v4_kvno (int argc, char *argv[]);
static void do_v5_kvno (int argc, char *argv[],
- char *ccachestr, char *etypestr, char *keytab_name);
+ char *ccachestr, char *etypestr, char *keytab_name,
+ char *sname);
#include <com_err.h>
static void extended_com_err_fn (const char *, errcode_t, const char *,
@@ -64,6 +65,7 @@
{
int option;
char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL;
+ char *sname = NULL;
int v4 = 0;
set_com_err_hook (extended_com_err_fn);
@@ -71,7 +73,7 @@
prog = strrchr(argv[0], '/');
prog = prog ? (prog + 1) : argv[0];
- while ((option = getopt(argc, argv, "c:e:hk:q4")) != -1) {
+ while ((option = getopt(argc, argv, "c:e:hk:q4S:")) != -1) {
switch (option) {
case 'c':
ccachestr = optarg;
@@ -91,6 +93,9 @@
case '4':
v4 = 1;
break;
+ case 'S':
+ sname = optarg;
+ break;
default:
xusage();
break;
@@ -103,10 +108,14 @@
if ((ccachestr != NULL || etypestr != NULL || keytab_name != NULL) && v4)
xusage();
+ if (sname != NULL && v4)
+ xusage();
+
if (v4)
do_v4_kvno(argc - optind, argv + optind);
else
- do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name);
+ do_v5_kvno(argc - optind, argv + optind,
+ ccachestr, etypestr, keytab_name, sname);
return 0;
}
@@ -172,7 +181,8 @@
}
static void do_v5_kvno (int count, char *names[],
- char * ccachestr, char *etypestr, char *keytab_name)
+ char * ccachestr, char *etypestr, char *keytab_name,
+ char *sname)
{
krb5_error_code ret;
int i, errors;
@@ -230,7 +240,13 @@
in_creds.client = me;
- ret = krb5_parse_name(context, names[i], &in_creds.server);
+ if (sname != NULL) {
+ ret = krb5_sname_to_principal(context, names[i],
+ sname, KRB5_NT_SRV_HST,
+ &in_creds.server);
+ } else {
+ ret = krb5_parse_name(context, names[i], &in_creds.server);
+ }
if (ret) {
if (!quiet)
com_err(prog, ret, "while parsing principal name %s", names[i]);
Index: src/lib/crypto/prng.c
===================================================================
--- src/lib/crypto/prng.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/crypto/prng.c (.../branches/krb5-1-6) (Revision 19936)
@@ -162,7 +162,7 @@
krb5_data data;
struct stat sb;
int fd;
- unsigned char buf[YARROW_SLOW_THRESH/8];
+ unsigned char buf[YARROW_SLOW_THRESH/8], *bp;
int left;
fd = open (device, O_RDONLY);
if (fd == -1)
@@ -173,14 +173,16 @@
close(fd);
return 0;
}
- for (left = sizeof (buf); left > 0;) {
+
+ for (bp = &buf, left = sizeof (buf); left > 0;) {
ssize_t count;
- count = read (fd, &buf, (unsigned) left);
+ count = read (fd, bp, (unsigned) left);
if (count <= 0) {
close(fd);
return 0;
}
left -= count;
+ bp += count;
}
close (fd);
data.length = sizeof (buf);
@@ -199,7 +201,7 @@
int unused;
int *oursuccess = success?success:&unused;
*oursuccess = 0;
- /* If we are getting strong data then try that first. We aare
+ /* If we are getting strong data then try that first. We are
guaranteed to cause a reseed of some kind if strong is true and
we have both /dev/random and /dev/urandom. We want the strong
data included in the reseed so we get it first.*/
Index: src/lib/gssapi/spnego/spnego_mech.c
===================================================================
--- src/lib/gssapi/spnego/spnego_mech.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/gssapi/spnego/spnego_mech.c (.../branches/krb5-1-6) (Revision 19936)
@@ -61,7 +61,7 @@
/* private routines for spnego_mechanism */
static spnego_token_t make_spnego_token(char *);
static gss_buffer_desc make_err_msg(char *);
-static int g_token_size(gss_OID_const, OM_uint32);
+static int g_token_size(gss_OID_const, unsigned int);
static int g_make_token_header(gss_OID_const, unsigned int,
unsigned char **, unsigned int);
static int g_verify_token_header(gss_OID_const, unsigned int *,
@@ -835,6 +835,7 @@
ret = GSS_S_FAILURE;
}
}
+ gss_release_buffer(&tmpmin, &mechtok_out);
if (ret == GSS_S_COMPLETE) {
/*
* Now, switch the output context to refer to the
Index: src/lib/krb4/send_to_kdc.c
===================================================================
--- src/lib/krb4/send_to_kdc.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb4/send_to_kdc.c (.../branches/krb5-1-6) (Revision 19936)
@@ -181,7 +181,7 @@
message.length = pkt->length;
message.data = (char *)pkt->dat; /* XXX yuck */
retval = internals.sendto_udp(NULL, &message, &al, NULL, &reply, addr,
- addrlen, NULL, 0, NULL);
+ addrlen, NULL, 0, NULL, NULL, NULL);
DEB(("sendto_udp returns %d\n", retval));
free_al:
internals.free_addrlist(&al);
Index: src/lib/krb5/os/sendto_kdc.c
===================================================================
--- src/lib/krb5/os/sendto_kdc.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/os/sendto_kdc.c (.../branches/krb5-1-6) (Revision 19936)
@@ -1,7 +1,7 @@
/*
* lib/krb5/os/sendto_kdc.c
*
- * Copyright 1990,1991,2001,2002,2004,2005 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2001,2002,2004,2005,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -295,6 +295,30 @@
return 0;
}
+static int
+check_for_svc_unavailable (krb5_context context,
+ const krb5_data *reply,
+ void *msg_handler_data)
+{
+ krb5_error_code *retval = (krb5_error_code *)msg_handler_data;
+
+ *retval = 0;
+
+ if (krb5_is_krb_error(reply)) {
+ krb5_error *err_reply;
+
+ if (decode_krb5_error(reply, &err_reply) == 0) {
+ *retval = err_reply->error;
+ krb5_free_error(context, err_reply);
+
+ /* Returning 0 means continue to next KDC */
+ return (*retval != KDC_ERR_SVC_UNAVAILABLE);
+ }
+ }
+
+ return 1;
+}
+
/*
* send the formatted request 'message' to a KDC for realm 'realm' and
* return the response (if any) in 'reply'.
@@ -381,9 +405,12 @@
}
if (addrs.naddrs > 0) {
+ krb5_error_code err = 0;
+
retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0,
- 0, 0, &addr_used);
- if (retval == 0) {
+ 0, 0, &addr_used, check_for_svc_unavailable, &err);
+ switch (retval) {
+ case 0:
/*
* Set use_master to 1 if we ended up talking to a master when
* we didn't explicitly request to
@@ -401,7 +428,19 @@
}
krb5int_free_addrlist (&addrs);
return 0;
- }
+ default:
+ break;
+ /* Cases here are for constructing useful error messages. */
+ case KRB5_KDC_UNREACH:
+ if (err == KDC_ERR_SVC_UNAVAILABLE) {
+ retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
+ } else {
+ krb5_set_error_message(context, retval,
+ "Cannot contact any KDC for realm '%.*s'",
+ realm->length, realm->data);
+ }
+ break;
+ }
krb5int_free_addrlist (&addrs);
}
return retval;
@@ -1015,9 +1054,12 @@
}
static int
-service_fds (struct select_state *selstate,
+service_fds (krb5_context context,
+ struct select_state *selstate,
struct conn_state *conns, size_t n_conns, int *winning_conn,
- struct select_state *seltemp)
+ struct select_state *seltemp,
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data)
{
int e, selret;
@@ -1056,9 +1098,22 @@
state_strings[(int) conns[i].state]);
if (conns[i].service (&conns[i], selstate, ssflags)) {
- dprint("fd service routine says we're done\n");
- *winning_conn = i;
- return 1;
+ int stop = 1;
+
+ if (msg_handler != NULL) {
+ krb5_data reply;
+
+ reply.data = conns[i].x.in.buf;
+ reply.length = conns[i].x.in.pos - conns[i].x.in.buf;
+
+ stop = (msg_handler(context, &reply, msg_handler_data) != 0);
+ }
+
+ if (stop) {
+ dprint("fd service routine says we're done\n");
+ *winning_conn = i;
+ return 1;
+ }
}
}
}
@@ -1098,7 +1153,10 @@
struct sendto_callback_info* callback_info, krb5_data *reply,
struct sockaddr *localaddr, socklen_t *localaddrlen,
struct sockaddr *remoteaddr, socklen_t *remoteaddrlen,
- int *addr_used)
+ int *addr_used,
+ /* return 0 -> keep going, 1 -> quit */
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data)
{
int i, pass;
int delay_this_pass = 2;
@@ -1185,8 +1243,8 @@
goto egress;
sel_state->end_time = now;
sel_state->end_time.tv_sec += 1;
- e = service_fds(sel_state, conns, host+1, &winning_conn,
- sel_state+1);
+ e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+ sel_state+1, msg_handler, msg_handler_data);
if (e)
break;
if (pass > 0 && sel_state->nfds == 0)
@@ -1206,7 +1264,8 @@
call with the last one from the above loop, if the loop
actually calls select. */
sel_state->end_time.tv_sec += delay_this_pass;
- e = service_fds(sel_state, conns, host+1, &winning_conn, sel_state+1);
+ e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+ sel_state+1, msg_handler, msg_handler_data);
if (e)
break;
if (sel_state->nfds == 0)
Index: src/lib/krb5/os/send524.c
===================================================================
--- src/lib/krb5/os/send524.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/os/send524.c (.../branches/krb5-1-6) (Revision 19936)
@@ -98,7 +98,7 @@
if (al.naddrs == 0)
return KRB5_REALM_UNKNOWN;
- retval = krb5int_sendto (context, message, &al, NULL, reply, addr, addrlen, NULL, 0, NULL);
+ retval = krb5int_sendto (context, message, &al, NULL, reply, addr, addrlen, NULL, 0, NULL, NULL, NULL);
krb5int_free_addrlist (&al);
return retval;
#else
Index: src/lib/krb5/os/changepw.c
===================================================================
--- src/lib/krb5/os/changepw.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/os/changepw.c (.../branches/krb5-1-6) (Revision 19936)
@@ -247,6 +247,8 @@
NULL,
ss2sa(&remote_addr),
&addrlen,
+ NULL,
+ NULL,
NULL
))) {
Index: src/lib/krb5/error_tables/krb5_err.et
===================================================================
--- src/lib/krb5/error_tables/krb5_err.et (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/error_tables/krb5_err.et (.../branches/krb5-1-6) (Revision 19936)
@@ -1,7 +1,7 @@
#
# lib/krb5/error_tables/krb5_err.et
#
-# Copyright 1989,1990,1991 by the Massachusetts Institute of Technology.
+# Copyright 1989,1990,1991,2007 by the Massachusetts Institute of Technology.
# All Rights Reserved.
#
# Export of this software from the United States of America may
@@ -68,7 +68,7 @@
error_code KRB5KDC_ERR_SERVER_NOMATCH, "Requested server and ticket don't match"
error_code KRB5PLACEHOLD_27, "KRB5 error code 27"
error_code KRB5PLACEHOLD_28, "KRB5 error code 28"
-error_code KRB5PLACEHOLD_29, "KRB5 error code 29"
+error_code KRB5KDC_ERR_SVC_UNAVAILABLE, "A service is not available that is required to process the request"
error_code KRB5PLACEHOLD_30, "KRB5 error code 30"
# vv 31
error_code KRB5KRB_AP_ERR_BAD_INTEGRITY, "Decrypt integrity check failed"
Index: src/lib/krb5/ccache/t_cc.c
===================================================================
--- src/lib/krb5/ccache/t_cc.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/ccache/t_cc.c (.../branches/krb5-1-6) (Revision 19936)
@@ -123,6 +123,7 @@
krb5_cc_cursor cursor;
const char *c_name;
char newcache[300];
+ char *save_type;
init_test_cred(context);
@@ -135,7 +136,9 @@
CHECK_STR(c_name, "get_name");
c_name = krb5_cc_get_type(context, id);
- CHECK_STR(c_name, "get_prefix");
+ CHECK_STR(c_name, "get_type");
+ save_type=strdup(c_name);
+ CHECK_STR(save_type, "copying type");
kret = krb5_cc_store_cred(context, id, &test_creds);
CHECK(kret, "store");
@@ -192,17 +195,22 @@
kret = krb5_cc_destroy(context, id);
CHECK(kret, "destroy");
-#if 0
/* ----------------------------------------------------- */
/* Tests the generate new code */
- kret = krb5_cc_resolve(context, name, &id);
- CHECK(kret, "resolve");
- kret = krb5_cc_gen_new(context, &id);
- CHECK(kret, "gen_new");
- kret = krb5_cc_destroy(context, id);
- CHECK(kret, "destroy");
-#endif
+ kret = krb5_cc_new_unique(context, save_type,
+ NULL, &id2);
+ CHECK(kret, "new_unique");
+
+ kret = krb5_cc_initialize(context, id2, test_creds.client);
+ CHECK(kret, "initialize");
+ kret = krb5_cc_store_cred(context, id2, &test_creds);
+ CHECK(kret, "store");
+
+ kret = krb5_cc_destroy(context, id2);
+ CHECK(kret, "destroy id2");
+
+ free(save_type);
free_test_cred(context);
}
Index: src/lib/krb5/ccache/cc_file.c
===================================================================
--- src/lib/krb5/ccache/cc_file.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/ccache/cc_file.c (.../branches/krb5-1-6) (Revision 19936)
@@ -1950,115 +1950,165 @@
{
krb5_ccache lid;
int ret;
- krb5_error_code retcode = 0;
+ krb5_error_code kret = 0;
char scratch[sizeof(TKT_ROOT)+6+1]; /* +6 for the scratch part, +1 for
NUL */
krb5_fcc_data *data;
+ krb5_int16 fcc_fvno = htons(context->fcc_default_format);
+ krb5_int16 fcc_flen = 0;
+ int errsave, cnt;
+ struct fcc_set *setptr;
- /* Allocate memory */
- lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
- if (lid == NULL)
- return KRB5_CC_NOMEM;
+ /* Set master lock */
+ kret = k5_mutex_lock(&krb5int_cc_file_mutex);
+ if (kret)
+ return kret;
- lid->ops = &krb5_fcc_ops;
-
(void) strcpy(scratch, TKT_ROOT);
(void) strcat(scratch, "XXXXXX");
#ifdef HAVE_MKSTEMP
ret = mkstemp(scratch);
if (ret == -1) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
return krb5_fcc_interpret(context, errno);
- } else close(ret);
+ }
#else /*HAVE_MKSTEMP*/
mktemp(scratch);
+ /* Make sure the file name is reserved */
+ ret = THREEPARAMOPEN(scratch, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, 0);
+ if (ret == -1) {
+ return krb5_fcc_interpret(context, errno);
+ }
#endif
- lid->data = (krb5_pointer) malloc(sizeof(krb5_fcc_data));
- if (lid->data == NULL) {
- krb5_xfree(lid);
+ /* Allocate memory */
+ data = (krb5_pointer) malloc(sizeof(krb5_fcc_data));
+ if (data == NULL) {
+ close(ret);
+ unlink(scratch);
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
return KRB5_CC_NOMEM;
}
- ((krb5_fcc_data *) lid->data)->filename = (char *)
- malloc(strlen(scratch) + 1);
- if (((krb5_fcc_data *) lid->data)->filename == NULL) {
- krb5_xfree(((krb5_fcc_data *) lid->data));
- krb5_xfree(lid);
+ data->filename = strdup(scratch);
+ if (data->filename == NULL) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ free(data);
+ close(ret);
+ unlink(scratch);
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
return KRB5_CC_NOMEM;
}
+ kret = k5_mutex_init(&data->lock);
+ if (kret) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ free(data->filename);
+ free(data);
+ close(ret);
+ unlink(scratch);
+ return kret;
+ }
+ kret = k5_mutex_lock(&data->lock);
+ if (kret) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_mutex_destroy(&data->lock);
+ free(data->filename);
+ free(data);
+ close(ret);
+ unlink(scratch);
+ return kret;
+ }
+
/*
* The file is initially closed at the end of this call...
*/
- ((krb5_fcc_data *) lid->data)->flags = 0;
- ((krb5_fcc_data *) lid->data)->file = -1;
- ((krb5_fcc_data *) lid->data)->valid_bytes = 0;
- data = (krb5_fcc_data *) lid->data;
+ data->flags = 0;
+ data->file = -1;
+ data->valid_bytes = 0;
+ /* data->version,mode filled in for real later */
+ data->version = data->mode = 0;
- retcode = k5_mutex_init(&data->lock);
- if (retcode)
- goto err_out;
- /* Set up the filename */
- strcpy(((krb5_fcc_data *) lid->data)->filename, scratch);
-
- /* Make sure the file name is reserved */
- ret = THREEPARAMOPEN(((krb5_fcc_data *) lid->data)->filename,
- O_CREAT | O_EXCL | O_WRONLY | O_BINARY, 0);
- if (ret == -1) {
- retcode = krb5_fcc_interpret(context, errno);
- goto err_out;
- } else {
- krb5_int16 fcc_fvno = htons(context->fcc_default_format);
- krb5_int16 fcc_flen = 0;
- int errsave, cnt;
-
- /* Ignore user's umask, set mode = 0600 */
+ /* Ignore user's umask, set mode = 0600 */
#ifndef HAVE_FCHMOD
#ifdef HAVE_CHMOD
- chmod(((krb5_fcc_data *) lid->data)->filename, S_IRUSR | S_IWUSR);
+ chmod(data->filename, S_IRUSR | S_IWUSR);
#endif
#else
- fchmod(ret, S_IRUSR | S_IWUSR);
+ fchmod(ret, S_IRUSR | S_IWUSR);
#endif
- if ((cnt = write(ret, (char *)&fcc_fvno, sizeof(fcc_fvno)))
- != sizeof(fcc_fvno)) {
- errsave = errno;
- (void) close(ret);
- (void) unlink(((krb5_fcc_data *) lid->data)->filename);
- retcode = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
- goto err_out;
+ if ((cnt = write(ret, (char *)&fcc_fvno, sizeof(fcc_fvno)))
+ != sizeof(fcc_fvno)) {
+ errsave = errno;
+ (void) close(ret);
+ (void) unlink(data->filename);
+ kret = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
+ goto err_out;
+ }
+ /* For version 4 we save a length for the rest of the header */
+ if (context->fcc_default_format == KRB5_FCC_FVNO_4) {
+ if ((cnt = write(ret, (char *)&fcc_flen, sizeof(fcc_flen)))
+ != sizeof(fcc_flen)) {
+ errsave = errno;
+ (void) close(ret);
+ (void) unlink(data->filename);
+ kret = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
+ goto err_out;
}
- /* For version 4 we save a length for the rest of the header */
- if (context->fcc_default_format == KRB5_FCC_FVNO_4) {
- if ((cnt = write(ret, (char *)&fcc_flen, sizeof(fcc_flen)))
- != sizeof(fcc_flen)) {
- errsave = errno;
- (void) close(ret);
- (void) unlink(((krb5_fcc_data *) lid->data)->filename);
- retcode = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
- goto err_out;
- }
- }
- if (close(ret) == -1) {
- errsave = errno;
- (void) unlink(((krb5_fcc_data *) lid->data)->filename);
- retcode = krb5_fcc_interpret(context, errsave);
- goto err_out;
- }
- *id = lid;
- /* default to open/close on every trn - otherwise destroy
- will get as to state confused */
- ((krb5_fcc_data *) lid->data)->flags = KRB5_TC_OPENCLOSE;
- krb5_change_cache ();
- return KRB5_OK;
}
+ if (close(ret) == -1) {
+ errsave = errno;
+ (void) unlink(data->filename);
+ kret = krb5_fcc_interpret(context, errsave);
+ goto err_out;
+ }
+
+ setptr = malloc(sizeof(struct fcc_set));
+ if (setptr == NULL) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_mutex_destroy(&data->lock);
+ free(data->filename);
+ free(data);
+ (void) close(ret);
+ (void) unlink(scratch);
+ return KRB5_CC_NOMEM;
+ }
+ setptr->refcount = 1;
+ setptr->data = data;
+ setptr->next = fccs;
+ fccs = setptr;
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+
+ k5_mutex_assert_locked(&data->lock);
+ k5_mutex_unlock(&data->lock);
+ lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+ if (lid == NULL) {
+ dereference(context, data);
+ return KRB5_CC_NOMEM;
+ }
+
+ lid->ops = &krb5_fcc_ops;
+ lid->data = data;
+ lid->magic = KV5M_CCACHE;
+
+ /* default to open/close on every trn - otherwise destroy
+ will get as to state confused */
+ ((krb5_fcc_data *) lid->data)->flags = KRB5_TC_OPENCLOSE;
+
+ *id = lid;
+
+
+ krb5_change_cache ();
+ return KRB5_OK;
+
err_out:
- krb5_xfree(((krb5_fcc_data *) lid->data)->filename);
- krb5_xfree(((krb5_fcc_data *) lid->data));
- krb5_xfree(lid);
- return retcode;
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_mutex_destroy(&data->lock);
+ free(data->filename);
+ free(data);
+ return kret;
}
/*
Index: src/lib/krb5/ccache/ccfns.c
===================================================================
--- src/lib/krb5/ccache/ccfns.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/ccache/ccfns.c (.../branches/krb5-1-6) (Revision 19936)
@@ -1,7 +1,7 @@
/*
* lib/krb5/ccache/ccfns.c
*
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -65,7 +65,29 @@
krb5_cc_store_cred (krb5_context context, krb5_ccache cache,
krb5_creds *creds)
{
- return cache->ops->store(context, cache, creds);
+ krb5_error_code ret;
+ krb5_ticket *tkt;
+ krb5_principal s1, s2;
+
+ ret = cache->ops->store(context, cache, creds);
+ if (ret) return ret;
+
+ /*
+ * If creds->server and the server in the decoded ticket differ,
+ * store both principals.
+ */
+ s1 = creds->server;
+ ret = decode_krb5_ticket(&creds->ticket, &tkt);
+ /* Bail out on errors in case someone is storing a non-ticket. */
+ if (ret) return 0;
+ s2 = tkt->server;
+ if (!krb5_principal_compare(context, s1, s2)) {
+ creds->server = s2;
+ ret = cache->ops->store(context, cache, creds);
+ creds->server = s1;
+ }
+ krb5_free_ticket(context, tkt);
+ return ret;
}
krb5_error_code KRB5_CALLCONV
@@ -73,7 +95,23 @@
krb5_flags flags, krb5_creds *mcreds,
krb5_creds *creds)
{
- return cache->ops->retrieve(context, cache, flags, mcreds, creds);
+ krb5_error_code ret;
+ krb5_data tmprealm;
+
+ ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+ if (ret != KRB5_CC_NOTFOUND)
+ return ret;
+ if (!krb5_is_referral_realm(&mcreds->server->realm))
+ return ret;
+
+ /*
+ * Retry using client's realm if service has referral realm.
+ */
+ tmprealm = mcreds->server->realm;
+ mcreds->server->realm = mcreds->client->realm;
+ ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+ mcreds->server->realm = tmprealm;
+ return ret;
}
krb5_error_code KRB5_CALLCONV
Index: src/lib/krb5/krb/gc_frm_kdc.c
===================================================================
--- src/lib/krb5/krb/gc_frm_kdc.c (.../tags/krb5-1-6-2-final) (Revision 19936)
+++ src/lib/krb5/krb/gc_frm_kdc.c (.../branches/krb5-1-6) (Revision 19936)
@@ -906,7 +906,6 @@
/* Whether or not that succeeded, we're done. */
goto cleanup;
}
- else {
/* Referral request succeeded; let's see what it is. */
if (krb5_principal_compare(context, in_cred->server,
(*out_cred)->server)) {
@@ -914,8 +913,40 @@
"for requested server principal\n"));
DUMP_PRINC("gc_from_kdc final referred reply",
in_cred->server);
+
+ /*
+ * Check if the return enctype is one that we requested if
+ * needed.
+ */
+ if (old_use_conf_ktypes || context->tgs_ktype_count == 0)
goto cleanup;
+ for (i = 0; i < context->tgs_ktype_count; i++) {
+ if ((*out_cred)->keyblock.enctype == context->tgs_ktypes[i]) {
+ /* Found an allowable etype, so we're done */
+ goto cleanup;
+ }
}
+ /*
+ * We need to try again, but this time use the
+ * tgs_ktypes in the context. At this point we should
+ * have all the tgts to succeed.
+ */
+
+ /* Free "wrong" credential */
+ krb5_free_creds(context, *out_cred);
+ *out_cred = NULL;
+ /* Re-establish tgs etypes */
+ context->use_conf_ktypes = old_use_conf_ktypes;
+ retval = krb5_get_cred_via_tkt(context, tgtptr,
+ KDC_OPT_CANONICALIZE |
+ FLAGS2OPTS(tgtptr->ticket_flags) |
+ kdcopt |
+ (in_cred->second_ticket.length ?
+ KDC_OPT_ENC_TKT_IN_SKEY : 0),
+ tgtptr->addresses,
+ in_cred, out_cred);
+ goto cleanup;
+ }
else if (IS_TGS_PRINC(context, (*out_cred)->server)) {
krb5_data *r1, *r2;
@@ -978,7 +1009,6 @@
krb5_free_creds(context, *out_cred);
*out_cred = NULL;
break;
- }
}
}