From 7efa8358d8699c1c00c70338f7ebd34e0b63ab7e Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Tue, 12 Aug 1997 01:16:32 +0000 Subject: [PATCH] * convt_tkt.c: Delete; it's not needed anymore * test.c: Remove reference to krb524_convert_creds_addr, as that doesn't exist anymore. * conv_creds.c: Clean up substantially to be less convoluted. * sendmsg.c: Fix to not do a full series of timeouts on each server; loop over the whole list before increasing the timeout. * configure.in: Update to use the new library build system to build libkrb524. * Makefile.in: Update to reflect changes in the library. Also, use the new library build system to build libkrb524. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10167 dc483132-0cff-0310-8789-dd5450dbe970 --- src/krb524/ChangeLog | 18 +++ src/krb524/Makefile.in | 28 ++--- src/krb524/configure.in | 6 +- src/krb524/conv_creds.c | 58 ++++++--- src/krb524/conv_tkt.c | 85 ------------- src/krb524/sendmsg.c | 265 +++++++++++++++++++++++++++------------- src/krb524/test.c | 7 +- 7 files changed, 258 insertions(+), 209 deletions(-) delete mode 100644 src/krb524/conv_tkt.c diff --git a/src/krb524/ChangeLog b/src/krb524/ChangeLog index 092fb55ea..2d46bc210 100644 --- a/src/krb524/ChangeLog +++ b/src/krb524/ChangeLog @@ -1,3 +1,21 @@ +Mon Aug 11 21:12:11 1997 Tom Yu + + * convt_tkt.c: Delete; it's not needed anymore. + + * test.c: Remove reference to krb524_convert_creds_addr, as that + doesn't exist anymore. + + * conv_creds.c: Clean up substantially to be less convoluted. + + * sendmsg.c: Fix to not do a full series of timeouts on each + server; loop over the whole list before increasing the timeout. + + * configure.in: Update to use the new library build system to + build libkrb524. + + * Makefile.in: Update to reflect changes in the library. Also, + use the new library build system to build libkrb524. + Thu Aug 7 17:34:59 1997 Tom Yu * cnv_tkt_skey.c: diff --git a/src/krb524/Makefile.in b/src/krb524/Makefile.in index 802d95696..05f991d4f 100644 --- a/src/krb524/Makefile.in +++ b/src/krb524/Makefile.in @@ -19,30 +19,32 @@ # PERFORMANCE OF THIS SOFTWARE. # +LIB=krb524 +LIBMAJOR=1 +LIBMINOR=0 +RELDIR=../krb524 +STOBJLISTS=OBJS.ST + CFLAGS = $(CCOPTS) -DUSE_MASTER $(DEFS) $(LOCALINCLUDE) PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH) PROG_RPATH=$(KRB5_LIBDIR) - -all:: - KRB524_DEPLIB = libkrb524.a KRB524_LIB = libkrb524.a LOCALINCLUDE= $(KRB4_INCLUDES) -I. -I$(srcdir) # Library sources -SRCS = conv_creds.c conv_princ.c conv_tkt.c cnv_tkt_skey.c \ +SRCS = conv_creds.c conv_princ.c cnv_tkt_skey.c \ encode.c misc.c globals.c sendmsg.c krb524_err.et -OBJS = conv_creds.o conv_princ.o conv_tkt.o cnv_tkt_skey.o \ +STLIBOBJS = conv_creds.o conv_princ.o cnv_tkt_skey.o \ encode.o misc.o globals.o sendmsg.o krb524_err.o GENS = krb524_err.c krb524_err.h -all:: $(GENS) libkrb524.a krb524d krb524test k524init +all:: $(GENS) +all:: all-libs -libkrb524.a: $(OBJS) - $(ARADD) $@ $(OBJS) - $(RANLIB) $@ +all:: krb524d krb524test k524init krb524test: libkrb524.a test.o $(KRB524_DEPLIB) $(KRB4COMPAT_DEPLIBS) $(CC_LINK) -o krb524test test.o $(KRB524_LIB) $(KRB4COMPAT_LIBS) @@ -53,12 +55,10 @@ krb524d: krb524d.o $(KADMSRV_DEPLIBS) $(KRB524_DEPLIB) $(KRB4COMPAT_DEPLIBS) k524init: k524init.o $(KRB524_DEPLIB) $(KRB4COMPAT_DEPLIBS) $(CC_LINK) -o k524init k524init.o $(KRB524_LIB) $(KRB4COMPAT_LIBS) -install:: - $(INSTALL_DATA) libkrb524.a $(DESTDIR)$(KRB5_LIBDIR)/libkrb524.a - $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libkrb524.a +install:: install-libs $(INSTALL_PROGRAM) krb524d $(DESTDIR)$(SERVER_BINDIR)/krb524d $(INSTALL_PROGRAM) k524init $(DESTDIR)$(CLIENT_BINDIR)/krb524init -clean:: - $(RM) libkrb524.a $(OBJS) $(GENS) core *~ *.bak #* +clean:: clean-libs clean-libobjs + $(RM) $(OBJS) $(GENS) core *~ *.bak #* $(RM) krb524test krb524d k524init test.o krb524d.o k524init.o diff --git a/src/krb524/configure.in b/src/krb524/configure.in index bf967c1cf..de61ccf6c 100644 --- a/src/krb524/configure.in +++ b/src/krb524/configure.in @@ -1,9 +1,7 @@ AC_INIT(krb524d.c) CONFIG_RULES -AC_PROG_ARCHIVE -AC_PROG_ARCHIVE_ADD -AC_PROG_RANLIB -AC_PROG_INSTALL +KRB5_BUILD_LIBRARY_STATIC +KRB5_BUILD_LIBOBJS AC_PROG_AWK AC_CHECK_HEADERS(sys/select.h) dnl AC_TYPE_SIGNAL diff --git a/src/krb524/conv_creds.c b/src/krb524/conv_creds.c index 1e30fa5cd..7ae810e13 100644 --- a/src/krb524/conv_creds.c +++ b/src/krb524/conv_creds.c @@ -30,36 +30,56 @@ #include "krb524.h" -int krb524_convert_creds_plain +krb5_error_code krb524_convert_creds_plain KRB5_PROTOTYPE((krb5_context context, krb5_creds *v5creds, CREDENTIALS *v4creds)); +krb5_error_code krb524_sendto_kdc +KRB5_PROTOTYPE((krb5_context context, const krb5_data *message, + krb5_data *realm, krb5_data *reply)); -int krb524_convert_creds_addr(context, v5creds, v4creds, saddr) +krb5_error_code +krb524_convert_creds_kdc(context, v5creds, v4creds) krb5_context context; krb5_creds *v5creds; CREDENTIALS *v4creds; - struct sockaddr *saddr; { - int ret; + krb5_error_code ret; + krb5_data reply; + char *p; - if ((ret = krb524_convert_creds_plain(context, v5creds, v4creds))) - return ret; + ret = krb524_convert_creds_plain(context, v5creds, v4creds); + if (ret) + return ret; + + reply.data = NULL; + ret = krb524_sendto_kdc(context, &v5creds->ticket, + &v5creds->server->realm, &reply); + if (ret) + return ret; + + p = reply.data; + ret = ntohl(*((krb5_error_code *) p)); + p += sizeof(krb5_error_code); + reply.length -= sizeof(krb5_error_code); + if (ret) + goto fail; + + v4creds->kvno = ntohl(*((krb5_error_code *) p)); + p += sizeof(int); + reply.length -= sizeof(int); + ret = decode_v4tkt(&v4creds->ticket_st, p, &reply.length); - return krb524_convert_tkt(v5creds->server, &v5creds->ticket, - &v4creds->ticket_st, - &v4creds->kvno, - (struct sockaddr_in *) saddr); +fail: + if (reply.data) + free(reply.data); + reply.data = NULL; + return ret; } -int krb524_convert_creds_kdc(context, v5creds, v4creds) - krb5_context context; - krb5_creds *v5creds; - CREDENTIALS *v4creds; +#if 0 +int broken() { - struct sockaddr_in *addrs; - int ret, naddrs, i; - if ((ret = krb5_locate_kdc(context, &v5creds->server->realm, &addrs, &naddrs))) return ret; @@ -92,8 +112,10 @@ int krb524_convert_creds_kdc(context, v5creds, v4creds) free(addrs); return ret; } +#endif -int krb524_convert_creds_plain(context, v5creds, v4creds) +krb5_error_code +krb524_convert_creds_plain(context, v5creds, v4creds) krb5_context context; krb5_creds *v5creds; CREDENTIALS *v4creds; diff --git a/src/krb524/conv_tkt.c b/src/krb524/conv_tkt.c deleted file mode 100644 index be0d055f7..000000000 --- a/src/krb524/conv_tkt.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 1994 by OpenVision Technologies, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appears in all copies and - * that both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of OpenVision not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. OpenVision makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "krb5.h" -#include -#include "krb524.h" - -/* - * 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; - status = ntohl(*((krb5_error_code *) p)); - p += sizeof(krb5_error_code); - reply.length -= sizeof(krb5_error_code); - if (status) { - ret = status; - goto fail; - } - *kvno = ntohl(*((krb5_error_code *) p)); - p += sizeof(int); - reply.length -= sizeof(int); - ret = decode_v4tkt(v4tkt, p, &reply.length); - -fail: - if (ret) { - if (reply.data) - free(reply.data); - reply.data = NULL; - reply.length = 0; - } - - return ret; -} - diff --git a/src/krb524/sendmsg.c b/src/krb524/sendmsg.c index 4c7c8b748..5281359a9 100644 --- a/src/krb524/sendmsg.c +++ b/src/krb524/sendmsg.c @@ -1,5 +1,5 @@ /* - * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,1997 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -22,15 +22,16 @@ * backoff retry algorithm. This is based on krb5_sendto_kdc. */ -#include "krb5.h" +/* Grab socket stuff. This might want to go away later. */ +#define NEED_SOCKETS +#define NEED_LOWLEVEL_IO +#include "k5-int.h" #include #include #include -#include -#include + #include -#include #ifdef _AIX #include @@ -39,9 +40,18 @@ #include #include "krb524.h" +/* Cheat and grab this internal function from lib/krb5/os. */ +krb5_error_code krb5_locate_kdc + PROTOTYPE((krb5_context, const krb5_data *, + struct sockaddr **, int *)); + /* - * Send the formatted request 'message' to the host/port specified in - * addr and return the response (if any) in 'reply'. + * krb524_sendto_kdc: + * + * A slightly modified version of krb5_sendto_kdc. + * + * send the formatted request 'message' to a KDC for realm 'realm' and + * return the response (if any) in 'reply'. * * If the message is sent and a response is received, 0 is returned, * otherwise an error code is returned. @@ -55,103 +65,184 @@ extern int krb5_max_skdc_timeout; extern int krb5_skdc_timeout_shift; extern int krb5_skdc_timeout_1; -int krb524_send_message - KRB5_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; +krb5_error_code +krb524_sendto_kdc (context, message, realm, reply) + krb5_context context; + const krb5_data * message; + const krb5_data * realm; + krb5_data * reply; { - register int timeout; - int nready, received; + register int timeout, host, i; + struct sockaddr *addr; + int naddr; + struct servent *serv; + int sent, nready; krb5_error_code retval; + SOCKET *socklist; fd_set readable; struct timeval waitlen; - int s, cc; - - if ((reply->data = malloc(krb5_max_dgram_size)) == NULL) + int cc; + + /* + * find KDC location(s) for realm + */ + + if (retval = krb5_locate_kdc (context, realm, &addr, &naddr)) + return retval; + if (naddr == 0) + return KRB5_REALM_UNKNOWN; + + socklist = (SOCKET *)malloc(naddr * sizeof(SOCKET)); + if (socklist == NULL) { + free(addr); return ENOMEM; - reply->length = krb5_max_dgram_size; + } + for (i = 0; i < naddr; i++) + socklist[i] = INVALID_SOCKET; - /* 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; + /* + * Bash the ports numbers. + */ + serv = getservbyname(KRB524_SERVICE, "udp"); + for (i = 0; i < naddr; i++) + if (serv) + ((struct sockaddr_in *)&addr[i])->sin_port = serv->s_port; + else + ((struct sockaddr_in *)&addr[i])->sin_port = htons(KRB524_PORT); + + if (!(reply->data = malloc(krb5_max_dgram_size))) { + free(addr); + free(socklist); + return ENOMEM; } - + reply->length = krb5_max_dgram_size; + +#if 0 /* - * 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. + * Not needed for Windows, since it's done by the DLL + * initialization. XXX What about for the Macintosh? + * + * See below for commented out SOCKET_CLEANUP() */ - if (connect(s, (struct sockaddr *) addr, sizeof(struct sockaddr)) == -1) { - retval = errno; - goto out; + if (SOCKET_INITIALIZE()) { /* PC needs this for some tcp/ip stacks */ + free(addr); + free(socklist); + free(reply->data); + return SOCKET_ERRNO; } - +#endif + /* - * Send the message, and wait for a reply, using an exponential - * backoff. Use the kdc timeout values, just for consistency. + * do exponential backoff. */ - received = 0; - for (timeout = krb5_skdc_timeout_1; - timeout < krb5_max_skdc_timeout; + 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 */ - } + 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 the loop exits normally, the max timeout expired without */ - /* a reply having arrived. */ - retval = KRB524_NOTRESP; + if (SOCKET_ERRNO == SOCKET_EINTR) + sent = 1; + continue; + } -out: - (void) close(s); + /* 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: + for (i = 0; i < naddr; i++) + if (socklist[i] != INVALID_SOCKET) + (void) closesocket (socklist[i]); +#if 0 + SOCKET_CLEANUP(); /* Done with sockets for now */ +#endif + free(addr); + free(socklist); if (retval) { - free(reply->data); - reply->data = 0; - reply->length = 0; + free(reply->data); + reply->data = 0; + reply->length = 0; } return retval; } diff --git a/src/krb524/test.c b/src/krb524/test.c index 50b1e5594..281c897e2 100644 --- a/src/krb524/test.c +++ b/src/krb524/test.c @@ -227,12 +227,14 @@ int main(argc, argv) while (argc) { if (strcmp(*argv, "-local") == 0) local++; +#if 0 else if (strcmp(*argv, "-remote") == 0) { argc--; argv++; if (!argc) usage(); remote = *argv; } +#endif else break; argc--; argv++; @@ -306,6 +308,7 @@ void do_remote(context, v5creds, server, key) printf("\nV5 credentials:\n"); krb5_print_creds(context, v5creds, key); +#if 0 if (strcmp(server, "kdc") != 0) { hp = gethostbyname(server); if (hp == NULL) { @@ -323,7 +326,9 @@ void do_remote(context, v5creds, server, key) server); exit(1); } - } else { + } else +#endif + { if ((ret = krb524_convert_creds_kdc(context, v5creds, &v4creds))) { com_err("test", ret, "converting credentials via kdc"); exit(1); -- 2.26.2