netkit-rsh-0.17/ 40700 144 144 0 7141142015 12721 5ustar dhollandpeoplenetkit-rsh-0.17/rcp/ 40700 144 144 0 7141142014 13504 5ustar dhollandpeoplenetkit-rsh-0.17/rcp/.cvsignore100644 144 144 4 6774163707 15554 0ustar dhollandpeoplercp netkit-rsh-0.17/rcp/Makefile100644 144 144 417 7024761714 15253 0ustar dhollandpeopleall: rcp include ../MCONFIG include ../MRULES rcp: rcp.o $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ install: rcp install -s -o root -m$(SUIDMODE) rcp $(INSTALLROOT)$(BINDIR) install -m$(MANMODE) rcp.1 $(INSTALLROOT)$(MANDIR)/man1 clean: rm -f *.o rcp rcp.o: ../version.h netkit-rsh-0.17/rcp/pathnames.h100644 144 144 3741 6172370460 15764 0ustar dhollandpeople/* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * 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. * * from: @(#)pathnames.h 5.3 (Berkeley) 5/31/90 * $Id: pathnames.h,v 1.3 1996/07/15 07:20:16 dholland Exp $ */ #include #define _PATH_CP "/bin/cp" #define _PATH_RSH "/usr/bin/rsh" netkit-rsh-0.17/rcp/rcp.1100644 144 144 10617 7141140317 14512 0ustar dhollandpeople.\" Copyright (c) 1983, 1990 The Regents of the University of California. .\" All rights reserved. .\" .\" 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. .\" .\" from: @(#)rcp.1 6.14 (Berkeley) 7/27/91 .\" $Id: rcp.1,v 1.11 2000/07/30 23:57:03 dholland Exp $ .\" .Dd August 15, 1999 .Dt RCP 1 .Os "Linux NetKit (0.17)" .Sh NAME .Nm rcp .Nd remote file copy .Sh SYNOPSIS .Nm rcp .Op Fl px .Op Fl k Ar realm .Ar file1 file2 .Nm rcp .Op Fl px .Op Fl r .Op Fl k Ar realm .Ar file ... .Ar directory .Sh DESCRIPTION .Nm Rcp copies files between machines. Each .Ar file or .Ar directory argument is either a remote file name of the form ``rname@rhost:path'', or a local file name (containing no `:' characters, or a `/' before any `:'s). .Pp .Bl -tag -width flag .It Fl r If any of the source files are directories, .Nm rcp copies each subtree rooted at that name; in this case the destination must be a directory. .It Fl p The .Fl p option causes .Nm rcp to attempt to preserve (duplicate) in its copies the modification times and modes of the source files, ignoring the .Ar umask . By default, the mode and owner of .Ar file2 are preserved if it already existed; otherwise the mode of the source file modified by the .Xr umask 2 on the destination host is used. .It Fl k The .Fl k option requests .Nm rcp to obtain tickets for the remote host in realm .Ar realm instead of the remote host's realm as determined by .Xr krb_realmofhost 3 . .It Fl x The .Fl x option turns on .Tn DES encryption for all data passed by .Nm rcp . This may impact response time and .Tn CPU utilization, but provides increased security. .El .Pp If .Ar path is not a full path name, it is interpreted relative to the login directory of the specified user .Ar ruser on .Ar rhost , or your current user name if no other remote user name is specified. A .Ar path on a remote host may be quoted (using \e, ", or \(aa) so that the metacharacters are interpreted remotely. .Pp .Nm Rcp does not prompt for passwords; it performs remote execution via .Xr rsh 1 , and requires the same authorization. .Pp .Nm Rcp handles third party copies, where neither source nor target files are on the current machine. .Sh SEE ALSO .Xr cp 1 , .Xr ftp 1 , .Xr rsh 1 , .Xr rlogin 1 .Sh HISTORY The .Nm rcp command appeared in .Bx 4.2 . The version of .Nm rcp described here has been reimplemented with Kerberos in .Bx 4.3 Reno . .Sh BUGS Doesn't detect all cases where the target of a copy might be a file in cases where only a directory should be legal. .Pp Is confused by any output generated by commands in a .Pa \&.login , .Pa \&.profile , or .Pa \&.cshrc file on the remote host. .Pp The destination user and hostname may have to be specified as ``rhost.rname'' when the destination machine is running the .Bx 4.2 version of .Nm rcp . netkit-rsh-0.17/rcp/rcp.c100644 144 144 46430 7136470626 14613 0ustar dhollandpeople/* * Copyright (c) 1983, 1990 The Regents of the University of California. * All rights reserved. * * 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. */ char copyright[] = "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n" "All rights reserved.\n"; /* * From: @(#)rcp.c 5.32 (Berkeley) 2/25/91 */ char rcsid[] = "$Id: rcp.c,v 1.15 2000/07/23 04:16:22 dholland Exp $"; #include "../version.h" /* * rcp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #define OPTIONS "dfprt" struct passwd *pwd; u_short port; uid_t userid; int errs, rem; int pflag, iamremote, iamrecursive, targetshouldbedirectory; static char **saved_environ; #define CMDNEEDS 64 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ typedef struct _buf { int cnt; char *buf; } BUF; static void lostconn(int); static char *colon(char *); static int response(void); static void verifydir(const char *cp); static int okname(const char *cp0); static int susystem(const char *s); static void source(int argc, char *argv[]); static void rsource(char *name, struct stat *statp); static void sink(int argc, char *argv[]); static BUF *allocbuf(BUF *bp, int fd, int blksize); static void nospace(void); static void usage(void); static void toremote(const char *targ, int argc, char *argv[]); static void tolocal(int argc, char *argv[]); static void error(const char *fmt, ...); int main(int argc, char *argv[]) { struct servent *sp; int ch, fflag, tflag; char *targ; const char *shell; char *null = NULL; saved_environ = __environ; __environ = &null; fflag = tflag = 0; while ((ch = getopt(argc, argv, OPTIONS)) != EOF) switch(ch) { /* user-visible flags */ case 'p': /* preserve access/mod times */ ++pflag; break; case 'r': ++iamrecursive; break; /* rshd-invoked options (server) */ case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ iamremote = 1; fflag = 1; break; case 't': /* "to" */ iamremote = 1; tflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; sp = getservbyname(shell = "shell", "tcp"); if (sp == NULL) { (void)fprintf(stderr, "rcp: %s/tcp: unknown service\n", shell); exit(1); } port = sp->s_port; if (!(pwd = getpwuid(userid = getuid()))) { (void)fprintf(stderr, "rcp: unknown user %d.\n", (int)userid); exit(1); } if (fflag) { /* follow "protocol", send data */ (void)response(); if (setuid(userid)) { fprintf(stderr, "rcp: setuid: %s\n", strerror(errno)); exit(1); } source(argc, argv); exit(errs); } if (tflag) { /* receive data */ if (setuid(userid)) { fprintf(stderr, "rcp: setuid: %s\n", strerror(errno)); exit(1); } sink(argc, argv); exit(errs); } if (argc < 2) usage(); if (argc > 2) targetshouldbedirectory = 1; rem = -1; /* command to be executed on remote system using "rsh" */ (void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void)signal(SIGPIPE, lostconn); if ((targ = colon(argv[argc - 1]))!=NULL) { /* destination is remote host */ *targ++ = 0; toremote(targ, argc, argv); } else { tolocal(argc, argv); /* destination is local host */ if (targetshouldbedirectory) verifydir(argv[argc - 1]); } exit(errs); } static void toremote(const char *targ, int argc, char *argv[]) { int i, len, tos; char *bp, *host, *src, *suser, *thost, *tuser; if (*targ == 0) targ = "."; if ((thost = strchr(argv[argc - 1], '@'))!=NULL) { /* user@host */ *thost++ = 0; tuser = argv[argc - 1]; if (*tuser == '\0') tuser = NULL; else if (!okname(tuser)) exit(1); } else { thost = argv[argc - 1]; tuser = NULL; } for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src) { /* remote to remote */ static char dot[] = "."; *src++ = 0; if (*src == 0) src = dot; host = strchr(argv[i], '@'); len = strlen(_PATH_RSH) + strlen(argv[i]) + strlen(src) + (tuser ? strlen(tuser) : 0) + strlen(thost) + strlen(targ) + CMDNEEDS + 20; if (!(bp = malloc(len))) nospace(); if (host) { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; (void)snprintf(bp, len, "%s %s -l %s -n %s %s '%s%s%s:%s'", _PATH_RSH, host, suser, cmd, src, tuser ? tuser : "", tuser ? "@" : "", thost, targ); } else (void)snprintf(bp, len, "%s %s -n %s %s '%s%s%s:%s'", _PATH_RSH, argv[i], cmd, src, tuser ? tuser : "", tuser ? "@" : "", thost, targ); (void)susystem(bp); (void)free(bp); } else { /* local to remote */ if (rem == -1) { len = strlen(targ) + CMDNEEDS + 20; if (!(bp = malloc(len))) nospace(); (void)snprintf(bp, len, "%s -t %s", cmd, targ); host = thost; rem = rcmd(&host, port, pwd->pw_name, tuser ? tuser : pwd->pw_name, bp, 0); if (rem < 0) exit(1); #ifdef IP_TOS tos = IPTOS_THROUGHPUT; if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) perror("rcp: setsockopt TOS (ignored)"); #endif if (response() < 0) exit(1); (void)free(bp); if (setuid(userid)) { fprintf(stderr, "rcp: setuid: %s\n", strerror(errno)); } } source(1, argv+i); } } } static void tolocal(int argc, char *argv[]) { static char dot[] = "."; int i, len, tos; char *bp, *host, *src, *suser; for (i = 0; i < argc - 1; i++) { if (!(src = colon(argv[i]))) { /* local to local */ len = strlen(_PATH_CP) + strlen(argv[i]) + strlen(argv[argc - 1]) + 20; if (!(bp = malloc(len))) nospace(); (void)snprintf(bp, len, "%s%s%s %s %s", _PATH_CP, iamrecursive ? " -r" : "", pflag ? " -p" : "", argv[i], argv[argc - 1]); (void)susystem(bp); (void)free(bp); continue; } *src++ = 0; if (*src == 0) src = dot; host = strchr(argv[i], '@'); if (host) { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; } else { host = argv[i]; suser = pwd->pw_name; } len = strlen(src) + CMDNEEDS + 20; if (!(bp = malloc(len))) nospace(); (void)snprintf(bp, len, "%s -f %s", cmd, src); rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0); (void)free(bp); if (rem < 0) { ++errs; continue; } (void)seteuid(userid); #ifdef IP_TOS tos = IPTOS_THROUGHPUT; if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) perror("rcp: setsockopt TOS (ignored)"); #endif sink(1, argv + argc - 1); (void)seteuid(0); (void)close(rem); rem = -1; } } static void verifydir(const char *cp) { struct stat stb; if (stat(cp, &stb) >= 0) { if ((stb.st_mode & S_IFMT) == S_IFDIR) return; errno = ENOTDIR; } error("rcp: %s: %s.\n", cp, strerror(errno)); exit(1); } static char * colon(char *cp) { for (; *cp; ++cp) { if (*cp == ':') return(cp); if (*cp == '/') return NULL; } return NULL; } static int okname(const char *cp0) { const char *cp = cp0; int c; do { c = *cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') goto bad; } while (*++cp); return(1); bad: (void)fprintf(stderr, "rcp: invalid user name %s\n", cp0); return 0; } typedef void (*sighandler)(int); static int susystem(const char *s) { int status, pid, w; sighandler istat, qstat; if ((pid = vfork()) == 0) { const char *args[4]; const char **argsfoo; char **argsbar; if (setuid(userid)) { fprintf(stderr, "rcp: child: setuid: %s\n", strerror(errno)); _exit(1); } args[0] = "sh"; args[1] = "-c"; args[2] = s; args[3] = NULL; /* Defeat C type system to permit passing char ** to execve */ argsfoo = args; memcpy(&argsbar, &argsfoo, sizeof(argsfoo)); execve(_PATH_BSHELL, argsbar, saved_environ); _exit(127); } istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; (void)signal(SIGINT, istat); (void)signal(SIGQUIT, qstat); return(status); } static void source(int argc, char *argv[]) { struct stat stb; static BUF buffer; BUF *bp; off_t i; int x, readerr, f, amt; char *last, *name, buf[BUFSIZ]; for (x = 0; x < argc; x++) { name = argv[x]; if ((f = open(name, O_RDONLY, 0)) < 0) { error("rcp: %s: %s\n", name, strerror(errno)); continue; } if (fstat(f, &stb) < 0) goto notreg; switch (stb.st_mode&S_IFMT) { case S_IFREG: break; case S_IFDIR: if (iamrecursive) { (void)close(f); rsource(name, &stb); continue; } /* FALLTHROUGH */ default: notreg: (void)close(f); error("rcp: %s: not a plain file\n", name); continue; } last = strrchr(name, '/'); if (last == 0) last = name; else last++; if (pflag) { /* * Make it compatible with possible future * versions expecting microseconds. */ (void)snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n", stb.st_mtime, stb.st_atime); (void)write(rem, buf, (int)strlen(buf)); if (response() < 0) { (void)close(f); continue; } } (void)snprintf(buf, sizeof(buf), "C%04o %ld %s\n", stb.st_mode&07777, stb.st_size, last); (void)write(rem, buf, (int)strlen(buf)); if (response() < 0) { (void)close(f); continue; } if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) { (void)close(f); continue; } readerr = 0; for (i = 0; i < stb.st_size; i += bp->cnt) { amt = bp->cnt; if (i + amt > stb.st_size) amt = stb.st_size - i; if (readerr == 0 && read(f, bp->buf, amt) != amt) readerr = errno; (void)write(rem, bp->buf, amt); } (void)close(f); if (readerr == 0) (void)write(rem, "", 1); else error("rcp: %s: %s\n", name, strerror(readerr)); (void)response(); } } static void rsource(char *name, struct stat *statp) { DIR *dirp; struct dirent *dp; char *last, *vect[1], path[MAXPATHLEN]; if (!(dirp = opendir(name))) { error("rcp: %s: %s\n", name, strerror(errno)); return; } last = strrchr(name, '/'); if (last == 0) last = name; else last++; if (pflag) { (void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n", statp->st_mtime, statp->st_atime); (void)write(rem, path, (int)strlen(path)); if (response() < 0) { closedir(dirp); return; } } (void)snprintf(path, sizeof(path), "D%04o %d %s\n", statp->st_mode&07777, 0, last); (void)write(rem, path, (int)strlen(path)); if (response() < 0) { closedir(dirp); return; } while ((dp = readdir(dirp))!=NULL) { if (dp->d_ino == 0) continue; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) { error("%s/%s: name too long.\n", name, dp->d_name); continue; } (void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name); vect[0] = path; source(1, vect); } closedir(dirp); (void)write(rem, "E\n", 2); (void)response(); } static int response(void) { register char *cp; char ch, resp, rbuf[BUFSIZ]; if (read(rem, &resp, sizeof(resp)) != sizeof(resp)) lostconn(0); cp = rbuf; switch(resp) { case 0: /* ok */ return 0; default: *cp++ = resp; /* FALLTHROUGH */ case 1: /* error, followed by err msg */ case 2: /* fatal error, "" */ do { if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) lostconn(0); *cp++ = ch; } while (cp < &rbuf[BUFSIZ] && ch != '\n'); if (!iamremote) write(2, rbuf, cp - rbuf); ++errs; if (resp == 1) return -1; exit(1); } /*NOTREACHED*/ return 0; } static void lostconn(int ignore) { (void)ignore; if (!iamremote) (void)fprintf(stderr, "rcp: lost connection\n"); exit(1); } static void sink(int argc, char *argv[]) { register char *cp; static BUF buffer; struct stat stb; struct timeval tv[2]; enum { YES, NO, DISPLAYED } wrerr; BUF *bp; off_t i, j; char ch, *targ; const char *why; int amt, count, exists, first, mask, mode; int ofd, setimes, size, targisdir; char *np, *vect[1], buf[BUFSIZ]; #define atime tv[0] #define mtime tv[1] #define SCREWUP(str) { why = str; goto screwup; } setimes = targisdir = 0; mask = umask(0); if (!pflag) (void)umask(mask); if (argc != 1) { error("rcp: ambiguous target\n"); exit(1); } targ = *argv; if (targetshouldbedirectory) verifydir(targ); (void)write(rem, "", 1); if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR) targisdir = 1; for (first = 1;; first = 0) { cp = buf; if (read(rem, cp, 1) <= 0) return; if (*cp++ == '\n') SCREWUP("unexpected "); do { if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) SCREWUP("lost connection"); *cp++ = ch; } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); *cp = 0; if (buf[0] == '\01' || buf[0] == '\02') { if (iamremote == 0) (void)write(2, buf + 1, (int)strlen(buf + 1)); if (buf[0] == '\02') exit(1); errs++; continue; } if (buf[0] == 'E') { (void)write(rem, "", 1); return; } if (ch == '\n') *--cp = 0; #define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); cp = buf; if (*cp == 'T') { setimes++; cp++; getnum(mtime.tv_sec); if (*cp++ != ' ') SCREWUP("mtime.sec not delimited"); getnum(mtime.tv_usec); if (*cp++ != ' ') SCREWUP("mtime.usec not delimited"); getnum(atime.tv_sec); if (*cp++ != ' ') SCREWUP("atime.sec not delimited"); getnum(atime.tv_usec); if (*cp++ != '\0') SCREWUP("atime.usec not delimited"); (void)write(rem, "", 1); continue; } if (*cp != 'C' && *cp != 'D') { /* * Check for the case "rcp remote:foo\* local:bar". * In this case, the line "No match." can be returned * by the shell before the rcp command on the remote is * executed so the ^Aerror_message convention isn't * followed. */ if (first) { error("%s\n", cp); exit(1); } SCREWUP("expected control record"); } mode = 0; for (++cp; cp < buf + 5; cp++) { if (*cp < '0' || *cp > '7') SCREWUP("bad mode"); mode = (mode << 3) | (*cp - '0'); } if (*cp++ != ' ') SCREWUP("mode not delimited"); size = 0; while (isdigit(*cp)) size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') SCREWUP("size not delimited"); if (targisdir) { static char *namebuf; static int cursize; int need; need = strlen(targ) + strlen(cp) + 250; if (need > cursize) { if (!(namebuf = malloc(need))) error("out of memory\n"); } (void)snprintf(namebuf, need, "%s%s%s", targ, *targ ? "/" : "", cp); np = namebuf; } else np = targ; exists = stat(np, &stb) == 0; if (buf[0] == 'D') { if (exists) { if ((stb.st_mode&S_IFMT) != S_IFDIR) { errno = ENOTDIR; goto bad; } if (pflag) (void)chmod(np, mode); } else if (mkdir(np, mode) < 0) goto bad; vect[0] = np; sink(1, vect); if (setimes) { setimes = 0; if (utimes(np, tv) < 0) error("rcp: can't set times on %s: %s\n", np, strerror(errno)); } continue; } if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { bad: error("rcp: %s: %s\n", np, strerror(errno)); continue; } if (exists && pflag) (void)fchmod(ofd, mode); (void)write(rem, "", 1); if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == 0) { (void)close(ofd); continue; } cp = bp->buf; count = 0; wrerr = NO; for (i = 0; i < size; i += BUFSIZ) { amt = BUFSIZ; if (i + amt > size) amt = size - i; count += amt; do { j = read(rem, cp, amt); if (j <= 0) { error("rcp: %s\n", j ? strerror(errno) : "dropped connection"); exit(1); } amt -= j; cp += j; } while (amt > 0); if (count == bp->cnt) { if (wrerr == NO && write(ofd, bp->buf, count) != count) wrerr = YES; count = 0; cp = bp->buf; } } if (count != 0 && wrerr == NO && write(ofd, bp->buf, count) != count) wrerr = YES; if (ftruncate(ofd, size)) { error("rcp: can't truncate %s: %s\n", np, strerror(errno)); wrerr = DISPLAYED; } (void)close(ofd); (void)response(); if (setimes && wrerr == NO) { setimes = 0; if (utimes(np, tv) < 0) { error("rcp: can't set times on %s: %s\n", np, strerror(errno)); wrerr = DISPLAYED; } } switch(wrerr) { case YES: error("rcp: %s: %s\n", np, strerror(errno)); break; case NO: (void)write(rem, "", 1); break; case DISPLAYED: break; } } screwup: error("rcp: protocol screwup: %s\n", why); exit(1); } static BUF * allocbuf(BUF *bp, int fd, int blksize) { struct stat stb; int size; if (fstat(fd, &stb) < 0) { error("rcp: fstat: %s\n", strerror(errno)); return(0); } size = roundup(stb.st_blksize, blksize); if (size == 0) size = blksize; if (bp->cnt < size) { if (bp->buf != 0) free(bp->buf); bp->buf = malloc(size); if (!bp->buf) { error("rcp: malloc: out of memory\n"); return NULL; } } bp->cnt = size; return(bp); } void error(const char *fmt, ...) { static FILE *fp; va_list ap; va_start(ap, fmt); ++errs; if (!fp && !(fp = fdopen(rem, "w"))) return; fprintf(fp, "%c", 0x01); vfprintf(fp, fmt, ap); fflush(fp); if (!iamremote) vfprintf(stderr, fmt, ap); va_end(ap); } static void nospace(void) { (void)fprintf(stderr, "rcp: out of memory.\n"); exit(1); } static void usage(void) { (void)fprintf(stderr, "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n"); exit(1); } netkit-rsh-0.17/.cvsignore100644 144 144 10 6775476744 15016 0ustar dhollandpeopleMCONFIG netkit-rsh-0.17/BUGS100644 144 144 671 6365176350 13517 0ustar dhollandpeoplercp: - should call rsh instead of using root - pukes on files in /proc - should warn that the connection isn't encrypted rlogin: - should use sigaction - should warn that the connection isn't encrypted rsh: - should try rexec if rcmd doesn't work - should warn that the connection isn't encrypted rexecd: - apparently the anti-portscanning fix (rcs rev 1.12 -> 1.13) causes rexecd to not work with some or all rexec clients. netkit-rsh-0.17/ChangeLog100644 144 144 11065 7136470626 14645 0ustar dhollandpeople23-Jul-2000: General audit for setuid/setgid/initgroups/etc. calls that didn't check for error. 22-Jul-2000: Use getdtablesize() instead of OPEN_MAX. (Olaf Kirch, okir@caldera.de) 5-Jan-2000: Fix to PAM handling. (Olaf Kirch, okir@caldera.de) Other PAM changes in rlogind. (Jeff Johnson, jbj@redhat.com, munged by yours truly.) 17-Dec-1999: Fix bug in rshd (hangs forever with zombie offspring). Also fix problems with rlogind. To be posted as patch 1, making netkit-rsh-0.16.1. 14-Dec-1999: netkit-rsh-0.16 is released. 14-Sep-1999: Close all files >= 3 before execing, in case libc has left something open. Also merge a Caldera doc fix. (Olaf Kirch, okir@caldera.de) 1-Aug-1999: Complete y2k and y2038 audit. 31-Jul-1999: Redid makefiles/config stuff for new confgen version. 3-Mar-1999: Add rexec client written by Michael Sadd (sadd@msc.cornell.edu). (I trust distributing this in netkit is ok; if not, it'll go away.) 22-Sep-1997: Clear crypt()'s internal state as well as the cleartext password. At least, hopefully. 27-Jul-1997: Erase cleartext passwords in rexecd after use. 13-Jun-1997: Massive cleanup of rlogind and rshd. 12-Jun-1997: netkit-rsh-0.10 released. 08-Jun-1997: Don't allow ordinary users to set SO_DEBUG in rsh. (Daniel Barlow, dan@telent.net) 19-May-1997: glibc fixes from Red Hat. 05-Apr-1997: Added configure script to generate MCONFIG. rlogind sets unused ttys to mode 600 now. PAM fixes from Red Hat. 08-Mar-1997: Split from full NetKit package. Generated this change log from NetKit's. 07-Mar-1997: Fixed rlogind to not let root use hosts.equiv. (Jean-Luc Szpyrka, Jean-luc.Szpyrka@sophia.inria.fr) 29-Dec-1996 NetKit-0.09 released. Assorted alpha/glibc patches. (Erik Troan, ewt@redhat.com) Assorted bug fixes from Debian. (Peter Tobias, tobias@et-inf.fho-emden.de) Hardened programs against DNS h_length spoofing attacks. Use inet_aton() everywhere instead of inet_addr(). Rudimentary shadow support in rexecd. Moved opening of stderr in rexecd after authentication so you can't do port scans with it. rlogind no longer gets mixed up when NIS or PAM does resolver operations. rlogind now supports a -h option to permit root rhosts files (which are not honored by default) and a -L option to disable all rhosts and hosts.equiv processing. rshd now supports the -h option also. To achieve the equivalent of rlogind's -L option, disable rshd entirely. Fix select problems in rsh. (Felix Egli, fegli@goldnet.ch) rlogin (and consequently rsh) doesn't dump core on high baudrates. (Alan Cox) 22-Aug-1996 NetKit-B-0.08 released. (almost) everything now compiles with lots of warnings turned on. Fixed rexecd to use fd_sets correctly. Clear environment in setuid programs to protect against library bugs. 25-Jul-1996 NetKit-B-0.07A released. 23-Jul-1996 NetKit-B-0.07 released. Integrated a collection of patches that had been lurking on the net, including the 256-ptys support for telnetd and passive mode ftp. Major security fixes, including to fingerd, lpr, rlogin, rsh, talkd, and telnetd. Do *not* use the sliplogin from earlier versions of this package, either. Much of the code builds without libbsd.a or bsd includes. Massive code cleanup. Almost everything compiles clean with gcc -Wall now. rusers and rusersd do not; patches to rpcgen to fix this would be appreciated if anyone feels like it. Kerberos support has been removed. It didn't work anyway, and proper Kerberos tools come with Kerberos. Added experimental support for PAM (Pluggable Authentication Modules) which may or may not actually work... New maintainer: David A. Holland, dholland@hcs.harvard.edu date not known NetKit-B-0.06 released. rsh was exiting before all of the output from the remote command was finished. This only happened together with Solaris machines, not SunOS 4.1. (Mark Weaver Mark_Weaver@brown.edu) Could you all please give rsh a very hard test? date not known NetKit-B-0.05 released. Fixed writing entries to /var/adm/wtmp by ftpd, rlogind and telnetd. (logwtmp.c) Florian This is only necessary for the GNU last, not for the one in util-linux... Changed rsh to stop looking for options after the first non-option. (See POSIXLY_CORRECT environment and "+" as first option for GNU getopt.) date not known NetKit-B-0.04 released. date not known NetKit-B-0.03 released. I found a bug-fix on of the news groups by Ulf Rimkus ulf@pc0435.psychologie.uni-marburg.de. 'rexecd' didn't set the environment at all. (Though it prepares all data for it...) netkit-rsh-0.17/MCONFIG.in100644 144 144 370 7017076031 14430 0ustar dhollandpeople# Dirs INSTALLROOT BINDIR SBINDIR MANDIR # Modes DAEMONMODE MANMODE SUIDMODE # Compiling ALLWARNINGS CC WARNINGS CFLAGS LDFLAGS LIBS # Features BSDSIGNAL FN(snprintf) FN(crypt) FN(forkpty) FN(logwtmp) TYPE(socklen_t) GLIBC LIBTERMCAP PAM SHADOW netkit-rsh-0.17/MRULES100644 144 144 173 6310315554 13752 0ustar dhollandpeople# Standard compilation rules (don't use make builtins) %.o: %.c $(CC) $(CFLAGS) $< -c %.o: %.cc $(CC) $(CFLAGS) $< -c netkit-rsh-0.17/Makefile100644 144 144 1003 7024720305 14466 0ustar dhollandpeople# You can do "make SUB=blah" to make only a few, or edit here, or both # You can also run make directly in the subdirs you want. SUB = rcp rexec rexecd rlogin rlogind rsh rshd %.build: (cd $(patsubst %.build, %, $@) && $(MAKE)) %.install: (cd $(patsubst %.install, %, $@) && $(MAKE) install) %.clean: (cd $(patsubst %.clean, %, $@) && $(MAKE) clean) all: $(patsubst %, %.build, $(SUB)) install: $(patsubst %, %.install, $(SUB)) clean: $(patsubst %, %.clean, $(SUB)) distclean: clean rm -f MCONFIG netkit-rsh-0.17/README100644 144 144 11161 7141137771 13745 0ustar dhollandpeopleThis is netkit-rsh-0.17 for Linux. This package updates netkit-rsh-0.16.1. If you're reading this off a CD, go right away and check the net archives for later versions and security fixes. As of this writing the home site for NetKit is ftp://ftp.uk.linux.org/pub/linux/Networking/netkit Contents: rexec Password-based remote execution program rsh Non-password-based remote execution program rcp Remote copy program using rsh rlogin Remote login program rshd Daemon for rsh connections rexecd Daemon for rexec connections rlogind Daemon for rlogin connections Note: None of these programs provide encryption or strong authentication of network connections. As such, their use is discouraged. The "ssh" protocol and package is a cryptographically secure replacement. Requires: Working compiler, libc, and kernel, and a recent ncurses or libtermcap. Security: This release contains no security fixes relative to netkit-rsh-0.16. However, as noted above, all programs in this package are inherently insecure except on trusted networks. They should not be used at all except with great caution. This package is maintained chiefly for the sake of compatibility. Note: do not rely on the behavior of the options that limit the use of .rhosts or /etc/hosts.equiv without testing them, as some of them depend on undocumented libc interfaces that may not work correctly on all systems. Versions of these programs prior to netkit-rsh-0.10 should not be used. WARNING: The PAM support in this version may be screwed up. If you use PAM, please be sure to double- and triple-check the behavior of rshd, rlogind, and rexecd to make sure they don't inadvertently grant access when it should be denied. If in doubt, get the SRPMs from Red Hat and use their sources instead. Installation: Do "./configure --help" and decide what options you want. The defaults should be suitable for most Linux systems. Then run the configure script. Do "make" to compile. Then (as root) do "make install". Save a backup copy of any mission-critical program in case the new one doesn't work, and so forth. We warned you. If you get gcc warnings from files in /usr/include, they are due to problems in your libc, not netkit. (You may only see them when compiling netkit because netkit turns on a lot of compiler warnings.) DEC CC: The DEC compiler for the Alpha is now freely available. This is a much better compiler with gcc, that is, it generates much better code. If you have the DEC compiler, you can explicitly use the DEC compiler instead of gcc by configuring like this: ./configure --with-c-compiler=ccc It is known to generate spurious warnings on some files. Also, some headers from some versions of glibc confuse it; that may prevent netkit from working. Other problems should be reported as bugs. Bugs: Please make sure the header files in /usr/include match the libc version installed in /lib and /usr/lib. If you have weird problems this is the most likely culprit. Also, before reporting a bug, be sure you're working with the latest version. If something doesn't compile for you, fix it and send diffs. If you can't, send the compiler's error output. If it compiles but doesn't work, send as complete a bug report as you can. Patches and fixes are welcome, as long as you describe adequately what they're supposed to fix. Please, one patch per distinct fix. Please do NOT send the whole archive back or reindent the source. Be sure to send all correspondence in e-mail to the netkit address. Postings to netnews or mailing lists will not be seen due to the enormous volume. Also, anything that doesn't get filed in the bug database is quite likely to end up forgotten. Please don't report known bugs (see the BUGS file(s)) unless you are including fixes. :-) Mail should be sent to: netbug@ftp.uk.linux.org Early in April 2000, a hacker broke into the machine that was hosting the netkit bug database for me and trashed it. Unfortunately, it seems backups hadn't gotten done for a while, so three months of mail (since mid-January) was lost. So, if you sent something and didn't hear back, or you sent something, heard back, but the changes failed to appear in this release (unlikely but possible) - please resend. Please see http://www.hcs.harvard.edu/~dholland/computers/netkit.html if you are curious why it was so long between the 0.10 and 0.16 releases. Future plans for netkit maintenance are still up in the air, but in the meantime new releases will still appear from time to time. I don't have a whole lot of cycles to spare to work on netkit, so things are likely to continue to be fairly slow. David A. Holland 23 July 2000 netkit-rsh-0.17/configure100755 144 144 33157 7140615675 15010 0ustar dhollandpeople#!/bin/sh # # This file was generated by confgen version 2. # Do not edit. # PREFIX='/usr' #EXECPREFIX='$PREFIX' INSTALLROOT='' BINMODE='755' #DAEMONMODE='$BINMODE' MANMODE='644' SUIDMODE='4755' while [ x$1 != x ]; do case $1 in --help) cat < __conftest.c int main() { int class=0; return class; } EOF if [ x"$CC" = x ]; then echo -n 'Looking for a C compiler... ' for TRY in egcs gcc g++ CC c++ cc; do ( $TRY __conftest.c -o __conftest || exit 1; ./__conftest || exit 1; ) >/dev/null 2>&1 || continue; CC=$TRY break; done if [ x"$CC" = x ]; then echo 'failed.' echo 'Cannot find a C compiler. Run configure with --with-c-compiler.' rm -f __conftest* exit fi echo "$CC" else echo -n 'Checking if C compiler works... ' if ( $CC __conftest.c -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' else echo 'no' echo 'Compiler '"$CC"' does not exist or cannot compile C; try another.' rm -f __conftest* exit fi fi echo -n "Checking if $CC accepts gcc warnings... " if ( $CC $WARNINGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' CC_WARNINGS=1 else echo 'no' fi if [ x$DEBUG = x ]; then echo -n "Checking if $CC accepts -O2... " if ( $CC -O2 __conftest.c -o __conftest ) >/dev/null 2>&1; then echo 'yes' CFLAGS="$CFLAGS -O2" else echo 'no' echo -n "Checking if $CC accepts -O... " if ( $CC -O __conftest.c -o __conftest ) >/dev/null 2>&1; then echo 'yes' CFLAGS="$CFLAGS -O" else echo 'no' fi fi else echo -n "Checking if $CC accepts -g... " if ( $CC -g __conftest.c -o __conftest ) >/dev/null 2>&1; then echo 'yes' CFLAGS="$CFLAGS -g" else echo 'no' fi fi LDFLAGS= LIBS= rm -f __conftest* ################################################## echo -n 'Checking for BSD signal semantics... ' cat <__conftest.c #include #include int count=0; void handle(int foo) { count++; } int main() { int pid=getpid(); signal(SIGINT, handle); kill(pid,SIGINT); kill(pid,SIGINT); kill(pid,SIGINT); if (count!=3) return 1; return 0; } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' else if ( $CC $CFLAGS -D__USE_BSD_SIGNAL __conftest.c -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo '-D__USE_BSD_SIGNAL' CFLAGS="$CFLAGS -D__USE_BSD_SIGNAL" else echo 'no' echo 'This package needs BSD signal semantics to run.' rm -f __conftest* exit fi fi rm -f __conftest* ################################################## echo -n 'Checking for ncurses... ' cat <__conftest.c #include #include #ifndef KEY_DOWN syntax error. /* not ncurses */ #endif int main() { endwin(); return 0; } EOF if ( $CC $CFLAGS __conftest.c -lncurses -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' NCURSES=1 else if ( $CC $CFLAGS -I/usr/include/ncurses __conftest.c -lncurses -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-I/usr/include/ncurses' CFLAGS="$CFLAGS -I/usr/include/ncurses" NCURSES=1 else echo 'no' fi fi if [ x$NCURSES != x ]; then LIBTERMCAP=-lncurses else echo -n 'Checking for traditional termcap... ' cat <__conftest.c #include #include int main() { tgetent(NULL, NULL); return 0; } EOF if ( $CC $CFLAGS __conftest.c -ltermcap -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-ltermcap' LIBTERMCAP=-ltermcap else echo 'not found' echo 'This package needs termcap to run.' rm -f __conftest* exit fi fi rm -f __conftest* ################################################## echo -n 'Checking for GNU libc... ' cat <__conftest.c #include #if defined(__GLIBC__) && (__GLIBC__ >= 2) int tester; #endif int main() { tester=6; return 0; } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' USE_GLIBC=1 else echo 'no' fi rm -f __conftest* ################################################## echo -n 'Checking for PAM... ' if [ x$WITHOUT_PAM != x ]; then echo disabled else cat <__conftest.c #include #include int main() { pam_start("configure", "nobody", NULL, NULL); return 0; } EOF if ( $CC $CFLAGS __conftest.c -ldl -lpam -lpam_misc -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' USE_PAM=1 else echo 'no' fi fi rm -f __conftest* ################################################## if [ x$USE_PAM = x ]; then echo -n 'Checking for shadow... ' if [ x$WITHOUT_SHADOW != x ]; then echo disabled else cat <__conftest.c #include #include int main() { getspnam("nobody"); return 0; } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' USE_SHADOW=1 LIBSHADOW= else if ( $CC $CFLAGS __conftest.c -lshadow -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-lshadow' USE_SHADOW=1 LIBSHADOW=-lshadow else echo 'no' fi fi fi fi rm -f __conftest* ################################################## echo -n 'Checking for crypt... ' cat <__conftest.c int main() { crypt("aa", "bb"); } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' else if ( $CC $CFLAGS __conftest.c -lcrypt -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-lcrypt' LIBS="$LIBS -lcrypt" else echo 'no' echo 'This package requires crypt.' rm -f __conftest* exit fi fi rm -f __conftest* ################################################## echo -n 'Checking for forkpty... ' cat <__conftest.c #include int main() { forkpty(0, 0, 0, 0); } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' else if ( $CC $CFLAGS __conftest.c -lutil -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-lutil' LIBS="$LIBS -lutil" else if ( $CC $CFLAGS __conftest.c -lbsd -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-lbsd' LIBBSD="-lbsd" else echo 'no' echo 'This package requires forkpty.' rm -f __conftest* exit fi fi fi rm -f __conftest* ################################################## echo -n 'Checking for logwtmp... ' cat <__conftest.c #ifdef __cplusplus extern "C" #endif void logwtmp(const char *, const char *, const char *); int main() { logwtmp(0, 0, 0); } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' else if ( $CC $CFLAGS __conftest.c -lutil -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-lutil' LIBS="$LIBS -lutil" else if ( $CC $CFLAGS __conftest.c -lbsd -o __conftest || exit 1 ) >/dev/null 2>&1; then echo '-lbsd' LIBBSD="-lbsd" else echo 'no' echo 'This package requires logwtmp.' rm -f __conftest* exit fi fi fi rm -f __conftest* ################################################## echo -n 'Checking for socklen_t... ' cat <__conftest.c #include #include #include int main() { struct sockaddr_in sn; socklen_t len = sizeof(sn); getpeername(0, (struct sockaddr *)&sn, &len); return 0; } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' else if ( $CC $CFLAGS -Dsocklen_t=int __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'int' CFLAGS="$CFLAGS -Dsocklen_t=int" else if ( $CC $CFLAGS -Dsocklen_t=size_t __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'size_t' CFLAGS="$CFLAGS -Dsocklen_t=size_t" else echo 'no' echo 'Cannot work out what to use for socklen_t. Help...' rm -f __conftest* exit fi fi fi rm -f __conftest* ################################################## echo -n 'Checking for snprintf declaration... ' cat <__conftest.c #include int main() { void *x = (void *)snprintf; printf("%lx", (long)x); return 0; } EOF if ( $CC $CFLAGS __conftest.c -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'ok' else if ( $CC $CFLAGS -D_GNU_SOURCE __conftest.c -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo '-D_GNU_SOURCE' CFLAGS="$CFLAGS -D_GNU_SOURCE" else echo 'manual' CFLAGS="$CFLAGS -DDECLARE_SNPRINTF" fi fi rm -f __conftest* echo -n 'Checking for snprintf implementation... ' cat <__conftest.c #include #include #ifdef DECLARE_SNPRINTF #ifdef __cplusplus extern "C" #endif /*__cplusplus*/ int snprintf(char *, int, const char *, ...); #endif /*DECLARE_SNPRINTF*/ int main() { char buf[32]; snprintf(buf, 8, "%s", "1234567890"); if (strlen(buf)!=7) return 1; return 0; } EOF if ( $CC $CFLAGS __conftest.c $LIBBSD -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo 'ok' else if ( $CC $CFLAGS __conftest.c -lsnprintf $LIBBSD -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo '-lsnprintf' LIBS="$LIBS -lsnprintf" else if ( $CC $CFLAGS __conftest.c -ldb $LIBBSD -o __conftest || exit 1 ./__conftest || exit 1 ) >/dev/null 2>&1; then echo '-ldb' LIBS="$LIBS -ldb" else echo 'missing' echo 'This package requires snprintf.' rm -f __conftest* exit fi fi fi rm -f __conftest* ################################################## ## libbsd should go last in case it's broken if [ "x$LIBBSD" != x ]; then LIBS="$LIBS $LIBBSD" fi echo 'Generating MCONFIG...' ( echo -n '# Generated by configure (confgen version 2) on ' date echo '#' echo echo "BINDIR=$BINDIR" echo "SBINDIR=$SBINDIR" echo "MANDIR=$MANDIR" echo "BINMODE=$BINMODE" echo "DAEMONMODE=$DAEMONMODE" echo "MANMODE=$MANMODE" echo "SUIDMODE=$SUIDMODE" echo "PREFIX=$PREFIX" echo "EXECPREFIX=$EXECPREFIX" echo "INSTALLROOT=$INSTALLROOT" echo "CC=$CC" if [ x$CC_WARNINGS != x ]; then CFLAGS="$CFLAGS $WARNINGS" fi echo "CFLAGS=$CFLAGS" | sed 's/= */=/' echo "LDFLAGS=$LDFLAGS" | sed 's/= */=/' echo "LIBS=$LIBS" | sed 's/= */=/' echo "LIBTERMCAP=$LIBTERMCAP" echo "USE_GLIBC=$USE_GLIBC" echo "USE_PAM=$USE_PAM" echo "USE_SHADOW=$USE_SHADOW" echo "LIBSHADOW=$LIBSHADOW" ) > MCONFIG netkit-rsh-0.17/version.h100644 144 144 144 7141140317 14650 0ustar dhollandpeople/* * String to embed in binaries to identify package */ char pkg[]="$NetKit: netkit-rsh-0.17 $"; netkit-rsh-0.17/rexec/ 40700 144 144 0 7141142014 14026 5ustar dhollandpeoplenetkit-rsh-0.17/rexec/.cvsignore100644 144 144 6 6774163707 16100 0ustar dhollandpeoplerexec netkit-rsh-0.17/rexec/Makefile100644 144 144 473 6750746664 15613 0ustar dhollandpeopleall: rexec include ../MCONFIG include ../MRULES PROG=rexec OBJS=rexec.o $(PROG): $(OBJS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ install: $(PROG) install -s -m $(BINMODE) $(PROG) $(INSTALLROOT)$(BINDIR) install -m $(MANMODE) $(PROG).1 $(INSTALLROOT)$(MANDIR)/man1 clean: rm -f *.o $(PROG) $(OBJS): ../version.h netkit-rsh-0.17/rexec/README100644 144 144 606 6667120665 15023 0ustar dhollandpeople To install, enter just enter the command make. You will be prompted for the installation locations. If the binary doesn't work, delete it and re-compile. Send me (sadd@msc.cornell.edu) any problems with installation. Mike Sadd Change Log: Sept. 16, 1996: Addes code to allow rexec to pass signals to the remote process. (Version 1.1) Sept. 12, 1996: Original code (Version 1)netkit-rsh-0.17/rexec/rexec.1100644 144 144 10721 6755642640 15372 0ustar dhollandpeople.\" Copyright (c) 1996 Michael Sadd (sadd@cornell.edu) .\" All rights reserved. .\" .\" 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. .\" .\" .TH REXEC 1 "August 15, 1999" .SH NAME rexec -- remote execution client for an exec server .SH SYNOPSIS .B rexec [ .B \-a \-c \-d \-h \-n \-s ] [--] host command .SH DESCRIPTION .B Rexec calls the .B rexec(3) routine to act as a client for the remote host's .B rexecd(8) server. .PP It asks that ``command'' be run on the host computer, using username/password authentication. See .B rexec(3) and .B rexecd(8) for details of the protocol. .SH OPTIONS .B Rexec accepts the following options: .\" .LP \fB\-a\fP .IP Do not set up an auxiliary channel for standard error from command; the remote standard error and output are then both returned on the local standard output. By default, .B rexec asks that a separate channel be set up for diagnostic output from the remote command. .\" .LP \fB\-c\fP .IP Do not close remote standard input when local standard input closes. Normally the standard input to the remote command is closed when the local standard input is closed. .\" .LP \fB\-d\fP .IP Turn on debugging information. In particular the command sent to the remote host will be echoed. .\" .LP \fB\-h\fP .IP Print a usage message. .\" .LP \fB\-n\fP .IP Explicitly prompt for name and password. Otherwise, $HOME/.netrc will be scanned for login information. .\" .LP \fB\-s\fP .IP Do not echo signals received by the rexec onto the remote process. Normally, signals which can be trapped are passed on to the remote process; then, when you type CNTRL-C, the remote process terminates as well. .\" .LP \fB\--\fP .IP Signals end of options to .B rexec to allow option switches in ``command.'' .PP The only option that is very useful is -n; even then, if you have not set up a password in $HOME/.netrc, you should still be prompted. .SH EXAMPLE .PP rexec othermachine -- cat ">remote_file; date" remote_file; date" #include #include #include #include #include #include #include #include #include #include #include #ifndef FD_SETSIZE #include #endif #define DEFAULT_PORT 512 #define MAX_PORT IPPORT_RESERVED #define EXTRA_PORT_LOW IPPORT_USERRESERVED #define EXTRA_PORT_MAX (EXTRA_PORT_LOW + 10000) #define BUFLEN 512 #ifndef EAGAIN #ifdef EWOULDBLOCK #define EAGAIN EWOULDBLOCK #else #define EAGAIN 0 #endif #endif #ifdef _PASSWORD_LEN #define USERLEN _PASSWORD_LEN #else #define USERLEN 256 #endif void parse_options(char *argv[], int argc, int *debug, int *extra_error, int *close_on_stdin, int *prompt, int *pass_sig, char **host, char **command); void usage(char *name); int echo_fd(int fd_to, int fd_from, char *prog_name, int debug); void set_signals(void); void echo_sig(int sig); /* These need to be global for signal passing. */ int aux_sock; /* Socket for auxiliary channel. */ int extra_error = 1; /* Setup special channel for standard error? */ int main(int argc, char *argv[]) { /* Program options and parameters. */ int debug = 0; /* Turn on debugging info? */ int prompt = 0; /* Prompt for name and password? */ int close_on_stdin = 1; /* Close socket on stdin, not on remote host. */ int pass_sig = 1; /* Should we pass signals to the remote process? */ char *host; /* Host name of remote machine. */ char *command; /* Command string to be executed on remote machine. */ /* Other variables. */ char *user_name = NULL, *passwd = NULL, user_buf[USERLEN]; struct servent *service; /* Returned from service datata base, give port. */ int port_exec; /* Rexec port to use. */ int sock; /* Rexec socket. */ int *p_to_aux_sock; /* Pointer to socket for auxiliary channel. */ int sock_open, stdin_open, aux_open, shut_down; /* Open file descriptor flags. */ parse_options(argv, argc, &debug, &extra_error, &close_on_stdin, &prompt, &pass_sig, &host, &command); service = getservbyname("exec","tcp"); if ( (port_exec = service->s_port) >= MAX_PORT ) { if (debug) { fprintf(stderr,"%s: getservbyname returned port %d\n",argv[0], ntohs(port_exec)); fprintf(stderr,"Using default port number %d instead.\n",DEFAULT_PORT); } port_exec = htons(DEFAULT_PORT); } if ( extra_error ) { int port_extra; /* Auxiliary port number. */ struct sockaddr_in aux_name; /* Auxilliary socket name for bind. */ int found_port = 0; if (debug) fprintf(stderr,"%s: Attempting to allocate channel for remote " "standard error\n", argv[0]); if ( (aux_sock = socket(PF_INET, SOCK_STREAM , 0)) < 0) { fprintf(stderr,"%s: Error in socket call: ",argv[0]); perror(NULL); exit(1); } aux_name.sin_family = AF_INET; aux_name.sin_addr.s_addr = htonl(INADDR_ANY); for ( port_extra = EXTRA_PORT_LOW; port_extra < EXTRA_PORT_MAX; ++port_extra) { aux_name.sin_port = htons(port_extra); found_port = (bind(aux_sock, (struct sockaddr *) &aux_name, sizeof(aux_name)) == 0); if ( found_port ) break; switch (errno) { case EADDRNOTAVAIL: case EADDRINUSE: case EACCES: if (debug) { fprintf(stderr,"%s: Error from bind for port No. %d: ",argv[0], port_extra); perror(NULL); fprintf(stderr,"Will try next port...\n"); } break; default: fprintf(stderr,"%s: Error binding to socket for aux. channel: ", argv[0]); perror(NULL); exit(1); break; } } if ( ! found_port ) { fprintf(stderr,"%s: Could not find available port for auxiliary ", argv[0]); fprintf(stderr,"channel in port range %d to %d.\n",EXTRA_PORT_LOW, EXTRA_PORT_MAX); exit(1); } p_to_aux_sock = &aux_sock; /* listen here? */ if (pass_sig) set_signals(); } else /* else we just want standard error directed as standar out--no aux */ p_to_aux_sock = NULL; if (prompt) { FILE *term_in,*term_out; if ( ( term_in = fopen("/dev/tty","r+")) == NULL) { term_in = stdin; term_out = stderr; } else term_out = term_in; fprintf(term_out,"Username at %s: ",host); user_name = fgets(user_buf,USERLEN,term_in); user_name[strlen(user_name)-1] = '\0'; /* Hopefully fgets always adds a newline. */ passwd = getpass("Password: "); } if ( (sock = rexec(&host, port_exec, user_name, passwd, command, p_to_aux_sock)) < 0 ) { fprintf(stderr,"%s: Error in rexec system call: ",argv[0]); perror(NULL); exit(1); } sock_open = stdin_open = aux_open = 1; shut_down = 0; while (sock_open || ( aux_open && extra_error )) /* echo stdin -> remote host remote host -> stdout until the remote host closes the socket. */ { fd_set read_set; FD_ZERO(&read_set); if (stdin_open) FD_SET(STDIN_FILENO, &read_set); if (sock_open) FD_SET(sock, &read_set); if ( extra_error && aux_open ) FD_SET(aux_sock, &read_set); /* Using an infinit timeout in select (last parameter = NULL). */ if ( select(FD_SETSIZE, &read_set, NULL, NULL, NULL) < 0 ) { fprintf(stderr,"%s: Error in select system call: ",argv[0]); perror(NULL); exit(1); } if ( FD_ISSET(sock, &read_set) ) /* Input available from remote host. */ sock_open = echo_fd(STDOUT_FILENO, sock, argv[0], debug); if ( FD_ISSET(STDIN_FILENO, &read_set) ) /* Input available from stdin. */ stdin_open = echo_fd(sock, STDIN_FILENO, argv[0], debug); if ( extra_error && FD_ISSET(aux_sock, &read_set) ) aux_open = echo_fd(STDERR_FILENO, aux_sock, argv[0], debug); if ( ! stdin_open && close_on_stdin && ! shut_down ) { if (shutdown(sock, 1) <0) { fprintf(stderr,"%s: Error from shutdown: ",argv[0]); perror(NULL); exit(1); } shut_down = 1; } } return 0; } #define OPTIONS "dahncs" void parse_options(char *argv[], int argc, int *debug, int *extra_error, int *close_on_stdin, int *prompt, int *pass_sig, char **host, char **command) { int opt; int len = 0,ind; while ((opt = getopt(argc, argv, OPTIONS)) > 0) switch (opt) { case 'd': *debug = 1; break; case 'a': *extra_error = 0; break; case 'h': usage(argv[0]); break; case 'n': *prompt = 1; break; case 'c': *close_on_stdin = 0; break; case 's': *pass_sig = 0; break; default: /* fprintf(stderr,"%s: Unknown option -%c\n",argv[0],(char)optopt);*/ usage(argv[0]); break; } if ( optind + 2 > argc ) /* User must have omitted host and command. */ { fprintf(stderr,"%s: Require at least a host name and command.\n",argv[0]); usage(argv[0]); } *host = argv[optind++]; for ( ind = optind; ind < argc; ++ind) len += strlen(argv[ind])+1; *command = (char *) malloc((len+1)*sizeof(char)); **command = '\0'; for ( ind = optind; (ind < argc) && strcat(*command," "); ++ind) (void) strcat(*command, argv[ind]); if (*debug) { fprintf(stderr,"%s: Host = %s\n", argv[0], *host); fprintf(stderr,"%s: Command to execute = %s\n", argv[0], *command); } } void usage(char *name) { fprintf(stderr,"Usage: %s [ -a -c -d -h -n ] [--] host command\n", name); fprintf(stderr,"\t-a: Do not set up an auxiliary channel for standard error\n"); fprintf(stderr,"\t-c: Do not close remote standard in when local input closes\n"); fprintf(stderr,"\t-d: Turn on debugging information.\n"); fprintf(stderr,"\t-h: Print this usage message.\n"); fprintf(stderr,"\t-n: Explicitly prompt for name and password.\n"); fprintf(stderr,"\t-s: Do not echo signals to the remote process. \n"); fprintf(stderr,"\t--: Signals end of options to allow options in `command`\n"); exit(1); } /* Echo's available input from fd_from to fd_to. Returns zero on end of file. */ int echo_fd(int fd_to, int fd_from, char *prog_name, int debug) { int sock_read; char buffer[BUFLEN]; (void)debug; if ( (sock_read = read(fd_from, buffer, BUFLEN)) < 0 ) { fprintf(stderr,"%s: Error in read from remote host: ", prog_name); perror(NULL); exit(1); } if ( sock_read ) write(fd_to, buffer, sock_read); return sock_read; } void set_signals(void) { int sig; for (sig = 1; sig < NSIG; ++sig) signal(sig, echo_sig); } void echo_sig(int sig) { char sigch = (char) sig; if (extra_error) write(aux_sock, &sigch, 1); raise(sig); } /* void set_no_blocking(int fd) { int old_flag = fcntl(fd, F_GETFD, 0); if (old_flag < 0) { perror("Error in fcntl(fd, F_GETFD, 0):"); exit(1); } if ( fcntl(fd, old_flag | O_NONBLOCK) < 0 ) { perror("Error in fcntl(fd, old_flag | O_NONBLOCK)"); exit(1); } } */ netkit-rsh-0.17/rexecd/ 40700 144 144 0 7141142014 14172 5ustar dhollandpeoplenetkit-rsh-0.17/rexecd/.cvsignore100644 144 144 7 6774163707 16245 0ustar dhollandpeoplerexecd netkit-rsh-0.17/rexecd/Makefile100644 144 144 1720 7024761714 15757 0ustar dhollandpeopleall: rexecd include ../MCONFIG include ../MRULES #ifdef HAVE_TCP_WRAPPER_LIBRARY #CFLAGS += -DTCP_WRAPPER #endif ifeq ($(USE_PAM),1) CFLAGS += -DUSE_PAM LIBS += -ldl -lpam endif ifeq ($(USE_SHADOW),1) CFLAGS += -DUSE_SHADOW LIBS += $(LIBSHADOW) endif # -DRESTRICT_FTP if you want to deny all users in /etc/ftpusers to use rexecd #ifeq ($(RESTRICT_FTP),1) #CFLAGS += -DRESTRICT_FTP #endif CFLAGS += -DRESTRICT_FTP=1 rexecd: rexecd.o $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ install: rexecd install -s -m$(DAEMONMODE) rexecd $(INSTALLROOT)$(SBINDIR)/in.rexecd install -m$(MANMODE) rexecd.8 $(INSTALLROOT)$(MANDIR)/man8/in.rexecd.8 ln -sf in.rexecd.8 $(INSTALLROOT)$(MANDIR)/man8/rexecd.8 ifeq ($(USE_PAM),1) @echo @echo You have chosen to use PAM as the authentication method @echo You should copy the rexec.pam file provided to /etc/pam.d @echo or if you know what you are doing, tailor it to your needs @echo endif clean: rm -f *.o rexecd rexecd.o: ../version.h netkit-rsh-0.17/rexecd/rexec.pam100644 144 144 611 6677105521 16103 0ustar dhollandpeople#%PAM-1.0 #auth required /lib/security/pam_securetty.so auth required /lib/security/pam_pwdb.so shadow nullok auth required /lib/security/pam_nologin.so auth required /lib/security/pam_listfile.so onerr=succeed item=user sense=deny file=/etc/ftpusers auth required /lib/security/pam_shells.so account required /lib/security/pam_pwdb.so netkit-rsh-0.17/rexecd/rexecd.8100644 144 144 11510 7141140320 15660 0ustar dhollandpeople.\" Copyright (c) 1983, 1991 The Regents of the University of California. .\" All rights reserved. .\" .\" 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. .\" .\" from: @(#)rexecd.8 6.5 (Berkeley) 3/16/91 .\" $Id: rexecd.8,v 1.13 2000/07/30 23:57:04 dholland Exp $ .\" .Dd March 16, 1991 .Dt REXECD 8 .Os "Linux NetKit (0.17)" .Sh NAME .Nm rexecd .Nd remote execution server .Sh SYNOPSIS .Nm rexecd .Sh DESCRIPTION .Nm Rexecd is the server for the .Xr rexec 3 routine. The server provides remote execution facilities with authentication based on user names and passwords. .Pp .Nm Rexecd listens for service requests at the port indicated in the ``exec'' service specification; see .Xr services 5 . When a service request is received the following protocol is initiated: .Bl -enum .It The server reads characters from the socket up to a NUL .Pq Ql \e0 byte. The resultant string is interpreted as an .Tn ASCII number, base 10. .It If the number received in step 1 is non-zero, it is interpreted as the port number of a secondary stream to be used for the .Em stderr . A second connection is then created to the specified port on the client's machine. .It A NUL terminated user name of at most 16 characters is retrieved on the initial socket. .It A NUL terminated, unencrypted password of at most 16 characters is retrieved on the initial socket. .It A NUL terminated command to be passed to a shell is retrieved on the initial socket. The length of the command is limited by the upper bound on the size of the system's argument list. .It .Nm Rexecd then validates the user as is done at login time and, if the authentication was successful, changes to the user's home directory, and establishes the user and group protections of the user. If any of these steps fail the connection is aborted with a diagnostic message returned. .It A NUL byte is returned on the initial socket and the command line is passed to the normal login shell of the user. The shell inherits the network connections established by .Nm rexecd . .El .Sh DIAGNOSTICS Except for the last one listed below, all diagnostic messages are returned on the initial socket, after which any network connections are closed. An error is indicated by a leading byte with a value of 1 (0 is returned in step 7 above upon successful completion of all the steps prior to the command execution). .Pp .Bl -tag -width Ds .It Sy username too long The name is longer than 16 characters. .It Sy password too long The password is longer than 16 characters. .It Sy command too long The command line passed exceeds the size of the argument list (as configured into the system). .It Sy Login incorrect. No password file entry for the user name existed or the wrong password was supplied. .It Sy \&No remote directory. The .Xr chdir command to the home directory failed. .It Sy Try again. A .Xr fork by the server failed. .It Sy : ... The user's login shell could not be started. This message is returned on the connection associated with the .Em stderr , and is not preceded by a flag byte. .El .Sh SEE ALSO .Xr rexec 3 .Sh BUGS A facility to allow all data and password exchanges to be encrypted should be present. .Sh HISTORY The .Nm command appeared in .Bx 4.2 . netkit-rsh-0.17/rexecd/rexecd.c100644 144 144 26674 7136470626 15777 0ustar dhollandpeople/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * 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. * * * 1-14-99 Karl R. Hakimian * * While the headers in this file claim only the purest decent from * their BSD roots, this program has had unspeakable things done to it * over the years. I have tried to clean things up and get them working * again. * * Put the port connect back to the client back where it belongs. * Replaced fork and coping data from stderr to error socket with a * dup2 of the error socket onto stderr. This code was in the BSD code, * but does not seem to be necessary and is broken under Linux * removed file descriptor from doit call. Not needed. f = 0 assumed * throughout * Removed unused variables. * * 3-31-99 Karl R. Hakimian * * Fixed problem where stderr socket can be left open if a daemon is * called from rexecd. * * KRH */ char copyright[] = "@(#) Copyright (c) 1983 The Regents of the University of California.\n" "All rights reserved.\n"; /* * From: @(#)rexecd.c 5.12 (Berkeley) 2/25/91 */ char rcsid[] = "$Id: rexecd.c,v 1.29 2000/07/23 04:16:22 dholland Exp $"; #include "../version.h" #include #include #include #include #include #include #include #include #include #include #include #include /* apparently necessary in some glibcs */ #include #include #include #include #include #ifdef USE_SHADOW #include #endif #ifdef USE_PAM #include #endif #define _PATH_FTPUSERS "/etc/ftpusers" #ifdef TCP_WRAPPER #include #include "log_tcp.h" struct from_host from_host; #endif int allow_severity = LOG_INFO; int deny_severity = LOG_WARNING; /* * remote execute server: * username\0 * password\0 * command\0 * data */ static void fatal(const char *); static void doit(struct sockaddr_in *fromp); static void getstr(char *buf, int cnt, const char *err); static const char *remote = NULL; int main(int argc, char **argv) { struct sockaddr_in from; socklen_t fromlen; (void)argc; fromlen = sizeof(from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { fprintf(stderr, "rexecd: getpeername: %s\n", strerror(errno)); return 1; } openlog(argv[0], LOG_PID, LOG_DAEMON); #ifdef TCP_WRAPPER /* Find out and report the remote host name. */ /* I don't think this works. -- dholland */ if (fromhost(&from_host) < 0 || !hosts_access(argv[0], &from_host)) refuse(&from_host); remote = hosts_info(&from_host); #else { struct hostent *h = gethostbyaddr((const char *)&from.sin_addr, sizeof(struct in_addr), AF_INET); if (!h || !h->h_name) { write(0, "\1Where are you?\n", 16); return 1; } /* Be advised that this may be utter nonsense. */ remote = strdup(h->h_name); } #endif syslog(allow_severity, "connect from %.128s", remote); doit(&from); return 0; } char username[20] = "USER="; char homedir[64] = "HOME="; char shell[64] = "SHELL="; char path[sizeof(_PATH_DEFPATH) + sizeof("PATH=")] = "PATH="; char *envinit[] = {homedir, shell, path, username, 0}; char **myenviron; #ifdef USE_PAM static char *PAM_username; static char *PAM_password; static int PAM_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int count = 0, replies = 0; struct pam_response *reply = NULL; int size = sizeof(struct pam_response); #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \ if (!reply) return PAM_CONV_ERR; \ size += sizeof(struct pam_response) #define COPY_STRING(s) (s) ? strdup(s) : NULL for (count = 0; count < num_msg; count++) { GET_MEM; switch (msg[count]->msg_style) { case PAM_PROMPT_ECHO_ON: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies++].resp = COPY_STRING(PAM_username); /* PAM frees resp */ break; case PAM_PROMPT_ECHO_OFF: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies++].resp = COPY_STRING(PAM_password); /* PAM frees resp */ break; case PAM_TEXT_INFO: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies++].resp = NULL; /* ignore it... */ break; case PAM_ERROR_MSG: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies++].resp = NULL; /* Must be an error of some sort... */ default: return PAM_CONV_ERR; } } if (reply) *resp = reply; return PAM_SUCCESS; } static struct pam_conv PAM_conversation = { &PAM_conv, NULL }; #endif /* USE_PAM */ static void doit(struct sockaddr_in *fromp) { char cmdbuf[ARG_MAX+1]; char user[16], pass[16]; struct passwd *pwd; int s = -1; u_short port; const char *theshell; const char *cp2; int ifd; #ifdef USE_PAM pam_handle_t *pamh; int pam_error; #else /* !USE_PAM */ char *namep, *cp; #ifdef RESTRICT_FTP char buf[BUFSIZ]; FILE *fp; #endif #endif /* USE_PAM */ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); #ifdef DEBUG { int t = open(_PATH_TTY, 2); if (t >= 0) { ioctl(t, TIOCNOTTY, NULL); close(t); } } #endif /* copy socket to stdout and stderr KRH */ dup2(0, 1); dup2(0, 2); alarm(60); port = 0; for (;;) { char c; if (read(0, &c, 1) != 1) exit(1); if (c == 0) break; port = port * 10 + c - '0'; } alarm(0); /* We must connect back to the client here if a port was provided. KRH */ if (port != 0) { s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) exit(1); #if 0 /* this shouldn't be necessary */ struct sockaddr_in asin = { AF_INET }; if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0) exit(1); #endif alarm(60); fromp->sin_port = htons(port); if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) exit(1); alarm(0); } getstr(user, sizeof(user), "username too long\n"); getstr(pass, sizeof(pass), "password too long\n"); getstr(cmdbuf, sizeof(cmdbuf), "command too long\n"); #ifdef USE_PAM #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \ pam_end(pamh, pam_error); exit(1); \ } PAM_username = user; PAM_password = pass; pam_error = pam_start("rexec", PAM_username, &PAM_conversation,&pamh); PAM_BAIL; pam_error = pam_authenticate(pamh, 0); PAM_BAIL; pam_error = pam_acct_mgmt(pamh, 0); PAM_BAIL; pam_error = pam_setcred(pamh, PAM_ESTABLISH_CRED); PAM_BAIL; pam_end(pamh, PAM_SUCCESS); /* If this point is reached, the user has been authenticated. */ setpwent(); pwd = getpwnam(user); endpwent(); #else /* !USE_PAM */ /* All of the following issues are dealt with in the PAM configuration file, so put all authentication/priviledge checks before the corresponding #endif below. */ setpwent(); pwd = getpwnam(user); if (pwd == NULL) { /* Log failed attempts. */ syslog(LOG_ERR, "LOGIN FAILURE from %.128s, %s", remote, user); fatal("Login incorrect.\n"); } endpwent(); #ifdef USE_SHADOW { struct spwd *sp = getspnam(pwd->pw_name); endspent(); if (sp) { pwd->pw_passwd = sp->sp_pwdp; } } #endif if (*pwd->pw_passwd != '\0') { namep = crypt(pass, pwd->pw_passwd); if (strcmp(namep, pwd->pw_passwd)) { /* Log failed attempts. */ syslog(LOG_ERR, "LOGIN FAILURE from %.128s, %s", remote, user); fatal("Login incorrect.\n"); } } /* Erase the cleartext password from memory. */ memset(pass, 0, sizeof(pass)); /* Clear out crypt()'s internal state, too. */ crypt("flurgle", pwd->pw_passwd); /* Disallow access to root account. */ if (pwd->pw_uid == 0) { syslog(LOG_ERR, "%s LOGIN REFUSED from %.128s", user, remote); fatal("Login incorrect.\n"); } #ifdef RESTRICT_FTP /* Disallow access to accounts in /etc/ftpusers. */ fp = fopen(_PATH_FTPUSERS, "r"); if (fp != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) { if ((cp = strchr(buf, '\n')) != NULL) *cp = '\0'; if (strcmp(buf, pwd->pw_name) == 0) { syslog(LOG_ERR, "%s LOGIN REFUSED from %.128s", user, remote); fatal("Login incorrect.\n"); } } fclose(fp); } else syslog(LOG_ERR, "cannot open /etc/ftpusers"); #endif #endif /* !USE_PAM */ /* Log successful attempts. */ syslog(LOG_INFO, "login from %.128s as %s", remote, user); if (chdir(pwd->pw_dir) < 0) { fatal("No remote directory.\n"); } write(2, "\0", 1); if (port) { /* If we have a port, dup STDERR on that port KRH */ close(2); dup2(s, 2); /* * We no longer need s, close it so we don't leave it * behind for a daemon. */ close (s); } if (*pwd->pw_shell == 0) { /* Shouldn't we deny access? (Can be done by PAM KRH) */ theshell = _PATH_BSHELL; } else theshell = pwd->pw_shell; /* shouldn't we check /etc/shells? (Can be done by PAM KRH) */ if (setgid(pwd->pw_gid)) { perror("setgid"); exit(1); } if (initgroups(pwd->pw_name, pwd->pw_gid)) { perror("initgroups"); exit(1); } if (setuid(pwd->pw_uid)) { perror("setuid"); exit(1); } strcat(path, _PATH_DEFPATH); myenviron = envinit; strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); strncat(shell, theshell, sizeof(shell)-7); strncat(username, pwd->pw_name, sizeof(username)-6); cp2 = strrchr(theshell, '/'); if (cp2) cp2++; else cp2 = theshell; /* * Close all fds, in case libc has left fun stuff like * /etc/shadow open. */ for (ifd = getdtablesize()-1; ifd > 2; ifd--) close(ifd); execle(theshell, cp2, "-c", cmdbuf, 0, myenviron); perror(theshell); exit(1); } static void fatal(const char *msg) { char x = 1; write(2, &x, 1); write(2, msg, strlen(msg)); exit(1); } static void getstr(char *buf, int cnt, const char *err) { char c; do { if (read(0, &c, 1) != 1) exit(1); *buf++ = c; if (--cnt <= 0) { fatal(err); } } while (c != 0); } netkit-rsh-0.17/rlogin/ 40700 144 144 0 7141142014 14212 5ustar dhollandpeoplenetkit-rsh-0.17/rlogin/.cvsignore100644 144 144 7 6774163710 16257 0ustar dhollandpeoplerlogin netkit-rsh-0.17/rlogin/Makefile100644 144 144 506 7024761715 15761 0ustar dhollandpeopleall: rlogin include ../MCONFIG include ../MRULES PROG=rlogin OBJS=rlogin.o $(PROG): $(OBJS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ install: $(PROG) install -s -o root -m$(SUIDMODE) $(PROG) $(INSTALLROOT)$(BINDIR) install -m $(MANMODE) $(PROG).1 $(INSTALLROOT)$(MANDIR)/man1 clean: rm -f *.o $(PROG) $(OBJS): ../version.h netkit-rsh-0.17/rlogin/des_rw.c100644 144 144 12320 6172405743 16004 0ustar dhollandpeople/*- * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * 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 static char sccsid[] = "@(#)des_rw.c 5.8 (Berkeley) 2/25/91"; #endif /* not lint */ #ifdef CRYPT #ifdef KERBEROS #include #include #include #include #include #include #include extern long random(); static unsigned char des_inbuf[10240], storage[10240], *store_ptr; static bit_64 *key; static u_char *key_schedule; /* * NB: These routines will not function properly if NBIO * is set */ /* * des_set_key * * Set des encryption/decryption key for use by the des_read and * des_write routines * * The inkey parameter is actually the DES initial vector, * and the insched is the DES Key unwrapped for faster decryption */ void des_set_key(inkey, insched) bit_64 *inkey; u_char *insched; { key = inkey; key_schedule = insched; } void des_clear_key() { bzero((char *) key, sizeof(C_Block)); bzero((char *) key_schedule, sizeof(Key_schedule)); } int des_read(fd, buf, len) int fd; register char *buf; int len; { int nreturned = 0; long net_len, rd_len; int nstored = 0; if (nstored >= len) { (void) bcopy(store_ptr, buf, len); store_ptr += len; nstored -= len; return(len); } else if (nstored) { (void) bcopy(store_ptr, buf, nstored); nreturned += nstored; buf += nstored; len -= nstored; nstored = 0; } if (krb_net_read(fd, &net_len, sizeof(net_len)) != sizeof(net_len)) { /* XXX can't read enough, pipe must have closed */ return(0); } net_len = ntohl(net_len); if (net_len <= 0 || net_len > sizeof(des_inbuf)) { /* preposterous length; assume out-of-sync; only recourse is to close connection, so return 0 */ return(0); } /* the writer tells us how much real data we are getting, but we need to read the pad bytes (8-byte boundary) */ rd_len = roundup(net_len, 8); if (krb_net_read(fd, des_inbuf, rd_len) != rd_len) { /* pipe must have closed, return 0 */ return(0); } (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ storage, /* outbuf */ net_len, /* length */ key_schedule, /* DES key */ key, /* IV */ DECRYPT); /* direction */ if(net_len < 8) store_ptr = storage + 8 - net_len; else store_ptr = storage; nstored = net_len; if (nstored > len) { (void) bcopy(store_ptr, buf, len); nreturned += len; store_ptr += len; nstored -= len; } else { (void) bcopy(store_ptr, buf, nstored); nreturned += nstored; nstored = 0; } return(nreturned); } static unsigned char des_outbuf[10240]; /* > longest write */ int des_write(fd, buf, len) int fd; char *buf; int len; { static int seeded = 0; static char garbage_buf[8]; long net_len, garbage; if(len < 8) { if(!seeded) { seeded = 1; srandom((int) time((long *)0)); } garbage = random(); /* insert random garbage */ (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); /* this "right-justifies" the data in the buffer */ (void) bcopy(buf, garbage_buf + 8 - len, len); } /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, des_outbuf, (len < 8) ? 8 : len, key_schedule, /* DES key */ key, /* IV */ ENCRYPT); /* tell the other end the real amount, but send an 8-byte padded packet */ net_len = htonl(len); (void) write(fd, &net_len, sizeof(net_len)); (void) write(fd, des_outbuf, roundup(len,8)); return(len); } #endif /* KERBEROS */ #endif /* CRYPT */ netkit-rsh-0.17/rlogin/rlogin.1100644 144 144 12621 7141140320 15715 0ustar dhollandpeople.\" Copyright (c) 1983, 1990 The Regents of the University of California. .\" All rights reserved. .\" .\" 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. .\" .\" from: @(#)rlogin.1 6.19 (Berkeley) 7/27/91 .\" $Id: rlogin.1,v 1.11 2000/07/30 23:57:04 dholland Exp $ .\" .Dd August 15, 1999 .Dt RLOGIN 1 .Os "Linux NetKit (0.17)" .Sh NAME .Nm rlogin .Nd remote login .Sh SYNOPSIS .Ar rlogin .Op Fl 8EKLdx .Op Fl e Ar char .Op Fl k Ar realm .Op Fl l Ar username .Ar host .Sh DESCRIPTION .Nm Rlogin starts a terminal session on a remote host .Ar host . .Pp .Nm Rlogin first attempts to use the Kerberos authorization mechanism, described below. If the remote host does not supporting Kerberos the standard Berkeley .Pa rhosts authorization mechanism is used. The options are as follows: .Bl -tag -width flag .It Fl 8 The .Fl 8 option allows an eight-bit input data path at all times; otherwise parity bits are stripped except when the remote side's stop and start characters are other than ^S/^Q . .It Fl E The .Fl E option stops any character from being recognized as an escape character. When used with the .Fl 8 option, this provides a completely transparent connection. .It Fl K The .Fl K option turns off all Kerberos authentication. .It Fl L The .Fl L option allows the rlogin session to be run in ``litout'' (see .Xr tty 4 ) mode. .It Fl d The .Fl d option turns on socket debugging (see .Xr setsockopt 2 ) on the TCP sockets used for communication with the remote host. .It Fl e The .Fl e option allows user specification of the escape character, which is ``~'' by default. This specification may be as a literal character, or as an octal value in the form \ennn. .It Fl k The .FL k option requests rlogin to obtain tickets for the remote host in realm .Ar realm instead of the remote host's realm as determined by .Xr krb_realmofhost 3 . .It Fl x The .Fl x option turns on .Tn DES encryption for all data passed via the rlogin session. This may impact response time and .Tn CPU utilization, but provides increased security. .El .Pp A line of the form ``.'' disconnects from the remote host. Similarly, the line ``^Z'' will suspend the .Nm rlogin session, and ``'' suspends the send portion of the rlogin, but allows output from the remote system. By default, the tilde (``~'') character is the escape character, and normally control-Y (``^Y'') is the delayed-suspend character. .Pp All echoing takes place at the remote site, so that (except for delays) the .Nm rlogin is transparent. Flow control via ^S/^Q and flushing of input and output on interrupts are handled properly. .Sh KERBEROS AUTHENTICATION Each user may have a private authorization list in the file .Pa .klogin in their home directory. Each line in this file should contain a Kerberos principal name of the form .Ar principal.instance@realm . If the originating user is authenticated to one of the principals named in .Pa .klogin , access is granted to the account. The principal .Ar accountname.@localrealm is granted access if there is no .Pa .klogin file. Otherwise a login and password will be prompted for on the remote machine as in .Xr login 1 . To avoid certain security problems, the .Pa .klogin file must be owned by the remote user. .Pp If Kerberos authentication fails, a warning message is printed and the standard Berkeley .Nm rlogin is used instead. .Sh ENVIRONMENT The following environment variable is utilized by .Nm rlogin : .Bl -tag -width TERM .It Ev TERM Determines the user's terminal type. .El .Sh SEE ALSO .Xr rsh 1 , .Xr kerberos 3 , .Xr krb_sendauth 3 , .Xr krb_realmofhost 3 .Sh HISTORY The .Nm rlogin command appeared in .Bx 4.2 . .Sh BUGS .Nm Rlogin will be replaced by .Xr telnet 1 in the near future. .Pp More of the environment should be propagated. netkit-rsh-0.17/rlogin/rlogin.c100644 144 144 46703 7136470626 16032 0ustar dhollandpeople/* * Copyright (c) 1983, 1990 The Regents of the University of California. * All rights reserved. * * 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. */ char copyright[] = "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n" "All rights reserved.\n"; /* * From: @(#)rlogin.c 5.33 (Berkeley) 3/1/91 * Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall * Exp Locker: kfall */ char rcsid[] = "$Id: rlogin.c,v 1.20 2000/07/23 04:16:22 dholland Exp $"; #include "../version.h" /* * rlogin - remote login */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * rlogin has problems with urgent data when logging into suns which * results in the connection being closed with an IO error. SUN_KLUDGE * is a work around - the actual bug is probably in tcp.c in the kernel, but * I haven't managed to find it yet. * Andrew.Tridgell@anu.edu.au (12th March 1993) * * This should all be ancient history now. * dholland@hcs.harvard.edu (15-Jul-1996) */ #if 0 #define SUN_KLUDGE #endif #ifndef TIOCPKT_WINDOW #define TIOCPKT_WINDOW 0x80 #endif #ifndef TIOCPKT_FLUSHWRITE #define TIOCPKT_FLUSHWRITE 0x02 #define TIOCPKT_NOSTOP 0x10 #define TIOCPKT_DOSTOP 0x20 #endif /* concession to Sun */ #ifndef SIGUSR1 #define SIGUSR1 30 #endif struct termios defmodes; struct termios ixon_state; static int eight, litout, rem; static int noescape; static u_char escapechar = '~'; static int childpid; static char defkill, defquit, defstart, defstop, defeol, defeof, defintr; static char defsusp, defdsusp, defreprint, defdiscard, defwerase, deflnext; #ifdef sun struct winsize { unsigned short ws_row, ws_col; unsigned short ws_xpixel, ws_ypixel; }; #endif struct winsize winsize; #ifndef sun #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) #endif static void mode(int f); static void stop(char cmdc); static void usage(void); static void doit(long omask); static void done(int status); static void writer(void); static int reader(int omask); static void msg(const char *str); static void setsignal(int sig, void (*act)(int)); static void sendwindow(void); static void echo(char c); static void stop(char cmdc); static void catch_child(int); static void copytochild(int); static void writeroob(int); static void lostpeer(int); static u_char getescape(const char *p); /* * It is beyond me why code of this nature should be necessary. * Why can't termios hand back an integer? */ static const char *getspeedstr(speed_t speed) { switch(speed) { case B0: return "0"; case B50: return "50"; case B75: return "75"; case B110: return "110"; case B134: return "134"; case B150: return "150"; case B200: return "200"; case B300: return "300"; case B600: return "600"; case B1200: return "1200"; case B1800: return "1800"; case B2400: return "2400"; case B4800: return "4800"; case B9600: return "9600"; case B19200: return "19200"; case B38400: return "38400"; case B57600: return "57600"; case B115200: return "115200"; case B230400: return "230400"; case B460800: return "460800"; } return "9600"; } int main(int argc, char **argv) { struct passwd *pw; struct servent *sp; struct termios tios; long omask; int argoff, ch, dflag, one, uid; char *host, *p, *user, term[1024]; const char *t; char *null = NULL; argoff = dflag = 0; one = 1; host = user = NULL; if ((p = strrchr(argv[0], '/'))!=NULL) ++p; else p = argv[0]; if (strcmp(p, "rlogin")) host = p; /* handle "rlogin host flags" */ if (!host && argc > 2 && argv[1][0] != '-') { host = argv[1]; argoff = 1; } #define OPTIONS "8EKLde:l:" while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) switch(ch) { case '8': eight = 1; break; case 'E': noescape = 1; break; case 'K': break; case 'L': litout = 1; break; case 'd': dflag = 1; break; case 'e': escapechar = getescape(optarg); break; case 'l': user = optarg; break; case '?': default: usage(); } optind += argoff; argc -= optind; argv += optind; /* if haven't gotten a host yet, do so */ if (!host && !(host = *argv++)) usage(); if (*argv) usage(); if (!(pw = getpwuid(uid = getuid()))) { fprintf(stderr, "rlogin: unknown user id.\n"); exit(1); } if (!user) user = pw->pw_name; sp = NULL; if (sp == NULL) sp = getservbyname("login", "tcp"); if (sp == NULL) { fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); exit(1); } t = getenv("TERM"); if (!t) t = "network"; if (tcgetattr(0, &tios) == 0) { speed_t speed = cfgetispeed(&tios); const char *speedstr = getspeedstr(speed); snprintf(term, sizeof(term), "%.256s/%s", t, speedstr); } else snprintf(term, sizeof(term), "%.256s", t); __environ = &null; get_window_size(0, &winsize); /* * Moved before rcmd call so that if get a SIGPIPE in rcmd * we will have the defmodes set already. */ tcgetattr(0, &defmodes); tcgetattr(0, &ixon_state); signal(SIGPIPE, lostpeer); /* will use SIGUSR1 for window size hack, so hold it off */ omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); if (rem < 0) exit(1); if (dflag) { if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) fprintf(stderr, "rlogin: setsockopt(SO_DEBUG): %s.\n", strerror(errno)); } #ifdef IP_TOS one = IPTOS_LOWDELAY; if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(one)) < 0) fprintf(stderr, "rlogin: setsockopt(TOS): %s.\n", strerror(errno)); #endif if (setuid(uid)) { fprintf(stderr, "rlogin: setuid: %s\n", strerror(errno)); exit(1); } doit(omask); /*NOTREACHED*/ return 0; } static void doit(long omask) { struct termios tios; tcgetattr(0, &tios); tios.c_cc[VMIN] = 1; tios.c_cc[VTIME] = 1; defkill = tios.c_cc[VKILL]; defquit = tios.c_cc[VQUIT]; defstart = tios.c_cc[VSTART]; defstop = tios.c_cc[VSTOP]; defeol = tios.c_cc[VEOL]; defeof = tios.c_cc[VEOF]; defintr = tios.c_cc[VINTR]; defsusp = tios.c_cc[VSUSP]; /* stop process */ #ifdef VDSUSP defdsusp = tios.c_cc[VDSUSP]; /* delayed stop process */ #else defdsusp = (char)0xFF; /* cast 0xFF for 32/64 bit platforms */ #endif defreprint = tios.c_cc[VREPRINT]; /* rprint line */ defdiscard = tios.c_cc[VDISCARD]; /* flush output */ defwerase = tios.c_cc[VWERASE]; /* word erase */ deflnext = tios.c_cc[VLNEXT]; /* literal next char */ signal(SIGINT, SIG_IGN); setsignal(SIGHUP, exit); setsignal(SIGQUIT, exit); /* * Do this *before* forking... */ signal(SIGCHLD, catch_child); childpid = fork(); if (childpid == -1) { fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); done(1); } if (childpid == 0) { mode(1); if (reader(omask) == 0) { msg("connection closed."); exit(0); } sleep(1); msg("\007connection closed."); exit(1); } /* * We may still own the socket, and may have a pending SIGURG (or might * receive one soon) that we really want to send to the reader. Set a * trap that simply copies such signals to the child. */ signal(SIGURG, copytochild); signal(SIGUSR1, writeroob); sigsetmask(omask); #ifdef __linux__ /*sleep(1);*/ /* why?!? */ #endif writer(); msg("closed connection."); done(0); } /* trap a signal, unless it is being ignored. */ static void setsignal(int sig, void (*act)(int)) { int omask = sigblock(sigmask(sig)); if (signal(sig, act) == SIG_IGN) signal(sig, SIG_IGN); sigsetmask(omask); } static void done(int status) { int w, wstatus; mode(0); if (childpid > 0) { /* make sure catch_child does not snap it up */ signal(SIGCHLD, SIG_DFL); if (kill(childpid, SIGKILL) >= 0) while ((w = wait(&wstatus)) > 0 && w != childpid); } exit(status); } int dosigwinch; void sigwinch(int); /* * This is called when the reader process gets the out-of-band (urgent) * request to turn on the window-changing protocol. */ static void writeroob(int ignore) { (void)ignore; if (dosigwinch == 0) { sendwindow(); signal(SIGWINCH, sigwinch); } dosigwinch = 1; } void catch_child(int ignore) { union wait status; int pid; (void)ignore; for (;;) { pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); if (pid == 0) return; /* if the child (reader) dies, just quit */ if (pid < 0 || (pid == childpid && !WIFSTOPPED(status))) done((int)(status.w_termsig | status.w_retcode)); } /* NOTREACHED */ } /* * writer: write to remote: 0 -> line. * ~. terminate * ~^Z suspend rlogin process. * ~ suspend rlogin process, but leave reader alone. */ static void writer(void) { register int bol, local, n; char c; bol = 1; /* beginning of line */ local = 0; for (;;) { n = read(STDIN_FILENO, &c, 1); if (n <= 0) { if (n < 0 && errno == EINTR) continue; break; } /* * If we're at the beginning of the line and recognize a * command character, then we echo locally. Otherwise, * characters are echo'd remotely. If the command character * is doubled, this acts as a force and local echo is * suppressed. */ if (bol) { bol = 0; if (!noescape && c == escapechar) { local = 1; continue; } } else if (local) { local = 0; if (c == '.' || c == defeof) { echo(c); break; } if (c == defsusp || c == defdsusp) { bol = 1; echo(c); stop(c); continue; } if (c != escapechar) write(rem, &escapechar, 1); } if (write(rem, &c, 1) == 0) { msg("line gone"); break; } bol = c == defkill || c == defeof || c == defintr || c == defsusp || c == '\r' || c == '\n'; } } static void echo(char c) { register char *p; char buf[8]; p = buf; c &= 0177; *p++ = escapechar; if (c < ' ') { *p++ = '^'; *p++ = c + '@'; } else if (c == 0177) { *p++ = '^'; *p++ = '?'; } else *p++ = c; *p++ = '\r'; *p++ = '\n'; write(STDOUT_FILENO, buf, p - buf); } static void stop(char cmdc) { mode(0); signal(SIGCHLD, SIG_IGN); kill(cmdc == defsusp ? 0 : getpid(), SIGTSTP); signal(SIGCHLD, catch_child); mode(1); sigwinch(SIGWINCH); /* check for size changes */ } void sigwinch(int signum) { struct winsize ws; (void)signum; if (dosigwinch && get_window_size(0, &ws) == 0 && bcmp(&ws, &winsize, sizeof(ws))) { winsize = ws; sendwindow(); } #ifdef SUN_KLUDGE signal(SIGWINCH,sigwinch); #endif } /* * Send the window size to the server via the magic escape */ static void sendwindow(void) { struct winsize *wp; char obuf[4 + sizeof (struct winsize)]; wp = (struct winsize *)(obuf+4); obuf[0] = (char)0377; /* (char) casts added for 32/64 bit machines */ obuf[1] = (char)0377; obuf[2] = (char)'s'; obuf[3] = (char)'s'; wp->ws_row = htons(winsize.ws_row); wp->ws_col = htons(winsize.ws_col); wp->ws_xpixel = htons(winsize.ws_xpixel); wp->ws_ypixel = htons(winsize.ws_ypixel); write(rem, obuf, sizeof(obuf)); } /* * reader: read from remote: line -> 1 */ #define READING 1 #define WRITING 2 static sigjmp_buf rcvtop; static int ppid, rcvcnt, rcvstate; static char rcvbuf[8 * 1024]; static void oob_real(void) { struct termios tios; int atmark, n, rcvd; unsigned char waste[BUFSIZ], mark; rcvd = 0; while (recv(rem, &mark, 1, MSG_OOB) < 0) { sleep(1); switch (errno) { case EWOULDBLOCK: /* * Urgent data not here yet. It may not be possible * to send it yet if we are blocked for output and * our input buffer is full. */ if (rcvcnt < (int)sizeof(rcvbuf)) { n = read(rem, rcvbuf + rcvcnt, sizeof(rcvbuf) - rcvcnt); if (n <= 0) return; rcvd += n; } else { n = read(rem, waste, sizeof(waste)); if (n <= 0) return; } continue; default: return; } } if (mark & TIOCPKT_WINDOW) { /* Let server know about window size changes */ kill(ppid, SIGUSR1); } if (!eight && (mark & TIOCPKT_NOSTOP)) { tcgetattr(0, &tios); tios.c_iflag &= ~IXON; /* tios.c_lflag &= ~ICANON; */ tcsetattr(0, TCSADRAIN, &tios); } if (!eight && (mark & TIOCPKT_DOSTOP)) { tcgetattr(0, &tios); /* tios.c_lflag |= ICANON;*/ tios.c_iflag |= IXON; tcsetattr(0, TCSADRAIN, &tios); } if (mark & TIOCPKT_FLUSHWRITE) { tcflush(1, TCOFLUSH); for (;;) { if (ioctl(rem, SIOCATMARK, &atmark) < 0) { fprintf(stderr, "rlogin: ioctl: %s.\n", strerror(errno)); break; } if (atmark) break; n = read(rem, waste, sizeof (waste)); if (n <= 0) break; } /* * Don't want any pending data to be output, so clear the recv * buffer. If we were hanging on a write when interrupted, * don't want it to restart. If we were reading, restart * anyway. */ rcvcnt = 0; siglongjmp(rcvtop, 1); } /* oob does not do FLUSHREAD (alas!) */ /* * If we filled the receive buffer while a read was pending, longjmp * to the top to restart appropriately. Don't abort a pending write, * however, or we won't know how much was written. */ if (rcvd && rcvstate == READING) { siglongjmp(rcvtop, 1); } } static void oob(int ignore) { (void)ignore; oob_real(); #ifdef SUN_KLUDGE signal(SIGURG,oob); #endif } /* reader: read from remote: line -> 1 */ static int reader(int omask) { int pid = getpid(); int n, remaining; char *volatile bufp = rcvbuf; signal(SIGTTOU, SIG_IGN); signal(SIGURG, oob); ppid = getppid(); /* fcntl(rem, F_SETOWN, pid); */ ioctl(rem, SIOCSPGRP, &pid); /* @@@ */ sigsetjmp(rcvtop, 1); sigsetmask(omask); for (;;) { while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { rcvstate = WRITING; n = write(STDOUT_FILENO, bufp, remaining); if (n < 0) { if (errno != EINTR) return -1; continue; } bufp += n; } bufp = rcvbuf; rcvcnt = 0; rcvstate = READING; rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); /* * If we get a EIO from a read then it may mean that we have unread ungent data * waiting that is getting in the way. We probably have got more then one lot of * urgent data but we only got one SIGURG due to a problem in the kernel tcp. * We can try and fix this by sending ourself a SIGURG and pretending the error * never occurred. This might be a problem if we really _should_ be getting * a EIO for some unrelated reason. (AJT 3/93) * * Hmm, I just checked this with the current (NET-2e BETA-1) kernel, and * it seems that this patch isn't needed anymore. FvK 09/20/93 */ #ifdef XX_SUN_KLUDGE if (rcvcnt < 0 && errno == EIO) { errno = 0; kill(getpid(),SIGURG); continue; } #endif if (rcvcnt == 0) return (0); if (rcvcnt < 0) { if (errno == EINTR) continue; fprintf(stderr, "rlogin: read: %s.\n", strerror(errno)); return -1; } } } static void mode(int f) { struct termios tios; tcgetattr(0, &tios); switch(f) { case 0: /* * remember whether IXON was set, so it can be restored * when mode(1) is next done */ tcgetattr(0, &ixon_state); /* * copy the initial modes we saved into sb; this is * for restoring to the initial state */ memcpy(&tios, &defmodes, sizeof(defmodes)); break; case 1: /* turn off output mappings */ tios.c_oflag &= ~(ONLCR|OCRNL); /* * turn off canonical processing and character echo; * also turn off signal checking -- ICANON might be * enough to do this, but we're being careful */ tios.c_lflag &= ~(ECHO|ICANON|ISIG); tios.c_iflag &= ~(ICRNL); tios.c_cc[VTIME] = 1; tios.c_cc[VMIN] = 1; if (eight) tios.c_iflag &= ~(ISTRIP); /* preserve tab delays, but turn off tab-to-space expansion */ if ((tios.c_oflag & TABDLY) == TAB3) tios.c_oflag &= ~TAB3; /* * restore current flow control state */ if ((ixon_state.c_iflag & IXON) && ! eight) { tios.c_iflag |= IXON; } else { tios.c_iflag &= ~IXON; } tios.c_cc[VSUSP] = 255; tios.c_cc[VEOL] = 255; tios.c_cc[VREPRINT] = 255; tios.c_cc[VDISCARD] = 255; tios.c_cc[VWERASE] = 255; tios.c_cc[VLNEXT] = 255; tios.c_cc[VEOL2] = 255; break; default: return; } tcsetattr(0, TCSADRAIN, &tios); } static void lostpeer(int ignore) { (void)ignore; signal(SIGPIPE, SIG_IGN); msg("\007connection closed."); done(1); } /* copy SIGURGs to the child process. */ void copytochild(int ignore) { (void)ignore; kill(childpid, SIGURG); #ifdef SUN_KLUDGE signal(SIGCHLD,copytochild); #endif } static void msg(const char *str) { fprintf(stderr, "rlogin: %s\r\n", str); } static void usage(void) { fprintf(stderr, "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", "8EL", " "); exit(1); } /* * The following routine provides compatibility (such as it is) between 4.2BSD * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. */ #ifdef sun get_window_size(fd, wp) int fd; struct winsize *wp; { struct ttysize ts; int error; error = ioctl(0, TIOCGSIZE, &ts); if (error != 0) return error; wp->ws_row = ts.ts_lines; wp->ws_col = ts.ts_cols; wp->ws_xpixel = 0; wp->ws_ypixel = 0; return 0; } #endif static u_char getescape(const char *p) { long val; int len; if ((len = strlen(p)) == 1) /* use any single char, including '\' */ return (u_char)*p; /* otherwise, \nnn */ if (*p == '\\' && len >= 2 && len <= 4) { val = strtol(++p, NULL, 8); for (;;) { if (!*++p) return (u_char)val; if (*p < '0' || *p > '8') break; } } msg("illegal option value -- e"); usage(); /* NOTREACHED */ return 0; } netkit-rsh-0.17/rlogind/ 40700 144 144 0 7141142015 14357 5ustar dhollandpeoplenetkit-rsh-0.17/rlogind/.cvsignore100644 144 144 10 6774163710 16435 0ustar dhollandpeoplerlogind netkit-rsh-0.17/rlogind/Makefile100644 144 144 1135 7024761715 16144 0ustar dhollandpeopleall: rlogind include ../MCONFIG include ../MRULES OBJS = rlogind.o network.o auth.o # logwtmp.o ifeq ($(USE_PAM),1) OBJS += sockconv.o CFLAGS += -DUSE_PAM LIBS += -ldl -lpam -lpam_misc endif rlogind: $(OBJS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ rlogind.o: pathnames.h logwtmp.h rlogind.h ../version.h logwtmp.o: logwtmp.h auth.o network.o: rlogind.h install: rlogind install -s -m$(DAEMONMODE) rlogind $(INSTALLROOT)$(SBINDIR)/in.rlogind install -m$(MANMODE) rlogind.8 $(INSTALLROOT)$(MANDIR)/man8/in.rlogind.8 ln -sf in.rlogind.8 $(INSTALLROOT)$(MANDIR)/man8/rlogind.8 clean: rm -f *.o rlogind netkit-rsh-0.17/rlogind/auth.c100644 144 144 17000 7035005535 15620 0ustar dhollandpeople/*- * Copyright (c) 1983, 1988, 1989 The Regents of the University of California. * All rights reserved. * * 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. */ #include #include #include "rlogind.h" #ifdef USE_PAM /* * Modifications for Linux-PAM: Al Longyear * General code clean up: Andrew Morgan * Re-built with #ifdef USE_PAM: Michael K. Johnson , * Red Hat Software * * The Linux-PAM mailing list (25JUN96) */ #include #include #include #include #include /* in sockconv.c */ int sock_conv(int num_msg, const struct pam_message **msgm, struct pam_response **response, void *appdata_ptr); static pam_handle_t *pamh; void auth_checkoptions(void) { if (use_rhosts==0 || deny_all_rhosts_hequiv || allow_root_rhosts) { syslog(LOG_ERR, "-l, -L, and -h functionality has been moved to " "pam_rhosts_auth in /etc/pam.conf"); } } void auth_finish(void) { if (pamh) { pam_end(pamh, PAM_SUCCESS); pamh = NULL; } } static int attempt_auth(void) { int retval; retval = pam_authenticate(pamh, 0); if (retval == PAM_SUCCESS) { retval = pam_acct_mgmt(pamh, 0); } if (retval == PAM_NEW_AUTHTOK_REQD) { retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); if (retval == PAM_SUCCESS) { /* * Try authentication again if passwd change * succeeded. Don't try again if it didn't; * sysadmin might not want passwords changed * over the net, and might have set password * to pam_deny.so to disable it... * * Hmm. Is it possible for the sysadmin to configure this * for infinite recursion? (That is, will the second attempt * also ever try to change the password?) */ retval = attempt_auth(); } } return retval; } /* * This function must either die, return -1 on authentication failure, * or return 0 on authentication success. Dying is discouraged. */ int auth_checkauth(const char *remoteuser, const char *host, char *localuser, size_t localusersize) { static struct pam_conv conv = { sock_conv, NULL }; struct passwd *pwd; char *ln; int retval; retval = pam_start("rlogin", localuser, &conv, &pamh); if (retval != PAM_SUCCESS) { syslog(LOG_ERR, "pam_start: %s\n", pam_strerror(pamh, retval)); fatal(STDERR_FILENO, "initialization failed", 0); } pam_set_item(pamh, PAM_USER, localuser); pam_set_item(pamh, PAM_RUSER, remoteuser); pam_set_item(pamh, PAM_RHOST, host); pam_set_item(pamh, PAM_TTY, "tty"); /* ? */ network_confirm(); retval = attempt_auth(); if (retval != PAM_SUCCESS) { syslog(LOG_ERR, "PAM authentication failed for in.rlogind"); return -1; } pam_get_item(pamh, PAM_USER, &ln); if (!ln || !*ln) { /* * Authentication wasn't adequate for requirements. * Fall through to login quietly; don't let the * remote user tell if he's found a valid username * or not. */ return -1; } /* * PAM is apparently willing to change the username on us. (!?) */ strncpy(localuser, ln, localusersize-1); localuser[localusersize-1] = 0; /* * And, as far as I can tell, this shouldn't be here at all. * /bin/login is supposed to handle this, isn't it? Certainly * the gids. But, allegedly, it's needed. * * I thought PAM was supposed to make this sort of thing _easier_. */ pwd = getpwnam(localuser); if (pwd==NULL) { syslog(LOG_ERR, "user returned by PAM does not exist\n"); /* don't print this - it tells people which accounts exist */ /*fprintf(stderr, "rlogind: internal error\n");*/ return -1; } if (setgid(pwd->pw_gid) != 0) { syslog(LOG_ERR, "cannot assume gid for user returned by PAM\n"); fprintf(stderr, "rlogind: internal error\n"); return -1; } if (initgroups(localuser, pwd->pw_gid) != 0) { syslog(LOG_ERR, "initgroups failed for user returned by PAM\n"); fprintf(stderr, "rlogind: internal error\n"); return -1; } retval = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (retval != PAM_SUCCESS) { syslog(LOG_ERR,"PAM authentication failed for in.rlogind"); return -1; } return 0; } #else /* not USE_PAM */ /* * Standard rlogin processing... */ #include /* for ruserok() in libc5 (!) */ #include /* for ruserok() in glibc (!) */ #if defined(__GLIBC__) && (__GLIBC__ >= 2) #define _check_rhosts_file __check_rhosts_file #endif extern int _check_rhosts_file; void auth_checkoptions(void) {} void auth_finish(void) {} /* * This function must either die, return -1 on authentication failure, * or return 0 on authentication success. Dying is discouraged. */ int auth_checkauth(const char *remoteuser, const char *host, char *localuser, size_t localusersize) { struct passwd *pwd; (void)localusersize; pwd = getpwnam(localuser); if (pwd == NULL) return -1; /* * The possibilities here are: * user == root * (1) .rhosts entry exists * (2) hosts_equiv entry exists * (3) neither .rhosts nor hosts_equiv entries exist * user != root * (4) .rhosts entry exists * (5) hosts_equiv entry exists * (6) neither .rhosts nor hosts_equiv entries exist * * ruserok() by itself will fail on (2), (3), and (6). * * Turning off use_rhosts will (or should) prevent (1) and (4). * Leaving allow_root_rhosts off will prevent (1). * Setting deny_all_rhosts_hequiv prevents all cases from succeeding. */ if (deny_all_rhosts_hequiv) return -1; if (!allow_root_rhosts && pwd->pw_uid == 0) return -1; _check_rhosts_file = use_rhosts; return ruserok(host, pwd->pw_uid==0, remoteuser, localuser); } #endif /* PAM */ netkit-rsh-0.17/rlogind/logwtmp.h100644 144 144 263 7017076032 16320 0ustar dhollandpeople/* * Put this here instead of including , since Linux is messed up * and doesn't have . */ void logwtmp(const char *_line, const char *name, const char *host); netkit-rsh-0.17/rlogind/network.c100644 144 144 15126 7024736034 16362 0ustar dhollandpeople/*- * Copyright (c) 1983, 1988, 1989 The Regents of the University of California. * All rights reserved. * * 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. */ #include /* for MAXHOSTNAMELEN */ #include #include #include #include #include /* for snprintf(), BUFSIZ */ #include #include #include #include #include #include "rlogind.h" static int confirmed=0; static int netf; static const char * topdomain(const char *h) { const char *p; const 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); } /* * Check whether host h is in our local domain, * defined as sharing the last two components of the domain part, * or the entire domain part if the local domain has only one component. * If either name is unqualified (contains no '.'), * assume that the host is local, as it will be * interpreted as such. */ static int local_domain(const char *h) { char localhost[MAXHOSTNAMELEN]; const char *p1, *p2; localhost[0] = 0; (void) gethostname(localhost, sizeof(localhost)); p1 = topdomain(localhost); p2 = topdomain(h); if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) return(1); return(0); } static char * find_hostname(const struct sockaddr_in *fromp, int *hostokp) { struct hostent *hop; char *hname; int hostok = 0; hop = gethostbyaddr((const char *)&fromp->sin_addr, sizeof(struct in_addr), fromp->sin_family); if (hop == NULL) { hname = strdup(inet_ntoa(fromp->sin_addr)); hostok = 1; } else if (check_all || local_domain(hop->h_name)) { /* * If name returned by gethostbyaddr is in our domain, * attempt to verify that we haven't been fooled by someone * in a remote net; look up the name and check that this * address corresponds to the name. */ hname = strdup(hop->h_name); hop = gethostbyname(hname); if (hop) { for (; hop->h_addr_list[0]; hop->h_addr_list++) { if (!memcmp(hop->h_addr_list[0], &fromp->sin_addr, sizeof(fromp->sin_addr))) { hostok = 1; break; } } /* not clear if this is worthwhile */ free(hname); hname = strdup(hop->h_name); } } else { hname = strdup(hop->h_name); hostok = 1; } /* * Actually it might be null if we're out of memory, but * where do we go then? We'd have to bail anyhow. */ assert(hname != NULL); *hostokp = hostok; return hname; } char * network_init(int f, int *hostokp) { struct sockaddr_in from, *fromp; socklen_t fromlen; int on = 1; char c; char *hname; int port; from.sin_family = AF_INET; fromlen = sizeof (from); if (getpeername(f, (struct sockaddr *)&from, &fromlen) < 0) { syslog(LOG_ERR,"Can't get peer name of remote host: %m"); fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); } if (keepalive && setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); #ifdef IP_TOS #define IPTOS_LOWDELAY 0x10 on = IPTOS_LOWDELAY; if (setsockopt(f, IPPROTO_IP, IP_TOS, &on, sizeof(on)) < 0) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif fromp = &from; alarm(60); read(f, &c, 1); if (c != 0) exit(1); alarm(0); hname = find_hostname(fromp, hostokp); port = ntohs(fromp->sin_port); if (fromp->sin_family != AF_INET || port >= IPPORT_RESERVED || port < IPPORT_RESERVED/2) { syslog(LOG_NOTICE, "Connection from %s on illegal port", inet_ntoa(fromp->sin_addr)); fatal(f, "Permission denied", 0); } #ifdef IP_OPTIONS { u_char optbuf[BUFSIZ/3], *cp; char lbuf[BUFSIZ]; int lboff; socklen_t optsize = sizeof(optbuf); int 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) { lboff=0; for (cp = optbuf; optsize > 0; cp++, optsize--, lboff += 3) snprintf(lbuf+lboff, sizeof(lbuf)-lboff, " %2.2x", *cp); syslog(LOG_NOTICE, "Connection received using IP options (ignored):%s", lbuf); if (setsockopt(0, ipproto, IP_OPTIONS, NULL, optsize) != 0) { syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); exit(1); } } } #endif return hname; } void network_confirm(void) { assert(confirmed>=0); if (confirmed == 0) { /* do_rlogin may do this */ write(netf, "", 1); confirmed = 1; /* we sent the null! */ } } void network_anticonfirm(void) { char x='\01'; /* error indicator */ assert(confirmed>=0); if (!confirmed) { write(netf, &x, 1); /* * Still not confirmed, but we shouldn't ever get here again * as we should be in the process of crashing. */ confirmed = -1; } } void network_close(void) { shutdown(netf, 2); } netkit-rsh-0.17/rlogind/pathnames.h100644 144 144 3705 6172422456 16641 0ustar dhollandpeople/* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * 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. * * from: @(#)pathnames.h 5.4 (Berkeley) 6/1/90 * $Id: pathnames.h,v 1.2 1996/07/15 11:02:06 dholland Exp $ */ #include #define _PATH_LOGIN "/bin/login" netkit-rsh-0.17/rlogind/rlogind.8100644 144 144 15131 7141140320 16233 0ustar dhollandpeople.\" Copyright (c) 1983, 1989, 1991 The Regents of the University of California. .\" All rights reserved. .\" .\" 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. .\" .\" from: @(#)rlogind.8 6.12 (Berkeley) 3/16/91 .\" $Id: rlogind.8,v 1.14 2000/07/30 23:57:04 dholland Exp $ .\" .Dd March 16, 1991 .Dt RLOGIND 8 .Os "Linux NetKit (0.17)" .Sh NAME .Nm rlogind .Nd remote login server .Sh SYNOPSIS .Nm rlogind .Op Fl ahlLn .Sh DESCRIPTION .Nm Rlogind is the server for the .Xr rlogin 1 program. The server provides a remote login facility with authentication based on privileged port numbers from trusted hosts. .Pp Options supported by .Nm rlogind : .Bl -tag -width Ds .It Fl a Ask hostname for verification. .It Fl h Permit use of superuser .Dq Pa .rhosts files. .It Fl l Prevent any authentication based on the user's .Dq Pa .rhosts file. If the user is logging in as the superuser and the \-h option is used, .Dq Pa .rhosts processing is still enabled. .It Fl L Prevent any authentication based on .Dq Pa .rhosts or .Dq Pa hosts.equiv information. .It Fl n Disable keep-alive messages. .El .Pp The \-h, \-l, and \-L flags are not used if PAM (Pluggable Authentication Module) support is in use. In this case the same effects can be achieved by editing .Pa /etc/pam.conf . .Pp The .Fl h and .Fl l options should also not be trusted without verifying that they work as expected with the particular version of libc installed on your system (and should be tested again after any libc update) because some versions of libc may not honor the internal flags used by .Nm rlogind . As the .Fl L option bypasses the libc functions entirely, it is not subject to this problem. .Pp Also note that the design of the .Pa .rhosts system is COMPLETELY INSECURE except on a carefully firewalled private network. Always use the .Fl L option under all other circumstances. Also, since .Nm rlogind does not encrypt communications, it should not, in general, be used at all. Consider .Xr ssh 8 . .Pp .Nm Rlogind listens for service requests at the port indicated in the ``login'' service specification; see .Xr services 5 . When a service request is received the following protocol is initiated: .Bl -enum .It The server checks the client's source port. If the port is not in the range 512-1023, the server aborts the connection. .It The server checks the client's source address and requests the corresponding host name (see .Xr gethostbyaddr 3 , .Xr hosts 5 and .Xr named 8 ) . If the hostname cannot be determined, the dot-notation representation of the host address is used. If the hostname is in the same domain as the server (according to the last two components of the domain name), or if the .Fl a option is given, the addresses for the hostname are requested, verifying that the name and address correspond. Normal authentication is bypassed if the address verification fails. .El .Pp Once the source port and address have been checked, .Nm rlogind proceeds with the authentication process described in .Xr rshd 8 . It then allocates a pseudo terminal (see .Xr pty 4 ) , and manipulates file descriptors so that the slave half of the pseudo terminal becomes the .Em stdin , .Em stdout , and .Em stderr for a login process. The login process is an instance of the .Xr login 1 program, invoked with the .Fl f option if authentication has succeeded. If automatic authentication fails, the user is prompted to log in as if on a standard terminal line. .Pp The parent of the login process manipulates the master side of the pseudo terminal, operating as an intermediary between the login process and the client instance of the .Xr rlogin program. In normal operation, the packet protocol described in .Xr pty 4 is invoked to provide .Ql ^S/^Q type facilities and propagate interrupt signals to the remote programs. The login process propagates the client terminal's baud rate and terminal type, as found in the environment variable, .Ql Ev TERM ; see .Xr environ 7 . The screen or window size of the terminal is requested from the client, and window size changes from the client are propagated to the pseudo terminal. .Pp Transport-level keepalive messages are enabled unless the .Fl n option is present. The use of keepalive messages allows sessions to be timed out if the client crashes or becomes unreachable. .Sh DIAGNOSTICS All initial diagnostic messages are indicated by a leading byte with a value of 1, after which any network connections are closed. If there are no errors before .Xr login is invoked, a null byte is returned as in indication of success. .Bl -tag -width Ds .It Sy Try again. A .Xr fork by the server failed. .El .Sh SEE ALSO .Xr login 1 , .Xr ruserok 3 , .Xr rshd 8 .Sh BUGS The authentication procedure used here assumes the integrity of each client machine and the connecting medium. This is insecure, but is useful in an ``open'' environment. .Pp A facility to allow all data exchanges to be encrypted should be present. .Pp A more extensible protocol should be used. .Sh HISTORY The .Nm command appeared in .Bx 4.2 . netkit-rsh-0.17/rlogind/rlogind.c100644 144 144 26735 7136460616 16343 0ustar dhollandpeople/*- * Copyright (c) 1983, 1988, 1989 The Regents of the University of California. * All rights reserved. * * 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. */ char copyright[] = "@(#) Copyright (c) 1983, 1988, 1989 " "The Regents of the University of California.\n" "All rights reserved.\n"; /* * From: @(#)rlogind.c 5.53 (Berkeley) 4/20/91 */ char rcsid[] = "$Id: rlogind.c,v 1.37 2000/07/23 03:07:58 dholland Exp $"; #include "../version.h" /* * remote login server: * \0 * remuser\0 * locuser\0 * terminal_type/speed\0 * data */ #include /* for size_t */ #include /* for MAXPATHLEN */ #include /* for chmod() */ #include /* for TIOCPKT */ #include /* for FD_SET() et al. */ #include /* for SIGCHLD */ #include /* for tcsetattr() */ #include /* for shutdown() */ #include /* for ntohs() */ #include /* for EOF, BUFSIZ, snprintf() */ #include /* for syslog() */ #include #include #include #include #include "pathnames.h" #include "logwtmp.h" #include "rlogind.h" pid_t forkpty(int *, char *, struct termios *, struct winsize *); int logout(const char *); #ifndef TIOCPKT_WINDOW #define TIOCPKT_WINDOW 0x80 #endif int keepalive = 1; int check_all = 0; int use_rhosts = 1; int allow_root_rhosts = 0; int deny_all_rhosts_hequiv = 0; static char oobdata[] = {(char)TIOCPKT_WINDOW}; static char line[MAXPATHLEN]; struct winsize win = { 0, 0, 0, 0 }; void fatal(int f, const char *msg, int syserr) { char buf[BUFSIZ]; /* * Send out a binary one if we haven't sent the magic null as confirmation. */ network_anticonfirm(); if (!syserr) { snprintf(buf, sizeof(buf), "rlogind: %s.\r\n", msg); } else { snprintf(buf, sizeof(buf), "rlogind: %s: %s.\r\n", msg, strerror(errno)); } write(f, buf, strlen(buf)); auth_finish(); exit(1); } ////////////////////////////////////////////////// parent //////////////////// /* * Handle a "control" request (signaled by magic being present) * in the data stream. For now, we are only willing to handle * window size changes. */ static int control(int pty, char *cp, int n) { struct winsize w; if (n < 4+(int)sizeof(w) || cp[2] != 's' || cp[3] != 's') { return 0; } oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ memcpy(&w, cp+4, sizeof(w)); w.ws_row = ntohs(w.ws_row); w.ws_col = ntohs(w.ws_col); w.ws_xpixel = ntohs(w.ws_xpixel); w.ws_ypixel = ntohs(w.ws_ypixel); ioctl(pty, TIOCSWINSZ, &w); return 4+sizeof(w); } /* * rlogin "protocol" machine. */ static void protocol(int f, int p) { static char magic[2] = { (char)0377, (char)0377 }; char pibuf[1024+1], fibuf[1024], *pbp = NULL, *fbp = NULL; int pcc = 0, fcc = 0; int cc, nfd, m; char cntl; /* * Must ignore SIGTTOU, otherwise we'll stop * when we try and set slave pty's window shape * (our controlling tty is the master pty). */ (void) signal(SIGTTOU, SIG_IGN); send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ if (f > p) nfd = f + 1; else nfd = p + 1; if (nfd > FD_SETSIZE) { syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); fatal(f, "internal error (select mask too small)", 0); } for (;;) { fd_set ibits, obits, ebits, *omask; FD_ZERO(&ebits); FD_ZERO(&ibits); FD_ZERO(&obits); omask = (fd_set *)NULL; if (fcc) { FD_SET(p, &obits); omask = &obits; } else FD_SET(f, &ibits); if (pcc >= 0) { if (pcc) { FD_SET(f, &obits); omask = &obits; } else { FD_SET(p, &ibits); } } FD_SET(p, &ebits); if ((m = select(nfd, &ibits, omask, &ebits, 0)) < 0) { if (errno == EINTR) continue; fatal(f, "select", 1); } if (m == 0) { /* shouldn't happen... */ sleep(5); continue; } #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) if (FD_ISSET(p, &ebits)) { cc = read(p, &cntl, 1); if (cc == 1 && pkcontrol(cntl)) { cntl |= oobdata[0]; send(f, &cntl, 1, MSG_OOB); if (cntl & TIOCPKT_FLUSHWRITE) { pcc = 0; FD_CLR(p, &ibits); } } } if (FD_ISSET(f, &ibits)) { fcc = read(f, fibuf, sizeof(fibuf)); if (fcc < 0 && errno == EWOULDBLOCK) fcc = 0; else { register char *cp; int left, nn; if (fcc <= 0) break; fbp = fibuf; top: for (cp = fibuf; cp < fibuf+fcc-1; cp++) if (cp[0] == magic[0] && cp[1] == magic[1]) { left = fcc - (cp-fibuf); nn = control(p, cp, left); if (nn) { left -= nn; if (left > 0) bcopy(cp+nn, cp, left); fcc -= nn; goto top; /* n^2 */ } } FD_SET(p, &obits); /* try write */ } } if (FD_ISSET(p, &obits) && fcc > 0) { cc = write(p, fbp, fcc); if (cc > 0) { fcc -= cc; fbp += cc; } } if (FD_ISSET(p, &ibits)) { pcc = read(p, pibuf, sizeof (pibuf)); pbp = pibuf; if (pcc < 0 && errno == EWOULDBLOCK) pcc = 0; else if (pcc <= 0) break; else if (pibuf[0] == 0) { pbp++, pcc--; FD_SET(f, &obits); /* try write */ } else { if (pkcontrol(pibuf[0])) { pibuf[0] |= oobdata[0]; send(f, &pibuf[0], 1, MSG_OOB); } pcc = 0; } } if ((FD_ISSET(f, &obits)) && pcc > 0) { cc = write(f, pbp, pcc); if (cc < 0 && errno == EWOULDBLOCK) { /* * This happens when we try write after read * from p, but some old kernels balk at large * writes even when select returns true. */ if (!FD_ISSET(p, &ibits)) sleep(5); continue; } if (cc > 0) { pcc -= cc; pbp += cc; } } } } static void cleanup(int sig) { char *p; (void)sig; p = line + sizeof(_PATH_DEV) - 1; if (logout(p)) logwtmp(p, "", ""); auth_finish(); network_close(); /* tty end to root.system mode 600 */ chmod(line, 0600); chown(line, 0, 0); /* pty end to root.system mode 666 */ *p = 'p'; chmod(line, 0666); chown(line, 0, 0); /* all done */ exit(0); } ////////////////////////////////////////////////// child //////////////////// static void setup_term(int fd, const char *termtype) { char *x; struct termios tt; tcgetattr(fd, &tt); if ((x=strchr(termtype, '/')) != NULL) { *x++ = '\0'; cfsetispeed(&tt, atoi(x)); cfsetospeed(&tt, atoi(x)); } #if 0 /* notyet */ tt.c_iflag = TTYDEF_IFLAG; tt.c_oflag = TTYDEF_OFLAG; tt.c_lflag = TTYDEF_LFLAG; #endif tcsetattr(fd, TCSAFLUSH, &tt); } /* * Close all fds, in case libc has left fun stuff like /etc/shadow open. */ static void closeall(void) { int i; for (i = getdtablesize()-1; i > 2; i--) close(i); } static void child(const char *hname, const char *termtype, const char *localuser, int authenticated) { char *termenv[2]; setup_term(0, termtype); termenv[0] = malloc(strlen(termtype)+6); if (termenv[0]) { /* shouldn't ever fail, mind you */ strcpy(termenv[0], "TERM="); strcat(termenv[0], termtype); } termenv[1] = NULL; if (authenticated) { auth_finish(); closeall(); execle(_PATH_LOGIN, "login", "-p", "-h", hname, "-f", localuser, NULL, termenv); } else { if (localuser[0] == '-') { syslog(LOG_AUTH|LOG_INFO, "rlogin with an option as a name!"); exit(1); } auth_finish(); closeall(); execle(_PATH_LOGIN, "login", "-p", "-h", hname, localuser, NULL, termenv); } /* Can't exec login, croak */ fatal(STDERR_FILENO, _PATH_LOGIN, 1); } ////////////////////////////////////////////////// main //////////////////// static void getstr(char *buf, int cnt, const char *errmsg) { char c; do { if (read(STDIN_FILENO, &c, 1) != 1) exit(1); if (--cnt < 0) fatal(STDOUT_FILENO, errmsg, 0); *buf++ = c; } while (c != 0); } static void doit(int netfd) { int master, pid, on = 1; int authenticated = 0; char *hname; int hostok; char lusername[32], rusername[32], termtype[256]; hname = network_init(netfd, &hostok); getstr(rusername, sizeof(rusername), "remuser too long"); getstr(lusername, sizeof(lusername), "locuser too long"); getstr(termtype, sizeof(termtype), "Terminal type too long"); /* * This function will either die, return -1 if authentication failed, * or return 0 if authentication succeeded. * * dholland 6/13/97 I've changed this so it doesn't even call * auth_checkauth if the hostname was bogus. I don't *think* * this will break anything or give away state secrets. */ if (hostok) { if (auth_checkauth(rusername, hname, lusername, sizeof(lusername)) == 0) { authenticated=1; } } network_confirm(); if (!hostok) { write(netfd, "rlogind: Host address mismatch.\r\n", 33); } pid = forkpty(&master, line, NULL, &win); if (pid < 0) { if (errno == ENOENT) fatal(netfd, "Out of ptys", 0); fatal(netfd, "Forkpty", 1); } if (pid == 0) { /* netfd should always be 0, but... */ if (netfd > 2) close(netfd); child(hname, termtype, lusername, authenticated); } on = 1; ioctl(netfd, FIONBIO, &on); ioctl(master, FIONBIO, &on); ioctl(master, TIOCPKT, &on); signal(SIGCHLD, cleanup); protocol(netfd, master); signal(SIGCHLD, SIG_IGN); cleanup(0); } int main(int argc, char **argv) { int ch; use_rhosts = 1; /* default */ openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); opterr = 0; while ((ch = getopt(argc, argv, "ahLln")) != EOF) { switch (ch) { case 'a': check_all = 1; break; case 'h': allow_root_rhosts = 1; break; case 'L': deny_all_rhosts_hequiv = 1; break; case 'l': use_rhosts = 0; break; case 'n': keepalive = 0; break; case '?': default: syslog(LOG_ERR, "usage: rlogind [-ahLln]"); break; } } argc -= optind; argv += optind; auth_checkoptions(); doit(0); return 0; } netkit-rsh-0.17/rlogind/rlogind.h100644 144 144 1363 7035005535 16307 0ustar dhollandpeople /* rlogind.c */ void fatal(int f, const char *msg, int syserr); /* network.c */ char *network_init(int fd, int *hostokp); void network_confirm(void); void network_anticonfirm(void); void network_close(void); /* auth.c */ void auth_checkoptions(void); void auth_finish(void); int auth_checkauth(const char *remoteuser, const char *host, char *localuser, size_t localusermaxsize); /* * Global flag variables */ /* Do paranoid DNS confirmation on all hosts? */ extern int check_all; /* Use TCP keepalive messages on connection? */ extern int keepalive; /* Check ~/.rhosts? */ extern int use_rhosts; /* Check ~root/.rhosts? */ extern int allow_root_rhosts; /* Ignore all ~/.rhosts and /etc/hosts_equiv? */ extern int deny_all_rhosts_hequiv; netkit-rsh-0.17/rlogind/sockconv.c100644 144 144 7436 6775477074 16525 0ustar dhollandpeople/* * A generic conversation function for text based applications * * Written by Andrew Morgan * modified for socket file descriptors by Erik Troan * * $Log: sockconv.c,v $ * Revision 1.6 1999/10/02 21:50:52 dholland * Various minor cleanup; straighten out (hopefully) the problems in * rlogind/auth.c. * * Revision 1.5 1999/09/30 23:23:14 netbug * added the TYPE(socklen_t) check to the MCONFIG.in files * question? do I need to update the .cvsignore files to * prevent CVS checking in configure scripts.... * * Revision 1.4 1999/03/27 07:42:06 dholland * PAM changes. * * Revision 1.3 1998/03/08 16:51:50 root * grabbed the redhat pam patches and integrated most of it * though I've decided to go with xstrdup as opposed to pam's x_strdup * * Revision 1.2 1997/06/08 19:57:22 dholland * minor fix - don't define __USE_BSD if already defined. * * Revision 1.1 1997/04/06 00:32:37 dholland * Initial revision * * * From: misc_conv.c,v 1.2 1996/07/07 23:59:56 morgan Exp * * Revision 1.2 1996/07/07 23:59:56 morgan * changed the name of the misc include file * * Revision 1.1 1996/05/02 05:17:06 morgan * Initial revision */ #include #include #ifndef __USE_BSD #define __USE_BSD /* needed for prototype for getpass() */ #endif #include #include #include int sock_conv(int num_msg, const struct pam_message **msgm, struct pam_response **response, void *appdata_ptr); #define INPUTSIZE PAM_MAX_MSG_SIZE #define CONV_ECHO_ON 1 #define CONV_ECHO_OFF 0 static char *read_string(int echo, const char *remark) { char buffer[INPUTSIZE]; char *text; int charsRead = 0; char * nl = "\n\r"; fprintf(stderr,"%s",remark); while (charsRead < (INPUTSIZE - 1)) { read(0, &buffer[charsRead], 1); if (buffer[charsRead] == '\r') { write(1, nl, 2); buffer[charsRead] = '\0'; break; } if (echo) { write(1, &buffer[charsRead], 1); } charsRead++; } /* get some space for this text */ text = strdup(buffer); return (text); } static void drop_reply(struct pam_response *reply, int replies) { int i; for (i=0; imsg_style) { case PAM_PROMPT_ECHO_OFF: string = read_string(CONV_ECHO_OFF,msgm[replies]->msg); if (string == NULL) { drop_reply(reply,replies); return (PAM_CONV_ERR); } break; case PAM_PROMPT_ECHO_ON: string = read_string(CONV_ECHO_ON,msgm[replies]->msg); if (string == NULL) { drop_reply(reply,replies); return (PAM_CONV_ERR); } break; case PAM_ERROR_MSG: fprintf(stderr,"%s\n",msgm[replies]->msg); string = NULL; break; case PAM_TEXT_INFO: fprintf(stderr,"%s\n",msgm[replies]->msg); string = NULL; break; default: fprintf(stderr, "erroneous conversation (%d)\n" ,msgm[replies]->msg_style); drop_reply(reply,replies); return (PAM_CONV_ERR); } /* add string to list of responses */ reply[replies].resp_retcode = 0; reply[replies].resp = string; } *response = reply; /* shut up gcc */ appdata_ptr=NULL; return PAM_SUCCESS; } netkit-rsh-0.17/rsh/ 40700 144 144 0 7141142015 13515 5ustar dhollandpeoplenetkit-rsh-0.17/rsh/.cvsignore100644 144 144 4 6774163711 15557 0ustar dhollandpeoplersh netkit-rsh-0.17/rsh/Makefile100644 144 144 441 6750746666 15276 0ustar dhollandpeopleall: rsh include ../MCONFIG include ../MRULES OBJS = rsh.o rsh: $(OBJS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ install: rsh install -s -o root -m$(SUIDMODE) rsh $(INSTALLROOT)$(BINDIR) install -m$(MANMODE) rsh.1 $(INSTALLROOT)$(MANDIR)/man1 clean: rm -f *.o rsh $(OBJS): ../version.h netkit-rsh-0.17/rsh/pathnames.h100644 144 144 3667 6172521355 16004 0ustar dhollandpeople/* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * 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. * * from: @(#)pathnames.h 5.2 (Berkeley) 4/9/90 * $Id: pathnames.h,v 1.1 1996/07/15 19:58:37 dholland Exp $ */ #define _PATH_RLOGIN "/usr/bin/rlogin" netkit-rsh-0.17/rsh/rsh.1100644 144 144 11610 7141140320 14516 0ustar dhollandpeople.\" Copyright (c) 1983, 1990 The Regents of the University of California. .\" All rights reserved. .\" .\" 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. .\" .\" from: @(#)rsh.1 6.10 (Berkeley) 7/24/91 .\" $Id: rsh.1,v 1.11 2000/07/30 23:57:04 dholland Exp $ .\" .Dd August 15, 1999 .Dt RSH 1 .Os "Linux NetKit (0.17)" .Sh NAME .Nm rsh .Nd remote shell .Sh SYNOPSIS .Nm rsh .Op Fl Kdnx .Op Fl k Ar realm .Op Fl l Ar username .Ar host .Op command .Sh DESCRIPTION .Nm Rsh executes .Ar command on .Ar host . .Pp .Nm Rsh copies its standard input to the remote command, the standard output of the remote command to its standard output, and the standard error of the remote command to its standard error. Interrupt, quit and terminate signals are propagated to the remote command; .Nm rsh normally terminates when the remote command does. The options are as follows: .Bl -tag -width flag .It Fl K The .Fl K option turns off all Kerberos authentication. .It Fl d The .Fl d option turns on socket debugging (using .Xr setsockopt 2 ) on the .Tn TCP sockets used for communication with the remote host. .It Fl k The .Fl k option causes .Nm rsh to obtain tickets for the remote host in .Ar realm instead of the remote host's realm as determined by .Xr krb_realmofhost 3 . .It Fl l By default, the remote username is the same as the local username. The .Fl l option allows the remote name to be specified. Kerberos authentication is used, and authorization is determined as in .Xr rlogin 1 . .It Fl n The .Fl n option redirects input from the special device .Pa /dev/null (see the .Sx BUGS section of this manual page). .It Fl x The .Fl x option turns on .Tn DES encryption for all data exchange. This may introduce a significant delay in response time. .El .Pp If no .Ar command is specified, you will be logged in on the remote host using .Xr rlogin 1 . .Pp Shell metacharacters which are not quoted are interpreted on local machine, while quoted metacharacters are interpreted on the remote machine. For example, the command .Pp .Dl rsh otherhost cat remotefile >> localfile .Pp appends the remote file .Ar remotefile to the local file .Ar localfile , while .Pp .Dl rsh otherhost cat remotefile \&">>\&" other_remotefile .Pp appends .Ar remotefile to .Ar other_remotefile . .\" .Pp .\" Many sites specify a large number of host names as commands in the .\" directory /usr/hosts. .\" If this directory is included in your search path, you can use the .\" shorthand ``host command'' for the longer form ``rsh host command''. .Sh FILES .Bl -tag -width /etc/hosts -compact .It Pa /etc/hosts .El .Sh SEE ALSO .Xr rlogin 1 , .Xr kerberos 3 , .Xr krb_sendauth 3 , .Xr krb_realmofhost 3 .Sh HISTORY The .Nm rsh command appeared in .Bx 4.2 . .Sh BUGS If you are using .Xr csh 1 and put a .Nm rsh in the background without redirecting its input away from the terminal, it will block even if no reads are posted by the remote command. If no input is desired you should redirect the input of .Nm rsh to .Pa /dev/null using the .Fl n option. .Pp You cannot run an interactive command (like .Xr rogue 6 or .Xr vi 1 ) using .Nm rsh ; use .Xr rlogin 1 instead. .Pp Stop signals stop the local .Nm rsh process only; this is arguably wrong, but currently hard to fix for reasons too complicated to explain here. netkit-rsh-0.17/rsh/rsh.c100644 144 144 17126 7136470630 14626 0ustar dhollandpeople/*- * Copyright (c) 1983, 1990 The Regents of the University of California. * All rights reserved. * * 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. */ char copyright[] = "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n" "All rights reserved.\n"; /* * From: @(#)rsh.c 5.24 (Berkeley) 7/1/91 */ char rcsid[] = "$Id: rsh.c,v 1.13 2000/07/23 04:16:24 dholland Exp $"; #include "../version.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" /* * rsh - remote shell */ static int rfd2; static char *copyargs(char **); static void sendsig(int); static void talk(int nflag, long omask, int pid, int rem); static void usage(void); int main(int argc, char *argv[]) { struct passwd *pw; struct servent *sp; long omask; int argoff, asrsh, ch, dflag, nflag, one, pid=0, rem, uid; char *p; char *args, *host, *user; char *null = NULL; char **saved_environ; saved_environ = __environ; __environ = &null; argoff = asrsh = dflag = nflag = 0; one = 1; host = user = NULL; /* if called as something other than "rsh", use it as the host name */ p = strrchr(argv[0], '/'); if (p) p++; else p = argv[0]; if (!strcmp(p, "rsh")) asrsh = 1; else host = p; /* handle "rsh host flags" */ if (!host && argc > 2 && argv[1][0] != '-') { host = argv[1]; argoff = 1; } #define OPTIONS "+8KLdel:nw" while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) switch(ch) { case 'K': break; case 'L': /* -8Lew are ignored to allow rlogin aliases */ case 'e': case 'w': case '8': break; case 'd': dflag = 1; break; case 'l': user = optarg; break; case 'n': nflag = 1; break; case '?': default: usage(); } optind += argoff; /* if haven't gotten a host yet, do so */ if (!host && !(host = argv[optind++])) usage(); /* if no further arguments, must have been called as rlogin. */ if (!argv[optind]) { if (setuid(getuid())) { fprintf(stderr, "rsh: setuid: %s\n", strerror(errno)); exit(1); } if (asrsh) argv[0] = (char *)"rlogin"; execve(_PATH_RLOGIN, argv, saved_environ); fprintf(stderr, "rsh: can't exec %s.\n", _PATH_RLOGIN); exit(1); } argc -= optind; argv += optind; if (!(pw = getpwuid(uid = getuid()))) { fprintf(stderr, "rsh: unknown user id.\n"); exit(1); } if (!user) user = pw->pw_name; args = copyargs(argv); sp = NULL; if (sp == NULL) sp = getservbyname("shell", "tcp"); if (sp == NULL) { fprintf(stderr, "rsh: shell/tcp: unknown service.\n"); exit(1); } rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); if (rem < 0) exit(1); if (rfd2 < 0) { fprintf(stderr, "rsh: can't establish stderr.\n"); exit(1); } if (setuid(uid)) { fprintf(stderr, "rsh: setuid: %s\n", strerror(errno)); exit(1); } if (dflag) { if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) fprintf(stderr, "rsh: setsockopt: %s.\n", strerror(errno)); if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) fprintf(stderr, "rsh: setsockopt: %s.\n", strerror(errno)); } omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, sendsig); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, sendsig); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, sendsig); if (!nflag) { pid = fork(); if (pid < 0) { fprintf(stderr, "rsh: fork: %s.\n", strerror(errno)); exit(1); } } { ioctl(rfd2, FIONBIO, &one); ioctl(rem, FIONBIO, &one); } talk(nflag, omask, pid, rem); if (!nflag) kill(pid, SIGKILL); exit(0); } static void talk(int nflag, long omask, int pid, int rem) { register int cc, wc; register char *bp; fd_set readfrom, rembits; int rfd2_ok, rem_ok; char buf[BUFSIZ]; FD_ZERO(&rembits); if (!nflag && pid == 0) { close(rfd2); reread: errno = 0; if ((cc = read(0, buf, sizeof buf)) <= 0) goto done; bp = buf; rewrite: FD_ZERO(&rembits); FD_SET(rem, &rembits); if (select(rem+1, 0, &rembits, 0, 0) < 0) { if (errno != EINTR) { fprintf(stderr, "rsh: select: %s.\n", strerror(errno)); exit(1); } goto rewrite; } if (! FD_ISSET(rem, &rembits)) goto rewrite; wc = write(rem, bp, cc); if (wc < 0) { if (errno == EWOULDBLOCK) goto rewrite; goto done; } bp += wc; cc -= wc; if (cc == 0) goto reread; goto rewrite; done: shutdown(rem, 1); exit(0); } rfd2_ok = rem_ok = 1; sigsetmask(omask); while (rfd2_ok || rem_ok) { FD_ZERO(&readfrom); if (rfd2_ok) FD_SET(rfd2, &readfrom); if (rem_ok) FD_SET(rem, &readfrom); if (select(rfd2 > rem ? rfd2+1 : rem+1, &readfrom, 0, 0, 0) < 0) { if (errno != EINTR) { fprintf(stderr, "rsh: select: %s.\n", strerror(errno)); exit(1); } continue; } if (FD_ISSET(rfd2, &readfrom)) { errno = 0; cc = read(rfd2, buf, sizeof buf); if (cc > 0) write(2, buf, cc); else if (cc == 0 || errno != EWOULDBLOCK) rfd2_ok = 0; } if (FD_ISSET(rem, &readfrom)) { errno = 0; cc = read(rem, buf, sizeof buf); if (cc > 0) write(1, buf, cc); else if (cc == 0 || errno != EWOULDBLOCK) rem_ok = 0; } } } void sendsig(int signo) { char x = (char) signo; write(rfd2, &x, 1); } char * copyargs(char **argv) { int cc; char **ap, *p; char *args; cc = 0; for (ap = argv; *ap; ++ap) cc += strlen(*ap) + 1; args = malloc(cc); if (!args) { fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM)); exit(1); } for (p = args, ap = argv; *ap; ++ap) { /*strcpy(p, *ap);*/ for (p = strcpy(p, *ap); *p; ++p); if (ap[1]) *p++ = ' '; } return(args); } void usage(void) { fprintf(stderr, "usage: rsh [-nd%s]%s[-l login] host [command]\n", "", " "); exit(1); } netkit-rsh-0.17/rshd/ 40700 144 144 0 7141142015 13661 5ustar dhollandpeoplenetkit-rsh-0.17/rshd/.cvsignore100644 144 144 5 6774163711 15724 0ustar dhollandpeoplershd netkit-rsh-0.17/rshd/Makefile100644 144 144 700 7024761715 15423 0ustar dhollandpeopleall: rshd include ../MCONFIG include ../MRULES OBJS = rshd.o ifeq ($(USE_PAM),1) # ? CFLAGS += # -DUSE_PAM LIBS += -ldl # -lpam -lpam_misc endif rshd: $(OBJS) $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ install: rshd install -s -m$(DAEMONMODE) rshd $(INSTALLROOT)$(SBINDIR)/in.rshd install -m$(MANMODE) rshd.8 $(INSTALLROOT)$(MANDIR)/man8/in.rshd.8 ln -sf in.rshd.8 $(INSTALLROOT)$(MANDIR)/man8/rshd.8 clean: rm -f *.o rshd $(OBJS): ../version.h netkit-rsh-0.17/rshd/rshd.8100644 144 144 16302 7141140320 15040 0ustar dhollandpeople.\" Copyright (c) 1983, 1989, 1991 The Regents of the University of California. .\" All rights reserved. .\" .\" 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. .\" .\" from: @(#)rshd.8 6.11 (Berkeley) 4/20/91 .\" $Id: rshd.8,v 1.15 2000/07/30 23:57:04 dholland Exp $ .\" .Dd April 20, 1991 .Dt RSHD 8 .Os "Linux NetKit (0.17)" .Sh NAME .Nm rshd .Nd remote shell server .Sh SYNOPSIS .Nm rshd .Op Fl ahlnL .Sh DESCRIPTION The .Nm rshd server is the server for the .Xr rcmd 3 routine and, consequently, for the .Xr rsh 1 program. The server provides remote execution facilities with authentication based on privileged port numbers from trusted hosts. .Pp The .Nm rshd server listens for service requests at the port indicated in the ``cmd'' service specification; see .Xr services 5 . When a service request is received the following protocol is initiated: .Bl -enum .It The server checks the client's source port. If the port is not in the range 512-1023, the server aborts the connection. .It The server reads characters from the socket up to a null (`\e0') byte. The resultant string is interpreted as an .Tn ASCII number, base 10. .It If the number received in step 2 is non-zero, it is interpreted as the port number of a secondary stream to be used for the .Em stderr . A second connection is then created to the specified port on the client's machine. The source port of this second connection is also in the range 512-1023. .It The server checks the client's source address and requests the corresponding host name (see .Xr gethostbyaddr 3 , .Xr hosts 5 and .Xr named 8 ) . If the hostname cannot be determined, the dot-notation representation of the host address is used. If the hostname is in the same domain as the server (according to the last two components of the domain name), or if the .Fl a option is given, the addresses for the hostname are requested, verifying that the name and address correspond. If address verification fails, the connection is aborted with the message, ``Host address mismatch.'' .It A null terminated user name of at most 16 characters is retrieved on the initial socket. This user name is interpreted as the user identity on the .Em client Ns 's machine. .It A null terminated user name of at most 16 characters is retrieved on the initial socket. This user name is interpreted as a user identity to use on the .Sy server Ns 's machine. .It A null terminated command to be passed to a shell is retrieved on the initial socket. The length of the command is limited by the upper bound on the size of the system's argument list. .It .Nm Rshd then validates the user using .Xr ruserok 3 , which uses the file .Pa /etc/hosts.equiv and the .Pa .rhosts file found in the user's home directory. The .Fl l option prevents .Xr ruserok 3 from doing any validation based on the user's ``.rhosts'' file (unless the user is the superuser and the .Fl h option is used.) If the .Fl h option is not used, superuser accounts may not be accessed via this service at all. .Pp The .Fl l option should not be trusted without verifying that it works as expected with the particular version of libc installed on your system (and should be tested again after any libc update) because some versions of libc may not honor the flags used by .Nm rshd . .Pp Also note that the design of the .Pa .rhosts system is COMPLETELY INSECURE except on a carefully firewalled private network. Under all other circumstances, .Nm rshd should be disabled entirely. .Pp .It A null byte is returned on the initial socket and the command line is passed to the normal login shell of the user. The shell inherits the network connections established by .Nm rshd . .El .Pp Transport-level keepalive messages are enabled unless the .Fl n option is present. The use of keepalive messages allows sessions to be timed out if the client crashes or becomes unreachable. .Pp The .Fl L option causes all successful accesses to be logged to .Xr syslogd 8 as .Li auth.info messages and all failed accesses to be logged as .Li auth.notice . .Sh DIAGNOSTICS Except for the last one listed below, all diagnostic messages are returned on the initial socket, after which any network connections are closed. An error is indicated by a leading byte with a value of 1 (0 is returned in step 9 above upon successful completion of all the steps prior to the execution of the login shell). .Bl -tag -width indent .It Sy Locuser too long. The name of the user on the client's machine is longer than 16 characters. .It Sy Ruser too long. The name of the user on the remote machine is longer than 16 characters. .It Sy Command too long . The command line passed exceeds the size of the argument list (as configured into the system). .It Sy Remote directory. The .Xr chdir command to the home directory failed. .It Sy Permission denied. The authentication procedure described above failed, or the user requested did not exist. (These conditions are intentionally conflated.) .It Sy Can't make pipe. The pipe needed for the .Em stderr , wasn't created. .It Sy Can't fork; try again. A .Xr fork by the server failed. .It Sy : ... The user's login shell could not be started. This message is returned on the connection associated with the .Em stderr , and is not preceded by a flag byte. .El .Sh SEE ALSO .Xr rsh 1 , .Xr rcmd 3 , .Xr ruserok 3 .Sh BUGS The authentication procedure used here assumes the integrity of each client machine and the connecting medium. This is insecure, but is useful in an ``open'' environment. .Pp A facility to allow all data exchanges to be encrypted should be present. .Pp A more extensible protocol (such as Telnet) should be used. netkit-rsh-0.17/rshd/rshd.c100644 144 144 35033 7136470630 15133 0ustar dhollandpeople/*- * Copyright (c) 1988, 1989 The Regents of the University of California. * All rights reserved. * * 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. */ /* * PAM modifications by Michael K. Johnson */ char copyright[] = "@(#) Copyright (c) 1988, 1989 The Regents of the University of California.\n" "All rights reserved.\n"; /* * From: @(#)rshd.c 5.38 (Berkeley) 3/2/91 */ char rcsid[] = "$Id: rshd.c,v 1.25 2000/07/23 04:16:24 dholland Exp $"; #include "../version.h" /* * remote shell server: * [port]\0 * remuser\0 * locuser\0 * command\0 * data */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for vsnprintf */ #include #include #include #include #include #include #if defined(__GLIBC__) && (__GLIBC__ >= 2) #define _check_rhosts_file __check_rhosts_file #endif #ifdef USE_PAM #include #include static pam_handle_t *pamh; #endif /* USE_PAM */ #define OPTIONS "ahlLn" static int keepalive = 1; static int check_all = 0; static int paranoid = 0; static int sent_null; static int allow_root_rhosts=0; char username[20] = "USER="; char homedir[64] = "HOME="; char shell[64] = "SHELL="; char path[100] = "PATH="; char *envinit[] = {homedir, shell, path, username, 0}; extern char **environ; static void error(const char *fmt, ...); static void doit(struct sockaddr_in *fromp); static void getstr(char *buf, int cnt, const char *err); extern int _check_rhosts_file; /* * 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. */ static void error(const char *fmt, ...) { va_list ap; char buf[BUFSIZ], *bp = buf; if (sent_null == 0) *bp++ = 1; va_start(ap, fmt); vsnprintf(bp, sizeof(buf)-1, fmt, ap); va_end(ap); write(2, buf, strlen(buf)); } static void fail(const char *errorstr, const char *remuser, const char *hostname, const char *locuser, const char *cmdbuf) { /* log the (failed) rsh request */ syslog(LOG_INFO|LOG_AUTH, "rsh denied to %s@%s as %s: %s", remuser, hostname, locuser, errorstr); if (paranoid) { syslog(LOG_INFO|LOG_AUTH, "rsh command was '%s'", cmdbuf); } error(errorstr, hostname); exit(1); } static void getstr(char *buf, int cnt, const char *err) { char c; do { if (read(0, &c, 1) != 1) exit(1); *buf++ = c; if (--cnt == 0) { error("%s too long\n", err); exit(1); } } while (c != 0); } static int getint(void) { int port = 0; char c; do { if (read(0, &c, 1) != 1) exit(1); if (isascii(c) && isdigit(c)) port = port*10 + c-'0'; } while (c != 0); return port; } static void stderr_parent(int sock, int pype, int pid) { fd_set ready, readfrom; char buf[BUFSIZ], sig; int one = 1; int nfd, cc, guys=2; ioctl(pype, FIONBIO, (char *)&one); /* should set s nbio! */ FD_ZERO(&readfrom); FD_SET(sock, &readfrom); FD_SET(pype, &readfrom); if (pype > sock) nfd = pype+1; else nfd = sock+1; while (guys > 0) { ready = readfrom; if (select(nfd, &ready, NULL, NULL, NULL) < 0) { if (errno != EINTR) { break; } continue; } if (FD_ISSET(sock, &ready)) { cc = read(sock, &sig, 1); if (cc <= 0) { FD_CLR(sock, &readfrom); guys--; } else killpg(pid, sig); } if (FD_ISSET(pype, &ready)) { cc = read(pype, buf, sizeof(buf)); if (cc <= 0) { shutdown(sock, 2); FD_CLR(pype, &readfrom); guys--; } else write(sock, buf, cc); } } #ifdef USE_PAM /* * This does not strike me as the right place for this; this is * in a child process... what does this need to accomplish? * * No, it's not the child process, the code is just confusing. */ pam_close_session(pamh, 0); pam_end(pamh, PAM_SUCCESS); #endif exit(0); } static struct passwd *doauth(const char *remuser, const char *hostname, const char *locuser) { #ifdef USE_PAM static struct pam_conv conv = { misc_conv, NULL }; int retcode; #endif struct passwd *pwd = getpwnam(locuser); if (pwd == NULL) return NULL; if (pwd->pw_uid==0) paranoid = 1; #ifdef USE_PAM retcode = pam_start("rsh", locuser, &conv, &pamh); if (retcode != PAM_SUCCESS) { syslog(LOG_ERR, "pam_start: %s\n", pam_strerror(pamh, retcode)); exit (1); } pam_set_item (pamh, PAM_RUSER, remuser); pam_set_item (pamh, PAM_RHOST, hostname); pam_set_item (pamh, PAM_TTY, "tty"); retcode = pam_authenticate(pamh, 0); if (retcode == PAM_SUCCESS) { retcode = pam_acct_mgmt(pamh, 0); } if (retcode == PAM_SUCCESS) { /* * Why do we need to set groups here? * Also, this stuff should be moved down near where the setuid() is. */ if (setgid(pwd->pw_gid) != 0) { pam_end(pamh, PAM_SYSTEM_ERR); return NULL; } if (initgroups(locuser, pwd->pw_gid) != 0) { pam_end(pamh, PAM_SYSTEM_ERR); return NULL; } retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); } if (retcode == PAM_SUCCESS) { retcode = pam_open_session(pamh,0); } if (retcode != PAM_SUCCESS) { pam_end(pamh, retcode); return NULL; } return pwd; #else if (pwd->pw_uid==0 && !allow_root_rhosts) return NULL; if (ruserok(hostname, pwd->pw_uid==0, remuser, locuser) < 0) { return NULL; } return pwd; #endif } static const char *findhostname(struct sockaddr_in *fromp, const char *remuser, const char *locuser, const char *cmdbuf) { struct hostent *hp; const char *hostname; hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), fromp->sin_family); errno = ENOMEM; /* malloc (thus strdup) may not set it */ if (hp) hostname = strdup(hp->h_name); else hostname = strdup(inet_ntoa(fromp->sin_addr)); if (hostname==NULL) { /* out of memory? */ error("strdup: %s\n", strerror(errno)); exit(1); } /* * Attempt to confirm the DNS. */ #ifdef RES_DNSRCH _res.options &= ~RES_DNSRCH; #endif hp = gethostbyname(hostname); if (hp == NULL) { syslog(LOG_INFO, "Couldn't look up address for %s", hostname); fail("Couldn't get address for your host (%s)\n", remuser, inet_ntoa(fromp->sin_addr), locuser, cmdbuf); } while (hp->h_addr_list[0] != NULL) { if (!memcmp(hp->h_addr_list[0], &fromp->sin_addr, sizeof(fromp->sin_addr))) { return hostname; } hp->h_addr_list++; } syslog(LOG_NOTICE, "Host addr %s not listed for host %s", inet_ntoa(fromp->sin_addr), hp->h_name); fail("Host address mismatch for %s\n", remuser, inet_ntoa(fromp->sin_addr), locuser, cmdbuf); return NULL; /* not reachable */ } static void doit(struct sockaddr_in *fromp) { char cmdbuf[ARG_MAX+1]; const char *theshell, *shellname; char locuser[16], remuser[16]; struct passwd *pwd; int sock = -1; const char *hostname; u_short port; int pv[2], pid, ifd; signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); alarm(60); port = getint(); alarm(0); if (port != 0) { int lport = IPPORT_RESERVED - 1; sock = rresvport(&lport); if (sock < 0) { syslog(LOG_ERR, "can't get stderr port: %m"); exit(1); } if (port >= IPPORT_RESERVED) { syslog(LOG_ERR, "2nd port not reserved\n"); exit(1); } fromp->sin_port = htons(port); if (connect(sock, (struct sockaddr *)fromp, sizeof(*fromp)) < 0) { syslog(LOG_INFO, "connect second port: %m"); exit(1); } } #if 0 /* We're running from inetd; socket is already on 0, 1, 2 */ dup2(f, 0); dup2(f, 1); dup2(f, 2); #endif getstr(remuser, sizeof(remuser), "remuser"); getstr(locuser, sizeof(locuser), "locuser"); getstr(cmdbuf, sizeof(cmdbuf), "command"); if (!strcmp(locuser, "root")) paranoid = 1; hostname = findhostname(fromp, remuser, locuser, cmdbuf); setpwent(); pwd = doauth(remuser, hostname, locuser); if (pwd == NULL) { fail("Permission denied.\n", remuser, hostname, locuser, cmdbuf); } if (chdir(pwd->pw_dir) < 0) { chdir("/"); /* * error("No remote directory.\n"); * exit(1); */ } if (pwd->pw_uid != 0 && !access(_PATH_NOLOGIN, F_OK)) { error("Logins currently disabled.\n"); exit(1); } (void) write(2, "\0", 1); sent_null = 1; if (port) { if (pipe(pv) < 0) { error("Can't make pipe.\n"); exit(1); } pid = fork(); if (pid == -1) { error("Can't fork; try again.\n"); exit(1); } if (pid) { close(0); close(1); close(2); close(pv[1]); stderr_parent(sock, pv[0], pid); /* NOTREACHED */ } setpgrp(); close(sock); close(pv[0]); dup2(pv[1], 2); close(pv[1]); } theshell = pwd->pw_shell; if (!theshell || !*theshell) { /* shouldn't we deny access? */ theshell = _PATH_BSHELL; } #if BSD > 43 if (setlogin(pwd->pw_name) < 0) { syslog(LOG_ERR, "setlogin() failed: %m"); } #endif #ifndef USE_PAM /* if PAM, already done */ if (setgid(pwd->pw_gid)) { syslog(LOG_ERR, "setgid: %m"); exit(1); } if (initgroups(pwd->pw_name, pwd->pw_gid)) { syslog(LOG_ERR, "initgroups: %m"); exit(1); } #endif if (setuid(pwd->pw_uid)) { syslog(LOG_ERR, "setuid: %m"); exit(1); } environ = envinit; strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); homedir[sizeof(homedir)-1] = 0; strcat(path, _PATH_DEFPATH); strncat(shell, theshell, sizeof(shell)-7); shell[sizeof(shell)-1] = 0; strncat(username, pwd->pw_name, sizeof(username)-6); username[sizeof(username)-1] = 0; shellname = strrchr(theshell, '/'); if (shellname) shellname++; else shellname = theshell; endpwent(); if (paranoid) { syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%s'", remuser, hostname, locuser, cmdbuf); } /* * Close all fds, in case libc has left fun stuff like * /etc/shadow open. */ for (ifd = getdtablesize()-1; ifd > 2; ifd--) close(ifd); execl(theshell, shellname, "-c", cmdbuf, 0); perror(theshell); exit(1); } static void network_init(int fd, struct sockaddr_in *fromp) { struct linger linger; socklen_t fromlen; int on=1; int port; fromlen = sizeof(*fromp); if (getpeername(fd, (struct sockaddr *) fromp, &fromlen) < 0) { syslog(LOG_ERR, "getpeername: %m"); _exit(1); } if (keepalive && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); linger.l_onoff = 1; linger.l_linger = 60; /* XXX */ if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof (linger)) < 0) syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); if (fromp->sin_family != AF_INET) { syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", fromp->sin_family); exit(1); } #ifdef IP_OPTIONS { u_char optbuf[BUFSIZ/3], *cp; char lbuf[BUFSIZ+1], *lp; socklen_t optsize = sizeof(optbuf); int 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) && optsize != 0) { lp = lbuf; /* * If these are true, this will not run off the end of lbuf[]. */ assert(optsize <= BUFSIZ/3); assert(3*optsize <= BUFSIZ); for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) snprintf(lp, 4, " %2.2x", *cp); syslog(LOG_NOTICE, "Connection received from %s using IP options" " (ignored): %s", inet_ntoa(fromp->sin_addr), lbuf); if (setsockopt(0, ipproto, IP_OPTIONS, NULL, optsize) != 0) { syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); exit(1); } } } #endif /* * Check originating port for validity. */ port = ntohs(fromp->sin_port); if (port >= IPPORT_RESERVED || port < IPPORT_RESERVED/2) { syslog(LOG_NOTICE|LOG_AUTH, "Connection from %s on illegal port", inet_ntoa(fromp->sin_addr)); exit(1); } } int main(int argc, char *argv[]) { int ch; struct sockaddr_in from; _check_rhosts_file=1; openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); opterr = 0; while ((ch = getopt(argc, argv, OPTIONS)) != EOF) { switch (ch) { case 'a': check_all = 1; break; case 'h': allow_root_rhosts = 1; break; case 'l': _check_rhosts_file = 0; break; case 'n': keepalive = 0; break; case 'L': paranoid = 1; break; case '?': default: syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS); exit(2); } } argc -= optind; argv += optind; #ifdef USE_PAM if (_check_rhosts_file == 0 || allow_root_rhosts) syslog(LOG_ERR, "-l and -h functionality has been moved to " "pam_rhosts_auth in /etc/pam.conf"); #endif /* USE_PAM */ network_init(0, &from); doit(&from); return 0; }