login.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. #include <authsrv.h>
  13. void
  14. readln(char *prompt, char *line, int len, int raw)
  15. {
  16. char *p;
  17. int fdin, fdout, ctl, n, nr;
  18. fdin = open("/dev/cons", OREAD);
  19. fdout = open("/dev/cons", OWRITE);
  20. fprint(fdout, "%s", prompt);
  21. if(raw){
  22. ctl = open("/dev/consctl", OWRITE);
  23. if(ctl < 0){
  24. fprint(2, "login: couldn't set raw mode");
  25. exits("readln");
  26. }
  27. write(ctl, "rawon", 5);
  28. } else
  29. ctl = -1;
  30. nr = 0;
  31. p = line;
  32. for(;;){
  33. n = read(fdin, p, 1);
  34. if(n < 0){
  35. close(ctl);
  36. close(fdin);
  37. close(fdout);
  38. fprint(2, "login: can't read cons");
  39. exits("readln");
  40. }
  41. if(*p == 0x7f)
  42. exits(0);
  43. if(n == 0 || *p == '\n' || *p == '\r'){
  44. *p = '\0';
  45. if(raw){
  46. write(ctl, "rawoff", 6);
  47. write(fdout, "\n", 1);
  48. }
  49. close(ctl);
  50. close(fdin);
  51. close(fdout);
  52. return;
  53. }
  54. if(*p == '\b'){
  55. if(nr > 0){
  56. nr--;
  57. p--;
  58. }
  59. }else{
  60. nr++;
  61. p++;
  62. }
  63. if(nr == len){
  64. fprint(fdout, "line too long; try again\n");
  65. nr = 0;
  66. p = line;
  67. }
  68. }
  69. }
  70. void
  71. setenv(char *var, char *val)
  72. {
  73. int fd;
  74. fd = create(var, OWRITE, 0644);
  75. if(fd < 0)
  76. print("init: can't open %s\n", var);
  77. else{
  78. fprint(fd, val);
  79. close(fd);
  80. }
  81. }
  82. /*
  83. * become the authenticated user
  84. */
  85. void
  86. chuid(AuthInfo *ai)
  87. {
  88. int rv, fd;
  89. /* change uid */
  90. fd = open("#¤/capuse", OWRITE);
  91. if(fd < 0)
  92. sysfatal("can't change uid: %r");
  93. rv = write(fd, ai->cap, strlen(ai->cap));
  94. close(fd);
  95. if(rv < 0)
  96. sysfatal("can't change uid: %r");
  97. }
  98. /*
  99. * mount a factotum
  100. */
  101. void
  102. mountfactotum(char *srvname)
  103. {
  104. int fd;
  105. /* mount it */
  106. fd = open(srvname, ORDWR);
  107. if(fd < 0)
  108. sysfatal("opening factotum: %r");
  109. mount(fd, -1, "/mnt", MBEFORE, "", 'M');
  110. close(fd);
  111. }
  112. /*
  113. * start a new factotum and pass it the username and password
  114. */
  115. void
  116. startfactotum(char *user, char *password, char *srvname)
  117. {
  118. int fd;
  119. strcpy(srvname, "/srv/factotum.XXXXXXXXXXX");
  120. mktemp(srvname);
  121. switch(fork()){
  122. case -1:
  123. sysfatal("can't start factotum: %r");
  124. case 0:
  125. execl("/boot/factotum", "loginfactotum", "-ns", srvname+5, nil);
  126. sysfatal("starting factotum: %r");
  127. break;
  128. }
  129. /* wait for agent to really be there */
  130. while(access(srvname, 0) < 0)
  131. sleep(250);
  132. /* mount it */
  133. mountfactotum(srvname);
  134. /* write in new key */
  135. fd = open("/mnt/factotum/ctl", ORDWR);
  136. if(fd < 0)
  137. sysfatal("opening factotum: %r");
  138. fprint(fd, "key proto=p9sk1 dom=cs.bell-labs.com user=%q !password=%q", user, password);
  139. close(fd);
  140. }
  141. void
  142. main(int argc, char *argv[])
  143. {
  144. char pass[ANAMELEN];
  145. char buf[2*ANAMELEN];
  146. char home[2*ANAMELEN];
  147. char srvname[2*ANAMELEN];
  148. char *user, *sysname, *tz, *cputype, *service;
  149. AuthInfo *ai;
  150. ARGBEGIN{
  151. }ARGEND;
  152. rfork(RFENVG|RFNAMEG);
  153. service = getenv("service");
  154. if(strcmp(service, "cpu") == 0)
  155. fprint(2, "login: warning: running on a cpu server!\n");
  156. if(argc != 1){
  157. fprint(2, "usage: login username\n");
  158. exits("usage");
  159. }
  160. user = argv[0];
  161. memset(pass, 0, sizeof(pass));
  162. readln("Password: ", pass, sizeof(pass), 1);
  163. /* authenticate */
  164. ai = auth_userpasswd(user, pass);
  165. if(ai == nil || ai->cap == nil)
  166. sysfatal("login incorrect");
  167. /* change uid */
  168. chuid(ai);
  169. /* start a new factotum and hand it a new key */
  170. startfactotum(user, pass, srvname);
  171. /* set up new namespace */
  172. newns(ai->cuid, nil);
  173. auth_freeAI(ai);
  174. /* remount the factotum */
  175. mountfactotum(srvname);
  176. /* set up a new environment */
  177. cputype = getenv("cputype");
  178. sysname = getenv("sysname");
  179. tz = getenv("timezone");
  180. rfork(RFCENVG);
  181. setenv("#e/service", "con");
  182. setenv("#e/user", user);
  183. snprint(home, sizeof(home), "/usr/%s", user);
  184. setenv("#e/home", home);
  185. setenv("#e/cputype", cputype);
  186. setenv("#e/objtype", cputype);
  187. if(sysname != nil)
  188. setenv("#e/sysname", sysname);
  189. if(tz != nil)
  190. setenv("#e/timezone", tz);
  191. /* go to new home directory */
  192. snprint(buf, sizeof(buf), "/usr/%s", user);
  193. if(chdir(buf) < 0)
  194. chdir("/");
  195. /* read profile and start interactive rc */
  196. execl("/bin/rc", "rc", "-li", nil);
  197. exits(0);
  198. }