rx.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <auth.h>
  12. int eof; /* send an eof if true */
  13. int crtonl; /* convert all received \r to \n */
  14. int returns; /* strip \r on reception */
  15. char *note = "die: yankee dog";
  16. char *ruser; /* for BSD authentication */
  17. char *key;
  18. void rex(int, char*, char*);
  19. void tcpexec(int, char*, char*);
  20. int call(char *, char*, char*, char**);
  21. char *buildargs(char*[]);
  22. int send(int);
  23. void error(char*, char*);
  24. void sshexec(char*, char*);
  25. void
  26. usage(void)
  27. {
  28. fprint(2, "usage: %s [-e] [-T] [-r] [-k keypattern] [-l user] net!host command...\n", argv0);
  29. exits("usage");
  30. }
  31. static int
  32. catch(void *v, char *s)
  33. {
  34. return strstr(s, "alarm") != nil;
  35. }
  36. void
  37. main(int argc, char *argv[])
  38. {
  39. char *host, *addr, *args;
  40. int fd;
  41. key = "";
  42. eof = 1;
  43. crtonl = 0;
  44. returns = 1;
  45. ARGBEGIN{
  46. case 'T':
  47. crtonl = 1;
  48. break;
  49. case 'r':
  50. returns = 0;
  51. break;
  52. case 'e':
  53. eof = 0;
  54. break;
  55. case 'k':
  56. key = EARGF(usage());
  57. break;
  58. case 'l':
  59. ruser = EARGF(usage());
  60. break;
  61. default:
  62. usage();
  63. }ARGEND
  64. if(argc < 2)
  65. usage();
  66. host = argv[0];
  67. args = buildargs(&argv[1]);
  68. atnotify(catch, 1);
  69. /* try rexexec p9any then dial again with p9sk2 */
  70. fd = call(0, host, "rexexec", &addr);
  71. if(fd >= 0)
  72. rex(fd, args, "p9any");
  73. close(fd);
  74. fd = call(0, host, "rexexec", &addr);
  75. if(fd >= 0)
  76. rex(fd, args, "p9sk2");
  77. close(fd);
  78. /* if there's an ssh port, try that */
  79. fd = call("tcp", host, "ssh", &addr);
  80. if(fd >= 0){
  81. close(fd);
  82. sshexec(host, args);
  83. /* falls through if no ssh */
  84. }
  85. /* specific attempts */
  86. fd = call("tcp", host, "shell", &addr);
  87. if(fd >= 0)
  88. tcpexec(fd, addr, args);
  89. error("can't dial", host);
  90. exits(0);
  91. }
  92. int
  93. call(char *net, char *host, char *service, char **na)
  94. {
  95. *na = netmkaddr(host, net, service);
  96. return dial(*na, 0, 0, 0);
  97. }
  98. void
  99. rex(int fd, char *cmd, char *proto)
  100. {
  101. char buf[4096];
  102. int kid, n, oalarm;
  103. AuthInfo *ai;
  104. oalarm = alarm(2 * 60 * 1000); /* don't hang forever */
  105. ai = auth_proxy(fd, auth_getkey, "proto=%s role=client %s", proto, key);
  106. alarm(oalarm);
  107. if(ai == nil){
  108. if(strcmp(proto, "p9any") == 0)
  109. return;
  110. error("auth_proxy", nil);
  111. }
  112. write(fd, cmd, strlen(cmd)+1);
  113. kid = send(fd);
  114. while((n=read(fd, buf, sizeof buf))>0)
  115. if(write(1, buf, n)!=n)
  116. error("write error", 0);
  117. sleep(250);
  118. postnote(PNPROC, kid, note);/**/
  119. exits(0);
  120. }
  121. void
  122. tcpexec(int fd, char *addr, char *cmd)
  123. {
  124. char *cp, *ep, *u, *ru, buf[4096];
  125. int kid, n;
  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. * 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. kid = send(fd);
  155. while((n=read(fd, buf, sizeof buf))>0){
  156. if(crtonl) {
  157. /* convert cr's to nl's */
  158. for (cp = buf; cp < buf + n; cp++)
  159. if (*cp == '\r')
  160. *cp = '\n';
  161. }
  162. else if(!returns){
  163. /* convert cr's to null's */
  164. cp = buf;
  165. ep = buf + n;
  166. while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){
  167. memmove(cp, cp+1, ep-cp-1);
  168. ep--;
  169. n--;
  170. }
  171. }
  172. if(write(1, buf, n)!=n)
  173. error("write error", 0);
  174. }
  175. sleep(250);
  176. postnote(PNPROC, kid, note);/**/
  177. exits(0);
  178. }
  179. void
  180. sshexec(char *host, char *cmd)
  181. {
  182. char *argv[10];
  183. int n;
  184. n = 0;
  185. argv[n++] = "ssh";
  186. argv[n++] = "-iCm";
  187. if(!returns)
  188. argv[n++] = "-r";
  189. if(ruser){
  190. argv[n++] = "-l";
  191. argv[n++] = ruser;
  192. }
  193. argv[n++] = host;
  194. argv[n++] = cmd;
  195. argv[n] = 0;
  196. exec("/bin/ssh", argv);
  197. }
  198. int
  199. send(int fd)
  200. {
  201. char buf[4096];
  202. int n;
  203. int kid;
  204. switch(kid = fork()){
  205. case -1:
  206. error("fork error", 0);
  207. case 0:
  208. break;
  209. default:
  210. return kid;
  211. }
  212. while((n=read(0, buf, sizeof buf))>0)
  213. if(write(fd, buf, n)!=n)
  214. exits("write error");
  215. if(eof)
  216. write(fd, buf, 0);
  217. exits(0);
  218. return 0; /* to keep compiler happy */
  219. }
  220. void
  221. error(char *s, char *z)
  222. {
  223. if(z == 0)
  224. fprint(2, "%s: %s: %r\n", argv0, s);
  225. else
  226. fprint(2, "%s: %s %s: %r\n", argv0, s, z);
  227. exits(s);
  228. }
  229. char *
  230. buildargs(char *argv[])
  231. {
  232. char *args;
  233. int m, n;
  234. args = malloc(1);
  235. args[0] = '\0';
  236. n = 0;
  237. while(*argv){
  238. m = strlen(*argv) + 1;
  239. args = realloc(args, n+m +1);
  240. if(args == 0)
  241. error("malloc fail", 0);
  242. args[n] = ' '; /* smashes old null */
  243. strcpy(args+n+1, *argv);
  244. n += m;
  245. argv++;
  246. }
  247. return args;
  248. }