9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] su for plan9
@ 1998-08-27  8:00 arisawa
  0 siblings, 0 replies; only message in thread
From: arisawa @ 1998-08-27  8:00 UTC (permalink / raw)


Hello 9fans!

Here is a "su" for Plan9.

I don't know much of authentication scheme of Plan9,
so I used naive method using challenge/response.
Let me know if you have other methods.

Kenji Arisawa
E-mail: arisawa@aichi-u.ac.jp

/*
	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 <u.h>
#include <libc.h>
#include <auth.h>

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);
}




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1998-08-27  8:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-08-27  8:00 [9fans] su for plan9 arisawa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).