From c341cd1f76e208904768e13a8fcc1deb673fe010 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Tue, 25 Jun 2002 23:19:52 +0000 Subject: [PATCH] enable ipv6 rsh connections git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14580 dc483132-0cff-0310-8789-dd5450dbe970 --- src/appl/bsd/ChangeLog | 14 +++ src/appl/bsd/configure.in | 2 +- src/appl/bsd/kcmd.c | 2 +- src/appl/bsd/krshd.c | 188 ++++++++++++++++++++++---------------- 4 files changed, 126 insertions(+), 80 deletions(-) diff --git a/src/appl/bsd/ChangeLog b/src/appl/bsd/ChangeLog index b552640b8..cd862246b 100644 --- a/src/appl/bsd/ChangeLog +++ b/src/appl/bsd/ChangeLog @@ -1,5 +1,19 @@ 2002-06-25 Ken Raeburn + * kcmd.c (kcmd): Don't restrict addresses to IPv4. + + * configure.in: Check for rresvport_af. + * krshd.c (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. Create secondary channel socket in same address family + as primary channel socket; use rresvport_af if available. + * kcmd.c (setup_secondary_channel): Use select to time out after 10 minutes, or notice the primary channel being closed or receiving data while we wait for the secondary one to be set up. diff --git a/src/appl/bsd/configure.in b/src/appl/bsd/configure.in index 345f31a91..9490702d7 100644 --- a/src/appl/bsd/configure.in +++ b/src/appl/bsd/configure.in @@ -76,7 +76,7 @@ AC_SUBST(V4RCPO) dnl AC_FUNC_VFORK AC_TYPE_MODE_T -AC_CHECK_FUNCS(isatty inet_aton getenv gettosbyname killpg initgroups setpriority setreuid setresuid waitpid setsid ptsname setlogin tcgetpgrp tcsetpgrp setpgid strsave utimes rmufile) +AC_CHECK_FUNCS(isatty inet_aton getenv gettosbyname killpg initgroups setpriority setreuid setresuid waitpid setsid ptsname setlogin tcgetpgrp tcsetpgrp setpgid strsave utimes rmufile rresvport_af) AC_CHECK_HEADERS(unistd.h stdlib.h string.h sys/filio.h sys/sockio.h sys/label.h sys/tty.h ttyent.h lastlog.h sys/select.h sys/ptyvar.h utmp.h sys/time.h krb4-proto.h sys/ioctl_compat.h paths.h arpa/nameser.h) AC_HEADER_STDARG AC_REPLACE_FUNCS(getdtablesize) diff --git a/src/appl/bsd/kcmd.c b/src/appl/bsd/kcmd.c index 74a56b3e0..6bd4aeea7 100644 --- a/src/appl/bsd/kcmd.c +++ b/src/appl/bsd/kcmd.c @@ -396,7 +396,7 @@ kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, service, realm, krb5_data cksumdat; char *kcmd_version; enum kcmd_proto protonum = *protonump; - int addrfamily = AF_INET; + int addrfamily = /* AF_INET */0; if ((cksumbuf = malloc(strlen(cmd)+strlen(remuser)+64)) == 0 ) { fprintf(stderr, "Unable to allocate memory for checksum buffer.\n"); diff --git a/src/appl/bsd/krshd.c b/src/appl/bsd/krshd.c index 30aa669fa..b3fea3a7a 100644 --- a/src/appl/bsd/krshd.c +++ b/src/appl/bsd/krshd.c @@ -200,10 +200,6 @@ krb5_context bsd_context; 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 *); @@ -216,7 +212,7 @@ int maxhostlen = 0; 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 */ @@ -264,7 +260,7 @@ void error (char *fmt, ...) ; 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) { @@ -286,13 +282,10 @@ int main(argc, argv) struct linger linger; #endif int on = 1, fromlen; - struct sockaddr_in from; + struct sockaddr_storage from; extern int opterr, optind; extern char *optarg; int ch; -#if 0 - int i; -#endif int fd; int debug_port = 0; #ifdef KERBEROS @@ -492,7 +485,7 @@ int main(argc, argv) fatal(fd, "Configuration error: mutually exclusive options specified"); } - doit(dup(fd), &from); + doit(dup(fd), (struct sockaddr *) &from); return 0; } @@ -509,10 +502,10 @@ char shell[64] = "SHELL="; 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 */ @@ -609,7 +602,7 @@ cleanup(signumber) void doit(f, fromp) int f; - struct sockaddr_in *fromp; + struct sockaddr *fromp; { char *cp; #ifdef KERBEROS @@ -640,17 +633,15 @@ void doit(f, fromp) #endif /* CRAY */ int s; - struct hostent *hp; - char hostname[MAXDNAME]; + char hostname[NI_MAXHOST]; char *sane_host; - char hostaddra[16]; + char hostaddra[NI_MAXHOST]; + int aierr; short port; 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 @@ -660,6 +651,7 @@ void doit(f, fromp) #ifdef HAVE_GETTOSBYNAME struct tosent *tp; + if ((tp = gettosbyname("interactive", "tcp")) && (setsockopt(f, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0)) #ifdef TOS_WARN @@ -671,13 +663,12 @@ void doit(f, fromp) #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); @@ -699,21 +690,25 @@ void doit(f, fromp) } } #endif - fromp->sin_port = ntohs((u_short)fromp->sin_port); - if (fromp->sin_family != AF_INET) { + if (fromp->sa_family != AF_INET +#if defined(KRB5_USE_INET6) && defined(KERBEROS) + && fromp->sa_family != AF_INET6 +#endif + ) { syslog(LOG_ERR , "malformed from address\n"); exit(1); } #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) { - syslog(LOG_ERR , "connection from bad port\n"); - exit(1); + { + struct sockaddr_in *frompin = sa2sin(fromp); + frompin->sin_port = ntohs((u_short)frompin->sin_port); + if (frompin->sin_port >= IPPORT_RESERVED || + frompin->sin_port < IPPORT_RESERVED/2) { + syslog(LOG_ERR , "connection from bad port\n"); + exit(1); + } } #endif /* KERBEROS */ @@ -768,28 +763,38 @@ void doit(f, fromp) (void) alarm(0); if (port != 0) { if (anyport) { - int addrfamily = AF_INET; + int addrfamily = fromp->sa_family; s = getport(0, &addrfamily); } else { int lport = IPPORT_RESERVED - 1; +#ifdef HAVE_RRESVPORT_AF + s = rresvport_af(&lport, fromp->sa_family); +#else s = rresvport(&lport); +#endif } if (s < 0) { syslog(LOG_ERR , "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); } #endif /* KERBEROS */ - fromp->sin_port = htons((u_short)port); - if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { + switch (fromp->sa_family) { + case AF_INET: + sa2sin(fromp)->sin_port = htons((u_short)port); + break; +#ifdef KRB5_USE_INET6 + case AF_INET6: + sa2sin6(fromp)->sin6_port = htons((u_short)port); + break; +#endif + } + if (connect(s, (struct sockaddr *)fromp, socklen(fromp)) < 0) { syslog(LOG_INFO , "connect second port: %m"); exit(1); @@ -798,16 +803,18 @@ void doit(f, fromp) dup2(f, 0); dup2(f, 1); dup2(f, 2); - hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), - fromp->sin_family); - strncpy(hostaddra, inet_ntoa(fromp->sin_addr), sizeof (hostaddra)); - hostaddra[sizeof (hostaddra) - 1] = '\0'; - if (hp != NULL){ - strncpy(hostname, hp->h_name, sizeof (hostname)); - hostname[sizeof (hostname) - 1] = '\0'; + aierr = getnameinfo(fromp, socklen(fromp), hostname, sizeof(hostname), + 0, 0, 0); + if (aierr) { + error("failed to get remote host address: %s", gai_strerror(aierr)); + exit(1); + } + aierr = getnameinfo(fromp, socklen(fromp), hostaddra, sizeof(hostaddra), + 0, 0, NI_NUMERICHOST); + if (aierr) { + error("failed to get remote host address: %s", gai_strerror(aierr)); + exit(1); } - else - hostname[0] = '\0'; #ifdef KERBEROS status = pty_make_sane_hostname((struct sockaddr *) fromp, maxhostlen, @@ -817,7 +824,7 @@ void doit(f, fromp) 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); } @@ -1238,8 +1245,8 @@ void doit(f, fromp) #endif (void) close(0); (void) close(1); (void) close(2); -if(port) - (void) close(pv[1]); + if(port) + (void) close(pv[1]); (void) close(pw[1]); (void) close(px[0]); @@ -1247,10 +1254,10 @@ if(port) FD_ZERO(&readfrom); FD_SET(f, &readfrom); -if(port) - FD_SET(s, &readfrom); -if(port) - FD_SET(pv[0], &readfrom); + if(port) { + FD_SET(s, &readfrom); + FD_SET(pv[0], &readfrom); + } FD_SET(pw[0], &readfrom); /* read from f, write to px[1] -- child stdin */ @@ -1436,23 +1443,38 @@ if(port) } { + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 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; - - 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. */ @@ -1525,7 +1547,7 @@ if(port) } else { execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); -} + } perror(pwd->pw_shell); perror(cp); exit(1); @@ -1537,7 +1559,6 @@ if(port) pty_logwtmp(ttyn,"",""); exit(1); } - void @@ -1760,7 +1781,6 @@ void usage() } - #ifdef KERBEROS #ifndef KRB_SENDAUTH_VLEN @@ -1773,7 +1793,7 @@ void usage() 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; @@ -1846,7 +1866,7 @@ recvauth(netfd, peersin, valid_checksum) 0, /* v4_opts */ "rcmd", /* v4_service */ v4_instance, /* v4_instance */ - &peersin, /* foreign address */ + peersin, /* foreign address */ &laddr, /* our local address */ "", /* use default srvtab */ @@ -1923,16 +1943,28 @@ recvauth(netfd, peersin, valid_checksum) 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); -- 2.26.2