rx.c 4.3 KB

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