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; 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 *host, char *cmd); 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 erexexec 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, buf[4096]; 124 int kid, n; 125 char *r; 126 127 /* 128 * do the ucb authentication and send command 129 */ 130 u = getuser(); 131 r = ruser ? ruser : u; 132 if(write(fd, "", 1)<0 || write(fd, u, strlen(u)+1)<0 133 || write(fd, r, strlen(r)+1)<0 || write(fd, cmd, strlen(cmd)+1)<0){ 134 close(fd); 135 error("can't authenticate to", addr); 136 } 137 138 /* 139 * get authentication reply 140 */ 141 if(read(fd, buf, 1) != 1){ 142 close(fd); 143 error("can't authenticate to", addr); 144 } 145 if(buf[0] != 0){ 146 while(read(fd, buf, 1) == 1){ 147 write(2, buf, 1); 148 if(buf[0] == '\n') 149 break; 150 } 151 close(fd); 152 error("rejected by", addr); 153 } 154 155 kid = send(fd); 156 while((n=read(fd, buf, sizeof buf))>0){ 157 if(crtonl) { 158 /* convert cr's to nl's */ 159 for (cp = buf; cp < buf + n; cp++) 160 if (*cp == '\r') 161 *cp = '\n'; 162 } 163 else if(!returns){ 164 /* convert cr's to null's */ 165 cp = buf; 166 ep = buf + n; 167 while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){ 168 memmove(cp, cp+1, ep-cp-1); 169 ep--; 170 n--; 171 } 172 } 173 if(write(1, buf, n)!=n) 174 error("write error", 0); 175 } 176 sleep(250); 177 postnote(PNPROC, kid, note);/**/ 178 exits(0); 179 } 180 181 void 182 sshexec(char *host, char *cmd) 183 { 184 execl("/bin/ssh", "ssh", "-iCm", host, cmd, 0); 185 } 186 187 int 188 send(int fd) 189 { 190 char buf[4096]; 191 int n; 192 int kid; 193 switch(kid = fork()){ 194 case -1: 195 error("fork error", 0); 196 case 0: 197 break; 198 default: 199 return kid; 200 } 201 while((n=read(0, buf, sizeof buf))>0) 202 if(write(fd, buf, n)!=n) 203 exits("write error"); 204 if(eof) 205 write(fd, buf, 0); 206 207 exits(0); 208 return 0; /* to keep compiler happy */ 209 } 210 211 void 212 error(char *s, char *z) 213 { 214 if(z == 0) 215 fprint(2, "%s: %s: %r\n", argv0, s); 216 else 217 fprint(2, "%s: %s %s: %r\n", argv0, s, z); 218 exits(s); 219 } 220 221 char * 222 buildargs(char *argv[]) 223 { 224 char *args; 225 int m, n; 226 227 args = malloc(1); 228 args[0] = '\0'; 229 n = 0; 230 while(*argv){ 231 m = strlen(*argv) + 1; 232 args = realloc(args, n+m +1); 233 if(args == 0) 234 error("malloc fail", 0); 235 args[n] = ' '; /* smashes old null */ 236 strcpy(args+n+1, *argv); 237 n += m; 238 argv++; 239 } 240 return args; 241 } 242