xref: /plan9/sys/src/cmd/rx.c (revision 588d0145e19f8596f2f4442d05dd8a9eda147983)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier int	eof;		/* send an eof if true */
63cb0b4acSDavid du Colombier int	crtonl;		/* convert all received \r to \n */
73cb0b4acSDavid du Colombier int	returns;	/* strip \r on reception */
83e12c5d1SDavid du Colombier char	*note = "die: yankee dog";
96dc4800dSDavid du Colombier char	*ruser;		/* for BSD authentication */
101118d624SDavid du Colombier char *key;
113e12c5d1SDavid du Colombier 
12a454565bSDavid du Colombier void	rex(int, char*, char*);
133e12c5d1SDavid du Colombier void	tcpexec(int, char*, char*);
143e12c5d1SDavid du Colombier int	call(char *, char*, char*, char**);
153e12c5d1SDavid du Colombier char	*buildargs(char*[]);
163e12c5d1SDavid du Colombier int	send(int);
173e12c5d1SDavid du Colombier void	error(char*, char*);
1815174232SDavid du Colombier void	sshexec(char*, char*);
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier void
usage(void)213e12c5d1SDavid du Colombier usage(void)
223e12c5d1SDavid du Colombier {
233cb0b4acSDavid du Colombier 	fprint(2, "usage: %s [-e] [-T] [-r] [-k keypattern] [-l user] net!host command...\n", argv0);
243e12c5d1SDavid du Colombier 	exits("usage");
253e12c5d1SDavid du Colombier }
263e12c5d1SDavid du Colombier 
27*588d0145SDavid du Colombier static int
catch(void *,char * s)28*588d0145SDavid du Colombier catch(void *, char *s)
29*588d0145SDavid du Colombier {
30*588d0145SDavid du Colombier 	return strstr(s, "alarm") != nil;
31*588d0145SDavid du Colombier }
32*588d0145SDavid du Colombier 
333e12c5d1SDavid du Colombier void
main(int argc,char * argv[])343e12c5d1SDavid du Colombier main(int argc, char *argv[])
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier 	char *host, *addr, *args;
373e12c5d1SDavid du Colombier 	int fd;
383e12c5d1SDavid du Colombier 
391118d624SDavid du Colombier 	key = "";
403e12c5d1SDavid du Colombier 	eof = 1;
413cb0b4acSDavid du Colombier 	crtonl = 0;
423cb0b4acSDavid du Colombier 	returns = 1;
433e12c5d1SDavid du Colombier 	ARGBEGIN{
443cb0b4acSDavid du Colombier 	case 'T':
453cb0b4acSDavid du Colombier 		crtonl = 1;
463cb0b4acSDavid du Colombier 		break;
473cb0b4acSDavid du Colombier 	case 'r':
483cb0b4acSDavid du Colombier 		returns = 0;
493cb0b4acSDavid du Colombier 		break;
503e12c5d1SDavid du Colombier 	case 'e':
513e12c5d1SDavid du Colombier 		eof = 0;
523e12c5d1SDavid du Colombier 		break;
531118d624SDavid du Colombier 	case 'k':
541118d624SDavid du Colombier 		key = EARGF(usage());
551118d624SDavid du Colombier 		break;
567dd7cddfSDavid du Colombier 	case 'l':
571118d624SDavid du Colombier 		ruser = EARGF(usage());
587dd7cddfSDavid du Colombier 		break;
593e12c5d1SDavid du Colombier 	default:
603e12c5d1SDavid du Colombier 		usage();
613e12c5d1SDavid du Colombier 	}ARGEND
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier 	if(argc < 2)
643e12c5d1SDavid du Colombier 		usage();
653e12c5d1SDavid du Colombier 	host = argv[0];
663e12c5d1SDavid du Colombier 	args = buildargs(&argv[1]);
67*588d0145SDavid du Colombier 	atnotify(catch, 1);
683e12c5d1SDavid du Colombier 
696dc4800dSDavid du Colombier 	/* try rexexec p9any then dial again with p9sk2 */
703e12c5d1SDavid du Colombier 	fd = call(0, host, "rexexec", &addr);
713e12c5d1SDavid du Colombier 	if(fd >= 0)
72a454565bSDavid du Colombier 		rex(fd, args, "p9any");
73a454565bSDavid du Colombier 	close(fd);
74a454565bSDavid du Colombier 	fd = call(0, host, "rexexec", &addr);
75a454565bSDavid du Colombier 	if(fd >= 0)
76a454565bSDavid du Colombier 		rex(fd, args, "p9sk2");
77a454565bSDavid du Colombier 	close(fd);
783e12c5d1SDavid du Colombier 
79f43e6a25SDavid du Colombier 	/* if there's an ssh port, try that */
80f43e6a25SDavid du Colombier 	fd = call("tcp", host, "ssh", &addr);
81f43e6a25SDavid du Colombier 	if(fd >= 0){
82f43e6a25SDavid du Colombier 		close(fd);
83f43e6a25SDavid du Colombier 		sshexec(host, args);
84f43e6a25SDavid du Colombier 		/* falls through if no ssh */
85f43e6a25SDavid du Colombier 	}
86f43e6a25SDavid du Colombier 
871118d624SDavid du Colombier 	/* specific attempts */
881118d624SDavid du Colombier 	fd = call("tcp", host, "shell", &addr);
891118d624SDavid du Colombier 	if(fd >= 0)
901118d624SDavid du Colombier 		tcpexec(fd, addr, args);
911118d624SDavid du Colombier 
923e12c5d1SDavid du Colombier 	error("can't dial", host);
933e12c5d1SDavid du Colombier 	exits(0);
943e12c5d1SDavid du Colombier }
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier int
call(char * net,char * host,char * service,char ** na)973e12c5d1SDavid du Colombier call(char *net, char *host, char *service, char **na)
983e12c5d1SDavid du Colombier {
993e12c5d1SDavid du Colombier 	*na = netmkaddr(host, net, service);
1003e12c5d1SDavid du Colombier 	return dial(*na, 0, 0, 0);
1013e12c5d1SDavid du Colombier }
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier void
rex(int fd,char * cmd,char * proto)104a454565bSDavid du Colombier rex(int fd, char *cmd, char *proto)
1053e12c5d1SDavid du Colombier {
106219b2ee8SDavid du Colombier 	char buf[4096];
107*588d0145SDavid du Colombier 	int kid, n, oalarm;
1089a747e4fSDavid du Colombier 	AuthInfo *ai;
1093e12c5d1SDavid du Colombier 
110*588d0145SDavid du Colombier 	oalarm = alarm(2 * 60 * 1000);		/* don't hang forever */
1111118d624SDavid du Colombier 	ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key);
112*588d0145SDavid du Colombier 	alarm(oalarm);
113a454565bSDavid du Colombier 	if(ai == nil){
114a454565bSDavid du Colombier 		if(strcmp(proto, "p9any") == 0)
115a454565bSDavid du Colombier 			return;
1169a747e4fSDavid du Colombier 		error("auth_proxy", nil);
117a454565bSDavid du Colombier 	}
1183e12c5d1SDavid du Colombier 	write(fd, cmd, strlen(cmd)+1);
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier 	kid = send(fd);
1213e12c5d1SDavid du Colombier 	while((n=read(fd, buf, sizeof buf))>0)
1223e12c5d1SDavid du Colombier 		if(write(1, buf, n)!=n)
1233e12c5d1SDavid du Colombier 			error("write error", 0);
1243e12c5d1SDavid du Colombier 	sleep(250);
125219b2ee8SDavid du Colombier 	postnote(PNPROC, kid, note);/**/
1263e12c5d1SDavid du Colombier 	exits(0);
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier 
1293e12c5d1SDavid du Colombier void
tcpexec(int fd,char * addr,char * cmd)1303e12c5d1SDavid du Colombier tcpexec(int fd, char *addr, char *cmd)
1313e12c5d1SDavid du Colombier {
13215174232SDavid du Colombier 	char *cp, *ep, *u, *ru, buf[4096];
1333e12c5d1SDavid du Colombier 	int kid, n;
1343e12c5d1SDavid du Colombier 
1353e12c5d1SDavid du Colombier 	/*
1363e12c5d1SDavid du Colombier 	 *  do the ucb authentication and send command
1373e12c5d1SDavid du Colombier 	 */
1383e12c5d1SDavid du Colombier 	u = getuser();
13915174232SDavid du Colombier 	ru = ruser;
14015174232SDavid du Colombier 	if(ru == nil)
14115174232SDavid du Colombier 		ru = u;
1423e12c5d1SDavid du Colombier 	if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0
14315174232SDavid du Colombier 	|| write(fd, ru, strlen(ru)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){
1443e12c5d1SDavid du Colombier 		close(fd);
1453e12c5d1SDavid du Colombier 		error("can't authenticate to", addr);
1463e12c5d1SDavid du Colombier 	}
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier 	/*
1493e12c5d1SDavid du Colombier 	 *  get authentication reply
1503e12c5d1SDavid du Colombier 	 */
1513e12c5d1SDavid du Colombier 	if(read(fd, buf, 1) != 1){
1523e12c5d1SDavid du Colombier 		close(fd);
1533e12c5d1SDavid du Colombier 		error("can't authenticate to", addr);
1543e12c5d1SDavid du Colombier 	}
1553e12c5d1SDavid du Colombier 	if(buf[0] != 0){
1563e12c5d1SDavid du Colombier 		while(read(fd, buf, 1) == 1){
1573e12c5d1SDavid du Colombier 			write(2, buf, 1);
1583e12c5d1SDavid du Colombier 			if(buf[0] == '\n')
1593e12c5d1SDavid du Colombier 				break;
1603e12c5d1SDavid du Colombier 		}
1613e12c5d1SDavid du Colombier 		close(fd);
1623e12c5d1SDavid du Colombier 		error("rejected by", addr);
1633e12c5d1SDavid du Colombier 	}
1643e12c5d1SDavid du Colombier 
1653e12c5d1SDavid du Colombier 	kid = send(fd);
1663cb0b4acSDavid du Colombier 	while((n=read(fd, buf, sizeof buf))>0){
1673cb0b4acSDavid du Colombier 		if(crtonl) {
1683cb0b4acSDavid du Colombier 			/* convert cr's to nl's */
1693cb0b4acSDavid du Colombier 			for (cp = buf; cp < buf + n; cp++)
1703cb0b4acSDavid du Colombier 				if (*cp == '\r')
1713cb0b4acSDavid du Colombier 					*cp = '\n';
1723cb0b4acSDavid du Colombier 		}
1733cb0b4acSDavid du Colombier 		else if(!returns){
1743cb0b4acSDavid du Colombier 			/* convert cr's to null's */
1753cb0b4acSDavid du Colombier 			cp = buf;
1763cb0b4acSDavid du Colombier 			ep = buf + n;
1773cb0b4acSDavid du Colombier 			while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){
1783cb0b4acSDavid du Colombier 				memmove(cp, cp+1, ep-cp-1);
1793cb0b4acSDavid du Colombier 				ep--;
1803cb0b4acSDavid du Colombier 				n--;
1813cb0b4acSDavid du Colombier 			}
1823cb0b4acSDavid du Colombier 		}
1833e12c5d1SDavid du Colombier 		if(write(1, buf, n)!=n)
1843e12c5d1SDavid du Colombier 			error("write error", 0);
1853cb0b4acSDavid du Colombier 	}
1863e12c5d1SDavid du Colombier 	sleep(250);
187219b2ee8SDavid du Colombier 	postnote(PNPROC, kid, note);/**/
1883e12c5d1SDavid du Colombier 	exits(0);
1893e12c5d1SDavid du Colombier }
1903e12c5d1SDavid du Colombier 
191f43e6a25SDavid du Colombier void
sshexec(char * host,char * cmd)192f43e6a25SDavid du Colombier sshexec(char *host, char *cmd)
193f43e6a25SDavid du Colombier {
19415174232SDavid du Colombier 	char *argv[10];
19515174232SDavid du Colombier 	int n;
19615174232SDavid du Colombier 
19715174232SDavid du Colombier 	n = 0;
19815174232SDavid du Colombier 	argv[n++] = "ssh";
19915174232SDavid du Colombier 	argv[n++] = "-iCm";
20015174232SDavid du Colombier 	if(!returns)
20115174232SDavid du Colombier 		argv[n++] = "-r";
20215174232SDavid du Colombier 	if(ruser){
20315174232SDavid du Colombier 		argv[n++] = "-l";
20415174232SDavid du Colombier 		argv[n++] = ruser;
20515174232SDavid du Colombier 	}
20615174232SDavid du Colombier 	argv[n++] = host;
20715174232SDavid du Colombier 	argv[n++] = cmd;
20815174232SDavid du Colombier 	argv[n] = 0;
20915174232SDavid du Colombier 	exec("/bin/ssh", argv);
210f43e6a25SDavid du Colombier }
211f43e6a25SDavid du Colombier 
2123e12c5d1SDavid du Colombier int
send(int fd)2133e12c5d1SDavid du Colombier send(int fd)
2143e12c5d1SDavid du Colombier {
2153e12c5d1SDavid du Colombier 	char buf[4096];
2163e12c5d1SDavid du Colombier 	int n;
2173e12c5d1SDavid du Colombier 	int kid;
2183e12c5d1SDavid du Colombier 	switch(kid = fork()){
2193e12c5d1SDavid du Colombier 	case -1:
2203e12c5d1SDavid du Colombier 		error("fork error", 0);
2213e12c5d1SDavid du Colombier 	case 0:
2223e12c5d1SDavid du Colombier 		break;
2233e12c5d1SDavid du Colombier 	default:
2243e12c5d1SDavid du Colombier 		return kid;
2253e12c5d1SDavid du Colombier 	}
2263e12c5d1SDavid du Colombier 	while((n=read(0, buf, sizeof buf))>0)
2273e12c5d1SDavid du Colombier 		if(write(fd, buf, n)!=n)
2283e12c5d1SDavid du Colombier 			exits("write error");
2293e12c5d1SDavid du Colombier 	if(eof)
2303e12c5d1SDavid du Colombier 		write(fd, buf, 0);
2313e12c5d1SDavid du Colombier 
2323e12c5d1SDavid du Colombier 	exits(0);
2333e12c5d1SDavid du Colombier 	return 0;			/* to keep compiler happy */
2343e12c5d1SDavid du Colombier }
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier void
error(char * s,char * z)2373e12c5d1SDavid du Colombier error(char *s, char *z)
2383e12c5d1SDavid du Colombier {
2393e12c5d1SDavid du Colombier 	if(z == 0)
240219b2ee8SDavid du Colombier 		fprint(2, "%s: %s: %r\n", argv0, s);
2413e12c5d1SDavid du Colombier 	else
242219b2ee8SDavid du Colombier 		fprint(2, "%s: %s %s: %r\n", argv0, s, z);
2433e12c5d1SDavid du Colombier 	exits(s);
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier 
2463e12c5d1SDavid du Colombier char *
buildargs(char * argv[])2473e12c5d1SDavid du Colombier buildargs(char *argv[])
2483e12c5d1SDavid du Colombier {
2493e12c5d1SDavid du Colombier 	char *args;
2503e12c5d1SDavid du Colombier 	int m, n;
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier 	args = malloc(1);
2533e12c5d1SDavid du Colombier 	args[0] = '\0';
2543e12c5d1SDavid du Colombier 	n = 0;
2553e12c5d1SDavid du Colombier 	while(*argv){
2563e12c5d1SDavid du Colombier 		m = strlen(*argv) + 1;
2573e12c5d1SDavid du Colombier 		args = realloc(args, n+m +1);
2583e12c5d1SDavid du Colombier 		if(args == 0)
2593e12c5d1SDavid du Colombier 			error("malloc fail", 0);
2603e12c5d1SDavid du Colombier 		args[n] = ' ';	/* smashes old null */
2613e12c5d1SDavid du Colombier 		strcpy(args+n+1, *argv);
2623e12c5d1SDavid du Colombier 		n += m;
2633e12c5d1SDavid du Colombier 		argv++;
2643e12c5d1SDavid du Colombier 	}
2653e12c5d1SDavid du Colombier 	return args;
2663e12c5d1SDavid du Colombier }
267