login.c 3.9 KB

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