X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/8c8a5b54e79564c14fc7a2823a21a8f048449bcf..af359dea2e5ab3e937b62107ecd6a51d78189ed7:/usr/src/libexec/rshd/rshd.c diff --git a/usr/src/libexec/rshd/rshd.c b/usr/src/libexec/rshd/rshd.c index 86a76edca7..f5203ae987 100644 --- a/usr/src/libexec/rshd/rshd.c +++ b/usr/src/libexec/rshd/rshd.c @@ -2,7 +2,33 @@ * Copyright (c) 1988, 1989 The Regents of the University of California. * All rights reserved. * - * %sccs.include.redist.c% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef lint @@ -12,7 +38,7 @@ char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)rshd.c 5.38 (Berkeley) %G%"; +static char sccsid[] = "@(#)rshd.c 5.38.1.1 (Berkeley) 8/20/91"; #endif /* not lint */ /* @@ -43,7 +69,6 @@ static char sccsid[] = "@(#)rshd.c 5.38 (Berkeley) %G%"; #include #include -#include "pathnames.h" #include #include #include @@ -53,12 +78,24 @@ static char sccsid[] = "@(#)rshd.c 5.38 (Berkeley) %G%"; int keepalive = 1; int check_all = 0; -int check_all = 0; char *index(), *rindex(), *strncat(); /*VARARGS1*/ int error(); int sent_null; -int sent_null; + +#ifdef KERBEROS +#include +#include +#define VERSION_SIZE 9 +#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n" +#define OPTIONS "alknvx" +char authbuf[sizeof(AUTH_DAT)]; +char tickbuf[sizeof(KTEXT_ST)]; +int doencrypt, use_kerberos, vacuous; +Key_schedule schedule; +#else +#define OPTIONS "aln" +#endif /*ARGSUSED*/ main(argc, argv) @@ -74,6 +111,7 @@ main(argc, argv) openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); opterr = 0; + while ((ch = getopt(argc, argv, OPTIONS)) != EOF) switch (ch) { case 'a': check_all = 1; @@ -84,6 +122,16 @@ main(argc, argv) case 'n': keepalive = 0; break; +#ifdef KERBEROS + case 'k': + use_kerberos = 1; + break; + + case 'v': + vacuous = 1; + break; + +#endif case '?': default: usage(); @@ -93,6 +141,13 @@ main(argc, argv) argc -= optind; argv += optind; +#ifdef KERBEROS + if (use_kerberos && vacuous) { + syslog(LOG_ERR, "only one of -k and -v allowed"); + exit(2); + } +#endif + fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { syslog(LOG_ERR, "getpeername: %m"); @@ -135,6 +190,19 @@ doit(fromp) int one = 1; char remotehost[2 * MAXHOSTNAMELEN + 1]; +#ifdef KERBEROS + AUTH_DAT *kdata = (AUTH_DAT *) NULL; + KTEXT ticket = (KTEXT) NULL; + char instance[INST_SZ], version[VERSION_SIZE]; + struct sockaddr_in fromaddr; + int rc; + long authopts; + int pv1[2], pv2[2]; + fd_set wready, writeto; + + fromaddr = *fromp; +#endif + (void) signal(SIGINT, SIG_DFL); (void) signal(SIGQUIT, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); @@ -152,12 +220,6 @@ doit(fromp) fromp->sin_family); exit(1); } -#ifdef IP_OPTIONS - { - u_char optbuf[BUFSIZ/3], *cp; - char lbuf[BUFSIZ], *lp; - int optsize = sizeof(optbuf), ipproto; - struct protoent *ip; #ifdef IP_OPTIONS { u_char optbuf[BUFSIZ/3], *cp; @@ -165,26 +227,6 @@ doit(fromp) int optsize = sizeof(optbuf), ipproto; struct protoent *ip; - if ((ip = getprotobyname("ip")) != NULL) - ipproto = ip->p_proto; - else - ipproto = IPPROTO_IP; - if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) == 0 && - optsize != 0) { - lp = lbuf; - for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) - sprintf(lp, " %2.2x", *cp); - syslog(LOG_NOTICE, - "Connection received using IP options (ignored):%s", lbuf); - if (setsockopt(0, ipproto, IP_OPTIONS, - (char *)NULL, &optsize) != 0) { - syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); - exit(1); - } - } - } -#endif - if ((ip = getprotobyname("ip")) != NULL) ipproto = ip->p_proto; else @@ -208,6 +250,14 @@ doit(fromp) #ifdef KERBEROS if (!use_kerberos) +#endif + if (fromp->sin_port >= IPPORT_RESERVED || + fromp->sin_port < IPPORT_RESERVED/2) { + syslog(LOG_NOTICE|LOG_AUTH, + "Connection from %s on illegal port", + inet_ntoa(fromp->sin_addr)); + exit(1); + } (void) alarm(60); port = 0; @@ -219,6 +269,8 @@ doit(fromp) shutdown(0, 1+1); exit(1); } + if (c== 0) + break; port = port * 10 + c - '0'; } @@ -232,6 +284,11 @@ doit(fromp) } #ifdef KERBEROS if (!use_kerberos) +#endif + if (port >= IPPORT_RESERVED) { + syslog(LOG_ERR, "2nd port not reserved\n"); + exit(1); + } fromp->sin_port = htons(port); if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { syslog(LOG_INFO, "connect second port: %m"); @@ -239,6 +296,13 @@ doit(fromp) } } +#ifdef KERBEROS + if (vacuous) { + error("rshd: remote host requires Kerberos authentication\n"); + exit(1); + } +#endif + #ifdef notdef /* from inetd, socket is already on 0, 1, 2 */ dup2(f, 0); @@ -270,9 +334,7 @@ doit(fromp) errorstr = "Couldn't look up address for your host (%s)\n"; hostname = inet_ntoa(fromp->sin_addr); - } -#ifdef h_addr /* 4.2 hack */ - for (; ; hp->h_addr_list++) { + } else for (; ; hp->h_addr_list++) { if (hp->h_addr_list[0] == NULL) { syslog(LOG_NOTICE, "Host addr %s not listed for host %s", @@ -290,22 +352,30 @@ doit(fromp) break; } } -#else - if (bcmp(hp->h_addr, (caddr_t)&fromp->sin_addr, - sizeof(fromp->sin_addr))) { - syslog(LOG_NOTICE, - "Host addr %s not listed for host %s", - inet_ntoa(fromp->sin_addr), - hp->h_name); - error("Host address mismatch\n"); - exit(1); - } -#endif } } else errorhost = hostname = inet_ntoa(fromp->sin_addr); - getstr(remuser, sizeof(remuser), "remuser"); +#ifdef KERBEROS + if (use_kerberos) { + kdata = (AUTH_DAT *) authbuf; + ticket = (KTEXT) tickbuf; + authopts = 0L; + strcpy(instance, "*"); + version[VERSION_SIZE - 1] = '\0'; + rc = krb_recvauth(authopts, 0, ticket, "rcmd", + instance, &fromaddr, + (struct sockaddr_in *) 0, + kdata, "", (bit_64 *) 0, version); + if (rc != KSUCCESS) { + error("Kerberos authentication failure: %s\n", + krb_err_txt[rc]); + exit(1); + } + } else +#endif + getstr(remuser, sizeof(remuser), "remuser"); + getstr(locuser, sizeof(locuser), "locuser"); getstr(cmdbuf, sizeof(cmdbuf), "command"); setpwent(); @@ -323,11 +393,29 @@ doit(fromp) #endif } - if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && - ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { - error("Permission denied.\n"); - exit(1); - } +#ifdef KERBEROS + if (use_kerberos) { + if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { + if (kuserok(kdata, locuser) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + "Kerberos rsh denied to %s.%s@%s", + kdata->pname, kdata->pinst, kdata->prealm); + error("Permission denied.\n"); + exit(1); + } + } + } else +#endif + + if (errorstr || + pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && + ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { +fail: + if (errorstr == NULL) + errorstr = "Permission denied.\n"; + error(errorstr, errorhost); + exit(1); + } if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { error("Logins currently disabled.\n"); @@ -336,7 +424,6 @@ doit(fromp) (void) write(2, "\0", 1); sent_null = 1; - sent_null = 1; if (port) { if (pipe(pv) < 0) { @@ -398,7 +485,6 @@ doit(fromp) (void) close(s); (void) close(pv[0]); dup2(pv[1], 2); close(pv[1]); - close(pv[1]); } if (*pwd->pw_shell == '\0') pwd->pw_shell = _PATH_BSHELL; @@ -420,10 +506,6 @@ doit(fromp) else cp = pwd->pw_shell; endpwent(); - if (pwd->pw_uid == 0) - syslog(LOG_INFO|LOG_AUTH, "ROOT shell from %s@%s, comm: %s\n", - remuser, hostname, cmdbuf); - endpwent(); if (pwd->pw_uid == 0) { #ifdef KERBEROS if (use_kerberos) @@ -442,12 +524,6 @@ doit(fromp) exit(1); } -/* - * Report error to client. - * Note: can't be used until second socket has connected - * to client, or older clients will hang waiting - * for that connection first. - */ /* * Report error to client. * Note: can't be used until second socket has connected @@ -499,7 +575,6 @@ local_domain(h) char localhost[MAXHOSTNAMELEN]; char *p1, *p2, *topdomain(); - localhost[0] = 0; localhost[0] = 0; (void) gethostname(localhost, sizeof(localhost)); p1 = topdomain(localhost); @@ -527,24 +602,6 @@ topdomain(h) return (maybe); } -char * -topdomain(h) - char *h; -{ - register char *p; - char *maybe = NULL; - int dots = 0; - - for (p = h + strlen(h); p >= h; p--) { - if (*p == '.') { - if (++dots == 2) - return (p); - maybe = p; - } - } - return (maybe); -} - usage() { syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS);