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