[1846] in Kerberos-V5-bugs
ss-962301 - krb524 and AFS
daemon@ATHENA.MIT.EDU (Doug Engert)
Mon Mar 25 13:51:09 1996
Date: Mon, 25 Mar 1996 12:50:56 -0600
From: Doug Engert <DEEngert@anl.gov>
To: krb5-bugs@MIT.EDU
I would like to submit these fixes/suggestions to the k5b524 code from
the Kerberos ss-962301 snapshot.
These changes cover four areas:
o Clients had problems contacting the krb524d when it was run on a
multi-homed host, and one of the interfaces was down. (Based on
tests with the K5 beta 5 code.)
o The lookup_service_key routine was changed to use the tickets
enctype, and kvno. Previously it assumed ENCTYPE_DES_CBC_MD5 and
passed a 0 kvno to krb5_kt_get_entry.
o Parameter lists were change to allow for the key and kvno used
to decrypt the K5 ticket to be different for the key and kvno used to
encrypt the v4 ticket. This was done mostly for the following AFS
modification, but could have some additional use.
o Support was added to allow a ticket for AFS to be decrypted using the
K5 key, converted to K4 and encrypted using the key and kvno from a
copy of the AFS KeyFile. This greatly simplifies the key maintenance
for AFS principals. A translation from the K5 principal
afsx/afs.cell.name@k5.realm to the the K4 principal: afs@afs.cell.name
is also performed. This allows a K5 realm to serve as the KDC for
multiple AFS cells. A modified version of aklog can take advantage
of this mapping. All code which requires AFS is controlled by
#ifdef AFS524. (There are some additions to parameter lists for an
afsflag which are not covered by the ifdefs so as to keep the changes
simpler. The flag is set to 0 in this case.)
The following changes were made:
cnv_tkt_skey.c - A new routine, get_afs_key_from_file, was added which
will read a copy of the AFS KeyFile named /krb5/afs.afs.cell.name
where afs.cell.name is the name of the AFS cell. The highest key and
kvno are returned. The call to krb524_convert_tkt_skey was modified
to add the v4kvno, since it could be using two different keys and
kvno.
conv_creds.c - krb524_convert_creds_addr now returns the number of
addresses so as to allow this to be passed to the sendmsg routines.
Code to loop thru the address was removed for this routine, since the
new sendmsg.c code does is internally. The afsflag was defined, since
it need to be passed between a number of routines.
conv_princ.c - as a final check, if AFS524 was defined, a
principal of the form afsx/afs.cell.name@dce.cell.name is converted
to afs@afs.cell.name. (The comments talk about DCE, since that is what
I am using, but should work the same with K5. Feel free to change the
comments.)
conv_tkt.c - naddrs is passed in, and the saddr->sin_port is reset on
all the addresses, since it was preset to the KDC port, rather then
the KRB524_PORT. The krb524_send_message is then called, passing the
naddrs parameter.
krb524d.c - lookup_service_key is called with the enctype and kvno
from the ticket. krb524_convert_tkt_skey now requires a v4kvno, since
it may not be the same as the v5kvno.
sendmsg.c - It now accepts the naddrs parameter. Basically, sendmsg.c
was based on an earlier version of sendto_kdc.c and was never updated.
The diff does not show this very well, but everything after line 61 or
so was copied from the current sendto_kdc.c.
test.c - Modified to pass naddrs = 1.
krb524.h - Prototypes for krb524_convert_tkt_skey,
krb524_convert_princs, krb524_convert_creds_addr, krb524_convert_tkt,
krb524_send_message were modified to include afsflag, naddrs or v4kvno
as required.
Douglas E. Engert
Systems Programming
Argonne National Laboratory
9700 South Cass Avenue
Argonne, Illinois 60439
(708) 252-5444
Internet: DEEngert@anl.gov
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*** ./krb524/,cnv_tkt_skey.c Wed Sep 6 14:54:52 1995
--- ./krb524/cnv_tkt_skey.c Mon Mar 18 09:47:38 1996
***************
*** 30,49 ****
#include <krb4-proto.h>
#include "krb524.h"
/*
* Convert a v5 ticket for server to a v4 ticket, using service key
* skey for both.
*/
! int krb524_convert_tkt_skey(context, v5tkt, v4tkt, skey)
krb5_context context;
krb5_ticket *v5tkt;
KTEXT_ST *v4tkt;
krb5_keyblock *skey;
{
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
char sname[ANAME_SZ], sinst[INST_SZ];
krb5_enc_tkt_part *v5etkt;
int ret, lifetime;
v5tkt->enc_part2 = NULL;
if ((ret = krb5_decrypt_tkt_part(context, skey, v5tkt))) {
--- 30,104 ----
#include <krb4-proto.h>
#include "krb524.h"
+ #ifdef AFS524
+ #include <stdio.h>
+ #include <fcntl.h>
+ #define int32 krb5_int32
+ #include </usr/afsws/include/afs/keys.h>
+ #endif
+
+ #ifdef AFS524
+ /*
+ * Get highest key for this AFS cell from copy of the KeyFile
+ */
+
+ int get_afs_key_from_file(char *afscell,
+ krb5_kvno *knvo, C_Block *afscblock)
+ {
+ int fd, i;
+
+ static char afscurrent[REALM_SZ] = "";
+ static C_Block afskey;
+ static krb5_kvno afskvno;
+
+ struct afsconf_keys afskeys;
+ char afsfilename[BUFSIZ];
+
+ /* If we have not opened the file, or if the call name if
+ * different read the keyfile if it exists. If not return 0.
+ * This should really use a link list.
+ * This allows for multiple afs cells from a single K5 realm.
+ * A link list of previously seen AFS cells would reduce
+ * overhead.
+ */
+
+ if (strcmp(afscell, afscurrent)) {
+ strcpy(afsfilename, "/krb5/afs.");
+ strcat(afsfilename,afscell);
+ if (((fd = open(afsfilename,O_RDONLY)) < 0) ||
+ (read(fd,&afskeys,sizeof(afskeys)) != sizeof(afskeys)))
+ return (0);
+
+ i = ntohl(afskeys.nkeys) - 1;
+ afskvno = ntohl(afskeys.key[i].kvno);
+ memcpy(afskey, afskeys.key[i].key, sizeof(afskey));
+
+ strcpy(afscurrent,afscell);
+ }
+ *knvo = afskvno;
+ memcpy(afscblock, afskey, sizeof(afskey));
+ return(1);
+ }
+ #endif /* AFS524 */
+
/*
* Convert a v5 ticket for server to a v4 ticket, using service key
* skey for both.
+ * It now accepts the kvno for the v4 ticket.
*/
! int krb524_convert_tkt_skey(context, v5tkt, v4tkt, skey, v4kvno)
krb5_context context;
krb5_ticket *v5tkt;
KTEXT_ST *v4tkt;
krb5_keyblock *skey;
+ krb5_kvno *v4kvno;
{
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
char sname[ANAME_SZ], sinst[INST_SZ];
krb5_enc_tkt_part *v5etkt;
int ret, lifetime;
+ int afsflag;
+ C_Block afscblock;
v5tkt->enc_part2 = NULL;
if ((ret = krb5_decrypt_tkt_part(context, skey, v5tkt))) {
***************
*** 54,60 ****
if ((ret = krb524_convert_princs(context, v5etkt->client, v5tkt->server,
pname, pinst, prealm, sname,
! sinst))) {
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return ret;
--- 109,115 ----
if ((ret = krb524_convert_princs(context, v5etkt->client, v5tkt->server,
pname, pinst, prealm, sname,
! sinst, &afsflag))) {
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
return ret;
***************
*** 97,102 ****
--- 152,168 ----
(long) v5etkt->times.authtime,
(long) lifetime);
+ /* if the principal is AFS, we want to use the AFS KeyFile
+ * for this cell to encrypt the V4 ticket. This requires
+ * us to reset the v4kvno as well */
+
+ *v4kvno = v5tkt->enc_part.kvno; /* set to v5 version */
+ #ifdef AFS524
+ if (afsflag) {
+ afsflag = get_afs_key_from_file(prealm, v4kvno, &afscblock);
+ }
+ #endif
+
/* XXX are there V5 flags we should map to V4 equivalents? */
ret = krb_create_ticket(v4tkt,
0, /* flags */
***************
*** 110,116 ****
v5etkt->times.starttime,
sname,
sinst,
! skey->contents);
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
--- 176,186 ----
v5etkt->times.starttime,
sname,
sinst,
! #ifdef AFS524
! afsflag ? &afscblock :
! #endif
! skey->contents);
!
krb5_free_enc_tkt_part(context, v5etkt);
v5tkt->enc_part2 = NULL;
*** ./krb524/,conv_creds.c Fri Nov 17 21:07:47 1995
--- ./krb524/conv_creds.c Mon Mar 18 08:34:36 1996
***************
*** 35,41 ****
CREDENTIALS *v4creds));
! int krb524_convert_creds_addr(context, v5creds, v4creds, saddr)
krb5_context context;
krb5_creds *v5creds;
CREDENTIALS *v4creds;
--- 35,41 ----
CREDENTIALS *v4creds));
! int krb524_convert_creds_addr(context, v5creds, v4creds, saddr, naddrs)
krb5_context context;
krb5_creds *v5creds;
CREDENTIALS *v4creds;
***************
*** 49,55 ****
return krb524_convert_tkt(v5creds->server, &v5creds->ticket,
&v4creds->ticket_st,
&v4creds->kvno,
! (struct sockaddr_in *) saddr);
}
int krb524_convert_creds_kdc(context, v5creds, v4creds)
--- 49,55 ----
return krb524_convert_tkt(v5creds->server, &v5creds->ticket,
&v4creds->ticket_st,
&v4creds->kvno,
! (struct sockaddr_in *) saddr, naddrs);
}
int krb524_convert_creds_kdc(context, v5creds, v4creds)
***************
*** 66,91 ****
if (naddrs == 0)
ret = KRB5_KDC_UNREACH;
else {
- for (i = 0; i<naddrs; i++) {
- addrs[i].sin_port = 0; /* use krb524 default port */
ret = krb524_convert_creds_addr(context, v5creds, v4creds,
! (struct sockaddr *) &addrs[i]);
! /* stop trying on success */
! if (!ret) break;
! switch(ret) {
! case ECONNREFUSED:
! case ENETUNREACH:
! case ENETDOWN:
! case ETIMEDOUT:
! case EHOSTDOWN:
! case EHOSTUNREACH:
! continue;
! default:
! break; /* out of switch */
! }
! /* if we fall through to here, it wasn't an "ok" error */
! break;
! }
}
free(addrs);
--- 66,73 ----
if (naddrs == 0)
ret = KRB5_KDC_UNREACH;
else {
ret = krb524_convert_creds_addr(context, v5creds, v4creds,
! (struct sockaddr *) &addrs[0], naddrs);
}
free(addrs);
***************
*** 99,104 ****
--- 81,87 ----
{
unsigned long addr;
int ret;
+ int afsflag;
memset((char *) v4creds, 0, sizeof(CREDENTIALS));
***************
*** 106,112 ****
v5creds->server,
v4creds->pname, v4creds->pinst,
v4creds->realm, v4creds->service,
! v4creds->instance)))
return ret;
/* Check enctype too */
--- 89,95 ----
v5creds->server,
v4creds->pname, v4creds->pinst,
v4creds->realm, v4creds->service,
! v4creds->instance, &afsflag)))
return ret;
/* Check enctype too */
*** ./krb524/,conv_princ.c Mon Jun 5 21:28:57 1995
--- ./krb524/conv_princ.c Mon Mar 18 09:22:37 1996
***************
*** 33,42 ****
#include "krb524.h"
int krb524_convert_princs(context, client, server, pname, pinst, prealm,
! sname, sinst)
krb5_context context;
krb5_principal client, server;
char *pname, *pinst, *prealm, *sname, *sinst;
{
char dummy[REALM_SZ];
int ret;
--- 33,43 ----
#include "krb524.h"
int krb524_convert_princs(context, client, server, pname, pinst, prealm,
! sname, sinst, afsflag)
krb5_context context;
krb5_principal client, server;
char *pname, *pinst, *prealm, *sname, *sinst;
+ int *afsflag;
{
char dummy[REALM_SZ];
int ret;
***************
*** 45,49 ****
prealm)))
return ret;
! return krb5_524_conv_principal(context, server, sname, sinst, dummy);
}
--- 46,75 ----
prealm)))
return ret;
! if ((ret = krb5_524_conv_principal(context, server, sname, sinst, dummy)))
! return ret;
!
! #ifdef AFS524
! /* When using DCE to store a afsx/afs.cell.name@dce.cell.name
! * convert this to afs@afs.cell.name
! *
! * If the client is in the same DCE cell as the server, then this
! * DCE cell is considered to be able to hand out tickets for the
! * AFS cell(s). We need to make it look like to AFS that the user
! * is in the AFS cell, so we set the clients prealm to match the
! * AFS cell name. But we don't want to do this if the client
! * is not in the same DCE cell, since AFS does some cross cell
! * authentication, and this would violate that. The user should
! * still look like he is in the foriegn DCE cell.
! */
! if (!strcmp(sname, "afsx")) {
! if (!strcmp(prealm, dummy))
! strcpy(prealm, sinst) ;
! strcpy(sname,"afs");
! *sinst = '\0';
! *afsflag = 1;
! } else
! #endif AFS524
! *afsflag = 0;
! return(0);
}
*** ./krb524/,conv_tkt.c Mon Jun 5 21:24:41 1995
--- ./krb524/conv_tkt.c Mon Mar 18 12:58:02 1996
***************
*** 34,62 ****
* krb524_convert_tkt. Open a network connection to krb524d, send it
* the V5 ticket, receive the V4 ticket in response.
*/
! int krb524_convert_tkt(server, v5tkt, v4tkt, kvno, saddr)
krb5_principal server;
krb5_data *v5tkt;
KTEXT_ST *v4tkt;
int *kvno;
struct sockaddr_in *saddr;
{
char *p;
krb5_data reply;
struct servent *serv;
int ret, status;
reply.data = NULL;
! if (saddr->sin_port == 0) {
serv = getservbyname(KRB524_SERVICE, "udp");
! if (serv)
! saddr->sin_port = serv->s_port;
! else
! saddr->sin_port = htons(KRB524_PORT);
! }
! if ((ret = krb524_send_message((struct sockaddr *) saddr, v5tkt, &reply)))
goto fail;
p = reply.data;
--- 34,67 ----
* krb524_convert_tkt. Open a network connection to krb524d, send it
* the V5 ticket, receive the V4 ticket in response.
*/
! int krb524_convert_tkt(server, v5tkt, v4tkt, kvno, saddr, naddrs)
krb5_principal server;
krb5_data *v5tkt;
KTEXT_ST *v4tkt;
int *kvno;
struct sockaddr_in *saddr;
+ int naddrs;
{
char *p;
krb5_data reply;
struct servent *serv;
int ret, status;
+ int i;
reply.data = NULL;
! /* if (saddr->sin_port == 0) { */
serv = getservbyname(KRB524_SERVICE, "udp");
! for (i = 0; i< naddrs; i++) {
! if (serv)
! saddr[i].sin_port = serv->s_port;
! else
! saddr[i].sin_port = htons(KRB524_PORT);
! }
! /* } */
! if ((ret = krb524_send_message((struct sockaddr *) saddr,
! naddrs, v5tkt, &reply)))
goto fail;
p = reply.data;
*** ./krb524/,krb524d.c Tue Dec 19 20:04:37 1995
--- ./krb524/krb524d.c Mon Mar 18 09:00:21 1996
***************
*** 262,267 ****
--- 262,268 ----
krb5_data msgdata, tktdata;
char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p;
int n, ret, saddrlen;
+ krb5_kvno v4kvno;
msgdata.data = msgbuf;
msgdata.length = MSGSIZE;
***************
*** 299,311 ****
/* XXX ENCTYPE_DES_CBC_MD5 shouldn't be hardcoded here. Should be
derived from the ticket. */
! if ((ret = lookup_service_key(context, v5tkt->server, ENCTYPE_DES_CBC_MD5,
! &service_key)))
goto error;
if (debug)
printf("service key retrieved\n");
! ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &service_key);
if (ret)
goto error;
krb5_free_keyblock_contents(context, &service_key);
--- 300,314 ----
/* XXX ENCTYPE_DES_CBC_MD5 shouldn't be hardcoded here. Should be
derived from the ticket. */
! /* fix above by passing the enctype, and kvno */
! if ((ret = lookup_service_key(context, v5tkt->server,
! v5tkt->enc_part.kvno,
! v5tkt->enc_part.enctype, &service_key)))
goto error;
if (debug)
printf("service key retrieved\n");
! ret = krb524_convert_tkt_skey(context, v5tkt, &v4tkt, &service_key, &v4kvno);
if (ret)
goto error;
krb5_free_keyblock_contents(context, &service_key);
***************
*** 334,340 ****
if (ret)
goto write_msg;
! n = htonl(v5tkt->enc_part.kvno);
memcpy(p, (char *) &n, sizeof(int));
p += sizeof(int);
msgdata.length += sizeof(int);
--- 337,343 ----
if (ret)
goto write_msg;
! n = htonl(v4kvno);
memcpy(p, (char *) &n, sizeof(int));
p += sizeof(int);
msgdata.length += sizeof(int);
***************
*** 355,363 ****
return ret;
}
! krb5_error_code lookup_service_key(context, p, ktype, key)
krb5_context context;
krb5_principal p;
krb5_enctype ktype;
krb5_keyblock *key;
{
--- 358,367 ----
return ret;
}
! krb5_error_code lookup_service_key(context, p, kvno, ktype, key)
krb5_context context;
krb5_principal p;
+ krb5_kvno kvno;
krb5_enctype ktype;
krb5_keyblock *key;
{
***************
*** 365,371 ****
krb5_keytab_entry entry;
if (use_keytab) {
! if ((ret = krb5_kt_get_entry(context, kt, p, 0, ktype, &entry)))
return ret;
memcpy(key, (char *) &entry.key, sizeof(krb5_keyblock));
return 0;
--- 369,375 ----
krb5_keytab_entry entry;
if (use_keytab) {
! if ((ret = krb5_kt_get_entry(context, kt, p, kvno, ktype, &entry)))
return ret;
memcpy(key, (char *) &entry.key, sizeof(krb5_keyblock));
return 0;
*** ./krb524/,sendmsg.c Tue Jun 27 15:54:43 1995
--- ./krb524/sendmsg.c Mon Mar 18 08:44:54 1996
***************
*** 56,157 ****
extern int krb5_skdc_timeout_1;
int krb524_send_message
! PROTOTYPE((const struct sockaddr * addr, const krb5_data * message,
krb5_data * reply));
! int krb524_send_message (addr, message, reply)
! const struct sockaddr * addr;
! const krb5_data * message;
! krb5_data * reply;
{
! register int timeout;
! int nready, received;
krb5_error_code retval;
fd_set readable;
struct timeval waitlen;
! int s, cc;
! if ((reply->data = malloc(krb5_max_dgram_size)) == NULL)
return ENOMEM;
! reply->length = krb5_max_dgram_size;
! /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the */
! /* socket creation here will work properly... */
! s = socket(addr->sa_family, SOCK_DGRAM, 0);
! if (s == -1) {
! retval = errno;
! goto out;
}
!
! /*
! * On BSD systems, a connected UDP socket will get connection
! * refused and net unreachable errors while an unconnected socket
! * will time out, so use connect, send, recv instead of sendto,
! * recvfrom. The connect here may return an error if the
! * destination host is known to be unreachable.
! */
! if (connect(s, (struct sockaddr *) addr, sizeof(struct sockaddr)) == -1) {
! retval = errno;
! goto out;
}
!
/*
! * Send the message, and wait for a reply, using an exponential
! * backoff. Use the kdc timeout values, just for consistency.
*/
! received = 0;
! for (timeout = krb5_skdc_timeout_1;
! timeout < krb5_max_skdc_timeout;
timeout <<= krb5_skdc_timeout_shift) {
!
! if (send(s, message->data, message->length, 0) != message->length) {
! retval = errno;
! goto out;
! }
!
! waitlen.tv_usec = 0;
! waitlen.tv_sec = timeout;
! FD_ZERO(&readable);
! FD_SET(s, &readable);
! nready = select(1 + s, &readable, 0, 0, &waitlen);
! if (nready < 0) {
! retval = errno;
! goto out;
! } else if (nready == 1) {
! if ((cc = recv(s, reply->data, reply->length, 0)) == -1) {
! retval = errno;
! goto out;
! }
!
! /*
! * We might consider here verifying that the reply came
! * from the host specified, but that check can be fouled
! * by some implementations of some network types which
! * might show a loopback return address, for example, if
! * the server is on the same host as the client.
! *
! * Besides, reply addresses can be spoofed, and we don't
! * want to provide a false sense of security.
! */
! reply->length = cc;
! retval = 0;
! goto out;
! }
! /* else timeout, try again */
}
!
! /* If the loop exits normally, the max timeout expired without */
! /* a reply having arrived. */
! retval = KRB524_NOTRESP;
!
! out:
! (void) close(s);
if (retval) {
! free(reply->data);
! reply->data = 0;
! reply->length = 0;
}
return retval;
}
--- 56,209 ----
extern int krb5_skdc_timeout_1;
int krb524_send_message
! PROTOTYPE((const struct sockaddr * addr, const int naddr,
! const krb5_data * message,
krb5_data * reply));
! int krb524_send_message (addr, naddr, message, reply)
! const struct sockaddr *addr;
! const int naddr;
! const krb5_data *message;
! krb5_data *reply;
{
! register int timeout, host, i;
! int sent, nready;
krb5_error_code retval;
+ SOCKET *socklist;
fd_set readable;
struct timeval waitlen;
! int cc;
! socklist = (SOCKET *)malloc(naddr * sizeof(SOCKET));
! if (socklist == NULL) {
! krb5_xfree(addr);
return ENOMEM;
! }
! for (i = 0; i < naddr; i++)
! socklist[i] = INVALID_SOCKET;
! if (!(reply->data = malloc(krb5_max_dgram_size))) {
! krb5_xfree(addr);
! krb5_xfree(socklist);
! return ENOMEM;
}
! reply->length = krb5_max_dgram_size;
!
! if (SOCKET_INITIALIZE()) { /* PC needs this for some tcp/ip stacks */
! krb5_xfree(socklist);
! free(reply->data);
! return SOCKET_ERRNO;
}
!
/*
! * do exponential backoff.
*/
! for (timeout = krb5_skdc_timeout_1; timeout < krb5_max_skdc_timeout;
timeout <<= krb5_skdc_timeout_shift) {
! sent = 0;
! for (host = 0; host < naddr; host++) {
! /* send to the host, wait timeout seconds for a response,
! then move on. */
! /* cache some sockets for each host */
! if (socklist[host] == INVALID_SOCKET) {
! /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the socket
! creation here will work properly... */
! /*
! * From socket(2):
! *
! * The protocol specifies a particular protocol to be
! * used with the socket. Normally only a single
! * protocol exists to support a particular socket type
! * within a given protocol family.
! */
! socklist[host] = socket(addr[host].sa_family, SOCK_DGRAM, 0);
! if (socklist[host] == INVALID_SOCKET)
! continue; /* try other hosts */
! /* have a socket to send/recv from */
! /* On BSD systems, a connected UDP socket will get connection
! refused and net unreachable errors while an unconnected
! socket will time out, so use connect, send, recv instead of
! sendto, recvfrom. The connect here may return an error if
! the destination host is known to be unreachable. */
! if (connect(socklist[host],
! &addr[host], sizeof(addr[host])) == SOCKET_ERROR)
! continue;
! }
! if (send(socklist[host],
! message->data, message->length, 0) != message->length)
! continue;
! retry:
! waitlen.tv_usec = 0;
! waitlen.tv_sec = timeout;
! FD_ZERO(&readable);
! FD_SET(socklist[host], &readable);
! if (nready = select(SOCKET_NFDS(socklist[host]),
! &readable,
! 0,
! 0,
! &waitlen)) {
! if (nready == SOCKET_ERROR) {
! if (SOCKET_ERRNO == SOCKET_EINTR)
! goto retry;
! retval = SOCKET_ERRNO;
! goto out;
! }
! if ((cc = recv(socklist[host],
! reply->data, reply->length, 0)) == SOCKET_ERROR)
! {
! /* man page says error could be:
! EBADF: won't happen
! ENOTSOCK: it's a socket.
! EWOULDBLOCK: not marked non-blocking, and we selected.
! EINTR: could happen
! EFAULT: we allocated the reply packet.
!
! In addition, net related errors like ECONNREFUSED
! are possble (but undocumented). Assume anything
! other than EINTR is a permanent error for the
! server (i.e. don't set sent = 1).
! */
!
! if (SOCKET_ERRNO == SOCKET_EINTR)
! sent = 1;
! continue;
! }
!
! /* We might consider here verifying that the reply
! came from one of the KDC's listed for that address type,
! but that check can be fouled by some implementations of
! some network types which might show a loopback return
! address, for example, if the KDC is on the same host
! as the client. */
!
! reply->length = cc;
! retval = 0;
! goto out;
! } else if (nready == 0) {
! /* timeout */
! sent = 1;
! }
! /* not ready, go on to next server */
! }
! if (!sent) {
! /* never were able to send to any servers; give up */
! retval = KRB5_KDC_UNREACH;
! break;
! }
}
! retval = KRB5_KDC_UNREACH;
! out:
! SOCKET_CLEANUP(); /* Done with sockets for now */
! for (i = 0; i < naddr; i++)
! if (socklist[i] != INVALID_SOCKET)
! (void) closesocket (socklist[i]);
! krb5_xfree(socklist);
if (retval) {
! free(reply->data);
! reply->data = 0;
! reply->length = 0;
}
return retval;
}
*** ./krb524/,test.c Wed Sep 6 14:54:53 1995
--- ./krb524/test.c Mon Mar 18 09:10:19 1996
***************
*** 313,320 ****
memcpy((char *) &saddr.sin_addr.s_addr, hp->h_addr,
sizeof(struct in_addr));
if ((ret = krb524_convert_creds_addr(context, v5creds, &v4creds,
! (struct sockaddr *) &saddr))) {
com_err("test", ret, "converting credentials on %s",
server);
exit(1);
--- 313,321 ----
memcpy((char *) &saddr.sin_addr.s_addr, hp->h_addr,
sizeof(struct in_addr));
+ /* for test, only use the first addr returned */
if ((ret = krb524_convert_creds_addr(context, v5creds, &v4creds,
! (struct sockaddr *) &saddr, 1))) {
com_err("test", ret, "converting credentials on %s",
server);
exit(1);
*** ./krb524/,krb524.h Mon Jun 5 21:22:14 1995
--- ./krb524/krb524.h Mon Mar 18 08:34:42 1996
***************
*** 32,51 ****
int krb524_convert_tkt_skey
PROTOTYPE((krb5_context context, krb5_ticket *v5tkt, KTEXT_ST *v4tkt,
! krb5_keyblock *skey));
/* conv_princ.c */
int krb524_convert_princs
PROTOTYPE((krb5_context context, krb5_principal client,
krb5_principal server, char *pname,
! char *pinst, char *prealm, char *sname, char *sinst));
/* conv_creds.c */
int krb524_convert_creds_addr
PROTOTYPE((krb5_context context, krb5_creds *v5creds,
! CREDENTIALS *v4creds, struct sockaddr *saddr));
int krb524_convert_creds_kdc
PROTOTYPE((krb5_context context, krb5_creds *v5creds,
--- 32,52 ----
int krb524_convert_tkt_skey
PROTOTYPE((krb5_context context, krb5_ticket *v5tkt, KTEXT_ST *v4tkt,
! krb5_keyblock *skey, krb5_kvno *v4kvno));
/* conv_princ.c */
int krb524_convert_princs
PROTOTYPE((krb5_context context, krb5_principal client,
krb5_principal server, char *pname,
! char *pinst, char *prealm, char *sname, char *sinst,
! int *afsflag));
/* conv_creds.c */
int krb524_convert_creds_addr
PROTOTYPE((krb5_context context, krb5_creds *v5creds,
! CREDENTIALS *v4creds, struct sockaddr *saddr, int naddrs));
int krb524_convert_creds_kdc
PROTOTYPE((krb5_context context, krb5_creds *v5creds,
***************
*** 55,61 ****
int krb524_convert_tkt
PROTOTYPE((krb5_principal server, krb5_data *v5tkt, KTEXT_ST *v4tkt,
! int *kvno, struct sockaddr_in *saddr));
/* encode.c */
--- 56,62 ----
int krb524_convert_tkt
PROTOTYPE((krb5_principal server, krb5_data *v5tkt, KTEXT_ST *v4tkt,
! int *kvno, struct sockaddr_in *saddr, int naddrs));
/* encode.c */
***************
*** 74,80 ****
/* sendmsg.c */
int krb524_send_message
! PROTOTYPE((const struct sockaddr * addr, const krb5_data * message,
krb5_data * reply));
#endif /* __KRB524_H__ */
--- 75,82 ----
/* sendmsg.c */
int krb524_send_message
! PROTOTYPE((const struct sockaddr * addr,
! const int naddr, const krb5_data * message,
krb5_data * reply));
#endif /* __KRB524_H__ */
--IAA25192.827764491/achilles.ctd.anl.gov--