rx.c 4.5 KB

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