2 * Copyright (c) 1983, 1990 The Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 RCSID("$Id: rsh.c,v 1.43.2.2 2000/10/10 12:53:50 assar Exp $");
39 Key_schedule schedule;
40 int use_kerberos = 1, doencrypt;
41 char dst_realm_buf[REALM_SZ], *dest_realm;
52 "usage: rsh [-ndKx] [-k realm] [-p port] [-l login] host [command]\n");
64 for (ap = argv; *ap; ++ap)
65 cc += strlen(*ap) + 1;
68 errx(1, "Out of memory.");
69 for (p = args, ap = argv; *ap; ++ap) {
85 des_enc_write(rfd2, &signo, 1, schedule, &cred.session);
88 write(rfd2, &signo, 1);
92 talk(int nflag, sigset_t omask, int pid, int rem)
96 fd_set readfrom, ready, rembits;
97 char buf[DES_RW_MAXWRITE];
106 if ((cc = read(0, buf, sizeof buf)) <= 0)
112 if (rem >= FD_SETSIZE)
113 errx(1, "fd too large");
114 FD_SET(rem, &rembits);
115 if (select(rem + 1, 0, &rembits, 0, 0) < 0) {
120 if (!FD_ISSET(rem, &rembits))
124 wc = des_enc_write(rem, bp, cc, schedule, &cred.session);
127 wc = write(rem, bp, cc);
129 if (errno == EWOULDBLOCK)
143 if (sigprocmask(SIG_SETMASK, &omask, 0) != 0)
146 if (rem >= FD_SETSIZE || rfd2 >= FD_SETSIZE)
147 errx(1, "fd too large");
148 FD_SET(rem, &readfrom);
149 FD_SET(rfd2, &readfrom);
152 if (select(max(rem,rfd2)+1, &ready, 0, 0, 0) < 0) {
157 if (FD_ISSET(rfd2, &ready)) {
161 cc = des_enc_read(rfd2, buf, sizeof buf,
162 schedule, &cred.session);
165 cc = read(rfd2, buf, sizeof buf);
167 if (errno != EWOULDBLOCK)
168 FD_CLR(rfd2, &readfrom);
172 if (FD_ISSET(rem, &ready)) {
176 cc = des_enc_read(rem, buf, sizeof buf,
177 schedule, &cred.session);
180 cc = read(rem, buf, sizeof buf);
182 if (errno != EWOULDBLOCK)
183 FD_CLR(rem, &readfrom);
187 } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom));
191 main(int argc, char **argv)
194 int sv_port, user_port = 0;
196 int argoff, ch, dflag, nflag, nfork, one, pid, rem, uid;
197 char *args, *host, *user, *local_user;
199 argoff = dflag = nflag = nfork = 0;
204 set_progname(argv[0]);
206 /* handle "rsh host flags" */
207 if (argc > 2 && argv[1][0] != '-') {
212 #define OPTIONS "+8KLde:k:l:np:wx"
213 while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1)
218 case 'L': /* -8Lew are ignored to allow rlogin aliases */
230 dest_realm = dst_realm_buf;
231 strlcpy(dest_realm, optarg, REALM_SZ);
242 user_port = strtol (optarg, &endptr, 0);
243 if (user_port == 0 && optarg == endptr)
244 errx (1, "Bad port `%s'", optarg);
245 user_port = htons(user_port);
254 /* if haven't gotten a host yet, do so */
255 if (!host && !(host = argv[optind++]))
258 /* if no further arguments, must have been called as rlogin. */
261 paranoid_setuid (getuid ());
262 execv(_PATH_RLOGIN, argv);
263 err(1, "can't exec %s", _PATH_RLOGIN);
267 if (!(pw = k_getpwuid(uid = getuid())))
268 errx(1, "unknown user id.");
269 local_user = pw->pw_name;
274 errx(1, "Sorry, you need to specify the username (with -l)");
278 /* -n must still fork but does not turn of the -n functionality */
282 args = copyargs(argv+optind);
287 sv_port = get_shell_port(use_kerberos, doencrypt);
290 paranoid_setuid(getuid());
293 if (dest_realm == NULL)
294 dest_realm = krb_realmofhost(host);
297 rem = krcmd_mutual(&host, sv_port, user, args,
298 &rfd2, dest_realm, &cred, schedule);
300 rem = krcmd(&host, sv_port, user, args, &rfd2,
306 if (errno == ECONNREFUSED)
307 warning("remote host doesn't support Kerberos");
309 warning("can't provide Kerberos auth data");
310 newargv = malloc((argc + 2) * sizeof(*newargv));
313 newargv[i] = argv[i];
315 if (argv[i][0] != '-') {
316 newargv[i] = argv[i];
320 for(; i <= argc; ++i)
321 newargv[i] = argv[i - 1];
322 newargv[argc + 1] = NULL;
323 execv(_PATH_RSH, newargv);
327 errx(1, "the -x flag requires Kerberos authentication.");
329 errx(1, "not installed setuid root, "
330 "only root may use non kerberized rsh");
331 rem = rcmd(&host, sv_port, local_user, user, args, &rfd2);
338 errx(1, "can't establish stderr.");
339 #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
341 if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, (void *)&one,
344 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, (void *)&one,
350 paranoid_setuid(uid);
353 sigemptyset(&sigmsk);
354 sigaddset(&sigmsk, SIGINT);
355 sigaddset(&sigmsk, SIGQUIT);
356 sigaddset(&sigmsk, SIGTERM);
357 if (sigprocmask(SIG_BLOCK, &sigmsk, &omask) != 0)
360 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
361 signal(SIGINT, sendsig);
362 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
363 signal(SIGQUIT, sendsig);
364 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
365 signal(SIGTERM, sendsig);
366 signal(SIGPIPE, SIG_IGN);
375 ioctl(rfd2, FIONBIO, &one);
376 ioctl(rem, FIONBIO, &one);
379 talk(nflag, omask, pid, rem);