Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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