2002-06-25 Ken Raeburn <raeburn@mit.edu>
+ * compat_recv.c: New file, moved from lib/krb5util.
+ * Makefile.in (SRCS, OBJS): Include it.
+ (rcp, kshd, klogind): Link against it instead of krb5util
+ library.
+ * defines.h (krb5_compat_recvauth, krb5_compat_recvauth_version):
+ Move declarations here from include/k5-util.h.
+ (princ_maps_to_lname): Declare.
+
+ * kcmd.c (kcmd_connect): Use strdup when copying hostname.
+ (princ_maps_to_lname, default_realm): Move functions here...
+ * krlogind.c (princ_maps_to_lname, default_realm): ...from here.
+ (recvauth): Use sockaddr_storage to hold addresses.
+ * krshd.c (default_realm, princ_maps_to_lname): Deleted.
+ (recvauth): Take sockaddr pointer argument instead of
+ sockaddr_in. Use getnameinfo to extract port number string.
+ (remote_addr, remote_port, local_addr, local_port): Make buffers
+ bigger.
+ (doit): Use sockaddr_storage for local address. Get rid of all
+ settings of non_privileged, since it's never used. Don't copy
+ remote address to local variable. Use getnameinfo instead of
+ inet_ntoa to format addresses and port numbers for environment
+ variables.
+
* krsh.c (SECURE_MESSAGE): Only indicate that input/output data
are being encrypted, and don't automatically say it's with DES.
KRSHDLIBS=@KRSHDLIBS@
SRCS= $(srcdir)/krcp.c $(srcdir)/krlogin.c $(srcdir)/krsh.c $(srcdir)/kcmd.c \
- $(srcdir)/forward.c \
+ $(srcdir)/forward.c $(srcdir)/compat_recv.c \
$(srcdir)/login.c $(srcdir)/krshd.c $(srcdir)/krlogind.c \
$(srcdir)/v4rcp.c
-OBJS= krcp.o krlogin.o krsh.o kcmd.o forward.o $(SETENVOBJ) \
+OBJS= krcp.o krlogin.o krsh.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) \
login.o krshd.o krlogind.o $(V4RCPO) $(LIBOBJS)
UCB_RLOGIN = @UCB_RLOGIN@
rsh: krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o rsh krsh.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
-rcp: krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(UTIL_DEPLIB) $(KRB4COMATP_DEPLIBS)
- $(CC_LINK) -o rcp krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(UTIL_LIB) $(KRB4COMPAT_LIBS)
+rcp: krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMATP_DEPLIBS)
+ $(CC_LINK) -o rcp krcp.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
v4rcp: v4rcp.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_DEPLIBS)
$(CC_LINK) -o v4rcp v4rcp.o $(SETENVOBJ) $(LIBOBJS) $(KRB4COMPAT_LIBS)
${DESTDIR}$(CLIENT_MANDIR)/`echo $$f|sed '$(transform)'`.1; \
fi
-kshd: krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(UTIL_DEPLIB) $(KRB4COMPAT_DEPLIBS)
- $(CC_LINK) -o kshd krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRSHDLIBS) $(PTY_LIB) $(UTIL_LIB) $(KRB4COMPAT_LIBS)
+kshd: krshd.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB4COMPAT_DEPLIBS)
+ $(CC_LINK) -o kshd krshd.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(KRSHDLIBS) $(PTY_LIB) $(KRB4COMPAT_LIBS)
-klogind: krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(UTIL_DEPLIB) $(KRB4COMPAT_DEPLIBS)
- $(CC_LINK) -o klogind krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_LIB) $(UTIL_LIB) $(KRB4COMPAT_LIBS)
+klogind: krlogind.o kcmd.o forward.o compat_recv.o $(SETENVOBJ) $(LIBOBJS) $(PTY_DEPLIB) $(KRB4COMPAT_DEPLIBS)
+ $(CC_LINK) -o klogind krlogind.o kcmd.o forward.o $(SETENVOBJ) $(LIBOBJS) $(PTY_LIB) $(KRB4COMPAT_LIBS)
install::
for f in kshd klogind; do \
# the Makefile.in file
#
$(OUTPRE)krcp.$(OBJEXT): krcp.c $(BUILDTOP)/include/krb5.h \
- $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/krb.h \
- $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/port-sockets.h \
- $(BUILDTOP)/include/krb5/autoconf.h defines.h $(SRCTOP)/include/fake-addrinfo.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/des.h \
+ $(SRCTOP)/include/port-sockets.h defines.h $(SRCTOP)/include/fake-addrinfo.h \
$(SRCTOP)/include/socket-utils.h
$(OUTPRE)krlogin.$(OBJEXT): krlogin.c $(BUILDTOP)/include/krb5.h \
$(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/krb.h \
$(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/port-sockets.h \
$(BUILDTOP)/include/krb5/autoconf.h defines.h $(SRCTOP)/include/fake-addrinfo.h \
$(SRCTOP)/include/socket-utils.h
-$(OUTPRE)kcmd.$(OBJEXT): kcmd.c $(BUILDTOP)/include/krb5.h \
+$(OUTPRE)kcmd.$(OBJEXT): kcmd.c $(SRCTOP)/include/fake-addrinfo.h \
+ $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/socket-utils.h $(BUILDTOP)/include/krb5.h \
$(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/krb.h \
- $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/port-sockets.h \
- $(BUILDTOP)/include/krb5/autoconf.h defines.h $(SRCTOP)/include/fake-addrinfo.h \
- $(SRCTOP)/include/socket-utils.h
+ $(SRCTOP)/include/kerberosIV/des.h defines.h
$(OUTPRE)forward.$(OBJEXT): forward.c $(SRCTOP)/include/k5-int.h \
$(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5/kdb.h \
$(BUILDTOP)/include/profile.h defines.h $(SRCTOP)/include/fake-addrinfo.h \
$(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h
+$(OUTPRE)compat_recv.$(OBJEXT): compat_recv.c $(SRCTOP)/include/k5-int.h \
+ $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ $(BUILDTOP)/include/profile.h $(SRCTOP)/include/kerberosIV/krb.h \
+ $(SRCTOP)/include/kerberosIV/des.h
$(OUTPRE)login.$(OBJEXT): login.c $(BUILDTOP)/include/libpty.h \
$(SRCTOP)/include/syslog.h $(SRCTOP)/include/k5-int.h \
$(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-util.h \
defines.h $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/socket-utils.h
$(OUTPRE)krlogind.$(OBJEXT): krlogind.c $(SRCTOP)/include/syslog.h \
+ $(SRCTOP)/include/fake-addrinfo.h $(SRCTOP)/include/port-sockets.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/socket-utils.h \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/kerberosIV/krb.h \
- $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/port-sockets.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(BUILDTOP)/include/libpty.h \
- $(SRCTOP)/include/k5-util.h defines.h $(SRCTOP)/include/fake-addrinfo.h \
- $(SRCTOP)/include/socket-utils.h
+ $(SRCTOP)/include/kerberosIV/des.h $(BUILDTOP)/include/libpty.h \
+ $(SRCTOP)/include/k5-util.h defines.h
$(OUTPRE)v4rcp.$(OBJEXT): v4rcp.c $(BUILDTOP)/include/krb5.h \
- $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h $(SRCTOP)/include/kerberosIV/krb.h \
- $(SRCTOP)/include/kerberosIV/des.h $(SRCTOP)/include/port-sockets.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/kerberosIV/krbports.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-util.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/kerberosIV/krb.h $(SRCTOP)/include/kerberosIV/des.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/kerberosIV/krbports.h \
rpaths.h
--- /dev/null
+/*
+ * lib/krb5/krb/compat_recv.c
+ *
+ * Copyright 1993 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.
+ *
+ *
+ * convenience sendauth/recvauth functions, with compatibility with V4
+ * recvauth.
+ *
+ * NOTE: linking in this function will pull in V4 kerberos routines.
+ *
+ * WARNING: In the V4-style arguments, the ticket and kdata arguments
+ * have different types than the V4 recvauth; in V4, they were KTEXT
+ * and AUTH_DAT *, respectively. Here, they are KTEXT * and AUTH_DAT **
+ * and they are allocated by recvauth if and only if we end up talking
+ * to a V4 sendauth.
+ */
+
+#define NEED_SOCKETS
+#include "k5-int.h"
+#if !defined(_MACINTOSH)
+#include <kerberosIV/krb.h>
+#include "com_err.h"
+#include <errno.h>
+
+#include <stdio.h>
+#include <string.h>
+
+static int krb_v4_recvauth(long options, int fd, KTEXT ticket,
+ char *service, char *instance,
+ struct sockaddr_in *faddr,
+ struct sockaddr_in *laddr,
+ AUTH_DAT *kdata,
+ char *filename,
+ Key_schedule schedule,
+ char *version);
+
+#define KRB_V4_SENDAUTH_VERS "AUTHV0.1" /* MUST be 8 chars long */
+#define KRB_V5_SENDAUTH_VERS "KRB5_SENDAUTH_V1.0"
+
+#define KRB5_RECVAUTH_V4 4
+#define KRB5_RECVAUTH_V5 5
+
+krb5_error_code
+krb5_compat_recvauth(context, auth_context,
+ /* IN */
+ fdp, appl_version, server, flags, keytab,
+ v4_options, v4_service, v4_instance, v4_faddr, v4_laddr,
+ v4_filename,
+ /* OUT */
+ ticket,
+ auth_sys, v4_kdata, v4_schedule, v4_version)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ krb5_pointer fdp;
+ char *appl_version;
+ krb5_principal server;
+ krb5_int32 flags;
+ krb5_keytab keytab;
+ krb5_ticket ** ticket;
+ krb5_int32 *auth_sys;
+
+ /*
+ * Version 4 arguments
+ */
+ krb5_int32 v4_options; /* bit-pattern of options */
+ char *v4_service; /* service expected */
+ char *v4_instance; /* inst expected (may be filled in) */
+ struct sockaddr_in *v4_faddr; /* foreign address */
+ struct sockaddr_in *v4_laddr; /* local address */
+ AUTH_DAT **v4_kdata; /* kerberos data (returned) */
+ char *v4_filename; /* name of file with service keys */
+ Key_schedule v4_schedule; /* key schedule (return) */
+ char *v4_version; /* version string (filled in) */
+{
+ union verslen {
+ krb5_int32 len;
+ char vers[4];
+ } vers;
+ char *buf;
+ int len, length;
+ krb5_int32 retval;
+ int fd = *( (int *) fdp);
+#ifdef KRB5_KRB4_COMPAT
+ KTEXT v4_ticket; /* storage for client's ticket */
+#endif
+
+ if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+ return((retval < 0) ? errno : ECONNABORTED);
+
+#ifdef KRB5_KRB4_COMPAT
+ if (!strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) {
+ /*
+ * We must be talking to a V4 sendauth; read in the
+ * rest of the version string and make sure.
+ */
+ if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+ return((retval < 0) ? errno : ECONNABORTED);
+
+ if (strncmp(vers.vers, KRB_V4_SENDAUTH_VERS+4, 4))
+ return KRB5_SENDAUTH_BADAUTHVERS;
+
+ *auth_sys = KRB5_RECVAUTH_V4;
+
+ *v4_kdata = (AUTH_DAT *) malloc( sizeof(AUTH_DAT) );
+ v4_ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
+
+ retval = krb_v4_recvauth(v4_options, fd, v4_ticket,
+ v4_service, v4_instance, v4_faddr,
+ v4_laddr, *v4_kdata, v4_filename,
+ v4_schedule, v4_version);
+ krb5_xfree(v4_ticket);
+ /*
+ * XXX error code translation?
+ */
+ switch (retval) {
+ case RD_AP_OK:
+ return 0;
+ case RD_AP_TIME:
+ return KRB5KRB_AP_ERR_SKEW;
+ case RD_AP_EXP:
+ return KRB5KRB_AP_ERR_TKT_EXPIRED;
+ case RD_AP_NYV:
+ return KRB5KRB_AP_ERR_TKT_NYV;
+ case RD_AP_NOT_US:
+ return KRB5KRB_AP_ERR_NOT_US;
+ case RD_AP_UNDEC:
+ return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ case RD_AP_REPEAT:
+ return KRB5KRB_AP_ERR_REPEAT;
+ case RD_AP_MSG_TYPE:
+ return KRB5KRB_AP_ERR_MSG_TYPE;
+ case RD_AP_MODIFIED:
+ return KRB5KRB_AP_ERR_MODIFIED;
+ case RD_AP_ORDER:
+ return KRB5KRB_AP_ERR_BADORDER;
+ case RD_AP_BADD:
+ return KRB5KRB_AP_ERR_BADADDR;
+ default:
+ return KRB5_SENDAUTH_BADRESPONSE;
+ }
+ }
+#endif
+
+ /*
+ * Assume that we're talking to a V5 recvauth; read in the
+ * the version string, and make sure it matches.
+ */
+
+ len = (int) ntohl(vers.len);
+
+ if (len < 0 || len > 255)
+ return KRB5_SENDAUTH_BADAUTHVERS;
+
+ buf = malloc(len);
+ if (!buf)
+ return ENOMEM;
+
+ length = krb5_net_read(context, fd, buf, len);
+ if (len != length) {
+ krb5_xfree(buf);
+ if (len < 0)
+ return errno;
+ else
+ return ECONNABORTED;
+ }
+
+ if (strcmp(buf, KRB_V5_SENDAUTH_VERS)) {
+ krb5_xfree(buf);
+ return KRB5_SENDAUTH_BADAUTHVERS;
+ }
+ krb5_xfree(buf);
+
+ *auth_sys = KRB5_RECVAUTH_V5;
+
+ retval = krb5_recvauth(context, auth_context, fdp, appl_version, server,
+ flags | KRB5_RECVAUTH_SKIP_VERSION,
+ keytab, ticket);
+
+ return retval;
+}
+
+krb5_error_code
+krb5_compat_recvauth_version(context, auth_context,
+ /* IN */
+ fdp, server, flags, keytab,
+ v4_options, v4_service, v4_instance, v4_faddr,
+ v4_laddr,
+ v4_filename,
+ /* OUT */
+ ticket,
+ auth_sys, v4_kdata, v4_schedule,
+ version)
+ krb5_context context;
+ krb5_auth_context *auth_context;
+ krb5_pointer fdp;
+ krb5_principal server;
+ krb5_int32 flags;
+ krb5_keytab keytab;
+ krb5_ticket ** ticket;
+ krb5_int32 *auth_sys;
+
+ /*
+ * Version 4 arguments
+ */
+ krb5_int32 v4_options; /* bit-pattern of options */
+ char *v4_service; /* service expected */
+ char *v4_instance; /* inst expected (may be filled in) */
+ struct sockaddr_in *v4_faddr; /* foreign address */
+ struct sockaddr_in *v4_laddr; /* local address */
+ AUTH_DAT **v4_kdata; /* kerberos data (returned) */
+ char *v4_filename; /* name of file with service keys */
+ Key_schedule v4_schedule; /* key schedule (return) */
+ krb5_data *version; /* application version filled in */
+{
+ union verslen {
+ krb5_int32 len;
+ char vers[4];
+ } vers;
+ char *buf;
+ int len, length;
+ krb5_int32 retval;
+ int fd = *( (int *) fdp);
+#ifdef KRB5_KRB4_COMPAT
+ KTEXT v4_ticket; /* storage for client's ticket */
+#endif
+
+ if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+ return((retval < 0) ? errno : ECONNABORTED);
+
+#ifdef KRB5_KRB4_COMPAT
+ if (!strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) {
+ /*
+ * We must be talking to a V4 sendauth; read in the
+ * rest of the version string and make sure.
+ */
+ if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4)
+ return((retval < 0) ? errno : ECONNABORTED);
+
+ if (strncmp(vers.vers, KRB_V4_SENDAUTH_VERS+4, 4))
+ return KRB5_SENDAUTH_BADAUTHVERS;
+
+ *auth_sys = KRB5_RECVAUTH_V4;
+
+ *v4_kdata = (AUTH_DAT *) malloc( sizeof(AUTH_DAT) );
+ v4_ticket = (KTEXT) malloc(sizeof(KTEXT_ST));
+
+ version->length = KRB_SENDAUTH_VLEN; /* no trailing \0! */
+ version->data = malloc (KRB_SENDAUTH_VLEN + 1);
+ version->data[KRB_SENDAUTH_VLEN] = 0;
+ if (version->data == 0)
+ return errno;
+ retval = krb_v4_recvauth(v4_options, fd, v4_ticket,
+ v4_service, v4_instance, v4_faddr,
+ v4_laddr, *v4_kdata, v4_filename,
+ v4_schedule, version->data);
+ krb5_xfree(v4_ticket);
+ /*
+ * XXX error code translation?
+ */
+ switch (retval) {
+ case RD_AP_OK:
+ return 0;
+ case RD_AP_TIME:
+ return KRB5KRB_AP_ERR_SKEW;
+ case RD_AP_EXP:
+ return KRB5KRB_AP_ERR_TKT_EXPIRED;
+ case RD_AP_NYV:
+ return KRB5KRB_AP_ERR_TKT_NYV;
+ case RD_AP_NOT_US:
+ return KRB5KRB_AP_ERR_NOT_US;
+ case RD_AP_UNDEC:
+ return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ case RD_AP_REPEAT:
+ return KRB5KRB_AP_ERR_REPEAT;
+ case RD_AP_MSG_TYPE:
+ return KRB5KRB_AP_ERR_MSG_TYPE;
+ case RD_AP_MODIFIED:
+ return KRB5KRB_AP_ERR_MODIFIED;
+ case RD_AP_ORDER:
+ return KRB5KRB_AP_ERR_BADORDER;
+ case RD_AP_BADD:
+ return KRB5KRB_AP_ERR_BADADDR;
+ default:
+ return KRB5_SENDAUTH_BADRESPONSE;
+ }
+ }
+#endif
+
+ /*
+ * Assume that we're talking to a V5 recvauth; read in the
+ * the version string, and make sure it matches.
+ */
+
+ len = (int) ntohl(vers.len);
+
+ if (len < 0 || len > 255)
+ return KRB5_SENDAUTH_BADAUTHVERS;
+
+ buf = malloc(len);
+ if (!buf)
+ return ENOMEM;
+
+ length = krb5_net_read(context, fd, buf, len);
+ if (len != length) {
+ krb5_xfree(buf);
+ if (len < 0)
+ return errno;
+ else
+ return ECONNABORTED;
+ }
+
+ if (strcmp(buf, KRB_V5_SENDAUTH_VERS)) {
+ krb5_xfree(buf);
+ return KRB5_SENDAUTH_BADAUTHVERS;
+ }
+ krb5_xfree(buf);
+
+ *auth_sys = KRB5_RECVAUTH_V5;
+
+ retval = krb5_recvauth_version(context, auth_context, fdp, server,
+ flags | KRB5_RECVAUTH_SKIP_VERSION,
+ keytab, ticket, version);
+
+ return retval;
+}
+
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+#ifdef KRB5_KRB4_COMPAT
+static int
+krb_v4_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
+ filename, schedule, version)
+long options; /* bit-pattern of options */
+int fd; /* file descr. to read from */
+KTEXT ticket; /* storage for client's ticket */
+char *service; /* service expected */
+char *instance; /* inst expected (may be filled in) */
+struct sockaddr_in *faddr; /* address of foreign host on fd */
+struct sockaddr_in *laddr; /* local address */
+AUTH_DAT *kdata; /* kerberos data (returned) */
+char *filename; /* name of file with service keys */
+Key_schedule schedule; /* key schedule (return) */
+char *version; /* version string (filled in) */
+{
+ int cc, old_vers = 0;
+ int rem;
+ krb5_int32 tkt_len, priv_len;
+ krb5_ui_4 cksum;
+ u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
+
+ /* read the application version string */
+ if ((krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
+ KRB_SENDAUTH_VLEN))
+ return(errno);
+ version[KRB_SENDAUTH_VLEN] = '\0';
+
+ /* get the length of the ticket */
+ if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
+ sizeof(tkt_len))
+ return(errno);
+
+ /* sanity check */
+ ticket->length = ntohl((unsigned long)tkt_len);
+ if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
+ if (options & KOPT_DO_MUTUAL) {
+ rem = KFAILURE;
+ goto mutual_fail;
+ } else
+ return(KFAILURE); /* XXX there may still be junk on the fd? */
+ }
+
+ /* read the ticket */
+ if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
+ != ticket->length)
+ return(errno);
+
+ /*
+ * now have the ticket. decrypt it to get the authenticated
+ * data.
+ */
+ rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
+ kdata,filename);
+
+ if (old_vers) return(rem); /* XXX can't do mutual with old client */
+
+ /* if we are doing mutual auth, compose a response */
+ if (options & KOPT_DO_MUTUAL) {
+ if (rem != KSUCCESS)
+ /* the krb_rd_req failed */
+ goto mutual_fail;
+
+ /* add one to the (formerly) sealed checksum, and re-seal it
+ for return to the client */
+ cksum = kdata->checksum + 1;
+ cksum = htonl(cksum);
+#ifndef NOENCRYPTION
+ key_sched(kdata->session,schedule);
+#endif /* !NOENCRYPTION */
+ priv_len = krb_mk_priv((unsigned char *)&cksum,
+ tmp_buf,
+ (unsigned long) sizeof(cksum),
+ schedule,
+ &kdata->session,
+ laddr,
+ faddr);
+ if (priv_len < 0) {
+ /* re-sealing failed; notify the client */
+ rem = KFAILURE; /* XXX */
+mutual_fail:
+ priv_len = -1;
+ tkt_len = htonl((unsigned long) priv_len);
+ /* a length of -1 is interpreted as an authentication
+ failure by the client */
+ if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+ != sizeof(tkt_len))
+ return(cc);
+ return(rem);
+ } else {
+ /* re-sealing succeeded, send the private message */
+ tkt_len = htonl((unsigned long)priv_len);
+ if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+ != sizeof(tkt_len))
+ return(cc);
+ if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
+ != (int) priv_len)
+ return(cc);
+ }
+ }
+ return(rem);
+}
+#endif
+#endif
krb5_data *inbuf, krb5_ticket *ticket,
krb5_ccache *ccache);
+
+int princ_maps_to_lname(krb5_principal principal, char *luser);
+
#ifdef NEED_SETENV
extern int setenv(char *, char *, int);
#endif
#include "fake-addrinfo.h"
+
+#ifdef KRB_DEFS
+krb5_error_code krb5_compat_recvauth(krb5_context, krb5_auth_context *,
+ krb5_pointer, char *, krb5_principal,
+ krb5_int32, krb5_keytab,
+ krb5_int32, char *, char *,
+ struct sockaddr_in *,
+ struct sockaddr_in *, char *,
+ krb5_ticket **, krb5_int32 *,
+ AUTH_DAT **, Key_schedule, char *);
+
+krb5_error_code
+krb5_compat_recvauth_version(krb5_context, krb5_auth_context *,
+ krb5_pointer, krb5_principal, krb5_int32,
+ krb5_keytab, krb5_int32, char *, char *,
+ struct sockaddr_in *, struct sockaddr_in *,
+ char *, krb5_ticket **, krb5_int32*,
+ AUTH_DAT **, Key_schedule, krb5_data *);
+#endif
#include <netinet/in.h>
#include <netdb.h>
-
+
#include <errno.h>
#include <krb5.h>
#ifdef KRB5_KRB4_COMPAT
return -1;
}
- *host_save = malloc(strlen(ap->ai_canonname) + 1);
- if (*host_save == NULL) {
- fprintf(stderr, "kcmd: no memory\n");
- freeaddrinfo(ap);
- return -1;
- }
- strcpy(*host_save, ap->ai_canonname);
+ *host_save = strdup(ap->ai_canonname ? ap->ai_canonname : hname);
for (ap2 = ap; ap; ap = ap->ai_next) {
char hostbuf[NI_MAXHOST];
(void) strcpy(ret,sp);
return(ret);
}
-
#endif
+
+/* Server side authentication, etc */
+
+int princ_maps_to_lname(principal, luser)
+ krb5_principal principal;
+ char *luser;
+{
+ char kuser[10];
+ if (!(krb5_aname_to_localname(bsd_context, principal,
+ sizeof(kuser), kuser))
+ && (strcmp(kuser, luser) == 0)) {
+ return 1;
+ }
+ return 0;
+}
+
+int default_realm(principal)
+ krb5_principal principal;
+{
+ char *def_realm;
+ unsigned int realm_length;
+ int retval;
+
+ realm_length = krb5_princ_realm(bsd_context, principal)->length;
+
+ if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
+ return 0;
+ }
+
+ if ((realm_length != strlen(def_realm)) ||
+ (memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data,
+ realm_length))) {
+ free(def_realm);
+ return 0;
+ }
+ free(def_realm);
+ return 1;
+}
+
#ifdef KERBEROS
-int princ_maps_to_lname(principal, luser)
- krb5_principal principal;
- char *luser;
-{
- char kuser[10];
- if (!(krb5_aname_to_localname(bsd_context, principal,
- sizeof(kuser), kuser))
- && (strcmp(kuser, luser) == 0)) {
- return 1;
- }
- return 0;
-}
-
-int default_realm(principal)
- krb5_principal principal;
-{
- char *def_realm;
- unsigned int realm_length;
- int retval;
-
- realm_length = krb5_princ_realm(bsd_context, principal)->length;
-
- if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
- return 0;
- }
-
- if ((realm_length != strlen(def_realm)) ||
- (memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data, realm_length))) {
- free(def_realm);
- return 0;
- }
- free(def_realm);
- return 1;
-}
-
#ifndef KRB_SENDAUTH_VLEN
#define KRB_SENDAUTH_VLEN 8 /* length for version strings */
{
krb5_auth_context auth_context = NULL;
krb5_error_code status;
- struct sockaddr_in peersin, laddr;
+ struct sockaddr_storage peersin, laddr;
int len;
krb5_data inbuf;
char v4_instance[INST_SZ]; /* V4 Instance */
do_encrypt ? KOPT_DO_MUTUAL : 0, /*v4_opts*/
"rcmd", /* v4_service */
v4_instance, /* v4_instance */
- &peersin, /* foriegn address */
- &laddr, /* our local address */
+ ss2sin(&peersin), /* foriegn address */
+ ss2sin(&laddr), /* our local address */
"", /* use default srvtab */
&ticket, /* return ticket */
char *srvtab = NULL;
krb5_keytab keytab = NULL;
krb5_ccache ccache = NULL;
-int default_realm(krb5_principal principal);
-#if defined(KERBEROS) && defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
-static int princ_maps_to_lname(krb5_principal principal, char *luser);
-#endif
void fatal(int, const char *);
int stripdomain = 1;
int always_ip = 0;
-static krb5_error_code recvauth(int netfd, struct sockaddr_in peersin,
+static krb5_error_code recvauth(int netfd, struct sockaddr *peersin,
int *valid_checksum);
#else /* !KERBEROS */
;
void usage(void), getstr(int, char *, int, char *),
- doit(int, struct sockaddr_in *);
+ doit(int, struct sockaddr *);
#ifndef HAVE_INITGROUPS
int initgroups(char* name, gid_t basegid) {
fatal(fd, "Configuration error: mutually exclusive options specified");
}
- doit(dup(fd), &from);
+ doit(dup(fd), (struct sockaddr *) &from);
return 0;
}
char term[64] = "TERM=network";
char path_rest[] = RPATH;
-char remote_addr[64]; /* = "KRB5REMOTEADDR=" */
-char remote_port[64]; /* = "KRB5REMOTEPORT=" */
-char local_addr[64]; /* = "KRB5LOCALADDR=" */
-char local_port[64]; /* = "KRB5LOCALPORT=" */
+char remote_addr[64+NI_MAXHOST]; /* = "KRB5REMOTEADDR=" */
+char remote_port[64+NI_MAXSERV]; /* = "KRB5REMOTEPORT=" */
+char local_addr[64+NI_MAXHOST]; /* = "KRB5LOCALADDR=" */
+char local_port[64+NI_MAXSERV]; /* = "KRB5LOCALPORT=" */
#define ADDRPAD 0,0,0,0
#define KRBPAD 0 /* KRB5CCNAME, optional */
void doit(f, fromp)
int f;
- struct sockaddr_in *fromp;
+ struct sockaddr *fromp;
{
char *cp;
#ifdef KERBEROS
int pv[2], pw[2], px[2], cc;
fd_set ready, readfrom;
char buf[RCMD_BUFSIZ], sig;
- struct sockaddr_in fromaddr;
- struct sockaddr_in localaddr;
- int non_privileged = 0;
+ struct sockaddr_storage localaddr;
#ifdef POSIX_SIGNALS
struct sigaction sa;
#endif
#endif /* IP_TOS */
{
- int sin_len = sizeof (struct sockaddr_in);
+ int sin_len = sizeof (localaddr);
if (getsockname(f, (struct sockaddr*)&localaddr, &sin_len) < 0) {
perror("getsockname");
exit(1);
}
}
- fromaddr = *fromp;
#ifdef POSIX_SIGNALS
(void)sigemptyset(&sa.sa_mask);
}
#ifdef KERBEROS
netf = f;
- if ( (fromp->sin_port >= IPPORT_RESERVED ||
- fromp->sin_port < IPPORT_RESERVED/2))
- non_privileged = 1;
#else
if (fromp->sin_port >= IPPORT_RESERVED ||
fromp->sin_port < IPPORT_RESERVED/2) {
"can't get stderr port: %m");
exit(1);
}
-#ifdef KERBEROS
- if ( port >= IPPORT_RESERVED)
- non_privileged = 1;
-#else
+#ifndef KERBEROS
if (port >= IPPORT_RESERVED) {
syslog(LOG_ERR , "2nd port not reserved\n");
exit(1);
exit(1);
}
- if ((status = recvauth(f, fromaddr,&valid_checksum))) {
+ if ((status = recvauth(f, fromp, &valid_checksum))) {
error("Authentication failed: %s\n", error_message(status));
exit(1);
}
{
int i;
/* these four are covered by ADDRPAD */
- sprintf(local_addr, "KRB5LOCALADDR=%s", inet_ntoa(localaddr.sin_addr));
- for (i = 0; envinit[i]; i++);
- envinit[i] =local_addr;
-
- sprintf(local_port, "KRB5LOCALPORT=%d", ntohs(localaddr.sin_port));
- for (; envinit[i]; i++);
- envinit[i] =local_port;
+ int aierr;
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
- sprintf(remote_addr, "KRB5REMOTEADDR=%s", inet_ntoa(fromp->sin_addr));
- for (; envinit[i]; i++);
- envinit[i] =remote_addr;
+ for (i = 0; envinit[i]; i++);
- sprintf(remote_port, "KRB5REMOTEPORT=%d", ntohs(fromp->sin_port));
- for (; envinit[i]; i++);
- envinit[i] =remote_port;
+ aierr = getnameinfo((struct sockaddr *)&localaddr,
+ socklen((struct sockaddr *)&localaddr),
+ hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (aierr)
+ goto skip_localaddr_env;
+ sprintf(local_addr, "KRB5LOCALADDR=%s", hbuf);
+ envinit[i++] =local_addr;
+
+ sprintf(local_port, "KRB5LOCALPORT=%s", sbuf);
+ envinit[i++] =local_port;
+ skip_localaddr_env:
+
+ aierr = getnameinfo(fromp, socklen(fromp),
+ hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (aierr)
+ goto skip_remoteaddr_env;
+ sprintf(remote_addr, "KRB5REMOTEADDR=%s", hbuf);
+ envinit[i++] =remote_addr;
+
+ sprintf(remote_port, "KRB5REMOTEPORT=%s", sbuf);
+ envinit[i++] =remote_port;
+
+ skip_remoteaddr_env:
+ ;
}
/* If we do anything else, make sure there is space in the array. */
}
-
-#if defined(KERBEROS) && defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
-static int princ_maps_to_lname(principal, luser)
- krb5_principal principal;
- char *luser;
-{
- char kuser[10];
- if (!(krb5_aname_to_localname(bsd_context, principal,
- sizeof(kuser), kuser))
- && (strcmp(kuser, luser) == 0)) {
- return 1;
- }
- return 0;
-}
-#endif
-
-
-int default_realm(principal)
- krb5_principal principal;
-{
- char *def_realm;
- unsigned int realm_length;
- int retval;
-
- realm_length = krb5_princ_realm(bsd_context, principal)->length;
-
- if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
- return 0;
- }
-
- if ((realm_length != strlen(def_realm)) ||
- (memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data,
- realm_length))) {
- free(def_realm);
- return 0;
- }
- free(def_realm);
- return 1;
-}
-
#ifdef KERBEROS
#ifndef KRB_SENDAUTH_VLEN
static krb5_error_code
recvauth(netfd, peersin, valid_checksum)
int netfd;
- struct sockaddr_in peersin;
+ struct sockaddr *peersin;
int *valid_checksum;
{
krb5_auth_context auth_context = NULL;
0, /* v4_opts */
"rcmd", /* v4_service */
v4_instance, /* v4_instance */
- &peersin, /* foreign address */
+ peersin, /* foreign address */
&laddr, /* our local address */
"", /* use default srvtab */
return status;
if (authenticator->checksum && !checksum_ignored) {
- struct sockaddr_in adr;
- int adr_length = sizeof(adr);
- char * chksumbuf = (char *) malloc(strlen(cmdbuf)+strlen(locuser)+32);
+ struct sockaddr_storage adr;
+ unsigned int adr_length = sizeof(adr);
+ int e;
+ unsigned int buflen = strlen(cmdbuf)+strlen(locuser)+32;
+ char * chksumbuf = (char *) malloc(buflen);
if (chksumbuf == 0)
goto error_cleanup;
if (getsockname(netfd, (struct sockaddr *) &adr, &adr_length) != 0)
goto error_cleanup;
- sprintf(chksumbuf,"%u:", ntohs(adr.sin_port));
+ e = getnameinfo((struct sockaddr *)&adr, adr_length, 0, 0,
+ chksumbuf, buflen, NI_NUMERICSERV);
+ if (e) {
+ free(chksumbuf);
+ fatal(netfd, "local error: can't examine port number");
+ }
+ if (strlen(chksumbuf) > 30) {
+ free(chksumbuf);
+ fatal(netfd, "wacky local port number?!");
+ }
+ strcat(chksumbuf, ":");
strcat(chksumbuf,cmdbuf);
strcat(chksumbuf,locuser);