xref: /plan9-contrib/sys/src/cmd/rx.c (revision f43e6a25a20bbf5b6ac5d77a24f06458fb6e28a3)
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 */
63e12c5d1SDavid du Colombier char	*note = "die: yankee dog";
77dd7cddfSDavid du Colombier char	*ruser;
81118d624SDavid du Colombier char *key;
93e12c5d1SDavid du Colombier 
10a454565bSDavid du Colombier void	rex(int, char*, char*);
113e12c5d1SDavid du Colombier void	tcpexec(int, char*, char*);
123e12c5d1SDavid du Colombier int	call(char *, char*, char*, char**);
133e12c5d1SDavid du Colombier char	*buildargs(char*[]);
143e12c5d1SDavid du Colombier int	send(int);
153e12c5d1SDavid du Colombier void	error(char*, char*);
16*f43e6a25SDavid du Colombier void	sshexec(char *host, char *cmd);
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier void
193e12c5d1SDavid du Colombier usage(void)
203e12c5d1SDavid du Colombier {
211118d624SDavid du Colombier 	fprint(2, "usage: %s [-e] [-k keypattern] [-l user] net!host command...\n", argv0);
223e12c5d1SDavid du Colombier 	exits("usage");
233e12c5d1SDavid du Colombier }
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier void
263e12c5d1SDavid du Colombier main(int argc, char *argv[])
273e12c5d1SDavid du Colombier {
283e12c5d1SDavid du Colombier 	char *host, *addr, *args;
293e12c5d1SDavid du Colombier 	int fd;
303e12c5d1SDavid du Colombier 
311118d624SDavid du Colombier 	key = "";
323e12c5d1SDavid du Colombier 	eof = 1;
333e12c5d1SDavid du Colombier 	ARGBEGIN{
343e12c5d1SDavid du Colombier 	case 'e':
353e12c5d1SDavid du Colombier 		eof = 0;
363e12c5d1SDavid du Colombier 		break;
371118d624SDavid du Colombier 	case 'k':
381118d624SDavid du Colombier 		key = EARGF(usage());
391118d624SDavid du Colombier 		break;
407dd7cddfSDavid du Colombier 	case 'l':
411118d624SDavid du Colombier 		ruser = EARGF(usage());
427dd7cddfSDavid du Colombier 		break;
433e12c5d1SDavid du Colombier 	default:
443e12c5d1SDavid du Colombier 		usage();
453e12c5d1SDavid du Colombier 	}ARGEND
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	if(argc < 2)
483e12c5d1SDavid du Colombier 		usage();
493e12c5d1SDavid du Colombier 	host = argv[0];
503e12c5d1SDavid du Colombier 	args = buildargs(&argv[1]);
513e12c5d1SDavid du Colombier 
52*f43e6a25SDavid du Colombier 	/* try erexexec p9any then dial again with p9sk2 */
533e12c5d1SDavid du Colombier 	fd = call(0, host, "rexexec", &addr);
543e12c5d1SDavid du Colombier 	if(fd >= 0)
55a454565bSDavid du Colombier 		rex(fd, args, "p9any");
56a454565bSDavid du Colombier 	close(fd);
57a454565bSDavid du Colombier 	fd = call(0, host, "rexexec", &addr);
58a454565bSDavid du Colombier 	if(fd >= 0)
59a454565bSDavid du Colombier 		rex(fd, args, "p9sk2");
60a454565bSDavid du Colombier 	close(fd);
613e12c5d1SDavid du Colombier 
62*f43e6a25SDavid du Colombier 	/* if there's an ssh port, try that */
63*f43e6a25SDavid du Colombier 	fd = call("tcp", host, "ssh", &addr);
64*f43e6a25SDavid du Colombier 	if(fd >= 0){
65*f43e6a25SDavid du Colombier 		close(fd);
66*f43e6a25SDavid du Colombier 		sshexec(host, args);
67*f43e6a25SDavid du Colombier 		/* falls through if no ssh */
68*f43e6a25SDavid du Colombier 	}
69*f43e6a25SDavid du Colombier 
701118d624SDavid du Colombier 	/* specific attempts */
711118d624SDavid du Colombier 	fd = call("tcp", host, "shell", &addr);
721118d624SDavid du Colombier 	if(fd >= 0)
731118d624SDavid du Colombier 		tcpexec(fd, addr, args);
741118d624SDavid du Colombier 
753e12c5d1SDavid du Colombier 	error("can't dial", host);
763e12c5d1SDavid du Colombier 	exits(0);
773e12c5d1SDavid du Colombier }
783e12c5d1SDavid du Colombier 
793e12c5d1SDavid du Colombier int
803e12c5d1SDavid du Colombier call(char *net, char *host, char *service, char **na)
813e12c5d1SDavid du Colombier {
823e12c5d1SDavid du Colombier 	*na = netmkaddr(host, net, service);
833e12c5d1SDavid du Colombier 	return dial(*na, 0, 0, 0);
843e12c5d1SDavid du Colombier }
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier void
87a454565bSDavid du Colombier rex(int fd, char *cmd, char *proto)
883e12c5d1SDavid du Colombier {
89219b2ee8SDavid du Colombier 	char buf[4096];
903e12c5d1SDavid du Colombier 	int kid, n;
919a747e4fSDavid du Colombier 	AuthInfo *ai;
923e12c5d1SDavid du Colombier 
931118d624SDavid du Colombier 	ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key);
94a454565bSDavid du Colombier 	if(ai == nil){
95a454565bSDavid du Colombier 		if(strcmp(proto, "p9any") == 0)
96a454565bSDavid du Colombier 			return;
979a747e4fSDavid du Colombier 		error("auth_proxy", nil);
98a454565bSDavid du Colombier 	}
993e12c5d1SDavid du Colombier 	write(fd, cmd, strlen(cmd)+1);
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier 	kid = send(fd);
1023e12c5d1SDavid du Colombier 	while((n=read(fd, buf, sizeof buf))>0)
1033e12c5d1SDavid du Colombier 		if(write(1, buf, n)!=n)
1043e12c5d1SDavid du Colombier 			error("write error", 0);
1053e12c5d1SDavid du Colombier 	sleep(250);
106219b2ee8SDavid du Colombier 	postnote(PNPROC, kid, note);/**/
1073e12c5d1SDavid du Colombier 	exits(0);
1083e12c5d1SDavid du Colombier }
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier void
1113e12c5d1SDavid du Colombier tcpexec(int fd, char *addr, char *cmd)
1123e12c5d1SDavid du Colombier {
1133e12c5d1SDavid du Colombier 	char *u, buf[4096];
1143e12c5d1SDavid du Colombier 	int kid, n;
1157dd7cddfSDavid du Colombier 	char *r;
1163e12c5d1SDavid du Colombier 
1173e12c5d1SDavid du Colombier 	/*
1183e12c5d1SDavid du Colombier 	 *  do the ucb authentication and send command
1193e12c5d1SDavid du Colombier 	 */
1203e12c5d1SDavid du Colombier 	u = getuser();
1217dd7cddfSDavid du Colombier 	r = ruser ? ruser : u;
1223e12c5d1SDavid du Colombier 	if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0
1237dd7cddfSDavid du Colombier 	|| write(fd, r, strlen(r)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){
1243e12c5d1SDavid du Colombier 		close(fd);
1253e12c5d1SDavid du Colombier 		error("can't authenticate to", addr);
1263e12c5d1SDavid du Colombier 	}
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier 	/*
1293e12c5d1SDavid du Colombier 	 *  get authentication reply
1303e12c5d1SDavid du Colombier 	 */
1313e12c5d1SDavid du Colombier 	if(read(fd, buf, 1) != 1){
1323e12c5d1SDavid du Colombier 		close(fd);
1333e12c5d1SDavid du Colombier 		error("can't authenticate to", addr);
1343e12c5d1SDavid du Colombier 	}
1353e12c5d1SDavid du Colombier 	if(buf[0] != 0){
1363e12c5d1SDavid du Colombier 		while(read(fd, buf, 1) == 1){
1373e12c5d1SDavid du Colombier 			write(2, buf, 1);
1383e12c5d1SDavid du Colombier 			if(buf[0] == '\n')
1393e12c5d1SDavid du Colombier 				break;
1403e12c5d1SDavid du Colombier 		}
1413e12c5d1SDavid du Colombier 		close(fd);
1423e12c5d1SDavid du Colombier 		error("rejected by", addr);
1433e12c5d1SDavid du Colombier 	}
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	kid = send(fd);
1463e12c5d1SDavid du Colombier 	while((n=read(fd, buf, sizeof buf))>0)
1473e12c5d1SDavid du Colombier 		if(write(1, buf, n)!=n)
1483e12c5d1SDavid du Colombier 			error("write error", 0);
1493e12c5d1SDavid du Colombier 	sleep(250);
150219b2ee8SDavid du Colombier 	postnote(PNPROC, kid, note);/**/
1513e12c5d1SDavid du Colombier 	exits(0);
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier 
154*f43e6a25SDavid du Colombier void
155*f43e6a25SDavid du Colombier sshexec(char *host, char *cmd)
156*f43e6a25SDavid du Colombier {
157*f43e6a25SDavid du Colombier 	execl("/bin/ssh", "ssh", "-iCm", host, cmd, 0);
158*f43e6a25SDavid du Colombier }
159*f43e6a25SDavid du Colombier 
1603e12c5d1SDavid du Colombier int
1613e12c5d1SDavid du Colombier send(int fd)
1623e12c5d1SDavid du Colombier {
1633e12c5d1SDavid du Colombier 	char buf[4096];
1643e12c5d1SDavid du Colombier 	int n;
1653e12c5d1SDavid du Colombier 	int kid;
1663e12c5d1SDavid du Colombier 	switch(kid = fork()){
1673e12c5d1SDavid du Colombier 	case -1:
1683e12c5d1SDavid du Colombier 		error("fork error", 0);
1693e12c5d1SDavid du Colombier 	case 0:
1703e12c5d1SDavid du Colombier 		break;
1713e12c5d1SDavid du Colombier 	default:
1723e12c5d1SDavid du Colombier 		return kid;
1733e12c5d1SDavid du Colombier 	}
1743e12c5d1SDavid du Colombier 	while((n=read(0, buf, sizeof buf))>0)
1753e12c5d1SDavid du Colombier 		if(write(fd, buf, n)!=n)
1763e12c5d1SDavid du Colombier 			exits("write error");
1773e12c5d1SDavid du Colombier 	if(eof)
1783e12c5d1SDavid du Colombier 		write(fd, buf, 0);
1793e12c5d1SDavid du Colombier 
1803e12c5d1SDavid du Colombier 	exits(0);
1813e12c5d1SDavid du Colombier 	return 0;			/* to keep compiler happy */
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier void
1853e12c5d1SDavid du Colombier error(char *s, char *z)
1863e12c5d1SDavid du Colombier {
1873e12c5d1SDavid du Colombier 	if(z == 0)
188219b2ee8SDavid du Colombier 		fprint(2, "%s: %s: %r\n", argv0, s);
1893e12c5d1SDavid du Colombier 	else
190219b2ee8SDavid du Colombier 		fprint(2, "%s: %s %s: %r\n", argv0, s, z);
1913e12c5d1SDavid du Colombier 	exits(s);
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier char *
1953e12c5d1SDavid du Colombier buildargs(char *argv[])
1963e12c5d1SDavid du Colombier {
1973e12c5d1SDavid du Colombier 	char *args;
1983e12c5d1SDavid du Colombier 	int m, n;
1993e12c5d1SDavid du Colombier 
2003e12c5d1SDavid du Colombier 	args = malloc(1);
2013e12c5d1SDavid du Colombier 	args[0] = '\0';
2023e12c5d1SDavid du Colombier 	n = 0;
2033e12c5d1SDavid du Colombier 	while(*argv){
2043e12c5d1SDavid du Colombier 		m = strlen(*argv) + 1;
2053e12c5d1SDavid du Colombier 		args = realloc(args, n+m +1);
2063e12c5d1SDavid du Colombier 		if(args == 0)
2073e12c5d1SDavid du Colombier 			error("malloc fail", 0);
2083e12c5d1SDavid du Colombier 		args[n] = ' ';	/* smashes old null */
2093e12c5d1SDavid du Colombier 		strcpy(args+n+1, *argv);
2103e12c5d1SDavid du Colombier 		n += m;
2113e12c5d1SDavid du Colombier 		argv++;
2123e12c5d1SDavid du Colombier 	}
2133e12c5d1SDavid du Colombier 	return args;
2143e12c5d1SDavid du Colombier }
215