as.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. /*
  10. * as user cmd [arg...] - run cmd with args as user on this cpu server.
  11. * must be hostowner for this to work.
  12. * needs #¤/caphash and #¤/capuse.
  13. */
  14. #include <u.h>
  15. #include <libc.h>
  16. #include <bio.h>
  17. #include <libsec.h>
  18. #include <auth.h>
  19. #include "authcmdlib.h"
  20. int debug;
  21. int becomeuser(char*);
  22. void createuser(void);
  23. void *emalloc(uint32_t);
  24. void *erealloc(void*, uint32_t);
  25. void initcap(void);
  26. int mkcmd(char*, char*, int);
  27. int myauth(int, char*);
  28. int qidcmp(Qid, Qid);
  29. void runas(char *, char *);
  30. void usage(void);
  31. #pragma varargck argpos clog 1
  32. #pragma varargck argpos fatal 1
  33. static void
  34. fatal(char *fmt, ...)
  35. {
  36. char msg[256];
  37. va_list arg;
  38. va_start(arg, fmt);
  39. vseprint(msg, msg + sizeof msg, fmt, arg);
  40. va_end(arg);
  41. error("%s", msg);
  42. }
  43. void
  44. main(int argc, char *argv[])
  45. {
  46. debug = 0;
  47. ARGBEGIN{
  48. case 'd':
  49. debug = 1;
  50. break;
  51. default:
  52. usage();
  53. }ARGEND
  54. initcap();
  55. srand(getpid()*time(0));
  56. runas(argv[0], argv[1]);
  57. }
  58. void
  59. runas(char *user, char *cmd)
  60. {
  61. if(becomeuser(user) < 0)
  62. sysfatal("can't change uid for %s: %r", user);
  63. putenv("service", "rx");
  64. execl("/bin/rc", "rc", "-lc", cmd, nil);
  65. sysfatal("exec /bin/rc: %r");
  66. }
  67. void *
  68. emalloc(uint32_t n)
  69. {
  70. void *p;
  71. if(p = mallocz(n, 1))
  72. return p;
  73. fatal("out of memory");
  74. return 0;
  75. }
  76. void *
  77. erealloc(void *p, uint32_t n)
  78. {
  79. if(p = realloc(p, n))
  80. return p;
  81. fatal("out of memory");
  82. return 0;
  83. }
  84. void
  85. usage(void)
  86. {
  87. fprint(2, "usage: %s [-c]\n", argv0);
  88. exits("usage");
  89. }
  90. void
  91. memrandom(void *p, int n)
  92. {
  93. uint8_t *cp;
  94. for(cp = (uint8_t*)p; n > 0; n--)
  95. *cp++ = fastrand();
  96. }
  97. /*
  98. * keep caphash fd open since opens of it could be disabled
  99. */
  100. static int caphashfd;
  101. void
  102. initcap(void)
  103. {
  104. caphashfd = open("#¤/caphash", OCEXEC|OWRITE);
  105. if(caphashfd < 0)
  106. fprint(2, "%s: opening #¤/caphash: %r\n", argv0);
  107. }
  108. /*
  109. * create a change uid capability
  110. */
  111. char*
  112. mkcap(char *from, char *to)
  113. {
  114. uint8_t rand[20];
  115. char *cap;
  116. char *key;
  117. int nfrom, nto, ncap;
  118. uint8_t hash[SHA1dlen];
  119. if(caphashfd < 0)
  120. return nil;
  121. /* create the capability */
  122. nto = strlen(to);
  123. nfrom = strlen(from);
  124. ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1;
  125. cap = emalloc(ncap);
  126. snprint(cap, ncap, "%s@%s", from, to);
  127. memrandom(rand, sizeof(rand));
  128. key = cap+nfrom+1+nto+1;
  129. enc64(key, sizeof(rand)*3, rand, sizeof(rand));
  130. /* hash the capability */
  131. hmac_sha1((uint8_t*)cap, strlen(cap), (uint8_t*)key, strlen(key),
  132. hash, nil);
  133. /* give the kernel the hash */
  134. key[-1] = '@';
  135. if(write(caphashfd, hash, SHA1dlen) < 0){
  136. free(cap);
  137. return nil;
  138. }
  139. return cap;
  140. }
  141. int
  142. usecap(char *cap)
  143. {
  144. int fd, rv;
  145. fd = open("#¤/capuse", OWRITE);
  146. if(fd < 0)
  147. return -1;
  148. rv = write(fd, cap, strlen(cap));
  149. close(fd);
  150. return rv;
  151. }
  152. int
  153. becomeuser(char *new)
  154. {
  155. char *cap;
  156. int rv;
  157. cap = mkcap(getuser(), new);
  158. if(cap == nil)
  159. return -1;
  160. rv = usecap(cap);
  161. free(cap);
  162. newns(new, nil);
  163. return rv;
  164. }