17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include <authsrv.h>
57dd7cddfSDavid du Colombier
67dd7cddfSDavid du Colombier void
readln(char * prompt,char * line,int len,int raw)77dd7cddfSDavid du Colombier readln(char *prompt, char *line, int len, int raw)
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier char *p;
107dd7cddfSDavid du Colombier int fdin, fdout, ctl, n, nr;
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier fdin = open("/dev/cons", OREAD);
137dd7cddfSDavid du Colombier fdout = open("/dev/cons", OWRITE);
147dd7cddfSDavid du Colombier fprint(fdout, "%s", prompt);
157dd7cddfSDavid du Colombier if(raw){
167dd7cddfSDavid du Colombier ctl = open("/dev/consctl", OWRITE);
177dd7cddfSDavid du Colombier if(ctl < 0){
18*d854de59SDavid du Colombier fprint(2, "login: couldn't set raw mode");
197dd7cddfSDavid du Colombier exits("readln");
207dd7cddfSDavid du Colombier }
217dd7cddfSDavid du Colombier write(ctl, "rawon", 5);
227dd7cddfSDavid du Colombier } else
237dd7cddfSDavid du Colombier ctl = -1;
247dd7cddfSDavid du Colombier nr = 0;
257dd7cddfSDavid du Colombier p = line;
267dd7cddfSDavid du Colombier for(;;){
277dd7cddfSDavid du Colombier n = read(fdin, p, 1);
287dd7cddfSDavid du Colombier if(n < 0){
297dd7cddfSDavid du Colombier close(ctl);
307dd7cddfSDavid du Colombier close(fdin);
317dd7cddfSDavid du Colombier close(fdout);
32*d854de59SDavid du Colombier fprint(2, "login: can't read cons");
337dd7cddfSDavid du Colombier exits("readln");
347dd7cddfSDavid du Colombier }
357dd7cddfSDavid du Colombier if(*p == 0x7f)
367dd7cddfSDavid du Colombier exits(0);
377dd7cddfSDavid du Colombier if(n == 0 || *p == '\n' || *p == '\r'){
387dd7cddfSDavid du Colombier *p = '\0';
397dd7cddfSDavid du Colombier if(raw){
407dd7cddfSDavid du Colombier write(ctl, "rawoff", 6);
417dd7cddfSDavid du Colombier write(fdout, "\n", 1);
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier close(ctl);
447dd7cddfSDavid du Colombier close(fdin);
457dd7cddfSDavid du Colombier close(fdout);
467dd7cddfSDavid du Colombier return;
477dd7cddfSDavid du Colombier }
487dd7cddfSDavid du Colombier if(*p == '\b'){
497dd7cddfSDavid du Colombier if(nr > 0){
507dd7cddfSDavid du Colombier nr--;
517dd7cddfSDavid du Colombier p--;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier }else{
547dd7cddfSDavid du Colombier nr++;
557dd7cddfSDavid du Colombier p++;
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier if(nr == len){
587dd7cddfSDavid du Colombier fprint(fdout, "line too long; try again\n");
597dd7cddfSDavid du Colombier nr = 0;
607dd7cddfSDavid du Colombier p = line;
617dd7cddfSDavid du Colombier }
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier void
setenv(char * var,char * val)667dd7cddfSDavid du Colombier setenv(char *var, char *val)
677dd7cddfSDavid du Colombier {
687dd7cddfSDavid du Colombier int fd;
697dd7cddfSDavid du Colombier
707dd7cddfSDavid du Colombier fd = create(var, OWRITE, 0644);
717dd7cddfSDavid du Colombier if(fd < 0)
727dd7cddfSDavid du Colombier print("init: can't open %s\n", var);
737dd7cddfSDavid du Colombier else{
747dd7cddfSDavid du Colombier fprint(fd, val);
757dd7cddfSDavid du Colombier close(fd);
767dd7cddfSDavid du Colombier }
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier
796b6b9ac8SDavid du Colombier /*
806b6b9ac8SDavid du Colombier * become the authenticated user
816b6b9ac8SDavid du Colombier */
826b6b9ac8SDavid du Colombier void
chuid(AuthInfo * ai)836b6b9ac8SDavid du Colombier chuid(AuthInfo *ai)
846b6b9ac8SDavid du Colombier {
856b6b9ac8SDavid du Colombier int rv, fd;
866b6b9ac8SDavid du Colombier
876b6b9ac8SDavid du Colombier /* change uid */
886b6b9ac8SDavid du Colombier fd = open("#¤/capuse", OWRITE);
896b6b9ac8SDavid du Colombier if(fd < 0)
906b6b9ac8SDavid du Colombier sysfatal("can't change uid: %r");
916b6b9ac8SDavid du Colombier rv = write(fd, ai->cap, strlen(ai->cap));
926b6b9ac8SDavid du Colombier close(fd);
936b6b9ac8SDavid du Colombier if(rv < 0)
946b6b9ac8SDavid du Colombier sysfatal("can't change uid: %r");
956b6b9ac8SDavid du Colombier }
966b6b9ac8SDavid du Colombier
976b6b9ac8SDavid du Colombier /*
986b6b9ac8SDavid du Colombier * mount a factotum
996b6b9ac8SDavid du Colombier */
1006b6b9ac8SDavid du Colombier void
mountfactotum(char * srvname)1016b6b9ac8SDavid du Colombier mountfactotum(char *srvname)
1026b6b9ac8SDavid du Colombier {
1036b6b9ac8SDavid du Colombier int fd;
1046b6b9ac8SDavid du Colombier
1056b6b9ac8SDavid du Colombier /* mount it */
1066b6b9ac8SDavid du Colombier fd = open(srvname, ORDWR);
1076b6b9ac8SDavid du Colombier if(fd < 0)
1086b6b9ac8SDavid du Colombier sysfatal("opening factotum: %r");
1096b6b9ac8SDavid du Colombier mount(fd, -1, "/mnt", MBEFORE, "");
1106b6b9ac8SDavid du Colombier close(fd);
1116b6b9ac8SDavid du Colombier }
1126b6b9ac8SDavid du Colombier
1136b6b9ac8SDavid du Colombier /*
1146b6b9ac8SDavid du Colombier * start a new factotum and pass it the username and password
1156b6b9ac8SDavid du Colombier */
1166b6b9ac8SDavid du Colombier void
startfactotum(char * user,char * password,char * srvname)1176b6b9ac8SDavid du Colombier startfactotum(char *user, char *password, char *srvname)
1186b6b9ac8SDavid du Colombier {
1196b6b9ac8SDavid du Colombier int fd;
1206b6b9ac8SDavid du Colombier
1216b6b9ac8SDavid du Colombier strcpy(srvname, "/srv/factotum.XXXXXXXXXXX");
1226b6b9ac8SDavid du Colombier mktemp(srvname);
1236b6b9ac8SDavid du Colombier
1246b6b9ac8SDavid du Colombier switch(fork()){
1256b6b9ac8SDavid du Colombier case -1:
1266b6b9ac8SDavid du Colombier sysfatal("can't start factotum: %r");
1276b6b9ac8SDavid du Colombier case 0:
128f19e7b74SDavid du Colombier execl("/boot/factotum", "loginfactotum", "-ns", srvname+5, nil);
1296b6b9ac8SDavid du Colombier sysfatal("starting factotum: %r");
1306b6b9ac8SDavid du Colombier break;
1316b6b9ac8SDavid du Colombier }
1326b6b9ac8SDavid du Colombier
1336b6b9ac8SDavid du Colombier /* wait for agent to really be there */
1346b6b9ac8SDavid du Colombier while(access(srvname, 0) < 0)
1356b6b9ac8SDavid du Colombier sleep(250);
1366b6b9ac8SDavid du Colombier
1376b6b9ac8SDavid du Colombier /* mount it */
1386b6b9ac8SDavid du Colombier mountfactotum(srvname);
1396b6b9ac8SDavid du Colombier
1406b6b9ac8SDavid du Colombier /* write in new key */
1416b6b9ac8SDavid du Colombier fd = open("/mnt/factotum/ctl", ORDWR);
1426b6b9ac8SDavid du Colombier if(fd < 0)
1436b6b9ac8SDavid du Colombier sysfatal("opening factotum: %r");
1446b6b9ac8SDavid du Colombier fprint(fd, "key proto=p9sk1 dom=cs.bell-labs.com user=%q !password=%q", user, password);
1456b6b9ac8SDavid du Colombier close(fd);
1466b6b9ac8SDavid du Colombier }
1476b6b9ac8SDavid du Colombier
1487dd7cddfSDavid du Colombier void
main(int argc,char * argv[])1497dd7cddfSDavid du Colombier main(int argc, char *argv[])
1507dd7cddfSDavid du Colombier {
1519a747e4fSDavid du Colombier char pass[ANAMELEN];
1529a747e4fSDavid du Colombier char buf[2*ANAMELEN];
1539a747e4fSDavid du Colombier char home[2*ANAMELEN];
1546b6b9ac8SDavid du Colombier char srvname[2*ANAMELEN];
1557dd7cddfSDavid du Colombier char *user, *sysname, *tz, *cputype, *service;
1566b6b9ac8SDavid du Colombier AuthInfo *ai;
1576b6b9ac8SDavid du Colombier
1586b6b9ac8SDavid du Colombier ARGBEGIN{
1596b6b9ac8SDavid du Colombier }ARGEND;
1607dd7cddfSDavid du Colombier
161d9306527SDavid du Colombier rfork(RFENVG|RFNAMEG);
162d9306527SDavid du Colombier
1637dd7cddfSDavid du Colombier service = getenv("service");
1646b6b9ac8SDavid du Colombier if(strcmp(service, "cpu") == 0)
165*d854de59SDavid du Colombier fprint(2, "login: warning: running on a cpu server!\n");
1666b6b9ac8SDavid du Colombier if(argc != 1){
1677dd7cddfSDavid du Colombier fprint(2, "usage: login username\n");
1687dd7cddfSDavid du Colombier exits("usage");
1697dd7cddfSDavid du Colombier }
1706b6b9ac8SDavid du Colombier user = argv[0];
1717dd7cddfSDavid du Colombier memset(pass, 0, sizeof(pass));
1727dd7cddfSDavid du Colombier readln("Password: ", pass, sizeof(pass), 1);
1736b6b9ac8SDavid du Colombier
1746b6b9ac8SDavid du Colombier /* authenticate */
1756b6b9ac8SDavid du Colombier ai = auth_userpasswd(user, pass);
1766b6b9ac8SDavid du Colombier if(ai == nil || ai->cap == nil)
1776b6b9ac8SDavid du Colombier sysfatal("login incorrect");
1786b6b9ac8SDavid du Colombier
1796b6b9ac8SDavid du Colombier /* change uid */
1806b6b9ac8SDavid du Colombier chuid(ai);
1816b6b9ac8SDavid du Colombier
1826b6b9ac8SDavid du Colombier /* start a new factotum and hand it a new key */
1836b6b9ac8SDavid du Colombier startfactotum(user, pass, srvname);
1846b6b9ac8SDavid du Colombier
1856b6b9ac8SDavid du Colombier /* set up new namespace */
1866b6b9ac8SDavid du Colombier newns(ai->cuid, nil);
1876b6b9ac8SDavid du Colombier auth_freeAI(ai);
1886b6b9ac8SDavid du Colombier
1896b6b9ac8SDavid du Colombier /* remount the factotum */
1906b6b9ac8SDavid du Colombier mountfactotum(srvname);
1917dd7cddfSDavid du Colombier
1927dd7cddfSDavid du Colombier /* set up a new environment */
1937dd7cddfSDavid du Colombier cputype = getenv("cputype");
1947dd7cddfSDavid du Colombier sysname = getenv("sysname");
19580ee5cbfSDavid du Colombier tz = getenv("timezone");
1967dd7cddfSDavid du Colombier rfork(RFCENVG);
1977dd7cddfSDavid du Colombier setenv("#e/service", "con");
1987dd7cddfSDavid du Colombier setenv("#e/user", user);
1997dd7cddfSDavid du Colombier snprint(home, sizeof(home), "/usr/%s", user);
2007dd7cddfSDavid du Colombier setenv("#e/home", home);
2017dd7cddfSDavid du Colombier setenv("#e/cputype", cputype);
2027dd7cddfSDavid du Colombier setenv("#e/objtype", cputype);
2037dd7cddfSDavid du Colombier if(sysname != nil)
2047dd7cddfSDavid du Colombier setenv("#e/sysname", sysname);
2057dd7cddfSDavid du Colombier if(tz != nil)
2067dd7cddfSDavid du Colombier setenv("#e/timezone", tz);
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier /* go to new home directory */
2097dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "/usr/%s", user);
2107dd7cddfSDavid du Colombier if(chdir(buf) < 0)
2117dd7cddfSDavid du Colombier chdir("/");
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier /* read profile and start interactive rc */
214f19e7b74SDavid du Colombier execl("/bin/rc", "rc", "-li", nil);
2157dd7cddfSDavid du Colombier exits(0);
2167dd7cddfSDavid du Colombier }
217