Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: rshd.c
===================================================================
--- rshd.c	(nonexistent)
+++ rshd.c	(revision 5)
@@ -0,0 +1,634 @@
+/*-
+ * 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 <johnsonm@redhat.com>
+ */
+
+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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+#include <resolv.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>  /* for vsnprintf */
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <assert.h>
+
+#if defined(__GLIBC__) && (__GLIBC__ >= 2)
+#define _check_rhosts_file  __check_rhosts_file
+#endif
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+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;
+	long cmdbuflen;
+	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;
+
+	cmdbuflen = sysconf (_SC_ARG_MAX);
+	if (!(cmdbuflen > 0)) {
+		syslog (LOG_ERR, "sysconf (_SC_ARG_MAX) failed");
+		exit (1);
+	}
+
+	cmdbuf = malloc (++cmdbuflen);
+	if (cmdbuf == NULL) {
+		syslog (LOG_ERR, "Could not allocate space for cmdbuf");
+		exit (1);
+	}
+
+	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;
+}
+
+
+
+
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 5)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~