123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <authsrv.h>
- void
- readln(char *prompt, char *line, int len, int raw)
- {
- char *p;
- int fdin, fdout, ctl, n, nr;
- fdin = open("/dev/cons", OREAD);
- fdout = open("/dev/cons", OWRITE);
- fprint(fdout, "%s", prompt);
- if(raw){
- ctl = open("/dev/consctl", OWRITE);
- if(ctl < 0){
- fprint(2, "couldn't set raw mode");
- exits("readln");
- }
- write(ctl, "rawon", 5);
- } else
- ctl = -1;
- nr = 0;
- p = line;
- for(;;){
- n = read(fdin, p, 1);
- if(n < 0){
- close(ctl);
- close(fdin);
- close(fdout);
- fprint(2, "can't read cons");
- exits("readln");
- }
- if(*p == 0x7f)
- exits(0);
- if(n == 0 || *p == '\n' || *p == '\r'){
- *p = '\0';
- if(raw){
- write(ctl, "rawoff", 6);
- write(fdout, "\n", 1);
- }
- close(ctl);
- close(fdin);
- close(fdout);
- return;
- }
- if(*p == '\b'){
- if(nr > 0){
- nr--;
- p--;
- }
- }else{
- nr++;
- p++;
- }
- if(nr == len){
- fprint(fdout, "line too long; try again\n");
- nr = 0;
- p = line;
- }
- }
- }
- void
- setenv(char *var, char *val)
- {
- int fd;
- fd = create(var, OWRITE, 0644);
- if(fd < 0)
- print("init: can't open %s\n", var);
- else{
- fprint(fd, val);
- close(fd);
- }
- }
- /*
- * become the authenticated user
- */
- void
- chuid(AuthInfo *ai)
- {
- int rv, fd;
- /* change uid */
- fd = open("#¤/capuse", OWRITE);
- if(fd < 0)
- sysfatal("can't change uid: %r");
- rv = write(fd, ai->cap, strlen(ai->cap));
- close(fd);
- if(rv < 0)
- sysfatal("can't change uid: %r");
- }
- /*
- * mount a factotum
- */
- void
- mountfactotum(char *srvname)
- {
- int fd;
- /* mount it */
- fd = open(srvname, ORDWR);
- if(fd < 0)
- sysfatal("opening factotum: %r");
- mount(fd, -1, "/mnt", MBEFORE, "");
- close(fd);
- }
- /*
- * start a new factotum and pass it the username and password
- */
- void
- startfactotum(char *user, char *password, char *srvname)
- {
- int fd;
- strcpy(srvname, "/srv/factotum.XXXXXXXXXXX");
- mktemp(srvname);
- switch(fork()){
- case -1:
- sysfatal("can't start factotum: %r");
- case 0:
- execl("/boot/factotum", "loginfactotum", "-ns", srvname+5, nil);
- sysfatal("starting factotum: %r");
- break;
- }
- /* wait for agent to really be there */
- while(access(srvname, 0) < 0)
- sleep(250);
- /* mount it */
- mountfactotum(srvname);
- /* write in new key */
- fd = open("/mnt/factotum/ctl", ORDWR);
- if(fd < 0)
- sysfatal("opening factotum: %r");
- fprint(fd, "key proto=p9sk1 dom=cs.bell-labs.com user=%q !password=%q", user, password);
- close(fd);
- }
- void
- main(int argc, char *argv[])
- {
- char pass[ANAMELEN];
- char buf[2*ANAMELEN];
- char home[2*ANAMELEN];
- char srvname[2*ANAMELEN];
- char *user, *sysname, *tz, *cputype, *service;
- AuthInfo *ai;
- ARGBEGIN{
- }ARGEND;
- rfork(RFENVG|RFNAMEG);
- service = getenv("service");
- if(strcmp(service, "cpu") == 0)
- fprint(2, "warning: running on a cpu server!\n");
- if(argc != 1){
- fprint(2, "usage: login username\n");
- exits("usage");
- }
- user = argv[0];
- memset(pass, 0, sizeof(pass));
- readln("Password: ", pass, sizeof(pass), 1);
- /* authenticate */
- ai = auth_userpasswd(user, pass);
- if(ai == nil || ai->cap == nil)
- sysfatal("login incorrect");
- /* change uid */
- chuid(ai);
- /* start a new factotum and hand it a new key */
- startfactotum(user, pass, srvname);
- /* set up new namespace */
- newns(ai->cuid, nil);
- auth_freeAI(ai);
- /* remount the factotum */
- mountfactotum(srvname);
- /* set up a new environment */
- cputype = getenv("cputype");
- sysname = getenv("sysname");
- tz = getenv("timezone");
- rfork(RFCENVG);
- setenv("#e/service", "con");
- setenv("#e/user", user);
- snprint(home, sizeof(home), "/usr/%s", user);
- setenv("#e/home", home);
- setenv("#e/cputype", cputype);
- setenv("#e/objtype", cputype);
- if(sysname != nil)
- setenv("#e/sysname", sysname);
- if(tz != nil)
- setenv("#e/timezone", tz);
- /* go to new home directory */
- snprint(buf, sizeof(buf), "/usr/%s", user);
- if(chdir(buf) < 0)
- chdir("/");
- /* read profile and start interactive rc */
- execl("/bin/rc", "rc", "-li", nil);
- exits(0);
- }
|