remote command execution & passwords

Dave Martindale dave at onfcanim.UUCP
Fri Mar 11 16:49:37 AEST 1988


In article <860 at hsi.UUCP> stevens at hsi.UUCP (Richard Stevens) writes:
>I see three ways for an arbitrary C program to execute a program on
>another system and communicate with it:
>
>(1) Use rexec(3).  Doing this requires that the user's unencrypted
>    password be explicitly passed to rexec.
>
>(2) Use rcmd(3).  Using this obviates the need to communicate passwords
>    between the two systems, however the program that calls rcmd
>    must be suid to root
>
>(3) Use the rsh(1) command as follows.  [ messy stuff ]

There is another way, and it's faster than all of the above, if the
thing you want to do on the other system is run a single server process,
and you control the other system.

The idea is that you create a new network "service" and publish it,
then let the appropriate server process know about it.

For example, I have a server that sits on our IRIS workstations that
allows writing scanlines to the screen, so our VAX can display pictures
though it has no frame buffer directly attached.

First, you add an entry to the /etc/services file:

	iris_slave	700/tcp			# to display on IRIS framebuffer

700 was picked because it wasn't near other already-defined services.
This allows getservbyname() to find the service number.

Then you inform the inetd about the new service and the server for it
by adding a line to /etc/inetd.conf (or /usr/etc/inetd.conf on the IRIS):

	iris_slave stream tcp	nowait	nobody	/usr/local/lib/iris_slave	iris_slave

Then you kill and restart the inetd on the IRIS (kill -1 doesn't work).

Then you call the code below to establish a connection from your current
machine to the slave process on the target machine.  Anything you write
to the network file descriptor can be read from the slave's standard
input, and its standard output can be read from the network file
descriptor in the master, though they need to agree on a protocol of
whose turn it is to write.

Calling method:

	if ((remfd = connect_slave(hostname, "iris_slave", "tcp")) < 0) {
		fprintf(stderr, "Can't connect to slave");
	}

Code for connect_slave:

/*
 + File:	connect_slave.c
 + Purpose:	Establish a network connection to a process on a remote
 +		machine, using the "known services" mechanism.
 +
 * Author:	Dave Martindale, National Film Board of Canada
 * Date:	03-Jan-88
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#ifdef m68000
#include <bsd/netdb.h>
#else
#include <netdb.h>
#endif

connect_slave(host, service, protocol)
char *host;
char *service;
char * protocol;
{
	int			s;
	unsigned int		timo = 1;
	struct hostent		*hp;
	struct servent		*sp;
	struct sockaddr_in	sin;
	extern int		errno;

	hp = gethostbyname(host);
	if (hp == (struct hostent *)0) {
		fprintf(stderr, "%s: unknown host\n", host);
		return -1;
	}

	sp = getservbyname(service, protocol);
	if (sp == (struct servent *)0) {
		fprintf(stderr, "%s: unknown service\n", service);
		return -1;
	}

retry:
	s = socket(AF_INET, SOCK_STREAM, 0);
	if (s < 0) {
		perror("connect_slave: socket");
		return -1;
	}
	sin.sin_family = hp->h_addrtype;
	sin.sin_port = sp->s_port;
	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
	if (connect(s, &sin, sizeof(sin)) < 0) {
		if (errno == ECONNREFUSED && timo <= 16) {
			(void) close(s);
			sleep(timo);
			timo *= 2;
			goto retry;
		}
		perror(hp->h_name);
		return -1;
	}
	return s;
}



More information about the Comp.unix.wizards mailing list