1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 5 int eof; /* send an eof if true */ 6 int crtonl; /* convert all received \r to \n */ 7 int returns; /* strip \r on reception */ 8 char *note = "die: yankee dog"; 9 char *ruser; /* for BSD authentication */ 10 char *key; 11 12 void rex(int, char*, char*); 13 void tcpexec(int, char*, char*); 14 int call(char *, char*, char*, char**); 15 char *buildargs(char*[]); 16 int send(int); 17 void error(char*, char*); 18 void sshexec(char*, char*); 19 20 void 21 usage(void) 22 { 23 fprint(2, "usage: %s [-e] [-T] [-r] [-k keypattern] [-l user] net!host command...\n", argv0); 24 exits("usage"); 25 } 26 27 void 28 main(int argc, char *argv[]) 29 { 30 char *host, *addr, *args; 31 int fd; 32 33 key = ""; 34 eof = 1; 35 crtonl = 0; 36 returns = 1; 37 ARGBEGIN{ 38 case 'T': 39 crtonl = 1; 40 break; 41 case 'r': 42 returns = 0; 43 break; 44 case 'e': 45 eof = 0; 46 break; 47 case 'k': 48 key = EARGF(usage()); 49 break; 50 case 'l': 51 ruser = EARGF(usage()); 52 break; 53 default: 54 usage(); 55 }ARGEND 56 57 if(argc < 2) 58 usage(); 59 host = argv[0]; 60 args = buildargs(&argv[1]); 61 62 /* try rexexec p9any then dial again with p9sk2 */ 63 fd = call(0, host, "rexexec", &addr); 64 if(fd >= 0) 65 rex(fd, args, "p9any"); 66 close(fd); 67 fd = call(0, host, "rexexec", &addr); 68 if(fd >= 0) 69 rex(fd, args, "p9sk2"); 70 close(fd); 71 72 /* if there's an ssh port, try that */ 73 fd = call("tcp", host, "ssh", &addr); 74 if(fd >= 0){ 75 close(fd); 76 sshexec(host, args); 77 /* falls through if no ssh */ 78 } 79 80 /* specific attempts */ 81 fd = call("tcp", host, "shell", &addr); 82 if(fd >= 0) 83 tcpexec(fd, addr, args); 84 85 error("can't dial", host); 86 exits(0); 87 } 88 89 int 90 call(char *net, char *host, char *service, char **na) 91 { 92 *na = netmkaddr(host, net, service); 93 return dial(*na, 0, 0, 0); 94 } 95 96 void 97 rex(int fd, char *cmd, char *proto) 98 { 99 char buf[4096]; 100 int kid, n; 101 AuthInfo *ai; 102 103 ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key); 104 if(ai == nil){ 105 if(strcmp(proto, "p9any") == 0) 106 return; 107 error("auth_proxy", nil); 108 } 109 write(fd, cmd, strlen(cmd)+1); 110 111 kid = send(fd); 112 while((n=read(fd, buf, sizeof buf))>0) 113 if(write(1, buf, n)!=n) 114 error("write error", 0); 115 sleep(250); 116 postnote(PNPROC, kid, note);/**/ 117 exits(0); 118 } 119 120 void 121 tcpexec(int fd, char *addr, char *cmd) 122 { 123 char *cp, *ep, *u, *ru, buf[4096]; 124 int kid, n; 125 126 /* 127 * do the ucb authentication and send command 128 */ 129 u = getuser(); 130 ru = ruser; 131 if(ru == nil) 132 ru = u; 133 if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0 134 || write(fd, ru, strlen(ru)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){ 135 close(fd); 136 error("can't authenticate to", addr); 137 } 138 139 /* 140 * get authentication reply 141 */ 142 if(read(fd, buf, 1) != 1){ 143 close(fd); 144 error("can't authenticate to", addr); 145 } 146 if(buf[0] != 0){ 147 while(read(fd, buf, 1) == 1){ 148 write(2, buf, 1); 149 if(buf[0] == '\n') 150 break; 151 } 152 close(fd); 153 error("rejected by", addr); 154 } 155 156 kid = send(fd); 157 while((n=read(fd, buf, sizeof buf))>0){ 158 if(crtonl) { 159 /* convert cr's to nl's */ 160 for (cp = buf; cp < buf + n; cp++) 161 if (*cp == '\r') 162 *cp = '\n'; 163 } 164 else if(!returns){ 165 /* convert cr's to null's */ 166 cp = buf; 167 ep = buf + n; 168 while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){ 169 memmove(cp, cp+1, ep-cp-1); 170 ep--; 171 n--; 172 } 173 } 174 if(write(1, buf, n)!=n) 175 error("write error", 0); 176 } 177 sleep(250); 178 postnote(PNPROC, kid, note);/**/ 179 exits(0); 180 } 181 182 void 183 sshexec(char *host, char *cmd) 184 { 185 char *argv[10]; 186 int n; 187 188 n = 0; 189 argv[n++] = "ssh"; 190 argv[n++] = "-iCm"; 191 if(!returns) 192 argv[n++] = "-r"; 193 if(ruser){ 194 argv[n++] = "-l"; 195 argv[n++] = ruser; 196 } 197 argv[n++] = host; 198 argv[n++] = cmd; 199 argv[n] = 0; 200 exec("/bin/ssh", argv); 201 } 202 203 int 204 send(int fd) 205 { 206 char buf[4096]; 207 int n; 208 int kid; 209 switch(kid = fork()){ 210 case -1: 211 error("fork error", 0); 212 case 0: 213 break; 214 default: 215 return kid; 216 } 217 while((n=read(0, buf, sizeof buf))>0) 218 if(write(fd, buf, n)!=n) 219 exits("write error"); 220 if(eof) 221 write(fd, buf, 0); 222 223 exits(0); 224 return 0; /* to keep compiler happy */ 225 } 226 227 void 228 error(char *s, char *z) 229 { 230 if(z == 0) 231 fprint(2, "%s: %s: %r\n", argv0, s); 232 else 233 fprint(2, "%s: %s %s: %r\n", argv0, s, z); 234 exits(s); 235 } 236 237 char * 238 buildargs(char *argv[]) 239 { 240 char *args; 241 int m, n; 242 243 args = malloc(1); 244 args[0] = '\0'; 245 n = 0; 246 while(*argv){ 247 m = strlen(*argv) + 1; 248 args = realloc(args, n+m +1); 249 if(args == 0) 250 error("malloc fail", 0); 251 args[n] = ' '; /* smashes old null */ 252 strcpy(args+n+1, *argv); 253 n += m; 254 argv++; 255 } 256 return args; 257 } 258