From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Thu, 27 Aug 1998 03:55:31 -0400 From: arisawa@plan9.aichi-u.ac.jp arisawa@plan9.aichi-u.ac.jp Subject: No subject Topicbox-Message-UUID: 7dba7e5a-eac8-11e9-9e20-41e7f4b1d025 Message-ID: <19980827075531.pSpoYpfJgAepWfPTkMEAg55Dzx8jmDyVebaq1ay4AYA@z> /* su: substitute user usage: su [user] I felt inconvenient to kill processes of none, so I wrote. Su is the plan9 version of UNIX su. Ref: Much of the codes comes from elsewhere. 1998/08/27 Kenji Arisawa (Kenar) E-mail: arisawa@ar.aichi-u.ac.jp */ #include #include #include void error(char *s) { fprint(2,"%s\n", s); exits(s); } int writefile(char *name, char *buf, int len) { int f, n; f = open(name, OWRITE); if(f < 0) return -1; n = write(f, buf, len); close(f); return (n != len) ? -1 : 0; } void prompt(char *p, char *b, int n) { char *e; int i; print("%s: ", p); for(e = b+n; b < e;){ i = read(0, b, e-b); if(i <= 0) exits("hungup"); b += i; if(*(b-1) == '\n'){ *(b-1) = 0; return; } } } int readln(char *prompt, char *line, int len) { char *p; int fd, ctl, n, nr; fd = open("/dev/cons", ORDWR); if(fd < 0) error("couldn't open cons"); ctl = open("/dev/consctl", OWRITE); if(ctl < 0) error("couldn't set raw mode"); write(ctl, "rawon", 5); fprint(fd, "%s", prompt); nr = 0; p = line; for(;;){ n = read(fd, p, 1); if(n < 0){ close(fd); close(ctl); return -1; } if(n == 0 || *p == '\n' || *p == '\r'){ *p = '\0'; write(fd, "\n", 1); close(fd); close(ctl); return nr; } if(*p == '\b'){ if(nr > 0){ nr--; p--; } }else if(*p == 21){ /* cntrl-u */ fprint(fd, "\n%s", prompt); nr = 0; p = line; }else{ nr++; p++; } if(nr == len){ fprint(fd, "line too long; try again\n%s", prompt); nr = 0; p = line; } } return -1; } /* * authenticate by challenge */ int challuser(char *user) { char nchall[NETCHLEN+32]; char response[NAMELEN]; Chalstate ch; int m=5; /* max trial */ while(m-- > 0){ if(getchal(&ch, user) < 0) return -1; sprint(nchall, "challenge: %s\r\nresponse", ch.chal); prompt(nchall, response, sizeof response); if(chalreply(&ch, response) == 0) break; } if(m < 0) return -1; return 0; } /* * authenticate by password * there may be more elegant method */ int passuser(char *user) { char buf[32], passwd[32], key[DESKEYLEN]; Chalstate ch; int n; int m=5; /* max trial */ while(m-- > 0){ n = readln("Password: ", passwd, sizeof(passwd)); passwd[n] = 0; if(n == 0) return -1; passtokey(key, passwd); if(getchal(&ch, user) < 0) return -1; strcpy(buf,ch.chal); n = strtol(buf, 0, 10); sprint(buf, "%d", n); netcrypt(key, buf); if(chalreply(&ch, buf) == 0) break; } if(m < 0) return -1; return 0; } int authuser(char *user){ char *s; /* check the host where su is running */ s = getenv("service"); if(s && strcmp(s, "terminal") == 0){ if(passuser(user) < 0) return -1; } else{ /* we apply challenge and response */ if(challuser(user) < 0) return -1; } return 0; } void main(int argc, char **argv) { int f; char *user=0; argv++; if(*argv) user=*argv; if(user){ if(authuser(user) < 0) { print("authentication failure\r\n"); exits("authentication"); } newns(user,0); } else{ /* set user to none */ if(writefile("/dev/user", "none", 4) < 0) exits("/dev/user"); newns("none",0); } putenv("prompt", "su% "); execl("/bin/rc", "rc", "-i", 0); }