summaryrefslogtreecommitdiff
path: root/libexec/rshd/rshd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/rshd/rshd.c')
-rw-r--r--libexec/rshd/rshd.c229
1 files changed, 228 insertions, 1 deletions
diff --git a/libexec/rshd/rshd.c b/libexec/rshd/rshd.c
index 029bd5bfc12..d85fc68faa9 100644
--- a/libexec/rshd/rshd.c
+++ b/libexec/rshd/rshd.c
@@ -39,7 +39,7 @@ static char copyright[] =
#ifndef lint
/* from: static char sccsid[] = "@(#)rshd.c 8.2 (Berkeley) 4/6/94"; */
-static char *rcsid = "$Id: rshd.c,v 1.2 1995/11/20 09:38:09 deraadt Exp $";
+static char *rcsid = "$Id: rshd.c,v 1.3 1995/12/16 22:20:23 tholo Exp $";
#endif /* not lint */
/*
@@ -82,7 +82,19 @@ int local_domain __P((char *));
char *topdomain __P((char *));
void usage __P((void));
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#define VERSION_SIZE 9
+#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n"
+#define OPTIONS "alnkvxL"
+char authbuf[sizeof(AUTH_DAT)];
+char tickbuf[sizeof(KTEXT_ST)];
+int doencrypt, use_kerberos, vacuous;
+Key_schedule schedule;
+#else
#define OPTIONS "alnL"
+#endif
int
main(argc, argv)
@@ -108,6 +120,21 @@ main(argc, argv)
case 'n':
keepalive = 0;
break;
+#ifdef KERBEROS
+ case 'k':
+ use_kerberos = 1;
+ break;
+
+ case 'v':
+ vacuous = 1;
+ break;
+
+#ifdef CRYPT
+ case 'x':
+ doencrypt = 1;
+ break;
+#endif
+#endif
case 'L':
log_success = 1;
break;
@@ -120,6 +147,18 @@ 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);
+ }
+#ifdef CRYPT
+ if (doencrypt && !use_kerberos) {
+ syslog(LOG_ERR, "-k is required for -x");
+ exit(2);
+ }
+#endif
+#endif
fromlen = sizeof (from);
if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
@@ -164,6 +203,18 @@ doit(fromp)
char remotehost[2 * MAXHOSTNAMELEN + 1];
char hostnamebuf[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);
@@ -210,6 +261,9 @@ doit(fromp)
}
#endif
+#ifdef KERBEROS
+ if (!use_kerberos)
+#endif
if (fromp->sin_port >= IPPORT_RESERVED ||
fromp->sin_port < IPPORT_RESERVED/2) {
syslog(LOG_NOTICE|LOG_AUTH,
@@ -242,6 +296,9 @@ doit(fromp)
syslog(LOG_ERR, "can't get stderr port: %m");
exit(1);
}
+#ifdef KERBEROS
+ if (!use_kerberos)
+#endif
if (port >= IPPORT_RESERVED) {
syslog(LOG_ERR, "2nd port not reserved\n");
exit(1);
@@ -253,6 +310,12 @@ 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 */
@@ -271,6 +334,9 @@ doit(fromp)
* address corresponds to the name.
*/
hostname = hp->h_name;
+#ifdef KERBEROS
+ if (!use_kerberos)
+#endif
if (check_all || local_domain(hp->h_name)) {
strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
remotehost[sizeof(remotehost) - 1] = 0;
@@ -310,6 +376,42 @@ doit(fromp)
sizeof(hostnamebuf) - 1);
hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
+#ifdef KERBEROS
+ if (use_kerberos) {
+ kdata = (AUTH_DAT *) authbuf;
+ ticket = (KTEXT) tickbuf;
+ authopts = 0L;
+ strcpy(instance, "*");
+ version[VERSION_SIZE - 1] = '\0';
+#ifdef CRYPT
+ if (doencrypt) {
+ struct sockaddr_in local_addr;
+ rc = sizeof(local_addr);
+ if (getsockname(0, (struct sockaddr *)&local_addr,
+ &rc) < 0) {
+ syslog(LOG_ERR, "getsockname: %m");
+ error("rlogind: getsockname: %m");
+ exit(1);
+ }
+ authopts = KOPT_DO_MUTUAL;
+ rc = krb_recvauth(authopts, 0, ticket,
+ "rcmd", instance, &fromaddr,
+ &local_addr, kdata, "", schedule,
+ version);
+ des_set_key(kdata->session, schedule);
+ } else
+#endif
+ 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");
@@ -335,6 +437,19 @@ doit(fromp)
#endif
}
+#ifdef KERBEROS
+ if (use_kerberos) {
+ if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
+ if (kuserok(kdata, locuser) != 0) {
+ syslog(LOG_INFO|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' &&
iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0,
@@ -368,12 +483,37 @@ fail:
error("Can't make pipe.\n");
exit(1);
}
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt) {
+ if (pipe(pv1) < 0) {
+ error("Can't make 2nd pipe.\n");
+ exit(1);
+ }
+ if (pipe(pv2) < 0) {
+ error("Can't make 3rd pipe.\n");
+ exit(1);
+ }
+ }
+#endif
+#endif
pid = fork();
if (pid == -1) {
error("Can't fork; try again.\n");
exit(1);
}
if (pid) {
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt) {
+ static char msg[] = SECURE_MESSAGE;
+ (void) close(pv1[1]);
+ (void) close(pv2[1]);
+ des_write(s, msg, sizeof(msg) - 1);
+
+ } else
+#endif
+#endif
{
(void) close(0);
(void) close(1);
@@ -388,17 +528,47 @@ fail:
nfd = pv[0];
else
nfd = s;
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt) {
+ FD_ZERO(&writeto);
+ FD_SET(pv2[0], &writeto);
+ FD_SET(pv1[0], &readfrom);
+
+ nfd = MAX(nfd, pv2[0]);
+ nfd = MAX(nfd, pv1[0]);
+ } else
+#endif
+#endif
ioctl(pv[0], FIONBIO, (char *)&one);
/* should set s nbio! */
nfd++;
do {
ready = readfrom;
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt) {
+ wready = writeto;
+ if (select(nfd, &ready,
+ &wready, (fd_set *) 0,
+ (struct timeval *) 0) < 0)
+ break;
+ } else
+#endif
+#endif
if (select(nfd, &ready, (fd_set *)0,
(fd_set *)0, (struct timeval *)0) < 0)
break;
if (FD_ISSET(s, &ready)) {
int ret;
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt)
+ ret = des_read(s, &sig, 1);
+ else
+#endif
+#endif
ret = read(s, &sig, 1);
if (ret <= 0)
FD_CLR(s, &readfrom);
@@ -412,18 +582,67 @@ fail:
shutdown(s, 1+1);
FD_CLR(pv[0], &readfrom);
} else {
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt)
+ (void)
+ des_write(s, buf, cc);
+ else
+#endif
+#endif
(void)
write(s, buf, cc);
}
}
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt && FD_ISSET(pv1[0], &ready)) {
+ errno = 0;
+ cc = read(pv1[0], buf, sizeof(buf));
+ if (cc <= 0) {
+ shutdown(pv1[0], 1+1);
+ FD_CLR(pv1[0], &readfrom);
+ } else
+ (void) des_write(STDOUT_FILENO,
+ buf, cc);
+ }
+
+ if (doencrypt && FD_ISSET(pv2[0], &wready)) {
+ errno = 0;
+ cc = des_read(STDIN_FILENO,
+ buf, sizeof(buf));
+ if (cc <= 0) {
+ shutdown(pv2[0], 1+1);
+ FD_CLR(pv2[0], &writeto);
+ } else
+ (void) write(pv2[0], buf, cc);
+ }
+#endif
+#endif
} while (FD_ISSET(s, &readfrom) ||
+#ifdef CRYPT
+#ifdef KERBEROS
+ (doencrypt && FD_ISSET(pv1[0], &readfrom)) ||
+#endif
+#endif
FD_ISSET(pv[0], &readfrom));
exit(0);
}
setpgrp(0, getpid());
(void) close(s);
(void) close(pv[0]);
+#ifdef CRYPT
+#ifdef KERBEROS
+ if (doencrypt) {
+ close(pv1[0]); close(pv2[0]);
+ dup2(pv1[1], 1);
+ dup2(pv2[1], 0);
+ close(pv1[1]);
+ close(pv2[1]);
+ }
+#endif
+#endif
dup2(pv[1], 2);
close(pv[1]);
}
@@ -448,6 +667,14 @@ fail:
cp = pwd->pw_shell;
endpwent();
if (log_success || pwd->pw_uid == 0) {
+#ifdef KERBEROS
+ if (use_kerberos)
+ syslog(LOG_INFO|LOG_AUTH,
+ "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'",
+ kdata->pname, kdata->pinst, kdata->prealm,
+ hostname, locuser, cmdbuf);
+ else
+#endif
syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
remuser, hostname, locuser, cmdbuf);
}