⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcmd.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983, 1993, 1994 *	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. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)rcmd.c	8.3 (Berkeley) 3/26/94";#endif /* LIBC_SCCS and not lint */#include <sys/cdefs.h>#include <sys/types.h>#include <time.h>#include <sys/select.h>#include "namespace.h"#include <sys/param.h>#include <sys/socket.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <fcntl.h>#include <netdb.h>#include <stdlib.h>#include <unistd.h>#include <pwd.h>#include <errno.h>#include <stdio.h>#include <ctype.h>#include <string.h>#ifdef YP#include <rpc/rpc.h>#include <rpcsvc/yp_prot.h>#include <rpcsvc/ypclnt.h>#endif#include <arpa/nameser.h>#include "un-namespace.h"/* wrapper for KAME-special getnameinfo() */#ifndef NI_WITHSCOPEID#define NI_WITHSCOPEID	0#endifextern int innetgr( const char *, const char *, const char *, const char * );extern int rcmdsh(char **ahost, int rport, const char *locuser, const char *remuser, const char *cmd, const char *rshprog);int rresvport_af(int *alport, int family);#define max(a, b)	((a > b) ? a : b)int __ivaliduser(FILE *, u_int32_t, const char *, const char *);int __ivaliduser_af(FILE *,const void *, const char *, const char *, int, int);int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t, const char *,    const char *);static int __icheckhost(const struct sockaddr *, socklen_t, const char *);char paddr[NI_MAXHOST];intrcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)	char **ahost;	u_short rport;	const char *locuser, *remuser, *cmd;	int *fd2p;	int af;{	struct addrinfo hints, *res, *ai;	struct sockaddr_storage from;	fd_set reads;	sigset_t oldmask, newmask;	pid_t pid;	int s, aport, lport, timo, error;	char c, *p;	int refused, nres;	char num[8];	static char canonnamebuf[MAXDNAME];	/* is it proper here? */	/* call rcmdsh() with specified remote shell if appropriate. */	if (!issetugid() && (p = getenv("RSH"))) {		struct servent *sp = getservbyname("shell", "tcp");		if (sp && sp->s_port == rport)			return (rcmdsh(ahost, rport, locuser, remuser,			    cmd, p));	}	/* use rsh(1) if non-root and remote port is shell. */	if (geteuid()) {		struct servent *sp = getservbyname("shell", "tcp");		if (sp && sp->s_port == rport)			return (rcmdsh(ahost, rport, locuser, remuser,			    cmd, NULL));	}	pid = getpid();	memset(&hints, 0, sizeof(hints));	hints.ai_flags = AI_CANONNAME;	hints.ai_family = af;	hints.ai_socktype = SOCK_STREAM;	hints.ai_protocol = 0;	(void)snprintf(num, sizeof(num), "%d", ntohs(rport));	error = getaddrinfo(*ahost, num, &hints, &res);	if (error) {		fprintf(stderr, "rcmd: getaddrinfo: %s\n",			gai_strerror(error));		if (error == EAI_SYSTEM)			fprintf(stderr, "rcmd: getaddrinfo: %s\n",				strerror(errno));		return (-1);	}	if (res->ai_canonname	 && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) {		strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));		*ahost = canonnamebuf;	}	nres = 0;	for (ai = res; ai; ai = ai->ai_next)		nres++;	ai = res;	refused = 0;	sigemptyset(&newmask);	sigaddset(&newmask, SIGURG);	sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask);	for (timo = 1, lport = IPPORT_RESERVED - 1;;) {		s = rresvport_af(&lport, ai->ai_family);		if (s < 0) {			if (errno != EAGAIN && ai->ai_next) {				ai = ai->ai_next;				continue;			}			if (errno == EAGAIN)				(void)fprintf(stderr,				    "rcmd: socket: All ports in use\n");			else				(void)fprintf(stderr, "rcmd: socket: %s\n",				    strerror(errno));			freeaddrinfo(res);			sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,			    NULL);			return (-1);		}		fcntl(s, F_SETOWN, pid);		if (connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)			break;		(void)close(s);		if (errno == EADDRINUSE) {			lport--;			continue;		}		if (errno == ECONNREFUSED)			refused = 1;		if (ai->ai_next == NULL && (!refused || timo > 16)) {			(void)fprintf(stderr, "%s: %s\n",				      *ahost, strerror(errno));			freeaddrinfo(res);			sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,			    NULL);			return (-1);		}		if (nres > 1) {			int oerrno = errno;			getnameinfo(ai->ai_addr, ai->ai_addrlen,				    paddr, sizeof(paddr),				    NULL, 0,				    NI_NUMERICHOST|NI_WITHSCOPEID);			(void)fprintf(stderr, "connect to address %s: ",				      paddr);			errno = oerrno;			perror(0);		}		if ((ai = ai->ai_next) == NULL) {			/* refused && timo <= 16 */			struct timespec time_to_sleep, time_remaining;			time_to_sleep.tv_sec = timo;			time_to_sleep.tv_nsec = 0;			(void)nanosleep(&time_to_sleep, &time_remaining);			timo *= 2;			ai = res;			refused = 0;		}		if (nres > 1) {			getnameinfo(ai->ai_addr, ai->ai_addrlen,				    paddr, sizeof(paddr),				    NULL, 0,				    NI_NUMERICHOST|NI_WITHSCOPEID);			fprintf(stderr, "Trying %s...\n", paddr);		}	}	lport--;	if (fd2p == 0) {		write(s, "", 1);		lport = 0;	} else {		char num[8];		int s2 = rresvport_af(&lport, ai->ai_family), s3;		int len = ai->ai_addrlen;		int nfds;		if (s2 < 0)			goto bad;		listen(s2, 1);		(void)snprintf(num, sizeof(num), "%d", lport);		if (write(s, num, strlen(num)+1) != strlen(num)+1) {			(void)fprintf(stderr,			    "rcmd: write (setting up stderr): %s\n",			    strerror(errno));			(void)close(s2);			goto bad;		}		nfds = max(s, s2)+1;		if(nfds > FD_SETSIZE) {			fprintf(stderr, "rcmd: too many files\n");			(void)close(s2);			goto bad;		}again:		FD_ZERO(&reads);		FD_SET(s, &reads);		FD_SET(s2, &reads);		errno = 0;		if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){			if (errno != 0)				(void)fprintf(stderr,				    "rcmd: select (setting up stderr): %s\n",				    strerror(errno));			else				(void)fprintf(stderr,				"select: protocol failure in circuit setup\n");			(void)close(s2);			goto bad;		}		s3 = accept(s2, (struct sockaddr *)&from, &len);		switch (from.ss_family) {		case AF_INET:			aport = ntohs(((struct sockaddr_in *)&from)->sin_port);			break;#ifdef INET6		case AF_INET6:			aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);			break;#endif		default:			aport = 0;	/* error */			break;		}		/*		 * XXX careful for ftp bounce attacks. If discovered, shut them		 * down and check for the real auxiliary channel to connect.		 */		if (aport == 20) {			close(s3);			goto again;		}		(void)close(s2);		if (s3 < 0) {			(void)fprintf(stderr,			    "rcmd: accept: %s\n", strerror(errno));			lport = 0;			goto bad;		}		*fd2p = s3;		if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {			(void)fprintf(stderr,			    "socket: protocol failure in circuit setup.\n");			goto bad2;		}	}	(void)write(s, locuser, strlen(locuser)+1);	(void)write(s, remuser, strlen(remuser)+1);	(void)write(s, cmd, strlen(cmd)+1);	if (read(s, &c, 1) != 1) {		(void)fprintf(stderr,		    "rcmd: %s: %s\n", *ahost, strerror(errno));		goto bad2;	}	if (c != 0) {		while (read(s, &c, 1) == 1) {			(void)write(STDERR_FILENO, &c, 1);			if (c == '\n')				break;		}		goto bad2;	}	sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);	freeaddrinfo(res);	return (s);bad2:	if (lport)		(void)close(*fd2p);bad:	(void)close(s);	sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);	freeaddrinfo(res);	return (-1);}intrcmd(ahost, rport, locuser, remuser, cmd, fd2p)	char **ahost;	u_short rport;	const char *locuser, *remuser, *cmd;	int *fd2p;{	return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);}intrresvport(port)	int *port;{	return rresvport_af(port, AF_INET);}intrresvport_af(alport, family)	int *alport, family;{	int s;	struct sockaddr_storage ss;	u_short *sport;	memset(&ss, 0, sizeof(ss));	ss.ss_family = family;	switch (family) {	case AF_INET:		sport = &((struct sockaddr_in *)&ss)->sin_port;		((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;		break;#ifdef INET6	case AF_INET6:		sport = &((struct sockaddr_in6 *)&ss)->sin6_port;		((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;		break;#endif	default:		errno = EAFNOSUPPORT;		return -1;	}	s = socket(ss.ss_family, SOCK_STREAM, 0);	if (s < 0)		return (-1);#if 0 /* compat_exact_traditional_rresvport_semantics */	sin.sin_port = htons((u_short)*alport);	if (_bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)		return (s);	if (errno != EADDRINUSE) {		(void)close(s);		return (-1);	}#endif	*sport = 0;	if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {		(void)close(s);		return (-1);	}	*alport = (int)ntohs(*sport);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -